From 43226dc93252f16d85a8381836e661497c57efcc Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Mon, 24 Apr 2017 16:20:03 +0100 Subject: [PATCH 1/4] Added a new rates table. We only need one rate per channel. This reflects that. The provider_rates has been left for now, it is still not being used. New dao has been added to select the right rate for the given notification_type and date of notificaiton. --- app/dao/rates_dao.py | 11 +++++ app/models.py | 9 +++++ migrations/versions/0074_update_sms_rate.py | 28 +++++++++++++ .../versions/0075_create_rates_table.py | 40 +++++++++++++++++++ tests/app/dao/test_rates_dao.py | 18 +++++++++ 5 files changed, 106 insertions(+) create mode 100644 app/dao/rates_dao.py create mode 100644 migrations/versions/0074_update_sms_rate.py create mode 100644 migrations/versions/0075_create_rates_table.py create mode 100644 tests/app/dao/test_rates_dao.py diff --git a/app/dao/rates_dao.py b/app/dao/rates_dao.py new file mode 100644 index 000000000..d41f67f0f --- /dev/null +++ b/app/dao/rates_dao.py @@ -0,0 +1,11 @@ +from sqlalchemy import desc + +from app import db +from app.models import Rates + + +def get_rate_for_type_and_date(notification_type, date_sent): + return db.session.query(Rates).filter(Rates.notification_type == notification_type, + Rates.valid_from <= date_sent + ).order_by(Rates.valid_from.desc() + ).limit(1).first() diff --git a/app/models.py b/app/models.py index dbde51fb8..3cda6909b 100644 --- a/app/models.py +++ b/app/models.py @@ -944,3 +944,12 @@ class Event(db.Model): nullable=False, default=datetime.datetime.utcnow) data = db.Column(JSON, nullable=False) + + +class Rates(db.Model): + __tablename__ = 'rates' + + id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) + valid_from = db.Column(db.DateTime, nullable=False) + rate = db.Column(db.Numeric(), nullable=False) + notification_type = db.Column(notification_types, index=True, nullable=False) diff --git a/migrations/versions/0074_update_sms_rate.py b/migrations/versions/0074_update_sms_rate.py new file mode 100644 index 000000000..319ca0dcd --- /dev/null +++ b/migrations/versions/0074_update_sms_rate.py @@ -0,0 +1,28 @@ +"""empty message + +Revision ID: 0074_update_sms_rate +Revises: 0072_add_dvla_orgs +Create Date: 2017-04-24 12:10:02.116278 + +""" + +import uuid + +revision = '0074_update_sms_rate' +down_revision = '0072_add_dvla_orgs' + +from alembic import op + + +def upgrade(): + op.get_bind() + op.execute("INSERT INTO provider_rates (id, valid_from, rate, provider_id) " + "VALUES ('{}', '2017-04-01 00:00:00', 1.58, " + "(SELECT id FROM provider_details WHERE identifier = 'mmg'))".format(uuid.uuid4()) + ) + + +def downgrade(): + op.get_bind() + op.execute("DELETE FROM provider_rates where valid_from = '2017-04-01 00:00:00' " + "and provider_id = (SELECT id FROM provider_details WHERE identifier = 'mmg')") \ No newline at end of file diff --git a/migrations/versions/0075_create_rates_table.py b/migrations/versions/0075_create_rates_table.py new file mode 100644 index 000000000..056330b79 --- /dev/null +++ b/migrations/versions/0075_create_rates_table.py @@ -0,0 +1,40 @@ +"""empty message + +Revision ID: 0075_create_rates_table +Revises: 0074_update_sms_rate +Create Date: 2017-04-24 15:12:18.907629 + +""" + +# revision identifiers, used by Alembic. +import uuid + +revision = '0075_create_rates_table' +down_revision = '0074_update_sms_rate' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +def upgrade(): + notification_types = postgresql.ENUM('email', 'sms', 'letter', name='notification_type', create_type=False) + op.create_table('rates', + sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), + sa.Column('valid_from', sa.DateTime(), nullable=False), + sa.Column('rate', sa.Numeric(), nullable=False), + sa.Column('notification_type', notification_types, nullable=False), + sa.PrimaryKeyConstraint('id') + ) + + op.create_index(op.f('ix_rates_notification_type'), 'rates', ['notification_type'], unique=False) + + op.get_bind() + op.execute("INSERT INTO rates(id, valid_from, rate, notification_type) " + "VALUES('{}', '2016-05-18 00:00:00', 1.65, 'sms')".format(uuid.uuid4())) + op.execute("INSERT INTO rates(id, valid_from, rate, notification_type) " + "VALUES('{}', '2017-04-01 00:00:00', 1.58, 'sms')".format(uuid.uuid4())) + + +def downgrade(): + op.drop_index(op.f('ix_rates_notification_type'), table_name='rates') + op.drop_table('rates') diff --git a/tests/app/dao/test_rates_dao.py b/tests/app/dao/test_rates_dao.py new file mode 100644 index 000000000..33f68a671 --- /dev/null +++ b/tests/app/dao/test_rates_dao.py @@ -0,0 +1,18 @@ +from datetime import datetime + +from decimal import Decimal + +from app.dao.rates_dao import get_rate_for_type_and_date + + +def test_get_rate_for_type_and_date(notify_db): + rate = get_rate_for_type_and_date('sms', datetime.utcnow()) + assert rate.rate == Decimal("1.58") + + rate = get_rate_for_type_and_date('sms', datetime(2016, 6, 1)) + assert rate.rate == Decimal("1.65") + + +def test_get_rate_for_type_and_date_early_date(notify_db): + rate = get_rate_for_type_and_date('sms', datetime(2014, 6, 1)) + assert not rate From 266c17dfd6dadb02c7621dd0344a127e4adaf8bd Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Mon, 24 Apr 2017 16:32:23 +0100 Subject: [PATCH 2/4] Do not delete rates --- tests/conftest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index b08059725..c7ec7ee3b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -76,7 +76,8 @@ def notify_db_session(notify_db): "job_status", "provider_details_history", "template_process_type", - "dvla_organisation"]: + "dvla_organisation", + "rates"]: notify_db.engine.execute(tbl.delete()) notify_db.session.commit() From 6c8ff80440411c5e938dac16419bc3e4f9cec0a1 Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Tue, 25 Apr 2017 09:53:43 +0100 Subject: [PATCH 3/4] Rename class to be singular --- app/dao/rates_dao.py | 10 +++++----- app/models.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/dao/rates_dao.py b/app/dao/rates_dao.py index d41f67f0f..47ed83a4e 100644 --- a/app/dao/rates_dao.py +++ b/app/dao/rates_dao.py @@ -1,11 +1,11 @@ from sqlalchemy import desc from app import db -from app.models import Rates +from app.models import Rate def get_rate_for_type_and_date(notification_type, date_sent): - return db.session.query(Rates).filter(Rates.notification_type == notification_type, - Rates.valid_from <= date_sent - ).order_by(Rates.valid_from.desc() - ).limit(1).first() + return db.session.query(Rate).filter(Rate.notification_type == notification_type, + Rate.valid_from <= date_sent + ).order_by(Rate.valid_from.desc() + ).limit(1).first() diff --git a/app/models.py b/app/models.py index 3cda6909b..22f94ada0 100644 --- a/app/models.py +++ b/app/models.py @@ -946,7 +946,7 @@ class Event(db.Model): data = db.Column(JSON, nullable=False) -class Rates(db.Model): +class Rate(db.Model): __tablename__ = 'rates' id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) From 3b28a1fa47d4e2339f2219eaf688b88b5901afea Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Tue, 25 Apr 2017 10:19:57 +0100 Subject: [PATCH 4/4] Fix db migration merge conflicts --- migrations/versions/0074_update_sms_rate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/migrations/versions/0074_update_sms_rate.py b/migrations/versions/0074_update_sms_rate.py index 319ca0dcd..7a5a0728a 100644 --- a/migrations/versions/0074_update_sms_rate.py +++ b/migrations/versions/0074_update_sms_rate.py @@ -1,7 +1,7 @@ """empty message Revision ID: 0074_update_sms_rate -Revises: 0072_add_dvla_orgs +Revises: 0073_add_international_sms_flag Create Date: 2017-04-24 12:10:02.116278 """ @@ -9,7 +9,7 @@ Create Date: 2017-04-24 12:10:02.116278 import uuid revision = '0074_update_sms_rate' -down_revision = '0072_add_dvla_orgs' +down_revision = '0073_add_international_sms_flag' from alembic import op