@mostajs/ticketing 1.0.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.
- package/README.md +479 -0
- package/dist/api/scan.route.d.ts +16 -0
- package/dist/api/scan.route.d.ts.map +1 -0
- package/dist/api/scan.route.js +75 -0
- package/dist/api/scan.route.js.map +1 -0
- package/dist/api/tickets.route.d.ts +15 -0
- package/dist/api/tickets.route.d.ts.map +1 -0
- package/dist/api/tickets.route.js +91 -0
- package/dist/api/tickets.route.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/quota-manager.d.ts +18 -0
- package/dist/lib/quota-manager.d.ts.map +1 -0
- package/dist/lib/quota-manager.js +31 -0
- package/dist/lib/quota-manager.js.map +1 -0
- package/dist/lib/scan-processor.d.ts +39 -0
- package/dist/lib/scan-processor.d.ts.map +1 -0
- package/dist/lib/scan-processor.js +168 -0
- package/dist/lib/scan-processor.js.map +1 -0
- package/dist/lib/validity-checker.d.ts +19 -0
- package/dist/lib/validity-checker.d.ts.map +1 -0
- package/dist/lib/validity-checker.js +45 -0
- package/dist/lib/validity-checker.js.map +1 -0
- package/dist/repositories/activity.repository.d.ts +38 -0
- package/dist/repositories/activity.repository.d.ts.map +1 -0
- package/dist/repositories/activity.repository.js +23 -0
- package/dist/repositories/activity.repository.js.map +1 -0
- package/dist/repositories/client-access.repository.d.ts +31 -0
- package/dist/repositories/client-access.repository.d.ts.map +1 -0
- package/dist/repositories/client-access.repository.js +31 -0
- package/dist/repositories/client-access.repository.js.map +1 -0
- package/dist/repositories/index.d.ts +11 -0
- package/dist/repositories/index.d.ts.map +1 -0
- package/dist/repositories/index.js +8 -0
- package/dist/repositories/index.js.map +1 -0
- package/dist/repositories/scan-log.repository.d.ts +32 -0
- package/dist/repositories/scan-log.repository.d.ts.map +1 -0
- package/dist/repositories/scan-log.repository.js +48 -0
- package/dist/repositories/scan-log.repository.js.map +1 -0
- package/dist/repositories/subscription-plan.repository.d.ts +27 -0
- package/dist/repositories/subscription-plan.repository.d.ts.map +1 -0
- package/dist/repositories/subscription-plan.repository.js +19 -0
- package/dist/repositories/subscription-plan.repository.js.map +1 -0
- package/dist/repositories/ticket.repository.d.ts +48 -0
- package/dist/repositories/ticket.repository.d.ts.map +1 -0
- package/dist/repositories/ticket.repository.js +65 -0
- package/dist/repositories/ticket.repository.js.map +1 -0
- package/dist/schemas/activity.schema.d.ts +3 -0
- package/dist/schemas/activity.schema.d.ts.map +1 -0
- package/dist/schemas/activity.schema.js +39 -0
- package/dist/schemas/activity.schema.js.map +1 -0
- package/dist/schemas/client-access.schema.d.ts +3 -0
- package/dist/schemas/client-access.schema.d.ts.map +1 -0
- package/dist/schemas/client-access.schema.js +25 -0
- package/dist/schemas/client-access.schema.js.map +1 -0
- package/dist/schemas/counter.schema.d.ts +3 -0
- package/dist/schemas/counter.schema.d.ts.map +1 -0
- package/dist/schemas/counter.schema.js +11 -0
- package/dist/schemas/counter.schema.js.map +1 -0
- package/dist/schemas/index.d.ts +7 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +9 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/scan-log.schema.d.ts +3 -0
- package/dist/schemas/scan-log.schema.d.ts.map +1 -0
- package/dist/schemas/scan-log.schema.js +26 -0
- package/dist/schemas/scan-log.schema.js.map +1 -0
- package/dist/schemas/subscription-plan.schema.d.ts +3 -0
- package/dist/schemas/subscription-plan.schema.d.ts.map +1 -0
- package/dist/schemas/subscription-plan.schema.js +29 -0
- package/dist/schemas/subscription-plan.schema.js.map +1 -0
- package/dist/schemas/ticket.schema.d.ts +3 -0
- package/dist/schemas/ticket.schema.d.ts.map +1 -0
- package/dist/schemas/ticket.schema.js +35 -0
- package/dist/schemas/ticket.schema.js.map +1 -0
- package/dist/types/index.d.ts +99 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// ScanLogRepository
|
|
2
|
+
// @mostajs/ticketing
|
|
3
|
+
// Author: Dr Hamid MADANI drmdh@msn.com
|
|
4
|
+
import { BaseRepository } from '@mostajs/orm';
|
|
5
|
+
import { ScanLogSchema } from '../schemas/scan-log.schema';
|
|
6
|
+
export class ScanLogRepository extends BaseRepository {
|
|
7
|
+
constructor(dialect) {
|
|
8
|
+
super(ScanLogSchema, dialect);
|
|
9
|
+
}
|
|
10
|
+
/** Find recent scan logs with ticket & scannedBy populated */
|
|
11
|
+
async findRecent(filter = {}, options) {
|
|
12
|
+
return this.findWithRelations(filter, ['ticket', 'scannedBy'], { sort: { timestamp: -1 }, ...options });
|
|
13
|
+
}
|
|
14
|
+
/** Find scan history for a specific client */
|
|
15
|
+
async findByClient(clientId, options) {
|
|
16
|
+
return this.findWithRelations({ client: clientId }, ['ticket', 'activity', 'scannedBy'], { sort: { timestamp: -1 }, ...options });
|
|
17
|
+
}
|
|
18
|
+
/** Count all scans for today */
|
|
19
|
+
async countToday() {
|
|
20
|
+
const start = new Date();
|
|
21
|
+
start.setHours(0, 0, 0, 0);
|
|
22
|
+
return this.count({ timestamp: { $gte: start } });
|
|
23
|
+
}
|
|
24
|
+
/** Count granted scans for today */
|
|
25
|
+
async countGrantedToday() {
|
|
26
|
+
const start = new Date();
|
|
27
|
+
start.setHours(0, 0, 0, 0);
|
|
28
|
+
return this.count({ result: 'granted', timestamp: { $gte: start } });
|
|
29
|
+
}
|
|
30
|
+
/** Get distinct clients with granted scans today (visitors present) */
|
|
31
|
+
async findDistinctClientsToday() {
|
|
32
|
+
const start = new Date();
|
|
33
|
+
start.setHours(0, 0, 0, 0);
|
|
34
|
+
return this.distinct('client', { result: 'granted', timestamp: { $gte: start } });
|
|
35
|
+
}
|
|
36
|
+
/** Check if a ticket was already scanned today (for day_reentry) */
|
|
37
|
+
async wasScannedToday(ticketId) {
|
|
38
|
+
const start = new Date();
|
|
39
|
+
start.setHours(0, 0, 0, 0);
|
|
40
|
+
const log = await this.findOne({
|
|
41
|
+
ticket: ticketId,
|
|
42
|
+
result: 'granted',
|
|
43
|
+
timestamp: { $gte: start },
|
|
44
|
+
});
|
|
45
|
+
return log !== null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=scan-log.repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-log.repository.js","sourceRoot":"","sources":["../../repositories/scan-log.repository.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,qBAAqB;AACrB,wCAAwC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAkB3D,MAAM,OAAO,iBAAkB,SAAQ,cAA0B;IAC/D,YAAY,OAAiB;QAC3B,KAAK,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,8DAA8D;IAC9D,KAAK,CAAC,UAAU,CAAC,SAAkC,EAAE,EAAE,OAAsB;QAC3E,OAAO,IAAI,CAAC,iBAAiB,CAC3B,MAAM,EACN,CAAC,QAAQ,EAAE,WAAW,CAAC,EACvB,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,EAAE,CACxC,CAAC;IACJ,CAAC;IAED,8CAA8C;IAC9C,KAAK,CAAC,YAAY,CAAC,QAAgB,EAAE,OAAsB;QACzD,OAAO,IAAI,CAAC,iBAAiB,CAC3B,EAAE,MAAM,EAAE,QAAQ,EAAE,EACpB,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,EACnC,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,EAAE,CACxC,CAAC;IACJ,CAAC;IAED,gCAAgC;IAChC,KAAK,CAAC,UAAU;QACd,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,oCAAoC;IACpC,KAAK,CAAC,iBAAiB;QACrB,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,uEAAuE;IACvE,KAAK,CAAC,wBAAwB;QAC5B,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,oEAAoE;IACpE,KAAK,CAAC,eAAe,CAAC,QAAgB;QACpC,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;YAC7B,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,SAAS;YACjB,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;SAC3B,CAAC,CAAC;QACH,OAAO,GAAG,KAAK,IAAI,CAAC;IACtB,CAAC;CACF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BaseRepository } from '@mostajs/orm';
|
|
2
|
+
import type { IDialect } from '@mostajs/orm';
|
|
3
|
+
export interface PlanActivityDTO {
|
|
4
|
+
activity: any;
|
|
5
|
+
sessionsCount: number | null;
|
|
6
|
+
}
|
|
7
|
+
export interface SubscriptionPlanDTO {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
type: 'temporal' | 'usage' | 'mixed';
|
|
12
|
+
duration: number | null;
|
|
13
|
+
activities: PlanActivityDTO[];
|
|
14
|
+
price: number;
|
|
15
|
+
currency: string;
|
|
16
|
+
isActive: boolean;
|
|
17
|
+
createdAt: string;
|
|
18
|
+
updatedAt: string;
|
|
19
|
+
}
|
|
20
|
+
export declare class SubscriptionPlanRepository extends BaseRepository<SubscriptionPlanDTO> {
|
|
21
|
+
constructor(dialect: IDialect);
|
|
22
|
+
/** Find all plans, newest first */
|
|
23
|
+
findAllWithActivities(): Promise<SubscriptionPlanDTO[]>;
|
|
24
|
+
/** Find active plans only */
|
|
25
|
+
findActive(): Promise<SubscriptionPlanDTO[]>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=subscription-plan.repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-plan.repository.d.ts","sourceRoot":"","sources":["../../repositories/subscription-plan.repository.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,GAAG,CAAC;IACd,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;IACrC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,0BAA2B,SAAQ,cAAc,CAAC,mBAAmB,CAAC;gBACrE,OAAO,EAAE,QAAQ;IAI7B,mCAAmC;IAC7B,qBAAqB,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAI7D,6BAA6B;IACvB,UAAU,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;CAGnD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// SubscriptionPlanRepository
|
|
2
|
+
// @mostajs/ticketing
|
|
3
|
+
// Author: Dr Hamid MADANI drmdh@msn.com
|
|
4
|
+
import { BaseRepository } from '@mostajs/orm';
|
|
5
|
+
import { SubscriptionPlanSchema } from '../schemas/subscription-plan.schema';
|
|
6
|
+
export class SubscriptionPlanRepository extends BaseRepository {
|
|
7
|
+
constructor(dialect) {
|
|
8
|
+
super(SubscriptionPlanSchema, dialect);
|
|
9
|
+
}
|
|
10
|
+
/** Find all plans, newest first */
|
|
11
|
+
async findAllWithActivities() {
|
|
12
|
+
return this.findAll({}, { sort: { createdAt: -1 } });
|
|
13
|
+
}
|
|
14
|
+
/** Find active plans only */
|
|
15
|
+
async findActive() {
|
|
16
|
+
return this.findAll({ isActive: true }, { sort: { createdAt: -1 } });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=subscription-plan.repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-plan.repository.js","sourceRoot":"","sources":["../../repositories/subscription-plan.repository.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,qBAAqB;AACrB,wCAAwC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAsB7E,MAAM,OAAO,0BAA2B,SAAQ,cAAmC;IACjF,YAAY,OAAiB;QAC3B,KAAK,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,mCAAmC;IACnC,KAAK,CAAC,qBAAqB;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,6BAA6B;IAC7B,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvE,CAAC;CACF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { BaseRepository } from '@mostajs/orm';
|
|
2
|
+
import type { IDialect, QueryOptions } from '@mostajs/orm';
|
|
3
|
+
import type { CodeFormat } from '../types/index';
|
|
4
|
+
export interface TicketDTO {
|
|
5
|
+
id: string;
|
|
6
|
+
ticketNumber: string;
|
|
7
|
+
client: any;
|
|
8
|
+
clientAccess: any;
|
|
9
|
+
activity: any;
|
|
10
|
+
ticketType: string;
|
|
11
|
+
sourceClient: any;
|
|
12
|
+
code: string;
|
|
13
|
+
codeFormat: CodeFormat;
|
|
14
|
+
clientName: string;
|
|
15
|
+
activityName: string;
|
|
16
|
+
validityMode: string;
|
|
17
|
+
validUntil: string | null;
|
|
18
|
+
status: 'active' | 'used' | 'expired' | 'cancelled';
|
|
19
|
+
scannedAt: string | null;
|
|
20
|
+
scannedBy: any;
|
|
21
|
+
amount: number;
|
|
22
|
+
currency: string;
|
|
23
|
+
printCount: number;
|
|
24
|
+
createdBy: string;
|
|
25
|
+
createdAt: string;
|
|
26
|
+
updatedAt: string;
|
|
27
|
+
}
|
|
28
|
+
export declare class TicketRepository extends BaseRepository<TicketDTO> {
|
|
29
|
+
constructor(dialect: IDialect);
|
|
30
|
+
/** Generate next ticket number: TKT-20260228-0001 */
|
|
31
|
+
getNextTicketNumber(prefix?: string): Promise<string>;
|
|
32
|
+
/** Create ticket with auto-generated ticketNumber and code */
|
|
33
|
+
createWithAutoFields(data: Partial<TicketDTO>): Promise<TicketDTO>;
|
|
34
|
+
/** Find by code value (QR, barcode, etc.) */
|
|
35
|
+
findByCode(code: string): Promise<TicketDTO | null>;
|
|
36
|
+
/** Find tickets for a client */
|
|
37
|
+
findByClient(clientId: string, options?: QueryOptions): Promise<TicketDTO[]>;
|
|
38
|
+
/** Count tickets for a given clientAccess */
|
|
39
|
+
countByAccess(clientAccessId: string): Promise<number>;
|
|
40
|
+
/** Count tickets grouped by clientAccess (for access grid) */
|
|
41
|
+
countsByAccess(accessIds: string[]): Promise<{
|
|
42
|
+
accessId: string;
|
|
43
|
+
count: number;
|
|
44
|
+
}[]>;
|
|
45
|
+
/** Mark ticket as used */
|
|
46
|
+
markUsed(id: string, scannedBy: string): Promise<TicketDTO | null>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=ticket.repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket.repository.d.ts","sourceRoot":"","sources":["../../repositories/ticket.repository.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC;IACZ,YAAY,EAAE,GAAG,CAAC;IAClB,QAAQ,EAAE,GAAG,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,GAAG,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,CAAC;IACpD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,GAAG,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,gBAAiB,SAAQ,cAAc,CAAC,SAAS,CAAC;gBACjD,OAAO,EAAE,QAAQ;IAI7B,qDAAqD;IAC/C,mBAAmB,CAAC,MAAM,SAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAS1D,8DAA8D;IACxD,oBAAoB,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;IAgBxE,6CAA6C;IACvC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAIzD,gCAAgC;IAC1B,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAIlF,6CAA6C;IACvC,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI5D,8DAA8D;IACxD,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAOzF,0BAA0B;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;CAOzE"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// TicketRepository
|
|
2
|
+
// @mostajs/ticketing
|
|
3
|
+
// Author: Dr Hamid MADANI drmdh@msn.com
|
|
4
|
+
import { randomUUID } from 'crypto';
|
|
5
|
+
import { BaseRepository } from '@mostajs/orm';
|
|
6
|
+
import { TicketSchema } from '../schemas/ticket.schema';
|
|
7
|
+
import { CounterSchema } from '../schemas/counter.schema';
|
|
8
|
+
export class TicketRepository extends BaseRepository {
|
|
9
|
+
constructor(dialect) {
|
|
10
|
+
super(TicketSchema, dialect);
|
|
11
|
+
}
|
|
12
|
+
/** Generate next ticket number: TKT-20260228-0001 */
|
|
13
|
+
async getNextTicketNumber(prefix = 'TKT') {
|
|
14
|
+
const today = new Date();
|
|
15
|
+
const dateStr = today.toISOString().slice(0, 10).replace(/-/g, '');
|
|
16
|
+
const counterRepo = new BaseRepository(CounterSchema, this.dialect);
|
|
17
|
+
const counter = await counterRepo.increment(`ticket-${dateStr}`, 'seq', 1);
|
|
18
|
+
const seq = counter?.seq ?? 1;
|
|
19
|
+
return `${prefix}-${dateStr}-${String(seq).padStart(4, '0')}`;
|
|
20
|
+
}
|
|
21
|
+
/** Create ticket with auto-generated ticketNumber and code */
|
|
22
|
+
async createWithAutoFields(data) {
|
|
23
|
+
if (!data.ticketNumber) {
|
|
24
|
+
data.ticketNumber = await this.getNextTicketNumber();
|
|
25
|
+
}
|
|
26
|
+
if (!data.codeFormat) {
|
|
27
|
+
data.codeFormat = 'qrcode';
|
|
28
|
+
}
|
|
29
|
+
const created = await this.create(data);
|
|
30
|
+
if (!data.code) {
|
|
31
|
+
const uuid = randomUUID();
|
|
32
|
+
await this.update(created.id, { code: uuid });
|
|
33
|
+
created.code = uuid;
|
|
34
|
+
}
|
|
35
|
+
return created;
|
|
36
|
+
}
|
|
37
|
+
/** Find by code value (QR, barcode, etc.) */
|
|
38
|
+
async findByCode(code) {
|
|
39
|
+
return this.findOne({ code });
|
|
40
|
+
}
|
|
41
|
+
/** Find tickets for a client */
|
|
42
|
+
async findByClient(clientId, options) {
|
|
43
|
+
return this.findAll({ client: clientId }, { sort: { createdAt: -1 }, ...options });
|
|
44
|
+
}
|
|
45
|
+
/** Count tickets for a given clientAccess */
|
|
46
|
+
async countByAccess(clientAccessId) {
|
|
47
|
+
return this.count({ clientAccess: clientAccessId });
|
|
48
|
+
}
|
|
49
|
+
/** Count tickets grouped by clientAccess (for access grid) */
|
|
50
|
+
async countsByAccess(accessIds) {
|
|
51
|
+
return this.aggregate([
|
|
52
|
+
{ $match: { clientAccess: { $in: accessIds } } },
|
|
53
|
+
{ $group: { _by: 'clientAccess', count: { $sum: 1 } } },
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
/** Mark ticket as used */
|
|
57
|
+
async markUsed(id, scannedBy) {
|
|
58
|
+
return this.update(id, {
|
|
59
|
+
status: 'used',
|
|
60
|
+
scannedAt: new Date(),
|
|
61
|
+
scannedBy,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=ticket.repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket.repository.js","sourceRoot":"","sources":["../../repositories/ticket.repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity.schema.d.ts","sourceRoot":"","sources":["../../schemas/activity.schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,eAAO,MAAM,cAAc,EAAE,YAwC5B,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const ActivitySchema = {
|
|
2
|
+
name: 'Activity',
|
|
3
|
+
collection: 'activities',
|
|
4
|
+
timestamps: true,
|
|
5
|
+
fields: {
|
|
6
|
+
name: { type: 'string', required: true },
|
|
7
|
+
slug: { type: 'string', required: true, unique: true, lowercase: true },
|
|
8
|
+
description: { type: 'string' },
|
|
9
|
+
icon: { type: 'string' },
|
|
10
|
+
color: { type: 'string' },
|
|
11
|
+
capacity: { type: 'number' },
|
|
12
|
+
currentOccupancy: { type: 'number', default: 0 },
|
|
13
|
+
schedule: {
|
|
14
|
+
type: 'array',
|
|
15
|
+
arrayOf: {
|
|
16
|
+
kind: 'embedded',
|
|
17
|
+
fields: {
|
|
18
|
+
dayOfWeek: { type: 'number', required: true },
|
|
19
|
+
openTime: { type: 'string', required: true },
|
|
20
|
+
closeTime: { type: 'string', required: true },
|
|
21
|
+
isOpen: { type: 'boolean', default: true },
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
ticketValidityMode: { type: 'string', enum: ['day_reentry', 'single_use', 'time_slot', 'unlimited'], default: 'single_use' },
|
|
26
|
+
ticketDuration: { type: 'number', default: null },
|
|
27
|
+
price: { type: 'number', required: true, default: 0 },
|
|
28
|
+
currency: { type: 'string', default: 'DA' },
|
|
29
|
+
status: { type: 'string', enum: ['active', 'inactive', 'maintenance'], default: 'active' },
|
|
30
|
+
sortOrder: { type: 'number', default: 0 },
|
|
31
|
+
},
|
|
32
|
+
relations: {
|
|
33
|
+
createdBy: { target: 'User', type: 'many-to-one', nullable: true },
|
|
34
|
+
},
|
|
35
|
+
indexes: [
|
|
36
|
+
{ fields: { status: 'asc' } },
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=activity.schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity.schema.js","sourceRoot":"","sources":["../../schemas/activity.schema.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,cAAc,GAAiB;IAC1C,IAAI,EAAE,UAAU;IAChB,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,IAAI;IAEhB,MAAM,EAAE;QACN,IAAI,EAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;QACtD,IAAI,EAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;QACrF,WAAW,EAAS,EAAE,IAAI,EAAE,QAAQ,EAAE;QACtC,IAAI,EAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE;QACtC,KAAK,EAAe,EAAE,IAAI,EAAE,QAAQ,EAAE;QACtC,QAAQ,EAAY,EAAE,IAAI,EAAE,QAAQ,EAAE;QACtC,gBAAgB,EAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;QAClD,QAAQ,EAAY;YAClB,IAAI,EAAE,OAAO;YACb,OAAO,EAAE;gBACP,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE;oBACN,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;oBAC7C,QAAQ,EAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;oBAC7C,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;oBAC7C,MAAM,EAAK,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE;iBAC9C;aACF;SACF;QACD,kBAAkB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE;QAC5H,cAAc,EAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;QACrD,KAAK,EAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE;QAClE,QAAQ,EAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;QACrD,MAAM,EAAc,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,aAAa,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE;QACtG,SAAS,EAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;KACnD;IAED,SAAS,EAAE;QACT,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;KACnE;IAED,OAAO,EAAE;QACP,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;KAC9B;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-access.schema.d.ts","sourceRoot":"","sources":["../../schemas/client-access.schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,eAAO,MAAM,kBAAkB,EAAE,YA0BhC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const ClientAccessSchema = {
|
|
2
|
+
name: 'ClientAccess',
|
|
3
|
+
collection: 'client_accesses',
|
|
4
|
+
timestamps: true,
|
|
5
|
+
fields: {
|
|
6
|
+
accessType: { type: 'string', enum: ['unlimited', 'count', 'temporal', 'mixed'], required: true },
|
|
7
|
+
totalQuota: { type: 'number', default: null },
|
|
8
|
+
remainingQuota: { type: 'number', default: null },
|
|
9
|
+
startDate: { type: 'date', required: true },
|
|
10
|
+
endDate: { type: 'date', default: null },
|
|
11
|
+
status: { type: 'string', enum: ['active', 'expired', 'blocked', 'depleted'], default: 'active' },
|
|
12
|
+
},
|
|
13
|
+
relations: {
|
|
14
|
+
client: { target: 'Client', type: 'many-to-one', required: true },
|
|
15
|
+
plan: { target: 'SubscriptionPlan', type: 'many-to-one', nullable: true },
|
|
16
|
+
activity: { target: 'Activity', type: 'many-to-one', required: true },
|
|
17
|
+
createdBy: { target: 'User', type: 'many-to-one', required: true },
|
|
18
|
+
},
|
|
19
|
+
indexes: [
|
|
20
|
+
{ fields: { client: 'asc', activity: 'asc' } },
|
|
21
|
+
{ fields: { client: 'asc', status: 'asc' } },
|
|
22
|
+
{ fields: { status: 'asc' } },
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=client-access.schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-access.schema.js","sourceRoot":"","sources":["../../schemas/client-access.schema.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,IAAI,EAAE,cAAc;IACpB,UAAU,EAAE,iBAAiB;IAC7B,UAAU,EAAE,IAAI;IAEhB,MAAM,EAAE;QACN,UAAU,EAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;QACrG,UAAU,EAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;QACjD,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;QACjD,SAAS,EAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;QAChD,OAAO,EAAS,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAC/C,MAAM,EAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE;KAC1G;IAED,SAAS,EAAE;QACT,MAAM,EAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;QACpE,IAAI,EAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC9E,QAAQ,EAAG,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;QACtE,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;KACnE;IAED,OAAO,EAAE;QACP,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;QAC9C,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;QAC5C,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;KAC9B;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"counter.schema.d.ts","sourceRoot":"","sources":["../../schemas/counter.schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,eAAO,MAAM,aAAa,EAAE,YAY3B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"counter.schema.js","sourceRoot":"","sources":["../../schemas/counter.schema.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,IAAI,EAAE,SAAS;IACf,UAAU,EAAE,UAAU;IACtB,UAAU,EAAE,KAAK;IAEjB,MAAM,EAAE;QACN,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;KACpC;IAED,SAAS,EAAE,EAAE;IAEb,OAAO,EAAE,EAAE;CACZ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { TicketSchema } from './ticket.schema';
|
|
2
|
+
export { ClientAccessSchema } from './client-access.schema';
|
|
3
|
+
export { ScanLogSchema } from './scan-log.schema';
|
|
4
|
+
export { SubscriptionPlanSchema } from './subscription-plan.schema';
|
|
5
|
+
export { ActivitySchema } from './activity.schema';
|
|
6
|
+
export { CounterSchema } from './counter.schema';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../schemas/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// @mostajs/ticketing — Schemas barrel
|
|
2
|
+
// Author: Dr Hamid MADANI drmdh@msn.com
|
|
3
|
+
export { TicketSchema } from './ticket.schema';
|
|
4
|
+
export { ClientAccessSchema } from './client-access.schema';
|
|
5
|
+
export { ScanLogSchema } from './scan-log.schema';
|
|
6
|
+
export { SubscriptionPlanSchema } from './subscription-plan.schema';
|
|
7
|
+
export { ActivitySchema } from './activity.schema';
|
|
8
|
+
export { CounterSchema } from './counter.schema';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../schemas/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,wCAAwC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-log.schema.d.ts","sourceRoot":"","sources":["../../schemas/scan-log.schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,eAAO,MAAM,aAAa,EAAE,YA2B3B,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const ScanLogSchema = {
|
|
2
|
+
name: 'ScanLog',
|
|
3
|
+
collection: 'scan_logs',
|
|
4
|
+
timestamps: false,
|
|
5
|
+
fields: {
|
|
6
|
+
scanMethod: { type: 'string', enum: ['webcam', 'pwa_camera'], default: 'webcam' },
|
|
7
|
+
result: { type: 'string', enum: ['granted', 'denied'], required: true },
|
|
8
|
+
denyReason: { type: 'string', default: null },
|
|
9
|
+
quotaBefore: { type: 'number', default: null },
|
|
10
|
+
quotaAfter: { type: 'number', default: null },
|
|
11
|
+
isReentry: { type: 'boolean', default: false },
|
|
12
|
+
timestamp: { type: 'date', default: 'now' },
|
|
13
|
+
},
|
|
14
|
+
relations: {
|
|
15
|
+
ticket: { target: 'Ticket', type: 'many-to-one', nullable: true },
|
|
16
|
+
client: { target: 'Client', type: 'many-to-one', nullable: true },
|
|
17
|
+
activity: { target: 'Activity', type: 'many-to-one', nullable: true },
|
|
18
|
+
scannedBy: { target: 'User', type: 'many-to-one', required: true },
|
|
19
|
+
},
|
|
20
|
+
indexes: [
|
|
21
|
+
{ fields: { client: 'asc' } },
|
|
22
|
+
{ fields: { timestamp: 'desc' } },
|
|
23
|
+
{ fields: { result: 'asc' } },
|
|
24
|
+
],
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=scan-log.schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-log.schema.js","sourceRoot":"","sources":["../../schemas/scan-log.schema.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,IAAI,EAAE,SAAS;IACf,UAAU,EAAE,WAAW;IACvB,UAAU,EAAE,KAAK;IAEjB,MAAM,EAAE;QACN,UAAU,EAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE;QAClF,MAAM,EAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC5E,UAAU,EAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;QAC9C,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;QAC9C,UAAU,EAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;QAC9C,SAAS,EAAI,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE;QAChD,SAAS,EAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE;KAC9C;IAED,SAAS,EAAE;QACT,MAAM,EAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;QACpE,MAAM,EAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;QACpE,QAAQ,EAAG,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;QACtE,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;KACnE;IAED,OAAO,EAAE;QACP,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;QAC7B,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE;QACjC,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;KAC9B;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-plan.schema.d.ts","sourceRoot":"","sources":["../../schemas/subscription-plan.schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,eAAO,MAAM,sBAAsB,EAAE,YA8BpC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const SubscriptionPlanSchema = {
|
|
2
|
+
name: 'SubscriptionPlan',
|
|
3
|
+
collection: 'subscription_plans',
|
|
4
|
+
timestamps: true,
|
|
5
|
+
fields: {
|
|
6
|
+
name: { type: 'string', required: true },
|
|
7
|
+
description: { type: 'string' },
|
|
8
|
+
type: { type: 'string', enum: ['temporal', 'usage', 'mixed'], required: true },
|
|
9
|
+
duration: { type: 'number', default: null },
|
|
10
|
+
activities: {
|
|
11
|
+
type: 'array',
|
|
12
|
+
arrayOf: {
|
|
13
|
+
kind: 'embedded',
|
|
14
|
+
fields: {
|
|
15
|
+
activity: { type: 'string', required: true },
|
|
16
|
+
sessionsCount: { type: 'number', default: null },
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
price: { type: 'number', required: true },
|
|
21
|
+
currency: { type: 'string', default: 'DA' },
|
|
22
|
+
isActive: { type: 'boolean', default: true },
|
|
23
|
+
},
|
|
24
|
+
relations: {},
|
|
25
|
+
indexes: [
|
|
26
|
+
{ fields: { isActive: 'asc' } },
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=subscription-plan.schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-plan.schema.js","sourceRoot":"","sources":["../../schemas/subscription-plan.schema.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,sBAAsB,GAAiB;IAClD,IAAI,EAAE,kBAAkB;IACxB,UAAU,EAAE,oBAAoB;IAChC,UAAU,EAAE,IAAI;IAEhB,MAAM,EAAE;QACN,IAAI,EAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC/C,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC/B,IAAI,EAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE;QACrF,QAAQ,EAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;QAC9C,UAAU,EAAG;YACX,IAAI,EAAE,OAAO;YACb,OAAO,EAAE;gBACP,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE;oBACN,QAAQ,EAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;oBACjD,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;iBACjD;aACF;SACF;QACD,KAAK,EAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC/C,QAAQ,EAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;QAC9C,QAAQ,EAAK,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE;KAChD;IAED,SAAS,EAAE,EAAE;IAEb,OAAO,EAAE;QACP,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;KAChC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket.schema.d.ts","sourceRoot":"","sources":["../../schemas/ticket.schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,eAAO,MAAM,YAAY,EAAE,YAoC1B,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export const TicketSchema = {
|
|
2
|
+
name: 'Ticket',
|
|
3
|
+
collection: 'tickets',
|
|
4
|
+
timestamps: true,
|
|
5
|
+
fields: {
|
|
6
|
+
ticketNumber: { type: 'string', unique: true },
|
|
7
|
+
ticketType: { type: 'string', default: 'standard' },
|
|
8
|
+
code: { type: 'string', unique: true },
|
|
9
|
+
codeFormat: { type: 'string', enum: ['qrcode', 'code128', 'code39', 'ean13', 'ean8', 'upc_a', 'itf', 'pdf417', 'datamatrix', 'aztec'], default: 'qrcode' },
|
|
10
|
+
clientName: { type: 'string', required: true },
|
|
11
|
+
activityName: { type: 'string', required: true },
|
|
12
|
+
validityMode: { type: 'string', required: true },
|
|
13
|
+
validUntil: { type: 'date', default: null },
|
|
14
|
+
status: { type: 'string', enum: ['active', 'used', 'expired', 'cancelled'], default: 'active' },
|
|
15
|
+
scannedAt: { type: 'date', default: null },
|
|
16
|
+
amount: { type: 'number', required: true, default: 0 },
|
|
17
|
+
currency: { type: 'string', default: 'DA' },
|
|
18
|
+
printCount: { type: 'number', default: 0 },
|
|
19
|
+
},
|
|
20
|
+
relations: {
|
|
21
|
+
client: { target: 'Client', type: 'many-to-one', required: true },
|
|
22
|
+
clientAccess: { target: 'ClientAccess', type: 'many-to-one', required: true },
|
|
23
|
+
activity: { target: 'Activity', type: 'many-to-one', required: true },
|
|
24
|
+
sourceClient: { target: 'Client', type: 'many-to-one', nullable: true },
|
|
25
|
+
scannedBy: { target: 'User', type: 'many-to-one', nullable: true },
|
|
26
|
+
createdBy: { target: 'User', type: 'many-to-one', required: true },
|
|
27
|
+
},
|
|
28
|
+
indexes: [
|
|
29
|
+
{ fields: { client: 'asc' } },
|
|
30
|
+
{ fields: { status: 'asc' } },
|
|
31
|
+
{ fields: { validUntil: 'asc' } },
|
|
32
|
+
{ fields: { codeFormat: 'asc' } },
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=ticket.schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ticket.schema.js","sourceRoot":"","sources":["../../schemas/ticket.schema.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,YAAY,GAAiB;IACxC,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE,SAAS;IACrB,UAAU,EAAE,IAAI;IAEhB,MAAM,EAAE;QACN,YAAY,EAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;QAC/C,UAAU,EAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE;QACtD,IAAI,EAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE;QAC/C,UAAU,EAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE;QAC7J,UAAU,EAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;QACjD,YAAY,EAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;QACjD,YAAY,EAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;QACjD,UAAU,EAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAC9C,MAAM,EAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE;QACtG,SAAS,EAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE;QAC9C,MAAM,EAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE;QAC7D,QAAQ,EAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE;QAChD,UAAU,EAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;KAC9C;IAED,SAAS,EAAE;QACT,MAAM,EAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;QACvE,YAAY,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC7E,QAAQ,EAAM,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;QACzE,YAAY,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;QACvE,SAAS,EAAK,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;QACrE,SAAS,EAAK,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE;KACtE;IAED,OAAO,EAAE;QACP,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;QAC7B,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;QAC7B,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE;QACjC,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE;KAClC;CACF,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export type CodeFormat = 'qrcode' | 'code128' | 'code39' | 'ean13' | 'ean8' | 'upc_a' | 'itf' | 'pdf417' | 'datamatrix' | 'aztec';
|
|
2
|
+
export type ValidityMode = 'day_reentry' | 'single_use' | 'time_slot' | 'unlimited';
|
|
3
|
+
export type TicketStatus = 'active' | 'used' | 'expired' | 'cancelled';
|
|
4
|
+
export type ScanResult = 'granted' | 'denied';
|
|
5
|
+
export type ScanMethod = 'webcam' | 'pwa_camera' | 'handheld_scanner' | 'nfc';
|
|
6
|
+
export type AccessType = 'unlimited' | 'count' | 'temporal' | 'mixed';
|
|
7
|
+
export type AccessStatus = 'active' | 'expired' | 'blocked' | 'depleted';
|
|
8
|
+
export type ActivityStatus = 'active' | 'inactive' | 'maintenance';
|
|
9
|
+
export type PlanType = 'temporal' | 'usage' | 'mixed';
|
|
10
|
+
export type DenyReason = 'invalid_ticket' | 'ticket_already_used' | 'ticket_expired' | 'ticket_cancelled' | 'quota_depleted' | 'access_expired' | 'client_suspended';
|
|
11
|
+
export interface ScanInput {
|
|
12
|
+
code: string;
|
|
13
|
+
scanMethod?: ScanMethod;
|
|
14
|
+
scannedBy: string;
|
|
15
|
+
}
|
|
16
|
+
export interface ScanGrantedResult {
|
|
17
|
+
result: 'granted';
|
|
18
|
+
isReentry: boolean;
|
|
19
|
+
ticket: TicketInfo;
|
|
20
|
+
client: ClientInfo;
|
|
21
|
+
access: AccessInfo;
|
|
22
|
+
}
|
|
23
|
+
export interface ScanDeniedResult {
|
|
24
|
+
result: 'denied';
|
|
25
|
+
reason: DenyReason;
|
|
26
|
+
ticket?: TicketInfo;
|
|
27
|
+
}
|
|
28
|
+
export type ScanOutput = ScanGrantedResult | ScanDeniedResult;
|
|
29
|
+
export interface TicketInfo {
|
|
30
|
+
ticketNumber: string;
|
|
31
|
+
clientName: string;
|
|
32
|
+
activityName: string;
|
|
33
|
+
ticketType: string;
|
|
34
|
+
validityMode: string;
|
|
35
|
+
status: string;
|
|
36
|
+
}
|
|
37
|
+
export interface ClientInfo {
|
|
38
|
+
id: string;
|
|
39
|
+
name: string;
|
|
40
|
+
clientNumber?: string;
|
|
41
|
+
photo?: string;
|
|
42
|
+
[key: string]: unknown;
|
|
43
|
+
}
|
|
44
|
+
export interface AccessInfo {
|
|
45
|
+
remainingQuota: number | null;
|
|
46
|
+
totalQuota: number | null;
|
|
47
|
+
endDate: string | null;
|
|
48
|
+
status: AccessStatus;
|
|
49
|
+
}
|
|
50
|
+
export interface CreateTicketInput {
|
|
51
|
+
clientId: string;
|
|
52
|
+
activityId: string;
|
|
53
|
+
ticketType?: string;
|
|
54
|
+
sourceClientId?: string;
|
|
55
|
+
amount?: number;
|
|
56
|
+
codeFormat?: CodeFormat;
|
|
57
|
+
}
|
|
58
|
+
export interface ScanHandlerConfig {
|
|
59
|
+
getRepositories: () => Promise<{
|
|
60
|
+
ticketRepo: any;
|
|
61
|
+
clientAccessRepo: any;
|
|
62
|
+
scanLogRepo: any;
|
|
63
|
+
clientRepo: any;
|
|
64
|
+
}>;
|
|
65
|
+
checkAuth: (req: Request) => Promise<{
|
|
66
|
+
error: Response | null;
|
|
67
|
+
userId: string;
|
|
68
|
+
}>;
|
|
69
|
+
onGranted?: (data: {
|
|
70
|
+
ticket: any;
|
|
71
|
+
client: any;
|
|
72
|
+
access: any;
|
|
73
|
+
isReentry: boolean;
|
|
74
|
+
userId: string;
|
|
75
|
+
}) => Promise<void>;
|
|
76
|
+
onDenied?: (data: {
|
|
77
|
+
reason: string;
|
|
78
|
+
ticket?: any;
|
|
79
|
+
userId: string;
|
|
80
|
+
}) => Promise<void>;
|
|
81
|
+
}
|
|
82
|
+
export interface TicketsHandlerConfig {
|
|
83
|
+
getRepositories: () => Promise<{
|
|
84
|
+
ticketRepo: any;
|
|
85
|
+
clientRepo: any;
|
|
86
|
+
clientAccessRepo: any;
|
|
87
|
+
activityRepo: any;
|
|
88
|
+
}>;
|
|
89
|
+
checkAuth: (req: Request, permission: string) => Promise<{
|
|
90
|
+
error: Response | null;
|
|
91
|
+
userId: string;
|
|
92
|
+
}>;
|
|
93
|
+
onCreated?: (data: {
|
|
94
|
+
ticket: any;
|
|
95
|
+
userId: string;
|
|
96
|
+
}) => Promise<void>;
|
|
97
|
+
defaultCodeFormat?: CodeFormat;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=index.d.ts.map
|