Calculate commission with amount threshold - c#

I have different schemas for different kind of commission over the sales. From 0 to 10.000€ its pay a commission of 2%, from 10.001 to 20.000 the commission is 2.5%, 20.001 to 30.000 is payee a commission of 3% and so until the commission is 5% or more. The threshold amount and the commission is taken from the database in a list. The problem is that I have to take on account the sales since the beginning of the year to achieve the given threshold but only calculated the commission for the sale of the current month. For instance if the sales in a given month is 30.000 and the cumulated sales from the beginning of the year is 8.000, the calculation is: 2.000 at 2%, 10.000 at 2.5 %, 10.000 at 3% and 8.000 at 3.5% with a result of 870. This is the code that I have but don’t work fine. Any help would be appreciated. Thanks in advance.
foreach (var bound in fxCollection)
{
if (antAmount < bound.FinalAmount)
{
if (antAmount >= bound.InitialAmount && antAmount <= bound.FinalAmount)
{
if (totalAmount > bound.FinalAmount)
{
totalAmountCardSchema = totalPeriod - (bound.FinalAmount.Value - antAmount);
totalCommission += (bound.FinalAmount.Value - antAmount) * (bound.Commission / 100);
}
else
{
totalCommission += totalPeriod * (bound.Commission / 100);
totalCommission = 0;
}
}
else
{
if ((bound.FinalAmount - bound.InitialAmount) < totalAmountCardSchema)
{
if (index == count) //last loop
{
totalCommission += totalAmountCardSchema * (bound.Commission / 100);
totalAmountCardSchema = 0;
}
else
{
totalCommission += (bound.FinalAmount.Value - bound.InitialAmount.Value) * (bound.Commission / 100);
totalAmountCardSchema = totalAmountCardSchema - (bound.FinalAmount.Value - bound.InitialAmount.Value);
}
}
else if (totalAmountCardSchema > 0)
{
totalCommission += totalAmountCardSchema * (bound.Commission / 100);
totalAmountCardSchema = 0;
}
}
}
index++;
var valueInvoiceLine = totalCommission;
To clarify:
Yes, this is the point. In the example is fine. To clarify, the sales from 1th of January until 31th May was 8.000 and the sales in one month was 30.000. I put this example because I want loop in several band for calculate the commission of the month but for achieve the first band to calculate the initial band in this month I have to add the sales since the first day of the year. In the example the first band is from 0 to 10.000 but I have to add the sales for the first day of the year (8.000) and then of the sales of the month (30.000), I have to take only 2.000 in the first band, in the second band I have to take 10.000, in the third band I have to take another 10.000 and in the fourth band I have to take the rest (8.000). Sorry if it’s not very clear. I hope that you understand. Thanks you so much.

Try something like this
decimal totalAmount = 35;
decimal commission = 0.0M;
decimal commissionAmount = 0.0M;
Dictionary<decimal,decimal> commissions = new Dictionary<decimal,decimal>() {
{ 0, .02M}, ///2%
{ 10, .005M}, //2.5%
{ 20, .005M}, //3.0%
{ 30, .005M}, //3.5%
{ 40, .005M}, //4.0%
{ 50, .005M}, //4.5%
{ 60, .005M}, //5.0%
};
foreach (decimal key in commissions.Keys)
{
if (totalAmount > key)
{
commissionAmount = totalAmount - key;
}
else
{
commissionAmount = totalAmount - key < 0 ? 0 : totalAmount - key;
}
commission += commissionAmount * commissions[key];
}

Related

Is there a way for me to output a variable that is initialized in a loop

In my problem, I am trying to output a Sales Summary for an employees commission on sales. One of the columns needed is "Sold" which requires you to get the amount of products sold for that specific product. The problem I am having is that numberSold variable is initialized in the While loop and it looks like I am not able to use it because of that. What is the best option for being able to be able to use it. Any other tips on how to make my CommEarnings cleaner would also be appreciated as I feel like there is a better way to do it compared to how I am getting it.
decimal grossSales = 0; // total gross sales
decimal earnings; // earnings made from sales
int product = 0; // the product number
int numberSold; // number sold of a given product
decimal commission1 = .09M;
decimal commission2 = .0925M;
decimal commission3 = .0701M;
decimal commission4 = .095M;
decimal commission5 = .10M;
decimal commission6 = .083M;
decimal basePay = 250.00M;
decimal product1CommEarnings = 0.00M;
decimal product2CommEarnings = 0.00M;
decimal product3CommEarnings = 0.00M;
decimal product4CommEarnings = 0.00M;
decimal product5CommEarnings = 0.00M;
decimal product6CommEarnings = 0.00M;
while ( product < 6 )
{
++product;
// prompt for and read number of the product sold from user
Console.Write( "Enter number sold of product # {0} -> ",
product );
numberSold = Convert.ToInt32( Console.ReadLine() );
// determine gross of each individual product and add to total
if (product == 1)
{
grossSales += numberSold * 239.99M;
product1CommEarnings = Math.Round(commission1 * numberSold * 239.99M, 2);
}
else if (product == 2)
{
grossSales += numberSold * 129.75M;
product2CommEarnings = Math.Round(commission2 * numberSold * 129.75M, 2);
}
else if (product == 3)
{
grossSales += numberSold * 99.95M;
product3CommEarnings = Math.Round(commission3 * numberSold * 99.95M, 2);
}
else if (product == 4)
{
grossSales += numberSold * 350.89M;
product4CommEarnings = Math.Round(commission4 * numberSold * 350.89M, 2);
}
else if (product == 5)
{
grossSales += numberSold * 100.00M;
product5CommEarnings = Math.Round(commission5 * numberSold * 100.00M, 2);
}
else if (product == 6)
{
grossSales += numberSold * 1000.00M;
product6CommEarnings = Math.Round(commission6 * numberSold * 1000.00M, 2);
}
} // end while loop
Console.WriteLine("\n");
Console.WriteLine(" Commission Price Comm");
Console.WriteLine(" Sales Summary Earnings Sold Each Extentsion Rate");
Console.WriteLine(" ------------- ---------- ---- ----- --------- ----");
Console.WriteLine($" Base Pay {basePay:C} ");
Console.WriteLine($" Product 1 {product1CommEarnings} ");
Console.WriteLine($" Product 2 {product2CommEarnings} ");
Console.WriteLine($" Product 3 {product3CommEarnings} ");
Console.WriteLine($" Product 4 {product4CommEarnings} ");
Console.WriteLine($" Product 5 {product5CommEarnings} ");
Console.WriteLine($" Product 6 {product6CommEarnings} ");
You should initialize the numberSold.
int numberSold = 0; //initial value will be discarded by the loop.
But you are still not going to get the numberSold for each item as you are rewriting it in the loop and the value being printed will be the value from the last iteration of the loop.
Use a record class or a tuple to save the values from each iteration.

I'm trying to get best calculation of Sub total VAT and Total

I'm trying to get best calculation of Sub total, VAT percentage and Total but I dont know what I missed here. the right calculation as I know for amount 100 and vat 15% is: subtotal = 86.96 and vat = 13.04 and total = 100 when VAT included.
But my code giving me another result. So what is the correct code and what I missed?
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
row.Cells[dataGridView1.Columns["Amount"].Index].Value = (Convert.ToDecimal(row.Cells[dataGridView1.Columns["Qtty"].Index].Value) *
Convert.ToDecimal(row.Cells[dataGridView1.Columns["PurchasePrice"].Index].Value));
}
//datagridview column total in label
decimal sum = 0;
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
sum += Convert.ToDecimal(dataGridView1.Rows[i].Cells[4].Value);
}
lblSum.Text = sum.ToString();
//vat
decimal vat = (sum * 15 / 100);
lblVat.Text = vat.ToString();
//subtotal
decimal subtotal = (sum - vat);
lblSubtotal.Text = subtotal.ToString();
If you are trying to obtain the VAT separation from a sum that contains the price including VAT then you should change this line
decimal vat = (sum * 15 / 100);
to
decimal vatpct = 15m;
decimal vat = Math.Round(sum - (sum / (1 + ( vatpct / 100))),2);
or simplyfied a bit
decimal vatpct = 1 + (100 / 15m);
decimal vat = sum - Math.Round((sum / vatpct),2);
Of course remember to load that 15 constant from some configuration because this value changes too often.

