How to reduce the total after every iteration - php

I have a $paymentsTotal variable which is the sum of all payments. I then want to loop through all outstanding amounts and reduce the $paymentsTotal variable for each outstanding amount.
eg:
TotalPayments = 900 - 200
700 - 300
400 - 100
300 - 300
Stop 0
And as long as the $paymentsTotal is greater than the outstanding amount, it should return true.
I tried this:
foreach ($invoices as $invoice) {
if($paymentTotal >= $paymentTotal -= $invoice->amount) {
echo $invoice->amount . ' - PAID <br>';
}
}
but it echos out each result no matter what.

Try something like...
$paymentTotal = 0; // whatever this is before iteration
foreach($invoices as $invoice) {
if ($invoice->amount > $paymentTotal) {
$paymentTotal -= $invoice->amount; // assuming you have a field for the paid amount
$invoice->amount = $paymentTotal; // new invoice amount
echo "{$invoice->amount} - PAID <br>";
}
}

Related

How to determine every 100 item in a while loop php?

I'm currently learning PHP, and I'm struggling with this:
"For every 100 ordered products in a category, 2% will be deducted:"
This is my code:
$gesA = 309; // (The amount of product)
$gesN = 1011.08; // (The full price of product)
$i = 1;
while($i)
{
if($gesA % 100 == 0)
{
echo $gesN;
echo "<br>";
$gesN = $gesN / 0.2;
}
$i++;
$gesN++;
}
echo $gesN;
Yet, I can't figure it out. Could someone help me?
First you find how many times it is that there are 100 ordered products, which can be calculated by divide the number of products by 100.
$no = $getA / 100;
But that can get you a floating number so you remove the decimal part with floor()
$no = floor($getA / 100);
Then the percentage will be 2% times the integer number.
$deductPercentage = 2 * $no;
And the final product price will be the remaining of the deducted price
$deductedPrice = $gesN * $deductPercentage / 100;
$finalPrice = $gesN - $deductedPrice;

How to create tier price amount according to value

I'm setting up a webshop to use in a printshop but I'm stuck on how to automatically provide prices for different amounts.
In example:
The client wants to see the price for 100 sheets and immediately it should see the price for 150, 200, 250, ... (it's cheaper per piece every time you the amount is larger).
This is easy of course; get $amount and add +50 every time. But when the client asks 1000 it should not be +50 but maybe +100.
Is there a slick and easy way to do this or is it going to be a lot of
if($amount < 100){ add +50 }elseif($amount > 100 && < 500){ add + 75 }....?
Ok, how about this:
$amount = 100; // client's amount
$i = 1; // iterator
$suggested = array(); // array for suggested amounts
$increment = ($amount / 2); // half of client's suggested amount
# while loop
while ($i <= 3) {
$amount = $amount + $increment; // formula
array_push($suggested, $amount); // add to array
$i++;
}
# will output 150, 200, 250
foreach ($suggested as $s) {
echo $s . '<br />';
}
Will that get you started in the right direction?

Distribute a payment value through monthly period

Imagine a scenario where monthly rent is 100,000 which is payable at the end of each month.
A tenant then decides to make a payment 350,000 to cater for the current month and those ahead. How do I distribute this amount since I can obviously see here that this amount caters for 3 months and a half month?
Here is what I was trying in PHP but I just can't get the last 50,000 to appear.
$rent = 100000; // rent amount
$amountPaid = 350000; // amount paid by tenant
$length = $amountPaid/$rent; // number of months paid for
for ($c = 1; $c <= $length; $c++)
{
$foreachMonth = $rent;
assignRentFunction($c, $foreachMonth);
}
function assignRentFunction($count, $amt)
{
echo "Month ".$count.': '.$amt."<br>";
}
Steps:
1) Get total months with ceil() function.
2) It will return 4 months. 3 months fully paid and one month paid only 50000.
3) Now, for each loop will add 10000 to total rent paid.
4) if this surpasses the amount paid, get mod which is 50000
$rent = 100000; // rent amount
$amountPaid = 350000; // amount paid by tenant
$length = ceil($amountPaid/$rent); // number of months paid for
$totalRent = 0;
for ($c = 1; $c <= $length; $c++) {
$totalRent += $rent;
$foreachMonth = $rent;
if ($amountPaid < $totalRent) { // Here is the logic, if amount exceeds, use the remaining amount.
$foreachMonth = $amountPaid % $rent;
}
assignRentFunction($c, $foreachMonth);
}
function assignRentFunction($count, $amt) {
echo "Month ".$count.': '.$amt."<br>";
}
**Output:**
Month 1: 100000
Month 2: 100000
Month 3: 100000
Month 4: 50000
$rent= 100000; // rent amount
$amountPaid= 350000; // amount paid by tenant
$length= $amountPaid/$rent; // number of months paid for
for ($c = 1; $c <= ceil($length); $c++)
{
$foreachMonth = 100000;
if($amountPaid>$rent)
{
$rent=$rent;
$amountPaid=$amountPaid-$rent;
}
else
{
$rent=$rent-$amountPaid;
}
assignRentFunction($c, $rent);
}
function assignRentFunction($count, $amt)
{
echo "Month ".$count.': '.$amt."<br>";
}
Since there seems to be a few ways to slice this, I thought I'd throw my hat in the ring also:
for($c = 1; $c<=ceil($amountPaid/$rent); $c++){
assignRentFunction($c, $rent - max(($c * $rent - $amountPaid),0));
}
And now the commented version:
for($month = 1; $month<=ceil($amountPaid/$rent); $month++){
//For each month there is money for rent (using ceil() to account for fractions)
assignRentFunction(
$month,
// The number of the month
$rent
//Show the rent ($rent)
-
//Deduct
max(($month * $rent - $amountPaid),0)
//Any difference if the whole rent for that month hasn't been paid
/**
* This relies on a little hack with the max() function:
* max($var,0) will return 0 if $var is less than 0.
* So we check to see if the sum of rent up to that month ($month * $rent)
* is greater than what was paid ($month * $rent) - $amountPaid.
* If it isn't because it's wrapped in the max,
* the net (negative) number will just be shown as nill.
* If it is, the net positive number will be subtracted
* from the month's rent.
**/
);
}
Change your loop part to
for ($c = 1; $c <= $length; $c++) {
$foreachMonth = $rent;
assignRentFunction($c, $foreachMonth);
}
$fractionalMonth = $length - intval($length);
if ($fractionalMonth)
assignRentFunction($c, $foreachMonth * $fractionalMonth);
Your error was since you're always incrementing $c by one, you wasn't able to get the fractional part for the last month
You can solve your problem like this,
$rent = 100000; // rent amount
$amountPaid = 350000; // amount paid by tenant
$length = ceil($amountPaid / $rent); // number of months paid for
$temp1 = $amountPaid;
for ($c = 1; $c <= $length; $c++) {
if($temp1 < $rent){ // assigning left amount to rent if less than amount left
$rent = $temp1;
}
if($temp1 > $rent){ // checking if amount left is still more than per month rent then minus that rent from pending paid amount
$temp1 = $temp1 - $rent;
}
assignRentFunction($c, $rent);
}
function assignRentFunction($count, $amt)
{
echo "Month " . $count . ': ' . $amt . "<br>";
}
Demo.

