Our client, Weavers Wines had a particular requirement when it came to their pricing structure.
A proportion of Weaver’s business is in selling b2b, meaning their internal pricing system leans towards ‘trade’ pricing models. However, for their new Magento 2 site, they required that any customer who was not logged in, or who was logged in as a general retail customer, would see the retail prices of all products on the site.
If the customer was logged in with any other account type, which by implication would be a specific trade account, they would then see the trade prices.
It was a requirement of the build that the trade prices were used as the product base price.
To handle the retail prices, we decided on storing them using Magento’s tier prices which allow setting prices based on customer groups. The retail price of products was simply set on the General customer group and the NOT LOGGED IN customer group.
Products on the site could also be tagged as being a “Mix6” product which marks them as eligible for a specific deal, such that once a retail customer adds 6 or more Mix6 products to their cart, they would then pay the trade price for each of those bottles. They would still pay the retail price for any non Mix6 product of course if any were also in the cart.
By default Magento will always pick the cheapest available price for the customer, which is usually ideal. However, because the trade price of products for this client is always cheaper than the retail price, the retail customers would still see the trade price. This is because it’s set as the main product price which is an available option for all customers.
To work around this issue we extended the BasePrice price model, which is the class that determines what the product’s base price will be. We altered the logic in the getValue method so that it would now always favour using a tiered price regardless of it being higher or lower than the product’s base price.
Now that the retail and trade prices are displaying correctly we needed to undo this functionality if the Mix6 deal is triggered.
To do this we used an observer to check the cart before it’s saved. This way we will trigger the deal if the cart is updated either by adding new products or from the cart page itself. The event to observe is checkout_cart_save_before.
In our observer it is simply a case of looping over the items in the cart and counting the number of products that are applicable for the Mix6 deal. If there is 6 or more then we need to loop over the cart again,but this time we change the prices of all the applicable products to their trade price.
We stored the logic that checks if the Mix6 deal has been triggered into a seperate method so this could be used in other sections of the site.
For example there is a thin banner of sliding text that the client can edit from the admin. This is primarily used to display certain highlighted promotions or shipping details.
However, using the method to check the Mix6 status of the cart allows us to override this if any Mix6 products have been entered in the cart. If you had for example added two Mix6 products to the cart the banner would change and display in formation about the Mix6 deal and indicate how many more products you needed to add in order to trigger the deal.
The finish line
Magento 2 certainly allows developers many different entry points for adding or extending functionality. With so many options and often several approaches to choose from the job often becomes picking the route that will best consider the maintainability of the site in the future.
We’re happy with the options we’ve picked above as the resulting code is fairly light and more importantly the functionality is controlled from a single observer or extended price model. This means that if the Mix6 deal needs to be updated in the future, it only needs to be adjusted in this single observer and the change will affect all cart related Mix6 updates in both the admin and frontend.