@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.
@@ -7,7 +7,6 @@ import {
7
7
  query,
8
8
  updateDoc,
9
9
  where,
10
- orderBy,
11
10
  } from "firebase/firestore";
12
11
  import {
13
12
  Requirement,
@@ -157,79 +156,4 @@ export class RequirementService extends BaseService {
157
156
  ...docSnap.data(),
158
157
  } as Requirement;
159
158
  }
160
-
161
- /**
162
- * Exports requirements to CSV string, suitable for Excel/Sheets.
163
- * Includes headers and optional UTF-8 BOM.
164
- * By default exports only active requirements (set includeInactive to true to export all).
165
- */
166
- async exportToCsv(options?: {
167
- includeInactive?: boolean;
168
- includeBom?: boolean;
169
- }): Promise<string> {
170
- const includeInactive = options?.includeInactive ?? false;
171
- const includeBom = options?.includeBom ?? true;
172
-
173
- const headers = [
174
- "id",
175
- "type",
176
- "name",
177
- "description",
178
- "timeframe_duration",
179
- "timeframe_unit",
180
- "timeframe_notifyAt",
181
- "importance",
182
- "isActive",
183
- ];
184
-
185
- const rows: string[] = [];
186
- rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
187
-
188
- // Get all requirements (they're not paginated in the original service)
189
- const q = includeInactive
190
- ? query(this.requirementsRef, orderBy("name"))
191
- : query(this.requirementsRef, where("isActive", "==", true), orderBy("name"));
192
-
193
- const snapshot = await getDocs(q);
194
-
195
- for (const d of snapshot.docs) {
196
- const requirement = ({ id: d.id, ...d.data() } as unknown) as Requirement;
197
- rows.push(this.requirementToCsvRow(requirement));
198
- }
199
-
200
- const csvBody = rows.join("\r\n");
201
- return includeBom ? "\uFEFF" + csvBody : csvBody;
202
- }
203
-
204
- private requirementToCsvRow(requirement: Requirement): string {
205
- const values = [
206
- requirement.id ?? "",
207
- requirement.type ?? "",
208
- requirement.name ?? "",
209
- requirement.description ?? "",
210
- requirement.timeframe?.duration?.toString() ?? "",
211
- requirement.timeframe?.unit ?? "",
212
- requirement.timeframe?.notifyAt?.join(";") ?? "",
213
- requirement.importance ?? "",
214
- String(requirement.isActive ?? ""),
215
- ];
216
- return values.map((v) => this.formatCsvValue(v)).join(",");
217
- }
218
-
219
- private formatDateIso(value: any): string {
220
- // Firestore timestamps may come back as Date or Timestamp; handle both
221
- if (value instanceof Date) return value.toISOString();
222
- if (value && typeof value.toDate === "function") {
223
- const d = value.toDate();
224
- return d instanceof Date ? d.toISOString() : String(value);
225
- }
226
- return String(value ?? "");
227
- }
228
-
229
- private formatCsvValue(value: any): string {
230
- const str = value === null || value === undefined ? "" : String(value);
231
- // Escape double quotes by doubling them and wrap in quotes
232
- const escaped = str.replace(/"/g, '""');
233
- return `"${escaped}"`;
234
- }
235
159
  }
@@ -305,91 +305,4 @@ export class SubcategoryService extends BaseService {
305
305
  ...docSnap.data(),
306
306
  } as Subcategory;
307
307
  }
