citi-alerts/db/notification.py

191 lines
5.5 KiB
Python

from dataclasses import dataclass
from datetime import datetime
import logging
import sqlite3
from typing import Iterable, Tuple
from db.transaction import Transaction
@dataclass(frozen=True)
class Notification:
id: int
id_transaction: int
user: str
pushover_receipt: str
acknowledged: bool
expired: bool
ts_update: datetime
ts_insert: datetime
class NotificationManager:
def __init__(self, log: logging.Logger, db_conn: sqlite3.Connection):
self.__log = log
self.__db_conn = db_conn
def insert_notification(self, notification: Notification) -> Notification:
now = datetime.now()
result = self.__db_conn.execute(
"""
INSERT INTO notification (
id_transaction,
user,
pushover_receipt,
acknowledged,
expired,
ts_update,
ts_insert
) VALUES (
?,
?,
?,
?,
?,
?,
?
) RETURNING id;
""",
(
notification.id_transaction,
notification.user,
notification.pushover_receipt,
notification.acknowledged,
notification.expired,
now.strftime("%s"),
now.strftime("%s"),
),
).fetchone()
self.__db_conn.commit()
return Notification(
id=result[0],
id_transaction=notification.id_transaction,
user=notification.user,
pushover_receipt=notification.pushover_receipt,
acknowledged=notification.acknowledged,
expired=notification.expired,
ts_update=now,
ts_insert=now,
)
def expire_notification(self, notification_id: int) -> Notification:
row = self.__db_conn.execute(
"""
UPDATE notification
SET expired = TRUE, ts_update = strftime('%s')
WHERE id = ?
RETURNING
id_transaction,
user,
pushover_receipt,
acknowledged,
ts_update,
ts_insert
""",
(notification_id,),
).fetchone()
self.__db_conn.commit()
return Notification(
id=notification_id,
id_transaction=row[0],
user=row[1],
pushover_receipt=row[2],
acknowledged=row[3],
expired=True,
ts_insert=datetime.fromtimestamp(row[4]),
ts_update=datetime.fromtimestamp(row[5]),
)
def acknowledge_notification(self, notification_id: int) -> Notification:
row = self.__db_conn.execute(
"""
UPDATE notification
SET acknowledged = TRUE, ts_update = strftime('%s')
WHERE id = ?
RETURNING
id_transaction,
user,
pushover_receipt,
acknowledged,
ts_update,
ts_insert
""",
(notification_id,),
).fetchone()
self.__db_conn.commit()
return Notification(
id=notification_id,
id_transaction=row[0],
user=row[1],
pushover_receipt=row[2],
acknowledged=row[3],
expired=True,
ts_insert=datetime.fromtimestamp(row[4]),
ts_update=datetime.fromtimestamp(row[5]),
)
def list_unacknowledged_transactions_with_notifications(self) -> Iterable[Tuple[Transaction, Notification]]:
result = self.__db_conn.execute(
"""
SELECT
t.id,
t.email_message_id,
t.amount,
t.card_ending_in,
t.merchant,
t.date,
t.time,
t.acknowledged,
t.ts_update,
t.ts_insert,
n.id,
n.id_transaction,
n.user,
n.pushover_receipt,
n.acknowledged,
n.expired,
n.ts_update,
n.ts_insert
FROM "transaction" AS t
JOIN notification AS n
ON t.id = n.id_transaction
WHERE
t.acknowledged = FALSE AND
n.expired = FALSE AND
n.acknowledged = FALSE
GROUP BY t.id
HAVING n.id = MAX(n.id)
""",
)
for row in result:
yield (
Transaction(
id=row[0],
email_message_id=row[1],
amount=row[2],
card_ending_in=row[3],
merchant=row[4],
date=row[5],
time=row[6],
acknowledged=row[7],
ts_update=datetime.fromtimestamp(row[8]),
ts_insert=datetime.fromtimestamp(row[9]),
),
Notification(
id=row[10],
id_transaction=row[11],
user=row[12],
pushover_receipt=row[13],
acknowledged=row[14],
expired=row[15],
ts_update=datetime.fromtimestamp(row[16]),
ts_insert=datetime.fromtimestamp(row[17]),
),
)