/// <summary> /// Called by the workflow runtime to execute an activity. /// </summary> /// <param name="executionContext">The <see cref="T:Mediachase.Commerce.WorkflowCompatibility.ActivityExecutionContext"/> to associate with this <see cref="T:Mediachase.Commerce.WorkflowCompatibility.Activity"/> and execution.</param> /// <returns> /// The <see cref="T:Mediachase.Commerce.WorkflowCompatibility.ActivityExecutionStatus"/> of the run task, which determines whether the activity remains in the executing state, or transitions to the closed state. /// </returns> protected override 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(); var orderForms = OrderGroup.OrderForms.Where(o => !OrderForm.IsReturnOrderForm(o)); foreach (OrderForm orderForm in orderForms) { foreach (Shipment shipment in orderForm.Shipments) { foreach (var lineItem in Shipment.GetShipmentLineItems(shipment)) { AdjustStockItemQuantity(shipment, lineItem); } } } // Retun the closed status indicating that this activity is complete. return(ActivityExecutionStatus.Closed); }
/// <summary> /// Gets the taxes for order form /// </summary> /// <param name="form">The order form.</param> /// <param name="marketId">The order market Id.</param> /// <param name="currency">The order currency.</param> /// <returns>The total taxes for the order form.</returns> public static void CalculateTaxes(OrderForm form, MarketId marketId, Currency currency) { var market = _marketService.Service.GetMarket(marketId); var totalTaxes = 0m; foreach (Shipment shipment in form.Shipments) { var shippingTax = 0m; var shippingCost = shipment.ShippingSubTotal - shipment.ShippingDiscountAmount; var lineItems = Shipment.GetShipmentLineItems(shipment); // Calculate sales and shipping taxes per items foreach (LineItem lineItem in lineItems) { var taxes = GetTaxValues(market, shipment, lineItem); if (!taxes.Any()) { continue; } // calculate quantity of item in current shipment var quantity = OrderForm.IsReturnOrderForm(form) ? lineItem.ReturnQuantity : Shipment.GetLineItemQuantity(shipment, lineItem.LineItemId); // price exclude tax for 1 line item var lineItemPricesExcTax = GetPriceExcludingTax(lineItem, quantity); var totalShipmentLineItemsQuantity = lineItems.Sum(l => Shipment.GetLineItemQuantity(shipment, lineItem.LineItemId)); var itemShippingCost = shipment.SubTotal == 0 ? quantity / totalShipmentLineItemsQuantity * shippingCost : lineItemPricesExcTax / shipment.SubTotal * shippingCost; shippingTax += GetTaxesAmount(taxes, TaxType.ShippingTax, itemShippingCost); totalTaxes += GetTaxesAmount(taxes, TaxType.SalesTax, lineItemPricesExcTax); } shipment.ShippingTax = currency.Round(shippingTax); totalTaxes += shipment.ShippingTax; } form.TaxTotal = currency.Round(totalTaxes); }
/// <summary> /// Called by the workflow runtime to execute an activity. /// </summary> /// <param name="executionContext">The <see cref="T:Mediachase.Commerce.WorkflowCompatibility.ActivityExecutionContext"/> to associate with this <see cref="T:Mediachase.Commerce.WorkflowCompatibility.Activity"/> and execution.</param> /// <returns> /// The <see cref="T:Mediachase.Commerce.WorkflowCompatibility.ActivityExecutionStatus"/> of the run task, which determines whether the activity remains in the executing state, or transitions to the closed state. /// </returns> protected override 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 Plan if (OrderGroup is PaymentPlan) { return(ActivityExecutionStatus.Closed); } var orderGroupStatus = OrderStatusManager.GetOrderGroupStatus(OrderGroup); var orderForms = OrderGroup.OrderForms.Where(o => !OrderForm.IsReturnOrderForm(o)); var inventoryRequests = new List <InventoryRequestItem>(); foreach (OrderForm orderForm in orderForms) { foreach (Shipment shipment in orderForm.Shipments) { if (!ValidateShipment(orderForm, shipment)) { continue; } var shipmentStatus = OrderStatusManager.GetOrderShipmentStatus(shipment); bool completingOrder = orderGroupStatus == OrderStatus.Completed || shipmentStatus == OrderShipmentStatus.Shipped; bool cancellingOrder = orderGroupStatus == OrderStatus.Cancelled || shipmentStatus == OrderShipmentStatus.Cancelled; _logger.Debug(string.Format("Adjusting inventory, got orderGroupStatus as {0} and shipmentStatus as {1}. completingOrder as {2} and cancellingOrder as {3}.", orderGroupStatus, shipmentStatus, completingOrder, cancellingOrder)); // When completing/cancelling an order or a shipment if (completingOrder || cancellingOrder) { var requestType = completingOrder ? InventoryRequestType.Complete : InventoryRequestType.Cancel; inventoryRequests.AddRange(GetRequestInventory(shipment, inventoryRequests.Count, requestType)); // When processed request, need to clear all operation keys from the shipment shipment.ClearOperationKeys(); } // When release a shipment, check if shipment contain a BackOrder then need to complete that BackOrder. else if (shipmentStatus == OrderShipmentStatus.Released) { foreach (LineItem lineItem in Shipment.GetShipmentLineItems(shipment)) { var lineItemIndex = orderForm.LineItems.IndexOf(lineItem); var completeBackOrderRequest = new List <InventoryRequestItem>(); var lineItemRequest = GetLineItemRequestInventory(shipment, lineItemIndex, 0, InventoryRequestType.Complete); // Only need to process complete BackOrder request type foreach (var request in lineItemRequest) { InventoryRequestType requestType; InventoryChange change; _operationKeySerializer.Service.TryDeserialize(request.OperationKey, out requestType, out change); if (requestType == InventoryRequestType.Backorder) { // Add BackOrder request to request list completeBackOrderRequest.Add(request); // Then remove BackOrder request operation key from shipment's operation key map shipment.RemoveOperationKey(lineItemIndex, request.OperationKey); } } // Storage the response operation keys from complete BackOrder mapping with line item index if (completeBackOrderRequest.Count > 0) { InventoryResponse response = _inventoryService.Service.Request(new InventoryRequest(DateTime.UtcNow, completeBackOrderRequest, null)); if (response != null && response.IsSuccess) { shipment.InsertOperationKeys(lineItemIndex, response.Items.Select(c => c.OperationKey)); } } } } else if (orderGroupStatus == OrderStatus.InProgress || orderGroupStatus == OrderStatus.AwaitingExchange) { // When placing an order or creating an exchange order bool placingOrder = shipmentStatus == OrderShipmentStatus.AwaitingInventory || shipmentStatus == OrderShipmentStatus.InventoryAssigned; if (placingOrder) { var lineItems = Shipment.GetShipmentLineItems(shipment); CancelOperationKeys(shipment); foreach (LineItem lineItem in lineItems) { RequestInventory(orderForm, shipment, lineItem); } } } } } if (inventoryRequests.Any()) { _inventoryService.Service.Request(new InventoryRequest(DateTime.UtcNow, inventoryRequests, null)); } // Retun the closed status indicating that this activity is complete. return(ActivityExecutionStatus.Closed); }