feat: Update service layer for new stock model
- Add StockItemService for CRUD operations on stock items - Update SupplierService to manage SupplierOfferings instead of SupplierStock (GetOfferingsForSupplierAsync, AddOfferingAsync, etc.) - Update CutListPackingService to use StockItems for available lengths - Register StockItemService in Program.cs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,7 @@ builder.Services.AddDbContext<ApplicationDbContext>(options =>
|
||||
// Add application services
|
||||
builder.Services.AddScoped<MaterialService>();
|
||||
builder.Services.AddScoped<SupplierService>();
|
||||
builder.Services.AddScoped<StockItemService>();
|
||||
builder.Services.AddScoped<ProjectService>();
|
||||
builder.Services.AddScoped<CutListPackingService>();
|
||||
builder.Services.AddScoped<ReportService>();
|
||||
|
||||
@@ -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))
|
||||
|
||||
99
CutList.Web/Services/StockItemService.cs
Normal file
99
CutList.Web/Services/StockItemService.cs
Normal file
@@ -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<List<StockItem>> 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<List<StockItem>> 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<StockItem?> 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<StockItem> 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<bool> 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();
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,9 @@ public class SupplierService
|
||||
public async Task<Supplier?> 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<List<SupplierStock>> GetStocksForSupplierAsync(int supplierId)
|
||||
// Offering management
|
||||
public async Task<List<SupplierOffering>> 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<List<SupplierStock>> GetStocksForMaterialAsync(int materialId)
|
||||
public async Task<List<SupplierOffering>> 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<SupplierStock?> GetStockByIdAsync(int id)
|
||||
public async Task<SupplierOffering?> 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<SupplierStock> AddStockAsync(SupplierStock stock)
|
||||
public async Task<SupplierOffering> 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<bool> StockExistsAsync(int supplierId, int materialId, decimal lengthInches, int? excludeId = null)
|
||||
public async Task<bool> 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();
|
||||
|
||||
Reference in New Issue
Block a user