Form 4562 Report

This commit is contained in:
2026-06-11 01:41:46 -05:00
parent 5074a3ad63
commit ab6e4c2a56
4 changed files with 153 additions and 23 deletions

View File

@@ -1,5 +1,5 @@
const { all, now, one, parseJson } = require('../db');
const { annualSchedule, money } = require('../depreciation');
const { annualSchedule, bonusAmount, depreciableBasis, getMethodRule, money, section179Amount } = require('../depreciation');
const { ruleSetForBook } = require('./ruleSets');
const { assetFromRow } = require('./assets');
@@ -453,32 +453,137 @@ function journalDisposals(options) {
};
}
// MACRS property class for Form 4562, Part III line 19 (and ADS line 20), by recovery period.
function form4562Class(months) {
const y = Number(months) / 12;
if (months >= 468) return { label: '(i) Nonresidential real property', sort: 9, recovery: '39 yrs' };
if (months >= 330) return { label: '(h) Residential rental property', sort: 8, recovery: '27.5 yrs' };
if (y >= 24) return { label: '(g) 25-year property', sort: 7, recovery: '25 yrs' };
if (y >= 18) return { label: '(f) 20-year property', sort: 6, recovery: '20 yrs' };
if (y >= 13) return { label: '(e) 15-year property', sort: 5, recovery: '15 yrs' };
if (y >= 9) return { label: '(d) 10-year property', sort: 4, recovery: '10 yrs' };
if (y >= 6.5) return { label: '(c) 7-year property', sort: 3, recovery: '7 yrs' };
if (y >= 4.5) return { label: '(b) 5-year property', sort: 2, recovery: '5 yrs' };
if (y >= 2.5) return { label: '(a) 3-year property', sort: 1, recovery: '3 yrs' };
return { label: 'Other', sort: 10, recovery: `${Math.round(y * 10) / 10} yrs` };
}
function form4562Method(methodRule) {
if (!methodRule) return 'S/L';
const f = methodRule.formula;
if (f === 'macrs_declining_balance' || f === 'macrs_table' || f === 'declining_balance') {
return Number(methodRule.rateMultiplier) === 1.5 ? '150 DB' : '200 DB';
}
if (f === 'sum_of_years_digits') return 'SYD';
return 'S/L';
}
function form4562Convention(bk, methodRule, year, companyId) {
if (!methodRule || methodRule.family !== 'MACRS') return '—';
const conv = methodRule.defaultConvention || bk.convention || 'half_year';
if (conv === 'mid_month' || Number(bk.useful_life_months) >= 330) return 'MM';
if (conv === 'half_year' && require('./midQuarter').applies(companyId, 'FEDERAL', year)) return 'MQ';
return conv === 'half_year' ? 'HY' : conv;
}
// IRS Form 4562 (Depreciation and Amortization) filing worksheet for the Federal book and tax year:
// Part I (§179 with the dollar limit, phase-out, income limitation and carryover), Part II (special/bonus
// allowance), Part III (MACRS — prior-year line 17 and current-year line 19 by property class), Part IV
// (summary total), and Part V (listed property). Computed from the asset register; assist only.
function form4562(options) {
const year = Number(options.year) || currentYear();
const companyId = options.entity_id;
const rules = ruleSetForBook('FEDERAL');
const items = assetBookRows('FEDERAL', options).map(toAssetBook)
.filter(({ asset }) => yearOf(asset.in_service_date || asset.acquired_date) === year);
let section179 = 0;
let bonus = 0;
let macrs = 0;
const rows = items.map(({ asset, book: bk }) => {
const limitation = require('./section179Limitation').summary(companyId, 'FEDERAL', year, options.taxable_income);
let line14Bonus = 0; // special (bonus) allowance, non-listed
let line16Other = 0; // other depreciation incl. ACRS / non-MACRS
let line17Prior = 0; // MACRS placed in service before this year
let line21Listed = 0; // listed property depreciation deduction
const classMap = new Map();
const listedRows = [];
for (const { asset, book: bk } of assetBookRows('FEDERAL', { entity_id: companyId }).map(toAssetBook)) {
const methodRule = getMethodRule(rules, bk.depreciation_method || 'straight_line');
const c = computeYear(asset, bk, rules, year);
const s179 = Math.min(Number(bk.cost ?? asset.acquisition_cost ?? 0), Number(bk.section_179_amount || 0));
section179 += s179;
macrs += c.depreciation;
return {
asset_id: asset.asset_id, description: asset.description, method: c.methodLabel,
cost: c.cost, section_179: money(s179), depreciation: c.depreciation
};
});
if (!c.depreciation) continue;
const placedThisYear = yearOf(asset.in_service_date || asset.acquired_date) === year;
const s179a = placedThisYear ? section179Amount(asset, bk) : 0;
const bonusa = placedThisYear ? bonusAmount(asset, bk) : 0;
const regular = money(c.depreciation - s179a - bonusa); // MACRS/other portion (excludes §179 & bonus)
if (asset.listed_property || asset.passenger_auto) {
line21Listed += money(regular + bonusa);
listedRows.push({
type: asset.description, in_service: asset.in_service_date || asset.acquired_date,
business_use: `${Number(asset.business_use_percent || 100)}%`,
cost: money(c.cost), basis: money(depreciableBasis(asset, bk, methodRule)),
recovery: form4562Class(bk.useful_life_months || asset.useful_life_months).recovery,
method: `${form4562Method(methodRule)} / ${form4562Convention(bk, methodRule, year, companyId)}`,
deduction: money(regular + bonusa), section_179: money(s179a)
});
continue;
}
line14Bonus += bonusa;
if (methodRule.family === 'MACRS') {
if (placedThisYear) {
const cls = form4562Class(bk.useful_life_months || asset.useful_life_months);
const e = classMap.get(cls.label) || { class: cls.label, sort: cls.sort, basis: 0, recovery: cls.recovery, convention: form4562Convention(bk, methodRule, year, companyId), method: form4562Method(methodRule), deduction: 0 };
e.basis = money(e.basis + depreciableBasis(asset, bk, methodRule));
e.deduction = money(e.deduction + regular);
classMap.set(cls.label, e);
} else {
line17Prior += money(c.depreciation);
}
} else {
line16Other += money(c.depreciation);
}
}
const line19Rows = [...classMap.values()].sort((a, b) => a.sort - b.sort);
const line19Total = money(line19Rows.reduce((s, r) => s + r.deduction, 0));
const line12 = limitation.allowed_deduction;
const total = money(line12 + line14Bonus + line16Other + line17Prior + line19Total + line21Listed);
const L = (part, line, description, amount) => ({ part, line, description, amount: money(amount) });
return {
columns: [
col('asset_id', 'Asset ID'), col('description', 'Description'), col('method', 'Method'),
col('cost', 'Cost', 'currency'), col('section_179', '§179', 'currency'), col('depreciation', 'Depreciation', 'currency')
title: `IRS Form 4562 worksheet — Federal, ${year}`,
columns: [col('part', 'Part'), col('line', 'Line'), col('description', 'Description'), col('amount', 'Amount', 'currency')],
rows: [
L('I', '1', 'Maximum §179 deduction', limitation.base_limit || 0),
L('I', '2', 'Total cost of §179 property placed in service', limitation.property_cost),
L('I', '3', 'Threshold cost of §179 property before reduction', limitation.phaseout_threshold || 0),
L('I', '4', 'Reduction in limitation (line 2 line 3)', limitation.phaseout_reduction),
L('I', '5', 'Dollar limitation for the year (line 1 line 4)', limitation.dollar_limit || 0),
L('I', '8', 'Total elected cost of §179 property', limitation.elected),
L('I', '9', 'Tentative deduction (smaller of line 5 or 8)', Math.min(limitation.dollar_limit || Infinity, limitation.elected)),
L('I', '10', 'Carryover of disallowed deduction from last year', limitation.prior_carryover),
L('I', '11', 'Business income limitation', limitation.taxable_income || 0),
L('I', '12', '§179 deduction (smaller of line 9+10 or 11)', limitation.allowed_deduction),
L('I', '13', 'Carryover of disallowed deduction to next year', limitation.carryover_to_next),
L('II', '14', 'Special depreciation allowance (bonus) — non-listed', line14Bonus),
L('II', '16', 'Other depreciation (including ACRS)', line16Other),
L('III', '17', 'MACRS for assets placed in service before this year', line17Prior),
L('III', '19', 'MACRS for assets placed in service this year (detail below)', line19Total),
L('IV', '21', 'Listed property (from Part V, detail below)', line21Listed),
L('IV', '22', 'TOTAL — add lines 12, 14, 16, 17, 19 and 21', total)
],
rows,
totals: { section_179: money(section179), bonus: money(bonus), depreciation: money(macrs), cost: money(rows.reduce((s, r) => s + r.cost, 0)) },
meta: { note: 'Summary for IRS Form 4562 (Federal book, current-year placements). Validate against current tax law before filing.' }
meta: {
note: `IRS Form 4562 filing worksheet — Federal book, ${year}. The §179 income limitation uses the figure saved on Financial → Section 179 (override with the report parameter). Assist only; validate against current tax law before filing.`,
sections: [
{
title: 'Part III, line 19 — MACRS property placed in service this tax year',
columns: [col('class', 'Classification'), col('basis', 'Basis for depreciation', 'currency'), col('recovery', 'Recovery'), col('convention', 'Conv.'), col('method', 'Method'), col('deduction', 'Deduction', 'currency')],
rows: line19Rows
},
{
title: 'Part V — Listed property (autos & other listed assets)',
columns: [col('type', 'Property'), col('in_service', 'In service', 'date'), col('business_use', 'Business use'), col('cost', 'Cost', 'currency'), col('basis', 'Basis', 'currency'), col('recovery', 'Recovery'), col('method', 'Method/Conv.'), col('deduction', 'Deduction', 'currency'), col('section_179', '§179', 'currency')],
rows: listedRows
}
]
}
};
}
@@ -1104,7 +1209,7 @@ const REPORTS = {
cip: { title: 'Construction-in-progress', group: 'Activity', params: ['entity_id'], build: (o) => constructionInProgress(o) },
journal_depreciation: { title: 'Journal entry: depreciation', group: 'Journal entries', params: ['book', 'year', 'entity_id'], build: (o) => journalDepreciation(o) },
journal_disposals: { title: 'Journal entry: disposals', group: 'Journal entries', params: ['year', 'entity_id'], build: (o) => journalDisposals(o) },
form_4562: { title: 'Federal Form 4562 (depreciation)', group: 'Tax', params: ['year', 'entity_id'], build: (o) => form4562(o) },
form_4562: { title: 'Federal Form 4562 (depreciation)', group: 'Tax', params: ['year', 'taxable_income', 'entity_id'], build: (o) => form4562(o) },
form_4797: { title: 'Federal Form 4797 (sales)', group: 'Tax', params: ['year', 'entity_id'], build: (o) => form4797(o) },
amt: { title: 'AMT depreciation', group: 'Tax', params: ['year', 'entity_id'], build: (o) => depreciationExpense(o, 'AMT') },
ace: { title: 'ACE depreciation', group: 'Tax', params: ['year', 'entity_id'], build: (o) => depreciationExpense(o, 'ACE') },
@@ -1167,6 +1272,7 @@ function paramSpecs() {
return {
book: { label: 'Book', type: 'select', options: bookCodes, default: bookCodes[0] || 'GAAP' },
year: { label: 'Year', type: 'number', default: year },
taxable_income: { label: 'Business taxable income (§179)', type: 'number', clearable: true, default: null },
month: { label: 'Through month', type: 'select', options: Array.from({ length: 12 }, (_, i) => i + 1), default: 12 },
txn_month: { label: 'Month (optional)', type: 'select', options: Array.from({ length: 12 }, (_, i) => i + 1), clearable: true, default: null },
startYear: { label: 'Start year', type: 'number', default: year },