@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.
Files changed (82) hide show
  1. package/README.md +479 -0
  2. package/dist/api/scan.route.d.ts +16 -0
  3. package/dist/api/scan.route.d.ts.map +1 -0
  4. package/dist/api/scan.route.js +75 -0
  5. package/dist/api/scan.route.js.map +1 -0
  6. package/dist/api/tickets.route.d.ts +15 -0
  7. package/dist/api/tickets.route.d.ts.map +1 -0
  8. package/dist/api/tickets.route.js +91 -0
  9. package/dist/api/tickets.route.js.map +1 -0
  10. package/dist/index.d.ts +11 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +14 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/lib/quota-manager.d.ts +18 -0
  15. package/dist/lib/quota-manager.d.ts.map +1 -0
  16. package/dist/lib/quota-manager.js +31 -0
  17. package/dist/lib/quota-manager.js.map +1 -0
  18. package/dist/lib/scan-processor.d.ts +39 -0
  19. package/dist/lib/scan-processor.d.ts.map +1 -0
  20. package/dist/lib/scan-processor.js +168 -0
  21. package/dist/lib/scan-processor.js.map +1 -0
  22. package/dist/lib/validity-checker.d.ts +19 -0
  23. package/dist/lib/validity-checker.d.ts.map +1 -0
  24. package/dist/lib/validity-checker.js +45 -0
  25. package/dist/lib/validity-checker.js.map +1 -0
  26. package/dist/repositories/activity.repository.d.ts +38 -0
  27. package/dist/repositories/activity.repository.d.ts.map +1 -0
  28. package/dist/repositories/activity.repository.js +23 -0
  29. package/dist/repositories/activity.repository.js.map +1 -0
  30. package/dist/repositories/client-access.repository.d.ts +31 -0
  31. package/dist/repositories/client-access.repository.d.ts.map +1 -0
  32. package/dist/repositories/client-access.repository.js +31 -0
  33. package/dist/repositories/client-access.repository.js.map +1 -0
  34. package/dist/repositories/index.d.ts +11 -0
  35. package/dist/repositories/index.d.ts.map +1 -0
  36. package/dist/repositories/index.js +8 -0
  37. package/dist/repositories/index.js.map +1 -0
  38. package/dist/repositories/scan-log.repository.d.ts +32 -0
  39. package/dist/repositories/scan-log.repository.d.ts.map +1 -0
  40. package/dist/repositories/scan-log.repository.js +48 -0
  41. package/dist/repositories/scan-log.repository.js.map +1 -0
  42. package/dist/repositories/subscription-plan.repository.d.ts +27 -0
  43. package/dist/repositories/subscription-plan.repository.d.ts.map +1 -0
  44. package/dist/repositories/subscription-plan.repository.js +19 -0
  45. package/dist/repositories/subscription-plan.repository.js.map +1 -0
  46. package/dist/repositories/ticket.repository.d.ts +48 -0
  47. package/dist/repositories/ticket.repository.d.ts.map +1 -0
  48. package/dist/repositories/ticket.repository.js +65 -0
  49. package/dist/repositories/ticket.repository.js.map +1 -0
  50. package/dist/schemas/activity.schema.d.ts +3 -0
  51. package/dist/schemas/activity.schema.d.ts.map +1 -0
  52. package/dist/schemas/activity.schema.js +39 -0
  53. package/dist/schemas/activity.schema.js.map +1 -0
  54. package/dist/schemas/client-access.schema.d.ts +3 -0
  55. package/dist/schemas/client-access.schema.d.ts.map +1 -0
  56. package/dist/schemas/client-access.schema.js +25 -0
  57. package/dist/schemas/client-access.schema.js.map +1 -0
  58. package/dist/schemas/counter.schema.d.ts +3 -0
  59. package/dist/schemas/counter.schema.d.ts.map +1 -0
  60. package/dist/schemas/counter.schema.js +11 -0
  61. package/dist/schemas/counter.schema.js.map +1 -0
  62. package/dist/schemas/index.d.ts +7 -0
  63. package/dist/schemas/index.d.ts.map +1 -0
  64. package/dist/schemas/index.js +9 -0
  65. package/dist/schemas/index.js.map +1 -0
  66. package/dist/schemas/scan-log.schema.d.ts +3 -0
  67. package/dist/schemas/scan-log.schema.d.ts.map +1 -0
  68. package/dist/schemas/scan-log.schema.js +26 -0
  69. package/dist/schemas/scan-log.schema.js.map +1 -0
  70. package/dist/schemas/subscription-plan.schema.d.ts +3 -0
  71. package/dist/schemas/subscription-plan.schema.d.ts.map +1 -0
  72. package/dist/schemas/subscription-plan.schema.js +29 -0
  73. package/dist/schemas/subscription-plan.schema.js.map +1 -0
  74. package/dist/schemas/ticket.schema.d.ts +3 -0
  75. package/dist/schemas/ticket.schema.d.ts.map +1 -0
  76. package/dist/schemas/ticket.schema.js +35 -0
  77. package/dist/schemas/ticket.schema.js.map +1 -0
  78. package/dist/types/index.d.ts +99 -0
  79. package/dist/types/index.d.ts.map +1 -0
  80. package/dist/types/index.js +4 -0
  81. package/dist/types/index.js.map +1 -0
  82. package/package.json +84 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tickets.route.js","sourceRoot":"","sources":["../../api/tickets.route.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,wCAAwC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAA4B;IAE/D,KAAK,UAAU,GAAG,CAAC,GAAY;QAC7B,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QAC7D,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QAExB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAClD,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC;QAE9D,MAAM,MAAM,GAAwB,EAAE,CAAC;QACvC,IAAI,QAAQ;YAAE,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC;QACvC,IAAI,MAAM;YAAE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;QAEnC,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC;QAC7C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAE3F,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,UAAU,IAAI,CAAC,GAAY;QAC9B,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QACvE,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QAExB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,GAAG,UAAU,EAAE,cAAc,EAAE,MAAM,GAAG,CAAC,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;QAEvG,IAAI,CAAC,QAAQ,IAAI,CAAC,UAAU,EAAE,CAAC;YAC7B,OAAO,QAAQ,CAAC,IAAI,CAClB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,+BAA+B,EAAE,EAAE,EACjF,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;QACJ,CAAC;QAED,4DAA4D;QAC5D,MAAM,cAAc,GAAG,UAAU,KAAK,QAAQ,IAAI,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC;QAE7F,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,eAAe,EAAE,CAAC;QAE7C,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACzD,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;YACnC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,UAAU,CAAC;YACvC,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,cAAc,EAAE,UAAU,CAAC;SACpE,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,mBAAmB,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACxG,CAAC;QACD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,sBAAsB,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC3G,CAAC;QACD,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO,QAAQ,CAAC,IAAI,CAClB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,0CAA0C,EAAE,EAAE,EACrF,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;QACJ,CAAC;QAED,cAAc;QACd,IAAI,YAAY,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;YACpC,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC1E,IAAI,gBAAgB,CAAC,YAAY,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,CAAC;gBAC3D,OAAO,QAAQ,CAAC,IAAI,CAClB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,mBAAmB,WAAW,IAAI,YAAY,CAAC,UAAU,UAAU,EAAE,EAAE,EACnH,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,iDAAiD;QACjD,MAAM,UAAU,GAAG,UAAU,KAAK,QAAQ;YACxC,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC,kBAAkB,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;QAE5E,MAAM,cAAc,GAAe,UAAU,IAAI,MAAM,CAAC,iBAAiB,IAAI,QAAQ,CAAC;QAEtF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,oBAAoB,CAAC;YACzD,MAAM,EAAE,QAAQ;YAChB,YAAY,EAAE,YAAY,CAAC,EAAE;YAC7B,QAAQ,EAAE,UAAU;YACpB,UAAU;YACV,YAAY,EAAE,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI;YAC7D,UAAU,EAAE,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,QAAQ,EAAE;YACpD,YAAY,EAAE,QAAQ,CAAC,IAAI;YAC3B,YAAY,EAAE,QAAQ,CAAC,kBAAkB;YACzC,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,IAAI;YAC7C,MAAM;YACN,UAAU,EAAE,cAAc;YAC1B,SAAS,EAAE,MAAM;SAClB,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrB,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7C,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AACvB,CAAC"}
