How to check every row of a table to continue my loop? - php

I'm stuck with this problem because my loop stops at only the first row of the table. Every customer has a set budget for purchasing products which resets every week to purchase items if ever the qty is not equal to 0. The admin is the one who can process the order for the customer. Customers have a budget = 1000 from customers table. Then customer_product table has the qty of products to be purchased by the customer. For example product_id = 1 has a price of 20 and has the qty of 10 so 20 x 10 = 200. Budget would be deducted by 200, remaining budget would be 800 after looping through the first row. Now i want to continue looping through the 2nd row with the remaining 800 budget instead of the 1000. It continues to loop as long as he still has a budget.
Database tables
customer
id | name | budget
customer_product
product_id | cus_id | qty | status
products
id | name | price
Controller
public function processOrder($id)
{
$customers = Customer::find($id);
foreach ($customers->products as $product)
{
$status = $product->pivot->status;
$budget = $product-budget;
$price = $product->price;
$qty = $product->pivot->qty;
if ($status == 1) {
$i = $qty;
for ($i; $i > 0; $i--) {
if ($budget < 1) {
break;
} else {
$budget-=$price;
}
}
};
echo "Status 0";
}
}
Routes
Route::get('processOrder/{id}', ['as' => 'processOrder',
'uses' => 'AdminController#processOrder']);
I can process the first row of the table and when it reaches 0 qty with my for loop, it stops there and doesn't continue to process the next row even though his budget is still enough to purchase products from the next row. Can someone please help me with this problem?

You should save the customer's budget before going into the loop, then update it while you iterate through the products.
public function processOrder($id)
{
$customer = Customer::find($id);
$remainingBudget = $customer->budget;
foreach ($customer->products as $product) {
// Calculate the total price to get the desired qty of product
$cost = $product->price * $product->pivot->qty;
// If we have enough remaining budget go ahead with the purchase
if ($product->pivot->status == 1 && $remainingBudget >= $cost) {
// Decrease the remaining budget
$remainingBudget -= $cost;
}
}
}

You are forcing the loop to break at the very first index
echo "Status 0"; break;
So remove break; at the end.
update:
foreach($customers->products as $product){
$status = $product->pivot->status;
$budget = $product-budget;
$price = $product->price;
$qty = $product->pivot->qty;
if($status == 1){
do {
if($budget < 1) break;
$budget -=$price;
} while ($qty != 0);
}
}

Related

PHP For Loop adding extra row at end of loop

Im pulling data from 2 different WordPress tables and looping through to get the appropreate data into a table row.
$tid = $_POST['pqrnum']; //get estimate number
$results = $wpdb->get_results('SELECT * FROM eqnum WHERE id='.$tid); //getting estimate data
$pArray = explode(',', $results[0]->pnum); //creating array of product numbers in estimate
$ptable = "<table>"; //create table
$presults = $wpdb->get_results('SELECT * FROM eparts'); //getting product data
$pres= count($presults); //products array count
for($l = 0; $l <=count($pArray); $l++){ //loop through each product in the array
$item = $pArray[$l]; //getting item number start 0
$titem = $item + 1; //adding 1 to $item without disturbing it because product array starts at 1
for ($x = 1; $x <= $pres; $x++) { //looping through product array
if($titem == $presults[$x-1]->id){ // if estimate item = product number
$ptable .= "<tr><td>item num ". $titem ." presults id ".$presults[$x-1]->id." presults name ".$presults[$x-1]->name."</td></tr>";
}
}
}
$ptable .= "</table>";
not sure why, but it seems to be printing an extra row, in this particular example there should be 3 rows, however this is the response:
item num 1 presults id 1 presults name Back up Alarm
item num 10 presults id 10 presults name Oil Filter
item num 11 presults id 11 presults name Spark Plug
item num 1 presults id 1 presults name Back up Alarm
as you can see the first and last lines are the same, it should be just the top 3, not 4.
just trying to determine why the extra row, any help appreciated.
Alex had the answer using < rather than <=, I thought I had tried that before but prefect thank you.

Fifo inventory in codeigniter

