Commit Graph

149 Commits

Author SHA1 Message Date
admin 215ecb3153 Budget Workbook: replace Budget Management with a YTD-actuals workbook
/dashboard/budget-management now renders a Budget Workbook that pulls YTD
actuals (from the accounting GL, through a chosen month), derives a monthly
average (YTD/N), takes a per-line inflation %, and projects an annual budget
(avg x 12 x (1+infl)). Footer rolls up annual budget / 12 / # units = per-unit
monthly assessment. Income + expense sections; all imported fields editable.

- Standalone saved worksheet (accounting.budget_workbooks/_lines, RLS like accounts)
- "Push to Budget" writes projected/12 into accounting.budgets + budget_entries
- Uses accounting.accounts (synced with the Accounting dashboard COA) and paginates
  the GL fetch (1000-row cap). Nav relabeled Budget Management -> Budget Workbook.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 16:29:25 -04:00
admin ea2f2a089a Accounting Banking: page through all register transactions
The bank register fetched transactions in a single request, which
PostgREST caps at 1000 rows. An imported bank account with a longer
register (e.g. Bridgewater Checking, ~1,500 rows) truncated, throwing
off the displayed running balance. Page through all rows ordered by a
stable key (date, created_at, id).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 13:30:19 -04:00
admin bd4c385478 Accounting reports: page through all GL lines (fix 1000-row truncation)
PostgREST caps each response at 1000 rows. The P&L and Balance Sheet
fetch every journal_entry_line for the company and aggregate client-side,
so any association with >1000 GL lines (e.g. an imported Buildium GL) only
saw the first 1000 — accounts whose activity fell past that point read as
$0 and were hidden, making reports look empty/out-of-balance. Fetch the GL
in 1000-row pages ordered by a stable key so every line is included.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 01:23:57 -04:00
admin d2d2c83e7b Accounting: refresh reports + General Ledger after posting a journal entry
Manual journal entries post straight to the GL, but saving/deleting one
only invalidated the journal-entries list — so the Reports data (P&L /
Balance Sheet) and the General Ledger tab kept showing stale figures
until a manual refresh. Invalidate reports-data and gl-journal-entries
on save and delete too.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 00:53:18 -04:00
admin 4b5c2ea2ea Accounting: add General Ledger tab
Buildium-style GL grouped by account type with date-range filter,
account filter, beginning/ending balances, per-line running balance,
and grand totals. Reads posted journal entries.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 22:17:23 -04:00
admin f315d86e03 Accounting: editable deposits (Recent Deposits list + edit/delete)
Add a "Recent Deposits" list to the Deposits page with Edit (date, bank
account, memo — GL re-posts via the deposit trigger) and Delete (releases the
deposited transactions/payments back to "awaiting deposit" and reverses the GL).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 19:57:10 -04:00
admin 8a2ea60824 Accounting: editable journal entries + Reports refresh button
- Journal Entries: add Edit (row + detail drawer) that loads an entry into the
  form and saves changes (updates the entry and replaces its lines). Warns when
  editing an auto-generated entry (may be overwritten by its source sync).
- Reports: add a Refresh button that re-fetches the underlying data so the
  report reflects the latest GL.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 19:33:39 -04:00
admin aa94622a78 Opening Balances: fix duplicate earnings accounts; recognize name variants
The auto-provision effect could fire twice and create duplicate "Current Year
Earnings" accounts (seen on Village Grove). Use the idempotent
coa_get_or_create RPC with a once-per-company ref guard, and match existing
name variants (Current Year Income / Net Income / Retained Earnings) so it
won't create redundant accounts. Balance sheet now also folds
"Current Year Income"/"Net Income" equity accounts into the Net Income line.
Removed the existing Village Grove duplicate (zero activity).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 19:04:51 -04:00
admin 7fd8ad2c52 Opening Balances: allow entering Retained Earnings + Current Year Earnings
Auto-provision "Retained Earnings" and "Current Year Earnings" equity accounts
per company so they appear as inputtable rows in the Chart of Accounts Opening
Balances grid. The Balance Sheet folds the posted "Current Year Earnings"
account into the Net Income line (already did this for Retained Earnings), so a
mid-year import can seed both equity figures without entering income/expense
detail, and Total Equity stays balanced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 18:11:01 -04:00
admin f3b81eaeeb Revert vendor->A/P posting rule (it collapsed the P&L)
The blanket rule stripped expense from direct-expense checks that have no bill,
leaving the P&L showing only a couple of accounts. Restore original
post_transaction_gl precedence (coded account before vendor). Re-posted affected
transactions to restore expense recognition. Double-count needs a bill-linkage fix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 17:38:15 -04:00
admin fdb9174c45 Accounting GL: vendor checks relieve A/P; Village Grove payments direct-to-bank
- post_transaction_gl: a vendor money-out (check) now posts Dr A/P / Cr Bank
  instead of re-debiting the coded expense account. Fixes double-counted expense
  and checks showing as P&L debits (bill already recognized the expense).
