@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.
package/dist/index.js CHANGED
@@ -1546,11 +1546,11 @@ function calculateItemSubtotal(item) {
1546
1546
  if (item.type === "note") {
1547
1547
  return 0;
1548
1548
  }
1549
+ const quantity = item.quantity || 0;
1549
1550
  if (item.priceOverrideAmount !== void 0 && item.priceOverrideAmount !== null) {
1550
- return item.priceOverrideAmount;
1551
+ return item.priceOverrideAmount * quantity;
1551
1552
  }
1552
1553
  const price = item.price || 0;
1553
- const quantity = item.quantity || 0;
1554
1554
  return price * quantity;
1555
1555
  }
1556
1556
  function calculateFinalBilling(zonesData, taxRate = 0.2) {
@@ -1666,7 +1666,18 @@ async function updateZoneItemUtil(db, appointmentId, zoneId, itemIndex, updates)
1666
1666
  ...updates,
1667
1667
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1668
1668
  };
1669
+ console.log(`[updateZoneItemUtil] BEFORE recalculation:`, {
1670
+ itemIndex,
1671
+ quantity: items[itemIndex].quantity,
1672
+ priceOverrideAmount: items[itemIndex].priceOverrideAmount,
1673
+ price: items[itemIndex].price,
1674
+ oldSubtotal: items[itemIndex].subtotal
1675
+ });
1669
1676
  items[itemIndex].subtotal = calculateItemSubtotal(items[itemIndex]);
1677
+ console.log(`[updateZoneItemUtil] AFTER recalculation:`, {
1678
+ itemIndex,
1679
+ newSubtotal: items[itemIndex].subtotal
1680
+ });
1670
1681
  const finalbilling = calculateFinalBilling(metadata.zonesData);
1671
1682
  const appointmentRef = (0, import_firestore5.doc)(db, APPOINTMENTS_COLLECTION, appointmentId);
