Form 4562 Report
This commit is contained in:
@@ -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 },
|
||||
|
||||
Reference in New Issue
Block a user