@blackcode_sa/metaestetics-api 1.12.43 → 1.12.45
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/admin/index.d.mts +6 -12
- package/dist/admin/index.d.ts +6 -12
- package/dist/backoffice/index.d.mts +18 -275
- package/dist/backoffice/index.d.ts +18 -275
- package/dist/backoffice/index.js +14 -802
- package/dist/backoffice/index.mjs +38 -830
- package/dist/index.d.mts +10 -255
- package/dist/index.d.ts +10 -255
- package/dist/index.js +32 -750
- package/dist/index.mjs +40 -761
- package/package.json +1 -1
- package/src/backoffice/services/brand.service.ts +0 -86
- package/src/backoffice/services/category.service.ts +0 -84
- package/src/backoffice/services/constants.service.ts +0 -77
- package/src/backoffice/services/product.service.ts +18 -316
- package/src/backoffice/services/requirement.service.ts +0 -76
- package/src/backoffice/services/subcategory.service.ts +0 -87
- package/src/backoffice/services/technology.service.ts +0 -289
- package/src/backoffice/types/product.types.ts +6 -116
- package/src/services/appointment/utils/zone-management.utils.ts +17 -3
- package/src/backoffice/services/migrate-products.ts +0 -116
package/dist/backoffice/index.js
CHANGED
|
@@ -261,73 +261,6 @@ var BrandService = class extends BaseService {
|
|
|
261
261
|
...docSnap.data()
|
|
262
262
|
};
|
|
263
263
|
}
|
|
264
|
-
/**
|
|
265
|
-
* Exports brands to CSV string, suitable for Excel/Sheets.
|
|
266
|
-
* Includes headers and optional UTF-8 BOM.
|
|
267
|
-
* By default exports only active brands (set includeInactive to true to export all).
|
|
268
|
-
*/
|
|
269
|
-
async exportToCsv(options) {
|
|
270
|
-
var _a, _b;
|
|
271
|
-
const includeInactive = (_a = options == null ? void 0 : options.includeInactive) != null ? _a : false;
|
|
272
|
-
const includeBom = (_b = options == null ? void 0 : options.includeBom) != null ? _b : true;
|
|
273
|
-
const headers = [
|
|
274
|
-
"id",
|
|
275
|
-
"name",
|
|
276
|
-
"manufacturer",
|
|
277
|
-
"website",
|
|
278
|
-
"description",
|
|
279
|
-
"isActive"
|
|
280
|
-
];
|
|
281
|
-
const rows = [];
|
|
282
|
-
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
283
|
-
const PAGE_SIZE = 1e3;
|
|
284
|
-
let cursor;
|
|
285
|
-
const baseConstraints = [];
|
|
286
|
-
if (!includeInactive) {
|
|
287
|
-
baseConstraints.push((0, import_firestore.where)("isActive", "==", true));
|
|
288
|
-
}
|
|
289
|
-
baseConstraints.push((0, import_firestore.orderBy)("name_lowercase"));
|
|
290
|
-
while (true) {
|
|
291
|
-
const constraints = [...baseConstraints, (0, import_firestore.limit)(PAGE_SIZE)];
|
|
292
|
-
if (cursor) constraints.push((0, import_firestore.startAfter)(cursor));
|
|
293
|
-
const q = (0, import_firestore.query)(this.getBrandsRef(), ...constraints);
|
|
294
|
-
const snapshot = await (0, import_firestore.getDocs)(q);
|
|
295
|
-
if (snapshot.empty) break;
|
|
296
|
-
for (const d of snapshot.docs) {
|
|
297
|
-
const brand = { id: d.id, ...d.data() };
|
|
298
|
-
rows.push(this.brandToCsvRow(brand));
|
|
299
|
-
}
|
|
300
|
-
cursor = snapshot.docs[snapshot.docs.length - 1];
|
|
301
|
-
if (snapshot.size < PAGE_SIZE) break;
|
|
302
|
-
}
|
|
303
|
-
const csvBody = rows.join("\r\n");
|
|
304
|
-
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
305
|
-
}
|
|
306
|
-
brandToCsvRow(brand) {
|
|
307
|
-
var _a, _b, _c, _d, _e, _f;
|
|
308
|
-
const values = [
|
|
309
|
-
(_a = brand.id) != null ? _a : "",
|
|
310
|
-
(_b = brand.name) != null ? _b : "",
|
|
311
|
-
(_c = brand.manufacturer) != null ? _c : "",
|
|
312
|
-
(_d = brand.website) != null ? _d : "",
|
|
313
|
-
(_e = brand.description) != null ? _e : "",
|
|
314
|
-
String((_f = brand.isActive) != null ? _f : "")
|
|
315
|
-
];
|
|
316
|
-
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
317
|
-
}
|
|
318
|
-
formatDateIso(value) {
|
|
319
|
-
if (value instanceof Date) return value.toISOString();
|
|
320
|
-
if (value && typeof value.toDate === "function") {
|
|
321
|
-
const d = value.toDate();
|
|
322
|
-
return d instanceof Date ? d.toISOString() : String(value);
|
|
323
|
-
}
|
|
324
|
-
return String(value != null ? value : "");
|
|
325
|
-
}
|
|
326
|
-
formatCsvValue(value) {
|
|
327
|
-
const str = value === null || value === void 0 ? "" : String(value);
|
|
328
|
-
const escaped = str.replace(/"/g, '""');
|
|
329
|
-
return `"${escaped}"`;
|
|
330
|
-
}
|
|
331
264
|
};
|
|
332
265
|
|
|
333
266
|
// src/backoffice/services/category.service.ts
|
|
@@ -513,71 +446,6 @@ var CategoryService = class extends BaseService {
|
|
|
513
446
|
...docSnap.data()
|
|
514
447
|
};
|
|
515
448
|
}
|
|
516
|
-
/**
|
|
517
|
-
* Exports categories to CSV string, suitable for Excel/Sheets.
|
|
518
|
-
* Includes headers and optional UTF-8 BOM.
|
|
519
|
-
* By default exports only active categories (set includeInactive to true to export all).
|
|
520
|
-
*/
|
|
521
|
-
async exportToCsv(options) {
|
|
522
|
-
var _a, _b;
|
|
523
|
-
const includeInactive = (_a = options == null ? void 0 : options.includeInactive) != null ? _a : false;
|
|
524
|
-
const includeBom = (_b = options == null ? void 0 : options.includeBom) != null ? _b : true;
|
|
525
|
-
const headers = [
|
|
526
|
-
"id",
|
|
527
|
-
"name",
|
|
528
|
-
"description",
|
|
529
|
-
"family",
|
|
530
|
-
"isActive"
|
|
531
|
-
];
|
|
532
|
-
const rows = [];
|
|
533
|
-
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
534
|
-
const PAGE_SIZE = 1e3;
|
|
535
|
-
let cursor;
|
|
536
|
-
const constraints = [];
|
|
537
|
-
if (!includeInactive) {
|
|
538
|
-
constraints.push((0, import_firestore2.where)("isActive", "==", true));
|
|
539
|
-
}
|
|
540
|
-
constraints.push((0, import_firestore2.orderBy)("name"));
|
|
541
|
-
while (true) {
|
|
542
|
-
const queryConstraints = [...constraints, (0, import_firestore2.limit)(PAGE_SIZE)];
|
|
543
|
-
if (cursor) queryConstraints.push((0, import_firestore2.startAfter)(cursor));
|
|
544
|
-
const q = (0, import_firestore2.query)(this.categoriesRef, ...queryConstraints);
|
|
545
|
-
const snapshot = await (0, import_firestore2.getDocs)(q);
|
|
546
|
-
if (snapshot.empty) break;
|
|
547
|
-
for (const d of snapshot.docs) {
|
|
548
|
-
const category = { id: d.id, ...d.data() };
|
|
549
|
-
rows.push(this.categoryToCsvRow(category));
|
|
550
|
-
}
|
|
551
|
-
cursor = snapshot.docs[snapshot.docs.length - 1];
|
|
552
|
-
if (snapshot.size < PAGE_SIZE) break;
|
|
553
|
-
}
|
|
554
|
-
const csvBody = rows.join("\r\n");
|
|
555
|
-
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
556
|
-
}
|
|
557
|
-
categoryToCsvRow(category) {
|
|
558
|
-
var _a, _b, _c, _d, _e;
|
|
559
|
-
const values = [
|
|
560
|
-
(_a = category.id) != null ? _a : "",
|
|
561
|
-
(_b = category.name) != null ? _b : "",
|
|
562
|
-
(_c = category.description) != null ? _c : "",
|
|
563
|
-
(_d = category.family) != null ? _d : "",
|
|
564
|
-
String((_e = category.isActive) != null ? _e : "")
|
|
565
|
-
];
|
|
566
|
-
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
567
|
-
}
|
|
568
|
-
formatDateIso(value) {
|
|
569
|
-
if (value instanceof Date) return value.toISOString();
|
|
570
|
-
if (value && typeof value.toDate === "function") {
|
|
571
|
-
const d = value.toDate();
|
|
572
|
-
return d instanceof Date ? d.toISOString() : String(value);
|
|
573
|
-
}
|
|
574
|
-
return String(value != null ? value : "");
|
|
575
|
-
}
|
|
576
|
-
formatCsvValue(value) {
|
|
577
|
-
const str = value === null || value === void 0 ? "" : String(value);
|
|
578
|
-
const escaped = str.replace(/"/g, '""');
|
|
579
|
-
return `"${escaped}"`;
|
|
580
|
-
}
|
|
581
449
|
};
|
|
582
450
|
|
|
583
451
|
// src/services/documentation-templates/documentation-template.service.ts
|
|
@@ -1325,14 +1193,7 @@ var TECHNOLOGIES_COLLECTION = "technologies";
|
|
|
1325
1193
|
// src/backoffice/services/product.service.ts
|
|
1326
1194
|
var ProductService = class extends BaseService {
|
|
1327
1195
|
/**
|
|
1328
|
-
* Gets reference to
|
|
1329
|
-
* @returns Firestore collection reference
|
|
1330
|
-
*/
|
|
1331
|
-
getTopLevelProductsRef() {
|
|
1332
|
-
return (0, import_firestore8.collection)(this.db, PRODUCTS_COLLECTION);
|
|
1333
|
-
}
|
|
1334
|
-
/**
|
|
1335
|
-
* Gets reference to products collection under a technology (backward compatibility)
|
|
1196
|
+
* Gets reference to products collection under a technology
|
|
1336
1197
|
* @param technologyId - ID of the technology
|
|
1337
1198
|
* @returns Firestore collection reference
|
|
1338
1199
|
*/
|
|
@@ -1348,7 +1209,6 @@ var ProductService = class extends BaseService {
|
|
|
1348
1209
|
...product,
|
|
1349
1210
|
brandId,
|
|
1350
1211
|
technologyId,
|
|
1351
|
-
// Required for old subcollection structure
|
|
1352
1212
|
createdAt: now,
|
|
1353
1213
|
updatedAt: now,
|
|
1354
1214
|
isActive: true
|
|
@@ -1408,26 +1268,30 @@ var ProductService = class extends BaseService {
|
|
|
1408
1268
|
}
|
|
1409
1269
|
/**
|
|
1410
1270
|
* Gets counts of active products grouped by category, subcategory, and technology.
|
|
1411
|
-
*
|
|
1271
|
+
* This uses a single collectionGroup query for efficiency.
|
|
1412
1272
|
*/
|
|
1413
1273
|
async getProductCounts() {
|
|
1274
|
+
const q = (0, import_firestore8.query)((0, import_firestore8.collectionGroup)(this.db, PRODUCTS_COLLECTION), (0, import_firestore8.where)("isActive", "==", true));
|
|
1275
|
+
const snapshot = await (0, import_firestore8.getDocs)(q);
|
|
1414
1276
|
const counts = {
|
|
1415
1277
|
byCategory: {},
|
|
1416
1278
|
bySubcategory: {},
|
|
1417
1279
|
byTechnology: {}
|
|
1418
1280
|
};
|
|
1419
|
-
|
|
1420
|
-
|
|
1281
|
+
if (snapshot.empty) {
|
|
1282
|
+
return counts;
|
|
1283
|
+
}
|
|
1421
1284
|
snapshot.docs.forEach((doc11) => {
|
|
1422
1285
|
const product = doc11.data();
|
|
1423
|
-
|
|
1424
|
-
|
|
1286
|
+
const { categoryId, subcategoryId, technologyId } = product;
|
|
1287
|
+
if (categoryId) {
|
|
1288
|
+
counts.byCategory[categoryId] = (counts.byCategory[categoryId] || 0) + 1;
|
|
1425
1289
|
}
|
|
1426
|
-
if (
|
|
1427
|
-
counts.bySubcategory[
|
|
1290
|
+
if (subcategoryId) {
|
|
1291
|
+
counts.bySubcategory[subcategoryId] = (counts.bySubcategory[subcategoryId] || 0) + 1;
|
|
1428
1292
|
}
|
|
1429
|
-
if (
|
|
1430
|
-
counts.byTechnology[
|
|
1293
|
+
if (technologyId) {
|
|
1294
|
+
counts.byTechnology[technologyId] = (counts.byTechnology[technologyId] || 0) + 1;
|
|
1431
1295
|
}
|
|
1432
1296
|
});
|
|
1433
1297
|
return counts;
|
|
@@ -1506,241 +1370,6 @@ var ProductService = class extends BaseService {
|
|
|
1506
1370
|
...docSnap.data()
|
|
1507
1371
|
};
|
|
1508
1372
|
}
|
|
1509
|
-
// ==========================================
|
|
1510
|
-
// NEW METHODS: Top-level collection (preferred)
|
|
1511
|
-
// ==========================================
|
|
1512
|
-
/**
|
|
1513
|
-
* Creates a new product in the top-level collection
|
|
1514
|
-
*/
|
|
1515
|
-
async createTopLevel(brandId, product, technologyIds = []) {
|
|
1516
|
-
const now = /* @__PURE__ */ new Date();
|
|
1517
|
-
const newProduct = {
|
|
1518
|
-
...product,
|
|
1519
|
-
brandId,
|
|
1520
|
-
assignedTechnologyIds: technologyIds,
|
|
1521
|
-
createdAt: now,
|
|
1522
|
-
updatedAt: now,
|
|
1523
|
-
isActive: true
|
|
1524
|
-
};
|
|
1525
|
-
const productRef = await (0, import_firestore8.addDoc)(this.getTopLevelProductsRef(), newProduct);
|
|
1526
|
-
return { id: productRef.id, ...newProduct };
|
|
1527
|
-
}
|
|
1528
|
-
/**
|
|
1529
|
-
* Gets all products from the top-level collection
|
|
1530
|
-
*/
|
|
1531
|
-
async getAllTopLevel(options) {
|
|
1532
|
-
const { rowsPerPage, lastVisible, brandId } = options;
|
|
1533
|
-
const constraints = [(0, import_firestore8.where)("isActive", "==", true), (0, import_firestore8.orderBy)("name")];
|
|
1534
|
-
if (brandId) {
|
|
1535
|
-
constraints.push((0, import_firestore8.where)("brandId", "==", brandId));
|
|
1536
|
-
}
|
|
1537
|
-
if (lastVisible) {
|
|
1538
|
-
constraints.push((0, import_firestore8.startAfter)(lastVisible));
|
|
1539
|
-
}
|
|
1540
|
-
constraints.push((0, import_firestore8.limit)(rowsPerPage));
|
|
1541
|
-
const q = (0, import_firestore8.query)(this.getTopLevelProductsRef(), ...constraints);
|
|
1542
|
-
const snapshot = await (0, import_firestore8.getDocs)(q);
|
|
1543
|
-
const products = snapshot.docs.map(
|
|
1544
|
-
(doc11) => ({
|
|
1545
|
-
id: doc11.id,
|
|
1546
|
-
...doc11.data()
|
|
1547
|
-
})
|
|
1548
|
-
);
|
|
1549
|
-
const newLastVisible = snapshot.docs[snapshot.docs.length - 1];
|
|
1550
|
-
return { products, lastVisible: newLastVisible };
|
|
1551
|
-
}
|
|
1552
|
-
/**
|
|
1553
|
-
* Gets a product by ID from the top-level collection
|
|
1554
|
-
*/
|
|
1555
|
-
async getByIdTopLevel(productId) {
|
|
1556
|
-
const docRef = (0, import_firestore8.doc)(this.getTopLevelProductsRef(), productId);
|
|
1557
|
-
const docSnap = await (0, import_firestore8.getDoc)(docRef);
|
|
1558
|
-
if (!docSnap.exists()) return null;
|
|
1559
|
-
return {
|
|
1560
|
-
id: docSnap.id,
|
|
1561
|
-
...docSnap.data()
|
|
1562
|
-
};
|
|
1563
|
-
}
|
|
1564
|
-
/**
|
|
1565
|
-
* Updates a product in the top-level collection
|
|
1566
|
-
*/
|
|
1567
|
-
async updateTopLevel(productId, product) {
|
|
1568
|
-
const updateData = {
|
|
1569
|
-
...product,
|
|
1570
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
1571
|
-
};
|
|
1572
|
-
const docRef = (0, import_firestore8.doc)(this.getTopLevelProductsRef(), productId);
|
|
1573
|
-
await (0, import_firestore8.updateDoc)(docRef, updateData);
|
|
1574
|
-
return this.getByIdTopLevel(productId);
|
|
1575
|
-
}
|
|
1576
|
-
/**
|
|
1577
|
-
* Deletes a product from the top-level collection (soft delete)
|
|
1578
|
-
*/
|
|
1579
|
-
async deleteTopLevel(productId) {
|
|
1580
|
-
await this.updateTopLevel(productId, {
|
|
1581
|
-
isActive: false
|
|
1582
|
-
});
|
|
1583
|
-
}
|
|
1584
|
-
/**
|
|
1585
|
-
* Assigns a product to a technology
|
|
1586
|
-
*/
|
|
1587
|
-
async assignToTechnology(productId, technologyId) {
|
|
1588
|
-
const docRef = (0, import_firestore8.doc)(this.getTopLevelProductsRef(), productId);
|
|
1589
|
-
await (0, import_firestore8.updateDoc)(docRef, {
|
|
1590
|
-
assignedTechnologyIds: (0, import_firestore8.arrayUnion)(technologyId),
|
|
1591
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
1592
|
-
});
|
|
1593
|
-
}
|
|
1594
|
-
/**
|
|
1595
|
-
* Unassigns a product from a technology
|
|
1596
|
-
*/
|
|
1597
|
-
async unassignFromTechnology(productId, technologyId) {
|
|
1598
|
-
const docRef = (0, import_firestore8.doc)(this.getTopLevelProductsRef(), productId);
|
|
1599
|
-
await (0, import_firestore8.updateDoc)(docRef, {
|
|
1600
|
-
assignedTechnologyIds: (0, import_firestore8.arrayRemove)(technologyId),
|
|
1601
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
1602
|
-
});
|
|
1603
|
-
}
|
|
1604
|
-
/**
|
|
1605
|
-
* Gets products assigned to a specific technology
|
|
1606
|
-
*/
|
|
1607
|
-
async getAssignedProducts(technologyId) {
|
|
1608
|
-
const q = (0, import_firestore8.query)(
|
|
1609
|
-
this.getTopLevelProductsRef(),
|
|
1610
|
-
(0, import_firestore8.where)("assignedTechnologyIds", "array-contains", technologyId),
|
|
1611
|
-
(0, import_firestore8.where)("isActive", "==", true),
|
|
1612
|
-
(0, import_firestore8.orderBy)("name")
|
|
1613
|
-
);
|
|
1614
|
-
const snapshot = await (0, import_firestore8.getDocs)(q);
|
|
1615
|
-
return snapshot.docs.map(
|
|
1616
|
-
(doc11) => ({
|
|
1617
|
-
id: doc11.id,
|
|
1618
|
-
...doc11.data()
|
|
1619
|
-
})
|
|
1620
|
-
);
|
|
1621
|
-
}
|
|
1622
|
-
/**
|
|
1623
|
-
* Gets products NOT assigned to a specific technology
|
|
1624
|
-
*/
|
|
1625
|
-
async getUnassignedProducts(technologyId) {
|
|
1626
|
-
const q = (0, import_firestore8.query)(
|
|
1627
|
-
this.getTopLevelProductsRef(),
|
|
1628
|
-
(0, import_firestore8.where)("isActive", "==", true),
|
|
1629
|
-
(0, import_firestore8.orderBy)("name")
|
|
1630
|
-
);
|
|
1631
|
-
const snapshot = await (0, import_firestore8.getDocs)(q);
|
|
1632
|
-
const allProducts = snapshot.docs.map(
|
|
1633
|
-
(doc11) => ({
|
|
1634
|
-
id: doc11.id,
|
|
1635
|
-
...doc11.data()
|
|
1636
|
-
})
|
|
1637
|
-
);
|
|
1638
|
-
return allProducts.filter(
|
|
1639
|
-
(product) => {
|
|
1640
|
-
var _a;
|
|
1641
|
-
return !((_a = product.assignedTechnologyIds) == null ? void 0 : _a.includes(technologyId));
|
|
1642
|
-
}
|
|
1643
|
-
);
|
|
1644
|
-
}
|
|
1645
|
-
/**
|
|
1646
|
-
* Gets all products for a brand (from top-level collection)
|
|
1647
|
-
*/
|
|
1648
|
-
async getByBrand(brandId) {
|
|
1649
|
-
const q = (0, import_firestore8.query)(
|
|
1650
|
-
this.getTopLevelProductsRef(),
|
|
1651
|
-
(0, import_firestore8.where)("brandId", "==", brandId),
|
|
1652
|
-
(0, import_firestore8.where)("isActive", "==", true),
|
|
1653
|
-
(0, import_firestore8.orderBy)("name")
|
|
1654
|
-
);
|
|
1655
|
-
const snapshot = await (0, import_firestore8.getDocs)(q);
|
|
1656
|
-
return snapshot.docs.map(
|
|
1657
|
-
(doc11) => ({
|
|
1658
|
-
id: doc11.id,
|
|
1659
|
-
...doc11.data()
|
|
1660
|
-
})
|
|
1661
|
-
);
|
|
1662
|
-
}
|
|
1663
|
-
/**
|
|
1664
|
-
* Exports products to CSV string, suitable for Excel/Sheets.
|
|
1665
|
-
* Includes headers and optional UTF-8 BOM.
|
|
1666
|
-
* By default exports only active products (set includeInactive to true to export all).
|
|
1667
|
-
*/
|
|
1668
|
-
async exportToCsv(options) {
|
|
1669
|
-
var _a, _b;
|
|
1670
|
-
const includeInactive = (_a = options == null ? void 0 : options.includeInactive) != null ? _a : false;
|
|
1671
|
-
const includeBom = (_b = options == null ? void 0 : options.includeBom) != null ? _b : true;
|
|
1672
|
-
const headers = [
|
|
1673
|
-
"id",
|
|
1674
|
-
"name",
|
|
1675
|
-
"brandId",
|
|
1676
|
-
"brandName",
|
|
1677
|
-
"assignedTechnologyIds",
|
|
1678
|
-
"description",
|
|
1679
|
-
"technicalDetails",
|
|
1680
|
-
"dosage",
|
|
1681
|
-
"composition",
|
|
1682
|
-
"indications",
|
|
1683
|
-
"contraindications",
|
|
1684
|
-
"warnings",
|
|
1685
|
-
"isActive"
|
|
1686
|
-
];
|
|
1687
|
-
const rows = [];
|
|
1688
|
-
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
1689
|
-
const PAGE_SIZE = 1e3;
|
|
1690
|
-
let cursor;
|
|
1691
|
-
const constraints = [];
|
|
1692
|
-
if (!includeInactive) {
|
|
1693
|
-
constraints.push((0, import_firestore8.where)("isActive", "==", true));
|
|
1694
|
-
}
|
|
1695
|
-
constraints.push((0, import_firestore8.orderBy)("name"));
|
|
1696
|
-
while (true) {
|
|
1697
|
-
const queryConstraints = [...constraints, (0, import_firestore8.limit)(PAGE_SIZE)];
|
|
1698
|
-
if (cursor) queryConstraints.push((0, import_firestore8.startAfter)(cursor));
|
|
1699
|
-
const q = (0, import_firestore8.query)(this.getTopLevelProductsRef(), ...queryConstraints);
|
|
1700
|
-
const snapshot = await (0, import_firestore8.getDocs)(q);
|
|
1701
|
-
if (snapshot.empty) break;
|
|
1702
|
-
for (const d of snapshot.docs) {
|
|
1703
|
-
const product = { id: d.id, ...d.data() };
|
|
1704
|
-
rows.push(this.productToCsvRow(product));
|
|
1705
|
-
}
|
|
1706
|
-
cursor = snapshot.docs[snapshot.docs.length - 1];
|
|
1707
|
-
if (snapshot.size < PAGE_SIZE) break;
|
|
1708
|
-
}
|
|
1709
|
-
const csvBody = rows.join("\r\n");
|
|
1710
|
-
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
1711
|
-
}
|
|
1712
|
-
productToCsvRow(product) {
|
|
1713
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
|
|
1714
|
-
const values = [
|
|
1715
|
-
(_a = product.id) != null ? _a : "",
|
|
1716
|
-
(_b = product.name) != null ? _b : "",
|
|
1717
|
-
(_c = product.brandId) != null ? _c : "",
|
|
1718
|
-
(_d = product.brandName) != null ? _d : "",
|
|
1719
|
-
(_f = (_e = product.assignedTechnologyIds) == null ? void 0 : _e.join(";")) != null ? _f : "",
|
|
1720
|
-
(_g = product.description) != null ? _g : "",
|
|
1721
|
-
(_h = product.technicalDetails) != null ? _h : "",
|
|
1722
|
-
(_i = product.dosage) != null ? _i : "",
|
|
1723
|
-
(_j = product.composition) != null ? _j : "",
|
|
1724
|
-
(_l = (_k = product.indications) == null ? void 0 : _k.join(";")) != null ? _l : "",
|
|
1725
|
-
(_n = (_m = product.contraindications) == null ? void 0 : _m.map((c) => c.name).join(";")) != null ? _n : "",
|
|
1726
|
-
(_p = (_o = product.warnings) == null ? void 0 : _o.join(";")) != null ? _p : "",
|
|
1727
|
-
String((_q = product.isActive) != null ? _q : "")
|
|
1728
|
-
];
|
|
1729
|
-
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
1730
|
-
}
|
|
1731
|
-
formatDateIso(value) {
|
|
1732
|
-
if (value instanceof Date) return value.toISOString();
|
|
1733
|
-
if (value && typeof value.toDate === "function") {
|
|
1734
|
-
const d = value.toDate();
|
|
1735
|
-
return d instanceof Date ? d.toISOString() : String(value);
|
|
1736
|
-
}
|
|
1737
|
-
return String(value != null ? value : "");
|
|
1738
|
-
}
|
|
1739
|
-
formatCsvValue(value) {
|
|
1740
|
-
const str = value === null || value === void 0 ? "" : String(value);
|
|
1741
|
-
const escaped = str.replace(/"/g, '""');
|
|
1742
|
-
return `"${escaped}"`;
|
|
1743
|
-
}
|
|
1744
1373
|
};
|
|
1745
1374
|
|
|
1746
1375
|
// src/backoffice/services/requirement.service.ts
|
|
@@ -1864,65 +1493,6 @@ var RequirementService = class extends BaseService {
|
|
|
1864
1493
|
...docSnap.data()
|
|
1865
1494
|
};
|
|
1866
1495
|
}
|
|
1867
|
-
/**
|
|
1868
|
-
* Exports requirements to CSV string, suitable for Excel/Sheets.
|
|
1869
|
-
* Includes headers and optional UTF-8 BOM.
|
|
1870
|
-
* By default exports only active requirements (set includeInactive to true to export all).
|
|
1871
|
-
*/
|
|
1872
|
-
async exportToCsv(options) {
|
|
1873
|
-
var _a, _b;
|
|
1874
|
-
const includeInactive = (_a = options == null ? void 0 : options.includeInactive) != null ? _a : false;
|
|
1875
|
-
const includeBom = (_b = options == null ? void 0 : options.includeBom) != null ? _b : true;
|
|
1876
|
-
const headers = [
|
|
1877
|
-
"id",
|
|
1878
|
-
"type",
|
|
1879
|
-
"name",
|
|
1880
|
-
"description",
|
|
1881
|
-
"timeframe_duration",
|
|
1882
|
-
"timeframe_unit",
|
|
1883
|
-
"timeframe_notifyAt",
|
|
1884
|
-
"importance",
|
|
1885
|
-
"isActive"
|
|
1886
|
-
];
|
|
1887
|
-
const rows = [];
|
|
1888
|
-
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
1889
|
-
const q = includeInactive ? (0, import_firestore9.query)(this.requirementsRef, (0, import_firestore9.orderBy)("name")) : (0, import_firestore9.query)(this.requirementsRef, (0, import_firestore9.where)("isActive", "==", true), (0, import_firestore9.orderBy)("name"));
|
|
1890
|
-
const snapshot = await (0, import_firestore9.getDocs)(q);
|
|
1891
|
-
for (const d of snapshot.docs) {
|
|
1892
|
-
const requirement = { id: d.id, ...d.data() };
|
|
1893
|
-
rows.push(this.requirementToCsvRow(requirement));
|
|
1894
|
-
}
|
|
1895
|
-
const csvBody = rows.join("\r\n");
|
|
1896
|
-
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
1897
|
-
}
|
|
1898
|
-
requirementToCsvRow(requirement) {
|
|
1899
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
1900
|
-
const values = [
|
|
1901
|
-
(_a = requirement.id) != null ? _a : "",
|
|
1902
|
-
(_b = requirement.type) != null ? _b : "",
|
|
1903
|
-
(_c = requirement.name) != null ? _c : "",
|
|
1904
|
-
(_d = requirement.description) != null ? _d : "",
|
|
1905
|
-
(_g = (_f = (_e = requirement.timeframe) == null ? void 0 : _e.duration) == null ? void 0 : _f.toString()) != null ? _g : "",
|
|
1906
|
-
(_i = (_h = requirement.timeframe) == null ? void 0 : _h.unit) != null ? _i : "",
|
|
1907
|
-
(_l = (_k = (_j = requirement.timeframe) == null ? void 0 : _j.notifyAt) == null ? void 0 : _k.join(";")) != null ? _l : "",
|
|
1908
|
-
(_m = requirement.importance) != null ? _m : "",
|
|
1909
|
-
String((_n = requirement.isActive) != null ? _n : "")
|
|
1910
|
-
];
|
|
1911
|
-
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
1912
|
-
}
|
|
1913
|
-
formatDateIso(value) {
|
|
1914
|
-
if (value instanceof Date) return value.toISOString();
|
|
1915
|
-
if (value && typeof value.toDate === "function") {
|
|
1916
|
-
const d = value.toDate();
|
|
1917
|
-
return d instanceof Date ? d.toISOString() : String(value);
|
|
1918
|
-
}
|
|
1919
|
-
return String(value != null ? value : "");
|
|
1920
|
-
}
|
|
1921
|
-
formatCsvValue(value) {
|
|
1922
|
-
const str = value === null || value === void 0 ? "" : String(value);
|
|
1923
|
-
const escaped = str.replace(/"/g, '""');
|
|
1924
|
-
return `"${escaped}"`;
|
|
1925
|
-
}
|
|
1926
1496
|
};
|
|
1927
1497
|
|
|
1928
1498
|
// src/backoffice/services/subcategory.service.ts
|
|
@@ -2150,74 +1720,6 @@ var SubcategoryService = class extends BaseService {
|
|
|
2150
1720
|
...docSnap.data()
|
|
2151
1721
|
};
|
|
2152
1722
|
}
|
|
2153
|
-
/**
|
|
2154
|
-
* Exports subcategories to CSV string, suitable for Excel/Sheets.
|
|
2155
|
-
* Includes headers and optional UTF-8 BOM.
|
|
2156
|
-
* By default exports only active subcategories (set includeInactive to true to export all).
|
|
2157
|
-
*/
|
|
2158
|
-
async exportToCsv(options) {
|
|
2159
|
-
var _a, _b;
|
|
2160
|
-
const includeInactive = (_a = options == null ? void 0 : options.includeInactive) != null ? _a : false;
|
|
2161
|
-
const includeBom = (_b = options == null ? void 0 : options.includeBom) != null ? _b : true;
|
|
2162
|
-
const headers = [
|
|
2163
|
-
"id",
|
|
2164
|
-
"name",
|
|
2165
|
-
"categoryId",
|
|
2166
|
-
"description",
|
|
2167
|
-
"isActive"
|
|
2168
|
-
];
|
|
2169
|
-
const rows = [];
|
|
2170
|
-
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
2171
|
-
const PAGE_SIZE = 1e3;
|
|
2172
|
-
let cursor;
|
|
2173
|
-
const constraints = [];
|
|
2174
|
-
if (!includeInactive) {
|
|
2175
|
-
constraints.push((0, import_firestore10.where)("isActive", "==", true));
|
|
2176
|
-
}
|
|
2177
|
-
constraints.push((0, import_firestore10.orderBy)("name"));
|
|
2178
|
-
while (true) {
|
|
2179
|
-
const queryConstraints = [...constraints, (0, import_firestore10.limit)(PAGE_SIZE)];
|
|
2180
|
-
if (cursor) queryConstraints.push((0, import_firestore10.startAfter)(cursor));
|
|
2181
|
-
const q = (0, import_firestore10.query)(
|
|
2182
|
-
(0, import_firestore10.collectionGroup)(this.db, SUBCATEGORIES_COLLECTION),
|
|
2183
|
-
...queryConstraints
|
|
2184
|
-
);
|
|
2185
|
-
const snapshot = await (0, import_firestore10.getDocs)(q);
|
|
2186
|
-
if (snapshot.empty) break;
|
|
2187
|
-
for (const d of snapshot.docs) {
|
|
2188
|
-
const subcategory = { id: d.id, ...d.data() };
|
|
2189
|
-
rows.push(this.subcategoryToCsvRow(subcategory));
|
|
2190
|
-
}
|
|
2191
|
-
cursor = snapshot.docs[snapshot.docs.length - 1];
|
|
2192
|
-
if (snapshot.size < PAGE_SIZE) break;
|
|
2193
|
-
}
|
|
2194
|
-
const csvBody = rows.join("\r\n");
|
|
2195
|
-
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
2196
|
-
}
|
|
2197
|
-
subcategoryToCsvRow(subcategory) {
|
|
2198
|
-
var _a, _b, _c, _d, _e;
|
|
2199
|
-
const values = [
|
|
2200
|
-
(_a = subcategory.id) != null ? _a : "",
|
|
2201
|
-
(_b = subcategory.name) != null ? _b : "",
|
|
2202
|
-
(_c = subcategory.categoryId) != null ? _c : "",
|
|
2203
|
-
(_d = subcategory.description) != null ? _d : "",
|
|
2204
|
-
String((_e = subcategory.isActive) != null ? _e : "")
|
|
2205
|
-
];
|
|
2206
|
-
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
2207
|
-
}
|
|
2208
|
-
formatDateIso(value) {
|
|
2209
|
-
if (value instanceof Date) return value.toISOString();
|
|
2210
|
-
if (value && typeof value.toDate === "function") {
|
|
2211
|
-
const d = value.toDate();
|
|
2212
|
-
return d instanceof Date ? d.toISOString() : String(value);
|
|
2213
|
-
}
|
|
2214
|
-
return String(value != null ? value : "");
|
|
2215
|
-
}
|
|
2216
|
-
formatCsvValue(value) {
|
|
2217
|
-
const str = value === null || value === void 0 ? "" : String(value);
|
|
2218
|
-
const escaped = str.replace(/"/g, '""');
|
|
2219
|
-
return `"${escaped}"`;
|
|
2220
|
-
}
|
|
2221
1723
|
};
|
|
2222
1724
|
|
|
2223
1725
|
// src/backoffice/services/technology.service.ts
|
|
@@ -2409,18 +1911,7 @@ var TechnologyService = class extends BaseService {
|
|
|
2409
1911
|
});
|
|
2410
1912
|
updateData.updatedAt = /* @__PURE__ */ new Date();
|
|
2411
1913
|
const docRef = (0, import_firestore11.doc)(this.technologiesRef, id);
|
|
2412
|
-
const beforeTech = await this.getById(id);
|
|
2413
1914
|
await (0, import_firestore11.updateDoc)(docRef, updateData);
|
|
2414
|
-
const categoryChanged = beforeTech && updateData.categoryId && beforeTech.categoryId !== updateData.categoryId;
|
|
2415
|
-
const subcategoryChanged = beforeTech && updateData.subcategoryId && beforeTech.subcategoryId !== updateData.subcategoryId;
|
|
2416
|
-
const nameChanged = beforeTech && updateData.name && beforeTech.name !== updateData.name;
|
|
2417
|
-
if (categoryChanged || subcategoryChanged || nameChanged) {
|
|
2418
|
-
await this.updateProductsInSubcollection(id, {
|
|
2419
|
-
categoryId: updateData.categoryId,
|
|
2420
|
-
subcategoryId: updateData.subcategoryId,
|
|
2421
|
-
technologyName: updateData.name
|
|
2422
|
-
});
|
|
2423
|
-
}
|
|
2424
1915
|
return this.getById(id);
|
|
2425
1916
|
}
|
|
2426
1917
|
/**
|
|
@@ -2856,225 +2347,6 @@ var TechnologyService = class extends BaseService {
|
|
|
2856
2347
|
})
|
|
2857
2348
|
);
|
|
2858
2349
|
}
|
|
2859
|
-
// ==========================================
|
|
2860
|
-
// NEW METHODS: Product assignment management
|
|
2861
|
-
// ==========================================
|
|
2862
|
-
/**
|
|
2863
|
-
* Assigns multiple products to a technology
|
|
2864
|
-
* Updates each product's assignedTechnologyIds array
|
|
2865
|
-
*/
|
|
2866
|
-
async assignProducts(technologyId, productIds) {
|
|
2867
|
-
const batch = (0, import_firestore11.writeBatch)(this.db);
|
|
2868
|
-
for (const productId of productIds) {
|
|
2869
|
-
const productRef = (0, import_firestore11.doc)(this.db, PRODUCTS_COLLECTION, productId);
|
|
2870
|
-
batch.update(productRef, {
|
|
2871
|
-
assignedTechnologyIds: (0, import_firestore11.arrayUnion)(technologyId),
|
|
2872
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
2873
|
-
});
|
|
2874
|
-
}
|
|
2875
|
-
await batch.commit();
|
|
2876
|
-
}
|
|
2877
|
-
/**
|
|
2878
|
-
* Unassigns multiple products from a technology
|
|
2879
|
-
* Updates each product's assignedTechnologyIds array
|
|
2880
|
-
*/
|
|
2881
|
-
async unassignProducts(technologyId, productIds) {
|
|
2882
|
-
const batch = (0, import_firestore11.writeBatch)(this.db);
|
|
2883
|
-
for (const productId of productIds) {
|
|
2884
|
-
const productRef = (0, import_firestore11.doc)(this.db, PRODUCTS_COLLECTION, productId);
|
|
2885
|
-
batch.update(productRef, {
|
|
2886
|
-
assignedTechnologyIds: (0, import_firestore11.arrayRemove)(technologyId),
|
|
2887
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
2888
|
-
});
|
|
2889
|
-
}
|
|
2890
|
-
await batch.commit();
|
|
2891
|
-
}
|
|
2892
|
-
/**
|
|
2893
|
-
* Gets products assigned to a specific technology
|
|
2894
|
-
* Reads from top-level collection for immediate consistency (Cloud Functions may lag)
|
|
2895
|
-
*/
|
|
2896
|
-
async getAssignedProducts(technologyId) {
|
|
2897
|
-
const q = (0, import_firestore11.query)(
|
|
2898
|
-
(0, import_firestore11.collection)(this.db, PRODUCTS_COLLECTION),
|
|
2899
|
-
(0, import_firestore11.where)("assignedTechnologyIds", "array-contains", technologyId),
|
|
2900
|
-
(0, import_firestore11.where)("isActive", "==", true),
|
|
2901
|
-
(0, import_firestore11.orderBy)("name")
|
|
2902
|
-
);
|
|
2903
|
-
const snapshot = await (0, import_firestore11.getDocs)(q);
|
|
2904
|
-
return snapshot.docs.map(
|
|
2905
|
-
(doc11) => ({
|
|
2906
|
-
id: doc11.id,
|
|
2907
|
-
...doc11.data()
|
|
2908
|
-
})
|
|
2909
|
-
);
|
|
2910
|
-
}
|
|
2911
|
-
/**
|
|
2912
|
-
* Gets products NOT assigned to a specific technology
|
|
2913
|
-
*/
|
|
2914
|
-
async getUnassignedProducts(technologyId) {
|
|
2915
|
-
const q = (0, import_firestore11.query)(
|
|
2916
|
-
(0, import_firestore11.collection)(this.db, PRODUCTS_COLLECTION),
|
|
2917
|
-
(0, import_firestore11.where)("isActive", "==", true),
|
|
2918
|
-
(0, import_firestore11.orderBy)("name")
|
|
2919
|
-
);
|
|
2920
|
-
const snapshot = await (0, import_firestore11.getDocs)(q);
|
|
2921
|
-
const allProducts = snapshot.docs.map(
|
|
2922
|
-
(doc11) => ({
|
|
2923
|
-
id: doc11.id,
|
|
2924
|
-
...doc11.data()
|
|
2925
|
-
})
|
|
2926
|
-
);
|
|
2927
|
-
return allProducts.filter(
|
|
2928
|
-
(product) => {
|
|
2929
|
-
var _a;
|
|
2930
|
-
return !((_a = product.assignedTechnologyIds) == null ? void 0 : _a.includes(technologyId));
|
|
2931
|
-
}
|
|
2932
|
-
);
|
|
2933
|
-
}
|
|
2934
|
-
/**
|
|
2935
|
-
* Gets product assignment statistics for a technology
|
|
2936
|
-
*/
|
|
2937
|
-
async getProductStats(technologyId) {
|
|
2938
|
-
const products = await this.getAssignedProducts(technologyId);
|
|
2939
|
-
const byBrand = {};
|
|
2940
|
-
products.forEach((product) => {
|
|
2941
|
-
byBrand[product.brandName] = (byBrand[product.brandName] || 0) + 1;
|
|
2942
|
-
});
|
|
2943
|
-
return {
|
|
2944
|
-
totalAssigned: products.length,
|
|
2945
|
-
byBrand
|
|
2946
|
-
};
|
|
2947
|
-
}
|
|
2948
|
-
/**
|
|
2949
|
-
* Updates products in technology subcollection when technology metadata changes
|
|
2950
|
-
* @param technologyId - ID of the technology
|
|
2951
|
-
* @param updates - Fields to update (categoryId, subcategoryId, technologyName)
|
|
2952
|
-
*/
|
|
2953
|
-
async updateProductsInSubcollection(technologyId, updates) {
|
|
2954
|
-
const productsRef = (0, import_firestore11.collection)(this.db, TECHNOLOGIES_COLLECTION, technologyId, PRODUCTS_COLLECTION);
|
|
2955
|
-
const productsSnapshot = await (0, import_firestore11.getDocs)(productsRef);
|
|
2956
|
-
if (productsSnapshot.empty) {
|
|
2957
|
-
return;
|
|
2958
|
-
}
|
|
2959
|
-
const batch = (0, import_firestore11.writeBatch)(this.db);
|
|
2960
|
-
for (const productDoc of productsSnapshot.docs) {
|
|
2961
|
-
const productRef = productDoc.ref;
|
|
2962
|
-
const updateFields = {};
|
|
2963
|
-
if (updates.categoryId !== void 0) {
|
|
2964
|
-
updateFields.categoryId = updates.categoryId;
|
|
2965
|
-
}
|
|
2966
|
-
if (updates.subcategoryId !== void 0) {
|
|
2967
|
-
updateFields.subcategoryId = updates.subcategoryId;
|
|
2968
|
-
}
|
|
2969
|
-
if (updates.technologyName !== void 0) {
|
|
2970
|
-
updateFields.technologyName = updates.technologyName;
|
|
2971
|
-
}
|
|
2972
|
-
if (Object.keys(updateFields).length > 0) {
|
|
2973
|
-
batch.update(productRef, updateFields);
|
|
2974
|
-
}
|
|
2975
|
-
}
|
|
2976
|
-
await batch.commit();
|
|
2977
|
-
}
|
|
2978
|
-
/**
|
|
2979
|
-
* Exports technologies to CSV string, suitable for Excel/Sheets.
|
|
2980
|
-
* Includes headers and optional UTF-8 BOM.
|
|
2981
|
-
* By default exports only active technologies (set includeInactive to true to export all).
|
|
2982
|
-
* Includes product names from subcollections.
|
|
2983
|
-
*/
|
|
2984
|
-
async exportToCsv(options) {
|
|
2985
|
-
var _a, _b;
|
|
2986
|
-
const includeInactive = (_a = options == null ? void 0 : options.includeInactive) != null ? _a : false;
|
|
2987
|
-
const includeBom = (_b = options == null ? void 0 : options.includeBom) != null ? _b : true;
|
|
2988
|
-
const headers = [
|
|
2989
|
-
"id",
|
|
2990
|
-
"name",
|
|
2991
|
-
"description",
|
|
2992
|
-
"family",
|
|
2993
|
-
"categoryId",
|
|
2994
|
-
"subcategoryId",
|
|
2995
|
-
"technicalDetails",
|
|
2996
|
-
"requirements_pre",
|
|
2997
|
-
"requirements_post",
|
|
2998
|
-
"blockingConditions",
|
|
2999
|
-
"contraindications",
|
|
3000
|
-
"benefits",
|
|
3001
|
-
"certificationMinimumLevel",
|
|
3002
|
-
"certificationRequiredSpecialties",
|
|
3003
|
-
"documentationTemplateIds",
|
|
3004
|
-
"productNames",
|
|
3005
|
-
"isActive"
|
|
3006
|
-
];
|
|
3007
|
-
const rows = [];
|
|
3008
|
-
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
3009
|
-
const PAGE_SIZE = 1e3;
|
|
3010
|
-
let cursor;
|
|
3011
|
-
const constraints = [];
|
|
3012
|
-
if (!includeInactive) {
|
|
3013
|
-
constraints.push((0, import_firestore11.where)("isActive", "==", true));
|
|
3014
|
-
}
|
|
3015
|
-
constraints.push((0, import_firestore11.orderBy)("name"));
|
|
3016
|
-
while (true) {
|
|
3017
|
-
const queryConstraints = [...constraints, (0, import_firestore11.limit)(PAGE_SIZE)];
|
|
3018
|
-
if (cursor) queryConstraints.push((0, import_firestore11.startAfter)(cursor));
|
|
3019
|
-
const q = (0, import_firestore11.query)(this.technologiesRef, ...queryConstraints);
|
|
3020
|
-
const snapshot = await (0, import_firestore11.getDocs)(q);
|
|
3021
|
-
if (snapshot.empty) break;
|
|
3022
|
-
for (const d of snapshot.docs) {
|
|
3023
|
-
const technology = { id: d.id, ...d.data() };
|
|
3024
|
-
const productNames = await this.getProductNamesForTechnology(technology.id);
|
|
3025
|
-
rows.push(this.technologyToCsvRow(technology, productNames));
|
|
3026
|
-
}
|
|
3027
|
-
cursor = snapshot.docs[snapshot.docs.length - 1];
|
|
3028
|
-
if (snapshot.size < PAGE_SIZE) break;
|
|
3029
|
-
}
|
|
3030
|
-
const csvBody = rows.join("\r\n");
|
|
3031
|
-
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
3032
|
-
}
|
|
3033
|
-
/**
|
|
3034
|
-
* Gets product names from the technology's product subcollection
|
|
3035
|
-
*/
|
|
3036
|
-
async getProductNamesForTechnology(technologyId) {
|
|
3037
|
-
try {
|
|
3038
|
-
const productsRef = (0, import_firestore11.collection)(this.db, TECHNOLOGIES_COLLECTION, technologyId, PRODUCTS_COLLECTION);
|
|
3039
|
-
const q = (0, import_firestore11.query)(productsRef, (0, import_firestore11.where)("isActive", "==", true));
|
|
3040
|
-
const snapshot = await (0, import_firestore11.getDocs)(q);
|
|
3041
|
-
return snapshot.docs.map((doc11) => {
|
|
3042
|
-
const product = doc11.data();
|
|
3043
|
-
return product.name || "";
|
|
3044
|
-
}).filter((name) => name);
|
|
3045
|
-
} catch (error) {
|
|
3046
|
-
console.error(`Error fetching products for technology ${technologyId}:`, error);
|
|
3047
|
-
return [];
|
|
3048
|
-
}
|
|
3049
|
-
}
|
|
3050
|
-
technologyToCsvRow(technology, productNames = []) {
|
|
3051
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A;
|
|
3052
|
-
const values = [
|
|
3053
|
-
(_a = technology.id) != null ? _a : "",
|
|
3054
|
-
(_b = technology.name) != null ? _b : "",
|
|
3055
|
-
(_c = technology.description) != null ? _c : "",
|
|
3056
|
-
(_d = technology.family) != null ? _d : "",
|
|
3057
|
-
(_e = technology.categoryId) != null ? _e : "",
|
|
3058
|
-
(_f = technology.subcategoryId) != null ? _f : "",
|
|
3059
|
-
(_g = technology.technicalDetails) != null ? _g : "",
|
|
3060
|
-
(_j = (_i = (_h = technology.requirements) == null ? void 0 : _h.pre) == null ? void 0 : _i.map((r) => r.name).join(";")) != null ? _j : "",
|
|
3061
|
-
(_m = (_l = (_k = technology.requirements) == null ? void 0 : _k.post) == null ? void 0 : _l.map((r) => r.name).join(";")) != null ? _m : "",
|
|
3062
|
-
(_o = (_n = technology.blockingConditions) == null ? void 0 : _n.join(";")) != null ? _o : "",
|
|
3063
|
-
(_q = (_p = technology.contraindications) == null ? void 0 : _p.map((c) => c.name).join(";")) != null ? _q : "",
|
|
3064
|
-
(_s = (_r = technology.benefits) == null ? void 0 : _r.map((b) => b.name).join(";")) != null ? _s : "",
|
|
3065
|
-
(_u = (_t = technology.certificationRequirement) == null ? void 0 : _t.minimumLevel) != null ? _u : "",
|
|
3066
|
-
(_x = (_w = (_v = technology.certificationRequirement) == null ? void 0 : _v.requiredSpecialties) == null ? void 0 : _w.join(";")) != null ? _x : "",
|
|
3067
|
-
(_z = (_y = technology.documentationTemplates) == null ? void 0 : _y.map((t) => t.templateId).join(";")) != null ? _z : "",
|
|
3068
|
-
productNames.join(";"),
|
|
3069
|
-
String((_A = technology.isActive) != null ? _A : "")
|
|
3070
|
-
];
|
|
3071
|
-
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
3072
|
-
}
|
|
3073
|
-
formatCsvValue(value) {
|
|
3074
|
-
const str = value === null || value === void 0 ? "" : String(value);
|
|
3075
|
-
const escaped = str.replace(/"/g, '""');
|
|
3076
|
-
return `"${escaped}"`;
|
|
3077
|
-
}
|
|
3078
2350
|
};
|
|
3079
2351
|
|
|
3080
2352
|
// src/backoffice/services/constants.service.ts
|
|
@@ -3307,66 +2579,6 @@ var ConstantsService = class extends BaseService {
|
|
|
3307
2579
|
contraindications: (0, import_firestore12.arrayRemove)(toRemove)
|
|
3308
2580
|
});
|
|
3309
2581
|
}
|
|
3310
|
-
// =================================================================
|
|
3311
|
-
// CSV Export Methods
|
|
3312
|
-
// =================================================================
|
|
3313
|
-
/**
|
|
3314
|
-
* Exports treatment benefits to CSV string, suitable for Excel/Sheets.
|
|
3315
|
-
* Includes headers and optional UTF-8 BOM.
|
|
3316
|
-
*/
|
|
3317
|
-
async exportBenefitsToCsv(options) {
|
|
3318
|
-
var _a;
|
|
3319
|
-
const includeBom = (_a = options == null ? void 0 : options.includeBom) != null ? _a : true;
|
|
3320
|
-
const headers = ["id", "name", "description"];
|
|
3321
|
-
const rows = [];
|
|
3322
|
-
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
3323
|
-
const benefits = await this.getAllBenefitsForFilter();
|
|
3324
|
-
for (const benefit of benefits) {
|
|
3325
|
-
rows.push(this.benefitToCsvRow(benefit));
|
|
3326
|
-
}
|
|
3327
|
-
const csvBody = rows.join("\r\n");
|
|
3328
|
-
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
3329
|
-
}
|
|
3330
|
-
/**
|
|
3331
|
-
* Exports contraindications to CSV string, suitable for Excel/Sheets.
|
|
3332
|
-
* Includes headers and optional UTF-8 BOM.
|
|
3333
|
-
*/
|
|
3334
|
-
async exportContraindicationsToCsv(options) {
|
|
3335
|
-
var _a;
|
|
3336
|
-
const includeBom = (_a = options == null ? void 0 : options.includeBom) != null ? _a : true;
|
|
3337
|
-
const headers = ["id", "name", "description"];
|
|
3338
|
-
const rows = [];
|
|
3339
|
-
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
3340
|
-
const contraindications = await this.getAllContraindicationsForFilter();
|
|
3341
|
-
for (const contraindication of contraindications) {
|
|
3342
|
-
rows.push(this.contraindicationToCsvRow(contraindication));
|
|
3343
|
-
}
|
|
3344
|
-
const csvBody = rows.join("\r\n");
|
|
3345
|
-
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
3346
|
-
}
|
|
3347
|
-
benefitToCsvRow(benefit) {
|
|
3348
|
-
var _a, _b, _c;
|
|
3349
|
-
const values = [
|
|
3350
|
-
(_a = benefit.id) != null ? _a : "",
|
|
3351
|
-
(_b = benefit.name) != null ? _b : "",
|
|
3352
|
-
(_c = benefit.description) != null ? _c : ""
|
|
3353
|
-
];
|
|
3354
|
-
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
3355
|
-
}
|
|
3356
|
-
contraindicationToCsvRow(contraindication) {
|
|
3357
|
-
var _a, _b, _c;
|
|
3358
|
-
const values = [
|
|
3359
|
-
(_a = contraindication.id) != null ? _a : "",
|
|
3360
|
-
(_b = contraindication.name) != null ? _b : "",
|
|
3361
|
-
(_c = contraindication.description) != null ? _c : ""
|
|
3362
|
-
];
|
|
3363
|
-
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
3364
|
-
}
|
|
3365
|
-
formatCsvValue(value) {
|
|
3366
|
-
const str = value === null || value === void 0 ? "" : String(value);
|
|
3367
|
-
const escaped = str.replace(/"/g, '""');
|
|
3368
|
-
return `"${escaped}"`;
|
|
3369
|
-
}
|
|
3370
2582
|
};
|
|
3371
2583
|
|
|
3372
2584
|
// src/backoffice/types/static/blocking-condition.types.ts
|