return 0;
const l6 = schedD.getValue(tr, '16');
- if (l6 > 0)
+ if (l6 >= 0)
return l6;
return schedD.getValue(tr, '21');
}, 'Capital gain/loss'),
// Not supported:
// Form 8814 (election to report child's interest or dividends)
// Form 4972 (relating to lump-sum distributions)
- const taxableIncome = this.getValue(tr, '11b');
- if (this.getValue(tr, '3a') > 0 && !tr.findForm(ScheduleD))
- throw new UnsupportedFeatureError('Qualified Dividends and Captial Gains Tax Worksheet not supported, Schedule D requried');
+ const schedD = tr.findForm(ScheduleD);
+ // Line 18 and 19 are not undefined or 0.
+ if (schedD && !schedD.getValue(tr, '20')) {
+ // Use ScheD tax worksheet;
+ const schedDtw = tr.findForm(ScheduleDTaxWorksheet);
+ if (schedDtw)
+ return schedDtw.getValue(tr, '47');
+ }
- const schedD = tr.findForm(ScheduleDTaxWorksheet);
- if (schedD)
- return schedD.getValue(tr, '47');
+ // If there are qualified dividends, use the QDCGTW.
+ if (this.getValue(tr, '3a') > 0) {
+ const qdcgtw = tr.getForm(QDCGTaxWorksheet);
+ return qdcgtw.getValue(tr, '27');
+ }
- return computeTax(taxableIncome, this.filingStatus);
+ // Otherwise, compute just on taxable income.
+ return computeTax(this.getValue(tr, '11b'), this.filingStatus);
}, 'Tax'),
'12b': new ComputedLine((tr): number => {
return ((income - bracketStart) * bracket[1]) + bracket[2];
};
+
+export class QDCGTaxWorksheet extends Form<QDCGTaxWorksheet['_lines']> {
+ readonly name = 'Qual Div Cap Gain Tax Worksheet';
+
+ protected readonly _lines = {
+ '1': new ReferenceLine(Form1040, '11b', 'Taxable income'),
+ '2': new ReferenceLine(Form1040, '3a', 'Qualified dividends'),
+ '3': new ComputedLine((tr): number => {
+ const schedD = tr.findForm(ScheduleD);
+ if (schedD)
+ return Math.min(schedD.getValue(tr, '15'), schedD.getValue(tr, '16'));
+ return tr.getForm(Form1040).getValue(tr, '6');
+ }),
+ '4': new ComputedLine((tr): number => this.getValue(tr, '2') + this.getValue(tr, '3')),
+ '5': new ComputedLine(() => 0), // Not supported - Form 4952/4g (nvestment interest expense deduction)
+ '6': new ComputedLine((tr): number => clampToZero(this.getValue(tr, '4') - this.getValue(tr, '5'))),
+ '7': new ComputedLine((tr): number => clampToZero(this.getValue(tr, '1') - this.getValue(tr, '6'))),
+ '8': new ComputedLine((tr): number => {
+ switch (tr.getForm(Form1040).filingStatus) {
+ case FilingStatus.Single:
+ case FilingStatus.MarriedFilingSeparate:
+ return 39375;
+ case FilingStatus.MarriedFilingJoint:
+ return 78750;
+ };
+ }),
+ '9': new ComputedLine((tr): number => Math.min(this.getValue(tr, '1'), this.getValue(tr, '8'))),
+ '10': new ComputedLine((tr): number => Math.min(this.getValue(tr, '7'), this.getValue(tr, '9'))),
+ '11': new ComputedLine((tr): number => {
+ return this.getValue(tr, '9') - this.getValue(tr, '10');
+ }, 'Amount taxed at 0%'),
+ '12': new ComputedLine((tr): number => Math.min(this.getValue(tr, '1'), this.getValue(tr, '6'))),
+ '13': new ReferenceLine(QDCGTaxWorksheet as any, '11'),
+ '14': new ComputedLine((tr): number => this.getValue(tr, '12') - this.getValue(tr, '13')),
+ '15': new ComputedLine((tr): number => {
+ switch (tr.getForm(Form1040).filingStatus) {
+ case FilingStatus.Single: return 434550;
+ case FilingStatus.MarriedFilingSeparate: return 244425;
+ case FilingStatus.MarriedFilingJoint: return 488850;
+ };
+ }),
+ '16': new ComputedLine((tr): number => Math.min(this.getValue(tr, '1'), this.getValue(tr, '15'))),
+ '17': new ComputedLine((tr): number => this.getValue(tr, '7') + this.getValue(tr, '11')),
+ '18': new ComputedLine((tr): number => clampToZero(this.getValue(tr, '16') - this.getValue(tr, '17'))),
+ '19': new ComputedLine((tr): number => Math.min(this.getValue(tr, '14'), this.getValue(tr, '18'))),
+ '20': new ComputedLine((tr): number => {
+ return this.getValue(tr, '19') * 0.15;
+ }, 'Amount taxed at 15%'),
+ '21': new ComputedLine((tr): number => this.getValue(tr, '11') + this.getValue(tr, '19')),
+ '22': new ComputedLine((tr): number => this.getValue(tr, '12') - this.getValue(tr, '21')),
+ '23': new ComputedLine((tr): number => {
+ return this.getValue(tr, '22') * 0.20;
+ }, 'Amount taxed at 20%'),
+ '24': new ComputedLine((tr): number => {
+ return computeTax(this.getValue(tr, '7'), tr.getForm(Form1040).filingStatus);
+ }, 'Tax on line 7'),
+ '25': new ComputedLine((tr): number => {
+ return this.getValue(tr, '20') +
+ this.getValue(tr, '23') +
+ this.getValue(tr, '24');
+ }),
+ '26': new ComputedLine((tr): number => {
+ return computeTax(this.getValue(tr, '1'), tr.getForm(Form1040).filingStatus);
+ }, 'Tax on line 1'),
+ '27': new ComputedLine((tr): number => {
+ return Math.min(this.getValue(tr, '25'), this.getValue(tr, '26'));
+ }, 'Tax on all taxable income')
+ };
+};
import { Form, Person, TaxReturn } from '../core';
import { Line, AccumulatorLine, ComputedLine, ReferenceLine, sumLineOfForms } from '../core/Line';
import { clampToZero } from '../core/Math';
-import { UnsupportedFeatureError } from '../core/Errors';
+import { NotFoundError, UnsupportedFeatureError } from '../core/Errors';
import Form8949, { Form8949Box } from './Form8949';
import Form1099DIV from './Form1099DIV';
-import Form1040, { FilingStatus, computeTax } from './Form1040';
+import Form1040, { FilingStatus, QDCGTaxWorksheet, computeTax } from './Form1040';
export default class ScheduleD extends Form<ScheduleD['_lines']> {
readonly name = 'Schedule D';
return f8949.getValue(tr, 'boxA').gainOrLoss +
f8949.getValue(tr, 'boxB').gainOrLoss +
f8949.getValue(tr, 'boxC').gainOrLoss;
- }, 'Net short-term capital gain or (loss)'),
+ }, 'Net short-term capital gain or loss'),
// 8a is not supported.
f8949.getValue(tr, 'boxE').gainOrLoss +
f8949.getValue(tr, 'boxF').gainOrLoss +
this.getValue(tr, '13');
- }, 'Net long-term capital gain or (loss)'),
+ }, 'Net long-term capital gain or loss'),
'16': new ComputedLine((tr): number => {
return this.getValue(tr, '7') + this.getValue(tr, '15');
- }),
+ // If value is a gain, enter on 1040/6 and goto 17.
+ // If value is a loss, goto 21 and 22.
+ // If value is zero, enter 0 on 1040/6 and goto 22.
+ }, 'Total capital gain or loss'),
'17': new ComputedLine((tr): boolean => {
return this.getValue(tr, '15') > 0 && this.getValue(tr, '16') > 0;
+ // If yes, goto 18.
+ // If no, goto 22.
}, 'Both ST and LT are gains'),
'18': new ComputedLine((tr): number | undefined => {
- if (!this.getValue(tr, '17') || this.getValue(tr, '16') <= 0)
- return undefined;
// Not supported - only for gains on Qualified Small Business Stock or collectibles.
return 0;
}, '28% Rate Gain Worksheet Value'),
- // 19 is not supported (Unrecaptured Section 1250 Gain Worksheet)
+ '19': new ComputedLine(() => undefined, 'Unrecaptured Section 1250 Gain Worksheet'), // Not supported.
'20': new ComputedLine((tr): boolean | undefined => {
- if (!this.getValue(tr, '17') || this.getValue(tr, '16') <= 0)
- return undefined;
const l18 = this.getValue(tr, '18');
- const l19 = undefined; //this.getValue(tr, '19');
+ const l19 = this.getValue(tr, '19');
return (l18 === 0 || l18 === undefined) || (l19 === 0 || l19 === undefined);
}, 'Line 18 and 19 both 0 or blank?'),
'21': new ComputedLine((tr): number | undefined => {
- if (!this.getValue(tr, '17') || !this.getValue(tr, '20'))
- return undefined;
+ const l16 = this.getValue(tr, '16');
+ if (l16 >= 0)
+ return 0;
const filingStatus = tr.getForm(Form1040).filingStatus;
const limit = filingStatus == FilingStatus.MarriedFilingSeparate ? -1500 : -3000;
- return Math.min(this.getValue(tr, '16'), limit);
+ return Math.max(l16, limit);
}, 'Net capital loss'),
+
+ '22': new ComputedLine((tr): boolean => {
+ return tr.getForm(Form1040).getValue(tr, '3a') > 0;
+ }, 'Need QD/CG Tax Worksheet'),
};
};
'10': new ComputedLine((tr): number => this.getValue(tr, '6') + this.getValue(tr, '9')),
'11': new ComputedLine((tr): number => {
const schedD = tr.getForm(ScheduleD);
- // TODO - line 19 is not supported.
- return Math.min(schedD.getValue(tr, '18'), Infinity); //schedD.getValue(tr, '19'));
+ return schedD.getValue(tr, '18') + schedD.getValue(tr, '19');
}),
'12': new ComputedLine((tr): number => Math.min(this.getValue(tr, '9'), this.getValue(tr, '11'))),
'13': new ComputedLine((tr): number => this.getValue(tr, '10') - this.getValue(tr, '12')),