Interest On Balance Calculation Repayments

I am trying to design some code that will calculate a repayment plan for a loan, given a principle amount, term period (12 months) and and interest rate. I want the payments each month to be the same value (the last can differ slightly to account for remainders), and the interest is calculated from the remaining loan balance.
The basic rules are
Interest is dependant on the loan balance.
Loan balance is dependant on the total monthly repayment value.
Capital repayment is dependant on total monthly repayment value and interest.
The total monthly repayment amount can vary but must be the same each month (except the last one which can be different).
Here is the code I currently have, it does continous iterations until it finds the correct total monthly repayment value. This does work sort of but seems very inefficient and it takes the balance horribly into negative when it shouldnt . I'm wondering if anyone knows of a better way of doing this?
static void calcRepaymentPlan()
{
decimal loanAmount = 100000; //100,000
decimal ir = 0.10m;
//day counts
int[] days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
//get month/days
int dayCount = days.Sum();
int months = days.Length;
//get interest values
decimal interestdaily = ir / dayCount;
//total each month
decimal ideal_total_repayment = (loanAmount / months); //random number but seems like the best place to start
//some arrays to store balances
decimal[] balances = null;
decimal[] interest = null;
decimal[] capitalrepayment = null;
decimal totalRepaymentsValue = 0;
while (totalRepaymentsValue != loanAmount)
{
//array for balance each month
balances = new decimal[months];
for (int i = 0; i < months; i++)
{
balances[i] = loanAmount - ((i+1) * ideal_total_repayment);
}
//array for interest each month
interest = new decimal[months];
for (int i = 0; i < months; i++)
{
interest[i] = (interestdaily * balances[i]) * days[i];
}
//array for capital each month
capitalrepayment = new decimal[months];
for (int i = 0; i < months; i++)
{
capitalrepayment[i] = ideal_total_repayment - interest[i];
}
//how much of the loan are we paying back?
totalRepaymentsValue = capitalrepayment.Sum();
//how much difference between the loan amount and the total we have got now?
decimal difference = loanAmount - totalRepaymentsValue;
//how much to increment
decimal incr = 1;
//are we within 100? if so make the increment finer
if (difference < 100)
incr = 0.1m;
//if the difference is less than 1, then just add/subtract it from the last repayment
if (difference < 1)
{
capitalrepayment[months - 1] += difference;
balances[months - 1] += difference;
//this should now be the
totalRepaymentsValue = capitalrepayment.Sum();
continue;
}
//change the ideal total repayment
ideal_total_repayment += totalRepaymentsValue < loanAmount ? incr : -incr;
}
Console.WriteLine("--------------------------------------------------------------------------------------");
Console.WriteLine(" Balance Capital Interest Total Repayment");
for (int i = 0; i < months; i++)
{
string balanceStr = balances[i].ToString("#,##0.00");
string capitalStr = capitalrepayment[i].ToString("#,##0.00");
string interestStr = interest[i].ToString("#,##0.00");
string totalStr = (capitalrepayment[i] + interest[i]).ToString("#,##0.00");
Console.WriteLine("{0}). {1} {2} {3} {4}", (i + 1),
balanceStr, capitalStr, interestStr, totalStr);
}
Console.WriteLine("Ideal Total Repayment Value : {0}", ideal_total_repayment);
Console.WriteLine("Total Repaying : {0}", totalRepaymentsValue);
Console.WriteLine("-------------------------------------------------------------------------------------");
}

