using System.ComponentModel.DataAnnotations.Schema; using PowderCoating.Core.Enums; namespace PowderCoating.Core.Entities; public class Job : BaseEntity { public string JobNumber { get; set; } = string.Empty; public int CustomerId { get; set; } public int? QuoteId { get; set; } public string? AssignedUserId { get; set; } // Assigned user public string Description { get; set; } = string.Empty; // Lookup foreign keys (replacing enums) public int JobStatusId { get; set; } public int JobPriorityId { get; set; } // Dates public DateTime? ScheduledDate { get; set; } public DateTime? StartedDate { get; set; } public DateTime? CompletedDate { get; set; } public DateTime? DueDate { get; set; } // Selected oven (carried over from quote; null = company default rate) public int? OvenCostId { get; set; } // Oven scheduling (carried over from quote) public int OvenBatches { get; set; } = 1; public int? OvenCycleMinutes { get; set; } // Pricing public decimal QuotedPrice { get; set; } public decimal FinalPrice { get; set; } public decimal OvenBatchCost { get; set; } public decimal ShopSuppliesAmount { get; set; } public decimal ShopSuppliesPercent { get; set; } // Discount & rush (mirrors quote fields; preserved through quote→job conversion and job edits) public bool IsRushJob { get; set; } public DiscountType DiscountType { get; set; } = DiscountType.None; public decimal DiscountValue { get; set; } public string? DiscountReason { get; set; } // Job Completion Details public decimal? ActualTimeSpentHours { get; set; } // Additional Information public string? CustomerPO { get; set; } public string? ProjectName { get; set; } public string? SpecialInstructions { get; set; } public string? InternalNotes { get; set; } // Internal notes from quote public string? Tags { get; set; } public bool RequiresCustomerApproval { get; set; } public bool IsCustomerApproved { get; set; } // Shop floor QR access token (no login required; scoped to this job only) public Guid ShopAccessCode { get; set; } = Guid.NewGuid(); // Part intake / receiving public DateTime? IntakeDate { get; set; } public string? IntakeConditionNotes { get; set; } public int? IntakePartCount { get; set; } public string? IntakeCheckedByUserId { get; set; } // Quote snapshot — UpdatedAt of the source quote at the moment this job was created from it. // Used to detect when the quote was subsequently edited so the job details page can warn the user. public DateTime? QuoteSnapshotUpdatedAt { get; set; } // Pricing snapshot — serialized QuotePricingBreakdownDto stored at save time so Details displays // the breakdown that was actually calculated, not a re-run against current operating costs. public string? PricingBreakdownJson { get; set; } // Rework tracking public bool IsReworkJob { get; set; } public int? OriginalJobId { get; set; } // Set when this job was created as a rework // Relationships [ForeignKey("IntakeCheckedByUserId")] public virtual ApplicationUser? IntakeCheckedBy { get; set; } public virtual OvenCost? OvenCost { get; set; } public virtual Customer Customer { get; set; } = null!; public virtual Quote? Quote { get; set; } public virtual ApplicationUser? AssignedUser { get; set; } public virtual JobStatusLookup JobStatus { get; set; } = null!; public virtual JobPriorityLookup JobPriority { get; set; } = null!; public virtual ICollection JobItems { get; set; } = new List(); public virtual ICollection Photos { get; set; } = new List(); public virtual ICollection Notes { get; set; } = new List(); public virtual ICollection StatusHistory { get; set; } = new List(); public virtual ICollection JobPrepServices { get; set; } = new List(); public virtual Invoice? Invoice { get; set; } public virtual ICollection TimeEntries { get; set; } = new List(); public virtual ICollection ReworkRecords { get; set; } = new List(); public virtual Job? OriginalJob { get; set; } }