Add Form 8959.
authorRobert Sesek <rsesek@bluestatic.org>
Sat, 22 Feb 2020 06:11:28 +0000 (01:11 -0500)
committerRobert Sesek <rsesek@bluestatic.org>
Sat, 22 Feb 2020 06:37:13 +0000 (01:37 -0500)
src/fed2019/Form1040.test.ts
src/fed2019/Form1040.ts
src/fed2019/Form8959.ts [new file with mode: 0644]

index 57936efc42fece5c114a8ef5dcbe2f9afc46fc52..15dc9f1ab76fb51674efb2fb042d7019fae520ef 100644 (file)
@@ -4,6 +4,7 @@ import TaxReturn from '../TaxReturn';
 import Form1040, { FilingStatus, Schedule2 } from './Form1040';
 import Form1099DIV from './Form1099DIV';
 import Form1099INT from './Form1099INT';
+import Form8959 from './Form8959';
 import FormW2 from './FormW2';
 
 test('w2 wages', () => {
@@ -15,6 +16,7 @@ test('w2 wages', () => {
   const f1040 = new Form1040({ filingStatus: FilingStatus.MarriedFilingJoint });
   tr.addForm(f1040);
   tr.addForm(new Schedule2);
+  tr.addForm(new Form8959);
   expect(f1040.getValue(tr, '1')).toBe(1000036.32);
   f1040.getValue(tr, '23');
 });
index b3fdda9abbc8676e5ae27bfe1844e0078f597050..7884ea506a8fd5899674f6739e130dcb0a68b18a 100644 (file)
@@ -3,6 +3,8 @@ import TaxReturn from '../TaxReturn';
 import { Line, AccumulatorLine, ComputedLine, ReferenceLine } from '../Line';
 import { UnsupportedFeatureError } from '../Errors';
 
+import Form8959 from './Form8959';
+
 export enum FilingStatus {
   Single,
   MarriedFilingSeparate,
@@ -207,23 +209,24 @@ export class Schedule2 extends Form<Schedule2['_lines']> {
       const wages = f1040.getLine('1').value(tr);
       const agi = f1040.getLine('8b').value(tr);
 
-      let additionalMedicare: boolean, niit: boolean;
+      let niit: boolean;
+      const filingStatus = f1040.getInput('filingStatus');
+
+      const additionalMedicare = wages > Form8959.filingStatusLimit(filingStatus);
+
       switch (f1040.getInput('filingStatus')) {
         case FilingStatus.Single:
           if (wages > 200000) {
-            additionalMedicare = true;
             niit = true;
           }
           break;
         case FilingStatus.MarriedFilingJoint:
           if (wages > 250000) {
-            additionalMedicare = true;
             niit = true;
           }
           break;
         case FilingStatus.MarriedFilingSeparate:
           if (wages > 125000) {
-            additionalMedicare = true;
             niit = true;
           }
           break;
diff --git a/src/fed2019/Form8959.ts b/src/fed2019/Form8959.ts
new file mode 100644 (file)
index 0000000..2e01a0e
--- /dev/null
@@ -0,0 +1,59 @@
+import Form from '../Form';
+import TaxReturn from '../TaxReturn';
+import { Line, AccumulatorLine, ComputedLine, ReferenceLine } from '../Line';
+
+import Form1040, { FilingStatus } from './Form1040';
+
+export default class Form8959 extends Form<Form8959['_lines']> {
+  readonly name = '8959';
+
+  protected readonly _lines = {
+    '1': new AccumulatorLine('W-2', '5', 'Medicare wages'),
+    // 2 is not supported (Unreported tips from Form 4137)
+    // 3 is not supported (Wages from Form 8919)
+    '4': new ComputedLine((tr: TaxReturn): number => {
+      // Should include 2-3.
+      return this.getValue(tr, '1');
+    }),
+    '5': new ComputedLine((tr: TaxReturn): number => {
+      return Form8959.filingStatusLimit(tr.getForm<Form1040>('1040').getInput('filingStatus'));
+    }),
+    '6': new ComputedLine((tr: TaxReturn): number => {
+      const value = this.getValue(tr, '5') - this.getValue(tr, '4');
+      return value < 0 ? 0 : value;
+    }),
+    '7': new ComputedLine((tr: TaxReturn): number => {
+      return this.getValue(tr, '6') * 0.009;
+    }, 'Additional Medicare tax on Medicare wages'),
+
+    // All of Section 2 and 3 skipped.
+
+    '18': new ComputedLine((tr: TaxReturn): number => {
+      // Should include 13 and 17.
+      return this.getValue(tr, '7');
+    }),
+
+    '19': new AccumulatorLine('W-2', '6', 'Medicare tax withheld'),
+    '20': new ReferenceLine<number>('8595', '1'),
+    '21': new ComputedLine((tr: TaxReturn): number => {
+      return this.getValue(tr, '20') * 0.0145;
+    }, 'Regular Medicare withholding on Medicare wages'),
+    '22': new ComputedLine((tr: TaxReturn): number => {
+      const value = this.getValue(tr, '19') - this.getValue(tr, '21');
+      return value < 0 ? 0 : value;
+    }, 'Additional Medicare withholding on Medicare wages'),
+    // 23 is not supported (Additional Medicare Tax withholding on railroad retirement (RRTA) compensation)
+    '24': new ComputedLine((tr: TaxReturn): number => {
+      // Should include 23.
+      return this.getValue(tr, '22');
+    }),
+  };
+
+  static filingStatusLimit(filingStatus: FilingStatus): number {
+    switch (filingStatus) {
+      case FilingStatus.Single:                return 200000;
+      case FilingStatus.MarriedFilingJoint:    return 250000;
+      case FilingStatus.MarriedFilingSeparate: return 125000;
+    }
+  }
+};