From 551116d7e578ef6b5a4b6583813e016c7e000dcf Mon Sep 17 00:00:00 2001 From: Scott Pouliot Date: Tue, 19 May 2026 19:34:54 -0400 Subject: [PATCH] Mobile layout fix for Job Details items; coat color on invoice line items MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Job Details: hide desktop item tables on mobile (d-none d-lg-block) so only the existing mobile-card layout shows on small screens — prevents 20-line rows on a narrow phone display - Invoices Create (ForJob path): load job item coats and derive ColorName from coat colors when the item itself has no explicit color set; multiple coats join as 'Color1 / Color2' — lets customers distinguish repeated items (e.g. multiple caliper sets) on the invoice Co-Authored-By: Claude Sonnet 4.6 --- .../Controllers/InvoicesController.cs | 21 ++++++++++++++++++- .../Views/Jobs/Details.cshtml | 6 ++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/PowderCoating.Web/Controllers/InvoicesController.cs b/src/PowderCoating.Web/Controllers/InvoicesController.cs index ddb3537..8a6d39e 100644 --- a/src/PowderCoating.Web/Controllers/InvoicesController.cs +++ b/src/PowderCoating.Web/Controllers/InvoicesController.cs @@ -355,6 +355,15 @@ public class InvoicesController : Controller var job = await _unitOfWork.Jobs.GetByIdAsync(jobId.Value, false, j => j.Customer, j => j.JobItems); if (job == null) return NotFound(); + // Pre-load coats so we can derive color names for invoice line items + var activeItemIds = job.JobItems.Where(ji => !ji.IsDeleted).Select(ji => ji.Id).ToList(); + var allCoats = activeItemIds.Any() + ? (await _unitOfWork.JobItemCoats.FindAsync(c => activeItemIds.Contains(c.JobItemId) && !c.IsDeleted)).ToList() + : new List(); + var coatsByItem = allCoats + .GroupBy(c => c.JobItemId) + .ToDictionary(g => g.Key, g => g.OrderBy(c => c.Sequence).ToList()); + // Validate no existing active invoice for this job (voided ones are kept as history) var existing = await _unitOfWork.Invoices.GetForJobAsync(jobId.Value); if (existing != null && existing.Status != InvoiceStatus.Voided) @@ -404,6 +413,16 @@ public class InvoicesController : Controller revenueAccountId = ci.RevenueAccountId; revenueAccountId ??= defaultRevenueAccount?.Id; + // Derive color from coats when the item itself has no explicit color set + var derivedColor = item.ColorName; + if (string.IsNullOrEmpty(derivedColor) && coatsByItem.TryGetValue(item.Id, out var itemCoats)) + { + var coatColors = itemCoats + .Where(c => !string.IsNullOrEmpty(c.ColorName)) + .Select(c => c.ColorName!); + derivedColor = string.Join(" / ", coatColors); + } + dto.InvoiceItems.Add(new CreateInvoiceItemDto { SourceJobItemId = item.Id, @@ -412,7 +431,7 @@ public class InvoicesController : Controller Quantity = item.Quantity > 0 ? item.Quantity : 1, UnitPrice = item.UnitPrice, TotalPrice = item.TotalPrice, - ColorName = item.ColorName, + ColorName = derivedColor, Notes = item.Notes, DisplayOrder = order++, RevenueAccountId = revenueAccountId diff --git a/src/PowderCoating.Web/Views/Jobs/Details.cshtml b/src/PowderCoating.Web/Views/Jobs/Details.cshtml index 2ca0385..ba820ec 100644 --- a/src/PowderCoating.Web/Views/Jobs/Details.cshtml +++ b/src/PowderCoating.Web/Views/Jobs/Details.cshtml @@ -324,6 +324,7 @@ @* -- Catalog Products -- *@ @if (catalogItems.Any()) { +
Catalog Products
@@ -412,11 +413,13 @@
+
} @* -- Custom Work -- *@ @if (customItems.Any()) { +
Custom Work
@@ -563,11 +566,13 @@
+
} @* -- Labor -- *@ @if (laborItems.Any()) { +
Labor
@@ -614,6 +619,7 @@
+
} @* -- Mobile cards -- *@