- post_payment_gl: Village Grove owner payments post straight to HOLII COGENT
  Checking instead of Undeposited Funds (scoped; others unchanged).

Both applied to the live DB; Ashley Manor's affected transactions re-posted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 14:45:04 -04:00
admin 5aa03d1cd6 Balance Sheet: fold posted Retained Earnings account into the prior-years line
A real "Retained Earnings" equity account is postable via journal entries, but
the balance sheet listed it separately from the calculated "Retained Earnings
(prior years)" line, so JE adjustments looked like they had no effect there.
Now the posted RE-account balance is added into the "Retained Earnings (prior
years)" line (and removed from the generic equity list). Total Equity is
unchanged — it already included that account.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 13:26:13 -04:00
admin 8f14877274 Balance Sheet: label the YTD earnings equity line "Net Income"
The equity section already carried a permanent current-year earnings line
(income − expenses for the fiscal year to date); rename it from "Current Year
Earnings" to "Net Income" to match the Movement of Equity report and the
requested terminology. No calc change — still YTD income minus expenses,
included in Total Equity.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 13:00:24 -04:00
admin f66165a8f5 Checks: Banking print now applies field positions + MICR gaps
Banking's generateCheckPDF opts omitted fieldPositions (and micr gaps), so the
per-field x/y position adjustments saved in Check Setup had no effect on checks
printed from Banking. Pass them through.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 12:50:38 -04:00
admin 3d264130b9 Checks: print the General Settings mailing address as the return address
Banking check printing hardcoded companyAddress: undefined, so the association
mailing/office address (accounting.companies.address, set in General Settings)
never printed below the name. Now loads and passes it. Bills check printing
falls back to the company name/address when no company_check_layouts payer is set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 12:15:48 -04:00
admin c66a11769c Checks: align Print Checks page with Check Setup generator
PrintChecksPage was still using the old generator (utils/checkPdfGenerator +
check_layouts), so it had the same bugs as Bill Approvals (wrong return address,
missing vendor address, ignored x/y offsets). Route it through
lib/checkPdf.generateCheckPDF using the accounting company (return address),
check_settings (layout/offsets/field positions/signature/MICR), the selected
bank account (routing/account), and vendor address as payee. DB side effects
unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 12:01:07 -04:00
admin dd4a088e9d Checks: print PDF now uses Check Setup settings (matches the sample)
Bulk "Print Checks" was rendering via a separate generator (utils/checkPdfGenerator
+ check_layouts), so the printed PDF ignored the accounting Check Setup: wrong
return address (generic company vs association name + mailing address), missing
vendor address, and ignored x/y field-position offsets.

Route the print through the same generator as the working sample
(lib/checkPdf.generateCheckPDF) fed by the accounting company (return address),
check_settings (style/offsets/field_positions/signature/MICR gaps), the chosen
bank account (routing/account), and the vendor address as payee. DB side effects
(checks, transactions, bill paid status, check numbering) unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 11:45:30 -04:00
admin a81e4f51ab RV/Boat Lots: map tab edits the association Map amenity + per-pin amount
The Map tab now binds to the association's active map-type amenity (the
reservation map) instead of a separate table — pins edited here are the public
reservation map. Adds a per-pin amount ($/mo) field (GoogleMapPicker showAmount
prop, backward-compatible). Shows a notice when no Map amenity is active and an
amenity picker when more than one exists.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 22:41:54 -04:00
admin 5a7f21fee6 Add AGENTIC_MAIL to environment variables 2026-06-07 22:41:22 -04:00
admin 69f643a51e RV/Boat Lots: sync lots to public rental_calendar amenities
Add a "Sync to Public Page" button that creates/updates one rental_calendar
amenity per lot (name, size · rate · availability in the description, rate in
booking_config, shown on the public page). Idempotent via amenities.source_rv_lot_id;
removes synced amenities for deleted lots.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 21:06:21 -04:00
admin f549f21c21 RV/Boat Lots: waitlist size + more vehicle types
- Waitlist now captures a free-form Size (requested_size column) in place of
  the type field in the internal form/table.
