Can i programmatically add a product with a specific id? - magento

How can I do something like adding a new product with a specified product_id/entity_id ?
$newprod = new Mage_Catalog_Model_Product();
$newprod->setProductId( 100 ); // how do i make this work
$newprod->setSku(... );

you may try something like this:
$product = Mage::getModel('catalog/product')->load($desiredId);
if(!$product){ //here also might be something like $product->getSku()
$product->set.......//set required fields here
$product->setEntityId($desiredId); //we won't mess up things, because product with desired id et not exists
$product->save()
}

Related

Retrieve original Customer object from sales_order_invoice_pay event

I'm building a small module for my Magento 1.7 installation.
My function is called when the sales_order_payment_pay event is triggered.
Basically, it looks into the customer's order to check for the presence of a specific magic product.
// Retrieve the order
$order = $observer->getPayment()->getOrder();
// Look for product ID 999, whatever that is
try {
$magic_product = $order->getItemById(999);
if ($magic_product){
// The order contains our magic product; let's find our customer object and do something with it.
//**$customer = $order->getCustomer();**
$customer->setData( "foo", "bar" );
$customer->save();
}
} catch ( Exception $e ) {
// Fail silently, I don't care...
}
I'm trying here to find a way to go up the object hierarchy to retrieve the customer (if any!) who made the order.
With getCustomerName() I could get it's name, but I can't find any way to find the object itself without resorting to some kind of hack. And I don't like hacks. Anyone can help me?
If you're trying to get the customer object that is related to the order, you have to load it and the order has the customers id:
$customerId = $order->getCustomerId();
$customer = Mage::getModel('customer/customer')->load($customerId);
// customer stuff
$event = $observer->getEvent();
$invoice = $event->getInvoice();
$order = $invoice->getOrder();
echo $order->getCustomerId();
Try using this in case you get a Null for Customer ID

Magento - Get Product SKU's and quantities on order

I have created an event observer on the "sales_order_place_after" event, which fires when the user places an order in Magento's checkout. That event triggers my observer, which needs to get the following information, which is then sent to an external inventory management system.
Information needed: The SKU and quantity of every product on the order
I have included part of my observer model below. I am accessing the order object. I can get all the items in the order, but how do I get the SKU for every product that makes up the order. For example, with a simple product, this is very easy. However, with a bundled or configurable product I do not know how to access the children that make up that bundled product with their SKU's and quantities. That is the info I need for both bundled and configurable products. I need the SKU and quantities of the children that were selected. For the life of me, I can't figure out what method to call to access that information. I wish there was something like: $item->getBundleChildrenSkuQuantity();
$order = $observer->getEvent()->getOrder();
$joomecomPacket = array();
if ($order->getTotalItemCount() > 0) {
$items = $order->getAllItems();
foreach ($items as $item) {
$productType = $item->getProductType();
switch ($productType) {
case 'bundle':
break;
case 'configurable':
default: // simple products
if (isset($joomecomPacket[$item['sku']])) {
$joomecomPacket[$item['sku']] += $item['qty_ordered'];
} else {
$joomecomPacket[$item['sku']] = $item['qty_ordered'];
}
break;
}
}
}
You're missing a break after your configurable case. The default case is executing for configurable products.
Try this:
$items = $order->getAllVisibleItems(); // gives only parent items
foreach ($items as $item){
$childItem = $item->getChildren(); //do something with $cildItem like $childItem->getSku() etc...
}

Attribute Options/Labels sorting define on Site View Level?