308
-
309
- /**
310
- * Exports subcategories to CSV string, suitable for Excel/Sheets.
311
- * Includes headers and optional UTF-8 BOM.
312
- * By default exports only active subcategories (set includeInactive to true to export all).
313
- */
314
- async exportToCsv(options?: {
315
- includeInactive?: boolean;
316
- includeBom?: boolean;
317
- }): Promise<string> {
318
- const includeInactive = options?.includeInactive ?? false;
319
- const includeBom = options?.includeBom ?? true;
320
-
321
- const headers = [
322
- "id",
323
- "name",
324
- "categoryId",
325
- "description",
326
- "isActive",
327
- ];
328
-
329
- const rows: string[] = [];
330
- rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
331
-
332
- const PAGE_SIZE = 1000;
333
- let cursor: any | undefined;
334
-
335
- // Build base constraints
336
- const constraints: any[] = [];
337
- if (!includeInactive) {
338
- constraints.push(where("isActive", "==", true));
339
- }
340
- constraints.push(orderBy("name"));
341
-
342
- // Page through all results using collectionGroup
343
- // eslint-disable-next-line no-constant-condition
344
- while (true) {
345
- const queryConstraints: any[] = [...constraints, limit(PAGE_SIZE)];
346
- if (cursor) queryConstraints.push(startAfter(cursor));
347
-
348
- const q = query(
349
- collectionGroup(this.db, SUBCATEGORIES_COLLECTION),
350
- ...queryConstraints
351
- );
352
- const snapshot = await getDocs(q);
353
- if (snapshot.empty) break;
354
-
355
- for (const d of snapshot.docs) {
356
- const subcategory = ({ id: d.id, ...d.data() } as unknown) as Subcategory;
357
- rows.push(this.subcategoryToCsvRow(subcategory));
358
- }
359
-
360
- cursor = snapshot.docs[snapshot.docs.length - 1];
361
- if (snapshot.size < PAGE_SIZE) break;
362
- }
363
-
364
- const csvBody = rows.join("\r\n");
365
- return includeBom ? "\uFEFF" + csvBody : csvBody;
366
- }
367
-
368
- private subcategoryToCsvRow(subcategory: Subcategory): string {
369
- const values = [
370
- subcategory.id ?? "",
371
- subcategory.name ?? "",
372
- subcategory.categoryId ?? "",
373
- subcategory.description ?? "",
374
- String(subcategory.isActive ?? ""),
375
- ];
376
- return values.map((v) => this.formatCsvValue(v)).join(",");
377
- }
378
-
379
- private formatDateIso(value: any): string {
380
- // Firestore timestamps may come back as Date or Timestamp; handle both
381
- if (value instanceof Date) return value.toISOString();
382
- if (value && typeof value.toDate === "function") {
383
- const d = value.toDate();
384
- return d instanceof Date ? d.toISOString() : String(value);
385
- }
386
- return String(value ?? "");
387
- }
388
-
389
- private formatCsvValue(value: any): string {
390
- const str = value === null || value === undefined ? "" : String(value);
391
- // Escape double quotes by doubling them and wrap in quotes
392
- const escaped = str.replace(/"/g, '""');
393
- return `"${escaped}"`;
394
- }
395
308
  }
@@ -15,8 +15,6 @@ import {
15
15
  arrayUnion,
16
16
  arrayRemove,
17
17
  Firestore,
18
- writeBatch,
19
- QueryConstraint,
20
18
  } from 'firebase/firestore';
21
19
  import { Technology, TECHNOLOGIES_COLLECTION, ITechnologyService } from '../types/technology.types';
22
20
  import { Requirement, RequirementType } from '../types/requirement.types';
