feat: financial data retention & aggregation system

Add CleanupExpiredFinancialRecords to enforce HMRC + Limitation Act
compliance (7-year retention, 1-year post-anonymization buffer).

- financial_aggregates table: monthly totals by payment method/type (no PII)
- CleanupExpiredFinancialRecords(): aggregates expired payments/refunds,
  deletes granular records, idempotent via ON CONFLICT DO UPDATE
- Wired into GET /api/availability alongside existing cleanup functions
- 8 tests: 7yr expiry, 1yr buffer, 9yr override, aggregation totals,
  idempotency, active user protection, both-thresholds elapsed, refunds
- testdb.go: financial_aggregates in drop-order and truncate lists
- README + Technical Manual updated
This commit is contained in:
2026-06-05 16:37:04 +01:00
parent 06efdfdac0
commit f4a6033715
8 changed files with 820 additions and 5 deletions
+25
View File
@@ -1517,6 +1517,31 @@ CREATE TABLE refunds (
CREATE INDEX idx_refunds_payment ON refunds(payment_id);
CREATE INDEX idx_refunds_booking ON refunds(booking_id);
-- =======================================
-- FINANCIAL AGGREGATES TABLE
-- Monthly aggregated financial statistics (no PII)
-- Populated by CleanupExpiredFinancialRecords when granular records expire
-- Retention: replaces per-transaction records after MAX(created_at + 7 years, user_anonymized_at + 1 year)
-- =======================================
CREATE TABLE financial_aggregates (
month DATE PRIMARY KEY,
total_payments NUMERIC(12,2) NOT NULL DEFAULT 0,
total_refunds NUMERIC(12,2) NOT NULL DEFAULT 0,
total_square_fees NUMERIC(12,2) NOT NULL DEFAULT 0,
total_cash NUMERIC(12,2) NOT NULL DEFAULT 0,
total_online NUMERIC(12,2) NOT NULL DEFAULT 0,
total_in_person NUMERIC(12,2) NOT NULL DEFAULT 0,
total_discounts NUMERIC(12,2) NOT NULL DEFAULT 0,
total_giftcard NUMERIC(12,2) NOT NULL DEFAULT 0,
total_tips NUMERIC(12,2) NOT NULL DEFAULT 0,
total_deposits NUMERIC(12,2) NOT NULL DEFAULT 0,
total_balances NUMERIC(12,2) NOT NULL DEFAULT 0,
total_partials NUMERIC(12,2) NOT NULL DEFAULT 0,
booking_count INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- =======================================
-- AFFILIATE PAYOUTS TABLE
-- =======================================