diff --git a/src/PowderCoating.Web/Controllers/InventoryController.cs b/src/PowderCoating.Web/Controllers/InventoryController.cs
index 0cadef0..34305e0 100644
--- a/src/PowderCoating.Web/Controllers/InventoryController.cs
+++ b/src/PowderCoating.Web/Controllers/InventoryController.cs
@@ -679,6 +679,7 @@ public class InventoryController : Controller
return Json(new { success = false, errorMessage = "AI Inventory Assist is not enabled for your account. Contact your administrator." });
var result = await _aiLookupService.LookupAsync(manufacturer, colorName, colorCode, partNumber);
+ if (result.Success) await ApplyTdsCureFallbackAsync(result, colorName);
return Json(result);
}
@@ -701,9 +702,31 @@ public class InventoryController : Controller
return Json(new { success = false, errorMessage = "No product URL provided." });
var result = await _aiLookupService.LookupByUrlAsync(productUrl, colorName);
+ if (result.Success) await ApplyTdsCureFallbackAsync(result, colorName);
return Json(result);
}
+ ///
+ /// If cure temperature or cure time is still missing after the primary lookup but a TDS URL
+ /// was returned, fetches that page and asks Claude to extract only the cure schedule.
+ /// Mutates in place; silently no-ops on failure so callers
+ /// can always return the result even if the TDS fetch does not help.
+ ///
+ private async Task ApplyTdsCureFallbackAsync(InventoryAiLookupResult result, string? colorName)
+ {
+ if ((result.CureTemperatureF == null || result.CureTimeMinutes == null)
+ && !string.IsNullOrEmpty(result.TdsUrl))
+ {
+ _logger.LogInformation("Cure specs missing after lookup; trying TDS at {Url}", result.TdsUrl);
+ var tds = await _aiLookupService.FetchTdsCureSpecsAsync(result.TdsUrl, colorName);
+ if (tds.Success)
+ {
+ if (result.CureTemperatureF == null) result.CureTemperatureF = tds.CureTemperatureF;
+ if (result.CureTimeMinutes == null) result.CureTimeMinutes = tds.CureTimeMinutes;
+ }
+ }
+ }
+
///
/// Accepts a base64 label photo or a decoded QR URL from the in-browser label scanner,
/// runs it through Claude (vision for photos, URL-fetch for QR), searches the platform
@@ -834,22 +857,14 @@ public class InventoryController : Controller
}
}
- // If cure specs are still missing but we have a TDS URL, fetch it and try to extract
- // cure temperature and cure time. Most TDS pages are HTML; PDFs fail silently.
- var resolvedCureTemp = catalogMatch?.CureTemperatureF ?? aiResult.CureTemperatureF;
- var resolvedCureTime = catalogMatch?.CureTimeMinutes ?? aiResult.CureTimeMinutes;
- var resolvedTdsUrl = catalogMatch?.TdsUrl ?? aiResult.TdsUrl;
-
- if ((resolvedCureTemp == null || resolvedCureTime == null) && !string.IsNullOrEmpty(resolvedTdsUrl))
- {
- _logger.LogInformation("Cure specs missing after main lookup; trying TDS at {Url}", resolvedTdsUrl);
- var tdsResult = await _aiLookupService.FetchTdsCureSpecsAsync(resolvedTdsUrl, colorName);
- if (tdsResult.Success)
- {
- if (resolvedCureTemp == null) aiResult.CureTemperatureF = tdsResult.CureTemperatureF;
- if (resolvedCureTime == null) aiResult.CureTimeMinutes = tdsResult.CureTimeMinutes;
- }
- }
+ // If cure specs are still missing but we have a TDS URL, try reading it.
+ // Prefer the catalog's TDS URL if present; the catalog record is more reliable.
+ // Temporarily merge the catalog TDS URL into aiResult so ApplyTdsCureFallbackAsync
+ // sees the best available URL and writes the result back into aiResult.
+ if (catalogMatch?.CureTemperatureF != null) aiResult.CureTemperatureF = catalogMatch.CureTemperatureF;
+ if (catalogMatch?.CureTimeMinutes != null) aiResult.CureTimeMinutes = catalogMatch.CureTimeMinutes;
+ aiResult.TdsUrl ??= catalogMatch?.TdsUrl;
+ await ApplyTdsCureFallbackAsync(aiResult, colorName);
// Check if this product already exists in the tenant's inventory.
// Match by ManufacturerPartNumber first (most precise); fall back to color name + manufacturer.
diff --git a/src/PowderCoating.Web/Views/Inventory/_InventoryColorFamilyScripts.cshtml b/src/PowderCoating.Web/Views/Inventory/_InventoryColorFamilyScripts.cshtml
index 7b968d4..4dba788 100644
--- a/src/PowderCoating.Web/Views/Inventory/_InventoryColorFamilyScripts.cshtml
+++ b/src/PowderCoating.Web/Views/Inventory/_InventoryColorFamilyScripts.cshtml
@@ -450,6 +450,21 @@
aiFilledImage = true;
}
+ // SDS / TDS document URLs — fill inputs and show open-link buttons
+ const fillDocUrl = (fieldId, linkId, url, label) => {
+ if (!url) return;
+ const el = document.getElementById(fieldId);
+ const link = document.getElementById(linkId);
+ if (el && (forceRefill || !el.value.trim())) {
+ el.value = url;
+ filled.push(label);
+ if (!aiFilledFields.includes(fieldId)) aiFilledFields.push(fieldId);
+ }
+ if (link) { link.href = url; link.classList.remove('d-none'); }
+ };
+ fillDocUrl('field-sdsurl', 'field-sdsurl-link', data.sdsUrl, 'SDS');
+ fillDocUrl('field-tdsurl', 'field-tdsurl-link', data.tdsUrl, 'TDS');
+
// Build a persistent "needs more info" tip if key identity fields are still unknown
const missingHints = [];
if (!data.manufacturer && !document.getElementById('field-manufacturer')?.value?.trim())