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