← back to La Socrata Ingester
yoloforever c7: RE-news deals-digest markdown generator (scripts/deals-digest.js)
02d9b82fd607e65f498d3e449fb7835976b8abf3 · 2026-08-12 07:43:12 -0700 · steve
Reads the latest deals-feed JSON (single source of truth) and renders publishable
markdown: top deals w/ council member + parcel value + map links + ⚠verify flags,
by-council-district table, source disclaimer. Presentation layer only.
Files touched
A scripts/deals-digest.js
Diff
commit 02d9b82fd607e65f498d3e449fb7835976b8abf3
Author: steve <steve@designerwallcoverings.com>
Date: Wed Aug 12 07:43:12 2026 -0700
yoloforever c7: RE-news deals-digest markdown generator (scripts/deals-digest.js)
Reads the latest deals-feed JSON (single source of truth) and renders publishable
markdown: top deals w/ council member + parcel value + map links + ⚠verify flags,
by-council-district table, source disclaimer. Presentation layer only.
---
scripts/deals-digest.js | 81 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/scripts/deals-digest.js b/scripts/deals-digest.js
new file mode 100644
index 0000000..99f0c78
--- /dev/null
+++ b/scripts/deals-digest.js
@@ -0,0 +1,81 @@
+// RE-news deals digest (READ-ONLY, $0 local). Reads the latest deals-feed-*.json
+// (the data layer from deals-feed.js) and renders a publishable markdown digest —
+// top deals + by-council-district sections + data-quality flags + source disclaimer.
+// Presentation only; the ranking logic lives in deals-feed.js (single source of truth).
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const DIR = path.resolve(__dirname, '../tmp/leads');
+const money = v => v == null ? null : '$' + Math.round(Number(v)).toLocaleString();
+const millions = v => '$' + (Number(v) / 1e6).toFixed(Number(v) >= 1e7 ? 0 : 1) + 'M';
+
+function latestFeed() {
+ if (!fs.existsSync(DIR)) return null;
+ const f = fs.readdirSync(DIR).filter(x => /^deals-feed-.*\.json$/.test(x)).sort().pop();
+ return f ? path.join(DIR, f) : null;
+}
+
+function main() {
+ const feedPath = latestFeed();
+ if (!feedPath) { console.error('No deals-feed-*.json found — run: node scripts/deals-feed.js'); process.exit(1); }
+ const feed = JSON.parse(fs.readFileSync(feedPath, 'utf8'));
+ const deals = feed.deals || [];
+ const stamp = feed.generated;
+ const totalValue = deals.reduce((s, d) => s + (d.project_value || 0), 0);
+ const flagged = deals.filter(d => d.valuation_outlier).length;
+
+ const L = [];
+ L.push(`# LA Development Deals — ${stamp}`);
+ L.push('');
+ L.push(`**${deals.length}** notable building permits issued in the last ${feed.window_days} days (project value ≥ ${money(feed.min_value)}), ranked by lead score. Total tracked project value: **${money(totalValue)}**.`);
+ L.push('');
+
+ // Top deals
+ L.push('## Top deals');
+ L.push('');
+ deals.slice(0, 15).forEach((d, i) => {
+ const bits = [];
+ if (d.council_member) bits.push(`CD ${d.council_district} · ${d.council_member}`);
+ if (d.assessed_value) bits.push(`parcel assessed ${millions(d.assessed_value)}`);
+ if (d.year_built) bits.push(`built ${d.year_built}`);
+ if (d.sqft) bits.push(`${Number(d.sqft).toLocaleString()} sqft`);
+ bits.push(`issued ${d.issued}`);
+ bits.push(`lead ${d.lead_score}`);
+ const mapLink = d.map ? ` · [map](${d.map})` : '';
+ const flag = d.valuation_outlier ? ' _(⚠ valuation unverified)_' : '';
+ L.push(`${i + 1}. **${millions(d.project_value)} ${d.kind}** — ${d.address}${d.zip ? ', ' + d.zip : ''}${flag}`);
+ L.push(` ${bits.join(' · ')}${mapLink}`);
+ L.push('');
+ });
+
+ // By council district
+ const byCd = {};
+ for (const d of deals) {
+ const k = d.council_district || '—';
+ (byCd[k] ||= { member: d.council_member, count: 0, value: 0 });
+ byCd[k].count++; byCd[k].value += d.project_value || 0;
+ }
+ const cdSorted = Object.entries(byCd).sort((a, b) => b[1].value - a[1].value).slice(0, 8);
+ L.push('## By council district');
+ L.push('');
+ L.push('| District | Member | Deals | Tracked value |');
+ L.push('|---|---|---:|---:|');
+ for (const [cd, v] of cdSorted) L.push(`| CD ${cd} | ${v.member || '—'} | ${v.count} | ${money(v.value)} |`);
+ L.push('');
+
+ // Notes
+ L.push('## Notes');
+ L.push('');
+ if (flagged) L.push(`- **${flagged}** deal(s) flagged _⚠ valuation unverified_ — LADBS permit valuations are self-reported; verify institutional-scale (>$100M) or parcel-mismatched figures before publishing.`);
+ L.push('- Data: City of Los Angeles building permits (public records) enriched with LA County Assessor parcel values. Provided as-is; not independently verified. Not affiliated with any government agency.');
+ L.push('');
+
+ const out = path.join(DIR, `deals-digest-${stamp}.md`);
+ fs.writeFileSync(out, L.join('\n'));
+ console.log(L.slice(0, 26).join('\n'));
+ console.log(`\n… digest (${deals.length} deals) → ${out}`);
+}
+
+main();
← 4aad896 yoloforever c6 FIX (Cody): drop invalid per-ZIP ratio, add v
·
back to La Socrata Ingester
·
yoloforever c7 FIX (Cody): honest digest — verified-only hea d115714 →