Skip to content

Instantly share code, notes, and snippets.

@mattbrailsford
Last active May 3, 2022 13:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattbrailsford/518c5771de89a0fc35d0644ca126d229 to your computer and use it in GitHub Desktop.
Save mattbrailsford/518c5771de89a0fc35d0644ca126d229 to your computer and use it in GitHub Desktop.
Example order line calculator that support price breaks
using System;
using System.Collections.Generic;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web;
using Vendr.Core.Calculators;
using Vendr.Core.Models;
using Vendr.Core.Services;
using Vendr.Web.Models;
namespace Vendr.DemoStore.Web.Calculators
{
public class PriceBreakOrderLineCalculator : OrderLineCalculator
{
private readonly IStoreService _storeService;
private readonly IPriceFreezerService _priceFreezerService;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
public PriceBreakOrderLineCalculator(ITaxService taxService, IStoreService storeService, IProductPriceFreezerService productPriceFreezerService,
IPriceFreezerService priceFreezerService, IUmbracoContextAccessor umbracoContextAccessor)
: base(taxService, storeService, productPriceFreezerService)
{
_storeService = storeService;
_priceFreezerService = priceFreezerService;
_umbracoContextAccessor = umbracoContextAccessor;
}
public override Price CalculateOrderLineUnitPrice(OrderReadOnly order, OrderLineReadOnly orderLine, Guid currencyId, TaxRate taxRate)
{
var store = _storeService.GetStore(order.StoreId);
// See if the product node has a priceBreaks value
var node = _umbracoContextAccessor.UmbracoContext.Content.GetById(Guid.Parse(orderLine.ProductReference));
if (node.HasValue("priceBreaks"))
{
// Work out which price break applies (if any)
var priceBreaks = node.Value<IEnumerable<IPublishedElement>>("priceBreaks");
IPublishedElement targetPriceBreak = null;
foreach (var priceBreak in priceBreaks)
{
var minQuantity = priceBreak.Value<int>("minQuantity");
if (orderLine.Quantity >= minQuantity)
{
targetPriceBreak = priceBreak;
}
else
{
break;
}
}
// See if we have a price break
if (targetPriceBreak != null)
{
// See if we have a frozen price for this price break and if so, use it
var key = $"{order.StoreId}_{order.Id}_{orderLine.ProductReference}_{targetPriceBreak.Key}";
var price = _priceFreezerService.GetFrozenPrice(order.Id, key, currencyId);
if (price == null || price.Equals(ProductPrice.ZeroValue(currencyId)))
{
// No frozen price yet, so work out the price and freeze it (if we can)
var priceBreakPrices = targetPriceBreak.Value<PricePropertyValue>("price");
var priceBreakPrice = priceBreakPrices.GetPriceFor(currencyId);
if (priceBreakPrice != null)
{
// Freeze the price if the order isn't new
// (ie, it doesn't exist in the DB yet and so an FK would fail)
if (!order.IsNew)
{
_priceFreezerService.FreezePrice(order.Id, key, priceBreakPrice);
}
price = priceBreakPrice;
}
}
return Price.Calculate(price.Value, taxRate, currencyId, store.PricesIncludeTax);
}
}
return base.CalculateOrderLineUnitPrice(order, orderLine, currencyId, taxRate);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment