Fix AI photo quote always returning shop minimum price
Two bugs caused AI estimates to collapse to the shop minimum floor: 1. Coating rate with no guard: when a shop hadn't calibrated their coating gun (rate = 0), the prompt injected '~0 sqft/hr' paired with 'MUST use shop-specific rates' — Claude returned near-zero estimatedMinutes, zeroing labor cost and triggering the floor. Fixed to mirror the existing blast-rate guard: rate=0 now sends a fallback instruction to use conservative industry-average times. 2. Per-item minutes divided by quantity: both the system prompt and user prompt explicitly tell Claude to return estimatedMinutes 'per single item', but CalculatePricingPreview() was dividing by qty anyway. For qty > 1 this halved (or more) the labor cost, again pushing toward the floor. Removed the incorrect divide. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -435,7 +435,15 @@ Only ask follow-up questions if truly needed — prefer to make reasonable assum
|
||||
shopSpeedLine = "- Shop blast rate: not calibrated — use conservative industry-average times for this shop tier";
|
||||
}
|
||||
|
||||
var coatingSpeedLine = $"- THIS SHOP'S coating application rate: ~{coatingRate:F0} sqft/hr";
|
||||
string coatingSpeedLine;
|
||||
if (coatingRate > 0)
|
||||
coatingSpeedLine = $"- THIS SHOP'S coating application rate: ~{coatingRate:F0} sqft/hr — use this to derive coating time (surface area ÷ coating rate), NOT generic industry averages";
|
||||
else
|
||||
coatingSpeedLine = "- Shop coating rate: not calibrated — use conservative industry-average coating times for this shop tier";
|
||||
|
||||
var rateInstruction = (blastRate > 0 || coatingRate > 0)
|
||||
? "IMPORTANT: For estimatedMinutes, you MUST use this shop's specific rates above where provided, not generic industry speeds."
|
||||
: "IMPORTANT: For estimatedMinutes, use conservative industry-average times appropriate for a professional powder coating shop.";
|
||||
|
||||
return $@"Please analyze the item(s) in the photo(s) for powder coating estimation.
|
||||
|
||||
@@ -453,7 +461,7 @@ Company operating costs for your reference:
|
||||
{shopSpeedLine}
|
||||
{coatingSpeedLine}
|
||||
|
||||
IMPORTANT: For estimatedMinutes, you MUST use this shop's specific blast and coating rates above, not generic industry speeds.
|
||||
{rateInstruction}
|
||||
Sandblasting time = surface area of item ÷ shop blast rate (sqft/hr), adjusted for part complexity (harder-to-reach areas take more passes).
|
||||
Coating time = surface area ÷ shop coating rate, adjusted for masking and complexity.
|
||||
Include racking/unracking, inspection, and any material-specific prep (preheat handling, chemical stripping) as ACTIVE labor time.
|
||||
@@ -547,9 +555,9 @@ Respond with the JSON object only.";
|
||||
_ => 0
|
||||
};
|
||||
|
||||
// Labor cost — AI returns total batch minutes, so divide by quantity to get per-item minutes.
|
||||
// The unit price × quantity must equal the total batch labor cost.
|
||||
var rawPerItemMinutes = aiResult.EstimatedMinutes / Math.Max(1m, (decimal)request.Quantity);
|
||||
// Labor cost — AI returns per-item minutes (both system prompt and user prompt say "per single item").
|
||||
// Unit price is per item; the caller multiplies by quantity for the line total.
|
||||
var rawPerItemMinutes = aiResult.EstimatedMinutes;
|
||||
var minFloorApplied = materialMinMinutes > 0 && rawPerItemMinutes < materialMinMinutes;
|
||||
var perItemMinutes = minFloorApplied ? materialMinMinutes : rawPerItemMinutes;
|
||||
var laborHours = perItemMinutes / 60m;
|
||||
|
||||
Reference in New Issue
Block a user