PHP woocommerce CSV array item count - php

I'm trying to exclude/ignore a specific item from a 'count' in an array which generates a CSV file.
I generate a daily CSV file of orders from Woocommerce;
Each Order is made up of a quantity of varying single products;
I define the CSV Headers manually -eg:
$csv_header = array('Order ID','Company Name','Contact Name','Address 1','Address 2','Suburb','Product 1', 'Product 2', 'Product 3','#Items')
I pull the metadata based on Order IDs:
$result = $wpdb->get_results('SELECT * FROM `'.$wpdb->prefix.'postmeta` WHERE post_id = '. (int)$order_id->ID);
I create an instance of each order and get the items:
$order = new WC_Order((int)$order_id->ID);
$items = $order->get_items();
After getting the details and setting the column for those - eg:
if( $res->meta_key == '_shipping_company'){
$order_line[2] = $res->meta_value;
I then loop to create the invidual item product count and the #items total
foreach ($items as $item ) {
$_count = array_search( $item['name'], $csv_header );
$order_line[$_count] = $item['item_meta']['_qty'][0];
$row_items += $order_line[$_count];
}
$order_line[10] = $row_items;
and add blanks to products not in the order:
for ($i = 0; $i < 37; $i++) {
if( !isset($order_line[$i]) && empty($order_line[$i]) ) {
$order_line[$i] = '';
}
This all works well, but now I need to EXCLUDE a product NOT defined in the $csv_header from the count - bearing in mind that the Order will contain defined products. eg: count products 1-3 but not Product 4.
At the moment if a Product is not defined in $csv-header, it will put a number in my first column in place of the order-id instead of ignoring it.
Any suggestions appreciated.

Related

Change all items price in cart with laravel

I am creating a webshop for a rental company. I want to be able to change the price of items according to amount of days they rent the item. I was already able to get the amount of days, but not sure on how to change the price of an item.
This is my code so far in the cart controller.
The error I get is that $rowId is not defined.
public function getTime(Request $request){
$startD = Carbon::parse($request->input('dateOut'));
$endD = Carbon::parse($request->input('dateIn'));
$length = $endD->diffInDays($startD) + 1;
$total = Cart::subtotal();
$rows = Cart::count();
for ($i=0; $i <$rows ; $i++) {
$item = Cart::get($rowId);
Cart::update(
$rowId, [
'price' => $items->product_price*$length,
]);
}
echo $startD;
echo $endD;
echo $length;
echo $total;
}
If you are updating the price of a specific cart, then you can use such a query.
\DB::statement("update carts set price = ABS(`price` * datediff(?,?)) where id=?", [$dateOut, $dateIn, $cart_id]);

Different Order Id for order from multiple restaurants

I am trying to place an order from multiple restaurants. When I place an order, same Order ID is adding in the database for orders. What I would like to have is, When the user places an order from multiple restaurants, I would like to have separate Order ID for them.
Here is my code:
$order_id = $this->generateNewOrderId();
foreach ($cart_content->rest_item_list as $item)
{
$td_data['order_id'] = $order_id;
$td_data['item_id'] = $item->id;
$i_details = $this->restaurant_menu_items_model->get_item_detail_by_id($item->id);
$td_data['item_name'] = $i_details->name;
$td_data['item_price'] = $i_details->price;
$td_data['item_quantity'] = $item->quantity;
}
Well this stands to reason, since you're generating an order ID only once, outside the loop, not once per order. Just move it inside the loop:
foreach ($cart_content->rest_item_list as $item) {
$order_id = $this->generateNewOrderId();
$td_data['order_id'] = $order_id;
//... etc ...

Where should i write db_select() from foreach loop so that it will reduce performance issue?

i have been working on performance improvement in drupal for that i wanted to remove db_select() query which is inside foreach loop to improve performace.
here i am adding my code
foreach( $order->commerce_line_items['und'] as $line_item ) {
$line_item = commerce_line_item_load($line_item['line_item_id']);
$product = commerce_product_load($line_item->commerce_product['und'][0] ['product_id']);
$stock = $product->commerce_stock['und'][0]['value'];
$query = db_select('commerce_order', 'c');
$query->join('commerce_line_item', 'l', 'c.order_id = l.order_id');
$query->addExpression('SUM(quantity)', 'quantity');
$query->condition('l.line_item_label', $product->sku, '=');
$query->condition('c.status', 'completed', '<>');
$result = $query->execute()->fetchAssoc();
$quantity = $result['quantity'];
if ( ($stock > 0) && ($quantity > $stock) ) {
$num_updated = db_update('commerce_order')
->fields(array(
'status' => 'manufacturer'
))
->condition('order_id', arg(1), '=')
->execute();
}
}
You have multiple queries to the DB in the loop that could be moved.
Each call to commerce_ENTITY_TYPE_load is a DB access. You should use the commerce_ENTITY_TYPE_load_multiple function. This imply collecting all the needed object in arrays, indexed by their respective IDs, which requires some basic boiler plate code.
// Collect line item IDs (indexed by delta);
$line_item_ids = array_map(function ($line_item) {
return $line_item['line_item_id'];
}, field_get_items('commerce_order', $oder, 'commerce_line_items'));
// Get line items, indexed by IDs.
$line_items = commerce_line_items_load_multiple($line_item_ids);
// Collect product IDs, indexed by line item IDs.
$product_ids = array_map(function ($line_item) {
return field_get_items('commerce_line_item', $line_item, 'commerce_product')[0]['product_id'];
}, $line_items);
// Get products, indexed by IDs.
$products = commerce_product_load_multiple($product_ids);
The custom select query is used to retrieve the quantity of a line item matching the SKU of the product for the line item. And you already loaded all the line items and product as entities. So there is no need for more database query and usage of the SKU. Also, since the query update the order itself once a line item with quantity > stock is found, you can break the loop for the first item which does.
foreach ($line_items as $line_item_id => $line_item) {
$product = $products[$products_ids[$line_item_id]];
$stock = field_get_items('commerce_product', $product, 'commerce_stock')[0]['value'];
$quantity = $line_item->quantity;
if (($stock > 0) && ($quantity > $stock)) {
$num_updated = db_update('commerce_order')
->fields(array(
'status' => 'manufacturer'
))
->condition('order_id', $order->order_id)
->execute();
break;
}
}

Magento: Accessing catalog and cart rule data

I'm building an extension that exports completed order information into a CSV file. I've been able to successfully access order and item information for the export but I'm having a problem accessing promotion data.
I'm looking to include the promotion data (catalog and cart rules) that are applied to that order in the export. Specifically I am trying to access the rule ids, names, descriptions, codes and applied dollar amount for a list of specific orders.
How would I access the promotion data in my extension?
If it helps, here is how I am currently accessing order/item data in my extension (qualifying by date frame):
$rows = array(); // array to hold data that will be exported to CSV
$read = Mage::getSingleton('core/resource')->getConnection('core_read');
$orders = $read->query("SELECT entity_id FROM sales_flat_order WHERE created_at >= '$from' AND created_at < '$today'");
while ($row = $orders->fetch()) {
$order = Mage::getModel('sales/order')->load($row['entity_id']);
$order_items = $read->query("SELECT item_id FROM sales_flat_order_item WHERE order_id={$order->getId()}");
while ($item_row = $order_items->fetch()) {
$item = Mage::getModel('sales/order_item')->load($item_row['item_id']);
$rows[] = array(
$order->getRealOrderId(),
$order->getCreatedAt(),
$item->getSky(),
$item->getQtyOrdered(),
..... );
); // end item loop
); // end order loop
Thanks in advance for any help you can provide,
-Mark
I believe this question has been answered on another question in the past. You can find the link to the original question and answer here Magento - get price rules from order
From that answer though..
//The order I want to check
$order_id = 859;
//Get the list of items for your order
$items = Mage::getModel('sales/order_item')
->getCollection()
->addFilter('order_id',array('eq'=>$order_id));
//loop through each item
foreach($items as $item){
//if the item has not had a rule applied to it skip it
if($item->getAppliedRuleIds() == '')continue;
/*
* I cant remember in the database they might be comma separated or space if multiple rules were applied
* the getAppliedRuleIds() function is the one you want
*/
foreach(explode(",",$item->getAppliedRuleIds()) as $ruleID){
//Load the rule object
$rule = Mage::getModel('catalogrule/rule')->load($ruleID);
// Throw out some information like the rule name what product it was applied to
echo "<p>".$item->getSku()." had rule ".$rule->getName()."(".$item->getAppliedRuleIds().") applied </p>";
}
}

Magento - How to convert simple products to grouped ones programmat​ically?

My client and I are trying to achieve something that we are maybe not supposed to do. We have a demanding set of non-standard products that include different types of product conditions, e.g. grade B ware etc. In addition product data is coming in in form of feeds from several suppliers. In order not to clutter up the product listing we would like to convert existing, manually edited simple products into grouped ones (or whatever is appropriate) with associated new simple products programmatically on the fly and vice versa whenever necessary, i.e. when there are at least two different sub products.
So far we managed to do this somehow, a test scenario produces the seemingly right product structure – correctly associated products are displayed in the backend, the quantities have been correct before. The problem occurs with the frontend check on 'isSaleable()' for both the grouped product and the associated products, it returns 'false' no matter what we do. When we enforce the display of the qty input boxes and add-to-cart button they will (naturally?) just product the error message 'Please specify the quantity of product(s)'. We tried to set 'is_salable' by different means throughout the code. What else is missing? Any little hint, any advice here would be appreciated!
The code is quite lengthy already, and probably there's already some redundancy in there because of our attempts to somehow fix this. There's a main script that fetches a product collection and compares each entry with the existing supplier feeds. The essential part then is the function call to convert the product:
if (sizeof($newProducts[$productsSku]) > 1 && $_product->getTypeId() == 'simple') {
$newProductQtys = createGroupedProduct($_product, $newProducts[$productsSku]);
}
There are 2 functions for the actual conversion process, one which creates duplicates of the master products (type = simple) and sets their values accordingly:
function createDuplicate($product, $values) {
global $suppliers, $conditions_arr;
$sku = $product->getSku();
$newSku = $sku.'-v'.$suppliers[$values['feed']]['id'];
$qty = $values['qty'];
$feed = $values['feed'];
$cost = $values['cost'];
$item_condition = $values['item_condition'];
$box_condition = $values['box_condition'];
$notes = stripslashes($values['notes']);
$newProduct = $product->duplicate();
$newProduct->setTypeId('simple');
$newProduct->setStoreId(0);
$newProduct->setWebsiteIds(array(1));
$newProduct->setVisibility(2);
$newProduct->setSku($newSku);
$newProduct->setData('media_gallery', array());
$newProduct->setStatus(Mage_Catalog_Model_Product_​Status::smileyfrustrated:TATUS_ENABLED);
$newProduct->setPrice((real)($cost + $cost*$suppliers[$feed]['price_increase']));
$newProduct->setTaxClassId(2);
$newProduct->getResource()->save($newProduct);
$productId = $newProduct->getId();
// Check if there is a stock item object
$stockItem = Mage::getModel('cataloginventory/stock_item')->loa​dByProduct($productId);
$stockItemData = $stockItem->getData();
if (empty($stockItemData)) {
// Create the initial stock item object
$stockItem->setData('inventory_manage_stock_defaul​t', 1);
$stockItem->setData('manage_stock',1);
$stockItem->setData('is_in_stock', $qty ? 1 : 0);
$stockItem->setData('is_salable', 1);
$stockItem->setData('use_config_manage_stock', 1);
$stockItem->setData('stock_id',1);
$stockItem->setData('product_id',$productId);
$stockItem->setData('qty',$qty);
$stockItem->setTypeId( $newProduct->getTypeId() );
$stockItem->save();
// Init the object again after it has been saved so we get the full object
$stockItem = Mage::getModel('cataloginventory/stock_item')->loa​dByProduct($productId);
}
// Set the quantity
$stockItem->setData('qty',$qty);
$stockItem->setData('is_salable', 1);
$stockItem->save();
// $newProduct->assignProduct($newProduct, 1, 1);
$newProduct->setIsSalable(1);
$newProduct->setStatus(Mage_Catalog_Model_Product_​Status::smileyfrustrated:TATUS_ENABLED);
$newProduct->save();
$event = Mage::getSingleton('index/indexer')->logEvent($new​Product,$newProduct->getResource()->getType(),Mage​_Index_Model_Event::TYPE_SAVE,false);
Mage::getSingleton('index/indexer')->getProcessByC​ode('cataloginventory_stock')->setMode(Mage_Index_​Model_Process::MODE_REAL_TIME)->processEvent($even​t);
return $productId;
}
and
function createGroupedProduct($product, $newProductsArr) {
global $suppliers;
$origProductId = $product->getId();
$sku = $product->getSku();
$newProductId = array();
$newProductQtys = array();
$qty = 0;
$price = 999999;
$product->setTypeId('grouped');
$product->save();
foreach($newProductsArr as $key => $values) {
$id = createDuplicate($product, $values);
$newProductId[] = $id;
$newProductQtys[$id] = $values['qty'];
// add up all stock quantities of all slave products for master
$qty += $values['qty'];
// determine lowest price among all slave products
$subItemPrice = (real)($values['cost'] + $values['cost']*$suppliers[$values['feed']]['price​_increase']);
if ($subItemPrice < $price) $price = $subItemPrice;
}
if (sizeof($newProductId) > 1) {
$products_links = Mage::getModel('catalog/product_link_api');
foreach($newProductId as $key => $id) {
$products_links->assign('grouped', $origProductId, $id);
}
}
// set new values for grouped product according to slave products values
$product->setPrice($price);
$product->getResource()->save($product);
// Check if there is a stock item object
$stockItem = Mage::getModel('cataloginventory/stock_item')->loa​dByProduct($origProductId);
$stockItemData = $stockItem->getData();
if (empty($stockItemData)) {
// Create the initial stock item object
$stockItem->setData('manage_stock',1);
$stockItem->setData('is_in_stock', $qty ? 1 : 0);
$stockItem->setData('is_salable', 1);
$stockItem->setData('use_config_manage_stock', 1);
$stockItem->setData('stock_id',1);
$stockItem->setData('product_id',$origProductId);
$stockItem->setData('qty',$qty);
// $stockItem->setTypeId( $product->getTypeId() );
$stockItem->setTypeId('grouped');
$stockItem->save();
// Init the object again after it has been saved so we get the full object
$stockItem = Mage::getModel('cataloginventory/stock_item')->loa​dByProduct($origProductId);
}
// Set the quantity
$stockItem->setData('qty',$qty);
$stockItem->setData('is_in_stock', $qty ? 1 : 0);
$stockItem->setData('is_salable', 1);
$stockItem->save();
$product->setStatus(Mage_Catalog_Model_Product_Sta​tus::smileyfrustrated:TATUS_ENABLED);
$product->save();
$event = Mage::getSingleton('index/indexer')->logEvent($pro​duct,$product->getResource()->getType(),Mage_Index​_Model_Event::TYPE_SAVE,false);
Mage::getSingleton('index/indexer')->getProcessByC​ode('cataloginventory_stock')->setMode(Mage_Index_​Model_Process::MODE_REAL_TIME)->processEvent($even​t);
$cache = Mage::getSingleton('core/cache');
$cache->flush();
return $newProductQtys;
}
We tried using the store ID '1' as well and had some success with the shopping cart when the front end used the same kind of mass-product-add-to-cart form that we integrated into the product listing. But the associated products then showed no product name and no image, and not in the admin at all.
If more code from the main script is necessary I will happily provide this.

Categories