{"record":{"id":"c023cd4246b5c832","repo":"nopSolutions/nopCommerce","slug":"checkout-minordertotalamount","errorCode":null,"errorMessage":"Checkout.MinOrderTotalAmount","messagePattern":"Checkout\\.MinOrderTotalAmount","errorType":"validation","errorClass":"NopException","httpStatus":null,"severity":"warning","filePath":"src/Libraries/Nop.Services/Orders/OrderProcessingService.cs","lineNumber":529,"sourceCode":"            var sciWarnings = await _shoppingCartService.GetShoppingCartItemWarningsAsync(details.Customer,\r\n                sci.ShoppingCartType, product, processPaymentRequest.StoreId, sci.AttributesXml,\r\n                sci.CustomerEnteredPrice, sci.RentalStartDateUtc, sci.RentalEndDateUtc, sci.Quantity, false, sci.Id);\r\n            if (sciWarnings.Any())\r\n                throw new NopException(sciWarnings.Aggregate(string.Empty, (current, next) => $\"{current}{next};\"));\r\n        }\r\n\r\n        //min totals validation\r\n        if (!await ValidateMinOrderSubtotalAmountAsync(details.Cart))\r\n        {\r\n            var minOrderSubtotalAmount = await _currencyService.ConvertFromPrimaryStoreCurrencyAsync(_orderSettings.MinOrderSubtotalAmount, currentCurrency);\r\n            throw new NopException(string.Format(await _localizationService.GetResourceAsync(\"Checkout.MinOrderSubtotalAmount\"),\r\n                await _priceFormatter.FormatPriceAsync(minOrderSubtotalAmount, true, false)));\r\n        }\r\n\r\n        if (!await ValidateMinOrderTotalAmountAsync(details.Cart))\r\n        {\r\n            var minOrderTotalAmount = await _currencyService.ConvertFromPrimaryStoreCurrencyAsync(_orderSettings.MinOrderTotalAmount, currentCurrency);\r\n            throw new NopException(string.Format(await _localizationService.GetResourceAsync(\"Checkout.MinOrderTotalAmount\"),\r\n                await _priceFormatter.FormatPriceAsync(minOrderTotalAmount, true, false)));\r\n        }\r\n    }\r\n\r\n    /// <summary>\r\n    /// Prepare and validate billing address\r\n    /// </summary>\r\n    /// <param name=\"details\">PlaceOrder container</param>\r\n    /// <returns>A task that represents the asynchronous operation</returns>\r\n    /// <exception cref=\"NopException\">Validation problems</exception>\r\n    protected virtual async Task PrepareAndValidateBillingAddressAsync(PlaceOrderContainer details)\r\n    {\r\n        if (details.Customer.BillingAddressId is null)\r\n            throw new NopException(\"Billing address is not provided\");\r\n\r\n        var billingAddress = await _customerService.GetCustomerBillingAddressAsync(details.Customer);\r\n\r\n        if (!CommonHelper.IsValidEmail(billingAddress?.Email))\r","sourceCodeStart":511,"sourceCodeEnd":547,"githubUrl":"https://github.com/nopSolutions/nopCommerce/blob/64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2/src/Libraries/Nop.Services/Orders/OrderProcessingService.cs#L511-L547","documentation":"Thrown when the cart total is below the configured minimum order total threshold (_orderSettings.MinOrderTotalAmount) and ValidateMinOrderTotalAmountAsync returns false. The message uses the localized 'Checkout.MinOrderTotalAmount' resource formatted with the threshold in the customer's currency. Unlike the subtotal check, this is evaluated after all discounts, gift cards, and reward points are applied to the final total.","triggerScenarios":"The store has MinOrderTotalAmount set (e.g. $20) and the customer's cart total after all discounts and reward points falls below it. A large discount or reward point redemption brings the final total under the minimum. Gift card application reduces the effective payable total below the threshold.","commonSituations":"Customer redeems reward points or applies a gift card that reduces the total below the minimum. A percentage discount or category-wide sale drops the payable amount. Admin set both MinOrderSubtotalAmount and MinOrderTotalAmount with the total threshold higher than expected. A new minimum was set mid-session.","solutions":["Increase the cart value or reduce discount/gift card/reward point usage so the final total meets the threshold.","Review _orderSettings.MinOrderTotalAmount in admin and lower or disable it if too restrictive.","Show both minimum subtotal and minimum total requirements on the cart/checkout pages.","Set MinOrderTotalAmount to 0 if no minimum order total is needed."],"exampleFix":"// before: orderSettings.MinOrderTotalAmount = 25m; cart total after discounts = 18m\n// after: orderSettings.MinOrderTotalAmount = 0m;  // disable minimum total","handlingStrategy":"validation","validationCode":"// Before PlaceOrder, check minimum order total\nif (await ValidateMinOrderTotalAmountAsync(cart) == false)\n{\n    var minAmount = await _currencyService.ConvertFromPrimaryStoreCurrencyAsync(\n        _orderSettings.MinOrderTotalAmount, currentCurrency);\n    var formatted = await _priceFormatter.FormatPriceAsync(minAmount, true, false);\n    _notificationService.ErrorNotification(\n        string.Format(await _localizationService.GetResourceAsync(\"Checkout.MinOrderTotalAmount\"), formatted));\n    return RedirectToRoute(\"ShoppingCart\");\n}","typeGuard":"async Task<bool> MeetsMinTotalAsync(IOrderTotalCalculationService svc, IList<ShoppingCartItem> cart, decimal min)\n{\n    var (total, _, _, _, _, _) = await svc.GetShoppingCartTotalAsync(cart);\n    return min <= 0 || (total.HasValue && total.Value >= min);\n}","tryCatchPattern":"try\n{\n    var result = await _orderProcessingService.PlaceOrderAsync(processPaymentRequest);\n}\ncatch (NopException ex) when (ex.Message.Contains(\"MinOrderTotal\"))\n{\n    _notificationService.ErrorNotification(ex.Message);\n    return RedirectToRoute(\"ShoppingCart\");\n}","preventionTips":["Display the minimum order total requirement on the checkout review page.","Warn when reward point or gift card redemption would bring the total below the minimum.","Review MinOrderTotalAmount whenever discount campaigns or pricing changes occur.","Set MinOrderTotalAmount to 0 if no minimum order total is required."],"tags":["nopcommerce","minimum-order","order-total","business-rule","discount","checkout","order-processing"],"backgroundTag":null,"analyzedSha":"64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2","analyzedAt":"2026-08-13T21:19:38.062Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}