Files
MixedAssets/server/rule-catalog.js
2026-06-05 04:15:24 -05:00

170 lines
6.9 KiB
JavaScript

function months(years) {
return Math.round(Number(years) * 12);
}
function method(code, family, label, formula, options = {}) {
return {
code,
family,
label,
formula,
...options
};
}
function macrsDeclining(prefix, labelPrefix, system, multiplier, lives, options = {}) {
return lives.map((life) => method(
`${prefix}_${String(life).replace('.', '_')}`,
'MACRS',
`${labelPrefix} ${life}-year`,
'macrs_declining_balance',
{
system,
lifeMonths: months(life),
rateMultiplier: multiplier,
switchToStraightLine: true,
defaultConvention: life >= 27.5 ? 'mid_month' : 'half_year',
...options
}
));
}
function straightLineMethods(prefix, family, labelPrefix, system, lives, options = {}) {
return lives.map((life) => method(
`${prefix}_${String(life).replace('.', '_')}`,
family,
`${labelPrefix} ${life}-year`,
'straight_line',
{
system,
lifeMonths: months(life),
defaultConvention: life >= 27.5 ? 'mid_month' : 'half_year',
...options
}
));
}
function acrsRateMethod(code, label, life, rates, options = {}) {
return method(code, 'ACRS', label, 'rate_table', {
system: 'ACRS',
lifeMonths: months(life),
defaultConvention: 'none',
rates,
...options
});
}
function buildMacrsMethods() {
return [
...macrsDeclining('macrs_gds_200db', 'MACRS GDS 200% DB', 'GDS', 2, [3, 5, 7, 10]),
...macrsDeclining('macrs_gds_150db', 'MACRS GDS 150% DB', 'GDS', 1.5, [3, 5, 7, 10, 15, 20]),
...straightLineMethods('macrs_gds_sl', 'MACRS', 'MACRS GDS straight-line', 'GDS', [3, 5, 7, 10, 15, 20, 27.5, 39]),
...straightLineMethods('macrs_ads_sl', 'MACRS', 'MACRS ADS straight-line', 'ADS', [3, 5, 7, 10, 12, 15, 20, 30, 40]),
...macrsDeclining('macrs_ads_150db_legacy', 'Legacy MACRS ADS 150% DB', 'ADS', 1.5, [3, 5, 7, 10, 12, 15, 20, 30, 40], {
legacy: true,
sourceNote: 'For property where an older ADS 150% DB election must continue.'
})
];
}
function buildAcrsMethods() {
const regular = [
acrsRateMethod('acrs_regular_3', 'ACRS regular 3-year', 3, [0.25, 0.38, 0.37]),
acrsRateMethod('acrs_regular_5', 'ACRS regular 5-year', 5, [0.15, 0.22, 0.21, 0.21, 0.21]),
acrsRateMethod('acrs_regular_10', 'ACRS regular 10-year', 10, [0.08, 0.14, 0.12, 0.10, 0.10, 0.10, 0.09, 0.09, 0.09, 0.09]),
acrsRateMethod('acrs_regular_15_real', 'ACRS regular 15-year real property', 15, [], { requiresMonthTable: true, fallbackFormula: 'straight_line' }),
acrsRateMethod('acrs_regular_15_low_income', 'ACRS regular 15-year low-income housing', 15, [], { requiresMonthTable: true, fallbackFormula: 'straight_line' }),
acrsRateMethod('acrs_regular_18_real', 'ACRS regular 18-year real property', 18, [], { requiresMonthTable: true, fallbackFormula: 'straight_line' }),
acrsRateMethod('acrs_regular_19_real', 'ACRS regular 19-year real property', 19, [], { requiresMonthTable: true, fallbackFormula: 'straight_line' }),
acrsRateMethod('acrs_regular_listed_property', 'ACRS listed property predominant-use table', 5, [], { requiresListedPropertyTable: true, fallbackFormula: 'straight_line' })
];
const alternate = straightLineMethods('acrs_alternate_sl', 'ACRS', 'ACRS alternate modified straight-line', 'ACRS', [3, 5, 10, 12, 15, 18, 19, 25], {
formula: 'acrs_alternate_straight_line',
defaultConvention: 'half_year'
});
const straightLine = straightLineMethods('acrs_required_sl', 'ACRS', 'ACRS required straight-line', 'ACRS', [3, 5, 10, 15, 18, 19, 35, 45], {
formula: 'straight_line',
defaultConvention: 'half_year',
legacy: true
});
return [...regular, ...alternate, ...straightLine];
}
function buildGaapMethods() {
return [
method('straight_line', 'GAAP', 'Straight-line', 'straight_line'),
method('sum_of_years_digits', 'GAAP', 'Sum-of-years-digits', 'sum_of_years_digits'),
method('declining_balance_200', 'GAAP', '200% declining balance', 'declining_balance', { rateMultiplier: 2 }),
method('declining_balance_175', 'GAAP', '175% declining balance', 'declining_balance', { rateMultiplier: 1.75 }),
method('declining_balance_150', 'GAAP', '150% declining balance', 'declining_balance', { rateMultiplier: 1.5 }),
method('declining_balance_125', 'GAAP', '125% declining balance', 'declining_balance', { rateMultiplier: 1.25 })
];
}
function buildSpecialMethods() {
return [
method('manual', 'Manual', 'Manual depreciation entry', 'manual'),
method('amortization', 'Lease', 'Straight-line amortization', 'straight_line')
];
}
// Sage-style 200% declining-balance method codes. The MACRS family (MF/MT/MI) ignores
// salvage value and recovers the full basis; the standard family (DB/DH/DD) honors salvage
// (depreciates only down to it). All use a 200% rate and switch to straight-line.
function build200Methods() {
return [
method('MF200', 'MACRS', 'MF200 — MACRS Formula, 200% DB (GDS)', 'macrs_declining_balance', {
system: 'GDS', rateMultiplier: 2, switchToStraightLine: true, defaultConvention: 'half_year', ignoreSalvage: true
}),
method('MT200', 'MACRS', 'MT200 — MACRS Tables, 200% DB (GDS)', 'macrs_declining_balance', {
system: 'GDS', rateMultiplier: 2, switchToStraightLine: true, defaultConvention: 'half_year', ignoreSalvage: true, usesTables: true
}),
method('MI200', 'MACRS', 'MI200 — MACRS 200% DB, Indian Reservation', 'macrs_declining_balance', {
system: 'GDS', rateMultiplier: 2, switchToStraightLine: true, defaultConvention: 'half_year', ignoreSalvage: true, indianReservation: true
}),
method('DB200', 'Declining Balance', 'DB200 — 200% Declining Balance to SL (uses book convention)', 'declining_balance', {
rateMultiplier: 2, switchToStraightLine: true
}),
method('DH200', 'Declining Balance', 'DH200 — 200% Declining Balance to SL, Half-Year', 'declining_balance', {
rateMultiplier: 2, switchToStraightLine: true, defaultConvention: 'half_year'
}),
method('DD200', 'Declining Balance', 'DD200 — 200% Declining Balance to SL, Full-Year', 'declining_balance', {
rateMultiplier: 2, switchToStraightLine: true, defaultConvention: 'none'
})
];
}
function buildDepreciationMethods() {
return [
...build200Methods(),
...buildMacrsMethods(),
...buildAcrsMethods(),
...buildGaapMethods(),
...buildSpecialMethods()
];
}
function expandRuleSet(ruleSet) {
const methods = buildDepreciationMethods();
return {
...ruleSet,
methodCatalog: ruleSet.methodCatalog || 'mixedassets-68-us-tax-and-accounting-v1',
methodCounts: {
macrs: methods.filter((item) => item.family === 'MACRS').length,
acrs: methods.filter((item) => item.family === 'ACRS').length,
gaap: methods.filter((item) => item.family === 'GAAP').length,
supplemental: methods.filter((item) => !['MACRS', 'ACRS', 'GAAP'].includes(item.family)).length,
total: methods.length
},
methods
};
}
module.exports = {
buildDepreciationMethods,
expandRuleSet
};