From 9292f3169c3988001a397dd874b284a0b3a892f5 Mon Sep 17 00:00:00 2001 From: Scott Pouliot Date: Wed, 6 May 2026 16:43:42 -0400 Subject: [PATCH] Fix catalog item pricing and rogue margin-points text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Catalog DefaultPrice is always the base price — removed the IncludePrepCost gate that was adding prep service labor on top of catalog items. PrepServices on catalog items exist for scheduling purposes only, not pricing. Also fixed Razor syntax bug in Details.cshtml where @(expr).ToString("F1") rendered the raw decimal followed by the literal string ".ToString("F1")" instead of the formatted value. Co-Authored-By: Claude Sonnet 4.6 --- .../Services/PricingCalculationService.cs | 12 ++---------- src/PowderCoating.Web/Views/Quotes/Details.cshtml | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/PowderCoating.Application/Services/PricingCalculationService.cs b/src/PowderCoating.Application/Services/PricingCalculationService.cs index ff16d20..c86fef6 100644 --- a/src/PowderCoating.Application/Services/PricingCalculationService.cs +++ b/src/PowderCoating.Application/Services/PricingCalculationService.cs @@ -391,16 +391,8 @@ public class PricingCalculationService : IPricingCalculationService baseSubtotal = baseUnitPrice * item.Quantity; _logger.LogInformation("Catalog base: ${Price} × {Qty} = ${Base}", baseUnitPrice, item.Quantity, baseSubtotal); - // Optionally add prep service labor cost for catalog items (opt-in toggle in wizard) - // AI items exclude prep cost — it's already baked into the AI estimate - if (!item.IsAiItem && item.IncludePrepCost && item.PrepServices != null && item.PrepServices.Any()) - { - var totalPrepMinutes = item.PrepServices.Sum(ps => ps.EstimatedMinutes); - var prepLaborCost = (totalPrepMinutes / 60m) * costs.StandardLaborRate; - baseSubtotal += prepLaborCost; - totalLaborCost += prepLaborCost; - _logger.LogInformation("Catalog item prep cost: {Min}min × ${Rate}/h = ${Cost}", totalPrepMinutes, costs.StandardLaborRate, prepLaborCost); - } + // Catalog DefaultPrice is always the base — prep service labor is never added on top. + // PrepServices on catalog items are used for scheduling only, not pricing. // Custom (non-inventory) powder coats must be purchased separately — add their material // cost on top of the catalog base price. Inventory powder is assumed baked into DefaultPrice. diff --git a/src/PowderCoating.Web/Views/Quotes/Details.cshtml b/src/PowderCoating.Web/Views/Quotes/Details.cshtml index d4ff49b..01dc410 100644 --- a/src/PowderCoating.Web/Views/Quotes/Details.cshtml +++ b/src/PowderCoating.Web/Views/Quotes/Details.cshtml @@ -1230,7 +1230,7 @@ var priceBeforeDiscount = pb.Total + pb.DiscountAmount; var marginBeforeDiscount = priceBeforeDiscount > 0 ? ((priceBeforeDiscount - totalDirectCost) / priceBeforeDiscount * 100m) : 0m;
- Without discount: @marginBeforeDiscount.ToString("F1")% — discount cost you @(marginBeforeDiscount - effectiveMargin).ToString("F1") margin points + Without discount: @marginBeforeDiscount.ToString("F1")% — discount cost you @((marginBeforeDiscount - effectiveMargin).ToString("F1")) margin points
} }