Use the original idea for Form8949, which is simpler.
[ustaxlib.git] / src / fed2019 / Form8949.ts
1 import Form from '../Form';
2 import Person from '../Person';
3 import TaxReturn from '../TaxReturn';
4 import { Line, InputLine, ComputedLine, sumLineOfForms } from '../Line';
5
6 import Form1099B, { GainType } from './Form1099B';
7
8 export enum Form8949Box {
9 A = 'A', // Short-term transactions reported on Form(s) 1099-B showing basis was reported to the IRS
10 B = 'B', // Short-term transactions reported on Form(s) 1099-B showing basis wasn’t reported to the IRS
11 C = 'C', // Short-term transactions not reported to you on Form 1099-B
12 D = 'D', // Long-term transactions reported on Form(s) 1099-B showing basis was reported to the IRS
13 E = 'E', // Long-term transactions reported on Form(s) 1099-B showing basis wasn’t reported to the IRS
14 F = 'F', // Long-term transactions not reported to you on Form 1099-B
15 };
16
17 export interface Adjustment {
18 entry: Form1099B;
19 code: string;
20 amount: number;
21 };
22
23 export interface Form8949Input {
24 adjustments?: Adjustment[];
25 };
26
27 export interface Form8949Total {
28 proceeds: number;
29 costBasis: number;
30 adjustments: number;
31 gainOrLoss: number;
32 };
33
34 function matching1099Bs(tr: TaxReturn, box: Form8949Box): Form1099B[] {
35 return tr.findForms(Form1099B).filter(f => {
36 const gainType: GainType = f.getValue(tr, '2');
37 const basisReported: boolean = f.getValue(tr, '12');
38
39 switch (box) {
40 case Form8949Box.A:
41 return gainType == GainType.ShortTerm && basisReported;
42 case Form8949Box.B:
43 return gainType == GainType.ShortTerm && !basisReported;
44 case Form8949Box.D:
45 return gainType == GainType.LongTerm && basisReported;
46 case Form8949Box.E:
47 return gainType == GainType.LongTerm && !basisReported;
48 };
49
50 return false;
51 });
52 }
53
54 class Form8949Line extends Line<Form8949Total> {
55 private _box: Form8949Box;
56 private _line: keyof Form1099B['lines'];
57
58 constructor(box: Form8949Box) {
59 super(`Form 8949 Box ${box} Total`);
60 this._box = box;
61 }
62
63 value(tr: TaxReturn): Form8949Total {
64 const f1099bs = matching1099Bs(tr, this._box);
65 const proceeds = sumLineOfForms(tr, f1099bs, '1d');
66 const costBasis = sumLineOfForms(tr, f1099bs, '1e');
67 const f8949 = tr.getForm(Form8949);
68 const adjustments = !f8949.hasInput('adjustments') ? 0 :
69 f8949.getInput('adjustments')
70 .filter(a => f1099bs.includes(a.entry))
71 .reduce((acc, curr) => acc + curr.amount, 0);
72 return {
73 proceeds,
74 costBasis,
75 adjustments,
76 gainOrLoss: proceeds - costBasis + adjustments,
77 };
78 }
79 };
80
81 export default class Form8949 extends Form<Form8949['_lines'], Form8949Input> {
82 readonly name = '8949';
83
84 readonly supportsMultipleCopies = true;
85
86 protected readonly _lines = {
87 'boxA': new Form8949Line(Form8949Box.A),
88 'boxB': new Form8949Line(Form8949Box.B),
89 'boxC': new Form8949Line(Form8949Box.C),
90 'boxD': new Form8949Line(Form8949Box.D),
91 'boxE': new Form8949Line(Form8949Box.E),
92 'boxF': new Form8949Line(Form8949Box.F),
93 };
94 };