I'm new to CodeIgniter. I'm trying to update the quantity of the table based on FIFO. I'm making a stock take page, if we count the physical item less than what the table has, we will reconcile and this will update the inventory table and the discard table. Updating inventory table is easy and I've done but I want to update the discard table's quantity based on FIFO. What I want is for example the quantity of item A in inventory table is 50 but when we count it physically it's 35, so when we reconcile, it should minus 15 from the discard table quantity.
Items
Qty
Date
Item A
5
2022-8-22
Item A
4
2022-8-22
Item A
9
2022-8-22
After update it should be like:
| Items | Qty | Date |
|:--------|:------:| --------:|
| Item A | 0 | 2022-8-22|
| Item A | 0 | 2022-8-22|
| Item A | 3 | 2022-8-22|
Please help me. If you need further clarification, do let me know. Thanks in advance
public function update_complete(){
$stock_diff = $this->input->post('stock_diff');
$counted_stock_value = $this->input->post('counted_stock_value');
$cost_diff = $this->input->post('cost_diff');
$reconcile = $this->input->post('reconcile');
$barcode = $this->input->post('barcode');
$stk_id = $this->input->post('stk_id');
for ($i = 0; $i < count($barcode); $i++)
{
$data = array(
'stocktake_value' => $counted_stock_value[$i],
'stock_diff' => $stock_diff[$i],
'cost_diff' => $cost_diff[$i],
'status' => $reconcile[$i]
);
// Commented for testing
$this->db->where('stk_id', $stk_id);
$this->db->where('barcode', $barcode[$i]);
$this->db->update('stocktake_trans', $data);
$itemResult = $this->item_model->getStockdiscardTransByBarcodeNew($barcode[$i]);
foreach($itemResult as $item)
{
$rest = $stock_diff[$i];
if($rest > 0)
{
if($item['quantity'] >= $rest)
{
$rest = $item['quantity']-=$rest;
//$rest = 0;
echo $rest;
}
else
{
$item['quantity'] = 0;
$rest = $rest - $item['quantity'];
}
$this->db->where('barcode', $barcode[$i]);
$this->db->update('stockdiscard_trans', array('quantity' => $rest));
}
}
}
// Update Stock Take
$data1 = array(
'reconciled_by' => $this->session->userdata('name'),
'reconciled_at' => date('Y-m-d')
);
$this->db->where('id', $stk_id);
$this->db->update('stocktake', $data1);
// Set message
$this->session->set_flashdata('stocktake_reconciled', 'Stock Take has been Reconciled!');
//redirect('stocktake/complete');
}
I understand you want to store the difference between the old stock and the new stock.
You can store the original quantity in a variable, update the product with the new value, and then do the difference between the original quantity and the new quantity. Finally, you store the difference in the discard table.
Is what I understood correct?
Edit 1:
Something like this?
$itemsModel = model('App\Models\itemsModel');
$totalDB = $itemsModel->where('Items', 'Item A')->select('sum(Qty)')->first(); // let say 50
$totalMag = 35;
$rest = $totalDB - $totalMag; // rest 50-35 = 15
$itemResult = $itemsModel->where('Items', 'Item A')->findAll();
foreach($itemResult as $item)
{
if($rest > 0)
{
if($item->Qty >= $rest)
{
$item->Qty -= $rest;
$rest = 0;
}
else
{
$item->Qty = 0;
$rest = $rest - $item->Qty;
}
$item->save();
}
}
Backtesting:
-remaining qty 15
5 >= 15? - FALSE
Qty = 0
Rest = 10
4 >= 10 FALSE
Qty = 0
Rest = 6
9 >= 6 TRUE
Qty = 9-6 = 3
Rest = 0
But you need to manage, for what will happen if the remaining stock of products will be more than 0 and the quantity of products A will be 0.
Lets say we have remaining qty to 19
5 >= 19? False
Qty = 0
Rest = 14
4 >= 14? False
Qty = 0
Rest = 10
9 >= 10? False
Qty = 0
Rest = 1
What will happen for the rest = 1 when all item in our table have 0 Qty?

Displaying Coupons

So I have this MySQL table where an item has a field called isCoupon. The default is set to 0 if the seller does not make the item available for coupon use. Each item is ordered by ID and in the shop, there can be more than one coupon where the item is also available for discount. But how do I make it that those coupons display when the item is included? How do I make it that the buyer gets to pick which coupon to use? And how do I calculate the new price if I put "50% off" on the record instead of 0.5?
Table Coupon
couponCode | items | discount
------------------------------
SAMPLE123 | 1 | 50% off
SAMPLE234 | 2,3 | 40% off
SAMPLE345 | 1,5 | 25% off
Table Item
itemID | isCoupon
-----------------
1 | 1
2 | 1
3 | 1
4 | 0
5 | 1
Thanks!
Try the below. As for the buyer picking to choose which coupon, you should let the buyer select the item first and then go to the checkout page by selecting the coupon.
$num_items = 5;
// the below array is used to store the coupons you can use for the item so you can
// proceed with it to the checkout page, there you can make a select dropdown to let
// the buyer select which coupon to use
$coupon_use = array();
for($i = 0; $i < $num_items; $i++) {
// check for current item
$SQL = "SELECT * FROM item WHERE itemID = '$i'";
$result = mysqli_query($connect, $SQL);
$field = mysqli_fetch_assoc($result);
// check if there is a coupon for the current item
if($field['isCoupon'] == 1) {
$SQL2 = "SELECT * FROM coupon";
$result2 = mysqli_query($connect, $SQL2);
// while method to go through every single coupon
while($field2 = mysqli_fetch_assoc($result2)) {
// if you put commas, you can use the explode method
// to store all the items for that coupon and use it to
// check for that current item
$coupons = explode(',', $field2['items']);
if(in_array($i, $coupons)) {
// do your items have a price?
// salePrice is the new price
// thePrice is the old price you need to get with $field (not $field2)
if($field2['discount'] == '50% off') { $salePrice = $thePrice * 0.5; }
else if($field2['discount'] == '40% off') { $salePrice = $thePrice * 0.6; }
else if($field2['discount'] == '25% off') { $salePrice = $thePrice * 0.75; }
// add the coupon code to the array of coupons available for use
array_push($coupon_use, $field2['couponCode']);
// display the prices
echo 'ITEM #'.$i.'<br><s>$'.$thePrice.'</s><br>$'.$salePrice.'<br><br>';
}
}
}
else { echo 'ITEM #'.$i.'$'.$thePrice; }
}
Now you can store the values of the coupon_use array to the checkout page.

