finance.depreciation-reducing-balance@1.0.0
impl/typescript.ts
1,870 bytes · the TypeScript implementation · view raw
Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import { type DepreciationPeriod } from "./finance_depreciation_straight_line_types.ts";
import { subtractMoney } from "./money_add.ts"; ← from money.add ^1.0.0 · built alongside by fune
import { type Money, money } from "./money_amount.ts"; ← from money.amount ^1.0.0 · built alongside by fune
import { applyRate } from "./money_apply_rate.ts"; ← from money.apply-rate ^1.0.0 · built alongside by fune
/**
* A reducing-balance depreciation schedule, year by year.
*
* Each charge is the rate applied to the opening value, rounded once. The last
* year writes off down to the residual value, and no year may go below it.
*/
export function reducingBalanceDepreciation(
cost: Money,
residualValue: Money,
rateBasisPoints: number,
years: number,
): readonly DepreciationPeriod[] {
if (!Number.isInteger(years) || years < 1) {
throw new RangeError(`years must be at least 1, received ${years}`);
}
if (!Number.isInteger(rateBasisPoints) || rateBasisPoints < 0 || rateBasisPoints > 10000) {
throw new RangeError(`rate must be 0 to 10000 basis points, received ${rateBasisPoints}`);
}
if (cost.minor < 0) {
throw new RangeError("cost must not be negative");
}
if (residualValue.minor < 0) {
throw new RangeError("residual value must not be negative");
}
// subtractMoney also refuses a cost and residual value in different currencies.
if (subtractMoney(cost, residualValue).minor < 0) {
throw new RangeError("residual value must not exceed cost");
}
const schedule: DepreciationPeriod[] = [];
let openingValue = cost;
for (let year = 1; year <= years; year += 1) {
const headroom = subtractMoney(openingValue, residualValue);
let charge = year === years ? headroom : applyRate(openingValue, rateBasisPoints, "half-up");
if (charge.minor > headroom.minor) charge = headroom;
const closingValue = subtractMoney(openingValue, charge);
schedule.push({ year, openingValue, charge, closingValue });
openingValue = closingValue;
}
return schedule;
}