diff --git a/app/dao/monthly_billing_dao.py b/app/dao/monthly_billing_dao.py new file mode 100644 index 000000000..c037b5c54 --- /dev/null +++ b/app/dao/monthly_billing_dao.py @@ -0,0 +1,6 @@ +from app import db + + +def update_monthly_billing(monthly_billing): + db.session.add(monthly_billing) + db.session.commit() diff --git a/app/models.py b/app/models.py index 0e3079c80..07ba505d8 100644 --- a/app/models.py +++ b/app/models.py @@ -4,7 +4,6 @@ import datetime from flask import url_for, current_app from sqlalchemy.ext.associationproxy import association_proxy -from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.dialects.postgresql import ( UUID, JSON @@ -1246,3 +1245,19 @@ class LetterRateDetail(db.Model): letter_rate = db.relationship('LetterRate', backref='letter_rates') page_total = db.Column(db.Integer, nullable=False) rate = db.Column(db.Numeric(), nullable=False) + + +class MonthlyBilling(db.Model): + __tablename__ = 'monthly_billing' + + id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) + service_id = db.Column(UUID(as_uuid=True), db.ForeignKey('services.id'), index=True, nullable=False) + service = db.relationship('Service', backref='monthly_billing') + month = db.Column(db.String, nullable=False) + year = db.Column(db.Float(asdecimal=False), nullable=False) + notification_type = db.Column(notification_types, nullable=False) + monthly_totals = db.Column(JSON, nullable=False) + + __table_args__ = ( + UniqueConstraint('service_id', 'month', 'year', 'notification_type', name='uix_monthly_billing'), + ) diff --git a/migrations/versions/0109_monthly_billing.py b/migrations/versions/0109_monthly_billing.py new file mode 100644 index 000000000..124a509cf --- /dev/null +++ b/migrations/versions/0109_monthly_billing.py @@ -0,0 +1,37 @@ +"""empty message + +Revision ID: 0109_monthly_billing +Revises: 0108_change_logo_not_nullable +Create Date: 2017-07-13 14:35:03.183659 + +""" + +# revision identifiers, used by Alembic. +revision = '0109_monthly_billing' +down_revision = '0108_change_logo_not_nullable' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + + +def upgrade(): + + op.create_table('monthly_billing', + sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), + sa.Column('service_id', postgresql.UUID(as_uuid=True), nullable=False), + sa.Column('month', sa.String(), nullable=False), + sa.Column('year', sa.Float(), nullable=False), + sa.Column('notification_type', + postgresql.ENUM('email', 'sms', 'letter', name='notification_type', create_type=False), + nullable=False), + sa.Column('monthly_totals', postgresql.JSON(), nullable=False), + sa.ForeignKeyConstraint(['service_id'], ['services.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index(op.f('ix_monthly_billing_service_id'), 'monthly_billing', ['service_id'], unique=False) + op.create_index(op.f('uix_monthly_billing'), 'monthly_billing', ['service_id', 'month', 'year', 'notification_type'], unique=True) + + +def downgrade(): + op.drop_table('monthly_billing') diff --git a/tests/app/dao/test_monthly_billing.py b/tests/app/dao/test_monthly_billing.py new file mode 100644 index 000000000..f04fa79ca --- /dev/null +++ b/tests/app/dao/test_monthly_billing.py @@ -0,0 +1,33 @@ +import uuid + +import pytest +from sqlalchemy.exc import IntegrityError + +from app.dao.monthly_billing_dao import update_monthly_billing +from app.models import MonthlyBilling + + +def test_add_monthly_billing_only_allows_one_row_per_service_month_type(sample_service): + first = MonthlyBilling(id=uuid.uuid4(), + service_id=sample_service.id, + notification_type='sms', + month='January', + year='2017', + monthly_totals={'billing_units': 100, + 'rate': 0.0158}) + + second = MonthlyBilling(id=uuid.uuid4(), + service_id=sample_service.id, + notification_type='sms', + month='January', + year='2017', + monthly_totals={'billing_units': 50, + 'rate': 0.0162}) + + update_monthly_billing(first) + with pytest.raises(IntegrityError): + update_monthly_billing(second) + monthly = MonthlyBilling.query.all() + assert len(monthly) == 1 + assert monthly[0].monthly_totals == {'billing_units': 100, + 'rate': 0.0158}