@uwmd/core 2.8.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.d.ts +9 -2
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +9 -2
- package/dist/browser.js.map +1 -1
- package/dist/calc/errors.d.ts +1 -1
- package/dist/calc/errors.d.ts.map +1 -1
- package/dist/calc/errors.js.map +1 -1
- package/dist/calc/index.js +3 -3
- package/dist/calc/index.js.map +1 -1
- package/dist/capital-stack.d.ts +6 -2
- package/dist/capital-stack.d.ts.map +1 -1
- package/dist/capital-stack.js +5 -0
- package/dist/capital-stack.js.map +1 -1
- package/dist/cash-flow-series.d.ts +7 -0
- package/dist/cash-flow-series.d.ts.map +1 -1
- package/dist/cash-flow-series.js +10 -3
- package/dist/cash-flow-series.js.map +1 -1
- package/dist/cli-cash-flows.d.ts +16 -0
- package/dist/cli-cash-flows.d.ts.map +1 -0
- package/dist/cli-cash-flows.js +96 -0
- package/dist/cli-cash-flows.js.map +1 -0
- package/dist/cli.js +90 -0
- package/dist/cli.js.map +1 -1
- package/dist/format.d.ts +1 -0
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +9 -0
- package/dist/format.js.map +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/property-cash-flow-inputs.d.ts +34 -0
- package/dist/property-cash-flow-inputs.d.ts.map +1 -0
- package/dist/property-cash-flow-inputs.js +95 -0
- package/dist/property-cash-flow-inputs.js.map +1 -0
- package/dist/property-cash-flows.d.ts +13 -0
- package/dist/property-cash-flows.d.ts.map +1 -0
- package/dist/property-cash-flows.js +369 -0
- package/dist/property-cash-flows.js.map +1 -0
- package/dist/protocol.d.ts +117 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +32 -2
- package/dist/protocol.js.map +1 -1
- package/dist/renderer.d.ts +5 -0
- package/dist/renderer.d.ts.map +1 -1
- package/dist/renderer.js +22 -3
- package/dist/renderer.js.map +1 -1
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +19 -3
- package/dist/report.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validator.d.ts +3 -0
- package/dist/validator.d.ts.map +1 -1
- package/dist/validator.js +288 -2
- package/dist/validator.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/waterfall.d.ts +6 -0
- package/dist/waterfall.d.ts.map +1 -1
- package/dist/waterfall.js +17 -7
- package/dist/waterfall.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
import { UNLEVERED_SALE_DEDUCTIONS, RESERVED_LEVERED_SALE_DEDUCTIONS } from './protocol.js';
|
|
2
|
+
import { CalcError } from './calc/errors.js';
|
|
3
|
+
import { isDayCountConvention, parseISODate } from './calc/day-count.js';
|
|
4
|
+
import { periodSection, periodPayload } from './period-path.js';
|
|
5
|
+
import { projectLeaseUpCashFlows, LeaseUpCashFlowProjectionError } from './lease-up-cash-flows.js';
|
|
6
|
+
import { CASH_FLOW_KINDS, CASH_FLOW_VERIFY_DECIMALS, quantizeAtDecimals, verifyCashFlowSeries, } from './cash-flow-series.js';
|
|
7
|
+
const own = (v, key) => Object.prototype.hasOwnProperty.call(v, key);
|
|
8
|
+
const isObj = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
9
|
+
const finite = (v) => typeof v === 'number' && Number.isFinite(v);
|
|
10
|
+
const text = (v) => typeof v === 'string' && v.length > 0;
|
|
11
|
+
export class PropertyCashFlowAssemblyError extends CalcError {
|
|
12
|
+
proto;
|
|
13
|
+
constructor(reason, message, pointer, evidence) {
|
|
14
|
+
super('CALC-CF-ASSEMBLY', message, pointer);
|
|
15
|
+
this.name = 'PropertyCashFlowAssemblyError';
|
|
16
|
+
this.proto = { category: 'calc', code: 'CALC-CF-ASSEMBLY', reason, message, pointer,
|
|
17
|
+
...(evidence ? { evidence } : {}) };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function refuse(reason, message, pointer, evidence) {
|
|
21
|
+
throw new PropertyCashFlowAssemblyError(reason, message, pointer, evidence);
|
|
22
|
+
}
|
|
23
|
+
function shape(v, keys, pointer) {
|
|
24
|
+
if (!isObj(v) || Object.keys(v).length !== keys.length || keys.some(k => !own(v, k)))
|
|
25
|
+
refuse('plan', `Expected exactly: ${keys.join(', ')}.`, pointer);
|
|
26
|
+
}
|
|
27
|
+
function string(v, pointer) {
|
|
28
|
+
if (!text(v))
|
|
29
|
+
refuse('plan', 'Expected a nonempty string.', pointer);
|
|
30
|
+
}
|
|
31
|
+
const assertionKeys = [
|
|
32
|
+
'cash_amounts_only', 'no_financing_or_investor_tax', 'no_overlapping_economic_amounts',
|
|
33
|
+
'reserve_spending_excluded', 'gross_sale_excludes_reserve_release',
|
|
34
|
+
'no_terminal_restricted_reserve', 'hold_only_and_exit_settled',
|
|
35
|
+
];
|
|
36
|
+
function validatePlan(value) {
|
|
37
|
+
shape(value, ['basis', 'tax_basis', 'currency_code', 'day_count', 'acquisition_date',
|
|
38
|
+
'disposition_date', 'lease_up', 'supplemental', 'assertions', 'coverage',
|
|
39
|
+
// RFC 0052 members are optional; a plan omitting both behaves as it did before.
|
|
40
|
+
...(isObj(value) && own(value, 'sale_deductions') ? ['sale_deductions'] : []),
|
|
41
|
+
...(isObj(value) && own(value, 'net_sale_proceeds') ? ['net_sale_proceeds'] : []),
|
|
42
|
+
], 'plan');
|
|
43
|
+
for (const k of ['basis', 'tax_basis', 'currency_code', 'day_count', 'acquisition_date', 'disposition_date'])
|
|
44
|
+
string(value[k], `plan.${k}`);
|
|
45
|
+
shape(value.lease_up, ['source_variant', 'currency_code', 'cash_dates'], 'plan.lease_up');
|
|
46
|
+
shape(value.supplemental, ['source_variant', 'currency_code'], 'plan.supplemental');
|
|
47
|
+
for (const k of ['lease_up', 'supplemental']) {
|
|
48
|
+
string(value[k].source_variant, `plan.${k}.source_variant`);
|
|
49
|
+
string(value[k].currency_code, `plan.${k}.currency_code`);
|
|
50
|
+
}
|
|
51
|
+
if (!Array.isArray(value.lease_up.cash_dates) || value.lease_up.cash_dates.length === 0)
|
|
52
|
+
refuse('plan', 'Expected a nonempty cash date map.', 'plan.lease_up.cash_dates');
|
|
53
|
+
Array.from(value.lease_up.cash_dates).forEach((row, i) => {
|
|
54
|
+
const p = `plan.lease_up.cash_dates[${i}]`;
|
|
55
|
+
shape(row, ['period', 'date'], p);
|
|
56
|
+
string(row.period, `${p}.period`);
|
|
57
|
+
string(row.date, `${p}.date`);
|
|
58
|
+
});
|
|
59
|
+
shape(value.assertions, assertionKeys, 'plan.assertions');
|
|
60
|
+
if (!Array.isArray(value.coverage) || value.coverage.length === 0)
|
|
61
|
+
refuse('plan', 'Expected nonempty coverage declarations.', 'plan.coverage');
|
|
62
|
+
Array.from(value.coverage).forEach((row, i) => {
|
|
63
|
+
const p = `plan.coverage[${i}]`;
|
|
64
|
+
shape(row, ['slot', 'category', isObj(row) && own(row, 'rows') ? 'rows' : 'zero'], p);
|
|
65
|
+
string(row.slot, `${p}.slot`);
|
|
66
|
+
string(row.category, `${p}.category`);
|
|
67
|
+
if (own(row, 'rows')) {
|
|
68
|
+
if (!Array.isArray(row.rows) || row.rows.length === 0 ||
|
|
69
|
+
Array.from(row.rows).some(v => !Number.isSafeInteger(v) || v < 0))
|
|
70
|
+
refuse('plan', 'rows requires nonnegative safe integer indexes.', `${p}.rows`);
|
|
71
|
+
}
|
|
72
|
+
else if (typeof row.zero !== 'string' || row.zero.trim().length === 0) {
|
|
73
|
+
refuse('plan', 'A zero declaration requires a nonblank explanation.', `${p}.zero`);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
if (value.basis !== 'unlevered' || value.tax_basis !== 'pre_tax')
|
|
77
|
+
refuse('basis_currency', 'Only unlevered pre-tax assembly is supported.', 'plan');
|
|
78
|
+
if (!isDayCountConvention(value.day_count))
|
|
79
|
+
refuse('basis_currency', 'An explicit registered day count is required.', 'plan.day_count');
|
|
80
|
+
if (!/^[A-Z]{3}$/.test(value.currency_code))
|
|
81
|
+
refuse('basis_currency', 'Declare one uppercase three-letter currency identity.', 'plan.currency_code');
|
|
82
|
+
for (const k of ['lease_up', 'supplemental']) {
|
|
83
|
+
if (value[k].currency_code !== value.currency_code)
|
|
84
|
+
refuse('basis_currency', 'Source currency must equal the plan currency.', `plan.${k}.currency_code`);
|
|
85
|
+
}
|
|
86
|
+
for (const k of assertionKeys) {
|
|
87
|
+
if (value.assertions[k] !== true)
|
|
88
|
+
refuse('coverage', 'An explicit true economic assertion is required.', `plan.assertions.${k}`);
|
|
89
|
+
}
|
|
90
|
+
validateSaleDeductions(value);
|
|
91
|
+
}
|
|
92
|
+
// RFC 0052. Names carry no sign rule of their own: the transaction_costs rule
|
|
93
|
+
// already governs every row they name, `seller_credits` included.
|
|
94
|
+
const SALE_DEDUCTION_NAMES = [...UNLEVERED_SALE_DEDUCTIONS, ...RESERVED_LEVERED_SALE_DEDUCTIONS];
|
|
95
|
+
function validateSaleDeductions(plan) {
|
|
96
|
+
if (own(plan, 'net_sale_proceeds') && !finite(plan.net_sale_proceeds))
|
|
97
|
+
refuse('plan', 'A stated net sale proceeds figure must be a finite number.', 'plan.net_sale_proceeds');
|
|
98
|
+
if (!own(plan, 'sale_deductions'))
|
|
99
|
+
return;
|
|
100
|
+
const named = plan.sale_deductions;
|
|
101
|
+
if (!Array.isArray(named) || named.length === 0)
|
|
102
|
+
refuse('plan', 'sale_deductions must be a nonempty list when stated.', 'plan.sale_deductions');
|
|
103
|
+
named.forEach((entry, i) => {
|
|
104
|
+
const p = `plan.sale_deductions[${i}]`;
|
|
105
|
+
shape(entry, isObj(entry) && own(entry, 'label') ? ['row', 'name', 'label'] : ['row', 'name'], p);
|
|
106
|
+
const row = entry.row;
|
|
107
|
+
if (!Number.isSafeInteger(row) || row < 0)
|
|
108
|
+
refuse('plan', 'row requires a nonnegative safe integer index.', `${p}.row`);
|
|
109
|
+
if (!SALE_DEDUCTION_NAMES.includes(entry.name))
|
|
110
|
+
refuse('sale_deduction', `Unknown deduction name. Use one of: ${SALE_DEDUCTION_NAMES.join(', ')}.`, `${p}.name`);
|
|
111
|
+
if (RESERVED_LEVERED_SALE_DEDUCTIONS.includes(entry.name))
|
|
112
|
+
refuse('sale_deduction', `${entry.name} is a levered, below-NOI amount reserved for a later contract; this assembly is unlevered and pre-tax. State it as "other" with a label if it genuinely belongs in a candidate stream.`, `${p}.name`);
|
|
113
|
+
if (entry.name === 'other' && !text(entry.label))
|
|
114
|
+
refuse('sale_deduction', 'An "other" deduction requires a nonempty label saying what it is.', `${p}.label`);
|
|
115
|
+
if (entry.name !== 'other' && own(entry, 'label'))
|
|
116
|
+
refuse('sale_deduction', 'Only an "other" deduction carries a label; the name already says what it is.', `${p}.label`);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const pointer = (section, variant) => `sections.${section}[${JSON.stringify(variant)}]`;
|
|
120
|
+
function select(parsed, section, variant) {
|
|
121
|
+
const p = pointer(section, variant);
|
|
122
|
+
try {
|
|
123
|
+
const block = periodSection(parsed, section, { sectionVariants: { [section]: variant } });
|
|
124
|
+
if (!block)
|
|
125
|
+
refuse('selection', 'Exact source variant is missing.', p);
|
|
126
|
+
return block;
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
if (e instanceof PropertyCashFlowAssemblyError)
|
|
130
|
+
throw e;
|
|
131
|
+
if (e instanceof CalcError)
|
|
132
|
+
refuse('selection', 'Cannot select the exact source variant.', p, { selection: e.proto });
|
|
133
|
+
throw e;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function structure(message, p, field, code = 'CF-01') {
|
|
137
|
+
refuse('structure', message, `${p}.${field}`, { structure: [
|
|
138
|
+
{ code, severity: 'error', section: 'cash_flow_series', field, message },
|
|
139
|
+
] });
|
|
140
|
+
}
|
|
141
|
+
// This boundary checks the selected payload, without validating unrelated deal sections.
|
|
142
|
+
function validateSupplemental(value, p, dayCount) {
|
|
143
|
+
if (!isObj(value))
|
|
144
|
+
refuse('structure', 'Expected cash_flow_series content.', p);
|
|
145
|
+
if (!isDayCountConvention(value.day_count))
|
|
146
|
+
structure('An explicit registered day count is required.', p, 'day_count');
|
|
147
|
+
if (value.day_count !== dayCount)
|
|
148
|
+
refuse('basis_currency', 'Source and plan day counts must agree.', `${p}.day_count`);
|
|
149
|
+
if (!Array.isArray(value.series) || value.series.length === 0)
|
|
150
|
+
structure('A nonempty dated series is required.', p, 'series', 'CF-02');
|
|
151
|
+
let prev;
|
|
152
|
+
let negative = false;
|
|
153
|
+
let positive = false;
|
|
154
|
+
for (const [i, row] of value.series.entries()) {
|
|
155
|
+
const field = `series[${i}]`;
|
|
156
|
+
if (!isObj(row))
|
|
157
|
+
structure('A cash row must be an object.', p, field);
|
|
158
|
+
if (typeof row.date !== 'string' || !parseISODate(row.date))
|
|
159
|
+
structure('Expected a real YYYY-MM-DD cash date.', p, `${field}.date`);
|
|
160
|
+
if (prev !== undefined && row.date < prev)
|
|
161
|
+
structure('Cash dates must be nondecreasing.', p, `${field}.date`, 'CF-02');
|
|
162
|
+
prev = row.date;
|
|
163
|
+
if (!finite(row.amount))
|
|
164
|
+
structure('Cash amounts must be finite numbers.', p, `${field}.amount`);
|
|
165
|
+
negative ||= row.amount < 0;
|
|
166
|
+
positive ||= row.amount > 0;
|
|
167
|
+
if (row.kind != null && !CASH_FLOW_KINDS.includes(row.kind))
|
|
168
|
+
structure('Unknown cash-flow kind.', p, `${field}.kind`);
|
|
169
|
+
if (row.label != null && typeof row.label !== 'string')
|
|
170
|
+
structure('Label must be text or null.', p, `${field}.label`);
|
|
171
|
+
}
|
|
172
|
+
const metrics = value.stated_metrics;
|
|
173
|
+
if (metrics != null) {
|
|
174
|
+
if (!isObj(metrics))
|
|
175
|
+
structure('stated_metrics must be an object or null.', p, 'stated_metrics');
|
|
176
|
+
for (const k of ['total_net', 'moic', 'xirr']) {
|
|
177
|
+
if (metrics[k] != null && !finite(metrics[k]))
|
|
178
|
+
structure('A stated metric must be finite or null.', p, `stated_metrics.${k}`);
|
|
179
|
+
}
|
|
180
|
+
if (metrics.xnpv != null && (!isObj(metrics.xnpv) || !finite(metrics.xnpv.rate) || !finite(metrics.xnpv.value)))
|
|
181
|
+
structure('xnpv requires finite rate and value.', p, 'stated_metrics.xnpv');
|
|
182
|
+
if (metrics.xirr != null && !(negative && positive))
|
|
183
|
+
structure('A stated xirr requires positive and negative amounts.', p, 'stated_metrics.xirr', 'CF-03');
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const leaseCategories = ['rent', 'concessions', 'ti_lc'];
|
|
187
|
+
const periodCategories = ['other_income', 'operating_expenses', 'other_capex', 'reserve_net'];
|
|
188
|
+
const key = (cell) => `${cell.slot}/${cell.category}`;
|
|
189
|
+
const cell = (slot, category) => ({ slot, category });
|
|
190
|
+
function dateInPeriod(date, period) {
|
|
191
|
+
if (/^\d{4}-\d{2}$/.test(period))
|
|
192
|
+
return date.slice(0, 7) === period;
|
|
193
|
+
return date.slice(0, 4) === period.slice(0, 4) &&
|
|
194
|
+
Math.floor((Number(date.slice(5, 7)) - 1) / 3) + 1 === Number(period.slice(-1));
|
|
195
|
+
}
|
|
196
|
+
/** Assemble a complete declared ledger. No monetary arithmetic or document writes. */
|
|
197
|
+
export async function assemblePropertyCashFlows(parsed, input) {
|
|
198
|
+
validatePlan(input);
|
|
199
|
+
const plan = structuredClone(input);
|
|
200
|
+
const snapshot = structuredClone(parsed);
|
|
201
|
+
const leaseBlock = select(snapshot, 'lease_up_schedule', plan.lease_up.source_variant);
|
|
202
|
+
const sourceBlock = select(snapshot, 'cash_flow_series', plan.supplemental.source_variant);
|
|
203
|
+
const source = periodPayload(sourceBlock);
|
|
204
|
+
const sourcePointer = pointer('cash_flow_series', plan.supplemental.source_variant);
|
|
205
|
+
validateSupplemental(source, sourcePointer, plan.day_count);
|
|
206
|
+
let projection;
|
|
207
|
+
try {
|
|
208
|
+
projection = await projectLeaseUpCashFlows(snapshot, {
|
|
209
|
+
source_variant: plan.lease_up.source_variant, day_count: plan.day_count,
|
|
210
|
+
cash_dates: plan.lease_up.cash_dates,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
catch (e) {
|
|
214
|
+
if (e instanceof LeaseUpCashFlowProjectionError)
|
|
215
|
+
refuse('verification', 'Lease-up projection refused.', pointer('lease_up_schedule', plan.lease_up.source_variant), { lease_up: e.proto });
|
|
216
|
+
if (e instanceof Error && e.message.startsWith('canonicalize:'))
|
|
217
|
+
refuse('structure', 'The source envelope contains a value that cannot be canonicalized.', 'sections');
|
|
218
|
+
throw e;
|
|
219
|
+
}
|
|
220
|
+
const verification = verifyCashFlowSeries(source);
|
|
221
|
+
if (verification.verdict !== 'verified')
|
|
222
|
+
refuse('verification', `Supplemental metrics are ${verification.verdict}.`, sourcePointer, { verification });
|
|
223
|
+
const hasMetrics = ['total_net', 'moic', 'xirr', 'xnpv'].some(k => source.stated_metrics != null && source.stated_metrics[k] != null);
|
|
224
|
+
const periods = periodPayload(leaseBlock).schedule.map(row => row.period);
|
|
225
|
+
if (!parseISODate(plan.acquisition_date) || !parseISODate(plan.disposition_date) ||
|
|
226
|
+
plan.acquisition_date >= plan.disposition_date ||
|
|
227
|
+
!dateInPeriod(plan.acquisition_date, periods[0]) ||
|
|
228
|
+
!dateInPeriod(plan.disposition_date, periods[periods.length - 1]))
|
|
229
|
+
refuse('date_horizon', 'Acquisition and disposition must bound the full source hold.', 'plan');
|
|
230
|
+
for (const [i, row] of projection.bindings.entries()) {
|
|
231
|
+
if (row.date < plan.acquisition_date || row.date > plan.disposition_date)
|
|
232
|
+
refuse('date_horizon', 'Lease-up cash date lies outside the hold.', `${pointer('lease_up_schedule', plan.lease_up.source_variant)}.schedule[${i}]`);
|
|
233
|
+
}
|
|
234
|
+
for (const [i, row] of source.series.entries()) {
|
|
235
|
+
if (row.date < plan.acquisition_date || row.date > plan.disposition_date)
|
|
236
|
+
refuse('date_horizon', 'Supplemental cash date lies outside the hold.', `${sourcePointer}.series[${i}].date`);
|
|
237
|
+
}
|
|
238
|
+
const required = [
|
|
239
|
+
...['purchase_price', 'transaction_costs', 'reserve_net'].map(c => cell('acquisition', c)),
|
|
240
|
+
...periods.flatMap(p => periodCategories.map(c => cell(p, c))),
|
|
241
|
+
...['gross_sale', 'transaction_costs', 'reserve_net'].map(c => cell('disposition', c)),
|
|
242
|
+
];
|
|
243
|
+
const requiredKeys = new Set(required.map(key));
|
|
244
|
+
const declarations = new Map();
|
|
245
|
+
const rowCells = new Map();
|
|
246
|
+
for (const [i, entry] of plan.coverage.entries()) {
|
|
247
|
+
const p = `plan.coverage[${i}]`;
|
|
248
|
+
if (!requiredKeys.has(key(entry)))
|
|
249
|
+
refuse('coverage', 'Unknown or lease-up-owned coverage cell.', p);
|
|
250
|
+
if (declarations.has(key(entry)))
|
|
251
|
+
refuse('coverage', 'Duplicate coverage cell.', p);
|
|
252
|
+
declarations.set(key(entry), { item: entry, index: i });
|
|
253
|
+
if (entry.rows)
|
|
254
|
+
for (const index of entry.rows) {
|
|
255
|
+
if (index >= source.series.length || rowCells.has(index))
|
|
256
|
+
refuse('coverage', 'Cash row is missing or already assigned.', `${p}.rows`);
|
|
257
|
+
rowCells.set(index, cell(entry.slot, entry.category));
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
for (const c of required)
|
|
261
|
+
if (!declarations.has(key(c)))
|
|
262
|
+
refuse('coverage', `Missing coverage for ${key(c)}.`, 'plan.coverage');
|
|
263
|
+
for (let i = 0; i < source.series.length; i++)
|
|
264
|
+
if (!rowCells.has(i))
|
|
265
|
+
refuse('coverage', 'Every supplemental row must be covered.', `${sourcePointer}.series[${i}]`);
|
|
266
|
+
for (const c of required) {
|
|
267
|
+
const { item, index } = declarations.get(key(c));
|
|
268
|
+
if (c.category === 'purchase_price' && !item.rows)
|
|
269
|
+
refuse('coverage', 'Acquisition requires a real negative purchase payment.', `plan.coverage[${index}]`);
|
|
270
|
+
for (const rowIndex of item.rows ?? []) {
|
|
271
|
+
const row = source.series[rowIndex];
|
|
272
|
+
if ((c.slot === 'acquisition' && row.date !== plan.acquisition_date) ||
|
|
273
|
+
(c.slot === 'disposition' && row.date !== plan.disposition_date))
|
|
274
|
+
refuse('date_horizon', 'Closing cash date must equal the declared closing date.', `${sourcePointer}.series[${rowIndex}].date`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
for (const c of required) {
|
|
278
|
+
const item = declarations.get(key(c)).item;
|
|
279
|
+
for (const rowIndex of item.rows ?? []) {
|
|
280
|
+
const amount = source.series[rowIndex].amount;
|
|
281
|
+
const bad = c.category === 'purchase_price' ? amount >= 0 :
|
|
282
|
+
['gross_sale', 'other_income'].includes(c.category) ? amount < 0 :
|
|
283
|
+
['transaction_costs', 'operating_expenses', 'other_capex'].includes(c.category) ? amount > 0 : false;
|
|
284
|
+
if (bad)
|
|
285
|
+
refuse('amount_sign', 'Cash amount has the wrong sign for its declared category.', `${sourcePointer}.series[${rowIndex}].amount`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// RFC 0052. Naming must be complete when present: a rollup over some of the
|
|
289
|
+
// deductions looks complete and is worse than no rollup at all.
|
|
290
|
+
const exitCostRows = declarations.get(key(cell('disposition', 'transaction_costs'))).item.rows ?? [];
|
|
291
|
+
if (plan.sale_deductions) {
|
|
292
|
+
const seen = new Set();
|
|
293
|
+
plan.sale_deductions.forEach((entry, i) => {
|
|
294
|
+
const p = `plan.sale_deductions[${i}].row`;
|
|
295
|
+
if (!exitCostRows.includes(entry.row))
|
|
296
|
+
refuse('sale_deduction', 'A named deduction must be a row covering (disposition, transaction_costs).', p);
|
|
297
|
+
if (seen.has(entry.row))
|
|
298
|
+
refuse('sale_deduction', 'A cash row carries exactly one deduction name.', p);
|
|
299
|
+
seen.add(entry.row);
|
|
300
|
+
});
|
|
301
|
+
const unnamed = exitCostRows.filter(r => !seen.has(r));
|
|
302
|
+
if (unnamed.length > 0)
|
|
303
|
+
refuse('sale_deduction', `Naming must cover every exit cost row; ${unnamed.length} row(s) are unnamed. Omit sale_deductions entirely, or name them all.`, 'plan.sale_deductions');
|
|
304
|
+
}
|
|
305
|
+
const bindings = projection.bindings.map((b, i) => ({
|
|
306
|
+
...b, output_row_index: 0, source_section: 'lease_up_schedule',
|
|
307
|
+
source_variant: plan.lease_up.source_variant, cells: leaseCategories.map(c => cell(periods[i], c)),
|
|
308
|
+
}));
|
|
309
|
+
// Keep each supplemental row's binding by source index: output_row_index is
|
|
310
|
+
// assigned after the sort below, and RFC 0052 evidence needs the pairing.
|
|
311
|
+
const supplementalBindings = new Map();
|
|
312
|
+
for (const [i, row] of source.series.entries()) {
|
|
313
|
+
const binding = {
|
|
314
|
+
output_row_index: 0, source_section: 'cash_flow_series', source_variant: plan.supplemental.source_variant,
|
|
315
|
+
source_path: `cash_flow_series.series[${i}].amount`, date: row.date, amount: row.amount,
|
|
316
|
+
cells: [rowCells.get(i)],
|
|
317
|
+
};
|
|
318
|
+
supplementalBindings.set(i, binding);
|
|
319
|
+
bindings.push(binding);
|
|
320
|
+
}
|
|
321
|
+
// Stable sort retains lease-up order, then supplemental source index on a tie.
|
|
322
|
+
bindings.sort((a, b) => a.date < b.date ? -1 : a.date > b.date ? 1 : 0);
|
|
323
|
+
bindings.forEach((b, i) => { b.output_row_index = i; });
|
|
324
|
+
const allCells = [
|
|
325
|
+
...required.filter(c => c.slot === 'acquisition'),
|
|
326
|
+
...periods.flatMap(p => [...leaseCategories, ...periodCategories].map(c => cell(p, c))),
|
|
327
|
+
...required.filter(c => c.slot === 'disposition'),
|
|
328
|
+
];
|
|
329
|
+
const cells = allCells.map(c => {
|
|
330
|
+
const declaration = declarations.get(key(c))?.item;
|
|
331
|
+
if (declaration && own(declaration, 'zero'))
|
|
332
|
+
return { ...c, zero: declaration.zero };
|
|
333
|
+
return { ...c, output_rows: bindings.filter(b => b.cells.some(v => key(v) === key(c))).map(b => b.output_row_index) };
|
|
334
|
+
});
|
|
335
|
+
// RFC 0052. Verify a stated figure; never derive one. The check spans the whole
|
|
336
|
+
// transaction_costs cell, not only the named rows, so it cannot be satisfied by
|
|
337
|
+
// leaving a deduction unnamed. reserve_net is excluded: a returned reserve is
|
|
338
|
+
// not sale proceeds, and the plan already asserts gross sale excludes it.
|
|
339
|
+
const grossSaleRows = declarations.get(key(cell('disposition', 'gross_sale'))).item.rows ?? [];
|
|
340
|
+
const sumOf = (rows) => rows.reduce((total, r) => total + source.series[r].amount, 0);
|
|
341
|
+
const dp = CASH_FLOW_VERIFY_DECIMALS.currency;
|
|
342
|
+
let netSaleProceeds = { status: 'not_stated' };
|
|
343
|
+
if (own(plan, 'net_sale_proceeds')) {
|
|
344
|
+
if (grossSaleRows.length === 0)
|
|
345
|
+
refuse('sale_deduction', 'A stated net sale proceeds figure requires a gross sale row.', 'plan.net_sale_proceeds');
|
|
346
|
+
const computed = quantizeAtDecimals(sumOf(grossSaleRows) + sumOf(exitCostRows), dp);
|
|
347
|
+
const stated = quantizeAtDecimals(plan.net_sale_proceeds, dp);
|
|
348
|
+
if (stated !== computed)
|
|
349
|
+
refuse('sale_deduction', `Stated net sale proceeds ${stated} disagrees with gross sale less exit costs ${computed}.`, 'plan.net_sale_proceeds');
|
|
350
|
+
netSaleProceeds = { status: 'verified', stated, computed };
|
|
351
|
+
}
|
|
352
|
+
const saleDeductions = plan.sale_deductions?.map(entry => ({
|
|
353
|
+
output_row_index: supplementalBindings.get(entry.row).output_row_index,
|
|
354
|
+
name: entry.name,
|
|
355
|
+
...(entry.label !== undefined ? { label: entry.label } : {}),
|
|
356
|
+
amount: source.series[entry.row].amount,
|
|
357
|
+
})).sort((a, b) => a.output_row_index - b.output_row_index);
|
|
358
|
+
return {
|
|
359
|
+
source_envelope_digest: projection.source_envelope_digest, plan,
|
|
360
|
+
coverage: 'declared_complete',
|
|
361
|
+
series: { label: 'Unlevered pre-tax property cash flow', day_count: plan.day_count,
|
|
362
|
+
series: bindings.map(b => ({ date: b.date, amount: b.amount, kind: 'other', label: b.source_path })) },
|
|
363
|
+
bindings, cells,
|
|
364
|
+
source_verification: { lease_up: 'verified', supplemental_metrics: hasMetrics ? 'verified' : 'not_stated' },
|
|
365
|
+
...(saleDeductions ? { sale_deductions: saleDeductions } : {}),
|
|
366
|
+
net_sale_proceeds: netSaleProceeds,
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
//# sourceMappingURL=property-cash-flows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"property-cash-flows.js","sourceRoot":"","sources":["../src/property-cash-flows.ts"],"names":[],"mappings":"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"}
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AssetClass, BlockRole, ConfidenceLevel, DealStage, FinancialThresholds, ParsedUWFile, PipelineStatus, UWBlock, UWMeta, UWSignatureAlgorithm, ValidationMessage, ValidationSeverity } from './types.js';
|
|
2
2
|
/** Semver of this protocol. Bumped independently of @uwmd/core's npm version. */
|
|
3
|
-
export declare const PROTOCOL_VERSION: "2.
|
|
3
|
+
export declare const PROTOCOL_VERSION: "2.13.0";
|
|
4
4
|
/**
|
|
5
5
|
* The format version this implementation *authors* — what a fresh scaffold
|
|
6
6
|
* declares. Reading is wider: see {@link SUPPORTED_FORMAT_VERSIONS}.
|
|
@@ -22,7 +22,7 @@ export declare const SUPPORTED_FORMAT_VERSIONS: readonly ["1.0", "1.1", "2.0"];
|
|
|
22
22
|
* v2 §1.3), so a module written against the 1.x protocol line still loads:
|
|
23
23
|
* its `requires_protocol` range is satisfied against any member of this set.
|
|
24
24
|
*/
|
|
25
|
-
export declare const SUPPORTED_PROTOCOL_VERSIONS: readonly ["1.14.0", "2.0.0", "2.1.0", "2.2.0", "2.
|
|
25
|
+
export declare const SUPPORTED_PROTOCOL_VERSIONS: readonly ["1.14.0", "2.0.0", "2.1.0", "2.2.0", "2.13.0"];
|
|
26
26
|
/** The four conformance tiers defined in UW_PROTOCOL_v1.md Part II. */
|
|
27
27
|
export type ViewerTier = 'tier-1-reader' | 'tier-2-editor' | 'tier-3-calc-host' | 'tier-4-agent-host';
|
|
28
28
|
/** What kind of actor the implementation serves. Informational. */
|
|
@@ -138,6 +138,8 @@ export declare const SUPPORTED_LOCALES: readonly ["en-US", "en-GB", "de-DE", "fr
|
|
|
138
138
|
export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number];
|
|
139
139
|
/** True when `tag` names a registered display locale (RFC 0001). */
|
|
140
140
|
export declare function isSupportedLocale(tag: unknown): tag is SupportedLocale;
|
|
141
|
+
/** True for the RFC 0046 document-level currency identity syntax. */
|
|
142
|
+
export declare function isCurrencyCode(value: unknown): value is string;
|
|
141
143
|
export declare const REFERENCE_IMPLEMENTATION_MANIFEST: ImplementationManifest;
|
|
142
144
|
export interface NumberFormatRules {
|
|
143
145
|
locale: SupportedLocale;
|
|
@@ -1005,4 +1007,117 @@ export interface LeaseUpCashFlowProjectionIssue extends ProtocolError {
|
|
|
1005
1007
|
verification?: import('./lease-up.js').LeaseUpVerification;
|
|
1006
1008
|
};
|
|
1007
1009
|
}
|
|
1010
|
+
export type PropertyCashFlowCategory = 'rent' | 'concessions' | 'ti_lc' | 'other_income' | 'operating_expenses' | 'other_capex' | 'reserve_net' | 'purchase_price' | 'transaction_costs' | 'gross_sale';
|
|
1011
|
+
export interface PropertyCashFlowCell {
|
|
1012
|
+
slot: string;
|
|
1013
|
+
category: PropertyCashFlowCategory;
|
|
1014
|
+
}
|
|
1015
|
+
export type PropertyCashFlowCoverage = PropertyCashFlowCell & ({
|
|
1016
|
+
rows: number[];
|
|
1017
|
+
zero?: never;
|
|
1018
|
+
} | {
|
|
1019
|
+
zero: string;
|
|
1020
|
+
rows?: never;
|
|
1021
|
+
});
|
|
1022
|
+
export interface PropertyCashFlowAssertions {
|
|
1023
|
+
cash_amounts_only: true;
|
|
1024
|
+
no_financing_or_investor_tax: true;
|
|
1025
|
+
no_overlapping_economic_amounts: true;
|
|
1026
|
+
reserve_spending_excluded: true;
|
|
1027
|
+
gross_sale_excludes_reserve_release: true;
|
|
1028
|
+
no_terminal_restricted_reserve: true;
|
|
1029
|
+
hold_only_and_exit_settled: true;
|
|
1030
|
+
}
|
|
1031
|
+
export declare const UNLEVERED_SALE_DEDUCTIONS: readonly ["broker_commission", "transfer_tax", "title_and_escrow", "legal_and_closing", "seller_credits", "survey_and_diligence", "other"];
|
|
1032
|
+
export declare const RESERVED_LEVERED_SALE_DEDUCTIONS: readonly ["prepayment_penalty", "defeasance", "loan_payoff"];
|
|
1033
|
+
export type SaleDeductionName = (typeof UNLEVERED_SALE_DEDUCTIONS)[number] | (typeof RESERVED_LEVERED_SALE_DEDUCTIONS)[number];
|
|
1034
|
+
export interface SaleDeduction {
|
|
1035
|
+
/** A supplemental row index covering the (disposition, transaction_costs) cell. */
|
|
1036
|
+
row: number;
|
|
1037
|
+
name: SaleDeductionName;
|
|
1038
|
+
/** Required when `name` is `other`; omitted otherwise. */
|
|
1039
|
+
label?: string;
|
|
1040
|
+
}
|
|
1041
|
+
export interface PropertyCashFlowPlan {
|
|
1042
|
+
basis: 'unlevered';
|
|
1043
|
+
tax_basis: 'pre_tax';
|
|
1044
|
+
currency_code: string;
|
|
1045
|
+
day_count: import('./calc/day-count.js').DayCountConvention;
|
|
1046
|
+
acquisition_date: string;
|
|
1047
|
+
disposition_date: string;
|
|
1048
|
+
lease_up: {
|
|
1049
|
+
source_variant: string;
|
|
1050
|
+
currency_code: string;
|
|
1051
|
+
cash_dates: Array<{
|
|
1052
|
+
period: string;
|
|
1053
|
+
date: string;
|
|
1054
|
+
}>;
|
|
1055
|
+
};
|
|
1056
|
+
supplemental: {
|
|
1057
|
+
source_variant: string;
|
|
1058
|
+
currency_code: string;
|
|
1059
|
+
};
|
|
1060
|
+
assertions: PropertyCashFlowAssertions;
|
|
1061
|
+
coverage: PropertyCashFlowCoverage[];
|
|
1062
|
+
/** RFC 0052. When present, names every (disposition, transaction_costs) row. */
|
|
1063
|
+
sale_deductions?: SaleDeduction[];
|
|
1064
|
+
/** RFC 0052. A stated net figure the assembler verifies, never derives. */
|
|
1065
|
+
net_sale_proceeds?: number;
|
|
1066
|
+
}
|
|
1067
|
+
export interface PropertyCashFlowBinding {
|
|
1068
|
+
output_row_index: number;
|
|
1069
|
+
source_section: 'lease_up_schedule' | 'cash_flow_series';
|
|
1070
|
+
source_variant: string;
|
|
1071
|
+
source_path: string;
|
|
1072
|
+
date: string;
|
|
1073
|
+
amount: number;
|
|
1074
|
+
cells: PropertyCashFlowCell[];
|
|
1075
|
+
}
|
|
1076
|
+
export type PropertyCashFlowCellEvidence = PropertyCashFlowCell & ({
|
|
1077
|
+
output_rows: number[];
|
|
1078
|
+
zero?: never;
|
|
1079
|
+
} | {
|
|
1080
|
+
zero: string;
|
|
1081
|
+
output_rows?: never;
|
|
1082
|
+
});
|
|
1083
|
+
export interface PropertyCashFlowAssembly {
|
|
1084
|
+
source_envelope_digest: string;
|
|
1085
|
+
plan: PropertyCashFlowPlan;
|
|
1086
|
+
coverage: 'declared_complete';
|
|
1087
|
+
series: import('./cash-flow-series.js').CashFlowSeries;
|
|
1088
|
+
bindings: PropertyCashFlowBinding[];
|
|
1089
|
+
cells: PropertyCashFlowCellEvidence[];
|
|
1090
|
+
source_verification: {
|
|
1091
|
+
lease_up: 'verified';
|
|
1092
|
+
supplemental_metrics: 'verified' | 'not_stated';
|
|
1093
|
+
};
|
|
1094
|
+
/** RFC 0052. Present only when the plan named its deductions. */
|
|
1095
|
+
sale_deductions?: Array<{
|
|
1096
|
+
output_row_index: number;
|
|
1097
|
+
name: SaleDeductionName;
|
|
1098
|
+
label?: string;
|
|
1099
|
+
amount: number;
|
|
1100
|
+
}>;
|
|
1101
|
+
/** RFC 0052. Evidence about a stated figure, not proof the exit is complete. */
|
|
1102
|
+
net_sale_proceeds: {
|
|
1103
|
+
status: 'verified';
|
|
1104
|
+
stated: number;
|
|
1105
|
+
computed: number;
|
|
1106
|
+
} | {
|
|
1107
|
+
status: 'not_stated';
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
export interface PropertyCashFlowAssemblyIssue {
|
|
1111
|
+
category: 'calc';
|
|
1112
|
+
code: 'CALC-CF-ASSEMBLY';
|
|
1113
|
+
reason: 'plan' | 'selection' | 'structure' | 'verification' | 'coverage' | 'basis_currency' | 'amount_sign' | 'date_horizon' | 'sale_deduction';
|
|
1114
|
+
message: string;
|
|
1115
|
+
pointer: string;
|
|
1116
|
+
evidence?: {
|
|
1117
|
+
selection?: ProtocolError;
|
|
1118
|
+
lease_up?: LeaseUpCashFlowProjectionIssue;
|
|
1119
|
+
structure?: ValidationMessage[];
|
|
1120
|
+
verification?: import('./cash-flow-series.js').CashFlowVerification;
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1008
1123
|
//# sourceMappingURL=protocol.d.ts.map
|