@blackcode_sa/metaestetics-api 1.15.17-staging.7 → 1.15.17-staging.8
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/dist/index.d.mts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +67 -11
- package/dist/index.mjs +67 -11
- package/package.json +1 -1
- package/src/services/resource/resource.service.ts +85 -16
package/dist/index.d.mts
CHANGED
|
@@ -10113,6 +10113,11 @@ declare class ResourceService extends BaseService {
|
|
|
10113
10113
|
* Soft deletes a resource by setting status to INACTIVE
|
|
10114
10114
|
*/
|
|
10115
10115
|
deleteResource(clinicBranchId: string, resourceId: string): Promise<void>;
|
|
10116
|
+
/**
|
|
10117
|
+
* Hard deletes a specific instance and all its calendar events.
|
|
10118
|
+
* Only works on INACTIVE instances with no future bookings.
|
|
10119
|
+
*/
|
|
10120
|
+
hardDeleteInstance(clinicBranchId: string, resourceId: string, instanceId: string): Promise<void>;
|
|
10116
10121
|
/**
|
|
10117
10122
|
* Gets all instances for a resource
|
|
10118
10123
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -10113,6 +10113,11 @@ declare class ResourceService extends BaseService {
|
|
|
10113
10113
|
* Soft deletes a resource by setting status to INACTIVE
|
|
10114
10114
|
*/
|
|
10115
10115
|
deleteResource(clinicBranchId: string, resourceId: string): Promise<void>;
|
|
10116
|
+
/**
|
|
10117
|
+
* Hard deletes a specific instance and all its calendar events.
|
|
10118
|
+
* Only works on INACTIVE instances with no future bookings.
|
|
10119
|
+
*/
|
|
10120
|
+
hardDeleteInstance(clinicBranchId: string, resourceId: string, instanceId: string): Promise<void>;
|
|
10116
10121
|
/**
|
|
10117
10122
|
* Gets all instances for a resource
|
|
10118
10123
|
*/
|
package/dist/index.js
CHANGED
|
@@ -25151,24 +25151,46 @@ var ResourceService = class extends BaseService {
|
|
|
25151
25151
|
if (data.status !== void 0) updateData.status = data.status;
|
|
25152
25152
|
if (data.quantity !== void 0 && data.quantity !== existing.quantity) {
|
|
25153
25153
|
if (data.quantity > existing.quantity) {
|
|
25154
|
+
const allInstances = await this.getResourceInstances(clinicBranchId, resourceId);
|
|
25155
|
+
const activeInstances = allInstances.filter((i) => i.status === "active" /* ACTIVE */);
|
|
25156
|
+
const inactiveInstances = allInstances.filter((i) => i.status === "inactive" /* INACTIVE */);
|
|
25157
|
+
const needed = data.quantity - activeInstances.length;
|
|
25154
25158
|
const batch = (0, import_firestore65.writeBatch)(this.db);
|
|
25155
25159
|
const now = (0, import_firestore65.serverTimestamp)();
|
|
25156
25160
|
const resourceName = data.name || existing.name;
|
|
25157
|
-
|
|
25161
|
+
let reactivated = 0;
|
|
25162
|
+
const sortedInactive = [...inactiveInstances].sort((a, b) => a.index - b.index);
|
|
25163
|
+
for (const instance of sortedInactive) {
|
|
25164
|
+
if (reactivated >= needed) break;
|
|
25158
25165
|
const instanceRef = (0, import_firestore65.doc)(
|
|
25159
|
-
this.getInstancesRef(clinicBranchId, resourceId)
|
|
25166
|
+
this.getInstancesRef(clinicBranchId, resourceId),
|
|
25167
|
+
instance.id
|
|
25160
25168
|
);
|
|
25161
|
-
|
|
25162
|
-
id: instanceRef.id,
|
|
25163
|
-
resourceId,
|
|
25164
|
-
clinicBranchId,
|
|
25165
|
-
label: `${resourceName} #${i}`,
|
|
25166
|
-
index: i,
|
|
25169
|
+
batch.update(instanceRef, {
|
|
25167
25170
|
status: "active" /* ACTIVE */,
|
|
25168
|
-
createdAt: now,
|
|
25169
25171
|
updatedAt: now
|
|
25170
|
-
};
|
|
25171
|
-
|
|
25172
|
+
});
|
|
25173
|
+
reactivated++;
|
|
25174
|
+
}
|
|
25175
|
+
const remaining = needed - reactivated;
|
|
25176
|
+
if (remaining > 0) {
|
|
25177
|
+
const maxIndex = allInstances.reduce((max, i) => Math.max(max, i.index), 0);
|
|
25178
|
+
for (let i = 1; i <= remaining; i++) {
|
|
25179
|
+
const instanceRef = (0, import_firestore65.doc)(
|
|
25180
|
+
this.getInstancesRef(clinicBranchId, resourceId)
|
|
25181
|
+
);
|
|
25182
|
+
const instanceData = {
|
|
25183
|
+
id: instanceRef.id,
|
|
25184
|
+
resourceId,
|
|
25185
|
+
clinicBranchId,
|
|
25186
|
+
label: `${resourceName} #${maxIndex + i}`,
|
|
25187
|
+
index: maxIndex + i,
|
|
25188
|
+
status: "active" /* ACTIVE */,
|
|
25189
|
+
createdAt: now,
|
|
25190
|
+
updatedAt: now
|
|
25191
|
+
};
|
|
25192
|
+
batch.set(instanceRef, instanceData);
|
|
25193
|
+
}
|
|
25172
25194
|
}
|
|
25173
25195
|
updateData.quantity = data.quantity;
|
|
25174
25196
|
const resourceDocRef2 = this.getResourceDocRef(
|
|
@@ -25235,6 +25257,40 @@ var ResourceService = class extends BaseService {
|
|
|
25235
25257
|
status: "inactive" /* INACTIVE */
|
|
25236
25258
|
});
|
|
25237
25259
|
}
|
|
25260
|
+
/**
|
|
25261
|
+
* Hard deletes a specific instance and all its calendar events.
|
|
25262
|
+
* Only works on INACTIVE instances with no future bookings.
|
|
25263
|
+
*/
|
|
25264
|
+
async hardDeleteInstance(clinicBranchId, resourceId, instanceId) {
|
|
25265
|
+
const instanceRef = (0, import_firestore65.doc)(
|
|
25266
|
+
this.getInstancesRef(clinicBranchId, resourceId),
|
|
25267
|
+
instanceId
|
|
25268
|
+
);
|
|
25269
|
+
const instanceSnap = await (0, import_firestore65.getDoc)(instanceRef);
|
|
25270
|
+
if (!instanceSnap.exists()) throw new Error("Instance not found");
|
|
25271
|
+
const instance = instanceSnap.data();
|
|
25272
|
+
if (instance.status === "active" /* ACTIVE */) {
|
|
25273
|
+
throw new Error("Cannot hard-delete an active instance. Deactivate it first.");
|
|
25274
|
+
}
|
|
25275
|
+
const hasFutureBookings = await this.instanceHasFutureBookings(
|
|
25276
|
+
clinicBranchId,
|
|
25277
|
+
resourceId,
|
|
25278
|
+
instanceId
|
|
25279
|
+
);
|
|
25280
|
+
if (hasFutureBookings) {
|
|
25281
|
+
throw new Error("Cannot delete instance with future bookings.");
|
|
25282
|
+
}
|
|
25283
|
+
const calendarRef = this.getInstanceCalendarRef(
|
|
25284
|
+
clinicBranchId,
|
|
25285
|
+
resourceId,
|
|
25286
|
+
instanceId
|
|
25287
|
+
);
|
|
25288
|
+
const calendarSnap = await (0, import_firestore65.getDocs)(calendarRef);
|
|
25289
|
+
const batch = (0, import_firestore65.writeBatch)(this.db);
|
|
25290
|
+
calendarSnap.docs.forEach((d) => batch.delete(d.ref));
|
|
25291
|
+
batch.delete(instanceRef);
|
|
25292
|
+
await batch.commit();
|
|
25293
|
+
}
|
|
25238
25294
|
/**
|
|
25239
25295
|
* Gets all instances for a resource
|
|
25240
25296
|
*/
|
package/dist/index.mjs
CHANGED
|
@@ -25384,24 +25384,46 @@ var ResourceService = class extends BaseService {
|
|
|
25384
25384
|
if (data.status !== void 0) updateData.status = data.status;
|
|
25385
25385
|
if (data.quantity !== void 0 && data.quantity !== existing.quantity) {
|
|
25386
25386
|
if (data.quantity > existing.quantity) {
|
|
25387
|
+
const allInstances = await this.getResourceInstances(clinicBranchId, resourceId);
|
|
25388
|
+
const activeInstances = allInstances.filter((i) => i.status === "active" /* ACTIVE */);
|
|
25389
|
+
const inactiveInstances = allInstances.filter((i) => i.status === "inactive" /* INACTIVE */);
|
|
25390
|
+
const needed = data.quantity - activeInstances.length;
|
|
25387
25391
|
const batch = writeBatch7(this.db);
|
|
25388
25392
|
const now = serverTimestamp36();
|
|
25389
25393
|
const resourceName = data.name || existing.name;
|
|
25390
|
-
|
|
25394
|
+
let reactivated = 0;
|
|
25395
|
+
const sortedInactive = [...inactiveInstances].sort((a, b) => a.index - b.index);
|
|
25396
|
+
for (const instance of sortedInactive) {
|
|
25397
|
+
if (reactivated >= needed) break;
|
|
25391
25398
|
const instanceRef = doc46(
|
|
25392
|
-
this.getInstancesRef(clinicBranchId, resourceId)
|
|
25399
|
+
this.getInstancesRef(clinicBranchId, resourceId),
|
|
25400
|
+
instance.id
|
|
25393
25401
|
);
|
|
25394
|
-
|
|
25395
|
-
id: instanceRef.id,
|
|
25396
|
-
resourceId,
|
|
25397
|
-
clinicBranchId,
|
|
25398
|
-
label: `${resourceName} #${i}`,
|
|
25399
|
-
index: i,
|
|
25402
|
+
batch.update(instanceRef, {
|
|
25400
25403
|
status: "active" /* ACTIVE */,
|
|
25401
|
-
createdAt: now,
|
|
25402
25404
|
updatedAt: now
|
|
25403
|
-
};
|
|
25404
|
-
|
|
25405
|
+
});
|
|
25406
|
+
reactivated++;
|
|
25407
|
+
}
|
|
25408
|
+
const remaining = needed - reactivated;
|
|
25409
|
+
if (remaining > 0) {
|
|
25410
|
+
const maxIndex = allInstances.reduce((max, i) => Math.max(max, i.index), 0);
|
|
25411
|
+
for (let i = 1; i <= remaining; i++) {
|
|
25412
|
+
const instanceRef = doc46(
|
|
25413
|
+
this.getInstancesRef(clinicBranchId, resourceId)
|
|
25414
|
+
);
|
|
25415
|
+
const instanceData = {
|
|
25416
|
+
id: instanceRef.id,
|
|
25417
|
+
resourceId,
|
|
25418
|
+
clinicBranchId,
|
|
25419
|
+
label: `${resourceName} #${maxIndex + i}`,
|
|
25420
|
+
index: maxIndex + i,
|
|
25421
|
+
status: "active" /* ACTIVE */,
|
|
25422
|
+
createdAt: now,
|
|
25423
|
+
updatedAt: now
|
|
25424
|
+
};
|
|
25425
|
+
batch.set(instanceRef, instanceData);
|
|
25426
|
+
}
|
|
25405
25427
|
}
|
|
25406
25428
|
updateData.quantity = data.quantity;
|
|
25407
25429
|
const resourceDocRef2 = this.getResourceDocRef(
|
|
@@ -25468,6 +25490,40 @@ var ResourceService = class extends BaseService {
|
|
|
25468
25490
|
status: "inactive" /* INACTIVE */
|
|
25469
25491
|
});
|
|
25470
25492
|
}
|
|
25493
|
+
/**
|
|
25494
|
+
* Hard deletes a specific instance and all its calendar events.
|
|
25495
|
+
* Only works on INACTIVE instances with no future bookings.
|
|
25496
|
+
*/
|
|
25497
|
+
async hardDeleteInstance(clinicBranchId, resourceId, instanceId) {
|
|
25498
|
+
const instanceRef = doc46(
|
|
25499
|
+
this.getInstancesRef(clinicBranchId, resourceId),
|
|
25500
|
+
instanceId
|
|
25501
|
+
);
|
|
25502
|
+
const instanceSnap = await getDoc47(instanceRef);
|
|
25503
|
+
if (!instanceSnap.exists()) throw new Error("Instance not found");
|
|
25504
|
+
const instance = instanceSnap.data();
|
|
25505
|
+
if (instance.status === "active" /* ACTIVE */) {
|
|
25506
|
+
throw new Error("Cannot hard-delete an active instance. Deactivate it first.");
|
|
25507
|
+
}
|
|
25508
|
+
const hasFutureBookings = await this.instanceHasFutureBookings(
|
|
25509
|
+
clinicBranchId,
|
|
25510
|
+
resourceId,
|
|
25511
|
+
instanceId
|
|
25512
|
+
);
|
|
25513
|
+
if (hasFutureBookings) {
|
|
25514
|
+
throw new Error("Cannot delete instance with future bookings.");
|
|
25515
|
+
}
|
|
25516
|
+
const calendarRef = this.getInstanceCalendarRef(
|
|
25517
|
+
clinicBranchId,
|
|
25518
|
+
resourceId,
|
|
25519
|
+
instanceId
|
|
25520
|
+
);
|
|
25521
|
+
const calendarSnap = await getDocs35(calendarRef);
|
|
25522
|
+
const batch = writeBatch7(this.db);
|
|
25523
|
+
calendarSnap.docs.forEach((d) => batch.delete(d.ref));
|
|
25524
|
+
batch.delete(instanceRef);
|
|
25525
|
+
await batch.commit();
|
|
25526
|
+
}
|
|
25471
25527
|
/**
|
|
25472
25528
|
* Gets all instances for a resource
|
|
25473
25529
|
*/
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blackcode_sa/metaestetics-api",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.15.17-staging.
|
|
4
|
+
"version": "1.15.17-staging.8",
|
|
5
5
|
"description": "Firebase authentication service with anonymous upgrade support",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.mjs",
|
|
@@ -228,34 +228,61 @@ export class ResourceService extends BaseService {
|
|
|
228
228
|
// Handle quantity change
|
|
229
229
|
if (data.quantity !== undefined && data.quantity !== existing.quantity) {
|
|
230
230
|
if (data.quantity > existing.quantity) {
|
|
231
|
-
//
|
|
231
|
+
// Increasing quantity — first reactivate inactive instances, then create new ones if needed
|
|
232
|
+
const allInstances = await this.getResourceInstances(clinicBranchId, resourceId);
|
|
233
|
+
const activeInstances = allInstances.filter(i => i.status === ResourceStatus.ACTIVE);
|
|
234
|
+
const inactiveInstances = allInstances.filter(i => i.status === ResourceStatus.INACTIVE);
|
|
235
|
+
|
|
236
|
+
const needed = data.quantity - activeInstances.length;
|
|
232
237
|
const batch = writeBatch(this.db);
|
|
233
238
|
const now = serverTimestamp();
|
|
234
239
|
const resourceName = data.name || existing.name;
|
|
235
240
|
|
|
236
|
-
|
|
241
|
+
let reactivated = 0;
|
|
242
|
+
|
|
243
|
+
// Step 1: Reactivate inactive instances (sorted by index, lowest first)
|
|
244
|
+
const sortedInactive = [...inactiveInstances].sort((a, b) => a.index - b.index);
|
|
245
|
+
for (const instance of sortedInactive) {
|
|
246
|
+
if (reactivated >= needed) break;
|
|
237
247
|
const instanceRef = doc(
|
|
238
|
-
this.getInstancesRef(clinicBranchId, resourceId)
|
|
248
|
+
this.getInstancesRef(clinicBranchId, resourceId),
|
|
249
|
+
instance.id
|
|
239
250
|
);
|
|
240
|
-
|
|
241
|
-
ResourceInstance,
|
|
242
|
-
"createdAt" | "updatedAt"
|
|
243
|
-
> & { createdAt: any; updatedAt: any } = {
|
|
244
|
-
id: instanceRef.id,
|
|
245
|
-
resourceId,
|
|
246
|
-
clinicBranchId,
|
|
247
|
-
label: `${resourceName} #${i}`,
|
|
248
|
-
index: i,
|
|
251
|
+
batch.update(instanceRef, {
|
|
249
252
|
status: ResourceStatus.ACTIVE,
|
|
250
|
-
createdAt: now,
|
|
251
253
|
updatedAt: now,
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
+
});
|
|
255
|
+
reactivated++;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Step 2: Create new instances for any remaining needed
|
|
259
|
+
const remaining = needed - reactivated;
|
|
260
|
+
if (remaining > 0) {
|
|
261
|
+
// Find the highest existing index to continue numbering
|
|
262
|
+
const maxIndex = allInstances.reduce((max, i) => Math.max(max, i.index), 0);
|
|
263
|
+
for (let i = 1; i <= remaining; i++) {
|
|
264
|
+
const instanceRef = doc(
|
|
265
|
+
this.getInstancesRef(clinicBranchId, resourceId)
|
|
266
|
+
);
|
|
267
|
+
const instanceData: Omit<
|
|
268
|
+
ResourceInstance,
|
|
269
|
+
"createdAt" | "updatedAt"
|
|
270
|
+
> & { createdAt: any; updatedAt: any } = {
|
|
271
|
+
id: instanceRef.id,
|
|
272
|
+
resourceId,
|
|
273
|
+
clinicBranchId,
|
|
274
|
+
label: `${resourceName} #${maxIndex + i}`,
|
|
275
|
+
index: maxIndex + i,
|
|
276
|
+
status: ResourceStatus.ACTIVE,
|
|
277
|
+
createdAt: now,
|
|
278
|
+
updatedAt: now,
|
|
279
|
+
};
|
|
280
|
+
batch.set(instanceRef, instanceData);
|
|
281
|
+
}
|
|
254
282
|
}
|
|
255
283
|
|
|
256
284
|
updateData.quantity = data.quantity;
|
|
257
285
|
|
|
258
|
-
// Update resource doc in the batch too
|
|
259
286
|
const resourceDocRef = this.getResourceDocRef(
|
|
260
287
|
clinicBranchId,
|
|
261
288
|
resourceId
|
|
@@ -337,6 +364,48 @@ export class ResourceService extends BaseService {
|
|
|
337
364
|
});
|
|
338
365
|
}
|
|
339
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Hard deletes a specific instance and all its calendar events.
|
|
369
|
+
* Only works on INACTIVE instances with no future bookings.
|
|
370
|
+
*/
|
|
371
|
+
async hardDeleteInstance(
|
|
372
|
+
clinicBranchId: string,
|
|
373
|
+
resourceId: string,
|
|
374
|
+
instanceId: string
|
|
375
|
+
): Promise<void> {
|
|
376
|
+
// Verify instance exists and is inactive
|
|
377
|
+
const instanceRef = doc(
|
|
378
|
+
this.getInstancesRef(clinicBranchId, resourceId),
|
|
379
|
+
instanceId
|
|
380
|
+
);
|
|
381
|
+
const instanceSnap = await getDoc(instanceRef);
|
|
382
|
+
if (!instanceSnap.exists()) throw new Error("Instance not found");
|
|
383
|
+
|
|
384
|
+
const instance = instanceSnap.data() as ResourceInstance;
|
|
385
|
+
if (instance.status === ResourceStatus.ACTIVE) {
|
|
386
|
+
throw new Error("Cannot hard-delete an active instance. Deactivate it first.");
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Check for future bookings
|
|
390
|
+
const hasFutureBookings = await this.instanceHasFutureBookings(
|
|
391
|
+
clinicBranchId, resourceId, instanceId
|
|
392
|
+
);
|
|
393
|
+
if (hasFutureBookings) {
|
|
394
|
+
throw new Error("Cannot delete instance with future bookings.");
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Delete all calendar events for this instance
|
|
398
|
+
const calendarRef = this.getInstanceCalendarRef(
|
|
399
|
+
clinicBranchId, resourceId, instanceId
|
|
400
|
+
);
|
|
401
|
+
const calendarSnap = await getDocs(calendarRef);
|
|
402
|
+
|
|
403
|
+
const batch = writeBatch(this.db);
|
|
404
|
+
calendarSnap.docs.forEach(d => batch.delete(d.ref));
|
|
405
|
+
batch.delete(instanceRef);
|
|
406
|
+
await batch.commit();
|
|
407
|
+
}
|
|
408
|
+
|
|
340
409
|
/**
|
|
341
410
|
* Gets all instances for a resource
|
|
342
411
|
*/
|