[object Object]

← back to Rentv 2026

fix(deals): parseOccupancy counts 'N% pre-leased' (new-dev pre-leasing recall); parseYearBuilt uses \bbuilt so 'rebuilt in YYYY' (renovation year) isn't recorded as original construction year

83953f448c6b290518064f0419d5198b2cd591c6 · 2026-08-06 09:14:03 -0700 · Steve

Files touched

Diff

commit 83953f448c6b290518064f0419d5198b2cd591c6
Author: Steve <steve@designerwallcoverings.com>
Date:   Thu Aug 6 09:14:03 2026 -0700

    fix(deals): parseOccupancy counts 'N% pre-leased' (new-dev pre-leasing recall); parseYearBuilt uses \bbuilt so 'rebuilt in YYYY' (renovation year) isn't recorded as original construction year
---
 scripts/lib/deal-parse.mjs | 6 ++++--
 test/deals/parse.test.mjs  | 2 ++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/scripts/lib/deal-parse.mjs b/scripts/lib/deal-parse.mjs
index 434077c6..9d503008 100644
--- a/scripts/lib/deal-parse.mjs
+++ b/scripts/lib/deal-parse.mjs
@@ -110,8 +110,10 @@ export function parseAddress(body) {
   const m = body.match(/(?:located at|situated at|address is|\bat)\s+(\d{2,6}\s[A-Z][A-Za-z0-9.\- ]+?(?:Rd|Road|St|Street|Ave|Avenue|Blvd|Boulevard|Dr|Drive|Way|Ln|Lane|Pl|Place|Ct|Court|Pkwy|Parkway|Hwy|Highway)\b)/);
   return m ? m[1].trim() : null;
 }
-export function parseOccupancy(body) { const m = body.match(/(\d{1,3})%\s?(?:leased|occup)/i); return m ? +m[1] : null; }
-export function parseYearBuilt(body) { const m = body.match(/built in (\d{4})/i); return m ? +m[1] : null; }
+// "85% pre-leased" (common for new developments) counts as occupancy too, not just "leased"/"occupied".
+export function parseOccupancy(body) { const m = body.match(/(\d{1,3})%\s?(?:pre-?)?(?:leased|occup)/i); return m ? +m[1] : null; }
+// \bbuilt so "rebuilt/prebuilt in YYYY" (a RENOVATION year) isn't recorded as the original construction year.
+export function parseYearBuilt(body) { const m = body.match(/\bbuilt in (\d{4})/i); return m ? +m[1] : null; }
 
 // two-sentence summary from the body (drop the leading title echo + date stamp)
 export function summarize(title, body) {
diff --git a/test/deals/parse.test.mjs b/test/deals/parse.test.mjs
index 8fcf6b4c..ef0e2c44 100644
--- a/test/deals/parse.test.mjs
+++ b/test/deals/parse.test.mjs
@@ -136,8 +136,10 @@ test('parseSize: an implausibly small SF next to a unit count is dropped (multif
 test('parseOccupancy + parseYearBuilt', () => {
   assert.equal(parseOccupancy('the asset is 95% leased'), 95);
   assert.equal(parseOccupancy('100% occupied at closing'), 100);
+  assert.equal(parseOccupancy('85% pre-leased at delivery'), 85); // new-development pre-leasing counts
   assert.equal(parseOccupancy('no occupancy figure'), null);
   assert.equal(parseYearBuilt('the property was built in 1998'), 1998);
+  assert.equal(parseYearBuilt('the tower was rebuilt in 2019'), null); // a renovation year is not the build year
   assert.equal(parseYearBuilt('no vintage given'), null);
 });
 

← 0884d55a PR intel: Gmail correspondence sync + per-contact timeline  ·  back to Rentv 2026  ·  News map: add Street/Satellite base-layer toggle (Esri World eacf3831 →