Commit Graph

78 Commits

Author SHA1 Message Date
grabowski 6d0fb30545 Constrain date inputs to 4-digit years (fixes yyyyyy-mm-dd display)
Deploy to LXC / deploy (push) Successful in 1m56s
Validate / validate (push) Successful in 33s
Chrome/Blink renders <input type="date"> with a 6-digit year field
unless min/max attributes restrict the range. Added a root-layout
hook that auto-sets min=1900-01-01, max=2100-12-31 on every date
input on mount and after navigation — no need to edit 19 form files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 16:16:18 +07:00
grabowski 8376116765 Auto-resolve FX rate on account creation (base=1, else fetch from API)
Deploy to LXC / deploy (push) Successful in 1m56s
Validate / validate (push) Successful in 37s
Account creation no longer requires the user to enter an FX rate.
On create:
  - If account currency == company base → fxRateToBase = 1
  - Otherwise → fetchRate(accountCurrency, baseCurrency) from the
    fawazahmed0 FX API (same helper the daily scheduler uses)
  - Fallback to 1 if API call fails
The manual override field is still shown on the edit form for admin
corrections, and the daily scheduler keeps it fresh.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 15:57:08 +07:00
grabowski 7367aa9572 Add '+ New Package' button to expense detail packages section
Deploy to LXC / deploy (push) Successful in 1m56s
Validate / validate (push) Successful in 35s
Visible whenever the user can manage. Always routes to the package
creation page. The link-existing dropdown still shows when other
packages exist.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 14:21:57 +07:00
grabowski 7465b498e0 Move invoice upload + package linking to the expense detail page
Deploy to LXC / deploy (push) Successful in 1m56s
Validate / validate (push) Successful in 34s
List page expenses now show a "View details →" link that routes to
the detail page. The detail page gains:
  - Invoice file upload (with Paperless push if configured)
  - Paperless URL link field
  - Link / unlink packages to the expense (many-to-many)

Same actions exist on both pages for convenience, but the detail page
is the primary workspace for managing an expense.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 13:31:47 +07:00
grabowski 7fba11941f Fix double-counting: available = total (expenses already debit accounts)
Deploy to LXC / deploy (push) Successful in 1m56s
Validate / validate (push) Successful in 35s
The previous Remaining Budget card subtracted approved expenses from
the account balance sum — but postExpenseTransaction already posts
negative-amount rows to the ledger, so the balance sum already reflects
them. Replaced with:
  - Available Cash (= sum of account balances)
  - Allocated (with % progress bar)
  - Unallocated (cash not assigned to any project)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 13:22:16 +07:00
grabowski 94e38aca9c Redesign overview: income vs expenses split with net-position card
Deploy to LXC / deploy (push) Successful in 1m56s
Validate / validate (push) Successful in 36s
Hero row is now a two-column green/red split showing Income and
Expenses side-by-side, with a full-width Net Position card below that
colours green or red based on the sign. Budget KPIs (Remaining,
Total, Allocated) moved to a secondary row underneath.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 13:11:13 +07:00
grabowski 00b8b239e0 Add expense detail page with edit (audit-logged) and clickable rows on projects
Deploy to LXC / deploy (push) Successful in 1m56s
Validate / validate (push) Successful in 33s
New expense detail at /companies/[id]/expenses/[expenseId] with full
info, edit form for admin/manager/accountant, and audit log entry on
every edit (`expense_updated`). Project view expense rows are now
clickable and navigate to the detail page. Ledger re-posts
automatically if an approved expense's amount or account changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 13:05:17 +07:00
grabowski 26945285eb Show base-currency equivalent next to foreign-currency account balances
Deploy to LXC / deploy (push) Successful in 1m57s
Validate / validate (push) Successful in 34s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 12:55:37 +07:00
grabowski 2540a7603e Add Sales tab to primary company nav (admin/manager/accountant)
Deploy to LXC / deploy (push) Successful in 1m57s
Validate / validate (push) Successful in 37s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 12:49:20 +07:00
grabowski 0795d78bdf Add confirmed-sales income to budget and overview
Budget page load now computes per-project income (net of withholding)
from confirmed sales. Overview has a full-width Income KPI showing
total confirmed net revenue.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 12:48:06 +07:00
grabowski 1c15cbc36e Add sales CRUD with line items, taxes, withholding, and package linking
New routes: /companies/[id]/sales (list + create) and [saleId] (detail).
Per-line tax rate, single withholding % on sale. Computed totals:
subtotal, tax, gross, withholding, net receivable. Status flow:
draft → confirmed → voided. Packages linked via sale_packages junction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 12:46:05 +07:00
grabowski f56d4caec8 Link multiple packages to expenses via junction table
Added linkPackage/unlinkPackage actions and a collapsible package
checklist per expense. Linked packages display as clickable cyan chips
on the expense row.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 11:56:39 +07:00
grabowski 34aab722b4 Add expense invoice upload with Paperless push + paperless URL link
Expenses now show Pending Invoice badge when no file/link attached.
Upload action saves file via existing uploads helper, optionally
pushes to Paperless-ngx if PAPERLESS_URL + PAPERLESS_TOKEN env set.
Download endpoint serves attached invoice with attachment disposition.
Paperless URL link provides a zero-integration alternative.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 11:54:13 +07:00
grabowski bbfab9faaa Add expense invoice fields, sales tables, and Paperless env vars
Expenses now have invoiceFileUrl, invoiceFileName, paperlessUrl,
paperlessDocumentId for supplier invoice attachment.

