There's no simple "Set product X to inventory Y" command or pipeline, but here's how we've done it. I've included stubs for handling variants, but not the code that actually loads the variant.
I preferred a pipeline, but I'll just delimit the blocks with comments to keep things simple. The pipeline was invoked once for each inventory update from a Command using a transaction.
It also assumes that the InventorySet
has already been found and added to the context (we only do this once, so it's not part of this pipeline).
Yes, it's a fair bit of code unfortunately, but it does all the things that the BizFX UI does when you associate a product to an inventory set.
public class UpdateInventoryArgument
{
public string ProductId { get; set; }
public int Quantity { get; set; }
}
//////////////////////////////////
// ResolveSellableItemBlock
// Inject
IFindEntityPipeline findEntityPipeline;
var sellableItemId = $"{CommerceEntity.IdPrefix<SellableItem>()}{arg.ProductId}";
var sellableItem = await findEntityPipeline.Run(new FindEntityArgument(typeof(SellableItem), sellableItemId, false), context) as SellableItem;
if (sellableItem == null)
{
context.Abort(await context.CommerceContext.AddMessage(context.GetPolicy<KnownResultCodes>().Warning, "EntityNotFound",
new[] { sellableItemId }, $"SellableItem '{sellableItemId}' was not found."), context);
return null;
}
context.CommerceContext.AddUniqueObjectByType(sellableItem);
ItemVariationComponent itemVariation = null;
// Launch this pipeline with Options, not a Context, so that future blocks
// don't accidentally get the previous interation's variant
if (itemVariation != null)
{
context.CommerceContext.AddUniqueObjectByType(itemVariation);
}
//////////////////////////////////
// ResolveInventoryInformationBlock
// Inject
IGetInventoryInformationPipeline getInventoryInformationPipeline;
var sellableItem = context.CommerceContext.GetObject<SellableItem>();
var itemVariation = context.CommerceContext.GetObject<ItemVariationComponent>();
var inventoryInformation = await getInventoryInformationPipeline.Run(new SellableItemInventorySetArgument(sellableItem.Id, arg.InventorySetId)
{
VariationId = itemVariation != null ? itemVariation.Id : null
}, context);
if (inventoryInformation == null)
{
string inventoryInformationId = $"{arg.InventorySetId.SimplifyEntityName()}-{sellableItem.ProductId}";
if (itemVariation != null)
{
inventoryInformationId += $"-{itemVariation.Id}";
}
inventoryInformation = new InventoryInformation
{
Id = $"{CommerceEntity.IdPrefix<InventoryInformation>()}{inventoryInformationId}",
FriendlyId = inventoryInformationId,
InventorySet = new EntityReference(arg.InventorySetId, ""),
SellableItem = new EntityReference(sellableItem.Id, ""),
VariationId = itemVariation != null ? itemVariation.Id : null
};
inventoryInformation.GetComponent<TransientListMembershipsComponent>().Memberships.Add(CommerceEntity.ListName<InventoryInformation>());
}
context.CommerceContext.AddUniqueObjectByType(inventoryInformation);
////////////////////////
// UpdateInventoryInformationBlock
var inventoryInformation = context.CommerceContext.GetObject<InventoryInformation>();
entoryInformation = context.CommerceContext.GetObject<InventoryInformation>();
if (inventoryInformation == null)
{
return Task.FromResult((UpdateInventoryArgument)null);
}
inventoryInformation.Quantity = arg.Quantity;
return Task.FromResult(arg);
//////////////////////
// PersistInventoryInformationPipeline
// Inject
ICreateRelationshipPipeline createRelationshipPipeline;
IPersistEntityPipeline persistEntityPipeline;
var inventoryInformation = context.CommerceContext.GetObject<InventoryInformation>();
var sellableItem = context.CommerceContext.GetObject<SellableItem>();
var itemVariation = context.CommerceContext.GetObject<ItemVariationComponent>();
if (inventoryInformation == null)
{
context.Abort(await context.CommerceContext.AddMessage(context.GetPolicy<KnownResultCodes>().Error, "EntityNotFound",
new object[0], $"InventoryInformation was not found in context"), context);
return null;
}
if (sellableItem == null)
{
context.Abort(await context.CommerceContext.AddMessage(context.GetPolicy<KnownResultCodes>().Error, "EntityNotFound",
new object[0], $"SellableItem was not found in context"), context);
return null;
}
var isNew = inventoryInformation.IsPersisted == false;
await persistEntityPipeline.Run(new PersistEntityArgument(inventoryInformation), context);
if (isNew)
{
await createRelationshipPipeline.Run(new RelationshipArgument(arg.InventorySetId, inventoryInformation.Id, "InventorySetToInventoryInformation"), context);
(itemVariation != null ? itemVariation.GetComponent<InventoryComponent>() : sellableItem.GetComponent<InventoryComponent>())
.InventoryAssociations.Add(new InventoryAssociation
{
InventoryInformation = new EntityReference(inventoryInformation.Id, ""),
InventorySet = new EntityReference(arg.InventorySetId, "")
});
await persistEntityPipeline.Run(new PersistEntityArgument(sellableItem), context);
}
return arg;