Files
Core_Be/Repos/InventoryRepository.cs
T
HarithaRandunu 2eb88b058e 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.
2026-10-07 15:43:20 +05:30

189 lines
6.7 KiB
C#

using Fitness_core_BE.Interfaces;
using Fitness_core_BE.Models;
using Microsoft.EntityFrameworkCore;
namespace Fitness_core_BE.Repos
{
public class InventoryRepository : IInventoryRepository
{
private readonly TenantDbContext _context;
public InventoryRepository(TenantDbContext context)
{
_context = context;
}
// --- Products ---
public async Task<List<Product>> GetProducts(Guid clientId, bool includeInactive = false)
{
var query = _context.Products.Where(p => p.FKClientId == clientId);
if (!includeInactive)
query = query.Where(p => p.IsActive);
return await query.OrderBy(p => p.Name).ToListAsync();
}
public Task<Product?> GetProductById(Guid productId)
=> _context.Products.FirstOrDefaultAsync(p => p.ProductId == productId);
public async Task<Product> CreateProduct(Product product)
{
product.ProductId = Guid.NewGuid();
product.CreatedAt = DateTime.UtcNow;
product.IsActive = true;
product.CostPrice = 0m;
product.QuantityOnHand = 0m;
_context.Products.Add(product);
return product;
}
public async Task<Product> UpdateProduct(Product product)
{
var existing = await _context.Products.FindAsync(product.ProductId)
?? throw new KeyNotFoundException("Product not found");
// Sku is system-generated at creation and never edited -- not copied here.
existing.Name = product.Name;
existing.UnitOfMeasure = product.UnitOfMeasure;
existing.SellingPrice = product.SellingPrice;
existing.IsActive = product.IsActive;
return existing;
}
public async Task<int> GetNextProductSequence(Guid clientId)
=> await _context.Products.CountAsync(p => p.FKClientId == clientId) + 1;
public Task<List<GoodsReceivedNoteItem>> GetGrnItemsForProduct(Guid productId)
=> _context.GoodsReceivedNoteItems
.Include(i => i.Grn)
.Where(i => i.FKProductId == productId)
.OrderByDescending(i => i.Grn!.ReceivedAt)
.ToListAsync();
public Task<List<SaleItem>> GetSaleItemsForProduct(Guid productId)
=> _context.SaleItems
.Include(i => i.Sale)
.Where(i => i.FKProductId == productId)
.OrderByDescending(i => i.Sale!.SoldAt)
.ToListAsync();
public Task<List<StockReturn>> GetStockReturnsForProduct(Guid productId)
=> _context.StockReturns
.Where(r => r.FKProductId == productId)
.OrderByDescending(r => r.ReturnedAt)
.ToListAsync();
// --- Suppliers ---
public async Task<List<Supplier>> GetSuppliers(Guid clientId, bool includeInactive = false)
{
var query = _context.Suppliers.Where(s => s.FKClientId == clientId);
if (!includeInactive)
query = query.Where(s => s.IsActive);
return await query.OrderBy(s => s.Name).ToListAsync();
}
public Task<Supplier?> GetSupplierById(Guid supplierId)
=> _context.Suppliers.FirstOrDefaultAsync(s => s.SupplierId == supplierId);
public async Task<Supplier> CreateSupplier(Supplier supplier)
{
supplier.SupplierId = Guid.NewGuid();
supplier.CreatedAt = DateTime.UtcNow;
supplier.IsActive = true;
_context.Suppliers.Add(supplier);
return supplier;
}
// --- GRN ---
public async Task<GoodsReceivedNote> CreateGrn(GoodsReceivedNote grn)
{
grn.GrnId = Guid.NewGuid();
grn.CreatedAt = DateTime.UtcNow;
foreach (var item in grn.Items)
item.GrnItemId = Guid.NewGuid();
_context.GoodsReceivedNotes.Add(grn);
return grn;
}
public Task<List<GoodsReceivedNote>> GetGrns(Guid clientId)
=> _context.GoodsReceivedNotes
.Include(g => g.Supplier)
.Include(g => g.Items).ThenInclude(i => i.Product)
.Where(g => g.FKClientId == clientId)
.OrderByDescending(g => g.ReceivedAt)
.ToListAsync();
public Task<GoodsReceivedNote?> GetGrnById(Guid grnId)
=> _context.GoodsReceivedNotes
.Include(g => g.Supplier)
.Include(g => g.Items).ThenInclude(i => i.Product)
.FirstOrDefaultAsync(g => g.GrnId == grnId);
public async Task<int> GetNextGrnSequence(Guid clientId)
=> await _context.GoodsReceivedNotes.CountAsync(g => g.FKClientId == clientId) + 1;
// --- Sales ---
public async Task<Sale> CreateSale(Sale sale)
{
sale.SaleId = Guid.NewGuid();
sale.CreatedAt = DateTime.UtcNow;
foreach (var item in sale.Items)
item.SaleItemId = Guid.NewGuid();
_context.Sales.Add(sale);
return sale;
}
public Task<List<Sale>> GetSales(Guid clientId)
=> _context.Sales
.Include(s => s.Items).ThenInclude(i => i.Product)
.Where(s => s.FKClientId == clientId)
.OrderByDescending(s => s.SoldAt)
.ToListAsync();
public Task<Sale?> GetSaleById(Guid saleId)
=> _context.Sales
.Include(s => s.Items).ThenInclude(i => i.Product)
.FirstOrDefaultAsync(s => s.SaleId == saleId);
public async Task<int> GetNextSaleSequence(Guid clientId)
=> await _context.Sales.CountAsync(s => s.FKClientId == clientId) + 1;
// --- Returns ---
public async Task<StockReturn> CreateStockReturn(StockReturn stockReturn)
{
stockReturn.StockReturnId = Guid.NewGuid();
stockReturn.CreatedAt = DateTime.UtcNow;
_context.StockReturns.Add(stockReturn);
return stockReturn;
}
public Task<List<StockReturn>> GetStockReturns(Guid clientId)
=> _context.StockReturns
.Include(r => r.Product)
.Include(r => r.Sale)
.Include(r => r.Grn)
.Where(r => r.FKClientId == clientId)
.OrderByDescending(r => r.ReturnedAt)
.ToListAsync();
public Task<StockReturn?> GetStockReturnById(Guid stockReturnId)
=> _context.StockReturns
.Include(r => r.Product)
.Include(r => r.Sale)
.Include(r => r.Grn)
.FirstOrDefaultAsync(r => r.StockReturnId == stockReturnId);
}
}