Multiple row sum and update - php

I want to update multiple rows while all of them will be summed up with their previous records. For Example, There are 2 products "a" and "b" in a table called "products", they have a column called "quantity". Let's say the product "a" has a quantity of 20 and product "b" has a quantity of 25. Now I am inserting both products' new quantities (the new quantity for product "a" is 5 and 4 for product "b"). The query should update both products' quantity before the insertion, like the quantity of product "a" will be 25 and product "b" will be 29. My codes are :
foreach ($request->product_id as $key => $value) {
$input['quantity'] = $request->product_quantity[$key];
$update_stock = Product::update(['id'=>$request->product_id[$key]],
$input);
}

You can use the increment here.
Suppose the request array will be,
$productsWithQty = [
1 => 5,
2 => 4
];
Where the 1 and 2 is your product ids, product A and B respectively and 5 and 4 is quantities. So query will be,
foreach ($productsWithQty as $product => $qty) {
Product::findOrFail($product)->increment('quantity', $qty);
}
Try this and let me know the results.

Related

Multidimensional array search for value and add to specific key if found

so what i have is just some data that should be fixed for printing, and i can't wrap my head around this one...
i have some finished products separated for each batch code (int_lot) with their quantities. You can select and give that values to the invoice, but what i need to do is calculate total of same product name (in relationship called FinishedProduct) and i get all finished products with relation that has quantities with:
DeliveryProductQuantity::where('delivery_note_id', $packingList->delivery_note_id)->with('FinishedProduct')->get();
then i get object like this:
"id" => 12
"finishedid" => "24"
"quantity" => "116"
"old_quantity" => "116"
"delivery_note_id" => "52"
now when i load relationship with first() i get data like for each item in foreach:
"id" => 12
"finished_product_name" => "Product Name"
"shift" => "Prva"
"expiry_date" => "19042023/1"
"user_id" => "6"
What i want to do first is just put all products with same finished_product_name. But finished_product_name is in relation and quantity is in array that's not in relationship.
So i need foreach item of first array of objects to check if relationships product name exists and then if it doesn't add a new entry in temporary array, if does just add quantity to the last one with same product name. What have i tried (besides many else):
$total_data = [];
foreach ($test2 as $product) {
foreach ($product->FinishedProduct as $key => $value) {
if(!in_array($product->FinishedProduct->first()->finished_product_name, $total_data)) {
array_push($total_data,
[
'finished_product_name' => $product->FinishedProduct->first()->finished_product_name,
'expiry_date' => $product->FinishedProduct->first()->expiry_date,
'quantity' => $product->quantity,
'old_quantity' => $product->old_quantity,
'delivery_note_id' => $product->delivery_note_id
]
);
}
if(in_array($product->FinishedProduct->first()->finished_product_name, $total_data)) {
foreach ($total_data as $key => $value) {
if($value['finished_product_name'] == $product->FinishedProduct->first()->finished_product_name) {
$total_data[$key]['quantity'] += $product->quantity;
$total_data[$key]['old_quantity'] += $product->old_quantity;
}
}
}
}
}

Laravel eager loading use parents column value

Here is my scenario, I have 2 table Product and Rack. They have many to many relationship, so there is a pivot table ( History Class ) to connect them .
Tables
This is our Products table:
id
Name
1
Product A
2
Product B
3
Product C
Rack table:
id
code
1
X1
2
Y2
3
Z3
History table:
product_id
rack_id
historyable_id
historyable_type
quantity
Product A
X1
1
Receive
10
Product A
Y1
1
Receive
5
Product A
X1
1
Delivery
2
Product B
X1
2
Receive
10
I want to get list like this:
product_id
rack_id
historyable_id
historyable_type
quantity
Product A
X1
1
Receive
8
Product A
Y1
1
Receive
5
Product B
X1
2
Receive
10
If type receive is 'debit' and delivery is 'credit' to calculate quantity, and i have two unique column in here product_id and rack_id.
Here is my method right now:
public function collection()
{
$products = Product::with('racks')->get();
$results = collect();
foreach ($products as $product) {
foreach ($product->racks as $rack) {
$rackWithHistory = $rack->load(['history' => function ($q) use ($product) {
return $q->where('product_id', $product->id)->with('histories:id');
}]);
$results->push([
'product_name' => $product->name,
'product_description' => $product->description,
'location' => $rack->code,
'quantity' => $rack->getQuantity($rackWithHistory->history)
]);
}
}
return $result;
}
It works but in large data (try in 2000rows) that takes a very long time, and always touch
php - Allowed memory size of 134217728 bytes exhausted can you guys give me some tips so it can load faster?
You could try chunking the data
Product::with('racks')->chunk(100, function ($products) use($results) {
foreach ($products as $product) {
foreach ($product->racks as $rack) {
$rackWithHistory = $rack->load(['history' => function ($q) use ($product) {
return $q->where('product_id', $product->id)->with('histories:id');
}]);
$results->push([
'product_name' => $product->name,
'product_description' => $product->description,
'location' => $rack->code,
'quantity' => $rack->getQuantity($rackWithHistory->history)
]);
}
}
});
When you chunk data, you only take a x amount of items at a time. In your case 100 items at a time.
https://laravel.com/docs/8.x/queries#chunking-results

