Commit Graph

62 Commits

Author SHA1 Message Date
05e241c792 fix: allow null planned_date when updating projects
Empty string date values from the frontend were being passed directly
to PostgreSQL, which cannot cast "" to DATE. Normalize empty strings
to null for all date columns in the update method and the dedicated
updatePlannedDate endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 10:05:29 -05:00
5ee4c71fc1 chore: update package-lock.json with newrelic dependency
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 09:54:12 -05:00
81908e48ea feat: add New Relic APM instrumentation to backend
Add Node.js New Relic agent with an on/off switch via NEW_RELIC_ENABLED
in .env. Uses a preload script (-r newrelic-preload.js) so the agent
loads before all other modules. Configured entirely through environment
variables — no newrelic.js config file needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 09:31:56 -05:00
6230558b91 fix: remove backend/frontend host port mappings from base compose
Docker Compose merges port arrays from base + override files, so the
base 3000:3000 and the prod overlay 127.0.0.1:3000:3000 conflicted.
Removed direct host port mappings from the base — dev traffic already
routes through the Docker nginx on port 80 via the bridge network.
The prod overlay cleanly adds loopback-only mappings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 20:14:24 -05:00
2c215353d4 refactor: remove Docker nginx from production, use host nginx directly
The production stack no longer runs a Docker nginx container. Instead,
the host-level nginx handles SSL termination AND request routing:
  /api/* → 127.0.0.1:3000 (backend)
  /*     → 127.0.0.1:3001 (frontend)

Changes:
- docker-compose.prod.yml: set nginx replicas to 0, expose backend and
  frontend on 127.0.0.1 only (loopback)
- nginx/host-production.conf: new ready-to-copy host nginx config with
  SSL, rate limiting, proxy buffering, and AI endpoint timeouts
- docs/DEPLOYMENT.md: rewritten production deployment and SSL sections
  to reflect the simplified single-nginx architecture

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 20:08:32 -05:00
d526025926 fix: map Docker nginx to port 8080 to avoid conflict with host reverse proxy
The base docker-compose.yml maps nginx to 80:80, which conflicts with
the host-level nginx that handles SSL termination on production servers.
The production overlay now explicitly maps to 8080:80 so the host proxy
can forward to localhost:8080. Updated DEPLOYMENT.md with host reverse
proxy setup instructions and corrected architecture diagrams.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:59:24 -05:00
411239bea4 Prod infra: frontend on port 3001, remove certbot from compose
- Frontend container nginx listens on 3001 instead of 80 to avoid
  conflicts with the host-level reverse proxy
- Removed certbot service, volumes, and SSL config from
  docker-compose.prod.yml — SSL/certbot is managed at the host level
- Updated nginx/production.conf: HTTP-only (host handles TLS),
  upstream frontend points to port 3001
- Updated nginx/ssl.conf frontend upstream to 3001 for consistency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:43:14 -05:00
7e6c4c16ce Update backend/src/main.ts 2026-03-02 17:56:01 -05:00
ea0e3d6f29 Fix TS error: guard null target_year in KanbanCard comparison
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 17:00:55 -05:00
8db89373e0 Add production infrastructure: compiled builds, clustering, connection pooling
Root cause of 502 errors under 30 concurrent users: the production server
was running dev-mode infrastructure (Vite dev server, NestJS --watch,
no DB connection pooling, single Node.js process).

Changes:
- backend/Dockerfile: multi-stage prod build (compiled JS, no devDeps)
- frontend/Dockerfile: multi-stage prod build (static assets served by nginx)
- frontend/nginx.conf: SPA routing config for frontend container
- docker-compose.prod.yml: production overlay with tuned Postgres, memory
  limits, health checks, restart policies
- nginx/production.conf: keepalive upstreams, proxy buffering, rate limiting
- backend/src/main.ts: Node.js clustering (1 worker per CPU, up to 4),
  conditional request logging, production CORS
- backend/src/app.module.ts: TypeORM connection pool (max 30, min 5)
- docs/DEPLOYMENT.md: new Production Deployment section

Deploy with: docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 16:55:30 -05:00
e719f593de Update frontend/vite.config.ts
Adding ssl hostname
2026-03-02 15:13:36 -05:00
16adfd6f26 Fix: add react-joyride to frontend dependencies
The package was imported by AppTour.tsx but missing from package.json,
causing a build failure on fresh installs / production deploys.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 15:06:27 -05:00
704f29362a Add database backup/restore script with auto-pruning
scripts/db-backup.sh provides three commands:
- backup: creates a timestamped, gzipped pg_dump (custom format) in ./backups/
- restore: drops, recreates, and loads a backup with confirmation prompt
- list: shows available backups with sizes and dates

Supports --keep N flag for automatic pruning of backups older than N days,
making it cron-friendly for daily automated backups. Also adds backups/
and *.dump.gz to .gitignore.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 14:40:51 -05:00
42767e3119 Add SSL/TLS support with Certbot and update deployment guide
- nginx/ssl.conf: full HTTPS config with HTTP→HTTPS redirect, modern TLS
  settings, HSTS header, and ACME challenge passthrough for renewals
- nginx/certbot-init.conf: minimal HTTP config for initial cert provisioning
- docker-compose.ssl.yml: compose override adding port 443, certbot volumes,
  and auto-renewal sidecar container
- docs/DEPLOYMENT.md: comprehensive 3-phase SSL walkthrough (obtain cert,
  enable SSL, auto-renewal) with day-to-day usage and revert instructions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 14:28:01 -05:00
a550a8d0be Add deployment guide for staging Docker servers with DB backup/restore
Covers fresh server setup, environment configuration, database backup
(full and per-tenant), restore into staged environment, migration
execution, and verification steps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 14:09:32 -05:00
063741adc7 Capital Planning: add Unscheduled bucket for imported projects without target_year
Projects imported via CSV that lack a target_year were invisible in Capital
Planning because findForPlanning() filtered on target_year IS NOT NULL. This
removes that filter and adds an "Unscheduled" Kanban column (orange background,
2-col layout) so users can drag unscheduled projects into year buckets.
Also bumps app version to 2026.3.2 (beta).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 14:03:39 -05:00
ad2f16d93b Capital Planning: show beyond-window projects in Future bucket, 2-col layout
Projects with target years beyond the 5-year planning window now
appear in the Future column of the Kanban board (previously they
were invisible). Cards for these projects show their specific target
year as a badge. The Future column uses a 2-column grid layout when
it has more than 3 projects to maximize screen utilization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 12:16:20 -05:00
b0b36df4e4 Reserve health: add projected cash flow with special assessments; add Last Updated to cards
Reserve fund analysis now includes 12-month forward projection with
special assessment income (by frequency), monthly budget data,
capital project costs, and investment maturities. AI prompt updated
to evaluate projected reserve liquidity and timing risks.

Both health score dashboard cards now show a subtle "Last updated"
timestamp at the bottom.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:18:34 -05:00
aa7f2dab32 Add 12-month projected cash flow to operating health score analysis
The operating health score now includes forward-looking cash flow
projections using monthly budget data, assessment income schedules,
and operating project costs. AI prompt updated to evaluate projected
liquidity, timing risks, and year-end cash position.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:10:51 -05:00
d2d553eed6 Fix health scores: use correct invoices column name (amount, not amount_due)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:00:23 -05:00
2ca277b6e6 Phase 8: AI-driven operating and reserve fund health scores
Add daily AI health score calculation (0-100) for both operating and
reserve funds. Scores include trajectory tracking, factor analysis,
recommendations, and data readiness checks. Dashboard displays
graphical RingProgress gauges with color-coded scores, trend
indicators, and expandable detail popovers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 09:56:56 -05:00
bfcbe086f2 Fix WriteAccessGuard: use req.userRole from middleware (runs before guards)
The global WriteAccessGuard was checking req.user.role, but req.user is
set by JwtAuthGuard (a per-controller guard) which runs AFTER global guards.
TenantMiddleware sets req.userRole from the JWT before guards execute,
so we now check that property first.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 09:21:09 -05:00
c92eb1b57b RBAC: Enforce read-only viewer role across backend and frontend
- Add global WriteAccessGuard that blocks POST/PUT/PATCH/DELETE for viewer role
- Add @AllowViewer() decorator for endpoints viewers need (switch-org, intro-seen, AI recommendations)
- Add useIsReadOnly hook to auth store for frontend role checks
- Hide write UI (add/edit/delete/import buttons, inline editors) in all 13 data pages for viewers
- Disable inline NumberInputs on Budgets and Monthly Actuals pages for viewers
- Skip onboarding wizard for viewer role users

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 09:18:32 -05:00
07347a644f QoL tweaks: Cash Flow cards, auto-primary accounts, investment projections, Sankey filters
- Dashboard: Remove tenant name/role subtitle
- Cash Flow: Replace Operating/Reserve net cards with inflow vs outflow
  breakdown showing In/Out amounts and signed net; replace Ending Cash
  card with AI Financial Health status from saved recommendation
- Accounts: Auto-set first asset account per fund_type as primary on creation
- Investments: Add 5th summary card for projected annual interest earnings
- Sankey: Add Actuals/Budget/Forecast data source toggle and
  All Funds/Operating/Reserve fund filter SegmentedControls with
  backend support for budget-based and forecast (actuals+budget) queries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 14:22:37 -05:00
f1e66966f3 Phase 7: Add user onboarding tour and tenant setup wizard
Feature 1 - How-To Intro Tour (react-joyride):
- 8-step guided walkthrough highlighting Dashboard, Accounts, Assessments,
  Transactions, Budgets, Reports, and AI Investment Planning
- Runs automatically on first login, tracked via has_seen_intro flag on user
- Centralized step config in config/tourSteps.ts for easy text editing
- data-tour attributes on Sidebar nav items and Dashboard for targeting

Feature 2 - Tenant Onboarding Wizard:
- 3-step modal wizard: create operating account, assessment group + units,
  import budget CSV
- Runs after tour completes, tracked via onboardingComplete in org settings JSONB
- Reuses existing API endpoints (POST /accounts, /assessment-groups, /units,
  /budgets/:year/import)

Backend changes:
- Add has_seen_intro column to shared.users + migration
- Add PATCH /auth/intro-seen endpoint to mark tour complete
- Add PATCH /organizations/settings endpoint for org settings updates
- Include hasSeenIntro in login response, settings in switch-org response

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 09:47:45 -05:00
d1c40c633f Fix dashboard KPIs: resolve nested aggregate and missing column errors
- Wrap account interest query in subquery to avoid SUM(SUM(...)) nesting
- Replace nonexistent interest_earned column with current_value - principal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 09:11:37 -05:00
0e82e238c1 Bug & tweak sprint: fix financial calculations, add quarterly report, enhance dashboard
- Fix Accounts page: include investment accounts in Est. Monthly Interest calc,
  add Fund column to investment table, split summary cards into Operating/Reserve
- Fix Cash Flow: ending balance now respects includeInvestments toggle
- Fix Budget Manager: separate operating/reserve income in summary cards
- Fix Projects: default sort by planned_date instead of name
- Add Vendors: last_negotiated date field with migration, CSV import/export
- New Quarterly Financial Report: budget vs actuals, over-budget flagging, YTD
- Enhance Dashboard: separate Operating/Reserve fund cards, expanded Quick Stats
  with monthly interest, YTD interest earned, planned capital spend

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 18:17:30 -05:00
2fed5d6ce1 Phase 6: Expand market rates and enhance AI investment recommendations
- Rate fetcher now scrapes CD, Money Market, and High Yield Savings rates
  from Bankrate.com with pauses between fetches to avoid rate limiting
- Historical rate data is preserved (no longer deleted on each fetch)
- Database migration adds rate_type column and tenant ai_recommendations table
- Backend returns market rates grouped by type with latest-batch-only queries
- AI prompt now includes all three rate types for comprehensive analysis
- AI recommendations are saved per-tenant for retrieval on page load
- Frontend: "Market CD Rates" replaced with "Today's Market Rates" tabbed view
- Rates section is collapsible (expanded by default) to save screen space
- Saved recommendations load automatically with "Last Updated" timestamp

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 13:39:53 -05:00
d9bb9363dd Add admin enhancements: impersonation, plan management, org status enforcement
Enhancement 1 - Block suspended/archived org access:
- Add org status check in switchOrganization() (auth.service.ts)
- Filter suspended/archived orgs from login response (generateTokenResponse)
- Add org status guard with 60s cache in TenantMiddleware
- Frontend: filter orgs in SelectOrgPage, add 403 handler in api.ts

Enhancement 2 - Change tenant plan level:
- Add updatePlanLevel() to organizations.service.ts
- Add PUT /admin/organizations/:id/plan endpoint
- Frontend: clickable plan dropdown in Organizations table + confirmation modal
- Plan level Select in tenant detail drawer

Enhancement 3 - User impersonation:
- Add impersonateUser() to auth.service.ts with impersonatedBy JWT claim
- Add POST /admin/impersonate/:userId endpoint
- Frontend: Impersonate button in Users tab (disabled for admins)
- Impersonation state management in authStore (start/stop/persist)
- Orange impersonation banner in AppLayout header with stop button

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 13:21:59 -05:00
e156cf7c87 Fix TypeORM entity type for confirmationNumber column
TypeORM needs explicit type: 'varchar' for nullable string columns
to avoid reflecting the union type as Object.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 08:53:54 -05:00
76ab63a200 Fix TypeScript nullable types for subscription fields
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 08:53:15 -05:00
a32d4cc179 Add comprehensive platform administration panel
- Database: Add login_history, ai_recommendation_log tables; is_platform_owner
  column on users; subscription fields on organizations (payment_date,
  confirmation_number, renewal_date)
- Backend: New AdminAnalyticsService with platform metrics, tenant detail, and
  health score calculations (0-100 based on activity, budget, transactions,
  members, AI usage)
- Backend: Login/org-switch now records to login_history; AI recommendations
  logged to ai_recommendation_log; platform owner protected from superadmin toggle
- Frontend: 4-tab admin panel (Dashboard, Organizations, Users, Tenant Health)
  with tenant detail drawer, subscription management, health scoring visualization
- Platform owner account (admin@hoaledgeriq.com) auto-redirects to admin panel
- Seed data includes platform owner account and sample login history

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 08:51:39 -05:00
0bd30a0eb8 Add 12-month cash flow forecast to AI investment context
The AI was making incorrect liquidity warnings because it only saw
current cash positions and annual budget totals — it had no visibility
into the month-by-month cash flow forecast that includes:
- Special assessment collections (reserve fund income from homeowners)
- Monthly budget income/expense breakdown (not just annual totals)
- Investment maturity schedule (when CDs return cash)
- Capital project expense timing

Now the AI receives:
1. Full assessment schedule (regular + special, with frequency)
2. 12-month forward forecast with projected operating/reserve cash,
   investment balances, and per-month income/expense drivers
3. Updated system prompt instructing the AI to use the forecast for
   liquidity analysis rather than just current balances

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:04:57 -05:00
0626b8d496 Increase nginx proxy timeout for AI recommendations endpoint
The AI recommendation endpoint calls a large language model (397B params)
which can take 60-120 seconds to respond. Nginx's default 60s proxy_read_timeout
was killing the connection before the response arrived. Added a dedicated
location block with 180s timeout for the recommendations endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:55:05 -05:00
25663fc79e Add AI debug logging and switch from fetch to https module
- Add toggle-able debug logging (AI_DEBUG env var) that logs prompts,
  request metadata, raw responses, parsed output, and full error chains
- Replace Node.js native fetch() with https module for Docker Alpine
  compatibility (fixes "fetch failed" error with large payloads)
- Reduce max_tokens from 16384 to 4096 (qwen3.5 doesn't need thinking
  token budget)
- Strip <think> blocks from model responses
- Add AI_DEBUG to docker-compose.yml and .env.example

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:50:39 -05:00
fe4989bbcc Switch AI model from kimi-k2.5 to qwen/qwen3.5-397b-a17b
kimi-k2.5 is a thinking model that times out on complex prompts (>3min).
qwen3.5-397b-a17b responds in ~2s with clean JSON output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 20:37:48 -05:00
36271585d9 Fix AI timeout and token limits for thinking model (kimi-k2.5)
- Increase max_tokens from 4096 to 16384 to accommodate reasoning tokens
- Increase timeout from 90s to 180s for thinking model latency
- Add logging for response diagnostics (content length, reasoning, finish reason)
- Better error message when model exhausts tokens on reasoning

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 15:50:53 -05:00
18c7989983 Fix: units table uses status='active' not is_active column
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 15:37:47 -05:00
c28d7aeffc Fix TypeScript: export interfaces for controller return type resolution
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 15:32:55 -05:00
f7e9c98bd9 Phase 5: AI investment planning - CD rate fetcher and AI recommendation engine
- Add shared.cd_rates table for cross-tenant market data (CD rates from Bankrate)
- Create standalone Puppeteer scraper script (scripts/fetch-cd-rates.ts) for cron-based rate fetching
- Add investment-planning backend module with 3 endpoints: snapshot, cd-rates, recommendations
- AI service gathers tenant financial data (accounts, investments, budgets, projects, cash flow) and calls OpenAI-compatible API (NVIDIA endpoint) for structured investment recommendations
- Create InvestmentPlanningPage with summary cards, current investments table, market CD rates table, and AI recommendation accordion
- Add Investment Planning to sidebar under Planning menu
- Configure AI_API_URL, AI_API_KEY, AI_MODEL environment variables

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 15:31:32 -05:00
e0c956859b Fix bugs: monthly actuals month filter, unit assessments, project funding logic, UI cleanup
- Fix monthly actuals showing same data for all months (SQL JOIN excluded
  month filter from SUM — added je.id IS NOT NULL guard)
- Fix units displaying $0 assessment by reading from assessment group
  instead of stale unit field; add special assessment column
- Replace proportional project funding with priority-based sequential
  allocation — near-term items get fully funded first; add is_funding_locked
  flag so users can manually lock a project's fund balance
- Remove post-creation opening balance UI (keep only initial balance on
  account creation); remove redundant Fund filter dropdown from Accounts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 14:05:07 -05:00
45a267d787 Quality-of-life enhancements: CSV import/export, opening balances, interest rates, mobile UX
- CSV import/export for Units, Projects, and Vendors with match-on-name/number upsert
- Cash Flow report toggle for Cash Only vs Cash + Investments
- Per-account and bulk opening balance setting with as-of date
- Interest rate field on normal accounts with estimated monthly/annual interest display
- Mobile sidebar auto-close on navigation
- Shared CSV parsing/export utility extracted to frontend/src/utils/csv.ts

DB migration needed for existing tenants:
  ALTER TABLE accounts ADD COLUMN IF NOT EXISTS interest_rate DECIMAL(6,4);

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 09:13:51 -05:00
32af961173 Fix monthly actuals: allow negative values and fix save/reconcile error
- Remove min={0} from NumberInput to allow negative actuals (refunds/corrections)
- Fix post() in journal-entries service: use id param directly instead of
  RETURNING result which returns [rows, count] in TypeORM QueryRunner
- Handle negative amounts in saveActuals(): negative expense credits the
  expense account, negative income debits the income account

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:51:33 -05:00
84822474f8 Sprint 6: Monthly actuals input, reconciliation, and file attachments
Add spreadsheet-style Monthly Actuals page for entering monthly actuals
against budget with auto-generated journal entries and reconciliation flag.
Add file attachment support (PDF, images, spreadsheets) on journal entries
for receipts and invoices. Enhance Budget vs Actual report with month
filter dropdown. Add reconciled badge to Transactions page. Replace bcrypt
with bcryptjs to fix Docker cross-platform native binding issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:48:57 -05:00
ea49b91bb3 Sprint 5: User profile menu, preferences, org member management, v0.2.0
- Move Settings from sidebar Admin section to User Profile dropdown menu
- Add User Preferences page (placeholder for future: dark mode, timezone,
  notifications, feature visibility)
- Add Manage Members page for tenant admins to invite/manage board members:
  - List all org members with roles, status, join date, last login
  - Add new members (creates user account + org membership)
  - Change member roles (president, treasurer, secretary, board member,
    property manager, viewer)
  - Remove members (soft-deactivate)
  - Role-gated: only president, admin, treasurer can manage members
- Backend: new org member management endpoints on OrganizationsController
  - GET /organizations/members
  - POST /organizations/members
  - PUT /organizations/members/:id/role
  - DELETE /organizations/members/:id
- Bump version to 0.2.0 MVP_P2 (package.json + Settings page)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 16:39:17 -05:00
b5861de609 Filter Accounts page to show only cash positions (asset, liability, investment)
- Hide income, expense, and equity accounts from Accounts view — they are
  internal bookkeeping managed via budget import and system operations
- Restrict Add Account form to asset and liability types plus investments
- Update summary cards to show Cash on Hand, Investments, Liabilities, Net Position
- Reports (Income Statement, Balance Sheet, Budget vs Actual, etc.) are unchanged
  and continue to use all account types from their own API endpoints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 18:53:15 -05:00
017421a85a Fix budget page UI: annual totals, summary cards, sticky headers, column layout
- Compute annual_total on data load via hydrateBudgetLine() (was only computed on edit)
- Ensure monthly values are cast to numbers from PostgreSQL response
- Fix summary cards to use pre-computed annual_total instead of re-summing months
- Make Income/Expense section headers sticky so labels stay visible on horizontal scroll
- Split account number and name into separate columns for better readability
- Add section total in annual column for each income/expense group
- Add subtle border between frozen columns and scrollable month data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 18:44:19 -05:00
61e43212b9 Flexible budget import with auto-account creation and text-based account numbers
Change account_number from INTEGER to VARCHAR(50) to support segmented codes
like 30-3001-0000 used by real HOA accounting systems. Budget CSV import now:
- Auto-creates income/expense accounts from CSV when they don't exist
- Infers account_type and fund_type from account number prefix conventions
- Parses currency-formatted values ($48,065.21, $(13,000.00), $-, etc.)
- Reports created accounts back to the user

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 14:24:00 -05:00
1e40848222 Add investments to All tab, withdrawal on create, modal fixes, and login logo
- Show investment subtable under All accounts tab (was only under Operating/Reserve)
- Add "Withdraw from primary account" switch (on by default) when creating
  investments; creates a journal entry to credit the primary asset account
  and debit the equity offset, keeping the books balanced
- Prevent all account modals from closing on outside click to avoid data loss
- Replace login page text title with the SVG logo

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:57:40 -05:00
d4ae5d1d33 Hide system equity accounts from Accounts page
System accounts (Operating Fund Balance, Reserve Fund Balance) are auto-created
as double-entry offsets when users set initial balances. They don't represent
real bank accounts and were confusing to see alongside actual accounts. Now
filtered from account lists, tab counts, and summary card totals. They remain
active under the covers for journal entries and are still visible on the
Balance Sheet report where equity belongs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:44:58 -05:00