{"record":{"id":"c1540d048c2c3d1c","repo":"nopSolutions/nopCommerce","slug":"enter-amount-to-refund","errorCode":null,"errorMessage":"Enter amount to refund","messagePattern":"Enter amount to refund","errorType":"exception","errorClass":"NopException","httpStatus":null,"severity":"warning","filePath":"src/Presentation/Nop.Web/Areas/Admin/Controllers/OrderController.cs","lineNumber":820,"sourceCode":"    [HttpPost]\n    [FormValueRequired(\"partialrefundorder\")]\n    [CheckPermission(StandardPermission.Orders.ORDERS_CREATE_EDIT_DELETE)]\n    public virtual async Task<IActionResult> PartiallyRefundOrderPopup(int id, bool online, OrderModel model)\n    {\n        //try to get an order with the specified id\n        var order = await _orderService.GetOrderByIdAsync(id);\n        if (order == null)\n            return RedirectToAction(\"List\");\n\n        //a vendor does not have access to this functionality\n        if (await _workContext.GetCurrentVendorAsync() != null)\n            return RedirectToAction(\"Edit\", new { id = order.Id });\n\n        try\n        {\n            var amountToRefund = model.AmountToRefund;\n            if (amountToRefund <= decimal.Zero)\n                throw new NopException(\"Enter amount to refund\");\n\n            var maxAmountToRefund = order.OrderTotal - order.RefundedAmount;\n            if (amountToRefund > maxAmountToRefund)\n                amountToRefund = maxAmountToRefund;\n\n            var errors = new List<string>();\n            if (online)\n                errors = (await _orderProcessingService.PartiallyRefundAsync(order, amountToRefund)).ToList();\n            else\n                await _orderProcessingService.PartiallyRefundOfflineAsync(order, amountToRefund);\n\n            await LogEditOrderAsync(order.Id);\n\n            if (!errors.Any())\n            {\n                //success\n                ViewBag.RefreshPage = true;\n","sourceCodeStart":802,"sourceCodeEnd":838,"githubUrl":"https://github.com/nopSolutions/nopCommerce/blob/64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2/src/Presentation/Nop.Web/Areas/Admin/Controllers/OrderController.cs#L802-L838","documentation":"Thrown in the OrderController partial-refund action when model.AmountToRefund is less than or equal to decimal.Zero. The action then clamps the amount to the maximum refundable (order total minus already-refunded), so a non-positive amount is treated as user input error rather than a partial refund. NopException, caught and shown as an error notification.","triggerScenarios":"POST to the partial refund (online or offline) endpoint with AmountToRefund of 0, a negative number, or an empty/non-numeric value that binds to 0.","commonSituations":"The admin leaves the refund amount field blank (binds to 0); a localized number format (comma vs dot decimal separator) fails model binding and defaults to 0; the refund form is submitted without selecting an amount.","solutions":["Enter a positive refund amount not exceeding (OrderTotal - RefundedAmount).","Check the amount field's number formatting matches the server culture (decimal separator).","Add client-side validation requiring a positive number before submit.","If the full order is already refunded, the maxAmountToRefund will be 0 — inform the admin rather than allowing submit."],"exampleFix":"// before\nvar amountToRefund = model.AmountToRefund;\nif (amountToRefund <= decimal.Zero)\n    throw new NopException(\"Enter amount to refund\");\n\n// after — guard with a friendly notification and clamp hint\nvar maxAmountToRefund = order.OrderTotal - order.RefundedAmount;\nif (model.AmountToRefund <= decimal.Zero || model.AmountToRefund > maxAmountToRefund)\n{\n    _notificationService.ErrorNotification($\"Enter an amount between 0.01 and {maxAmountToRefund}.\");\n    return RedirectToAction(\"Edit\", new { id = order.Id });\n}","handlingStrategy":"validation","validationCode":"// Before refunding: validate the amount against the refundable ceiling\nvar maxRefund = order.OrderTotal - order.RefundedAmount;\nif (model.AmountToRefund <= decimal.Zero || model.AmountToRefund > maxRefund)\n{\n    _notificationService.ErrorNotification($\"Enter a refund amount between 0.01 and {maxRefund}.\");\n    return RedirectToAction(\"Edit\", new { id = order.Id });\n}","typeGuard":"bool IsValidRefundAmount(decimal amount, Order order) => amount > decimal.Zero && amount <= (order.OrderTotal - order.RefundedAmount);","tryCatchPattern":"// The action's try/catch shows exc.Message; pre-validate the amount client-side and server-side.","preventionTips":["Add client-side required + min(0.01) + max(refundable) validation on the amount field.","Match the server culture's decimal separator when posting the amount.","Disable the refund button when the full amount is already refunded."],"tags":["nopcommerce","admin","order","refund","validation","money"],"backgroundTag":null,"analyzedSha":"64bdf2ff08c8b39e65717bcf974fb43dc2ef68f2","analyzedAt":"2026-08-13T21:19:38.062Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}