Commit Graph

151 Commits

Author SHA1 Message Date
admin 2c50e96fbd Email: default automated sender to notifications@avriamail.com
The retired no-reply@avriamail.com had no email_senders row, so the
queue dispatcher 500'd on every run. Point DEFAULT_AUTOMATED_FROM at
notifications@avriamail.com (the sole remaining sender). The
AUTOMATED_EMAIL_FROM secret was set to match and the function deployed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 12:03:18 -04:00
admin 9aa1f94eb4 Accounting: categorize register transactions from Buildium GL lines
partymap mode now also resolves each Buildium transaction's dominant
income/expense account (from its Journal lines) to a local category, staged
alongside the party. Used to backfill accounting.transactions.category on the
materialized bank register. Applied to Village Woods.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 20:16:00 -04:00
admin 0faee9994d Accounting: partymap mode + register payee backfill
Adds "partymap" mode to buildium-payee-backfill: resolves each Buildium GL
transaction to a local vendor (by name) / customer (by unit_number) and stages
it in accounting.buildium_party_map. The materialized bank register
(accounting.transactions) is then backfilled in SQL by bridging each register
row to its journal-entry bank line (bijective row-number pairing within
date/amount/side groups, so same-amount/same-day payments each get a distinct
owner) and pulling the resolved vendor/customer + name from staging.

