Fix pricing consistency across Quote → Job → Invoice; add stage-flow tests

- Store complete PricingBreakdownJson snapshot on Job at every save point so
  the Details page reads stored data rather than re-running the pricing engine
- Add 7 missing fields to Quote entity (FacilityOverheadCost, tier/quote discounts,
  SubtotalAfterDiscount) and persist them via ApplyPricingSnapshot
- Fix OvenCostId-as-rate bug in JobsController (FK was passed as decimal $/hr)
- Fix hardcoded LaborCost * 0.4 multiplier in two JobItemAssemblyService overloads
- Fix FacilityOverheadCost dropped from invoices in both quote and direct-job paths
- Fix RushFee missing from direct-job invoices (read from PricingBreakdownJson)
- Fix Notes and CatalogItemId not copied to InvoiceItem
- Add 14 unit tests in PricingStageFlowTests covering all three pricing stages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-15 15:03:06 -04:00
parent 226a6237a6
commit 6721de91e4
13 changed files with 11657 additions and 128 deletions
@@ -0,0 +1,71 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace PowderCoating.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class AddJobPricingSnapshot : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "PricingBreakdownJson",
table: "Jobs",
type: "nvarchar(max)",
nullable: true);
migrationBuilder.UpdateData(
table: "PricingTiers",
keyColumn: "Id",
keyValue: 1,
column: "CreatedAt",
value: new DateTime(2026, 5, 15, 16, 29, 32, 589, DateTimeKind.Utc).AddTicks(4618));
migrationBuilder.UpdateData(
table: "PricingTiers",
keyColumn: "Id",
keyValue: 2,
column: "CreatedAt",
value: new DateTime(2026, 5, 15, 16, 29, 32, 589, DateTimeKind.Utc).AddTicks(4623));
migrationBuilder.UpdateData(
table: "PricingTiers",
keyColumn: "Id",
keyValue: 3,
column: "CreatedAt",
value: new DateTime(2026, 5, 15, 16, 29, 32, 589, DateTimeKind.Utc).AddTicks(4625));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PricingBreakdownJson",
table: "Jobs");
migrationBuilder.UpdateData(
table: "PricingTiers",
keyColumn: "Id",
keyValue: 1,
column: "CreatedAt",
value: new DateTime(2026, 5, 15, 0, 30, 26, 273, DateTimeKind.Utc).AddTicks(2464));
migrationBuilder.UpdateData(
table: "PricingTiers",
keyColumn: "Id",
keyValue: 2,
column: "CreatedAt",
value: new DateTime(2026, 5, 15, 0, 30, 26, 273, DateTimeKind.Utc).AddTicks(2473));
migrationBuilder.UpdateData(
table: "PricingTiers",
keyColumn: "Id",
keyValue: 3,
column: "CreatedAt",
value: new DateTime(2026, 5, 15, 0, 30, 26, 273, DateTimeKind.Utc).AddTicks(2474));
}
}
}