Fix oven batch conversion, invoice quantity, AI photo pricing, and enforce pricing flag propagation
- Carry OvenBatches/OvenCycleMinutes from Quote → Job entity (was missing fields; all job pricing recalcs hardcoded 1/null) - Fix invoice creation from job always showing Quantity=1 (was using TotalPrice as UnitPrice with qty 1) - Add IsAiItem to JobItem + migration; map in all 3 JobItemAssemblyService.CreateJobItem overloads so AI photo jobs no longer double-price on first edit after quote→job conversion - Propagate IsAiItem through all existingItemsData JSON blocks in Jobs views (Edit, EditItems, Create) so the wizard preserves AI routing on re-edit - Add PricingRoutingFlags_ExistOnBothQuoteItemAndJobItem structural test + 3 behavioral IsAiItem tests to JobItemAssemblyServiceTests - Consolidate item wizard partials (_ItemWizardModal, _SqFtCalculatorModal) and item-wizard.css into shared locations - Document pricing flag propagation checklist in CLAUDE.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
<div class="modal fade" id="itemWizardModal" tabindex="-1" data-bs-backdrop="static">
|
||||
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div class="d-flex flex-column">
|
||||
<h5 class="modal-title mb-0" id="wizardTitle">Add Item</h5>
|
||||
<div class="text-muted small mb-1" id="wizardStepTitle">Choose Item Type</div>
|
||||
<div class="d-flex align-items-center gap-2" id="wizardStepIndicator">
|
||||
<span class="wizard-step-dot active" data-step="1" title="Item Type"></span>
|
||||
<div class="wizard-step-line"></div>
|
||||
<span class="wizard-step-dot" data-step="2" title="Item Details"></span>
|
||||
<div class="wizard-step-line" id="step2Line"></div>
|
||||
<span class="wizard-step-dot" data-step="3" title="Coating Layers" id="step3Dot"></span>
|
||||
<div class="wizard-step-line" id="step3Line"></div>
|
||||
<span class="wizard-step-dot" data-step="4" title="Prep Services" id="step4Dot"></span>
|
||||
<span class="text-muted small ms-2" id="wizardStepLabel">Step 1 of 4</span>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body" id="wizardBody" style="min-height: 300px;"></div>
|
||||
<div class="modal-footer justify-content-between">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<div class="d-flex gap-2">
|
||||
<button type="button" class="btn btn-outline-secondary d-none" id="btnWizardBack" onclick="wizardBack()">
|
||||
<i class="bi bi-arrow-left me-1"></i>Back
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary" id="btnWizardNext" onclick="wizardNext()">
|
||||
Next <i class="bi bi-arrow-right ms-1"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-success d-none" id="btnWizardSave" onclick="wizardSave()">
|
||||
<i class="bi bi-check-lg me-1"></i>Add Item
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,63 @@
|
||||
@{
|
||||
var useMetric = ViewBag.UseMetric == true;
|
||||
var unit = useMetric ? "cm" : "in";
|
||||
var divisorLabel = useMetric ? "10,000" : "144";
|
||||
var areaUnit = (string?)ViewBag.AreaUnit ?? "sq ft";
|
||||
}
|
||||
<div class="modal fade" id="sqFtCalculatorModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="bi bi-calculator me-2"></i>Surface Area Calculator <small class="text-muted">(per item)</small></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Shape</label>
|
||||
<select id="calcShape" class="form-select" onchange="toggleShapeInputs()">
|
||||
<option value="rectangle">Rectangle / Square</option>
|
||||
<option value="cylinder">Cylinder (Tube)</option>
|
||||
<option value="circle">Circle (Flat)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="rectangleInputs">
|
||||
<div class="row g-2">
|
||||
<div class="col-6">
|
||||
<label class="form-label">Length (@unit)</label>
|
||||
<input type="number" id="rectLength" class="form-control" min="0" step="0.01" value="0" oninput="calculateSqFt()">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="form-label">Width (@unit)</label>
|
||||
<input type="number" id="rectWidth" class="form-control" min="0" step="0.01" value="0" oninput="calculateSqFt()">
|
||||
</div>
|
||||
</div>
|
||||
<small class="text-muted">Formula: L × W ÷ @divisorLabel</small>
|
||||
</div>
|
||||
<div id="cylinderInputs" style="display:none">
|
||||
<div class="row g-2">
|
||||
<div class="col-6">
|
||||
<label class="form-label">Diameter (@unit)</label>
|
||||
<input type="number" id="cylDiameter" class="form-control" min="0" step="0.01" value="0" oninput="calculateSqFt()">
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="form-label">Height (@unit)</label>
|
||||
<input type="number" id="cylHeight" class="form-control" min="0" step="0.01" value="0" oninput="calculateSqFt()">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="circleInputs" style="display:none">
|
||||
<label class="form-label">Diameter (@unit)</label>
|
||||
<input type="number" id="circDiameter" class="form-control" min="0" step="0.01" value="0" oninput="calculateSqFt()">
|
||||
</div>
|
||||
<hr />
|
||||
<div class="alert alert-info alert-permanent mb-0"><strong>Result:</strong> <span id="calcResult">0.00</span> @areaUnit</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" onclick="useSqFtResult()">
|
||||
<i class="bi bi-check-circle me-1"></i>Use This Value
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user