/// <summary> /// Calculates Total Allowances /// </summary> /// <param name="role">Subject's role within the calculation</param> /// <param name="maritalStatus">Marital status</param> /// <param name="stateOfResidency">State of residency</param> /// <param name="numInCollege">Number in college</param> /// <param name="numInHousehold">Number in household</param> /// <param name="employablePersons">People capable of employment. Exact definition varies depending on /// role. If the role is "Parent", for example, <see cref="employablePersons"/> refers to the parents. /// If the role is "IndependentStudent", <see cref="employablePersons"/> refers to the student and /// spouse</param> /// <param name="totalIncome">Total income</param> /// <param name="incomeTaxPaid">U.S. income tax paid</param> /// <returns>"Total Allowances"</returns> public double CalculateTotalAllowances( EfcCalculationRole role, MaritalStatus maritalStatus, UnitedStatesStateOrTerritory stateOfResidency, int numInCollege, int numInHousehold, List <HouseholdMember> employablePersons, double totalIncome, double incomeTaxPaid) { double totalAllowances = 0; // Income Tax Paid totalAllowances += CalculateIncomeTaxAllowance(incomeTaxPaid); // State Tax totalAllowances += CalculateStateTaxAllowance(role, stateOfResidency, totalIncome); // Social Security Tax totalAllowances += employablePersons .Where(person => person.IsWorking) .Sum(person => CalculateSocialSecurityTaxAllowance(person.WorkIncome)); // Employment Expense Allowance if (role != EfcCalculationRole.DependentStudent) { totalAllowances += CalculateEmploymentExpenseAllowance(role, maritalStatus, employablePersons); } // Income Protection Allowance totalAllowances += CalculateIncomeProtectionAllowance(role, maritalStatus, numInCollege, numInHousehold); return(Math.Round(totalAllowances < 0 ? 0 : totalAllowances, MidpointRounding.AwayFromZero)); }
/// <summary> /// Calculates State and Other Tax allowance /// </summary> /// <param name="role">Subject's role within the calculation</param> /// <param name="stateOfResidency">State of residency</param> /// <param name="totalIncome">Total income</param> /// <returns>State and Other Tax allowance</returns> public double CalculateStateTaxAllowance( EfcCalculationRole role, UnitedStatesStateOrTerritory stateOfResidency, double totalIncome) { double stateTaxAllowance = 0; switch (role) { // For Parents and Independent Students With Dependents, use the "Parent" State Tax Allowance chart case EfcCalculationRole.Parent: case EfcCalculationRole.IndependentStudentWithDependents: if (totalIncome < _constants.StateTaxAllowanceIncomeThreshold) { stateTaxAllowance = (_constants.ParentStateTaxAllowancePercents[(int)stateOfResidency] * 0.01) * totalIncome; } else { stateTaxAllowance = ((_constants.ParentStateTaxAllowancePercents[(int)stateOfResidency] - 1) * 0.01) * totalIncome; } break; // For Dependent Students and Independent Students Without Dependents, use the "Student" State Tax Allowance chart case EfcCalculationRole.DependentStudent: case EfcCalculationRole.IndependentStudentWithoutDependents: stateTaxAllowance = (_constants.StudentStateTaxAllowancePercents[(int)stateOfResidency] * 0.01) * totalIncome; break; } return(Math.Round(stateTaxAllowance < 0 ? 0 : stateTaxAllowance, MidpointRounding.AwayFromZero)); }
/// <summary> /// Calculates "Employmement Expense Allowance" /// </summary> /// <param name="role">Subject's role within the calculation</param> /// <param name="maritalStatus">Marital status</param> /// <param name="employablePersons">People capable of employment. Exact definition varies depending on /// role. If the role is "Parent", for example, <see cref="employablePersons"/> refers to the parents. /// If the role is "IndependentStudent", <see cref="employablePersons"/> refers to the student and /// spouse</param> /// <returns>"Employment Expense Allowance"</returns> public double CalculateEmploymentExpenseAllowance( EfcCalculationRole role, MaritalStatus maritalStatus, List <HouseholdMember> employablePersons) { if (employablePersons == null || !employablePersons.Any() || (role == EfcCalculationRole.DependentStudent) || (role == EfcCalculationRole.IndependentStudentWithoutDependents && maritalStatus == MaritalStatus.SingleSeparatedDivorced)) { return(0); } IEnumerable <HouseholdMember> incomeEarners = employablePersons .Where(ep => ep.IsWorking) .OrderBy(ie => ie.WorkIncome); // Not all of the employable persons are working if (incomeEarners.Count() != employablePersons.Count()) { return(0); } // Use the lesser of the incomes for the calculation double lowestIncome = incomeEarners.First().WorkIncome; double adjustedLowestIncome = (lowestIncome * _constants.EmploymentExpensePercent); double employmentExpenseAllowance = adjustedLowestIncome > _constants.EmploymentExpenseMaximum ? _constants.EmploymentExpenseMaximum : adjustedLowestIncome; return(Math.Round(employmentExpenseAllowance < 0 ? 0 : employmentExpenseAllowance, MidpointRounding.AwayFromZero)); }
/// <summary> /// Calculates Total Allowances /// </summary> /// <param name="role">Subject's role within the calculation</param> /// <param name="maritalStatus">Marital status</param> /// <param name="stateOfResidency">State of residency</param> /// <param name="numInCollege">Number in college</param> /// <param name="numInHousehold">Number in household</param> /// <param name="employablePersons">People capable of employment. Exact definition varies depending on /// role. If the role is "Parent", for example, <see cref="employablePersons"/> refers to the parents. /// If the role is "IndependentStudent", <see cref="employablePersons"/> refers to the student and /// spouse</param> /// <param name="totalIncome">Total income</param> /// <param name="incomeTaxPaid">U.S. income tax paid</param> /// <returns>"Total Allowances"</returns> public double CalculateTotalAllowances( EfcCalculationRole role, MaritalStatus maritalStatus, UnitedStatesStateOrTerritory stateOfResidency, int numInCollege, int numInHousehold, List<HouseholdMember> employablePersons, double totalIncome, double incomeTaxPaid) { double totalAllowances = 0; // Income Tax Paid totalAllowances += CalculateIncomeTaxAllowance(incomeTaxPaid); // State Tax totalAllowances += CalculateStateTaxAllowance(role, stateOfResidency, totalIncome); // Social Security Tax totalAllowances += employablePersons .Where(person => person.IsWorking) .Sum(person => CalculateSocialSecurityTaxAllowance(person.WorkIncome)); // Employment Expense Allowance if (role != EfcCalculationRole.DependentStudent) { totalAllowances += CalculateEmploymentExpenseAllowance(role, maritalStatus, employablePersons); } // Income Protection Allowance totalAllowances += CalculateIncomeProtectionAllowance(role, maritalStatus, numInCollege, numInHousehold); return Math.Round(totalAllowances < 0 ? 0 : totalAllowances, MidpointRounding.AwayFromZero); }
/// <summary> /// Calculates "Employmement Expense Allowance" /// </summary> /// <param name="role">Subject's role within the calculation</param> /// <param name="maritalStatus">Marital status</param> /// <param name="employablePersons">People capable of employment. Exact definition varies depending on /// role. If the role is "Parent", for example, <see cref="employablePersons"/> refers to the parents. /// If the role is "IndependentStudent", <see cref="employablePersons"/> refers to the student and /// spouse</param> /// <returns>"Employment Expense Allowance"</returns> public double CalculateEmploymentExpenseAllowance( EfcCalculationRole role, MaritalStatus maritalStatus, List <HouseholdMember> employablePersons) { if (employablePersons == null || employablePersons.Count == 0 || (role == EfcCalculationRole.DependentStudent) || (role == EfcCalculationRole.IndependentStudentWithoutDependents && maritalStatus == MaritalStatus.SingleSeparatedDivorced)) { return(0); } // Create a list of working Household Members List <HouseholdMember> incomeEarners = new List <HouseholdMember>(); foreach (HouseholdMember person in employablePersons) { if (person.IsWorking) { incomeEarners.Add(person); } } // Not all of the employable persons are working if (incomeEarners.Count != employablePersons.Count) { return(0); } HouseholdMember lowestIncomeEarner = incomeEarners[0]; foreach (HouseholdMember person in incomeEarners) { if (person.WorkIncome < lowestIncomeEarner.WorkIncome) { lowestIncomeEarner = person; } } // Use the lesser of the incomes for the calculation double lowestIncome = lowestIncomeEarner.WorkIncome; double adjustedLowestIncome = (lowestIncome * _constants.EmploymentExpensePercent); double employmentExpenseAllowance = adjustedLowestIncome > _constants.EmploymentExpenseMaximum ? _constants.EmploymentExpenseMaximum : adjustedLowestIncome; return(Math.Round(employmentExpenseAllowance < 0 ? 0 : employmentExpenseAllowance, MidpointRounding.AwayFromZero)); }
/// <summary> /// Calculates Net Worth contribution /// </summary> /// <param name="role">Role of the subject within the calculation</param> /// <param name="cashSavingsCheckings">Cash, savings, and checkings value</param> /// <param name="investmentNetWorth">Net worth of investments</param> /// <param name="businessFarmNetWorth">Net worth of business and/or investment farm</param> /// <returns>Net Worth contribution</returns> public double CalculateNetWorth( EfcCalculationRole role, double cashSavingsCheckings, double investmentNetWorth, double businessFarmNetWorth) { double netWorth = 0; netWorth += CalculateCashSavingsCheckingsContribution(cashSavingsCheckings); netWorth += CalculateInvestmentNetWorthContribution(investmentNetWorth); netWorth += CalculateAdjustedBusinessFarmNetWorthContribution(role, businessFarmNetWorth); return(Math.Round(netWorth, MidpointRounding.AwayFromZero)); }
/// <summary> /// Calculates Available Income /// </summary> /// <param name="role">Role of the subject within the calculation</param> /// <param name="totalIncome">Total income</param> /// <param name="totalAllowances">Total allowances</param> /// <returns></returns> public double CalculateAvailableIncome(EfcCalculationRole role, double totalIncome, double totalAllowances) { double availableIncome = Math.Round(totalIncome - totalAllowances, MidpointRounding.AwayFromZero); // The available income for Dependent Students and Independent Students Without Depends is // multiplied by an assessment percent if (role == EfcCalculationRole.DependentStudent || role == EfcCalculationRole.IndependentStudentWithoutDependents) { return availableIncome < 0 ? 0 : Math.Round(availableIncome * _constants.AiAssessmentPercent, MidpointRounding.AwayFromZero); } return availableIncome; }
/// <summary> /// Calculates Contribution from Adjusted Available Income (AAI) /// </summary> /// <param name="role">Role of the subject within the calculation</param> /// <param name="adjustedAvailableIncome">Adjusted Available Income</param> /// <returns>"Contribution from AAI"</returns> public double CalculateContributionFromAai(EfcCalculationRole role, double adjustedAvailableIncome) { if (role == EfcCalculationRole.DependentStudent || role == EfcCalculationRole.IndependentStudentWithoutDependents) { return(Math.Round(adjustedAvailableIncome < 0 ? 0 : adjustedAvailableIncome, MidpointRounding.AwayFromZero)); } if (adjustedAvailableIncome < _constants.AaiContributionRanges[0]) { return(0); } int baseRange = 0; int index = 0; // Loop through AAIContributionRanges until adjustedAvailableIncome param is within range for (int i = 0; i < _constants.AaiContributionRanges.Length; i++) { index = i; // If at end of ranges, set baseAmount to maximum range if (i == _constants.AaiContributionRanges.Length - 1) { baseRange = _constants.AaiContributionRanges[i]; break; } // If adjustedAvailableIncome is within range if (adjustedAvailableIncome < _constants.AaiContributionRanges[i + 1]) { // If adjustedAvailableIncome is within first range, there is no baseAmount; // otherwise, assign standard baseAmount baseRange = (i == 0) ? 0 : _constants.AaiContributionRanges[i]; break; } } // Contribution From AAI = // (Base Amount for Range) // + (((Adjusted Available Income) - (Lowest Value of Range)) * (Percent for Range)) double contributionFromAai = _constants.AaiContributionBases[index] + ((adjustedAvailableIncome - baseRange) * (_constants.AaiContributionPercents[index] * 0.01)); return(Math.Round((contributionFromAai < 0) ? 0 : contributionFromAai, MidpointRounding.AwayFromZero)); }
/// <summary> /// Calculates the Adjusted Net Worth of Business/Farm contribution /// </summary> /// <param name="role">Role of the subject within the calculation</param> /// <param name="businessFarmNetWorth">Net worth of business and/or investment farm</param> /// <returns></returns> public double CalculateAdjustedBusinessFarmNetWorthContribution( EfcCalculationRole role, double businessFarmNetWorth) { if (role == EfcCalculationRole.DependentStudent) { return(Math.Round(businessFarmNetWorth < 0 ? 0 : businessFarmNetWorth, MidpointRounding.AwayFromZero)); } int baseRange = 0; int index = 0; int maxIndex = _constants.BusinessFarmNetWorthAdjustmentRanges.Length - 1; // Loop through BusinessFarmNetWorthAdjustmentContributionRanges until businessFarmNetWorth // param is within range for (int i = 0; i < _constants.BusinessFarmNetWorthAdjustmentRanges.Length; i++) { index = i; // If at end of ranges, set baseAmount to maximum range if (i == maxIndex) { baseRange = _constants.BusinessFarmNetWorthAdjustmentRanges[i]; break; } // If businessFarmNetWorth is within range if (businessFarmNetWorth < _constants.BusinessFarmNetWorthAdjustmentRanges[i + 1]) { // If businessFarmNetWorth is within first range, there is no baseAmount // Otherwise, assign standard baseAmount baseRange = (i == 0) ? 0 : _constants.BusinessFarmNetWorthAdjustmentRanges[i]; break; } } // Contribution From AAI = // (Base Amount for Range) // + (((Business Farm Net Worth) - (Lowest Value of Range)) * (Percent for Range)) double adjustedBusinessFarmNetWorth = _constants.BusinessFarmNetWorthAdjustmentBases[index] + ((businessFarmNetWorth - baseRange) * (_constants.BusinessFarmNetWorthAdjustmentPercents[index] * 0.01)); return(Math.Round((adjustedBusinessFarmNetWorth < 0) ? 0 : adjustedBusinessFarmNetWorth, MidpointRounding.AwayFromZero)); }
/// <summary> /// Calculates Contribution From Assets /// </summary> /// <param name="role">Role of the subject within the calculation</param> /// <param name="maritalStatus">Marital Status</param> /// <param name="age">Age</param> /// <param name="cashSavingsCheckings">Cash, savings, and checkings value</param> /// <param name="investmentNetWorth">Net worth of investments</param> /// <param name="businessFarmNetWorth">Net worth of business and/or investment farm</param> /// <returns>"Contribution From Assets"</returns> public double CalculateContributionFromAssets( EfcCalculationRole role, MaritalStatus maritalStatus, int age, double cashSavingsCheckings, double investmentNetWorth, double businessFarmNetWorth) { double contributionFromAssets = 0; if (role == EfcCalculationRole.DependentStudent) { contributionFromAssets += CalculateNetWorth(role, cashSavingsCheckings, investmentNetWorth, businessFarmNetWorth); } else { contributionFromAssets += CalculateDiscretionaryNetWorth(role, maritalStatus, age, cashSavingsCheckings, investmentNetWorth, businessFarmNetWorth); } double assetRate = 1; switch (role) { case EfcCalculationRole.Parent: assetRate = _constants.DependentParentAssetRate; break; case EfcCalculationRole.DependentStudent: assetRate = _constants.DependentStudentAssetRate; break; case EfcCalculationRole.IndependentStudentWithDependents: assetRate = _constants.IndependentWithDependentsAssetRate; break; case EfcCalculationRole.IndependentStudentWithoutDependents: assetRate = _constants.IndependentWithoutDependentsAssetRate; break; } contributionFromAssets *= assetRate; return(Math.Round(contributionFromAssets < 0 ? 0 : contributionFromAssets, MidpointRounding.AwayFromZero)); }
/// <summary> /// Calculates Contribution From Assets /// </summary> /// <param name="role">Role of the subject within the calculation</param> /// <param name="maritalStatus">Marital Status</param> /// <param name="age">Age</param> /// <param name="cashSavingsCheckings">Cash, savings, and checkings value</param> /// <param name="investmentNetWorth">Net worth of investments</param> /// <param name="businessFarmNetWorth">Net worth of business and/or investment farm</param> /// <returns>"Contribution From Assets"</returns> public double CalculateContributionFromAssets( EfcCalculationRole role, MaritalStatus maritalStatus, int age, double cashSavingsCheckings, double investmentNetWorth, double businessFarmNetWorth) { double contributionFromAssets = 0; if (role == EfcCalculationRole.DependentStudent) { contributionFromAssets += CalculateNetWorth(role, cashSavingsCheckings, investmentNetWorth, businessFarmNetWorth); } else { contributionFromAssets += CalculateDiscretionaryNetWorth(role, maritalStatus, age, cashSavingsCheckings, investmentNetWorth, businessFarmNetWorth); } double assetRate = 1; switch (role) { case EfcCalculationRole.Parent: assetRate = _constants.DependentParentAssetRate; break; case EfcCalculationRole.DependentStudent: assetRate = _constants.DependentStudentAssetRate; break; case EfcCalculationRole.IndependentStudentWithDependents: assetRate = _constants.IndependentWithDependentsAssetRate; break; case EfcCalculationRole.IndependentStudentWithoutDependents: assetRate = _constants.IndependentWithoutDependentsAssetRate; break; } contributionFromAssets *= assetRate; return Math.Round(contributionFromAssets < 0 ? 0 : contributionFromAssets, MidpointRounding.AwayFromZero); }
/// <summary> /// Calculates Discretionary Net Worth contribution /// </summary> /// <param name="role">Role of the subject within the calculation</param> /// <param name="maritalStatus">Marital Status</param> /// <param name="age">Age</param> /// <param name="cashSavingsCheckings">Cash, savings, and checkings value</param> /// <param name="investmentNetWorth">Net worth of investments</param> /// <param name="businessFarmNetWorth">Net worth of business and/or investment farm</param> /// <returns>"Discretionary Net Worth" contribution</returns> public double CalculateDiscretionaryNetWorth( EfcCalculationRole role, MaritalStatus maritalStatus, int age, double cashSavingsCheckings, double investmentNetWorth, double businessFarmNetWorth) { double discretionaryNetWorth = 0; discretionaryNetWorth += CalculateNetWorth(role, cashSavingsCheckings, investmentNetWorth, businessFarmNetWorth); discretionaryNetWorth -= CalculateAssetProtectionAllowance(maritalStatus, age); return(Math.Round(discretionaryNetWorth, MidpointRounding.AwayFromZero)); }
/// <summary> /// Calculates State and Other Tax allowance /// </summary> /// <param name="role">Subject's role within the calculation</param> /// <param name="stateOfResidency">State of residency</param> /// <param name="totalIncome">Total income</param> /// <returns>State and Other Tax allowance</returns> public double CalculateStateTaxAllowance( EfcCalculationRole role, UnitedStatesStateOrTerritory stateOfResidency, double totalIncome) { double stateTaxAllowance = 0; switch (role) { // For Parents and Independent Students With Dependents, use the "Parent" State Tax Allowance chart case EfcCalculationRole.Parent: case EfcCalculationRole.IndependentStudentWithDependents: if (totalIncome < _constants.StateTaxAllowanceIncomeThreshold) { stateTaxAllowance = (_constants.ParentStateTaxAllowancePercents[(int)stateOfResidency] * 0.01) * totalIncome; } else { stateTaxAllowance = ((_constants.ParentStateTaxAllowancePercents[(int)stateOfResidency] - 1) * 0.01) * totalIncome; } break; // For Dependent Students and Independent Students Without Dependents, use the "Student" State Tax Allowance chart case EfcCalculationRole.DependentStudent: case EfcCalculationRole.IndependentStudentWithoutDependents: stateTaxAllowance = (_constants.StudentStateTaxAllowancePercents[(int)stateOfResidency] * 0.01) * totalIncome; break; } return Math.Round(stateTaxAllowance < 0 ? 0 : stateTaxAllowance, MidpointRounding.AwayFromZero); }
/// <summary> /// Calculates "Employmement Expense Allowance" /// </summary> /// <param name="role">Subject's role within the calculation</param> /// <param name="maritalStatus">Marital status</param> /// <param name="employablePersons">People capable of employment. Exact definition varies depending on /// role. If the role is "Parent", for example, <see cref="employablePersons"/> refers to the parents. /// If the role is "IndependentStudent", <see cref="employablePersons"/> refers to the student and /// spouse</param> /// <returns>"Employment Expense Allowance"</returns> public double CalculateEmploymentExpenseAllowance( EfcCalculationRole role, MaritalStatus maritalStatus, List<HouseholdMember> employablePersons) { if (employablePersons == null || employablePersons.Count == 0 || (role == EfcCalculationRole.DependentStudent) || (role == EfcCalculationRole.IndependentStudentWithoutDependents && maritalStatus == MaritalStatus.SingleSeparatedDivorced)) { return 0; } // Create a list of working Household Members List<HouseholdMember> incomeEarners = new List<HouseholdMember>(); foreach (HouseholdMember person in employablePersons) { if (person.IsWorking) { incomeEarners.Add(person); } } // Not all of the employable persons are working if (incomeEarners.Count != employablePersons.Count) { return 0; } HouseholdMember lowestIncomeEarner = incomeEarners[0]; foreach (HouseholdMember person in incomeEarners) { if (person.WorkIncome < lowestIncomeEarner.WorkIncome) { lowestIncomeEarner = person; } } // Use the lesser of the incomes for the calculation double lowestIncome = lowestIncomeEarner.WorkIncome; double adjustedLowestIncome = (lowestIncome * _constants.EmploymentExpensePercent); double employmentExpenseAllowance = adjustedLowestIncome > _constants.EmploymentExpenseMaximum ? _constants.EmploymentExpenseMaximum : adjustedLowestIncome; return Math.Round(employmentExpenseAllowance < 0 ? 0 : employmentExpenseAllowance, MidpointRounding.AwayFromZero); }
/// <summary> /// Calculates Income Protection Allowance /// </summary> /// <param name="role">Subject's role within the calculation</param> /// <param name="maritalStatus">Marital status</param> /// <param name="numInCollege">Number in college</param> /// <param name="numInHousehold">Number in household</param> /// <returns>"Income Protection Allowance"</returns> public double CalculateIncomeProtectionAllowance( EfcCalculationRole role, MaritalStatus maritalStatus, int numInCollege, int numInHousehold) { if (numInCollege > numInHousehold || numInCollege <= 0 || numInHousehold <= 0) { return 0; } double incomeProtectionAllowance = 0; switch (role) { case EfcCalculationRole.IndependentStudentWithDependents: case EfcCalculationRole.Parent: // Determine the appropriate charts to use for Income Protection Allowance values int[,] incomeProtectionAllowances = (role == EfcCalculationRole.Parent) ? _constants.DependentParentIncomeProtectionAllowances : _constants.IndependentWithDependentsIncomeProtectionAllowances; int additionalStudentAllowance = (role == EfcCalculationRole.Parent) ? _constants.DependentAdditionalStudentAllowance : _constants.IndependentAdditionalStudentAllowance; int additionalFamilyAllowance = (role == EfcCalculationRole.Parent) ? _constants.DependentAdditionalFamilyAllowance : _constants.IndependentAdditionalFamilyAllowance; // If number of children in the household exceeds table range, add additionalFamilyAllowance // for each additional child int maxHouseholdCount = incomeProtectionAllowances.GetLength(0) - 1; int householdCount = numInHousehold; if (numInHousehold > maxHouseholdCount) { // Set number in household to maximum table range householdCount = maxHouseholdCount; incomeProtectionAllowance += (numInHousehold - maxHouseholdCount) * additionalFamilyAllowance; } // If number of children in college exceeds table range, add additionalStudentAllowance // for each additional child int maxCollegeCount = incomeProtectionAllowances.GetLength(1) - 1; int collegeCount = numInCollege; if (numInCollege > maxCollegeCount) { // Set number in college to maximum table range collegeCount = maxCollegeCount; incomeProtectionAllowance -= (numInCollege - maxCollegeCount) * additionalStudentAllowance; } // Add standard incomeProtectionAllowance value incomeProtectionAllowance += incomeProtectionAllowances[householdCount, collegeCount]; break; case EfcCalculationRole.IndependentStudentWithoutDependents: if (maritalStatus == MaritalStatus.SingleSeparatedDivorced) { incomeProtectionAllowance = _constants.SingleIndependentWithoutDependentsIncomeProtectionAllowance; } else { // If spouse is enrolled at least 1/2 time, then use the Income Protection Allowance value // for Single/Separated/Divorced incomeProtectionAllowance = (numInCollege > 1) ? _constants.SingleIndependentWithoutDependentsIncomeProtectionAllowance : _constants.MarriedIndependentWithoutDependentsIncomeProtectionAllowance; } break; case EfcCalculationRole.DependentStudent: incomeProtectionAllowance = _constants.DependentStudentIncomeProtectionAllowance; break; } return Math.Round(incomeProtectionAllowance < 0 ? 0 : incomeProtectionAllowance, MidpointRounding.AwayFromZero); }
/// <summary> /// Calculates student contribution (PC) and expected family contribution (EFC) for an independent student /// </summary> /// <param name="args">Parameters for the calculation</param> /// <returns>Student contribution (PC) and expected family contribution (EFC) for an independent student</returns> public EfcProfile GetIndependentEfcProfile(IndependentEfcCalculatorArguments args) { if (args.NumberInCollege <= 0 || args.MonthsOfEnrollment <= 0 || args.Student == null) { return(new EfcProfile(0, 0, 0, 0)); } EfcCalculationRole role = (args.HasDependents) ? EfcCalculationRole.IndependentStudentWithDependents : EfcCalculationRole.IndependentStudentWithoutDependents; double workIncome = 0; List <HouseholdMember> householdMembers = new List <HouseholdMember> { args.Student }; workIncome += args.Student.IsWorking ? args.Student.WorkIncome : 0; if (args.Spouse != null) { if (args.Spouse.IsWorking) { workIncome += args.Spouse.WorkIncome; } householdMembers.Add(args.Spouse); } double simpleIncome = (args.AreTaxFilers) ? args.AdjustedGrossIncome : workIncome; // Determine Auto Zero EFC eligibility if (args.IsQualifiedForSimplified && role == EfcCalculationRole.IndependentStudentWithDependents && simpleIncome <= _constants.AutoZeroEfcMax) { return(new EfcProfile(0, 0, 0, 0)); } // Student's Total Income double totalIncome = _incomeCalculator.CalculateTotalIncome( args.AdjustedGrossIncome, workIncome, args.AreTaxFilers, args.UntaxedIncomeAndBenefits, args.AdditionalFinancialInfo); // Student's Total Allowances double totalAllowances = _allowanceCalculator.CalculateTotalAllowances( role, args.MaritalStatus, args.StateOfResidency, args.NumberInCollege, args.NumberInHousehold, householdMembers, totalIncome, args.IncomeTaxPaid); // Student's Available Income (Contribution from Available Income) double availableIncome = _incomeCalculator.CalculateAvailableIncome(role, totalIncome, totalAllowances); // Determine Simplified EFC Equation Eligibility bool useSimplified = (args.IsQualifiedForSimplified && simpleIncome <= _constants.SimplifiedEfcMax); // Student's Contribution From Assets double assetContribution = 0; if (!useSimplified) { assetContribution = _assetContributionCalculator.CalculateContributionFromAssets( role, args.MaritalStatus, args.Age, args.CashSavingsCheckings, args.InvestmentNetWorth, args.BusinessFarmNetWorth); } // Student's Adjusted Available Income double adjustedAvailableIncome = availableIncome + assetContribution; // Student Contribution From AAI double studentContributionFromAai = _aaiContributionCalculator.CalculateContributionFromAai(role, adjustedAvailableIncome); // Student's Contribution double studentContribution = Math.Round(studentContributionFromAai / args.NumberInCollege, MidpointRounding.AwayFromZero); // Modify Student's Available Income based on months of enrollment if (args.MonthsOfEnrollment < DefaultMonthsOfEnrollment) { // LESS than default months of enrollment double monthlyContribution = Math.Round(studentContribution / DefaultMonthsOfEnrollment); studentContribution = monthlyContribution * args.MonthsOfEnrollment; } // For MORE than default months of enrollment, the standard contribution is used EfcProfile profile = new EfcProfile(studentContribution, 0, studentContribution, 0); return(profile); }
/// <summary> /// Calculates "Employmement Expense Allowance" /// </summary> /// <param name="role">Subject's role within the calculation</param> /// <param name="maritalStatus">Marital status</param> /// <param name="employablePersons">People capable of employment. Exact definition varies depending on /// role. If the role is "Parent", for example, <see cref="employablePersons"/> refers to the parents. /// If the role is "IndependentStudent", <see cref="employablePersons"/> refers to the student and /// spouse</param> /// <returns>"Employment Expense Allowance"</returns> public double CalculateEmploymentExpenseAllowance( EfcCalculationRole role, MaritalStatus maritalStatus, List<HouseholdMember> employablePersons) { if (employablePersons == null || !employablePersons.Any() || (role == EfcCalculationRole.DependentStudent) || (role == EfcCalculationRole.IndependentStudentWithoutDependents && maritalStatus == MaritalStatus.SingleSeparatedDivorced)) { return 0; } IEnumerable<HouseholdMember> incomeEarners = employablePersons .Where(ep => ep.IsWorking) .OrderBy(ie => ie.WorkIncome); // Not all of the employable persons are working if (incomeEarners.Count() != employablePersons.Count()) { return 0; } // Use the lesser of the incomes for the calculation double lowestIncome = incomeEarners.First().WorkIncome; double adjustedLowestIncome = (lowestIncome * _constants.EmploymentExpensePercent); double employmentExpenseAllowance = adjustedLowestIncome > _constants.EmploymentExpenseMaximum ? _constants.EmploymentExpenseMaximum : adjustedLowestIncome; return Math.Round(employmentExpenseAllowance < 0 ? 0 : employmentExpenseAllowance, MidpointRounding.AwayFromZero); }
/// <summary> /// Calculates Net Worth contribution /// </summary> /// <param name="role">Role of the subject within the calculation</param> /// <param name="cashSavingsCheckings">Cash, savings, and checkings value</param> /// <param name="investmentNetWorth">Net worth of investments</param> /// <param name="businessFarmNetWorth">Net worth of business and/or investment farm</param> /// <returns>Net Worth contribution</returns> public double CalculateNetWorth( EfcCalculationRole role, double cashSavingsCheckings, double investmentNetWorth, double businessFarmNetWorth) { double netWorth = 0; netWorth += CalculateCashSavingsCheckingsContribution(cashSavingsCheckings); netWorth += CalculateInvestmentNetWorthContribution(investmentNetWorth); netWorth += CalculateAdjustedBusinessFarmNetWorthContribution(role, businessFarmNetWorth); return Math.Round(netWorth, MidpointRounding.AwayFromZero); }
/// <summary> /// Calculates the Adjusted Net Worth of Business/Farm contribution /// </summary> /// <param name="role">Role of the subject within the calculation</param> /// <param name="businessFarmNetWorth">Net worth of business and/or investment farm</param> /// <returns></returns> public double CalculateAdjustedBusinessFarmNetWorthContribution( EfcCalculationRole role, double businessFarmNetWorth) { if (role == EfcCalculationRole.DependentStudent) { return Math.Round(businessFarmNetWorth < 0 ? 0 : businessFarmNetWorth, MidpointRounding.AwayFromZero); } int baseRange = 0; int index = 0; int maxIndex = _constants.BusinessFarmNetWorthAdjustmentRanges.Length - 1; // Loop through BusinessFarmNetWorthAdjustmentContributionRanges until businessFarmNetWorth // param is within range for (int i = 0; i < _constants.BusinessFarmNetWorthAdjustmentRanges.Length; i++) { index = i; // If at end of ranges, set baseAmount to maximum range if (i == maxIndex) { baseRange = _constants.BusinessFarmNetWorthAdjustmentRanges[i]; break; } // If businessFarmNetWorth is within range if (businessFarmNetWorth < _constants.BusinessFarmNetWorthAdjustmentRanges[i + 1]) { // If businessFarmNetWorth is within first range, there is no baseAmount // Otherwise, assign standard baseAmount baseRange = (i == 0) ? 0 : _constants.BusinessFarmNetWorthAdjustmentRanges[i]; break; } } // Contribution From AAI = // (Base Amount for Range) // + (((Business Farm Net Worth) - (Lowest Value of Range)) * (Percent for Range)) double adjustedBusinessFarmNetWorth = _constants.BusinessFarmNetWorthAdjustmentBases[index] + ((businessFarmNetWorth - baseRange) * (_constants.BusinessFarmNetWorthAdjustmentPercents[index] * 0.01)); return Math.Round((adjustedBusinessFarmNetWorth < 0) ? 0 : adjustedBusinessFarmNetWorth, MidpointRounding.AwayFromZero); }
/// <summary> /// Calculates Income Protection Allowance /// </summary> /// <param name="role">Subject's role within the calculation</param> /// <param name="maritalStatus">Marital status</param> /// <param name="numInCollege">Number in college</param> /// <param name="numInHousehold">Number in household</param> /// <returns>"Income Protection Allowance"</returns> public double CalculateIncomeProtectionAllowance( EfcCalculationRole role, MaritalStatus maritalStatus, int numInCollege, int numInHousehold) { if (numInCollege > numInHousehold || numInCollege <= 0 || numInHousehold <= 0) { return(0); } double incomeProtectionAllowance = 0; switch (role) { case EfcCalculationRole.IndependentStudentWithDependents: case EfcCalculationRole.Parent: // Determine the appropriate charts to use for Income Protection Allowance values int[,] incomeProtectionAllowances = (role == EfcCalculationRole.Parent) ? _constants.DependentParentIncomeProtectionAllowances : _constants.IndependentWithDependentsIncomeProtectionAllowances; int additionalStudentAllowance = (role == EfcCalculationRole.Parent) ? _constants.DependentAdditionalStudentAllowance : _constants.IndependentAdditionalStudentAllowance; int additionalFamilyAllowance = (role == EfcCalculationRole.Parent) ? _constants.DependentAdditionalFamilyAllowance : _constants.IndependentAdditionalFamilyAllowance; // If number of children in the household exceeds table range, add additionalFamilyAllowance // for each additional child int maxHouseholdCount = incomeProtectionAllowances.GetLength(0) - 1; int householdCount = numInHousehold; if (numInHousehold > maxHouseholdCount) { // Set number in household to maximum table range householdCount = maxHouseholdCount; incomeProtectionAllowance += (numInHousehold - maxHouseholdCount) * additionalFamilyAllowance; } // If number of children in college exceeds table range, add additionalStudentAllowance // for each additional child int maxCollegeCount = incomeProtectionAllowances.GetLength(1) - 1; int collegeCount = numInCollege; if (numInCollege > maxCollegeCount) { // Set number in college to maximum table range collegeCount = maxCollegeCount; incomeProtectionAllowance -= (numInCollege - maxCollegeCount) * additionalStudentAllowance; } // Add standard incomeProtectionAllowance value incomeProtectionAllowance += incomeProtectionAllowances[householdCount, collegeCount]; break; case EfcCalculationRole.IndependentStudentWithoutDependents: if (maritalStatus == MaritalStatus.SingleSeparatedDivorced) { incomeProtectionAllowance = _constants.SingleIndependentWithoutDependentsIncomeProtectionAllowance; } else { // If spouse is enrolled at least 1/2 time, then use the Income Protection Allowance value // for Single/Separated/Divorced incomeProtectionAllowance = (numInCollege > 1) ? _constants.SingleIndependentWithoutDependentsIncomeProtectionAllowance : _constants.MarriedIndependentWithoutDependentsIncomeProtectionAllowance; } break; case EfcCalculationRole.DependentStudent: incomeProtectionAllowance = _constants.DependentStudentIncomeProtectionAllowance; break; } return(Math.Round(incomeProtectionAllowance < 0 ? 0 : incomeProtectionAllowance, MidpointRounding.AwayFromZero)); }
/// <summary> /// Calculates Discretionary Net Worth contribution /// </summary> /// <param name="role">Role of the subject within the calculation</param> /// <param name="maritalStatus">Marital Status</param> /// <param name="age">Age</param> /// <param name="cashSavingsCheckings">Cash, savings, and checkings value</param> /// <param name="investmentNetWorth">Net worth of investments</param> /// <param name="businessFarmNetWorth">Net worth of business and/or investment farm</param> /// <returns>"Discretionary Net Worth" contribution</returns> public double CalculateDiscretionaryNetWorth( EfcCalculationRole role, MaritalStatus maritalStatus, int age, double cashSavingsCheckings, double investmentNetWorth, double businessFarmNetWorth) { double discretionaryNetWorth = 0; discretionaryNetWorth += CalculateNetWorth(role, cashSavingsCheckings, investmentNetWorth, businessFarmNetWorth); discretionaryNetWorth -= CalculateAssetProtectionAllowance(maritalStatus, age); return Math.Round(discretionaryNetWorth, MidpointRounding.AwayFromZero); }