Remove the need to self-reference Form['lines'] in Form subclasses.
[ustaxlib.git] / src / fed2019 / Form8949.ts
1 // Copyright 2020 Blue Static <https://www.bluestatic.org>
2 // This program is free software licensed under the GNU General Public License,
3 // version 3.0. The full text of the license can be found in LICENSE.txt.
4 // SPDX-License-Identifier: GPL-3.0-only
5
6 import * as Trace from '../core/Trace';
7 import { Form, Person, TaxReturn } from '../core';
8 import { Line, InputLine, ComputedLine, sumLineOfForms } from '../core/Line';
9 import { undefinedToZero } from '../core/Math';
10
11 import Form1099B, { Form1099BRow, Form1099BInput } from './Form1099B';
12
13 export enum Form8949Box {
14 A = 'A', // Short-term transactions reported on Form(s) 1099-B showing basis was reported to the IRS
15 B = 'B', // Short-term transactions reported on Form(s) 1099-B showing basis wasn’t reported to the IRS
16 C = 'C', // Short-term transactions not reported to you on Form 1099-B
17 D = 'D', // Long-term transactions reported on Form(s) 1099-B showing basis was reported to the IRS
18 E = 'E', // Long-term transactions reported on Form(s) 1099-B showing basis wasn’t reported to the IRS
19 F = 'F', // Long-term transactions not reported to you on Form 1099-B
20 };
21
22 export interface Form8949Total {
23 proceeds: number;
24 costBasis: number;
25 adjustments: number;
26 gainOrLoss: number;
27 };
28
29 class Form8949Line extends Line<Form8949Total> {
30 private _box: Form8949Box;
31 private _line: keyof Form1099B['lines'];
32
33 constructor(box: Form8949Box) {
34 super(`Form 8949 Box ${box} Total`);
35 this._box = box;
36 }
37
38 value(tr: TaxReturn): Form8949Total {
39 Trace.begin(this);
40
41 const f1099bs = tr.findForms(Form1099B);
42 const fieldMap: { [key: string]: keyof Form1099BInput } = {
43 [Form8949Box.A]: 'shortTermBasisReported',
44 [Form8949Box.B]: 'shortTermBasisUnreported',
45 [Form8949Box.C]: 'shortTermUnreported',
46 [Form8949Box.D]: 'longTermBasisReported',
47 [Form8949Box.E]: 'longTermBasisUnreported',
48 [Form8949Box.F]: 'longTermUnreported',
49 };
50 const field: keyof Form1099BInput = fieldMap[this._box];
51
52 const value = {
53 proceeds: 0,
54 costBasis: 0,
55 adjustments: 0,
56 gainOrLoss: 0
57 };
58
59 for (const f1099b of f1099bs) {
60 if (!f1099b.hasInput(field))
61 continue;
62
63 const rows = f1099b.getInput(field) as Form1099BRow[];
64 for (const row of rows) {
65 let { proceeds, costBasis, adjustments } = row;
66 adjustments = undefinedToZero(adjustments);
67 value.proceeds += proceeds;
68 value.costBasis += costBasis;
69 value.adjustments += adjustments;
70 value.gainOrLoss += proceeds - costBasis + adjustments;
71 }
72 }
73
74 Trace.end();
75 return value;
76 }
77 };
78
79 export default class Form8949 extends Form {
80 readonly name = '8949';
81
82 readonly supportsMultipleCopies = true;
83
84 readonly lines = {
85 'boxA': new Form8949Line(Form8949Box.A),
86 'boxB': new Form8949Line(Form8949Box.B),
87 'boxC': new Form8949Line(Form8949Box.C),
88 'boxD': new Form8949Line(Form8949Box.D),
89 'boxE': new Form8949Line(Form8949Box.E),
90 'boxF': new Form8949Line(Form8949Box.F),
91 };
92 };