Miscellaneous UI and pricing updates from prior sessions
- PricingCalculationService: powder coverage and specific gravity math fixes - Dashboard/Index: minor widget updates - Jobs/Details, Jobs/Intake: shop floor and intake view improvements - Quotes/Details: detail view updates - GiftCertificates/Details: detail view update - job-photos.js: photo gallery improvements Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -422,12 +422,14 @@ public class PricingCalculationService : IPricingCalculationService
|
||||
else
|
||||
{
|
||||
// Non-catalog: derive base from first coat's material + labor + equipment + markup
|
||||
decimal coatLaborCost = 0m; // coat-only labor, used for coating booth (not prep/sandblast)
|
||||
if (item.Coats != null && item.Coats.Count > 0)
|
||||
{
|
||||
var firstCoatResult = await CalculateCoatPriceAsync(
|
||||
item.Coats[0], item.SurfaceAreaSqFt, item.Quantity, 0, item.EstimatedMinutes, companyId);
|
||||
totalMaterialCost = firstCoatResult.CoatMaterialCost;
|
||||
totalLaborCost = firstCoatResult.CoatLaborCost;
|
||||
coatLaborCost = firstCoatResult.CoatLaborCost;
|
||||
totalLaborCost = coatLaborCost;
|
||||
}
|
||||
|
||||
// Prep service labor (done once per item batch)
|
||||
@@ -443,9 +445,10 @@ public class PricingCalculationService : IPricingCalculationService
|
||||
// Consumables surcharge (5% of material)
|
||||
totalMaterialCost += totalMaterialCost * ConsumablesSurchargePercent;
|
||||
|
||||
// Equipment cost: coating booth only (oven cost moved to quote-level batch calculation)
|
||||
var totalLaborHours = totalLaborCost / costs.StandardLaborRate;
|
||||
totalEquipmentCost = totalLaborHours * costs.CoatingBoothCostPerHour;
|
||||
// Equipment cost: coating booth only — use coat labor hours, not prep/sandblast hours
|
||||
// (sandblasting happens in a blast cabinet, not the powder coating booth)
|
||||
var coatLaborHours = costs.StandardLaborRate > 0 ? coatLaborCost / costs.StandardLaborRate : 0m;
|
||||
totalEquipmentCost = coatLaborHours * costs.CoatingBoothCostPerHour;
|
||||
|
||||
// Apply pricing mode: markup on material only, or target margin on total cost
|
||||
if (costs.PricingMode == PowderCoating.Core.Enums.PricingMode.MarginOnTotalCost)
|
||||
@@ -675,22 +678,24 @@ public class PricingCalculationService : IPricingCalculationService
|
||||
var effectiveBatches = Math.Max(1, ovenBatches);
|
||||
var fullOvenBatchCost = effectiveBatches * (effectiveCycleMinutes / 60m) * effectiveOvenRate;
|
||||
|
||||
// Scale oven cost by the fraction of total surface area coming from non-AI items.
|
||||
// Use item count as a fallback when surface areas are all zero.
|
||||
var totalSqFt = items.Sum(i => i.SurfaceAreaSqFt * i.Quantity);
|
||||
var aiSqFt = items.Where(i => i.IsAiItem).Sum(i => i.SurfaceAreaSqFt * i.Quantity);
|
||||
var nonAiSqFt = totalSqFt - aiSqFt;
|
||||
// Only items with coating layers go in the oven — sandblast/prep-only items (zero coats) don't.
|
||||
// Of those coating items, AI items already have oven cost baked into their AI price.
|
||||
var coatingItems = items.Where(i => i.Coats != null && i.Coats.Any()).ToList();
|
||||
var nonAiCoatItems = coatingItems.Where(i => !i.IsAiItem).ToList();
|
||||
|
||||
decimal nonAiFraction;
|
||||
if (totalSqFt > 0)
|
||||
if (!coatingItems.Any())
|
||||
{
|
||||
nonAiFraction = nonAiSqFt / totalSqFt;
|
||||
nonAiFraction = 0m; // No coated items — no oven charge
|
||||
}
|
||||
else
|
||||
{
|
||||
var totalCount = items.Count;
|
||||
var aiCount = items.Count(i => i.IsAiItem);
|
||||
nonAiFraction = totalCount > 0 ? (decimal)(totalCount - aiCount) / totalCount : 1m;
|
||||
var totalCoatSqFt = coatingItems.Sum(i => i.SurfaceAreaSqFt * i.Quantity);
|
||||
var nonAiCoatSqFt = nonAiCoatItems.Sum(i => i.SurfaceAreaSqFt * i.Quantity);
|
||||
if (totalCoatSqFt > 0)
|
||||
nonAiFraction = nonAiCoatSqFt / totalCoatSqFt;
|
||||
else
|
||||
nonAiFraction = coatingItems.Count > 0 ? (decimal)nonAiCoatItems.Count / coatingItems.Count : 1m;
|
||||
}
|
||||
|
||||
var ovenBatchCost = fullOvenBatchCost * nonAiFraction;
|
||||
|
||||
Reference in New Issue
Block a user