← 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
M scripts/lib/deal-parse.mjsM test/deals/parse.test.mjs
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 →