From eeb837f32e94cebc26751e2c28eb1bec3c1798c0 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Fri, 1 May 2026 00:56:00 +0330 Subject: [PATCH] feat: enhance inventory release logic in ExpirePendingOrdersService and InventoryService --- .../ExpirePendingOrdersService.cs | 39 ++++++++++++++++++- .../Services/InventoryService.cs | 13 ++++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/CMSMicroservice.Infrastructure/BackgroundServices/ExpirePendingOrdersService.cs b/src/CMSMicroservice.Infrastructure/BackgroundServices/ExpirePendingOrdersService.cs index 3eb9df5..79bd0f8 100644 --- a/src/CMSMicroservice.Infrastructure/BackgroundServices/ExpirePendingOrdersService.cs +++ b/src/CMSMicroservice.Infrastructure/BackgroundServices/ExpirePendingOrdersService.cs @@ -79,10 +79,47 @@ public class ExpirePendingOrdersService : BackgroundService // آزادسازی رزرو موجودی foreach (var detail in order.OrderDetails) { + var inventoryItem = await inventoryService.GetInventoryAsync( + detail.ProductId, + ProductType.DiscountProduct, + null, + cancellationToken); + + if (inventoryItem == null) + { + _logger.LogWarning( + "Skipping inventory release for expired order #{OrderId}, ProductId={ProductId} because InventoryItem was not found", + order.Id, + detail.ProductId); + continue; + } + + if (inventoryItem.ReservedQuantity <= 0) + { + _logger.LogInformation( + "Skipping inventory release for expired order #{OrderId}, ProductId={ProductId} because no reserved quantity remains", + order.Id, + detail.ProductId); + continue; + } + + var releaseQuantity = Math.Min(detail.Count, inventoryItem.ReservedQuantity); + + if (releaseQuantity < detail.Count) + { + _logger.LogWarning( + "Partial reservation release for expired order #{OrderId}, ProductId={ProductId}: requested={Requested}, reserved={Reserved}, releasing={Released}", + order.Id, + detail.ProductId, + detail.Count, + inventoryItem.ReservedQuantity, + releaseQuantity); + } + await inventoryService.ReleaseReservationAsync( detail.ProductId, ProductType.DiscountProduct, - detail.Count, + releaseQuantity, order.Id, cancellationToken); } diff --git a/src/CMSMicroservice.Infrastructure/Services/InventoryService.cs b/src/CMSMicroservice.Infrastructure/Services/InventoryService.cs index 423e7ee..5fe2bd1 100644 --- a/src/CMSMicroservice.Infrastructure/Services/InventoryService.cs +++ b/src/CMSMicroservice.Infrastructure/Services/InventoryService.cs @@ -249,14 +249,23 @@ public class InventoryService : IInventoryService var quantityBefore = item.ReservedQuantity; item.ReservedQuantity = Math.Max(0, item.ReservedQuantity - quantity); + var releasedQuantity = quantityBefore - item.ReservedQuantity; await _context.SaveChangesAsync(ct); + if (releasedQuantity == 0) + { + _logger.LogInformation( + "No reserved units to release for {ProductType} Id={ProductId}, OrderId={OrderId}", + productType, productId, orderId); + return true; + } + // ثبت StockMovement await LogMovementAsync( item.Id, StockMovementType.Released, - quantity, + -releasedQuantity, quantityBefore, item.ReservedQuantity, orderId, @@ -268,7 +277,7 @@ public class InventoryService : IInventoryService _logger.LogInformation( "Released {Quantity} reserved units for {ProductType} Id={ProductId}, OrderId={OrderId}", - quantity, productType, productId, orderId); + releasedQuantity, productType, productId, orderId); return true; }