Budget vs Actuals: shade the Budget / Actual / Variance / Variance % columns
in a light→dark grey gradient with left vertical borders so they're easy to
tell apart (shared BVA_COL styles applied to header, group-total and detail
rows; variance text bumped to emerald/red-700 for contrast on the darker fills).
Reconciliation R2: reconcile() classified GL lines via the active-only account
list and dropped lines on archived accounts, so the "Assets = Liabilities +
Equity (incl. net income)" check went out of balance by the archived balance
(e.g. VW's archived 4016 Renters Insurance Income, -$75). Feed reconcile any
account referenced by glCumulative but missing from the active list (joined
metadata), matching the Balance Sheet builder; once every line is typed, R2
reduces to R1 and passes whenever the ledger balances. Also tightens R3/R4.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fetchOwnerLedger pulled all entries regardless of is_archived, so the
accounting AR Aging / Prepaid / batch reports still counted archived
(voided/duplicate) charges — e.g. 2455-VL showed $4K in violations
instead of $3K. Exclude archived entries at the source.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Archived (voided/duplicate) owner_ledger_entries were still counted in
the per-unit account breakdown, Collections, and Outstanding Balances —
inflating totals (e.g. 2455-VL showed $4K in violations vs the real
$3K after a duplicate was archived). Filter out archived entries in all
three, matching the canonical Unit Ledger view.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a PDF upload to the bid/quote dialog (stored in the bid-attachments
bucket, saved to document_url/document_name) and shows the attachment in
the detail view. Board members with can_upload can attach PDFs — table
RLS and the storage bucket already permit it; only the UI was missing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The "Staff full access on status_updates" policy was missing from the
live DB (dropped outside migrations), so all inserts/updates failed with
"new row violates row-level security policy". Recreate it (admin/manager).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lets management post internal status updates that don't appear in the
board portal. Adds status_updates.hidden_from_board and re-creates the
association-scoped RLS SELECT policy so board members can't read hidden
rows (staff still see all). Dialog gains a "Hide from board" toggle, the
board view filters hidden updates, and management cards show a badge.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Budget column overlap-weighted partial months, so a YTD range
ending mid-month showed a fractional budget. Now include each budget
period's full amount whenever the selected window touches it, for both
the main and comparison windows — exactly as entered on the budget.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The accounting Budget vs. Actuals report computed actuals from
operational tables (bill_items + payment transactions + a
budget-weighted paid-invoice plug), which double-counted (a bill
counted as its line item AND its payment, plus redundant imported
bills) and diverged from the posted books — especially for Buildium
GL-import / import-mode associations whose activity lives only in
journal entries.
Now fetch GL lines via fetchAllGLLines and net per account
(income = credit - debit, expense = debit - credit), matching the
Income Statement. Budget side was already correct (reads active
accounting.budgets + budget_entries).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
An archived COA account that still carried a GL balance was dropped from the
Balance Sheet (fetchAllGLLines filtered is_archived=false), so the report went
out of balance by exactly that amount. Now the financial-report GL fetches
include archived accounts (those without activity never appear, since this
queries journal lines), and buildBalanceSheet surfaces archived asset/liability
/equity accounts that carry a balance as line items; archived income/expense
flow into Net Income. Fixes the Village Woods $170.30 out-of-balance and the
same latent issue in Bent Oak and Casuarina.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Buildium often records vendor payments as direct checks (Dr Expense/Cr Bank)
with no bill. For import-mode companies post_bill_gl no-ops, so a bill is a
record only. New fn accounting.autocreate_nobill_vendor_bills() creates a paid
record-only bill for each such buildium_gl payment (vendor resolved by payee,
idempotent by external_id); buildium-gl-sync calls it per import-mode company
after each pull. No GL impact, no double-count.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Below the Submit vendor profile button, instruct vendors to email bills to
ap@avriacam.com or mail them to the association's mailing address, c/o Avria
Community Management, LLC. The address is resolved from the vendor's
association (association_id, falling back to association_ids[0]).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
post_transaction_gl now skips posting a register row whose exact bank
movement (company + bank account + date + amount + direction) is already
in buildium_gl, so categorizing an ad-hoc-materialized register row can no
longer duplicate the Buildium GL pull. Also freezes (exclude_from_gl) any
remaining unguarded buildium-overlapping register rows across all
import-mode companies. Genuinely-missing manual items (no GL match) still
post normally.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
- 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>
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>
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>
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>
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>
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>
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>
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>
- 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>
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>
- 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>
- 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>
- 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>
- 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>
- 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>
- 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>
- 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>
/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>