decrease stock quantity at order placement in laravel - laravel

I want to decrease quantity from products table when order is added to cart ,right now when I add something to cart, correct quantity is not decreasing. For example if a I place order of 6 items then a random amount gets decreased from my products table.
Here is my code in order controller of livewire:
public function IncrementQty($cartId)
{
$carts=Cart::find($cartId);
$carts->increment('product_qty',1);
$updatePrice=$carts->product_qty * $carts->product->price;
$carts->update(['product_price'=>$updatePrice]);
$getProductStock=Product::where(['id'=>$carts['product_id']])->first()->toArray();
$newStock=$getProductStock['quantity'] - $carts['product_qty'];
Product::where(['id'=>$carts['product_id']])->update(['quantity'=>$newStock]);
$this->mount();
}
Being a beginner I am unable to understand about what's wrong here. Should I be substracting it from orderDetails table instead of carts table? If yes then how?

A couple of things to note first,
You should not call $this->mount() or any other lifecycle hooks from Livewire. If there are code inside your mount-method you need to run again, then abstract it into a separate method, and call it from both your mount() method and your IncrementQty() method.
You can use model-route-binding to inject the correct model into the method
public function IncrementQty(Cart $cart)
You can then simplify your code by using the product relation on the cart directly, and calling decrement() on that.
public function IncrementQty(Cart $cart)
{
$product = $cart->product;
$cart->increment('product_qty', 1);
$cart->update(['product_price' => $cart->product_qty * $product->price]);
$product->decrement('quantity', 1);
$this->mount(); // Do not call mount manually, abstract the contents you need into a separate method instead
}
If you are still experiencing issues, then it cannot possibly be this piece of code, or you are misreading your data somehow - in any case, if you are still experiencing issues, you will need to provide additional information with your table-structure, models, how you call this method, and data before and after your actions.

it seems you have a problem in this line:
$newStock=$getProductStock['quantity'] - $carts['product_qty'];
$carts is an object not an array, so, do:
$newStock = $getProductStock['quantity'] - $carts->product_qty;

Related

Model's scope function is showing wrong value, but only in production server

I'm facing a weird problem which only happen in the production server (It's 100% normal in my local). I'm using Laravel 8, and have a model named Student. Inside the model, I created several scope methods like this:
public function scopeWhereAlreadySubmitData($query)
{
return $query->where('status_data_id', '!=', 1);
}
public function scopeWhereAlreadySubmitDocument($query)
{
return $query->where('status_document_id', '!=', 1);
}
Then I use the methods above in an AJAX controller to chain it with count method. Something like:
public function getAggregates()
{
$student = Student::with(['something', 'somethingElse']);
$count_student_already_submit_data = $student->whereAlreadySubmitData()->count();
$count_student_already_submit_document = $student->whereAlreadySubmitDocument()->count();
return compact('count_student_already_submit_data', 'count_student_already_submit_document');
}
Here's is where the weird thing happens: while the controller above produce the correct value in my local, in production count_student_already_submit_data has a correct value but count_student_already_submit_document has zero value. Seeing at the database directly, count_student_already_submit_document should have value more than zero as there are many records has status_document_id not equals to 1.
I've also tried to use the scopeWhereAlreadySubmitDocument method in tinker. Both in local and production, it shows the correct value, not just zero.
Another thing to note is that Student model actually had 4 scope methods like the above, not just 2. 3 of them is working correctly, and only 1 is not. Plus, there's another controller using all the scope methods above and all of them are showing the correct value.
Have you ever face such thing? What could be the problem behind this? Your input is appreciated.
Turns out this is because the query builder is effected by the given chain. The weird thing I mentioned about "local vs production" is likely doesn't gets noticed in the local because its only has a few records. I should've use clone() when chaining the builder. See the topic below for more information.
Laravel query builder - re-use query with amended where statement

Laravel Eloquent Model Return Human value

I Have a User model with the property is_active.
When i'm inside a foreach loop, I don't want to use the following:
echo if ( $user->is_active == 0 ) 'not active' : 'active'
What will be the best way to implement this? write a isActive() method on the User model and place the logic there?
There are a few approaches that you can take.
Approach 1: Acessor!
Create on your model:
public function getFormattedActiveMethod() {
return $this->attributes['active'] ? 'active' : 'not active';
}
And then you can use it like: $user->formattedActive (or whathever you want to call it, as long your method name matches getCamelCaseNameAttribute()).
You can also add this attribute into the $appends property array, so it will show up when you cast the model to array/json.
Approach 2: Presenter Pattern
Simply create a new class just to present data to your views. It's a good approach to prevent the Model from bloating and also separate your logic.
There are a few packages that helps you to achieve it, like robclancy/presenter, laracasts/Presenter, ShawnMcCool/laravel-auto-presenter and even League's Fractal, that can help you building a consistent API too.
Depending on the size of your project, it's better to take this approach.

