← back to Nationalrealestate
src/ingest/brokers/fl_dbpr.ts
64 lines
/**
* FL — DBPR free licensee extracts (www2.myfloridalicense.com/sto/file_download/extracts/,
* refreshed ~daily, probed 2026-07-21). 14 regional files RE_rgn1..14.csv, headerless
* DBPR standard layout (latin-1). Column map (0-based, verified against live rows):
* 1 license-type group · 2 name · 3 dba · 4 rank ("SL Sales Associate", "BK Broker",
* "BL Broker Sales", "CQ RE Corp.", "PR RE Partnership", branch/instructor ranks)
* 8 city · 9 state · 13 numeric license # · 14 primary status ("Current"/"Invol Inactive"…)
* 15 secondary status ("Active"/"Inactive") · 19 prefixed license # (SL1234567)
* 21 employer firm name · 22 employer numeric license #.
* Firm source_id uses the NUMERIC license number so CQ firm rows and employer refs join.
*/
import { download } from '../run.ts';
import { parseCsvFile } from './csv.ts';
import type { BrokerRow, FetchedFile, StateAdapter } from './types.ts';
const BASE = 'https://www2.myfloridalicense.com/sto/file_download/extracts/';
const REGIONS = Array.from({ length: 14 }, (_, i) => `RE_rgn${i + 1}.csv`);
export const flDbpr: StateAdapter = {
state: 'FL',
source: 'fl_dbpr',
url: BASE + 'RE_rgn1.csv',
async fetch() {
const out = [];
for (const f of REGIONS) out.push(await download(BASE + f, `fl_dbpr_${f}`));
return out;
},
*parse(files: FetchedFile[]): Generator<BrokerRow> {
for (const file of files) {
for (const r of parseCsvFile(file.path, 'latin1')) {
if (r.length < 20) continue;
const rank = (r[4] || '').trim();
const prefix = rank.slice(0, 2).toUpperCase();
const name = (r[2] || '').trim();
const licNo = (r[19] || '').trim() || (r[13] || '').trim();
if (!name || !licNo) continue;
const status = [r[14], r[15]].map(s => (s || '').trim()).filter(Boolean).join(' / ') || null;
const city = (r[8] || '').trim() || null;
const st = (r[9] || '').trim().toUpperCase() || null;
if (prefix === 'CQ' || prefix === 'PR') {
yield {
kind: 'firm', name, license_no: licNo,
license_type: prefix === 'CQ' ? 'Real Estate Corporation' : 'Real Estate Partnership',
license_status: status, city, state_code: st,
// numeric license joins employer refs — engine keys firms on firm_license_no
firm_license_no: (r[13] || '').trim() || null,
};
} else if (prefix === 'SL' || prefix === 'BK' || prefix === 'BL') {
const empName = (r[21] || '').trim() || null;
const empLic = (r[22] || '').trim() || null;
yield {
kind: 'broker', name, license_no: licNo,
license_type: rank.slice(3).trim() || rank,
license_status: status,
firm_name: empName, firm_license_no: empName ? empLic : null,
city, state_code: st,
};
}
// branch offices / instructors / additional locations skipped by design
}
}
},
};