What am i doing wrong with the math?

private void btnDisplay_Click(object sender, EventArgs e)
{
string EmploymentStatus = Convert.ToString(txtES.Text).ToLower();
string UnionStatus = Convert.ToString(txtMS.Text).ToLower();
double TotalSales = Convert.ToDouble(txtSales.Text) * 9.25;
double Years = Convert.ToDouble(txtYears.Text);
double uniondues;
double FICA = 0;
double bonus = 0;
double WPay = 0;
double TotalComission = 0;
if (EmploymentStatus == "full")
{
WPay = 800.00;
}
else if (EmploymentStatus == "part")
{
WPay = 200.00;
}
else
{
MessageBox.Show("Error, please enter either FULL or PART");
}
if (UnionStatus == "member")
{
uniondues = 5.25;
WPay = WPay - uniondues;
}
else if (UnionStatus == "non-member")
{
uniondues = 0;
}
else
{
MessageBox.Show("Error, please enter either MEMBER or NON-MEMBER");
}
if ((EmploymentStatus == "full") && (TotalSales > 640))
{
bonus = TotalSales * .05;
}
else if (EmploymentStatus == "part")
{
bonus = 0;
}
if (Years >= 10)
{
TotalComission = TotalSales * .10;
}
else if (Years < 10)
{
TotalComission = TotalSales * .05;
}
else
{
MessageBox.Show("Error, please enter a valid number");
}
FICA = WPay * .16;
WPay = WPay - FICA;
lblqWPay.Text = "The weekly pay for the employee is: " + (WPay.ToString("C"));
lblqTS.Text = "The total sales for this employee is: " + (TotalSales.ToString("C"));
lblqCom.Text = "The comission for this employee is: " + (TotalComission.ToString("C"));
lblqBonus.Text = "The bonus for this employee is: " + (bonus.ToString("C"));
When i enter the employment status as "FULL" and union status as "MEMBER", with the quantity sold as "100", and the years employed as "25". The weekly pay output should be "$783.30". But i end up getting $667.59 as the output. I cannot see what i am doing wrong.
Here are the guidelines that have to follow:
Full time representatives work 40 hours per week at a rate of $20.00 per hour
Part time representatives work 20 hours per week at a rate of $10.00 per hour
Some representatives belong to the union and pay $5.25 each week in union dues
If the representative has worked 10 years or more they get a commission of 10% of sales, otherwise they get a commission of 5% of sales
Widgets sell for $9.25
If a full time worker has sales that are more than 80% of their base pay they are entitled to a bonus of 5% of their sales
All representatives pay a 16% FICA tax based on their total earnings
P.S. I know this is a lot of reading, but if you can help me with this, it would be like a Christmas miracle to me.
Your computation is off based on the union dues...
Apparently, to get the 783.30 pay, the union dues are deducted AFTER the FICA tax has been applied...
800.00 (base)
+ 46.25 (5% bonus when over 80% base)
+ 92.50 (10% commission on 925 sales)
=======
938.75
-150.20 (16% FICA)
=======
788.55 Net pay before union dues
- 5.25 (union)
=======
783.30
private void btnDisplay_Click(object sender, EventArgs e)
{
string EmploymentStatus = Convert.ToString(txtES.Text).ToLower();
string UnionStatus = Convert.ToString(txtMS.Text).ToLower();
double TotalSales = Convert.ToDouble(txtSales.Text) * 9.25;
double Years = Convert.ToDouble(txtYears.Text);
double uniondues = 0;
double FICA = 0;
double bonus = 0;
double WPay = 0;
double TotalComission = 0;
if (EmploymentStatus == "full")
{
WPay = 800.00;
// since already in full-time status check, compute bonus here now.
// based on 80% of base pay
if (TotalSales > WPay * .80)
bonus = TotalSales * .05;
}
else if (EmploymentStatus == "part")
WPay = 200.00;
else
MessageBox.Show("Error, please enter either FULL or PART");
// Only if qualified full/part time status
if( WPay > 0 )
{
if (UnionStatus == "member")
uniondues = 5.25;
else if (UnionStatus == "non-member")
uniondues = 0;
else
MessageBox.Show("Error, please enter either MEMBER or NON-MEMBER");
if (Years >= 10)
TotalComission = TotalSales * .10;
else if (Years < 10)
TotalComission = TotalSales * .05;
else
MessageBox.Show("Error, please enter a valid number");
// NOW, build out the total pay before computing FICA
WPay = WPay + bonus + TotalComission;
// NOW Compute FICA
FICA = WPay * .16;
// and remove FICA and Union dues from gross pay to get net pay
WPay = WPay - FICA - uniondues;
}
lblqWPay.Text = "The weekly pay for the employee is: " + (WPay.ToString("C"));
lblqTS.Text = "The total sales for this employee is: " + (TotalSales.ToString("C"));
lblqCom.Text = "The comission for this employee is: " + (TotalComission.ToString("C"));
lblqBonus.Text = "The bonus for this employee is: " + (bonus.ToString("C"));
}
The value of 783.30 is wrong by my calculations. Doing the math by hand:
(800 (base) - 5.25 (union) + 92.5 (commision) + 46.25 (bonus))*.84 (tax) = 784.14. Unless the pay is determined differently from the guides you have mentioned your program is running correctly and the old one was wrong.

How to convert a number to a range of prices

I want to calculate the amount to charge my customers, when they buy licenses of my product.
I sell it in ranges of licenses:
1-10 : $50/user
11-20 : $40/user
21-30 : $30/user
31-50 : $20/user
So when someone purchases 136 licenses, I will charge him:
50 x 2 x $20 = $2000
30 x 1 x $30 = $900
6 x $50 = $300
I'm looking for an algorithm on how to process the given number and break it into number of occurrences in a range..
How can I do this in plain C# or LINQ?
------------ EDIT ----------------------------
I started a less confusing question (Algorithm for Fogbugz pricing scheme) and I got the answer I've been looking for.
Thank you all..
If presented with this price structure I would think that it is in the customer's best interest to minimize the cost by buying the package that best suits their need. The following algorithm uses dynamic programming to calculate the minimal possible price to exactly buy a certain number of licenses (you can save money by buying more than you need, although I haven't implemented that):
int getPrice(int n)
{
if (n >= 1 && n <= 10) return 50 * n;
if (n >= 11 && n <= 20) return 40 * n;
if (n >= 21 && n <= 30) return 30 * n;
if (n >= 31 && n <= 50) return 20 * n;
throw new Exception("Impossible");
}
int minimizePrice(int n)
{
int[] minimumPrice = new int[n + 1];
for (int i = 1; i <= n; ++i)
{
minimumPrice[i] = int.MaxValue;
for (int j = Math.Max(0, i - 50); j < i; ++j)
{
minimumPrice[i] = Math.Min(minimumPrice[i],
minimumPrice[j] + getPrice(i - j));
}
}
return minimumPrice[n];
}
For 70 licenses the minimal price is $1400 which can be obtained by buying 2 blocks of 35 licenses. You are suggesting a greedy algorithm. This will confuse your customers. A clever customer will place two orders instead of one large order and save $400.
I'd suggest changing your prices so that there is no upper limit to the number of licenses you can buy at $20 each.
This looks like it would be very similar to algorithms that make change for purchases (which coins to choose). The only difference is that you're comparing against a range instead of a single number.
The code could look something like this:
var val = 136;
var price = 0;
while (val > 0)
{
var range = FindMatchingRange(val); // Use a dictionary, list, or array.
var number = Math.Min(val, range.Max);
price += range.CostPerUser * number;
val -= number;
}
If I were a person who needed 10 licenses, under your suggested pricing plan why would I ever buy just 10 licenses?
10 licenses * $50/license = $500
11 licenses * $40/license = $440
What you would want is plan that lowers the cost for the most recently purchased licenses. So that for person wanting 11 licenses they would pay:
(10 licenses * $50/license) + (1 license * $40/license) = $540
A possible plan would look like this:
first 10 licenses (1-10): $50/user
next 10 licenses (11-20): $40/user
next 10 licenses (21-30): $30/user
all licenses after that (31+) : $20/user
Writing code to compute final cost for any number of users is a simple exercise. The calculation for someone purchasing 136 licenses would look like this:
(10 licenses * $50/license) + (10 licenses * $40/license) + (10 licenses * $30/license) + (106 licenses * $20/license) = $500 + $400 + $300 + $2120 = $3,220.
The original pricing plan is wacky, in my opinion. Take the customer who purchased 130 licenses last year who comes back and wants 10 more. What justification is there for charging them the highest rate? They are a high volume customer, you want to sell them (and they justifiably expect to receive) additional licenses at the lowest "marginal" price.
I made a calculation class for you... just more customer-orientated.
It calculates the cheapest price possible with your defined priceranges.
Example: 136 Licenses
50 Licenses 20$ each ( because: 31-50 : $20/user )
50 Licenses 20$ each ( because: 31-50 : $20/user )
36 Licenses 20$ each ( because: 31-50 : $20/user )
TOTAL: 1720
Example 130 Licenses
50 Licenses 20$ each
50 Licenses 20$ each
30 Licenses 30$ each
TOTAL: 1900
Code for the class:
public class PriceCalculator
{
public List<OrderPackage> CalculateCheapestPrice(Int32 AmountOfLicenses,
List<PriceRange> PriceRanges, out Double Total)
{
List<OrderPackage> result = new List<OrderPackage>();
Total = 0;
Int32 AmountsOfLicensesleft = AmountOfLicenses;
PriceRanges.Sort(ComparePrice);
for (int i = 0; i < PriceRanges.Count; i++)
{
for (int j = PriceRanges[i].MaxAmount; j >= PriceRanges[i].MinAmount; j--)
{
if (j <= AmountsOfLicensesleft)
{
OrderPackage Order = new OrderPackage();
Int32 AmountOfThisPackage = AmountsOfLicensesleft / j;
//Int32 AmountForThisPrice = Convert.ToInt32(Math.Floor(tmp));
Order.PriceRange = PriceRanges[i];
Order.AmountOfLicenses = j;
Total += Order.AmountOfLicenses * Order.PriceRange.PricePerLicense;
for (int k = 0; k < AmountOfThisPackage; k++)
{
result.Add(Order);
}
AmountsOfLicensesleft = AmountsOfLicensesleft - (AmountOfThisPackage * j);
}
}
}
return result;
}
private static int ComparePrice(PriceRange x, PriceRange y)
{
if (x.PricePerLicense == y.PricePerLicense)
return 0;
if (x.PricePerLicense > y.PricePerLicense)
return 1;
if (x.PricePerLicense < y.PricePerLicense)
return -1;
return 0;
}
public class OrderPackage
{
public PriceRange PriceRange { get; set; }
public Int32 AmountOfLicenses { get; set; }
}
public class PriceRange
{
public int MinAmount { get; set; }
public int MaxAmount { get; set; }
public Double PricePerLicense { get; set; }
}
}
Usage example:
private void button1_Click(object sender, EventArgs e)
{
// Preparing PriceRangeDefinitions
List<PriceCalculator.PriceRange> PriceRangeDefinitions = new List<PriceCalculator.PriceRange>();
PriceRangeDefinitions.Add(new PriceCalculator.PriceRange() { MinAmount = 1, MaxAmount = 10, PricePerLicense = 50 });
PriceRangeDefinitions.Add(new PriceCalculator.PriceRange() { MinAmount = 11, MaxAmount = 20, PricePerLicense = 40 });
PriceRangeDefinitions.Add(new PriceCalculator.PriceRange() { MinAmount = 21, MaxAmount = 30, PricePerLicense = 30 });
PriceRangeDefinitions.Add(new PriceCalculator.PriceRange() { MinAmount = 31, MaxAmount = 50, PricePerLicense = 20 });
// Start the Calculation
PriceCalculator calculator = new PriceCalculator();
Double Total;
List<PriceCalculator.OrderPackage> Packages =
calculator.CalculateCheapestPrice(130, PriceRangeDefinitions, out Total);
// Show Proof of Concept
String ProofOfConcept = String.Empty;
for (int i = 0; i < Packages.Count; i++)
{
ProofOfConcept += Packages[i].AmountOfLicenses.ToString() + " Licenses " +
Packages[i].PriceRange.PricePerLicense.ToString() + "$ each" + Environment.NewLine;
}
ProofOfConcept += Environment.NewLine + "TOTAL: " + Total.ToString();
MessageBox.Show(ProofOfConcept);
}
A KeyValuePair collection or dictionary maybe?

Categories