counting total within a while loop

In my project I am fetching data from the database using a while loop where each data is fetched by a customer id as $cid. Now all the data is calculated and finally put into a variable $cashflow. Now suppose there are 20 persons so the table will display 20 records where each data is counted for each person / customer. Now what I want to do is count the total of all 20 records and echo it seperately.
For eg.
Cust.1 : 500 (calculated from $cashflow)
Cust. 2 : 1000
Cust.3 : 800 ..... and so on.
Now these data are well echoed in my table. Now what I want is to add 500+1000+800 and echo 2300 as total separately. But I am not being able to figure out how to do it in my code. Should I take a variable in loop as a ++ counter? or something else? Please help.
Code:
$cash = "SELECT SUM(paid) FROM hbil WHERE cid = '".$cid."' AND method = 'cash'";
$cash_qur = mysql_query($cash) or die(mysql_error());
$cash_neg = "SELECT SUM(price) FROM hbil WHERE cid = '".$cid."' AND method = 'cash' AND price < 0";
$cash_qur_neg = mysql_query($cash_neg) or die(mysql_error());
while($cash_fetch = mysql_fetch_array($cash_qur))
{
$cash_fet = mysql_fetch_array($cash_qur_neg);
$cashpay = $cash_fetch['SUM(paid)'];
$cashneg = $cash_fet['SUM(price)'];
$cash_total = $cashpay-$cashneg;
$cashflow = number_format($cash_total,2,'.',',');
}
$total = 0;
while (...) {
//...
$total += $cash_total;
}
echo $total;
Will do the trick

Adding Postgres table cells based on same value

I have a table called expenses. There are numerous columns but the ones involved in my php page are date, spplierinv, amount. I have created a page that lists all the expenses in a given month and totals it at the end. However, each row has a value, but many rows might be on the same supplier invoice.This means adding each row with the same supplierinv to get a total as per my bank statement. Is there anyway I can get a total for the rows based on the supplierinv. I mean say I have 10 rows. 5 on supplierinv 4, two on supplierinv 5 and 3 on supplierinv 12, how can a get 3 figures (inv 4, 5 and 12) and the grand total at the bottom. Many thanks
Do you need to show the individual expense rows as well as all the totals? If not, you can group by the supplierinv column and sum the amounts:
select supplierinv, sum(amount) as invoice_amount
from expenses group by supplierinv
then you can simply add all the invoice_amount values client-side to get the grand total.
if you do need each expense row, you can do the invoice aggregation client-side fairly easily:
$invtotals = array();
$grand_total = 0;
foreach (getexpenses() as $row) {
$supplierinv = $row['supplierinv'];
if (!array_key_exists($supplierinv, $invtotals)) {
$invtotals[$supplierinv] = 0;
}
$invtotals[$supplierinv] += $row['amount'];
$grand_total += $row['amount'];
}
another approach, if you want to show the table split up into invoices, is to just ensure the results are ordered by supplierinv and then:
$grand_total = 0;
$invoice_total = 0;
$current_invoice = -1;
foreach (getexpenses() as $row) {
if ($current_invoice > 0 && $current_invoice != $row['supplierinv']) {
show_invoice_total($current_invoice, $invoice_total);
$grand_total += $invoice_amount;
$current_invoice = $row['supplierinv'];
$invoice_total = 0;
}
$invoice_total += $row['amount'];
show_expense($row);
}
if ($current_invoice > 0) {
show_invoice_total($current_invoice, $invoice_total);
$grand_total += $invoice_amount;
}
show_grand_total($grand_total);
You can have the database do the aggregation for each invoice and the grand total like so:
select date, supplierinv, amount,
sum(amount) over(partition by supplierinv) as invoice_amount,
sum(amount) over()
from expenses
although you still have to do some post-processing to display this sensibly, so this doesn't really gain anything imho.

Categories