Applied to all five Buildium-imported associations (Village Woods, Bent Oak,
Village Grove, Bridgewater, Casuarina).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 19:44:42 -04:00
admin 12e551f578 Accounting: add account/txn detail modes to buildium-payee-backfill
account mode lists a single account's ledger entries; txn mode reconstructs
one transaction's full double-entry across accounts. Used to trace the VW
5098 discrepancy to a missing 2025-12-31 reserve-funded reclass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 17:27:00 -04:00
admin e999890ee5 Accounting: add report mode to buildium-payee-backfill
report mode pulls /v1/generalledger signed balances per account for the
window so imported books can be diffed against Buildium's authoritative GL
to verify completeness.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 17:18:34 -04:00
admin 3a7e08fb78 Accounting: buildium-payee-backfill edge function
Re-pulls Buildium GL transactions and backfills payor/payee names onto
imported journal_entries.description (matched by external_id). Vendor for
Bill/Check/EFT via PaymentDetail.Payee; owner for Charge/Payment/ApplyDeposit
resolved from UnitId via /v1/associations/owners. Idempotent; modes
sample/dry/apply. Used to backfill Village Woods.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 17:12:00 -04:00
admin 0eaf3efb4f Accounting: surface Recurring from Journal Entries & Bills pages
Add a 'Recurring' button to the Journal Entries and Bills page headers
that links to the Recurring (Bills & Journals) page, and rename the
sidebar item so it's clear it covers journals too. Improves discovery —
users looking for recurring journals on the Journal Entries page now have
a direct link.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:43:25 -04:00
admin 10cd24e738 Bank feeds: replace Plaid with Stripe Financial Connections
Swap the bank-linking + transaction-download integration from Plaid to
Stripe Financial Connections (you're already on Stripe for payments).

- accounting.stripe_bank_connections table (mirrors plaid_connections)
- stripe-financial-connections edge function: create_session / save_account
  / sync / disconnect, using per-association keys from stripe_account_mappings
  (handles connected accounts via Stripe-Account + stripeAccount on the client)
- lib/stripeBank.ts: client wrappers + the Stripe.js collectFinancialConnections
  Accounts flow
- AccountingBankingPage: Connect/Sync/Disconnect now drive Stripe FC; removed
  react-plaid-link usage and the PlaidLinkButton
- Integrations page wording updated
- Imported transactions land uncategorised in the bank feed (credit/debit by
  amount sign) for matching, same as before

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 00:27:05 -04:00
admin 266a99d4b2 Accounting: recurring bills & journal entries
Add accounting.recurring_templates (bill|journal) with a schedule
(frequency/interval/day-of-month/start/end). New generate_due_recurring()
materialises real bills (-> A/P) and journal entries on cadence — catching
up any missed periods — posting through existing triggers. Runs nightly via
pg_cron ('accounting-recurring-daily') and on demand from a new Recurring
page ('Generate due now'). Page lists templates with pause/resume/edit/
delete; create dialog handles both kinds (vendor + line items for bills,
signed balanced lines for journals). Wired into routes + accounting nav.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 23:28:43 -04:00
admin 91882a0422 Expense Summary: exclude unpaid bills (billed-but-paid view)
Expense Summary kept billed-date recognition but counted bills the
association hasn't paid yet. Back out the unpaid (prorated) portion of
period bills per expense account, so the report reflects amounts actually
paid. Direct payments are unaffected (cash already out). Bent Oak's open
5/27 City of Titusville water bill ($136) now drops out: Water/Sewer
757.25 -> 621.25.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 00:52:26 -04:00
admin a1926b0623 Fix: drop non-existent payee_name from transactions selects
The Financial Overview (dashboard Recent Transactions) and the reconciliation
list selected a payee_name column that doesn't exist on accounting.transactions,
so PostgREST errored and the views came back empty. Resolve payee/payor from
vendors/customers only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 23:33:20 -04:00
admin 08c1d66aa1 Financial Overview: add Payee/Payor to Recent Transactions
The dashboard's Recent Transactions table (shown on the Financial Overview) now
has a Payee / Payor column — vendor for money out, customer for money in.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 23:27:58 -04:00
admin fa9671b4f5 Cash Disbursement: resolve vendor/bill for imported (Buildium GL) payments
The report only enriched app-posted (acmacc_txn) entries with vendor/bill, so
import-mode payments (buildium_gl) always showed 'No vendor on record'. It now
also pulls the vendor/bill from the register transaction linked to each GL bank
line (journal_entry_line_id), so matched imported disbursements show the vendor
(Robertson's, City of Titusville, Avria, FPL...) and bill instead of A/P.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 22:27:46 -04:00
admin ac454e8f5e Reports: drop Income Statement, add Monthly columns view to P&L
The Income Statement was a duplicate of the P&L, so removed it from the report
menu. The P&L now has a 'Monthly columns' toggle that renders the same
multi-period (by month/quarter/year) breakdown the income statement provided —
relabeled 'Profit & Loss'. Default P&L view is unchanged (single period).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 18:13:56 -04:00
admin 5714543533 Accounting: show Payee/Payor on transaction-style lists
Add a Payee / Payor column to the bank register (Banking), the reconciliation
list, and the Deposits 'awaiting deposit' list — showing the vendor (payee) for
money out or the customer/homeowner (payor) for money in. Expenses already shows
Vendor and Receive Payments shows Homeowner, so those were left as-is.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 17:49:26 -04:00
admin 1370b98be9 Bills: editing a paid bill saves and keeps its payment in sync
Editing a paid bill now updates the linked payment along with the bill: when the
amount changes and the bill has a single bill payment, the bank transaction, the
check, and the paid amount are all updated to the new total. The whole save is
wrapped in error handling and the bill_items insert is now error-checked, so any
failure surfaces a clear toast instead of silently appearing to 'not save'.
Also refreshes the transactions/accounts caches after a bill edit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 16:59:06 -04:00
admin 9063e49389 Reconciliation PDF: include outstanding items in prior-period reports; Balance Sheet: stop folding distinctly-named equity accounts
- Prior-reconciliation 'View Report' PDF was hard-coding empty uncleared lists,
  so outstanding items never appeared. It now reconstructs the items outstanding
  as of that statement (dated on/before the statement date, not voided, and not
  cleared in that or an earlier reconciliation) and includes them, with the book
  balance reflecting them.
- Balance Sheet equity folding matched any name containing 'retained earnings'
  (or 'current year earnings'), so a distinct account like 'Retained Earnings
  Savings' was swallowed into the calculated line and never shown. Now only the
  exact standard accounts fold; other equity accounts render on their own line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 12:47:46 -04:00
admin 3ab016fc57 Accounting: post locally-entered bank transactions to the GL (import mode)
Import-mode companies pull their GL from Buildium, so transactions entered
directly in Banking/Reconciliation never reached the GL — they reconciled but
were missing from GL-based reports (P&L etc.). This is why Bent Oak's May P&L
was missing Bank Interest and understated expenses.

- post_transaction_gl no longer gates on gl_managed; it posts any transaction
  that isn't voided, Buildium-sourced (journal_entry_line_id set), frozen
  (exclude_from_gl), a transfer/deposit leg, or missing an account/counter
- New accounting.transactions.exclude_from_gl flag freezes pre-existing manual /
  duplicate register rows on already-tied books so they can't double-post
- One-time data ops: linked all Buildium-sourced register rows to their GL bank
  line; froze remaining pre-existing manual rows for Bridgewater/Casuarina/
  Village Grove (ambiguous, would risk double-count); posted Bent Oak's 4
  verified-missing operating items. Bent Oak GL stays balanced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 12:15:59 -04:00
admin b243256e80 Cash Disbursement report: group payments by vendor
Top-level grouping is now by vendor (name as the section header) with a
per-vendor subtotal, instead of by bank account. The bank account each payment
was drawn from moves to a column on the row. Vendor is resolved from the
reliable payment→vendor / payment→bill→vendor linkage; disbursements with no
vendor on record (e.g. Buildium GL-pull entries) collect under a 'No vendor on
record' group sorted last rather than being guessed. PDF + CSV updated to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 12:01:31 -04:00
admin ab6c2747fa Reconciliation: cap unreconciled list at the statement date
Show outstanding items dated on/before the statement_end_date (prior periods
included), but hide anything dated after it — e.g. a 2/28/2026 statement shows
2/28 and earlier, nothing later.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 11:17:13 -04:00
admin 6ad7688fbd Reconciliation: clear any uncleared item regardless of billed date
A transaction's billed date no longer gates which reconciliation it can clear
in — items billed in one period frequently clear the bank in another. The
reconcile list now shows every uncleared, non-voided item for the account
(reconciliation_id is null), dropping the date <= statement_end_date ceiling.
Finalized items still carry a reconciliation_id and drop off.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 11:02:06 -04:00
admin 6bf9da5482 Accounting: prior-period reconcile items, void txns, unified report filters, accrual-only
1. Reconciliation now shows ALL outstanding (unreconciled) items on/before the
   statement date, including ones from prior periods — removed the prior-recon
   date floor. Finalized items still drop off (they carry a reconciliation_id).

2. Void transactions in Banking and Reconciliation. New accounting.transactions
   .voided flag (+ voided_at/by); voided rows stay visible (strikethrough + VOID
   badge) but are excluded from the running balance, register totals, cached
   account balance, and reconciliation. post_transaction_gl reverses the GL for
   gl_managed companies; un-void supported from Banking.

3. Unified report filters: the single Period bar on the Reports page now drives
   every report. General Ledger, Trial Balance, AR Aging (Property), Pre-Paid
   Homeowners, Cash Disbursement, and Reserve Fund no longer have their own date
   pickers — they consume the shared from/to (range) or to (as-of).

4. Accrual only: removed the cash-basis toggle from Trial Balance and General
   Ledger (the data was always accrual GL anyway; the cash label was misleading).
   All income/expense reports recognize on billed/issue date.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 10:51:03 -04:00
admin 5aef967b74 Buildium GL sync: keep import-mode bank registers current
Root cause of 'syncs stop at 5/31': the nightly buildium-gl-sync writes journal
entries (so reports stay current) but never created the matching bank-register
transactions for import-mode companies (gl_auto_post=false). Those registers were
materialized once at import, so the reconciliation/register views froze ~5/31
while the GL kept advancing.

- Add accounting.transactions.journal_entry_line_id (FK + unique index) to link
  register rows to their source GL line, making materialization idempotent
- buildium-gl-sync now materializes a register transaction for each bank line it
  inserts, for import-mode companies only (bank debit -> deposit/credit,
  bank credit -> withdrawal/debit; category/coa from the single offset account),
  upserting on journal_entry_line_id so re-runs never double-insert
- One-time backfill (run against prod) filled the existing gap: 231 register
  rows across Bridgewater/Casuarina/Village Grove/Bent Oak, skipping 3 near-miss
  rows that share a day with an existing register row (incl. a Casuarina transfer)
  for manual review

gl_managed companies are unaffected — their register drives the GL via
post_transaction_gl, not the other way around.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 10:10:25 -04:00
admin 42475a0e93 Reconciliation: require a vendor on manual withdrawals
The Add Deposit/Withdrawal dialog on the reconciliation screen now shows a
required vendor dropdown for withdrawals (debits) and stores vendor_id on the
transaction, matching the vendor-required rule on Bills/Expenses/Banking.
Deposits (credits) are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 09:53:07 -04:00
admin dedcbb8889 Bill Approvals: Buildium two-column form + require vendor on all backend payments
- Bill Approvals Create/Edit dialogs redesigned to the same professional
  two-column Buildium layout used on the accounting Bills page: left
  attachment panel (drag-drop + live image/PDF preview), right grouped form,
  prominent blue total bar, primary-action-first footer
- Accounting backend payments now require a vendor chosen from the dropdown:
  - Expenses: vendor is required; removed the free-text vendor fallback
  - Bills: must pick a 'Pay to' vendor before saving
  - Banking payments already enforced this
  (Reconciliation bank adjustments — interest/service charges — intentionally
   still allow no vendor, as they are not vendor payments)
- Board members remain locked to approving/denying their own assigned rows
  plus commenting and submitting invoices (per request); all bill edits, GL,
  line items, status, and deletes stay read-only for board users

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 00:14:13 -04:00
admin fbc5019730 Accounting: fix cross-page account-picker cache collisions + allow equity on bills
Root cause of filters conflicting between pages: many accounting pages shared
the same React Query keys (['accounts',cid], ['bank-accounts',cid],
['deposit-accounts',cid]) while running DIFFERENT queries, so whichever page
loaded first poisoned the others' cache (e.g. bill payment picker showing
banks-only with no equity; archived accounts leaking from the CoA list).

- Give every account read query a unique key discriminator per page/purpose;
  ['accounts',cid] / ['bank-accounts',cid] / ['deposit-accounts',cid] stay as
  invalidation prefixes (React Query partial match) so cross-page refresh still works
- Bill line-item category picker now includes expense + asset + equity + liability
  (was expense-only) — fixes 11 bills/13 lines categorized to equity (reserve-funded)
  that showed blank/—; and lets you assign an equity account to a bill
- Payment account picker (bills + expenses) reliably shows banks + equity now that
  it no longer collides with the banks-only deposit/receive-payment pickers

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 23:54:38 -04:00
admin f518f0b8f4 Bills: Buildium-style record/edit form + new read-only bill detail view
- Record/Edit dialog redesigned to a two-column layout: large attachment panel
  (drop/preview/replace) on the left; Bill Details + Item Details table on the
  right; prominent total bar; Save / Save & add another / Cancel footer.
  Keeps AI parse, field highlighting, vendor mapping
- New read-only bill detail view (click a bill #/vendor): header with vendor +
  status + Pay/Duplicate/Delete/Edit, Bill details card, item-details table,
  and a Bill amount sidebar (Total / Paid / Remaining)
- duplicateBill clones a bill into a fresh create form

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 23:41:36 -04:00
admin 512abcc1a2 Reconciliation: add deposits/withdrawals directly from the reconcile screen
- Deposit / Withdrawal buttons in the statement-transactions header open a
  dialog (date, amount, description, income/expense category, reference)
- New transaction posts to the bank account, is marked cleared, and is
  auto-checked into the current reconciliation; category picker excludes bank
  and archived accounts. gl-managed companies post the offset via the existing
  transaction GL trigger; import-mode books add register-only (consistent with
  Banking), so imported GL isn't double-counted

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 23:26:10 -04:00
admin 2d6f7ea17b Reconciliation: only show the open period + sortable column headers
- Transactions on/before the last completed reconciliation's statement date no
  longer reappear in a new reconciliation (date floor). Imported GL registers
  were inserted cleared-but-unreconciled, flooding the list with prior-period
  rows; reconciling now works period-by-period
- Sortable headers (Date / Description / Ref # / Deposit / Withdrawal) with
  asc/desc toggle indicators

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 23:08:12 -04:00
admin 8a57f53317 Accounting report batches: saved per-association packets → one combined PDF
- accounting.report_batches (name + ordered report_ids per company, member RLS)
- batchReports.ts engine: cover page + each report on a fresh page + one global
  Page X/Y footer. Financial four reuse the page's fetchReportData/buildFinancial
  (injected to avoid an import cycle); Trial Balance, General Ledger, Cash
  Disbursement, AR Aging, Pre-Paid, Reserve Fund built from the same source data
- Reports page: Report Batches dialog (name, ordered report checklist, saved
  batches load/delete, Save, Generate PDF); page now defaults to This Month
- reportPdf.appendStructuredReportPdf used for the financial sections

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 22:57:12 -04:00
admin b9235f644f Accounting: period presets (Month/YTD/Prev-Year/Custom) + logo-free reports
- Shared PeriodPicker (default This Month); wired into General Ledger report,
  Journal Entries page, and bank registers (Banking shows a Balance forward
  row carrying the running balance at period start)
- Financial reports are now logo-free: drawBrandedHeader/reportPdf skip the
  logo block; ReportSheet drops the on-screen logo
- reportPdf: appendStructuredReportPdf + skipFooter scaffolding for upcoming
  report batches (not yet wired)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 22:40:58 -04:00
admin b4014f378c Payment accounts can be equity; archived accounts excluded from all dropdowns
- Bill payment + expense paid-through pickers now offer bank OR equity
  accounts (reserve-component style payments); label updated to
  'Payment account'
- is_archived=false filter added to every accounting account dropdown:
  journal entries, bills (expense + payment), expenses, invoices/sales
  receipts/receive payments deposit-to, deposits (bank + line source),
  assessments, opening balances, budget detail, reconciliation

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 20:38:00 -04:00
admin 920def8826 Reports: archived accounts hidden everywhere except the General Ledger
- fetchAllGLLines filters accounts.is_archived=false, covering P&L, Balance
  Sheet, Cash Flow, Movement of Equity and Income Statement in one place
- Trial Balance, Reserve Fund Schedule and Budget vs Actuals account lists
  exclude archived; Banking page hides archived accounts from cards/pickers
- General Ledger report intentionally keeps archived accounts (history)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 20:27:18 -04:00
admin 03d3c5ee8d Chart of Accounts: archive accounts + safe deletes
- accounting.accounts.is_archived; COA mirror sets public is_active accordingly
  so association-side pickers hide archived accounts
- COA page: archive/restore per row + bulk, show-archived toggle, delete
  confirm dialog with 'Archive instead'; FK-blocked deletes (posted activity)
  get a friendly message + one-click archive; bulk delete skips blocked
  accounts per-id instead of failing the batch
- fetchChartOfAccounts excludes archived platform accounts from pickers;
  parent dropdowns and Opening Balances only offer active accounts

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 20:11:11 -04:00
admin df8623ff9f buildium-gl-sync: include inactive bank-account GL ids from /v1/bankaccounts
/v1/glaccounts omits some inactive accounts (e.g. prior-management bank
accounts) whose ledgers still hold one side of historical transactions,
making checks/deposits come back unbalanced on backfills (found during the
Casuarina Club GL import).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 19:52:21 -04:00
admin 28c3c7bd0a Bills import: degrade gracefully when Buildium API key lacks Vendors permission
GET /v1/vendors 403s on keys without the Vendors scope; import bills without
vendor links instead of failing the pull, and surface it in results.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 18:58:13 -04:00
admin cc5f70bc5b Bills import: A/P cutover guard — only post JEs dated after the GL watermark
Anything on/before buildium_gl.last_synced_date is already in the books as
buildium_gl entries; ap_cutover_date freezes that boundary so direct
buildium_bill/billpay postings never double-count history.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 18:46:24 -04:00
admin 25064d8418 Direct Buildium A/P import: bills, payments, one-off checks via GL Account Map
- public.bills.line_items + line-aware accounting mirror (one bill_item per
  Buildium line with its mapped platform account)
- buildium-sync bills: strict per-line resolution through
  buildium_gl_account_links (unmapped -> bill held + flagged); pulls
  /bills/{id}/payments (check#, bank, date) and /bankaccounts/{id}/checks
  (one-off checks become paid bill+payment pairs)
- import-mode companies get direct JEs (buildium_bill Dr expense/Cr AP,
  buildium_billpay Dr AP/Cr mapped bank) + cleared register rows; sets
  buildium_gl.exclude_ap so the nightly GL pull skips Bill/Bill Payment/Check
- buildium-gl-sync: exclude_ap transaction-type filter; preserve buildium_gl
  config keys when advancing the watermark
- Settings: Pull Bills & Expenses card with held/unmapped reporting

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 18:43:58 -04:00
admin 4e77098f88 Buildium GL account map: active accounts only, add-one-at-a-time UI
- gl_accounts fetched without includeAll (active Buildium accounts only)
- replaced per-account row grid (370+ selects) with a single add row:
  Buildium dropdown -> system account dropdown -> Add
- mappings list is plain rows with remove + push-target radio; changes save
  immediately (no bulk Save); flagged sync-blockers are click-to-select chips
- Auto-map exact matches button inserts code/name-identical pairs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 17:31:40 -04:00
admin e510a76dfc Accounting reports: AR Aging (Property), Pre-Paid Homeowners, Cash Disbursement
Buildium-style reports built on the owner ledger and GL:
- AR Aging (Property): FIFO-aged buckets (0-30/over 30/60/90) per unit with
  charge-type breakdown, collection status, summary + distribution bar
- Pre-Paid Homeowners: units with net credit balances as of a date
- Cash Disbursement: bank-credit GL entries grouped by bank account with
  check#/vendor/invoice enrichment from the banking register and GL line detail
All with branded PDF/CSV exports; shared owner-ledger helpers in lib/ownerLedger.ts

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 17:26:30 -04:00
admin 4c7fe7840b ARC decision letters: launch letter editor prefilled with ARC merge fields
- ARC detail header: Decision Letter button -> Forms & Letters (Letters tab) with
  association/owner/subject + projectTitle/decisionStatus/arcDate/decisionDate/
  propertyAddress/decisionNotes context
- LetterGenerator: resolves ARC tokens (before generic ones), new {{mailingAddress}}
  token, click-to-insert merge-field palette; templates via existing Save Template flow

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 15:56:27 -04:00
admin c1fad194f7 ARC imports: record Buildium decision votes + richer decision notes; PDF spacing
- Buildium API exposes no ARC comment threads or member votes (verified live);
  surface the final decision instead: vote row dated to the actual decision,
  decision_notes 'Approved by X on date (via Buildium)'
- record_buildium_arc_vote RPC bypasses the finalized-ARC write lock that was
  silently swallowing import votes; 69 existing imports backfilled
- Application Record PDF: paragraph break between comments and decision notes

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 14:26:48 -04:00
admin ff65c8a656 Buildium GL account map: strict account links, separate pull/push charges
- buildium_gl_account_links + buildium_unmapped_gl_accounts tables (strict, hold-and-flag)
- buildium-sync: pull charges syncType, account-first push resolution, no fuzzy matching, push dryRun
- buildium-gl-sync: links-only resolution, watermark held while unmapped accounts exist
- GL Account Map settings tab + Pull Charges card + unmapped results panel

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 14:07:18 -04:00
admin abd46bcb2b Hostinger Reach integration UI + ARC Buildium matching, drop Mailchimp
- HostingerReachPage (replaces MailchimpPage): connect Reach via
  reach-connection, per-association segment sync via reach-sync
- ARC Applications: Buildium import review/matching updates
- buildium-import-stage/apply: latest staging + apply changes (already
  deployed to Supabase)
- migrations: hostinger_reach_integration + arc_finalized_lock service
  role (already applied to live DB)
- CI: note that deployment is VPS-side polling (auto-deploy.sh cron)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 23:07:30 -04:00
admin 220892203c CI: auto-deploy to VPS on push to main
After the build check passes, SSH to the VPS with a forced-command key
(can only run deploy.sh) which pulls main, builds, and rsyncs dist/ to
public_html. Replaces the manual `ssh myvps ... deploy.sh` step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 22:55:39 -04:00
admin f5f6285bbd Accounting: fix empty JE/GL pages + nightly Buildium GL pull sync
- Add missing indexes on journal_entry_lines (journal_entry_id, account_id)
  and journal_entries (company_id, date): Bridgewater's ledger query took
  7.5s, blew the 8s statement timeout, and rendered the JE/GL pages empty
- Paginate JE/GL page fetches past the 1000-row PostgREST cap (shared
  fetchJournalEntries helper) and surface query errors instead of
  swallowing them into an empty list
- New buildium-gl-sync edge function (scheduled nightly via pg_cron):
  incrementally pulls new Buildium GL activity into accounting journal
  entries via GET /v1/generalledger, reconstructing double-entry JEs by
  grouping per-account entries by transaction id; watermark + 14-day
  overlap window, dedupe on (company_id, external_source, external_id),
  account mapping by external_id/code/name with auto-create for new
  Buildium accounts

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 22:12:38 -04:00
admin 4f0ac97e83 Income Statement: Buildium-style category subgroups
Group the multi-period Income Statement by account category (Operating Income,
Administration, Utilities, Reserves Budget, …) with "Total for <category>"
subtotals, matching the Buildium layout, in the on-screen table, PDF, and CSV.

- New accounting.accounts.category column (nullable; null = ungrouped), seeded
  from the local chart_of_accounts parent hierarchy.
- Editable in Chart of Accounts: single-edit (with datalist autocomplete) and
  bulk-edit (blank = no change, __clear__ to unset).
- buildium-account-categories edge function pulls each account's parent-GL
  category from Buildium (matched by code, fallback name) and backfills
  accounting.accounts.category; idempotent and re-runnable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 22:34:58 -04:00
admin cb8a29696f Accounting reports: add multi-period Income Statement
New "Income Statement" report with a By Month/Quarter/Year selector that lays
out income/expense accounts in period columns plus a Total column, with Total
Income / Total Expense / Net Income rows. Built from the GL over the selected
range; includes branded PDF and CSV export. Accounts are listed flat under
Income/Expense for now (category subgroups to follow once accounts are
categorized).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 21:04:49 -04:00
admin ca092f7b8b Budget Workbook: step through all clients with prev/next
Add prev/next buttons and a "Client N of M" indicator around the association
picker so a budget can be built for every client in turn. Cycles in name order
and wraps; direct dropdown selection still works.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 11:35:36 -04:00
admin 217e511792 Budget Workbook: export a Proposed Budget PDF
Add a PDF button that generates a board-ready proposed budget: income and
expense tables (monthly/annual per account with totals), a summary, and a
headline banner for the per-unit monthly assessment. Uses the workbook's
projected figures (overrides/inflation/unit override) via jsPDF + autotable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 10:58:59 -04:00