@devlider001/washlab-backend 1.0.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,7 @@
8
8
  * @module
9
9
  */
10
10
 
11
+ import type * as actions from "../actions.js";
11
12
  import type * as admin from "../admin.js";
12
13
  import type * as analytics from "../analytics.js";
13
14
  import type * as attendants from "../attendants.js";
@@ -16,10 +17,12 @@ import type * as branches from "../branches.js";
16
17
  import type * as clerk from "../clerk.js";
17
18
  import type * as customers from "../customers.js";
18
19
  import type * as http from "../http.js";
20
+ import type * as lib_attendance from "../lib/attendance.js";
19
21
  import type * as lib_audit from "../lib/audit.js";
20
22
  import type * as lib_auth from "../lib/auth.js";
21
23
  import type * as lib_biometricComparison from "../lib/biometricComparison.js";
22
24
  import type * as lib_biometricEncryption from "../lib/biometricEncryption.js";
25
+ import type * as lib_passwordHashing from "../lib/passwordHashing.js";
23
26
  import type * as lib_tokenHashing from "../lib/tokenHashing.js";
24
27
  import type * as lib_utils from "../lib/utils.js";
25
28
  import type * as loyalty from "../loyalty.js";
@@ -27,6 +30,7 @@ import type * as notifications from "../notifications.js";
27
30
  import type * as orders from "../orders.js";
28
31
  import type * as payments from "../payments.js";
29
32
  import type * as resources from "../resources.js";
33
+ import type * as stations from "../stations.js";
30
34
  import type * as vouchers from "../vouchers.js";
31
35
 
