From 00d2e543dcbbeaf3b5c02bd4d826f69f05cd41b4 Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Tue, 5 Dec 2017 10:32:19 +0000 Subject: [PATCH 1/4] Refactor letter_rates table to include everything needed to calculate billing for letter notificaitons. It is ok to drop the existing tables as they are not used anywhere as of yet. --- app/models.py | 15 ++---- .../versions/0150_refactor_letter_rates.py | 47 +++++++++++++++++++ 2 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 migrations/versions/0150_refactor_letter_rates.py diff --git a/app/models.py b/app/models.py index 9d81073c7..0a65ae0a7 100644 --- a/app/models.py +++ b/app/models.py @@ -1484,17 +1484,12 @@ class LetterRate(db.Model): __tablename__ = 'letter_rates' id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) - valid_from = valid_from = db.Column(db.DateTime, nullable=False) - - -class LetterRateDetail(db.Model): - __tablename__ = 'letter_rate_details' - - id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) - letter_rate_id = db.Column(UUID(as_uuid=True), db.ForeignKey('letter_rates.id'), index=True, nullable=False) - letter_rate = db.relationship('LetterRate', backref='letter_rates') - page_total = db.Column(db.Integer, nullable=False) + start_date = db.Column(db.DateTime, nullable=False) + end_date = db.Column(db.DateTime, nullable=True) + sheet_total = db.Column(db.Integer, nullable=False) # double sided sheet rate = db.Column(db.Numeric(), nullable=False) + crown = db.Column(db.Boolean, nullable=False) + post_class = db.Column(db.String, nullable=False) class MonthlyBilling(db.Model): diff --git a/migrations/versions/0150_refactor_letter_rates.py b/migrations/versions/0150_refactor_letter_rates.py new file mode 100644 index 000000000..2429e5222 --- /dev/null +++ b/migrations/versions/0150_refactor_letter_rates.py @@ -0,0 +1,47 @@ +""" + +Revision ID: 0150_refactor_letter_rates +Revises: 0148_add_letters_as_pdf_svc_perm +Create Date: 2017-12-05 10:24:41.232128 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +revision = '0150_refactor_letter_rates' +down_revision = '0148_add_letters_as_pdf_svc_perm' + + +def upgrade(): + op.drop_table('letter_rate_details') + op.drop_table('letter_rates') + op.create_table('letter_rates', + sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), + sa.Column('start_date', sa.DateTime(), nullable=False), + sa.Column('end_date', sa.DateTime(), nullable=True), + sa.Column('sheet_total', sa.Integer(), nullable=False), + sa.Column('rate', sa.Numeric(), nullable=False), + sa.Column('crown', sa.Boolean(), nullable=False), + sa.Column('post_class', sa.String(), nullable=False), + sa.PrimaryKeyConstraint('id') + ) + + +def downgrade(): + op.drop_table('letter_rates') + op.create_table('letter_rates', + sa.Column('id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('valid_from', postgresql.TIMESTAMP(), autoincrement=False, nullable=False), + sa.PrimaryKeyConstraint('id', name='letter_rates_pkey'), + postgresql_ignore_search_path=False + ) + op.create_table('letter_rate_details', + sa.Column('id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('letter_rate_id', postgresql.UUID(), autoincrement=False, nullable=False), + sa.Column('page_total', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('rate', sa.NUMERIC(), autoincrement=False, nullable=False), + sa.ForeignKeyConstraint(['letter_rate_id'], ['letter_rates.id'], + name='letter_rate_details_letter_rate_id_fkey'), + sa.PrimaryKeyConstraint('id', name='letter_rate_details_pkey') + ) From 07a71ef71c7dc69bb64d1f5ffe495b9048bc816f Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Tue, 5 Dec 2017 13:54:10 +0000 Subject: [PATCH 2/4] Fix db migration script --- migrations/versions/0149_add_crown_to_services.py | 2 +- migrations/versions/0150_refactor_letter_rates.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/migrations/versions/0149_add_crown_to_services.py b/migrations/versions/0149_add_crown_to_services.py index bfbbf976c..0a6412e9d 100644 --- a/migrations/versions/0149_add_crown_to_services.py +++ b/migrations/versions/0149_add_crown_to_services.py @@ -1,6 +1,6 @@ """ -Revision ID: 0149_add_crown_column_to_services +Revision ID: 0149_add_crown_to_services Revises: 0148_add_letters_as_pdf_svc_perm Create Date: 2017-12-04 12:13:35.268712 diff --git a/migrations/versions/0150_refactor_letter_rates.py b/migrations/versions/0150_refactor_letter_rates.py index 2429e5222..b29c7d9a5 100644 --- a/migrations/versions/0150_refactor_letter_rates.py +++ b/migrations/versions/0150_refactor_letter_rates.py @@ -1,7 +1,7 @@ """ Revision ID: 0150_refactor_letter_rates -Revises: 0148_add_letters_as_pdf_svc_perm +Revises: 0149_add_crown_to_services Create Date: 2017-12-05 10:24:41.232128 """ @@ -10,7 +10,7 @@ import sqlalchemy as sa from sqlalchemy.dialects import postgresql revision = '0150_refactor_letter_rates' -down_revision = '0148_add_letters_as_pdf_svc_perm' +down_revision = '0149_add_crown_to_services' def upgrade(): From 14be85160c9348f2913c1231cb053d77b1b315ca Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Wed, 6 Dec 2017 16:40:38 +0000 Subject: [PATCH 3/4] Insert initial letter rates. Create letter rates dao. Query to fetch letter rates. --- app/dao/letter_rate_dao.py | 23 +++++++++++ app/models.py | 2 +- .../versions/0150_refactor_letter_rates.py | 26 +++++++++++- tests/app/dao/test_letter_rate_dao.py | 41 +++++++++++++++++++ 4 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 app/dao/letter_rate_dao.py create mode 100644 tests/app/dao/test_letter_rate_dao.py diff --git a/app/dao/letter_rate_dao.py b/app/dao/letter_rate_dao.py new file mode 100644 index 000000000..e69001a44 --- /dev/null +++ b/app/dao/letter_rate_dao.py @@ -0,0 +1,23 @@ +from app import db +from app.dao.dao_utils import transactional +from app.models import LetterRate + + +@transactional +def dao_create_letter_rate(letter_rate): + db.session.add(letter_rate) + + +def get_letter_rates_for_daterange(date, crown, sheet_count, post_class='second'): + rates = LetterRate.query.filter( + LetterRate.start_date <= date + ).filter((LetterRate.end_date == None) | # noqa + (LetterRate.end_date > date) + ).filter( + LetterRate.crown == crown + ).filter( + LetterRate.sheet_count == sheet_count + ).filter( + LetterRate.post_class == post_class + ).all() + return rates diff --git a/app/models.py b/app/models.py index d5c4ea5af..e36e91491 100644 --- a/app/models.py +++ b/app/models.py @@ -1487,7 +1487,7 @@ class LetterRate(db.Model): id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) start_date = db.Column(db.DateTime, nullable=False) end_date = db.Column(db.DateTime, nullable=True) - sheet_total = db.Column(db.Integer, nullable=False) # double sided sheet + sheet_count = db.Column(db.Integer, nullable=False) # double sided sheet rate = db.Column(db.Numeric(), nullable=False) crown = db.Column(db.Boolean, nullable=False) post_class = db.Column(db.String, nullable=False) diff --git a/migrations/versions/0150_refactor_letter_rates.py b/migrations/versions/0150_refactor_letter_rates.py index b29c7d9a5..1b2555438 100644 --- a/migrations/versions/0150_refactor_letter_rates.py +++ b/migrations/versions/0150_refactor_letter_rates.py @@ -5,6 +5,9 @@ Revises: 0149_add_crown_to_services Create Date: 2017-12-05 10:24:41.232128 """ +import uuid +from datetime import datetime + from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import postgresql @@ -20,13 +23,34 @@ def upgrade(): sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('start_date', sa.DateTime(), nullable=False), sa.Column('end_date', sa.DateTime(), nullable=True), - sa.Column('sheet_total', sa.Integer(), nullable=False), + sa.Column('sheet_count', sa.Integer(), nullable=False), sa.Column('rate', sa.Numeric(), nullable=False), sa.Column('crown', sa.Boolean(), nullable=False), sa.Column('post_class', sa.String(), nullable=False), sa.PrimaryKeyConstraint('id') ) + start_date = datetime(2016, 3, 31, 23, 00, 00) + op.execute("insert into letter_rates values('{}', '{}', null, 1, 0.30, True, 'second')".format( + str(uuid.uuid4()), start_date) + ) + op.execute("insert into letter_rates values('{}', '{}', null, 2, 0.33, True, 'second')".format( + str(uuid.uuid4()), start_date) + ) + op.execute("insert into letter_rates values('{}', '{}', null, 3, 0.36, True, 'second')".format( + str(uuid.uuid4()), start_date) + ) + + op.execute("insert into letter_rates values('{}', '{}', null, 1, 0.33, False, 'second')".format( + str(uuid.uuid4()), start_date) + ) + op.execute("insert into letter_rates values('{}', '{}', null, 2, 0.39, False, 'second')".format( + str(uuid.uuid4()), start_date) + ) + op.execute("insert into letter_rates values('{}', '{}', null, 3, 0.45, False, 'second')".format( + str(uuid.uuid4()), start_date) + ) + def downgrade(): op.drop_table('letter_rates') diff --git a/tests/app/dao/test_letter_rate_dao.py b/tests/app/dao/test_letter_rate_dao.py new file mode 100644 index 000000000..f3fd0d139 --- /dev/null +++ b/tests/app/dao/test_letter_rate_dao.py @@ -0,0 +1,41 @@ +from datetime import datetime + +from decimal import Decimal + +from app.dao.letter_rate_dao import dao_create_letter_rate, get_letter_rates_for_daterange +from app.models import LetterRate + + +def test_dao_create_letter_rate(notify_db_session): + letter_rate = LetterRate(start_date=datetime(2017, 12, 1), + rate=0.33, + crown=True, + sheet_count=1, + post_class='second') + + dao_create_letter_rate(letter_rate) + + rates = LetterRate.query.all() + assert len(rates) == 1 + + +def test_get_letter_rates_for_daterange(notify_db_session): + letter_rate = LetterRate(start_date=datetime(2017, 12, 1), + rate=0.33, + crown=True, + sheet_count=1, + post_class='second') + + dao_create_letter_rate(letter_rate) + letter_rate = LetterRate(start_date=datetime(2016, 12, 1), + end_date=datetime(2017, 12, 1), + rate=0.30, + crown=True, + sheet_count=1, + post_class='second') + + dao_create_letter_rate(letter_rate) + + results = get_letter_rates_for_daterange(date=datetime(2017, 12, 2), crown=True, sheet_count=1, post_class='second') + assert len(results) == 1 + assert results[0].rate == Decimal('0.33') From da656af6e023cd3844ddd896e9937c5845f327a3 Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Wed, 6 Dec 2017 17:26:32 +0000 Subject: [PATCH 4/4] Fix merge conflict with db script --- ...ctor_letter_rates.py => 0151_refactor_letter_rates.py} | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) rename migrations/versions/{0150_refactor_letter_rates.py => 0151_refactor_letter_rates.py} (94%) diff --git a/migrations/versions/0150_refactor_letter_rates.py b/migrations/versions/0151_refactor_letter_rates.py similarity index 94% rename from migrations/versions/0150_refactor_letter_rates.py rename to migrations/versions/0151_refactor_letter_rates.py index 1b2555438..7a969cc42 100644 --- a/migrations/versions/0150_refactor_letter_rates.py +++ b/migrations/versions/0151_refactor_letter_rates.py @@ -1,7 +1,7 @@ """ -Revision ID: 0150_refactor_letter_rates -Revises: 0149_add_crown_to_services +Revision ID: 0151_refactor_letter_rates +Revises: 0150_another_letter_org Create Date: 2017-12-05 10:24:41.232128 """ @@ -12,8 +12,8 @@ from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import postgresql -revision = '0150_refactor_letter_rates' -down_revision = '0149_add_crown_to_services' +revision = '0151_refactor_letter_rates' +down_revision = '0150_another_letter_org' def upgrade():