I'm trying to add a "Contribution" product to the cart. This product is a bit like a donation, and doesn't really exist. I created it like this:
internal class ContributionProduct : IProductSnapshot
{
public const string ContributionName = "Contribution";
public const string ContributionSku = "Contrib";
public ContributionProduct(Guid storeId, Guid? taxClassId, ProductPrice price)
{
this.StoreId = storeId;
this.Prices = new[] { price };
this.TaxClassId = taxClassId;
this.Properties = new Dictionary<string, string>() { { MyConstants.Store.ContributionProductIdentifierPropertyName, bool.TrueString } };
}
public Guid StoreId { get; }
public IEnumerable<ProductPrice> Prices { get; }
public IDictionary<string, string> Properties { get; }
public bool IsGiftCard => false;
public string ProductReference => nameof(ContributionProduct);
public string Sku => ContributionSku;
public string Name => ContributionName;
public Guid? TaxClassId { get; }
public static ContributionProduct Create(OrderReadOnly order, decimal contributionValue)
{
return new ContributionProduct(order.StoreId, order.TaxClassId, new ProductPrice(contributionValue, order.CurrencyId));
}
}
and I add it like this
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddContribution(AddContributionDto postModel)
{
try
{
var store = this.CurrentPage.GetStore();
using (var uow = this._uowProvider.Create())
{
var order = this._sessionManager.GetOrCreateCurrentOrder(store.Id)
.AsWritable(uow);
var contributionProduct = ContributionProduct.Create(order, postModel.ContributionValue);
var productPrices = contributionProduct.Prices;
var currencyPrice = productPrices?.FirstOrDefault(x => x.CurrencyId == order.CurrencyId);
if (currencyPrice == null)
{
Debug.WriteLine($"Can't add a Product to an Order where there is no price for the Order currency.");
}
order.AddProduct(contributionProduct, 1);
this._orderService.SaveOrder(order);
uow.Complete();
}
}
catch (ValidationException)
{
this.ModelState.AddModelError("productReference", "Failed to add contribution to cart");
return this.CurrentUmbracoPage();
}
return this.RedirectToCurrentUmbracoPage();
}
However I'm getting an exception stating "Can't add a Product to an Order where there is no price for the Order currency." at AddProduct(...) and my Debug.WriteLine(...) is never hit.
So ProductSnapshots are generally meant to be used in combination with a ProductAdapter (https://vendr.net/docs/core/1-3-0/key-concepts/product-adapters/) and so you are seeing this error because there is a validation rule setup to ensure a price is available for the given currency, but that validation rule uses the product adapter to get the snapshot to validate against, rather than the snapshot that you've passed to AddProduct.
For custom priced products, how I'd be tempted to approach this is to store the donation amount as a property on the order line against a donation product node with a 0 value price and then use an order line calculator (https://vendr.net/docs/core/1-3-0/key-concepts/calculators/) to detect order lines with that product and for it's CalculateOrderLineUnitPrice method, get the value from the order line property and use that instead of the default value from the product.
FYI: I got this working without needing to have a false product in the content tree. I just created a ProductAdapter which used Umbraco content + my snapshot. This preferable in case an editor decided to remove my contribution product.
I still needed to use the IOrderLineCalculator and properties though, because the ProductAdapter doesn't have the ability to create snapshots with varying prices (AFAIK).
Can't add a Product to an Order where there is no price for the Order currency.
I note that there is a similar query here.
I'm trying to add a "Contribution" product to the cart. This product is a bit like a donation, and doesn't really exist. I created it like this:
and I add it like this
However I'm getting an exception stating "Can't add a Product to an Order where there is no price for the Order currency." at
AddProduct(...)
and myDebug.WriteLine(...)
is never hit.I'm a bit lost. Any points appreciated.
Hi David,
So ProductSnapshots are generally meant to be used in combination with a ProductAdapter (https://vendr.net/docs/core/1-3-0/key-concepts/product-adapters/) and so you are seeing this error because there is a validation rule setup to ensure a price is available for the given currency, but that validation rule uses the product adapter to get the snapshot to validate against, rather than the snapshot that you've passed to
AddProduct
.For custom priced products, how I'd be tempted to approach this is to store the donation amount as a property on the order line against a donation product node with a 0 value price and then use an order line calculator (https://vendr.net/docs/core/1-3-0/key-concepts/calculators/) to detect order lines with that product and for it's
CalculateOrderLineUnitPrice
method, get the value from the order line property and use that instead of the default value from the product.Hope this helps
Matt
If you say it's the way to go, then I'm sure you're correct. I'll go with that. Cheers.
And thank you for the quick response
FYI: I got this working without needing to have a false product in the content tree. I just created a ProductAdapter which used Umbraco content + my snapshot. This preferable in case an editor decided to remove my contribution product.
I still needed to use the IOrderLineCalculator and properties though, because the ProductAdapter doesn't have the ability to create snapshots with varying prices (AFAIK).
is working on a reply...