diff --git a/src/PowderCoating.Application/Services/PricingCalculationService.cs b/src/PowderCoating.Application/Services/PricingCalculationService.cs index 0e4c39d..c56b501 100644 --- a/src/PowderCoating.Application/Services/PricingCalculationService.cs +++ b/src/PowderCoating.Application/Services/PricingCalculationService.cs @@ -590,53 +590,9 @@ public class PricingCalculationService : IPricingCalculationService { QuoteItemPricingResult itemResult; - // Catalog items - if they have coats, add coat costs to catalog base price - if (item.CatalogItemId.HasValue) - { - var catalogItem = await _unitOfWork.CatalogItems.GetByIdAsync(item.CatalogItemId.Value); - if (catalogItem != null) - { - // If the catalog item has coats, calculate using CalculateQuoteItemPriceAsync - // (which already includes the catalog base price + coat costs) - if (item.Coats != null && item.Coats.Any()) - { - // CalculateQuoteItemPriceAsync already adds catalog base price to coat costs - itemResult = await CalculateQuoteItemPriceAsync(item, companyId, ovenCostOverride); - } - else - { - // No coats - use simple catalog default price - var catalogItemTotal = catalogItem.DefaultPrice * item.Quantity; - itemResult = new QuoteItemPricingResult - { - MaterialCost = 0, - LaborCost = 0, - EquipmentCost = 0, - ItemSubtotal = catalogItemTotal, - UnitPrice = catalogItem.DefaultPrice, - TotalPrice = catalogItemTotal - }; - } - } - else - { - // Catalog item not found, create zero result - itemResult = new QuoteItemPricingResult - { - MaterialCost = 0, - LaborCost = 0, - EquipmentCost = 0, - ItemSubtotal = 0, - UnitPrice = 0, - TotalPrice = 0 - }; - } - } - else - { - // Calculated items use the full pricing calculation - itemResult = await CalculateQuoteItemPriceAsync(item, companyId, ovenCostOverride); - } + // All items (catalog and calculated) go through CalculateQuoteItemPriceAsync, which + // handles PowderCostOverride, prep cost inclusion, and all item type variants. + itemResult = await CalculateQuoteItemPriceAsync(item, companyId, ovenCostOverride); itemResults.Add(itemResult); } diff --git a/src/PowderCoating.Application/Services/QuotePricingAssemblyService.cs b/src/PowderCoating.Application/Services/QuotePricingAssemblyService.cs index bf5a2f6..f023d3b 100644 --- a/src/PowderCoating.Application/Services/QuotePricingAssemblyService.cs +++ b/src/PowderCoating.Application/Services/QuotePricingAssemblyService.cs @@ -104,8 +104,11 @@ public class QuotePricingAssemblyService : IQuotePricingAssemblyService var catalogItem = await _unitOfWork.CatalogItems.GetByIdAsync(itemDto.CatalogItemId.Value); if (catalogItem != null) { - item.UnitPrice = catalogItem.DefaultPrice; - item.TotalPrice = catalogItem.DefaultPrice * itemDto.Quantity; + var unitPrice = itemDto.PowderCostOverride is > 0 + ? itemDto.PowderCostOverride.Value + : catalogItem.DefaultPrice; + item.UnitPrice = unitPrice; + item.TotalPrice = unitPrice * itemDto.Quantity; _logger.LogInformation("Catalog item no coats: UnitPrice={Unit}, TotalPrice={Total}", item.UnitPrice, item.TotalPrice); } diff --git a/src/PowderCoating.Web/Views/Jobs/Details.cshtml b/src/PowderCoating.Web/Views/Jobs/Details.cshtml index a0368d1..6632886 100644 --- a/src/PowderCoating.Web/Views/Jobs/Details.cshtml +++ b/src/PowderCoating.Web/Views/Jobs/Details.cshtml @@ -2978,6 +2978,7 @@ if (!r.ok) { const d = await r.json(); errEl.textContent = d.error ?? 'Save failed.'; errEl.classList.remove('d-none'); return; } modal.hide(); await load(); + costing.load(); showToast(id > 0 ? 'Time entry updated.' : 'Time logged.', 'success'); } catch { errEl.textContent = 'Network error.'; errEl.classList.remove('d-none'); } } @@ -2990,7 +2991,7 @@ headers: { 'Content-Type': 'application/json', 'RequestVerificationToken': tok }, body: JSON.stringify({ id }) }); - if (r.ok) { await load(); showToast('Time entry deleted.', 'secondary'); } + if (r.ok) { await load(); costing.load(); showToast('Time entry deleted.', 'secondary'); } } function esc(s) {