From 063c84431067e09bb098f94b5f4f875738a272a9 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sat, 1 Aug 2026 08:41:28 -0400 Subject: [PATCH] feat: delete SupplierService, PurchaseItemService, and their API surface --- .../Controllers/SuppliersController.cs | 172 ------------------ CutList.Web/DTOs/SupplierDtos.cs | 57 ------ CutList.Web/Program.cs | 2 - CutList.Web/Services/PurchaseItemService.cs | 119 ------------ CutList.Web/Services/SupplierService.cs | 139 -------------- 5 files changed, 489 deletions(-) delete mode 100644 CutList.Web/Controllers/SuppliersController.cs delete mode 100644 CutList.Web/DTOs/SupplierDtos.cs delete mode 100644 CutList.Web/Services/PurchaseItemService.cs delete mode 100644 CutList.Web/Services/SupplierService.cs diff --git a/CutList.Web/Controllers/SuppliersController.cs b/CutList.Web/Controllers/SuppliersController.cs deleted file mode 100644 index e13ac0e..0000000 --- a/CutList.Web/Controllers/SuppliersController.cs +++ /dev/null @@ -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>> GetAll([FromQuery] bool includeInactive = false) - { - var suppliers = await _supplierService.GetAllAsync(includeInactive); - return Ok(suppliers.Select(MapToDto).ToList()); - } - - [HttpGet("{id}")] - public async Task> GetById(int id) - { - var supplier = await _supplierService.GetByIdAsync(id); - if (supplier == null) - return NotFound(); - - return Ok(MapToDto(supplier)); - } - - [HttpPost] - public async Task> 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> 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 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>> 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> 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> 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 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 - }; -} diff --git a/CutList.Web/DTOs/SupplierDtos.cs b/CutList.Web/DTOs/SupplierDtos.cs deleted file mode 100644 index 9c70813..0000000 --- a/CutList.Web/DTOs/SupplierDtos.cs +++ /dev/null @@ -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; } -} diff --git a/CutList.Web/Program.cs b/CutList.Web/Program.cs index c842d38..96d06b9 100644 --- a/CutList.Web/Program.cs +++ b/CutList.Web/Program.cs @@ -25,12 +25,10 @@ builder.Services.AddDbContextFactory(options => // Add application services builder.Services.AddScoped(); -builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); -builder.Services.AddScoped(); builder.Services.AddScoped(); var app = builder.Build(); diff --git a/CutList.Web/Services/PurchaseItemService.cs b/CutList.Web/Services/PurchaseItemService.cs deleted file mode 100644 index f56120a..0000000 --- a/CutList.Web/Services/PurchaseItemService.cs +++ /dev/null @@ -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 _factory; - - public PurchaseItemService(IDbContextFactory factory) - { - _factory = factory; - } - - public async Task> 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 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 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 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(); - } - } -} diff --git a/CutList.Web/Services/SupplierService.cs b/CutList.Web/Services/SupplierService.cs deleted file mode 100644 index db1078c..0000000 --- a/CutList.Web/Services/SupplierService.cs +++ /dev/null @@ -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 _factory; - - public SupplierService(IDbContextFactory factory) - { - _factory = factory; - } - - public async Task> 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 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 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> 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> 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 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 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 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(); - } -}