Pub 946 Compliance
This commit is contained in:
@@ -1985,6 +1985,51 @@ async function main() {
|
||||
if (!Array.isArray(deprAgg.byBook) || !deprAgg.byBook.some((b) => b.book === 'GAAP')) throw new Error('Dashboard depreciation aggregator missing byBook/GAAP');
|
||||
if (!Array.isArray(deprAgg.byCategory)) throw new Error('Dashboard depreciation aggregator missing byCategory');
|
||||
|
||||
// ---- MACRS mid-quarter 40% auto-test (IRS Pub 946) --------------------------
|
||||
// Q4-heavy portfolio (80% of basis placed in service in Q4) → mid-quarter convention is mandatory and
|
||||
// must be applied automatically: the Q4 asset's first-year MACRS depreciation should be the mid-quarter
|
||||
// amount (8000 × 0.40 × 0.125 = 400), not the half-year amount (8000 × 0.40 × 0.5 = 1600).
|
||||
const macrsBook = (cost) => ({ book_type: 'FEDERAL', active: true, depreciation_method: 'macrs_gds_200db_5', convention: 'half_year', useful_life_months: 60, bonus_percent: 0, section_179_amount: 0, cost });
|
||||
await request('/api/assets', { method: 'POST', headers: aHeaders, body: JSON.stringify({ asset_id: `MQ1-${suffix}`, description: 'Mid-quarter Q1', category: 'Computer Equipment', acquisition_cost: 2000, acquired_date: '2029-02-15', in_service_date: '2029-02-15', useful_life_months: 60, books: [macrsBook(2000)] }) });
|
||||
await request('/api/assets', { method: 'POST', headers: aHeaders, body: JSON.stringify({ asset_id: `MQ4-${suffix}`, description: 'Mid-quarter Q4', category: 'Computer Equipment', acquisition_cost: 8000, acquired_date: '2029-11-15', in_service_date: '2029-11-15', useful_life_months: 60, books: [macrsBook(8000)] }) });
|
||||
const mqReport = (await request('/api/reports/run', { method: 'POST', headers: aHeaders, body: JSON.stringify({ type: 'depreciation_expense', options: { book: 'FEDERAL', year: 2029 } }) })).report;
|
||||
const mqRow = mqReport.rows.find((r) => r.asset_id === `MQ4-${suffix}`);
|
||||
if (!mqRow) throw new Error('Mid-quarter test asset missing from the depreciation report');
|
||||
if (Math.abs(mqRow.depreciation - 400) > 1) throw new Error(`Mid-quarter convention not auto-applied: expected ~400 (mid-quarter), got ${mqRow.depreciation}`);
|
||||
|
||||
// Verify the §179 limits were updated to the IRS Pub 946 (2026) figures.
|
||||
const s179 = (await request('/api/section-179-limits', { headers: auth })).limits;
|
||||
const y2026 = s179.find((l) => l.tax_year === 2026);
|
||||
if (!y2026 || Number(y2026.base_limit) !== 2560000 || Number(y2026.phaseout_threshold) !== 4090000) {
|
||||
throw new Error(`2026 §179 limit should be 2,560,000 / 4,090,000, got ${JSON.stringify(y2026)}`);
|
||||
}
|
||||
|
||||
// ---- §280F passenger-auto cap + listed-property >50% ADS test (IRS Pub 946) ---
|
||||
const macrsBook5 = (cost) => ({ book_type: 'FEDERAL', active: true, depreciation_method: 'macrs_gds_200db_5', convention: 'half_year', useful_life_months: 60, bonus_percent: 0, section_179_amount: 0, cost });
|
||||
// $90k luxury auto, 100% business, 2024 → year-1 MACRS would be 18,000 but §280F caps it to 12,400.
|
||||
await request('/api/assets', { method: 'POST', headers: aHeaders, body: JSON.stringify({ asset_id: `AUTO-${suffix}`, description: 'Luxury auto', category: 'Computer Equipment', acquisition_cost: 90000, acquired_date: '2024-06-01', in_service_date: '2024-06-01', useful_life_months: 60, business_use_percent: 100, passenger_auto: true, books: [macrsBook5(90000)] }) });
|
||||
// Listed property at 40% business use → forced ADS straight-line (basis 10k×40% / 5yr × half-year = 400).
|
||||
await request('/api/assets', { method: 'POST', headers: aHeaders, body: JSON.stringify({ asset_id: `LIST-${suffix}`, description: 'Listed low-use', category: 'Computer Equipment', acquisition_cost: 10000, acquired_date: '2024-06-01', in_service_date: '2024-06-01', useful_life_months: 60, business_use_percent: 40, listed_property: true, books: [macrsBook5(10000)] }) });
|
||||
const depr2024 = (await request('/api/reports/run', { method: 'POST', headers: aHeaders, body: JSON.stringify({ type: 'depreciation_expense', options: { book: 'FEDERAL', year: 2024 } }) })).report;
|
||||
const autoRow = depr2024.rows.find((r) => r.asset_id === `AUTO-${suffix}`);
|
||||
if (!autoRow || Math.abs(autoRow.depreciation - 12400) > 1) throw new Error(`§280F auto cap not applied: expected 12,400, got ${autoRow && autoRow.depreciation}`);
|
||||
const listRow = depr2024.rows.find((r) => r.asset_id === `LIST-${suffix}`);
|
||||
if (!listRow || Math.abs(listRow.depreciation - 400) > 1) throw new Error(`Listed ≤50% ADS not applied: expected 400, got ${listRow && listRow.depreciation}`);
|
||||
if (!(await request('/api/section-280f-limits', { headers: auth })).limits.some((l) => l.pis_year === 2024)) throw new Error('§280F limits not seeded');
|
||||
|
||||
// ---- §179 taxable-income limitation + carryover ----------------------------
|
||||
const s179Book = (amt) => ({ book_type: 'FEDERAL', active: true, depreciation_method: 'macrs_gds_200db_7', useful_life_months: 84, section_179_amount: amt, cost: amt });
|
||||
await request('/api/assets', { method: 'POST', headers: aHeaders, body: JSON.stringify({ asset_id: `S179A-${suffix}`, description: '179 A', category: 'Computer Equipment', acquisition_cost: 1500000, acquired_date: '2031-03-01', in_service_date: '2031-03-01', useful_life_months: 84, books: [s179Book(1500000)] }) });
|
||||
await request('/api/assets', { method: 'POST', headers: aHeaders, body: JSON.stringify({ asset_id: `S179B-${suffix}`, description: '179 B', category: 'Computer Equipment', acquisition_cost: 1500000, acquired_date: '2031-04-01', in_service_date: '2031-04-01', useful_life_months: 84, books: [s179Book(1500000)] }) });
|
||||
// Elected 3,000,000; 2031 dollar limit 2,560,000; taxable income 1,000,000 → allowed 1,000,000, carry 2,000,000.
|
||||
const limSaved = (await request('/api/section-179/limitation', { method: 'PUT', headers: aHeaders, body: JSON.stringify({ book: 'FEDERAL', year: 2031, taxable_income: 1000000 }) })).summary;
|
||||
if (limSaved.elected !== 3000000) throw new Error(`§179 elected wrong: ${limSaved.elected}`);
|
||||
if (limSaved.dollar_allowed !== 2560000) throw new Error(`§179 dollar limit wrong: ${limSaved.dollar_allowed}`);
|
||||
if (limSaved.allowed_deduction !== 1000000) throw new Error(`§179 income limitation wrong: ${limSaved.allowed_deduction}`);
|
||||
if (limSaved.carryover_to_next !== 2000000) throw new Error(`§179 carryover wrong: ${limSaved.carryover_to_next}`);
|
||||
const lim2032 = (await request('/api/section-179/limitation?book=FEDERAL&year=2032', { headers: aHeaders })).summary;
|
||||
if (lim2032.prior_carryover !== 2000000) throw new Error(`§179 carryover did not chain to next year: ${lim2032.prior_carryover}`);
|
||||
|
||||
console.log('Smoke test passed');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user