Files
Dhananjaya99 bffc9b1686 first commit
2026-09-28 11:44:26 +05:30

59 lines
2.7 KiB
C#

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Fitness_core_BE.Models
{
/// <summary>A prepaid time balance on an RFID card, deducted by actual use via a tap-in/
/// tap-out swipe pattern (a 1-hour visit deducts 60 minutes, a 15-minute visit deducts 15 --
/// see ActiveSessionStartedAt) — separate from Booking's per-session OTP flow. Can belong to
/// a member (FKCustomerId set, e.g. an add-on to their plan) or be sold standalone to a
/// walk-in against just the RFID tag.</summary>
public class TimeBankCard
{
[Key]
public Guid TimeBankCardId { get; set; }
public Guid FKClientId { get; set; }
[ForeignKey(nameof(FKClientId))]
public Client Client { get; set; }
// Tenant-bucket entity: holds a TenantCustomerLinkId, not the central Customer.CusId
// directly -- see Models/TenantCustomerLink.cs. Null for a card sold to a walk-in with
// no membership at all.
public Guid? FKCustomerId { get; set; }
[ForeignKey(nameof(FKCustomerId))]
public TenantCustomerLink? TenantCustomerLink { get; set; }
[MaxLength(64)]
public string RfidTagId { get; set; } = string.Empty;
public int TotalMinutesPurchased { get; set; }
public int MinutesRemaining { get; set; }
public decimal AmountPaid { get; set; } = 0m;
public Guid? FKPaymentTransactionId { get; set; }
[ForeignKey(nameof(FKPaymentTransactionId))]
public PaymentTransaction? PaymentTransaction { get; set; }
public DateTime PurchasedAt { get; set; } = DateTime.UtcNow;
/// <summary>Null = balance never expires (spend it whenever); business can still set one.</summary>
public DateTime? ExpiresAt { get; set; }
public bool IsActive { get; set; } = true;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
// Tap-in/tap-out state: null = not currently on the floor anywhere. A swipe with this
// null starts a session (tap-in, no deduction yet); a swipe with this set ends it
// (tap-out) and deducts the elapsed minutes. One open session per card at a time --
// a second tap-in without a matching tap-out first is rejected by the service, not
// silently overwritten, so a lost/forgotten tap-out surfaces instead of losing time.
public DateTime? ActiveSessionStartedAt { get; set; }
public Guid? ActiveSessionFacilityId { get; set; }
[ForeignKey(nameof(ActiveSessionFacilityId))]
public Facility? ActiveSessionFacility { get; set; }
public virtual ICollection<TimeBankCardUsageLog> UsageLogs { get; set; }
}
}