@@ -31,7 +29,6 @@ import {
31
29
  import { BaseService } from '../../services/base.service';
32
30
  import { ProcedureFamily } from '../types/static/procedure-family.types';
33
31
  import { Practitioner, PractitionerCertification } from '../../types/practitioner';
34
- import { Product, PRODUCTS_COLLECTION } from '../types/product.types';
35
32
 
36
33
  /**
37
34
  * Default vrednosti za sertifikaciju
@@ -243,25 +240,7 @@ export class TechnologyService extends BaseService implements ITechnologyService
243
240
  updateData.updatedAt = new Date();
244
241
 
245
242
  const docRef = doc(this.technologiesRef, id);
246
-
247
- // Get the technology before update to check what changed
248
- const beforeTech = await this.getById(id);
249
-
250
243
  await updateDoc(docRef, updateData);
251
-
252
- // If categoryId, subcategoryId, or name changed, update all products in subcollection
253
- const categoryChanged = beforeTech && updateData.categoryId && beforeTech.categoryId !== updateData.categoryId;
254
- const subcategoryChanged = beforeTech && updateData.subcategoryId && beforeTech.subcategoryId !== updateData.subcategoryId;
255
- const nameChanged = beforeTech && updateData.name && beforeTech.name !== updateData.name;
256
-
257
- if (categoryChanged || subcategoryChanged || nameChanged) {
258
- await this.updateProductsInSubcollection(id, {
259
- categoryId: updateData.categoryId,
260
- subcategoryId: updateData.subcategoryId,
261
- technologyName: updateData.name,
262
- });
263
- }
264
-
265
244
  return this.getById(id);
266
245
  }
267
246
 
@@ -799,272 +778,4 @@ export class TechnologyService extends BaseService implements ITechnologyService
799
778
  } as Technology),
800
779
  );
801
780
  }
802
-
803
- // ==========================================
804
- // NEW METHODS: Product assignment management
805
- // ==========================================
806
-
807
- /**
808
- * Assigns multiple products to a technology
809
- * Updates each product's assignedTechnologyIds array
810
- */
811
- async assignProducts(technologyId: string, productIds: string[]): Promise<void> {
812
- const batch = writeBatch(this.db);
813
-
814
- for (const productId of productIds) {
815
- const productRef = doc(this.db, PRODUCTS_COLLECTION, productId);
816
- batch.update(productRef, {
817
- assignedTechnologyIds: arrayUnion(technologyId),
818
- updatedAt: new Date(),
819
- });
820
- }
821
-
822
- await batch.commit();
823
- // Cloud Function will handle syncing to subcollections
824
- }
825
-
826
- /**
827
- * Unassigns multiple products from a technology
828
- * Updates each product's assignedTechnologyIds array
829
- */
830
- async unassignProducts(technologyId: string, productIds: string[]): Promise<void> {
831
- const batch = writeBatch(this.db);
832
-
833
- for (const productId of productIds) {
834
- const productRef = doc(this.db, PRODUCTS_COLLECTION, productId);
835
- batch.update(productRef, {
836
- assignedTechnologyIds: arrayRemove(technologyId),
837
- updatedAt: new Date(),
838
- });
839
- }
840
-
841
- await batch.commit();
842
- // Cloud Function will handle removing from subcollections
843
- }
844
-
845
- /**
846
- * Gets products assigned to a specific technology
847
- * Reads from top-level collection for immediate consistency (Cloud Functions may lag)
848
- */
849
- async getAssignedProducts(technologyId: string): Promise<Product[]> {
850
- const q = query(
851
- collection(this.db, PRODUCTS_COLLECTION),
852
- where('assignedTechnologyIds', 'array-contains', technologyId),
853
- where('isActive', '==', true),
854
- orderBy('name'),
855
- );
856
- const snapshot = await getDocs(q);
857
-
858
- return snapshot.docs.map(
859
- doc =>
860
- ({
861
- id: doc.id,
862
- ...doc.data(),
863
- } as Product),
864
- );
865
- }
866
-
867
- /**
868
- * Gets products NOT assigned to a specific technology
869
- */
870
- async getUnassignedProducts(technologyId: string): Promise<Product[]> {
871
- const q = query(
872
- collection(this.db, PRODUCTS_COLLECTION),
873
- where('isActive', '==', true),
874
- orderBy('name'),
875
- );
876
- const snapshot = await getDocs(q);
877
-
878
- const allProducts = snapshot.docs.map(
879
- doc =>
880
- ({
881
- id: doc.id,
882
- ...doc.data(),
883
- } as Product),
884
- );
885
-
886
- // Filter out products already assigned to this technology
887
- return allProducts.filter(product =>
888
- !product.assignedTechnologyIds?.includes(technologyId)
889
- );
890
- }
891
-
892
- /**
893
- * Gets product assignment statistics for a technology
894
- */
895
- async getProductStats(technologyId: string): Promise<{
896
- totalAssigned: number;
897
- byBrand: Record<string, number>;
898
- }> {
899
- const products = await this.getAssignedProducts(technologyId);
900
-
901
- const byBrand: Record<string, number> = {};
902
- products.forEach(product => {
903
- byBrand[product.brandName] = (byBrand[product.brandName] || 0) + 1;
904
- });
905
-
906
- return {
907
- totalAssigned: products.length,
908
- byBrand,
909
- };
910
- }
911
-
912
- /**
913
- * Updates products in technology subcollection when technology metadata changes
914
- * @param technologyId - ID of the technology
915
- * @param updates - Fields to update (categoryId, subcategoryId, technologyName)
916
- */
917
- private async updateProductsInSubcollection(
918
- technologyId: string,
919
- updates: { categoryId?: string; subcategoryId?: string; technologyName?: string }
920
- ): Promise<void> {
921
- const productsRef = collection(this.db, TECHNOLOGIES_COLLECTION, technologyId, PRODUCTS_COLLECTION);
922
- const productsSnapshot = await getDocs(productsRef);
923
-
924
- if (productsSnapshot.empty) {
925
- return;
926
- }
927
-
928
- const batch = writeBatch(this.db);
929
-
930
- for (const productDoc of productsSnapshot.docs) {
931
- const productRef = productDoc.ref;
932
- const updateFields: any = {};
933
-
934
- if (updates.categoryId !== undefined) {
935
- updateFields.categoryId = updates.categoryId;
936
- }
937
- if (updates.subcategoryId !== undefined) {
938
- updateFields.subcategoryId = updates.subcategoryId;
939
- }
940
- if (updates.technologyName !== undefined) {
941
- updateFields.technologyName = updates.technologyName;
942
- }
943
-
944
- if (Object.keys(updateFields).length > 0) {
945
- batch.update(productRef, updateFields);
946
- }
947
- }
948
-
949
- await batch.commit();
950
- }
951
-
952
- /**
953
- * Exports technologies to CSV string, suitable for Excel/Sheets.
954
- * Includes headers and optional UTF-8 BOM.
955
- * By default exports only active technologies (set includeInactive to true to export all).
956
- * Includes product names from subcollections.
957
- */
958
- async exportToCsv(options?: {
959
- includeInactive?: boolean;
960
- includeBom?: boolean;
961
- }): Promise<string> {
962
- const includeInactive = options?.includeInactive ?? false;
963
- const includeBom = options?.includeBom ?? true;
964
-
965
- const headers = [
966
- "id",
967
- "name",
968
- "description",
969
- "family",
970
- "categoryId",
971
- "subcategoryId",
972
- "technicalDetails",
973
- "requirements_pre",
974
- "requirements_post",
975
- "blockingConditions",
976
- "contraindications",
977
- "benefits",
978
- "certificationMinimumLevel",
979
- "certificationRequiredSpecialties",
980
- "documentationTemplateIds",
981
- "productNames",
982
- "isActive",
983
- ];
984
-
985
- const rows: string[] = [];
986
- rows.push(headers.map((h) => this.formatCsvValue(h)).join(","));
987
-
988
- const PAGE_SIZE = 1000;
989
- let cursor: any | undefined;
990
-
991
- // Build base constraints
992
- const constraints: QueryConstraint[] = [];
993
- if (!includeInactive) {
994
- constraints.push(where("isActive", "==", true));
995
- }
996
- constraints.push(orderBy("name"));
997
-
998
- // Page through all results
999
- // eslint-disable-next-line no-constant-condition
1000
- while (true) {
1001
- const queryConstraints: QueryConstraint[] = [...constraints, limit(PAGE_SIZE)];
1002
- if (cursor) queryConstraints.push(startAfter(cursor));
1003
-
1004
- const q = query(this.technologiesRef, ...queryConstraints);
1005
- const snapshot = await getDocs(q);
1006
- if (snapshot.empty) break;
1007
-
1008
- for (const d of snapshot.docs) {
1009
- const technology = ({ id: d.id, ...d.data() } as unknown) as Technology;
1010
- // Fetch products for this technology
1011
- const productNames = await this.getProductNamesForTechnology(technology.id!);
1012
- rows.push(this.technologyToCsvRow(technology, productNames));
1013
- }
1014
-
1015
- cursor = snapshot.docs[snapshot.docs.length - 1];
1016
- if (snapshot.size < PAGE_SIZE) break;
1017
- }
1018
-
1019
- const csvBody = rows.join("\r\n");
1020
- return includeBom ? "\uFEFF" + csvBody : csvBody;
1021
- }
1022
-
1023
- /**
1024
- * Gets product names from the technology's product subcollection
1025
- */
1026
- private async getProductNamesForTechnology(technologyId: string): Promise<string[]> {
1027
- try {
1028
- const productsRef = collection(this.db, TECHNOLOGIES_COLLECTION, technologyId, PRODUCTS_COLLECTION);
1029
- const q = query(productsRef, where("isActive", "==", true));
1030
- const snapshot = await getDocs(q);
1031
- return snapshot.docs.map(doc => {
1032
- const product = doc.data() as Product;
1033
- return product.name || "";
1034
- }).filter(name => name); // Filter out empty names
1035
- } catch (error) {
1036
- console.error(`Error fetching products for technology ${technologyId}:`, error);
1037
- return [];
1038
- }
1039
- }
1040
-
1041
- private technologyToCsvRow(technology: Technology, productNames: string[] = []): string {
1042
- const values = [
1043
- technology.id ?? "",
1044
- technology.name ?? "",
1045
- technology.description ?? "",
1046
- technology.family ?? "",
1047
- technology.categoryId ?? "",
1048
- technology.subcategoryId ?? "",
1049
- technology.technicalDetails ?? "",
1050
- technology.requirements?.pre?.map(r => r.name).join(";") ?? "",
1051
- technology.requirements?.post?.map(r => r.name).join(";") ?? "",
1052
- technology.blockingConditions?.join(";") ?? "",
1053
- technology.contraindications?.map(c => c.name).join(";") ?? "",
1054
- technology.benefits?.map(b => b.name).join(";") ?? "",
1055
- technology.certificationRequirement?.minimumLevel ?? "",
1056
- technology.certificationRequirement?.requiredSpecialties?.join(";") ?? "",
1057
- technology.documentationTemplates?.map(t => t.templateId).join(";") ?? "",
1058
- productNames.join(";"),
1059
- String(technology.isActive ?? ""),
1060
- ];
1061
- return values.map((v) => this.formatCsvValue(v)).join(",");
1062
- }
1063
-
1064
- private formatCsvValue(value: any): string {
1065
- const str = value === null || value === undefined ? "" : String(value);
1066
- // Escape double quotes by doubling them and wrap in quotes
1067
- const escaped = str.replace(/"/g, '""');
1068
- return `"${escaped}"`;
1069
- }
1070
781
  }
@@ -6,10 +6,9 @@ import type { ContraindicationDynamic } from './admin-constants.types';
6
6
  *
7
7
  * @property id - Unique identifier of the product
8
8
  * @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)
