Commit Graph

15 Commits (main)

Author SHA1 Message Date
Talha Ahmed 367a64b59d Audit trail: record who uploads, processes, exports, deletes; admin-only log view
Deploy to S3 / deploy (push) Successful in 23s Details
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>
2026-09-01 21:01:58 +05:00
Talha Ahmed f46fc69562 Convert at the transaction date's FX rate, auto-fetched from the API
Deploy to S3 / deploy (push) Successful in 28s Details
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>
2026-08-25 15:23:59 +05:00
Talha Ahmed c2e1840f5b Aging report: selectable band width (weekly / monthly / 6 months / yearly)
Deploy to S3 / deploy (push) Successful in 29s Details
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>
2026-08-24 22:09:55 +05:00
Talha Ahmed 04dfbcf0e6 Import bank disbursements Excel as payout receipts
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>
2026-08-24 22:09:49 +05:00
Talha Ahmed 4ec322da71 Forgot-password: unregistered emails get an explicit 404
Deliberate for the small internal team - a clear 'is not a registered
account' beats the anti-enumeration non-answer that read as success.
Successful sends now name the address and expiry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 22:05:34 +05:00
Talha Ahmed 8677117e66 Forgot-password is now a 3-step wizard: email -> verify code -> new password
New POST /api/auth/verify-code checks the code without consuming it
(wrong guesses still count toward the 5-attempt lockout); the password
fields only appear after the code verifies. Email step hints that codes
go only to registered @utopiabrands.com accounts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 21:49:29 +05:00
Talha Ahmed 984069b368 Password codes via the company Mail API (primary), SMTP stays fallback
Same internal mail service the TikTok dashboard uses for its
verification codes: bearer-token multipart POST (stdlib urllib, no new
deps). Configured with AR_MAIL_API_URL/TOKEN; credentials live only in
the gitignored env files. Live send verified ({status:sent}).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 19:54:50 +05:00
Talha Ahmed 2aed450f4c Password updates via emailed 6-digit code
New flow (active once AR_SMTP_* is configured; hidden otherwise):
- POST /api/auth/request-code emails a code to the account address
  (usernames are emails). HMAC-stored, 10-min expiry, single-use,
  5-attempt lockout, 60s resend throttle, no user enumeration.
- POST /api/auth/reset-password sets the new password with the code —
  works signed-in (Settings) and from the login screen (Forgot
  password?), so users can self-recover without the admin.
- Mailer: stdlib smtplib (STARTTLS/SSL, certifi CA bundle); SMTP
  settings documented in .env templates.
- Settings switches to the code flow when email is on; the
  current-password form remains the fallback.

Note: CRAI_Report was checked as the reference for code-sending — it
has no email/OTP functionality, so this is a fresh implementation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 19:35:07 +05:00
Talha Ahmed 11bceedaca Add change-password: users update their own password from Settings
POST /api/auth/change-password requires the current password; admins
still reset others via manage.py set-password. UI on the Settings page
(signed-in users only) with match/length validation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 19:07:28 +05:00
Talha Ahmed d823a45cb2 Production readiness: month separation, auth, FX service, AWS deployment
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>
2026-08-19 18:46:47 +05:00
Talha Ahmed c322437599 fix isuses 2026-08-18 19:37:57 +05:00
sheheryarsoomro12 60c4489415 New 2026-08-17 15:41:46 +05:00
sheheryarsoomro12 bacd13c8b5 New 2026-08-04 11:41:50 +05:00
sheheryarsoomro12 b795d51aa7 Enhance API functionality and session management 2026-08-03 11:38:48 +05:00
sheheryarsoomro12 bf0cdc14c3 Initial commit: AR aging app with root gitignore.
Ignore financial workbooks, OS junk, and build artifacts; track app source and project skills.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-29 18:07:21 +05:00