feat(models): settle_transaction op, alerts_pubkey, operator_notified_at (m017)

ADR-005 §6 groundwork. settle_transaction is a machine-wide op like
resume_cash_out; it carries the machine txid it closes and the operator's
provenance note. super_config.alerts_pubkey overrides where owed-cash
alerts go; dca_settlements.operator_notified_at stops a report resend
from re-alerting.
This commit is contained in:
Padreug 2026-10-10 22:26:45 +02:00
commit 786857f568
4 changed files with 106 additions and 6 deletions

15
crud.py
View file

@ -739,6 +739,15 @@ async def create_settlement_idempotent(
return await get_settlement(settlement_id)
async def mark_settlement_notified(settlement_id: str) -> None:
"""The operator alert for this settlement went out (ADR-005 §6)."""
await db.execute(
"UPDATE spirekeeper.dca_settlements SET operator_notified_at = :now "
"WHERE id = :id AND operator_notified_at IS NULL",
{"id": settlement_id, "now": datetime.now()},
)
async def get_settlement_by_txid(
machine_id: str, bitspire_txid: str
) -> DcaSettlement | None:
@ -1927,9 +1936,9 @@ async def create_cassette_op(
"""
INSERT INTO spirekeeper.cassette_ops
(id, machine_id, position, op_type, bills, count, denomination,
created_at, created_by)
txid, note, created_at, created_by)
VALUES (:id, :machine_id, :position, :op_type, :bills, :count,
:denomination, :created_at, :created_by)
:denomination, :txid, :note, :created_at, :created_by)
""",
{
"id": op_id,
@ -1939,6 +1948,8 @@ async def create_cassette_op(
"bills": data.bills,
"count": data.count,
"denomination": data.denomination,
"txid": data.txid,
"note": data.note,
"created_at": datetime.now(),
"created_by": created_by,
},