corp-status: surface annual-report-overdue signal (backfilled for CT)
entity_cache had CT status but no annual-report clock, so the corporation-check tool told overdue-but-active CT businesses they were fine. Now: - backfill_ct_annual_report_due.py: pulls annual_report_due_date from the live CT Socrata registry into entity_cache.annual_report_due_date (keyed by accountnumber=entity_number). Ran: 577,562 CT rows populated, 235,875 overdue. - corp-status API: reads annual_report_due_date, returns annual_report_overdue + days_overdue, and bumps years_behind to >=1 for an overdue-but-active entity so the remediation cost isn't $0. This makes the tool match the CT campaign hook.
This commit is contained in:
parent
b016caecea
commit
42a7beb655
2 changed files with 160 additions and 1 deletions
|
|
@ -43,6 +43,11 @@ interface CorpStatusResult {
|
|||
state: string | null;
|
||||
// Computed fields
|
||||
years_behind: number;
|
||||
// Annual-report deadline signal (from entity_cache.annual_report_due_date,
|
||||
// currently backfilled for CT). null when we have no due date for this entity.
|
||||
annual_report_due_date: string | null;
|
||||
annual_report_overdue: boolean;
|
||||
annual_report_days_overdue: number | null;
|
||||
annual_report_fee_cents: number;
|
||||
annual_report_frequency: string | null;
|
||||
cost_per_year_cents: number;
|
||||
|
|
@ -71,7 +76,8 @@ export async function lookupCorpStatus(
|
|||
try {
|
||||
const exact = await pool.query(
|
||||
`SELECT entity_name, entity_number, entity_type, status,
|
||||
formation_date, dissolution_date, registered_agent, state
|
||||
formation_date, dissolution_date, registered_agent, state,
|
||||
annual_report_due_date
|
||||
FROM entity_cache
|
||||
WHERE state = $1 AND LOWER(entity_name) = LOWER($2)
|
||||
LIMIT 1`,
|
||||
|
|
@ -86,6 +92,7 @@ export async function lookupCorpStatus(
|
|||
const fuzzy = await pool.query(
|
||||
`SELECT entity_name, entity_number, entity_type, status,
|
||||
formation_date, dissolution_date, registered_agent, state,
|
||||
annual_report_due_date,
|
||||
similarity(entity_name, $2) AS sim
|
||||
FROM entity_cache
|
||||
WHERE state = $1 AND similarity(entity_name, $2) > 0.8
|
||||
|
|
@ -129,6 +136,7 @@ export async function lookupCorpStatus(
|
|||
dissolution_date: null,
|
||||
registered_agent: liveData.registered_agent || null,
|
||||
state,
|
||||
annual_report_due_date: null,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
|
|
@ -188,6 +196,28 @@ export async function lookupCorpStatus(
|
|||
}
|
||||
}
|
||||
|
||||
// Annual-report deadline signal (from entity_cache.annual_report_due_date,
|
||||
// backfilled for CT). This catches the common case the status field misses: a
|
||||
// business still "ACTIVE" whose annual report is nonetheless past due. When
|
||||
// overdue, ensure yearsBehind reflects at least the current lapse so the cost
|
||||
// estimate isn't $0 for a genuinely-overdue (but not-yet-forfeited) entity.
|
||||
const dueRaw = row.annual_report_due_date
|
||||
? new Date(row.annual_report_due_date as string)
|
||||
: null;
|
||||
const annualReportDueDate = dueRaw ? dueRaw.toISOString().slice(0, 10) : null;
|
||||
let annualReportOverdue = false;
|
||||
let annualReportDaysOverdue: number | null = null;
|
||||
if (dueRaw && !Number.isNaN(dueRaw.getTime())) {
|
||||
const days = Math.floor((Date.now() - dueRaw.getTime()) / 86400000);
|
||||
annualReportDaysOverdue = days;
|
||||
annualReportOverdue = days > 0;
|
||||
if (annualReportOverdue && yearsBehind === 0) {
|
||||
// Overdue-but-active: at least the current year's report is owed. Add a
|
||||
// second year only once it's more than ~a year late.
|
||||
yearsBehind = days > 400 ? 2 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Cost calculations
|
||||
const costPerYear = annualFee + FILING_MARKUP_CENTS;
|
||||
const totalCatchup = yearsBehind * costPerYear;
|
||||
|
|
@ -226,6 +256,9 @@ export async function lookupCorpStatus(
|
|||
principal_address: (row.principal_address as string) || null,
|
||||
state,
|
||||
years_behind: yearsBehind,
|
||||
annual_report_due_date: annualReportDueDate,
|
||||
annual_report_overdue: annualReportOverdue,
|
||||
annual_report_days_overdue: annualReportDaysOverdue,
|
||||
annual_report_fee_cents: annualFee,
|
||||
annual_report_frequency: frequency,
|
||||
cost_per_year_cents: costPerYear,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue