@infuro/cms-core 1.0.53 → 1.0.55

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.
@@ -1914,6 +1914,32 @@ async function ensureUniqueProductSlug(repo, baseSlug, vendorId, excludeId) {
1914
1914
  }
1915
1915
  }
1916
1916
  chunkUSNT2KNT_cjs.__name(ensureUniqueProductSlug, "ensureUniqueProductSlug");
1917
+ function isSlugUniqueViolation(err) {
1918
+ const msg = err instanceof Error ? err.message : String(err);
1919
+ return /duplicate key|unique constraint/i.test(msg) && /slug/i.test(msg);
1920
+ }
1921
+ chunkUSNT2KNT_cjs.__name(isSlugUniqueViolation, "isSlugUniqueViolation");
1922
+ async function assertUniqueEventSlug(repo, slugRaw, vendorId, excludeId) {
1923
+ const slug = typeof slugRaw === "string" ? slugRaw.trim() : "";
1924
+ if (!slug) return "Slug is required";
1925
+ await chunkOY2YTBMP_cjs.retireSoftDeletedUniqueValue(repo, "slug", slug);
1926
+ const where = excludeId != null ? {
1927
+ slug,
1928
+ vendorId,
1929
+ deleted: false,
1930
+ id: typeorm.Not(excludeId)
1931
+ } : {
1932
+ slug,
1933
+ vendorId,
1934
+ deleted: false
1935
+ };
1936
+ const dup = await repo.findOne({
1937
+ where
1938
+ });
1939
+ if (dup) return "An event with this slug already exists";
1940
+ return null;
1941
+ }
1942
+ chunkUSNT2KNT_cjs.__name(assertUniqueEventSlug, "assertUniqueEventSlug");
1917
1943
  async function normalizeComboNameAndSlug(repo, body, vendorId, existing, excludeId) {
1918
1944
  const incomingName = typeof body.name === "string" ? body.name.trim() : "";
1919
1945
  const incomingSlugRaw = typeof body.slug === "string" ? body.slug.trim() : "";
@@ -4784,6 +4810,17 @@ function createCrudHandler(dataSource, entityMap, options) {
4784
4810
  status: 400
4785
4811
  });
4786
4812
  }
4813
+ if (resource === "events") {
4814
+ const vendorIdForSlug = scopeCreate.type === "vendor" ? scopeCreate.vendorId : Number(persistBody.vendorId);
4815
+ if (Number.isFinite(vendorIdForSlug) && vendorIdForSlug > 0) {
4816
+ const eventSlugErr = await assertUniqueEventSlug(repo, persistBody.slug, vendorIdForSlug);
4817
+ if (eventSlugErr) return json({
4818
+ error: eventSlugErr
4819
+ }, {
4820
+ status: 400
4821
+ });
4822
+ }
4823
+ }
4787
4824
  sanitizeBodyForEntity(repo, persistBody);
4788
4825
  let created;
4789
4826
  try {
@@ -5063,6 +5100,13 @@ function createCrudHandler(dataSource, entityMap, options) {
5063
5100
  }
5064
5101
  } catch (err) {
5065
5102
  const message = err instanceof Error ? err.message : String(err);
5103
+ if (resource === "events" && isSlugUniqueViolation(err)) {
5104
+ return json({
5105
+ error: "An event with this slug already exists"
5106
+ }, {
5107
+ status: 400
5108
+ });
5109
+ }
5066
5110
  logCrudServerError("POST create save failed", {
5067
5111
  resource,
5068
5112
  message,
@@ -6339,6 +6383,17 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
6339
6383
  });
6340
6384
  }
6341
6385
  }
6386
+ if ("slug" in updatePayload) {
6387
+ const vendorIdForSlug = scopePut.type === "vendor" ? scopePut.vendorId : Number(currentEvent.vendorId);
6388
+ if (Number.isFinite(vendorIdForSlug) && vendorIdForSlug > 0) {
6389
+ const eventSlugErr = await assertUniqueEventSlug(repo, updatePayload.slug, vendorIdForSlug, numericId);
6390
+ if (eventSlugErr) return json({
6391
+ error: eventSlugErr
6392
+ }, {
6393
+ status: 400
6394
+ });
6395
+ }
6396
+ }
6342
6397
  }
