From 31526f41f3ec7f1d92dba2a9d7e0e1224fba9c51 Mon Sep 17 00:00:00 2001 From: Remi Rampin Date: Tue, 10 May 2022 20:48:51 -0400 Subject: [PATCH] Change schema: just record numbers per family --- france/france_rsvp/database.py | 96 +++++++++++++--------------------- france/schema.sql | 13 ++--- france/test-data.sql | 16 +++--- 3 files changed, 52 insertions(+), 73 deletions(-) diff --git a/france/france_rsvp/database.py b/france/france_rsvp/database.py index d0a1feb..9fd37c2 100644 --- a/france/france_rsvp/database.py +++ b/france/france_rsvp/database.py @@ -22,78 +22,56 @@ def get_db(): db.close() -def get_people_and_replies(code): +def get_name_and_replies(code): with get_db() as db: - return list(db.execute( + rows = db.execute( '''\ + WITH latest_reply AS ( + SELECT + adults, children + FROM replies + WHERE family_code = :code + ORDER BY date DESC + LIMIT 1 + ) SELECT - persons.id, persons.name, - ( - SELECT rsvp FROM replies - WHERE - replies.person_id = persons.id - AND replies.date = ( - SELECT MAX(date) - FROM replies - WHERE person_id = persons.id - ) - ) AS rsvp - FROM - persons - WHERE - persons.code = :code; + families.name, + (SELECT adults FROM latest_reply) AS adults, + (SELECT children FROM latest_reply) AS children + FROM families + WHERE families.code = :code + LIMIT 1; ''', dict(code=code), - )) - - -def record_reply(code, persons): - assert isinstance(persons, dict) - with get_db() as db: - # Check the IDs of people match - expected_people_ids = set( - row[0] - for row in db.execute( - '''\ - SELECT - id - FROM - persons - WHERE - code = :code; - ''', - dict(code=code), - ) ) - if not expected_people_ids: - logger.warning("Got reply with invalid code %r", code) + try: + return next(rows) + except StopIteration: raise ValueError("Invalid code") - for person_id in persons.keys(): - if person_id not in expected_people_ids: - logger.warning( - "Got invalid person id=%d for code %r", - person_id, - code, - ) - raise ValueError("Invalid person") + +def record_reply(code, adults, children): + assert isinstance(adults, int) + assert isinstance(children, int) + assert 0 <= adults and 0 <= children + assert adults > 0 or children == 0 + + with get_db() as db: # Insert update cursor = db.cursor() date = datetime.utcnow() - for person_id, rsvp in persons.items(): - if rsvp not in ('yes', 'no'): - raise ValueError("Invalid rsvp %r", rsvp) - cursor.execute( - '''\ - INSERT INTO replies(person_id, date, rsvp) - VALUES(:id, :date, :rsvp); - ''', - dict(id=person_id, date=date, rsvp=rsvp), - ) + cursor.execute( + '''\ + INSERT INTO replies(family_code, date, adults, children) + VALUES(:code, :date, :adults, :children); + ''', + dict(code=code, date=date, adults=adults, children=children), + ) cursor.execute('COMMIT;') logger.info( - "Recorded update for code=%r date=%r persons: %s", + "Recorded update for code=%r date=%r adults=%d children=%d", code, date, - ' '.join('%d=%s' % p for p in sorted(persons.items())), + adults, + children, ) diff --git a/france/schema.sql b/france/schema.sql index 1b03203..1eca389 100644 --- a/france/schema.sql +++ b/france/schema.sql @@ -1,11 +1,12 @@ -CREATE TABLE persons( - id INTEGER PRIMARY KEY, - code VARCHAR(8) NOT NULL, - name TEXT NOT NULL +CREATE TABLE families( + code VARCHAR(8) PRIMARY KEY, + name TEXT ); CREATE TABLE replies( - person_id INTEGER NOT NULL, + family_code VARCHAR(8) NOT NULL, date DATETIME NOT NULL, - rsvp VARCHAR(8) NOT NULL + adults INTEGER NOT NULL, + children INTEGER NOT NULL, + FOREIGN KEY(family_code) REFERENCES families(code) ); diff --git a/france/test-data.sql b/france/test-data.sql index a84e84d..fc9582f 100644 --- a/france/test-data.sql +++ b/france/test-data.sql @@ -1,9 +1,9 @@ -INSERT INTO persons(id, code, name) VALUES - (1, 'aaaa', 'one'), - (2, 'aaaa', 'two'), - (3, 'bbbb', 'three'); +INSERT INTO families(code, name) VALUES + ('aaaa', 'one'), + ('bbbb', 'two'), + ('cccc', 'three'); -INSERT INTO replies(person_id, date, rsvp) VALUES - (1, '2022-05-10 20:37:39', 'yes'), - (2, '2022-05-10 20:37:39', 'yes'), - (1, '2022-05-10 23:55:55', 'no'); +INSERT INTO replies(family_code, date, adults, children) VALUES + ('aaaa', '2022-05-10 20:37:39', 2, 0), + ('aaaa', '2022-05-10 23:55:55', 0, 0), + ('bbbb', '2022-05-10 20:22:11', 2, 1);