11
- * @property assignedTechnologyIds - Array of technology IDs this product is assigned to
12
9
  * @property description - Detailed description of the product and its purpose
10
+ * @property brandId - ID of the brand that manufactures this product
11
+ * @property technologyId - ID of the technology this product is used with
13
12
  * @property technicalDetails - Technical details and specifications
14
13
  * @property warnings - List of warnings related to product use
15
14
  * @property dosage - Dosage information (if applicable)
@@ -25,11 +24,10 @@ export interface Product {
25
24
  name: string;
26
25
  brandId: string;
27
26
  brandName: string;
28
-
29
- // NEW: Technology assignment tracking
30
- assignedTechnologyIds?: string[];
31
-
32
- // Product details
27
+ technologyId: string;
28
+ technologyName: string;
29
+ categoryId: string;
30
+ subcategoryId: string;
33
31
  createdAt: Date;
34
32
  updatedAt: Date;
35
33
  isActive: boolean;
@@ -40,18 +38,6 @@ export interface Product {
40
38
  composition?: string;
41
39
  indications?: string[];
42
40
  contraindications?: ContraindicationDynamic[];
43
-
44
- // LEGACY FIELDS: Only present in technology subcollections (/technologies/{id}/products/)
45
- // These fields are synced by Cloud Functions for backward compatibility
46
- // NOT stored in top-level /products collection
47
- /** Present only in subcollections - synced from technology metadata */
48
- technologyId?: string;
49
- /** Present only in subcollections - synced from technology name */
50
- technologyName?: string;
51
- /** Present only in subcollections - synced from technology categoryId */
52
- categoryId?: string;
53
- /** Present only in subcollections - synced from technology subcategoryId */
54
- subcategoryId?: string;
55
41
  }
56
42
 
57
43
  /**
@@ -61,97 +47,9 @@ export const PRODUCTS_COLLECTION = 'products';
61
47
 
62
48
  /**
63
49
  * Interface for the ProductService class
64
- *
65
- * NOTE: This interface maintains backward compatibility while adding new top-level collection methods.
66
- * Old methods using technologyId are kept for existing code, new methods work with top-level collection.
67
50
  */
68
51
  export interface IProductService {
69
- // ==========================================
70
- // NEW METHODS: Top-level collection (preferred)
71
- // ==========================================
72
-
73
- /**
74
- * Creates a new product in the top-level collection
75
- * @param brandId - ID of the brand that manufactures this product
76
- * @param product - Product data
77
- * @param technologyIds - Optional array of technology IDs to assign this product to
78
- */
79
- createTopLevel(
80
- brandId: string,
81
- product: Omit<Product, 'id' | 'createdAt' | 'updatedAt' | 'brandId' | 'assignedTechnologyIds'>,
82
- technologyIds?: string[],
83
- ): Promise<Product>;
84
-
85
- /**
86
- * Gets all products from the top-level collection
87
- * @param options - Query options
88
- */
89
- getAllTopLevel(options: {
90
- rowsPerPage: number;
91
- lastVisible?: any;
92
- brandId?: string;
93
- }): Promise<{ products: Product[]; lastVisible: any }>;
94
-
95
- /**
96
- * Gets a product by ID from the top-level collection
97
- * @param productId - ID of the product
98
- */
99
- getByIdTopLevel(productId: string): Promise<Product | null>;
100
-
101
- /**
102
- * Updates a product in the top-level collection
103
- * @param productId - ID of the product to update
104
- * @param product - Updated product data
105
- */
106
- updateTopLevel(
107
- productId: string,
108
- product: Partial<Omit<Product, 'id' | 'createdAt' | 'brandId'>>,
109
- ): Promise<Product | null>;
110
-
111
- /**
112
- * Deletes a product from the top-level collection (soft delete)
113
- * @param productId - ID of the product to delete
114
- */
115
- deleteTopLevel(productId: string): Promise<void>;
116
-
117
- /**
118
- * Assigns a product to a technology
119
- * @param productId - ID of the product
120
- * @param technologyId - ID of the technology
121
- */
122
- assignToTechnology(productId: string, technologyId: string): Promise<void>;
123
-
124
- /**
125
- * Unassigns a product from a technology
126
- * @param productId - ID of the product
127
- * @param technologyId - ID of the technology
128
- */
129
- unassignFromTechnology(productId: string, technologyId: string): Promise<void>;
130
-
131
- /**
132
- * Gets products assigned to a specific technology
133
- * @param technologyId - ID of the technology
134
- */
135
- getAssignedProducts(technologyId: string): Promise<Product[]>;
136
-
137
- /**
138
- * Gets products NOT assigned to a specific technology
139
- * @param technologyId - ID of the technology
140
- */
141
- getUnassignedProducts(technologyId: string): Promise<Product[]>;
142
-
143
- /**
144
- * Gets all products for a brand
145
- * @param brandId - ID of the brand
146
- */
147
- getByBrand(brandId: string): Promise<Product[]>;
148
-
149
- // ==========================================
150
- // DEPRECATED METHODS: Kept for backward compatibility
151
- // ==========================================
152
-
153
52
  /**
154
- * @deprecated Use createTopLevel instead
155
53
  * Creates a new product
156
54
  * @param technologyId - ID of the technology this product is used with
157
55
  * @param brandId - ID of the brand that manufactures this product
@@ -164,7 +62,6 @@ export interface IProductService {
164
62
  ): Promise<Product>;
165
63
 
166
64
  /**
167
- * @deprecated Use getAllTopLevel instead
168
65
  * Gets a paginated list of all products, with optional filters.
169
66
  */
170
67
  getAll(options: {
@@ -176,7 +73,6 @@ export interface IProductService {
176
73
  }): Promise<{ products: Product[]; lastVisible: any }>;
177
74
 
178
75
  /**
179
- * @deprecated Use alternative counting methods
180
76
  * Gets the total count of active products, with optional filters.
181
77
  */
182
78
  getProductsCount(options: {
@@ -186,7 +82,6 @@ export interface IProductService {
186
82
  }): Promise<number>;
187
83
 
188
84
  /**
189
- * @deprecated Use alternative counting methods
190
85
  * Gets counts of active products grouped by category, subcategory, and technology.
191
86
  */
192
87
  getProductCounts(): Promise<{
@@ -196,21 +91,18 @@ export interface IProductService {
196
91
  }>;
197
92
 
198
93
  /**
199
- * @deprecated Use getAssignedProducts instead
200
94
  * Gets all products for a specific technology (non-paginated, for filters/dropdowns)
201
95
  * @param technologyId - ID of the technology
202
96
  */
203
97
  getAllByTechnology(technologyId: string): Promise<Product[]>;
204
98
 
205
99
  /**
206
- * @deprecated Use getByBrand instead
207
100
  * Gets all products for a brand
208
101
  * @param brandId - ID of the brand
209
102
  */
210
103
  getAllByBrand(brandId: string): Promise<Product[]>;
211
104
 
212
105
  /**
213
- * @deprecated Use updateTopLevel instead
214
106
  * Updates a product
215
107
  * @param technologyId - ID of the technology
216
108
  * @param productId - ID of the product to update
@@ -223,7 +115,6 @@ export interface IProductService {
223
115
  ): Promise<Product | null>;
224
116
 
225
117
  /**
226
- * @deprecated Use deleteTopLevel instead
227
118
  * Deletes a product (soft delete)
228
119
  * @param technologyId - ID of the technology
229
120
  * @param productId - ID of the product to delete
@@ -231,7 +122,6 @@ export interface IProductService {
231
122
  delete(technologyId: string, productId: string): Promise<void>;
232
123
 
233
124
  /**
234
- * @deprecated Use getByIdTopLevel instead
235
125
  * Gets a product by ID
236
126
  * @param technologyId - ID of the technology
237
127
  * @param productId - ID of the product