Add inventory management features including Sales, Stock Returns, and Suppliers

- Implement Sale and SaleItem models for tracking sales transactions.
- Create StockReturn model to manage stock adjustments for various reasons.
- Introduce Supplier model to represent suppliers of products.
- Develop InventoryRepository for CRUD operations on products, suppliers, sales, and stock returns.
- Implement InventoryService to handle business logic for inventory management.
- Update TenantDbContext to include new models and relationships.
- Enhance ProfitLossRepository to account for sales, purchases, and stock returns in profit and loss calculations.
- Modify Program.cs to register new inventory-related services.
This commit is contained in:
2026-10-07 15:43:20 +05:30
parent f96db48ec2
commit 2eb88b058e
16 changed files with 1678 additions and 0 deletions
+59
View File
@@ -105,9 +105,68 @@ namespace Fitness_core_BE.Repos
})
.ToListAsync(ct);
// Inventory: a Sale's revenue, a GRN's cost, and a StockReturn's Amount (staff-
// entered -- see StockReturn's doc comment). Every return Category still posts the
// same way here (one Expense category, reducing profit) even though CustomerReturn
// is the one category that adds the stock back -- the P&L side stays uniform while
// the stock-direction side doesn't.
var productSales = await _context.Sales
.AsNoTracking()
.Where(sale =>
sale.FKClientId == clientId &&
sale.SoldAt >= fromUtc &&
sale.SoldAt < toUtc)
.Select(sale => new LedgerEntryDto
{
EntryType = "Income",
Category = "Product Sales",
Description = sale.SaleNumber,
Amount = sale.TotalAmount,
EntryDate = sale.SoldAt,
IsManual = false
})
.ToListAsync(ct);
var inventoryPurchases = await _context.GoodsReceivedNotes
.AsNoTracking()
.Where(grn =>
grn.FKClientId == clientId &&
grn.ReceivedAt >= fromUtc &&
grn.ReceivedAt < toUtc)
.Select(grn => new LedgerEntryDto
{
EntryType = "Expense",
Category = "Inventory Purchases",
Description = grn.GrnNumber,
Amount = grn.TotalAmount,
EntryDate = grn.ReceivedAt,
IsManual = false
})
.ToListAsync(ct);
var inventoryWriteOffs = await _context.StockReturns
.AsNoTracking()
.Where(stockReturn =>
stockReturn.FKClientId == clientId &&
stockReturn.ReturnedAt >= fromUtc &&
stockReturn.ReturnedAt < toUtc)
.Select(stockReturn => new LedgerEntryDto
{
EntryType = "Expense",
Category = "Inventory Write-offs",
Description = stockReturn.Category + " — " + stockReturn.Product!.Name,
Amount = stockReturn.Amount,
EntryDate = stockReturn.ReturnedAt,
IsManual = false
})
.ToListAsync(ct);
memberPayments.AddRange(platformInvoices);
memberPayments.AddRange(staffPayments);
memberPayments.AddRange(bookingPayments);
memberPayments.AddRange(productSales);
memberPayments.AddRange(inventoryPurchases);
memberPayments.AddRange(inventoryWriteOffs);
return memberPayments;
}