using System.ComponentModel.DataAnnotations; namespace Fitness_core_BE.DTOs.CustomerPlan { public class CreateCustomerPlanRequest { [Required] public string PlanName { get; set; } = string.Empty; public string? PlanDescription { get; set; } [Required] [Range(0, double.MaxValue, ErrorMessage = "Plan price must be a positive value")] public decimal PlanPrice { get; set; } public bool? HasOnboardingFee { get; set; } [Range(0, double.MaxValue, ErrorMessage = "Onboarding fee must be zero or greater")] public decimal? OnboardingFeeAmount { get; set; } /// Required when DurationMode is "Rolling" (validated in the service). [Range(1, int.MaxValue, ErrorMessage = "Duration must be at least 1 day")] public int? DurationInDays { get; set; } /// "Individual" (default) | "Group". public string? PlanScope { get; set; } /// Required >= 2 when PlanScope is "Group". public int? MemberLimit { get; set; } /// "Rolling" (default) | "FixedRange". public string? DurationMode { get; set; } public DateTime? ValidFrom { get; set; } public DateTime? ValidTo { get; set; } public bool? AllowSplitPayments { get; set; } /// Number of mostly-equal installments; defaults to plan duration in months when split is enabled. public int? InstallmentCount { get; set; } /// Null (default) = unlimited-access plan. A number = this plan grants that /// many bookable Facility sessions per billing cycle (e.g. "4 pool sessions a month"). [Range(1, int.MaxValue, ErrorMessage = "SessionsPerCycle must be at least 1 when set")] public int? SessionsPerCycle { get; set; } /// "NoRollover" (default) | "GracePeriod". Only meaningful when SessionsPerCycle is set. public string? SessionRolloverPolicy { get; set; } /// Required (>= 1) when SessionRolloverPolicy is "GracePeriod". [Range(0, int.MaxValue, ErrorMessage = "RolloverGraceDays must be zero or greater")] public int? RolloverGraceDays { get; set; } /// "Prepaid" (default, pay before the cycle starts) | "Postpaid" (use first, /// invoice at cycle end, access suspended if unpaid past due). Asked once per package. public string? BillingTiming { get; set; } /// Places this plan grants access to. Null/omitted or empty = unrestricted /// (reaches every active access device, today's behavior). public List? PlaceIds { get; set; } /// Set only by the Classes tab's "Manage Plan" action -- links this new plan to /// one class via CustomerPlanClass. Omitted for an ordinary gym plan. public Guid? FacilityClassId { get; set; } /// Only meaningful when FacilityClassId is set -- whether this class plan also /// grants general gym-floor access ("class + gym" as one product) instead of class-only. /// Defaults to false (class-only) when omitted. public bool? GrantsGymAccess { get; set; } } }