Commit Graph

86 Commits

Author SHA1 Message Date
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
admin 0f5c33d1dd Merge pull request #7 from renee-png/bills-approvals-fixes-2026-06-04
Bill approvals: surface approvers, fix email path, schema cleanup
2026-06-04 17:41:54 -04:00
admin 6376d5cc7e send-bill-approval-invites: forward Authorization on inner invoke
The supabase-js .functions.invoke() call from one edge function to
another doesn't reliably attach the apikey as Authorization, so the
inner send-transactional-email call was failing verify_jwt and
returning 401. Pass the service-role bearer header explicitly.

This is what was actually preventing bill-approval-vote-invite emails
from going out — every Notify Board flow logged 401s on the per-bill
sends, with zero rows ever landing in email_send_log for that template.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-04 17:37:11 -04:00
admin 2c723410a4 Bill approvals: surface approvers, fix email path, schema cleanup
UI

- Dashboard BillApprovalsCard: render approver name chips (color-coded
  by vote status) per pending bill instead of leaving the approver
  identity invisible.
- BillDetailPage: collapse the duplicate "Requested Approvers" card
  into the existing "Approvers" table. Approve/deny handler now stamps
  approved_by = auth.uid() for audit trail.
- MasterBoardDashboardPage: the "pending approvals for me" count was
  filtering on a non-existent bill_approvals.approver_user_id column.
  Replaced with a board_members.member_name -> bill_approvals.approver_name
  join (matches the RLS policy).
- BillApprovalRequestDialog + AIInvoiceParserPage: bill_approvals inserts
  now set created_by.

Database

