diff --git a/CutList.Web/Program.cs b/CutList.Web/Program.cs index dcbfbef..ec05740 100644 --- a/CutList.Web/Program.cs +++ b/CutList.Web/Program.cs @@ -17,6 +17,7 @@ builder.Services.AddDbContext(options => // Add application services builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/CutList.Web/Services/CutListPackingService.cs b/CutList.Web/Services/CutListPackingService.cs index e6fbcac..06ddb64 100644 --- a/CutList.Web/Services/CutListPackingService.cs +++ b/CutList.Web/Services/CutListPackingService.cs @@ -38,8 +38,8 @@ public class CutListPackingService .Where(s => s.MaterialId == materialId && s.IsActive && s.Quantity > 0) .ToListAsync(); - // Get supplier stock lengths for this material (for purchase) - var supplierLengths = await _context.SupplierStocks + // Get stock item lengths for this material (for purchase) + var stockItemLengths = await _context.StockItems .Where(s => s.MaterialId == materialId && s.IsActive) .Select(s => s.LengthInches) .Distinct() @@ -60,8 +60,8 @@ public class CutListPackingService }); } - // Supplier stock bins with unlimited quantity - foreach (var length in supplierLengths) + // Stock item bins with unlimited quantity + foreach (var length in stockItemLengths) { // Only add if not already covered by in-stock if (!stockBins.Any(b => b.LengthInches == length && b.IsInStock)) diff --git a/CutList.Web/Services/StockItemService.cs b/CutList.Web/Services/StockItemService.cs new file mode 100644 index 0000000..a00c4bb --- /dev/null +++ b/CutList.Web/Services/StockItemService.cs @@ -0,0 +1,99 @@ +using CutList.Web.Data; +using CutList.Web.Data.Entities; +using Microsoft.EntityFrameworkCore; + +namespace CutList.Web.Services; + +public class StockItemService +{ + private readonly ApplicationDbContext _context; + + public StockItemService(ApplicationDbContext context) + { + _context = context; + } + + public async Task> GetAllAsync(bool includeInactive = false) + { + var query = _context.StockItems + .Include(s => s.Material) + .AsQueryable(); + + if (!includeInactive) + { + query = query.Where(s => s.IsActive); + } + + return await query + .OrderBy(s => s.Material.Shape) + .ThenBy(s => s.Material.Size) + .ThenBy(s => s.LengthInches) + .ToListAsync(); + } + + public async Task> GetByMaterialAsync(int materialId, bool includeInactive = false) + { + var query = _context.StockItems + .Include(s => s.Material) + .Where(s => s.MaterialId == materialId); + + if (!includeInactive) + { + query = query.Where(s => s.IsActive); + } + + return await query + .OrderBy(s => s.LengthInches) + .ToListAsync(); + } + + public async Task GetByIdAsync(int id) + { + return await _context.StockItems + .Include(s => s.Material) + .Include(s => s.SupplierOfferings) + .ThenInclude(o => o.Supplier) + .FirstOrDefaultAsync(s => s.Id == id); + } + + public async Task CreateAsync(StockItem stockItem) + { + stockItem.CreatedAt = DateTime.UtcNow; + _context.StockItems.Add(stockItem); + await _context.SaveChangesAsync(); + return stockItem; + } + + public async Task UpdateAsync(StockItem stockItem) + { + stockItem.UpdatedAt = DateTime.UtcNow; + _context.StockItems.Update(stockItem); + await _context.SaveChangesAsync(); + } + + public async Task DeleteAsync(int id) + { + var stockItem = await _context.StockItems.FindAsync(id); + if (stockItem != null) + { + stockItem.IsActive = false; + stockItem.UpdatedAt = DateTime.UtcNow; + await _context.SaveChangesAsync(); + } + } + + public async Task ExistsAsync(int materialId, decimal lengthInches, int? excludeId = null) + { + var query = _context.StockItems.Where(s => + s.MaterialId == materialId && + s.LengthInches == lengthInches && + s.IsActive); + + if (excludeId.HasValue) + { + query = query.Where(s => s.Id != excludeId.Value); + } + + return await query.AnyAsync(); + } +} diff --git a/CutList.Web/Services/SupplierService.cs b/CutList.Web/Services/SupplierService.cs index bcd2d89..bed6c3f 100644 --- a/CutList.Web/Services/SupplierService.cs +++ b/CutList.Web/Services/SupplierService.cs @@ -26,8 +26,9 @@ public class SupplierService public async Task GetByIdAsync(int id) { return await _context.Suppliers - .Include(s => s.Stocks) - .ThenInclude(st => st.Material) + .Include(s => s.Offerings) + .ThenInclude(o => o.StockItem) + .ThenInclude(si => si.Material) .FirstOrDefaultAsync(s => s.Id == id); } @@ -55,70 +56,70 @@ public class SupplierService } } - // Stock management - public async Task> GetStocksForSupplierAsync(int supplierId) + // Offering management + public async Task> GetOfferingsForSupplierAsync(int supplierId) { - return await _context.SupplierStocks - .Include(s => s.Material) - .Where(s => s.SupplierId == supplierId && s.IsActive) - .OrderBy(s => s.Material.Shape) - .ThenBy(s => s.Material.Size) - .ThenBy(s => s.LengthInches) + return await _context.SupplierOfferings + .Include(o => o.StockItem) + .ThenInclude(si => si.Material) + .Where(o => o.SupplierId == supplierId && o.IsActive) + .OrderBy(o => o.StockItem.Material.Shape) + .ThenBy(o => o.StockItem.Material.Size) + .ThenBy(o => o.StockItem.LengthInches) .ToListAsync(); } - public async Task> GetStocksForMaterialAsync(int materialId) + public async Task> GetOfferingsForStockItemAsync(int stockItemId) { - return await _context.SupplierStocks - .Include(s => s.Supplier) - .Where(s => s.MaterialId == materialId && s.IsActive && s.Supplier.IsActive) - .OrderBy(s => s.Supplier.Name) - .ThenBy(s => s.LengthInches) + return await _context.SupplierOfferings + .Include(o => o.Supplier) + .Where(o => o.StockItemId == stockItemId && o.IsActive && o.Supplier.IsActive) + .OrderBy(o => o.Supplier.Name) .ToListAsync(); } - public async Task GetStockByIdAsync(int id) + public async Task GetOfferingByIdAsync(int id) { - return await _context.SupplierStocks - .Include(s => s.Material) - .Include(s => s.Supplier) - .FirstOrDefaultAsync(s => s.Id == id); + return await _context.SupplierOfferings + .Include(o => o.StockItem) + .ThenInclude(si => si.Material) + .Include(o => o.Supplier) + .FirstOrDefaultAsync(o => o.Id == id); } - public async Task AddStockAsync(SupplierStock stock) + public async Task AddOfferingAsync(SupplierOffering offering) { - _context.SupplierStocks.Add(stock); + _context.SupplierOfferings.Add(offering); await _context.SaveChangesAsync(); - return stock; + return offering; } - public async Task UpdateStockAsync(SupplierStock stock) + public async Task UpdateOfferingAsync(SupplierOffering offering) { - _context.SupplierStocks.Update(stock); + _context.SupplierOfferings.Update(offering); await _context.SaveChangesAsync(); } - public async Task DeleteStockAsync(int id) + public async Task DeleteOfferingAsync(int id) { - var stock = await _context.SupplierStocks.FindAsync(id); - if (stock != null) + var offering = await _context.SupplierOfferings.FindAsync(id); + if (offering != null) { - stock.IsActive = false; + offering.IsActive = false; await _context.SaveChangesAsync(); } } - public async Task StockExistsAsync(int supplierId, int materialId, decimal lengthInches, int? excludeId = null) + public async Task OfferingExistsAsync(int supplierId, int stockItemId, int? excludeId = null) { - var query = _context.SupplierStocks.Where(s => - s.SupplierId == supplierId && - s.MaterialId == materialId && - s.LengthInches == lengthInches && - s.IsActive); + var query = _context.SupplierOfferings.Where(o => + o.SupplierId == supplierId && + o.StockItemId == stockItemId && + o.IsActive); if (excludeId.HasValue) { - query = query.Where(s => s.Id != excludeId.Value); + query = query.Where(o => o.Id != excludeId.Value); } return await query.AnyAsync();