- Lot type selector (add + bulk edit) expanded to RV, Boat, Travel Trailer,
  Fifth Wheel, Camper, Car, Truck, Trailer, Other.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 21:01:18 -04:00
admin 0c0300efce RV/Boat Lots: internal lot map with directory-unit links
Add a Map tab that reuses the reservation-map pin picker. Staff drop/label
pins per lot and optionally link a directory unit (pin.linked_amenity_id =
unit id). Config persists per association in rv_boat_lot_maps.

GoogleMapPicker generalized with optional linkLabel + allowLinkAnyStatus
(defaults preserve the amenity reservation-map behavior).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 20:40:52 -04:00
admin 10a9d31b94 RV/Boat Lots: insurance expiring-soon / expired indicator
Color-code each rental's insurance status like vendors: red when expired,
amber when expiring within 90 days (with days remaining), green otherwise.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 20:23:07 -04:00
admin 308af20aa1 RV/Boat Lots: request renter insurance (vendor-style flow)
Phase 4. Mirror the vendor insurance request flow for RV/boat renters:
- Migration: insurance fields on rv_boat_lot_rentals + rv_renter_insurance_requests
  table + token-scoped lookup/submit SECURITY DEFINER RPCs (granted to anon).
- Edge fn send-rv-renter-insurance-request emails the renter a secure link
  (reuses the vendor-insurance-request email template).
- Public page /rv-insurance/:token to submit carrier/policy/expiration + COI upload.
- "Request Insurance" button on each active rental + insurance status display.

DB RPCs verified end-to-end (rolled-back txn): submit matches token, updates the
rental, marks the request submitted. Edge function deployed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 20:16:31 -04:00
admin d8465f2297 RV/Boat Lots: link rentals to owner/unit + Notice to Vacate toggle
Phase 2: rental form now has optional Owner and Unit selectors (auto-fills
renter info/unit from the chosen owner), persisting owner_id/unit_id.

