Add Stock Tracking endpoint to Inventory
Adds GET /client/inventory/stock-movements, a unified read-only ledger flattening every GRN line, sale line and return across all products into one shape for the new Stock Tracking tab's table.
This commit is contained in:
@@ -576,6 +576,67 @@ namespace Fitness_core_BE.Services
|
||||
return MapToDto(stockReturn);
|
||||
}
|
||||
|
||||
// --- Stock Tracking (unified ledger, new) ---
|
||||
|
||||
/// <summary>Every GRN line, sale line and return across every product, flattened into one
|
||||
/// shape for the Stock Tracking tab's table. Built from the same three already-tenant-
|
||||
/// scoped reads the GRN/Sales/Returns tabs use -- no new repository queries needed, and
|
||||
/// the dataset is small enough (a single gym's "simple inventory") that filtering happens
|
||||
/// client-side rather than via query params.</summary>
|
||||
public async Task<object> GetStockMovements(object payload, HttpContext httpContext)
|
||||
{
|
||||
var clientId = await _userRoleHelper.GetClientId(DataExtractor.GetUserIdFromContext(httpContext));
|
||||
|
||||
var grns = await _inventoryRepository.GetGrns(clientId);
|
||||
var sales = await _inventoryRepository.GetSales(clientId);
|
||||
var returns = await _inventoryRepository.GetStockReturns(clientId);
|
||||
|
||||
var movements = new List<StockMovementDto>();
|
||||
|
||||
foreach (var g in grns)
|
||||
foreach (var i in g.Items)
|
||||
movements.Add(new StockMovementDto
|
||||
{
|
||||
Type = "GRN",
|
||||
ProductId = i.FKProductId,
|
||||
ProductName = i.Product?.Name ?? string.Empty,
|
||||
Reference = g.GrnNumber,
|
||||
QuantityChange = i.Quantity,
|
||||
Amount = i.LineTotal,
|
||||
Date = g.ReceivedAt
|
||||
});
|
||||
|
||||
foreach (var s in sales)
|
||||
foreach (var i in s.Items)
|
||||
movements.Add(new StockMovementDto
|
||||
{
|
||||
Type = "Sale",
|
||||
ProductId = i.FKProductId,
|
||||
ProductName = i.Product?.Name ?? string.Empty,
|
||||
Reference = s.SaleNumber,
|
||||
QuantityChange = -i.Quantity,
|
||||
Amount = i.LineTotal,
|
||||
Date = s.SoldAt
|
||||
});
|
||||
|
||||
foreach (var r in returns)
|
||||
movements.Add(new StockMovementDto
|
||||
{
|
||||
Type = "Return",
|
||||
ProductId = r.FKProductId,
|
||||
ProductName = r.Product?.Name ?? string.Empty,
|
||||
Reference = r.Sale?.SaleNumber ?? r.Grn?.GrnNumber ?? r.Category,
|
||||
Category = r.Category,
|
||||
// CustomerReturn is the one category that adds back to stock -- see
|
||||
// StockReturn's doc comment.
|
||||
QuantityChange = r.Category == "CustomerReturn" ? r.Quantity : -r.Quantity,
|
||||
Amount = r.Amount,
|
||||
Date = r.ReturnedAt
|
||||
});
|
||||
|
||||
return movements.OrderByDescending(m => m.Date).ToList();
|
||||
}
|
||||
|
||||
/// <summary>Staff optionally picking an existing registered member to attach to a sale
|
||||
/// (search-and-pick, not free-typed) -- purely for identification, mirrors
|
||||
/// BookingService.ResolveOptionalCustomerLinkAsync exactly.</summary>
|
||||
|
||||
Reference in New Issue
Block a user