@blackcode_sa/metaestetics-api 1.14.34 → 1.14.36

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.js CHANGED
@@ -23359,13 +23359,12 @@ var BrandService = class extends BaseService {
23359
23359
  return { id: docRef.id, ...newBrand };
23360
23360
  }
23361
23361
  /**
23362
- * Gets a paginated list of active brands, optionally filtered by name and category.
23362
+ * Gets a paginated list of active brands, optionally filtered by name.
23363
23363
  * @param rowsPerPage - The number of brands to fetch.
23364
23364
  * @param searchTerm - An optional string to filter brand names by (starts-with search).
23365
23365
  * @param lastVisible - An optional document snapshot to use as a cursor for pagination.
23366
- * @param category - An optional category to filter brands by.
23367
23366
  */
23368
- async getAll(rowsPerPage, searchTerm, lastVisible, category) {
23367
+ async getAll(rowsPerPage, searchTerm, lastVisible) {
23369
23368
  const constraints = [
23370
23369
  (0, import_firestore61.where)("isActive", "==", true),
23371
23370
  (0, import_firestore61.orderBy)("name_lowercase")
@@ -23377,9 +23376,6 @@ var BrandService = class extends BaseService {
23377
23376
  (0, import_firestore61.where)("name_lowercase", "<=", lowercasedSearchTerm + "\uF8FF")
23378
23377
  );
23379
23378
  }
23380
- if (category) {
23381
- constraints.push((0, import_firestore61.where)("category", "==", category));
23382
- }
23383
23379
  if (lastVisible) {
23384
23380
  constraints.push((0, import_firestore61.startAfter)(lastVisible));
23385
23381
  }
@@ -23396,11 +23392,10 @@ var BrandService = class extends BaseService {
23396
23392
  return { brands, lastVisible: newLastVisible };
23397
23393
  }
23398
23394
  /**
23399
- * Gets the total count of active brands, optionally filtered by name and category.
23395
+ * Gets the total count of active brands, optionally filtered by name.
23400
23396
  * @param searchTerm - An optional string to filter brand names by (starts-with search).
23401
- * @param category - An optional category to filter brands by.
23402
23397
  */
23403
- async getBrandsCount(searchTerm, category) {
23398
+ async getBrandsCount(searchTerm) {
23404
23399
  const constraints = [(0, import_firestore61.where)("isActive", "==", true)];
23405
23400
  if (searchTerm) {
23406
23401
  const lowercasedSearchTerm = searchTerm.toLowerCase();
@@ -23409,9 +23404,6 @@ var BrandService = class extends BaseService {
23409
23404
  (0, import_firestore61.where)("name_lowercase", "<=", lowercasedSearchTerm + "\uF8FF")
23410
23405
  );
23411
23406
  }
23412
- if (category) {
23413
- constraints.push((0, import_firestore61.where)("category", "==", category));
23414
- }
23415
23407
  const q = (0, import_firestore61.query)(this.getBrandsRef(), ...constraints);
23416
23408
  const snapshot = await (0, import_firestore61.getCountFromServer)(q);
23417
23409
  return snapshot.data().count;
@@ -23481,7 +23473,6 @@ var BrandService = class extends BaseService {
23481
23473
  "id",
23482
23474
  "name",
23483
23475
  "manufacturer",
23484
- "category",
23485
23476
  "website",
23486
23477
  "description",
23487
23478
  "isActive"
@@ -23512,15 +23503,14 @@ var BrandService = class extends BaseService {
23512
23503
  return includeBom ? "\uFEFF" + csvBody : csvBody;
23513
23504
  }
23514
23505
  brandToCsvRow(brand) {
23515
- var _a, _b, _c, _d, _e, _f, _g;
23506
+ var _a, _b, _c, _d, _e, _f;
23516
23507
  const values = [
23517
23508
  (_a = brand.id) != null ? _a : "",
23518
23509
  (_b = brand.name) != null ? _b : "",
23519
23510
  (_c = brand.manufacturer) != null ? _c : "",
23520
- (_d = brand.category) != null ? _d : "",
23521
- (_e = brand.website) != null ? _e : "",
23522
- (_f = brand.description) != null ? _f : "",
23523
- String((_g = brand.isActive) != null ? _g : "")
23511
+ (_d = brand.website) != null ? _d : "",
23512
+ (_e = brand.description) != null ? _e : "",
23513
+ String((_f = brand.isActive) != null ? _f : "")
23524
23514
  ];
23525
23515
  return values.map((v) => this.formatCsvValue(v)).join(",");
23526
23516
  }
@@ -24946,7 +24936,8 @@ var TechnologyService = class extends BaseService {
24946
24936
  const products = await this.getAssignedProducts(technologyId);
24947
24937
  const byBrand = {};
24948
24938
  products.forEach((product) => {
24949
- byBrand[product.brandName] = (byBrand[product.brandName] || 0) + 1;
24939
+ const brandName = product.brandName || "Unknown";
24940
+ byBrand[brandName] = (byBrand[brandName] || 0) + 1;
24950
24941
  });
24951
24942
  return {
24952
24943
  totalAssigned: products.length,
@@ -25277,11 +25268,10 @@ var ProductService = class extends BaseService {
25277
25268
  /**
25278
25269
  * Creates a new product in the top-level collection
25279
25270
  */
25280
- async createTopLevel(brandId, product, technologyIds = []) {
25271
+ async createTopLevel(product, technologyIds = []) {
25281
25272
  const now = /* @__PURE__ */ new Date();
25282
25273
  const newProduct = {
25283
25274
  ...product,
25284
- brandId,
25285
25275
  assignedTechnologyIds: technologyIds,
25286
25276
  createdAt: now,
25287
25277
  updatedAt: now,
@@ -25294,11 +25284,14 @@ var ProductService = class extends BaseService {
25294
25284
  * Gets all products from the top-level collection
25295
25285
  */
25296
25286
  async getAllTopLevel(options) {
25297
- const { rowsPerPage, lastVisible, brandId } = options;
25287
+ const { rowsPerPage, lastVisible, brandId, category } = options;
25298
25288
  const constraints = [(0, import_firestore65.where)("isActive", "==", true), (0, import_firestore65.orderBy)("name")];
25299
25289
  if (brandId) {
25300
25290
  constraints.push((0, import_firestore65.where)("brandId", "==", brandId));
25301
25291
  }
25292
+ if (category) {
25293
+ constraints.push((0, import_firestore65.where)("category", "==", category));
25294
+ }
25302
25295
  if (lastVisible) {
25303
25296
  constraints.push((0, import_firestore65.startAfter)(lastVisible));
25304
25297
  }
@@ -25439,14 +25432,10 @@ var ProductService = class extends BaseService {
25439
25432
  "name",
25440
25433
  "brandId",
25441
25434
  "brandName",
25435
+ "category",
25442
25436
  "assignedTechnologyIds",
25443
25437
  "description",
25444
- "technicalDetails",
25445
- "dosage",
25446
- "composition",
25447
- "indications",
25448
- "contraindications",
25449
- "warnings",
25438
+ "metadata",
25450
25439
  "isActive"
25451
25440
  ];
25452
25441
  const rows = [];
@@ -25475,21 +25464,17 @@ var ProductService = class extends BaseService {
25475
25464
  return includeBom ? "\uFEFF" + csvBody : csvBody;
25476
25465
  }
25477
25466
  productToCsvRow(product) {
25478
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
25467
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
25479
25468
  const values = [
25480
25469
  (_a = product.id) != null ? _a : "",
25481
25470
  (_b = product.name) != null ? _b : "",
25482
25471
  (_c = product.brandId) != null ? _c : "",
25483
25472
  (_d = product.brandName) != null ? _d : "",
25484
- (_f = (_e = product.assignedTechnologyIds) == null ? void 0 : _e.join(";")) != null ? _f : "",
25485
- (_g = product.description) != null ? _g : "",
25486
- (_h = product.technicalDetails) != null ? _h : "",
25487
- (_i = product.dosage) != null ? _i : "",
25488
- (_j = product.composition) != null ? _j : "",
25489
- (_l = (_k = product.indications) == null ? void 0 : _k.join(";")) != null ? _l : "",
25490
- (_n = (_m = product.contraindications) == null ? void 0 : _m.map((c) => c.name).join(";")) != null ? _n : "",
25491
- (_p = (_o = product.warnings) == null ? void 0 : _o.join(";")) != null ? _p : "",
25492
- String((_q = product.isActive) != null ? _q : "")
25473
+ (_e = product.category) != null ? _e : "",
25474
+ (_g = (_f = product.assignedTechnologyIds) == null ? void 0 : _f.join(";")) != null ? _g : "",
25475
+ (_h = product.description) != null ? _h : "",
25476
+ product.metadata ? JSON.stringify(product.metadata) : "",
25477
+ String((_i = product.isActive) != null ? _i : "")
25493
25478
  ];
25494
25479
  return values.map((v) => this.formatCsvValue(v)).join(",");
25495
25480
  }
package/dist/index.mjs CHANGED
@@ -23618,13 +23618,12 @@ var BrandService = class extends BaseService {
23618
23618
  return { id: docRef.id, ...newBrand };
23619
23619
  }
23620
23620
  /**
23621
- * Gets a paginated list of active brands, optionally filtered by name and category.
23621
+ * Gets a paginated list of active brands, optionally filtered by name.
23622
23622
  * @param rowsPerPage - The number of brands to fetch.
23623
23623
  * @param searchTerm - An optional string to filter brand names by (starts-with search).
23624
23624
  * @param lastVisible - An optional document snapshot to use as a cursor for pagination.
23625
- * @param category - An optional category to filter brands by.
23626
23625
  */
23627
- async getAll(rowsPerPage, searchTerm, lastVisible, category) {
23626
+ async getAll(rowsPerPage, searchTerm, lastVisible) {
23628
23627
  const constraints = [
23629
23628
  where35("isActive", "==", true),
23630
23629
  orderBy19("name_lowercase")
@@ -23636,9 +23635,6 @@ var BrandService = class extends BaseService {
23636
23635
  where35("name_lowercase", "<=", lowercasedSearchTerm + "\uF8FF")
23637
23636
  );
23638
23637
  }
23639
- if (category) {
23640
- constraints.push(where35("category", "==", category));
23641
- }
23642
23638
  if (lastVisible) {
23643
23639
  constraints.push(startAfter15(lastVisible));
23644
23640
  }
@@ -23655,11 +23651,10 @@ var BrandService = class extends BaseService {
23655
23651
  return { brands, lastVisible: newLastVisible };
23656
23652
  }
23657
23653
  /**
23658
- * Gets the total count of active brands, optionally filtered by name and category.
23654
+ * Gets the total count of active brands, optionally filtered by name.
23659
23655
  * @param searchTerm - An optional string to filter brand names by (starts-with search).
23660
- * @param category - An optional category to filter brands by.
23661
23656
  */
23662
- async getBrandsCount(searchTerm, category) {
23657
+ async getBrandsCount(searchTerm) {
23663
23658
  const constraints = [where35("isActive", "==", true)];
23664
23659
  if (searchTerm) {
23665
23660
  const lowercasedSearchTerm = searchTerm.toLowerCase();
@@ -23668,9 +23663,6 @@ var BrandService = class extends BaseService {
23668
23663
  where35("name_lowercase", "<=", lowercasedSearchTerm + "\uF8FF")
23669
23664
  );
23670
23665
  }
23671
- if (category) {
23672
- constraints.push(where35("category", "==", category));
23673
- }
23674
23666
  const q = query35(this.getBrandsRef(), ...constraints);
23675
23667
  const snapshot = await getCountFromServer3(q);
23676
23668
  return snapshot.data().count;
@@ -23740,7 +23732,6 @@ var BrandService = class extends BaseService {
23740
23732
  "id",
23741
23733
  "name",
23742
23734
  "manufacturer",
23743
- "category",
23744
23735
  "website",
23745
23736
  "description",
23746
23737
  "isActive"
@@ -23771,15 +23762,14 @@ var BrandService = class extends BaseService {
23771
23762
  return includeBom ? "\uFEFF" + csvBody : csvBody;
23772
23763
  }
23773
23764
  brandToCsvRow(brand) {
23774
- var _a, _b, _c, _d, _e, _f, _g;
23765
+ var _a, _b, _c, _d, _e, _f;
23775
23766
  const values = [
23776
23767
  (_a = brand.id) != null ? _a : "",
23777
23768
  (_b = brand.name) != null ? _b : "",
23778
23769
  (_c = brand.manufacturer) != null ? _c : "",
23779
- (_d = brand.category) != null ? _d : "",
23780
- (_e = brand.website) != null ? _e : "",
23781
- (_f = brand.description) != null ? _f : "",
23782
- String((_g = brand.isActive) != null ? _g : "")
23770
+ (_d = brand.website) != null ? _d : "",
23771
+ (_e = brand.description) != null ? _e : "",
23772
+ String((_f = brand.isActive) != null ? _f : "")
23783
23773
  ];
23784
23774
  return values.map((v) => this.formatCsvValue(v)).join(",");
23785
23775
  }
@@ -25247,7 +25237,8 @@ var TechnologyService = class extends BaseService {
25247
25237
  const products = await this.getAssignedProducts(technologyId);
25248
25238
  const byBrand = {};
25249
25239
  products.forEach((product) => {
25250
- byBrand[product.brandName] = (byBrand[product.brandName] || 0) + 1;
25240
+ const brandName = product.brandName || "Unknown";
25241
+ byBrand[brandName] = (byBrand[brandName] || 0) + 1;
25251
25242
  });
25252
25243
  return {
25253
25244
  totalAssigned: products.length,
@@ -25594,11 +25585,10 @@ var ProductService = class extends BaseService {
25594
25585
  /**
25595
25586
  * Creates a new product in the top-level collection
25596
25587
  */
25597
- async createTopLevel(brandId, product, technologyIds = []) {
25588
+ async createTopLevel(product, technologyIds = []) {
25598
25589
  const now = /* @__PURE__ */ new Date();
25599
25590
  const newProduct = {
25600
25591
  ...product,
25601
- brandId,
25602
25592
  assignedTechnologyIds: technologyIds,
25603
25593
  createdAt: now,
25604
25594
  updatedAt: now,
@@ -25611,11 +25601,14 @@ var ProductService = class extends BaseService {
25611
25601
  * Gets all products from the top-level collection
25612
25602
  */
25613
25603
  async getAllTopLevel(options) {
25614
- const { rowsPerPage, lastVisible, brandId } = options;
25604
+ const { rowsPerPage, lastVisible, brandId, category } = options;
25615
25605
  const constraints = [where39("isActive", "==", true), orderBy23("name")];
25616
25606
  if (brandId) {
25617
25607
  constraints.push(where39("brandId", "==", brandId));
25618
25608
  }
25609
+ if (category) {
25610
+ constraints.push(where39("category", "==", category));
25611
+ }
25619
25612
  if (lastVisible) {
25620
25613
  constraints.push(startAfter19(lastVisible));
25621
25614
  }
@@ -25756,14 +25749,10 @@ var ProductService = class extends BaseService {
25756
25749
  "name",
25757
25750
  "brandId",
25758
25751
  "brandName",
25752
+ "category",
25759
25753
  "assignedTechnologyIds",
25760
25754
  "description",
25761
- "technicalDetails",
25762
- "dosage",
25763
- "composition",
25764
- "indications",
25765
- "contraindications",
25766
- "warnings",
25755
+ "metadata",
25767
25756
  "isActive"
25768
25757
  ];
25769
25758
  const rows = [];
@@ -25792,21 +25781,17 @@ var ProductService = class extends BaseService {
25792
25781
  return includeBom ? "\uFEFF" + csvBody : csvBody;
25793
25782
  }
25794
25783
  productToCsvRow(product) {
25795
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q;
25784
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
25796
25785
  const values = [
25797
25786
  (_a = product.id) != null ? _a : "",
25798
25787
  (_b = product.name) != null ? _b : "",
25799
25788
  (_c = product.brandId) != null ? _c : "",
25800
25789
  (_d = product.brandName) != null ? _d : "",
25801
- (_f = (_e = product.assignedTechnologyIds) == null ? void 0 : _e.join(";")) != null ? _f : "",
25802
- (_g = product.description) != null ? _g : "",
25803
- (_h = product.technicalDetails) != null ? _h : "",
25804
- (_i = product.dosage) != null ? _i : "",
25805
- (_j = product.composition) != null ? _j : "",
25806
- (_l = (_k = product.indications) == null ? void 0 : _k.join(";")) != null ? _l : "",
25807
- (_n = (_m = product.contraindications) == null ? void 0 : _m.map((c) => c.name).join(";")) != null ? _n : "",
25808
- (_p = (_o = product.warnings) == null ? void 0 : _o.join(";")) != null ? _p : "",
25809
- String((_q = product.isActive) != null ? _q : "")
25790
+ (_e = product.category) != null ? _e : "",
25791
+ (_g = (_f = product.assignedTechnologyIds) == null ? void 0 : _f.join(";")) != null ? _g : "",
25792
+ (_h = product.description) != null ? _h : "",
25793
+ product.metadata ? JSON.stringify(product.metadata) : "",
25794
+ String((_i = product.isActive) != null ? _i : "")
25810
25795
  ];
25811
25796
  return values.map((v) => this.formatCsvValue(v)).join(",");
25812
25797
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blackcode_sa/metaestetics-api",
3
3
  "private": false,
4
- "version": "1.14.34",
4
+ "version": "1.14.36",
5
5
  "description": "Firebase authentication service with anonymous upgrade support",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",
@@ -46,17 +46,15 @@ export class BrandService extends BaseService {
46
46
  }
47
47
 
48
48
  /**
49
- * Gets a paginated list of active brands, optionally filtered by name and category.
49
+ * Gets a paginated list of active brands, optionally filtered by name.
50
50
  * @param rowsPerPage - The number of brands to fetch.
51
51
  * @param searchTerm - An optional string to filter brand names by (starts-with search).
52
52
  * @param lastVisible - An optional document snapshot to use as a cursor for pagination.
53
- * @param category - An optional category to filter brands by.
54
53
  */
55
54
  async getAll(
56
55
  rowsPerPage: number,
57
56
  searchTerm?: string,
58
- lastVisible?: any,
59
- category?: string
57
+ lastVisible?: any
60
58
  ) {
61
59
  const constraints: QueryConstraint[] = [
62
60
  where("isActive", "==", true),
@@ -71,10 +69,6 @@ export class BrandService extends BaseService {
71
69
  );
72
70
  }
73
71
 
74
- if (category) {
75
- constraints.push(where("category", "==", category));
76
- }
77
-
78
72
  if (lastVisible) {
79
73
  constraints.push(startAfter(lastVisible));
80
74
  }
@@ -97,11 +91,10 @@ export class BrandService extends BaseService {
97
91
  }
98
92
 
99
93
  /**
100
- * Gets the total count of active brands, optionally filtered by name and category.
94
+ * Gets the total count of active brands, optionally filtered by name.
101
95
  * @param searchTerm - An optional string to filter brand names by (starts-with search).
102
- * @param category - An optional category to filter brands by.
103
96
  */
104
- async getBrandsCount(searchTerm?: string, category?: string) {
97
+ async getBrandsCount(searchTerm?: string) {
105
98
  const constraints: QueryConstraint[] = [where("isActive", "==", true)];
106
99
 
107
100
  if (searchTerm) {
@@ -112,10 +105,6 @@ export class BrandService extends BaseService {
112
105
  );
113
106
  }
114
107
 
115
- if (category) {
116
- constraints.push(where("category", "==", category));
117
- }
118
-
119
108
  const q = query(this.getBrandsRef(), ...constraints);
120
109
  const snapshot = await getCountFromServer(q);
121
110
  return snapshot.data().count;
@@ -199,7 +188,6 @@ export class BrandService extends BaseService {
199
188
  "id",
200
189
  "name",
201
190
  "manufacturer",
202
- "category",
203
191
  "website",
204
192
  "description",
205
193
  "isActive",
@@ -246,7 +234,6 @@ export class BrandService extends BaseService {
246
234
  brand.id ?? "",
247
235
  brand.name ?? "",
248
236
  brand.manufacturer ?? "",
249
- brand.category ?? "",
250
237
  brand.website ?? "",
251
238
  brand.description ?? "",
252
239
  String(brand.isActive ?? ""),
@@ -268,14 +268,12 @@ export class ProductService extends BaseService implements IProductService {
268
268
  * Creates a new product in the top-level collection
269
269
  */
270
270
  async createTopLevel(
271
- brandId: string,
272
- product: Omit<Product, 'id' | 'createdAt' | 'updatedAt' | 'brandId' | 'assignedTechnologyIds'>,
271
+ product: Omit<Product, 'id' | 'createdAt' | 'updatedAt' | 'assignedTechnologyIds'>,
273
272
  technologyIds: string[] = [],
274
273
  ): Promise<Product> {
275
274
  const now = new Date();
276
275
  const newProduct: Omit<Product, 'id'> = {
277
276
  ...product,
278
- brandId,
279
277
  assignedTechnologyIds: technologyIds,
280
278
  createdAt: now,
281
279
  updatedAt: now,
@@ -293,8 +291,9 @@ export class ProductService extends BaseService implements IProductService {
293
291
  rowsPerPage: number;
294
292
  lastVisible?: any;
295
293
  brandId?: string;
294
+ category?: string;
296
295
  }): Promise<{ products: Product[]; lastVisible: any }> {
297
- const { rowsPerPage, lastVisible, brandId } = options;
296
+ const { rowsPerPage, lastVisible, brandId, category } = options;
298
297
 
299
298
  const constraints: QueryConstraint[] = [where('isActive', '==', true), orderBy('name')];
300
299
 
@@ -302,6 +301,10 @@ export class ProductService extends BaseService implements IProductService {
302
301
  constraints.push(where('brandId', '==', brandId));
303
302
  }
304
303
 
304
+ if (category) {
305
+ constraints.push(where('category', '==', category));
306
+ }
307
+
305
308
  if (lastVisible) {
306
309
  constraints.push(startAfter(lastVisible));
307
310
  }
@@ -340,7 +343,7 @@ export class ProductService extends BaseService implements IProductService {
340
343
  */
341
344
  async updateTopLevel(
342
345
  productId: string,
343
- product: Partial<Omit<Product, 'id' | 'createdAt' | 'brandId'>>,
346
+ product: Partial<Omit<Product, 'id' | 'createdAt'>>,
344
347
  ): Promise<Product | null> {
345
348
  const updateData = {
346
349
  ...product,
@@ -468,14 +471,10 @@ export class ProductService extends BaseService implements IProductService {
468
471
  "name",
469
472
  "brandId",
470
473
  "brandName",
474
+ "category",
471
475
  "assignedTechnologyIds",
472
476
  "description",
473
- "technicalDetails",
474
- "dosage",
475
- "composition",
476
- "indications",
477
- "contraindications",
478
- "warnings",
477
+ "metadata",
479
478
  "isActive",
480
479
  ];
481
480
 
@@ -521,14 +520,10 @@ export class ProductService extends BaseService implements IProductService {
521
520
  product.name ?? "",
522
521
  product.brandId ?? "",
523
522
  product.brandName ?? "",
523
+ product.category ?? "",
524
524
  product.assignedTechnologyIds?.join(";") ?? "",
525
525
  product.description ?? "",
526
- product.technicalDetails ?? "",
527
- product.dosage ?? "",
528
- product.composition ?? "",
529
- product.indications?.join(";") ?? "",
530
- product.contraindications?.map(c => c.name).join(";") ?? "",
531
- product.warnings?.join(";") ?? "",
526
+ product.metadata ? JSON.stringify(product.metadata) : "",
532
527
  String(product.isActive ?? ""),
533
528
  ];
534
529
  return values.map((v) => this.formatCsvValue(v)).join(",");
@@ -979,7 +979,9 @@ export class TechnologyService extends BaseService implements ITechnologyService
979
979
 
980
980
  const byBrand: Record<string, number> = {};
981
981
  products.forEach(product => {
982
- byBrand[product.brandName] = (byBrand[product.brandName] || 0) + 1;
982
+ // Use brandName for grouping stats
983
+ const brandName = product.brandName || 'Unknown';
984
+ byBrand[brandName] = (byBrand[brandName] || 0) + 1;
983
985
  });
984
986
 
985
987
  return {
@@ -7,7 +7,6 @@
7
7
  * @property manufacturer - Naziv proizvođača
8
8
  * @property description - Detaljan opis brenda i njegovih proizvoda
9
9
  * @property website - Web stranica brenda
10
- * @property category - Kategorija brenda (npr. "laser", "peeling", "injectables") - za filtriranje
11
10
  * @property isActive - Da li je brend aktivan u sistemu
12
11
  * @property createdAt - Datum kreiranja
13
12
  * @property updatedAt - Datum poslednjeg ažuriranja
@@ -22,7 +21,6 @@ export interface Brand {
22
21
  isActive: boolean;
23
22
  website?: string;
24
23
  description?: string;
25
- category?: string;
26
24
  }
27
25
 
28
26
  /**
@@ -1,21 +1,14 @@
1
- import type { ContraindicationDynamic } from './admin-constants.types';
2
-
3
1
  /**
4
2
  * Product used in procedures
5
- * Can be consumables, equipment, or any other product needed for performing procedures
3
+ * Simplified structure with only essential fields and flexible metadata
6
4
  *
7
5
  * @property id - Unique identifier of the product
8
6
  * @property name - Name of the product
9
- * @property brandId - ID of the brand that manufactures this product
10
- * @property brandName - Name of the brand (denormalized for display)
7
+ * @property brandId - Reference to the Brand document ID
8
+ * @property brandName - Display name of the brand (denormalized for performance)
9
+ * @property description - Detailed description of the product
11
10
  * @property assignedTechnologyIds - Array of technology IDs this product is assigned to
12
- * @property description - Detailed description of the product and its purpose
13
- * @property technicalDetails - Technical details and specifications
14
- * @property warnings - List of warnings related to product use
15
- * @property dosage - Dosage information (if applicable)
16
- * @property composition - Product composition
17
- * @property indications - List of indications for use
18
- * @property contraindications - List of contraindications
11
+ * @property metadata - Flexible key-value pairs for additional product information
19
12
  * @property isActive - Whether the product is active in the system
20
13
  * @property createdAt - Creation date
21
14
  * @property updatedAt - Last update date
@@ -23,23 +16,21 @@ import type { ContraindicationDynamic } from './admin-constants.types';
23
16
  export interface Product {
24
17
  id?: string;
25
18
  name: string;
26
- brandId: string;
27
- brandName: string;
19
+ brandId: string; // Reference to Brand document
20
+ brandName: string; // Denormalized brand name for display
21
+ description: string;
22
+ category?: string; // "Injectables", "Laser Devices", "Skincare", etc.
28
23
 
29
- // NEW: Technology assignment tracking
24
+ // Technology assignment tracking
30
25
  assignedTechnologyIds?: string[];
31
26
 
32
- // Product details
27
+ // Flexible metadata for any additional information
28
+ metadata?: Record<string, string | number | boolean>;
29
+
30
+ // System fields
31
+ isActive: boolean;
33
32
  createdAt: Date;
34
33
  updatedAt: Date;
35
- isActive: boolean;
36
- description?: string;
37
- technicalDetails?: string;
38
- warnings?: string[];
39
- dosage?: string;
40
- composition?: string;
41
- indications?: string[];
42
- contraindications?: ContraindicationDynamic[];
43
34
 
44
35
  // LEGACY FIELDS: Only present in technology subcollections (/technologies/{id}/products/)
45
36
  // These fields are synced by Cloud Functions for backward compatibility
@@ -72,13 +63,11 @@ export interface IProductService {
72
63
 
73
64
  /**
74
65
  * Creates a new product in the top-level collection
75
- * @param brandId - ID of the brand that manufactures this product
76
66
  * @param product - Product data
77
67
  * @param technologyIds - Optional array of technology IDs to assign this product to
78
68
  */
79
69
  createTopLevel(
80
- brandId: string,
81
- product: Omit<Product, 'id' | 'createdAt' | 'updatedAt' | 'brandId' | 'assignedTechnologyIds'>,
70
+ product: Omit<Product, 'id' | 'createdAt' | 'updatedAt' | 'assignedTechnologyIds'>,
82
71
  technologyIds?: string[],
83
72
  ): Promise<Product>;
84
73
 
@@ -90,6 +79,7 @@ export interface IProductService {
90
79
  rowsPerPage: number;
91
80
  lastVisible?: any;
92
81
  brandId?: string;
82
+ category?: string;
93
83
  }): Promise<{ products: Product[]; lastVisible: any }>;
94
84
 
95
85
  /**
@@ -105,7 +95,7 @@ export interface IProductService {
105
95
  */
106
96
  updateTopLevel(
107
97
  productId: string,
108
- product: Partial<Omit<Product, 'id' | 'createdAt' | 'brandId'>>,
98
+ product: Partial<Omit<Product, 'id' | 'createdAt'>>,
109
99
  ): Promise<Product | null>;
110
100
 
111
101
  /**