Add full category path to AI price check for coating-type context
- Skip $0-priced items (placeholders/category headers) in RunAiPriceCheck - Build full category path (e.g. "Cerakote > Firearms") via BuildCategoryPath so Claude receives coating-type context — Cerakote pricing differs significantly from standard powder coat - Update AI system prompt to instruct Claude to use the category path when determining process type, equipment, cure times, and market rates Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -938,8 +938,8 @@ namespace PowderCoating.Web.Controllers
|
||||
r => r.CompanyId == currentUser.CompanyId);
|
||||
var report = existing.OrderByDescending(r => r.RunAt).FirstOrDefault();
|
||||
|
||||
var activeItems = await _unitOfWork.CatalogItems.FindAsync(ci => ci.IsActive);
|
||||
ViewBag.ActiveItemCount = activeItems.Count();
|
||||
var pricedItems = await _unitOfWork.CatalogItems.FindAsync(ci => ci.IsActive && ci.DefaultPrice > 0);
|
||||
ViewBag.ActiveItemCount = pricedItems.Count();
|
||||
|
||||
CatalogPriceCheckReportDto? dto = null;
|
||||
if (report != null)
|
||||
@@ -990,16 +990,23 @@ namespace PowderCoating.Web.Controllers
|
||||
|
||||
try
|
||||
{
|
||||
// Load all active catalog items with categories
|
||||
// Load active catalog items with a real price — skip $0 items (placeholders,
|
||||
// category headers, etc.) since there's no pricing to evaluate.
|
||||
var items = (await _unitOfWork.CatalogItems.FindAsync(
|
||||
ci => ci.IsActive, false, ci => ci.Category)).ToList();
|
||||
ci => ci.IsActive && ci.DefaultPrice > 0, false, ci => ci.Category)).ToList();
|
||||
|
||||
if (items.Count == 0)
|
||||
{
|
||||
TempData["Warning"] = "No active catalog items to analyze.";
|
||||
TempData["Warning"] = "No priced catalog items to analyze. Add prices to your catalog items first.";
|
||||
return RedirectToAction(nameof(AiPriceCheck));
|
||||
}
|
||||
|
||||
// Load all categories so we can build full paths (e.g. "Cerakote > Firearms").
|
||||
// The full path gives Claude the coating-type context it needs — an item in
|
||||
// "Firearms" under "Cerakote" costs very differently than one under "Powder Coat".
|
||||
var allCategories = (await _unitOfWork.CatalogCategories.GetAllAsync())
|
||||
.ToDictionary(c => c.Id);
|
||||
|
||||
// Load company operating costs
|
||||
var costs = (await _unitOfWork.CompanyOperatingCosts.FindAsync(
|
||||
c => c.CompanyId == currentUser.CompanyId)).FirstOrDefault();
|
||||
@@ -1012,7 +1019,7 @@ namespace PowderCoating.Web.Controllers
|
||||
Id = i.Id,
|
||||
Name = i.Name,
|
||||
Description = i.Description,
|
||||
CategoryName = i.Category?.Name ?? "Uncategorized",
|
||||
CategoryName = BuildCategoryPath(i.CategoryId, allCategories),
|
||||
CurrentPrice = i.DefaultPrice,
|
||||
ApproximateAreaSqFt = i.ApproximateArea,
|
||||
EstimatedMinutes = i.DefaultEstimatedMinutes,
|
||||
@@ -1083,6 +1090,25 @@ namespace PowderCoating.Web.Controllers
|
||||
$"Blaster ${c.SandblasterCostPerHour:F2}/hr | Booth ${c.CoatingBoothCostPerHour:F2}/hr | " +
|
||||
$"Powder ${c.PowderCostPerSqFt:F2}/sqft | " +
|
||||
$"{(c.PricingMode == "margin" ? "Margin" : "Markup")} {c.MarkupOrMarginPercent:F1}%";
|
||||
|
||||
/// <summary>
|
||||
/// Walks up the category parent chain to produce a full path like "Cerakote > Firearms",
|
||||
/// giving Claude the coating-type context it needs for accurate pricing analysis.
|
||||
/// </summary>
|
||||
private static string BuildCategoryPath(int? categoryId, Dictionary<int, CatalogCategory> all)
|
||||
{
|
||||
if (categoryId == null) return "Uncategorized";
|
||||
var parts = new List<string>();
|
||||
var current = all.GetValueOrDefault(categoryId.Value);
|
||||
while (current != null)
|
||||
{
|
||||
parts.Insert(0, current.Name);
|
||||
current = current.ParentCategoryId.HasValue
|
||||
? all.GetValueOrDefault(current.ParentCategoryId.Value)
|
||||
: null;
|
||||
}
|
||||
return parts.Count > 0 ? string.Join(" > ", parts) : "Uncategorized";
|
||||
}
|
||||
}
|
||||
|
||||
// Helper class for hierarchical display
|
||||
|
||||
Reference in New Issue
Block a user