Last active
August 6, 2024 19:52
-
-
Save derikwhittaker/5f8ff0e0502c7e7a90ef1061e3d3082a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| public class Earning | |
| { | |
| public string Code { get; set; } | |
| public string Type { get; set; } | |
| public decimal Hours { get; set; } | |
| public decimal Rate { get; set; } | |
| public bool IsTaxable { get; set; } | |
| } | |
| public abstract class Deduction | |
| { | |
| public string Code { get; set; } | |
| public string Type { get; set; } | |
| public int Priority { get; set; } | |
| public abstract decimal CalculateAmount(decimal taxableEarnings, decimal preTaxDeductions, decimal taxes); | |
| } | |
| public class PercentageDeduction : Deduction | |
| { | |
| public decimal Value { get; set; } | |
| public bool IsPreTax { get; set; } | |
| public override decimal CalculateAmount(decimal taxableEarnings, decimal preTaxDeductions, decimal taxes) | |
| { | |
| if (IsPreTax) | |
| { | |
| return taxableEarnings * (Value / 100); | |
| } | |
| else | |
| { | |
| return (taxableEarnings - preTaxDeductions - taxes) * (Value / 100); | |
| } | |
| } | |
| } | |
| public class FlatDeduction : Deduction | |
| { | |
| public decimal Value { get; set; } | |
| public bool IsPreTax { get; set; } | |
| public override decimal CalculateAmount(decimal taxableEarnings, decimal preTaxDeductions, decimal taxes) | |
| { | |
| if (IsPreTax) | |
| { | |
| return Value; | |
| } | |
| else | |
| { | |
| return Value; | |
| } | |
| } | |
| } | |
| public abstract class Tax | |
| { | |
| public string Code { get; set; } | |
| public string Type { get; set; } | |
| public int Priority { get; set; } | |
| public abstract decimal CalculateAmount(decimal taxableEarnings, decimal preTaxDeductions); | |
| } | |
| public class PercentageTax : Tax | |
| { | |
| public decimal Value { get; set; } | |
| public override decimal CalculateAmount(decimal taxableEarnings, decimal preTaxDeductions) | |
| { | |
| return (taxableEarnings - preTaxDeductions) * (Value / 100); | |
| } | |
| } | |
| public class CappedPercentageTax : Tax | |
| { | |
| public decimal Value { get; set; } | |
| public decimal Cap { get; set; } | |
| public override decimal CalculateAmount(decimal taxableEarnings, decimal preTaxDeductions) | |
| { | |
| decimal taxAmount = (taxableEarnings - preTaxDeductions) * (Value / 100); | |
| return Math.Min(taxAmount, Cap); | |
| } | |
| } | |
| public class PayrollCalculator | |
| { | |
| public decimal CalculateNetPay(List<Earning> earnings, List<Deduction> deductions, List<Tax> taxes) | |
| { | |
| decimal grossPay = 0; | |
| decimal taxableEarnings = 0; | |
| decimal preTaxDeductions = 0; | |
| decimal taxesAmount = 0; | |
| decimal postTaxDeductions = 0; | |
| decimal nonTaxableEarnings = 0; | |
| var withheldAmounts = new List<dynamic>(); | |
| // Calculate earnings | |
| foreach (var earning in earnings) | |
| { | |
| if (earning.Type == "hourly") | |
| { | |
| decimal earningsAmount = earning.Hours * earning.Rate; | |
| grossPay += earningsAmount; | |
| if (earning.IsTaxable) | |
| { | |
| taxableEarnings += earningsAmount; | |
| } | |
| else | |
| { | |
| nonTaxableEarnings += earningsAmount; | |
| } | |
| } | |
| else if (earning.Type == "salary") | |
| { | |
| grossPay += earning.Rate; | |
| if (earning.IsTaxable) | |
| { | |
| taxableEarnings += earning.Rate; | |
| } | |
| else | |
| { | |
| nonTaxableEarnings += earning.Rate; | |
| } | |
| } | |
| } | |
| // Calculate pre-tax deductions | |
| foreach (var deduction in deductions) | |
| { | |
| if (deduction is PercentageDeduction percentageDeduction && percentageDeduction.IsPreTax) | |
| { | |
| decimal deductionAmount = percentageDeduction.CalculateAmount(taxableEarnings, preTaxDeductions, taxesAmount); | |
| preTaxDeductions += deductionAmount; | |
| withheldAmounts.Add(new { code = deduction.Code, amount = deductionAmount, deficit = 0 }); | |
| } | |
| else if (deduction is FlatDeduction flatDeduction && flatDeduction.IsPreTax) | |
| { | |
| preTaxDeductions += flatDeduction.Value; | |
| withheldAmounts.Add(new { code = deduction.Code, amount = flatDeduction.Value, deficit = 0 }); | |
| } | |
| } | |
| // Calculate taxes | |
| foreach (var tax in taxes) | |
| { | |
| if (tax is PercentageTax percentageTax) | |
| { | |
| decimal taxAmount = percentageTax.CalculateAmount(taxableEarnings, preTaxDeductions); | |
| taxesAmount += taxAmount; | |
| withheldAmounts.Add(new { code = tax.Code, amount = taxAmount, deficit = 0 }); | |
| } | |
| else if (tax is CappedPercentageTax cappedPercentageTax) | |
| { | |
| decimal taxAmount = cappedPercentageTax.CalculateAmount(taxableEarnings, preTaxDeductions); | |
| taxesAmount += taxAmount; | |
| decimal deficit = cappedPercentageTax.CalculateAmount(taxableEarnings, preTaxDeductions) - taxAmount; | |
| withheldAmounts.Add(new { code = tax.Code, amount = taxAmount, deficit = deficit }); | |
| } | |
| } | |
| // Calculate post-tax deductions | |
| foreach (var deduction in deductions) | |
| { | |
| if (deduction is PercentageDeduction percentageDeduction && !percentageDeduction.IsPreTax) | |
| { | |
| decimal deductionAmount = percentageDeduction.CalculateAmount(taxableEarnings, preTaxDeductions, taxesAmount); | |
| postTaxDeductions += deductionAmount; | |
| withheldAmounts.Add(new { code = deduction.Code, amount = deductionAmount, deficit = 0 }); | |
| } | |
| else if (deduction is FlatDeduction flatDeduction && !flatDeduction.IsPreTax) | |
| { | |
| postTaxDeductions += flatDeduction.Value; | |
| withheldAmounts.Add(new { code = deduction.Code, amount = flatDeduction.Value, deficit = 0 }); | |
| } | |
| } | |
| // Calculate net pay | |
| decimal netPay = taxableEarnings - preTaxDeductions - taxesAmount - postTaxDeductions + nonTaxableEarnings; | |
| return netPay; | |
| } | |
| } | |
| public class Program | |
| { | |
| public static void Main() | |
| { | |
| // Sample input object | |
| var input = new | |
| { | |
| earnings = new List<Earning> | |
| { | |
| new Earning { Code = "overtime", Type = "hourly", Hours = 20, Rate = 15, IsTaxable = true }, | |
| new Earning { Code = "regular", Type = "hourly", Hours = 20, Rate = 13, IsTaxable = false }, | |
| new Earning { Code = "bonus", Type = "salary", Rate = 1500, IsTaxable = true } | |
| }, | |
| deductions = new List<Deduction> | |
| { | |
| new PercentageDeduction { Code = "401k", Type = "percentage", Priority = 1, Value = 10, IsPreTax = false }, | |
| new FlatDeduction { Code = "healthInsurance", Type = "flat", Priority = 2, Value = 20, IsPreTax = true } | |
| }, | |
| taxes = new List<Tax> | |
| { | |
| new PercentageTax { Code = "federalIncome", Type = "percentage", Priority = 1, Value = 10 }, | |
| new CappedPercentageTax { Code = "fica", Type = "cappedPercentage", Priority = 2, Value = 10, Cap = 50 } | |
| } | |
| }; | |
| var calculator = new PayrollCalculator(); | |
| decimal netPay = calculator.CalculateNetPay(input.earnings, input.deductions, input.taxes); | |
| // Output results | |
| Console.WriteLine("Net Pay to Employee: $" + netPay); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| public class Program | |
| { | |
| public static void Main() | |
| { | |
| // Sample input object | |
| var input = new | |
| { | |
| earnings = new List<dynamic> | |
| { | |
| new { code = "overtime", type = "hourly", hours = 20, rate = 15, isTaxable = true }, | |
| new { code = "regular", type = "hourly", hours = 20, rate = 13, isTaxable = false }, | |
| new { code = "bonus", type = "salary", amount = 1500, isTaxable = true } | |
| }, | |
| deductions = new List<dynamic> | |
| { | |
| new { code = "401k", type = "percentage", priority = 1, value = 10, isPreTax = false }, | |
| new { code = "healthInsurance", type = "flat", priority = 2, value = 20, isPreTax = true } | |
| }, | |
| taxes = new List<dynamic> | |
| { | |
| new { code = "federalIncome", type = "percentage", priority = 1, value = 10 }, | |
| new { code = "fica", type = "cappedPercentage", priority = 2, value = 10, cap = 50 } | |
| } | |
| }; | |
| // Calculate net pay | |
| var netPay = CalculateNetPay(input); | |
| // Output results | |
| Console.WriteLine("Gross Pay: $" + netPay.grossPay); | |
| Console.WriteLine("Net Pay to Employee: $" + netPay.netPay); | |
| Console.WriteLine("Amounts Withheld for Deductions and Taxes:"); | |
| foreach (var item in netPay.withheldAmounts) | |
| { | |
| Console.WriteLine(item.code + ": $" + item.amount + (item.deficit > 0 ? " (Deficit: $" + item.deficit + ")" : "")); | |
| } | |
| } | |
| public static dynamic CalculateNetPay(dynamic input) | |
| { | |
| decimal grossPay = 0; | |
| decimal taxableEarnings = 0; | |
| decimal preTaxDeductions = 0; | |
| decimal taxes = 0; | |
| decimal postTaxDeductions = 0; | |
| decimal nonTaxableEarnings = 0; | |
| var withheldAmounts = new List<dynamic>(); | |
| // Calculate earnings | |
| foreach (var earning in input.earnings) | |
| { | |
| if (earning.type == "hourly") | |
| { | |
| decimal earnings = earning.hours * earning.rate; | |
| grossPay += earnings; | |
| if (earning.isTaxable) | |
| { | |
| taxableEarnings += earnings; | |
| } | |
| else | |
| { | |
| nonTaxableEarnings += earnings; | |
| } | |
| } | |
| else if (earning.type == "salary") | |
| { | |
| grossPay += earning.amount; | |
| if (earning.isTaxable) | |
| { | |
| taxableEarnings += earning.amount; | |
| } | |
| else | |
| { | |
| nonTaxableEarnings += earning.amount; | |
| } | |
| } | |
| } | |
| // Calculate pre-tax deductions | |
| foreach (var deduction in input.deductions) | |
| { | |
| if (deduction.isPreTax) | |
| { | |
| if (deduction.type == "percentage") | |
| { | |
| decimal deductionAmount = taxableEarnings * (deduction.value / 100); | |
| preTaxDeductions += deductionAmount; | |
| withheldAmounts.Add(new { code = deduction.code, amount = deductionAmount, deficit = 0 }); | |
| } | |
| else if (deduction.type == "flat") | |
| { | |
| preTaxDeductions += deduction.value; | |
| withheldAmounts.Add(new { code = deduction.code, amount = deduction.value, deficit = 0 }); | |
| } | |
| } | |
| } | |
| // Calculate taxes | |
| foreach (var tax in input.taxes) | |
| { | |
| if (tax.type == "percentage") | |
| { | |
| decimal taxAmount = (taxableEarnings - preTaxDeductions) * (tax.value / 100); | |
| taxes += taxAmount; | |
| withheldAmounts.Add(new { code = tax.code, amount = taxAmount, deficit = 0 }); | |
| } | |
| else if (tax.type == "cappedPercentage") | |
| { | |
| decimal taxAmount = (taxableEarnings - preTaxDeductions) * (tax.value / 100); | |
| decimal cappedTaxAmount = Math.Min(taxAmount, tax.cap); | |
| taxes += cappedTaxAmount; | |
| decimal deficit = taxAmount - cappedTaxAmount; | |
| withheldAmounts.Add(new { code = tax.code, amount = cappedTaxAmount, deficit = deficit }); | |
| } | |
| } | |
| // Calculate post-tax deductions | |
| foreach (var deduction in input.deductions) | |
| { | |
| if (!deduction.isPreTax) | |
| { | |
| if (deduction.type == "percentage") | |
| { | |
| decimal deductionAmount = (taxableEarnings - preTaxDeductions - taxes) * (deduction.value / 100); | |
| postTaxDeductions += deductionAmount; | |
| withheldAmounts.Add(new { code = deduction.code, amount = deductionAmount, deficit = 0 }); | |
| } | |
| else if (deduction.type == "flat") | |
| { | |
| postTaxDeductions += deduction.value; | |
| withheldAmounts.Add(new { code = deduction.code, amount = deduction.value, deficit = 0 }); | |
| } | |
| } | |
| } | |
| // Calculate net pay | |
| decimal netPay = taxableEarnings - preTaxDeductions - taxes - postTaxDeductions + nonTaxableEarnings; | |
| return new { grossPay, netPay, withheldAmounts }; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| public class Earning | |
| { | |
| public string Code { get; set; } | |
| public string Type { get; set; } | |
| public decimal Hours { get; set; } | |
| public decimal Rate { get; set; } | |
| public bool IsTaxable { get; set; } | |
| } | |
| public abstract class Deduction | |
| { | |
| public string Code { get; set; } | |
| public string Type { get; set; } | |
| public int Priority { get; set; } | |
| public abstract decimal Calculate(decimal taxableEarnings, decimal preTaxDeductions, decimal taxes); | |
| } | |
| public class PercentageDeduction : Deduction | |
| { | |
| public decimal Value { get; set; } | |
| public bool IsPreTax { get; set; } | |
| public override decimal Calculate(decimal taxableEarnings, decimal preTaxDeductions, decimal taxes) => | |
| IsPreTax ? taxableEarnings * (Value / 100) : (taxableEarnings - preTaxDeductions - taxes) * (Value / 100); | |
| } | |
| public class FlatDeduction : Deduction | |
| { | |
| public decimal Value { get; set; } | |
| public bool IsPreTax { get; set; } | |
| public override decimal Calculate(decimal taxableEarnings, decimal preTaxDeductions, decimal taxes) => | |
| IsPreTax ? Value : Value; | |
| } | |
| public abstract class Tax | |
| { | |
| public string Code { get; set; } | |
| public string Type { get; set; } | |
| public int Priority { get; set; } | |
| public abstract decimal Calculate(decimal taxableEarnings, decimal preTaxDeductions); | |
| } | |
| public class PercentageTax : Tax | |
| { | |
| public decimal Value { get; set; } | |
| public override decimal Calculate(decimal taxableEarnings, decimal preTaxDeductions) => | |
| (taxableEarnings - preTaxDeductions) * (Value / 100); | |
| } | |
| public class CappedPercentageTax : Tax | |
| { | |
| public decimal Value { get; set; } | |
| public decimal Cap { get; set; } | |
| public override decimal Calculate(decimal taxableEarnings, decimal preTaxDeductions) => | |
| Math.Min((taxableEarnings - preTaxDeductions) * (Value / 100), Cap); | |
| } | |
| public class PayrollCalculator | |
| { | |
| public decimal CalculateNetPay(List<Earning> earnings, List<Deduction> deductions, List<Tax> taxes) => | |
| earnings.Sum(e => e.Type == "hourly" ? e.Hours * e.Rate : e.Rate) - | |
| deductions.Sum(d => d.Calculate( | |
| earnings.Sum(e => e.IsTaxable ? (e.Type == "hourly" ? e.Hours * e.Rate : e.Rate) : 0), | |
| deductions.Where(dd => dd.Priority < d.Priority).Sum(dd => dd.Calculate( | |
| earnings.Sum(e => e.IsTaxable ? (e.Type == "hourly" ? e.Hours * e.Rate : e.Rate) : 0), | |
| deductions.Where(ddd => ddd.Priority < dd.Priority).Sum(ddd => ddd.Calculate( | |
| earnings.Sum(e => e.IsTaxable ? (e.Type == "hourly" ? e.Hours * e.Rate : e.Rate) : 0), | |
| deductions.Where(dddd => dddd.Priority < ddd.Priority).Sum(dddd => dddd.Calculate( | |
| earnings.Sum(e => e.IsTaxable ? (e.Type == "hourly" ? e.Hours * e.Rate : e.Rate) : 0), | |
| taxes.Where(t => t.Priority < d.Priority).Sum(t => t.Calculate( | |
| earnings.Sum(e => e.IsTaxable ? (e.Type == "hourly" ? e.Hours * e.Rate : e.Rate) : 0), | |
| deductions.Where(dd => dd.Priority < t.Priority).Sum(dd => dd.Calculate( | |
| earnings.Sum(e => e.IsTaxable ? (e.Type == "hourly" ? e.Hours * e.Rate : e.Rate) : 0), | |
| deductions.Where(ddd => ddd.Priority < dd.Priority).Sum(ddd => ddd.Calculate( | |
| earnings.Sum(e => e.IsTaxable ? (e.Type == "hourly" ? e.Hours * e.Rate : e.Rate) : 0), | |
| deductions.Where(dddd => dddd.Priority < ddd.Priority).Sum(dddd => dddd.Calculate( | |
| earnings.Sum(e => e.IsTaxable ? (e.Type == "hourly" ? e.Hours * e.Rate : e.Rate) : 0), | |
| 0)))))))))))))) + | |
| earnings.Sum(e => e.IsTaxable ? (e.Type == "hourly" ? e.Hours * e.Rate : e.Rate) : 0); | |
| } | |
| public class Program | |
| { | |
| public static void Main() | |
| { | |
| var input = new | |
| { | |
| earnings = new List<Earning> | |
| { | |
| new Earning { Code = "overtime", Type = "hourly", Hours = 20, Rate = 15, IsTaxable = true }, | |
| new Earning { Code = "regular", Type = "hourly", Hours = 20, Rate = 13, IsTaxable = false }, | |
| new Earning { Code = "bonus", Type = "salary", Rate = 1500, IsTaxable = true } | |
| }, | |
| deductions = new List<Deduction> | |
| { | |
| new PercentageDeduction { Code = "401k", Type = "percentage", Priority = 1, Value = 10, IsPreTax = false }, | |
| new FlatDeduction { Code = "healthInsurance", Type = "flat", Priority = 2, Value = 20, IsPreTax = true } | |
| }, | |
| taxes = new List<Tax> | |
| { | |
| new PercentageTax { Code = "federalIncome", Type = "percentage", Priority = 1, Value = 10 }, | |
| new CappedPercentageTax { Code = "fica", Type = "cappedPercentage", Priority = 2, Value = 10, Cap = 50 } | |
| } | |
| }; | |
| var calculator = new PayrollCalculator(); | |
| decimal netPay = calculator.CalculateNetPay(input.earnings, input.deductions, input.taxes); | |
| Console.WriteLine("Net Pay to Employee: $" + netPay); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment