Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more
ARCHIVED This content is retired and no longer maintained. See the version selector for other versions of this topic.
AdjustInventory activity [Legacy]
During checkout, activity flows process payments, adjust item stock quantity, and record promotion usage. Episerver Commerce includes an adjust inventory activity that is incorporated into activity flows. The activity re-calculates and adjusts warehouse inventories after placing an order.
Classes in this topic are available in the following namespace:
The CartCheckout activity flow is executed when a cart is submitted for processing during order placement. The flow performs these tasks:
If the Process payment flag is true, calls the ProcessPayment method associated with the cart's payment providers.
Calculates totals for the cart based on line item price, item quantity, shipping totals, handling totals, and taxes. OrderForm, Cart, and LineItem properties are updated for totals.
If inventory tracking is enabled, the SKU inventory is adjusted after purchase.
Saves promotion usage data to the PromotionUsage table, where it tracks each promotion entry for enforcement of promotion redemption limits.
The AdjustInventory activity recalculates and adjusts the stock quantity of the cart's items.
using EPiServer.Commerce.Internal;
using EPiServer.Commerce.Order;
using EPiServer.Logging;
using EPiServer.ServiceLocation;
using Mediachase.Commerce.Inventory;
using Mediachase.Commerce.InventoryService;
using Mediachase.Commerce.Orders;
using Mediachase.Commerce.Orders.Managers;
using Mediachase.Commerce.WorkflowCompatibility;
using System;
using System.Collections.Generic;
using System.Linq;
namespaceMediachase.Commerce.Workflow.Activities.Cart
{
publicclassAdjustInventoryActivity : CartActivityBase
{
private Injected OrderRepository;
////// Called by the workflow runtime to execute an activity.//////The to associate with this and execution.////// The of the run task, which determines whether the activity remains in the executing state, or transitions to the closed state.///protectedoverride ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
// Check for multiple warehouses. In the default, we simply reject processing an order if the application has// multiple warehouses. Any corresponding fulfillment process is the responsibility of the client.
CheckMultiWarehouse();
// Validate the properties at runtime
ValidateRuntime();
// Return close status if order group is Payment Planif (OrderGroup is PaymentPlan)
{
return ActivityExecutionStatus.Closed;
}
AdjustInventoryOrRemoveLineItems();
// Retun the closed status indicating that this activity is complete.return ActivityExecutionStatus.Closed;
}
privatevoidAdjustInventoryOrRemoveLineItems()
{
var orderGroup = OrderGroup as IOrderGroup;
var validationIssues = new Dictionary<ILineItem, IList>();
RemoveEmptyShipment(orderGroup);
//This is needed for backward compatibilityforeach (var lineItem in orderGroup.GetAllLineItems())
{
if (!InventoryTrackingEnabled(lineItem))
{
Warnings[$"InventoryNotRequested:{lineItem.Code}"] = "Inventory tracking is disabled.";
}
}
orderGroup.AdjustInventoryOrRemoveLineItems((item, issue) => AddValidationIssues(validationIssues, item, issue));
//This is needed for backward compatibilityforeach (var validationIssue in validationIssues)
{
var lineItem = validationIssue.Key;
foreach (var issue in validationIssue.Value)
{
switch (issue)
{
case ValidationIssue.RemovedDueToInsufficientQuantityInInventory:
Warnings.Add($"LineItemRemoved-{lineItem.LineItemId.ToString()}", $"Item \"{lineItem.DisplayName}\" has been removed from the cart because there is not enough available quantity.");
break;
case ValidationIssue.RejectedInventoryRequestDueToInsufficientQuantity:
Warnings[OrderGroupWorkflowManager.RejectedInventoryDueToInsufficientQuantityWarning] = "Can not request inventory due to not enough quantity.";
Warnings[OrderGroupWorkflowManager.RejectedInventoryDueToInsufficientQuantityWarning + ":" + lineItem.Code] = "Can not request inventory due to not enough quantity.";
break;
default:
break;
}
}
}
RemoveEmptyShipment(orderGroup);
}
privatevoidRemoveEmptyShipment(IOrderGroup orderGroup)
{
//Remove empty shipmentvar deletedShipments = new List();
foreach (var shipment in orderGroup.Forms.SelectMany(form => form.Shipments))
{
if (!shipment.LineItems.Any())
{
deletedShipments.Add(shipment);
}
}
if (!deletedShipments.Any())
{
return;
}
foreach (var shipment in deletedShipments)
{
var form = orderGroup.Forms.FirstOrDefault(f => f.Shipments.Contains(shipment));
// Keep at least one shipment in the order form.if (form.Shipments.Count > 1)
{
form.Shipments.Remove(shipment);
InventoryRequester.CancelReservedQuantityForShipment((IShipmentInventory) shipment);
}
}
OrderRepository.Service.Save(orderGroup);
}
privatevoidCheckMultiWarehouse()
{
var warehouses = WarehouseRepository.List().Where(w => w.IsActive && w.IsFulfillmentCenter);
if (warehouses.Count() > 1)
{
thrownew NotSupportedException("Multiple fulfillment centers without custom fulfillment process.");
}
}
}
}
/// Adjusts the inventory.//////The order group.///A callback that is invoked if a validation issue is detected.///The inventory processor.publicstaticvoidAdjustInventoryOrRemoveLineItems(this
IOrderGroup orderGroup,
Action<ILineItem,
ValidationIssue> onValidationError,
IInventoryProcessor inventoryProcessor)
{
foreach (var shipment in orderGroup.Forms.SelectMany(form => form.Shipments))
{
inventoryProcessor.AdjustInventoryOrRemoveLineItem(shipment, orderGroup.OrderStatus, onValidationError);
}
}
Customizing the AdjustInventory activity
To customize the AdjustInventory activity, create an activity flow that mirrors the CartCheckout activity flow, and substitute the AdjustInventoryActivity with your implementation.