2bf8871892
- Appointment reminders: add AppointmentReminderBackgroundService (60s poll), ReminderSentAt dedup stamp, NotifyAppointmentReminderAsync sends both customer email and creator staff email; AppointmentReminderStaff notification type + default template added; DateTime.Now used instead of UtcNow to match locally-stored ScheduledStartTime; ToLocalTime() double-conversion removed - NoExtraLayerCharge not persisted: flag existed on CreateQuoteItemCoatDto and was used by pricing engine but never written to JobItemCoat/QuoteItemCoat entities — every edit reset it to false and re-applied the extra layer charge; added column to both entities (migration AddNoExtraLayerChargeToCoats), both read DTOs, all 3 JobItemAssemblyService overloads, JobItemCoatSeed inner class, and existingItemsData JSON in all 5 wizard views; fixed JS template path that hard-coded noExtraLayerCharge: false - Coat notes not visible: notes were rendered in desktop job details but missing from the wizard item card summary and the mobile card view; both fixed - Scroll position lost on item save: sessionStorage save/restore added to item-wizard.js owner form submit handler; path-keyed so cross-page navigation does not restore stale position; requestAnimationFrame used for reliable mobile scroll restoration - Invoice Send dead button: #sendChannelModal was gated inside @if (isDraft) but the button targeting it fires for Sent/Overdue invoices too when customer has both email and SMS; modal moved outside the Draft guard - InitialCreate migration added for fresh database installs; Baseline migration guarded with IF OBJECT_ID check so it no-ops on fresh DBs; Razor scoping bug fixed in Customers/Index.cshtml Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
60 lines
2.3 KiB
C#
60 lines
2.3 KiB
C#
namespace PowderCoating.Core.Entities;
|
|
|
|
/// <summary>
|
|
/// Represents a single coating layer applied to a job item.
|
|
/// Supports multi-coat configurations (primer, base coat, top coat, clear coat, etc.)
|
|
/// </summary>
|
|
public class JobItemCoat : BaseEntity
|
|
{
|
|
// Parent relationship
|
|
public int JobItemId { get; set; }
|
|
|
|
// Coat identification (user-defined)
|
|
public string CoatName { get; set; } = string.Empty; // "Primer", "Base Coat", "Top Coat", etc.
|
|
public int Sequence { get; set; } // 1, 2, 3... for ordering
|
|
|
|
// Powder selection (from quote)
|
|
public int? InventoryItemId { get; set; } // In-stock powder
|
|
public string? ColorName { get; set; } // Color name
|
|
public int? VendorId { get; set; } // Vendor for custom powder
|
|
public string? ColorCode { get; set; } // RAL code, etc.
|
|
public string? Finish { get; set; } // Gloss, Matte, Textured, etc.
|
|
|
|
// Coverage parameters (from quote)
|
|
public decimal CoverageSqFtPerLb { get; set; } = 30m;
|
|
public decimal TransferEfficiency { get; set; } = 65m;
|
|
|
|
// Cost information (from quote)
|
|
public decimal? PowderCostPerLb { get; set; } // $/lb
|
|
public decimal? PowderToOrder { get; set; } // Pounds estimated to order
|
|
|
|
// Job completion tracking
|
|
public decimal? ActualPowderUsedLbs { get; set; } // Actual powder used when job is completed
|
|
|
|
// Powder ordering tracking
|
|
public bool PowderOrdered { get; set; } = false;
|
|
public DateTime? PowderOrderedAt { get; set; }
|
|
public string? PowderOrderedByUserId { get; set; }
|
|
|
|
// Powder receiving tracking
|
|
public bool PowderReceived { get; set; } = false;
|
|
public DateTime? PowderReceivedAt { get; set; }
|
|
public string? PowderReceivedByUserId { get; set; }
|
|
public decimal? PowderReceivedLbs { get; set; }
|
|
|
|
// Pricing flags
|
|
/// <summary>
|
|
/// When true, the additional layer labor charge is not applied for this coat even if it is
|
|
/// not the first coat in the sequence. Used for clear coats, sealers, etc.
|
|
/// </summary>
|
|
public bool NoExtraLayerCharge { get; set; }
|
|
|
|
// Notes
|
|
public string? Notes { get; set; }
|
|
|
|
// Navigation properties
|
|
public virtual JobItem JobItem { get; set; } = null!;
|
|
public virtual InventoryItem? InventoryItem { get; set; }
|
|
public virtual Vendor? Vendor { get; set; }
|
|
}
|