@devlider001/washlab-backend 1.0.4 → 1.0.5
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/audit.d.ts +39 -0
- package/convex/notifications.d.ts +170 -0
- package/convex/schema.d.ts +51 -0
- 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 +3 -3
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { MutationCtx } from "../_generated/server";
|
|
2
|
+
import { Id } from "../_generated/dataModel";
|
|
3
|
+
/**
|
|
4
|
+
* Audit logging utilities
|
|
5
|
+
*
|
|
6
|
+
* These functions create audit log entries for all important actions
|
|
7
|
+
* to maintain accountability and compliance.
|
|
8
|
+
*/
|
|
9
|
+
interface AuditLogParams {
|
|
10
|
+
ctx: MutationCtx;
|
|
11
|
+
actorId: string;
|
|
12
|
+
actorType: "customer" | "attendant" | "admin";
|
|
13
|
+
actorRole: string;
|
|
14
|
+
action: string;
|
|
15
|
+
entityType: string;
|
|
16
|
+
entityId?: string;
|
|
17
|
+
branchId?: Id<"branches">;
|
|
18
|
+
deviceId?: string;
|
|
19
|
+
details?: string;
|
|
20
|
+
oldValue?: string;
|
|
21
|
+
newValue?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Create an audit log entry
|
|
25
|
+
*/
|
|
26
|
+
export declare function createAuditLog({ ctx, actorId, actorType, actorRole, action, entityType, entityId, branchId, deviceId, details, oldValue, newValue, }: AuditLogParams): Promise<Id<"auditLogs">>;
|
|
27
|
+
/**
|
|
28
|
+
* Create audit log for order status change
|
|
29
|
+
*/
|
|
30
|
+
export declare function logOrderStatusChange(ctx: MutationCtx, orderId: Id<"orders">, attendantId: Id<"attendants">, oldStatus: string, newStatus: string, branchId: Id<"branches">, notes?: string): Promise<Id<"auditLogs">>;
|
|
31
|
+
/**
|
|
32
|
+
* Create audit log for payment
|
|
33
|
+
*/
|
|
34
|
+
export declare function logPayment(ctx: MutationCtx, paymentId: Id<"payments">, orderId: Id<"orders">, customerId: Id<"users">, action: string, amount: number, paymentMethod: string, branchId?: Id<"branches">, attendantId?: Id<"attendants">, reason?: string): Promise<Id<"auditLogs">>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../../convex/lib/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,EAAE,EAAE,MAAM,yBAAyB,CAAC;AAE7C;;;;;GAKG;AAEH,UAAU,cAAc;IACtB,GAAG,EAAE,WAAW,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,EACnC,GAAG,EACH,OAAO,EACP,SAAS,EACT,SAAS,EACT,MAAM,EACN,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,QAAQ,GACT,EAAE,cAAc,GAAG,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAe3C;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,EACrB,WAAW,EAAE,EAAE,CAAC,YAAY,CAAC,EAC7B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,EAAE,CAAC,UAAU,CAAC,EACxB,KAAK,CAAC,EAAE,MAAM,4BAcf;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,EAAE,CAAC,UAAU,CAAC,EACzB,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,EACrB,UAAU,EAAE,EAAE,CAAC,OAAO,CAAC,EACvB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,QAAQ,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,EACzB,WAAW,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,EAC9B,MAAM,CAAC,EAAE,MAAM,4BAmBhB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create an audit log entry
|
|
3
|
+
*/
|
|
4
|
+
export async function createAuditLog({ ctx, actorId, actorType, actorRole, action, entityType, entityId, branchId, deviceId, details, oldValue, newValue, }) {
|
|
5
|
+
return await ctx.db.insert("auditLogs", {
|
|
6
|
+
actorId,
|
|
7
|
+
actorType,
|
|
8
|
+
actorRole,
|
|
9
|
+
action,
|
|
10
|
+
entityType,
|
|
11
|
+
entityId,
|
|
12
|
+
branchId,
|
|
13
|
+
deviceId,
|
|
14
|
+
details: details,
|
|
15
|
+
oldValue: oldValue,
|
|
16
|
+
newValue: newValue,
|
|
17
|
+
timestamp: Date.now(),
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create audit log for order status change
|
|
22
|
+
*/
|
|
23
|
+
export async function logOrderStatusChange(ctx, orderId, attendantId, oldStatus, newStatus, branchId, notes) {
|
|
24
|
+
return await createAuditLog({
|
|
25
|
+
ctx,
|
|
26
|
+
actorId: attendantId,
|
|
27
|
+
actorType: "attendant",
|
|
28
|
+
actorRole: "attendant",
|
|
29
|
+
action: "order.status_changed",
|
|
30
|
+
entityType: "order",
|
|
31
|
+
entityId: orderId,
|
|
32
|
+
branchId,
|
|
33
|
+
oldValue: JSON.stringify({ status: oldStatus }),
|
|
34
|
+
newValue: JSON.stringify({ status: newStatus, notes }),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Create audit log for payment
|
|
39
|
+
*/
|
|
40
|
+
export async function logPayment(ctx, paymentId, orderId, customerId, action, amount, paymentMethod, branchId, attendantId, reason) {
|
|
41
|
+
return await createAuditLog({
|
|
42
|
+
ctx,
|
|
43
|
+
actorId: attendantId || customerId,
|
|
44
|
+
actorType: attendantId ? "attendant" : "customer",
|
|
45
|
+
actorRole: attendantId ? "attendant" : "customer",
|
|
46
|
+
action,
|
|
47
|
+
entityType: "payment",
|
|
48
|
+
entityId: paymentId,
|
|
49
|
+
branchId,
|
|
50
|
+
details: JSON.stringify({
|
|
51
|
+
orderId,
|
|
52
|
+
customerId,
|
|
53
|
+
amount,
|
|
54
|
+
paymentMethod,
|
|
55
|
+
reason,
|
|
56
|
+
}),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../convex/lib/audit.ts"],"names":[],"mappings":"AAyBA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,EACnC,GAAG,EACH,OAAO,EACP,SAAS,EACT,SAAS,EACT,MAAM,EACN,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,QAAQ,GACO;IACf,OAAO,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE;QACtC,OAAO;QACP,SAAS;QACT,SAAS;QACT,MAAM;QACN,UAAU;QACV,QAAQ;QACR,QAAQ;QACR,QAAQ;QACR,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,QAAQ;QAClB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACtB,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,GAAgB,EAChB,OAAqB,EACrB,WAA6B,EAC7B,SAAiB,EACjB,SAAiB,EACjB,QAAwB,EACxB,KAAc;IAEd,OAAO,MAAM,cAAc,CAAC;QAC1B,GAAG;QACH,OAAO,EAAE,WAAW;QACpB,SAAS,EAAE,WAAW;QACtB,SAAS,EAAE,WAAW;QACtB,MAAM,EAAE,sBAAsB;QAC9B,UAAU,EAAE,OAAO;QACnB,QAAQ,EAAE,OAAO;QACjB,QAAQ;QACR,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QAC/C,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;KACvD,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAgB,EAChB,SAAyB,EACzB,OAAqB,EACrB,UAAuB,EACvB,MAAc,EACd,MAAc,EACd,aAAqB,EACrB,QAAyB,EACzB,WAA8B,EAC9B,MAAe;IAEf,OAAO,MAAM,cAAc,CAAC;QAC1B,GAAG;QACH,OAAO,EAAE,WAAW,IAAI,UAAU;QAClC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU;QACjD,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU;QACjD,MAAM;QACN,UAAU,EAAE,SAAS;QACrB,QAAQ,EAAE,SAAS;QACnB,QAAQ;QACR,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;YACtB,OAAO;YACP,UAAU;YACV,MAAM;YACN,aAAa;YACb,MAAM;SACP,CAAC;KACH,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { QueryCtx, MutationCtx } from "../_generated/server";
|
|
2
|
+
import { Id } from "../_generated/dataModel";
|
|
3
|
+
/**
|
|
4
|
+
* Get the current authenticated Clerk user identity
|
|
5
|
+
* @throws Error if user is not authenticated
|
|
6
|
+
*/
|
|
7
|
+
export declare function getClerkIdentity(ctx: QueryCtx | MutationCtx): Promise<import("convex/server").UserIdentity>;
|
|
8
|
+
/**
|
|
9
|
+
* Get current customer user from Clerk identity
|
|
10
|
+
* @throws Error if user is not authenticated or not found
|
|
11
|
+
*/
|
|
12
|
+
export declare function getCurrentCustomer(ctx: QueryCtx | MutationCtx): Promise<{
|
|
13
|
+
_id: import("convex/values").GenericId<"users">;
|
|
14
|
+
_creationTime: number;
|
|
15
|
+
email?: string | undefined;
|
|
16
|
+
clerkUserId?: string | undefined;
|
|
17
|
+
statusNote?: string | undefined;
|
|
18
|
+
statusChangedBy?: import("convex/values").GenericId<"admins"> | undefined;
|
|
19
|
+
statusChangedAt?: number | undefined;
|
|
20
|
+
lastLoginAt?: number | undefined;
|
|
21
|
+
preferredBranchId?: import("convex/values").GenericId<"branches"> | undefined;
|
|
22
|
+
phoneNumber: string;
|
|
23
|
+
name: string;
|
|
24
|
+
isRegistered: boolean;
|
|
25
|
+
isVerified: boolean;
|
|
26
|
+
status: "active" | "blocked" | "suspended" | "restricted";
|
|
27
|
+
createdAt: number;
|
|
28
|
+
isDeleted: boolean;
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Get current attendant from Clerk identity
|
|
32
|
+
* @throws Error if user is not authenticated or not found
|
|
33
|
+
*/
|
|
34
|
+
export declare function getCurrentAttendant(ctx: QueryCtx | MutationCtx): Promise<{
|
|
35
|
+
_id: import("convex/values").GenericId<"attendants">;
|
|
36
|
+
_creationTime: number;
|
|
37
|
+
lastLoginAt?: number | undefined;
|
|
38
|
+
passcode?: string | undefined;
|
|
39
|
+
phoneNumber: string;
|
|
40
|
+
email: string;
|
|
41
|
+
name: string;
|
|
42
|
+
clerkUserId: string;
|
|
43
|
+
createdAt: number;
|
|
44
|
+
isDeleted: boolean;
|
|
45
|
+
branchId: import("convex/values").GenericId<"branches">;
|
|
46
|
+
isActive: boolean;
|
|
47
|
+
}>;
|
|
48
|
+
/**
|
|
49
|
+
* Get current admin from Clerk identity
|
|
50
|
+
* @throws Error if user is not authenticated or not found
|
|
51
|
+
*/
|
|
52
|
+
export declare function getCurrentAdmin(ctx: QueryCtx | MutationCtx): Promise<{
|
|
53
|
+
_id: import("convex/values").GenericId<"admins">;
|
|
54
|
+
_creationTime: number;
|
|
55
|
+
lastLoginAt?: number | undefined;
|
|
56
|
+
email: string;
|
|
57
|
+
name: string;
|
|
58
|
+
clerkUserId: string;
|
|
59
|
+
createdAt: number;
|
|
60
|
+
isDeleted: boolean;
|
|
61
|
+
role: "super_admin" | "admin";
|
|
62
|
+
}>;
|
|
63
|
+
/**
|
|
64
|
+
* Get current admin with super admin role check
|
|
65
|
+
* @throws Error if user is not authenticated, not found, or not super admin
|
|
66
|
+
*/
|
|
67
|
+
export declare function getSuperAdmin(ctx: QueryCtx | MutationCtx): Promise<{
|
|
68
|
+
_id: import("convex/values").GenericId<"admins">;
|
|
69
|
+
_creationTime: number;
|
|
70
|
+
lastLoginAt?: number | undefined;
|
|
71
|
+
email: string;
|
|
72
|
+
name: string;
|
|
73
|
+
clerkUserId: string;
|
|
74
|
+
createdAt: number;
|
|
75
|
+
isDeleted: boolean;
|
|
76
|
+
role: "super_admin" | "admin";
|
|
77
|
+
}>;
|
|
78
|
+
/**
|
|
79
|
+
* Verify attendant is assigned to the specified branch
|
|
80
|
+
* @throws Error if attendant is not assigned to the branch
|
|
81
|
+
*/
|
|
82
|
+
export declare function verifyAttendantBranch(ctx: QueryCtx | MutationCtx, attendantId: Id<"attendants">, branchId: Id<"branches">): Promise<{
|
|
83
|
+
_id: import("convex/values").GenericId<"attendants">;
|
|
84
|
+
_creationTime: number;
|
|
85
|
+
lastLoginAt?: number | undefined;
|
|
86
|
+
passcode?: string | undefined;
|
|
87
|
+
phoneNumber: string;
|
|
88
|
+
email: string;
|
|
89
|
+
name: string;
|
|
90
|
+
clerkUserId: string;
|
|
91
|
+
createdAt: number;
|
|
92
|
+
isDeleted: boolean;
|
|
93
|
+
branchId: import("convex/values").GenericId<"branches">;
|
|
94
|
+
isActive: boolean;
|
|
95
|
+
}>;
|
|
96
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../convex/lib/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,EAAE,EAAE,MAAM,yBAAyB,CAAC;AAG7C;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,iDAMjE;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW;;;;;;;;;;;;;;;;;GAkBnE;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW;;;;;;;;;;;;;GAkBpE;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW;;;;;;;;;;GAkBhE;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW;;;;;;;;;;GAQ9D;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,QAAQ,GAAG,WAAW,EAC3B,WAAW,EAAE,EAAE,CAAC,YAAY,CAAC,EAC7B,QAAQ,EAAE,EAAE,CAAC,UAAU,CAAC;;;;;;;;;;;;;GAYzB"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the current authenticated Clerk user identity
|
|
3
|
+
* @throws Error if user is not authenticated
|
|
4
|
+
*/
|
|
5
|
+
export async function getClerkIdentity(ctx) {
|
|
6
|
+
const identity = await ctx.auth.getUserIdentity();
|
|
7
|
+
if (!identity) {
|
|
8
|
+
throw new Error("Authentication required");
|
|
9
|
+
}
|
|
10
|
+
return identity;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get current customer user from Clerk identity
|
|
14
|
+
* @throws Error if user is not authenticated or not found
|
|
15
|
+
*/
|
|
16
|
+
export async function getCurrentCustomer(ctx) {
|
|
17
|
+
const identity = await getClerkIdentity(ctx);
|
|
18
|
+
const clerkUserId = identity.subject;
|
|
19
|
+
const user = await ctx.db
|
|
20
|
+
.query("users")
|
|
21
|
+
.withIndex("by_clerk_user", (q) => q.eq("clerkUserId", clerkUserId))
|
|
22
|
+
.first();
|
|
23
|
+
if (!user) {
|
|
24
|
+
throw new Error("Customer not found. Please complete registration.");
|
|
25
|
+
}
|
|
26
|
+
if (user.isDeleted) {
|
|
27
|
+
throw new Error("Customer account has been deleted");
|
|
28
|
+
}
|
|
29
|
+
return user;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get current attendant from Clerk identity
|
|
33
|
+
* @throws Error if user is not authenticated or not found
|
|
34
|
+
*/
|
|
35
|
+
export async function getCurrentAttendant(ctx) {
|
|
36
|
+
const identity = await getClerkIdentity(ctx);
|
|
37
|
+
const clerkUserId = identity.subject;
|
|
38
|
+
const attendant = await ctx.db
|
|
39
|
+
.query("attendants")
|
|
40
|
+
.withIndex("by_clerk_user", (q) => q.eq("clerkUserId", clerkUserId))
|
|
41
|
+
.first();
|
|
42
|
+
if (!attendant) {
|
|
43
|
+
throw new Error("Attendant not found");
|
|
44
|
+
}
|
|
45
|
+
if (attendant.isDeleted || !attendant.isActive) {
|
|
46
|
+
throw new Error("Attendant account is inactive");
|
|
47
|
+
}
|
|
48
|
+
return attendant;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get current admin from Clerk identity
|
|
52
|
+
* @throws Error if user is not authenticated or not found
|
|
53
|
+
*/
|
|
54
|
+
export async function getCurrentAdmin(ctx) {
|
|
55
|
+
const identity = await getClerkIdentity(ctx);
|
|
56
|
+
const clerkUserId = identity.subject;
|
|
57
|
+
const admin = await ctx.db
|
|
58
|
+
.query("admins")
|
|
59
|
+
.withIndex("by_clerk_user", (q) => q.eq("clerkUserId", clerkUserId))
|
|
60
|
+
.first();
|
|
61
|
+
if (!admin) {
|
|
62
|
+
throw new Error("Admin not found");
|
|
63
|
+
}
|
|
64
|
+
if (admin.isDeleted) {
|
|
65
|
+
throw new Error("Admin account has been deleted");
|
|
66
|
+
}
|
|
67
|
+
return admin;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get current admin with super admin role check
|
|
71
|
+
* @throws Error if user is not authenticated, not found, or not super admin
|
|
72
|
+
*/
|
|
73
|
+
export async function getSuperAdmin(ctx) {
|
|
74
|
+
const admin = await getCurrentAdmin(ctx);
|
|
75
|
+
if (admin.role !== "super_admin") {
|
|
76
|
+
throw new Error("Super admin access required");
|
|
77
|
+
}
|
|
78
|
+
return admin;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Verify attendant is assigned to the specified branch
|
|
82
|
+
* @throws Error if attendant is not assigned to the branch
|
|
83
|
+
*/
|
|
84
|
+
export async function verifyAttendantBranch(ctx, attendantId, branchId) {
|
|
85
|
+
const attendant = await ctx.db.get(attendantId);
|
|
86
|
+
if (!attendant || attendant.isDeleted) {
|
|
87
|
+
throw new Error("Attendant not found");
|
|
88
|
+
}
|
|
89
|
+
if (attendant.branchId !== branchId) {
|
|
90
|
+
throw new Error("Attendant is not assigned to this branch");
|
|
91
|
+
}
|
|
92
|
+
return attendant;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../convex/lib/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for common operations
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Generate unique order number
|
|
6
|
+
* Format: WL-YYYY-XXXXXX (where XXXXXX is sequential)
|
|
7
|
+
*/
|
|
8
|
+
export declare function generateOrderNumber(): string;
|
|
9
|
+
/**
|
|
10
|
+
* Calculate order price based on weight and branch pricing
|
|
11
|
+
*/
|
|
12
|
+
export declare function calculateOrderPrice(weight: number, pricingPerKg: number, deliveryFee: number, isDelivery: boolean): {
|
|
13
|
+
basePrice: number;
|
|
14
|
+
deliveryFee: number;
|
|
15
|
+
totalPrice: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Calculate service price based on service type
|
|
19
|
+
* Service pricing:
|
|
20
|
+
* - wash_only: ₵25/load
|
|
21
|
+
* - wash_and_dry: ₵50/load
|
|
22
|
+
* - dry_only: ₵25/load
|
|
23
|
+
*/
|
|
24
|
+
export declare function calculateServicePrice(serviceType: "wash_only" | "wash_and_dry" | "dry_only", estimatedWeight: number, estimatedLoads: number, pricingPerKg: number, // Fallback pricing per kg
|
|
25
|
+
deliveryFee: number, isDelivery: boolean): {
|
|
26
|
+
basePrice: number;
|
|
27
|
+
deliveryFee: number;
|
|
28
|
+
totalPrice: number;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Format date to YYYY-MM-DD string
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatDate(date: Date): string;
|
|
34
|
+
/**
|
|
35
|
+
* Get current timestamp in milliseconds
|
|
36
|
+
*/
|
|
37
|
+
export declare function getCurrentTimestamp(): number;
|
|
38
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../convex/lib/utils.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAM5C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,OAAO,GAClB;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB,CAUA;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,WAAW,GAAG,cAAc,GAAG,UAAU,EACtD,eAAe,EAAE,MAAM,EACvB,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EAAE,0BAA0B;AAChD,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,OAAO,GAClB;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB,CAsBA;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAK7C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for common operations
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Generate unique order number
|
|
6
|
+
* Format: WL-YYYY-XXXXXX (where XXXXXX is sequential)
|
|
7
|
+
*/
|
|
8
|
+
export function generateOrderNumber() {
|
|
9
|
+
const year = new Date().getFullYear();
|
|
10
|
+
const random = Math.floor(Math.random() * 1000000)
|
|
11
|
+
.toString()
|
|
12
|
+
.padStart(6, "0");
|
|
13
|
+
return `WL-${year}-${random}`;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Calculate order price based on weight and branch pricing
|
|
17
|
+
*/
|
|
18
|
+
export function calculateOrderPrice(weight, pricingPerKg, deliveryFee, isDelivery) {
|
|
19
|
+
const basePrice = weight * pricingPerKg;
|
|
20
|
+
const fee = isDelivery ? deliveryFee : 0;
|
|
21
|
+
const totalPrice = basePrice + fee;
|
|
22
|
+
return {
|
|
23
|
+
basePrice: Math.round(basePrice * 100) / 100, // Round to 2 decimals
|
|
24
|
+
deliveryFee: fee,
|
|
25
|
+
totalPrice: Math.round(totalPrice * 100) / 100,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Calculate service price based on service type
|
|
30
|
+
* Service pricing:
|
|
31
|
+
* - wash_only: ₵25/load
|
|
32
|
+
* - wash_and_dry: ₵50/load
|
|
33
|
+
* - dry_only: ₵25/load
|
|
34
|
+
*/
|
|
35
|
+
export function calculateServicePrice(serviceType, estimatedWeight, estimatedLoads, pricingPerKg, // Fallback pricing per kg
|
|
36
|
+
deliveryFee, isDelivery) {
|
|
37
|
+
// Service pricing per load
|
|
38
|
+
const servicePricing = {
|
|
39
|
+
wash_only: 25,
|
|
40
|
+
wash_and_dry: 50,
|
|
41
|
+
dry_only: 25,
|
|
42
|
+
};
|
|
43
|
+
// Calculate base price: service price per load × number of loads
|
|
44
|
+
// If loads not provided, estimate based on weight (assume ~3kg per load)
|
|
45
|
+
const loads = estimatedLoads || Math.ceil(estimatedWeight / 3);
|
|
46
|
+
const pricePerLoad = servicePricing[serviceType];
|
|
47
|
+
const basePrice = loads * pricePerLoad;
|
|
48
|
+
const fee = isDelivery ? deliveryFee : 0;
|
|
49
|
+
const totalPrice = basePrice + fee;
|
|
50
|
+
return {
|
|
51
|
+
basePrice: Math.round(basePrice * 100) / 100,
|
|
52
|
+
deliveryFee: fee,
|
|
53
|
+
totalPrice: Math.round(totalPrice * 100) / 100,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Format date to YYYY-MM-DD string
|
|
58
|
+
*/
|
|
59
|
+
export function formatDate(date) {
|
|
60
|
+
const year = date.getFullYear();
|
|
61
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
62
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
63
|
+
return `${year}-${month}-${day}`;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get current timestamp in milliseconds
|
|
67
|
+
*/
|
|
68
|
+
export function getCurrentTimestamp() {
|
|
69
|
+
return Date.now();
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../convex/lib/utils.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC;SAC/C,QAAQ,EAAE;SACV,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpB,OAAO,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;AAChC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAc,EACd,YAAoB,EACpB,WAAmB,EACnB,UAAmB;IAMnB,MAAM,SAAS,GAAG,MAAM,GAAG,YAAY,CAAC;IACxC,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,SAAS,GAAG,GAAG,CAAC;IAEnC,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,GAAG,GAAG,EAAE,sBAAsB;QACpE,WAAW,EAAE,GAAG;QAChB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC,GAAG,GAAG;KAC/C,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,WAAsD,EACtD,eAAuB,EACvB,cAAsB,EACtB,YAAoB,EAAE,0BAA0B;AAChD,WAAmB,EACnB,UAAmB;IAMnB,2BAA2B;IAC3B,MAAM,cAAc,GAAG;QACrB,SAAS,EAAE,EAAE;QACb,YAAY,EAAE,EAAE;QAChB,QAAQ,EAAE,EAAE;KACb,CAAC;IAEF,iEAAiE;IACjE,yEAAyE;IACzE,MAAM,KAAK,GAAG,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC;IAC/D,MAAM,YAAY,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,KAAK,GAAG,YAAY,CAAC;IAEvC,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,SAAS,GAAG,GAAG,CAAC;IAEnC,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,GAAG,GAAG;QAC5C,WAAW,EAAE,GAAG;QAChB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC,GAAG,GAAG;KAC/C,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAU;IACnC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpD,OAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loyalty Functions
|
|
3
|
+
*
|
|
4
|
+
* Handles loyalty points earning, redemption, and balance management.
|
|
5
|
+
* Rules: 1 point per completed order, 10 points = 1 free wash.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Get customer loyalty points balance
|
|
9
|
+
*/
|
|
10
|
+
export declare const getBalance: import("convex/server").RegisteredQuery<"public", {}, Promise<{
|
|
11
|
+
points: number;
|
|
12
|
+
totalEarned: number;
|
|
13
|
+
totalRedeemed: number;
|
|
14
|
+
lastEarnedAt: number | undefined;
|
|
15
|
+
lastRedeemedAt: number | undefined;
|
|
16
|
+
}>>;
|
|
17
|
+
/**
|
|
18
|
+
* Get loyalty transaction history
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Get loyalty transactions - Paginated
|
|
22
|
+
* Supports usePaginatedQuery for infinite scroll
|
|
23
|
+
*/
|
|
24
|
+
export declare const getTransactions: import("convex/server").RegisteredQuery<"public", {
|
|
25
|
+
cursor?: string | undefined;
|
|
26
|
+
numItems?: number | undefined;
|
|
27
|
+
}, Promise<{
|
|
28
|
+
page: {
|
|
29
|
+
_id: import("convex/values").GenericId<"loyaltyTransactions">;
|
|
30
|
+
_creationTime: number;
|
|
31
|
+
createdBy?: import("convex/values").GenericId<"admins"> | undefined;
|
|
32
|
+
orderId?: import("convex/values").GenericId<"orders"> | undefined;
|
|
33
|
+
description?: string | undefined;
|
|
34
|
+
type: "earned" | "redeemed" | "expired" | "adjusted";
|
|
35
|
+
createdAt: number;
|
|
36
|
+
isDeleted: boolean;
|
|
37
|
+
customerId: import("convex/values").GenericId<"users">;
|
|
38
|
+
points: number;
|
|
39
|
+
balanceAfter: number;
|
|
40
|
+
}[];
|
|
41
|
+
isDone: boolean;
|
|
42
|
+
continueCursor: string;
|
|
43
|
+
}>>;
|
|
44
|
+
/**
|
|
45
|
+
* Earn loyalty points (internal - called when order is completed)
|
|
46
|
+
*/
|
|
47
|
+
export declare const earnPoints: import("convex/server").RegisteredMutation<"internal", {
|
|
48
|
+
customerId: import("convex/values").GenericId<"users">;
|
|
49
|
+
orderId: import("convex/values").GenericId<"orders">;
|
|
50
|
+
points: number;
|
|
51
|
+
}, Promise<void>>;
|
|
52
|
+
/**
|
|
53
|
+
* Redeem loyalty points for free wash
|
|
54
|
+
*/
|
|
55
|
+
export declare const redeemPoints: import("convex/server").RegisteredMutation<"public", {
|
|
56
|
+
orderId: import("convex/values").GenericId<"orders">;
|
|
57
|
+
pointsToRedeem: number;
|
|
58
|
+
}, Promise<{
|
|
59
|
+
pointsRedeemed: number;
|
|
60
|
+
newBalance: number;
|
|
61
|
+
discountAmount: number;
|
|
62
|
+
finalPrice: number;
|
|
63
|
+
}>>;
|
|
64
|
+
/**
|
|
65
|
+
* Adjust loyalty points (admin only)
|
|
66
|
+
*/
|
|
67
|
+
export declare const adjustPoints: import("convex/server").RegisteredMutation<"public", {
|
|
68
|
+
customerId: import("convex/values").GenericId<"users">;
|
|
69
|
+
points: number;
|
|
70
|
+
description: string;
|
|
71
|
+
}, Promise<{
|
|
72
|
+
_id: import("convex/values").GenericId<"loyaltyPoints">;
|
|
73
|
+
_creationTime: number;
|
|
74
|
+
lastEarnedAt?: number | undefined;
|
|
75
|
+
lastRedeemedAt?: number | undefined;
|
|
76
|
+
isDeleted: boolean;
|
|
77
|
+
customerId: import("convex/values").GenericId<"users">;
|
|
78
|
+
points: number;
|
|
79
|
+
totalEarned: number;
|
|
80
|
+
totalRedeemed: number;
|
|
81
|
+
}>>;
|
|
82
|
+
//# sourceMappingURL=loyalty.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loyalty.d.ts","sourceRoot":"","sources":["../../convex/loyalty.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AAEH;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;GA4BrB,CAAC;AAEH;;GAEG;AACH;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;GAyB1B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,UAAU;;;;iBAiErB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;;;;GAyFvB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;GAiEvB,CAAC"}
|