New expense_packages junction links expenses to multiple packages.

New sales + sale_line_items + sale_packages tables for income tracking
with per-line tax rate and per-sale withholding rate.

Added saleStatusEnum and 4 audit events: expense_invoice_uploaded,
sale_created, sale_confirmed, sale_voided.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 11:51:18 +07:00
grabowski 84c8beca15 Auto-refresh FX rates daily from fawazahmed0/exchange-api
Deploy to LXC / deploy (push) Successful in 1m56s
Validate / validate (push) Successful in 33s
Scheduler checks every 15min; if 24h since last FX refresh, fetches
rates for all foreign-currency accounts and updates fxRateToBase.
Uses CDN primary + Cloudflare fallback with 10s timeout.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 16:36:17 +07:00
grabowski 34b1524d3a Add FX rate per account, convert foreign balances to base currency in budget
Deploy to LXC / deploy (push) Successful in 1m55s
Validate / validate (push) Successful in 34s
Accounts now have fxRateToBase (default 1.0). The budget total query
multiplies each transaction by the account's rate, so a USD account
with rate 34.5 contributes correctly to the THB-denominated budget.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 16:24:00 +07:00
grabowski bc0699a992 Derive total budget from account balances instead of manual field
Deploy to LXC / deploy (push) Successful in 1m55s
Validate / validate (push) Successful in 38s
Total budget is now sum(account transaction amounts) across all
non-deleted accounts. Removed the manual 'Add Budget' action and form.
Budget page is now read-only for the total; allocations still work.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 16:16:05 +07:00
grabowski 283f0d4dd1 Add invoice linking on expenses: optional FK, dropdown on add form, clickable chip
Deploy to LXC / deploy (push) Successful in 1m56s
Validate / validate (push) Successful in 32s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 15:46:20 +07:00
grabowski 0710d63cc1 Add inline expense form on expenses tab with company-wide (General) option
Deploy to LXC / deploy (push) Successful in 1m56s
Validate / validate (push) Successful in 37s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 15:26:18 +07:00
grabowski 5ff4f07ff4 Add invoice void with ledger reversal, required reason, and voided badge
Deploy to LXC / deploy (push) Successful in 1m56s
Validate / validate (push) Successful in 48s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 15:18:35 +07:00
grabowski 0906a448b3 Add procedure instance detail with step completion and auto-complete
Deploy to LXC / deploy (push) Successful in 1m55s
Validate / validate (push) Successful in 33s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 14:58:10 +07:00
grabowski 65cee9855c Add procedures templates, step management, and nav tab
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 14:51:29 +07:00
grabowski f1dd6877f6 Add procedures schema: templates, steps, instances, 7 audit events
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 14:47:36 +07:00
grabowski 8a23a849da Fix CSP: allow unsafe-inline scripts for SvelteKit hydration
Deploy to LXC / deploy (push) Successful in 1m56s
Validate / validate (push) Successful in 38s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 14:32:12 +07:00
grabowski b4eda2d553 Fix security audit findings: auth scoping, OIDC hardening, CSP, file download
Deploy to LXC / deploy (push) Successful in 1m56s
Validate / validate (push) Successful in 33s
C3: Budget allocation now verifies project belongs to company
M4: Expense approve/reject scoped by company via project join
H2: OIDC cookies get secure flag on HTTPS
H3: OIDC auto-link only when email_verified by provider
H4: Content-Security-Policy + X-Content-Type-Options in hooks
M7: SSRF favicon redirect depth capped at 3
M2: File downloads use attachment disposition (not inline)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 14:18:28 +07:00
grabowski dbfd229ba8 Link service accounts to recurring bills with dropdown and display chip
Deploy to LXC / deploy (push) Successful in 2m1s
Validate / validate (push) Successful in 35s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 13:58:43 +07:00
grabowski 1ce614186d Add service accounts page with CRUD, filter pills, and nav tab
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 13:52:33 +07:00
grabowski 493ffa4097 Add service accounts schema, enum, audit events, recurringBills FK
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 13:49:16 +07:00
grabowski a1fffebbf6 Add CI/CD deploy setup doc
Validate / validate (push) Successful in 31s
Deploy to LXC / deploy (push) Successful in 1m55s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 16:52:46 +07:00
grabowski 1fed8ee920 Add Gitea Actions deploy workflow
Mirrors the buildfor_life_repair workflow: SSH into LXC, reset working
tree, pull, npm ci, build, db:push, restart the buildfor-life-budget
systemd service, health-check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 16:49:33 +07:00
grabowski 639c261995 Regenerate deployment architecture diagram via beautiful-mermaid
Validate / validate (push) Successful in 30s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 16:42:08 +07:00
grabowski 5451a591ad Add deployment doc: Caddy + Tor + Yggdrasil + NetBird + external TLS proxy
Validate / validate (push) Successful in 32s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 16:36:49 +07:00
grabowski fef69b653c Add inline rename/edit on project detail page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 16:09:52 +07:00
grabowski 57f3d42133 Redesign company overview: 4 compact KPIs, side-by-side projects + recent expenses
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 16:06:19 +07:00
grabowski f51e156539 Restructure company nav: 8 primary tabs + HR/Ops/Admin dropdowns with active highlight
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 15:59:25 +07:00
grabowski 03526ff3b9 Restore pointer cursor on buttons (Tailwind v4 Preflight reset)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 15:35:46 +07:00
grabowski b43924f527 Add recurring bills UI with full CRUD, filters, overdue highlight, amount override
Validate / validate (push) Successful in 33s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 15:23:53 +07:00
grabowski b611207d25 Add recurring bills poster, scheduler boot, and manual run stub
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 15:17:38 +07:00
grabowski bd87cd09f5 Add recurring bills schema and cycle math helper
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 15:13:38 +07:00
grabowski 70bb5954a0 Make entire account card clickable to open detail
Stretched-link pattern: absolute-positioned overlay anchor covers the
card; action controls (edit/archive/delete + inline forms) get
`relative z-10` so they float above and stay clickable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 14:25:03 +07:00
grabowski c1a575241f Fix zero balance on accounts list page
The correlated subquery in the SELECT was returning 0 for every row.
Replaced with a separate grouped-sum query joined in JS — same data, more
reliable SQL generation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 14:17:33 +07:00
grabowski 77c5d72e43 Reconciliation link, account CSVs in export, drop legacy bank/card tables
Validate / validate (push) Successful in 31s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 14:06:53 +07:00
grabowski 0d4fdb6fd7 Add account detail page with transaction history, filters, and CSV export
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 13:58:44 +07:00
grabowski 3a095851e9 Auto-post expenses and invoice payments to accounts ledger
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:04:15 +07:00
grabowski d75fe6ed95 Add opening balance, manual transactions, and cross-currency transfers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:54:10 +07:00
grabowski aea6dbc06e Add accounts list page with CRUD, Accounts nav tab, profile deprecation banner
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:50:40 +07:00
grabowski 57e72e5b6c Add companyAccounts schema, ledger helper, legacy migration script
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:34:57 +07:00
grabowski 2c2353e2e7 Wire favicon fetch and refresh action into links page
Validate / validate (push) Successful in 27s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 11:56:31 +07:00
grabowski 1ef68a4d0d Add personal bookmarks CRUD on links page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 11:54:11 +07:00
grabowski ca0335671c Add company links page with CRUD and Links nav tab
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 11:49:04 +07:00