Sorting order items - magento

I've been trying lots of methods to achieve but none worked.
Please give me a hint how to to this.
I need to use a sort by sku on products that appear on an order print.
$order = Mage::getModel('sales/order')->load($order)
this is $order collection and a few lines below I have:
foreach ($order->getAllItems() as $item) { ... }
I need the sort to be applied on getAllItems before showing, obviously.
I hope I was clear enough, if not ask.

you might have already solved, but I will answer this for people having the same problem:
$oItems = $oOrder->getItemsCollection()->addAttributeToSort('price_incl_tax', 'DESC');
$aItems = array();
foreach ($oItems as $oItem) {
if (!$oItem->isDeleted()) {
$aItems[] = $oItem;
}
}
Hope this helps anyone.

Related

eager load and empty queries

I'm trying to put my catalog in cache by team.
Price may vary by team.
But if the price is not set for a product I need to send the "default" team value", and can't find an easy way to do this.
$teams = Team::all();
foreach ($teams as $team) {
$teamId = $team->id;
$catalog = Cache::rememberForever('catalog-' . $team->id, function () use ($teamId) {
$catalog = Category::with(['products.prices' => function ($q) use ($teamId) {
$q->where("team_id", $teamId); // and if no result $q->where("team_id",1);
}])->all();
return $catalog;
});
}
I was searching with queries like $q->whereNotExist, but I can't find a way to do it correctly. They may be some other way to do this via Product or Price model (and mutator), but I also stuck here.
Thank you.

Optimize a Deeply Nested Eloquent Loop

How would I take something with a crazy N+1 issue like:
foreach ($serie->categories as $category) {
foreach ($category->processes as $process) {
foreach ($process->cards as $card) {
foreach ($card->groups as $group) {
$group->upload;
}
}
}
}
And make it into one or two statements?
I'm using Laravel's Eloquent ORM.
You can do deeply nested eager loading with:
Serie::with('categories.processes.cards.groups')->get();
This already loads all processes per category, cards per process, etc.
Look at the documentation
$books = Book::with('author.contacts')->get();
If you want a quick way to get all groups, try:
$series = Serie::with('categories.processes.cards.groups')->get()->toArray();
$groups = array_pluck($series, 'categories.processes.cards.groups');
This returns the attributes for every group in array format. You only need to find a new way to perform the ->upload() method on the group object.

Display collection of Shopping cart rules and products categories associated to each rule

