Files
PowderCoatingLogix/src/PowderCoating.Core/Entities/QuoteItem.cs
T
spouliot d8622b3187 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>
2026-05-06 16:04:45 -04:00

65 lines
2.7 KiB
C#

namespace PowderCoating.Core.Entities;
public class QuoteItem : BaseEntity
{
public int QuoteId { get; set; }
public string Description { get; set; } = string.Empty;
public decimal Quantity { get; set; }
// Measurements (optional for quoting)
public decimal? SurfaceArea { get; set; }
public decimal SurfaceAreaSqFt { get; set; } // Surface area in square feet for pricing
// Catalog item reference (optional)
public int? CatalogItemId { get; set; } // Link to catalog item (optional)
// Pricing
public decimal UnitPrice { get; set; }
public decimal TotalPrice { get; set; }
// Cost breakdown snapshot (set at save time for breakdown display)
public decimal ItemMaterialCost { get; set; }
public decimal ItemLaborCost { get; set; }
public decimal ItemEquipmentCost { get; set; }
public bool IsGenericItem { get; set; }
public decimal? ManualUnitPrice { get; set; }
public decimal? PowderCostOverride { get; set; } // Optional unit price override for catalog items
public bool IsLaborItem { get; set; }
public bool IsSalesItem { get; set; }
public string? Sku { get; set; }
// Processing estimates
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; }
// Part complexity level — applies a price multiplier for calculated items
// Values: "Simple" | "Moderate" | "Complex" | "Extreme"
public string? Complexity { get; set; }
// True when this item was generated via AI photo analysis.
// Must be persisted so that recalculations (Details view, Edit view) can
// honour ManualUnitPrice instead of running the regular pricing engine.
public bool IsAiItem { get; set; }
// AI-generated standardized tags (comma-separated, e.g. "automotive,tubular")
public string? AiTags { get; set; }
// Link to shared AI prediction record (null for non-AI items)
public int? AiPredictionId { get; set; }
public virtual AiItemPrediction? AiPrediction { get; set; }
// Relationships
public virtual Quote Quote { get; set; } = null!;
public virtual CatalogItem? CatalogItem { get; set; }
public virtual ICollection<QuoteItemCoat> Coats { get; set; } = new List<QuoteItemCoat>();
public virtual ICollection<QuoteItemPrepService> PrepServices { get; set; } = new List<QuoteItemPrepService>();
}