import Form1099DIV from './Form1099DIV';
import Form1099R, { Box7Code } from './Form1099R';
import FormW2 from './FormW2';
+import Schedule1 from './Schedule1';
import Schedule2 from './Schedule2';
import ScheduleD, { ScheduleDTaxWorksheet } from './ScheduleD';
return l6;
return schedD.getValue(tr, '21');
}, 'Capital gain/loss'),
- '7a': new ReferenceLine(/*'Schedule 1'*/ undefined, '9', 'Other income from Schedule 1', 0),
+ '7a': new ReferenceLine(Schedule1, '9', 'Other income from Schedule 1', 0),
'7b': new ComputedLine((tr): number => {
let income = 0;
return income;
}, 'Total income'),
- '8a': new ReferenceLine(undefined /*'Schedule 1'*/, '22', 'Adjustments to income', 0),
+ '8a': new ReferenceLine(Schedule1, '22', 'Adjustments to income', 0),
'8b': new ComputedLine((tr): number => {
return this.getValue(tr, '7b') - this.getValue(tr, '8a');
--- /dev/null
+import TaxReturn from '../TaxReturn';
+import Person from '../Person';
+import { UnsupportedFeatureError } from '../Errors';
+
+import Form1040, { FilingStatus } from './Form1040';
+import Schedule1, { Schedule1Input } from './Schedule1';
+
+test('state tax refund', () => {
+ const p = Person.self('A');
+ const tr = new TaxReturn(2019);
+ tr.addForm(new Form1040({
+ filingStatus: FilingStatus.Single
+ }));
+ const f = new Schedule1({
+ stateAndLocalTaxableRefunds: 500
+ });
+ tr.addForm(f);
+
+ expect(f.getValue(tr, '9')).toBe(500);
+ expect(tr.getForm(Form1040).getValue(tr, '7a')).toBe(500);
+});
+
+test('unsupported inputs', () => {
+ const keys: (keyof Schedule1Input)[] = [
+ 'businessIncome',
+ 'otherGainsOrLosses',
+ 'rentalRealEstateRoyaltiesPartnershipsSCorps',
+ 'farmIncome',
+ 'businessExpensesForm2106',
+ 'hsaDeduction',
+ 'armedForcesMovingExpenses',
+ 'deductibleSelfEmploymentTax',
+ 'tuitionAndFees',
+ ];
+ for (const input of keys) {
+ const p = Person.self('A');
+ const tr = new TaxReturn(2019);
+ const f = new Schedule1({
+ [input]: 100
+ });
+ tr.addForm(f);
+ expect(() => f.getValue(tr, '9') + f.getValue(tr, '22')).toThrow(UnsupportedFeatureError);
+ }
+});
--- /dev/null
+import Form from '../Form';
+import TaxReturn from '../TaxReturn';
+import { ComputedLine, InputLine } from '../Line';
+import { NotFoundError, UnsupportedFeatureError } from '../Errors';
+import { undefinedToZero } from '../Math';
+
+import Form1040 from './Form1040';
+
+export interface Schedule1Input {
+ // Additional Income
+ stateAndLocalTaxableRefunds?: number;
+ alimonyReceived?: number;
+ businessIncome?: number;
+ otherGainsOrLosses?: number
+ rentalRealEstateRoyaltiesPartnershipsSCorps?: number;
+ farmIncome?: number;
+ unemploymentCompensation?: number;
+ otherIncome?: number;
+
+ // Adjustments
+ educatorExpenses?: number;
+ businessExpensesForm2106?: number;
+ hsaDeduction?: number;
+ armedForcesMovingExpenses?: number;
+ deductibleSelfEmploymentTax?: number;
+ selfEmployedSepSimpleQualifiedPlans?: number;
+ selfEmployedHealthInsuranceDeduction?: number;
+ penaltyOnEarlyWithdrawal?: number;
+ alimonyPaid?: number;
+ iraDeduction?: number;
+ studentLoanInterestDeduction?: number;
+ tuitionAndFees?: number;
+};
+
+class Input<T extends keyof Schedule1Input> extends InputLine<Schedule1Input, T> {
+ private _predicate: (value: Schedule1Input[T]) => void;
+
+ constructor(input: T, predicate?: (value: Schedule1Input[T]) => void) {
+ super(input);
+ this._predicate = predicate;
+ }
+
+ value(tr: TaxReturn): Schedule1Input[T] {
+ let value: Schedule1Input[T] = undefined;
+ try {
+ value = super.value(tr);
+ } catch (NotFoundError) {
+ }
+ if (this._predicate)
+ this._predicate(value);
+ return value;
+ }
+};
+
+export default class Schedule1 extends Form<Schedule1['_lines'], Schedule1Input> {
+ readonly name = 'Schedule 1';
+
+ readonly _lines = {
+ // Part 1
+ '1': new Input('stateAndLocalTaxableRefunds'),
+ '2': new Input('alimonyReceived'),
+ '3': new Input('businessIncome', (value: number) => {
+ if (value !== undefined)
+ throw new UnsupportedFeatureError('Schedule C not supported');
+ }),
+ '4': new Input('otherGainsOrLosses', (value: number) => {
+ if (value !== undefined)
+ throw new UnsupportedFeatureError('Form 4797 not supported');
+ }),
+ '5': new Input('rentalRealEstateRoyaltiesPartnershipsSCorps', (value: number) => {
+ if (value !== undefined)
+ throw new UnsupportedFeatureError('Schedule E not supported');
+ }),
+ '6': new Input('farmIncome', (value: number) => {
+ if (value !== undefined)
+ throw new UnsupportedFeatureError('Schedule F not supported');
+ }),
+ '7': new Input('unemploymentCompensation'),
+ '8': new Input('otherIncome'),
+ '9': new ComputedLine((tr): number => {
+ return undefinedToZero(this.getValue(tr, '1')) +
+ undefinedToZero(this.getValue(tr, '2')) +
+ undefinedToZero(this.getValue(tr, '3')) +
+ undefinedToZero(this.getValue(tr, '4')) +
+ undefinedToZero(this.getValue(tr, '5')) +
+ undefinedToZero(this.getValue(tr, '6')) +
+ undefinedToZero(this.getValue(tr, '7')) +
+ undefinedToZero(this.getValue(tr, '8'));
+ }),
+
+ // Part 2
+ '10': new Input('educatorExpenses'),
+ '11': new Input('businessExpensesForm2106', (value: number) => {
+ if (value !== undefined)
+ throw new UnsupportedFeatureError('Form 2106 not supported');
+ }),
+ '12': new Input('hsaDeduction', (value: number) => {
+ if (value !== undefined)
+ throw new UnsupportedFeatureError('Form 8889 not supported');
+ }),
+ '13': new Input('armedForcesMovingExpenses', (value: number) => {
+ if (value !== undefined)
+ throw new UnsupportedFeatureError('Form 3903 not supported');
+ }),
+ '14': new Input('deductibleSelfEmploymentTax', (value: number) => {
+ if (value !== undefined)
+ throw new UnsupportedFeatureError('Schedule SE not supported');
+ }),
+ '15': new Input('selfEmployedSepSimpleQualifiedPlans'),
+ '16': new Input('selfEmployedHealthInsuranceDeduction'),
+ '17': new Input('penaltyOnEarlyWithdrawal'),
+ '18': new Input('alimonyPaid'),
+ '19': new Input('iraDeduction'),
+ '20': new Input('studentLoanInterestDeduction'),
+ '21': new Input('tuitionAndFees', (value: number) => {
+ if (value !== undefined)
+ throw new UnsupportedFeatureError('Form 8917 not supported');
+ }),
+ '22': new ComputedLine((tr): number => {
+ return undefinedToZero(this.getValue(tr, '10')) +
+ undefinedToZero(this.getValue(tr, '11')) +
+ undefinedToZero(this.getValue(tr, '12')) +
+ undefinedToZero(this.getValue(tr, '13')) +
+ undefinedToZero(this.getValue(tr, '14')) +
+ undefinedToZero(this.getValue(tr, '15')) +
+ undefinedToZero(this.getValue(tr, '16')) +
+ undefinedToZero(this.getValue(tr, '17')) +
+ undefinedToZero(this.getValue(tr, '18')) +
+ undefinedToZero(this.getValue(tr, '19')) +
+ undefinedToZero(this.getValue(tr, '20')) +
+ undefinedToZero(this.getValue(tr, '21'));
+ }),
+ };
+};