How to get a decreasing rental cost based on the number of days

Is there a fast way to get a decreasing rental cost based on the number of days?
For example:
If I rent a car for 1day, the cost is 100$
If I rent a car for 2days, the cost is 100$ + 70$ = 170$
If I rent a car for 3days, the cost is 100$ + 70$ + 50$ = 220$
If I rent a car for 4days, the cost is 100$ + 70$ + 50$ + 50$ = 270$
If I rent a car for 5days, the cost is 100$ + 70$ + 50$ + 50$ + 50$ = 320$
So I need a fast way to get the total cost based on the number of days.
For example:
function getcost(days){
...
return $cost;
}
echo getcost(1); // it show 100$
echo getcost(3); // it show 220$
// and so on...
Assuming that from day three all consecutive days cost 50$:
function getcost(int $days) {
return ($days > 1) ? (($days - 2) * 50 + 170) : (($days == 1) ? 100 : 0);
}
function getcost(days){
$cost=0;
for($idx=1;$idx<=$days;$idx++)
{
switch($idx)
{
case 1:
$cost+=100;
break;
case 2:
$cost+=70;
break;
default:
$cost+=50;
break;
}
}
return $cost;
}
$price = $days * 50 + ($days > 1 ? 70 : 20);
If you want to you can put it in a function.
You can try like this way-
<?php
function getcost($days){
$array=['base' => 100, 'for_2nd' => 70, 'after_2nd' => 50];
if($days==1){
$cost = $array['base'] * $days;
}else if($days>=2){
$cost = $array['base'] + ($days == 2 ? $array['for_2nd'] : $array['for_2nd'] + ($days - 2) * $array['after_2nd']);
}
return $cost.'$';
}
echo getcost(1); // it show 100$
echo getcost(2); // it show 170$
echo getcost(3); // it show 220$
echo getcost(4); // it show 270$
echo getcost(5); // it show 320$
?>
DEMO: https://3v4l.org/h9tF5
If your day rate is based on number of days, then to allow you to have a dynamic rate (perhaps different type of car etc.) then it's best to have some form of array which is passed into the function. The function then uses this and adds the days up till it the rates run out and adds any remaining days according to the last rate...
// Cost for each day
$costs = [100, 70, 50];
function getcost( $costs, $days){
$totalCost = 0;
foreach ( $costs as $dayCost ) {
// Add each cost
$totalCost += $dayCost;
// Decrement number of days left and exit if reached 0
if ( --$days == 0 ) {
break;
}
}
// If remaining days - add last day cost * number of days
if ($days > 0 ) {
$totalCost += ($dayCost*$days);
}
return $totalCost;
}
echo getcost($costs, 1); // it show 100$
echo getcost($costs, 3); // it show 220$
echo getcost($costs, 5); // it show 320$

