using PowderCoating.Core.Enums; namespace PowderCoating.Core.Entities; public class Invoice : BaseEntity { public string InvoiceNumber { get; set; } = string.Empty; public int? JobId { get; set; } public int CustomerId { get; set; } public string? PreparedById { get; set; } public InvoiceStatus Status { get; set; } = InvoiceStatus.Draft; // Dates public DateTime InvoiceDate { get; set; } = DateTime.UtcNow; public DateTime? DueDate { get; set; } public DateTime? SentDate { get; set; } public DateTime? PaidDate { get; set; } // Financials public decimal SubTotal { get; set; } public decimal TaxPercent { get; set; } public decimal TaxAmount { get; set; } public decimal DiscountAmount { get; set; } public decimal Total { get; set; } public decimal AmountPaid { get; set; } public decimal CreditApplied { get; set; } // Sum of credit memo applications public decimal GiftCertificateRedeemed { get; set; } // Sum of gift certificate redemptions public decimal BalanceDue => Total - AmountPaid - CreditApplied - GiftCertificateRedeemed; /// /// Permanent public token for the customer-facing invoice view page (/invoice/{token}). /// Generated when the invoice is first sent (regardless of Stripe status) and never expires. /// Distinct from PaymentLinkToken which is Stripe-gated and expires in 5 days. /// public string? PublicViewToken { get; set; } // Online payments (Stripe Connect) public OnlinePaymentStatus OnlinePaymentStatus { get; set; } = OnlinePaymentStatus.NotApplicable; public string? PaymentLinkToken { get; set; } // Signed token for /pay/{token} public DateTime? PaymentLinkExpiresAt { get; set; } // 5 days from generation public string? StripePaymentIntentId { get; set; } // Most recent PaymentIntent ID public decimal OnlineAmountPaid { get; set; } = 0; // Running total of online payments received public decimal OnlineSurchargeCollected { get; set; } = 0; // Surcharge amount collected (for records) // Text public string? Notes { get; set; } public string? InternalNotes { get; set; } public string? Terms { get; set; } public string? CustomerPO { get; set; } public string? ProjectName { get; set; } /// /// Early payment discount percentage (e.g., 2 means 2% discount). /// Parsed from the customer's payment terms when the invoice is created (e.g., "2/10 Net 30"). /// Informational only — does not automatically reduce the amount due. /// public decimal EarlyPaymentDiscountPercent { get; set; } /// /// Number of days after invoice date within which the early payment discount applies. /// Parsed from the customer's payment terms (e.g., "2/10 Net 30" → 10 days). /// public int EarlyPaymentDiscountDays { get; set; } /// /// Original invoice number from an external system (e.g. QuickBooks invoice # "3048"). /// Stored for searchability and traceability after import. Searchable from the invoice list. /// public string? ExternalReference { get; set; } /// /// Liability account where collected sales tax is tracked (e.g., 2200 Sales Tax Payable). /// Populated automatically when TaxAmount > 0. /// public int? SalesTaxAccountId { get; set; } // Navigation public virtual Job? Job { get; set; } public virtual Customer Customer { get; set; } = null!; public virtual ApplicationUser? PreparedBy { get; set; } public virtual Account? SalesTaxAccount { get; set; } public virtual ICollection InvoiceItems { get; set; } = new List(); public virtual ICollection Payments { get; set; } = new List(); public virtual ICollection Refunds { get; set; } = new List(); public virtual ICollection CreditApplications { get; set; } = new List(); public virtual ICollection GiftCertificateRedemptions { get; set; } = new List(); }