From 8ad98f2806376d297b78d9803c685c561eb68741 Mon Sep 17 00:00:00 2001 From: venusbb Date: Wed, 25 Oct 2017 11:35:13 +0100 Subject: [PATCH] create entry when creating a new service --- app/billing/rest.py | 9 +++--- app/dao/annual_billing_dao.py | 16 ++++++++-- app/dao/services_dao.py | 7 +++++ app/models.py | 35 +++++++++++---------- app/service/rest.py | 4 +-- app/service/utils.py | 11 +++++++ tests/app/billing/test_billing.py | 40 +++++++++++++----------- tests/app/dao/test_annual_billing_dao.py | 26 ++++----------- tests/app/dao/test_services_dao.py | 5 +-- tests/app/db.py | 1 + tests/app/service/test_rest.py | 20 ++++++++++++ 11 files changed, 107 insertions(+), 67 deletions(-) diff --git a/app/billing/rest.py b/app/billing/rest.py index 7d254c751..7d73bc098 100644 --- a/app/billing/rest.py +++ b/app/billing/rest.py @@ -126,11 +126,10 @@ def create_or_update_free_sms_fragment_limit(service_id): if result: result.free_sms_fragment_limit = free_sms_fragment_limit - dao_create_or_update_annual_billing_for_year(result) - else: - annual_billing = AnnualBilling(service_id=service_id, financial_year_start=financial_year_start, - free_sms_fragment_limit=free_sms_fragment_limit) - dao_create_or_update_annual_billing_for_year(annual_billing) + result = AnnualBilling(service_id=service_id, financial_year_start=financial_year_start, + free_sms_fragment_limit=free_sms_fragment_limit) + + dao_create_or_update_annual_billing_for_year(result) return jsonify(data=form), 201 diff --git a/app/dao/annual_billing_dao.py b/app/dao/annual_billing_dao.py index 2343104b3..8e8f7c886 100644 --- a/app/dao/annual_billing_dao.py +++ b/app/dao/annual_billing_dao.py @@ -5,6 +5,7 @@ from app.dao.dao_utils import ( ) from app.models import AnnualBilling from datetime import datetime +from app.service.utils import get_current_financial_year_start_year def dao_get_annual_billing(service_id): @@ -14,8 +15,6 @@ def dao_get_annual_billing(service_id): def dao_create_or_update_annual_billing_for_year(annual_billing): - if annual_billing.id is None: - annual_billing.id = create_uuid() db.session.add(annual_billing) db.session.commit() @@ -33,3 +32,16 @@ def dao_get_all_free_sms_fragment_limit(service_id): return AnnualBilling.query.filter_by( service_id=service_id, ).all() + + +def insert_annual_billing(service): + """ + This method is called from create_service which is wrapped in a transaction. + """ + annual_billing = AnnualBilling( + free_sms_fragment_limit=service.free_sms_fragment_limit, + financial_year_start=get_current_financial_year_start_year(), + service=service, + ) + + db.session.add(annual_billing) diff --git a/app/dao/services_dao.py b/app/dao/services_dao.py index e6e677adc..3f9e1b9c5 100644 --- a/app/dao/services_dao.py +++ b/app/dao/services_dao.py @@ -37,10 +37,12 @@ from app.models import ( EMAIL_TYPE, INTERNATIONAL_SMS_TYPE, ServiceSmsSender, + AnnualBilling ) from app.service.statistics import format_monthly_template_notification_stats from app.statsd_decorators import statsd from app.utils import get_london_month_from_utc_column, get_london_midnight_in_utc +from app.dao.annual_billing_dao import insert_annual_billing DEFAULT_SERVICE_PERMISSIONS = [ SMS_TYPE, @@ -164,6 +166,9 @@ def dao_create_service(service, user, service_id=None, service_permissions=None) if service_permissions is None: service_permissions = DEFAULT_SERVICE_PERMISSIONS + if service.free_sms_fragment_limit is None: + service.free_sms_fragment_limit = current_app.config['FREE_SMS_TIER_FRAGMENT_COUNT'] + from app.dao.permissions_dao import permission_dao service.users.append(user) permission_dao.add_default_service_permissions_for_user(user, service) @@ -176,6 +181,7 @@ def dao_create_service(service, user, service_id=None, service_permissions=None) service.permissions.append(service_permission) insert_service_sms_sender(service, service.sms_sender) + insert_annual_billing(service) db.session.add(service) @@ -238,6 +244,7 @@ def delete_service_and_all_associated_db_objects(service): _delete_commit(ServicePermission.query.filter_by(service_id=service.id)) _delete_commit(ApiKey.query.filter_by(service=service)) _delete_commit(ApiKey.get_history_model().query.filter_by(service_id=service.id)) + _delete_commit(AnnualBilling.query.filter_by(service_id=service.id)) verify_codes = VerifyCode.query.join(User).filter(User.id.in_([x.id for x in service.users])) list(map(db.session.delete, verify_codes)) diff --git a/app/models.py b/app/models.py index 31cbd0a3d..a757485bc 100644 --- a/app/models.py +++ b/app/models.py @@ -179,23 +179,6 @@ class ServicePermissionTypes(db.Model): name = db.Column(db.String(255), primary_key=True) -class AnnualBilling(db.Model): - __tablename__ = "annual_billing" - id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=False) - service_id = db.Column(UUID(as_uuid=True), db.ForeignKey('services.id'), unique=False, index=True, nullable=False) - financial_year_start = db.Column(db.Integer, nullable=False, default=True, unique=False) - free_sms_fragment_limit = db.Column(db.Integer, nullable=False, index=False, unique=False) - updated_at = db.Column(db.DateTime, nullable=True, onupdate=datetime.datetime.utcnow) - created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow) - UniqueConstraint('financial_year_start', 'service_id', name='ix_annual_billing_service_id') - - def serialize(self): - return { - 'free_sms_fragment_limit': self.free_sms_fragment_limit, - 'financial_year_start': self.financial_year_start, - } - - class Service(db.Model, Versioned): __tablename__ = 'services' @@ -286,6 +269,24 @@ class Service(db.Model, Versioned): return default_letter_contact[0].contact_block if default_letter_contact else None +class AnnualBilling(db.Model): + __tablename__ = "annual_billing" + id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=False) + service_id = db.Column(UUID(as_uuid=True), db.ForeignKey('services.id'), unique=False, index=True, nullable=False) + financial_year_start = db.Column(db.Integer, nullable=False, default=True, unique=False) + free_sms_fragment_limit = db.Column(db.Integer, nullable=False, index=False, unique=False) + updated_at = db.Column(db.DateTime, nullable=True, onupdate=datetime.datetime.utcnow) + created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow) + UniqueConstraint('financial_year_start', 'service_id', name='ix_annual_billing_service_id') + service = db.relationship(Service, backref=db.backref("annual_billing", uselist=True)) + + def serialize(self): + return { + 'free_sms_fragment_limit': self.free_sms_fragment_limit, + 'financial_year_start': self.financial_year_start, + } + + class InboundNumber(db.Model): __tablename__ = "inbound_numbers" diff --git a/app/service/rest.py b/app/service/rest.py index eab409bc1..be08e5028 100644 --- a/app/service/rest.py +++ b/app/service/rest.py @@ -170,8 +170,8 @@ def create_service(): raise InvalidRequest(errors, status_code=400) # TODO: to be removed when front-end is updated - if 'free_sms_fragment_limit' not in data: - data['free_sms_fragment_limit'] = current_app.config['FREE_SMS_TIER_FRAGMENT_COUNT'] + # if 'free_sms_fragment_limit' not in data: + # data['free_sms_fragment_limit'] = current_app.config['FREE_SMS_TIER_FRAGMENT_COUNT'] # validate json with marshmallow service_schema.load(request.get_json()) diff --git a/app/service/utils.py b/app/service/utils.py index 2c4ccbf04..475d420e2 100644 --- a/app/service/utils.py +++ b/app/service/utils.py @@ -6,6 +6,8 @@ from app.models import ( KEY_TYPE_TEST, KEY_TYPE_TEAM, KEY_TYPE_NORMAL) from notifications_utils.recipients import allowed_to_send_to +from app.dao.notifications_dao import get_financial_year +from datetime import datetime def get_recipients_from_request(request_json, key, type): @@ -51,3 +53,12 @@ def service_allowed_to_send_to(recipient, service, key_type): whitelist_members ) ) + + +def get_current_financial_year_start_year(): + now = datetime.now() + financial_year_start = now.year + start_date, end_date = get_financial_year(now.year) + if now < start_date: + financial_year_start = financial_year_start - 1 + return financial_year_start diff --git a/tests/app/billing/test_billing.py b/tests/app/billing/test_billing.py index e49cea604..86bfcc6d6 100644 --- a/tests/app/billing/test_billing.py +++ b/tests/app/billing/test_billing.py @@ -259,15 +259,19 @@ def test_transform_billing_calculates_with_different_rate_multipliers(sample_ser def test_get_free_sms_fragment_limit(client, sample_service): years = [2016, 2017, 2018] sms_allowance = [1000, 2000, 3000] + for i in range(0, len(years)): y = years[i] sms_l = sms_allowance[i] - data = AnnualBilling( - free_sms_fragment_limit=sms_l, - financial_year_start=y, - service_id=sample_service.id, - ) - dao_create_or_update_annual_billing_for_year(data) + annual_billing = dao_get_free_sms_fragment_limit_for_year(sample_service.id, years[i]) + if annual_billing: + annual_billing.free_sms_fragment_limit = sms_allowance[i] + else: + annual_billing = AnnualBilling(service_id=sample_service.id, + financial_year_start=years[i], + free_sms_fragment_limit=sms_allowance[i]) + + dao_create_or_update_annual_billing_for_year(annual_billing) response = client.get('service/{}/billing/free-sms-fragment-limit?financial_year_start=2017' .format(sample_service.id), @@ -348,13 +352,12 @@ def test_update_free_sms_fragment_limit(client, sample_service): def test_get_free_sms_fragment_limit_year_return_correct_data(client, sample_service): years = [2015, 2016, 2017] limits = [1000, 2000, 3000] + for i in range(0, len(years)): - data = AnnualBilling( - free_sms_fragment_limit=limits[i], - financial_year_start=years[i], - service_id=sample_service.id, - ) - dao_create_or_update_annual_billing_for_year(data) + annual_billing = {'financial_year_start': years[i], 'free_sms_fragment_limit': limits[i]} + response = client.post('service/{}/billing/free-sms-fragment-limit'.format(sample_service.id), + data=json.dumps(annual_billing), + headers=[('Content-Type', 'application/json'), create_authorization_header()]) for i in range(0, len(years)): response_get = client.get( @@ -365,16 +368,15 @@ def test_get_free_sms_fragment_limit_year_return_correct_data(client, sample_ser assert json_resp['data']['free_sms_fragment_limit'] == limits[i] -def test_get_free_sms_fragment_limit_for_all_year(client, sample_service): +def test_get_free_sms_fragment_limit_for_all_years(client, sample_service): years = [2015, 2016, 2017] limits = [1000, 2000, 3000] + for i in range(0, len(years)): - data = AnnualBilling( - free_sms_fragment_limit=limits[i], - financial_year_start=years[i], - service_id=sample_service.id, - ) - dao_create_or_update_annual_billing_for_year(data) + annual_billing = {'financial_year_start': years[i], 'free_sms_fragment_limit': limits[i]} + response = client.post('service/{}/billing/free-sms-fragment-limit'.format(sample_service.id), + data=json.dumps(annual_billing), + headers=[('Content-Type', 'application/json'), create_authorization_header()]) response_get = client.get( # Not specify a particular year to return all data for that service diff --git a/tests/app/dao/test_annual_billing_dao.py b/tests/app/dao/test_annual_billing_dao.py index 73b230431..e971c6460 100644 --- a/tests/app/dao/test_annual_billing_dao.py +++ b/tests/app/dao/test_annual_billing_dao.py @@ -1,8 +1,4 @@ -# from datetime import datetime, timedelta -# import uuid -# import functools -# import pytest - +from app.service.utils import get_current_financial_year_start_year from app.models import AnnualBilling from app.dao.annual_billing_dao import ( dao_create_or_update_annual_billing_for_year, @@ -10,23 +6,13 @@ from app.dao.annual_billing_dao import ( ) -def test_dao_create_get_free_sms_fragment_limit(notify_db_session, sample_service): - years = [2015, 2016, 2017] - free_limit_data = [1000, 2000, 3000] - for i in range(0, len(years)): - data = AnnualBilling( - free_sms_fragment_limit=free_limit_data[i], - financial_year_start=years[i], - service_id=sample_service.id, - ) - dao_create_or_update_annual_billing_for_year(data) +def test_sample_service_has_free_sms_fragment_limit(notify_db_session, sample_service): - for i in range(0, len(years)): - free_limit = dao_get_free_sms_fragment_limit_for_year(sample_service.id, years[i]) + free_limit = dao_get_free_sms_fragment_limit_for_year(sample_service.id, get_current_financial_year_start_year()) - assert free_limit.free_sms_fragment_limit == free_limit_data[i] - assert free_limit.financial_year_start == years[i] - assert free_limit.service_id == sample_service.id + assert free_limit.free_sms_fragment_limit == 250000 + assert free_limit.financial_year_start == get_current_financial_year_start_year() + assert free_limit.service_id == sample_service.id def test_dao_update_free_sms_fragment_limit(notify_db_session, sample_service): diff --git a/tests/app/dao/test_services_dao.py b/tests/app/dao/test_services_dao.py index a1538eebf..f672c7e42 100644 --- a/tests/app/dao/test_services_dao.py +++ b/tests/app/dao/test_services_dao.py @@ -104,7 +104,7 @@ def test_cannot_create_two_services_with_same_name(sample_user): email_from="email_from1", message_limit=1000, restricted=False, - created_by=sample_user) + created_by=sample_user,) service2 = Service(name="service_name", email_from="email_from2", @@ -171,7 +171,8 @@ def test_should_remove_user_from_service(sample_user): email_from="email_from", message_limit=1000, restricted=False, - created_by=sample_user) + created_by=sample_user, + free_sms_fragment_limit=9999) dao_create_service(service, sample_user) new_user = User( name='Test User', diff --git a/tests/app/db.py b/tests/app/db.py index 0cdf7cfee..74d2033e2 100644 --- a/tests/app/db.py +++ b/tests/app/db.py @@ -68,6 +68,7 @@ def create_service( service = Service( name=service_name, message_limit=1000, + free_sms_fragment_limit=7777, restricted=restricted, email_from=email_from if email_from else service_name.lower().replace(' ', '.'), created_by=user or create_user(email='{}@digital.cabinet-office.gov.uk'.format(uuid.uuid4())), diff --git a/tests/app/service/test_rest.py b/tests/app/service/test_rest.py index 3e1483d1a..1a5ec4e99 100644 --- a/tests/app/service/test_rest.py +++ b/tests/app/service/test_rest.py @@ -37,6 +37,7 @@ from tests.app.db import ( create_service_sms_sender ) from tests.app.db import create_user +from app.service.utils import get_current_financial_year_start_year def test_get_service_list(client, service_factory): @@ -300,6 +301,7 @@ def test_create_service(client, sample_user): assert not json_resp['data']['research_mode'] assert json_resp['data']['dvla_organisation'] == '001' assert json_resp['data']['sms_sender'] == current_app.config['FROM_NUMBER'] + # TODO: Remove this after the new data is used assert json_resp['data']['free_sms_fragment_limit'] == current_app.config['FREE_SMS_TIER_FRAGMENT_COUNT'] service_db = Service.query.get(json_resp['data']['id']) @@ -365,6 +367,15 @@ def test_create_service_free_sms_fragment_limit_is_optional(client, sample_user) headers=headers) json_resp = json.loads(resp.get_data(as_text=True)) assert resp.status_code == 201 + + # Test data from the new annual billing table + service_id = json_resp['data']['id'] + annual_billing = client.get('service/{}/billing/free-sms-fragment-limit?financial_year_start={}' + .format(service_id, get_current_financial_year_start_year()), + headers=[('Content-Type', 'application/json'), create_authorization_header()]) + json_resp = json.loads(annual_billing.get_data(as_text=True)) + assert json_resp['data']['free_sms_fragment_limit'] == 9999 + # TODO: Remove this after the new data is used assert json_resp['data']['free_sms_fragment_limit'] == 9999 data2 = { @@ -385,6 +396,14 @@ def test_create_service_free_sms_fragment_limit_is_optional(client, sample_user) headers=headers) json_resp = json.loads(resp.get_data(as_text=True)) assert resp.status_code == 201 + # Test data from the new annual billing table + service_id = json_resp['data']['id'] + annual_billing = client.get('service/{}/billing/free-sms-fragment-limit?financial_year_start={}' + .format(service_id, get_current_financial_year_start_year()), + headers=[('Content-Type', 'application/json'), create_authorization_header()]) + json_resp = json.loads(annual_billing.get_data(as_text=True)) + assert json_resp['data']['free_sms_fragment_limit'] == current_app.config['FREE_SMS_TIER_FRAGMENT_COUNT'] + # TODO: Remove this after the new data is used assert json_resp['data']['free_sms_fragment_limit'] == current_app.config['FREE_SMS_TIER_FRAGMENT_COUNT'] @@ -623,6 +642,7 @@ def test_update_service_flags_will_remove_service_permissions(client, notify_db, assert set([p.permission for p in permissions]) == set([SMS_TYPE, EMAIL_TYPE]) +# TODO: Remove after new table is created and verified def test_update_service_free_sms_fragment_limit(client, notify_db, sample_service): org = Organisation(colour='#000000', logo='justice-league.png', name='Justice League') notify_db.session.add(org)