Fix catalog item repricing on oven-only quote edits

QuoteItem was missing IncludePrepCost, so the Edit GET always deserialized
it as true (DTO default). On save, prep service labor was added on top of
the catalog base price, silently bumping prices whenever any quote field
(e.g. oven cycle minutes) was changed without touching items.

Migration defaults new column to false for catalog items and true for
non-catalog items (matching the wizard's historical defaults).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-06 16:04:45 -04:00
parent 2d8827ad5c
commit d8622b3187
4 changed files with 9617 additions and 3 deletions
@@ -32,6 +32,11 @@ public class QuoteItem : BaseEntity
public bool RequiresSandblasting { get; set; }
public bool RequiresMasking { get; set; }
public int EstimatedMinutes { get; set; }
// Whether to add prep service labor cost on top of this item's base price.
// Defaults to false for catalog items (catalog price assumed to include standard labor);
// true for calculated items where prep is a separate billable add-on.
public bool IncludePrepCost { get; set; }
public string? Notes { get; set; }
@@ -0,0 +1,78 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace PowderCoating.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class AddQuoteItemIncludePrepCost : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IncludePrepCost",
table: "QuoteItems",
type: "bit",
nullable: false,
defaultValue: false);
// Non-catalog items were historically submitted with IncludePrepCost=true by the wizard
// (wizard defaults: ON for calculated items, OFF for catalog items).
// Set existing non-catalog rows to true to preserve their original pricing intent.
migrationBuilder.Sql(
"UPDATE QuoteItems SET IncludePrepCost = 1 WHERE CatalogItemId IS NULL");
migrationBuilder.UpdateData(
table: "PricingTiers",
keyColumn: "Id",
keyValue: 1,
column: "CreatedAt",
value: new DateTime(2026, 5, 6, 19, 59, 56, 264, DateTimeKind.Utc).AddTicks(846));
migrationBuilder.UpdateData(
table: "PricingTiers",
keyColumn: "Id",
keyValue: 2,
column: "CreatedAt",
value: new DateTime(2026, 5, 6, 19, 59, 56, 264, DateTimeKind.Utc).AddTicks(852));
migrationBuilder.UpdateData(
table: "PricingTiers",
keyColumn: "Id",
keyValue: 3,
column: "CreatedAt",
value: new DateTime(2026, 5, 6, 19, 59, 56, 264, DateTimeKind.Utc).AddTicks(853));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IncludePrepCost",
table: "QuoteItems");
migrationBuilder.UpdateData(
table: "PricingTiers",
keyColumn: "Id",
keyValue: 1,
column: "CreatedAt",
value: new DateTime(2026, 5, 6, 12, 35, 37, 694, DateTimeKind.Utc).AddTicks(5288));
migrationBuilder.UpdateData(
table: "PricingTiers",
keyColumn: "Id",
keyValue: 2,
column: "CreatedAt",
value: new DateTime(2026, 5, 6, 12, 35, 37, 694, DateTimeKind.Utc).AddTicks(5294));
migrationBuilder.UpdateData(
table: "PricingTiers",
keyColumn: "Id",
keyValue: 3,
column: "CreatedAt",
value: new DateTime(2026, 5, 6, 12, 35, 37, 694, DateTimeKind.Utc).AddTicks(5296));
}
}
}
@@ -6059,7 +6059,7 @@ namespace PowderCoating.Infrastructure.Migrations
{
Id = 1,
CompanyId = 0,
CreatedAt = new DateTime(2026, 5, 6, 12, 35, 37, 694, DateTimeKind.Utc).AddTicks(5288),
CreatedAt = new DateTime(2026, 5, 6, 19, 59, 56, 264, DateTimeKind.Utc).AddTicks(846),
Description = "Standard pricing for regular customers",
DiscountPercent = 0m,
IsActive = true,
@@ -6070,7 +6070,7 @@ namespace PowderCoating.Infrastructure.Migrations
{
Id = 2,
CompanyId = 0,
CreatedAt = new DateTime(2026, 5, 6, 12, 35, 37, 694, DateTimeKind.Utc).AddTicks(5294),
CreatedAt = new DateTime(2026, 5, 6, 19, 59, 56, 264, DateTimeKind.Utc).AddTicks(852),
Description = "5% discount for preferred customers",
DiscountPercent = 5m,
IsActive = true,
@@ -6081,7 +6081,7 @@ namespace PowderCoating.Infrastructure.Migrations
{
Id = 3,
CompanyId = 0,
CreatedAt = new DateTime(2026, 5, 6, 12, 35, 37, 694, DateTimeKind.Utc).AddTicks(5296),
CreatedAt = new DateTime(2026, 5, 6, 19, 59, 56, 264, DateTimeKind.Utc).AddTicks(853),
Description = "10% discount for premium customers",
DiscountPercent = 10m,
IsActive = true,
@@ -6594,6 +6594,9 @@ namespace PowderCoating.Infrastructure.Migrations
b.Property<int>("EstimatedMinutes")
.HasColumnType("int");
b.Property<bool>("IncludePrepCost")
.HasColumnType("bit");
b.Property<bool>("IsAiItem")
.HasColumnType("bit");