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> 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 GetProductById(Guid productId) => _context.Products.FirstOrDefaultAsync(p => p.ProductId == productId); public async Task 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 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 GetNextProductSequence(Guid clientId) => await _context.Products.CountAsync(p => p.FKClientId == clientId) + 1; public Task> GetGrnItemsForProduct(Guid productId) => _context.GoodsReceivedNoteItems .Include(i => i.Grn) .Where(i => i.FKProductId == productId) .OrderByDescending(i => i.Grn!.ReceivedAt) .ToListAsync(); public Task> GetSaleItemsForProduct(Guid productId) => _context.SaleItems .Include(i => i.Sale) .Where(i => i.FKProductId == productId) .OrderByDescending(i => i.Sale!.SoldAt) .ToListAsync(); public Task> GetStockReturnsForProduct(Guid productId) => _context.StockReturns .Where(r => r.FKProductId == productId) .OrderByDescending(r => r.ReturnedAt) .ToListAsync(); // --- Suppliers --- public async Task> 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 GetSupplierById(Guid supplierId) => _context.Suppliers.FirstOrDefaultAsync(s => s.SupplierId == supplierId); public async Task CreateSupplier(Supplier supplier) { supplier.SupplierId = Guid.NewGuid(); supplier.CreatedAt = DateTime.UtcNow; supplier.IsActive = true; _context.Suppliers.Add(supplier); return supplier; } // --- GRN --- public async Task 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> 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 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 GetNextGrnSequence(Guid clientId) => await _context.GoodsReceivedNotes.CountAsync(g => g.FKClientId == clientId) + 1; // --- Sales --- public async Task 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> 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 GetSaleById(Guid saleId) => _context.Sales .Include(s => s.Items).ThenInclude(i => i.Product) .FirstOrDefaultAsync(s => s.SaleId == saleId); public async Task GetNextSaleSequence(Guid clientId) => await _context.Sales.CountAsync(s => s.FKClientId == clientId) + 1; // --- Returns --- public async Task CreateStockReturn(StockReturn stockReturn) { stockReturn.StockReturnId = Guid.NewGuid(); stockReturn.CreatedAt = DateTime.UtcNow; _context.StockReturns.Add(stockReturn); return stockReturn; } public Task> 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 GetStockReturnById(Guid stockReturnId) => _context.StockReturns .Include(r => r.Product) .Include(r => r.Sale) .Include(r => r.Grn) .FirstOrDefaultAsync(r => r.StockReturnId == stockReturnId); } }