refactor: strip supplier/pricing from StockItemService and stock-items API
This commit is contained in:
@@ -11,12 +11,10 @@ namespace CutList.Web.Controllers;
|
||||
public class StockItemsController : ControllerBase
|
||||
{
|
||||
private readonly StockItemService _stockItemService;
|
||||
private readonly SupplierService _supplierService;
|
||||
|
||||
public StockItemsController(StockItemService stockItemService, SupplierService supplierService)
|
||||
public StockItemsController(StockItemService stockItemService)
|
||||
{
|
||||
_stockItemService = stockItemService;
|
||||
_supplierService = supplierService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
@@ -120,34 +118,6 @@ public class StockItemsController : ControllerBase
|
||||
return Ok(items.Select(MapToDto).ToList());
|
||||
}
|
||||
|
||||
[HttpGet("{id}/offerings")]
|
||||
public async Task<ActionResult<List<OfferingDto>>> GetOfferings(int id)
|
||||
{
|
||||
var item = await _stockItemService.GetByIdAsync(id);
|
||||
if (item == null)
|
||||
return NotFound();
|
||||
|
||||
var offerings = await _supplierService.GetOfferingsForStockItemAsync(id);
|
||||
return Ok(offerings.Select(MapOfferingToDto).ToList());
|
||||
}
|
||||
|
||||
[HttpGet("{id}/pricing")]
|
||||
public async Task<ActionResult<StockPricingDto>> GetPricing(int id)
|
||||
{
|
||||
var item = await _stockItemService.GetByIdAsync(id);
|
||||
if (item == null)
|
||||
return NotFound();
|
||||
|
||||
var avgCost = await _stockItemService.GetAverageCostAsync(id);
|
||||
var lastPrice = await _stockItemService.GetLastPurchasePriceAsync(id);
|
||||
|
||||
return Ok(new StockPricingDto
|
||||
{
|
||||
AverageCost = avgCost,
|
||||
LastPurchasePrice = lastPrice
|
||||
});
|
||||
}
|
||||
|
||||
[HttpGet("{id}/transactions")]
|
||||
public async Task<ActionResult<List<StockTransactionDto>>> GetTransactions(int id, [FromQuery] int? limit = null)
|
||||
{
|
||||
@@ -164,7 +134,7 @@ public class StockItemsController : ControllerBase
|
||||
{
|
||||
try
|
||||
{
|
||||
var transaction = await _stockItemService.AddStockAsync(id, dto.Quantity, dto.SupplierId, dto.UnitPrice, dto.Notes);
|
||||
var transaction = await _stockItemService.AddStockAsync(id, dto.Quantity, dto.Notes);
|
||||
return Ok(MapTransactionToDto(transaction));
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
@@ -250,23 +220,7 @@ public class StockItemsController : ControllerBase
|
||||
Type = t.Type.ToString(),
|
||||
JobId = t.JobId,
|
||||
JobNumber = t.Job?.JobNumber,
|
||||
SupplierId = t.SupplierId,
|
||||
SupplierName = t.Supplier?.Name,
|
||||
UnitPrice = t.UnitPrice,
|
||||
Notes = t.Notes,
|
||||
CreatedAt = t.CreatedAt
|
||||
};
|
||||
|
||||
private static OfferingDto MapOfferingToDto(SupplierOffering o) => new()
|
||||
{
|
||||
Id = o.Id,
|
||||
SupplierId = o.SupplierId,
|
||||
SupplierName = o.Supplier?.Name,
|
||||
StockItemId = o.StockItemId,
|
||||
PartNumber = o.PartNumber,
|
||||
SupplierDescription = o.SupplierDescription,
|
||||
Price = o.Price,
|
||||
Notes = o.Notes,
|
||||
IsActive = o.IsActive
|
||||
};
|
||||
}
|
||||
|
||||
@@ -37,9 +37,6 @@ public class StockTransactionDto
|
||||
public string Type { get; set; } = string.Empty;
|
||||
public int? JobId { get; set; }
|
||||
public string? JobNumber { get; set; }
|
||||
public int? SupplierId { get; set; }
|
||||
public string? SupplierName { get; set; }
|
||||
public decimal? UnitPrice { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
@@ -47,8 +44,6 @@ public class StockTransactionDto
|
||||
public class AddStockDto
|
||||
{
|
||||
public int Quantity { get; set; }
|
||||
public int? SupplierId { get; set; }
|
||||
public decimal? UnitPrice { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
}
|
||||
|
||||
@@ -70,9 +65,3 @@ public class ScrapStockDto
|
||||
public int Quantity { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
}
|
||||
|
||||
public class StockPricingDto
|
||||
{
|
||||
public decimal? AverageCost { get; set; }
|
||||
public decimal? LastPurchasePrice { get; set; }
|
||||
}
|
||||
|
||||
@@ -57,8 +57,6 @@ public class StockItemService
|
||||
|
||||
return await context.StockItems
|
||||
.Include(s => s.Material)
|
||||
.Include(s => s.SupplierOfferings)
|
||||
.ThenInclude(o => o.Supplier)
|
||||
.FirstOrDefaultAsync(s => s.Id == id);
|
||||
}
|
||||
|
||||
@@ -112,7 +110,7 @@ public class StockItemService
|
||||
}
|
||||
|
||||
// Stock transaction methods
|
||||
public async Task<StockTransaction> AddStockAsync(int stockItemId, int quantity, int? supplierId = null, decimal? unitPrice = null, string? notes = null)
|
||||
public async Task<StockTransaction> AddStockAsync(int stockItemId, int quantity, string? notes = null)
|
||||
{
|
||||
await using var context = _factory.CreateDbContext();
|
||||
|
||||
@@ -124,8 +122,6 @@ public class StockItemService
|
||||
StockItemId = stockItemId,
|
||||
Quantity = quantity,
|
||||
Type = StockTransactionType.Received,
|
||||
SupplierId = supplierId,
|
||||
UnitPrice = unitPrice,
|
||||
Notes = notes,
|
||||
CreatedAt = DateTime.UtcNow
|
||||
};
|
||||
@@ -139,34 +135,6 @@ public class StockItemService
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public async Task<decimal?> GetAverageCostAsync(int stockItemId)
|
||||
{
|
||||
await using var context = _factory.CreateDbContext();
|
||||
|
||||
var transactions = await context.StockTransactions
|
||||
.Where(t => t.StockItemId == stockItemId && t.Type == StockTransactionType.Received && t.UnitPrice.HasValue)
|
||||
.ToListAsync();
|
||||
|
||||
if (transactions.Count == 0)
|
||||
return null;
|
||||
|
||||
var totalCost = transactions.Sum(t => t.Quantity * t.UnitPrice!.Value);
|
||||
var totalQty = transactions.Sum(t => t.Quantity);
|
||||
|
||||
return totalQty > 0 ? totalCost / totalQty : null;
|
||||
}
|
||||
|
||||
public async Task<decimal?> GetLastPurchasePriceAsync(int stockItemId)
|
||||
{
|
||||
await using var context = _factory.CreateDbContext();
|
||||
|
||||
return await context.StockTransactions
|
||||
.Where(t => t.StockItemId == stockItemId && t.Type == StockTransactionType.Received && t.UnitPrice.HasValue)
|
||||
.OrderByDescending(t => t.CreatedAt)
|
||||
.Select(t => t.UnitPrice)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<StockTransaction> UseStockAsync(int stockItemId, int quantity, int? jobId = null, string? notes = null)
|
||||
{
|
||||
await using var context = _factory.CreateDbContext();
|
||||
@@ -251,7 +219,6 @@ public class StockItemService
|
||||
|
||||
var query = context.StockTransactions
|
||||
.Include(t => t.Job)
|
||||
.Include(t => t.Supplier)
|
||||
.Where(t => t.StockItemId == stockItemId)
|
||||
.OrderByDescending(t => t.CreatedAt)
|
||||
.AsQueryable();
|
||||
|
||||
Reference in New Issue
Block a user