@devlider001/washlab-backend 1.0.4 → 1.0.6
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.
- package/convex/_generated/api.d.ts +2 -0
- package/convex/admin.d.ts +1 -1
- package/convex/audit.d.ts +39 -0
- package/convex/customers.d.ts +12 -5
- package/convex/lib/auth.d.ts +24 -1
- package/convex/notifications.d.ts +170 -0
- package/convex/schema.d.ts +53 -2
- package/dist/convex/admin.d.ts +377 -0
- package/dist/convex/admin.d.ts.map +1 -0
- package/dist/convex/admin.js +959 -0
- package/dist/convex/admin.js.map +1 -0
- package/dist/convex/analytics.d.ts +87 -0
- package/dist/convex/analytics.d.ts.map +1 -0
- package/dist/convex/analytics.js +361 -0
- package/dist/convex/analytics.js.map +1 -0
- package/dist/convex/attendants.d.ts +140 -0
- package/dist/convex/attendants.d.ts.map +1 -0
- package/dist/convex/attendants.js +337 -0
- package/dist/convex/attendants.js.map +1 -0
- package/dist/convex/audit.d.ts +158 -0
- package/dist/convex/audit.d.ts.map +1 -0
- package/dist/convex/audit.js +184 -0
- package/dist/convex/audit.js.map +1 -0
- package/dist/convex/clerk.d.ts +53 -0
- package/dist/convex/clerk.d.ts.map +1 -0
- package/dist/convex/clerk.js +316 -0
- package/dist/convex/clerk.js.map +1 -0
- package/dist/convex/customers.d.ts +224 -0
- package/dist/convex/customers.d.ts.map +1 -0
- package/dist/convex/customers.js +504 -0
- package/dist/convex/customers.js.map +1 -0
- package/dist/convex/http.d.ts +3 -0
- package/dist/convex/http.d.ts.map +1 -0
- package/dist/convex/http.js +115 -0
- package/dist/convex/http.js.map +1 -0
- package/dist/convex/lib/audit.d.ts +36 -0
- package/dist/convex/lib/audit.d.ts.map +1 -0
- package/dist/convex/lib/audit.js +59 -0
- package/dist/convex/lib/audit.js.map +1 -0
- package/dist/convex/lib/auth.d.ts +96 -0
- package/dist/convex/lib/auth.d.ts.map +1 -0
- package/dist/convex/lib/auth.js +94 -0
- package/dist/convex/lib/auth.js.map +1 -0
- package/dist/convex/lib/utils.d.ts +38 -0
- package/dist/convex/lib/utils.d.ts.map +1 -0
- package/dist/convex/lib/utils.js +71 -0
- package/dist/convex/lib/utils.js.map +1 -0
- package/dist/convex/loyalty.d.ts +82 -0
- package/dist/convex/loyalty.d.ts.map +1 -0
- package/dist/convex/loyalty.js +286 -0
- package/dist/convex/loyalty.js.map +1 -0
- package/dist/convex/orders.d.ts +326 -0
- package/dist/convex/orders.d.ts.map +1 -0
- package/dist/convex/orders.js +570 -0
- package/dist/convex/orders.js.map +1 -0
- package/dist/convex/payments.d.ts +134 -0
- package/dist/convex/payments.d.ts.map +1 -0
- package/dist/convex/payments.js +360 -0
- package/dist/convex/payments.js.map +1 -0
- package/dist/convex/resources.d.ts +119 -0
- package/dist/convex/resources.d.ts.map +1 -0
- package/dist/convex/resources.js +283 -0
- package/dist/convex/resources.js.map +1 -0
- package/dist/convex/schema.d.ts +450 -0
- package/dist/convex/schema.d.ts.map +1 -0
- package/dist/convex/schema.js +347 -0
- package/dist/convex/schema.js.map +1 -0
- package/dist/convex/vouchers.d.ts +187 -0
- package/dist/convex/vouchers.d.ts.map +1 -0
- package/dist/convex/vouchers.js +464 -0
- package/dist/convex/vouchers.js.map +1 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +9 -0
- package/dist/src/index.js.map +1 -0
- package/package.json +5 -3
- package/convex/_generated/api.js +0 -23
- package/convex/_generated/server.js +0 -93
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attendant Functions
|
|
3
|
+
*
|
|
4
|
+
* Handles attendant authentication, attendance clock-in/out, and profile queries.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Get attendants by branch (admin/attendant view)
|
|
8
|
+
*/
|
|
9
|
+
export declare const getByBranch: import("convex/server").RegisteredQuery<"public", {
|
|
10
|
+
branchId: import("convex/values").GenericId<"branches">;
|
|
11
|
+
}, Promise<{
|
|
12
|
+
_id: import("convex/values").GenericId<"attendants">;
|
|
13
|
+
_creationTime: number;
|
|
14
|
+
lastLoginAt?: number | undefined;
|
|
15
|
+
passcode?: string | undefined;
|
|
16
|
+
phoneNumber: string;
|
|
17
|
+
email: string;
|
|
18
|
+
name: string;
|
|
19
|
+
clerkUserId: string;
|
|
20
|
+
createdAt: number;
|
|
21
|
+
isDeleted: boolean;
|
|
22
|
+
branchId: import("convex/values").GenericId<"branches">;
|
|
23
|
+
isActive: boolean;
|
|
24
|
+
}[]>>;
|
|
25
|
+
/**
|
|
26
|
+
* Get current attendant profile (from authenticated Clerk session)
|
|
27
|
+
*/
|
|
28
|
+
export declare const getCurrentUser: import("convex/server").RegisteredQuery<"public", {}, Promise<{
|
|
29
|
+
branch: {
|
|
30
|
+
_id: import("convex/values").GenericId<"branches">;
|
|
31
|
+
name: string;
|
|
32
|
+
address: string;
|
|
33
|
+
} | null;
|
|
34
|
+
_id: import("convex/values").GenericId<"attendants">;
|
|
35
|
+
_creationTime: number;
|
|
36
|
+
lastLoginAt?: number | undefined;
|
|
37
|
+
passcode?: string | undefined;
|
|
38
|
+
phoneNumber: string;
|
|
39
|
+
email: string;
|
|
40
|
+
name: string;
|
|
41
|
+
clerkUserId: string;
|
|
42
|
+
createdAt: number;
|
|
43
|
+
isDeleted: boolean;
|
|
44
|
+
branchId: import("convex/values").GenericId<"branches">;
|
|
45
|
+
isActive: boolean;
|
|
46
|
+
}>>;
|
|
47
|
+
/**
|
|
48
|
+
* Get current active attendance session
|
|
49
|
+
*/
|
|
50
|
+
export declare const getActiveSession: import("convex/server").RegisteredQuery<"public", {}, Promise<{
|
|
51
|
+
_id: import("convex/values").GenericId<"attendanceLogs">;
|
|
52
|
+
_creationTime: number;
|
|
53
|
+
clockOutAt?: number | undefined;
|
|
54
|
+
deviceId?: string | undefined;
|
|
55
|
+
deviceInfo?: string | undefined;
|
|
56
|
+
isDeleted: boolean;
|
|
57
|
+
branchId: import("convex/values").GenericId<"branches">;
|
|
58
|
+
isActive: boolean;
|
|
59
|
+
attendantId: import("convex/values").GenericId<"attendants">;
|
|
60
|
+
clockInAt: number;
|
|
61
|
+
} | null>>;
|
|
62
|
+
/**
|
|
63
|
+
* Get attendance history - Paginated
|
|
64
|
+
* Supports usePaginatedQuery for infinite scroll
|
|
65
|
+
*/
|
|
66
|
+
export declare const getAttendanceHistory: import("convex/server").RegisteredQuery<"public", {
|
|
67
|
+
branchId?: import("convex/values").GenericId<"branches"> | undefined;
|
|
68
|
+
cursor?: string | undefined;
|
|
69
|
+
numItems?: number | undefined;
|
|
70
|
+
}, Promise<{
|
|
71
|
+
page: {
|
|
72
|
+
_id: import("convex/values").GenericId<"attendanceLogs">;
|
|
73
|
+
_creationTime: number;
|
|
74
|
+
clockOutAt?: number | undefined;
|
|
75
|
+
deviceId?: string | undefined;
|
|
76
|
+
deviceInfo?: string | undefined;
|
|
77
|
+
isDeleted: boolean;
|
|
78
|
+
branchId: import("convex/values").GenericId<"branches">;
|
|
79
|
+
isActive: boolean;
|
|
80
|
+
attendantId: import("convex/values").GenericId<"attendants">;
|
|
81
|
+
clockInAt: number;
|
|
82
|
+
}[];
|
|
83
|
+
isDone: boolean;
|
|
84
|
+
continueCursor: string;
|
|
85
|
+
}>>;
|
|
86
|
+
/**
|
|
87
|
+
* Clock in attendant (start attendance session)
|
|
88
|
+
*/
|
|
89
|
+
export declare const clockIn: import("convex/server").RegisteredMutation<"public", {
|
|
90
|
+
deviceId?: string | undefined;
|
|
91
|
+
deviceInfo?: string | undefined;
|
|
92
|
+
branchId: import("convex/values").GenericId<"branches">;
|
|
93
|
+
}, Promise<import("convex/values").GenericId<"attendanceLogs">>>;
|
|
94
|
+
/**
|
|
95
|
+
* Clock out attendant (end attendance session)
|
|
96
|
+
*/
|
|
97
|
+
export declare const clockOut: import("convex/server").RegisteredMutation<"public", {
|
|
98
|
+
attendanceLogId?: import("convex/values").GenericId<"attendanceLogs"> | undefined;
|
|
99
|
+
}, Promise<import("convex/values").GenericId<"attendanceLogs">>>;
|
|
100
|
+
/**
|
|
101
|
+
* Get attendance statistics for a branch
|
|
102
|
+
*/
|
|
103
|
+
export declare const getBranchAttendanceStats: import("convex/server").RegisteredQuery<"public", {
|
|
104
|
+
date?: string | undefined;
|
|
105
|
+
branchId: import("convex/values").GenericId<"branches">;
|
|
106
|
+
}, Promise<{
|
|
107
|
+
date: string;
|
|
108
|
+
branchId: import("convex/values").GenericId<"branches">;
|
|
109
|
+
clockIns: number;
|
|
110
|
+
clockOuts: number;
|
|
111
|
+
activeSessions: number;
|
|
112
|
+
uniqueAttendants: number;
|
|
113
|
+
totalHoursWorked: number;
|
|
114
|
+
averageHoursPerAttendant: number;
|
|
115
|
+
}>>;
|
|
116
|
+
/**
|
|
117
|
+
* Get attendance summary for date range
|
|
118
|
+
*/
|
|
119
|
+
export declare const getAttendanceSummary: import("convex/server").RegisteredQuery<"public", {
|
|
120
|
+
branchId?: import("convex/values").GenericId<"branches"> | undefined;
|
|
121
|
+
startDate?: number | undefined;
|
|
122
|
+
endDate?: number | undefined;
|
|
123
|
+
}, Promise<{
|
|
124
|
+
totalSessions: number;
|
|
125
|
+
completedSessions: number;
|
|
126
|
+
activeSessions: number;
|
|
127
|
+
uniqueAttendants: number;
|
|
128
|
+
totalHoursWorked: number;
|
|
129
|
+
averageHoursPerSession: number;
|
|
130
|
+
attendanceByDay: Record<string, {
|
|
131
|
+
clockIns: number;
|
|
132
|
+
clockOuts: number;
|
|
133
|
+
hours: number;
|
|
134
|
+
}>;
|
|
135
|
+
dateRange: {
|
|
136
|
+
start: number;
|
|
137
|
+
end: number;
|
|
138
|
+
};
|
|
139
|
+
}>>;
|
|
140
|
+
//# sourceMappingURL=attendants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attendants.d.ts","sourceRoot":"","sources":["../../convex/attendants.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;KAsBtB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;GAiBzB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;UAa3B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;GAgC/B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,OAAO;;;;gEAsDlB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,QAAQ;;gEAuDnB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;GAiEnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;kBA0DO,MAAM;mBAAa,MAAM;eAAS,MAAM;;;;;;GAkB9E,CAAC"}
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { query, mutation } from "./_generated/server";
|
|
2
|
+
import { v } from "convex/values";
|
|
3
|
+
import { getCurrentAttendant, verifyAttendantBranch, getCurrentAdmin } from "./lib/auth";
|
|
4
|
+
import { createAuditLog } from "./lib/audit";
|
|
5
|
+
import { getCurrentTimestamp } from "./lib/utils";
|
|
6
|
+
/**
|
|
7
|
+
* Attendant Functions
|
|
8
|
+
*
|
|
9
|
+
* Handles attendant authentication, attendance clock-in/out, and profile queries.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Get attendants by branch (admin/attendant view)
|
|
13
|
+
*/
|
|
14
|
+
export const getByBranch = query({
|
|
15
|
+
args: {
|
|
16
|
+
branchId: v.id("branches"),
|
|
17
|
+
},
|
|
18
|
+
handler: async (ctx, args) => {
|
|
19
|
+
// Allow both attendants and admins to view
|
|
20
|
+
try {
|
|
21
|
+
const attendant = await getCurrentAttendant(ctx);
|
|
22
|
+
await verifyAttendantBranch(ctx, attendant._id, args.branchId);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// Try admin access
|
|
26
|
+
const { getCurrentAdmin } = await import("./lib/auth");
|
|
27
|
+
await getCurrentAdmin(ctx);
|
|
28
|
+
}
|
|
29
|
+
const attendants = await ctx.db
|
|
30
|
+
.query("attendants")
|
|
31
|
+
.withIndex("by_branch", (q) => q.eq("branchId", args.branchId))
|
|
32
|
+
.collect();
|
|
33
|
+
return attendants.filter((a) => !a.isDeleted);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* Get current attendant profile (from authenticated Clerk session)
|
|
38
|
+
*/
|
|
39
|
+
export const getCurrentUser = query({
|
|
40
|
+
args: {},
|
|
41
|
+
handler: async (ctx) => {
|
|
42
|
+
const attendant = await getCurrentAttendant(ctx);
|
|
43
|
+
// Get branch info
|
|
44
|
+
const branch = await ctx.db.get(attendant.branchId);
|
|
45
|
+
return {
|
|
46
|
+
...attendant,
|
|
47
|
+
branch: branch ? {
|
|
48
|
+
_id: branch._id,
|
|
49
|
+
name: branch.name,
|
|
50
|
+
address: branch.address,
|
|
51
|
+
} : null,
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
/**
|
|
56
|
+
* Get current active attendance session
|
|
57
|
+
*/
|
|
58
|
+
export const getActiveSession = query({
|
|
59
|
+
args: {},
|
|
60
|
+
handler: async (ctx) => {
|
|
61
|
+
const attendant = await getCurrentAttendant(ctx);
|
|
62
|
+
const session = await ctx.db
|
|
63
|
+
.query("attendanceLogs")
|
|
64
|
+
.withIndex("by_attendant", (q) => q.eq("attendantId", attendant._id))
|
|
65
|
+
.filter((q) => q.eq(q.field("isActive"), true))
|
|
66
|
+
.first();
|
|
67
|
+
return session;
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
/**
|
|
71
|
+
* Get attendance history - Paginated
|
|
72
|
+
* Supports usePaginatedQuery for infinite scroll
|
|
73
|
+
*/
|
|
74
|
+
export const getAttendanceHistory = query({
|
|
75
|
+
args: {
|
|
76
|
+
branchId: v.optional(v.id("branches")),
|
|
77
|
+
cursor: v.optional(v.string()),
|
|
78
|
+
numItems: v.optional(v.number()),
|
|
79
|
+
},
|
|
80
|
+
handler: async (ctx, args) => {
|
|
81
|
+
const attendant = await getCurrentAttendant(ctx);
|
|
82
|
+
const numItems = args.numItems ?? 20;
|
|
83
|
+
const result = await ctx.db
|
|
84
|
+
.query("attendanceLogs")
|
|
85
|
+
.withIndex("by_attendant", (q) => q.eq("attendantId", attendant._id))
|
|
86
|
+
.order("desc")
|
|
87
|
+
.filter((q) => q.eq(q.field("isDeleted"), false))
|
|
88
|
+
.paginate({
|
|
89
|
+
cursor: args.cursor ?? null,
|
|
90
|
+
numItems,
|
|
91
|
+
});
|
|
92
|
+
let filtered = result.page;
|
|
93
|
+
if (args.branchId) {
|
|
94
|
+
filtered = filtered.filter((s) => s.branchId === args.branchId);
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
page: filtered,
|
|
98
|
+
isDone: result.isDone,
|
|
99
|
+
continueCursor: result.continueCursor,
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
/**
|
|
104
|
+
* Clock in attendant (start attendance session)
|
|
105
|
+
*/
|
|
106
|
+
export const clockIn = mutation({
|
|
107
|
+
args: {
|
|
108
|
+
branchId: v.id("branches"),
|
|
109
|
+
deviceId: v.optional(v.string()),
|
|
110
|
+
deviceInfo: v.optional(v.string()),
|
|
111
|
+
},
|
|
112
|
+
handler: async (ctx, args) => {
|
|
113
|
+
const attendant = await getCurrentAttendant(ctx);
|
|
114
|
+
await verifyAttendantBranch(ctx, attendant._id, args.branchId);
|
|
115
|
+
// Check if attendant already has active session
|
|
116
|
+
const activeSession = await ctx.db
|
|
117
|
+
.query("attendanceLogs")
|
|
118
|
+
.withIndex("by_attendant", (q) => q.eq("attendantId", attendant._id))
|
|
119
|
+
.filter((q) => q.eq(q.field("isActive"), true))
|
|
120
|
+
.first();
|
|
121
|
+
if (activeSession) {
|
|
122
|
+
throw new Error("Attendant already has an active session. Please clock out first.");
|
|
123
|
+
}
|
|
124
|
+
const now = getCurrentTimestamp();
|
|
125
|
+
// Create attendance log entry
|
|
126
|
+
const attendanceLogId = await ctx.db.insert("attendanceLogs", {
|
|
127
|
+
attendantId: attendant._id,
|
|
128
|
+
branchId: args.branchId,
|
|
129
|
+
clockInAt: now,
|
|
130
|
+
clockOutAt: undefined,
|
|
131
|
+
deviceId: args.deviceId,
|
|
132
|
+
deviceInfo: args.deviceInfo,
|
|
133
|
+
isActive: true,
|
|
134
|
+
isDeleted: false,
|
|
135
|
+
});
|
|
136
|
+
// Update attendant last login
|
|
137
|
+
await ctx.db.patch(attendant._id, {
|
|
138
|
+
lastLoginAt: now,
|
|
139
|
+
});
|
|
140
|
+
await createAuditLog({
|
|
141
|
+
ctx,
|
|
142
|
+
actorId: attendant._id,
|
|
143
|
+
actorType: "attendant",
|
|
144
|
+
actorRole: "attendant",
|
|
145
|
+
action: "attendance.clocked_in",
|
|
146
|
+
entityType: "attendanceLog",
|
|
147
|
+
entityId: attendanceLogId,
|
|
148
|
+
branchId: args.branchId,
|
|
149
|
+
deviceId: args.deviceId,
|
|
150
|
+
});
|
|
151
|
+
return attendanceLogId;
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
/**
|
|
155
|
+
* Clock out attendant (end attendance session)
|
|
156
|
+
*/
|
|
157
|
+
export const clockOut = mutation({
|
|
158
|
+
args: {
|
|
159
|
+
attendanceLogId: v.optional(v.id("attendanceLogs")), // Optional - if not provided, finds active session
|
|
160
|
+
},
|
|
161
|
+
handler: async (ctx, args) => {
|
|
162
|
+
const attendant = await getCurrentAttendant(ctx);
|
|
163
|
+
let attendanceLog;
|
|
164
|
+
if (args.attendanceLogId) {
|
|
165
|
+
attendanceLog = await ctx.db.get(args.attendanceLogId);
|
|
166
|
+
if (!attendanceLog || attendanceLog.isDeleted) {
|
|
167
|
+
throw new Error("Attendance log not found");
|
|
168
|
+
}
|
|
169
|
+
if (attendanceLog.attendantId !== attendant._id) {
|
|
170
|
+
throw new Error("Attendance log does not belong to attendant");
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
// Find active session
|
|
175
|
+
attendanceLog = await ctx.db
|
|
176
|
+
.query("attendanceLogs")
|
|
177
|
+
.withIndex("by_attendant", (q) => q.eq("attendantId", attendant._id))
|
|
178
|
+
.filter((q) => q.eq(q.field("isActive"), true))
|
|
179
|
+
.first();
|
|
180
|
+
if (!attendanceLog) {
|
|
181
|
+
throw new Error("No active attendance session found");
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (!attendanceLog.isActive) {
|
|
185
|
+
throw new Error("Attendance session is not active");
|
|
186
|
+
}
|
|
187
|
+
const now = getCurrentTimestamp();
|
|
188
|
+
// Update attendance log
|
|
189
|
+
await ctx.db.patch(attendanceLog._id, {
|
|
190
|
+
clockOutAt: now,
|
|
191
|
+
isActive: false,
|
|
192
|
+
});
|
|
193
|
+
await createAuditLog({
|
|
194
|
+
ctx,
|
|
195
|
+
actorId: attendant._id,
|
|
196
|
+
actorType: "attendant",
|
|
197
|
+
actorRole: "attendant",
|
|
198
|
+
action: "attendance.clocked_out",
|
|
199
|
+
entityType: "attendanceLog",
|
|
200
|
+
entityId: attendanceLog._id,
|
|
201
|
+
branchId: attendanceLog.branchId,
|
|
202
|
+
});
|
|
203
|
+
return attendanceLog._id;
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
/**
|
|
207
|
+
* Get attendance statistics for a branch
|
|
208
|
+
*/
|
|
209
|
+
export const getBranchAttendanceStats = query({
|
|
210
|
+
args: {
|
|
211
|
+
branchId: v.id("branches"),
|
|
212
|
+
date: v.optional(v.string()), // YYYY-MM-DD, defaults to today
|
|
213
|
+
},
|
|
214
|
+
handler: async (ctx, args) => {
|
|
215
|
+
// Allow both attendants and admins
|
|
216
|
+
try {
|
|
217
|
+
const attendant = await getCurrentAttendant(ctx);
|
|
218
|
+
await verifyAttendantBranch(ctx, attendant._id, args.branchId);
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
const { getCurrentAdmin } = await import("./lib/auth");
|
|
222
|
+
await getCurrentAdmin(ctx);
|
|
223
|
+
}
|
|
224
|
+
const dateStr = args.date || new Date().toISOString().split("T")[0];
|
|
225
|
+
const dateStart = new Date(dateStr);
|
|
226
|
+
dateStart.setHours(0, 0, 0, 0);
|
|
227
|
+
const dateEnd = new Date(dateStr);
|
|
228
|
+
dateEnd.setHours(23, 59, 59, 999);
|
|
229
|
+
const startTimestamp = dateStart.getTime();
|
|
230
|
+
const endTimestamp = dateEnd.getTime();
|
|
231
|
+
// Get all attendance logs for the branch
|
|
232
|
+
const logs = await ctx.db
|
|
233
|
+
.query("attendanceLogs")
|
|
234
|
+
.withIndex("by_branch", (q) => q.eq("branchId", args.branchId))
|
|
235
|
+
.collect();
|
|
236
|
+
const dayLogs = logs.filter((l) => !l.isDeleted &&
|
|
237
|
+
l.clockInAt >= startTimestamp &&
|
|
238
|
+
l.clockInAt <= endTimestamp);
|
|
239
|
+
const activeSessions = dayLogs.filter((l) => l.isActive);
|
|
240
|
+
const clockIns = dayLogs.length;
|
|
241
|
+
const clockOuts = dayLogs.filter((l) => l.clockOutAt).length;
|
|
242
|
+
// Calculate total hours worked
|
|
243
|
+
const totalHours = dayLogs
|
|
244
|
+
.filter((l) => l.clockOutAt)
|
|
245
|
+
.reduce((sum, l) => {
|
|
246
|
+
const hours = (l.clockOutAt - l.clockInAt) / (1000 * 60 * 60);
|
|
247
|
+
return sum + hours;
|
|
248
|
+
}, 0);
|
|
249
|
+
// Get unique attendants
|
|
250
|
+
const attendantIds = new Set(dayLogs.map((l) => l.attendantId));
|
|
251
|
+
const uniqueAttendants = attendantIds.size;
|
|
252
|
+
return {
|
|
253
|
+
date: dateStr,
|
|
254
|
+
branchId: args.branchId,
|
|
255
|
+
clockIns,
|
|
256
|
+
clockOuts,
|
|
257
|
+
activeSessions: activeSessions.length,
|
|
258
|
+
uniqueAttendants,
|
|
259
|
+
totalHoursWorked: Math.round(totalHours * 100) / 100,
|
|
260
|
+
averageHoursPerAttendant: uniqueAttendants > 0
|
|
261
|
+
? Math.round((totalHours / uniqueAttendants) * 100) / 100
|
|
262
|
+
: 0,
|
|
263
|
+
};
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
/**
|
|
267
|
+
* Get attendance summary for date range
|
|
268
|
+
*/
|
|
269
|
+
export const getAttendanceSummary = query({
|
|
270
|
+
args: {
|
|
271
|
+
branchId: v.optional(v.id("branches")),
|
|
272
|
+
startDate: v.optional(v.number()),
|
|
273
|
+
endDate: v.optional(v.number()),
|
|
274
|
+
},
|
|
275
|
+
handler: async (ctx, args) => {
|
|
276
|
+
await getCurrentAdmin(ctx);
|
|
277
|
+
const now = Date.now();
|
|
278
|
+
const startDate = args.startDate || (now - 30 * 24 * 60 * 60 * 1000);
|
|
279
|
+
const endDate = args.endDate || now;
|
|
280
|
+
// Get all attendance logs
|
|
281
|
+
let logs;
|
|
282
|
+
if (args.branchId) {
|
|
283
|
+
logs = await ctx.db
|
|
284
|
+
.query("attendanceLogs")
|
|
285
|
+
.withIndex("by_branch", (q) => q.eq("branchId", args.branchId))
|
|
286
|
+
.collect();
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
logs = await ctx.db.query("attendanceLogs").collect();
|
|
290
|
+
}
|
|
291
|
+
const filtered = logs.filter((l) => !l.isDeleted &&
|
|
292
|
+
l.clockInAt >= startDate &&
|
|
293
|
+
l.clockInAt <= endDate);
|
|
294
|
+
const totalSessions = filtered.length;
|
|
295
|
+
const completedSessions = filtered.filter((l) => l.clockOutAt).length;
|
|
296
|
+
const activeSessions = filtered.filter((l) => l.isActive).length;
|
|
297
|
+
// Calculate total hours
|
|
298
|
+
const totalHours = filtered
|
|
299
|
+
.filter((l) => l.clockOutAt)
|
|
300
|
+
.reduce((sum, l) => {
|
|
301
|
+
const hours = (l.clockOutAt - l.clockInAt) / (1000 * 60 * 60);
|
|
302
|
+
return sum + hours;
|
|
303
|
+
}, 0);
|
|
304
|
+
// Get unique attendants
|
|
305
|
+
const attendantIds = new Set(filtered.map((l) => l.attendantId));
|
|
306
|
+
const uniqueAttendants = attendantIds.size;
|
|
307
|
+
// Attendance by day
|
|
308
|
+
const attendanceByDay = filtered.reduce((acc, l) => {
|
|
309
|
+
const date = new Date(l.clockInAt).toISOString().split("T")[0];
|
|
310
|
+
if (!acc[date]) {
|
|
311
|
+
acc[date] = { clockIns: 0, clockOuts: 0, hours: 0 };
|
|
312
|
+
}
|
|
313
|
+
acc[date].clockIns += 1;
|
|
314
|
+
if (l.clockOutAt) {
|
|
315
|
+
acc[date].clockOuts += 1;
|
|
316
|
+
acc[date].hours += (l.clockOutAt - l.clockInAt) / (1000 * 60 * 60);
|
|
317
|
+
}
|
|
318
|
+
return acc;
|
|
319
|
+
}, {});
|
|
320
|
+
return {
|
|
321
|
+
totalSessions,
|
|
322
|
+
completedSessions,
|
|
323
|
+
activeSessions,
|
|
324
|
+
uniqueAttendants,
|
|
325
|
+
totalHoursWorked: Math.round(totalHours * 100) / 100,
|
|
326
|
+
averageHoursPerSession: completedSessions > 0
|
|
327
|
+
? Math.round((totalHours / completedSessions) * 100) / 100
|
|
328
|
+
: 0,
|
|
329
|
+
attendanceByDay,
|
|
330
|
+
dateRange: {
|
|
331
|
+
start: startDate,
|
|
332
|
+
end: endDate,
|
|
333
|
+
},
|
|
334
|
+
};
|
|
335
|
+
},
|
|
336
|
+
});
|
|
337
|
+
//# sourceMappingURL=attendants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attendants.js","sourceRoot":"","sources":["../../convex/attendants.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit Functions
|
|
3
|
+
*
|
|
4
|
+
* Handles querying audit logs for compliance and accountability.
|
|
5
|
+
* Only admins can access audit logs.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Get audit logs by entity
|
|
9
|
+
*/
|
|
10
|
+
export declare const getByEntity: import("convex/server").RegisteredQuery<"public", {
|
|
11
|
+
entityId?: string | undefined;
|
|
12
|
+
limit?: number | undefined;
|
|
13
|
+
entityType: string;
|
|
14
|
+
}, Promise<{
|
|
15
|
+
_id: import("convex/values").GenericId<"auditLogs">;
|
|
16
|
+
_creationTime: number;
|
|
17
|
+
branchId?: import("convex/values").GenericId<"branches"> | undefined;
|
|
18
|
+
deviceId?: string | undefined;
|
|
19
|
+
entityId?: string | undefined;
|
|
20
|
+
ipAddress?: string | undefined;
|
|
21
|
+
details?: string | undefined;
|
|
22
|
+
oldValue?: string | undefined;
|
|
23
|
+
newValue?: string | undefined;
|
|
24
|
+
actorId: string;
|
|
25
|
+
actorType: "admin" | "customer" | "attendant";
|
|
26
|
+
actorRole: string;
|
|
27
|
+
action: string;
|
|
28
|
+
entityType: string;
|
|
29
|
+
timestamp: number;
|
|
30
|
+
}[]>>;
|
|
31
|
+
/**
|
|
32
|
+
* Get audit logs by actor
|
|
33
|
+
*/
|
|
34
|
+
export declare const getByActor: import("convex/server").RegisteredQuery<"public", {
|
|
35
|
+
actorType?: "admin" | "customer" | "attendant" | undefined;
|
|
36
|
+
limit?: number | undefined;
|
|
37
|
+
actorId: string;
|
|
38
|
+
}, Promise<{
|
|
39
|
+
_id: import("convex/values").GenericId<"auditLogs">;
|
|
40
|
+
_creationTime: number;
|
|
41
|
+
branchId?: import("convex/values").GenericId<"branches"> | undefined;
|
|
42
|
+
deviceId?: string | undefined;
|
|
43
|
+
entityId?: string | undefined;
|
|
44
|
+
ipAddress?: string | undefined;
|
|
45
|
+
details?: string | undefined;
|
|
46
|
+
oldValue?: string | undefined;
|
|
47
|
+
newValue?: string | undefined;
|
|
48
|
+
actorId: string;
|
|
49
|
+
actorType: "admin" | "customer" | "attendant";
|
|
50
|
+
actorRole: string;
|
|
51
|
+
action: string;
|
|
52
|
+
entityType: string;
|
|
53
|
+
timestamp: number;
|
|
54
|
+
}[]>>;
|
|
55
|
+
/**
|
|
56
|
+
* Get audit logs by branch
|
|
57
|
+
*/
|
|
58
|
+
export declare const getByBranch: import("convex/server").RegisteredQuery<"public", {
|
|
59
|
+
limit?: number | undefined;
|
|
60
|
+
branchId: import("convex/values").GenericId<"branches">;
|
|
61
|
+
}, Promise<{
|
|
62
|
+
_id: import("convex/values").GenericId<"auditLogs">;
|
|
63
|
+
_creationTime: number;
|
|
64
|
+
branchId?: import("convex/values").GenericId<"branches"> | undefined;
|
|
65
|
+
deviceId?: string | undefined;
|
|
66
|
+
entityId?: string | undefined;
|
|
67
|
+
ipAddress?: string | undefined;
|
|
68
|
+
details?: string | undefined;
|
|
69
|
+
oldValue?: string | undefined;
|
|
70
|
+
newValue?: string | undefined;
|
|
71
|
+
actorId: string;
|
|
72
|
+
actorType: "admin" | "customer" | "attendant";
|
|
73
|
+
actorRole: string;
|
|
74
|
+
action: string;
|
|
75
|
+
entityType: string;
|
|
76
|
+
timestamp: number;
|
|
77
|
+
}[]>>;
|
|
78
|
+
/**
|
|
79
|
+
* Get audit logs by action
|
|
80
|
+
*/
|
|
81
|
+
export declare const getByAction: import("convex/server").RegisteredQuery<"public", {
|
|
82
|
+
limit?: number | undefined;
|
|
83
|
+
action: string;
|
|
84
|
+
}, Promise<{
|
|
85
|
+
_id: import("convex/values").GenericId<"auditLogs">;
|
|
86
|
+
_creationTime: number;
|
|
87
|
+
branchId?: import("convex/values").GenericId<"branches"> | undefined;
|
|
88
|
+
deviceId?: string | undefined;
|
|
89
|
+
entityId?: string | undefined;
|
|
90
|
+
ipAddress?: string | undefined;
|
|
91
|
+
details?: string | undefined;
|
|
92
|
+
oldValue?: string | undefined;
|
|
93
|
+
newValue?: string | undefined;
|
|
94
|
+
actorId: string;
|
|
95
|
+
actorType: "admin" | "customer" | "attendant";
|
|
96
|
+
actorRole: string;
|
|
97
|
+
action: string;
|
|
98
|
+
entityType: string;
|
|
99
|
+
timestamp: number;
|
|
100
|
+
}[]>>;
|
|
101
|
+
/**
|
|
102
|
+
* Get audit logs by time range
|
|
103
|
+
*/
|
|
104
|
+
export declare const getByTimeRange: import("convex/server").RegisteredQuery<"public", {
|
|
105
|
+
limit?: number | undefined;
|
|
106
|
+
startTimestamp: number;
|
|
107
|
+
endTimestamp: number;
|
|
108
|
+
}, Promise<{
|
|
109
|
+
_id: import("convex/values").GenericId<"auditLogs">;
|
|
110
|
+
_creationTime: number;
|
|
111
|
+
branchId?: import("convex/values").GenericId<"branches"> | undefined;
|
|
112
|
+
deviceId?: string | undefined;
|
|
113
|
+
entityId?: string | undefined;
|
|
114
|
+
ipAddress?: string | undefined;
|
|
115
|
+
details?: string | undefined;
|
|
116
|
+
oldValue?: string | undefined;
|
|
117
|
+
newValue?: string | undefined;
|
|
118
|
+
actorId: string;
|
|
119
|
+
actorType: "admin" | "customer" | "attendant";
|
|
120
|
+
actorRole: string;
|
|
121
|
+
action: string;
|
|
122
|
+
entityType: string;
|
|
123
|
+
timestamp: number;
|
|
124
|
+
}[]>>;
|
|
125
|
+
/**
|
|
126
|
+
* Get all audit logs with filters - Paginated
|
|
127
|
+
* Supports usePaginatedQuery for infinite scroll
|
|
128
|
+
*/
|
|
129
|
+
export declare const getAll: import("convex/server").RegisteredQuery<"public", {
|
|
130
|
+
actorType?: "admin" | "customer" | "attendant" | undefined;
|
|
131
|
+
action?: string | undefined;
|
|
132
|
+
entityType?: string | undefined;
|
|
133
|
+
cursor?: string | undefined;
|
|
134
|
+
numItems?: number | undefined;
|
|
135
|
+
startTimestamp?: number | undefined;
|
|
136
|
+
endTimestamp?: number | undefined;
|
|
137
|
+
}, Promise<{
|
|
138
|
+
page: {
|
|
139
|
+
_id: import("convex/values").GenericId<"auditLogs">;
|
|
140
|
+
_creationTime: number;
|
|
141
|
+
branchId?: import("convex/values").GenericId<"branches"> | undefined;
|
|
142
|
+
deviceId?: string | undefined;
|
|
143
|
+
entityId?: string | undefined;
|
|
144
|
+
ipAddress?: string | undefined;
|
|
145
|
+
details?: string | undefined;
|
|
146
|
+
oldValue?: string | undefined;
|
|
147
|
+
newValue?: string | undefined;
|
|
148
|
+
actorId: string;
|
|
149
|
+
actorType: "admin" | "customer" | "attendant";
|
|
150
|
+
actorRole: string;
|
|
151
|
+
action: string;
|
|
152
|
+
entityType: string;
|
|
153
|
+
timestamp: number;
|
|
154
|
+
}[];
|
|
155
|
+
isDone: boolean;
|
|
156
|
+
continueCursor: string;
|
|
157
|
+
}>>;
|
|
158
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../convex/audit.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;KA8BtB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;KA8BrB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;KAkBtB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;KAkBtB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;KAyBzB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DjB,CAAC"}
|