How to exclude product(s) from search result programatically in Magento

I'm trying to exclude products from populating the search result.
It seems to be working fine on my localhost but not on clients dev server.
I'm observing the event
catalog_block_product_list_collection
and in observer method, in the end is this code:
$observer->getCollection()
->addFieldToFilter('entity_id', array('nin' => array_keys($_excludeProducts)))
->clear()
->load();
which works for catalog as well and search result list but for the moment not on search result list on clients dev server.
Any guidance/help is greatly appreciated.
Edit: Debugging this method gives me an empty collection but still the data is populating from somewhere.
I've changed the approach and used another event: catalog_product_collection_load_before
found better method to implement the approach with less code. #optimization
$excludeIds = array(2,3,4); //$excludeIds mixed
$observer->getCollection()
->addIdFilter($excludeIds, true); //exclude = true
The event also helps in keeping the correct items count on toolbar as it is dispatched before collection load.
I ran into a similar issue when trying to filter this collection using this event.
Do you have flat categories and flat products set the same in both environments? In my case, my code would only work with flat tables OFF, since I was using joining other EAV attributes.
In your case, if you are using flat, I think you just need to do addAttributeToFilter() instead.
In my case, here is what my observer looks like:
function onCategoryCollectionLoad($observer) {
$collection = $observer->getEvent()->getCategoryCollection();
$customerGroupId = (int) Mage::getSingleton('customer/session')->getCustomerGroupId();
// hidden_from_groups is an EAV attribute; I couldn't figure out how to make it work with flat because it has a backend_model
$collection->addAttributeToSelect('hidden_from_groups');
$collection->addExpressionAttributeToSelect('should_be_hidden', "COALESCE(FIND_IN_SET($customerGroupId, {{attribute}}), 0)", 'hidden_from_groups');
// should_be_hidden is not a real db field (nor EAV attribute); it only exists because of the addExpressionAttributeToSelect() above.
$collection->addFieldToFilter('should_be_hidden', array('lt' => 1));
// I don't call $collection->load(); that will get called further down the line.
}

How do I define relation between users and points in Eloquent ORM

I have 3 tables:
Users - for storing users
User_point - for associacion between users and points(has only user_id and point_id)
Points for description of points(id, amount, description)
How do I define a relation between these? I tried
public function points(){
return $this->belongsToMany('\App\Point', 'user_point');
}
but when I do
return $user->points()->sum('amount');
it returns just one
Edit:
At first I tried making it like this as it makes more sense:
public function points(){
return $this->hasMany('\App\Point');
}
But it wouldn't work
SUM is an aggregate function and so it should only return one row.
$user->points will be a collection of points attached to that user.
$user->points() is a query that you can do additional work against (i.e. $user->points()->whereSomething(true)->get()).
As user ceejayoz pointed out, using user->points() is going to return a builder which you can do additional work on. I believe using sum() on that will look at the first row returned which is what you indicated is actually happening.
Likely, what you really want to do is $user->points->sum('amount');
That will get the sum of that column for the entire collection.

Get a single entity from a magento model collection

I'm encountering an issue because I'm sure I'm not doing this correctly with my programming. I have created a custom model in Magento.
In the database table of my model there are several entities with the same attributes...
I need to pick just one from all these entities with the same attribute that I have. For the moment I did this:
$myvariable = Mage::getModel('test/test')->getCollection()
->setOrder('idserialkeys', 'asc')
->addFilter('idproduit', 1)
->addFilter('utilise', 0)
->addFilter('customerid', 0)
->addFilter('numcommande', 0)
From this loading I have around a hundred results but I need to update only one of these, so just after I'm doing:
->setPageSize(1);
The problem is that I need a foreach after to update my entity
foreach($mavaribale as $modifiemoi) {
// Update of my entity because of course there is only one
}
As you can see I'm obliged to do a loop (for each) even if I have a setPagesize... I would like to avoid this loop to optimize my code.
When you have a collection, and you only need one element, use the getFirstItem method. Try this:
$modifiemoi = $myvariable->getFirstItem();
Make sure that you also use your setPageSize call so that you only transfer data for one item.
All collections are Varien_Data_Collection objects so you can use getFirstItem:
$modifiemoi = $mavaribale->getFirstItem();

Resources