Enrich received custom powders from the catalog
When a quote uses a powder the company doesn't stock but the master catalog
does, receiving it ("Got it") created an inventory record with only the color
code/name and cost carried on the quote — cure schedule, SDS/TDS, sample image,
color families, etc. were left blank.
AddCustomPowderToInventory now matches the platform powder catalog by SKU (the
coat's color code, preferring the same manufacturer, then by color name) and
fills every blank spec/document field from it, links PowderCatalogItemId, and
falls back to standard coverage/efficiency defaults. Only gaps are filled, so
anything entered on the receive form is preserved.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -765,6 +765,12 @@ public class DashboardController : Controller
|
|||||||
UpdatedAt = DateTime.UtcNow,
|
UpdatedAt = DateTime.UtcNow,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Enrich from the platform powder catalog so the new inventory record carries the full
|
||||||
|
// spec/doc set (cure schedule, SDS/TDS, sample image, color families) rather than just
|
||||||
|
// the color code/name carried on the quote. Match by the catalog SKU (stored as the
|
||||||
|
// coat's colorCode), preferring the same manufacturer; fall back to color name.
|
||||||
|
await EnrichInventoryFromCatalogAsync(inventoryItem, colorCode, colorName, manufacturer);
|
||||||
|
|
||||||
await _unitOfWork.InventoryItems.AddAsync(inventoryItem);
|
await _unitOfWork.InventoryItems.AddAsync(inventoryItem);
|
||||||
await _unitOfWork.CompleteAsync(); // flush to get inventoryItem.Id
|
await _unitOfWork.CompleteAsync(); // flush to get inventoryItem.Id
|
||||||
|
|
||||||
@@ -828,6 +834,69 @@ public class DashboardController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fills blank spec/document fields on a newly received custom-powder inventory item from the
|
||||||
|
/// matching platform powder catalog row — cure schedule, coverage, specific gravity, transfer
|
||||||
|
/// efficiency, SDS/TDS links, sample image, color families, product page — so the tenant gets a
|
||||||
|
/// complete record instead of just the color code/name carried on the quote. Matches by catalog
|
||||||
|
/// SKU (stored as the coat's color code), preferring the same manufacturer, then by color name.
|
||||||
|
/// Only fills gaps (never overwrites form-entered values) and links the item to the catalog row.
|
||||||
|
/// </summary>
|
||||||
|
private async Task EnrichInventoryFromCatalogAsync(
|
||||||
|
InventoryItem item, string? colorCode, string? colorName, string? manufacturer)
|
||||||
|
{
|
||||||
|
PowderCatalogItem? catalog = null;
|
||||||
|
|
||||||
|
var code = colorCode?.Trim();
|
||||||
|
if (!string.IsNullOrWhiteSpace(code))
|
||||||
|
{
|
||||||
|
var codeLower = code.ToLower();
|
||||||
|
var hits = (await _unitOfWork.PowderCatalog.FindAsync(p => p.Sku.ToLower() == codeLower)).ToList();
|
||||||
|
var mfr = manufacturer?.Trim().ToLower();
|
||||||
|
catalog = (!string.IsNullOrWhiteSpace(mfr)
|
||||||
|
? hits.FirstOrDefault(p => p.VendorName.ToLower().Contains(mfr))
|
||||||
|
: null)
|
||||||
|
?? hits.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (catalog == null && !string.IsNullOrWhiteSpace(colorName))
|
||||||
|
{
|
||||||
|
var nameLower = colorName.Trim().ToLower();
|
||||||
|
catalog = (await _unitOfWork.PowderCatalog.FindAsync(p => p.ColorName.ToLower() == nameLower))
|
||||||
|
.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (catalog == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
item.PowderCatalogItemId = catalog.Id;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(item.ManufacturerPartNumber)) item.ManufacturerPartNumber = catalog.Sku;
|
||||||
|
if (string.IsNullOrWhiteSpace(item.Manufacturer)) item.Manufacturer = catalog.VendorName;
|
||||||
|
if (string.IsNullOrWhiteSpace(item.ColorName)) item.ColorName = catalog.ColorName;
|
||||||
|
if (string.IsNullOrWhiteSpace(item.Finish)) item.Finish = catalog.Finish;
|
||||||
|
if (string.IsNullOrWhiteSpace(item.ColorFamilies)) item.ColorFamilies = catalog.ColorFamilies;
|
||||||
|
if (string.IsNullOrWhiteSpace(item.ImageUrl)) item.ImageUrl = catalog.ImageUrl;
|
||||||
|
if (string.IsNullOrWhiteSpace(item.SdsUrl)) item.SdsUrl = catalog.SdsUrl;
|
||||||
|
if (string.IsNullOrWhiteSpace(item.TdsUrl)) item.TdsUrl = catalog.TdsUrl;
|
||||||
|
if (string.IsNullOrWhiteSpace(item.SpecPageUrl)) item.SpecPageUrl = catalog.ProductUrl;
|
||||||
|
|
||||||
|
item.CureTemperatureF ??= catalog.CureTemperatureF;
|
||||||
|
item.CureTimeMinutes ??= catalog.CureTimeMinutes;
|
||||||
|
item.SpecificGravity ??= catalog.SpecificGravity;
|
||||||
|
item.CoverageSqFtPerLb ??= catalog.CoverageSqFtPerLb ?? 30m;
|
||||||
|
item.TransferEfficiency ??= catalog.TransferEfficiency ?? 65m;
|
||||||
|
|
||||||
|
if (!item.RequiresClearCoat && catalog.RequiresClearCoat == true)
|
||||||
|
item.RequiresClearCoat = true;
|
||||||
|
|
||||||
|
if (item.UnitCost <= 0 && catalog.UnitPrice > 0)
|
||||||
|
{
|
||||||
|
item.UnitCost = catalog.UnitPrice;
|
||||||
|
item.LastPurchasePrice = catalog.UnitPrice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Platform-level dashboard visible only to SuperAdmins who are not impersonating a tenant.
|
/// Platform-level dashboard visible only to SuperAdmins who are not impersonating a tenant.
|
||||||
/// Displays a cross-company overview: total/active/inactive company counts, user count,
|
/// Displays a cross-company overview: total/active/inactive company counts, user count,
|
||||||
|
|||||||
Reference in New Issue
Block a user