0

I added some custom attributes to my product such as cost and markup. By default markup will be set to 1.5 but the admin can adjust this.

When I am in the admin panel, I want to be able to observe a change on the cost field and have the price field populated automatically based on the formula:

price = cost * markup

If anyone can point me in the right direction on where this code may need to be updated or provide any examples that would be awesome.

2
  • 1
    which version you have tried?
    – Sohel Rana
    Commented Jan 24, 2017 at 18:39
  • @SohelRana Magento ver. 2.1.2 Commented Jan 24, 2017 at 18:42

2 Answers 2

1

First off, I would suggest updating to Magento 2.1.3 first, since this changes some fundamental ways on how products are saved.

Secondly, you need to catch a hook on where the product is saved. An event or a plugin (interceptor) could be used for this.

You could add a plugin before the save method of the product repository:

public function beforeSave(
    \Magento\Catalog\Model\ProductRepository $subject,
    \Magento\Catalog\Api\Data\ProductInterface $product,
    bool $saveOptions
) {
    ...

    return [$product, $saveOptions];
}

Or a plugin for the save()-method on the resource model:

public function beforeSave(
    \Magento\Catalog\Model\ResourceModel\Product $subject,
    \Magento\Framework\Model\AbstractModel $object
) {
    ...

    return [$object];
}

Or catch the event (I believe in 2.1.2 you can still use catalog_product_save_before, but in 2.1.3 the saving of the product is done with the entity manager. I'm not sure if this event still exists in 2.1.3). Haven't had time to test this out yet.

For any of these options I would suggest looking at the Price Modifier (Magento\Catalog\Model\Product\PriceModifierInterface). This has a modifyPrice()-method that allows you to set a new price for a product.

protected $priceModifier;

public function __construct(
    \Magento\Catalog\Model\Product\PriceModifierInterface $priceModifier
) {
    $this->priceModifier = $priceModifier;
}

public function changePrice()
{
    ... get price and product ...

    $this->priceModifier->modifyPrice($price, $product);
}

Haven't had the time to test any of the above yet, but perhaps it helps you find your solution.

JavaScript

Since you stated in your comment that you want the price to be updated realtime, you need to add some JavaScript. Once again, there are various ways to do this. The most elegant way would require you to create a new UI Component that does your magic on change and apply it to the cost-input-field.

There also is a more 'hacky' way to do is by extending the JavaScript Magento_Ui/js/form/element/abstract and manipulate the onUpdate()-method. This method is fired when the user changes input on any input field so we need to do an additional check:

/**
 * Callback that fires when 'value' property is updated.
 */
onUpdate: function () {
  this.bubble('update', this.hasChanged());

  if (this.namespace === 'product_form' && this.index === 'cost') {
    // The most hacky solution I've ever seen ...
    var priceField = document.querySelector('[name="product\\[price\\]"]');
    priceField.value = this.value() * 1.5;

    // Force trigger the 'change'-event on this field:
    var event = new Event('change');
    priceField.dispatchEvent(event);
  }

  this.validate();
}

Needless to say, this is very ugly. But if you look at the code, you'll see that the update-event bubbles. So a more proper way would be to utilise this event and leave the original class intact. Unfortunately for you I don't have too much experience on this specific area, but perhaps it gives you a good starting point.

In Conclusion

To achieve your goal you need to do the following:

  • Update on save (in case the product is saved somewhere other than the form).
  • Extend an existing JS Component to manipulate the onUpdate method - OR - utilize the event bubbling in UI Components.
5
  • I would like the formula to calculate once the user types in the cost and then moves to a new textbox. I would not want to do it on save, it is better to show them the result. Commented Jan 25, 2017 at 21:50
  • I see... Then you would need JavaScript. But please be aware that you'll need the save event as well in case a price isn't manipulated using the admin (by importing for example or another module that triggers a product save / price change). Commented Jan 26, 2017 at 7:35
  • I've updated my answer to aid you a bit with the JavaScript part. Commented Jan 26, 2017 at 8:08
  • the javascript way is definitely the right path to the solution. thank you very much for this I will post a full answer once everything is in place. Commented Jan 30, 2017 at 19:53
  • hey I am having issues getting the onupdate to trigger. can you check this out: magento.stackexchange.com/questions/157745/… Commented Feb 7, 2017 at 18:26
0

or... just buy this extension (I have no affiliation with it, but it seems like it could easily do what you need): https://www.itoris.com/magento-2-product-price-formula.html

1
  • Although this looks like a very versatile extension, I don't think it also automatically updates the price in the admin in real-time as soon as you change the cost-attribute (which is what the original question is). Also I think it's best to know how to program / manipulate Magento then install an extension for every other thing. Especially in this case the extension you suggested offers way way more than what the original question is. But that could just be me, the programmer talking ;-) Commented Jan 31, 2017 at 8:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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