@blackcode_sa/metaestetics-api 1.12.42 → 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.
@@ -13,8 +13,6 @@ import {
13
13
  startAfter,
14
14
  getCountFromServer,
15
15
  QueryConstraint,
16
- arrayUnion,
17
- arrayRemove,
18
16
  } from 'firebase/firestore';
19
17
  import { Product, PRODUCTS_COLLECTION, IProductService } from '../types/product.types';
20
18
  import { BaseService } from '../../services/base.service';
@@ -22,15 +20,7 @@ import { TECHNOLOGIES_COLLECTION } from '../types/technology.types';
22
20
 
23
21
  export class ProductService extends BaseService implements IProductService {
24
22
  /**
25
- * Gets reference to top-level products collection (source of truth)
26
- * @returns Firestore collection reference
27
- */
28
- private getTopLevelProductsRef() {
29
- return collection(this.db, PRODUCTS_COLLECTION);
30
- }
31
-
32
- /**
33
- * Gets reference to products collection under a technology (backward compatibility)
23
+ * Gets reference to products collection under a technology
34
24
  * @param technologyId - ID of the technology
35
25
  * @returns Firestore collection reference
36
26
  */
@@ -47,11 +37,11 @@ export class ProductService extends BaseService implements IProductService {
47
37
  product: Omit<Product, 'id' | 'createdAt' | 'updatedAt' | 'brandId' | 'technologyId'>,
48
38
  ): Promise<Product> {
49
39
  const now = new Date();
50
- // Create product with legacy structure for subcollection compatibility
40
+ // categoryId and subcategoryId are now expected to be part of the product object
51
41
  const newProduct: Omit<Product, 'id'> = {
52
42
  ...product,
53
43
  brandId,
54
- technologyId, // Required for old subcollection structure
44
+ technologyId,
55
45
  createdAt: now,
56
46
  updatedAt: now,
57
47
  isActive: true,
@@ -135,35 +125,38 @@ export class ProductService extends BaseService implements IProductService {
135
125
 
136
126
  /**
137
127
  * Gets counts of active products grouped by category, subcategory, and technology.
138
- * Queries technology subcollections which have the legacy fields synced by Cloud Functions.
128
+ * This uses a single collectionGroup query for efficiency.
139
129
  */
140
130
  async getProductCounts(): Promise<{
141
131
  byCategory: Record<string, number>;
142
132
  bySubcategory: Record<string, number>;
143
133
  byTechnology: Record<string, number>;
144
134
  }> {
135
+ const q = query(collectionGroup(this.db, PRODUCTS_COLLECTION), where('isActive', '==', true));
136
+ const snapshot = await getDocs(q);
137
+
145
138
  const counts = {
146
139
  byCategory: {} as Record<string, number>,
147
140
  bySubcategory: {} as Record<string, number>,
148
141
  byTechnology: {} as Record<string, number>,
149
142
  };
150
143
 
151
- // Query technology subcollections (which have synced legacy fields)
152
- const q = query(collectionGroup(this.db, PRODUCTS_COLLECTION), where('isActive', '==', true));
153
- const snapshot = await getDocs(q);
144
+ if (snapshot.empty) {
145
+ return counts;
146
+ }
154
147
 
155
148
  snapshot.docs.forEach(doc => {
156
149
  const product = doc.data() as Product;
157
-
158
- // Use legacy fields from subcollections
159
- if (product.categoryId) {
160
- counts.byCategory[product.categoryId] = (counts.byCategory[product.categoryId] || 0) + 1;
150
+ const { categoryId, subcategoryId, technologyId } = product;
151
+
152
+ if (categoryId) {
153
+ counts.byCategory[categoryId] = (counts.byCategory[categoryId] || 0) + 1;
161
154
  }
162
- if (product.subcategoryId) {
163
- counts.bySubcategory[product.subcategoryId] = (counts.bySubcategory[product.subcategoryId] || 0) + 1;
155
+ if (subcategoryId) {
156
+ counts.bySubcategory[subcategoryId] = (counts.bySubcategory[subcategoryId] || 0) + 1;
164
157
  }
165
- if (product.technologyId) {
166
- counts.byTechnology[product.technologyId] = (counts.byTechnology[product.technologyId] || 0) + 1;
158
+ if (technologyId) {
159
+ counts.byTechnology[technologyId] = (counts.byTechnology[technologyId] || 0) + 1;
167
160
  }
168
161
  });
169
162
 
@@ -259,195 +252,4 @@ export class ProductService extends BaseService implements IProductService {
259
252
  ...docSnap.data(),
260
253
  } as Product;
261
254
  }
262
-
263
- // ==========================================
264
- // NEW METHODS: Top-level collection (preferred)
265
- // ==========================================
266
-
267
- /**
268
- * Creates a new product in the top-level collection
269
- */
270
- async createTopLevel(
271
- brandId: string,
272
- product: Omit<Product, 'id' | 'createdAt' | 'updatedAt' | 'brandId' | 'assignedTechnologyIds'>,
273
- technologyIds: string[] = [],
274
- ): Promise<Product> {
275
- const now = new Date();
276
- const newProduct: Omit<Product, 'id'> = {
277
- ...product,
278
- brandId,
279
- assignedTechnologyIds: technologyIds,
280
- createdAt: now,
281
- updatedAt: now,
282
- isActive: true,
283
- };
284
-
285
- const productRef = await addDoc(this.getTopLevelProductsRef(), newProduct);
286
- return { id: productRef.id, ...newProduct };
287
- }
288
-
289
- /**
290
- * Gets all products from the top-level collection
291
- */
292
- async getAllTopLevel(options: {
293
- rowsPerPage: number;
294
- lastVisible?: any;
295
- brandId?: string;
296
- }): Promise<{ products: Product[]; lastVisible: any }> {
297
- const { rowsPerPage, lastVisible, brandId } = options;
298
-
299
- const constraints: QueryConstraint[] = [where('isActive', '==', true), orderBy('name')];
300
-
301
- if (brandId) {
302
- constraints.push(where('brandId', '==', brandId));
303
- }
304
-
305
- if (lastVisible) {
306
- constraints.push(startAfter(lastVisible));
307
- }
308
- constraints.push(limit(rowsPerPage));
309
-
310
- const q = query(this.getTopLevelProductsRef(), ...constraints);
311
- const snapshot = await getDocs(q);
312
-
313
- const products = snapshot.docs.map(
314
- doc =>
315
- ({
316
- id: doc.id,
317
- ...doc.data(),
318
- } as Product),
319
- );
320
- const newLastVisible = snapshot.docs[snapshot.docs.length - 1];
321
-
322
- return { products, lastVisible: newLastVisible };
323
- }
324
-
325
- /**
326
- * Gets a product by ID from the top-level collection
327
- */
328
- async getByIdTopLevel(productId: string): Promise<Product | null> {
329
- const docRef = doc(this.getTopLevelProductsRef(), productId);
330
- const docSnap = await getDoc(docRef);
331
- if (!docSnap.exists()) return null;
332
- return {
333
- id: docSnap.id,
334
- ...docSnap.data(),
335
- } as Product;
336
- }
337
-
338
- /**
339
- * Updates a product in the top-level collection
340
- */
341
- async updateTopLevel(
342
- productId: string,
343
- product: Partial<Omit<Product, 'id' | 'createdAt' | 'brandId'>>,
344
- ): Promise<Product | null> {
345
- const updateData = {
346
- ...product,
347
- updatedAt: new Date(),
348
- };
349
-
350
- const docRef = doc(this.getTopLevelProductsRef(), productId);
351
- await updateDoc(docRef, updateData);
352
-
353
- return this.getByIdTopLevel(productId);
354
- }
355
-
356
- /**
357
- * Deletes a product from the top-level collection (soft delete)
358
- */
359
- async deleteTopLevel(productId: string): Promise<void> {
360
- await this.updateTopLevel(productId, {
361
- isActive: false,
362
- });
363
- }
364
-
365
- /**
366
- * Assigns a product to a technology
367
- */
368
- async assignToTechnology(productId: string, technologyId: string): Promise<void> {
369
- const docRef = doc(this.getTopLevelProductsRef(), productId);
370
- await updateDoc(docRef, {
371
- assignedTechnologyIds: arrayUnion(technologyId),
372
- updatedAt: new Date(),
373
- });
374
- // Cloud Function will handle syncing to subcollection
375
- }
376
-
377
- /**
378
- * Unassigns a product from a technology
379
- */
380
- async unassignFromTechnology(productId: string, technologyId: string): Promise<void> {
381
- const docRef = doc(this.getTopLevelProductsRef(), productId);
382
- await updateDoc(docRef, {
383
- assignedTechnologyIds: arrayRemove(technologyId),
384
- updatedAt: new Date(),
385
- });
386
- // Cloud Function will handle removing from subcollection
387
- }
388
-
389
- /**
390
- * Gets products assigned to a specific technology
391
- */
392
- async getAssignedProducts(technologyId: string): Promise<Product[]> {
393
- const q = query(
394
- this.getTopLevelProductsRef(),
395
- where('assignedTechnologyIds', 'array-contains', technologyId),
396
- where('isActive', '==', true),
397
- orderBy('name'),
398
- );
399
- const snapshot = await getDocs(q);
400
- return snapshot.docs.map(
401
- doc =>
402
- ({
403
- id: doc.id,
404
- ...doc.data(),
405
- } as Product),
406
- );
407
- }
408
-
409
- /**
410
- * Gets products NOT assigned to a specific technology
411
- */
412
- async getUnassignedProducts(technologyId: string): Promise<Product[]> {
413
- const q = query(
414
- this.getTopLevelProductsRef(),
415
- where('isActive', '==', true),
416
- orderBy('name'),
417
- );
418
- const snapshot = await getDocs(q);
419
-
420
- const allProducts = snapshot.docs.map(
421
- doc =>
422
- ({
423
- id: doc.id,
424
- ...doc.data(),
425
- } as Product),
426
- );
427
-
428
- // Filter out products already assigned to this technology
429
- return allProducts.filter(product =>
430
- !product.assignedTechnologyIds?.includes(technologyId)
431
- );
432
- }
433
-
434
- /**
435
- * Gets all products for a brand (from top-level collection)
436
- */
437
- async getByBrand(brandId: string): Promise<Product[]> {
438
- const q = query(
439
- this.getTopLevelProductsRef(),
440
- where('brandId', '==', brandId),
441
- where('isActive', '==', true),
442
- orderBy('name'),
443
- );
444
- const snapshot = await getDocs(q);
445
- return snapshot.docs.map(
446
- doc =>
447
- ({
448
- id: doc.id,
449
- ...doc.data(),
450
- } as Product),
451
- );
452
- }
453
255
  }
@@ -15,7 +15,6 @@ import {
15
15
  arrayUnion,
16
16
  arrayRemove,
17
17
  Firestore,
18
- writeBatch,
19
18
  } from 'firebase/firestore';
20
19
  import { Technology, TECHNOLOGIES_COLLECTION, ITechnologyService } from '../types/technology.types';
21
20
  import { Requirement, RequirementType } from '../types/requirement.types';
@@ -30,7 +29,6 @@ import {
30
29
  import { BaseService } from '../../services/base.service';
31
30
  import { ProcedureFamily } from '../types/static/procedure-family.types';
32
31
  import { Practitioner, PractitionerCertification } from '../../types/practitioner';
33
- import { Product, PRODUCTS_COLLECTION } from '../types/product.types';
34
32
 
35
33
  /**
36
34
  * Default vrednosti za sertifikaciju
@@ -242,25 +240,7 @@ export class TechnologyService extends BaseService implements ITechnologyService
242
240
  updateData.updatedAt = new Date();
243
241
 
244
242
  const docRef = doc(this.technologiesRef, id);
245
-
246
- // Get the technology before update to check what changed
247
- const beforeTech = await this.getById(id);
248
-
249
243
  await updateDoc(docRef, updateData);
250
-
251
- // If categoryId, subcategoryId, or name changed, update all products in subcollection
252
- const categoryChanged = beforeTech && updateData.categoryId && beforeTech.categoryId !== updateData.categoryId;
253
- const subcategoryChanged = beforeTech && updateData.subcategoryId && beforeTech.subcategoryId !== updateData.subcategoryId;
254
- const nameChanged = beforeTech && updateData.name && beforeTech.name !== updateData.name;
255
-
256
- if (categoryChanged || subcategoryChanged || nameChanged) {
257
- await this.updateProductsInSubcollection(id, {
258
- categoryId: updateData.categoryId,
259
- subcategoryId: updateData.subcategoryId,
260
- technologyName: updateData.name,
261
- });
262
- }
263
-
264
244
  return this.getById(id);
265
245
  }
266
246
 
@@ -798,153 +778,4 @@ export class TechnologyService extends BaseService implements ITechnologyService
798
778
  } as Technology),
799
779
  );
800
780
  }
801
-
802
- // ==========================================
803
- // NEW METHODS: Product assignment management
804
- // ==========================================
805
-
806
- /**
807
- * Assigns multiple products to a technology
808
- * Updates each product's assignedTechnologyIds array
809
- */
810
- async assignProducts(technologyId: string, productIds: string[]): Promise<void> {
811
- const batch = writeBatch(this.db);
812
-
813
- for (const productId of productIds) {
814
- const productRef = doc(this.db, PRODUCTS_COLLECTION, productId);
815
- batch.update(productRef, {
816
- assignedTechnologyIds: arrayUnion(technologyId),
817
- updatedAt: new Date(),
818
- });
819
- }
820
-
821
- await batch.commit();
822
- // Cloud Function will handle syncing to subcollections
823
- }
824
-
825
- /**
826
- * Unassigns multiple products from a technology
827
- * Updates each product's assignedTechnologyIds array
828
- */
829
- async unassignProducts(technologyId: string, productIds: string[]): Promise<void> {
830
- const batch = writeBatch(this.db);
831
-
832
- for (const productId of productIds) {
833
- const productRef = doc(this.db, PRODUCTS_COLLECTION, productId);
834
- batch.update(productRef, {
835
- assignedTechnologyIds: arrayRemove(technologyId),
836
- updatedAt: new Date(),
837
- });
838
- }
839
-
840
- await batch.commit();
841
- // Cloud Function will handle removing from subcollections
842
- }
843
-
844
- /**
845
- * Gets products assigned to a specific technology
846
- * Reads from top-level collection for immediate consistency (Cloud Functions may lag)
847
- */
848
- async getAssignedProducts(technologyId: string): Promise<Product[]> {
849
- const q = query(
850
- collection(this.db, PRODUCTS_COLLECTION),
851
- where('assignedTechnologyIds', 'array-contains', technologyId),
852
- where('isActive', '==', true),
853
- orderBy('name'),
854
- );
855
- const snapshot = await getDocs(q);
856
-
857
- return snapshot.docs.map(
858
- doc =>
859
- ({
860
- id: doc.id,
861
- ...doc.data(),
862
- } as Product),
863
- );
864
- }
865
-
866
- /**
867
- * Gets products NOT assigned to a specific technology
868
- */
869
- async getUnassignedProducts(technologyId: string): Promise<Product[]> {
870
- const q = query(
871
- collection(this.db, PRODUCTS_COLLECTION),
872
- where('isActive', '==', true),
873
- orderBy('name'),
874
- );
875
- const snapshot = await getDocs(q);
876
-
877
- const allProducts = snapshot.docs.map(
878
- doc =>
879
- ({
880
- id: doc.id,
881
- ...doc.data(),
882
- } as Product),
883
- );
884
-
885
- // Filter out products already assigned to this technology
886
- return allProducts.filter(product =>
887
- !product.assignedTechnologyIds?.includes(technologyId)
888
- );
889
- }
890
-
891
- /**
892
- * Gets product assignment statistics for a technology
893
- */
894
- async getProductStats(technologyId: string): Promise<{
895
- totalAssigned: number;
896
- byBrand: Record<string, number>;
897
- }> {
898
- const products = await this.getAssignedProducts(technologyId);
899
-
900
- const byBrand: Record<string, number> = {};
901
- products.forEach(product => {
902
- byBrand[product.brandName] = (byBrand[product.brandName] || 0) + 1;
903
- });
904
-
905
- return {
906
- totalAssigned: products.length,
907
- byBrand,
908
- };
909
- }
910
-
911
- /**
912
- * Updates products in technology subcollection when technology metadata changes
913
- * @param technologyId - ID of the technology
914
- * @param updates - Fields to update (categoryId, subcategoryId, technologyName)
915
- */
916
- private async updateProductsInSubcollection(
917
- technologyId: string,
918
- updates: { categoryId?: string; subcategoryId?: string; technologyName?: string }
919
- ): Promise<void> {
920
- const productsRef = collection(this.db, TECHNOLOGIES_COLLECTION, technologyId, PRODUCTS_COLLECTION);
921
- const productsSnapshot = await getDocs(productsRef);
922
-
923
- if (productsSnapshot.empty) {
924
- return;
925
- }
926
-
927
- const batch = writeBatch(this.db);
928
-
929
- for (const productDoc of productsSnapshot.docs) {
930
- const productRef = productDoc.ref;
931
- const updateFields: any = {};
932
-
933
- if (updates.categoryId !== undefined) {
934
- updateFields.categoryId = updates.categoryId;
935
- }
936
- if (updates.subcategoryId !== undefined) {
937
- updateFields.subcategoryId = updates.subcategoryId;
938
- }
939
- if (updates.technologyName !== undefined) {
940
- updateFields.technologyName = updates.technologyName;
941
- }
942
-
943
- if (Object.keys(updateFields).length > 0) {
944
- batch.update(productRef, updateFields);
945
- }
946
- }
947
-
948
- await batch.commit();
949
- }
950
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