Deploy to S3 / deploy (push) Successful in 23sDetails
Every business action now lands in a new append-only audit_log table with the
verified signed-in identity: logins, closing create/delete/reopen, file upload
(incl. replacements) and delete, processing runs, export generation and
downloads. Rows carry no FK so history survives a closing's deletion.
Admins (new users.is_admin flag, granted via `manage.py set-admin <username>`)
can read it at /api/audit and in a new Audit Log page in the sidebar; everyone
else gets 403 and no nav entry. login/me responses now carry is_admin.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deploy to S3 / deploy (push) Successful in 28sDetails
Processing now seeds fx_rates_daily from the provider (Frankfurter) over the
closing's actual transaction span, and the AR Ledger / daily FX table convert
each dated movement at the rate effective on its own date: exact fixing, else
the previous banking day's fixing (weekends/holidays), else the month rate.
Manual daily overrides are preserved by the auto-fetch and never carry forward.
Provider outages never block the close - they surface as a warning exception.
New AR_FX_AUTO_DAILY env toggle (default on; forced off in tests).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Deploy to S3 / deploy (push) Successful in 29sDetails
GET /sessions/{id}/aging?scheme=... rebands the same days-past-due data;
the Aging page gets a segmented filter and renders whatever bands the API
returns. Totals tie to the headline receivable in every scheme. Also carries
the alias-guard test for the reference-workbook headers.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
POST /sessions/{id}/payouts/receipts/import parses the bank workbook (Payouts
sheet), matches deposits to the closing's Transfer payouts by marketplace +
date window + amount (currency-aware: converted deposits match by date only),
and returns a preview; the UI applies selected matches through the existing
PUT so upsert/reprocess semantics stay in one place. Replaces hand-typing
bank dates in the Bank receipts grid.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Month management & data separation:
- Fix double-count bug: re-uploading a filename updates the existing
session_files row in place; identical content (sha256) is skipped —
a closing can never parse the same file twice
- Guard against duplicate closings per reporting month (409 unless
explicitly overridden); dashboard flags duplicates
- Default new closings to carry-forward openings; month switcher in the
closing header; publish state visible everywhere; Accounts Summary
lists unpublished months with the reason instead of dropping them
- Completed closings are locked read-only with an explicit reopen
Authentication (stdlib only, no new deps):
- Per-user login (scrypt + HMAC tokens), AR_AUTH=auto turns on with the
first user; manage.py add-user/set-password/deactivate-user
- Verified identity feeds reviewed_by/approved_by/confirmed_by
Exchange rates:
- fx_service with provider abstraction: Frankfurter (free, keyless,
ECB) default, exchangerate-api stub; month-end + daily fetch
endpoints and UI buttons; rates arrive unconfirmed so Control C5
still gates the close; cache table; certifi CA bundle
Deployment & hardening:
- Production Docker stack: caddy (auto-HTTPS) + nginx + single-worker
backend + mysql:8.4; per-context .dockerignore (images carry no
financial data); .env.example with local+production sections
- deploy/DEPLOY.md runbook + nightly S3 backup script
- Stale-job recovery on startup; export retention (AR_RETENTION_DAYS);
deep /api/health; request/job logging; Gitea Actions CI
- Repo reorganized: launchers in scripts/, dated lowercase docs,
root README, .gitattributes for deterministic line endings
Tests: 152 passed (25+ new: dedup, month locking, auth, FX orientation)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>