6343
6398
  if (resource === "product_categories" && scopePut.type === "all") {
6344
6399
  const existingCatalogCat = await repo.findOne({
@@ -6502,7 +6557,18 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
6502
6557
  }
6503
6558
  sanitizeBodyForEntity(repo, updatePayload);
6504
6559
  await retireSoftDeletedUniquesFromBody(repo, updatePayload);
6505
- await repo.update(numericId, updatePayload);
6560
+ try {
6561
+ await repo.update(numericId, updatePayload);
6562
+ } catch (err) {
6563
+ if (resource === "events" && isSlugUniqueViolation(err)) {
6564
+ return json({
6565
+ error: "An event with this slug already exists"
6566
+ }, {
6567
+ status: 400
6568
+ });
6569
+ }
6570
+ throw err;
6571
+ }
6506
6572
  }
6507
6573
  if (resource === "orders" && rawBody && entityMap["order_addresses"]) {
6508
6574
  const addressRawScalar = String(rawBody["contact.address"] ?? "").trim();
@@ -8695,11 +8761,21 @@ function createUploadHandler(config) {
8695
8761
  const storageService = raw instanceof Promise ? await raw : raw;
8696
8762
  if (storageService) {
8697
8763
  const fileUrl = await storageService.upload(buffer, `uploads/${relativeUnderUploads}`, contentType);
8764
+ console.info("[upload] stored via storage plugin", {
8765
+ key: `uploads/${relativeUnderUploads}`,
8766
+ contentType,
8767
+ bytes: buffer.length,
8768
+ fileUrl
8769
+ });
8698
8770
  return json({
8699
8771
  filePath: fileUrl,
8700
8772
  parentId
8701
8773
  });
8702
8774
  }
8775
+ console.warn("[upload] no storage plugin \u2014 writing local disk (broken on most deploys)", {
8776
+ localUploadDir,
8777
+ key: relativeUnderUploads
8778
+ });
8703
8779
  const fs2 = await import('fs/promises');
8704
8780
  const path2 = await import('path');
8705
8781
  const dir = path2.join(process.cwd(), localUploadDir);
@@ -8715,11 +8791,13 @@ function createUploadHandler(config) {
8715
8791
  });
8716
8792
  } catch (err) {
8717
8793
  const message = err instanceof Error ? err.message : String(err);
8794
+ const awsMeta = err && typeof err === "object" && "$metadata" in err ? err.$metadata : void 0;
8718
8795
  console.error("[upload] File upload failed", {
8719
8796
  error: message,
8720
8797
  stack: err instanceof Error ? err.stack : void 0,
8721
8798
  name: err instanceof Error ? err.name : void 0,
8722
- metadata: err && typeof err === "object" && "$metadata" in err ? err.$metadata : void 0
8799
+ code: err && typeof err === "object" && ("Code" in err || "code" in err) ? err.Code ?? err.code : void 0,
8800
+ metadata: awsMeta
8723
8801
  });
8724
8802
  if (/Failed to parse body as FormData/i.test(message)) {
8725
8803
  return json({
@@ -8729,7 +8807,8 @@ function createUploadHandler(config) {
8729
8807
  });
8730
8808
  }
8731
8809
  return json({
8732
- error: "File upload failed"
8810
+ error: "File upload failed",
8811
+ details: message
8733
8812
  }, {
8734
8813
  status: 500
8735
8814
  });
@@ -30870,9 +30949,51 @@ function createStorefrontApiHandler(config) {
30870
30949
  "items.product.taxes",
30871
30950
  "items.product.taxes.tax"
30872
30951
  ];
30873
- function resolveSingleVendorIdFromCart(cart) {
30952
+ function comboIdFromCartItem(it) {
30953
+ const meta = it.metadata && typeof it.metadata === "object" && !Array.isArray(it.metadata) ? it.metadata : {};
30954
+ const fromMeta = Number(meta.comboId ?? meta.combo_id);
30955
+ if (Number.isInteger(fromMeta) && fromMeta > 0) return fromMeta;
30956
+ if (meta.isCombo === true || meta.type === "combo" || meta.lineType === "combo") {
30957
+ const pid = Number(it.productId);
30958
+ if (Number.isInteger(pid) && pid > 0) return pid;
30959
+ }
30960
+ return null;
30961
+ }
30962
+ chunkUSNT2KNT_cjs.__name(comboIdFromCartItem, "comboIdFromCartItem");
30963
+ async function resolveSingleVendorIdFromCart(cart) {
30874
30964
  const vendorIds = /* @__PURE__ */ new Set();
30965
+ const comboRepo = entityMap.combos ? dataSource.getRepository(entityMap.combos) : null;
30966
+ const comboVendorCache = /* @__PURE__ */ new Map();
30967
+ async function vendorIdForCombo(comboId) {
30968
+ if (comboVendorCache.has(comboId)) return comboVendorCache.get(comboId);
30969
+ if (!comboRepo) return null;
30970
+ const combo = await comboRepo.findOne({
30971
+ where: {
30972
+ id: comboId,
30973
+ deleted: false
30974
+ },
30975
+ select: [
30976
+ "id",
30977
+ "vendorId"
30978
+ ]
30979
+ });
30980
+ const vid = Number(combo?.vendorId);
30981
+ if (Number.isInteger(vid) && vid > 0) {
30982
+ comboVendorCache.set(comboId, vid);
30983
+ return vid;
30984
+ }
30985
+ return null;
30986
+ }
30987
+ chunkUSNT2KNT_cjs.__name(vendorIdForCombo, "vendorIdForCombo");
30875
30988
  for (const it of cart.items || []) {
30989
+ const comboId = comboIdFromCartItem(it);
30990
+ if (comboId != null) {
30991
+ const comboVendorId = await vendorIdForCombo(comboId);
30992
+ if (comboVendorId != null) {
30993
+ vendorIds.add(comboVendorId);
30994
+ continue;
30995
+ }
30996
+ }
30876
30997
  const p = it.product;
30877
30998
  if (!p || p.deleted || p.status !== "available") continue;
30878
30999
  const vid = Number(p.vendorId);
@@ -33198,7 +33319,7 @@ function createStorefrontApiHandler(config) {
33198
33319
  }, {
33199
33320
  status: prepOrd.status
33200
33321
  });
33201
- const vendorRes = resolveSingleVendorIdFromCart(cart);
33322
+ const vendorRes = await resolveSingleVendorIdFromCart(cart);
33202
33323
  if ("error" in vendorRes) return json({
33203
33324
  error: vendorRes.error
33204
33325
  }, {
@@ -33274,7 +33395,7 @@ function createStorefrontApiHandler(config) {
33274
33395
  }, {
33275
33396
  status: prepChk.status
33276
33397
  });
33277
- const vendorResChk = resolveSingleVendorIdFromCart(cart);
33398
+ const vendorResChk = await resolveSingleVendorIdFromCart(cart);
33278
33399
  if ("error" in vendorResChk) return json({
33279
33400
  error: vendorResChk.error
33280
33401
  }, {
@@ -33344,17 +33465,48 @@ function createStorefrontApiHandler(config) {
33344
33465
  if (!contact) return json({
33345
33466
  orders: []
33346
33467
  });
33347
- const orders = await orderRepo().find({
33348
- where: {
33349
- contactId: contact.id,
33350
- deleted: false,
33351
- orderKind: "sale"
33352
- },
33468
+ let linkedCustomerContactIds = [];
33469
+ if (entityMap.customer && entityMap.customer_contacts) {
33470
+ const rows = await dataSource.query(`SELECT cc.id
33471
+ FROM customer_contacts cc
33472
+ JOIN customer c ON c.id = cc."customerId"
33473
+ WHERE c."userId" = $1`, [
33474
+ uid
33475
+ ]);
33476
+ linkedCustomerContactIds = rows.map((row) => Number(row.id)).filter((id) => Number.isFinite(id) && id > 0);
33477
+ }
33478
+ const visibleOrders = await orderRepo().find({
33479
+ where: [
33480
+ {
33481
+ contactId: contact.id,
33482
+ deleted: false,
33483
+ orderKind: "sale"
33484
+ },
33485
+ ...linkedCustomerContactIds.length ? [
33486
+ {
33487
+ customerContactId: typeorm.In(linkedCustomerContactIds),
33488
+ deleted: false,
33489
+ orderKind: "sale"
33490
+ }
33491
+ ] : []
33492
+ ],
33353
33493
  order: {
33354
33494
  createdAt: "DESC"
33355
33495
  },
33356
33496
  take: 50
33357
33497
  });
33498
+ const orders = visibleOrders.filter((o) => {
33499
+ const row = o;
33500
+ const orderContactId = Number(row.contactId);
33501
+ const customerContactId = Number(row.customerContactId);
33502
+ if (Number.isFinite(orderContactId) && orderContactId > 0 && orderContactId === Number(contact.id)) {
33503
+ return true;
33504
+ }
33505
+ if (Number.isFinite(customerContactId) && customerContactId > 0) {
33506
+ return linkedCustomerContactIds.includes(customerContactId);
33507
+ }
33508
+ return false;
33509
+ });
33358
33510
  const orderIds = orders.map((o) => o.id);
33359
33511
  const previewByOrder = {};
33360
33512
  if (orderIds.length) {
@@ -33447,10 +33599,19 @@ function createStorefrontApiHandler(config) {
33447
33599
  status: 404
33448
33600
  });
33449
33601
  const orderId = parseInt(path2[1], 10);
33602
+ let linkedCustomerContactIds = [];
33603
+ if (entityMap.customer && entityMap.customer_contacts) {
33604
+ const rows = await dataSource.query(`SELECT cc.id
33605
+ FROM customer_contacts cc
33606
+ JOIN customer c ON c.id = cc."customerId"
33607
+ WHERE c."userId" = $1`, [
33608
+ uid
33609
+ ]);
33610
+ linkedCustomerContactIds = rows.map((row) => Number(row.id)).filter((id) => Number.isFinite(id) && id > 0);
33611
+ }
33450
33612
  let order = await orderRepo().findOne({
33451
33613
  where: {
33452
33614
  id: orderId,
33453
- contactId: contact.id,
33454
33615
  deleted: false
33455
33616
  },
33456
33617
  relations: [
@@ -33463,13 +33624,20 @@ function createStorefrontApiHandler(config) {
33463
33624
  }, {
33464
33625
  status: 404
33465
33626
  });
33627
+ const orderContactId = Number(order.contactId);
33628
+ const orderCustomerContactId = Number(order.customerContactId);
33629
+ const isOwner = Number.isFinite(orderContactId) && orderContactId > 0 && orderContactId === Number(contact.id) || Number.isFinite(orderCustomerContactId) && orderCustomerContactId > 0 && linkedCustomerContactIds.includes(orderCustomerContactId);
33630
+ if (!isOwner) return json({
33631
+ error: "Not found"
33632
+ }, {
33633
+ status: 404
33634
+ });
33466
33635
  if (getCms) {
33467
33636
  const cms = await getCms();
33468
33637
  await tryRefreshOrderFromErpForStorefront(cms, dataSource, entityMap, order);
33469
33638
  order = await orderRepo().findOne({
33470
33639
  where: {
33471
33640
  id: orderId,
33472
- contactId: contact.id,
33473
33641
  deleted: false
33474
33642
  },
33475
33643
  relations: [
@@ -33483,6 +33651,14 @@ function createStorefrontApiHandler(config) {
33483
33651
  }, {
33484
33652
  status: 404
33485
33653
  });
33654
+ const refreshedOrderContactId = Number(order.contactId);
33655
+ const refreshedCustomerContactId = Number(order.customerContactId);
33656
+ const isOwnerAfterRefresh = Number.isFinite(refreshedOrderContactId) && refreshedOrderContactId > 0 && refreshedOrderContactId === Number(contact.id) || Number.isFinite(refreshedCustomerContactId) && refreshedCustomerContactId > 0 && linkedCustomerContactIds.includes(refreshedCustomerContactId);
33657
+ if (!isOwnerAfterRefresh) return json({
33658
+ error: "Not found"
33659
+ }, {
33660
+ status: 404
33661
+ });
33486
33662
  const o = order;
33487
33663
  const lines = (o.items || []).map((line) => {
33488
33664
  const p = line.product;
@@ -1904,6 +1904,32 @@ async function ensureUniqueProductSlug(repo, baseSlug, vendorId, excludeId) {
1904
1904
  }
1905
1905
  }
1906
1906
  __name(ensureUniqueProductSlug, "ensureUniqueProductSlug");
1907
+ function isSlugUniqueViolation(err) {
1908
+ const msg = err instanceof Error ? err.message : String(err);
1909
+ return /duplicate key|unique constraint/i.test(msg) && /slug/i.test(msg);
1910
+ }
1911
+ __name(isSlugUniqueViolation, "isSlugUniqueViolation");
1912
+ async function assertUniqueEventSlug(repo, slugRaw, vendorId, excludeId) {
1913
+ const slug = typeof slugRaw === "string" ? slugRaw.trim() : "";
1914
+ if (!slug) return "Slug is required";
1915
+ await retireSoftDeletedUniqueValue(repo, "slug", slug);
1916
+ const where = excludeId != null ? {
1917
+ slug,
1918
+ vendorId,
1919
+ deleted: false,
1920
+ id: Not(excludeId)
1921
+ } : {
1922
+ slug,
1923
+ vendorId,
1924
+ deleted: false
1925
+ };
1926
+ const dup = await repo.findOne({
1927
+ where
1928
+ });
1929
+ if (dup) return "An event with this slug already exists";
1930
+ return null;
1931
+ }
1932
+ __name(assertUniqueEventSlug, "assertUniqueEventSlug");
1907
1933
  async function normalizeComboNameAndSlug(repo, body, vendorId, existing, excludeId) {
1908
1934
  const incomingName = typeof body.name === "string" ? body.name.trim() : "";
1909
1935
  const incomingSlugRaw = typeof body.slug === "string" ? body.slug.trim() : "";
@@ -4774,6 +4800,17 @@ function createCrudHandler(dataSource, entityMap, options) {
4774
4800
  status: 400
4775
4801
  });
4776
4802
  }
4803
+ if (resource === "events") {
4804
+ const vendorIdForSlug = scopeCreate.type === "vendor" ? scopeCreate.vendorId : Number(persistBody.vendorId);
4805
+ if (Number.isFinite(vendorIdForSlug) && vendorIdForSlug > 0) {
4806
+ const eventSlugErr = await assertUniqueEventSlug(repo, persistBody.slug, vendorIdForSlug);
4807
+ if (eventSlugErr) return json({
4808
+ error: eventSlugErr
4809
+ }, {
4810
+ status: 400
4811
+ });
4812
+ }
4813
+ }
4777
4814
  sanitizeBodyForEntity(repo, persistBody);
4778
4815
  let created;
4779
4816
  try {
@@ -5053,6 +5090,13 @@ function createCrudHandler(dataSource, entityMap, options) {
5053
5090
  }
5054
5091
  } catch (err) {
5055
5092
  const message = err instanceof Error ? err.message : String(err);
5093
+ if (resource === "events" && isSlugUniqueViolation(err)) {
5094
+ return json({
5095
+ error: "An event with this slug already exists"
5096
+ }, {
5097
+ status: 400
5098
+ });
5099
+ }
5056
5100
  logCrudServerError("POST create save failed", {
5057
5101
  resource,
5058
5102
  message,
@@ -6329,6 +6373,17 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
6329
6373
  });
6330
6374
  }
6331
6375
  }
6376
+ if ("slug" in updatePayload) {
6377
+ const vendorIdForSlug = scopePut.type === "vendor" ? scopePut.vendorId : Number(currentEvent.vendorId);
6378
+ if (Number.isFinite(vendorIdForSlug) && vendorIdForSlug > 0) {
6379
+ const eventSlugErr = await assertUniqueEventSlug(repo, updatePayload.slug, vendorIdForSlug, numericId);
6380
+ if (eventSlugErr) return json({
6381
+ error: eventSlugErr
6382
+ }, {
6383
+ status: 400
6384
+ });
6385
+ }
6386
+ }
6332
6387
  }
6333
6388
  if (resource === "product_categories" && scopePut.type === "all") {
6334
6389
  const existingCatalogCat = await repo.findOne({
@@ -6492,7 +6547,18 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
6492
6547
  }
6493
6548
  sanitizeBodyForEntity(repo, updatePayload);
6494
6549
  await retireSoftDeletedUniquesFromBody(repo, updatePayload);
6495
- await repo.update(numericId, updatePayload);
6550
+ try {
6551
+ await repo.update(numericId, updatePayload);
6552
+ } catch (err) {
6553
+ if (resource === "events" && isSlugUniqueViolation(err)) {
6554
+ return json({
6555
+ error: "An event with this slug already exists"
6556
+ }, {
6557
+ status: 400
6558
+ });
6559
+ }
6560
+ throw err;
6561
+ }
6496
6562
  }
6497
6563
  if (resource === "orders" && rawBody && entityMap["order_addresses"]) {
6498
6564
  const addressRawScalar = String(rawBody["contact.address"] ?? "").trim();
@@ -8685,11 +8751,21 @@ function createUploadHandler(config) {
8685
8751
  const storageService = raw instanceof Promise ? await raw : raw;
8686
8752
  if (storageService) {
8687
8753
  const fileUrl = await storageService.upload(buffer, `uploads/${relativeUnderUploads}`, contentType);
8754
+ console.info("[upload] stored via storage plugin", {
8755
+ key: `uploads/${relativeUnderUploads}`,
8756
+ contentType,
8757
+ bytes: buffer.length,
8758
+ fileUrl
8759
+ });
8688
8760
  return json({
8689
8761
  filePath: fileUrl,
8690
8762
  parentId
8691
8763
  });
8692
8764
  }
8765
+ console.warn("[upload] no storage plugin \u2014 writing local disk (broken on most deploys)", {
8766
+ localUploadDir,
8767
+ key: relativeUnderUploads
8768
+ });
8693
8769
  const fs2 = await import('fs/promises');
8694
8770
  const path2 = await import('path');
8695
8771
  const dir = path2.join(process.cwd(), localUploadDir);
@@ -8705,11 +8781,13 @@ function createUploadHandler(config) {
8705
8781
  });
8706
8782
  } catch (err) {
8707
8783
  const message = err instanceof Error ? err.message : String(err);
8784
+ const awsMeta = err && typeof err === "object" && "$metadata" in err ? err.$metadata : void 0;
8708
8785
  console.error("[upload] File upload failed", {
8709
8786
  error: message,
8710
8787
  stack: err instanceof Error ? err.stack : void 0,
8711
8788
  name: err instanceof Error ? err.name : void 0,
8712
- metadata: err && typeof err === "object" && "$metadata" in err ? err.$metadata : void 0
8789
+ code: err && typeof err === "object" && ("Code" in err || "code" in err) ? err.Code ?? err.code : void 0,
8790
+ metadata: awsMeta
8713
8791
  });
8714
8792
  if (/Failed to parse body as FormData/i.test(message)) {
8715
8793
  return json({
@@ -8719,7 +8797,8 @@ function createUploadHandler(config) {
8719
8797
  });
8720
8798
  }
8721
8799
  return json({
8722
- error: "File upload failed"
8800
+ error: "File upload failed",
8801
+ details: message
8723
8802
  }, {
8724
8803
  status: 500
8725
8804
  });
@@ -30860,9 +30939,51 @@ function createStorefrontApiHandler(config) {
30860
30939
  "items.product.taxes",
30861
30940
  "items.product.taxes.tax"
30862
30941
  ];
30863
- function resolveSingleVendorIdFromCart(cart) {
30942
+ function comboIdFromCartItem(it) {
30943
+ const meta = it.metadata && typeof it.metadata === "object" && !Array.isArray(it.metadata) ? it.metadata : {};
30944
+ const fromMeta = Number(meta.comboId ?? meta.combo_id);
30945
+ if (Number.isInteger(fromMeta) && fromMeta > 0) return fromMeta;
30946
+ if (meta.isCombo === true || meta.type === "combo" || meta.lineType === "combo") {
30947
+ const pid = Number(it.productId);
30948
+ if (Number.isInteger(pid) && pid > 0) return pid;
30949
+ }
30950
+ return null;
30951
+ }
30952
+ __name(comboIdFromCartItem, "comboIdFromCartItem");
30953
+ async function resolveSingleVendorIdFromCart(cart) {
30864
30954
  const vendorIds = /* @__PURE__ */ new Set();
30955
+ const comboRepo = entityMap.combos ? dataSource.getRepository(entityMap.combos) : null;
30956
+ const comboVendorCache = /* @__PURE__ */ new Map();
30957
+ async function vendorIdForCombo(comboId) {
30958
+ if (comboVendorCache.has(comboId)) return comboVendorCache.get(comboId);
30959
+ if (!comboRepo) return null;
30960
+ const combo = await comboRepo.findOne({
30961
+ where: {
30962
+ id: comboId,
30963
+ deleted: false
30964
+ },
30965
+ select: [
30966
+ "id",
30967
+ "vendorId"
30968
+ ]
30969
+ });
30970
+ const vid = Number(combo?.vendorId);
30971
+ if (Number.isInteger(vid) && vid > 0) {
30972
+ comboVendorCache.set(comboId, vid);
30973
+ return vid;
30974
+ }
30975
+ return null;
30976
+ }
30977
+ __name(vendorIdForCombo, "vendorIdForCombo");
30865
30978
  for (const it of cart.items || []) {
30979
+ const comboId = comboIdFromCartItem(it);
30980
+ if (comboId != null) {
30981
+ const comboVendorId = await vendorIdForCombo(comboId);
30982
+ if (comboVendorId != null) {
30983
+ vendorIds.add(comboVendorId);
30984
+ continue;
30985
+ }
30986
+ }
30866
30987
  const p = it.product;
30867
30988
  if (!p || p.deleted || p.status !== "available") continue;
30868
30989
  const vid = Number(p.vendorId);
@@ -33188,7 +33309,7 @@ function createStorefrontApiHandler(config) {
33188
33309
  }, {
33189
33310
  status: prepOrd.status
33190
33311
  });
33191
- const vendorRes = resolveSingleVendorIdFromCart(cart);
33312
+ const vendorRes = await resolveSingleVendorIdFromCart(cart);
33192
33313
  if ("error" in vendorRes) return json({
33193
33314
  error: vendorRes.error
33194
33315
  }, {
@@ -33264,7 +33385,7 @@ function createStorefrontApiHandler(config) {
33264
33385
  }, {
33265
33386
  status: prepChk.status
33266
33387
  });
33267
- const vendorResChk = resolveSingleVendorIdFromCart(cart);
33388
+ const vendorResChk = await resolveSingleVendorIdFromCart(cart);
33268
33389
  if ("error" in vendorResChk) return json({
33269
33390
  error: vendorResChk.error
33270
33391
  }, {
@@ -33334,17 +33455,48 @@ function createStorefrontApiHandler(config) {
33334
33455
  if (!contact) return json({
33335
33456
  orders: []
33336
33457
  });
33337
- const orders = await orderRepo().find({
33338
- where: {
33339
- contactId: contact.id,
33340
- deleted: false,
33341
- orderKind: "sale"
33342
- },
33458
+ let linkedCustomerContactIds = [];
33459
+ if (entityMap.customer && entityMap.customer_contacts) {
33460
+ const rows = await dataSource.query(`SELECT cc.id
33461
+ FROM customer_contacts cc
33462
+ JOIN customer c ON c.id = cc."customerId"
33463
+ WHERE c."userId" = $1`, [
33464
+ uid
33465
+ ]);
33466
+ linkedCustomerContactIds = rows.map((row) => Number(row.id)).filter((id) => Number.isFinite(id) && id > 0);
33467
+ }
33468
+ const visibleOrders = await orderRepo().find({
33469
+ where: [
33470
+ {
33471
+ contactId: contact.id,
33472
+ deleted: false,
33473
+ orderKind: "sale"
33474
+ },
33475
+ ...linkedCustomerContactIds.length ? [
33476
+ {
33477
+ customerContactId: In(linkedCustomerContactIds),
33478
+ deleted: false,
33479
+ orderKind: "sale"
33480
+ }
33481
+ ] : []
33482
+ ],
33343
33483
  order: {
33344
33484
  createdAt: "DESC"
33345
33485
  },
33346
33486
  take: 50
33347
33487
  });
33488
+ const orders = visibleOrders.filter((o) => {
33489
+ const row = o;
33490
+ const orderContactId = Number(row.contactId);
33491
+ const customerContactId = Number(row.customerContactId);
33492
+ if (Number.isFinite(orderContactId) && orderContactId > 0 && orderContactId === Number(contact.id)) {
33493
+ return true;
33494
+ }
33495
+ if (Number.isFinite(customerContactId) && customerContactId > 0) {
33496
+ return linkedCustomerContactIds.includes(customerContactId);
33497
+ }
33498
+ return false;
33499
+ });
33348
33500
  const orderIds = orders.map((o) => o.id);
33349
33501
  const previewByOrder = {};
33350
33502
  if (orderIds.length) {
@@ -33437,10 +33589,19 @@ function createStorefrontApiHandler(config) {
33437
33589
  status: 404
33438
33590
  });
33439
33591
  const orderId = parseInt(path2[1], 10);
33592
+ let linkedCustomerContactIds = [];
33593
+ if (entityMap.customer && entityMap.customer_contacts) {
33594
+ const rows = await dataSource.query(`SELECT cc.id
33595
+ FROM customer_contacts cc
33596
+ JOIN customer c ON c.id = cc."customerId"
33597
+ WHERE c."userId" = $1`, [
33598
+ uid
33599
+ ]);
33600
+ linkedCustomerContactIds = rows.map((row) => Number(row.id)).filter((id) => Number.isFinite(id) && id > 0);
33601
+ }
33440
33602
  let order = await orderRepo().findOne({
33441
33603
  where: {
33442
33604
  id: orderId,
33443
- contactId: contact.id,
33444
33605
  deleted: false
33445
33606
  },
33446
33607
  relations: [
@@ -33453,13 +33614,20 @@ function createStorefrontApiHandler(config) {
33453
33614
  }, {
33454
33615
  status: 404
33455
33616
  });
33617
+ const orderContactId = Number(order.contactId);
33618
+ const orderCustomerContactId = Number(order.customerContactId);
33619
+ const isOwner = Number.isFinite(orderContactId) && orderContactId > 0 && orderContactId === Number(contact.id) || Number.isFinite(orderCustomerContactId) && orderCustomerContactId > 0 && linkedCustomerContactIds.includes(orderCustomerContactId);
33620
+ if (!isOwner) return json({
33621
+ error: "Not found"
33622
+ }, {
33623
+ status: 404
33624
+ });
33456
33625
  if (getCms) {
33457
33626
  const cms = await getCms();
33458
33627
  await tryRefreshOrderFromErpForStorefront(cms, dataSource, entityMap, order);
33459
33628
  order = await orderRepo().findOne({
33460
33629
  where: {
33461
33630
  id: orderId,
33462
- contactId: contact.id,
33463
33631
  deleted: false
33464
33632
  },
33465
33633
  relations: [
@@ -33473,6 +33641,14 @@ function createStorefrontApiHandler(config) {
33473
33641
  }, {
33474
33642
  status: 404
33475
33643
  });
33644
+ const refreshedOrderContactId = Number(order.contactId);
33645
+ const refreshedCustomerContactId = Number(order.customerContactId);
33646
+ const isOwnerAfterRefresh = Number.isFinite(refreshedOrderContactId) && refreshedOrderContactId > 0 && refreshedOrderContactId === Number(contact.id) || Number.isFinite(refreshedCustomerContactId) && refreshedCustomerContactId > 0 && linkedCustomerContactIds.includes(refreshedCustomerContactId);
33647
+ if (!isOwnerAfterRefresh) return json({
33648
+ error: "Not found"
33649
+ }, {
33650
+ status: 404
33651
+ });
33476
33652
  const o = order;
33477
33653
  const lines = (o.items || []).map((line) => {
33478
33654
  const p = line.product;