@blackcode_sa/metaestetics-api 1.12.42 → 1.12.43
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/backoffice/index.d.mts +93 -0
- package/dist/backoffice/index.d.ts +93 -0
- package/dist/backoffice/index.js +500 -0
- package/dist/backoffice/index.mjs +514 -13
- package/dist/index.d.mts +81 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.js +441 -0
- package/dist/index.mjs +441 -0
- package/package.json +1 -1
- package/src/backoffice/services/brand.service.ts +86 -0
- package/src/backoffice/services/category.service.ts +84 -0
- package/src/backoffice/services/constants.service.ts +77 -0
- package/src/backoffice/services/product.service.ts +100 -0
- package/src/backoffice/services/requirement.service.ts +76 -0
- package/src/backoffice/services/subcategory.service.ts +87 -0
- package/src/backoffice/services/technology.service.ts +120 -0
|
@@ -169,6 +169,73 @@ var BrandService = class extends BaseService {
|
|
|
169
169
|
...docSnap.data()
|
|
170
170
|
};
|
|
171
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Exports brands to CSV string, suitable for Excel/Sheets.
|
|
174
|
+
* Includes headers and optional UTF-8 BOM.
|
|
175
|
+
* By default exports only active brands (set includeInactive to true to export all).
|
|
176
|
+
*/
|
|
177
|
+
async exportToCsv(options) {
|
|
178
|
+
var _a, _b;
|
|
179
|
+
const includeInactive = (_a = options == null ? void 0 : options.includeInactive) != null ? _a : false;
|
|
180
|
+
const includeBom = (_b = options == null ? void 0 : options.includeBom) != null ? _b : true;
|
|
181
|
+
const headers = [
|
|
182
|
+
"id",
|
|
183
|
+
"name",
|
|
184
|
+
"manufacturer",
|
|
185
|
+
"website",
|
|
186
|
+
"description",
|
|
187
|
+
"isActive"
|
|
188
|
+
];
|
|
189
|
+
const rows = [];
|
|
190
|
+
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
191
|
+
const PAGE_SIZE = 1e3;
|
|
192
|
+
let cursor;
|
|
193
|
+
const baseConstraints = [];
|
|
194
|
+
if (!includeInactive) {
|
|
195
|
+
baseConstraints.push(where("isActive", "==", true));
|
|
196
|
+
}
|
|
197
|
+
baseConstraints.push(orderBy("name_lowercase"));
|
|
198
|
+
while (true) {
|
|
199
|
+
const constraints = [...baseConstraints, limit(PAGE_SIZE)];
|
|
200
|
+
if (cursor) constraints.push(startAfter(cursor));
|
|
201
|
+
const q = query(this.getBrandsRef(), ...constraints);
|
|
202
|
+
const snapshot = await getDocs(q);
|
|
203
|
+
if (snapshot.empty) break;
|
|
204
|
+
for (const d of snapshot.docs) {
|
|
205
|
+
const brand = { id: d.id, ...d.data() };
|
|
206
|
+
rows.push(this.brandToCsvRow(brand));
|
|
207
|
+
}
|
|
208
|
+
cursor = snapshot.docs[snapshot.docs.length - 1];
|
|
209
|
+
if (snapshot.size < PAGE_SIZE) break;
|
|
210
|
+
}
|
|
211
|
+
const csvBody = rows.join("\r\n");
|
|
212
|
+
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
213
|
+
}
|
|
214
|
+
brandToCsvRow(brand) {
|
|
215
|
+
var _a, _b, _c, _d, _e, _f;
|
|
216
|
+
const values = [
|
|
217
|
+
(_a = brand.id) != null ? _a : "",
|
|
218
|
+
(_b = brand.name) != null ? _b : "",
|
|
219
|
+
(_c = brand.manufacturer) != null ? _c : "",
|
|
220
|
+
(_d = brand.website) != null ? _d : "",
|
|
221
|
+
(_e = brand.description) != null ? _e : "",
|
|
222
|
+
String((_f = brand.isActive) != null ? _f : "")
|
|
223
|
+
];
|
|
224
|
+
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
225
|
+
}
|
|
226
|
+
formatDateIso(value) {
|
|
227
|
+
if (value instanceof Date) return value.toISOString();
|
|
228
|
+
if (value && typeof value.toDate === "function") {
|
|
229
|
+
const d = value.toDate();
|
|
230
|
+
return d instanceof Date ? d.toISOString() : String(value);
|
|
231
|
+
}
|
|
232
|
+
return String(value != null ? value : "");
|
|
233
|
+
}
|
|
234
|
+
formatCsvValue(value) {
|
|
235
|
+
const str = value === null || value === void 0 ? "" : String(value);
|
|
236
|
+
const escaped = str.replace(/"/g, '""');
|
|
237
|
+
return `"${escaped}"`;
|
|
238
|
+
}
|
|
172
239
|
};
|
|
173
240
|
|
|
174
241
|
// src/backoffice/services/category.service.ts
|
|
@@ -367,6 +434,71 @@ var CategoryService = class extends BaseService {
|
|
|
367
434
|
...docSnap.data()
|
|
368
435
|
};
|
|
369
436
|
}
|
|
437
|
+
/**
|
|
438
|
+
* Exports categories to CSV string, suitable for Excel/Sheets.
|
|
439
|
+
* Includes headers and optional UTF-8 BOM.
|
|
440
|
+
* By default exports only active categories (set includeInactive to true to export all).
|
|
441
|
+
*/
|
|
442
|
+
async exportToCsv(options) {
|
|
443
|
+
var _a, _b;
|
|
444
|
+
const includeInactive = (_a = options == null ? void 0 : options.includeInactive) != null ? _a : false;
|
|
445
|
+
const includeBom = (_b = options == null ? void 0 : options.includeBom) != null ? _b : true;
|
|
446
|
+
const headers = [
|
|
447
|
+
"id",
|
|
448
|
+
"name",
|
|
449
|
+
"description",
|
|
450
|
+
"family",
|
|
451
|
+
"isActive"
|
|
452
|
+
];
|
|
453
|
+
const rows = [];
|
|
454
|
+
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
455
|
+
const PAGE_SIZE = 1e3;
|
|
456
|
+
let cursor;
|
|
457
|
+
const constraints = [];
|
|
458
|
+
if (!includeInactive) {
|
|
459
|
+
constraints.push(where2("isActive", "==", true));
|
|
460
|
+
}
|
|
461
|
+
constraints.push(orderBy2("name"));
|
|
462
|
+
while (true) {
|
|
463
|
+
const queryConstraints = [...constraints, limit2(PAGE_SIZE)];
|
|
464
|
+
if (cursor) queryConstraints.push(startAfter2(cursor));
|
|
465
|
+
const q = query2(this.categoriesRef, ...queryConstraints);
|
|
466
|
+
const snapshot = await getDocs2(q);
|
|
467
|
+
if (snapshot.empty) break;
|
|
468
|
+
for (const d of snapshot.docs) {
|
|
469
|
+
const category = { id: d.id, ...d.data() };
|
|
470
|
+
rows.push(this.categoryToCsvRow(category));
|
|
471
|
+
}
|
|
472
|
+
cursor = snapshot.docs[snapshot.docs.length - 1];
|
|
473
|
+
if (snapshot.size < PAGE_SIZE) break;
|
|
474
|
+
}
|
|
475
|
+
const csvBody = rows.join("\r\n");
|
|
476
|
+
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
477
|
+
}
|
|
478
|
+
categoryToCsvRow(category) {
|
|
479
|
+
var _a, _b, _c, _d, _e;
|
|
480
|
+
const values = [
|
|
481
|
+
(_a = category.id) != null ? _a : "",
|
|
482
|
+
(_b = category.name) != null ? _b : "",
|
|
483
|
+
(_c = category.description) != null ? _c : "",
|
|
484
|
+
(_d = category.family) != null ? _d : "",
|
|
485
|
+
String((_e = category.isActive) != null ? _e : "")
|
|
486
|
+
];
|
|
487
|
+
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
488
|
+
}
|
|
489
|
+
formatDateIso(value) {
|
|
490
|
+
if (value instanceof Date) return value.toISOString();
|
|
491
|
+
if (value && typeof value.toDate === "function") {
|
|
492
|
+
const d = value.toDate();
|
|
493
|
+
return d instanceof Date ? d.toISOString() : String(value);
|
|
494
|
+
}
|
|
495
|
+
return String(value != null ? value : "");
|
|
496
|
+
}
|
|
497
|
+
formatCsvValue(value) {
|
|
498
|
+
const str = value === null || value === void 0 ? "" : String(value);
|
|
499
|
+
const escaped = str.replace(/"/g, '""');
|
|
500
|
+
return `"${escaped}"`;
|
|
501
|
+
}
|
|
370
502
|
};
|
|
371
503
|
|
|
372
504
|
// src/services/documentation-templates/documentation-template.service.ts
|
|
@@ -1507,6 +1639,87 @@ var ProductService = class extends BaseService {
|
|
|
1507
1639
|
})
|
|
1508
1640
|
);
|
|
1509
1641
|
}
|
|
1642
|
+
/**
|
|
1643
|
+
* Exports products to CSV string, suitable for Excel/Sheets.
|
|
1644
|
+
* Includes headers and optional UTF-8 BOM.
|
|
1645
|
+
* By default exports only active products (set includeInactive to true to export all).
|
|
1646
|
+
*/
|
|
1647
|
+
async exportToCsv(options) {
|
|
1648
|
+
var _a, _b;
|
|
1649
|
+
const includeInactive = (_a = options == null ? void 0 : options.includeInactive) != null ? _a : false;
|
|
1650
|
+
const includeBom = (_b = options == null ? void 0 : options.includeBom) != null ? _b : true;
|
|
1651
|
+
const headers = [
|
|
1652
|
+
"id",
|
|
1653
|
+
"name",
|
|
1654
|
+
"brandId",
|
|
1655
|
+
"brandName",
|
|
1656
|
+
"assignedTechnologyIds",
|
|
1657
|
+
"description",
|
|
1658
|
+
"technicalDetails",
|
|
1659
|
+
"dosage",
|
|
1660
|
+
"composition",
|
|
1661
|
+
"indications",
|
|
1662
|
+
"contraindications",
|
|
1663
|
+
"warnings",
|
|
1664
|
+
"isActive"
|
|
1665
|
+
];
|
|
1666
|
+
const rows = [];
|
|
1667
|
+
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
1668
|
+
const PAGE_SIZE = 1e3;
|
|
1669
|
+
let cursor;
|
|
1670
|
+
const constraints = [];
|
|
1671
|
+
if (!includeInactive) {
|
|
1672
|
+
constraints.push(where6("isActive", "==", true));
|
|
1673
|
+
}
|
|
1674
|
+
constraints.push(orderBy6("name"));
|
|
1675
|
+
while (true) {
|
|
1676
|
+
const queryConstraints = [...constraints, limit6(PAGE_SIZE)];
|
|
1677
|
+
if (cursor) queryConstraints.push(startAfter5(cursor));
|
|
1678
|
+
const q = query6(this.getTopLevelProductsRef(), ...queryConstraints);
|
|
1679
|
+
const snapshot = await getDocs6(q);
|
|
1680
|
+
if (snapshot.empty) break;
|
|
1681
|
+
for (const d of snapshot.docs) {
|
|
1682
|
+
const product = { id: d.id, ...d.data() };
|
|
1683
|
+
rows.push(this.productToCsvRow(product));
|
|
1684
|
+
}
|
|
1685
|
+
cursor = snapshot.docs[snapshot.docs.length - 1];
|
|
1686
|
+
if (snapshot.size < PAGE_SIZE) break;
|
|
1687
|
+
}
|
|
1688
|
+
const csvBody = rows.join("\r\n");
|
|
1689
|
+
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
1690
|
+
}
|
|
1691
|
+
productToCsvRow(product) {
|
|
1692
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
|
|
1693
|
+
const values = [
|
|
1694
|
+
(_a = product.id) != null ? _a : "",
|
|
1695
|
+
(_b = product.name) != null ? _b : "",
|
|
1696
|
+
(_c = product.brandId) != null ? _c : "",
|
|
1697
|
+
(_d = product.brandName) != null ? _d : "",
|
|
1698
|
+
(_f = (_e = product.assignedTechnologyIds) == null ? void 0 : _e.join(";")) != null ? _f : "",
|
|
1699
|
+
(_g = product.description) != null ? _g : "",
|
|
1700
|
+
(_h = product.technicalDetails) != null ? _h : "",
|
|
1701
|
+
(_i = product.dosage) != null ? _i : "",
|
|
1702
|
+
(_j = product.composition) != null ? _j : "",
|
|
1703
|
+
(_l = (_k = product.indications) == null ? void 0 : _k.join(";")) != null ? _l : "",
|
|
1704
|
+
(_n = (_m = product.contraindications) == null ? void 0 : _m.map((c) => c.name).join(";")) != null ? _n : "",
|
|
1705
|
+
(_p = (_o = product.warnings) == null ? void 0 : _o.join(";")) != null ? _p : "",
|
|
1706
|
+
String((_q = product.isActive) != null ? _q : "")
|
|
1707
|
+
];
|
|
1708
|
+
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
1709
|
+
}
|
|
1710
|
+
formatDateIso(value) {
|
|
1711
|
+
if (value instanceof Date) return value.toISOString();
|
|
1712
|
+
if (value && typeof value.toDate === "function") {
|
|
1713
|
+
const d = value.toDate();
|
|
1714
|
+
return d instanceof Date ? d.toISOString() : String(value);
|
|
1715
|
+
}
|
|
1716
|
+
return String(value != null ? value : "");
|
|
1717
|
+
}
|
|
1718
|
+
formatCsvValue(value) {
|
|
1719
|
+
const str = value === null || value === void 0 ? "" : String(value);
|
|
1720
|
+
const escaped = str.replace(/"/g, '""');
|
|
1721
|
+
return `"${escaped}"`;
|
|
1722
|
+
}
|
|
1510
1723
|
};
|
|
1511
1724
|
|
|
1512
1725
|
// src/backoffice/services/requirement.service.ts
|
|
@@ -1518,7 +1731,8 @@ import {
|
|
|
1518
1731
|
getDocs as getDocs7,
|
|
1519
1732
|
query as query7,
|
|
1520
1733
|
updateDoc as updateDoc7,
|
|
1521
|
-
where as where7
|
|
1734
|
+
where as where7,
|
|
1735
|
+
orderBy as orderBy7
|
|
1522
1736
|
} from "firebase/firestore";
|
|
1523
1737
|
|
|
1524
1738
|
// src/backoffice/types/requirement.types.ts
|
|
@@ -1639,6 +1853,65 @@ var RequirementService = class extends BaseService {
|
|
|
1639
1853
|
...docSnap.data()
|
|
1640
1854
|
};
|
|
1641
1855
|
}
|
|
1856
|
+
/**
|
|
1857
|
+
* Exports requirements to CSV string, suitable for Excel/Sheets.
|
|
1858
|
+
* Includes headers and optional UTF-8 BOM.
|
|
1859
|
+
* By default exports only active requirements (set includeInactive to true to export all).
|
|
1860
|
+
*/
|
|
1861
|
+
async exportToCsv(options) {
|
|
1862
|
+
var _a, _b;
|
|
1863
|
+
const includeInactive = (_a = options == null ? void 0 : options.includeInactive) != null ? _a : false;
|
|
1864
|
+
const includeBom = (_b = options == null ? void 0 : options.includeBom) != null ? _b : true;
|
|
1865
|
+
const headers = [
|
|
1866
|
+
"id",
|
|
1867
|
+
"type",
|
|
1868
|
+
"name",
|
|
1869
|
+
"description",
|
|
1870
|
+
"timeframe_duration",
|
|
1871
|
+
"timeframe_unit",
|
|
1872
|
+
"timeframe_notifyAt",
|
|
1873
|
+
"importance",
|
|
1874
|
+
"isActive"
|
|
1875
|
+
];
|
|
1876
|
+
const rows = [];
|
|
1877
|
+
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
1878
|
+
const q = includeInactive ? query7(this.requirementsRef, orderBy7("name")) : query7(this.requirementsRef, where7("isActive", "==", true), orderBy7("name"));
|
|
1879
|
+
const snapshot = await getDocs7(q);
|
|
1880
|
+
for (const d of snapshot.docs) {
|
|
1881
|
+
const requirement = { id: d.id, ...d.data() };
|
|
1882
|
+
rows.push(this.requirementToCsvRow(requirement));
|
|
1883
|
+
}
|
|
1884
|
+
const csvBody = rows.join("\r\n");
|
|
1885
|
+
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
1886
|
+
}
|
|
1887
|
+
requirementToCsvRow(requirement) {
|
|
1888
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
1889
|
+
const values = [
|
|
1890
|
+
(_a = requirement.id) != null ? _a : "",
|
|
1891
|
+
(_b = requirement.type) != null ? _b : "",
|
|
1892
|
+
(_c = requirement.name) != null ? _c : "",
|
|
1893
|
+
(_d = requirement.description) != null ? _d : "",
|
|
1894
|
+
(_g = (_f = (_e = requirement.timeframe) == null ? void 0 : _e.duration) == null ? void 0 : _f.toString()) != null ? _g : "",
|
|
1895
|
+
(_i = (_h = requirement.timeframe) == null ? void 0 : _h.unit) != null ? _i : "",
|
|
1896
|
+
(_l = (_k = (_j = requirement.timeframe) == null ? void 0 : _j.notifyAt) == null ? void 0 : _k.join(";")) != null ? _l : "",
|
|
1897
|
+
(_m = requirement.importance) != null ? _m : "",
|
|
1898
|
+
String((_n = requirement.isActive) != null ? _n : "")
|
|
1899
|
+
];
|
|
1900
|
+
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
1901
|
+
}
|
|
1902
|
+
formatDateIso(value) {
|
|
1903
|
+
if (value instanceof Date) return value.toISOString();
|
|
1904
|
+
if (value && typeof value.toDate === "function") {
|
|
1905
|
+
const d = value.toDate();
|
|
1906
|
+
return d instanceof Date ? d.toISOString() : String(value);
|
|
1907
|
+
}
|
|
1908
|
+
return String(value != null ? value : "");
|
|
1909
|
+
}
|
|
1910
|
+
formatCsvValue(value) {
|
|
1911
|
+
const str = value === null || value === void 0 ? "" : String(value);
|
|
1912
|
+
const escaped = str.replace(/"/g, '""');
|
|
1913
|
+
return `"${escaped}"`;
|
|
1914
|
+
}
|
|
1642
1915
|
};
|
|
1643
1916
|
|
|
1644
1917
|
// src/backoffice/services/subcategory.service.ts
|
|
@@ -1652,7 +1925,7 @@ import {
|
|
|
1652
1925
|
getDoc as getDoc8,
|
|
1653
1926
|
getDocs as getDocs8,
|
|
1654
1927
|
limit as limit7,
|
|
1655
|
-
orderBy as
|
|
1928
|
+
orderBy as orderBy8,
|
|
1656
1929
|
query as query8,
|
|
1657
1930
|
setDoc as setDoc4,
|
|
1658
1931
|
startAfter as startAfter6,
|
|
@@ -1726,7 +1999,7 @@ var SubcategoryService = class extends BaseService {
|
|
|
1726
1999
|
const { active = true, limit: queryLimit = 10, lastVisible } = options;
|
|
1727
2000
|
const constraints = [
|
|
1728
2001
|
where8("isActive", "==", active),
|
|
1729
|
-
|
|
2002
|
+
orderBy8("name"),
|
|
1730
2003
|
queryLimit ? limit7(queryLimit) : void 0,
|
|
1731
2004
|
lastVisible ? startAfter6(lastVisible) : void 0
|
|
1732
2005
|
].filter((c) => !!c);
|
|
@@ -1753,7 +2026,7 @@ var SubcategoryService = class extends BaseService {
|
|
|
1753
2026
|
const { active = true, limit: queryLimit = 10, lastVisible } = options;
|
|
1754
2027
|
const constraints = [
|
|
1755
2028
|
where8("isActive", "==", active),
|
|
1756
|
-
|
|
2029
|
+
orderBy8("name"),
|
|
1757
2030
|
queryLimit ? limit7(queryLimit) : void 0,
|
|
1758
2031
|
lastVisible ? startAfter6(lastVisible) : void 0
|
|
1759
2032
|
].filter((c) => !!c);
|
|
@@ -1882,6 +2155,74 @@ var SubcategoryService = class extends BaseService {
|
|
|
1882
2155
|
...docSnap.data()
|
|
1883
2156
|
};
|
|
1884
2157
|
}
|
|
2158
|
+
/**
|
|
2159
|
+
* Exports subcategories to CSV string, suitable for Excel/Sheets.
|
|
2160
|
+
* Includes headers and optional UTF-8 BOM.
|
|
2161
|
+
* By default exports only active subcategories (set includeInactive to true to export all).
|
|
2162
|
+
*/
|
|
2163
|
+
async exportToCsv(options) {
|
|
2164
|
+
var _a, _b;
|
|
2165
|
+
const includeInactive = (_a = options == null ? void 0 : options.includeInactive) != null ? _a : false;
|
|
2166
|
+
const includeBom = (_b = options == null ? void 0 : options.includeBom) != null ? _b : true;
|
|
2167
|
+
const headers = [
|
|
2168
|
+
"id",
|
|
2169
|
+
"name",
|
|
2170
|
+
"categoryId",
|
|
2171
|
+
"description",
|
|
2172
|
+
"isActive"
|
|
2173
|
+
];
|
|
2174
|
+
const rows = [];
|
|
2175
|
+
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
2176
|
+
const PAGE_SIZE = 1e3;
|
|
2177
|
+
let cursor;
|
|
2178
|
+
const constraints = [];
|
|
2179
|
+
if (!includeInactive) {
|
|
2180
|
+
constraints.push(where8("isActive", "==", true));
|
|
2181
|
+
}
|
|
2182
|
+
constraints.push(orderBy8("name"));
|
|
2183
|
+
while (true) {
|
|
2184
|
+
const queryConstraints = [...constraints, limit7(PAGE_SIZE)];
|
|
2185
|
+
if (cursor) queryConstraints.push(startAfter6(cursor));
|
|
2186
|
+
const q = query8(
|
|
2187
|
+
collectionGroup2(this.db, SUBCATEGORIES_COLLECTION),
|
|
2188
|
+
...queryConstraints
|
|
2189
|
+
);
|
|
2190
|
+
const snapshot = await getDocs8(q);
|
|
2191
|
+
if (snapshot.empty) break;
|
|
2192
|
+
for (const d of snapshot.docs) {
|
|
2193
|
+
const subcategory = { id: d.id, ...d.data() };
|
|
2194
|
+
rows.push(this.subcategoryToCsvRow(subcategory));
|
|
2195
|
+
}
|
|
2196
|
+
cursor = snapshot.docs[snapshot.docs.length - 1];
|
|
2197
|
+
if (snapshot.size < PAGE_SIZE) break;
|
|
2198
|
+
}
|
|
2199
|
+
const csvBody = rows.join("\r\n");
|
|
2200
|
+
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
2201
|
+
}
|
|
2202
|
+
subcategoryToCsvRow(subcategory) {
|
|
2203
|
+
var _a, _b, _c, _d, _e;
|
|
2204
|
+
const values = [
|
|
2205
|
+
(_a = subcategory.id) != null ? _a : "",
|
|
2206
|
+
(_b = subcategory.name) != null ? _b : "",
|
|
2207
|
+
(_c = subcategory.categoryId) != null ? _c : "",
|
|
2208
|
+
(_d = subcategory.description) != null ? _d : "",
|
|
2209
|
+
String((_e = subcategory.isActive) != null ? _e : "")
|
|
2210
|
+
];
|
|
2211
|
+
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
2212
|
+
}
|
|
2213
|
+
formatDateIso(value) {
|
|
2214
|
+
if (value instanceof Date) return value.toISOString();
|
|
2215
|
+
if (value && typeof value.toDate === "function") {
|
|
2216
|
+
const d = value.toDate();
|
|
2217
|
+
return d instanceof Date ? d.toISOString() : String(value);
|
|
2218
|
+
}
|
|
2219
|
+
return String(value != null ? value : "");
|
|
2220
|
+
}
|
|
2221
|
+
formatCsvValue(value) {
|
|
2222
|
+
const str = value === null || value === void 0 ? "" : String(value);
|
|
2223
|
+
const escaped = str.replace(/"/g, '""');
|
|
2224
|
+
return `"${escaped}"`;
|
|
2225
|
+
}
|
|
1885
2226
|
};
|
|
1886
2227
|
|
|
1887
2228
|
// src/backoffice/services/technology.service.ts
|
|
@@ -1892,7 +2233,7 @@ import {
|
|
|
1892
2233
|
getDoc as getDoc9,
|
|
1893
2234
|
getDocs as getDocs9,
|
|
1894
2235
|
limit as limit8,
|
|
1895
|
-
orderBy as
|
|
2236
|
+
orderBy as orderBy9,
|
|
1896
2237
|
query as query9,
|
|
1897
2238
|
startAfter as startAfter7,
|
|
1898
2239
|
updateDoc as updateDoc9,
|
|
@@ -2006,7 +2347,7 @@ var TechnologyService = class extends BaseService {
|
|
|
2006
2347
|
const { active = true, limit: queryLimit = 10, lastVisible } = options;
|
|
2007
2348
|
const constraints = [
|
|
2008
2349
|
where9("isActive", "==", active),
|
|
2009
|
-
|
|
2350
|
+
orderBy9("name"),
|
|
2010
2351
|
queryLimit ? limit8(queryLimit) : void 0,
|
|
2011
2352
|
lastVisible ? startAfter7(lastVisible) : void 0
|
|
2012
2353
|
].filter((c) => !!c);
|
|
@@ -2032,7 +2373,7 @@ var TechnologyService = class extends BaseService {
|
|
|
2032
2373
|
const constraints = [
|
|
2033
2374
|
where9("categoryId", "==", categoryId),
|
|
2034
2375
|
where9("isActive", "==", active),
|
|
2035
|
-
|
|
2376
|
+
orderBy9("name"),
|
|
2036
2377
|
queryLimit ? limit8(queryLimit) : void 0,
|
|
2037
2378
|
lastVisible ? startAfter7(lastVisible) : void 0
|
|
2038
2379
|
].filter((c) => !!c);
|
|
@@ -2058,7 +2399,7 @@ var TechnologyService = class extends BaseService {
|
|
|
2058
2399
|
const constraints = [
|
|
2059
2400
|
where9("subcategoryId", "==", subcategoryId),
|
|
2060
2401
|
where9("isActive", "==", active),
|
|
2061
|
-
|
|
2402
|
+
orderBy9("name"),
|
|
2062
2403
|
queryLimit ? limit8(queryLimit) : void 0,
|
|
2063
2404
|
lastVisible ? startAfter7(lastVisible) : void 0
|
|
2064
2405
|
].filter((c) => !!c);
|
|
@@ -2487,7 +2828,7 @@ var TechnologyService = class extends BaseService {
|
|
|
2487
2828
|
collection9(this.db, TECHNOLOGIES_COLLECTION),
|
|
2488
2829
|
where9("isActive", "==", true),
|
|
2489
2830
|
where9("subcategoryId", "==", subcategoryId),
|
|
2490
|
-
|
|
2831
|
+
orderBy9("name")
|
|
2491
2832
|
);
|
|
2492
2833
|
const snapshot = await getDocs9(q);
|
|
2493
2834
|
return snapshot.docs.map(
|
|
@@ -2508,7 +2849,7 @@ var TechnologyService = class extends BaseService {
|
|
|
2508
2849
|
where9("isActive", "==", true),
|
|
2509
2850
|
where9("categoryId", "==", categoryId),
|
|
2510
2851
|
where9("subcategoryId", "==", subcategoryId),
|
|
2511
|
-
|
|
2852
|
+
orderBy9("name")
|
|
2512
2853
|
);
|
|
2513
2854
|
const snapshot = await getDocs9(q);
|
|
2514
2855
|
return snapshot.docs.map(
|
|
@@ -2525,7 +2866,7 @@ var TechnologyService = class extends BaseService {
|
|
|
2525
2866
|
const q = query9(
|
|
2526
2867
|
collection9(this.db, TECHNOLOGIES_COLLECTION),
|
|
2527
2868
|
where9("isActive", "==", true),
|
|
2528
|
-
|
|
2869
|
+
orderBy9("name")
|
|
2529
2870
|
);
|
|
2530
2871
|
const snapshot = await getDocs9(q);
|
|
2531
2872
|
return snapshot.docs.map(
|
|
@@ -2577,7 +2918,7 @@ var TechnologyService = class extends BaseService {
|
|
|
2577
2918
|
collection9(this.db, PRODUCTS_COLLECTION),
|
|
2578
2919
|
where9("assignedTechnologyIds", "array-contains", technologyId),
|
|
2579
2920
|
where9("isActive", "==", true),
|
|
2580
|
-
|
|
2921
|
+
orderBy9("name")
|
|
2581
2922
|
);
|
|
2582
2923
|
const snapshot = await getDocs9(q);
|
|
2583
2924
|
return snapshot.docs.map(
|
|
@@ -2594,7 +2935,7 @@ var TechnologyService = class extends BaseService {
|
|
|
2594
2935
|
const q = query9(
|
|
2595
2936
|
collection9(this.db, PRODUCTS_COLLECTION),
|
|
2596
2937
|
where9("isActive", "==", true),
|
|
2597
|
-
|
|
2938
|
+
orderBy9("name")
|
|
2598
2939
|
);
|
|
2599
2940
|
const snapshot = await getDocs9(q);
|
|
2600
2941
|
const allProducts = snapshot.docs.map(
|
|
@@ -2654,6 +2995,106 @@ var TechnologyService = class extends BaseService {
|
|
|
2654
2995
|
}
|
|
2655
2996
|
await batch.commit();
|
|
2656
2997
|
}
|
|
2998
|
+
/**
|
|
2999
|
+
* Exports technologies to CSV string, suitable for Excel/Sheets.
|
|
3000
|
+
* Includes headers and optional UTF-8 BOM.
|
|
3001
|
+
* By default exports only active technologies (set includeInactive to true to export all).
|
|
3002
|
+
* Includes product names from subcollections.
|
|
3003
|
+
*/
|
|
3004
|
+
async exportToCsv(options) {
|
|
3005
|
+
var _a, _b;
|
|
3006
|
+
const includeInactive = (_a = options == null ? void 0 : options.includeInactive) != null ? _a : false;
|
|
3007
|
+
const includeBom = (_b = options == null ? void 0 : options.includeBom) != null ? _b : true;
|
|
3008
|
+
const headers = [
|
|
3009
|
+
"id",
|
|
3010
|
+
"name",
|
|
3011
|
+
"description",
|
|
3012
|
+
"family",
|
|
3013
|
+
"categoryId",
|
|
3014
|
+
"subcategoryId",
|
|
3015
|
+
"technicalDetails",
|
|
3016
|
+
"requirements_pre",
|
|
3017
|
+
"requirements_post",
|
|
3018
|
+
"blockingConditions",
|
|
3019
|
+
"contraindications",
|
|
3020
|
+
"benefits",
|
|
3021
|
+
"certificationMinimumLevel",
|
|
3022
|
+
"certificationRequiredSpecialties",
|
|
3023
|
+
"documentationTemplateIds",
|
|
3024
|
+
"productNames",
|
|
3025
|
+
"isActive"
|
|
3026
|
+
];
|
|
3027
|
+
const rows = [];
|
|
3028
|
+
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
3029
|
+
const PAGE_SIZE = 1e3;
|
|
3030
|
+
let cursor;
|
|
3031
|
+
const constraints = [];
|
|
3032
|
+
if (!includeInactive) {
|
|
3033
|
+
constraints.push(where9("isActive", "==", true));
|
|
3034
|
+
}
|
|
3035
|
+
constraints.push(orderBy9("name"));
|
|
3036
|
+
while (true) {
|
|
3037
|
+
const queryConstraints = [...constraints, limit8(PAGE_SIZE)];
|
|
3038
|
+
if (cursor) queryConstraints.push(startAfter7(cursor));
|
|
3039
|
+
const q = query9(this.technologiesRef, ...queryConstraints);
|
|
3040
|
+
const snapshot = await getDocs9(q);
|
|
3041
|
+
if (snapshot.empty) break;
|
|
3042
|
+
for (const d of snapshot.docs) {
|
|
3043
|
+
const technology = { id: d.id, ...d.data() };
|
|
3044
|
+
const productNames = await this.getProductNamesForTechnology(technology.id);
|
|
3045
|
+
rows.push(this.technologyToCsvRow(technology, productNames));
|
|
3046
|
+
}
|
|
3047
|
+
cursor = snapshot.docs[snapshot.docs.length - 1];
|
|
3048
|
+
if (snapshot.size < PAGE_SIZE) break;
|
|
3049
|
+
}
|
|
3050
|
+
const csvBody = rows.join("\r\n");
|
|
3051
|
+
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
3052
|
+
}
|
|
3053
|
+
/**
|
|
3054
|
+
* Gets product names from the technology's product subcollection
|
|
3055
|
+
*/
|
|
3056
|
+
async getProductNamesForTechnology(technologyId) {
|
|
3057
|
+
try {
|
|
3058
|
+
const productsRef = collection9(this.db, TECHNOLOGIES_COLLECTION, technologyId, PRODUCTS_COLLECTION);
|
|
3059
|
+
const q = query9(productsRef, where9("isActive", "==", true));
|
|
3060
|
+
const snapshot = await getDocs9(q);
|
|
3061
|
+
return snapshot.docs.map((doc11) => {
|
|
3062
|
+
const product = doc11.data();
|
|
3063
|
+
return product.name || "";
|
|
3064
|
+
}).filter((name) => name);
|
|
3065
|
+
} catch (error) {
|
|
3066
|
+
console.error(`Error fetching products for technology ${technologyId}:`, error);
|
|
3067
|
+
return [];
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
technologyToCsvRow(technology, productNames = []) {
|
|
3071
|
+
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;
|
|
3072
|
+
const values = [
|
|
3073
|
+
(_a = technology.id) != null ? _a : "",
|
|
3074
|
+
(_b = technology.name) != null ? _b : "",
|
|
3075
|
+
(_c = technology.description) != null ? _c : "",
|
|
3076
|
+
(_d = technology.family) != null ? _d : "",
|
|
3077
|
+
(_e = technology.categoryId) != null ? _e : "",
|
|
3078
|
+
(_f = technology.subcategoryId) != null ? _f : "",
|
|
3079
|
+
(_g = technology.technicalDetails) != null ? _g : "",
|
|
3080
|
+
(_j = (_i = (_h = technology.requirements) == null ? void 0 : _h.pre) == null ? void 0 : _i.map((r) => r.name).join(";")) != null ? _j : "",
|
|
3081
|
+
(_m = (_l = (_k = technology.requirements) == null ? void 0 : _k.post) == null ? void 0 : _l.map((r) => r.name).join(";")) != null ? _m : "",
|
|
3082
|
+
(_o = (_n = technology.blockingConditions) == null ? void 0 : _n.join(";")) != null ? _o : "",
|
|
3083
|
+
(_q = (_p = technology.contraindications) == null ? void 0 : _p.map((c) => c.name).join(";")) != null ? _q : "",
|
|
3084
|
+
(_s = (_r = technology.benefits) == null ? void 0 : _r.map((b) => b.name).join(";")) != null ? _s : "",
|
|
3085
|
+
(_u = (_t = technology.certificationRequirement) == null ? void 0 : _t.minimumLevel) != null ? _u : "",
|
|
3086
|
+
(_x = (_w = (_v = technology.certificationRequirement) == null ? void 0 : _v.requiredSpecialties) == null ? void 0 : _w.join(";")) != null ? _x : "",
|
|
3087
|
+
(_z = (_y = technology.documentationTemplates) == null ? void 0 : _y.map((t) => t.templateId).join(";")) != null ? _z : "",
|
|
3088
|
+
productNames.join(";"),
|
|
3089
|
+
String((_A = technology.isActive) != null ? _A : "")
|
|
3090
|
+
];
|
|
3091
|
+
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
3092
|
+
}
|
|
3093
|
+
formatCsvValue(value) {
|
|
3094
|
+
const str = value === null || value === void 0 ? "" : String(value);
|
|
3095
|
+
const escaped = str.replace(/"/g, '""');
|
|
3096
|
+
return `"${escaped}"`;
|
|
3097
|
+
}
|
|
2657
3098
|
};
|
|
2658
3099
|
|
|
2659
3100
|
// src/backoffice/services/constants.service.ts
|
|
@@ -2893,6 +3334,66 @@ var ConstantsService = class extends BaseService {
|
|
|
2893
3334
|
contraindications: arrayRemove3(toRemove)
|
|
2894
3335
|
});
|
|
2895
3336
|
}
|
|
3337
|
+
// =================================================================
|
|
3338
|
+
// CSV Export Methods
|
|
3339
|
+
// =================================================================
|
|
3340
|
+
/**
|
|
3341
|
+
* Exports treatment benefits to CSV string, suitable for Excel/Sheets.
|
|
3342
|
+
* Includes headers and optional UTF-8 BOM.
|
|
3343
|
+
*/
|
|
3344
|
+
async exportBenefitsToCsv(options) {
|
|
3345
|
+
var _a;
|
|
3346
|
+
const includeBom = (_a = options == null ? void 0 : options.includeBom) != null ? _a : true;
|
|
3347
|
+
const headers = ["id", "name", "description"];
|
|
3348
|
+
const rows = [];
|
|
3349
|
+
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
3350
|
+
const benefits = await this.getAllBenefitsForFilter();
|
|
3351
|
+
for (const benefit of benefits) {
|
|
3352
|
+
rows.push(this.benefitToCsvRow(benefit));
|
|
3353
|
+
}
|
|
3354
|
+
const csvBody = rows.join("\r\n");
|
|
3355
|
+
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
3356
|
+
}
|
|
3357
|
+
/**
|
|
3358
|
+
* Exports contraindications to CSV string, suitable for Excel/Sheets.
|
|
3359
|
+
* Includes headers and optional UTF-8 BOM.
|
|
3360
|
+
*/
|
|
3361
|
+
async exportContraindicationsToCsv(options) {
|
|
3362
|
+
var _a;
|
|
3363
|
+
const includeBom = (_a = options == null ? void 0 : options.includeBom) != null ? _a : true;
|
|
3364
|
+
const headers = ["id", "name", "description"];
|
|
3365
|
+
const rows = [];
|
|
3366
|
+
rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
|
|
3367
|
+
const contraindications = await this.getAllContraindicationsForFilter();
|
|
3368
|
+
for (const contraindication of contraindications) {
|
|
3369
|
+
rows.push(this.contraindicationToCsvRow(contraindication));
|
|
3370
|
+
}
|
|
3371
|
+
const csvBody = rows.join("\r\n");
|
|
3372
|
+
return includeBom ? "\uFEFF" + csvBody : csvBody;
|
|
3373
|
+
}
|
|
3374
|
+
benefitToCsvRow(benefit) {
|
|
3375
|
+
var _a, _b, _c;
|
|
3376
|
+
const values = [
|
|
3377
|
+
(_a = benefit.id) != null ? _a : "",
|
|
3378
|
+
(_b = benefit.name) != null ? _b : "",
|
|
3379
|
+
(_c = benefit.description) != null ? _c : ""
|
|
3380
|
+
];
|
|
3381
|
+
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
3382
|
+
}
|
|
3383
|
+
contraindicationToCsvRow(contraindication) {
|
|
3384
|
+
var _a, _b, _c;
|
|
3385
|
+
const values = [
|
|
3386
|
+
(_a = contraindication.id) != null ? _a : "",
|
|
3387
|
+
(_b = contraindication.name) != null ? _b : "",
|
|
3388
|
+
(_c = contraindication.description) != null ? _c : ""
|
|
3389
|
+
];
|
|
3390
|
+
return values.map((v) => this.formatCsvValue(v)).join(",");
|
|
3391
|
+
}
|
|
3392
|
+
formatCsvValue(value) {
|
|
3393
|
+
const str = value === null || value === void 0 ? "" : String(value);
|
|
3394
|
+
const escaped = str.replace(/"/g, '""');
|
|
3395
|
+
return `"${escaped}"`;
|
|
3396
|
+
}
|
|
2896
3397
|
};
|
|
2897
3398
|
|
|
2898
3399
|
// src/backoffice/types/static/blocking-condition.types.ts
|