Fix sandblast-only oven charge and wizard overflow; fix Jenkins test failures

Sandblast-only oven charge root cause:
renderCoatsList() is called on every step-3 render. When the sandblast-only
toggle was checked it cleared wz.data.coats to [], but renderCoatsList()
then saw an empty list and auto-called addCoatRow(), silently pushing a
Base Coat back into wz.data.coats. The server saw Coats.Any() = true and
included the item in the oven fraction calculation, producing an unexpected
oven batch charge. Fixed by bailing out of renderCoatsList() when
sandblastOnly is active, and added a matching safety net in
buildItemFromWizard() that forces coats:[] when sandblastOnly is true.

Also fixed sandblast-only toggle label overflow: subtitle span changed to
d-block so it wraps beneath the bold label instead of running inline.

Test fixes:
- DepositsController and GiftCertificatesController tests updated with the
  required ICompanyLogoService mock parameter added to the logo fix commit.
- Two PricingCalculationServiceTests updated to include a coat entry on
  each item, matching the service's updated requirement that only items
  with coating layers are considered for oven fraction calculation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-06 13:56:20 -04:00
parent 71caa93461
commit 63a85b6ce9
@@ -1464,9 +1464,9 @@ function renderStep3Html() {
<div class="form-check form-switch border rounded py-2 px-3 mb-3 bg-light">
<input class="form-check-input" type="checkbox" id="sandblastOnlyToggle"
${isSandblastOnly ? 'checked' : ''} onchange="onSandblastOnlyToggle()">
<label class="form-check-label" for="sandblastOnlyToggle">
<label class="form-check-label" for="sandblastOnlyToggle" style="line-height:1.3">
<strong>Sandblast / Prep Only</strong>
<span class="text-muted fw-normal ms-2 small">— no powder coating applied</span>
<span class="d-block text-muted fw-normal small">No powder coating — no oven or powder costs</span>
</label>
</div>
<div id="coatingSectionWrap"${isSandblastOnly ? ' class="d-none"' : ''}>
@@ -1500,6 +1500,8 @@ function onSandblastOnlyToggle() {
}
function renderCoatsList() {
// Sandblast-only items have no coating layers — don't auto-add a coat
if (wz.data.sandblastOnly) return;
const coats = wz.data.coats || [];
if (coats.length === 0) {
addCoatRow(); // auto-add a Base Coat
@@ -2327,7 +2329,7 @@ function buildItemFromWizard() {
requiresSandblasting: false,
requiresMasking: false,
notes: d.notes || null,
coats: d.coats || [],
coats: isSandblastOnly ? [] : (d.coats || []),
prepServices: d.prepServices || [],
includePrepCost: d.includePrepCost ?? (wz.itemType !== 'product'),
complexity: d.complexity || 'Simple',