Phase 3: add RvRentalVacateButton on Owner and Unit profiles — shows only
when that owner/unit has an active/vacating RV-boat rental, and toggles the
rental status between active (renting) and vacating. Active Rentals tab now
includes vacating rentals with a badge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 18:20:58 -04:00
admin 7c18576390 RV/Boat Lots: batch edit Lots and Active Rentals
Add row checkboxes + select-all to the Lots and Active Rentals tables with a
selection bar. Bulk edit lots (type, status, monthly rate) and bulk delete;
bulk edit rentals (status incl. end, owner/renter flag, monthly rate).
Phase 1 of the RV/Boat lots enhancements.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 17:54:43 -04:00
admin 4ecbdcfd4d Calendar: manage rental/meeting calendars from the dashboard
Add a "Manage Calendars" action (rental/meeting modes) that opens the full
AmenitiesManager for a chosen association in a dialog — so staff can create/
configure rental calendars, manage their bookings, and block/unblock
availability without going to the association overview page. Adding bookings
inline was already supported in these modes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 17:39:44 -04:00
admin 6932c5acbb Unit ledger: let amount input accept $0.00
The amount field had min="0.01", so the browser's native form validation
blocked a $0.00 charge before the JS check ran. Lower to min="0" so a $0.00
charge/note can be submitted; the JS still restricts $0 to charge-type
entries (payments require a positive amount).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 17:22:07 -04:00
admin 3f39bfbd70 Unit ledger: allow posting a $0.00 charge
Relax the amount validation so a Charge/Expense/WriteOff can be posted with a
$0.00 amount (used as a note/memo on the ledger). Payments and prepayments
still require a positive amount; negatives remain blocked.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 17:04:25 -04:00
admin 271a6d2701 Nav: add Owner Ledger link under Finance → Receivables
The Owner Ledger page (/dashboard/owner-ledger) was a route with no menu
entry, so it was only reachable by URL. Add it to the Receivables group so
staff can reach it (and the new Add Note action).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 15:41:59 -04:00
admin 2503dc4846 Owner Ledger notes: show notes to homeowners
Reverts the homeowner-facing exclusion — ledger notes now appear on the
homeowner ledger and statements views as intended.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 15:18:00 -04:00
admin e641b05a91 Owner Ledger notes: hide internal notes from homeowner-facing views
Exclude transaction_type 'note' from the homeowner ledger and statements
pages so internal staff notes aren't shown to owners.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 15:16:53 -04:00
admin f53a0aaf46 Owner Ledger: add $0.00 note entries
Add an "Add Note" action that records a memo on an owner's ledger as a
$0.00 entry (transaction_type 'note', debit/credit 0). Notes work on any
ledger including paid-up ($0.00 balance) accounts, render as styled memo
rows, and don't affect the running balance. The accounting sync treats a
zero entry as a no-op, so no phantom AR is created.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 15:12:50 -04:00
admin 36787b193d Accounting COA: bulk edit + bulk delete of accounts
Add row checkboxes (with per-category select-all) to the accounting Chart of
Accounts. A selection bar exposes Edit/Delete/Clear. Bulk edit applies any of
type, parent account, bank flag, reserve flag to all selected (each field has
a "No change" option); bulk delete removes selected accounts. Mirrors the
existing bulk-edit UX on the per-association chart_of_accounts page.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 14:54:19 -04:00
admin 6f68619b9c Bill approvals: backfill imported bills' approvers + auto-create on import
Approved/paid bills that never went through in-app approval (imports, bulk
loads) had no approver row, so the Approvers column was blank. Backfill a
synthetic approver: 'Imported' for system imports (created_by null), the
creator's name (fallback 'Direct entry') for in-app entries. Adds an AFTER
INSERT trigger so future imported-as-approved/paid bills get one too.
Applied to prod: +1,140 rows, 0 approved/paid bills now missing an approver.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 13:52:19 -04:00
admin 25f7865901 CI: skip native postinstall scripts (canvas) in bun install
canvas tried to compile native bindings on the runner and failed (no
prebuilt binary for the Node ABI, no system cairo/pango). The Vite browser
build doesn't need it, so install with --ignore-scripts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 13:24:20 -04:00
admin cb740c2521 Bill approvals: fix approver column always showing "None"
The list loaded all bills (~1,150) then fetched approvers with
.in("bill_id", [all ids]); that request URL exceeds server limits and
fails silently, so approvalsByBill was always empty. Fetch the small
bill_approvals table directly (RLS scopes per role) and group locally.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 13:21:08 -04:00
admin aee3d057e6 chore: trigger production deploy
Re-fire the auto-deploy with bill-approvals approver_name + admins-only
mark-paid changes (already merged in PRs #8 and #10).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 12:58:10 -04:00
admin 9eb5993566 Merge pull request #10 from renee-png/bill-approvals-paid-and-approvers
Bill approvals: admins-only mark-paid + DB guard
2026-06-07 12:29:38 -04:00
admin fd7107290a Bill approvals: admins-only mark-paid + DB guard
Restrict marking a bill paid to admins only, per requirement.
- BillDetailPage: gate Mark Paid / Mark Unpaid on useAuth().isAdmin
  (was only hidden in board view).
- BillApprovalsPage: gate Print Checks (which sets bills to paid) on isAdmin.
- Migration: BEFORE INSERT/UPDATE trigger enforce_admin_marks_bill_paid()
  rejects the transition into 'paid' for authenticated non-admins. Service-role
  / system contexts (auth.uid() null: buildium-sync, accounting triggers,
  autopay) remain allowed. Verified: admin allowed, non-admin blocked (23514).

Note: the approver column showing "None" in production is a stale-deploy
issue — the DB column was renamed vendor_name->approver_name (Jun 4) but
prod still ran code querying vendor_name. Deploying current main resolves it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 12:28:03 -04:00
admin 631f9d5c3c Merge pull request #9 from renee-png/fix-ci-workflows
CI: replace broken webpack/pages workflows with bun build check
2026-06-07 11:03:53 -04:00
admin d42baaecf9 CI: replace broken webpack/pages workflows with bun build check
The webpack.yml workflow ran `npx webpack` on a Vite project (no webpack
present), failing on every push/PR. static.yml uploaded the raw repo root
to GitHub Pages (not a real build; the app deploys via Vercel/Lovable) and
also failed. Replace both with a CI workflow that installs via bun
(bun.lockb is the maintained lockfile; package-lock.json is stale) and runs
the Vite build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 23:36:39 -04:00
admin e8288cf4e4 Merge pull request #8 from renee-png/accounting-sales-receipts-coa-sync-expenses
Accounting: sales receipts, COA sync/import, vendor-expense recognition, bill approvals
2026-06-06 23:26:06 -04:00
admin ea8cf6efb6 Merge remote-tracking branch 'origin/main' into accounting-sales-receipts-coa-sync-expenses
# Conflicts:
#	src/integrations/supabase/types.ts
#	src/pages/BillDetailPage.tsx
2026-06-06 23:24:45 -04:00
admin af67e2fb9a Accounting: rename bill_approvals.vendor_name→approver_name + COA import dialog
Rename the bill_approvals approver column from vendor_name to approver_name
across UI, hooks, types, and buildium-sync. Add a Chart of Accounts import
dialog (XLSX upload + column mapping + type-alias normalization) and a
"denied" status color.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 23:04:29 -04:00
admin 096cac6b0b Merge pull request #6 from renee-png/accounting-sales-receipts-coa-sync-expenses
Accounting: sales receipts, COA dashboard sync, accrual A/P, manual deposits, per-association COA, bill-approval sync fix
2026-06-05 20:52:43 -04:00
admin cc34ae9418 Accounting: two-way bill creation + mirror pending bills
- bill_should_mirror now includes 'pending', so approval bills appear in
  Payables immediately (still excludes draft/rejected/void/cancelled/denied).
- New reverse-creation path: a bill created natively in the Accounting module
  (external_source NULL, non-auto, non-payment, non-void) now creates a matching
  public.bills row. The accounting row is pre-linked to the new public id so the
  forward sync adopts it (no duplicate mirror); vendor is mapped back to
  public.vendors and the line's GL is carried to expense_account_id.
- Backfill: mirrored existing pending public bills and reverse-created the 8
  eligible native accounting bills. Verified: 0 unlinked native, 0 duplicate
  mirrors, pending bills mirrored.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 20:54:09 -04:00
admin 756ebce121 buildium-sync: robustly resolve bill line GL account into expense_account_id
Buildium bill imports left expense_account_id null on all bills because the
importer only read firstLine.GLAccountId, but the bill-line payload exposes the
GL id under GLAccount.Id (nested). chart_of_accounts.account_number already
stores the Buildium GL Id, so resolve the line's GL id from either shape before
mapping it. Re-syncing backfills existing bills via the update path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 20:17:07 -04:00
admin 84c8483169 Accounting: unify vendor roster + COA across bill-approvals and accounting bills
Single vendor source (public.vendors) and single COA source (accounting.accounts)
across both bill flows:

- Forward sync now carries public.bills.expense_account_id into the mirrored
  accounting.bill_items.account_id (when it resolves to accounting.accounts).
- Reverse trigger flows a GL change on a mirrored accounting bill line back to
  public.bills.expense_account_id (loop-guarded).
- New public.ensure_accounting_vendor RPC resolves a chosen public vendor to its
  accounting.vendors row; one-time backfill of mirrored line account_id.
- BillApprovalsPage GL pickers now use ChartOfAccountsDropdown (accounting.accounts).
- AccountingBillsPage vendor picker now lists public.vendors scoped to the
  company's association and maps to accounting.vendors on save.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 18:57:32 -04:00
admin 84541a6813 Accounting: back-sync bill paid status to bill_approvals on INSERT
trg_acct_bill_paid_back was AFTER UPDATE only, so bills mirrored into
accounting already-paid never triggered the back-sync that flips
public.bills + bill_approvals to 'paid'. Fire the trigger on INSERT too
and reconcile existing already-paid mirrored bills. Also backfill
invoice-track approvals that uniquely match a bill (bill_id was null).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 18:17:39 -04:00