using Jiaowu.Api.Domain.Common; namespace Jiaowu.Api.Domain.Academic; public sealed class AttendanceSheet : EntityBase { public Guid TeachingTaskId { get; set; } public TeachingTask? TeachingTask { get; set; } public required string Name { get; set; } public DateTime AttendanceDate { get; set; } public AttendanceSheetStatus Status { get; set; } = AttendanceSheetStatus.Draft; public AttendanceCheckInMethod CheckInMethod { get; set; } = AttendanceCheckInMethod.Manual; public string? CheckInToken { get; set; } public DateTime? CheckInStartsAt { get; set; } public DateTime? CheckInEndsAt { get; set; } public decimal? TargetLatitude { get; set; } public decimal? TargetLongitude { get; set; } public int? LocationRadiusMeters { get; set; } public string? Notes { get; set; } public DateTime? SubmittedAt { get; set; } public ICollection Records { get; set; } = []; public ICollection CheckInAttempts { get; set; } = []; } public sealed class AttendanceRecord { public Guid AttendanceSheetId { get; set; } public AttendanceSheet? AttendanceSheet { get; set; } public Guid StudentId { get; set; } public Student? Student { get; set; } public AttendanceStatus Status { get; set; } = AttendanceStatus.Present; public string? Notes { get; set; } public DateTime? CheckInAt { get; set; } public AttendanceCheckInMethod? CheckedInMethod { get; set; } public decimal? CheckInLatitude { get; set; } public decimal? CheckInLongitude { get; set; } public double? CheckInAccuracyMeters { get; set; } public double? CheckInDistanceMeters { get; set; } public AttendanceAppealStatus AppealStatus { get; set; } = AttendanceAppealStatus.None; public string? AppealReason { get; set; } public DateTime? AppealSubmittedAt { get; set; } public string? AppealReviewComment { get; set; } public DateTime? AppealReviewedAt { get; set; } } public sealed class AttendanceCheckInAttempt : EntityBase { public Guid AttendanceSheetId { get; set; } public AttendanceSheet? AttendanceSheet { get; set; } public Guid StudentId { get; set; } public Student? Student { get; set; } public AttendanceCheckInMethod CheckInMethod { get; set; } public bool IsSuccessful { get; set; } public string? FailureCode { get; set; } public string? DeviceIdentifierHash { get; set; } public string? DevicePlatform { get; set; } public string? IpAddress { get; set; } public string? UserAgent { get; set; } public string? RiskFlags { get; set; } public decimal? Latitude { get; set; } public decimal? Longitude { get; set; } public double? AccuracyMeters { get; set; } public double? DistanceMeters { get; set; } } public enum AttendanceSheetStatus { Draft = 1, Submitted = 2 } public enum AttendanceStatus { Present = 1, Absent = 2, Late = 3, Leave = 4, Excused = 5 } public enum AttendanceCheckInMethod { Manual = 1, QrCode = 2, Location = 3 } public enum AttendanceAppealStatus { None = 0, Pending = 1, Approved = 2, Rejected = 3 }