1 import Form from '../Form';
2 import Person from '../Person';
3 import TaxReturn from '../TaxReturn';
4 import { Line, InputLine, ComputedLine, sumLineOfForms } from '../Line';
6 import Form1099B, { GainType } from './Form1099B';
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
17 export interface Adjustment {
23 export interface Form8949Input {
25 adjustments?: Adjustment[];
28 function matching1099Bs(tr: TaxReturn, box: Form8949Box): Form1099B[] {
29 return tr.findForms(Form1099B).filter(f => {
30 const gainType: GainType = f.getValue(tr, '2');
31 const basisReported: boolean = f.getValue(tr, '12');
35 return gainType == GainType.ShortTerm && basisReported;
37 return gainType == GainType.ShortTerm && !basisReported;
39 return gainType == GainType.LongTerm && basisReported;
41 return gainType == GainType.LongTerm && !basisReported;
48 class Form8949Line extends Line<number> {
49 private _box: Form8949Box;
50 private _line: keyof Form1099B['lines'];
52 constructor(f8949Functor: () => Form8949, line: keyof Form1099B['lines'], description: string) {
53 const box = f8949Functor().getInput('box');
54 super(`Form 8949 Box ${box} total of 1099-B ${line} (${description})`);
59 value(tr: TaxReturn): number {
60 const f1099bs = matching1099Bs(tr, this._box);
61 return sumLineOfForms(tr, f1099bs, this._line);
65 export default class Form8949 extends Form<Form8949['_lines'], Form8949Input> {
66 readonly name = '8949';
68 readonly supportsMultipleCopies = true;
70 protected readonly _lines = {
71 'Box': new InputLine<Form8949Input>('box'),
72 '2(d)': new Form8949Line(() => this, '1d', 'proceeds'),
73 '2(e)': new Form8949Line(() => this, '1e', 'cost'),
74 '2(g)': new ComputedLine((tr: TaxReturn): number => {
75 const f1099bs = matching1099Bs(tr, this.getInput('box'));
76 const adjustments = this.getInput('adjustments').filter((a: Adjustment): boolean => {
77 return f1099bs.includes(a.entry);
79 return adjustments.reduce((acc, curr) => acc + curr.amount, 0);
83 static addForms(tr: TaxReturn, adjustments: Adjustment[]) {
84 tr.addForm(new Form8949({ box: Form8949Box.A, adjustments }));
85 tr.addForm(new Form8949({ box: Form8949Box.B, adjustments }));
86 tr.addForm(new Form8949({ box: Form8949Box.C, adjustments }));
87 tr.addForm(new Form8949({ box: Form8949Box.D, adjustments }));
88 tr.addForm(new Form8949({ box: Form8949Box.E, adjustments }));
89 tr.addForm(new Form8949({ box: Form8949Box.F, adjustments }));
94 export interface Adjustment {
100 export interface Form8949Input {
101 adjustments?: []Adjustment;
104 export interface Form8949Total {
107 adjustmentAmount: number;
111 class Form8949Line extends Line<Form8949Total> {
112 private _box: Form8949Box;
114 constructor(description: string, box: Form8949Input) {
119 value(tr: TaxReturn): Form8949Total {
120 const lineShortTerm = this._box == Form8949Box.A || this._box == Form8949Box.B || this._box == Form8949Box.C;
121 const lineBasisReported = this._box == Form8949Box.A || this._box == Form8949Box.D;
123 const f1099bs = tr.findForms(Form1099B);
124 const relevant1099bs: Form1099B[] = [];
125 for (const form of f1099bs) {
126 const gainType = form.getValue(tr, '2');
127 const basisReported = form.getValue(tr, '12');
129 if (lineBasisReported != basisReported)
132 if (gainType == GainType.ShortTerm && lineShortTerm) {
133 relevant1099bs.push(form);
134 } else if (gainType == GainType.LongTerm && !lineShortTerm) {
135 relevant1099bs.push(form);
139 const sumValues = (line: keyof Form1099B['lines']) =>
140 relevant1099bs.map((f: Form1099B): number => f.getValue(tr, line))
141 .reduce((acc, curr) => acc + curr, 0);
143 const proceeds = sumValues('1d');
144 const costBasis = sumValues('1e');
150 gainOrLoss: costBasis - proceeds,
155 export default class Form8949 extends Form<Form8949['_lines'], Form8949Input> {
156 readonly name = '8949';
158 protected readonly _lines = {
159 boxATotals: new Form8949Line('Short-term basis reported', Form8949Box.A),
160 boxBTotals: new Form8949Line('Short-term basis NOT reported', Form8949Box.B),
161 boxCTotals: new Form8949Line('Short-term unreported', Form8949Box.C),
162 boxDTotals: new Form8949Line('Long-term basis reported', Form8949Box.D),
163 boxETotals: new Form8949Line('Long-term basis NOT reported', Form8949Box.E),
164 boxFTotals: new Form8949Line('Long-term unreported', Form8949Box.F)