4 Commits

Author SHA1 Message Date
f47fbfcf93 Merge branch 'claude/ecstatic-elgamal' 2026-03-11 15:42:24 -04:00
04771f370c fix: clarify reserve health score when no components are entered
- Add missing-data warning when reserve_components table is empty so
  users see "No reserve components found" on the dashboard
- Change AI prompt to show "N/A" instead of "0.0%" for funded ratio
  when no components exist, preventing misleading "0% funded" reports
- Instruct AI not to report 0% funded when data is simply missing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 15:42:15 -04:00
208c1dd7bc security: address assessment findings and bump to v2026.3.11
- C1: Disable Swagger UI in production (env gate)
- M1+M2: Add Helmet.js for security headers (CSP, X-Frame-Options,
  X-Content-Type-Options, Referrer-Policy) and remove X-Powered-By
- H2: Add @nestjs/throttler rate limiting (5 req/min on login/register)
- M4: Remove orgSchema from JWT payload and client-side storage;
  tenant middleware now resolves schema from orgId via cached DB lookup
- L1: Fix Chatwoot user identification (read from auth store on ready)
- Remove schemaName from frontend Organization type and UI displays

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 15:32:51 -04:00
a047144922 Added userID and URL to Chatwoot Script 2026-03-10 14:49:50 -04:00

View File

@@ -220,6 +220,14 @@ export class HealthScoresService {
missing.push(`No budget found for ${year}. Upload or create an annual budget.`);
}
// Should have reserve components (warn but don't block)
const components = await qr.query(
`SELECT COUNT(*) as cnt FROM reserve_components`,
);
if (parseInt(components[0].cnt) === 0) {
missing.push('No reserve components found. Add reserve components (roof, parking, pool, etc.) with replacement costs for an accurate funded-ratio calculation.');
}
// Should have capital projects (warn but don't block)
const projects = await qr.query(
`SELECT COUNT(*) as cnt FROM projects WHERE is_active = true`,
@@ -997,8 +1005,8 @@ Reserve Cash (bank accounts): $${data.reserveCash.toFixed(2)}
Reserve Investments: $${data.totalInvestments.toFixed(2)}
Total Reserve Fund: $${data.totalReserveFund.toFixed(2)}
Total Replacement Cost (all components): $${data.totalReplacementCost.toFixed(2)}
Percent Funded: ${data.percentFunded.toFixed(1)}%
Total Replacement Cost (all components): ${data.totalReplacementCost > 0 ? '$' + data.totalReplacementCost.toFixed(2) : '$0.00 (no reserve components entered — funded ratio cannot be calculated)'}
Percent Funded: ${data.totalReplacementCost > 0 ? data.percentFunded.toFixed(1) + '%' : 'N/A — no reserve components with replacement costs have been entered. Do NOT report a 0% funded ratio; instead note that funded ratio is unavailable due to missing component data.'}
Annual Reserve Contribution (budgeted income): $${data.annualReserveContribution.toFixed(2)}
Annual Reserve Expenses (budgeted): $${data.annualReserveExpenses.toFixed(2)}