feat: delete SupplierService, PurchaseItemService, and their API surface

This commit is contained in:
aj
2026-08-01 08:41:28 -04:00
parent 597181bd78
commit 063c844310
5 changed files with 0 additions and 489 deletions
@@ -1,172 +0,0 @@
using CutList.Core.Formatting;
using CutList.Web.Data.Entities;
using CutList.Web.DTOs;
using CutList.Web.Services;
using Microsoft.AspNetCore.Mvc;
namespace CutList.Web.Controllers;
[ApiController]
[Route("api/[controller]")]
public class SuppliersController : ControllerBase
{
private readonly SupplierService _supplierService;
public SuppliersController(SupplierService supplierService)
{
_supplierService = supplierService;
}
[HttpGet]
public async Task<ActionResult<List<SupplierDto>>> GetAll([FromQuery] bool includeInactive = false)
{
var suppliers = await _supplierService.GetAllAsync(includeInactive);
return Ok(suppliers.Select(MapToDto).ToList());
}
[HttpGet("{id}")]
public async Task<ActionResult<SupplierDto>> GetById(int id)
{
var supplier = await _supplierService.GetByIdAsync(id);
if (supplier == null)
return NotFound();
return Ok(MapToDto(supplier));
}
[HttpPost]
public async Task<ActionResult<SupplierDto>> Create(CreateSupplierDto dto)
{
if (string.IsNullOrWhiteSpace(dto.Name))
return BadRequest("Name is required");
var supplier = new Supplier
{
Name = dto.Name,
ContactInfo = dto.ContactInfo,
Notes = dto.Notes
};
await _supplierService.CreateAsync(supplier);
return CreatedAtAction(nameof(GetById), new { id = supplier.Id }, MapToDto(supplier));
}
[HttpPut("{id}")]
public async Task<ActionResult<SupplierDto>> Update(int id, UpdateSupplierDto dto)
{
var supplier = await _supplierService.GetByIdAsync(id);
if (supplier == null)
return NotFound();
if (dto.Name != null) supplier.Name = dto.Name;
if (dto.ContactInfo != null) supplier.ContactInfo = dto.ContactInfo;
if (dto.Notes != null) supplier.Notes = dto.Notes;
await _supplierService.UpdateAsync(supplier);
return Ok(MapToDto(supplier));
}
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
var supplier = await _supplierService.GetByIdAsync(id);
if (supplier == null)
return NotFound();
await _supplierService.DeleteAsync(id);
return NoContent();
}
// --- Offerings ---
[HttpGet("{id}/offerings")]
public async Task<ActionResult<List<OfferingDto>>> GetOfferings(int id)
{
var supplier = await _supplierService.GetByIdAsync(id);
if (supplier == null)
return NotFound();
var offerings = await _supplierService.GetOfferingsForSupplierAsync(id);
return Ok(offerings.Select(MapOfferingToDto).ToList());
}
[HttpPost("{id}/offerings")]
public async Task<ActionResult<OfferingDto>> CreateOffering(int id, CreateOfferingDto dto)
{
var supplier = await _supplierService.GetByIdAsync(id);
if (supplier == null)
return NotFound();
var exists = await _supplierService.OfferingExistsAsync(id, dto.StockItemId);
if (exists)
return Conflict("An offering for this supplier and stock item already exists");
var offering = new SupplierOffering
{
SupplierId = id,
StockItemId = dto.StockItemId,
PartNumber = dto.PartNumber,
SupplierDescription = dto.SupplierDescription,
Price = dto.Price,
Notes = dto.Notes
};
await _supplierService.AddOfferingAsync(offering);
// Reload with includes
var created = await _supplierService.GetOfferingByIdAsync(offering.Id);
return CreatedAtAction(nameof(GetOfferings), new { id }, MapOfferingToDto(created!));
}
[HttpPut("{supplierId}/offerings/{offeringId}")]
public async Task<ActionResult<OfferingDto>> UpdateOffering(int supplierId, int offeringId, UpdateOfferingDto dto)
{
var offering = await _supplierService.GetOfferingByIdAsync(offeringId);
if (offering == null || offering.SupplierId != supplierId)
return NotFound();
if (dto.PartNumber != null) offering.PartNumber = dto.PartNumber;
if (dto.SupplierDescription != null) offering.SupplierDescription = dto.SupplierDescription;
if (dto.Price.HasValue) offering.Price = dto.Price;
if (dto.Notes != null) offering.Notes = dto.Notes;
await _supplierService.UpdateOfferingAsync(offering);
return Ok(MapOfferingToDto(offering));
}
[HttpDelete("{supplierId}/offerings/{offeringId}")]
public async Task<IActionResult> DeleteOffering(int supplierId, int offeringId)
{
var offering = await _supplierService.GetOfferingByIdAsync(offeringId);
if (offering == null || offering.SupplierId != supplierId)
return NotFound();
await _supplierService.DeleteOfferingAsync(offeringId);
return NoContent();
}
private static SupplierDto MapToDto(Supplier s) => new()
{
Id = s.Id,
Name = s.Name,
ContactInfo = s.ContactInfo,
Notes = s.Notes,
IsActive = s.IsActive
};
private static OfferingDto MapOfferingToDto(SupplierOffering o) => new()
{
Id = o.Id,
SupplierId = o.SupplierId,
SupplierName = o.Supplier?.Name,
StockItemId = o.StockItemId,
MaterialName = o.StockItem?.Material?.DisplayName,
LengthInches = o.StockItem?.LengthInches,
LengthFormatted = o.StockItem != null ? ArchUnits.FormatFromInches((double)o.StockItem.LengthInches) : null,
PartNumber = o.PartNumber,
SupplierDescription = o.SupplierDescription,
Price = o.Price,
Notes = o.Notes,
IsActive = o.IsActive
};
}
-57
View File
@@ -1,57 +0,0 @@
namespace CutList.Web.DTOs;
public class SupplierDto
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string? ContactInfo { get; set; }
public string? Notes { get; set; }
public bool IsActive { get; set; }
}
public class CreateSupplierDto
{
public string Name { get; set; } = string.Empty;
public string? ContactInfo { get; set; }
public string? Notes { get; set; }
}
public class UpdateSupplierDto
{
public string? Name { get; set; }
public string? ContactInfo { get; set; }
public string? Notes { get; set; }
}
public class OfferingDto
{
public int Id { get; set; }
public int SupplierId { get; set; }
public string? SupplierName { get; set; }
public int StockItemId { get; set; }
public string? MaterialName { get; set; }
public decimal? LengthInches { get; set; }
public string? LengthFormatted { get; set; }
public string? PartNumber { get; set; }
public string? SupplierDescription { get; set; }
public decimal? Price { get; set; }
public string? Notes { get; set; }
public bool IsActive { get; set; }
}
public class CreateOfferingDto
{
public int StockItemId { get; set; }
public string? PartNumber { get; set; }
public string? SupplierDescription { get; set; }
public decimal? Price { get; set; }
public string? Notes { get; set; }
}
public class UpdateOfferingDto
{
public string? PartNumber { get; set; }
public string? SupplierDescription { get; set; }
public decimal? Price { get; set; }
public string? Notes { get; set; }
}
-2
View File
@@ -25,12 +25,10 @@ builder.Services.AddDbContextFactory<ApplicationDbContext>(options =>
// Add application services
builder.Services.AddScoped<MaterialService>();
builder.Services.AddScoped<SupplierService>();
builder.Services.AddScoped<StockItemService>();
builder.Services.AddScoped<JobService>();
builder.Services.AddScoped<CutListPackingService>();
builder.Services.AddScoped<ReportService>();
builder.Services.AddScoped<PurchaseItemService>();
builder.Services.AddScoped<CatalogService>();
var app = builder.Build();
-119
View File
@@ -1,119 +0,0 @@
using CutList.Web.Data;
using CutList.Web.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace CutList.Web.Services;
public class PurchaseItemService
{
private readonly IDbContextFactory<ApplicationDbContext> _factory;
public PurchaseItemService(IDbContextFactory<ApplicationDbContext> factory)
{
_factory = factory;
}
public async Task<List<PurchaseItem>> GetAllAsync(PurchaseItemStatus? status = null)
{
await using var context = _factory.CreateDbContext();
var query = context.PurchaseItems
.Include(p => p.StockItem)
.ThenInclude(s => s.Material)
.Include(p => p.Supplier)
.Include(p => p.Job)
.AsQueryable();
if (status.HasValue)
{
query = query.Where(p => p.Status == status.Value);
}
return await query
.OrderBy(p => p.Status)
.ThenByDescending(p => p.CreatedAt)
.ToListAsync();
}
public async Task<PurchaseItem?> GetByIdAsync(int id)
{
await using var context = _factory.CreateDbContext();
return await context.PurchaseItems
.Include(p => p.StockItem)
.ThenInclude(s => s.Material)
.Include(p => p.Supplier)
.Include(p => p.Job)
.FirstOrDefaultAsync(p => p.Id == id);
}
public async Task<PurchaseItem> CreateAsync(PurchaseItem item)
{
await using var context = _factory.CreateDbContext();
item.CreatedAt = DateTime.UtcNow;
context.PurchaseItems.Add(item);
await context.SaveChangesAsync();
return item;
}
public async Task CreateBulkAsync(List<PurchaseItem> items)
{
await using var context = _factory.CreateDbContext();
var now = DateTime.UtcNow;
foreach (var item in items)
{
item.CreatedAt = now;
}
context.PurchaseItems.AddRange(items);
await context.SaveChangesAsync();
}
public async Task UpdateAsync(PurchaseItem item)
{
await using var context = _factory.CreateDbContext();
item.UpdatedAt = DateTime.UtcNow;
context.PurchaseItems.Update(item);
await context.SaveChangesAsync();
}
public async Task UpdateStatusAsync(int id, PurchaseItemStatus status)
{
await using var context = _factory.CreateDbContext();
var item = await context.PurchaseItems.FindAsync(id);
if (item != null)
{
item.Status = status;
item.UpdatedAt = DateTime.UtcNow;
await context.SaveChangesAsync();
}
}
public async Task UpdateSupplierAsync(int id, int? supplierId)
{
await using var context = _factory.CreateDbContext();
var item = await context.PurchaseItems.FindAsync(id);
if (item != null)
{
item.SupplierId = supplierId;
item.UpdatedAt = DateTime.UtcNow;
await context.SaveChangesAsync();
}
}
public async Task DeleteAsync(int id)
{
await using var context = _factory.CreateDbContext();
var item = await context.PurchaseItems.FindAsync(id);
if (item != null)
{
context.PurchaseItems.Remove(item);
await context.SaveChangesAsync();
}
}
}
-139
View File
@@ -1,139 +0,0 @@
using CutList.Web.Data;
using CutList.Web.Data.Entities;
using Microsoft.EntityFrameworkCore;
namespace CutList.Web.Services;
public class SupplierService
{
private readonly IDbContextFactory<ApplicationDbContext> _factory;
public SupplierService(IDbContextFactory<ApplicationDbContext> factory)
{
_factory = factory;
}
public async Task<List<Supplier>> GetAllAsync(bool includeInactive = false)
{
await using var context = _factory.CreateDbContext();
var query = context.Suppliers.AsQueryable();
if (!includeInactive)
{
query = query.Where(s => s.IsActive);
}
return await query.OrderBy(s => s.Name).ToListAsync();
}
public async Task<Supplier?> GetByIdAsync(int id)
{
await using var context = _factory.CreateDbContext();
return await context.Suppliers
.Include(s => s.Offerings)
.ThenInclude(o => o.StockItem)
.ThenInclude(si => si.Material)
.FirstOrDefaultAsync(s => s.Id == id);
}
public async Task<Supplier> CreateAsync(Supplier supplier)
{
await using var context = _factory.CreateDbContext();
supplier.CreatedAt = DateTime.UtcNow;
context.Suppliers.Add(supplier);
await context.SaveChangesAsync();
return supplier;
}
public async Task UpdateAsync(Supplier supplier)
{
await using var context = _factory.CreateDbContext();
context.Suppliers.Update(supplier);
await context.SaveChangesAsync();
}
public async Task DeleteAsync(int id)
{
await using var context = _factory.CreateDbContext();
var supplier = await context.Suppliers.FindAsync(id);
if (supplier != null)
{
supplier.IsActive = false;
await context.SaveChangesAsync();
}
}
// Offering management
public async Task<List<SupplierOffering>> GetOfferingsForSupplierAsync(int supplierId)
{
await using var context = _factory.CreateDbContext();
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<SupplierOffering>> GetOfferingsForStockItemAsync(int stockItemId)
{
await using var context = _factory.CreateDbContext();
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<SupplierOffering?> GetOfferingByIdAsync(int id)
{
await using var context = _factory.CreateDbContext();
return await context.SupplierOfferings
.Include(o => o.StockItem)
.ThenInclude(si => si.Material)
.Include(o => o.Supplier)
.FirstOrDefaultAsync(o => o.Id == id);
}
public async Task<SupplierOffering> AddOfferingAsync(SupplierOffering offering)
{
await using var context = _factory.CreateDbContext();
context.SupplierOfferings.Add(offering);
await context.SaveChangesAsync();
return offering;
}
public async Task UpdateOfferingAsync(SupplierOffering offering)
{
await using var context = _factory.CreateDbContext();
context.SupplierOfferings.Update(offering);
await context.SaveChangesAsync();
}
public async Task DeleteOfferingAsync(int id)
{
await using var context = _factory.CreateDbContext();
var offering = await context.SupplierOfferings.FindAsync(id);
if (offering != null)
{
offering.IsActive = false;
await context.SaveChangesAsync();
}
}
public async Task<bool> OfferingExistsAsync(int supplierId, int stockItemId, int? excludeId = null)
{
await using var context = _factory.CreateDbContext();
var query = context.SupplierOfferings.Where(o =>
o.SupplierId == supplierId &&
o.StockItemId == stockItemId &&
o.IsActive);
if (excludeId.HasValue)
{
query = query.Where(o => o.Id != excludeId.Value);
}
return await query.AnyAsync();
}
}