London Dev Meetup Rescheduled! Due to unavoidable reasons, the event has been moved to 21st May. Speakers remain the same—any changes will be communicated. Seats are limited—register here to secure your spot!

OrderRepository.SaveAsPurchaseOrder(cart) returns null when trying to create a purchase order

Vote:
 

Hello, 

We got an error on a customer site where OrderRepository.SaveAsPurchaseOrder(cart) returns null when trying to create a purchase order. It doesn't throw an exception with an descriptive error message, but only returns null, so we don't know why it fails (we get null-ref exc when we try to use the purchaseOrder). How do we figure out why it gives us null, is something missing on the cart or is this a bug?

We're running Epi-commerce 13.14.1

#221289
Edited, Apr 16, 2020 7:53
Vote:
 

Hi Oscar, Please validate the cart using ICartValidationService before saving as purchase order.

Please try the below code.

1. Create an error view model.

public class ErrorViewModel
{
    public string Message { get; set; }

    public string LineItemCode { get; set; }

    public static ErrorViewModel Make(string error, string code)
    {
        return new ErrorViewModel
        {
            Message = error,
            LineItemCode = code
        };
    }
}
  

2. Create an interface with ICartValidationService 

public interface ICartValidationService
{
   IEnumerable<ErrorViewModel> ValidateCart(ICart cart);
}

3.  Finally, create a cart validation service.

public class CartValidationService : ICartValidationService
    {
        private readonly IInventoryProcessor _inventoryProcessor;
        private readonly ILineItemValidator _lineItemValidator;
        private readonly IPlacedPriceProcessor _placedPriceProcessor;
        private readonly IPromotionEngine _promotionEngine;

        public CartValidationService(
            IInventoryProcessor inventoryProcessor,
            ILineItemValidator lineItemValidator,
            IPlacedPriceProcessor placedPriceProcessor,
            IPromotionEngine promotionEngine)
        {
            _inventoryProcessor = inventoryProcessor ?? throw new ArgumentNullException(nameof(inventoryProcessor));
            _lineItemValidator = lineItemValidator ?? throw new ArgumentNullException(nameof(lineItemValidator));
            _placedPriceProcessor =
                placedPriceProcessor ?? throw new ArgumentNullException(nameof(placedPriceProcessor));
            _promotionEngine = promotionEngine ?? throw new ArgumentNullException(nameof(promotionEngine));
        }

        public IEnumerable<ErrorViewModel> ValidateCart(ICart cart)
        {
            var errors =
                this.Validate(cart)
                    ?.Select(lineItemEntry => new
                    {
                        LineItemIssues =
                            lineItemEntry.Value
                                .Select(validationIssue => new
                                {
                                    ValidationIssueMessage = this?.GetCartValidationMessage(validationIssue),
                                    LineItemCode = lineItemEntry.Key.Code,
                                })
                                .ToList(),
                    })
                    .SelectMany(lineItemIssueGroup => lineItemIssueGroup.LineItemIssues)
                    .Select(x => ErrorViewModel.Make(x.ValidationIssueMessage, x.LineItemCode))
                    .ToList() ?? new List<ErrorViewModel>();

            return errors;
        }

        private Dictionary<ILineItem, List<ValidationIssue>> Validate(ICart cart)
        {
            if (cart == null)
                return null;

            if (string.Equals(cart.Name, OrderNames.WishList, StringComparison.InvariantCultureIgnoreCase))
                return new Dictionary<ILineItem, List<ValidationIssue>>();

            var validationIssues = new Dictionary<ILineItem, List<ValidationIssue>>();

            cart.ValidateOrRemoveLineItems(
                (item, issue) => this.AddValidationIssues(validationIssues, item, issue),
                _lineItemValidator);

            cart.UpdatePlacedPriceOrRemoveLineItems(
                CustomerContext.Current.GetContactById(cart.CustomerId),
                (item, issue) => this.AddValidationIssues(validationIssues, item, issue),
                _placedPriceProcessor);

            cart.UpdateInventoryOrRemoveLineItems(
                (item, issue) => this.AddValidationIssues(validationIssues, item, issue),
                _inventoryProcessor);

            cart.ApplyDiscounts(_promotionEngine, new PromotionEngineSettings());

            cart.UpdateInventoryOrRemoveLineItems(
                (item, issue) => { },
                _inventoryProcessor);

            return validationIssues;
        }

        private void AddValidationIssues(
            Dictionary<ILineItem, List<ValidationIssue>> validationIssues,
            ILineItem item,
            ValidationIssue issue)
        {
            if (validationIssues == null)
                return;

            if (!validationIssues.ContainsKey(item))
            {
                validationIssues.Add(item, new List<ValidationIssue>());
            }

            var issues = validationIssues[item];

            if (issues.Any(x => x == issue))
                return;

            issues.Add(issue);

            validationIssues[item] = issues;
        }

        private string GetCartValidationMessage(ValidationIssue issue)
        {
            switch (issue)
            {
                default:
                case ValidationIssue.None:
                    return null;

                case ValidationIssue.CannotProcessDueToMissingOrderStatus:
                    return "Message...";

                case ValidationIssue.RemovedDueToCodeMissing:
                    return "Message...";

                case ValidationIssue.RemovedDueToNotAvailableInMarket:
                    return "Message...";

                case ValidationIssue.RemovedDueToUnavailableCatalog:
                    return "Message...";

                case ValidationIssue.RemovedDueToUnavailableItem:
                    return "Message...";

                case ValidationIssue.RemovedDueToInsufficientQuantityInInventory:
                    return "Message...";

                case ValidationIssue.RemovedDueToInactiveWarehouse:
                    return "Message...";

                case ValidationIssue.RemovedDueToMissingInventoryInformation:
                    return "Message...";

                case ValidationIssue.RemovedDueToInvalidPrice:
                    return "Message...";

                case ValidationIssue.RemovedDueToInvalidMaxQuantitySetting:
                    return "Message...";

                case ValidationIssue.AdjustedQuantityByMinQuantity:
                    return "Message...";

                case ValidationIssue.AdjustedQuantityByMaxQuantity:
                    return "Message...";

                case ValidationIssue.AdjustedQuantityByBackorderQuantity:
                    return "Message...";

                case ValidationIssue.AdjustedQuantityByPreorderQuantity:
                    return "Message...";

                case ValidationIssue.AdjustedQuantityByAvailableQuantity:
                    return "Message...";

                case ValidationIssue.PlacedPricedChanged:
                    return "Message...";

                case ValidationIssue.RemovedGiftDueToInsufficientQuantityInInventory:
                    return "Message...";

                case ValidationIssue.RejectedInventoryRequestDueToInsufficientQuantity:
                    return "Message...";
            }
        }
    }
#221317
Edited, Apr 16, 2020 9:57
Vote:
 

Thank you, we'll do that!

Where can I find the ICartValidationService ? Because it doesn't seem to exist in Commerce 13.14.1?

#221320
Edited, Apr 16, 2020 10:04
Sanjay Kumar - Apr 16, 2020 10:45
Hi Oscar, I have updated my previous comment so, please try.
Validate a cart Episerver help url: https://world.episerver.com/documentation/developer-guides/commerce/orders/shopping-carts
Vote:
 

Ah, thanks alot for sharing that :). 

#221329
Apr 16, 2020 10:48
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.