using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Fitness_core_BE.Models { /// One reservation against a FacilitySession — either an existing member using a /// CustomerPlan session allowance (FKCustomerId set, IsGuest = false) or a non-member who /// booked online and pays per-session (IsGuest = true, no membership at all). The guest's /// identity proof for check-in is the OTP issued at booking time, verified at the door /// instead of a fingerprint/face profile a non-member will never have. public class Booking { [Key] public Guid BookingId { get; set; } public Guid FKFacilitySessionId { get; set; } [ForeignKey(nameof(FKFacilitySessionId))] public FacilitySession FacilitySession { get; set; } public Guid FKClientId { get; set; } [ForeignKey(nameof(FKClientId))] public Client Client { get; set; } public bool IsGuest { get; set; } = false; // Member path. Tenant-bucket entity: holds a TenantCustomerLinkId, not the central // Customer.CusId directly -- see Models/TenantCustomerLink.cs. public Guid? FKCustomerId { get; set; } [ForeignKey(nameof(FKCustomerId))] public TenantCustomerLink? TenantCustomerLink { get; set; } // A member's booking draws down this specific subscription's per-cycle session // allowance; null for guest bookings (they have no subscription at all). public Guid? FKCustomerSubscriptionId { get; set; } [ForeignKey(nameof(FKCustomerSubscriptionId))] public CustomerSubscription? CustomerSubscription { get; set; } // Guest path -- no member record exists at all, so identity is captured inline. [MaxLength(200)] public string? GuestName { get; set; } [MaxLength(32)] public string? GuestPhone { get; set; } /// Issued when the booking is created; the guest presents this at the door /// instead of a fingerprint/face profile. Members don't need one -- their existing /// access credential covers check-in. [MaxLength(10)] public string? OtpCode { get; set; } public DateTime? OtpVerifiedAt { get; set; } /// "Paid" | "Unpaid" | "NotRequired" (member using a plan's included session). public string PaymentStatus { get; set; } = "NotRequired"; public decimal AmountCharged { get; set; } = 0m; // Set only once payment is confirmed for a pay-per-session guest booking, or // immediately for a member session (no payment gate) -- see PaymentStatus. public Guid? FKPaymentTransactionId { get; set; } [ForeignKey(nameof(FKPaymentTransactionId))] public PaymentTransaction? PaymentTransaction { get; set; } /// "Confirmed" | "CheckedIn" | "Cancelled" | "NoShow". public string Status { get; set; } = "Confirmed"; public DateTime BookedAt { get; set; } = DateTime.UtcNow; public DateTime? CheckedInAt { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; } }