Group data from 2d array by column and count or sum other columns

I am build a multidimension array from data that has a multiple entries but some entries have the same value;
id name delivery# weight time
--------------------------------------------
12 test 112233 45 now
13 test 112234 456 now
14 testA 112245 33 later
15 testB 334421 334 later
...
...
and foreach id I push to array like so;
array_push($arraydata, array(
"id" => $id,
"name" => $name,
"delivery" => $delivery,
"weight" => $weight,
"time" => $time
));
and later I use to loop through it;
foreach($arraydata as $arraydataItem) {
//do stuff...
//test appears twice - echo count & delivery values
//testA once - echo count
//testB once - echo count
}
Basically I want check how many times the same name value appears and add the weight values together for a total.
As then for each "delivery" with the same "name" divide the delivery weight by the total weight of "name" and get the percentage which I will use for calculating the percentage of the total cost of "name"..
Instead of creating that associative array using array_push(), you should create a multidimensional array like this,
$arraydata[$name][] = array('id' => $id, 'delivery' => $delivery, 'weight' => $weight, 'time' => $time);
And as per your question,
Basically I want check how many times the same name value appears and add the weight values together for a total.
Simply use a foreach loop to loop through $arraydata array and display count and total weight associated for each name, like this:
foreach($arraydata as $key => $arraydataItem){
// Display count and total weight associated for each name
echo $key . ": (count: " . count($arraydataItem) . ", total weight: " . array_sum(array_column($arraydataItem,'weight')) . ")<br />";
}
This will output:
test: (count: 2, total weight: 501)
testA: (count: 1, total weight: 33)
testB: (count: 1, total weight: 334)
Moreover, you can tweak this code to fulfil your further requirements.
Note: If you want to see the structure of $arraydata array, do var_dump($arraydata);

Getting all items on Amazon Product API

Amazon's Product API limits us to get only 10 items per page, and only 10 pages at a certain query.
I have developed a code that would almost get all items;
first, I have supplied a params that looks like this:
$item_params = [
"Service" => "AWSECommerceService",
"Operation" => "ItemSearch",
"AWSAccessKeyId" => env('AWS_ACCESS_KEY_ID'),
"AssociateTag" => env('AWS_ASSOCIATE_TAG_ID'),
"SearchIndex" => "HomeGarden",
"ResponseGroup" => "ItemAttributes,SalesRank,Offers",
"Sort" => "-price",
"BrowseNode" => $item_params['BrowseNode'],
"MaximumPrice" => $max_price,
"MinimumPrice" => "0"
];
then, the code will get all items under that browse node (category), SORTED BY PRICE (desc) also by specifying the MAX and MIN Price of the items to limit the search.
the pseudo-code (original code is too long)
function getProducts($item_params, $max_price = null){
$products = //request to amazon
foreach ($product as $key=>$value){
//add product to db
}
// if the total number of results on the query is not equal to zero, continue looping
if (!$products->totalResults() == 0){
$product = //get the first lowest priced item on the db
$this->getProducts($item_params, $product->price);
}
}
however I am experiencing this scenario :
Sample request output (assuming all items from amazon):
ASIN(unique id) | Price
1 | 201
2 | 194
3 | 195
.
.
n | 33
n+1 | 33
n+2 | 33
.
n+120 | 33
n+121 | 34
n+122 | 35
wherein the products from n to n+120 are equal. This will create an infinite loop to my getProducts function. How can I avoid this? Knowing that only 10 items are returned on each request and only 10 pages.
How can I avoid this?
I don't think you can with just using price. You have to divide your search into multiple sub-searches by using additional keywords. For example, if you're searching for "laptop", instead do searches on "laptop asus", "laptop dell", etc.
You can also filter on Browse node IDs, so if your results come from multiple browse nodes, you can do two or more searches.
Add the ItemPage parameter and increment it in a loop. You should be able to get up to 100 unique ASINs (10 pages of 10 products per page).
$page = 1;
while($page <= 10) {
$item_params = [
"Service" => "AWSECommerceService",
"Operation" => "ItemSearch",
"AWSAccessKeyId" => env('AWS_ACCESS_KEY_ID'),
"AssociateTag" => env('AWS_ASSOCIATE_TAG_ID'),
"SearchIndex" => "HomeGarden",
"ResponseGroup" => "ItemAttributes,SalesRank,Offers",
"Sort" => "-price",
"BrowseNode" => $item_params['BrowseNode'],
"MaximumPrice" => $max_price,
"MinimumPrice" => "0",
"ItemPage" => $page
];
// execute query and save data
//increment page number
$page++;
}

Laravel 4 - Not updating sessions

I am trying to achieve the following:
I am building a very basic shopping cart, if someone adds an item to the basket, this gets saved inside a session. I.e. Session - array('id' => '1', 'quantity' => '1'); If they add another of these items with the same id, the product is not added again, but the quantity is adjusted with this.
My implementation:
$quantity = Session::get('basket_items2')[$product->id]['quantity'];
$newQuantity = (int)$quantity + 1;
$products[$product->id] = array("product_id" => $product->id, "quantity" => $newQuantity);
Session::put('basket_items2', $products);
However, the quantity just remains at 1 so no matter how many times you add the product, the quantity is always "2" therefore the session is not updating / overriding.
Any ideas, please?

Categories