From 1b5aaed10a2a0eb05aeb1c52679d6948e3a985e7 Mon Sep 17 00:00:00 2001 From: Katie Smith Date: Mon, 19 Feb 2018 14:00:33 +0000 Subject: [PATCH] Create DAO for daily sorted letter model --- app/dao/daily_sorted_letter_dao.py | 37 +++++++++++++++ tests/app/dao/test_daily_sorted_letter_dao.py | 47 +++++++++++++++++++ tests/app/db.py | 16 ++++++- 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 app/dao/daily_sorted_letter_dao.py create mode 100644 tests/app/dao/test_daily_sorted_letter_dao.py diff --git a/app/dao/daily_sorted_letter_dao.py b/app/dao/daily_sorted_letter_dao.py new file mode 100644 index 000000000..3afad4b2a --- /dev/null +++ b/app/dao/daily_sorted_letter_dao.py @@ -0,0 +1,37 @@ +from datetime import datetime + +from sqlalchemy.dialects.postgresql import insert + +from app import db +from app.dao.dao_utils import transactional +from app.models import DailySortedLetter + + +def dao_get_daily_sorted_letter_by_billing_day(billing_day): + return DailySortedLetter.query.filter_by( + billing_day=billing_day + ).first() + + +@transactional +def dao_create_or_update_daily_sorted_letter(new_daily_sorted_letter): + ''' + This uses the Postgres upsert to avoid race conditions when two threads try and insert + at the same row. The excluded object refers to values that we tried to insert but were + rejected. + http://docs.sqlalchemy.org/en/latest/dialects/postgresql.html#insert-on-conflict-upsert + ''' + table = DailySortedLetter.__table__ + stmt = insert(table).values( + billing_day=new_daily_sorted_letter.billing_day, + unsorted_count=new_daily_sorted_letter.unsorted_count, + sorted_count=new_daily_sorted_letter.sorted_count) + stmt = stmt.on_conflict_do_update( + index_elements=[table.c.billing_day], + set_={ + 'unsorted_count': table.c.unsorted_count + stmt.excluded.unsorted_count, + 'sorted_count': table.c.sorted_count + stmt.excluded.sorted_count, + 'updated_at': datetime.utcnow() + } + ) + db.session.connection().execute(stmt) diff --git a/tests/app/dao/test_daily_sorted_letter_dao.py b/tests/app/dao/test_daily_sorted_letter_dao.py new file mode 100644 index 000000000..2a4ceb318 --- /dev/null +++ b/tests/app/dao/test_daily_sorted_letter_dao.py @@ -0,0 +1,47 @@ +from datetime import date + +from app.dao.daily_sorted_letter_dao import ( + dao_create_or_update_daily_sorted_letter, + dao_get_daily_sorted_letter_by_billing_day, +) +from app.models import DailySortedLetter +from tests.app.db import create_daily_sorted_letter + + +def test_dao_get_daily_sorted_letter_by_billing_day(notify_db, notify_db_session): + billing_day = date(2018, 2, 1) + other_day = date(2017, 9, 8) + + daily_sorted_letters = create_daily_sorted_letter(billing_day=billing_day) + + assert dao_get_daily_sorted_letter_by_billing_day(billing_day) == daily_sorted_letters + assert not dao_get_daily_sorted_letter_by_billing_day(other_day) + + +def test_dao_create_or_update_daily_sorted_letter_creates_a_new_entry(notify_db, notify_db_session): + billing_day = date(2018, 2, 1) + dsl = DailySortedLetter(billing_day=billing_day, unsorted_count=2, sorted_count=0) + dao_create_or_update_daily_sorted_letter(dsl) + + daily_sorted_letter = dao_get_daily_sorted_letter_by_billing_day(billing_day) + + assert daily_sorted_letter.billing_day == billing_day + assert daily_sorted_letter.unsorted_count == 2 + assert daily_sorted_letter.sorted_count == 0 + assert not daily_sorted_letter.updated_at + + +def test_dao_create_or_update_daily_sorted_letter_updates_an_existing_entry( + notify_db, + notify_db_session +): + create_daily_sorted_letter(unsorted_count=2, sorted_count=3) + + dsl = DailySortedLetter(billing_day=date(2018, 1, 18), unsorted_count=5, sorted_count=17) + dao_create_or_update_daily_sorted_letter(dsl) + + daily_sorted_letter = dao_get_daily_sorted_letter_by_billing_day(dsl.billing_day) + + assert daily_sorted_letter.unsorted_count == 7 + assert daily_sorted_letter.sorted_count == 20 + assert daily_sorted_letter.updated_at diff --git a/tests/app/db.py b/tests/app/db.py index 6a09413a8..b159976da 100644 --- a/tests/app/db.py +++ b/tests/app/db.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, date import uuid from app import db @@ -9,6 +9,7 @@ from app.dao.service_sms_sender_dao import update_existing_sms_sender_with_inbou from app.dao.invited_org_user_dao import save_invited_org_user from app.models import ( ApiKey, + DailySortedLetter, InboundSms, InboundNumber, Job, @@ -506,3 +507,16 @@ def create_invited_org_user(organisation, invited_by, email_address='invite@exam ) save_invited_org_user(invited_org_user) return invited_org_user + + +def create_daily_sorted_letter(billing_day=date(2018, 1, 18), unsorted_count=0, sorted_count=0): + daily_sorted_letter = DailySortedLetter( + billing_day=billing_day, + unsorted_count=unsorted_count, + sorted_count=sorted_count + ) + + db.session.add(daily_sorted_letter) + db.session.commit() + + return daily_sorted_letter