State taxes added to simulation
This commit is contained in:
parent
2f9dc03f57
commit
e3d804e01a
@ -2,17 +2,12 @@ import moment from 'moment';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Single-filer federal tax calculation (2023).
|
* Single-filer federal tax calculation (2023).
|
||||||
* Includes standard deduction ($13,850).
|
* Includes standard deduction ($13,850).
|
||||||
* If you need to update the brackets/deduction, edit here.
|
|
||||||
*/
|
*/
|
||||||
function calculateAnnualFederalTaxSingle(annualIncome) {
|
function calculateAnnualFederalTaxSingle(annualIncome) {
|
||||||
// 1. Subtract standard deduction
|
|
||||||
const STANDARD_DEDUCTION_SINGLE = 13850;
|
const STANDARD_DEDUCTION_SINGLE = 13850;
|
||||||
const taxableIncome = Math.max(0, annualIncome - STANDARD_DEDUCTION_SINGLE);
|
const taxableIncome = Math.max(0, annualIncome - STANDARD_DEDUCTION_SINGLE);
|
||||||
|
|
||||||
// 2. Define bracket thresholds & rates for single filers (2023)
|
|
||||||
// The 'limit' is the upper bound for that bracket segment.
|
|
||||||
// Use Infinity for the top bracket.
|
|
||||||
const brackets = [
|
const brackets = [
|
||||||
{ limit: 11000, rate: 0.10 },
|
{ limit: 11000, rate: 0.10 },
|
||||||
{ limit: 44725, rate: 0.12 },
|
{ limit: 44725, rate: 0.12 },
|
||||||
@ -26,23 +21,37 @@ function calculateAnnualFederalTaxSingle(annualIncome) {
|
|||||||
let tax = 0;
|
let tax = 0;
|
||||||
let lastLimit = 0;
|
let lastLimit = 0;
|
||||||
|
|
||||||
// 3. Accumulate tax across brackets
|
|
||||||
for (let i = 0; i < brackets.length; i++) {
|
for (let i = 0; i < brackets.length; i++) {
|
||||||
const { limit, rate } = brackets[i];
|
const { limit, rate } = brackets[i];
|
||||||
if (taxableIncome <= limit) {
|
if (taxableIncome <= limit) {
|
||||||
// only tax the portion within this bracket
|
|
||||||
tax += (taxableIncome - lastLimit) * rate;
|
tax += (taxableIncome - lastLimit) * rate;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// tax the entire bracket range, then continue
|
|
||||||
tax += (limit - lastLimit) * rate;
|
tax += (limit - lastLimit) * rate;
|
||||||
lastLimit = limit;
|
lastLimit = limit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tax;
|
return tax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example state tax calculation.
|
||||||
|
* Currently a simple flat rate based on `stateCode` from a small dictionary.
|
||||||
|
* You can replace with bracket-based logic if desired.
|
||||||
|
*/
|
||||||
|
function calculateAnnualStateTax(annualIncome, stateCode) {
|
||||||
|
// Example dictionary of flat rates (not real data!)
|
||||||
|
const stateTaxInfo = {
|
||||||
|
CA: 0.08, // 8%
|
||||||
|
NY: 0.06, // 6%
|
||||||
|
TX: 0.00,
|
||||||
|
FL: 0.00,
|
||||||
|
GA: 0.05
|
||||||
|
};
|
||||||
|
const rate = stateTaxInfo[stateCode] ?? 0.05; // default 5% if not found
|
||||||
|
return annualIncome * rate;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the standard monthly loan payment for principal, annualRate (%) and term (years).
|
* Calculate the standard monthly loan payment for principal, annualRate (%) and term (years).
|
||||||
*/
|
*/
|
||||||
@ -53,7 +62,6 @@ function calculateLoanPayment(principal, annualRate, years) {
|
|||||||
const numPayments = years * 12;
|
const numPayments = years * 12;
|
||||||
|
|
||||||
if (monthlyRate === 0) {
|
if (monthlyRate === 0) {
|
||||||
// no interest
|
|
||||||
return principal / numPayments;
|
return principal / numPayments;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
@ -63,7 +71,7 @@ function calculateLoanPayment(principal, annualRate, years) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main projection function with bracket-based tax logic for single filers.
|
* Main projection function with bracket-based FEDERAL + optional STATE tax logic.
|
||||||
*/
|
*/
|
||||||
export function simulateFinancialProjection(userProfile) {
|
export function simulateFinancialProjection(userProfile) {
|
||||||
const {
|
const {
|
||||||
@ -85,9 +93,9 @@ export function simulateFinancialProjection(userProfile) {
|
|||||||
programType,
|
programType,
|
||||||
hoursCompleted = 0,
|
hoursCompleted = 0,
|
||||||
creditHoursPerYear,
|
creditHoursPerYear,
|
||||||
calculatedTuition,
|
calculatedTuition,
|
||||||
gradDate,
|
gradDate,
|
||||||
startDate,
|
startDate,
|
||||||
academicCalendar = 'monthly',
|
academicCalendar = 'monthly',
|
||||||
annualFinancialAid = 0,
|
annualFinancialAid = 0,
|
||||||
|
|
||||||
@ -107,10 +115,13 @@ export function simulateFinancialProjection(userProfile) {
|
|||||||
surplusRetirementAllocation = 50,
|
surplusRetirementAllocation = 50,
|
||||||
|
|
||||||
// Potential override
|
// Potential override
|
||||||
programLength
|
programLength,
|
||||||
|
|
||||||
|
// NEW: user’s state code (e.g. 'CA', 'NY', 'TX', etc.)
|
||||||
|
stateCode = 'TX', // default to TX (no state income tax)
|
||||||
} = userProfile;
|
} = userProfile;
|
||||||
|
|
||||||
// 1. Calculate standard monthly loan payment (if not deferring)
|
// 1. Monthly loan payment if not deferring
|
||||||
let monthlyLoanPayment = loanDeferralUntilGraduation
|
let monthlyLoanPayment = loanDeferralUntilGraduation
|
||||||
? 0
|
? 0
|
||||||
: calculateLoanPayment(studentLoanAmount, interestRate, loanTerm);
|
: calculateLoanPayment(studentLoanAmount, interestRate, loanTerm);
|
||||||
@ -137,17 +148,16 @@ export function simulateFinancialProjection(userProfile) {
|
|||||||
const dynamicProgramLength = Math.ceil(remainingCreditHours / creditHoursPerYear);
|
const dynamicProgramLength = Math.ceil(remainingCreditHours / creditHoursPerYear);
|
||||||
const finalProgramLength = programLength || dynamicProgramLength;
|
const finalProgramLength = programLength || dynamicProgramLength;
|
||||||
|
|
||||||
// 3. Net annual tuition after financial aid
|
// 3. Net annual tuition after aid
|
||||||
const netAnnualTuition = Math.max(0, calculatedTuition - annualFinancialAid);
|
const netAnnualTuition = Math.max(0, calculatedTuition - annualFinancialAid);
|
||||||
const totalTuitionCost = netAnnualTuition * finalProgramLength;
|
const totalTuitionCost = netAnnualTuition * finalProgramLength;
|
||||||
|
|
||||||
// 4. Setup lumps per year based on academicCalendar
|
// 4. Setup lumps per year
|
||||||
let lumpsPerYear = 12; // monthly fallback
|
let lumpsPerYear, lumpsSchedule;
|
||||||
let lumpsSchedule = [];
|
|
||||||
switch (academicCalendar) {
|
switch (academicCalendar) {
|
||||||
case 'semester':
|
case 'semester':
|
||||||
lumpsPerYear = 2;
|
lumpsPerYear = 2;
|
||||||
lumpsSchedule = [0, 6];
|
lumpsSchedule = [0, 6];
|
||||||
break;
|
break;
|
||||||
case 'quarter':
|
case 'quarter':
|
||||||
lumpsPerYear = 4;
|
lumpsPerYear = 4;
|
||||||
@ -160,41 +170,39 @@ export function simulateFinancialProjection(userProfile) {
|
|||||||
case 'monthly':
|
case 'monthly':
|
||||||
default:
|
default:
|
||||||
lumpsPerYear = 12;
|
lumpsPerYear = 12;
|
||||||
lumpsSchedule = [...Array(12).keys()]; // 0..11
|
lumpsSchedule = [...Array(12).keys()];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const totalAcademicMonths = finalProgramLength * 12;
|
const totalAcademicMonths = finalProgramLength * 12;
|
||||||
const lumpAmount = totalTuitionCost / (lumpsPerYear * finalProgramLength);
|
const lumpAmount = totalTuitionCost / (lumpsPerYear * finalProgramLength);
|
||||||
|
|
||||||
// 5. Simulation loop up to 20 years
|
// 5. Simulation loop
|
||||||
const maxMonths = 240;
|
const maxMonths = 240;
|
||||||
let date = startDate ? new Date(startDate) : new Date();
|
let date = startDate ? new Date(startDate) : new Date();
|
||||||
|
|
||||||
let loanBalance = Math.max(studentLoanAmount, 0);
|
let loanBalance = Math.max(studentLoanAmount, 0);
|
||||||
let loanPaidOffMonth = null;
|
let loanPaidOffMonth = null;
|
||||||
|
|
||||||
let currentEmergencySavings = emergencySavings;
|
let currentEmergencySavings = emergencySavings;
|
||||||
let currentRetirementSavings = retirementSavings;
|
let currentRetirementSavings = retirementSavings;
|
||||||
|
|
||||||
let projectionData = [];
|
let projectionData = [];
|
||||||
let wasInDeferral = inCollege && loanDeferralUntilGraduation;
|
let wasInDeferral = inCollege && loanDeferralUntilGraduation;
|
||||||
|
|
||||||
// If gradDate is provided, parse it to Date
|
|
||||||
const graduationDate = gradDate ? new Date(gradDate) : null;
|
const graduationDate = gradDate ? new Date(gradDate) : null;
|
||||||
|
|
||||||
// Keep a map of year => { ytdGross, ytdTaxSoFar } for bracket-based taxes
|
// YTD tracking for each year (federal + state)
|
||||||
|
// e.g. taxStateByYear[2025] = { federalYtdGross, federalYtdTaxSoFar, stateYtdGross, stateYtdTaxSoFar }
|
||||||
const taxStateByYear = {};
|
const taxStateByYear = {};
|
||||||
|
|
||||||
for (let month = 0; month < maxMonths; month++) {
|
for (let month = 0; month < maxMonths; month++) {
|
||||||
date.setMonth(date.getMonth() + 1);
|
date.setMonth(date.getMonth() + 1);
|
||||||
const currentYear = date.getFullYear();
|
const currentYear = date.getFullYear();
|
||||||
|
|
||||||
// If loan is fully paid, record if not already done
|
// Check if loan is fully paid
|
||||||
if (loanBalance <= 0 && !loanPaidOffMonth) {
|
if (loanBalance <= 0 && !loanPaidOffMonth) {
|
||||||
loanPaidOffMonth = `${currentYear}-${String(date.getMonth() + 1).padStart(2, '0')}`;
|
loanPaidOffMonth = `${currentYear}-${String(date.getMonth() + 1).padStart(2, '0')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if user is still in college (trusted gradDate or approximate)
|
// Are we still in college?
|
||||||
let stillInCollege = false;
|
let stillInCollege = false;
|
||||||
if (inCollege) {
|
if (inCollege) {
|
||||||
if (graduationDate) {
|
if (graduationDate) {
|
||||||
@ -208,7 +216,7 @@ export function simulateFinancialProjection(userProfile) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. Check if we owe tuition lumps this month
|
// 6. Tuition lumps
|
||||||
let tuitionCostThisMonth = 0;
|
let tuitionCostThisMonth = 0;
|
||||||
if (stillInCollege && lumpsPerYear > 0) {
|
if (stillInCollege && lumpsPerYear > 0) {
|
||||||
const simStart = startDate ? new Date(startDate) : new Date();
|
const simStart = startDate ? new Date(startDate) : new Date();
|
||||||
@ -224,71 +232,79 @@ export function simulateFinancialProjection(userProfile) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. Detect if we are now exiting college this month
|
// 7. Exiting college?
|
||||||
const nowExitingCollege = (wasInDeferral && !stillInCollege);
|
const nowExitingCollege = (wasInDeferral && !stillInCollege);
|
||||||
|
|
||||||
// 8. If in deferral, lumps get added to the loan principal
|
// 8. Deferral lumps get added to loan
|
||||||
if (stillInCollege && loanDeferralUntilGraduation) {
|
if (stillInCollege && loanDeferralUntilGraduation) {
|
||||||
if (tuitionCostThisMonth > 0) {
|
if (tuitionCostThisMonth > 0) {
|
||||||
loanBalance += tuitionCostThisMonth;
|
loanBalance += tuitionCostThisMonth;
|
||||||
tuitionCostThisMonth = 0;
|
tuitionCostThisMonth = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 9. Gross monthly income depends on college status
|
// 9. Gross monthly income
|
||||||
let grossMonthlyIncome = 0;
|
let grossMonthlyIncome = 0;
|
||||||
if (!inCollege || !stillInCollege) {
|
if (!inCollege || !stillInCollege) {
|
||||||
// Graduated or never was in college => use expectedSalary if given
|
|
||||||
grossMonthlyIncome = (expectedSalary > 0 ? expectedSalary : currentSalary) / 12;
|
grossMonthlyIncome = (expectedSalary > 0 ? expectedSalary : currentSalary) / 12;
|
||||||
} else {
|
} else {
|
||||||
// Still in college => currentSalary + part-time
|
|
||||||
grossMonthlyIncome = (currentSalary / 12) + (partTimeIncome / 12);
|
grossMonthlyIncome = (currentSalary / 12) + (partTimeIncome / 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// 10. Tax calculations
|
||||||
* 10. Calculate monthly TAX via bracket-based approach:
|
|
||||||
* We track year-to-date (YTD) for the current calendar year.
|
|
||||||
*/
|
|
||||||
if (!taxStateByYear[currentYear]) {
|
if (!taxStateByYear[currentYear]) {
|
||||||
taxStateByYear[currentYear] = { ytdGross: 0, ytdTaxSoFar: 0 };
|
taxStateByYear[currentYear] = {
|
||||||
|
federalYtdGross: 0,
|
||||||
|
federalYtdTaxSoFar: 0,
|
||||||
|
stateYtdGross: 0,
|
||||||
|
stateYtdTaxSoFar: 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add this month’s gross to YTD
|
// Update YTD gross for federal + state
|
||||||
taxStateByYear[currentYear].ytdGross += grossMonthlyIncome;
|
taxStateByYear[currentYear].federalYtdGross += grossMonthlyIncome;
|
||||||
|
taxStateByYear[currentYear].stateYtdGross += grossMonthlyIncome;
|
||||||
|
|
||||||
// Calculate total tax for YTD
|
// Compute total fed tax for the year so far
|
||||||
const annualTaxSoFar = calculateAnnualFederalTaxSingle(
|
const newFedTaxTotal = calculateAnnualFederalTaxSingle(
|
||||||
taxStateByYear[currentYear].ytdGross
|
taxStateByYear[currentYear].federalYtdGross
|
||||||
);
|
);
|
||||||
|
// Monthly fed tax = difference
|
||||||
|
const monthlyFederalTax = newFedTaxTotal - taxStateByYear[currentYear].federalYtdTaxSoFar;
|
||||||
|
taxStateByYear[currentYear].federalYtdTaxSoFar = newFedTaxTotal;
|
||||||
|
|
||||||
// This month’s tax = (new YTD tax) - (old YTD tax)
|
// Compute total state tax for the year so far
|
||||||
const monthlyTax = annualTaxSoFar - taxStateByYear[currentYear].ytdTaxSoFar;
|
const newStateTaxTotal = calculateAnnualStateTax(
|
||||||
|
taxStateByYear[currentYear].stateYtdGross,
|
||||||
|
stateCode
|
||||||
|
);
|
||||||
|
const monthlyStateTax = newStateTaxTotal - taxStateByYear[currentYear].stateYtdTaxSoFar;
|
||||||
|
taxStateByYear[currentYear].stateYtdTaxSoFar = newStateTaxTotal;
|
||||||
|
|
||||||
// Update YTD tax
|
// Combined monthly tax
|
||||||
taxStateByYear[currentYear].ytdTaxSoFar = annualTaxSoFar;
|
const combinedTax = monthlyFederalTax + monthlyStateTax;
|
||||||
|
|
||||||
// Net monthly income after tax
|
// Net monthly income after taxes
|
||||||
const netMonthlyIncome = grossMonthlyIncome - monthlyTax;
|
const netMonthlyIncome = grossMonthlyIncome - combinedTax;
|
||||||
|
|
||||||
// 11. Monthly expenses (excluding student loan if deferring)
|
// 11. Expenses & loan
|
||||||
let thisMonthLoanPayment = 0;
|
let thisMonthLoanPayment = 0;
|
||||||
let totalMonthlyExpenses = monthlyExpenses + monthlyDebtPayments + tuitionCostThisMonth;
|
let totalMonthlyExpenses = monthlyExpenses + monthlyDebtPayments + tuitionCostThisMonth;
|
||||||
|
|
||||||
// Re-amortize if we're just now exiting college
|
// Re-amortize if just exited college
|
||||||
if (nowExitingCollege) {
|
if (nowExitingCollege) {
|
||||||
monthlyLoanPayment = calculateLoanPayment(
|
monthlyLoanPayment = calculateLoanPayment(
|
||||||
loanBalance,
|
loanBalance,
|
||||||
interestRate,
|
interestRate,
|
||||||
10 // fresh 10-year term post-college
|
10
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 12. If still deferring, just accrue interest
|
// If not deferring, we do normal payments
|
||||||
if (stillInCollege && loanDeferralUntilGraduation) {
|
if (stillInCollege && loanDeferralUntilGraduation) {
|
||||||
const interestForMonth = loanBalance * (interestRate / 100 / 12);
|
const interestForMonth = loanBalance * (interestRate / 100 / 12);
|
||||||
loanBalance += interestForMonth;
|
loanBalance += interestForMonth;
|
||||||
} else {
|
} else {
|
||||||
// Normal repayment if loan > 0
|
|
||||||
if (loanBalance > 0) {
|
if (loanBalance > 0) {
|
||||||
const interestForMonth = loanBalance * (interestRate / 100 / 12);
|
const interestForMonth = loanBalance * (interestRate / 100 / 12);
|
||||||
const principalForMonth = Math.min(
|
const principalForMonth = Math.min(
|
||||||
@ -303,11 +319,11 @@ export function simulateFinancialProjection(userProfile) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 13. leftover after mandatory expenses
|
// 12. leftover after mandatory expenses
|
||||||
let leftover = netMonthlyIncome - totalMonthlyExpenses;
|
let leftover = netMonthlyIncome - totalMonthlyExpenses;
|
||||||
if (leftover < 0) leftover = 0;
|
if (leftover < 0) leftover = 0;
|
||||||
|
|
||||||
// Baseline monthly contributions
|
// Baseline contributions
|
||||||
const baselineContributions = monthlyRetirementContribution + monthlyEmergencyContribution;
|
const baselineContributions = monthlyRetirementContribution + monthlyEmergencyContribution;
|
||||||
let effectiveRetirementContribution = 0;
|
let effectiveRetirementContribution = 0;
|
||||||
let effectiveEmergencyContribution = 0;
|
let effectiveEmergencyContribution = 0;
|
||||||
@ -317,48 +333,44 @@ export function simulateFinancialProjection(userProfile) {
|
|||||||
effectiveEmergencyContribution = monthlyEmergencyContribution;
|
effectiveEmergencyContribution = monthlyEmergencyContribution;
|
||||||
leftover -= baselineContributions;
|
leftover -= baselineContributions;
|
||||||
} else {
|
} else {
|
||||||
// Not enough leftover => zero out contributions
|
|
||||||
effectiveRetirementContribution = 0;
|
effectiveRetirementContribution = 0;
|
||||||
effectiveEmergencyContribution = 0;
|
effectiveEmergencyContribution = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for shortfall vs. mandatory expenses
|
// Check shortfall
|
||||||
const totalWantedContributions = effectiveRetirementContribution + effectiveEmergencyContribution;
|
const totalWantedContributions = effectiveRetirementContribution + effectiveEmergencyContribution;
|
||||||
const actualExpensesPaid = totalMonthlyExpenses + totalWantedContributions;
|
const actualExpensesPaid = totalMonthlyExpenses + totalWantedContributions;
|
||||||
let shortfall = actualExpensesPaid - netMonthlyIncome;
|
let shortfall = actualExpensesPaid - netMonthlyIncome;
|
||||||
if (shortfall > 0) {
|
if (shortfall > 0) {
|
||||||
// Attempt to cover from emergency savings
|
|
||||||
const canCover = Math.min(shortfall, currentEmergencySavings);
|
const canCover = Math.min(shortfall, currentEmergencySavings);
|
||||||
currentEmergencySavings -= canCover;
|
currentEmergencySavings -= canCover;
|
||||||
shortfall -= canCover;
|
shortfall -= canCover;
|
||||||
if (shortfall > 0) {
|
if (shortfall > 0) {
|
||||||
// Even after emergency, we can't cover => break (bankrupt scenario)
|
// bankrupt scenario
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 14. Surplus allocation if leftover > 0
|
// 13. Surplus
|
||||||
const newLeftover = leftover;
|
if (leftover > 0) {
|
||||||
if (newLeftover > 0) {
|
|
||||||
// Allocate by percentage
|
|
||||||
const totalPct = surplusEmergencyAllocation + surplusRetirementAllocation;
|
const totalPct = surplusEmergencyAllocation + surplusRetirementAllocation;
|
||||||
const emergencyPortion = newLeftover * (surplusEmergencyAllocation / totalPct);
|
const emergencyPortion = leftover * (surplusEmergencyAllocation / totalPct);
|
||||||
const retirementPortion = newLeftover * (surplusRetirementAllocation / totalPct);
|
const retirementPortion = leftover * (surplusRetirementAllocation / totalPct);
|
||||||
|
|
||||||
currentEmergencySavings += emergencyPortion;
|
currentEmergencySavings += emergencyPortion;
|
||||||
currentRetirementSavings += retirementPortion;
|
currentRetirementSavings += retirementPortion;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 15. netSavings for the month (could be leftover minus contributions, etc.)
|
// netSavings for display
|
||||||
// But we already subtracted everything from netMonthlyIncome except what ended up surplus
|
|
||||||
const finalExpensesPaid = totalMonthlyExpenses + totalWantedContributions;
|
const finalExpensesPaid = totalMonthlyExpenses + totalWantedContributions;
|
||||||
const netSavings = netMonthlyIncome - finalExpensesPaid;
|
const netSavings = netMonthlyIncome - finalExpensesPaid;
|
||||||
|
|
||||||
// Record in the projection data
|
|
||||||
projectionData.push({
|
projectionData.push({
|
||||||
month: `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`,
|
month: `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`,
|
||||||
grossMonthlyIncome: Math.round(grossMonthlyIncome * 100) / 100,
|
grossMonthlyIncome: Math.round(grossMonthlyIncome * 100) / 100,
|
||||||
monthlyTax: Math.round(monthlyTax * 100) / 100,
|
monthlyFederalTax: Math.round(monthlyFederalTax * 100) / 100,
|
||||||
|
monthlyStateTax: Math.round(monthlyStateTax * 100) / 100,
|
||||||
|
combinedTax: Math.round(combinedTax * 100) / 100,
|
||||||
netMonthlyIncome: Math.round(netMonthlyIncome * 100) / 100,
|
netMonthlyIncome: Math.round(netMonthlyIncome * 100) / 100,
|
||||||
totalExpenses: Math.round(finalExpensesPaid * 100) / 100,
|
totalExpenses: Math.round(finalExpensesPaid * 100) / 100,
|
||||||
effectiveRetirementContribution: Math.round(effectiveRetirementContribution * 100) / 100,
|
effectiveRetirementContribution: Math.round(effectiveRetirementContribution * 100) / 100,
|
||||||
@ -370,11 +382,9 @@ export function simulateFinancialProjection(userProfile) {
|
|||||||
loanPaymentThisMonth: Math.round(thisMonthLoanPayment * 100) / 100
|
loanPaymentThisMonth: Math.round(thisMonthLoanPayment * 100) / 100
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update deferral flag for next iteration
|
|
||||||
wasInDeferral = (stillInCollege && loanDeferralUntilGraduation);
|
wasInDeferral = (stillInCollege && loanDeferralUntilGraduation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the final output
|
|
||||||
return {
|
return {
|
||||||
projectionData,
|
projectionData,
|
||||||
loanPaidOffMonth,
|
loanPaidOffMonth,
|
||||||
|
Loading…
Reference in New Issue
Block a user