I want to check if there is a sales promotion on the product then stick the promotion label on that product on category list page. But I don't know how to loop through all the shopping cart rules and retrieve the products/categories associated to each rule.
EDITED
Thanks seanbreeden, but I can't pull the skus from $conditions. var_dump($conditions); shows this:
{s:4:"type";s:32:"salesrule/rule_condition_combine";s:9:"attribute";N;s:8:"operator";N;s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";}a:7:{s:4:"type";s:32:"salesrule/rule_condition_combine";s:9:"attribute";N;s:8:"operator";N;s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";s:10:"conditions";a:1:{i:0;a:7:{s:4:"type";s:42:"salesrule/rule_condition_product_subselect";s:9:"attribute";s:3:"qty";s:8:"operator";s:2:">=";s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";s:10:"conditions";a:1:{i:0;a:5:{s:4:"type";s:32:"salesrule/rule_condition_product";s:9:"attribute";s:12:"category_ids";s:8:"operator";s:2:"==";s:5:"value";s:2:"23";s:18:"is_value_processed";b:0;}}}}}a:7:{s:4:"type";s:32:"salesrule/rule_condition_combine";s:9:"attribute";N;s:8:"operator";N;s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";s:10:"conditions";a:2:{i:0;a:5:{s:4:"type";s:32:"salesrule/rule_condition_address";s:9:"attribute";s:13:"base_subtotal";s:8:"operator";s:2:">=";s:5:"value";s:2:"45";s:18:"is_value_processed";b:0;}i:1;a:7:{s:4:"type";s:42:"salesrule/rule_condition_product_subselect";s:9:"attribute";s:3:"qty";s:8:"operator";s:2:">=";s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";s:10:"conditions";a:1:{i:0;a:5:{s:4:"type";s:32:"salesrule/rule_condition_product";s:9:"attribute";s:3:"sku";s:8:"operator";s:2:"==";s:5:"value";s:46:"test-config, BLFA0968C-BK001, BLFA0968C-CR033X";s:18:"is_value_processed";b:0;}}}}}a:6:{s:4:"type";s:32:"salesrule/rule_condition_combine";s:9:"attribute";N;s:8:"operator";N;s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";}a:6:{s:4:"type";s:32:"salesrule/rule_condition_combine";s:9:"attribute";N;s:8:"operator";N;s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";}a:7:{s:4:"type";s:32:"salesrule/rule_condition_combine";s:9:"attribute";N;s:8:"operator";N;s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";s:10:"conditions";a:1:{i:0;a:7:{s:4:"type";s:42:"salesrule/rule_condition_product_subselect";s:9:"attribute";s:3:"qty";s:8:"operator";s:2:">=";s:5:"value";s:1:"1";s:18:"is_value_processed";N;s:10:"aggregator";s:3:"all";s:10:"conditions";a:1:{i:0;a:5:{s:4:"type";s:32:"salesrule/rule_condition_product";s:9:"attribute";s:3:"sku";s:8:"operator";s:2:"==";s:5:"value";s:16:"BLFA0968C-CR033X";s:18:"is_value_processed";b:0;}}}}}
but when I loop through $conditions i.e.
$rules = Mage::getResourceModel('salesrule/rule_collection')->load();
foreach ($rules as $rule) {
$conditions = $rule->getConditionsSerialized();
foreach ($conditions as $condition) {
var_dump($condition);
}
}
it doesn't show anything so don't really know how to pull skus here.
EDIT2
As Alaxandre suggested, I'm not using unserialized approach. I'm doing it like this now:
$rules = Mage::getResourceModel('salesrule/rule_collection')->load();
foreach ($rules as $rule) {
if ($rule->getIsActive()) {
//print_r($rule->getData());
$rule = Mage::getModel('salesrule/rule')->load($rule->getId());
$conditions = $rule->getConditions();
$conditions = $rule->getConditions()->asArray();
foreach( $conditions['conditions'] as $_conditions ):
foreach( $_conditions['conditions'] as $_condition ):
$string = explode(',', $_condition['value']);
for ($i=0; $i<count($string); $i++) {
$skus[] = trim($string[$i]);
}
endforeach;
endforeach;
}
}
return $skus;
And then checking in list page if sku matches within $skus array then show the label. But again there are limitation with this approach as well. I'm think of another approach (I'm not sure if thats is possible).
Thinking of creating a new table (to save the sales rules products).Everytime save the sales rule, catch the save rule event and update the table with Rule name and all the associated products. Then on the list page check that table, if products exist in the table, show the appropriate label. Now I think the event is adminhtml_controller_salesrule_prepare_save (not 100% sure) but I don't know how to get the sku from the rule condition in the observer to save in the new table.
I would suggest you to do it like this. When you had a product to cart, each rules are checked to calculate the final price and reduction. You can know which rules are applied to each item of your cart. In the table sales_flat_quote_item you have the column applied_rule_ids. I think you can access to this in php, by a function getAllItemsInCart or something like this (you have to find out). After you do $item->getAppliedRuleIds() and finally you can get the name of the rule apply to an item (product).
Good luck :)
Edit:
I read again your request and I think my answer doesn't fit with your request.
Your case is even more complicated. For each product on your catalog page you have to apply all the rules of your website. But Mage_SalesRule_Model_Validator process expect item and not product...
If you have lot of rules this task will slow down your catalog and this is really not good! The best would be to cache this result of the rules label in the database, may be in the table catalog_category_product or... (and even better to generate this cache automatically).
Edit2:
Other possibility would be to have a new field in rule creation where you set manually the related products (sku). You save this data in the table salesrule or in a new table salesrule_related_sku.
Then when you display the catalog you check for the sku and if the rule still active.
This solution would be the easiest one :-)
You could pull the getMatchingProductsIds from /app/code/core/Mage/CatalogRule/Model/Rule.php and compare them with the skus displayed on the category list page.
$catalog_rule = Mage::getModel('catalogrule/rule')->load(1); // ID of your catalog rule here, or you could leave off ->load(1) and iterate through ->getCollection() instead
$catalog_rule_skus = $catalog_rule->getMatchingProductIds();
hth
EDIT
Here's a way to get the serialized conditions:
$rules = Mage::getResourceModel('salesrule/rule_collection')->load();
foreach ($rules as $rule) {
$conditions = $rule->getConditionsSerialized();
var_dump($conditions);
}
EDIT 2
There would have to be a better way to do this. The only way I could pull that data was to unserialize then iterate with foreach through each layer. Anyone have any better ideas for this? This works but is very sloppy.
$rules = Mage::getResourceModel('salesrule/rule_collection')->load();
foreach ($rules as $rule) {
if ($rule->getIsActive()) {
$conditions = $rule->getConditionsSerialized();
$unserialized_conditions = unserialize($conditions);
$unserialized_conditions_compact = array();
foreach($unserialized_conditions as $key => $value) {
$unserialized_conditions_compact[] = compact('key', 'value');
}
for ($i=0;$i<count($unserialized_conditions_compact);$i++) {
if (in_array("conditions",$unserialized_conditions_compact[$i])) {
foreach($unserialized_conditions_compact[$i] as $key => $value) {
foreach($value as $key1 => $value1) {
foreach($value1 as $key2 => $value2) {
foreach($value2 as $key3 => $value3) {
$skus[] = explode(",",$value3['value']);
}
}
}
}
}
}
}
}
var_dump($skus);
The rules are associated to all product for a website. There is no rules set for a specific products/categories from the database point of view. For each product in the cart, Magento will validate all the rules you have for a website. This operation is done in the class Mage_SalesRule_Model_Validator. The only way to solve your request is to extend the function process from this class (at least I think so :p).
I wanted the same thing as you want. I wanted to get associated SKUS, Category Ids and any other conditions value to generate Google feeds to be used in Google merchant promotions.
I have used the recursive function to reach to last children of the condition and fetch its value.
I am checking based on the attribute value of the condition. If an attribute value is blank then go one step down and check if attribute value present and if so then fetch the value of it otherwise continue to go down.
Here is the code that I used to fetch values. Which will also work for the case, when two conditions are on the same level.
public function get_value_recursively($value){
foreach($value as $key => $new_value) {
if(strlen($new_value[attribute]) == 0){
$value = $new_value[conditions];
return $this->get_value_recursively($value);
}else{
$resultSet = array();
if (count($value) > 1){
for ($i=0;$i<count($value);$i++) {
$resultSet[] = array('attribute' => $value[$i][attribute], 'value' => $value[$i][value]);
}
$result = $resultSet;
}else{
$result = array('attribute' => $new_value[attribute], 'value' => $new_value[value]);
}
return json_encode($result, JSON_FORCE_OBJECT);
}
}
}
according to #seanbreeden answer you can call this function from first foreach
It will return the result like this :
{"0":{"attribute":"category_ids","value":"5, 15"},"1":{"attribute":"sku","value":"msj000, msj001, msj002"}}
P.S. I am not PHP dev. So, Ignore layman style code. :)