Looking for a more elegant solution to this loop

I tried asking this earlier, but I don't think I phrased the question correctly so I worked out something that got me the result I was after and now am hoping that it will help someone help me.
Problem: I have 10 items. If you buy 1, it's $10. I will sell you the second one for $9. I will sell you the third item for $8. I will keep taking off money until we get to $5/item because that is the lowest I will sell it for. So, if you buy all 10, it will cost you $65.
This is the pricing model I am trying to achieve, except at a much larger scale. Instead of a handful of items using dollars, I'm talking about up to millions and using fractions of pennies.
This is my current code:
<?php
function getCost($num_items)
{
$min_price = 0.002;
$max_price = 0.007;
$discount_range = 1000000;
$discount_per_additional_item = ($max_price - $min_price) / ($discount_range - 1);
$price_per_unit = MAX($min_price, ($max_price - ($num_items - 1) * $discount_per_additional_item) );
return $price_per_unit;
}
$array = [100, 1000, 10000, 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000];
foreach ($array as $value)
{
$sum = 0;
for ($i = 0; $i < $value; ++$i)
$sum += getCost($i);
echo number_format($value) . ' | $' . number_format($sum) . "\n";
}
Which results in:
100 | $1
1,000 | $7
10,000 | $70
100,000 | $675
200,000 | $1,300
300,000 | $1,875
400,000 | $2,400
500,000 | $2,875
600,000 | $3,300
700,000 | $3,675
800,000 | $4,000
900,000 | $4,275
1,000,000 | $4,500
I'm using $array as a sanity check where in the real world, I would simply calculate for the actual number the customer is being charged for.
My question is: Is there a way to accomplish this without using a for loop? Something, perhaps, more elegant?
I made an example online: http://sandbox.onlinephpfunctions.com/code/47e270dbad8cbe16c9ea906ffd2dce098a52fbca
This code will have the same output, and does not have the inner loop:
$min_price = 0.002;
$max_price = 0.007;
$discount_range = 1000000;
$discount_per_additional_item = ($max_price - $min_price)/($discount_range - 1);
$num_progressively_discounted_items =
ceil(($max_price - $min_price) / $discount_per_additional_item);
foreach ($array as $value) {
$num_items_above_min = min($value, $num_progressively_discounted_items);
$num_items_at_min = $value - $num_items_above_min;
$sum = $num_items_at_min * $min_price +
$num_items_above_min * $max_price -
$discount_per_additional_item
* $num_items_above_min * ($num_items_above_min - 1)/2;
echo number_format($value) . ' | $' . number_format($sum) . "\n";
}
This is what it does:
It first checks how many times the unit discount can be subtracted from the original price before hitting the minimum price. If more than the number of items you are buying, then this calculated figure is corrected to that number of items.
The remaining number of items (if any) are also taken note of: these will all have the minimum price.
The sum consists of two parts. The easy part is represented by the number of items that will go for the minimum price, and it is a simple multiplication.
The second part of the sum consists of an always decreasing term, or otherwise put: it is the maximum price for the number of items that don't go for the minimum price, minus the sum of 0+1+2+3+4+5...+n. For that the formula is known: n(n-1)/2.
Like I mentioned in comments, there is something strange in your code: for $i=0 the value returned by getCost($i) is higher than the max price, as the unit discount gets added to it. This can be corrected by starting your inner loop with $i=1. Anyway, this means there is a tiny difference in the result of my proposed code, as it does not have this peculiarity. But as the discount per unit is so tiny, you don't actually notice it in the printed output.
You can do this a little bit more functional style:
function sumOfNaturalSeries($n)
{
return ((1 + $n) / 2) * $n;
}
$minPrice = 0.002;
$maxPrice = 0.007;
$discountRange = 1000000;
$discountStep = ($maxPrice - $minPrice) / $discountRange;
$getPrice = function ($numberOfItems) use (
$minPrice,
$maxPrice,
$discountRange,
$discountStep
) {
if ($numberOfItems <= $discountRange) {
return $maxPrice * $numberOfItems - sumOfNaturalSeries($numberOfItems - 1) * $discountStep;
}
$itemsAboveRange = $numberOfItems - $discountRange;
return $maxPrice * $discountRange - sumOfNaturalSeries($discountRange - 1) * $discountStep + $minPrice * $itemsAboveRange;
};
$array = [100, 1000, 10000, 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000];
$sums = array_map($getPrice, $array);
var_dump($sums);
var_dump(array_map('number_format', $sums));
Here is demo.
Take a notice on computational error.

Categories