@blackcode_sa/metaestetics-api 1.15.14 → 1.15.17

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 (42) hide show
  1. package/dist/admin/index.d.mts +377 -222
  2. package/dist/admin/index.d.ts +377 -222
  3. package/dist/admin/index.js +625 -206
  4. package/dist/admin/index.mjs +624 -206
  5. package/dist/backoffice/index.d.mts +24 -0
  6. package/dist/backoffice/index.d.ts +24 -0
  7. package/dist/index.d.mts +376 -9
  8. package/dist/index.d.ts +376 -9
  9. package/dist/index.js +2228 -1581
  10. package/dist/index.mjs +1544 -892
  11. package/package.json +1 -1
  12. package/src/admin/aggregation/appointment/README.md +24 -2
  13. package/src/admin/aggregation/appointment/appointment.aggregation.service.ts +46 -0
  14. package/src/admin/booking/README.md +61 -2
  15. package/src/admin/booking/booking.admin.ts +257 -0
  16. package/src/admin/booking/booking.calculator.ts +139 -1
  17. package/src/admin/booking/booking.types.ts +17 -0
  18. package/src/admin/calendar/README.md +56 -1
  19. package/src/admin/calendar/index.ts +1 -0
  20. package/src/admin/calendar/resource-calendar.admin.ts +198 -0
  21. package/src/config/index.ts +1 -0
  22. package/src/config/tiers.config.ts +121 -5
  23. package/src/services/index.ts +1 -0
  24. package/src/services/plan-config.service.ts +55 -0
  25. package/src/services/resource/README.md +119 -0
  26. package/src/services/resource/index.ts +1 -0
  27. package/src/services/resource/resource.service.ts +555 -0
  28. package/src/services/tier-enforcement.ts +16 -11
  29. package/src/types/appointment/index.ts +7 -0
  30. package/src/types/calendar/index.ts +1 -0
  31. package/src/types/clinic/index.ts +1 -0
  32. package/src/types/clinic/rbac.types.ts +3 -2
  33. package/src/types/index.ts +6 -0
  34. package/src/types/procedure/index.ts +6 -0
  35. package/src/types/resource/README.md +153 -0
  36. package/src/types/resource/index.ts +199 -0
  37. package/src/types/system/index.ts +1 -0
  38. package/src/types/system/planConfig.types.ts +86 -0
  39. package/src/validations/README.md +94 -0
  40. package/src/validations/index.ts +1 -0
  41. package/src/validations/procedure.schema.ts +12 -0
  42. package/src/validations/resource.schema.ts +57 -0
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Plan Config Service — reads `system/planConfig` from Firestore with caching.
3
+ * Uses the Firebase client SDK (same as tier-enforcement.ts).
4
+ * Falls back to DEFAULT_PLAN_CONFIG if the document doesn't exist.
5
+ */
6
+ import { Firestore, doc, getDoc } from 'firebase/firestore';
7
+ import { DEFAULT_PLAN_CONFIG } from '../config/tiers.config';
8
+ import type { PlanConfigDocument } from '../types/system/planConfig.types';
9
+ import { PLAN_CONFIG_PATH } from '../types/system/planConfig.types';
10
+
11
+ const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
12
+
13
+ class PlanConfigService {
14
+ private cachedConfig: PlanConfigDocument | null = null;
15
+ private cacheExpiry = 0;
16
+
17
+ /**
18
+ * Returns the current plan config, reading from Firestore if the cache
19
+ * has expired. Falls back to DEFAULT_PLAN_CONFIG if the doc is missing.
20
+ */
21
+ async getConfig(db: Firestore): Promise<PlanConfigDocument> {
22
+ const now = Date.now();
23
+ if (this.cachedConfig && now < this.cacheExpiry) {
24
+ return this.cachedConfig;
25
+ }
26
+
27
+ try {
28
+ const [collectionPath, docId] = PLAN_CONFIG_PATH.split('/');
29
+ const configRef = doc(db, collectionPath, docId);
30
+ const snap = await getDoc(configRef);
31
+
32
+ if (snap.exists()) {
33
+ this.cachedConfig = snap.data() as PlanConfigDocument;
34
+ } else {
35
+ this.cachedConfig = DEFAULT_PLAN_CONFIG;
36
+ }
37
+ } catch (error) {
38
+ console.error('PlanConfigService: Firestore read failed, using fallback config', error);
39
+ if (!this.cachedConfig) {
40
+ this.cachedConfig = DEFAULT_PLAN_CONFIG;
41
+ }
42
+ }
43
+
44
+ this.cacheExpiry = now + CACHE_TTL_MS;
45
+ return this.cachedConfig;
46
+ }
47
+
48
+ /** Clears the cache — useful for testing or after config updates. */
49
+ invalidateCache(): void {
50
+ this.cachedConfig = null;
51
+ this.cacheExpiry = 0;
52
+ }
53
+ }
54
+
55
+ export const planConfigService = new PlanConfigService();
@@ -0,0 +1,119 @@
1
+ # Resource Service (`Api/src/services/resource/`)
2
+
3
+ Server-side service for managing clinic resources and their instances. Extends `BaseService` and provides full CRUD operations backed by Firestore.
4
+
5
+ ## File: `resource.service.ts`
6
+
7
+ ### Class: `ResourceService extends BaseService`
8
+
9
+ #### Constructor
10
+
11
+ ```typescript
12
+ constructor(db: Firestore, auth: Auth, app: FirebaseApp)
13
+ ```
14
+
15
+ Inherits Firestore, Auth, and Firebase App from `BaseService`.
16
+
17
+ ---
18
+
19
+ ### Methods
20
+
21
+ #### `createResource(data: CreateResourceData): Promise<Resource>`
22
+
23
+ Creates a new resource and auto-generates instances.
24
+
25
+ - Validates input with `createResourceSchema` (Zod)
26
+ - Creates the `Resource` document under `clinics/{clinicBranchId}/resources/{id}`
27
+ - Batch-creates `N` `ResourceInstance` subdocuments (where N = `data.quantity`)
28
+ - Each instance gets label `"{name} #{index}"` (1-based)
29
+ - Returns the created `Resource`
30
+
31
+ #### `getResource(clinicBranchId: string, resourceId: string): Promise<Resource | null>`
32
+
33
+ Fetches a single resource by ID.
34
+
35
+ #### `getResourcesByClinic(clinicBranchId: string): Promise<Resource[]>`
36
+
37
+ Fetches all resources for a clinic branch.
38
+
39
+ #### `getActiveResourcesByClinic(clinicBranchId: string): Promise<Resource[]>`
40
+
41
+ Fetches only active resources (`status === 'active'`) for a clinic branch.
42
+
43
+ #### `updateResource(clinicBranchId: string, resourceId: string, data: UpdateResourceData): Promise<Resource>`
44
+
45
+ Updates a resource. Handles quantity changes:
46
+
47
+ - **Quantity increase**: Creates new instances starting from `currentQuantity + 1`
48
+ - **Quantity decrease**: Checks if affected instances (from the end) have future bookings. If any do, the operation is **rejected** with an error. Otherwise, instances are deactivated (status set to `inactive`).
49
+
50
+ #### `deleteResource(clinicBranchId: string, resourceId: string): Promise<void>`
51
+
52
+ Soft-deletes a resource by setting `status: 'inactive'`. Does not remove documents from Firestore.
53
+
54
+ #### `getResourceInstances(clinicBranchId: string, resourceId: string): Promise<ResourceInstance[]>`
55
+
56
+ Fetches all instances for a resource, ordered by `index`.
57
+
58
+ #### `getActiveResourceInstances(clinicBranchId: string, resourceId: string): Promise<ResourceInstance[]>`
59
+
60
+ Fetches only active instances (`status === 'active'`), ordered by `index`.
61
+
62
+ #### `getResourceCalendarEvents(clinicBranchId, resourceId, instanceId, start, end): Promise<ResourceCalendarEvent[]>`
63
+
64
+ Fetches calendar events for a specific instance within a time range. Used by the booking engine to check instance availability.
65
+
66
+ #### `instanceHasFutureBookings(clinicBranchId, resourceId, instanceId): Promise<boolean>`
67
+
68
+ Checks if an instance has any future booking events. Used when decreasing resource quantity to prevent deactivating instances with active bookings.
69
+
70
+ ---
71
+
72
+ ### Blocking Event Methods
73
+
74
+ CRUD operations for managing blocking events on resource instance calendars. Blocking events mark an instance as unavailable for a time period (maintenance, out of order, etc.).
75
+
76
+ #### `createResourceBlockingEvent(params: CreateResourceBlockingEventParams): Promise<ResourceCalendarEvent>`
77
+
78
+ Creates a blocking event on an instance's calendar.
79
+
80
+ - Validates input with `createResourceBlockingEventSchema` (Zod)
81
+ - Creates document at `clinics/{clinicBranchId}/resources/{resourceId}/instances/{instanceId}/calendar/{eventId}`
82
+ - Sets `eventType: BLOCKING`, `status: CONFIRMED`
83
+ - Appointment-specific fields are omitted
84
+
85
+ #### `updateResourceBlockingEvent(params: UpdateResourceBlockingEventParams): Promise<ResourceCalendarEvent>`
86
+
87
+ Updates an existing blocking event. Only provided fields are modified.
88
+
89
+ - Validates input with `updateResourceBlockingEventSchema`
90
+ - Verifies event exists before updating
91
+ - Returns the updated event
92
+
93
+ #### `deleteResourceBlockingEvent(clinicBranchId, resourceId, instanceId, eventId): Promise<void>`
94
+
95
+ Hard deletes a blocking event from the instance's calendar.
96
+
97
+ - Verifies event exists before deleting
98
+
99
+ #### `getResourceInstanceBlockingEvents(clinicBranchId, resourceId, instanceId): Promise<ResourceCalendarEvent[]>`
100
+
101
+ Fetches all blocking events for a specific instance, ordered by start time. Filters by `eventType == "blocking"`.
102
+
103
+ ---
104
+
105
+ ### Firestore Paths
106
+
107
+ | Entity | Path |
108
+ |--------|------|
109
+ | Resource | `clinics/{clinicBranchId}/resources/{resourceId}` |
110
+ | Instance | `clinics/{clinicBranchId}/resources/{resourceId}/instances/{instanceId}` |
111
+ | Calendar Event | `clinics/{clinicBranchId}/resources/{resourceId}/instances/{instanceId}/calendar/{eventId}` |
112
+
113
+ ---
114
+
115
+ ### Export
116
+
117
+ `index.ts` re-exports `ResourceService` from `resource.service.ts`. The service is also exported via `Api/src/services/index.ts`.
118
+
119
+ See [main Resource System README](../../../../docs/RESOURCE_SYSTEM.md) for the full system overview.
@@ -0,0 +1 @@
1
+ export * from "./resource.service";