How do I get details for the products that were ordered on the success page in Magento?

I was able to get order details and customer details inside template/checkout/success.html file, but not sure how to get details for the exact products that were ordered? I need their names for some third party stat appliances. I bet it's simple - just another weird chained call to some "where-did-this-come-from?" method...
Help?
do (as you have order model)
$order_items = $order->getAllItems();
foreach($order_items as $item) {
$product = Mage::getModel('catalog/product')->load($item->getProductId());
//and you can do what ever you want with the product
}
You can retrieve the order details like:
$order = Mage::getModel('sales/order')->load(Mage::getSingleton('checkout /session')->getLastOrderId());
Then you can pull in all the various data with this:
$subtotal = $order->getSubtotal();
$order->getId();
$order->getIncrementId();
$order->getGrandTotal();

Magento Tracking Number from Order Object

Given a magento order object how can I find the tracking number associated with that order?
$order = Mage::getModel('sales/order')->loadByIncrementId(100000064);
$shipmentCollection = Mage::getResourceModel('sales/order_shipment_collection')
->setOrderFilter($order)
->load();
foreach ($shipmentCollection as $shipment){
// This will give me the shipment IncrementId, but not the actual tracking information.
$shipment->getData();
}
I struggled over this one too, returning null values. Finally figured it out though. First, as previously noted, retrieve the shipment collection associated with the given order:
$shipmentCollection = Mage::getResourceModel('sales/order_shipment_collection')
->setOrderFilter($order)
->load();
foreach ($shipmentCollection as $shipment){
// This will give me the shipment IncrementId, but not the actual tracking information.
foreach($shipment->getAllTracks() as $tracknum)
{
$tracknums[]=$tracknum->getNumber();
}
}
The array $tracknums will now contain each of the tracking numbers linked to this order/shipment.
Try the code below: Its not tested though.
$shipment->getAllTracks();
You can simply do this:
$order = Mage::getModel('sales/order')->loadByIncrementId(100000064);
$trackNumber = array();
foreach ($order->getTracksCollection() as $track){
$trackNumber[] = $track->getNumber();
}
use
$order->getTrackingNumbers()
It should be
Mage::getResourceModel('sales/order_shipment_collection')
->setOrderFilter($order)
->load();

Resources