← back to Nationalrealestate
src/ingest/brokers/ct_dcp_reb.ts
55 lines
/**
* CT — DCP "Real Estate Broker Licenses" on data.ct.gov (fwpc-pgqj; 21,754 rows
* probed 2026-07-26). The broker-side (REB) complement to the salesperson roster
* ingested by ct_dcp.ts (eqtn-rppv, RES credentials). Separate `source='ct_dcp_reb'`
* so REB.# credentials never collide with the salespersons' RES.# source_ids.
*
* `type` splits the roster: INDIVIDUAL → an individual broker licensee; the entity
* types (LIMITED LIABILITY COMPANY / CORPORATION / PARTNERSHIP / BUSINESS) are the
* brokerage FIRMS. All statuses kept (ACTIVE / INACTIVE / EXPIRED APPLICATION …),
* mailing city+state preserved. Cost $0 (SODA CSV).
*/
import { download } from '../run.ts';
import { parseCsvObjects } from './csv.ts';
import type { BrokerRow, FetchedFile, StateAdapter } from './types.ts';
const URL = 'https://data.ct.gov/resource/fwpc-pgqj.csv?$order=fullcredentialcode&$limit=100000';
const ENTITY = /^(BUSINESS|CORPORATION|PARTNERSHIP|LIMITED LIABILITY COMPANY)$/i;
export const ctDcpReb: StateAdapter = {
state: 'CT',
source: 'ct_dcp_reb',
url: URL,
async fetch() {
return [await download(URL, 'ct_dcp_broker_roster.csv')];
},
*parse(files: FetchedFile[]): Generator<BrokerRow> {
for (const o of parseCsvObjects(files[0].path)) {
const lic = (o.fullcredentialcode || '').replace(/\.[A-Za-z]+$/, '').trim();
if (!lic || !/\d/.test(lic)) continue;
const status = o.status || null;
const city = o.city || null;
const st = (o.state || '').toUpperCase() || null;
const type = (o.type || '').toUpperCase();
if (ENTITY.test(type)) {
const name = o.businessname || o.name;
if (!name) continue;
yield {
kind: 'firm', name, license_no: lic,
license_type: o.credential || 'Real Estate Broker', license_status: status,
city, state_code: st,
};
} else {
const name = o.name;
if (!name) continue;
yield {
kind: 'broker', name, license_no: lic,
license_type: o.credential || 'Real Estate Broker', license_status: status,
city, state_code: st,
};
}
}
},
};