Phase 3: Optimize & clean up — unified projects, account enhancements, new tenant fix

- Unify reserve_components + capital_projects into single projects model with
  full CRUD backend and new Projects page frontend
- Rewrite Capital Planning to read from unified projects/planning endpoint;
  add empty state directing users to Projects page when no planning items exist
- Add default designation to assessment groups with auto-set on first creation;
  units now require an assessment group (pre-populated with default)
- Add primary account designation (one per fund type) and balance adjustment
  via journal entries against equity offset accounts (3000/3100)
- Add computed investment fields (interest earned, maturity value, days remaining)
  with PostgreSQL date arithmetic fix for DATE - DATE integer result
- Restructure sidebar: investments in Accounts tab, Year-End under Reports,
  Planning section with Projects and Capital Planning
- Fix new tenant creation seeding unwanted default chart of accounts —
  new tenants now start with a blank slate

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 14:32:35 -05:00
parent 17fdacc0f2
commit 301f8a7bde
20 changed files with 1760 additions and 145 deletions

View File

@@ -19,7 +19,6 @@ export class TenantSchemaService {
await queryRunner.query(statement);
}
await this.seedDefaultChartOfAccounts(queryRunner, schemaName);
await this.seedDefaultFiscalPeriods(queryRunner, schemaName);
await queryRunner.commitTransaction();
@@ -45,6 +44,7 @@ export class TenantSchemaService {
is_1099_reportable BOOLEAN DEFAULT FALSE,
is_active BOOLEAN DEFAULT TRUE,
is_system BOOLEAN DEFAULT FALSE,
is_primary BOOLEAN DEFAULT FALSE,
balance DECIMAL(15,2) DEFAULT 0.00,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
@@ -110,6 +110,7 @@ export class TenantSchemaService {
special_assessment DECIMAL(10,2) DEFAULT 0.00,
unit_count INTEGER DEFAULT 0,
frequency VARCHAR(20) DEFAULT 'monthly' CHECK (frequency IN ('monthly', 'quarterly', 'annual')),
is_default BOOLEAN DEFAULT FALSE,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
@@ -281,6 +282,37 @@ export class TenantSchemaService {
updated_at TIMESTAMPTZ DEFAULT NOW()
)`,
// Unified Projects (replaces reserve_components + capital_projects for new features)
`CREATE TABLE "${s}".projects (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR(255) NOT NULL,
description TEXT,
category VARCHAR(100),
estimated_cost DECIMAL(15,2) NOT NULL DEFAULT 0,
actual_cost DECIMAL(15,2),
current_fund_balance DECIMAL(15,2) DEFAULT 0.00,
annual_contribution DECIMAL(12,2) DEFAULT 0.00,
fund_source VARCHAR(20) CHECK (fund_source IN ('operating', 'reserve', 'special_assessment')),
funded_percentage DECIMAL(5,2) DEFAULT 0,
useful_life_years INTEGER,
remaining_life_years DECIMAL(5,1),
condition_rating INTEGER CHECK (condition_rating BETWEEN 1 AND 10),
last_replacement_date DATE,
next_replacement_date DATE,
planned_date DATE,
target_year INTEGER,
target_month INTEGER CHECK (target_month BETWEEN 1 AND 12),
status VARCHAR(20) DEFAULT 'planned' CHECK (status IN (
'planned', 'approved', 'in_progress', 'completed', 'deferred', 'cancelled'
)),
priority INTEGER DEFAULT 3 CHECK (priority BETWEEN 1 AND 5),
account_id UUID REFERENCES "${s}".accounts(id),
notes TEXT,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
)`,
// Indexes
`CREATE INDEX "idx_${s}_je_date" ON "${s}".journal_entries(entry_date)`,
`CREATE INDEX "idx_${s}_je_fiscal" ON "${s}".journal_entries(fiscal_period_id)`,