add billable_units column to notifications table

this replaces content_char_count, by performing the additional
steps to calculated billable units at insert time, rather than
read time. This means we can take into account whether the
service was in research mode or using a test api key when the
notification was sent :tada
This commit is contained in:
Leo Hemsted
2016-08-03 14:27:58 +01:00
parent 4ca23b2282
commit 2793541b9c
3 changed files with 115 additions and 1 deletions

View File

@@ -0,0 +1,113 @@
"""empty message
Revision ID: 0045_billable_units
Revises: 0044_jobs_to_notification_hist
Create Date: 2016-08-02 16:36:42.455838
"""
# revision identifiers, used by Alembic.
revision = '0045_billable_units'
down_revision = '0044_jobs_to_notification_hist'
from alembic import op
import sqlalchemy as sa
from sqlalchemy.orm.session import Session
from app.models import Service
import logging
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
def upgrade():
op.add_column('notifications', sa.Column('billable_units', sa.Integer()))
op.add_column('notification_history', sa.Column('billable_units', sa.Integer()))
op.execute('update notifications set billable_units = 0')
op.execute('update notification_history set billable_units = 0')
op.alter_column('notifications', 'billable_units', nullable=False)
op.alter_column('notification_history', 'billable_units', nullable=False)
conn = op.get_bind()
# caveats
# only adjusts notifications for services that have never been in research mode. On live, research mode was
# limited to only services that we have set up ourselves so deemed this acceptable.
billable_services = conn.execute('''
SELECT id FROM services_history WHERE id not in (select id from services_history where research_mode)
''')
# set to 'null' if there are no billable services so we don't get a syntax error in the update statement
service_ids = ','.join("'{}'".format(service.id) for service in billable_services) or 'null'
update_statement = '''
UPDATE {}
SET billable_units = (
CASE
WHEN content_char_count <= 160 THEN 1
ELSE ceil(content_char_count::float / 153::float)
END
)
WHERE content_char_count is not null
AND service_id in ({})
AND notification_type = 'sms'
'''
conn = op.get_bind()
conn.execute(update_statement.format('notifications', service_ids))
conn.execute(update_statement.format('notification_history', service_ids))
op.drop_column('notifications', 'content_char_count')
op.drop_column('notification_history', 'content_char_count')
def downgrade():
op.add_column('notifications', sa.Column(
'content_char_count',
sa.INTEGER(),
autoincrement=False,
nullable=True)
)
op.add_column('notification_history', sa.Column(
'content_char_count',
sa.INTEGER(),
autoincrement=False,
nullable=True)
)
conn = op.get_bind()
# caveats
# only adjusts notifications for services that have never been in research mode. On live, research mode was
# limited to only services that we have set up ourselves
billable_services = conn.execute('''
SELECT id FROM services_history WHERE id not in (select id from services_history where research_mode)
''')
# set to 'null' if there are no billable services so we don't get a syntax error in the update statement
service_ids = ','.join("'{}'".format(service.id) for service in billable_services) or 'null'
billable_services = session.query(Service).filter(Service.research_mode == False).all()
# caveats:
# only approximates character counts - billable * 153 to get at least a decent ballpark
# research mode messages assumed to be one message length
update_statement = '''
UPDATE {table}
SET content_char_count = GREATEST(billable_units, 1) * 150
)
WHERE service_id in ({})
AND notification_type = 'sms'
'''
conn = op.get_bind()
conn.execute(update_statement.format(
'notifications',
services=','.join(repr(str(service.id)) for service in billable_services)
))
conn.execute(update_statement.format(
'notification_history',
services=','.join(repr(str(service.id)) for service in billable_services)
))
op.drop_column('notifications', 'billable_units')
op.drop_column('notification_history', 'billable_units')