[object Object]

← 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

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 →