Add more computations for form 1040.
[ustaxlib.git] / src / fed2019 / Form1040.ts
1 import Form from '../Form';
2 import TaxReturn from '../TaxReturn';
3 import { Line, AccumulatorLine, ComputedLine, ReferenceLine } from '../Line';
4
5 export enum FilingStatus {
6 Single,
7 MarriedFilingSingle,
8 MarriedFilingJoint,
9 };
10
11 export interface Form1040Input {
12 filingStatus: FilingStatus;
13 };
14
15 const reduceBySum = (list: number[]) => list.reduce((acc, curr) => acc + curr, 0);
16
17 export default class Form1040 extends Form<Form1040Input> {
18 get name(): string { return '1040'; }
19
20 protected getLines(): Line<any>[] {
21 return [
22 new AccumulatorLine('1', 'W-2', '1', 'Wages, salaries, tips, etc.'),
23 new AccumulatorLine('2a', '1099-INT', '8', 'Tax-exempt interest'),
24 new AccumulatorLine('2b', '1009-INT', '1', 'Taxable interest'),
25 new AccumulatorLine('3a', '1099-DIV', '1b', 'Qualified dividends'),
26 new AccumulatorLine('3b', '1099-DIV', '1a', 'Ordinary dividends'),
27 // 4a and 4b are complex
28 // 4c and 4d are not supported
29 // 5a and 5b are not supported
30 // 6 - Sched D
31 new ReferenceLine<number>('7a', 'Schedule 1', '9', 'Other income from Schedule 1'),
32
33 new ComputedLine<number>('7b', (tr: TaxReturn): number => {
34 const lineIds = ['1', '2b', '3b', '4b', '4d', '5b', '6', '7a'];
35 const lines = lineIds.map(l => this.getValue<number>(tr, l));
36 return reduceBySum(lines);
37 }, 'Total income'),
38
39 new ReferenceLine<number>('8a', 'Schedule 1', '22', 'Adjustments to income'),
40
41 new ComputedLine<number>('8b', (tr: TaxReturn): number => {
42 return this.getValue<number>(tr, '7b') - this.getValue<number>(tr, '8a');
43 }, 'Adjusted gross income'),
44
45 // 9 - Deduction
46
47 new ComputedLine<number>('10', (tr: TaxReturn): number => {
48 const taxableIncome = this.getValue<number>(tr, '8b');
49 let use8995a = false;
50 switch (this.getInput('filingStatus')) {
51 case FilingStatus.Single: use8995a = taxableIncome <= 160700; break;
52 case FilingStatus.MarriedFilingSingle: use8995a = taxableIncome <= 160725; break;
53 case FilingStatus.MarriedFilingJoint: use8995a = taxableIncome <= 321400; break;
54 };
55 return 0;
56 }, 'Qualified business income deduction'),
57
58 new ComputedLine<number>('11a', (tr: TaxReturn) => {
59 return this.getValue<number>(tr, '9') + this.getValue<number>(tr, '10');
60 }),
61 new ComputedLine<number>('11b', (tr: TaxReturn) => {
62 const value = this.getValue<number>(tr, '8b') - this.getValue<number>(tr, '11a');
63 return value < 0 ? 0 : value;
64 }, 'Taxable income'),
65
66 new ComputedLine<number>('16', (tr: TaxReturn) => {
67 return 0;
68 }, 'Total tax'),
69
70 new ComputedLine<number>('17', (tr: TaxReturn) => {
71 const fedTaxWithheldBoxes = [
72 ['W-2', '2'], ['1099-R', '4'], ['1099-DIV', '4'], ['1099-INT', '4']
73 ];
74 const withholding = fedTaxWithheldBoxes.map(b => (new AccumulatorLine('F1040.L17+', b[0], b[1])).value(tr));
75
76 let additionalMedicare = 0;
77 const f8959 = tr.maybeGetForm('8595')
78 if (f8959) {
79 additionalMedicare = f8959.getValue<number>(tr, '24');
80 }
81
82 return reduceBySum(withholding) + additionalMedicare;
83 }, 'Federal income tax withheld'),
84
85 // 18 not supported
86
87 new ReferenceLine<number>('19', '1040', '17', 'Total payments'),
88
89 new ComputedLine<number>('20', (tr: TaxReturn) => {
90 const l16 = this.getValue<number>(tr, '16');
91 const l19 = this.getValue<number>(tr, '19');
92 if (l19 > l16)
93 return l19 - l16;
94 return 0;
95 }, 'Amount overpaid'),
96
97 new ComputedLine<number>('23', (tr: TaxReturn) => {
98 const l16 = this.getValue<number>(tr, '16');
99 const l19 = this.getValue<number>(tr, '19');
100 if (l19 < l16)
101 return l16 - l19;
102 return 0;
103 }, 'Amount you owe'),
104 ];
105 }
106 };