@@ -0,0 +1,11 @@
1
+ export { TicketSchema, ClientAccessSchema, ScanLogSchema, SubscriptionPlanSchema, ActivitySchema, CounterSchema, } from './schemas/index';
2
+ export { TicketRepository, ClientAccessRepository, ScanLogRepository, SubscriptionPlanRepository, ActivityRepository, } from './repositories/index';
3
+ export type { TicketDTO, ClientAccessDTO, ScanLogDTO, SubscriptionPlanDTO, PlanActivityDTO, ActivityDTO, ActivityScheduleDTO, } from './repositories/index';
4
+ export { processScan } from './lib/scan-processor';
5
+ export type { ScanDeps } from './lib/scan-processor';
6
+ export { computeValidUntil, isExpired, isToday } from './lib/validity-checker';
7
+ export { decrementQuota, isQuotaDepleted, wouldExceedQuota } from './lib/quota-manager';
8
+ export { createScanHandler } from './api/scan.route';
9
+ export { createTicketsHandler } from './api/tickets.route';
10
+ export type { CodeFormat, ValidityMode, TicketStatus, ScanResult, ScanMethod, AccessType, AccessStatus, ActivityStatus, PlanType, DenyReason, ScanInput, ScanOutput, ScanGrantedResult, ScanDeniedResult, TicketInfo, ClientInfo, AccessInfo, CreateTicketInput, ScanHandlerConfig, TicketsHandlerConfig, } from './types/index';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,cAAc,EACd,aAAa,GACd,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,SAAS,EACT,eAAe,EACf,UAAU,EACV,mBAAmB,EACnB,eAAe,EACf,WAAW,EACX,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,YAAY,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAG3D,YAAY,EACV,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,UAAU,EACV,UAAU,EACV,YAAY,EACZ,cAAc,EACd,QAAQ,EACR,UAAU,EACV,SAAS,EACT,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ // @mostajs/ticketing — Main barrel exports
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ // ── Schemas ────────────────────────────────────────────────────────
4
+ export { TicketSchema, ClientAccessSchema, ScanLogSchema, SubscriptionPlanSchema, ActivitySchema, CounterSchema, } from './schemas/index';
5
+ // ── Repositories ───────────────────────────────────────────────────
6
+ export { TicketRepository, ClientAccessRepository, ScanLogRepository, SubscriptionPlanRepository, ActivityRepository, } from './repositories/index';
7
+ // ── Core logic (pure functions) ────────────────────────────────────
8
+ export { processScan } from './lib/scan-processor';
9
+ export { computeValidUntil, isExpired, isToday } from './lib/validity-checker';
10
+ export { decrementQuota, isQuotaDepleted, wouldExceedQuota } from './lib/quota-manager';
11
+ // ── API route factories ────────────────────────────────────────────
12
+ export { createScanHandler } from './api/scan.route';
13
+ export { createTicketsHandler } from './api/tickets.route';
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,wCAAwC;AAExC,sEAAsE;AACtE,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,sBAAsB,EACtB,cAAc,EACd,aAAa,GACd,MAAM,iBAAiB,CAAC;AAEzB,sEAAsE;AACtE,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAY9B,sEAAsE;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAGnD,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAExF,sEAAsE;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,18 @@
1
+ export interface QuotaUpdate {
2
+ remainingQuota: number;
3
+ status?: 'depleted';
4
+ }
5
+ /**
6
+ * Compute the new quota after decrementing by 1.
7
+ * Returns null if the access has no quota (unlimited).
8
+ */
9
+ export declare function decrementQuota(remainingQuota: number | null): QuotaUpdate | null;
10
+ /**
11
+ * Check if a quota is exhausted.
12
+ */
13
+ export declare function isQuotaDepleted(remainingQuota: number | null): boolean;
14
+ /**
15
+ * Check if generating a new ticket would exceed the total quota.
16
+ */
17
+ export declare function wouldExceedQuota(totalQuota: number | null, currentCount: number): boolean;
18
+ //# sourceMappingURL=quota-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-manager.d.ts","sourceRoot":"","sources":["../../lib/quota-manager.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,GAAG,IAAI,CAQhF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAEtE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAGzF"}
@@ -0,0 +1,31 @@
1
+ // @mostajs/ticketing — Quota manager (pure functions, zero coupling)
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ /**
4
+ * Compute the new quota after decrementing by 1.
5
+ * Returns null if the access has no quota (unlimited).
6
+ */
7
+ export function decrementQuota(remainingQuota) {
8
+ if (remainingQuota == null)
9
+ return null;
10
+ const newQuota = Math.max(0, remainingQuota - 1);
11
+ const update = { remainingQuota: newQuota };
12
+ if (newQuota === 0) {
13
+ update.status = 'depleted';
14
+ }
15
+ return update;
16
+ }
17
+ /**
18
+ * Check if a quota is exhausted.
19
+ */
20
+ export function isQuotaDepleted(remainingQuota) {
21
+ return remainingQuota != null && remainingQuota <= 0;
22
+ }
23
+ /**
24
+ * Check if generating a new ticket would exceed the total quota.
25
+ */
26
+ export function wouldExceedQuota(totalQuota, currentCount) {
27
+ if (totalQuota == null)
28
+ return false;
29
+ return currentCount >= totalQuota;
30
+ }
31
+ //# sourceMappingURL=quota-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quota-manager.js","sourceRoot":"","sources":["../../lib/quota-manager.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,wCAAwC;AAOxC;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,cAA6B;IAC1D,IAAI,cAAc,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,cAAc,GAAG,CAAC,CAAC,CAAC;IACjD,MAAM,MAAM,GAAgB,EAAE,cAAc,EAAE,QAAQ,EAAE,CAAC;IACzD,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;QACnB,MAAM,CAAC,MAAM,GAAG,UAAU,CAAC;IAC7B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,cAA6B;IAC3D,OAAO,cAAc,IAAI,IAAI,IAAI,cAAc,IAAI,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAyB,EAAE,YAAoB;IAC9E,IAAI,UAAU,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IACrC,OAAO,YAAY,IAAI,UAAU,CAAC;AACpC,CAAC"}
@@ -0,0 +1,39 @@
1
+ import type { ScanOutput, ScanMethod } from '../types/index';
2
+ export interface ScanDeps {
3
+ /** Find ticket by code value (QR code, barcode, etc.) */
4
+ findTicketByCode: (code: string) => Promise<any | null>;
5
+ /** Find client access by ID */
6
+ findAccessById: (id: string) => Promise<any | null>;
7
+ /** Find client by ID */
8
+ findClientById: (id: string) => Promise<any | null>;
9
+ /** Check if this ticket was already scanned (granted) today */
10
+ wasScannedToday: (ticketId: string) => Promise<boolean>;
11
+ /** Update ticket fields */
12
+ updateTicket: (id: string, data: Record<string, any>) => Promise<void>;
13
+ /** Update client access fields */
14
+ updateAccess: (id: string, data: Record<string, any>) => Promise<void>;
15
+ /** Create a scan log entry */
16
+ createScanLog: (data: Record<string, any>) => Promise<void>;
17
+ /** Extract the raw ID from a relation field (may be object or string) */
18
+ resolveId: (ref: any) => string;
19
+ /** Format a client's display name */
20
+ formatClientName: (client: any) => string;
21
+ }
22
+ /**
23
+ * Process a ticket scan through the 8-step validation pipeline.
24
+ *
25
+ * This is a pure business-logic function with zero coupling to any framework,
26
+ * ORM, or database. All I/O is performed via the injected `deps` callbacks.
27
+ *
28
+ * Steps:
29
+ * 1. Find ticket by code
30
+ * 2. Check ticket status
31
+ * 3. Check validUntil expiry
32
+ * 4. Load client access
33
+ * 5. Check client status
34
+ * 6. Process validity mode (day_reentry / single_use / time_slot / unlimited)
35
+ * 7. Update ticket + access, create scan log
36
+ * 8. Return result
37
+ */
38
+ export declare function processScan(code: string, scanMethod: ScanMethod, scannedBy: string, deps: ScanDeps): Promise<ScanOutput>;
39
+ //# sourceMappingURL=scan-processor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-processor.d.ts","sourceRoot":"","sources":["../../lib/scan-processor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAA0B,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAKrF,MAAM,WAAW,QAAQ;IACvB,yDAAyD;IACzD,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACxD,+BAA+B;IAC/B,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACpD,wBAAwB;IACxB,cAAc,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACpD,+DAA+D;IAC/D,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,2BAA2B;IAC3B,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,kCAAkC;IAClC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,8BAA8B;IAC9B,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,yEAAyE;IACzE,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,CAAC;IAChC,qCAAqC;IACrC,gBAAgB,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,MAAM,CAAC;CAC3C;AAID;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,UAAU,CAAC,CAqIrB"}
@@ -0,0 +1,168 @@
1
+ // @mostajs/ticketing — Scan processor (core business logic, zero framework coupling)
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ import { decrementQuota } from './quota-manager';
4
+ // ── Main scan processing pipeline ──────────────────────────────────
5
+ /**
6
+ * Process a ticket scan through the 8-step validation pipeline.
7
+ *
8
+ * This is a pure business-logic function with zero coupling to any framework,
9
+ * ORM, or database. All I/O is performed via the injected `deps` callbacks.
10
+ *
11
+ * Steps:
12
+ * 1. Find ticket by code
13
+ * 2. Check ticket status
14
+ * 3. Check validUntil expiry
15
+ * 4. Load client access
16
+ * 5. Check client status
17
+ * 6. Process validity mode (day_reentry / single_use / time_slot / unlimited)
18
+ * 7. Update ticket + access, create scan log
19
+ * 8. Return result
20
+ */
21
+ export async function processScan(code, scanMethod, scannedBy, deps) {
22
+ // 1. Find ticket
23
+ const ticket = await deps.findTicketByCode(code);
24
+ if (!ticket) {
25
+ await deps.createScanLog({
26
+ scannedBy,
27
+ scanMethod,
28
+ result: 'denied',
29
+ denyReason: 'invalid_ticket',
30
+ timestamp: new Date(),
31
+ });
32
+ return { result: 'denied', reason: 'invalid_ticket' };
33
+ }
34
+ const ticketId = deps.resolveId(ticket.id ?? ticket._id);
35
+ // 2. Check ticket status
36
+ if (ticket.status === 'used' && ticket.validityMode !== 'day_reentry') {
37
+ await createDeniedLog(deps, ticket, scannedBy, scanMethod, 'ticket_already_used');
38
+ return { result: 'denied', reason: 'ticket_already_used', ticket: extractTicketInfo(ticket) };
39
+ }
40
+ if (ticket.status === 'expired' || ticket.status === 'cancelled') {
41
+ const reason = `ticket_${ticket.status}`;
42
+ await createDeniedLog(deps, ticket, scannedBy, scanMethod, reason);
43
+ return { result: 'denied', reason, ticket: extractTicketInfo(ticket) };
44
+ }
45
+ // 3. Check validUntil
46
+ if (ticket.validUntil && new Date() > new Date(ticket.validUntil)) {
47
+ await deps.updateTicket(ticketId, { status: 'expired' });
48
+ await createDeniedLog(deps, ticket, scannedBy, scanMethod, 'ticket_expired');
49
+ return { result: 'denied', reason: 'ticket_expired', ticket: extractTicketInfo(ticket) };
50
+ }
51
+ // 4. Load client access
52
+ const accessId = deps.resolveId(ticket.clientAccess);
53
+ const clientAccess = await deps.findAccessById(accessId);
54
+ if (!clientAccess || clientAccess.status !== 'active') {
55
+ const reason = clientAccess?.status === 'depleted' ? 'quota_depleted' : 'access_expired';
56
+ await createDeniedLog(deps, ticket, scannedBy, scanMethod, reason);
57
+ return { result: 'denied', reason, ticket: extractTicketInfo(ticket) };
58
+ }
59
+ // 5. Check client status
60
+ const clientId = deps.resolveId(ticket.client);
61
+ const client = await deps.findClientById(clientId);
62
+ if (!client || client.status !== 'active') {
63
+ await createDeniedLog(deps, ticket, scannedBy, scanMethod, 'client_suspended');
64
+ return { result: 'denied', reason: 'client_suspended', ticket: extractTicketInfo(ticket) };
65
+ }
66
+ // 6. Process validity mode
67
+ const quotaBefore = clientAccess.remainingQuota;
68
+ let quotaAfter = quotaBefore;
69
+ let isReentry = false;
70
+ const ticketUpdates = {};
71
+ const accessUpdates = {};
72
+ switch (ticket.validityMode) {
73
+ case 'single_use':
74
+ case 'time_slot':
75
+ case 'unlimited': {
76
+ ticketUpdates.status = 'used';
77
+ ticketUpdates.scannedAt = new Date();
78
+ ticketUpdates.scannedBy = scannedBy;
79
+ const quota = decrementQuota(clientAccess.remainingQuota);
80
+ if (quota) {
81
+ accessUpdates.remainingQuota = quota.remainingQuota;
82
+ quotaAfter = quota.remainingQuota;
83
+ if (quota.status)
84
+ accessUpdates.status = quota.status;
85
+ }
86
+ break;
87
+ }
88
+ case 'day_reentry': {
89
+ const alreadyToday = await deps.wasScannedToday(ticketId);
90
+ if (alreadyToday) {
91
+ isReentry = true;
92
+ }
93
+ else {
94
+ ticketUpdates.status = 'used';
95
+ const quota = decrementQuota(clientAccess.remainingQuota);
96
+ if (quota) {
97
+ accessUpdates.remainingQuota = quota.remainingQuota;
98
+ quotaAfter = quota.remainingQuota;
99
+ if (quota.status)
100
+ accessUpdates.status = quota.status;
101
+ }
102
+ }
103
+ ticketUpdates.scannedAt = new Date();
104
+ ticketUpdates.scannedBy = scannedBy;
105
+ break;
106
+ }
107
+ }
108
+ // 7. Persist updates + scan log
109
+ await Promise.all([
110
+ Object.keys(ticketUpdates).length > 0 ? deps.updateTicket(ticketId, ticketUpdates) : Promise.resolve(),
111
+ Object.keys(accessUpdates).length > 0 ? deps.updateAccess(clientAccess.id, accessUpdates) : Promise.resolve(),
112
+ ]);
113
+ const activityId = deps.resolveId(ticket.activity);
114
+ await deps.createScanLog({
115
+ ticket: ticketId,
116
+ client: clientId,
117
+ activity: activityId,
118
+ scannedBy,
119
+ scanMethod,
120
+ result: 'granted',
121
+ quotaBefore,
122
+ quotaAfter,
123
+ isReentry,
124
+ timestamp: new Date(),
125
+ });
126
+ // 8. Return granted result
127
+ return {
128
+ result: 'granted',
129
+ isReentry,
130
+ ticket: extractTicketInfo(ticket),
131
+ client: {
132
+ id: clientId,
133
+ name: deps.formatClientName(client),
134
+ clientNumber: client.clientNumber,
135
+ photo: client.photo,
136
+ },
137
+ access: {
138
+ remainingQuota: quotaAfter,
139
+ totalQuota: clientAccess.totalQuota,
140
+ endDate: clientAccess.endDate,
141
+ status: accessUpdates.status || clientAccess.status,
142
+ },
143
+ };
144
+ }
145
+ // ── Helpers ────────────────────────────────────────────────────────
146
+ function extractTicketInfo(ticket) {
147
+ return {
148
+ ticketNumber: ticket.ticketNumber,
149
+ clientName: ticket.clientName,
150
+ activityName: ticket.activityName,
151
+ ticketType: ticket.ticketType,
152
+ validityMode: ticket.validityMode,
153
+ status: ticket.status,
154
+ };
155
+ }
156
+ async function createDeniedLog(deps, ticket, scannedBy, scanMethod, reason) {
157
+ await deps.createScanLog({
158
+ ticket: deps.resolveId(ticket.id ?? ticket._id),
159
+ client: deps.resolveId(ticket.client),
160
+ activity: deps.resolveId(ticket.activity),
161
+ scannedBy,
162
+ scanMethod,
163
+ result: 'denied',
164
+ denyReason: reason,
165
+ timestamp: new Date(),
166
+ });
167
+ }
168
+ //# sourceMappingURL=scan-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-processor.js","sourceRoot":"","sources":["../../lib/scan-processor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { ValidityMode } from '../types/index';
2
+ /**
3
+ * Compute the expiration date for a ticket based on validity mode.
4
+ *
5
+ * - day_reentry → end of current day (23:59:59.999)
6
+ * - time_slot → now + duration minutes
7
+ * - single_use → null (expires on use)
8
+ * - unlimited → null (no expiration)
9
+ */
10
+ export declare function computeValidUntil(mode: ValidityMode, durationMinutes: number | null): Date | null;
11
+ /**
12
+ * Check if a ticket is expired based on its validUntil date.
13
+ */
14
+ export declare function isExpired(validUntil: string | Date | null): boolean;
15
+ /**
16
+ * Check if a timestamp falls within today (since midnight).
17
+ */
18
+ export declare function isToday(date: string | Date): boolean;
19
+ //# sourceMappingURL=validity-checker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validity-checker.d.ts","sourceRoot":"","sources":["../../lib/validity-checker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAiBjG;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,OAAO,CAGnE;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAKpD"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Compute the expiration date for a ticket based on validity mode.
3
+ *
4
+ * - day_reentry → end of current day (23:59:59.999)
5
+ * - time_slot → now + duration minutes
6
+ * - single_use → null (expires on use)
7
+ * - unlimited → null (no expiration)
8
+ */
9
+ export function computeValidUntil(mode, durationMinutes) {
10
+ const now = new Date();
11
+ switch (mode) {
12
+ case 'day_reentry': {
13
+ const end = new Date(now);
14
+ end.setHours(23, 59, 59, 999);
15
+ return end;
16
+ }
17
+ case 'time_slot': {
18
+ if (!durationMinutes)
19
+ return null;
20
+ return new Date(now.getTime() + durationMinutes * 60_000);
21
+ }
22
+ case 'single_use':
23
+ case 'unlimited':
24
+ default:
25
+ return null;
26
+ }
27
+ }
28
+ /**
29
+ * Check if a ticket is expired based on its validUntil date.
30
+ */
31
+ export function isExpired(validUntil) {
32
+ if (!validUntil)
33
+ return false;
34
+ return new Date() > new Date(validUntil);
35
+ }
36
+ /**
37
+ * Check if a timestamp falls within today (since midnight).
38
+ */
39
+ export function isToday(date) {
40
+ const d = new Date(date);
41
+ const start = new Date();
42
+ start.setHours(0, 0, 0, 0);
43
+ return d >= start;
44
+ }
45
+ //# sourceMappingURL=validity-checker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validity-checker.js","sourceRoot":"","sources":["../../lib/validity-checker.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAkB,EAAE,eAA8B;IAClF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;YAC1B,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;YAC9B,OAAO,GAAG,CAAC;QACb,CAAC;QACD,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,IAAI,CAAC,eAAe;gBAAE,OAAO,IAAI,CAAC;YAClC,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,eAAe,GAAG,MAAM,CAAC,CAAC;QAC5D,CAAC;QACD,KAAK,YAAY,CAAC;QAClB,KAAK,WAAW,CAAC;QACjB;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,UAAgC;IACxD,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9B,OAAO,IAAI,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,IAAmB;IACzC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;IACzB,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3B,OAAO,CAAC,IAAI,KAAK,CAAC;AACpB,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { BaseRepository } from '@mostajs/orm';
2
+ import type { IDialect } from '@mostajs/orm';
3
+ export interface ActivityScheduleDTO {
4
+ dayOfWeek: number;
5
+ openTime: string;
6
+ closeTime: string;
7
+ isOpen: boolean;
8
+ }
9
+ export interface ActivityDTO {
10
+ id: string;
11
+ name: string;
12
+ slug: string;
13
+ description?: string;
14
+ icon?: string;
15
+ color?: string;
16
+ capacity?: number;
17
+ currentOccupancy: number;
18
+ schedule: ActivityScheduleDTO[];
19
+ ticketValidityMode: 'day_reentry' | 'single_use' | 'time_slot' | 'unlimited';
20
+ ticketDuration: number | null;
21
+ price: number;
22
+ currency: string;
23
+ status: 'active' | 'inactive' | 'maintenance';
24
+ sortOrder: number;
25
+ createdBy?: string;
26
+ createdAt: string;
27
+ updatedAt: string;
28
+ }
29
+ export declare class ActivityRepository extends BaseRepository<ActivityDTO> {
30
+ constructor(dialect: IDialect);
31
+ /** Find all sorted by sortOrder then name */
32
+ findAllOrdered(): Promise<ActivityDTO[]>;
33
+ /** Find by slug (unique) */
34
+ findBySlug(slug: string): Promise<ActivityDTO | null>;
35
+ /** Find active activities only */
36
+ findActive(): Promise<ActivityDTO[]>;
37
+ }
38
+ //# sourceMappingURL=activity.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.repository.d.ts","sourceRoot":"","sources":["../../repositories/activity.repository.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,kBAAkB,EAAE,aAAa,GAAG,YAAY,GAAG,WAAW,GAAG,WAAW,CAAC;IAC7E,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,aAAa,CAAC;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,kBAAmB,SAAQ,cAAc,CAAC,WAAW,CAAC;gBACrD,OAAO,EAAE,QAAQ;IAI7B,6CAA6C;IACvC,cAAc,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAI9C,4BAA4B;IACtB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAI3D,kCAAkC;IAC5B,UAAU,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;CAG3C"}
@@ -0,0 +1,23 @@
1
+ // ActivityRepository
2
+ // @mostajs/ticketing
3
+ // Author: Dr Hamid MADANI drmdh@msn.com
4
+ import { BaseRepository } from '@mostajs/orm';
5
+ import { ActivitySchema } from '../schemas/activity.schema';
6
+ export class ActivityRepository extends BaseRepository {
7
+ constructor(dialect) {
8
+ super(ActivitySchema, dialect);
9
+ }
10
+ /** Find all sorted by sortOrder then name */
11
+ async findAllOrdered() {
12
+ return this.findAll({}, { sort: { sortOrder: 1, name: 1 } });
13
+ }
14
+ /** Find by slug (unique) */
15
+ async findBySlug(slug) {
16
+ return this.findOne({ slug });
17
+ }
18
+ /** Find active activities only */
19
+ async findActive() {
20
+ return this.findAll({ status: 'active' }, { sort: { sortOrder: 1 } });
21
+ }
22
+ }
23
+ //# sourceMappingURL=activity.repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity.repository.js","sourceRoot":"","sources":["../../repositories/activity.repository.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,qBAAqB;AACrB,wCAAwC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AA+B5D,MAAM,OAAO,kBAAmB,SAAQ,cAA2B;IACjE,YAAY,OAAiB;QAC3B,KAAK,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,6CAA6C;IAC7C,KAAK,CAAC,cAAc;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,4BAA4B;IAC5B,KAAK,CAAC,UAAU,CAAC,IAAY;QAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,kCAAkC;IAClC,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACxE,CAAC;CACF"}
@@ -0,0 +1,31 @@
1
+ import { BaseRepository } from '@mostajs/orm';
2
+ import type { IDialect } from '@mostajs/orm';
3
+ export interface ClientAccessDTO {
4
+ id: string;
5
+ client: any;
6
+ plan: any;
7
+ activity: any;
8
+ accessType: 'unlimited' | 'count' | 'temporal' | 'mixed';
9
+ totalQuota: number | null;
10
+ remainingQuota: number | null;
11
+ startDate: string;
12
+ endDate: string | null;
13
+ status: 'active' | 'expired' | 'blocked' | 'depleted';
14
+ createdBy: string;
15
+ createdAt: string;
16
+ updatedAt: string;
17
+ }
18
+ export declare class ClientAccessRepository extends BaseRepository<ClientAccessDTO> {
19
+ constructor(dialect: IDialect);
20
+ /** Find all accesses for a client with activity & plan populated */
21
+ findByClient(clientId: string): Promise<ClientAccessDTO[]>;
22
+ /** Find active access for a client + activity */
23
+ findActiveAccess(clientId: string, activityId: string): Promise<ClientAccessDTO | null>;
24
+ /** Find blocked access for a client + activity (for reactivation) */
25
+ findBlockedAccess(clientId: string, activityId: string): Promise<ClientAccessDTO | null>;
26
+ /** Decrement remaining quota by 1 */
27
+ decrementQuota(id: string): Promise<ClientAccessDTO | null>;
28
+ /** Soft-block an access */
29
+ block(id: string): Promise<ClientAccessDTO | null>;
30
+ }
31
+ //# sourceMappingURL=client-access.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-access.repository.d.ts","sourceRoot":"","sources":["../../repositories/client-access.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,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,GAAG,CAAC;IACZ,IAAI,EAAE,GAAG,CAAC;IACV,QAAQ,EAAE,GAAG,CAAC;IACd,UAAU,EAAE,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;IACzD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,sBAAuB,SAAQ,cAAc,CAAC,eAAe,CAAC;gBAC7D,OAAO,EAAE,QAAQ;IAI7B,oEAAoE;IAC9D,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAQhE,iDAAiD;IAC3C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAI7F,qEAAqE;IAC/D,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAI9F,qCAAqC;IAC/B,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAIjE,2BAA2B;IACrB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;CAGzD"}
@@ -0,0 +1,31 @@
1
+ // ClientAccessRepository
2
+ // @mostajs/ticketing
3
+ // Author: Dr Hamid MADANI drmdh@msn.com
4
+ import { BaseRepository } from '@mostajs/orm';
5
+ import { ClientAccessSchema } from '../schemas/client-access.schema';
6
+ export class ClientAccessRepository extends BaseRepository {
7
+ constructor(dialect) {
8
+ super(ClientAccessSchema, dialect);
9
+ }
10
+ /** Find all accesses for a client with activity & plan populated */
11
+ async findByClient(clientId) {
12
+ return this.findWithRelations({ client: clientId }, ['activity', 'plan'], { sort: { createdAt: -1 } });
13
+ }
14
+ /** Find active access for a client + activity */
15
+ async findActiveAccess(clientId, activityId) {
16
+ return this.findOne({ client: clientId, activity: activityId, status: 'active' });
17
+ }
18
+ /** Find blocked access for a client + activity (for reactivation) */
19
+ async findBlockedAccess(clientId, activityId) {
20
+ return this.findOne({ client: clientId, activity: activityId, status: 'blocked' });
21
+ }
22
+ /** Decrement remaining quota by 1 */
23
+ async decrementQuota(id) {
24
+ return this.increment(id, 'remainingQuota', -1);
25
+ }
26
+ /** Soft-block an access */
27
+ async block(id) {
28
+ return this.update(id, { status: 'blocked' });
29
+ }
30
+ }
31
+ //# sourceMappingURL=client-access.repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-access.repository.js","sourceRoot":"","sources":["../../repositories/client-access.repository.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,qBAAqB;AACrB,wCAAwC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAmBrE,MAAM,OAAO,sBAAuB,SAAQ,cAA+B;IACzE,YAAY,OAAiB;QAC3B,KAAK,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,oEAAoE;IACpE,KAAK,CAAC,YAAY,CAAC,QAAgB;QACjC,OAAO,IAAI,CAAC,iBAAiB,CAC3B,EAAE,MAAM,EAAE,QAAQ,EAAE,EACpB,CAAC,UAAU,EAAE,MAAM,CAAC,EACpB,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAC5B,CAAC;IACJ,CAAC;IAED,iDAAiD;IACjD,KAAK,CAAC,gBAAgB,CAAC,QAAgB,EAAE,UAAkB;QACzD,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,qEAAqE;IACrE,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAC1D,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,qCAAqC;IACrC,KAAK,CAAC,cAAc,CAAC,EAAU;QAC7B,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,2BAA2B;IAC3B,KAAK,CAAC,KAAK,CAAC,EAAU;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAS,CAAC,CAAC;IACvD,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ export { TicketRepository } from './ticket.repository';
2
+ export type { TicketDTO } from './ticket.repository';
3
+ export { ClientAccessRepository } from './client-access.repository';
4
+ export type { ClientAccessDTO } from './client-access.repository';
5
+ export { ScanLogRepository } from './scan-log.repository';
6
+ export type { ScanLogDTO } from './scan-log.repository';
7
+ export { SubscriptionPlanRepository } from './subscription-plan.repository';
8
+ export type { SubscriptionPlanDTO, PlanActivityDTO } from './subscription-plan.repository';
9
+ export { ActivityRepository } from './activity.repository';
10
+ export type { ActivityDTO, ActivityScheduleDTO } from './activity.repository';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../repositories/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,YAAY,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAElE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAC5E,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAE3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,YAAY,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,8 @@
1
+ // @mostajs/ticketing — Repositories barrel
2
+ // Author: Dr Hamid MADANI drmdh@msn.com
3
+ export { TicketRepository } from './ticket.repository';
4
+ export { ClientAccessRepository } from './client-access.repository';
5
+ export { ScanLogRepository } from './scan-log.repository';
6
+ export { SubscriptionPlanRepository } from './subscription-plan.repository';
7
+ export { ActivityRepository } from './activity.repository';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../repositories/index.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,wCAAwC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAGpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,gCAAgC,CAAC;AAG5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { BaseRepository } from '@mostajs/orm';
2
+ import type { IDialect, QueryOptions } from '@mostajs/orm';
3
+ export interface ScanLogDTO {
4
+ id: string;
5
+ ticket: any;
6
+ client: any;
7
+ activity: any;
8
+ scannedBy: any;
9
+ scanMethod: string;
10
+ result: 'granted' | 'denied';
11
+ denyReason: string | null;
12
+ quotaBefore: number | null;
13
+ quotaAfter: number | null;
14
+ isReentry: boolean;
15
+ timestamp: string;
16
+ }
17
+ export declare class ScanLogRepository extends BaseRepository<ScanLogDTO> {
18
+ constructor(dialect: IDialect);
19
+ /** Find recent scan logs with ticket & scannedBy populated */
20
+ findRecent(filter?: Record<string, unknown>, options?: QueryOptions): Promise<ScanLogDTO[]>;
21
+ /** Find scan history for a specific client */
22
+ findByClient(clientId: string, options?: QueryOptions): Promise<ScanLogDTO[]>;
23
+ /** Count all scans for today */
24
+ countToday(): Promise<number>;
25
+ /** Count granted scans for today */
26
+ countGrantedToday(): Promise<number>;
27
+ /** Get distinct clients with granted scans today (visitors present) */
28
+ findDistinctClientsToday(): Promise<unknown[]>;
29
+ /** Check if a ticket was already scanned today (for day_reentry) */
30
+ wasScannedToday(ticketId: string): Promise<boolean>;
31
+ }
32
+ //# sourceMappingURL=scan-log.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-log.repository.d.ts","sourceRoot":"","sources":["../../repositories/scan-log.repository.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,GAAG,CAAC;IACZ,MAAM,EAAE,GAAG,CAAC;IACZ,QAAQ,EAAE,GAAG,CAAC;IACd,SAAS,EAAE,GAAG,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,UAAU,CAAC;gBACnD,OAAO,EAAE,QAAQ;IAI7B,8DAA8D;IACxD,UAAU,CAAC,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAQrG,8CAA8C;IACxC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAQnF,gCAAgC;IAC1B,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAMnC,oCAAoC;IAC9B,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAM1C,uEAAuE;IACjE,wBAAwB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAMpD,oEAAoE;IAC9D,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAU1D"}