UmbracoProductAdapter - Overriding GetProductSnapshot sets Stock value to 0
Umbraco 9.3.0 - Vendr 2.1.0
In our Vendr store we want to make use of a sale price that can be active from a certain from date until a certain to date. To do this we have added a sale price field, a saleFrom date field, a saleTo date field and a saleIsActive boolean field to the product. The product also has a 'Vendr: Stock' field.
To change the price we have made use of an UmbracoProductAdapter and a custom ProductSnapshot. This functionality works and the price is set correctly if a sale price is active. However when using the custom ProductSnapshot the Stock field is changed to 0 (both in the frontend and backend).
Any ideas why this is? Or should this be implemented another way?
public class SalePriceProductAdapter : UmbracoProductAdapter
{
public SalePriceProductAdapter(IUmbracoContextFactory umbracoContextFactory, IContentService contentService, PublishedContentWrapperFactory publishedContentWrapperFactory, IExamineManager examineManager) : base(umbracoContextFactory, contentService, publishedContentWrapperFactory, examineManager)
{
}
public override IProductSnapshot GetProductSnapshot(Guid storeId, string productReference, string productVariantReference, string languageIsoCode)
{
// Generate the snapshot using the default extractor
var snapshot = (UmbracoProductSnapshot)base.GetProductSnapshot(storeId, productReference, productVariantReference, languageIsoCode);
// Decorate the snapshot with our custom decorator
return snapshot != null
? new VendrCustomProductSnapshot(snapshot)
: null;
}
}
public class VendrCustomProductSnapshot : ProductSnapshotBase
{
private readonly UmbracoProductSnapshot _snapshot;
private List<ProductPrice> customPrices;
public VendrCustomProductSnapshot(UmbracoProductSnapshot snapshot)
{
_snapshot = snapshot;
DtProduct product = snapshot.Content as DtProduct;
bool updatePrices = false;
if (product.SaleActive)
{
if (product.SaleFrom == DateTime.MinValue && product.SaleTo == DateTime.MinValue)
{
updatePrices = true;
}
else if (product.SaleTo == DateTime.MinValue && DateTime.Now >= product.SaleFrom)
{
updatePrices = true;
}
else if (product.SaleFrom == DateTime.MinValue && DateTime.Now <= product.SaleTo)
{
updatePrices = true;
}
else if (DateTime.Now >= product.SaleFrom && DateTime.Now <= product.SaleTo)
{
updatePrices = true;
}
}
if (updatePrices)
{
customPrices = new List<ProductPrice>();
foreach (ProductPrice productPrice in snapshot.Prices)
{
ProductPrice salePrice = product.SalePrice.GetPriceFor(productPrice.CurrencyId);
customPrices.Add(salePrice);
}
}
else
{
customPrices = (List<ProductPrice>)snapshot.Prices;
}
}
public override string Name => _snapshot.Name;
public override string Sku => _snapshot.Sku;
public override Guid StoreId => _snapshot.StoreId;
public override string ProductReference => _snapshot.ProductReference;
public override Guid? TaxClassId => _snapshot.TaxClassId;
public override IEnumerable<ProductPrice> Prices => customPrices;
public override IDictionary<string, string> Properties => _snapshot.Properties;
public override bool IsGiftCard => _snapshot.IsGiftCard;
public override string ProductVariantReference => _snapshot.ProductVariantReference;
public override IEnumerable<AttributeCombination> Attributes => _snapshot.Attributes;
}
I think the problem will likely be that the default stock implementation only works if the the product snapshot returned from the product adapter is assignable to UmbracoProductSnapshot which in your case it's not as you are replacing it with your VendrCustomProductSnapshot
You may need to have UmbracoProductSnapshot as your base class, or maybe try implementing an implicit conversion operator for conversion to UmbracoProductSnapshot but I think this is likely the issue.
public static implicit operator UmbracoProductSnapshot(VendrCustomProductSnapshot s) => s._snapshot;
I've just tried the implicit operator and unfortunately this won't work so your only current option is that your snapshot needs to inherit from UmbracoProductSnapshot instead.
This is necessary as the default stock implementation accesses the current content / variant nodes from the snapshot to determine which stock levels to adjust. We could maybe look at exposing an IUmbracoProductSnapshot interface so that you don't need to implement UmbracoProductSnapshot but this wouldn't necessarily help you right now unfortunately.
UPDATE
I've currently got a 2.1.1 patch release in progress and have added IUmbracoProductSnapshot to this so once I release this, you can have your product snapshot implement this to keep working with the default stock implementation. If you are just starting out locally, you can use our latest unstable build if you like via our unstable feed at https://nuget.outfield.digital/unstable/vendr/v3/index.json You'll want the 2.1.1-beta0098 build that should be on there shortly.
Hi Klaash,
Have you done your implementation? Can you share your custom product snapshot as we are interesting on implementing the same features as yours?
UmbracoProductAdapter - Overriding GetProductSnapshot sets Stock value to 0
Umbraco 9.3.0 - Vendr 2.1.0
In our Vendr store we want to make use of a sale price that can be active from a certain from date until a certain to date. To do this we have added a sale price field, a saleFrom date field, a saleTo date field and a saleIsActive boolean field to the product. The product also has a 'Vendr: Stock' field.
To change the price we have made use of an UmbracoProductAdapter and a custom ProductSnapshot. This functionality works and the price is set correctly if a sale price is active. However when using the custom ProductSnapshot the Stock field is changed to 0 (both in the frontend and backend).
Any ideas why this is? Or should this be implemented another way?
Hey Klaash
I think the problem will likely be that the default stock implementation only works if the the product snapshot returned from the product adapter is assignable to
UmbracoProductSnapshot
which in your case it's not as you are replacing it with yourVendrCustomProductSnapshot
You may need to have
UmbracoProductSnapshot
as your base class, or maybe try implementing an implicit conversion operator for conversion toUmbracoProductSnapshot
but I think this is likely the issue.Hope this helps
Matt
I've just tried the implicit operator and unfortunately this won't work so your only current option is that your snapshot needs to inherit from
UmbracoProductSnapshot
instead.This is necessary as the default stock implementation accesses the current content / variant nodes from the snapshot to determine which stock levels to adjust. We could maybe look at exposing an
IUmbracoProductSnapshot
interface so that you don't need to implementUmbracoProductSnapshot
but this wouldn't necessarily help you right now unfortunately.UPDATE
I've currently got a 2.1.1 patch release in progress and have added
IUmbracoProductSnapshot
to this so once I release this, you can have your product snapshot implement this to keep working with the default stock implementation. If you are just starting out locally, you can use our latest unstable build if you like via our unstable feed at https://nuget.outfield.digital/unstable/vendr/v3/index.json You'll want the 2.1.1-beta0098 build that should be on there shortly.Hey Matt,
Thank you for your quick reply and explanation! I think we will wait for the official patch and continue on then.
Hi Klaash, Have you done your implementation? Can you share your custom product snapshot as we are interesting on implementing the same features as yours?
Thanks.
Hey Hieu,
We ended up doing it this way:
is working on a reply...