first commit

This commit is contained in:
Dhananjaya99
2026-09-28 11:44:26 +05:30
parent 721743ae6b
commit bffc9b1686
424 changed files with 46474 additions and 0 deletions
+47
View File
@@ -0,0 +1,47 @@
using System.ComponentModel.DataAnnotations;
namespace Fitness_core_BE.DTOs.AccessDevice
{
public class UnlinkedFingerprintDto
{
public Guid Id { get; set; }
public int DeviceUserId { get; set; }
public string DeviceEmployeeNo { get; set; } = string.Empty;
public string? DeviceReportedName { get; set; }
public string? DeviceUserType { get; set; }
public int FingerprintCount { get; set; }
public Guid DeviceId { get; set; }
public string? DeviceName { get; set; }
public DateTime DiscoveredAt { get; set; }
}
public class LinkFingerprintRequest
{
public Guid UnlinkedEnrollmentId { get; set; }
}
/// <summary>
/// Body of POST client/customers/{id}/face-photo. The browser resizes and re-encodes to
/// JPEG before sending, so this carries a ready-to-enrol image; a data: prefix is accepted.
/// </summary>
public class SetFacePhotoRequest
{
[Required]
public string ImageBase64 { get; set; } = string.Empty;
}
public class AccessStatusDto
{
public long AccessProfileId { get; set; }
public string AccessNumber { get; set; } = string.Empty;
public string PersonType { get; set; } = string.Empty;
public string DesiredAccessState { get; set; } = string.Empty;
public string ProvisionStatus { get; set; } = "NoDevice";
public string ActualAccessState { get; set; } = "Unknown";
public int FingerprintCount { get; set; }
public string? LastError { get; set; }
public DateTime? LastSyncedAt { get; set; }
public int DeviceCount { get; set; }
public int SyncedDeviceCount { get; set; }
}
}
+76
View File
@@ -0,0 +1,76 @@
namespace Fitness_core_BE.DTOs.Agent
{
// POST /api/agent/enroll (bootstrap, no api-key auth)
public class EnrollRequest
{
public string Code { get; set; }
public string AgentName { get; set; }
}
// POST /api/agent/devices
public class RegisterDeviceRequest
{
public string DeviceName { get; set; }
public Guid? DeviceId { get; set; }
public string? HardwareId { get; set; }
}
// POST /api/agent/attendance
public class AgentAttendanceRequest
{
public Guid DeviceId { get; set; }
public List<AgentAttendanceEvent> Events { get; set; } = new();
}
public class AgentAttendanceEvent
{
public string EmployeeNoString { get; set; }
public DateTime Time { get; set; }
public string AttendanceStatus { get; set; }
}
// POST /api/agent/commands/{id}/result
public class CommandResultRequest
{
public bool Success { get; set; }
public string? ResultJson { get; set; }
}
// Full person inventory contains metadata only. Fingerprint template bytes stay
// on the terminal and are never uploaded to the cloud.
public class DeviceInventoryRequest
{
public Guid DeviceId { get; set; }
public List<DeviceInventoryPerson> People { get; set; } = new();
}
public class DeviceInventoryPerson
{
public string EmployeeNo { get; set; } = string.Empty;
public string? Name { get; set; }
public string? UserType { get; set; }
public int FingerprintCount { get; set; }
}
// POST /api/agent/heartbeat. Device reachability is measured on the LAN by
// the agent; the cloud never attempts to connect to a private terminal.
public class AgentHeartbeatRequest
{
public List<AgentDeviceHealthReport> Devices { get; set; } = new();
}
public class AgentDeviceHealthReport
{
public Guid DeviceId { get; set; }
public bool IsOnline { get; set; }
}
// POST /api/agent/time-bank-cards/redeem -- an RFID-reader-equipped agent station
// reporting a card swipe (tap-in or tap-out, see TimeBankCardService.Swipe). FacilityId is
// the reader's own fixed station, not something read off the card.
public class AgentSwipeTimeBankCardRequest
{
public string RfidTagId { get; set; } = string.Empty;
public Guid FacilityId { get; set; }
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace Fitness_core_BE.DTOs.Attendance
{
public class AttendanceCountDTO
{
public Guid CustomerId { get; set; }
public string? CustomerName { get; set; }
public int AttendanceCount { get; set; }
}
}
+14
View File
@@ -0,0 +1,14 @@
namespace Fitness_core_BE.DTOs
{
public class AttendanceDTO
{
public Guid DeviceId { get; set; }
public Guid? CustomerId { get; set; }
public Guid UserId { get; set; }
public long AccessProfileId { get; set; }
public int DeviceUserId { get; set; }
public string DeviceEmployeeNo { get; set; } = string.Empty;
public DateTime EventTime { get; set; }
public string EventType { get; set; }
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace Fitness_core_BE.DTOs.Attendance
{
public class TodayAttendanceDTO
{
public string? CustomerName { get; set; }
public DateTime EventTime { get; set; }
public string? EventType { get; set; }
}
}
+10
View File
@@ -0,0 +1,10 @@
namespace Fitness_core_BE.DTOs.Auth
{
public class AuthResponse
{
public int StatusCode { get; set; }
public bool Success { get; set; }
public string Message { get; set; } = string.Empty;
public object? Data { get; set; }
}
}
+31
View File
@@ -0,0 +1,31 @@
namespace Fitness_core_BE.DTOs.Booking
{
public class BookingDto
{
public Guid BookingId { get; set; }
public Guid FacilitySessionId { get; set; }
public string? FacilityName { get; set; }
public DateTime? SessionStartTime { get; set; }
public DateTime? SessionEndTime { get; set; }
public bool IsGuest { get; set; }
public Guid? CustomerId { get; set; }
public string? GuestName { get; set; }
public string? GuestPhone { get; set; }
/// <summary>Only populated in the response right after booking creation -- the
/// guest's receipt. Never returned by list/lookup endpoints afterward.</summary>
public string? OtpCode { get; set; }
public bool OtpVerified { get; set; }
public string PaymentStatus { get; set; } = string.Empty;
public decimal AmountCharged { get; set; }
public string Status { get; set; } = string.Empty;
public DateTime BookedAt { get; set; }
public DateTime? CheckedInAt { get; set; }
/// <summary>A public, unauthenticated link to this booking's confirmation page --
/// copy-paste-and-share receipt. Works for both member and guest bookings.</summary>
public string? ShareUrl { get; set; }
}
}
+44
View File
@@ -0,0 +1,44 @@
using System.ComponentModel.DataAnnotations;
namespace Fitness_core_BE.DTOs.Booking
{
public class CreateMemberBookingRequest
{
[Required]
public Guid FacilitySessionId { get; set; }
}
public class CreateGuestBookingRequest
{
[Required]
public Guid FacilitySessionId { get; set; }
[Required]
public string GuestName { get; set; } = string.Empty;
[Required]
public string GuestPhone { get; set; } = string.Empty;
}
public class MarkGuestBookingPaidRequest
{
[Required]
public Guid BookingId { get; set; }
[Required]
[Range(0.01, double.MaxValue, ErrorMessage = "AmountCharged must be greater than zero")]
public decimal AmountCharged { get; set; }
}
public class CheckInBookingRequest
{
[Required]
public string OtpCode { get; set; } = string.Empty;
}
public class CancelBookingRequest
{
[Required]
public Guid BookingId { get; set; }
}
}
+15
View File
@@ -0,0 +1,15 @@
namespace Fitness_core_BE.DTOs.ClientInvoice
{
public class ClientInvoiceDto
{
public Guid ClientInvoiceId { get; set; }
public Guid SubscriptionId { get; set; }
public string? ClientName { get; set; }
public string? UserEmail { get; set; }
public string? PackageName { get; set; }
public decimal Amount { get; set; }
public string Status { get; set; } = string.Empty;
public DateTime ClientInvoiceDate { get; set; }
public List<ClientInvoiceItemDto> Items { get; set; } = new List<ClientInvoiceItemDto>();
}
}
@@ -0,0 +1,11 @@
namespace Fitness_core_BE.DTOs.ClientInvoice
{
public class ClientInvoiceItemDto
{
public Guid ClientInvoiceItemId { get; set; }
public string? ItemName { get; set; }
public string? ItemDescription { get; set; }
public decimal ItemPrice { get; set; }
public DateTime CreatedAt { get; set; }
}
}
@@ -0,0 +1,7 @@
namespace Fitness_core_BE.DTOs.ClientInvoice
{
public class CreateClientInvoiceRequest
{
public Guid SubscriptionId { get; set; }
}
}
@@ -0,0 +1,8 @@
namespace Fitness_core_BE.DTOs.ClientInvoice
{
public class UpdateClientInvoiceStatusRequest
{
public Guid ClientInvoiceId { get; set; }
public string Status { get; set; } = string.Empty;
}
}
+14
View File
@@ -0,0 +1,14 @@
namespace Fitness_core_BE.DTOs.Customer
{
public class CreateCustomerRequest
{
// Customer details
public string CusName { get; set; } = string.Empty;
// User details
public string UserName { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string PhoneNumber { get; set; } = string.Empty;
public bool IsActive { get; set; } = true;
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace Fitness_core_BE.DTOs.Customer
{
public class CustomerDto
{
public Guid CusId { get; set; }
public string CusName { get; set; } = string.Empty;
public Guid FKUserId { get; set; }
public string? UserName { get; set; }
public string? UserEmail { get; set; }
}
}
+4
View File
@@ -0,0 +1,4 @@
namespace Fitness_core_BE.DTOs.Customer
{
public record FollowedPlanDto(Guid PlanId, string? Name, bool IsFollowing, DateTime? CompletedDate);
}
+56
View File
@@ -0,0 +1,56 @@
using Fitness_core_BE.Models;
namespace Fitness_core_BE.DTOs.Customer
{
/// <summary>
/// One row per gym member for GET api/client/customers. Deliberate superset of
/// the previous CustomerSubscription row shape so the frontend change is additive:
/// group members each get their own row pointing at the shared subscription.
/// </summary>
public class MemberListRowDto
{
public Guid SubscriptionId { get; set; }
public Guid FKCustomerPlanId { get; set; }
public Guid FKCustomerId { get; set; }
public DateTime OnboardDate { get; set; }
public DateTime? ExpiryDate { get; set; }
public DateTime? RenewalDate { get; set; }
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; }
public Models.Customer? Customer { get; set; }
public bool IsPrimary { get; set; }
/// <summary>False when the member has been unassigned from their plan but is still a member of the gym.</summary>
public bool IsPlanAssigned { get; set; } = true;
public string? PlanName { get; set; }
public string PlanScope { get; set; } = "Individual";
public int MemberCount { get; set; } = 1;
public int MemberLimit { get; set; } = 1;
public decimal InvoiceAmount { get; set; }
public decimal PaidAmount { get; set; }
public decimal Balance { get; set; }
public string PaymentStatus { get; set; } = "Pending";
public bool AllowSplitPayments { get; set; }
// Linked fingerprint/device-access enrollment, if any (name may be null when the
// device didn't report one at enrollment time).
public int? FingerprintId { get; set; }
public string? FingerprintName { get; set; }
public long? AccessProfileId { get; set; }
public string? AccessNumber { get; set; }
public string AccessProvisionStatus { get; set; } = "NotConfigured";
public string ActualAccessState { get; set; } = "Unknown";
public string DesiredAccessState { get; set; } = "Enabled";
public int FingerprintCount { get; set; }
public string? AccessLastError { get; set; }
public bool IsLocked { get; set; }
public string? LockReason { get; set; }
/// <summary>Face-photo enrolment on the gym's access terminals.</summary>
public bool HasFacePhoto { get; set; }
/// <summary>"None" | "Pending" | "Synced" | "Failed".</summary>
public string FacePhotoStatus { get; set; } = "None";
public string? FacePhotoError { get; set; }
}
}
+14
View File
@@ -0,0 +1,14 @@
namespace Fitness_core_BE.DTOs.Customer
{
public class UpdateCustomerRequest
{
// Customer details
public string? CusName { get; set; }
// User details
public string? UserName { get; set; }
public string? Email { get; set; }
public string? PhoneNumber { get; set; }
public bool? IsActive { get; set; }
}
}
@@ -0,0 +1,7 @@
namespace Fitness_core_BE.DTOs.CustomerInvoice
{
public class CreateCustomerInvoiceRequest
{
public Guid SubscriptionId { get; set; }
}
}
@@ -0,0 +1,17 @@
namespace Fitness_core_BE.DTOs.CustomerInvoice
{
public class CustomerInvoiceDto
{
public Guid CustomerInvoiceId { get; set; }
public Guid SubscriptionId { get; set; }
public Guid FKClientId { get; set; }
public string? ClientName { get; set; }
public string? CustomerName { get; set; }
public string? UserEmail { get; set; }
public string? PackageName { get; set; }
public decimal Amount { get; set; }
public string Status { get; set; } = string.Empty;
public DateTime CustomerInvoiceDate { get; set; }
public List<CustomerInvoiceItemDto> Items { get; set; } = new List<CustomerInvoiceItemDto>();
}
}
@@ -0,0 +1,11 @@
namespace Fitness_core_BE.DTOs.CustomerInvoice
{
public class CustomerInvoiceItemDto
{
public Guid CustomerInvoiceItemId { get; set; }
public string? ItemName { get; set; }
public string? ItemDescription { get; set; }
public decimal ItemPrice { get; set; }
public DateTime CreatedAt { get; set; }
}
}
@@ -0,0 +1,8 @@
namespace Fitness_core_BE.DTOs.CustomerInvoice
{
public class UpdateCustomerInvoiceStatusRequest
{
public Guid CustomerInvoiceId { get; set; }
public string Status { get; set; } = string.Empty;
}
}
@@ -0,0 +1,62 @@
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; }
/// <summary>Required when DurationMode is "Rolling" (validated in the service).</summary>
[Range(1, int.MaxValue, ErrorMessage = "Duration must be at least 1 day")]
public int? DurationInDays { get; set; }
/// <summary>"Individual" (default) | "Group".</summary>
public string? PlanScope { get; set; }
/// <summary>Required >= 2 when PlanScope is "Group".</summary>
public int? MemberLimit { get; set; }
/// <summary>"Rolling" (default) | "FixedRange".</summary>
public string? DurationMode { get; set; }
public DateTime? ValidFrom { get; set; }
public DateTime? ValidTo { get; set; }
public bool? AllowSplitPayments { get; set; }
/// <summary>Number of mostly-equal installments; defaults to plan duration in months when split is enabled.</summary>
public int? InstallmentCount { get; set; }
/// <summary>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").</summary>
[Range(1, int.MaxValue, ErrorMessage = "SessionsPerCycle must be at least 1 when set")]
public int? SessionsPerCycle { get; set; }
/// <summary>"NoRollover" (default) | "GracePeriod". Only meaningful when SessionsPerCycle is set.</summary>
public string? SessionRolloverPolicy { get; set; }
/// <summary>Required (>= 1) when SessionRolloverPolicy is "GracePeriod".</summary>
[Range(0, int.MaxValue, ErrorMessage = "RolloverGraceDays must be zero or greater")]
public int? RolloverGraceDays { get; set; }
/// <summary>"Prepaid" (default, pay before the cycle starts) | "Postpaid" (use first,
/// invoice at cycle end, access suspended if unpaid past due). Asked once per package.</summary>
public string? BillingTiming { get; set; }
/// <summary>Places this plan grants access to. Null/omitted or empty = unrestricted
/// (reaches every active access device, today's behavior).</summary>
public List<Guid>? PlaceIds { get; set; }
}
}
+33
View File
@@ -0,0 +1,33 @@
namespace Fitness_core_BE.DTOs.CustomerPlan
{
public class CustomerPlanDto
{
public Guid CustomerPlanId { get; set; }
public Guid FKClientId { get; set; }
public string? ClientName { get; set; }
public string? PlanName { get; set; }
public string? PlanDescription { get; set; }
public decimal PlanPrice { get; set; }
public bool HasOnboardingFee { get; set; }
public decimal OnboardingFeeAmount { get; set; }
public int DurationInDays { get; set; }
public string PlanScope { get; set; } = "Individual";
public int MemberLimit { get; set; } = 1;
public string DurationMode { get; set; } = "Rolling";
public DateTime? ValidFrom { get; set; }
public DateTime? ValidTo { get; set; }
public bool AllowSplitPayments { get; set; }
public int InstallmentCount { get; set; } = 1;
public int? SessionsPerCycle { get; set; }
public string SessionRolloverPolicy { get; set; } = "NoRollover";
public int RolloverGraceDays { get; set; }
public string BillingTiming { get; set; } = "Prepaid";
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; }
// Which Places this plan grants access to. Empty = unrestricted (reaches every
// active device) -- see AccessDeviceService's allowed-device resolution.
public List<Guid> PlaceIds { get; set; } = new();
public List<string> PlaceNames { get; set; } = new();
}
}
@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
namespace Fitness_core_BE.DTOs.CustomerPlan
{
/// <summary>
/// Body of PATCH client/plans/{id}/status -- activate or deactivate a membership plan
/// without resending its configuration.
/// </summary>
public class SetCustomerPlanStatusRequest
{
[Required]
public bool IsActive { get; set; }
}
}
@@ -0,0 +1,54 @@
using System.ComponentModel.DataAnnotations;
namespace Fitness_core_BE.DTOs.CustomerPlan
{
public class UpdateCustomerPlanRequest
{
[Required]
public Guid CustomerPlanId { get; set; }
public string? PlanName { get; set; }
public string? PlanDescription { get; set; }
[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; }
[Range(1, int.MaxValue, ErrorMessage = "Duration must be at least 1 day")]
public int? DurationInDays { get; set; }
public string? PlanScope { get; set; }
public int? MemberLimit { get; set; }
public string? DurationMode { get; set; }
public DateTime? ValidFrom { get; set; }
public DateTime? ValidTo { get; set; }
public bool? AllowSplitPayments { get; set; }
public int? InstallmentCount { get; set; }
[Range(1, int.MaxValue, ErrorMessage = "SessionsPerCycle must be at least 1 when set")]
public int? SessionsPerCycle { get; set; }
public string? SessionRolloverPolicy { get; set; }
[Range(0, int.MaxValue, ErrorMessage = "RolloverGraceDays must be zero or greater")]
public int? RolloverGraceDays { get; set; }
public string? BillingTiming { get; set; }
public bool? IsActive { get; set; }
/// <summary>Replaces this plan's place set when provided (empty array clears it back
/// to unrestricted). Omit/null to leave the plan's places unchanged.</summary>
public List<Guid>? PlaceIds { get; set; }
}
}
@@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
namespace Fitness_core_BE.DTOs.CustomerSubscription
{
public class CreateCustomerSubscriptionRequest
{
[Required]
public Guid CustomerId { get; set; }
[Required]
public Guid CustomerPlanId { get; set; }
public DateTime? OnboardDate { get; set; }
public DateTime? ExpiryDate { get; set; }
}
}
@@ -0,0 +1,40 @@
namespace Fitness_core_BE.DTOs.CustomerSubscription
{
public class CustomerSubscriptionDto
{
public Guid SubscriptionId { get; set; }
public Guid CustomerId { get; set; }
public string? CustomerName { get; set; }
public Guid CustomerPlanId { get; set; }
public string? PlanName { get; set; }
public decimal PlanPrice { get; set; }
public int DurationInDays { get; set; }
public DateTime OnboardDate { get; set; }
public DateTime? ExpiryDate { get; set; }
public DateTime? RenewalDate { get; set; }
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; }
public string? DiscountType { get; set; }
public decimal? DiscountValue { get; set; }
public List<CustomerSubItemDto>? SubItems { get; set; }
}
public class CustomerSubItemDto
{
public Guid CustomerSubItemId { get; set; }
public string? SubItemName { get; set; }
public string? SubItemDescription { get; set; }
public decimal SubItemPrice { get; set; }
public string Frequency { get; set; } = "OneTime";
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; }
}
public class AddExtraFeeRequest
{
public string Name { get; set; } = string.Empty;
public string? Description { get; set; }
public decimal Amount { get; set; }
public string Frequency { get; set; } = "OneTime"; // "OneTime" | "Recurring"
}
}
@@ -0,0 +1,62 @@
namespace Fitness_core_BE.DTOs.CustomerSubscription
{
/// <summary>Full picture of one subscription: plan config, members, money, schedule.</summary>
public class SubscriptionSummaryDto
{
public Guid SubscriptionId { get; set; }
public Guid CustomerPlanId { get; set; }
public string? PlanName { get; set; }
public string PlanScope { get; set; } = "Individual";
public int MemberLimit { get; set; } = 1;
public string DurationMode { get; set; } = "Rolling";
public bool AllowSplitPayments { get; set; }
public decimal PlanPrice { get; set; }
public DateTime OnboardDate { get; set; }
public DateTime? ExpiryDate { get; set; }
public DateTime? RenewalDate { get; set; }
public bool IsActive { get; set; }
public Guid? CustomerInvoiceId { get; set; }
public decimal InvoiceAmount { get; set; }
public decimal PaidAmount { get; set; }
public decimal Balance { get; set; }
public string PaymentStatus { get; set; } = "Pending";
public List<SubscriptionMemberDto> Members { get; set; } = new();
public List<SubscriptionInstallmentDto> Installments { get; set; } = new();
public bool AutoChargeEnabled { get; set; }
public AutoChargeCardDto? AutoChargeCard { get; set; }
}
public class AutoChargeCardDto
{
public Guid CardId { get; set; }
public string? CardLast4 { get; set; }
public string? CardType { get; set; }
}
public class SubscriptionMemberDto
{
public Guid SubscriptionMemberId { get; set; }
public Guid CustomerId { get; set; }
public string? CusName { get; set; }
public string? Email { get; set; }
public string? PrimaryPH { get; set; }
public bool IsPrimary { get; set; }
public DateTime JoinedAt { get; set; }
public bool IsActive { get; set; }
/// <summary>False when unassigned from the plan but still a member of the gym.</summary>
public bool IsPlanAssigned { get; set; } = true;
}
public class SubscriptionInstallmentDto
{
public Guid SubscriptionInstallmentId { get; set; }
public int InstallmentNo { get; set; }
public DateTime DueDate { get; set; }
public decimal Amount { get; set; }
public decimal PaidAmount { get; set; }
public string Status { get; set; } = "Pending";
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace Fitness_core_BE.DTOs
{
public class DocumentDownloadModel
{
public string FileName { get; set; }
public string FileType { get; set; }
public byte[] FileData { get; set; }
}
}
+25
View File
@@ -0,0 +1,25 @@
namespace Fitness_core_BE.DTOs.Facility
{
public class FacilityDto
{
public Guid FacilityId { get; set; }
public string Name { get; set; } = string.Empty;
public string FacilityType { get; set; } = string.Empty;
public string? Description { get; set; }
public int DefaultCapacity { get; set; }
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; }
}
public class FacilitySessionDto
{
public Guid FacilitySessionId { get; set; }
public Guid FacilityId { get; set; }
public string? FacilityName { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public int Capacity { get; set; }
public int BookedCount { get; set; }
public bool IsCancelled { get; set; }
}
}
+51
View File
@@ -0,0 +1,51 @@
using System.ComponentModel.DataAnnotations;
namespace Fitness_core_BE.DTOs.Facility
{
public class CreateFacilityRequest
{
[Required]
public string Name { get; set; } = string.Empty;
/// <summary>"Gym" | "Pool" | "Court" | "Class".</summary>
[Required]
public string FacilityType { get; set; } = "Class";
public string? Description { get; set; }
[Range(1, int.MaxValue, ErrorMessage = "DefaultCapacity must be at least 1")]
public int DefaultCapacity { get; set; } = 1;
}
public class UpdateFacilityRequest
{
[Required]
public Guid FacilityId { get; set; }
public string? Name { get; set; }
public string? FacilityType { get; set; }
public string? Description { get; set; }
public int? DefaultCapacity { get; set; }
public bool? IsActive { get; set; }
}
public class SetFacilityStatusRequest
{
[Required]
public bool IsActive { get; set; }
}
public class CreateFacilitySessionRequest
{
[Required]
public Guid FacilityId { get; set; }
[Required]
public DateTime StartTime { get; set; }
[Required]
public DateTime EndTime { get; set; }
/// <summary>Overrides the facility's default capacity for this specific session.</summary>
public int? Capacity { get; set; }
}
}
+40
View File
@@ -0,0 +1,40 @@
namespace Fitness_core_BE.DTOs.Ledger
{
public class LedgerEntryDto
{
public Guid? Id { get; set; } // null for derived (non-manual) entries
public string EntryType { get; set; } = "Expense"; // "Income" | "Expense"
public string Category { get; set; } = string.Empty;
public string? Description { get; set; }
public decimal Amount { get; set; }
public DateTime EntryDate { get; set; }
public bool IsManual { get; set; }
}
public class AddLedgerEntryRequest
{
public string EntryType { get; set; } = "Expense"; // "Income" | "Expense"
public string Category { get; set; } = "Other";
public string? Description { get; set; }
public decimal Amount { get; set; }
public DateTime? EntryDate { get; set; }
}
public class CategoryTotalDto
{
public string Category { get; set; } = string.Empty;
public decimal Amount { get; set; }
}
public class ProfitLossDto
{
public DateTime From { get; set; }
public DateTime To { get; set; }
public decimal TotalIncome { get; set; }
public decimal TotalExpense { get; set; }
public decimal NetProfit { get; set; }
public List<CategoryTotalDto> IncomeByCategory { get; set; } = new();
public List<CategoryTotalDto> ExpenseByCategory { get; set; } = new();
public List<LedgerEntryDto> Entries { get; set; } = new();
}
}
+16
View File
@@ -0,0 +1,16 @@
namespace Fitness_core_BE.DTOs.Meal
{
public class CustomerMealDto
{
public Guid CustomerMealId { get; set; }
public Guid CustomerId { get; set; }
public string? CustomerName { get; set; }
public Guid MealPlanId { get; set; }
public string? MealPlanName { get; set; }
public bool IsActive { get; set; }
public bool IsFollowing { get; set; }
public DateTime AssignedDate { get; set; }
public DateTime? CompletedDate { get; set; }
public string? Notes { get; set; }
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace Fitness_core_BE.DTOs.Meal
{
public class MealCategoryDto
{
public Guid MealCategoryId { get; set; }
public string Name { get; set; }
public string? Description { get; set; }
public bool IsActive { get; set; }
public DateTime CreateDate { get; set; }
}
}
+19
View File
@@ -0,0 +1,19 @@
namespace Fitness_core_BE.DTOs.Meal
{
public class MealDto
{
public Guid MealId { get; set; }
public string Name { get; set; }
public string? Description { get; set; }
public decimal? Calories { get; set; }
public decimal? Protein { get; set; }
public decimal? Carbohydrates { get; set; }
public decimal? Fats { get; set; }
public string? ServingSize { get; set; }
public object? MealItems { get; set; }
public string? PreparationNotes { get; set; }
public Guid MealPlanId { get; set; }
public bool IsActive { get; set; }
public DateTime CreateDate { get; set; }
}
}
+22
View File
@@ -0,0 +1,22 @@
namespace Fitness_core_BE.DTOs.Meal
{
public class MealPlanDetailDto
{
public Guid MealPlanId { get; set; }
public string Name { get; set; }
public string? Description { get; set; }
public bool IsTemplate { get; set; }
public Guid MealCategoryId { get; set; }
public string MealCategoryName { get; set; }
public Guid? ClientId { get; set; }
public string? ClientName { get; set; }
public bool IsActive { get; set; }
public DateTime CreateDate { get; set; }
public List<MealDto> MealItems { get; set; } = new List<MealDto>();
public List<CustomerMealDto> AssignedCustomers { get; set; } = new List<CustomerMealDto>();
public decimal? TotalCalories { get; set; }
public decimal? TotalProtein { get; set; }
public decimal? TotalCarbohydrates { get; set; }
public decimal? TotalFats { get; set; }
}
}
+17
View File
@@ -0,0 +1,17 @@
namespace Fitness_core_BE.DTOs.Meal
{
public class MealPlanDto
{
public Guid MealPlanId { get; set; }
public string Name { get; set; }
public string? Description { get; set; }
public bool IsTemplate { get; set; }
public Guid MealCategoryId { get; set; }
public string MealCategoryName { get; set; }
public Guid? ClientId { get; set; }
public string? ClientName { get; set; }
public bool IsActive { get; set; }
public DateTime CreateDate { get; set; }
public List<CustomerMealDto> AssignedCustomers { get; set; } = new List<CustomerMealDto>();
}
}
+65
View File
@@ -0,0 +1,65 @@
namespace Fitness_core_BE.DTOs.Mobile
{
public class SendOtpRequest
{
public string Identifier { get; set; } = string.Empty;
public int NumberOfDigits { get; set; } = 4;
public bool NewUser { get; set; }
}
public class VerifyOtpLoginRequest
{
public string OtpCode { get; set; } = string.Empty;
public string ReferenceNumber { get; set; } = string.Empty;
}
public class VerifyOtpAltRequest
{
public string OtpCode { get; set; } = string.Empty;
public string ReferenceNumber { get; set; } = string.Empty;
public string? IdentifireType { get; set; }
public string? Identifier { get; set; }
}
public class RefreshTokenRequest
{
public string? RefreshToken { get; set; }
}
public class RegisterCustomerRequest
{
public string Gender { get; set; } = string.Empty;
public string Bod { get; set; } = string.Empty;
public string UserTypeId { get; set; } = string.Empty;
public string RoleId { get; set; } = string.Empty;
public bool ChkUser { get; set; }
public string? DeviceName { get; set; }
public string? PushTokenId { get; set; }
public string Fullname { get; set; } = string.Empty;
public string MobileNumber { get; set; } = string.Empty;
}
public class ForgotPasswordRequest
{
public string Identifier { get; set; } = string.Empty;
public bool UseResetLink { get; set; }
public int NumberOfDigits { get; set; } = 6;
}
public class ResetPasswordRequest
{
public string ReferenceNumber { get; set; } = string.Empty;
public string NewPassword { get; set; } = string.Empty;
public string ConfirmPassword { get; set; } = string.Empty;
}
// Verifies an OTP for a customer's own channel and sets the matching verified flag.
public class VerifyChannelRequest
{
// "PrimaryPH" | "SecondaryPH" | "Email"
public string IdentifireType { get; set; } = string.Empty;
public string OtpCode { get; set; } = string.Empty;
public string ReferenceNumber { get; set; } = string.Empty;
public string Identifier { get; set; } = string.Empty;
}
}
+15
View File
@@ -0,0 +1,15 @@
namespace Fitness_core_BE.DTOs.Mobile
{
public class GetOrCreateChatRequest
{
public Guid OtherUserId { get; set; }
}
public class SendChatMessageRequest
{
public Guid ChatId { get; set; }
public Guid SenderId { get; set; }
public string Message { get; set; } = string.Empty;
public string Type { get; set; } = "text";
}
}
+72
View File
@@ -0,0 +1,72 @@
namespace Fitness_core_BE.DTOs.Mobile
{
/// <summary>Self-service profile update (mobile). Distinct from DTOs/Customer/UpdateCustomerRequest,
/// which is the client-managed shape used by ClientController.</summary>
public class UpdateCustomerProfileRequest
{
public string? Fullname { get; set; }
public string? Gender { get; set; }
public DateOnly? Bod { get; set; }
public string? PrimaryPH { get; set; }
public string? SecondaryPH { get; set; }
public string? Nic { get; set; }
public string? Address { get; set; }
public string? Email { get; set; }
}
public class UpdateHealthRequest
{
public string? BloodGroup { get; set; }
public string? Disabilities { get; set; }
}
public class CreateProgressRequest
{
public decimal? Height { get; set; }
public decimal? CurrentWeight { get; set; }
public decimal? TargetWeight { get; set; }
public string? Goal { get; set; }
public int? Age { get; set; }
public string? Gender { get; set; }
public string? ActivityLevel { get; set; }
public decimal? TimePeriod { get; set; }
}
/// <summary>Updates the customer's latest height and/or weight measurement.</summary>
public class UpdateProgressRequest
{
public decimal? Height { get; set; }
public decimal? Weight { get; set; }
public DateTime? ProgressDate { get; set; }
}
/// <summary>Member self-serve "add card" for auto-deduct. cardToken is an opaque client-side
/// value (mock today, would be real PayHere/Stripe tokenization once a gateway is wired up).</summary>
public class SaveCardRequest
{
public string CardToken { get; set; } = string.Empty;
public string? CardLast4 { get; set; }
public string? CardType { get; set; }
public string? NickName { get; set; }
/// <summary>Must be explicitly true — this is the member's auto-deduct consent.</summary>
public bool Consent { get; set; }
}
public class SetAutoChargeRequest
{
public bool Enabled { get; set; }
public Guid? CardId { get; set; }
}
public class UpdatePushTokenRequest
{
public string PushTokenId { get; set; } = string.Empty;
}
/// <summary>documentId comes from POST /customer/documents' upload response — the client
/// uploads the picked image first, then links it here as the profile picture.</summary>
public class UpdateProfileImageRequest
{
public int DocumentId { get; set; }
}
}
+7
View File
@@ -0,0 +1,7 @@
namespace Fitness_core_BE.DTOs.Mobile
{
public class AcceptGymTermsRequest
{
public int Version { get; set; }
}
}
+20
View File
@@ -0,0 +1,20 @@
namespace Fitness_core_BE.DTOs.Mobile
{
public class CreateTicketRequest
{
public string MainReason { get; set; } = string.Empty;
public string? TicketCategoryId { get; set; }
public string? TicketStatus { get; set; }
}
public class SendTicketMessageRequest
{
public string Message { get; set; } = string.Empty;
}
public class SubmitTicketFeedbackRequest
{
public int Rating { get; set; }
public string? Feedback { get; set; }
}
}
@@ -0,0 +1,89 @@
namespace Fitness_core_BE.DTOs.PaymentGateways
{
// Mirrors Payment-Service's DTOs/Payments/*.cs for the HMAC-signed, per-platform
// Cards/Payments/Refunds surface (IPaymentGatewayClient) — distinct from
// PaymentGatewayDtos.cs, which is the X-Internal-Key admin/catalog surface.
public class OnboardCardRequest
{
public string GatewayName { get; set; } = "DirectPay";
public string CustomerId { get; set; } = string.Empty;
public string CardLabel { get; set; } = string.Empty;
public string CardholderName { get; set; } = string.Empty;
public bool IsDefault { get; set; } = false;
public string? ReturnUrl { get; set; }
}
public class OnboardCardResult
{
public string Status { get; set; } = string.Empty;
public string? RedirectUrl { get; set; }
public string CardToken { get; set; } = string.Empty;
public string MaskedPan { get; set; } = string.Empty;
public string CardLabel { get; set; } = string.Empty;
public string CardBrand { get; set; } = string.Empty;
public int ExpiryMonth { get; set; }
public int ExpiryYear { get; set; }
public bool IsDefault { get; set; }
public string GatewayRef { get; set; } = string.Empty;
}
public class CardDetailsResult
{
public string CardToken { get; set; } = string.Empty;
public string MaskedPan { get; set; } = string.Empty;
public string CardLabel { get; set; } = string.Empty;
public string CardBrand { get; set; } = string.Empty;
public int ExpiryMonth { get; set; }
public int ExpiryYear { get; set; }
public bool IsDefault { get; set; }
public string GatewayName { get; set; } = string.Empty;
}
public class AttemptPaymentRequest
{
public string IdempotencyKey { get; set; } = string.Empty;
public string GatewayName { get; set; } = "DirectPay";
public string CardToken { get; set; } = string.Empty;
public decimal AmountMinorUnits { get; set; }
public string Currency { get; set; } = "LKR";
public string Description { get; set; } = string.Empty;
}
public class AttemptPaymentResult
{
public Guid PaymentId { get; set; }
public string Status { get; set; } = string.Empty;
public string? GatewayRef { get; set; }
public DateTime CreatedAtUtc { get; set; }
}
public class RefundPaymentResult
{
public Guid PaymentId { get; set; }
public string Status { get; set; } = string.Empty;
public string GatewayRef { get; set; } = string.Empty;
}
public class SetDefaultCardResult
{
public string CardToken { get; set; } = string.Empty;
public bool IsDefault { get; set; }
}
public class PaymentListItemResult
{
public Guid PaymentId { get; set; }
public decimal AmountMinorUnits { get; set; }
public string Currency { get; set; } = string.Empty;
public string Status { get; set; } = string.Empty;
public DateTime CreatedAtUtc { get; set; }
}
public class PaymentListResult
{
public int Total { get; set; }
public int Page { get; set; }
public List<PaymentListItemResult> Items { get; set; } = new();
}
}
@@ -0,0 +1,38 @@
namespace Fitness_core_BE.DTOs.PaymentGateways
{
// Mirrors Payment-Service's DTOs/Gateways/GatewayDtos.cs - Fitness_Core_BE's
// AdminController proxies to Payment-Service rather than exposing it directly
// to the admin frontend (see Phase 0 decision: no admin/JWT auth surface there).
public class GatewayDefinitionDto
{
public Guid Id { get; set; }
public string GatewayName { get; set; } = string.Empty;
public string DisplayName { get; set; } = string.Empty;
public bool IsEnabled { get; set; }
public bool IsDefault { get; set; }
public string Mode { get; set; } = "Sandbox";
public bool SupportsWebhooks { get; set; }
}
public class UpsertGatewayDefinitionRequest
{
public string GatewayName { get; set; } = string.Empty;
public string DisplayName { get; set; } = string.Empty;
public bool IsEnabled { get; set; } = true;
public bool IsDefault { get; set; } = false;
public string Mode { get; set; } = "Sandbox";
public bool SupportsWebhooks { get; set; } = true;
}
public class SetGatewayEnabledRequest
{
public bool IsEnabled { get; set; }
}
public class UpsertPlatformGatewayCredentialRequest
{
public Guid PlatformId { get; set; }
public string GatewayName { get; set; } = string.Empty;
public string CredentialsJson { get; set; } = string.Empty;
}
}
@@ -0,0 +1,37 @@
namespace Fitness_core_BE.DTOs.PaymentsEnablement
{
// Gym owner's own payout track selection, KYC submission, wallet and payout schedule —
// distinct from Fitness_Core_BE.DTOs.PaymentGateways, which is the platform-admin's
// gateway catalog (proxied to Payment-Service).
public record PaymentTrackOption(string Track, object FeeSummary);
public record SelectPaymentTrackRequest(string Track);
public record PaymentTrackSelectionResult(string Track, bool KycRequired);
public record SubmitGatewayOnboardingRequest(Guid GatewayId);
public record GatewayOnboardingStatusDto(
string KycStatus,
Guid? GatewayId,
string? GatewayName,
string? RejectionReason);
public record ClientPayoutKycDto(
Guid Id,
Guid ClientId,
string? ClientName,
Guid? GatewayId,
string? GatewayName,
string KycStatus,
DateTime SubmittedAt,
DateTime? ReviewedAt,
string? RejectionReason,
string? NicNumber,
int? NicFrontDocId,
int? NicBackDocId);
public record ReviewPayoutKycRequest(string Status, string? Reason);
public record WalletDto(decimal Balance, string Currency, List<WalletLedgerEntryDto> Ledger, DateTime? LastPayoutDate);
public record WalletLedgerEntryDto(Guid Id, string EntryType, decimal Amount, string? Description, DateTime CreatedAt);
public record PayoutScheduleDto(DateTime NextPayoutDate, string Cadence, decimal PendingAmount);
}
+15
View File
@@ -0,0 +1,15 @@
namespace Fitness_core_BE.DTOs.Place
{
public class PlaceDto
{
public Guid PlaceId { get; set; }
public string Name { get; set; } = string.Empty;
public string? Description { get; set; }
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; }
// At most one for now -- see AccessDevice.FKPlaceId.
public Guid? DeviceId { get; set; }
public string? DeviceName { get; set; }
}
}
+32
View File
@@ -0,0 +1,32 @@
using System.ComponentModel.DataAnnotations;
namespace Fitness_core_BE.DTOs.Place
{
public class CreatePlaceRequest
{
[Required]
public string Name { get; set; } = string.Empty;
public string? Description { get; set; }
}
public class UpdatePlaceRequest
{
[Required]
public Guid PlaceId { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public bool? IsActive { get; set; }
}
public class SetPlaceStatusRequest
{
[Required]
public bool IsActive { get; set; }
}
public class AssignPlaceDeviceRequest
{
// Null unassigns the place's current device.
public Guid? DeviceId { get; set; }
}
}
@@ -0,0 +1,53 @@
namespace Fitness_core_BE.DTOs.PlatformBilling
{
// The gym's own saved card(s) for paying their HexaFitness platform subscription
// (ClientCard), and the transaction history behind those charges. Distinct from
// PaymentGatewayDtos.cs (admin gateway catalog) and PaymentsEnablementDtos.cs
// (payout track/KYC/wallet) — this is the "gym pays HexaFitness" card-charging surface.
// Fetched live from Payment-Service on every call — CardToken is the identifier (not a
// local id), and none of these fields are ever cached in Core's own database.
public class ClientCardDto
{
public string CardToken { get; set; } = string.Empty;
public string MaskedPan { get; set; } = string.Empty;
public string CardBrand { get; set; } = string.Empty;
public int ExpiryMonth { get; set; }
public int ExpiryYear { get; set; }
public bool IsDefault { get; set; }
}
public class StartCardOnboardingRequest
{
public string? CardLabel { get; set; }
public string? ReturnUrl { get; set; }
}
public class StartCardOnboardingResult
{
public string RedirectUrl { get; set; } = string.Empty;
public string SessionId { get; set; } = string.Empty;
}
public class CardOnboardingStatusResult
{
public bool IsComplete { get; set; }
public ClientCardDto? Card { get; set; }
}
public class TransactionHistoryItemDto
{
public Guid PaymentId { get; set; }
public decimal AmountMinorUnits { get; set; }
public string Currency { get; set; } = string.Empty;
public string Status { get; set; } = string.Empty;
public DateTime CreatedAtUtc { get; set; }
}
public class TransactionHistoryResult
{
public int Total { get; set; }
public int Page { get; set; }
public List<TransactionHistoryItemDto> Items { get; set; } = new();
}
}
+137
View File
@@ -0,0 +1,137 @@
namespace Fitness_core_BE.DTOs.PlatformBilling
{
public class PricingPlanDto
{
public Guid ClientPackageId { get; set; }
public string? PackageName { get; set; }
public string? PackageDescription { get; set; }
public decimal PerMemberRate { get; set; }
public decimal MinimumMonthlyBill { get; set; }
public decimal? MonthlyCap { get; set; }
public decimal SetupFee { get; set; }
public int IncludedMemberCount { get; set; }
public int? MaxBillableMemberCount { get; set; }
public decimal OwnGatewayFeePercent { get; set; }
public decimal OwnGatewayFeeFixed { get; set; }
public decimal OurGatewayFeePercent { get; set; }
public decimal OurGatewayFeeFixed { get; set; }
public int PayoutDayOfMonth { get; set; }
public bool IsDefault { get; set; }
public bool IsActive { get; set; }
}
public class UpsertPricingPlanRequest
{
public Guid? ClientPackageId { get; set; }
public string PackageName { get; set; } = string.Empty;
public string? PackageDescription { get; set; }
public decimal PerMemberRate { get; set; }
public decimal MinimumMonthlyBill { get; set; }
public decimal? MonthlyCap { get; set; }
public decimal SetupFee { get; set; }
public int IncludedMemberCount { get; set; }
public int? MaxBillableMemberCount { get; set; }
public decimal OwnGatewayFeePercent { get; set; }
public decimal OwnGatewayFeeFixed { get; set; }
public decimal OurGatewayFeePercent { get; set; }
public decimal OurGatewayFeeFixed { get; set; }
public int PayoutDayOfMonth { get; set; } = 1;
public bool IsDefault { get; set; }
}
public class DevicePricingDto
{
public decimal DeviceRentalFeePerMonth { get; set; }
public decimal DeviceInstallationFee { get; set; }
public decimal DeviceConfigureExistingFee { get; set; }
}
public class AssignPricingPlanRequest
{
public Guid ClientPackageId { get; set; }
// Optional: decide the fingerprint-machine charge at the same time as the plan assignment.
public string? DeviceBillingMode { get; set; } // "FullPurchase" | "Rental" | null (no device charge)
public decimal? DeviceAgreedAmount { get; set; }
public decimal? DeviceSetupFee { get; set; }
}
public class ClientDeviceBillingDto
{
public Guid Id { get; set; }
public string Mode { get; set; } = "Rental";
public decimal AgreedAmount { get; set; }
public decimal SetupFee { get; set; }
public DateTime AssignedAt { get; set; }
}
public class RecordClientInvoicePaymentRequest
{
public decimal Amount { get; set; }
}
public class PlatformFeeBreakdownDto
{
public Guid ClientId { get; set; }
public string? PlanName { get; set; }
public int ActiveMemberCount { get; set; }
public decimal PerMemberRate { get; set; }
public decimal MinimumMonthlyBill { get; set; }
public decimal? MonthlyCap { get; set; }
public decimal BaseFee { get; set; }
public int DeviceCount { get; set; }
public decimal DeviceFee { get; set; }
public decimal GatewayFee { get; set; }
public decimal TotalFee { get; set; }
}
public class ClientInvoiceItemDto
{
public string? ItemName { get; set; }
public string? ItemDescription { get; set; }
public decimal ItemPrice { get; set; }
}
public class ClientInvoiceSummaryDto
{
public Guid ClientInvoiceId { get; set; }
public decimal Amount { get; set; }
public string Status { get; set; } = string.Empty;
public DateTime ClientInvoiceDate { get; set; }
public List<ClientInvoiceItemDto> Items { get; set; } = new();
}
public class PendingPlatformInvoiceDto
{
public Guid ClientInvoiceId { get; set; }
public Guid ClientId { get; set; }
public string? ClientName { get; set; }
public string? City { get; set; }
public decimal Amount { get; set; }
public decimal PaidAmount { get; set; }
public string Status { get; set; } = string.Empty;
public DateTime ClientInvoiceDate { get; set; }
public int DaysOverdue { get; set; }
}
// Result of one worker run: RunAndChargeSubscriptionBillingAsync both generates any
// invoices newly due this period and drives them (and any still-in-flight from a prior
// run) toward Paid/Failed via Payment-Service.
public class SubscriptionChargeRunResult
{
public int InvoicesGenerated { get; set; }
public int ChargesAttempted { get; set; }
public int Paid { get; set; }
public int StillProcessing { get; set; }
public int Failed { get; set; }
public int SkippedNoCard { get; set; }
// A prior attempt already came back Failed — Payment-Service payments can never leave
// Failed, so these are left Pending for the existing manual pay-link fallback rather
// than retried automatically here.
public int SkippedPreviouslyFailed { get; set; }
// The invoice's balance changed (e.g. an admin recorded a manual partial payment) since
// an in-flight charge was created for the old balance — retrying would either overcharge
// or hit Payment-Service's idempotency-conflict check, so this is left for manual review.
public int SkippedAmountMismatch { get; set; }
public int Errors { get; set; }
}
}
+47
View File
@@ -0,0 +1,47 @@
namespace Fitness_core_BE.DTOs.Rbac
{
public class NavItemDto
{
public string Key { get; set; } = string.Empty;
public string Label { get; set; } = string.Empty;
public string? ShortLabel { get; set; }
public string Href { get; set; } = string.Empty;
public string Icon { get; set; } = string.Empty;
}
public class NavResponseDto
{
public bool IsOwner { get; set; }
public List<NavItemDto> Items { get; set; } = new();
}
public class GymRoleDto
{
public Guid GymRoleId { get; set; }
public string Name { get; set; } = string.Empty;
public bool IsActive { get; set; }
public List<string> NavKeys { get; set; } = new();
}
public class CreateGymRoleRequest
{
public string Name { get; set; } = string.Empty;
}
public class UpdateGymRoleRequest
{
public string? Name { get; set; }
public bool? IsActive { get; set; }
}
public class SetRolePermissionsRequest
{
public List<string> NavKeys { get; set; } = new();
}
public class AssignStaffRoleRequest
{
// Nullable to support unassigning a staff member's role.
public Guid? GymRoleId { get; set; }
}
}
+27
View File
@@ -0,0 +1,27 @@
using System.ComponentModel.DataAnnotations;
namespace Fitness_core_BE.DTOs.Staff
{
public class CreateStaffRequest
{
[Required]
public Guid ClientId { get; set; }
[Required]
public string UserName { get; set; } = string.Empty;
[Required]
[EmailAddress]
public string Email { get; set; } = string.Empty;
[Required]
[Phone]
public string PhoneNumber { get; set; } = string.Empty;
public string? StaffPosition { get; set; }
public string? Department { get; set; }
public DateTime? HireDate { get; set; }
}
}
+27
View File
@@ -0,0 +1,27 @@
namespace Fitness_core_BE.DTOs.Staff
{
public class StaffDto
{
public Guid StaffId { get; set; }
public Guid UserId { get; set; }
public string? UserName { get; set; }
public string? Email { get; set; }
public string? PhoneNumber { get; set; }
public Guid ClientId { get; set; }
public string? ClientName { get; set; }
public Guid? GymRoleId { get; set; }
public string? GymRoleName { get; set; }
public string? StaffPosition { get; set; }
public string? Department { get; set; }
public DateTime HireDate { get; set; }
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; }
public long? AccessProfileId { get; set; }
public string? AccessNumber { get; set; }
public string AccessProvisionStatus { get; set; } = "NotConfigured";
public string ActualAccessState { get; set; } = "Unknown";
public string DesiredAccessState { get; set; } = "Enabled";
public int FingerprintCount { get; set; }
public string? AccessLastError { get; set; }
}
}
+30
View File
@@ -0,0 +1,30 @@
namespace Fitness_core_BE.DTOs.Staff
{
public class StaffPayRateDto
{
public Guid Id { get; set; }
public string RateType { get; set; } = "Monthly";
public decimal Amount { get; set; }
public DateTime EffectiveFrom { get; set; }
}
public class UpsertStaffPayRateRequest
{
public string RateType { get; set; } = "Monthly"; // "Monthly" | "Hourly"
public decimal Amount { get; set; }
}
public class StaffPaymentDto
{
public Guid Id { get; set; }
public decimal Amount { get; set; }
public string? Note { get; set; }
public DateTime PaidAt { get; set; }
}
public class RecordStaffPaymentRequest
{
public decimal Amount { get; set; }
public string? Note { get; set; }
}
}
+24
View File
@@ -0,0 +1,24 @@
using System.ComponentModel.DataAnnotations;
namespace Fitness_core_BE.DTOs.Staff
{
public class UpdateStaffRequest
{
[Required]
public Guid StaffId { get; set; }
public string? UserName { get; set; }
[EmailAddress]
public string? Email { get; set; }
[Phone]
public string? PhoneNumber { get; set; }
public string? StaffPosition { get; set; }
public string? Department { get; set; }
public bool? IsActive { get; set; }
}
}
+21
View File
@@ -0,0 +1,21 @@
namespace Fitness_core_BE.DTOs.Stats
{
public class ClientStatSummaryDto
{
public int TotalCustomerCount { get; set; }
public int ThisMonthCustomerCount { get; set; }
public int LastMonthCustomerCount { get; set; }
public decimal CustomerGrowthPercentage { get; set; }
public decimal ThisMonthRevenue { get; set; }
public decimal LastMonthRevenue { get; set; }
public decimal RevenueGrowthPercentage { get; set; }
public decimal TotalRevenue { get; set; }
public int OverdueCount { get; set; }
public int ExpiringWithin7DaysCount { get; set; }
public int TodayPaymentsCount { get; set; }
public decimal TodayPaymentsTotal { get; set; }
// Muscle Beast-only pilot feature (their explicit request) -- gated server-side so the
// frontend never needs to know any gym's ClientId to decide whether to show it.
public bool ShowTodayPayments { get; set; }
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace Fitness_core_BE.DTOs.Stats
{
public class MonthlyRevenueStat
{
public int Year { get; set; }
public int Month { get; set; }
public string MonthLabel { get; set; }
public decimal Revenue { get; set; }
public int NewMemberCount { get; set; }
}
}
+48
View File
@@ -0,0 +1,48 @@
using Fitness_core_BE.Models.Enums;
namespace Fitness_core_BE.DTOs.Ticket
{
public class TicketDetailDto
{
public Guid TicketId { get; set; }
public string MainReason { get; set; }
public DateTime CreateDate { get; set; }
// User Information
public Guid UserId { get; set; }
public string UserName { get; set; }
public string UserEmail { get; set; }
public string UserPhoneNumber { get; set; }
// Admin Information (nullable)
public Guid? AdminId { get; set; }
public string? AdminName { get; set; }
public string? AdminPhoneNumber { get; set; }
// Category Information
public Guid? TicketCategoryId { get; set; }
public string? TicketCategoryName { get; set; }
public PriorityLevel? PriorityLevel { get; set; }
// Status Information
public TicketStatusEnum TicketStatus { get; set; }
// Feedback Information
public int? UserRating { get; set; }
public string? UserFeedback { get; set; }
public DateTime? FeedbackAt { get; set; }
// Messages
public List<TicketMessageDto> Messages { get; set; } = new List<TicketMessageDto>();
}
public class TicketMessageDto
{
public Guid MessageId { get; set; }
public bool IsSentByAdmin { get; set; }
public string Message { get; set; }
public string? AttachmentURL { get; set; }
public DateTime CreateDate { get; set; }
public int? FKDocumentId { get; set; }
}
}
+31
View File
@@ -0,0 +1,31 @@
using Fitness_core_BE.Models.Enums;
namespace Fitness_core_BE.DTOs.Ticket
{
public class TicketDto
{
public Guid TicketId { get; set; }
public string MainReason { get; set; }
public DateTime CreateDate { get; set; }
// User Information
public Guid UserId { get; set; }
public string UserName { get; set; }
public string UserEmail { get; set; }
// Admin Information (nullable)
public Guid? AdminId { get; set; }
public string? AdminName { get; set; }
// Category Information
public Guid? TicketCategoryId { get; set; }
public string? TicketCategoryName { get; set; }
public PriorityLevel? PriorityLevel { get; set; }
// Rating
public int? UserRating { get; set; }
// Status Information
public TicketStatusEnum TicketStatus { get; set; }
}
}
+24
View File
@@ -0,0 +1,24 @@
namespace Fitness_core_BE.DTOs.TimeBankCard
{
public class TimeBankCardDto
{
public Guid TimeBankCardId { get; set; }
public string RfidTagId { get; set; } = string.Empty;
public Guid? CustomerId { get; set; }
public int TotalMinutesPurchased { get; set; }
public int MinutesRemaining { get; set; }
public decimal AmountPaid { get; set; }
public DateTime PurchasedAt { get; set; }
public DateTime? ExpiresAt { get; set; }
public bool IsActive { get; set; }
/// <summary>True right after a tap-in swipe (session open, clock running); false after
/// tap-out or when the card has no open session.</summary>
public bool SessionOpen { get; set; }
public DateTime? SessionStartedAt { get; set; }
public string? SessionFacilityName { get; set; }
/// <summary>Only populated in the response to a tap-out swipe.</summary>
public int? MinutesDeductedThisSwipe { get; set; }
}
}
+33
View File
@@ -0,0 +1,33 @@
using System.ComponentModel.DataAnnotations;
namespace Fitness_core_BE.DTOs.TimeBankCard
{
public class IssueTimeBankCardRequest
{
[Required]
public string RfidTagId { get; set; } = string.Empty;
[Required]
[Range(1, int.MaxValue, ErrorMessage = "TotalMinutesPurchased must be at least 1")]
public int TotalMinutesPurchased { get; set; }
[Range(0, double.MaxValue, ErrorMessage = "AmountPaid must be zero or greater")]
public decimal AmountPaid { get; set; }
/// <summary>Ties the card to a member's own account; omit for a walk-in-only card.</summary>
public Guid? CustomerId { get; set; }
public DateTime? ExpiresAt { get; set; }
}
// No MinutesToDeduct -- the swipe itself is tap-in (first swipe, starts the clock) or
// tap-out (second swipe, deducts the elapsed time). See TimeBankCard.ActiveSessionStartedAt.
public class SwipeTimeBankCardRequest
{
[Required]
public string RfidTagId { get; set; } = string.Empty;
[Required]
public Guid FacilityId { get; set; }
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace Fitness_core_BE.DTOs.Tute
{
public class UpdateTuteItemRequest
{
public int Id { get; set; }
public string Title { get; set; } = string.Empty;
public string? Notes { get; set; }
}
}
+16
View File
@@ -0,0 +1,16 @@
namespace Fitness_core_BE.DTOs.Workout
{
public class CustomerWorkoutDto
{
public Guid CustomerWorkoutId { get; set; }
public Guid CustomerId { get; set; }
public string? CustomerName { get; set; }
public Guid WorkoutPlanId { get; set; }
public string? WorkoutPlanName { get; set; }
public bool IsActive { get; set; }
public bool IsFollowing { get; set; }
public DateTime AssignedDate { get; set; }
public DateTime? CompletedDate { get; set; }
public string? Notes { get; set; }
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace Fitness_core_BE.DTOs.Workout
{
public class WorkoutCategoryDto
{
public Guid WorkoutCategoryId { get; set; }
public string Name { get; set; }
public string? Description { get; set; }
public bool IsActive { get; set; }
public DateTime CreateDate { get; set; }
}
}
+17
View File
@@ -0,0 +1,17 @@
namespace Fitness_core_BE.DTOs.Workout
{
public class WorkoutExerciseDto
{
public Guid WorkoutExerciseId { get; set; }
public string Name { get; set; } = string.Empty;
public string? MuscleGroup { get; set; }
public int? Sets { get; set; }
public string? Reps { get; set; }
public string? Description { get; set; }
public string? BreathIn { get; set; }
public string? BreathOut { get; set; }
public string? VideoUrl { get; set; }
public int SortOrder { get; set; }
public bool IsCompleted { get; set; }
}
}
+23
View File
@@ -0,0 +1,23 @@
namespace Fitness_core_BE.DTOs.Workout
{
public class WorkoutItemDto
{
public Guid WorkoutItemId { get; set; }
public string ExerciseDay { get; set; } = string.Empty;
public string? Description { get; set; }
public string? Exercises { get; set; }
public string? HowToDo { get; set; }
public string? DoURL { get; set; }
public string? Duration { get; set; }
public string? WormUp { get; set; }
public string? Cooldown { get; set; }
public Guid WorkoutPlanId { get; set; }
public bool IsActive { get; set; }
public DateTime CreateDate { get; set; }
public DateTime? UpdatedAt { get; set; }
public List<WorkoutExerciseDto> WorkoutExercises { get; set; } = new List<WorkoutExerciseDto>();
public int TotalExercises { get; set; }
public int CompletedExercises { get; set; }
public bool IsCompleted { get; set; }
}
}
+18
View File
@@ -0,0 +1,18 @@
namespace Fitness_core_BE.DTOs.Workout
{
public class WorkoutPlanDetailDto
{
public Guid WorkoutPlanId { get; set; }
public string Name { get; set; }
public string? Description { get; set; }
public bool IsTemplate { get; set; }
public Guid WorkoutCategoryId { get; set; }
public string WorkoutCategoryName { get; set; }
public Guid? ClientId { get; set; }
public string? ClientName { get; set; }
public bool IsActive { get; set; }
public DateTime CreateDate { get; set; }
public List<WorkoutItemDto> WorkoutItems { get; set; } = new List<WorkoutItemDto>();
public List<CustomerWorkoutDto> AssignedCustomers { get; set; } = new List<CustomerWorkoutDto>();
}
}
+17
View File
@@ -0,0 +1,17 @@
namespace Fitness_core_BE.DTOs.Workout
{
public class WorkoutPlanDto
{
public Guid WorkoutPlanId { get; set; }
public string Name { get; set; }
public string? Description { get; set; }
public bool IsTemplate { get; set; }
public Guid WorkoutCategoryId { get; set; }
public string WorkoutCategoryName { get; set; }
public Guid? ClientId { get; set; }
public string? ClientName { get; set; }
public bool IsActive { get; set; }
public DateTime CreateDate { get; set; }
public List<CustomerWorkoutDto> AssignedCustomers { get; set; } = new List<CustomerWorkoutDto>();
}
}