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:
2026-05-14 16:54:22 -04:00
parent 7e79a13cb1
commit 539c6c2559
24 changed files with 22175 additions and 994 deletions
@@ -2839,7 +2839,9 @@ public class QuotesController : Controller
JobNumber = await GenerateJobNumberAsync(),
CustomerId = quote.CustomerId ?? 0, // Should always have a customer by approval time
QuoteId = quote.Id,
OvenCostId = quote.OvenCostId, // Carry oven selection from quote
OvenCostId = quote.OvenCostId, // Carry oven selection from quote
OvenBatches = quote.OvenBatches > 0 ? quote.OvenBatches : 1,
OvenCycleMinutes = quote.OvenCycleMinutes,
Description = quote.Description ?? $"Job from Quote {quote.QuoteNumber}",
JobStatusId = approvedStatus?.Id ?? 1,
JobPriorityId = selectedPriority?.Id ?? 1,