I using Magento 1.6.2.
Is there any way to set the position for Attribute Option Labels on a Site View Level and not on a global level?
Reason: Here the Values for Color in English and German
Black / Schwarz
Clear / Transparent
Copper / Kupfer
Yellow / Gelb
It is obvious that the sorting is different for different languages.
Overriding the position value and sorting the values in the frontpage code is not possible because there are options where alphanumeric sorting doesn't make sense:
i.e. Small Medium Large
Please help
Yes, this is very possible. But it's a fairly deep change, depending on what you would like to accomplish with this. This will get you started:
You want to first add a new column to eav/attribute_option_value table. Here is the setup script for that:
$installer = $this;
$installer->startSetup();
$installer->run("
ALTER TABLE `{$this->getTable('eav/attribute_option_value')}` ADD COLUMN `sort_order` INT UNSIGNED NULL DEFAULT 0;
");
$installer->endSetup();
Next, you need to rewrite Mage_Eav_Model_Mysql4_Entity_Attribute_Option_Collection. When performing the join for the store filter, you need to add your sort_order there:
public function setStoreFilter($storeId=null, $useDefaultValue=true)
{
if (is_null($storeId)) {
$storeId = Mage::app()->getStore()->getId();
}
$sortBy = 'store_default_value';
if ($useDefaultValue) {
$this->getSelect()
->join(array('store_default_value'=>$this->_optionValueTable),
'store_default_value.option_id=main_table.option_id',
array('default_value'=>'value'))
->joinLeft(array('store_value'=>$this->_optionValueTable),
'store_value.option_id=main_table.option_id AND '.$this->getConnection()->quoteInto('store_value.store_id=?', $storeId),
array('store_value'=>'value',
'value' => new Zend_Db_Expr('IF(store_value.value_id>0, store_value.value,store_default_value.value)',
'sort_order'))) // ADDED
->where($this->getConnection()->quoteInto('store_default_value.store_id=?', 0));
}
else {
$sortBy = 'store_value';
$this->getSelect()
->joinLeft(array('store_value'=>$this->_optionValueTable),
'store_value.option_id=main_table.option_id AND '.$this->getConnection()->quoteInto('store_value.store_id=?', $storeId),
'value',
'sort_order') // ADDED
->where($this->getConnection()->quoteInto('store_value.store_id=?', $storeId));
}
$this->setOrder("store_value.sort_order", 'ASC'); // CHANGED
return $this;
}
To show what is going on: each attribute has a source model. The source model is responsible for providing the values in a frontend dropdown-type list (select, multiselect). If the source model is Mage_Eav_Model_Entity_Attribute_Source_Table, which it will be by default if the attribute type is select or multiselect, then this code retrieves the values:
$collection = Mage::getResourceModel('eav/entity_attribute_option_collection')
->setPositionOrder('asc')
->setAttributeFilter($this->getAttribute()->getId())
->setStoreFilter($this->getAttribute()->getStoreId())
->load();
As you can see, we are rewriting the setStoreFilter() function. This is the last one called. You might want to add an unshiftOrder('main_table.sort_order', 'ASC') at the beginning of the rewritten function, just for good measure that the `main_table.sort_order does not get in the way.
I'll leave it to you to make the necessary adjustments to the admin panel to provide the option for setting the sort order matrix.

Replacing "product name" with "Item + productId" when product is added in Magento via admin panel

I want to auto generate product names in Magento.
When I'm going to add a product, for the product name I will type some string.
When I save the product, I want the product name to be automatically generated such that the product name becomes Item."productId".
Answering assuming that OP wants to incorporate the auto-increment value from the entity table into business data. This is generally not a great idea.
This is an interesting task which can be easily accomplished with Magento's EAV implementation - particularly when working in the catalog module. First, some background.
When an EAV entity is saved, it has a nice, neat array of key => value pairs which represent the attributes and attribute values for that entity:
Mage_Catalog_Model_Product->_data['attribute_code'] = 'attribute value';
During the save process, the EAV resource model takes this array and iterates over it. For each attribute, identified by its code (attribute_code in the above example) and its entity (catalog_product in the case of products), the configuration for the attribute itself is loaded. Of particular importance is the "backend model" for an attribute, as it is invoked to do pre- and post-processing of/relating to the value.
In the current case, there is a piece of information which will not be present when we are saving the attribute, at least, not in a way in which we can use it: the new product id. This can be used to adjust the original value as part of the save process.
It's always nice to have an example from the core, so, refer to the price attribute and its backend model, Mage_Catalog_Model_Product_Attribute_Backend_Price which can be seen in the eav_attribute table:
SELECT `attribute_code`, `backend_model`
FROM `eav_attribute`
LEFT JOIN `eav_entity_type` USING (`entity_type_id`)
WHERE `attribute_code` = 'price';
#+----------------+-----------------------------------------+
#| attribute_code | backend_model |
#+----------------+-----------------------------------------+
#| price | catalog/product_attribute_backend_price |
#+----------------+-----------------------------------------+
#1 row in set (0.00 sec)
When a product is saved, the price attribute's backend_model is instantiated and (in this case) the afterSave() method is called. Incidentally, this method is what updates pricing by conversion rate for website-scoped pricing. This same approach can be used to modify the name attribute.
The following setup script will add the backend model:
<?php
$installer = Mage::getResourceModel('catalog/setup','default_setup');
$installer->startSetup();
$installer->updateAttribute(
'catalog_product',
'name',
'backend_model',
'custom/product_attribute_backend_name'
);
$installer->endSetup();
The corresponding afterSave() method should do the trick:
public function afterSave($object)
{
$value = $object->getData($this->getAttribute()->getAttributeCode());
$origData = $object->getOrigData();
$origValueExist = $origData && array_key_exists($this->getAttribute()->getAttributeCode(), $origData);
//don't do this in case of update
if ($object->getStoreId() != 0 || !$value || $origValueExist) {
return $this;
}
//append autoinc id
$newValue = $value .'.'. $object->getId(); // or whatever
//assume global store, otherwise the stated need is getting weird!
$object->addAttributeUpdate($this->getAttribute()->getAttributeCode(), $newValue, 0);
return $this;
}
If you're doing this from the admin panel product edit screen, you're going to have to remove the "Required" class from the "Name" field so you can save it without the name. This means overriding the Edit form to replace that field specifically. Then you'll have to overload the save-related methods on the product model (or you can do it from the controller), but the child will have to generate the name on save before it goes to the database.
For example:
class Module_Catalog_Model_Product extends Mage_Catalog_Model_Product
{
protected function _beforeSave()
{
parent::_beforeSave();
$productName = 'Item' . $this->getId();
if (!$this->getId() && !$this->getName())
{
$this->setName('Item Unnamed');
} elseif ($this->getId()) && strcasecmp($this->getName(), $productName) <> 0)
{
$this->setName($productName);
}
}
}
The only problem with this is that it requires two saves. If you want to have it work on the fly, you'll have to do a second save using the _afterSave() method. Or, once again, you can do it from the controller.
I would use a Magento Event to do this:
Since Models in Magento have an event prefixes (just take a look at Mage_Catalog_Model_Product and look for $_eventPrefix, for our current model the eventPrefix is set to catalog_product.
If you now take a look at Mage_Core_Model_Abstract and search for _eventPrefix. You see that eventPrefix are found in _beforeLoad, _afterLoad, _beforeSave, _afterSave and a few others. In these methods you can see an event is dispatched using something as below:
Mage::dispatchEvent($this->_eventPrefix.'_save_before', $this->_getEventData());
This means you have an event available called catalog_product_save_before. With this event you can hook into Magento at that time and do your thing, change the field in this case, and Magento handles the rest.
Take a look at http://www.magentocommerce.com/wiki/5_-_modules_and_development/0_-_module_development_in_magento/customizing_magento_using_event-observer_method for more information how to use these events and turn them into a module. If you don't know how to build modules for Magento and want to learn, there are some awesome on-demand video's for free: http://www.magentocommerce.com/training/on-demand
First I want to thanks to all users which write in the topic. Thanks a lot of guys!
I did it, but I make it easier. (because I have very basic knowledge in Magento and it would toke more time)
So... With my colegues decided to make it with php/jquery/ajax.
First we create one single php file, which return the last id:
<?php
header('Access-Control-Allow-Origin: *');
require_once 'app/Mage.php';
umask(o);
Mage::app('default');
Mage::getSingleton('core/session', array('name'=>'frontend'));
$model = Mage::getModel('catalog/product'); //getting product model
$collection = $model->getCollection(); //products collection
foreach ($collection as $product) //loop for getting products
{
$id=$product->getId();
}
if($id)echo $id+1; //id of product
else{
echo 0;
}
?>
After step one I set the value of input (i.e. I auto generate the name):
if($j('#name').val()=='' && window.location.href.indexOf("admin/catalog_product/new/") > -1) {
$j.post('http://www.website.com/file.php', function(data) {
$j('#name').val('Item №'+data);
});
}
Thanks again for help.
Best Regards,
Jordan!

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();

Resources