I want to add values from Custom Attribute to short description of Configurable Product in Magento. I am using SCP module to show dynamically short description, title and price for this one regarding to "Associated Simple Products ". The price, Title and short description work fine but it not change the long description and not show the custom Attributes associated to Simple product.
Can some body help me with this problem? I need some indication how can I do that?
I think that I can do it on the original file configurable.php from SCP (Simple Configurable products) module that I attached to this post but I am not sure.
Thank you in advance.
public function getJsonConfig()
{
$config = Zend_Json::decode(parent::getJsonConfig());
$childProducts = array();
//Create the extra price and tier price data/html we need.
foreach ($this->getAllowProducts() as $product) {
$productId = $product->getId();
$childProducts[$productId] = array(
"price" => $this->_registerJsPrice($this->_convertPrice($product->getPrice())),
"finalPrice" => $this->_registerJsPrice($this->_convertPrice($product->getFinalPrice()))
);
if (Mage::getStoreConfig('SCP_options/product_page/change_name')) {
$childProducts[$productId]["productName"] = $product->getName();
}
if (Mage::getStoreConfig('SCP_options/product_page/change_description')) {
$childProducts[$productId]["description"] = $product->getDescription();
}
if (Mage::getStoreConfig('SCP_options/product_page/change_short_description')) {
$childProducts[$productId]["shortDescription"] = $product->getShortDescription();
}
if (Mage::getStoreConfig('SCP_options/product_page/change_attributes')) {
$childBlock = $this->getLayout()->createBlock('catalog/product_view_attributes');
$childProducts[$productId]["productAttributes"] = $childBlock->setTemplate('catalog/product/view/attributes.phtml')
->setProduct($product)
->toHtml();
}
#if image changing is enabled..
if (Mage::getStoreConfig('SCP_options/product_page/change_image')) {
#but dont bother if fancy image changing is enabled
if (!Mage::getStoreConfig('SCP_options/product_page/change_image_fancy')) {
#If image is not placeholder...
if($product->getImage()!=='no_selection') {
$childProducts[$productId]["imageUrl"] = (string)Mage::helper('catalog/image')->init($product, 'image');
}
}
}
}
//Remove any existing option prices.
//Removing holes out of existing arrays is not nice,
//but it keeps the extension's code separate so if Varien's getJsonConfig
//is added to, things should still work.
if (is_array($config['attributes'])) {
foreach ($config['attributes'] as $attributeID => &$info) {
if (is_array($info['options'])) {
foreach ($info['options'] as &$option) {
unset($option['price']);
}
unset($option); //clear foreach var ref
}
}
unset($info); //clear foreach var ref
}
$p = $this->getProduct();
$config['childProducts'] = $childProducts;
if ($p->getMaxPossibleFinalPrice() != $p->getFinalPrice()) {
$config['priceFromLabel'] = $this->__('Price From:');
} else {
$config['priceFromLabel'] = $this->__('');
}
$config['ajaxBaseUrl'] = Mage::getUrl('oi/ajax/');
$config['productName'] = $this->getProduct()->getName();
$config['description'] = $this->getProduct()->getDescription();
$config['shortDescription'] = $this->getProduct()->getShortDescription();
if (Mage::getStoreConfig('SCP_options/product_page/change_image')) {
$config["imageUrl"] = (string)Mage::helper('catalog/image')->init($this->getProduct(), 'image');
}
$childBlock = $this->getLayout()->createBlock('catalog/product_view_attributes');
$config["productAttributes"] = $childBlock->setTemplate('catalog/product/view/attributes.phtml')
->setProduct($this->getProduct())
->toHtml();
if (Mage::getStoreConfig('SCP_options/product_page/change_image')) {
if (Mage::getStoreConfig('SCP_options/product_page/change_image_fancy')) {
$childBlock = $this->getLayout()->createBlock('catalog/product_view_media');
$config["imageZoomer"] = $childBlock->setTemplate('catalog/product/view/media.phtml')
->setProduct($this->getProduct())
->toHtml();
}
}
if (Mage::getStoreConfig('SCP_options/product_page/show_price_ranges_in_options')) {
$config['showPriceRangesInOptions'] = true;
$config['rangeToLabel'] = $this->__('to');
}
//Mage::log($config);
return Zend_Json::encode($config);
//parent getJsonConfig uses the following instead, but it seems to just break inline translate of this json?
//return Mage::helper('core')->jsonEncode($config);
}
Related
My products have variable sizes which affect weight and I need to put weight logic in the cart to more accurately calculate shipping costs. I've moved a copy of app/code/core/Mage/Sales/Model/Quote/Item.php to the local code pool. I've been able to grab the associated product's base weight, however, I am not able to get the custom option (text field) value to do the math calculation before updating the cart. I'm doing this in the public function, setProduct. Here's what I have so far:
public function setProduct($product)
{
if ($this->getQuote()) {
$product->setStoreId($this->getQuote()->getStoreId());
$product->setCustomerGroupId($this->getQuote()->getCustomerGroupId());
}
//Get the Weight per UOM
$sku = $product->getSku();
$item = Mage::getModel('catalog/product')->loadByAttribute('sku',$sku);
$wpuom = $item->getResource()->getAttribute('weight_per_uom')->getFrontend()->getValue($item);
//Get the Length
$params = Mage::app()->getRequest()->getParams();
/** #var Mage_Catalog_Model_Product $product */
$info = new Varien_Object($params);
// Don't throw an exception if required options are missing
$processMode = Mage_Catalog_Model_Product_Type_Abstract::PROCESS_MODE_LITE;
$options = array();
foreach ($product->getOptions() as $option) {
/* #var $option Mage_Catalog_Model_Product_Option */
$group = $option->groupFactory($option->getType())
->setOption($option)
->setProduct($product)
->setRequest($info)
->setProcessMode($processMode)
->validateUserValue($info->getOptions());
$optionValue = $info->getData('options/' . $option->getId());
$options[] = array(
'label' => $option->getTitle(),
'value' => $group->getFormattedOptionValue($optionValue),
'value2' => $option->getValues(),
'option_id' => $option->getId(),
'option_type' => $option->getType()
);
//<<<This is Where I Cannot Get the Value for the Custom Option>>>
if($options[0]['label'] == 'Length') {
//print_r($options[0]['value']);
}
}
//Update Weight
$baseWeight = $item->getWeight();
$uom = $item->getResource()->getAttribute('uom')->getFrontend()->getValue($item);
if((($uom == 'Meters') && ($length >= 76)) || (($uom == 'Feet') && ($length >= 250))) { $spoolWeight = 3; }
else { $spoolWeight = 0; }
$finalWeight = ($baseWeight + ($length * $wpuom) + $spoolWeight);
$this->setData('product', $product)
->setProductId($product->getId())
->setProductType($product->getTypeId())
->setSku($this->getProduct()->getSku())
->setName($product->getName())
->setWeight($this->getProduct()->getWeight())
->setTaxClassId($product->getTaxClassId())
->setBaseCost($product->getCost())
->setIsRecurring($product->getIsRecurring());
if ($product->getStockItem()) {
$this->setIsQtyDecimal($product->getStockItem()->getIsQtyDecimal());
}
Mage::dispatchEvent('sales_quote_item_set_product', array(
'product' => $product,
'quote_item' => $this
));
return $this;
}
When I try adding print_r($options[0]);, I get everything except value, it's not even an array. What am I missing in order to get the value?
You're likely going to run into issues with the wishlist and other functionality if you display the product price in various spots on your site such as category pages, wishlist and other areas on the site.
That being said, I made some modifications to your code and updated it below. I took a slightly different approach to get the end result. First, get all the cart items for the current session. If the product type is configurable, do some logic, if not, do other logic. Inside the logic, I am gathering the items, associated attribute values, custom options, and custom option values. I also added some functionality to add the length and the unit of measure to the sku. Then I went ahead and showed examples of how you can use direct mySQL queries to update the database with your new pricing, skus, weight, and other details.
public function setProduct($product)
{
if ($this->getQuote()) {
$product->setStoreId($this->getQuote()->getStoreId());
$product->setCustomerGroupId($this->getQuote()->getCustomerGroupId());
}
$quote = Mage::getSingleton('checkout/session')->getQuote();
foreach ($quote->getAllVisibleItems() as $itm){
$sku = $product->getSku();
$item = Mage::getModel('catalog/product')->loadByAttribute('sku',$sku);
$assocProd = Mage::getModel('catalog/product')->loadByAttribute('sku',$itm->getSku());
if($product->getTypeId() == 'configurable') { //configurable product
foreach ($product->getOptions() as $o) {
if($o->getTitle() == "YOUR CUSTOM OPTION LABEL" && $o->getType() == "field"){
$optionId = $o->getOptionId();
$opz = $itm->getOptionByCode('info_buyRequest');
$buyRequest = new Varien_Object($opz ? unserialize($opz->getValue()) : null);
foreach($buyRequest['options'] as $key => $value){
if($key == $optionId) {
$length = $value;
//here is your length... do with it what you please
}
//example of how to update the database
$itemId = $itm->getId();
$query = 'UPDATE `sales_flat_quote_item` SET `weight` = "'.$finalWeight.'", `display_sku` = "'.$displaySku.'" WHERE `item_id` = "'.$itemId.'"';
$resource = Mage::getSingleton('core/resource');
$writeConnection = $resource->getConnection('core_write');
$writeConnection->query($query);
}
}
}
}
}
else { //simple product
if($product->getOptions()) { //has options
foreach ($product->getOptions() as $o) {
if($o->getTitle() == "YOUR OPTION LABEL" && $o->getType() == "field"){
$optionId = $o->getOptionId();
$opz = $itm->getOptionByCode('info_buyRequest');
$buyRequest = new Varien_Object($opz ? unserialize($opz->getValue()) : null);
foreach($buyRequest['options'] as $key => $value){
$finalWeight = '';
if($key == $optionId) {
$length = $value;
//here's your length value for simple products
}
//to update the database
$itemId = $itm->getId();
$query = 'UPDATE `sales_flat_quote_item` SET `weight` = "'.$finalWeight.'", `display_sku` = "'.$displaySku.'" WHERE `item_id` = "'.$itemId.'"';
$resource = Mage::getSingleton('core/resource');
$writeConnection = $resource->getConnection('core_write');
$writeConnection->query($query);
}
}
}
}
}
else { //doesn't have options
//this would be your logic for a simple product with no options
}
}
I hope this helps and feel free to let me know if you have any questions!
I am generating orders from a custom web service called from a mobile app. However when the order is finally generated, I get "Original Price" as Rs0.00 . This is creating a problem since we have third party integrations for invoicing and Shipping.
However in the normal course of action when order is generated from website, the Original Price is correct.
I inspected the sales_flat_order_item table for both these orders, the original_price is indeed 0.00 in the first order, Hence I must be missing something in my code which is not setting the original_price for the orderItem.
Here is the code where the quote is converted to order.
public function placeorder($custid, $Jproduct, $store, $address, $couponCode, $is_create_quote, $transid, $payment_code, $shipping_code, $currency, $message)
{
$res = array();
$quantity_error = array();
try {
$quote_data = $this->prepareQuote($custid, $Jproduct, $store, $address, $shipping_code, $couponCode, $currency, 1, 0);
if ($quote_data["status"] == "error") {
return $quote_data;
}
$quote = Mage::getModel('sales/quote')->load($quote_data['quote_id']);
$quote = $this->setQuoteGiftMessage($quote, $message, $custid);
$quote = $this->setQuotePayment($quote, $payment_code, $transid);
$convertQuote = Mage::getSingleton('sales/convert_quote');
try {
$order = $convertQuote->addressToOrder($quote->getShippingAddress());
}
catch (Exception $Exc) {
echo $Exc->getMessage();
}
$items = $quote->getAllItems();
foreach ($items as $item) {
$orderItem = $convertQuote->itemToOrderItem($item);
$order->addItem($orderItem);
}
try {
$decode_address = json_decode(base64_decode($address));
$order->setCustomer_email($decode_address->billing->email);
$order->setCustomerFirstname($decode_address->billing->firstname)->setCustomerLastname($decode_address->billing->lastname);
}
catch (Exception $e) {
}
$order->setBillingAddress($convertQuote->addressToOrderAddress($quote->getBillingAddress()));
$order->setShippingAddress($convertQuote->addressToOrderAddress($quote->getShippingAddress()));
$order->setPayment($convertQuote->paymentToOrderPayment($quote->getPayment()));
$order->save();
$quantity_error = $this->updateQuantityAfterOrder($Jproduct);
$res["status"] = 1;
$res["id"] = $order->getId();
$res["orderid"] = $order->getIncrementId();
$res["transid"] = $order->getPayment()->getTransactionId();
$res["shipping_method"] = $shipping_code;
$res["payment_method"] = $payment_code;
$res["quantity_error"] = $quantity_error;
$order->addStatusHistoryComment("Order was placed using Mobile App")->setIsVisibleOnFront(false)->setIsCustomerNotified(false);
if ($res["orderid"] > 0 && ($payment_code == "cashondelivery" || $payment_code == "banktransfer" || $payment_code == "free")) {
$this->ws_sendorderemail($res["orderid"]);
$order->setState(Mage_Sales_Model_Order::STATE_NEW, true)->save();
$res["order_status"] = "PENDING_PAYMENT";
} else {
$order->setState(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT, true)->save();
$res["order_status"] = "PENDING_PAYMENT";
}
}catch (Exception $except) {
$res["status"] = 0;
$res["shipping_method"] = $shipping_code;
$res["payment_method"] = $payment_code;
}
return $res;
}
It would be very helpful if someone points out what I missed. I will edit if any other info is required.
Missing original_price indicates that you didn't run collectTotals() on the quote yet, try the following:
$quote->collectTotals()->save();
$order->save();
i am tyring to add categories programmatically for german and english languages.
website-ID: 1
website store-ID: 1
view-ID english, code "en" => 1
view-ID german, code "de" => 2
$category['general']['path'] = $v['cat_name_de'];
$category['general']['name'] = $v['cat_name_de'];
$category['general']['meta_title'] = "";
$category['general']['meta_description'] = "";
$category['general']['is_active'] = 1;
$category['general']['url_key'] = urlencode($v['cat_name_de']);
$category['general']['display_mode'] = "PRODUCTS";
$category['general']['is_anchor'] = 0;
$category['category']['parent'] = $v['magento_cat_id'];
$storeId = 0; // default
$magento_subcat_id = createCategory($category, $storeId);
...
function createCategory($data, $storeId) {
echo "Erzeuge '{$data['general']['name']}' - Elternkategorie:
[{$data['category']['parent']}] ...";
$category = Mage::getModel('catalog/category');
$category->setStoreId($storeId);
if (is_array($data)) {
$category->addData($data['general']);
if (!$category->getId()) {
$parentId = $data['category']['parent'];
if (!$parentId) {
if ($storeId) {
$parentId = Mage::app()->getStore($storeId)->getRootCategoryId();
} else {
$parentId = Mage_Catalog_Model_Category::TREE_ROOT_ID;
}
}
$parentCategory = Mage::getModel('catalog/category')->load($parentId);
$category->setPath($parentCategory->getPath());
}
if ($useDefaults = $data['use_default']) {
foreach ($useDefaults as $attributeCode) {
$category->setData($attributeCode, null);
}
}
$category->setAttributeSetId($category->getDefaultAttributeSetId());
if (isset($data['category_products']) &&
!$category->getProductsReadonly()) {
$products = array();
parse_str($data['category_products'], $products);
$category->setPostedProducts($products);
}
try {
$category->save();
return $category->getId();
} catch (Exception $e) {
return FALSE;
}
}
}
What i am puzzling with at the moment is setting view-ID individually for passing the $category['general']['name'] for each language.
I tried to set each language string with a foreach setting english/german texts. But this did not work out, because i somehow mixed up setting the view correctly.
To make it short:
Creating categories and subcategories like this does work very good, but i do not get it to work to pass english/german categoty titles.
Thanks guys
For all of you who are struggeling with this situation i made a workaound like this:
I added all those values to the affected database tables directly. This is for sure a quick and dirty way, but it does the job.
For all in need of some ideas here is the (undocumented) snipped belonging to my initial post.
// Get values for next language insert
$entity_type_id = $category
->getResource()
->getTypeId();
$entity_id = $category->getEntityId();
$read_entity = Mage::getSingleton('core/resource')
->getConnection('core_write');
$sql_entity = "SELECT * FROM eav_attribute WHERE
`attribute_code` = 'name' AND
`entity_type_id` = " . $entity_type_id . ";";
$row_entity = $read_entity
->fetchRow($sql_entity);
$attribute_id = $row_entity['attribute_id'];
// prepare value for name field in different langauge
$val = Mage::getSingleton('core/resource')
->getConnection('default_write')
->quote($v['en']);
$sql_insert = "INSERT INTO `catalog_category_entity_varchar`
(`entity_type_id`,`attribute_id`,`store_id`,`entity_id`,`value`)
VALUES ($entity_type_id,$attribute_id,$storeId,$entity_id,$val);";
$read_entity->query($sql_insert);
I hope this helps someone out who is in need of this.
I have an order that looks like this:
I want to create a shipment for the following on this order (not for everything):
2 x VCF001
1 x SBA364
To achieve this, I found the following info on the shipment api: http://bit.ly/17rpuwj
Based on this documentation of the API, I came up with the following code. When I tried to execute it, I got the following error Cannot create an empty shipment:
$order_number = '300000002';
$order = Mage::getModel('sales/order')->loadByIncrementId($order_number);
$allocations = array(
array('sku' => 'VCF001', 'allocated_qty' => 2),
array('sku' => 'SBA364', 'allocated_qty' => 1)
);
function GetOrderItemId($order_items, $sku) {
foreach ($order_items as $order_item) {
if ($order_item->getSku() == $sku) {
return $order_item->getItemId();
}
}
return 0;
}
function CreateShipment($order, $allocations)
{
// Get Order Items
$order_items = $order->getItemsCollection();
// Parepare Item Qtys For Shipment
$item_qtys = array();
foreach ($allocations as $allocation) {
$item_qtys[] = array(GetOrderItemId($order_items,
$allocation['sku']) => $allocation['allocated_qty']);
}
// Anticipate Errors
try
{
// Create Shipment
$shipment = new Mage_Sales_Model_Order_Shipment_Api();
$shipmentId = $shipment->create($order->getIncrementId(),
$item_qtys, 'Pick #123 Sent to Warehouse');
// Done
echo 'Shipment Created - ID #'. $shipmentId;
}
catch (Exception $e)
{
print_r($e);
}
}
CreateShipment($order, $allocations);
Any idea why this isn't working as intended? See the full exception log here : http://pastebin.com/raw.php?i=GMN4WCAE
Try it like this instead :
protected function _createShipment($order, $qtysForProducts)
{
$shipment = $order->prepareShipment($qtysForProducts);
if ($shipment) {
$shipment->register();
$shipment->sendEmail(true)
->setEmailSent(true)
->save();
$order->setIsInProcess(true);
$transactionSave = Mage::getModel('core/resource_transaction')
->addObject($shipment)
->addObject($shipment->getOrder())
->save();
}
return $shipment;
}
does Magmi has a option to disable or make quantity to 0 for products not in csv file in import?.
Because my supplier remove all out of stock products from csv file.
If someone can help me on this or finding another solution please.
Thank you in advance
I've created a plugin that disables files not in the CSV. I prefer disabling the items, instead of actually deleting them in case something goes wrong (it won't wipe my database).
Create the plugin file magmi/plugins/extra/general/itemdisabler/magmi_itemdisabler_plugin.php
In the file, paste in the following and save:
Plugin Code:
<?php
class Magmi_ItemdisablerPlugin extends Magmi_ItemProcessor
{
protected $datasource_skus = array();
public function getPluginInfo()
{
return array("name"=>"Magmi Magento Item Disabler",
"author"=>"Axel Norvell (axelnorvell.com)",
"version"=>"1.0.6");
}
public function afterImport()
{
$this->log("Running Item Disabler Plugin","info");
$this->disableItems();
return true;
}
public function getPluginParams($params)
{
return array();
}
public function isRunnable()
{
return array(true,"");
}
public function initialize($params)
{
}
public function processItemAfterId(&$item,$params=null)
{
if(isset($item['sku']))
{
$this->datasource_skus[] = $item['sku'];
}
}
public function disableItems()
{
if(count($this->datasource_skus) <= 0)
{
$this->log('No items were found in datasource. Item Disabler will not run.', "info");
return false; /* Nothing to disable */
}
//Setup tables
$ea = $prefix!=""?$prefix."eav_attribute":"eav_attribute";
$eet = $prefix!=""?$prefix."eav_entity_type":"eav_entity_type";
$cpe = $prefix!=""?$prefix."catalog_product_entity":"catalog_product_entity";
$cpei = $prefix!=""?$prefix."catalog_product_entity_int":"catalog_product_entity_int";
//Get "status" attribute_id
$status_attr_id = "
SELECT ea.attribute_id FROM $ea ea
LEFT JOIN $eet eet ON ea.entity_type_id = eet.entity_type_id
WHERE ea.attribute_code = 'status'
AND eet.entity_type_code = 'catalog_product'";
$result = $this->selectAll($status_attr_id);
if (count($result) == 1) {
$attribute_id = $result[0]['attribute_id'];
}
unset($result);
//Get all active items
$sql = "SELECT e.sku, e.entity_id FROM $cpei i
INNER JOIN $cpe e ON
e.entity_id = i.entity_id
WHERE attribute_id=?
AND i.value = 1";
$all_magento_items = $this->selectAll($sql, array($attribute_id));
//Setup the magento_skus array for easy processing.
$magento_skus = array();
foreach($all_magento_items as $item)
{
$this->log("{$item['sku']} found in Mage", "info");
$magento_skus[$item['sku']] = $item['entity_id'];
}
//process the array, move anything thats in the datasource.
foreach($this->datasource_skus as $sku)
{
if(isset($magento_skus[$sku]))
{
unset($magento_skus[$sku]);
}
}
if(!empty($magento_skus))
{
foreach($magento_skus as $sku => $id)
{
$this->log("Disabling Item Id $id with SKU: $sku", "info");
$this->update("
UPDATE $cpei i
INNER JOIN $cpe e ON
e.entity_id = i.entity_id
SET VALUE = '2'
WHERE attribute_id = ?
AND i.value = 1
AND e.sku=?", array($attribute_id, $sku));
}
}
else
{
//If the Datasource contains all Magento's items.
$this->log('All items present in datasource. No items to disable.', "info");
}
}
}
Then login to Magmi, enable the plugin and run the import. This plugin will execute after the import has completed. It opens the datasource, logs all of the SKUs, then compares them against the Magento database. Any skus that aren't found in the datasource are disabled. This plugin could be optimized a bit better but it works as it is right now.