1672
1683
  await (0, import_firestore4.updateDoc)(appointmentRef, {
@@ -18647,11 +18658,6 @@ var SubcategoryService = class extends BaseService {
18647
18658
 
18648
18659
  // src/backoffice/services/technology.service.ts
18649
18660
  var import_firestore61 = require("firebase/firestore");
18650
-
18651
- // src/backoffice/types/product.types.ts
18652
- var PRODUCTS_COLLECTION = "products";
18653
-
18654
- // src/backoffice/services/technology.service.ts
18655
18661
  var DEFAULT_CERTIFICATION_REQUIREMENT = {
18656
18662
  minimumLevel: "aesthetician" /* AESTHETICIAN */,
18657
18663
  requiredSpecialties: []
@@ -18813,18 +18819,7 @@ var TechnologyService = class extends BaseService {
18813
18819
  });
18814
18820
  updateData.updatedAt = /* @__PURE__ */ new Date();
18815
18821
  const docRef = (0, import_firestore61.doc)(this.technologiesRef, id);
18816
- const beforeTech = await this.getById(id);
18817
18822
  await (0, import_firestore61.updateDoc)(docRef, updateData);
18818
- const categoryChanged = beforeTech && updateData.categoryId && beforeTech.categoryId !== updateData.categoryId;
18819
- const subcategoryChanged = beforeTech && updateData.subcategoryId && beforeTech.subcategoryId !== updateData.subcategoryId;
18820
- const nameChanged = beforeTech && updateData.name && beforeTech.name !== updateData.name;
18821
- if (categoryChanged || subcategoryChanged || nameChanged) {
18822
- await this.updateProductsInSubcollection(id, {
18823
- categoryId: updateData.categoryId,
18824
- subcategoryId: updateData.subcategoryId,
18825
- technologyName: updateData.name
18826
- });
18827
- }
18828
18823
  return this.getById(id);
18829
18824
  }
18830
18825
  /**
@@ -19260,139 +19255,18 @@ var TechnologyService = class extends BaseService {
19260
19255
  })
19261
19256
  );
19262
19257
  }
19263
- // ==========================================
19264
- // NEW METHODS: Product assignment management
19265
- // ==========================================
19266
- /**
19267
- * Assigns multiple products to a technology
19268
- * Updates each product's assignedTechnologyIds array
19269
- */
19270
- async assignProducts(technologyId, productIds) {
19271
- const batch = (0, import_firestore61.writeBatch)(this.db);
19272
- for (const productId of productIds) {
19273
- const productRef = (0, import_firestore61.doc)(this.db, PRODUCTS_COLLECTION, productId);
19274
- batch.update(productRef, {
19275
- assignedTechnologyIds: (0, import_firestore61.arrayUnion)(technologyId),
19276
- updatedAt: /* @__PURE__ */ new Date()
19277
- });
19278
- }
19279
- await batch.commit();
19280
- }
19281
- /**
19282
- * Unassigns multiple products from a technology
19283
- * Updates each product's assignedTechnologyIds array
19284
- */
19285
- async unassignProducts(technologyId, productIds) {
19286
- const batch = (0, import_firestore61.writeBatch)(this.db);
19287
- for (const productId of productIds) {
19288
- const productRef = (0, import_firestore61.doc)(this.db, PRODUCTS_COLLECTION, productId);
19289
- batch.update(productRef, {
19290
- assignedTechnologyIds: (0, import_firestore61.arrayRemove)(technologyId),
19291
- updatedAt: /* @__PURE__ */ new Date()
19292
- });
19293
- }
19294
- await batch.commit();
19295
- }
19296
- /**
19297
- * Gets products assigned to a specific technology
19298
- * Reads from top-level collection for immediate consistency (Cloud Functions may lag)
19299
- */
19300
- async getAssignedProducts(technologyId) {
19301
- const q = (0, import_firestore61.query)(
19302
- (0, import_firestore61.collection)(this.db, PRODUCTS_COLLECTION),
19303
- (0, import_firestore61.where)("assignedTechnologyIds", "array-contains", technologyId),
19304
- (0, import_firestore61.where)("isActive", "==", true),
19305
- (0, import_firestore61.orderBy)("name")
19306
- );
19307
- const snapshot = await (0, import_firestore61.getDocs)(q);
19308
- return snapshot.docs.map(
19309
- (doc44) => ({
19310
- id: doc44.id,
19311
- ...doc44.data()
19312
- })
19313
- );
19314
- }
19315
- /**
19316
- * Gets products NOT assigned to a specific technology
19317
- */
19318
- async getUnassignedProducts(technologyId) {
19319
- const q = (0, import_firestore61.query)(
19320
- (0, import_firestore61.collection)(this.db, PRODUCTS_COLLECTION),
19321
- (0, import_firestore61.where)("isActive", "==", true),
19322
- (0, import_firestore61.orderBy)("name")
19323
- );
19324
- const snapshot = await (0, import_firestore61.getDocs)(q);
19325
- const allProducts = snapshot.docs.map(
19326
- (doc44) => ({
19327
- id: doc44.id,
19328
- ...doc44.data()
19329
- })
19330
- );
19331
- return allProducts.filter(
19332
- (product) => {
19333
- var _a;
19334
- return !((_a = product.assignedTechnologyIds) == null ? void 0 : _a.includes(technologyId));
19335
- }
19336
- );
19337
- }
19338
- /**
19339
- * Gets product assignment statistics for a technology
19340
- */
19341
- async getProductStats(technologyId) {
19342
- const products = await this.getAssignedProducts(technologyId);
19343
- const byBrand = {};
19344
- products.forEach((product) => {
19345
- byBrand[product.brandName] = (byBrand[product.brandName] || 0) + 1;
19346
- });
19347
- return {
19348
- totalAssigned: products.length,
19349
- byBrand
19350
- };
19351
- }
19352
- /**
19353
- * Updates products in technology subcollection when technology metadata changes
19354
- * @param technologyId - ID of the technology
19355
- * @param updates - Fields to update (categoryId, subcategoryId, technologyName)
19356
- */
19357
- async updateProductsInSubcollection(technologyId, updates) {
19358
- const productsRef = (0, import_firestore61.collection)(this.db, TECHNOLOGIES_COLLECTION, technologyId, PRODUCTS_COLLECTION);
19359
- const productsSnapshot = await (0, import_firestore61.getDocs)(productsRef);
19360
- if (productsSnapshot.empty) {
19361
- return;
19362
- }
19363
- const batch = (0, import_firestore61.writeBatch)(this.db);
19364
- for (const productDoc of productsSnapshot.docs) {
19365
- const productRef = productDoc.ref;
19366
- const updateFields = {};
19367
- if (updates.categoryId !== void 0) {
19368
- updateFields.categoryId = updates.categoryId;
19369
- }
19370
- if (updates.subcategoryId !== void 0) {
19371
- updateFields.subcategoryId = updates.subcategoryId;
19372
- }
19373
- if (updates.technologyName !== void 0) {
19374
- updateFields.technologyName = updates.technologyName;
19375
- }
19376
- if (Object.keys(updateFields).length > 0) {
19377
- batch.update(productRef, updateFields);
19378
- }
19379
- }
19380
- await batch.commit();
19381
- }
19382
19258
  };
19383
19259
 
19384
19260
  // src/backoffice/services/product.service.ts
19385
19261
  var import_firestore62 = require("firebase/firestore");
19262
+
19263
+ // src/backoffice/types/product.types.ts
19264
+ var PRODUCTS_COLLECTION = "products";
19265
+
19266
+ // src/backoffice/services/product.service.ts
19386
19267
  var ProductService = class extends BaseService {
19387
19268
  /**
19388
- * Gets reference to top-level products collection (source of truth)
19389
- * @returns Firestore collection reference
19390
- */
19391
- getTopLevelProductsRef() {
19392
- return (0, import_firestore62.collection)(this.db, PRODUCTS_COLLECTION);
19393
- }
19394
- /**
19395
- * Gets reference to products collection under a technology (backward compatibility)
19269
+ * Gets reference to products collection under a technology
19396
19270
  * @param technologyId - ID of the technology
19397
19271
  * @returns Firestore collection reference
19398
19272
  */
@@ -19408,7 +19282,6 @@ var ProductService = class extends BaseService {
19408
19282
  ...product,
19409
19283
  brandId,
19410
19284
  technologyId,
19411
- // Required for old subcollection structure
19412
19285
  createdAt: now,
19413
19286
  updatedAt: now,
19414
19287
  isActive: true
@@ -19468,26 +19341,30 @@ var ProductService = class extends BaseService {
19468
19341
  }
19469
19342
  /**
19470
19343
  * Gets counts of active products grouped by category, subcategory, and technology.
19471
- * Queries technology subcollections which have the legacy fields synced by Cloud Functions.
19344
+ * This uses a single collectionGroup query for efficiency.
19472
19345
  */
19473
19346
  async getProductCounts() {
19347
+ const q = (0, import_firestore62.query)((0, import_firestore62.collectionGroup)(this.db, PRODUCTS_COLLECTION), (0, import_firestore62.where)("isActive", "==", true));
19348
+ const snapshot = await (0, import_firestore62.getDocs)(q);
19474
19349
  const counts = {
19475
19350
  byCategory: {},
19476
19351
  bySubcategory: {},
19477
19352
  byTechnology: {}
19478
19353
  };
19479
- const q = (0, import_firestore62.query)((0, import_firestore62.collectionGroup)(this.db, PRODUCTS_COLLECTION), (0, import_firestore62.where)("isActive", "==", true));
19480
- const snapshot = await (0, import_firestore62.getDocs)(q);
19354
+ if (snapshot.empty) {
19355
+ return counts;
19356
+ }
19481
19357
  snapshot.docs.forEach((doc44) => {
19482
19358
  const product = doc44.data();
19483
- if (product.categoryId) {
19484
- counts.byCategory[product.categoryId] = (counts.byCategory[product.categoryId] || 0) + 1;
19359
+ const { categoryId, subcategoryId, technologyId } = product;
19360
+ if (categoryId) {
19361
+ counts.byCategory[categoryId] = (counts.byCategory[categoryId] || 0) + 1;
19485
19362
  }
19486
- if (product.subcategoryId) {
19487
- counts.bySubcategory[product.subcategoryId] = (counts.bySubcategory[product.subcategoryId] || 0) + 1;
19363
+ if (subcategoryId) {
19364
+ counts.bySubcategory[subcategoryId] = (counts.bySubcategory[subcategoryId] || 0) + 1;
19488
19365
  }
19489
- if (product.technologyId) {
19490
- counts.byTechnology[product.technologyId] = (counts.byTechnology[product.technologyId] || 0) + 1;
19366
+ if (technologyId) {
19367
+ counts.byTechnology[technologyId] = (counts.byTechnology[technologyId] || 0) + 1;
19491
19368
  }
19492
19369
  });
19493
19370
  return counts;
@@ -19566,160 +19443,6 @@ var ProductService = class extends BaseService {
19566
19443
  ...docSnap.data()
19567
19444
  };
19568
19445
  }
19569
- // ==========================================
19570
- // NEW METHODS: Top-level collection (preferred)
19571
- // ==========================================
19572
- /**
19573
- * Creates a new product in the top-level collection
19574
- */
19575
- async createTopLevel(brandId, product, technologyIds = []) {
19576
- const now = /* @__PURE__ */ new Date();
19577
- const newProduct = {
19578
- ...product,
19579
- brandId,
19580
- assignedTechnologyIds: technologyIds,
19581
- createdAt: now,
19582
- updatedAt: now,
19583
- isActive: true
19584
- };
19585
- const productRef = await (0, import_firestore62.addDoc)(this.getTopLevelProductsRef(), newProduct);
19586
- return { id: productRef.id, ...newProduct };
19587
- }
19588
- /**
19589
- * Gets all products from the top-level collection
19590
- */
19591
- async getAllTopLevel(options) {
19592
- const { rowsPerPage, lastVisible, brandId } = options;
19593
- const constraints = [(0, import_firestore62.where)("isActive", "==", true), (0, import_firestore62.orderBy)("name")];
19594
- if (brandId) {
19595
- constraints.push((0, import_firestore62.where)("brandId", "==", brandId));
19596
- }
19597
- if (lastVisible) {
19598
- constraints.push((0, import_firestore62.startAfter)(lastVisible));
19599
- }
19600
- constraints.push((0, import_firestore62.limit)(rowsPerPage));
19601
- const q = (0, import_firestore62.query)(this.getTopLevelProductsRef(), ...constraints);
19602
- const snapshot = await (0, import_firestore62.getDocs)(q);
19603
- const products = snapshot.docs.map(
19604
- (doc44) => ({
19605
- id: doc44.id,
19606
- ...doc44.data()
19607
- })
19608
- );
19609
- const newLastVisible = snapshot.docs[snapshot.docs.length - 1];
19610
- return { products, lastVisible: newLastVisible };
19611
- }
19612
- /**
19613
- * Gets a product by ID from the top-level collection
19614
- */
19615
- async getByIdTopLevel(productId) {
19616
- const docRef = (0, import_firestore62.doc)(this.getTopLevelProductsRef(), productId);
19617
- const docSnap = await (0, import_firestore62.getDoc)(docRef);
19618
- if (!docSnap.exists()) return null;
19619
- return {
19620
- id: docSnap.id,
19621
- ...docSnap.data()
19622
- };
19623
- }
19624
- /**
19625
- * Updates a product in the top-level collection
19626
- */
19627
- async updateTopLevel(productId, product) {
19628
- const updateData = {
19629
- ...product,
19630
- updatedAt: /* @__PURE__ */ new Date()
19631
- };
19632
- const docRef = (0, import_firestore62.doc)(this.getTopLevelProductsRef(), productId);
19633
- await (0, import_firestore62.updateDoc)(docRef, updateData);
19634
- return this.getByIdTopLevel(productId);
19635
- }
19636
- /**
19637
- * Deletes a product from the top-level collection (soft delete)
19638
- */
19639
- async deleteTopLevel(productId) {
19640
- await this.updateTopLevel(productId, {
19641
- isActive: false
19642
- });
19643
- }
19644
- /**
19645
- * Assigns a product to a technology
19646
- */
19647
- async assignToTechnology(productId, technologyId) {
19648
- const docRef = (0, import_firestore62.doc)(this.getTopLevelProductsRef(), productId);
19649
- await (0, import_firestore62.updateDoc)(docRef, {
19650
- assignedTechnologyIds: (0, import_firestore62.arrayUnion)(technologyId),
19651
- updatedAt: /* @__PURE__ */ new Date()
19652
- });
19653
- }
19654
- /**
19655
- * Unassigns a product from a technology
19656
- */
19657
- async unassignFromTechnology(productId, technologyId) {
19658
- const docRef = (0, import_firestore62.doc)(this.getTopLevelProductsRef(), productId);
19659
- await (0, import_firestore62.updateDoc)(docRef, {
19660
- assignedTechnologyIds: (0, import_firestore62.arrayRemove)(technologyId),
19661
- updatedAt: /* @__PURE__ */ new Date()
19662
- });
19663
- }
19664
- /**
19665
- * Gets products assigned to a specific technology
19666
- */
19667
- async getAssignedProducts(technologyId) {
19668
- const q = (0, import_firestore62.query)(
19669
- this.getTopLevelProductsRef(),
19670
- (0, import_firestore62.where)("assignedTechnologyIds", "array-contains", technologyId),
19671
- (0, import_firestore62.where)("isActive", "==", true),
19672
- (0, import_firestore62.orderBy)("name")
19673
- );
19674
- const snapshot = await (0, import_firestore62.getDocs)(q);
19675
- return snapshot.docs.map(
19676
- (doc44) => ({
19677
- id: doc44.id,
19678
- ...doc44.data()
19679
- })
19680
- );
19681
- }
19682
- /**
19683
- * Gets products NOT assigned to a specific technology
19684
- */
19685
- async getUnassignedProducts(technologyId) {
19686
- const q = (0, import_firestore62.query)(
19687
- this.getTopLevelProductsRef(),
19688
- (0, import_firestore62.where)("isActive", "==", true),
19689
- (0, import_firestore62.orderBy)("name")
19690
- );
19691
- const snapshot = await (0, import_firestore62.getDocs)(q);
19692
- const allProducts = snapshot.docs.map(
19693
- (doc44) => ({
19694
- id: doc44.id,
19695
- ...doc44.data()
19696
- })
19697
- );
19698
- return allProducts.filter(
19699
- (product) => {
19700
- var _a;
19701
- return !((_a = product.assignedTechnologyIds) == null ? void 0 : _a.includes(technologyId));
19702
- }
19703
- );
19704
- }
19705
- /**
19706
- * Gets all products for a brand (from top-level collection)
19707
- */
19708
- async getByBrand(brandId) {
19709
- const q = (0, import_firestore62.query)(
19710
- this.getTopLevelProductsRef(),
19711
- (0, import_firestore62.where)("brandId", "==", brandId),
19712
- (0, import_firestore62.where)("isActive", "==", true),
19713
- (0, import_firestore62.orderBy)("name")
19714
- );
19715
- const snapshot = await (0, import_firestore62.getDocs)(q);
19716
- return snapshot.docs.map(
19717
- (doc44) => ({
19718
- id: doc44.id,
19719
- ...doc44.data()
19720
- })
19721
- );
19722
- }
19723
19446
  };
19724
19447
 
19725
19448
  // src/backoffice/services/constants.service.ts