- Rename public.bill_approvals.vendor_name -> approver_name. RLS policies
  auto-rewritten by ALTER TABLE RENAME COLUMN; the column was misnamed
  (it stores the approver's board-member name, never a vendor).
- Restore the bill_approval_email_tokens table + lookup_/record_
  bill_approval_by_token RPCs. The original 20260520153409 migration
  was never applied successfully; rewrote it to use approver_name and
  to populate approved_by/created_by from board_members.user_id on
  token-driven votes. Added the v2 migration that matches the live DB
  state.
- accounting trigger: void on accounting.bills cascades to
  public.bills.status='cancelled' (existing forward sync then drops the
  accounting row per accounting.bill_should_mirror).

Edge function

- send-transactional-email: add bill-approval-request and
  bill-approval-vote-invite templates (caller paths in BillApprovalsPage
  + send-bill-approval-invites referenced templates that weren't in the
  registry, so every email 404'd). Restored the local copies of
  election-invite, board-vote-invite, and the missing registry.ts so the
  repo matches what's deployed. Deployed to send-transactional-email v35.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-04 17:17:05 -04:00
admin 6634907799 Per-association chart of accounts
Each association now owns an independent set of chart_of_accounts rows. Two
associations can both have a "5000" meaning different things, edited
independently — previously buildium rows were shared across associations via the
association_ids[] array, so editing one association's number edited it for all.

- Data migration: split each shared buildium row into one row per association in
  its association_ids (excluding nulls and ids of deleted associations). The
  original row stays as the per-association row for its own association_id;
  clones are added for the others — nothing is deleted, so no FK dangles.
  94 -> 370 buildium rows. References repointed by each record's association
  (bills, budgets, owner_ledger_entries, vendor_coa_mappings, units, vendors,
  journal_entries; budget_actuals_monthly is a view). parent_account_id remapped
  same-association; orphan-parent children become top-level. Pristine backup in
  public._coa_perassoc_backup. Ran in one transaction with in-line verification.
- Uniqueness: drop (account_number, accounting_system); add
  UNIQUE(association_id, account_number) WHERE accounting_system <> 'platform'
  (platform rows mirror accounting.accounts and carry blank/dup codes). This also
  finally backs the buildium importers' existing onConflict target.
- Keep association_ids as a single-element mirror of association_id during the
  transition so the admin COA page and direct array-contains callers keep working.
- App: fetchChartOfAccounts scopes buildium/zoho by association_id when an
  association is given (was system-wide). Importers and sync_account_to_public_coa
  were already per-association; no change needed.

Verified on live data: 370 singleton-array rows across 12 associations, zero
intra-association duplicates, zero cross-association references or parents, and a
live two-association "5000" independence test (create/rename/isolate) passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 13:38:50 -04:00
admin 8f1cbcd3af Accounting: selectable-source / multi-line manual deposits
Deposits no longer force the credit side through Undeposited Funds — the
structural cause of negative Undeposited balances. A deposit can now credit any
account(s): interest income, a refund, an insurance reimbursement, cash straight
to the bank, etc.

- Schema: add accounting.deposit_lines (deposit_id, company_id, account_id,
  amount, memo) for the credit side, plus deposits.source_account_id as a
  single-source fallback. RLS mirrors deposits (staff + company member).
- post_deposit_gl: Dr bank for the total; Cr each deposit_lines row's account
  for its amount; no lines -> Cr source_account_id; neither -> Cr Undeposited
  Funds (backward compatible — existing deposits stay Dr Bank / Cr Undeposited).
  Remainder safety net keeps the entry balanced. New trg_acct_deposit_line_gl
  re-posts when lines change (header trigger fires before lines exist).
- Make Deposit page: GL-driven submit writes the deposit header + deposit_lines
  and marks selected payments deposited. Adds an "Other deposit lines" grid
  (account + amount + memo) alongside the existing Undeposited selection, with a
  running grand total and a soft guard against over-crediting Undeposited.
  Drops the old bank/Undeposited register-transaction inserts and manual balance
  pokes (never exercised in production; carried a money-in sign bug). Deposits
  are GL-only, consistent with the sync-created deposits already in the DB.

Verified Dr/Cr for single-source and multi-line scenarios against the live GL.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 13:00:41 -04:00
admin 7464d55b6c Accounting: enforce accrual A/P on bill payments (match rule + guard + cleanup)
Under accrual, a vendor expense is recognized once — when the bill is entered
(Dr Expense / Cr A/P). Paying a bill must only relieve the liability
(Dr A/P / Cr Bank) and never re-hit the expense account. This hardens the
existing Pay Bills flow against re-recognition and double counting.

- Strict bill matching: extract a pure, dependency-free matcher into
  lib/billMatch.ts (debitMatchesBill/matchOpenBills) — same vendor, status
  open/overdue/partially_paid, amount within $0.01 of remaining (or <= remaining
  for partials), debit date within ±30 days of due/issue date. Unit-tested in
  billMatch.test.ts (covers the identical-recurring-charge regression).
- AccountingBankingPage.saveTx uses the strict rule (was "any open bill"), so a
  thrice-paid identical charge only clears the in-window bill.
- Bank-feed categorizer (bulkSetCategory) matches open bills before assigning an
  expense COA: single match clears A/P + links the bill; multi-match is skipped
  with a prompt to resolve in Pay Bills; no match categorizes as a direct expense.
- DB guard: add accounting.transactions.bill_id (FK -> bills) and CHECK
  chk_bill_payment_no_coa (bill_id IS NULL OR coa_account_id IS NULL) so a
  bill-linked payment can never carry an expense category. Both writers set
  bill_id on single-bill payments; partial payments now write partially_paid.
- One-time cleanup: clear coa_account_id on Ashley Manor's 8 double-counted bill
  payments ($2,198.98) so the GL reposts them as Dr A/P / Cr Bank.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 12:30:44 -04:00
admin d82466f826 Accounting: Sales Receipts, COA sync to dashboard, vendor-expense recognition
- Add Sales Receipts page (dashboard/accounting/sales-receipts): records a
  cash sale (name, address, income account, price, qty) — deposits and books
  income in one step via a transaction. New accounting.sales_receipts table.
- Sync chart of accounts to the accounting dashboard: mirror accounting.accounts
  into public.chart_of_accounts for platform associations (one-way, same id) so
  Bill Approvals and every COA consumer use the dashboard's accounts. Legacy
  rows hidden; Bill Approvals made system-aware.
- Vendor-expense recognition: a vendor payment with no bill now books the
  expense directly (Dr Expense / Cr Bank) on the payment date instead of going
  to A/P; payments against open bills still clear A/P (applied FIFO). Backfill
  reclassifies unbilled payments stuck in A/P. Expense Summary report made
  GL-driven so it follows the same rule.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 10:01:18 -04:00
admin bd5caf5415 Merge pull request #3 from renee-png/email-cutover-and-accrual
Migrate email pipeline off Lovable + branded auth emails
2026-06-03 02:40:35 -04:00
admin 35c3c0da72 Merge pull request #5 from renee-png/buildium-accounting-sync
Buildium → Accounting: company auto-provision + opening-balance migration
2026-06-03 02:34:17 -04:00
admin f7dc5d8177 Buildium -> Accounting: auto-provision companies + opening-balance migration
- buildium-sync now ensures every active association has an accounting company
  after syncing associations. Once it exists, the existing DB triggers flow
  units -> customers, owner ledger -> A/R + income, and bills -> A/P + expense
  into Accounting automatically (closing the gap where Buildium synced only the
  main dashboard, not Accounting).
- New buildium-opening-balances function: fetches an association's Buildium GL
  trial balance as of a cutoff (default 2025-12-31, Accrual), maps GL accounts
  to accounting accounts (flagging bank accounts), rolls prior-year P&L into
  Retained Earnings, writes accounting.opening_balances, and posts the opening
  GL entry. Idempotent; service-role gated.

Applied to 6 Buildium associations (opening balances + 2026 activity); all
balance. New columns/data applied to the project directly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 02:31:21 -04:00
admin 5436396a23 Merge pull request #4 from renee-png/accounting-bill-payment-ap
Accounting: A/P-clearing payments, check return address + MICR gaps, dashboard fixes
2026-06-03 01:18:14 -04:00
admin 3b220a3f26 Checks: drop "Authorized Signer", move signature label below the line
Removes the "Authorized Signer" text from the payee/address block, moves the
"AUTHORIZED SIGNATURE" label to just below the signature line, and raises the
signature image cap (0.42 -> 0.65 in) so the signature renders full size in
the now-clear space above the line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 01:12:52 -04:00
admin 7ccfc133f8 Bill-payment checks: per-element positioning + visibility
The bill-payment check generator (checkPdf.ts) now supports per-field
position offsets (X/Y inches) and show/hide for every element — check
number, return address, bank block, date, pay-to, amounts, payee address,
memo, signature, and MICR — layered on the existing layout (defaults render
identically). Edited in Settings → Check Setup ("Element positions").
Stored in accounting.check_settings.field_positions (jsonb). Also replaced a
"→" with ">" in the MICR placeholder to avoid the UTF-16 spacing artifact.

Migration applied: check_settings.field_positions.

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