32
36
  import type {
@@ -36,6 +40,7 @@ import type {
36
40
  } from "convex/server";
37
41
 
38
42
  declare const fullApi: ApiFromModules<{
43
+ actions: typeof actions;
39
44
  admin: typeof admin;
40
45
  analytics: typeof analytics;
41
46
  attendants: typeof attendants;
@@ -44,10 +49,12 @@ declare const fullApi: ApiFromModules<{
44
49
  clerk: typeof clerk;
45
50
  customers: typeof customers;
46
51
  http: typeof http;
52
+ "lib/attendance": typeof lib_attendance;
47
53
  "lib/audit": typeof lib_audit;
48
54
  "lib/auth": typeof lib_auth;
49
55
  "lib/biometricComparison": typeof lib_biometricComparison;
50
56
  "lib/biometricEncryption": typeof lib_biometricEncryption;
57
+ "lib/passwordHashing": typeof lib_passwordHashing;
51
58
  "lib/tokenHashing": typeof lib_tokenHashing;
52
59
  "lib/utils": typeof lib_utils;
53
60
  loyalty: typeof loyalty;
@@ -55,6 +62,7 @@ declare const fullApi: ApiFromModules<{
55
62
  orders: typeof orders;
56
63
  payments: typeof payments;
57
64
  resources: typeof resources;
65
+ stations: typeof stations;
58
66
  vouchers: typeof vouchers;
59
67
  }>;
60
68
 
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Action Execution Functions
3
+ *
4
+ * Handles attendance-linked action execution with verification.
5
+ * All critical actions must be linked to an active attendance session.
6
+ */
7
+ import { MutationCtx } from "./_generated/server";
8
+ import { Id } from "./_generated/dataModel";
9
+ /**
10
+ * Create action log entry (attendance-linked)
11
+ * This is called after verifying attendance and executing the action
12
+ * Note: This function requires MutationCtx for insert operations
13
+ */
14
+ export declare function createActionLog(ctx: MutationCtx, attendanceId: Id<"attendanceLogs">, attendantId: Id<"attendants">, branchId: Id<"branches">, actionType: string, entityType: string, entityId: string | Id<"orders">, deviceId?: string, metadata?: Record<string, any>, actionStatus?: "pending" | "completed" | "failed" | "cancelled"): Promise<Id<"actionLogs">>;
15
+ /**
16
+ * Execute action with attendance verification
17
+ * This is the main entry point for critical actions
18
+ */
19
+ export declare const executeAction: import("convex/server").RegisteredMutation<"public", {
20
+ branchId?: import("convex/values").GenericId<"branches"> | undefined;
21
+ deviceId?: string | undefined;
22
+ metadata?: string | undefined;
23
+ entityType: string;
24
+ entityId: string;
25
+ actionType: string;
26
+ }, Promise<{
27
+ success: boolean;
28
+ actionLogId: Id<"actionLogs">;
29
+ attendanceId: import("convex/values").GenericId<"attendanceLogs">;
30
+ timestamp: number;
31
+ }>>;
32
+ /**
33
+ * Get actions by attendance session
34
+ */
35
+ export declare const getActionsByAttendance: import("convex/server").RegisteredQuery<"public", {
36
+ attendanceId: import("convex/values").GenericId<"attendanceLogs">;
37
+ }, Promise<{
38
+ _id: import("convex/values").GenericId<"actionLogs">;
39
+ _creationTime: number;
40
+ amount?: number | undefined;
41
+ completedAt?: number | undefined;
42
+ entityType?: string | undefined;
43
+ entityId?: import("convex/values").GenericId<"orders"> | undefined;
44
+ errorMessage?: string | undefined;
45
+ actionData?: string | undefined;
46
+ verificationMethod?: "biometric_face" | "biometric_hand" | "pin" | "password" | undefined;
47
+ verificationId?: import("convex/values").GenericId<"biometricVerifications"> | undefined;
48
+ createdAt: number;
49
+ branchId: import("convex/values").GenericId<"branches">;
50
+ attendantId: import("convex/values").GenericId<"attendants">;
51
+ attendanceId: import("convex/values").GenericId<"attendanceLogs">;
52
+ actionType: string;
53
+ actionStatus: "pending" | "completed" | "cancelled" | "failed";
54
+ }[]>>;
55
+ /**
56
+ * Get actions by attendant (with pagination)
57
+ */
58
+ export declare const getActionsByAttendant: import("convex/server").RegisteredQuery<"public", {
59
+ attendantId: import("convex/values").GenericId<"attendants">;
60
+ paginationOpts: {
61
+ id?: number;
62
+ endCursor?: string | null;
63
+ maximumRowsRead?: number;
64
+ maximumBytesRead?: number;
65
+ numItems: number;
66
+ cursor: string | null;
67
+ };
68
+ }, Promise<import("convex/server").PaginationResult<{
69
+ _id: import("convex/values").GenericId<"actionLogs">;
70
+ _creationTime: number;
71
+ amount?: number | undefined;
72
+ completedAt?: number | undefined;
73
+ entityType?: string | undefined;
74
+ entityId?: import("convex/values").GenericId<"orders"> | undefined;
75
+ errorMessage?: string | undefined;
76
+ actionData?: string | undefined;
77
+ verificationMethod?: "biometric_face" | "biometric_hand" | "pin" | "password" | undefined;
78
+ verificationId?: import("convex/values").GenericId<"biometricVerifications"> | undefined;
79
+ createdAt: number;
80
+ branchId: import("convex/values").GenericId<"branches">;
81
+ attendantId: import("convex/values").GenericId<"attendants">;
82
+ attendanceId: import("convex/values").GenericId<"attendanceLogs">;
83
+ actionType: string;
84
+ actionStatus: "pending" | "completed" | "cancelled" | "failed";
85
+ }>>>;
86
+ /**
87
+ * Get actions by branch (with pagination)
88
+ */
89
+ export declare const getActionsByBranch: import("convex/server").RegisteredQuery<"public", {
90
+ actionType?: string | undefined;
91
+ startDate?: number | undefined;
92
+ endDate?: number | undefined;
93
+ branchId: import("convex/values").GenericId<"branches">;
94
+ paginationOpts: {
95
+ id?: number;
96
+ endCursor?: string | null;
97
+ maximumRowsRead?: number;
98
+ maximumBytesRead?: number;
99
+ numItems: number;
100
+ cursor: string | null;
101
+ };
102
+ }, Promise<import("convex/server").PaginationResult<{
103
+ _id: import("convex/values").GenericId<"actionLogs">;
104
+ _creationTime: number;
105
+ amount?: number | undefined;
106
+ completedAt?: number | undefined;
107
+ entityType?: string | undefined;
108
+ entityId?: import("convex/values").GenericId<"orders"> | undefined;
109
+ errorMessage?: string | undefined;
110
+ actionData?: string | undefined;
111
+ verificationMethod?: "biometric_face" | "biometric_hand" | "pin" | "password" | undefined;
112
+ verificationId?: import("convex/values").GenericId<"biometricVerifications"> | undefined;
113
+ createdAt: number;
114
+ branchId: import("convex/values").GenericId<"branches">;
115
+ attendantId: import("convex/values").GenericId<"attendants">;
116
+ attendanceId: import("convex/values").GenericId<"attendanceLogs">;
117
+ actionType: string;
118
+ actionStatus: "pending" | "completed" | "cancelled" | "failed";
119
+ }>>>;
120
+ /**
121
+ * Get actions by entity (e.g., all actions on a specific order)
122
+ * Note: Currently only supports orders as entityType due to schema limitation
123
+ * This query is not optimized for large datasets - consider using pagination or adding an index
124
+ */
125
+ export declare const getActionsByEntity: import("convex/server").RegisteredQuery<"public", {
126
+ entityType: string;
127
+ entityId: import("convex/values").GenericId<"orders">;
128
+ }, Promise<{
129
+ _id: import("convex/values").GenericId<"actionLogs">;
130
+ _creationTime: number;
131
+ amount?: number | undefined;
132
+ completedAt?: number | undefined;
133
+ entityType?: string | undefined;
134
+ entityId?: import("convex/values").GenericId<"orders"> | undefined;
135
+ errorMessage?: string | undefined;
136
+ actionData?: string | undefined;
137
+ verificationMethod?: "biometric_face" | "biometric_hand" | "pin" | "password" | undefined;
138
+ verificationId?: import("convex/values").GenericId<"biometricVerifications"> | undefined;
139
+ createdAt: number;
140
+ branchId: import("convex/values").GenericId<"branches">;
141
+ attendantId: import("convex/values").GenericId<"attendants">;
142
+ attendanceId: import("convex/values").GenericId<"attendanceLogs">;
143
+ actionType: string;
144
+ actionStatus: "pending" | "completed" | "cancelled" | "failed";
145
+ }[]>>;
146
+ /**
147
+ * Get action statistics for an attendance session
148
+ */
149
+ export declare const getAttendanceActionStats: import("convex/server").RegisteredQuery<"public", {
150
+ attendanceId: import("convex/values").GenericId<"attendanceLogs">;
151
+ }, Promise<{
152
+ totalActions: number;
153
+ actionsByType: Record<string, number>;
154
+ firstAction: number | null;
155
+ lastAction: number | null;
156
+ durationMinutes: number | null;
157
+ }>>;
158
+ //# sourceMappingURL=actions.d.ts.map
package/convex/admin.d.ts CHANGED
@@ -38,6 +38,8 @@ export declare const getBranches: import("convex/server").RegisteredQuery<"publi
38
38
  _id: import("convex/values").GenericId<"branches">;
39
39
  _creationTime: number;
40
40
  email?: string | undefined;
41
+ stationPinHash?: string | undefined;
42
+ requireStationLogin?: boolean | undefined;
41
43
  phoneNumber: string;
42
44
  name: string;
43
45
  createdAt: number;
@@ -63,6 +65,8 @@ export declare const getBranchByCode: import("convex/server").RegisteredQuery<"p
63
65
  _id: import("convex/values").GenericId<"branches">;
64
66
  _creationTime: number;
65
67
  email?: string | undefined;
68
+ stationPinHash?: string | undefined;
69
+ requireStationLogin?: boolean | undefined;
66
70
  phoneNumber: string;
67
71
  name: string;
68
72
  createdAt: number;
@@ -85,6 +89,8 @@ export declare const getBranch: import("convex/server").RegisteredQuery<"public"
85
89
  _id: import("convex/values").GenericId<"branches">;
86
90
  _creationTime: number;
87
91
  email?: string | undefined;
92
+ stationPinHash?: string | undefined;
93
+ requireStationLogin?: boolean | undefined;
88
94
  phoneNumber: string;
89
95
  name: string;
90
96
  createdAt: number;
@@ -104,16 +110,17 @@ export declare const getBranch: import("convex/server").RegisteredQuery<"public"
104
110
  */
105
111
  export declare const getAttendants: import("convex/server").RegisteredQuery<"public", {
106
112
  branchId?: import("convex/values").GenericId<"branches"> | undefined;
107
- includeInactive?: boolean | undefined;
108
113
  numItems?: number | undefined;
109
114
  cursor?: string | undefined;
115
+ includeInactive?: boolean | undefined;
110
116
  }, Promise<{
111
117
  page: {
112
118
  _id: import("convex/values").GenericId<"attendants">;
113
119
  _creationTime: number;
114
120
  clerkUserId?: string | undefined;
115
121
  lastLoginAt?: number | undefined;
116
- passcode?: string | undefined;
122
+ passcodeHash?: string | undefined;
123
+ authenticationMethods?: ("biometric_face" | "biometric_hand" | "pin" | "password")[] | undefined;
117
124
  enrollmentTokenHash?: string | undefined;
118
125
  enrollmentTokenExpiresAt?: number | undefined;
119
126
  enrolledAt?: number | undefined;
@@ -310,6 +317,8 @@ export declare const deleteCustomer: import("convex/server").RegisteredMutation<
310
317
  */
311
318
  export declare const createBranch: import("convex/server").RegisteredMutation<"public", {
312
319
  email?: string | undefined;
320
+ requireStationLogin?: boolean | undefined;
321
+ stationPin?: string | undefined;
313
322
  phoneNumber: string;
314
323
  name: string;
315
324
  code: string;
@@ -333,6 +342,8 @@ export declare const updateBranch: import("convex/server").RegisteredMutation<"p
333
342
  country?: string | undefined;
334
343
  pricingPerKg?: number | undefined;
335
344
  deliveryFee?: number | undefined;
345
+ requireStationLogin?: boolean | undefined;
346
+ stationPin?: string | undefined;
336
347
  branchId: import("convex/values").GenericId<"branches">;
337
348
  }, Promise<import("convex/values").GenericId<"branches">>>;
338
349
  /**
@@ -369,9 +380,9 @@ export declare const updateAttendant: import("convex/server").RegisteredMutation
369
380
  phoneNumber?: string | undefined;
370
381
  email?: string | undefined;
371
382
  name?: string | undefined;
372
- passcode?: string | undefined;
373
383
  branchId?: import("convex/values").GenericId<"branches"> | undefined;
374
384
  isActive?: boolean | undefined;
385
+ passcode?: string | undefined;
375
386
  attendantId: import("convex/values").GenericId<"attendants">;
376
387
  }, Promise<import("convex/values").GenericId<"attendants">>>;
377
388
  /**
@@ -381,6 +392,70 @@ export declare const assignAttendantToBranch: import("convex/server").Registered
381
392
  branchId: import("convex/values").GenericId<"branches">;
382
393
  attendantId: import("convex/values").GenericId<"attendants">;
383
394
  }, Promise<import("convex/values").GenericId<"attendants">>>;
395
+ /**
396
+ * Change attendant enrollment status (suspend, activate, lock, unlock)
397
+ */
398
+ export declare const changeAttendantStatus: import("convex/server").RegisteredMutation<"public", {
399
+ reason?: string | undefined;
400
+ status: "active" | "suspended" | "invited" | "enrolling" | "locked";
401
+ attendantId: import("convex/values").GenericId<"attendants">;
402
+ }, Promise<{
403
+ attendantId: import("convex/values").GenericId<"attendants">;
404
+ oldStatus: "active" | "suspended" | "invited" | "enrolling" | "locked";
405
+ newStatus: "active" | "suspended" | "invited" | "enrolling" | "locked";
406
+ }>>;
407
+ /**
408
+ * Suspend attendant (convenience function)
409
+ */
410
+ export declare const suspendAttendant: import("convex/server").RegisteredMutation<"public", {
411
+ reason?: string | undefined;
412
+ attendantId: import("convex/values").GenericId<"attendants">;
413
+ }, Promise<{
414
+ attendantId: import("convex/values").GenericId<"attendants">;
415
+ oldStatus: "active" | "invited" | "enrolling" | "locked";
416
+ newStatus: string;
417
+ }>>;
418
+ /**
419
+ * Activate attendant (convenience function - unsuspend/unlock)
420
+ */
421
+ export declare const activateAttendant: import("convex/server").RegisteredMutation<"public", {
422
+ reason?: string | undefined;
423
+ attendantId: import("convex/values").GenericId<"attendants">;
424
+ }, Promise<{
425
+ attendantId: import("convex/values").GenericId<"attendants">;
426
+ oldStatus: "suspended" | "invited" | "enrolling" | "locked";
427
+ newStatus: string;
428
+ }>>;
429
+ /**
430
+ * Lock attendant (convenience function)
431
+ */
432
+ export declare const lockAttendant: import("convex/server").RegisteredMutation<"public", {
433
+ reason?: string | undefined;
434
+ attendantId: import("convex/values").GenericId<"attendants">;
435
+ }, Promise<{
436
+ attendantId: import("convex/values").GenericId<"attendants">;
437
+ oldStatus: "active" | "suspended" | "invited" | "enrolling";
438
+ newStatus: string;
439
+ }>>;
440
+ /**
441
+ * Reset attendant verification failures
442
+ */
443
+ export declare const resetAttendantFailures: import("convex/server").RegisteredMutation<"public", {
444
+ reason?: string | undefined;
445
+ attendantId: import("convex/values").GenericId<"attendants">;
446
+ }, Promise<{
447
+ attendantId: import("convex/values").GenericId<"attendants">;
448
+ }>>;
449
+ /**
450
+ * Revoke all active sessions for an attendant
451
+ */
452
+ export declare const revokeAttendantSessions: import("convex/server").RegisteredMutation<"public", {
453
+ reason?: string | undefined;
454
+ attendantId: import("convex/values").GenericId<"attendants">;
455
+ }, Promise<{
456
+ attendantId: import("convex/values").GenericId<"attendants">;
457
+ sessionsRevoked: number;
458
+ }>>;
384
459
  /**
385
460
  * Delete attendant (soft delete)
386
461
  */
@@ -13,7 +13,8 @@ export declare const getByBranch: import("convex/server").RegisteredQuery<"publi
13
13
  _creationTime: number;
14
14
  clerkUserId?: string | undefined;
15
15
  lastLoginAt?: number | undefined;
16
- passcode?: string | undefined;
16
+ passcodeHash?: string | undefined;
17
+ authenticationMethods?: ("biometric_face" | "biometric_hand" | "pin" | "password")[] | undefined;
17
18
  enrollmentTokenHash?: string | undefined;
18
19
  enrollmentTokenExpiresAt?: number | undefined;
19
20
  enrolledAt?: number | undefined;
@@ -55,7 +56,8 @@ export declare const getCurrentUser: import("convex/server").RegisteredQuery<"pu
55
56
  _creationTime: number;
56
57
  clerkUserId?: string | undefined;
57
58
  lastLoginAt?: number | undefined;
58
- passcode?: string | undefined;
59
+ passcodeHash?: string | undefined;
60
+ authenticationMethods?: ("biometric_face" | "biometric_hand" | "pin" | "password")[] | undefined;
59
61
  enrollmentTokenHash?: string | undefined;
60
62
  enrollmentTokenExpiresAt?: number | undefined;
61
63
  enrolledAt?: number | undefined;
@@ -85,20 +87,52 @@ export declare const getCurrentUser: import("convex/server").RegisteredQuery<"pu
85
87
  createdBy: import("convex/values").GenericId<"admins">;
86
88
  }>>;
87
89
  /**
88
- * Get current active attendance session
90
+ * Get current active attendance session for authenticated attendant
91
+ * Returns attendance details with branch and attendant info
89
92
  */
90
- export declare const getActiveSession: import("convex/server").RegisteredQuery<"public", {}, Promise<{
91
- _id: import("convex/values").GenericId<"attendanceLogs">;
92
- _creationTime: number;
93
- deviceInfo?: string | undefined;
94
- clockOutAt?: number | undefined;
95
- deviceId?: string | undefined;
96
- isDeleted: boolean;
93
+ export declare const getActiveAttendanceSession: import("convex/server").RegisteredQuery<"public", {}, Promise<{
94
+ attendance: {
95
+ _id: import("convex/values").GenericId<"attendanceLogs">;
96
+ attendantId: import("convex/values").GenericId<"attendants">;
97
+ branchId: import("convex/values").GenericId<"branches">;
98
+ clockInAt: number;
99
+ deviceId: string | undefined;
100
+ deviceInfo: string | undefined;
101
+ };
102
+ branch: {
103
+ _id: import("convex/values").GenericId<"branches">;
104
+ name: string;
105
+ address: string;
106
+ } | null;
107
+ attendant: {
108
+ _id: import("convex/values").GenericId<"attendants">;
109
+ name: string;
110
+ email: string;
111
+ };
112
+ } | null>>;
113
+ /**
114
+ * Get all active attendances for a branch
115
+ * Useful for station dashboard to show who's currently clocked in
116
+ */
117
+ export declare const getActiveAttendancesByBranch: import("convex/server").RegisteredQuery<"public", {
97
118
  branchId: import("convex/values").GenericId<"branches">;
98
- isActive: boolean;
99
- attendantId: import("convex/values").GenericId<"attendants">;
119
+ }, Promise<({
120
+ _id: import("convex/values").GenericId<"attendanceLogs">;
100
121
  clockInAt: number;
101
- } | null>>;
122
+ deviceId: string | undefined;
123
+ deviceInfo: string | undefined;
124
+ attendant: null;
125
+ } | {
126
+ _id: import("convex/values").GenericId<"attendanceLogs">;
127
+ clockInAt: number;
128
+ deviceId: string | undefined;
129
+ deviceInfo: string | undefined;
130
+ attendant: {
131
+ _id: import("convex/values").GenericId<"attendants">;
132
+ name: string;
133
+ email: string;
134
+ };
135
+ })[]>>;
102
136
  /**
103
137
  * Get attendance history - Paginated
104
138
  * Supports usePaginatedQuery for infinite scroll
@@ -136,7 +170,37 @@ export declare const clockIn: import("convex/server").RegisteredMutation<"public
136
170
  */
137
171
  export declare const clockOut: import("convex/server").RegisteredMutation<"public", {
138
172
  attendanceLogId?: import("convex/values").GenericId<"attendanceLogs"> | undefined;
139
- }, Promise<import("convex/values").GenericId<"attendanceLogs">>>;
173
+ }, Promise<{
174
+ attendanceLogId: import("convex/values").GenericId<"attendanceLogs">;
175
+ sessionsRevoked: number;
176
+ durationMinutes: number;
177
+ }>>;
178
+ /**
179
+ * Get attendance details by ID
180
+ */
181
+ export declare const getAttendanceById: import("convex/server").RegisteredQuery<"public", {
182
+ attendanceId: import("convex/values").GenericId<"attendanceLogs">;
183
+ }, Promise<{
184
+ _id: import("convex/values").GenericId<"attendanceLogs">;
185
+ attendantId: import("convex/values").GenericId<"attendants">;
186
+ branchId: import("convex/values").GenericId<"branches">;
187
+ clockInAt: number;
188
+ clockOutAt: number | undefined;
189
+ deviceId: string | undefined;
190
+ deviceInfo: string | undefined;
191
+ isActive: boolean;
192
+ durationMinutes: number;
193
+ attendant: {
194
+ _id: import("convex/values").GenericId<"attendants">;
195
+ name: string;
196
+ email: string;
197
+ } | null;
198
+ branch: {
199
+ _id: import("convex/values").GenericId<"branches">;
200
+ name: string;
201
+ address: string;
202
+ } | null;
203
+ }>>;
140
204
  /**
141
205
  * Get attendance statistics for a branch
142
206
  */
@@ -237,9 +301,12 @@ export declare const findByEmail: import("convex/server").RegisteredQuery<"publi
237
301
  email: string;
238
302
  }, Promise<{
239
303
  id: import("convex/values").GenericId<"attendants">;
240
- name: string;
241
304
  email: string;
305
+ name: string;
242
306
  branchId: import("convex/values").GenericId<"branches">;
307
+ authenticationMethods: ("biometric_face" | "biometric_hand" | "pin" | "password")[];
308
+ hasBiometric: boolean;
309
+ hasPin: boolean;
243
310
  } | null>>;
244
311
  /**
245
312
  * Start verification (for login or action)
@@ -308,4 +375,80 @@ export declare const checkVerificationStatus: import("convex/server").Registered
308
375
  consecutiveFailures: number;
309
376
  enrollmentStatus: "active" | "suspended" | "invited" | "enrolling" | "locked";
310
377
  }>>;
378
+ /**
379
+ * Create session after successful biometric verification
380
+ */
381
+ export declare const createSession: import("convex/server").RegisteredMutation<"public", {
382
+ deviceInfo?: string | undefined;
383
+ attendantId: import("convex/values").GenericId<"attendants">;
384
+ }, Promise<{
385
+ success: boolean;
386
+ sessionToken: string;
387
+ refreshToken: string;
388
+ expiresAt: number;
389
+ refreshExpiresAt: number;
390
+ sessionId: import("convex/values").GenericId<"attendantSessions">;
391
+ }>>;
392
+ /**
393
+ * Refresh session access token
394
+ */
395
+ export declare const refreshSession: import("convex/server").RegisteredMutation<"public", {
396
+ refreshToken: string;
397
+ }, Promise<{
398
+ success: boolean;
399
+ sessionToken: string;
400
+ expiresAt: number;
401
+ }>>;
402
+ /**
403
+ * Logout - invalidate session
404
+ */
405
+ export declare const logout: import("convex/server").RegisteredMutation<"public", {
406
+ sessionToken?: string | undefined;
407
+ }, Promise<{
408
+ success: boolean;
409
+ sessionsRevoked?: undefined;
410
+ } | {
411
+ success: boolean;
412
+ sessionsRevoked: number;
413
+ }>>;
414
+ /**
415
+ * Authenticate attendant with PIN or Password
416
+ */
417
+ export declare const authenticateWithPinOrPassword: import("convex/server").RegisteredMutation<"public", {
418
+ deviceInfo?: string | undefined;
419
+ branchId: import("convex/values").GenericId<"branches">;
420
+ attendantId: import("convex/values").GenericId<"attendants">;
421
+ pinOrPassword: string;
422
+ isPin: boolean;
423
+ }, Promise<{
424
+ success: boolean;
425
+ attendantId: import("convex/values").GenericId<"attendants">;
426
+ name: string;
427
+ email: string;
428
+ branchId: import("convex/values").GenericId<"branches">;
429
+ }>>;
430
+ /**
431
+ * Get current session (validate and return session info)
432
+ */
433
+ export declare const getCurrentSession: import("convex/server").RegisteredQuery<"public", {
434
+ sessionToken: string;
435
+ }, Promise<{
436
+ success: boolean;
437
+ attendant: {
438
+ _id: import("convex/values").GenericId<"attendants">;
439
+ name: string;
440
+ email: string;
441
+ branchId: import("convex/values").GenericId<"branches">;
442
+ };
443
+ branch: {
444
+ _id: import("convex/values").GenericId<"branches">;
445
+ name: string;
446
+ address: string;
447
+ } | null;
448
+ session: {
449
+ expiresAt: number;
450
+ lastActivityAt: number;
451
+ createdAt: number;
452
+ };
453
+ }>>;
311
454
  //# sourceMappingURL=attendants.d.ts.map
package/convex/audit.d.ts CHANGED
@@ -17,6 +17,7 @@ export declare const getByEntity: import("convex/server").RegisteredQuery<"publi
17
17
  branchId?: import("convex/values").GenericId<"branches"> | undefined;
18
18
  deviceId?: string | undefined;
19
19
  entityId?: string | undefined;
20
+ attendanceId?: import("convex/values").GenericId<"attendanceLogs"> | undefined;
20
21
  ipAddress?: string | undefined;
21
22
  details?: string | undefined;
22
23
  oldValue?: string | undefined;
@@ -41,6 +42,7 @@ export declare const getByActor: import("convex/server").RegisteredQuery<"public
41
42
  branchId?: import("convex/values").GenericId<"branches"> | undefined;
42
43
  deviceId?: string | undefined;
43
44
  entityId?: string | undefined;
45
+ attendanceId?: import("convex/values").GenericId<"attendanceLogs"> | undefined;
44
46
  ipAddress?: string | undefined;
45
47
  details?: string | undefined;
46
48
  oldValue?: string | undefined;
@@ -64,6 +66,7 @@ export declare const getByBranch: import("convex/server").RegisteredQuery<"publi
64
66
  branchId?: import("convex/values").GenericId<"branches"> | undefined;
65
67
  deviceId?: string | undefined;
66
68
  entityId?: string | undefined;
69
+ attendanceId?: import("convex/values").GenericId<"attendanceLogs"> | undefined;
67
70
  ipAddress?: string | undefined;
68
71
  details?: string | undefined;
69
72
  oldValue?: string | undefined;
@@ -87,6 +90,7 @@ export declare const getByAction: import("convex/server").RegisteredQuery<"publi
87
90
  branchId?: import("convex/values").GenericId<"branches"> | undefined;
88
91
  deviceId?: string | undefined;
89
92
  entityId?: string | undefined;
93
+ attendanceId?: import("convex/values").GenericId<"attendanceLogs"> | undefined;
90
94
  ipAddress?: string | undefined;
91
95
  details?: string | undefined;
92
96
  oldValue?: string | undefined;
@@ -111,6 +115,7 @@ export declare const getByTimeRange: import("convex/server").RegisteredQuery<"pu
111
115
  branchId?: import("convex/values").GenericId<"branches"> | undefined;
112
116
  deviceId?: string | undefined;
113
117
  entityId?: string | undefined;
118
+ attendanceId?: import("convex/values").GenericId<"attendanceLogs"> | undefined;
114
119
  ipAddress?: string | undefined;
115
120
  details?: string | undefined;
116
121
  oldValue?: string | undefined;
@@ -147,6 +152,7 @@ export declare const getAll: import("convex/server").RegisteredQuery<"public", {
147
152
  branchId?: import("convex/values").GenericId<"branches"> | undefined;
148
153
  deviceId?: string | undefined;
149
154
  entityId?: string | undefined;
155
+ attendanceId?: import("convex/values").GenericId<"attendanceLogs"> | undefined;
150
156
  ipAddress?: string | undefined;
151
157
  details?: string | undefined;
152
158
  oldValue?: string | undefined;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Attendance Utility Functions
3
+ *
4
+ * Provides helper functions for attendance-related operations,
5
+ * including verification and validation for attendance-linked actions.
6
+ */
7
+ import { QueryCtx, MutationCtx } from "../_generated/server";
8
+ import { Id } from "../_generated/dataModel";
9
+ /**
10
+ * Get active attendance record for an attendant
11
+ * @throws Error if no active attendance found
12
+ */
13
+ export declare function getActiveAttendance(ctx: QueryCtx | MutationCtx, attendantId: Id<"attendants">): Promise<{
14
+ _id: import("convex/values").GenericId<"attendanceLogs">;
15
+ _creationTime: number;
16
+ deviceInfo?: string | undefined;
17
+ clockOutAt?: number | undefined;
18
+ deviceId?: string | undefined;
19
+ isDeleted: boolean;
20
+ branchId: import("convex/values").GenericId<"branches">;
21
+ isActive: boolean;
22
+ attendantId: import("convex/values").GenericId<"attendants">;
23
+ clockInAt: number;
24
+ }>;
25
+ /**
26
+ * Verify that an attendant has an active attendance session
27
+ * Returns the attendance record if valid, throws error otherwise
28
+ */
29
+ export declare function verifyActiveAttendance(ctx: QueryCtx | MutationCtx, attendantId: Id<"attendants">, branchId?: Id<"branches">): Promise<{
30
+ _id: import("convex/values").GenericId<"attendanceLogs">;
31
+ _creationTime: number;
32
+ deviceInfo?: string | undefined;
33
+ clockOutAt?: number | undefined;
34
+ deviceId?: string | undefined;
35
+ isDeleted: boolean;
36
+ branchId: import("convex/values").GenericId<"branches">;
37
+ isActive: boolean;
38
+ attendantId: import("convex/values").GenericId<"attendants">;
39
+ clockInAt: number;
40
+ }>;
41
+ /**
42
+ * Check if attendant has active attendance (does not throw, returns boolean)
43
+ */
44
+ export declare function hasActiveAttendance(ctx: QueryCtx | MutationCtx, attendantId: Id<"attendants">): Promise<boolean>;
45
+ /**
46
+ * Get all active attendances for a branch
47
+ */
48
+ export declare function getActiveAttendancesByBranch(ctx: QueryCtx | MutationCtx, branchId: Id<"branches">): Promise<{
49
+ _id: import("convex/values").GenericId<"attendanceLogs">;
50
+ _creationTime: number;
51
+ deviceInfo?: string | undefined;
52
+ clockOutAt?: number | undefined;
53
+ deviceId?: string | undefined;
54
+ isDeleted: boolean;
55
+ branchId: import("convex/values").GenericId<"branches">;
56
+ isActive: boolean;
57
+ attendantId: import("convex/values").GenericId<"attendants">;
58
+ clockInAt: number;
59
+ }[]>;
60
+ /**
61
+ * Get attendance history for an attendant
62
+ */
63
+ export declare function getAttendantAttendanceHistory(ctx: QueryCtx | MutationCtx, attendantId: Id<"attendants">, limit?: number): Promise<{
64
+ _id: import("convex/values").GenericId<"attendanceLogs">;
65
+ _creationTime: number;
66
+ deviceInfo?: string | undefined;
67
+ clockOutAt?: number | undefined;
68
+ deviceId?: string | undefined;
69
+ isDeleted: boolean;
70
+ branchId: import("convex/values").GenericId<"branches">;
71
+ isActive: boolean;
72
+ attendantId: import("convex/values").GenericId<"attendants">;
73
+ clockInAt: number;
74
+ }[]>;
75
+ /**
76
+ * Calculate duration of an attendance session in minutes
77
+ */
78
+ export declare function calculateAttendanceDuration(clockInAt: number, clockOutAt?: number): number;
79
+ //# sourceMappingURL=attendance.d.ts.map
@@ -14,6 +14,7 @@ interface AuditLogParams {
14
14
  action: string;
15
15
  entityType: string;
16
16
  entityId?: string;
17
+ attendanceId?: Id<"attendanceLogs">;
17
18
  branchId?: Id<"branches">;
18
19
  deviceId?: string;
19
20
  details?: string;
@@ -23,7 +24,7 @@ interface AuditLogParams {
23
24
  /**
24
25
  * Create an audit log entry
25
26
  */
26
- export declare function createAuditLog({ ctx, actorId, actorType, actorRole, action, entityType, entityId, branchId, deviceId, details, oldValue, newValue, }: AuditLogParams): Promise<Id<"auditLogs">>;
27
+ export declare function createAuditLog({ ctx, actorId, actorType, actorRole, action, entityType, entityId, attendanceId, branchId, deviceId, details, oldValue, newValue, }: AuditLogParams): Promise<Id<"auditLogs">>;
27
28
  /**
28
29
  * Create audit log for order status change
29
30
  */
@@ -59,7 +59,8 @@ export declare function getCurrentAttendant(ctx: QueryCtx | MutationCtx): Promis
59
59
  _creationTime: number;
60
60
  clerkUserId?: string | undefined;
61
61
  lastLoginAt?: number | undefined;
62
- passcode?: string | undefined;
62
+ passcodeHash?: string | undefined;
63
+ authenticationMethods?: ("biometric_face" | "biometric_hand" | "pin" | "password")[] | undefined;
63
64
  enrollmentTokenHash?: string | undefined;
64
65
  enrollmentTokenExpiresAt?: number | undefined;
65
66
  enrolledAt?: number | undefined;
@@ -127,7 +128,8 @@ export declare function verifyAttendantBranch(ctx: QueryCtx | MutationCtx, atten
127
128
  _creationTime: number;
128
129
  clerkUserId?: string | undefined;
129
130
  lastLoginAt?: number | undefined;
130
- passcode?: string | undefined;
131
+ passcodeHash?: string | undefined;
132
+ authenticationMethods?: ("biometric_face" | "biometric_hand" | "pin" | "password")[] | undefined;
131
133
  enrollmentTokenHash?: string | undefined;
132
134
  enrollmentTokenExpiresAt?: number | undefined;
133
135
  enrolledAt?: number | undefined;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Password/PIN Hashing Utilities
3
+ *
4
+ * Provides secure password/PIN hashing using Web Crypto API.
5
+ * Uses PBKDF2 for password hashing (more secure than SHA-256 for passwords).
6
+ */
7
+ /**
8
+ * Hash a password or PIN using PBKDF2
9
+ * This is more secure than SHA-256 for passwords as it's designed for this purpose
10
+ */
11
+ export declare function hashPassword(password: string, salt?: string): Promise<{
12
+ hash: string;
13
+ salt: string;
14
+ }>;
15
+ /**
16
+ * Verify a password or PIN against its hash
17
+ */
18
+ export declare function verifyPassword(password: string, hash: string, salt: string): Promise<boolean>;
19
+ /**
20
+ * Simple PIN hashing (4-6 digits) - uses SHA-256 with salt for simplicity
21
+ * PINs are less secure, so we use a simpler approach but still with salt
22
+ */
23
+ export declare function hashPIN(pin: string, salt?: string): Promise<{
24
+ hash: string;
25
+ salt: string;
26
+ }>;
27
+ /**
28
+ * Verify a PIN against its hash
29
+ */
30
+ export declare function verifyPIN(pin: string, hash: string, salt: string): Promise<boolean>;
31
+ //# sourceMappingURL=passwordHashing.d.ts.map
@@ -38,6 +38,8 @@ export declare const getBranches: import("convex/server").RegisteredQuery<"publi
38
38
  _id: import("convex/values").GenericId<"branches">;
39
39
  _creationTime: number;
40
40
  email?: string | undefined;
41
+ stationPinHash?: string | undefined;
42
+ requireStationLogin?: boolean | undefined;
41
43
  phoneNumber: string;
42
44
  name: string;
43
45
  createdAt: number;
@@ -63,6 +65,8 @@ export declare const getBranchByCode: import("convex/server").RegisteredQuery<"p
63
65
  _id: import("convex/values").GenericId<"branches">;
64
66
  _creationTime: number;
65
67
  email?: string | undefined;
68
+ stationPinHash?: string | undefined;
69
+ requireStationLogin?: boolean | undefined;
66
70
  phoneNumber: string;
67
71
  name: string;
68
72
  createdAt: number;
@@ -85,6 +89,8 @@ export declare const getBranch: import("convex/server").RegisteredQuery<"public"
85
89
  _id: import("convex/values").GenericId<"branches">;
86
90
  _creationTime: number;
87
91
  email?: string | undefined;
92
+ stationPinHash?: string | undefined;
93
+ requireStationLogin?: boolean | undefined;
88
94
  phoneNumber: string;
89
95
  name: string;
90
96
  createdAt: number;
@@ -104,16 +110,17 @@ export declare const getBranch: import("convex/server").RegisteredQuery<"public"
104
110
  */
105
111
  export declare const getAttendants: import("convex/server").RegisteredQuery<"public", {
106
112
  branchId?: import("convex/values").GenericId<"branches"> | undefined;
107
- includeInactive?: boolean | undefined;
108
113
  numItems?: number | undefined;
109
114
  cursor?: string | undefined;
115
+ includeInactive?: boolean | undefined;
110
116
  }, Promise<{
111
117
  page: {
112
118
  _id: import("convex/values").GenericId<"attendants">;
113
119
  _creationTime: number;
114
120
  clerkUserId?: string | undefined;
115
121
  lastLoginAt?: number | undefined;
116
- passcode?: string | undefined;
122
+ passcodeHash?: string | undefined;
123
+ authenticationMethods?: ("biometric_face" | "biometric_hand" | "pin" | "password")[] | undefined;
117
124
  enrollmentTokenHash?: string | undefined;
118
125
  enrollmentTokenExpiresAt?: number | undefined;
119
126
  enrolledAt?: number | undefined;
@@ -369,9 +376,9 @@ export declare const updateAttendant: import("convex/server").RegisteredMutation
369
376
  phoneNumber?: string | undefined;
370
377
  email?: string | undefined;
371
378
  name?: string | undefined;
372
- passcode?: string | undefined;
373
379
  branchId?: import("convex/values").GenericId<"branches"> | undefined;
374
380
  isActive?: boolean | undefined;
381
+ passcode?: string | undefined;
375
382
  attendantId: import("convex/values").GenericId<"attendants">;
376
383
  }, Promise<import("convex/values").GenericId<"attendants">>>;
377
384
  /**
@@ -226,6 +226,8 @@ export declare const getTransactionHistory: import("convex/server").RegisteredQu
226
226
  _id: import("convex/values").GenericId<"branches">;
227
227
  _creationTime: number;
228
228
  email?: string | undefined;
229
+ stationPinHash?: string | undefined;
230
+ requireStationLogin?: boolean | undefined;
229
231
  phoneNumber: string;
230
232
  name: string;
231
233
  createdAt: number;
@@ -44,7 +44,8 @@ declare const _default: import("convex/server").SchemaDefinition<{
44
44
  attendants: import("convex/server").TableDefinition<import("convex/values").VObject<{
45
45
  clerkUserId?: string | undefined;
46
46
  lastLoginAt?: number | undefined;
47
- passcode?: string | undefined;
47
+ passcodeHash?: string | undefined;
48
+ authenticationMethods?: ("biometric_face" | "biometric_hand" | "pin" | "password")[] | undefined;
48
49
  enrollmentTokenHash?: string | undefined;
49
50
  enrollmentTokenExpiresAt?: number | undefined;
50
51
  enrolledAt?: number | undefined;
@@ -77,7 +78,8 @@ declare const _default: import("convex/server").SchemaDefinition<{
77
78
  email: import("convex/values").VString<string, "required">;
78
79
  phoneNumber: import("convex/values").VString<string, "required">;
79
80
  clerkUserId: import("convex/values").VString<string | undefined, "optional">;
80
- passcode: import("convex/values").VString<string | undefined, "optional">;
81
+ passcodeHash: import("convex/values").VString<string | undefined, "optional">;
82
+ authenticationMethods: import("convex/values").VArray<("biometric_face" | "biometric_hand" | "pin" | "password")[] | undefined, import("convex/values").VUnion<"biometric_face" | "biometric_hand" | "pin" | "password", [import("convex/values").VLiteral<"biometric_face", "required">, import("convex/values").VLiteral<"biometric_hand", "required">, import("convex/values").VLiteral<"pin", "required">, import("convex/values").VLiteral<"password", "required">], "required", never>, "optional">;
81
83
  branchId: import("convex/values").VId<import("convex/values").GenericId<"branches">, "required">;
82
84
  isActive: import("convex/values").VBoolean<boolean, "required">;
83
85
  enrollmentStatus: import("convex/values").VUnion<"active" | "suspended" | "invited" | "enrolling" | "locked", [import("convex/values").VLiteral<"invited", "required">, import("convex/values").VLiteral<"enrolling", "required">, import("convex/values").VLiteral<"active", "required">, import("convex/values").VLiteral<"suspended", "required">, import("convex/values").VLiteral<"locked", "required">], "required", never>;
@@ -110,7 +112,7 @@ declare const _default: import("convex/server").SchemaDefinition<{
110
112
  createdBy: import("convex/values").VId<import("convex/values").GenericId<"admins">, "required">;
111
113
  lastLoginAt: import("convex/values").VFloat64<number | undefined, "optional">;
112
114
  isDeleted: import("convex/values").VBoolean<boolean, "required">;
113
- }, "required", "phoneNumber" | "email" | "name" | "clerkUserId" | "createdAt" | "lastLoginAt" | "isDeleted" | "passcode" | "branchId" | "isActive" | "enrollmentStatus" | "enrollmentTokenHash" | "enrollmentTokenExpiresAt" | "enrolledAt" | "enrolledBy" | "biometricTemplateHash" | "biometricDataEncrypted" | "biometricCaptureMetadata" | "lastVerificationAt" | "lastVerificationSuccess" | "consecutiveFailures" | "verificationTimeoutAt" | "createdBy" | "biometricCaptureMetadata.captureType" | "biometricCaptureMetadata.anglesCaptured" | "biometricCaptureMetadata.captureQuality" | "biometricCaptureMetadata.livenessPassed" | "biometricCaptureMetadata.deviceInfo" | "biometricCaptureMetadata.captureTimestamp">, {
115
+ }, "required", "phoneNumber" | "email" | "name" | "clerkUserId" | "createdAt" | "lastLoginAt" | "isDeleted" | "passcodeHash" | "authenticationMethods" | "branchId" | "isActive" | "enrollmentStatus" | "enrollmentTokenHash" | "enrollmentTokenExpiresAt" | "enrolledAt" | "enrolledBy" | "biometricTemplateHash" | "biometricDataEncrypted" | "biometricCaptureMetadata" | "lastVerificationAt" | "lastVerificationSuccess" | "consecutiveFailures" | "verificationTimeoutAt" | "createdBy" | "biometricCaptureMetadata.captureType" | "biometricCaptureMetadata.anglesCaptured" | "biometricCaptureMetadata.captureQuality" | "biometricCaptureMetadata.livenessPassed" | "biometricCaptureMetadata.deviceInfo" | "biometricCaptureMetadata.captureTimestamp">, {
114
116
  by_branch: ["branchId", "_creationTime"];
115
117
  by_email: ["email", "_creationTime"];
116
118
  by_phone: ["phoneNumber", "_creationTime"];
@@ -140,6 +142,8 @@ declare const _default: import("convex/server").SchemaDefinition<{
140
142
  }, {}, {}>;
141
143
  branches: import("convex/server").TableDefinition<import("convex/values").VObject<{
142
144
  email?: string | undefined;
145
+ stationPinHash?: string | undefined;
146
+ requireStationLogin?: boolean | undefined;
143
147
  phoneNumber: string;
144
148
  name: string;
145
149
  createdAt: number;
@@ -162,11 +166,13 @@ declare const _default: import("convex/server").SchemaDefinition<{
162
166
  email: import("convex/values").VString<string | undefined, "optional">;
163
167
  pricingPerKg: import("convex/values").VFloat64<number, "required">;
164
168
  deliveryFee: import("convex/values").VFloat64<number, "required">;
169
+ stationPinHash: import("convex/values").VString<string | undefined, "optional">;
170
+ requireStationLogin: import("convex/values").VBoolean<boolean | undefined, "optional">;
165
171
  isActive: import("convex/values").VBoolean<boolean, "required">;
166
172
  createdAt: import("convex/values").VFloat64<number, "required">;
167
173
  createdBy: import("convex/values").VId<import("convex/values").GenericId<"admins">, "required">;
168
174
  isDeleted: import("convex/values").VBoolean<boolean, "required">;
169
- }, "required", "phoneNumber" | "email" | "name" | "createdAt" | "isDeleted" | "isActive" | "createdBy" | "code" | "address" | "city" | "country" | "pricingPerKg" | "deliveryFee">, {
175
+ }, "required", "phoneNumber" | "email" | "name" | "createdAt" | "isDeleted" | "isActive" | "createdBy" | "code" | "address" | "city" | "country" | "pricingPerKg" | "deliveryFee" | "stationPinHash" | "requireStationLogin">, {
170
176
  by_city: ["city", "_creationTime"];
171
177
  by_active: ["isActive", "_creationTime"];
172
178
  by_code: ["code", "_creationTime"];
@@ -404,6 +410,7 @@ declare const _default: import("convex/server").SchemaDefinition<{
404
410
  branchId?: import("convex/values").GenericId<"branches"> | undefined;
405
411
  deviceId?: string | undefined;
406
412
  entityId?: string | undefined;
413
+ attendanceId?: import("convex/values").GenericId<"attendanceLogs"> | undefined;
407
414
  ipAddress?: string | undefined;
408
415
  details?: string | undefined;
409
416
  oldValue?: string | undefined;
@@ -421,6 +428,7 @@ declare const _default: import("convex/server").SchemaDefinition<{
421
428
  action: import("convex/values").VString<string, "required">;
422
429
  entityType: import("convex/values").VString<string, "required">;
423
430
  entityId: import("convex/values").VString<string | undefined, "optional">;
431
+ attendanceId: import("convex/values").VId<import("convex/values").GenericId<"attendanceLogs"> | undefined, "optional">;
424
432
  branchId: import("convex/values").VId<import("convex/values").GenericId<"branches"> | undefined, "optional">;
425
433
  deviceId: import("convex/values").VString<string | undefined, "optional">;
426
434
  ipAddress: import("convex/values").VString<string | undefined, "optional">;
@@ -428,12 +436,13 @@ declare const _default: import("convex/server").SchemaDefinition<{
428
436
  oldValue: import("convex/values").VString<string | undefined, "optional">;
429
437
  newValue: import("convex/values").VString<string | undefined, "optional">;
430
438
  timestamp: import("convex/values").VFloat64<number, "required">;
431
- }, "required", "branchId" | "deviceId" | "actorId" | "actorType" | "actorRole" | "action" | "entityType" | "entityId" | "ipAddress" | "details" | "oldValue" | "newValue" | "timestamp">, {
439
+ }, "required", "branchId" | "deviceId" | "actorId" | "actorType" | "actorRole" | "action" | "entityType" | "entityId" | "attendanceId" | "ipAddress" | "details" | "oldValue" | "newValue" | "timestamp">, {
432
440
  by_actor: ["actorId", "actorType", "_creationTime"];
433
441
  by_action: ["action", "_creationTime"];
434
442
  by_entity: ["entityType", "entityId", "_creationTime"];
435
443
  by_timestamp: ["timestamp", "_creationTime"];
436
444
  by_branch: ["branchId", "_creationTime"];
445
+ by_attendance: ["attendanceId", "_creationTime"];
437
446
  }, {}, {}>;
438
447
  vouchers: import("convex/server").TableDefinition<import("convex/values").VObject<{
439
448
  name?: string | undefined;
@@ -640,6 +649,41 @@ declare const _default: import("convex/server").SchemaDefinition<{
640
649
  by_status: ["status", "_creationTime"];
641
650
  by_challenge_hash: ["challengeHash", "_creationTime"];
642
651
  }, {}, {}>;
652
+ stationSessions: import("convex/server").TableDefinition<import("convex/values").VObject<{
653
+ deviceInfo?: string | undefined;
654
+ ipAddress?: string | undefined;
655
+ loggedInBy?: import("convex/values").GenericId<"attendants"> | undefined;
656
+ stationPinUsed?: boolean | undefined;
657
+ loggedOutAt?: number | undefined;
658
+ loggedOutBy?: import("convex/values").GenericId<"attendants"> | undefined;
659
+ isDeleted: boolean;
660
+ branchId: import("convex/values").GenericId<"branches">;
661
+ isActive: boolean;
662
+ deviceId: string;
663
+ expiresAt: number;
664
+ sessionTokenHash: string;
665
+ loggedInAt: number;
666
+ }, {
667
+ branchId: import("convex/values").VId<import("convex/values").GenericId<"branches">, "required">;
668
+ deviceId: import("convex/values").VString<string, "required">;
669
+ sessionTokenHash: import("convex/values").VString<string, "required">;
670
+ deviceInfo: import("convex/values").VString<string | undefined, "optional">;
671
+ ipAddress: import("convex/values").VString<string | undefined, "optional">;
672
+ loggedInBy: import("convex/values").VId<import("convex/values").GenericId<"attendants"> | undefined, "optional">;
673
+ loggedInAt: import("convex/values").VFloat64<number, "required">;
674
+ stationPinUsed: import("convex/values").VBoolean<boolean | undefined, "optional">;
675
+ expiresAt: import("convex/values").VFloat64<number, "required">;
676
+ isActive: import("convex/values").VBoolean<boolean, "required">;
677
+ loggedOutAt: import("convex/values").VFloat64<number | undefined, "optional">;
678
+ loggedOutBy: import("convex/values").VId<import("convex/values").GenericId<"attendants"> | undefined, "optional">;
679
+ isDeleted: import("convex/values").VBoolean<boolean, "required">;
680
+ }, "required", "isDeleted" | "branchId" | "isActive" | "deviceInfo" | "deviceId" | "ipAddress" | "expiresAt" | "sessionTokenHash" | "loggedInBy" | "loggedInAt" | "stationPinUsed" | "loggedOutAt" | "loggedOutBy">, {
681
+ by_branch: ["branchId", "_creationTime"];
682
+ by_device: ["deviceId", "_creationTime"];
683
+ by_session_token: ["sessionTokenHash", "_creationTime"];
684
+ by_active: ["isActive", "_creationTime"];
685
+ by_branch_device: ["branchId", "deviceId", "_creationTime"];
686
+ }, {}, {}>;
643
687
  attendantSessions: import("convex/server").TableDefinition<import("convex/values").VObject<{
644
688
  deviceInfo?: string | undefined;
645
689
  ipAddress?: string | undefined;
@@ -842,6 +886,45 @@ declare const _default: import("convex/server").SchemaDefinition<{
842
886
  by_verified_at: ["verifiedAt", "_creationTime"];
843
887
  by_success: ["success", "_creationTime"];
844
888
  }, {}, {}>;
889
+ actionLogs: import("convex/server").TableDefinition<import("convex/values").VObject<{
890
+ amount?: number | undefined;
891
+ completedAt?: number | undefined;
892
+ entityType?: string | undefined;
893
+ entityId?: import("convex/values").GenericId<"orders"> | undefined;
894
+ errorMessage?: string | undefined;
895
+ actionData?: string | undefined;
896
+ verificationMethod?: "biometric_face" | "biometric_hand" | "pin" | "password" | undefined;
897
+ verificationId?: import("convex/values").GenericId<"biometricVerifications"> | undefined;
898
+ createdAt: number;
899
+ branchId: import("convex/values").GenericId<"branches">;
900
+ attendantId: import("convex/values").GenericId<"attendants">;
901
+ attendanceId: import("convex/values").GenericId<"attendanceLogs">;
902
+ actionType: string;
903
+ actionStatus: "pending" | "completed" | "cancelled" | "failed";
904
+ }, {
905
+ attendanceId: import("convex/values").VId<import("convex/values").GenericId<"attendanceLogs">, "required">;
906
+ attendantId: import("convex/values").VId<import("convex/values").GenericId<"attendants">, "required">;
907
+ branchId: import("convex/values").VId<import("convex/values").GenericId<"branches">, "required">;
908
+ actionType: import("convex/values").VString<string, "required">;
909
+ actionStatus: import("convex/values").VUnion<"pending" | "completed" | "cancelled" | "failed", [import("convex/values").VLiteral<"pending", "required">, import("convex/values").VLiteral<"completed", "required">, import("convex/values").VLiteral<"failed", "required">, import("convex/values").VLiteral<"cancelled", "required">], "required", never>;
910
+ entityType: import("convex/values").VString<string | undefined, "optional">;
911
+ entityId: import("convex/values").VId<import("convex/values").GenericId<"orders"> | undefined, "optional">;
912
+ actionData: import("convex/values").VString<string | undefined, "optional">;
913
+ errorMessage: import("convex/values").VString<string | undefined, "optional">;
914
+ amount: import("convex/values").VFloat64<number | undefined, "optional">;
915
+ verificationMethod: import("convex/values").VUnion<"biometric_face" | "biometric_hand" | "pin" | "password" | undefined, [import("convex/values").VLiteral<"biometric_face", "required">, import("convex/values").VLiteral<"biometric_hand", "required">, import("convex/values").VLiteral<"pin", "required">, import("convex/values").VLiteral<"password", "required">], "optional", never>;
916
+ verificationId: import("convex/values").VId<import("convex/values").GenericId<"biometricVerifications"> | undefined, "optional">;
917
+ createdAt: import("convex/values").VFloat64<number, "required">;
918
+ completedAt: import("convex/values").VFloat64<number | undefined, "optional">;
919
+ }, "required", "createdAt" | "branchId" | "amount" | "completedAt" | "attendantId" | "entityType" | "entityId" | "attendanceId" | "errorMessage" | "actionType" | "actionStatus" | "actionData" | "verificationMethod" | "verificationId">, {
920
+ by_attendance: ["attendanceId", "_creationTime"];
921
+ by_attendant: ["attendantId", "_creationTime"];
922
+ by_branch: ["branchId", "_creationTime"];
923
+ by_action_type: ["actionType", "_creationTime"];
924
+ by_status: ["actionStatus", "_creationTime"];
925
+ by_created_at: ["createdAt", "_creationTime"];
926
+ by_attendance_created: ["attendanceId", "createdAt", "_creationTime"];
927
+ }, {}, {}>;
845
928
  }, true>;
846
929
  export default _default;
847
930
  //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Station/Branch Login Functions
3
+ *
4
+ * Handles station (branch) login and session management.
5
+ * Station login is separate from attendant authentication.
6
+ */
7
+ /**
8
+ * Verify branch code (public - no auth required)
9
+ * Returns branch info without sensitive data
10
+ */
11
+ export declare const verifyBranchCode: import("convex/server").RegisteredQuery<"public", {
12
+ code: string;
13
+ }, Promise<{
14
+ _id: import("convex/values").GenericId<"branches">;
15
+ name: string;
16
+ code: string;
17
+ address: string;
18
+ city: string;
19
+ country: string;
20
+ phoneNumber: string;
21
+ email: string | undefined;
22
+ requireStationLogin: boolean;
23
+ hasStationPin: boolean;
24
+ } | null>>;
25
+ /**
26
+ * Login to station (branch) - First step
27
+ * Creates station session if PIN is provided and valid, or if PIN not required
28
+ */
29
+ export declare const loginStation: import("convex/server").RegisteredMutation<"public", {
30
+ deviceInfo?: string | undefined;
31
+ stationPin?: string | undefined;
32
+ branchId: import("convex/values").GenericId<"branches">;
33
+ deviceId: string;
34
+ }, Promise<{
35
+ success: boolean;
36
+ branchId: import("convex/values").GenericId<"branches">;
37
+ branchName: string;
38
+ stationToken: string;
39
+ expiresAt: number;
40
+ sessionId: import("convex/values").GenericId<"stationSessions">;
41
+ }>>;
42
+ /**
43
+ * Verify station session token
44
+ */
45
+ export declare const verifyStationSession: import("convex/server").RegisteredQuery<"public", {
46
+ stationToken: string;
47
+ }, Promise<{
48
+ valid: boolean;
49
+ branchId: import("convex/values").GenericId<"branches">;
50
+ branchName: string | undefined;
51
+ deviceId: string;
52
+ expiresAt: number;
53
+ loggedInAt: number;
54
+ } | null>>;
55
+ /**
56
+ * Logout from station
57
+ */
58
+ export declare const logoutStation: import("convex/server").RegisteredMutation<"public", {
59
+ stationToken: string;
60
+ }, Promise<{
61
+ success: boolean;
62
+ }>>;
63
+ /**
64
+ * Get active station session for device
65
+ */
66
+ export declare const getActiveStationSession: import("convex/server").RegisteredQuery<"public", {
67
+ branchId: import("convex/values").GenericId<"branches">;
68
+ deviceId: string;
69
+ }, Promise<{
70
+ _id: import("convex/values").GenericId<"stationSessions">;
71
+ branchId: import("convex/values").GenericId<"branches">;
72
+ branchName: string | undefined;
73
+ deviceId: string;
74
+ loggedInAt: number;
75
+ expiresAt: number;
76
+ } | null>>;
77
+ //# sourceMappingURL=stations.d.ts.map
@@ -7,9 +7,9 @@
7
7
  * Get all vouchers (admin only)
8
8
  */
9
9
  export declare const getAll: import("convex/server").RegisteredQuery<"public", {
10
- includeInactive?: boolean | undefined;
11
10
  numItems?: number | undefined;
12
11
  cursor?: string | undefined;
12
+ includeInactive?: boolean | undefined;
13
13
  }, Promise<{
14
14
  page: {
15
15
  _id: import("convex/values").GenericId<"vouchers">;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devlider001/washlab-backend",
3
- "version": "1.0.9",
3
+ "version": "1.1.0",
4
4
  "description": "Washlab backend - Convex API package for Lider Technology Ltd",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",