0

In my Magento project I have to receive pricing and inventory information on our products. Right now I have created my own method within the product model to make a SOAP request in the getPrice() function.

Here's what that looks like:

../app/code/core/Mage/Catalog/Model/Product.php

/**
 * Get product price throught type instance
 *
 * @return unknown
 */
public function getPrice()
{
    if ($this->getData('is_api')){
        $this->getAPIData();
    }
    if ($this->_calculatePrice || !$this->getData('price')) {
        return $this->getPriceModel()->getPrice($this);
    } else {
        return $this->getData('price');
    }
}

/**
 * Get time since last update
 *
 * @return  int
 */
public function getTimeSinceLastUpdate() {
    return time() - strtotime($this->getUpdatedAt());
}

/**
 * Get product data from API
 *
 * @return  price
 */
public function getAPIData(){
    if ($this->getTimeSinceLastUpdate() > 5){
        $parts = new SoapClient("XXXX");
        $res = $parts->PartLookup([
            'userName' => 'XXXX',
            'password' => 'XXXX',
            'partnumber' => 'XXXX',
            'make' => ''
        ]);
        $this->updateAPIProduct($res);
        return $res;
    }
}

/**
 * Update API Product
 *
 * @return   unknown
 */
public function updateAPIProduct($data){
    $this->setPrice($data->PartLookupResult->PartInformation_v2[0]->Price);
    Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
    $this->save();
    Mage::app()->setCurrentStore(1);
}

However, this seems like the wrong way to do this. To me, it would make more sense to test whether or not it's an api product during product object creation. At that point I would update pricing AND inventory information.

I've also run into a bug where when I update the pricing while on the frontend the new price is grey and has a strike through it and the old price next to it.

The only problem is that I have no idea where to go to update that information at that point.

  • This is no answer, so I'll add it in a comment: this seems like a very flawed design to me. There will not be any operation (load backend, load frontend, order, anything) that is possible, when the SOAP-server is not reachable, or the access data has been changed, or there's another problem. You are completely relying on something that is not in Magento. You should update the product data with a cronjob or sth, save it in Magento, and then use the "normal" Magento way to show the data to the user. – simonthesorcerer Oct 19 '16 at 19:52
  • @simonthesorcerer thanks for the comment! I can easily build in something that will pass by the request if the server is unreachable. A cronjob is not realistic. The data needs to be requested in real time. Mainly pricing and inventory. Requesting data on 600k+ SKUs everyday will take lots of resources and time. The API is specifically designed to be used on an as needed basis. – Ryan Cady Oct 19 '16 at 20:12
  • can you not implement a push system by the external source to import data into magneto every time it has been changed? – simonthesorcerer Oct 19 '16 at 20:14
  • Their API is very limited. The only thing we get that changes is we get a bulk dump everyday that includes a SKU, and description. We would only see new products added or old ones removed. No pricing or inventory information. All of that info must be requested via the SOAP api. It's very very limited unfortunately. – Ryan Cady Oct 19 '16 at 20:17
0

Not a real answer, but too long for a comment:

I think to set the information when the object is created is the correct approach. With your solution now, one product could technically have a different price in different sections of the site, because the price could have been updated in the "source" in the meantime.

I would also try to do it in an observer and not in a class rewrite, as the latter can lead to problems with other extensions (only one rewrite of a certain class can be active at a time in Magento).

So, I would suggest to try something like this (not sure about the exact event name):

<!-- config.xml  -->
<global>
    <events>
        <catalog_product_load_after>
            <observers>
                <my_module_observer_name>
                    <class>mymodel/observer</class>
                    <method>setRealValues</method>
                </my_module_observer_name>
            </observers>
        </catalog_product_load_after>
    </events>
</global>

...and the PHP file:

<?php // Observer.php

    class Namespace_Mymodel_Model_Observer {
        public function setRealValues($observer) {
            $product = $observer->getEvent()->getProduct();
            $attributes = ['price', 'name', 'something']
            /*
             * Either get all values you need with one request, or 
             * do a foreach() loop over $attributes
             */
        }
    }

You would also have to do this for cataloginventory_stockitem_load_after, because technically, this holds the stock data.

There is another problem with product lists: Magento uses a collection object for this. I think if the API only allows single request - have fun requesting the data for 20+ products in a time that is acceptable for the customer :) cURL can do some kind of asynchronous stuff that might help you here. The event to listen for would be catalog_product_resource_collection _load_after, I guess (not sure again).

Maybe that this does not get all the possibilities where the price is displayed, but I think it's a place to start.

Update after comment:

I think saving the products at night would be a good start; keep in mind that the most expensive action will be loading the collection (600k SKUs means you should probably do it in chunks) and saving the product with a save() method. The latter can be avoided if you first check if the data has actually changed, and if you use $product->getResource()->saveAttribute($product, 'price', 10.00) (not sure about exact method name) instead of saving the whole model.

You might also want to make separate functions for updating the product and the stock item, as the stock item does not operate with such big objects and can maybe run more often.

  • Thank you so much for this! After all you guys have mentioned I've began to start thinking about this more in depth. I have been thinking that maybe it would be more wise to update pricing once a day through a product import. Then check inventory when added to cart if the inventory amount was under a specified amount like 10 units left or something similar. What do you think? – Ryan Cady Oct 20 '16 at 17:52
  • I have updated my answer – simonthesorcerer Oct 20 '16 at 21:04
  • Awesome! I think this is most likely the best way to do it. I found out that we may be able to have our dump file contain all the pricing and inventory information as well in a csv. If that's true, I'll just create a cronjob that will compare the two and detect changes then push that to the server and update as needed. – Ryan Cady Oct 21 '16 at 13:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.