import { Types, Document, ClientSession, Model } from 'mongoose'; /** * ClockIn Type Definitions * * Production-grade types for attendance tracking with TypeScript * Follows industry patterns from Stripe, Netflix, Uber * * @module @classytic/clockin */ /** Re-export mongoose ObjectId */ type ObjectId = Types.ObjectId; /** ObjectId or string representation */ type ObjectIdLike = ObjectId | string; /** Generic document type */ type AnyDocument = Document & Record; /** Generic model type */ type AnyModel = Model; /** Deep partial type for nested objects */ type DeepPartial = { [P in keyof T]?: T[P] extends object ? DeepPartial : T[P]; }; /** Attendance record status */ type AttendanceStatus = 'valid' | 'invalid' | 'corrected' | 'disputed'; /** Check-in method */ type CheckInMethod = 'manual' | 'qr_code' | 'rfid' | 'biometric' | 'mobile_app' | 'api'; /** Member engagement level */ type EngagementLevel = 'highly_active' | 'active' | 'regular' | 'occasional' | 'inactive' | 'at_risk' | 'dormant'; /** Time period for aggregation */ type AttendancePeriod = 'daily' | 'weekly' | 'monthly' | 'yearly'; /** * Built-in target model types with smart defaults. * These models have pre-configured detection rules and auto-checkout settings. */ type BuiltInTargetModel = 'Membership' | 'Employee' | 'Trainer' | 'Class' | 'Student' | 'User'; /** * Target model type. * * As of v2.0, this is a string type to support custom target models. * Use `registerTargetModel()` in the builder to configure custom models. * * @example * ```typescript * // Built-in models work out of the box * const clockin = ClockIn.create() * .withModels({ Attendance, Membership }) * .build(); * * // Custom models can be registered with config * const clockin = ClockIn.create() * .withModels({ Attendance, Event }) * .registerTargetModel('Event', { * detection: { type: 'time-based' }, * autoCheckout: { enabled: true, afterHours: 4 } * }) * .build(); * ``` */ type AttendanceTargetModel = string; /** Stats calculation mode */ type StatsCalculationMode = 'real_time' | 'pre_calculated' | 'hybrid'; /** Attendance type for work day classification */ type AttendanceType = 'full_day' | 'half_day_morning' | 'half_day_afternoon' | 'paid_leave' | 'unpaid_leave' | 'overtime'; /** Time slot for pattern analysis */ type TimeSlot = 'early_morning' | 'morning' | 'afternoon' | 'evening' | 'night'; /** Correction request type */ type CorrectionRequestType = 'update_check_in_time' | 'update_check_out_time' | 'add_missing_attendance' | 'delete_duplicate' | 'override_attendance_type'; /** Correction request status */ type CorrectionRequestStatus = 'pending' | 'approved' | 'rejected' | 'applied'; /** Priority level */ type Priority = 'low' | 'normal' | 'high' | 'urgent'; /** Engagement thresholds configuration */ interface EngagementThresholds { /** Minimum visits for highly active (default: 12) */ highlyActive: number; /** Minimum visits for active (default: 8) */ active: number; /** Minimum visits for regular (default: 4) */ regular: number; /** Minimum visits for occasional (default: 1) */ occasional: number; /** At-risk configuration */ atRisk: { /** Days inactive before at-risk (default: 14) */ daysInactive: number; }; /** Dormant configuration */ dormant: { /** Days inactive before dormant (default: 30) */ daysInactive: number; }; } /** Stats calculation configuration */ interface StatsConfig { /** Default calculation mode */ defaultMode: StatsCalculationMode; /** Cache duration in seconds */ cacheDuration: number; /** Auto-update stats on check-in */ autoUpdateStats: boolean; /** Enable batch updates */ batchUpdateEnabled: boolean; /** Batch size for bulk operations */ batchSize: number; } /** Monthly aggregation configuration */ interface AggregationConfig { /** Maximum check-ins per document */ maxCheckInsPerMonth: number; /** Months to keep detailed history */ detailedHistoryMonths: number; /** Archive records after X months */ archiveAfterMonths: number; /** Compress archived records */ compressArchived: boolean; } /** Streak calculation configuration */ interface StreakConfig { /** Minimum hours between visits for separate days */ minHoursBetweenVisits: number; /** Maximum gap days to maintain streak */ maxGapDays: number; /** Reset streak after X days */ resetStreakAfterDays: number; /** Hours until streak breaks */ breakAfterHours: number; /** Milestone values */ milestones: number[]; } /** Check-in validation rules */ interface CheckInRules { /** Minutes between duplicate check-ins */ duplicatePreventionMinutes: number; /** Minutes before scheduled for early check-in */ earlyCheckInMinutes: number; /** Minutes after scheduled for late check-in */ lateCheckInMinutes: number; /** Minimum hours between check-ins */ minimumTimeBetweenCheckIns: number; } /** Analytics configuration */ interface AnalyticsConfig { /** Threshold for peak hours detection (0-1) */ peakHoursThreshold: number; /** Days for trending period */ trendingPeriodDays: number; /** Days for forecast window */ forecastDays: number; /** Dashboard refresh interval in seconds */ dashboardRefreshSeconds: number; } /** Notification configuration */ interface NotificationConfig { /** Streak milestone values */ streakMilestones: number[]; /** Days of inactivity before alert */ inactivityAlertDays: number; /** Visit milestone values */ visitMilestones: number[]; } /** Auto-checkout configuration */ interface AutoCheckoutConfig { /** Enable auto-checkout */ enabled: boolean; /** Default hours after check-in */ afterHours: number; /** Maximum session duration in hours */ maxSession: number; } /** Schedule validation configuration */ interface ValidationConfig { /** Enforce schedule rules */ enforceSchedule: boolean; /** Allow weekend check-ins */ allowWeekends: boolean; /** Grace period in hours */ gracePeriod: number; /** Only warn, don't block */ warnOnly: boolean; } /** Detection rules configuration */ interface DetectionRules { /** Duration thresholds */ thresholds: { overtime: number; fullDay: number; halfDay?: number; unpaid?: number; minimal?: number; }; /** Fallback thresholds when no schedule */ fallback?: { standardHours: number; overtime: number; fullDay: number; halfDay: number; }; /** Default attendance type */ defaultType: AttendanceType; } /** Time hints for half-day classification */ interface TimeHints { /** Hour cutoff for morning shift */ morningCutoff: number; /** Hour start for afternoon shift */ afternoonStart: number; } /** Detection configuration */ interface DetectionConfig { /** Detection type */ type: 'schedule-aware' | 'time-based'; /** Field containing work schedule */ scheduleSource: string | null; /** Detection rules */ rules: DetectionRules; /** Time classification hints */ timeHints: TimeHints | null; } /** Target model configuration */ interface TargetModelConfig { /** Target model name */ targetModel: string; /** Detection configuration */ detection: DetectionConfig; /** Auto-checkout configuration */ autoCheckout: AutoCheckoutConfig; /** Validation configuration */ validation: ValidationConfig; } /** Single-tenant configuration */ interface SingleTenantConfig { /** Fixed organization ID */ organizationId: ObjectIdLike; /** Auto-inject organizationId if missing */ autoInject: boolean; } /** Main ClockIn configuration */ interface ClockInConfig { /** Attendance model (required) */ AttendanceModel: Model; /** Custom configs per target model */ configs?: Record; /** Single-tenant configuration */ singleTenant?: SingleTenantConfig | null; /** Custom logger */ logger?: Logger; /** TTL for attendance records in days (default: 730) */ recordTtlDays?: number; } /** User reference for audit */ interface UserReference { userId?: ObjectId; name?: string; role?: string; userName?: string; userRole?: string; } /** Location data */ interface LocationData { lat?: number; lng?: number; accuracy?: number; } /** Device information */ interface DeviceInfo { type?: string; platform?: string; appVersion?: string; } /** Correction entry */ interface CorrectionEntry { field: string; originalValue: unknown; newValue: unknown; reason?: string; correctedBy: UserReference; correctedAt: Date; } /** Single check-in entry */ interface CheckInEntry { _id?: ObjectId; timestamp: Date; checkOutAt?: Date | null; expectedCheckOutAt?: Date | null; duration?: number | null; autoCheckedOut: boolean; recordedBy: UserReference; checkedOutBy?: UserReference | null; method: CheckInMethod; status: AttendanceStatus; timeSlot?: TimeSlot; attendanceType: AttendanceType; location?: LocationData; device?: DeviceInfo; notes?: string; corrections?: CorrectionEntry[]; metadata?: Map; } /** Time slot distribution */ interface TimeSlotDistribution { early_morning: number; morning: number; afternoon: number; evening: number; night: number; } /** Correction request */ interface CorrectionRequest { _id?: ObjectId; requestType: CorrectionRequestType; status: CorrectionRequestStatus; checkInId?: ObjectId; requestedChanges: { checkInTime?: Date; checkOutTime?: Date; attendanceType?: AttendanceType; reason: string; }; priority: Priority; reviewedBy?: UserReference; reviewedAt?: Date; reviewNotes?: string; appliedAt?: Date; createdAt: Date; } /** Monthly attendance record document */ interface AttendanceRecord { _id?: ObjectId; organizationId: ObjectId; targetModel: AttendanceTargetModel; targetId: ObjectId; year: number; month: number; checkIns: CheckInEntry[]; monthlyTotal: number; uniqueDaysVisited: number; fullDaysCount: number; halfDaysCount: number; paidLeaveDaysCount: number; overtimeDaysCount: number; totalWorkDays: number; timeSlotDistribution: TimeSlotDistribution; dayOfWeekDistribution: Map; correctionRequests: CorrectionRequest[]; metadata?: Map; createdAt?: Date; updatedAt?: Date; } /** Pre-calculated attendance stats (embedded in member documents) */ interface AttendanceStats { totalVisits: number; lastVisitedAt?: Date | null; firstVisitedAt?: Date | null; currentStreak: number; longestStreak: number; monthlyAverage: number; thisMonthVisits: number; lastMonthVisits: number; engagementLevel: EngagementLevel; daysSinceLastVisit?: number; favoriteTimeSlot?: TimeSlot; loyaltyScore: number; updatedAt?: Date; } /** Current session tracking (embedded in member documents) */ interface CurrentSession { isActive: boolean; checkInId?: ObjectId | null; checkInTime?: Date | null; expectedCheckOutAt?: Date | null; method?: CheckInMethod | null; /** Virtual field - calculated dynamically */ readonly durationMinutes?: number; } /** Work schedule definition */ interface WorkSchedule { hoursPerDay?: number; hoursPerWeek?: number; workingDays?: number[]; shiftStart?: string; shiftEnd?: string; } /** Base operation context */ interface OperationContext { /** User performing the operation */ userId?: ObjectIdLike; /** User name */ userName?: string; /** User role */ userRole?: string; /** Organization ID */ organizationId?: ObjectIdLike; /** MongoDB session for transactions */ session?: ClientSession; } /** Check-in data */ interface CheckInData { /** Check-in method */ method?: CheckInMethod; /** Timestamp (defaults to now) */ timestamp?: Date; /** Location data */ location?: LocationData; /** Device info */ device?: DeviceInfo; /** Notes */ notes?: string; /** Custom metadata */ metadata?: Record; } /** Check-in parameters */ interface CheckInParams { /** Member/entity document */ member: TMember; /** Target model name */ targetModel: AttendanceTargetModel; /** Check-in data */ data?: CheckInData; /** Operation context */ context?: OperationContext; } /** Check-out parameters */ interface CheckOutParams { /** Member/entity document */ member: TMember; /** Target model name */ targetModel: AttendanceTargetModel; /** Check-in ID to checkout */ checkInId: ObjectIdLike; /** Operation context */ context?: OperationContext; } /** Check-in result */ interface CheckInResult { /** Created check-in entry */ checkIn: CheckInEntry; /** Updated attendance record */ attendance: AttendanceRecord; /** Updated member document */ updatedMember: AnyDocument; /** Updated stats */ stats: AttendanceStats; } /** Check-out result */ interface CheckOutResult { /** Updated check-in entry */ checkIn: CheckInEntry; /** Session duration in minutes */ duration: number; } /** Batch checkout parameters for expired sessions */ interface CheckoutExpiredParams { /** Organization ID (optional in single-tenant mode) */ organizationId?: ObjectIdLike; /** Target model name (optional: process all registered models) */ targetModel?: AttendanceTargetModel; /** Process sessions with expectedCheckOutAt before this time */ before?: Date; /** Max sessions to process per target model */ limit?: number; /** Operation context */ context?: OperationContext; } /** Batch checkout result summary */ interface CheckoutExpiredResult { /** Total sessions considered */ total: number; /** Successfully checked out */ processed: number; /** Failed to check out */ failed: number; /** Failure details */ errors: Array<{ targetModel?: string; memberId?: ObjectIdLike; checkInId?: ObjectIdLike; reason: string; }>; } /** Toggle result (check-in or check-out) */ interface ToggleResult extends Partial, Partial { /** Action performed */ action: 'check-in' | 'check-out'; /** Member info */ member?: { id: ObjectId; membershipCode?: string; name?: string; }; } /** Validation result */ interface ValidationResult { /** Whether validation passed */ valid: boolean; /** Error message if invalid */ error?: string; /** Warning messages */ warnings?: string[]; /** Last check-in timestamp */ lastCheckIn?: Date; /** Next allowed check-in time */ nextAllowedTime?: Date; } /** Bulk check-in data */ interface BulkCheckInData extends CheckInData { /** Member identifier (email, code, etc.) */ memberIdentifier: string; /** Target model */ targetModel?: AttendanceTargetModel; } /** Bulk operation result */ interface BulkOperationResult { /** Successful operations */ success: number; /** Failed operations */ failed: number; /** Error details */ errors: Array<{ memberIdentifier: string; error: string; }>; } /** Dashboard parameters */ interface DashboardParams { /** Member model */ MemberModel: Model; /** Organization ID */ organizationId: ObjectIdLike; /** Start date */ startDate?: Date; /** End date */ endDate?: Date; } /** Dashboard summary */ interface DashboardSummary { /** Total members count */ totalMembers: number; /** Active members this month */ activeMembers: number; /** Activation rate percentage */ activationRate: number; /** Total check-ins in period */ totalCheckIns: number; /** Average visits per member */ avgVisitsPerMember: number; /** Unique visitors in period */ uniqueVisitors: number; } /** Engagement distribution entry */ interface EngagementDistributionEntry { /** Engagement level */ level: EngagementLevel | null; /** Member count */ count: number; } /** Top member entry */ interface TopMemberEntry { _id: ObjectId; customer?: { name?: string; email?: string; }; attendanceStats: AttendanceStats; } /** Dashboard result */ interface DashboardResult { /** Summary metrics */ summary: DashboardSummary; /** Engagement distribution */ engagementDistribution: EngagementDistributionEntry[]; /** Top members by visits */ topMembers: TopMemberEntry[]; /** At-risk members */ atRiskMembers: TopMemberEntry[]; /** Date range */ dateRange: { start: Date; end: Date; }; } /** History parameters */ interface HistoryParams { /** Target document ID (e.g., Membership ID, Employee ID) */ targetId: ObjectIdLike; /** Organization ID */ organizationId: ObjectIdLike; /** Year filter */ year?: number; /** Month filter */ month?: number; /** Target model filter */ targetModel?: AttendanceTargetModel; } /** Occupancy data */ interface OccupancyData { /** Total currently checked in */ total: number; /** Breakdown by target model */ byType: Record; /** Timestamp */ timestamp: Date; } /** Active session data */ interface ActiveSessionData { /** Check-in ID */ checkInId: ObjectId; /** Check-in timestamp */ timestamp: Date; /** Expected checkout */ expectedCheckOutAt?: Date; /** Duration in minutes */ duration: number; /** Check-in method */ method: CheckInMethod; } /** Daily trend entry */ interface DailyTrendEntry { /** Date string */ date: string; /** Total check-ins */ count: number; /** Unique members */ uniqueMembers: number; } /** Period stats */ interface PeriodStats { /** Total check-ins */ totalCheckIns: number; /** Unique members */ uniqueMembers: number; /** Average check-ins per member */ avgCheckInsPerMember: number; } /** Update check-in time parameters */ interface UpdateCheckInTimeParams { /** Attendance record ID */ attendanceId: ObjectIdLike; /** Check-in entry ID */ checkInId: ObjectIdLike; /** New timestamp */ newTimestamp: Date; /** Reason for correction */ reason: string; /** Operation context */ context: OperationContext; } /** Update check-out time parameters */ interface UpdateCheckOutTimeParams { /** Attendance record ID */ attendanceId: ObjectIdLike; /** Check-in entry ID */ checkInId: ObjectIdLike; /** New checkout timestamp */ newCheckOutTime: Date; /** Reason for correction */ reason: string; /** Operation context */ context: OperationContext; } /** Override attendance type parameters */ interface OverrideAttendanceTypeParams { /** Attendance record ID */ attendanceId: ObjectIdLike; /** Check-in entry ID */ checkInId: ObjectIdLike; /** New attendance type */ newType: AttendanceType; /** Reason for override */ reason: string; /** Operation context */ context: OperationContext; } /** Submit correction request parameters */ interface SubmitCorrectionRequestParams { /** Member ID */ memberId: ObjectIdLike; /** Organization ID */ organizationId?: ObjectIdLike; /** Year */ year: number; /** Month */ month: number; /** Target model (required when creating a new attendance record) */ targetModel?: AttendanceTargetModel; /** Request type */ requestType: CorrectionRequestType; /** Check-in ID (if applicable) */ checkInId?: ObjectIdLike; /** Proposed changes */ proposedChanges: { checkInTime?: Date; checkOutTime?: Date; attendanceType?: AttendanceType; reason: string; }; /** Priority */ priority?: Priority; /** Operation context (session, user metadata) */ context?: OperationContext; } /** Review correction request parameters */ interface ReviewCorrectionRequestParams { /** Attendance record ID */ attendanceId: ObjectIdLike; /** Request ID */ requestId: ObjectIdLike; /** Approval status */ approved: boolean; /** Review notes */ notes?: string; /** Operation context */ context: OperationContext; } /** List correction requests parameters */ interface ListCorrectionRequestsParams { /** Attendance record ID */ attendanceId?: ObjectIdLike; /** Member ID (used with organizationId + year/month) */ memberId?: ObjectIdLike; /** Organization ID (required if attendanceId is not provided) */ organizationId?: ObjectIdLike; /** Year (required if attendanceId is not provided) */ year?: number; /** Month (required if attendanceId is not provided) */ month?: number; /** Target model name */ targetModel?: AttendanceTargetModel; /** Filter by status */ status?: CorrectionRequestStatus; /** Filter by request type */ requestType?: CorrectionRequestType; /** Operation context */ context?: OperationContext; } /** Apply correction request parameters */ interface ApplyCorrectionRequestParams { /** Attendance record ID */ attendanceId: ObjectIdLike; /** Request ID */ requestId: ObjectIdLike; /** Operation context */ context: OperationContext; } /** Result type for service methods */ type Result = { ok: true; value: T; } | { ok: false; error: E; }; /** ClockIn instance for plugin reference */ interface ClockInInstance { /** Configured attendance model */ AttendanceModel: Model; /** Model name */ model: string; /** Event hooks */ _hooks: Map void | Promise>>; /** Is initialized */ _initialized: boolean; /** Check-in operations */ checkIn: { /** Validate if member can check in */ validate(member: TMember | null | undefined, targetModel: string, options?: { timestamp?: Date; }): ValidationResult; /** Record a check-in */ record(params: CheckInParams): Promise>; /** Bulk check-in (for data imports) */ recordBulk(checkIns: BulkCheckInData[], context?: OperationContext): Promise; }; /** Check-out operations */ checkOut: { /** Record a check-out */ record(params: CheckOutParams): Promise>; /** Toggle check-in/out (smart action based on current state) */ toggle(params: { member: TMember; targetModel: string; data?: CheckInData; context?: OperationContext; }): Promise>; /** Get current occupancy (who's checked in right now) */ getOccupancy(params: { organizationId: ObjectIdLike; targetModel?: string; }): Promise>; /** Batch check-out for expired sessions */ checkoutExpired(params: CheckoutExpiredParams): Promise>; /** Get member's current active session */ getCurrentSession(params: { memberId: ObjectIdLike; organizationId: ObjectIdLike; targetModel: string; }): Promise>; }; /** Analytics operations */ analytics: { /** Get dashboard analytics */ dashboard(params: DashboardParams): Promise>; /** Get member attendance history */ history(params: HistoryParams): Promise>; /** Get daily attendance trend */ dailyTrend(params: { organizationId: ObjectIdLike; days?: number; targetModel?: string; }): Promise>; /** Get period statistics */ periodStats(params: { organizationId: ObjectIdLike; year: number; month: number; targetModel?: string; }): Promise>; /** Get time slot distribution */ timeSlotDistribution(params: { organizationId: ObjectIdLike; startDate?: Date; endDate?: Date; }): Promise>>; /** Recalculate stats for members */ recalculateStats(params: { MemberModel: Model; organizationId: ObjectIdLike; memberIds?: ObjectIdLike[]; }): Promise>; }; /** Register event listener */ on(event: string, listener: (data: unknown) => void | Promise): () => void; /** Register one-time event listener */ once(event: string, listener: (data: unknown) => void | Promise): () => void; /** Remove event listener */ off(event: string, listener: (data: unknown) => void | Promise): void; /** Whether single-tenant mode is enabled */ readonly isSingleTenant: boolean; /** Single-tenant organization ID (if configured) */ readonly singleTenantOrgId: ObjectIdLike | undefined; /** Destroy instance and clean up resources */ destroy(): Promise; /** Extended properties from plugins */ [key: string]: unknown; } /** Plugin interface */ interface Plugin { /** Plugin name */ name: string; /** Apply plugin to ClockIn instance */ apply(clockIn: ClockInInstance): void; } /** Plugin function signature */ type PluginFunction = (clockIn: ClockInInstance) => void; /** Plugin type (object or function) */ type PluginType = Plugin | PluginFunction; /** Event names */ type ClockInEvent = 'checkIn:recorded' | 'checkIn:failed' | 'checkOut:recorded' | 'checkOut:failed' | 'milestone:achieved' | 'engagement:changed' | 'stats:updated' | 'member:atRisk' | 'member:inactive' | 'session:expired'; /** Event payload base */ interface EventPayloadBase { /** Event type */ type: ClockInEvent; /** Event timestamp */ timestamp: Date; } /** Check-in recorded event */ interface CheckInRecordedEvent extends EventPayloadBase { type: 'checkIn:recorded'; data: { checkIn: { id: ObjectId; timestamp: Date; method: CheckInMethod; }; member: { id: ObjectId; name?: string; }; stats: { totalVisits: number; currentStreak: number; engagementLevel: EngagementLevel; }; context?: OperationContext; }; } /** Milestone achieved event */ interface MilestoneAchievedEvent extends EventPayloadBase { type: 'milestone:achieved'; data: { member: { id: ObjectId; name?: string; }; milestone: { type: 'visits' | 'streak'; value: number; message: string; }; stats: AttendanceStats; }; } /** Engagement changed event */ interface EngagementChangedEvent extends EventPayloadBase { type: 'engagement:changed'; data: { member: { id: ObjectId; name?: string; }; engagement: { from: EngagementLevel; to: EngagementLevel; }; stats: AttendanceStats; }; } /** All event payloads union */ type EventPayload = CheckInRecordedEvent | MilestoneAchievedEvent | EngagementChangedEvent; /** Logger interface */ interface Logger { info(message: string, meta?: Record): void; error(message: string, meta?: Record): void; warn(message: string, meta?: Record): void; debug(message: string, meta?: Record): void; } /** Error code enumeration */ type ErrorCode = 'ATTENDANCE_ERROR' | 'NOT_INITIALIZED' | 'MEMBER_NOT_FOUND' | 'INVALID_MEMBER' | 'DUPLICATE_CHECK_IN' | 'VALIDATION_ERROR' | 'ATTENDANCE_NOT_ENABLED' | 'NO_ACTIVE_SESSION' | 'ALREADY_CHECKED_OUT' | 'TARGET_MODEL_NOT_ALLOWED'; /** HTTP error with status code */ interface HttpError extends Error { code: ErrorCode; status: number; context?: Record; timestamp: Date; } /** Streak calculation result */ interface StreakResult { /** Current consecutive days */ currentStreak: number; /** Longest streak ever */ longestStreak: number; } /** Schedule thresholds */ interface ScheduleThresholds { /** Hours for overtime */ overtime: number; /** Hours for full day */ fullDay: number; /** Hours for half day */ halfDay: number; /** Hours for unpaid */ unpaid: number; } /** Schedule check result */ interface ScheduleCheckResult { /** Is within shift */ within: boolean; /** Hours early */ earlyBy: number; /** Hours late */ lateBy: number; } /** Working day check result */ interface WorkingDayResult { /** Is a working day */ isWorking: boolean; /** Day name */ dayName: string; } /** * Base member interface that ClockIn expects * Extend this in your application */ interface ClockInMember { _id: ObjectId; organizationId: ObjectId; status?: string; attendanceEnabled?: boolean; attendanceStats?: AttendanceStats; currentSession?: CurrentSession; customer?: { name?: string; email?: string; }; name?: string; membershipCode?: string; workSchedule?: WorkSchedule; } /** * Member model with ClockIn fields applied * Use this to type your member model */ type WithClockIn = TMember & { attendanceStats: AttendanceStats; currentSession: CurrentSession; attendanceEnabled: boolean; }; export type { ActiveSessionData, AggregationConfig, AnalyticsConfig, AnyDocument, AnyModel, ApplyCorrectionRequestParams, AttendancePeriod, AttendanceRecord, AttendanceStats, AttendanceStatus, AttendanceTargetModel, AttendanceType, AutoCheckoutConfig, BuiltInTargetModel, BulkCheckInData, BulkOperationResult, CheckInData, CheckInEntry, CheckInMethod, CheckInParams, CheckInRecordedEvent, CheckInResult, CheckInRules, CheckOutParams, CheckOutResult, CheckoutExpiredParams, CheckoutExpiredResult, ClockInConfig, ClockInEvent, ClockInInstance, ClockInMember, CorrectionEntry, CorrectionRequest, CorrectionRequestStatus, CorrectionRequestType, CurrentSession, DailyTrendEntry, DashboardParams, DashboardResult, DashboardSummary, DeepPartial, DetectionConfig, DetectionRules, DeviceInfo, EngagementChangedEvent, EngagementDistributionEntry, EngagementLevel, EngagementThresholds, ErrorCode, EventPayload, EventPayloadBase, HistoryParams, HttpError, ListCorrectionRequestsParams, LocationData, Logger, MilestoneAchievedEvent, NotificationConfig, ObjectId, ObjectIdLike, OccupancyData, OperationContext, OverrideAttendanceTypeParams, PeriodStats, Plugin, PluginFunction, PluginType, Priority, Result, ReviewCorrectionRequestParams, ScheduleCheckResult, ScheduleThresholds, SingleTenantConfig, StatsCalculationMode, StatsConfig, StreakConfig, StreakResult, SubmitCorrectionRequestParams, TargetModelConfig, TimeHints, TimeSlot, TimeSlotDistribution, ToggleResult, TopMemberEntry, UpdateCheckInTimeParams, UpdateCheckOutTimeParams, UserReference, ValidationConfig, ValidationResult, WithClockIn, WorkSchedule, WorkingDayResult };