@infuro/cms-core 1.0.61 → 1.0.63

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.
Files changed (50) hide show
  1. package/dist/admin.cjs +3624 -2642
  2. package/dist/admin.js +2415 -1433
  3. package/dist/api.cjs +41 -37
  4. package/dist/api.js +9 -5
  5. package/dist/chunk-3VZAAQUV.js +106 -0
  6. package/dist/{chunk-UHT4INVW.js → chunk-77YWLP4X.js} +625 -252
  7. package/dist/{chunk-BXYZDMTZ.cjs → chunk-7L556RGL.cjs} +3 -94
  8. package/dist/{chunk-T3HPSF7K.js → chunk-AYWDQFJZ.js} +3 -0
  9. package/dist/{chunk-URN7GS23.js → chunk-BWOITUNI.js} +203 -1062
  10. package/dist/{chunk-CNAHVRRU.cjs → chunk-CJEOH6QC.cjs} +676 -312
  11. package/dist/{chunk-O2642WVS.js → chunk-DTUL3Q5L.js} +17 -3
  12. package/dist/{chunk-YSYX4GUD.cjs → chunk-EWXG4E74.cjs} +213 -1082
  13. package/dist/chunk-GWDI752Q.js +83 -0
  14. package/dist/chunk-H3IVLIPR.cjs +86 -0
  15. package/dist/chunk-JLDHK2QE.cjs +109 -0
  16. package/dist/chunk-KAOHOHCA.js +901 -0
  17. package/dist/{chunk-2KUCQVAQ.js → chunk-MWEK7N3F.js} +2 -91
  18. package/dist/{chunk-V25RDUOU.cjs → chunk-MXABMVF7.cjs} +38 -4
  19. package/dist/chunk-OVTOP42W.js +199 -0
  20. package/dist/{chunk-73WVHINE.cjs → chunk-RHYVNRYG.cjs} +18 -4
  21. package/dist/{chunk-L3525VXI.js → chunk-RXTUSF3R.js} +36 -2
  22. package/dist/{chunk-77I3KS7V.cjs → chunk-UEE4PTTB.cjs} +3 -0
  23. package/dist/chunk-WFMVD567.cjs +209 -0
  24. package/dist/chunk-YVP4NQII.cjs +914 -0
  25. package/dist/{email-queue-6NJY6HNM.cjs → email-queue-VTYL2KFA.cjs} +7 -6
  26. package/dist/{email-queue-OI2HSCGE.js → email-queue-YPRSVG56.js} +3 -2
  27. package/dist/email-service-ATCPJFWG.cjs +28 -0
  28. package/dist/email-service-DPKVQOKP.js +3 -0
  29. package/dist/{emit-order-notification-trigger-TNEZOYEE.cjs → emit-order-notification-trigger-WI4HGMKH.cjs} +4 -4
  30. package/dist/{emit-order-notification-trigger-CZU3V2WE.js → emit-order-notification-trigger-XVG2B5ZF.js} +2 -2
  31. package/dist/{erp-order-invoice-3GXDE443.js → erp-order-invoice-3UGWLICU.js} +2 -1
  32. package/dist/{erp-order-invoice-EYYNR526.cjs → erp-order-invoice-KJYJNWMG.cjs} +6 -5
  33. package/dist/index.cjs +366 -316
  34. package/dist/index.d.cts +61 -21
  35. package/dist/index.d.ts +61 -21
  36. package/dist/index.js +79 -29
  37. package/dist/migrations/1783000000000-AddOrderPendingProcessingCompletedTriggers.ts +56 -0
  38. package/dist/migrations/1783100000000-AddSmsToOrderNotificationBindingsChannelEnum.ts +17 -0
  39. package/dist/migrations/1783200000000-AddOrderAssigneeColumns.ts +30 -0
  40. package/dist/order-assignees-handlers-LKMAGLG6.js +150 -0
  41. package/dist/order-assignees-handlers-NPKD64P6.cjs +152 -0
  42. package/dist/order-completion-otp-handlers-IMMQGHDR.cjs +363 -0
  43. package/dist/order-completion-otp-handlers-WGM7HWG4.js +361 -0
  44. package/dist/order-notification-dispatcher-5TUFCDU7.cjs +35 -0
  45. package/dist/order-notification-dispatcher-JKFQJYGG.js +10 -0
  46. package/dist/sms-notification-templates-handlers-SJLO7JGZ.js +47 -0
  47. package/dist/sms-notification-templates-handlers-YSB3L2PK.cjs +49 -0
  48. package/package.json +1 -1
  49. package/dist/order-notification-dispatcher-KJVGLK5E.cjs +0 -24
  50. package/dist/order-notification-dispatcher-ZSFKEYMP.js +0 -7
@@ -1,10 +1,13 @@
1
+ import { normalizePhoneE164, generateNumericOtp, createOtpChallenge, queueSms, verifyAndConsumeOtpChallenge } from './chunk-OVTOP42W.js';
1
2
  import { JOB_RUNNER_QUEUE } from './chunk-GO7PPYNU.js';
2
3
  import { validateInventoryForConfirmedOrderLines, orderStatusHoldsStock, reconcileOrderInventoryBetweenSnapshots, orderInventorySnapshotFromRow, validateInventoryForOrderBecomingConfirmed } from './chunk-3K5AIEIZ.js';
3
- import { resolveChatEmailToolSettings, CHAT_EMAIL_LOG, detectChatLeadIntent, parseIntentRecipientEmails, sendChatLeadEmail, buildTranscriptForLeadEmail, buildChatbotSystemPromptWithEmailTool, validateFcmCredentials, sendFcmPushNotification, parseEmailRecipientsFromConfig, isWhatsAppPluginEnabled, mergeWhatsAppConfigLayers, whatsAppConfigured, WhatsAppService, registerWhatsAppQueueProcessor, emailPlugin, initWhatsappTriggerDispatcher } from './chunk-URN7GS23.js';
4
+ import { resolveChatEmailToolSettings, CHAT_EMAIL_LOG, detectChatLeadIntent, parseIntentRecipientEmails, sendChatLeadEmail, buildTranscriptForLeadEmail, buildChatbotSystemPromptWithEmailTool, validateFcmCredentials, sendFcmPushNotification, parseEmailRecipientsFromConfig, isWhatsAppPluginEnabled, WhatsAppService, emailPlugin, initWhatsappTriggerDispatcher } from './chunk-BWOITUNI.js';
5
+ import { registerWhatsAppQueueProcessor } from './chunk-GWDI752Q.js';
4
6
  import { inviteStatusForActivation } from './chunk-JXF23MPG.js';
5
- import { queueEmail, queueVendorOnboardEmails, registerEmailQueueProcessor } from './chunk-L3525VXI.js';
6
- import { mergeEmailLayoutCompanyDetails, unwrapErpReadData, mapErpPayloadToFulfillment, extractChildOrderRefsFromSalePayload, mapErpPayloadToInvoiceNumber, streamOrderInvoicePdf } from './chunk-2KUCQVAQ.js';
7
+ import { queueEmail, queueVendorOnboardEmails, registerEmailQueueProcessor } from './chunk-RXTUSF3R.js';
8
+ import { unwrapErpReadData, mapErpPayloadToFulfillment, extractChildOrderRefsFromSalePayload, mapErpPayloadToInvoiceNumber, streamOrderInvoicePdf } from './chunk-MWEK7N3F.js';
7
9
  import { isErpIntegrationEnabled } from './chunk-JC6DLWTE.js';
10
+ import { mergeEmailLayoutCompanyDetails } from './chunk-3VZAAQUV.js';
8
11
  import { getSmsTemplateDefault, SMS_MESSAGE_TEMPLATE_DEFAULTS } from './chunk-MQBT33IV.js';
9
12
  import { EVENT_ORDER_MESSAGE_TEMPLATE_DEFAULTS, EVENT_ORDER_TEMPLATE_KEY, EVENT_ORDER_TEMPLATE_VARIABLES } from './chunk-AYERBA7I.js';
10
13
  import { ensureCustomerRecord, linkUnclaimedContactToUser, ensureCustomerForUser, canManageRoles, sessionHasEntityAccess } from './chunk-NR44CK5E.js';
@@ -14,7 +17,7 @@ import { queueErp } from './chunk-SYBOCAWB.js';
14
17
  import { __name } from './chunk-SHUYVCID.js';
15
18
  import { PrimaryGeneratedColumn, Column, Entity, ManyToOne, JoinColumn, CreateDateColumn, UpdateDateColumn, Unique, OneToMany, Index, ManyToMany, JoinTable, In, ILike, Between, MoreThanOrEqual, LessThanOrEqual, Not, MoreThan, IsNull } from 'typeorm';
16
19
  import { Country, State, City } from 'country-state-city';
17
- import crypto2, { randomBytes, randomUUID, createHmac, timingSafeEqual, randomInt } from 'crypto';
20
+ import crypto2, { randomBytes, randomUUID } from 'crypto';
18
21
  import Parser from 'rss-parser';
19
22
  import fs from 'fs/promises';
20
23
  import path from 'path';
@@ -1516,9 +1519,15 @@ async function autoExpireOrderIfPaymentTimeExceeded(dataSource, entityMap, order
1516
1519
  if (status !== "pending") return order;
1517
1520
  const meta = typeof order.metadata === "object" && order.metadata ? order.metadata : {};
1518
1521
  const expiresAtStr = meta.paymentExpiresAt ? String(meta.paymentExpiresAt) : null;
1519
- if (!expiresAtStr) return order;
1520
- const expiresMs = new Date(expiresAtStr).getTime();
1521
- if (Number.isNaN(expiresMs) || Date.now() <= expiresMs) return order;
1522
+ let isExpired = false;
1523
+ if (expiresAtStr) {
1524
+ const expiresMs = new Date(expiresAtStr).getTime();
1525
+ if (!Number.isNaN(expiresMs) && Date.now() > expiresMs) isExpired = true;
1526
+ } else if (order.createdAt) {
1527
+ const createdMs = new Date(order.createdAt).getTime();
1528
+ if (!Number.isNaN(createdMs) && Date.now() - createdMs > 10 * 60 * 1e3) isExpired = true;
1529
+ }
1530
+ if (!isExpired) return order;
1522
1531
  try {
1523
1532
  const orderId = Number(order.id);
1524
1533
  if (orderId && entityMap.orders) {
@@ -3547,7 +3556,7 @@ function createCrudHandler(dataSource, entityMap, options) {
3547
3556
  });
3548
3557
  }
3549
3558
  }
3550
- const qb = repo2.createQueryBuilder("order").leftJoinAndSelect("order.contact", "contact").leftJoinAndSelect("order.items", "items").leftJoinAndSelect("items.product", "product").leftJoinAndSelect("product.collection", "collection").leftJoinAndSelect("order.payments", "payments").andWhere("order.deleted = :orderDel", {
3559
+ const qb = repo2.createQueryBuilder("order").leftJoinAndSelect("order.contact", "contact").leftJoinAndSelect("order.items", "items").leftJoinAndSelect("items.product", "product").leftJoinAndSelect("product.collection", "collection").leftJoinAndSelect("order.payments", "payments").leftJoinAndSelect("order.assignedUser", "assignedUser").andWhere("order.deleted = :orderDel", {
3551
3560
  orderDel: false
3552
3561
  }).orderBy(`order.${sortField2}`, sortOrderOrders).skip(skip).take(limit);
3553
3562
  applyVendorScopeToQueryBuilder(qb, "order", scope);
@@ -3605,7 +3614,9 @@ function createCrudHandler(dataSource, entityMap, options) {
3605
3614
  }
3606
3615
  const [rows, total2] = await qb.getManyAndCount();
3607
3616
  const data2 = await Promise.all(rows.map(async (order) => {
3617
+ await autoExpireOrderIfPaymentTimeExceeded(dataSource, entityMap, order);
3608
3618
  const contact = order.contact;
3619
+ const assignedUserObj = order.assignedUser;
3609
3620
  const items = order.items ?? [];
3610
3621
  const orderPayments = order.payments ?? [];
3611
3622
  const parts = [];
@@ -3653,6 +3664,11 @@ function createCrudHandler(dataSource, entityMap, options) {
3653
3664
  email: contact.email,
3654
3665
  phone: contact.phone
3655
3666
  } : null,
3667
+ assignedUser: assignedUserObj ? {
3668
+ id: assignedUserObj.id,
3669
+ name: assignedUserObj.name || assignedUserObj.email,
3670
+ email: assignedUserObj.email
3671
+ } : null,
3656
3672
  itemsSummary,
3657
3673
  paymentStatus: paymentStatus2
3658
3674
  };
@@ -5189,18 +5205,99 @@ function createCrudHandler(dataSource, entityMap, options) {
5189
5205
  }
5190
5206
  await recordDiscountUsage2(dataSource, entityMap, created.id, orderDiscountId, persistBody.contactId, discount);
5191
5207
  }
5208
+ if (entityMap["payments"]) {
5209
+ try {
5210
+ const paymentRepo = dataSource.getRepository(entityMap["payments"]);
5211
+ const initialPayStatus2 = String(persistBody.paymentStatus ?? body.paymentStatus ?? "unpaid").toLowerCase();
5212
+ const isPaid = initialPayStatus2 === "paid" || initialPayStatus2 === "captured";
5213
+ const vId = Number(orderVendorId ?? created?.vendorId ?? 1);
5214
+ const cId = persistBody.contactId ? Number(persistBody.contactId) : null;
5215
+ await paymentRepo.save(paymentRepo.create({
5216
+ vendorId: vId,
5217
+ contactId: cId,
5218
+ orderId: created.id,
5219
+ status: initialPayStatus2,
5220
+ amount: Number(total ?? persistBody.total ?? 0),
5221
+ currency: orderCurrency ?? persistBody.currency ?? "INR",
5222
+ paidAt: isPaid ? /* @__PURE__ */ new Date() : null,
5223
+ method: String(body.paymentMethod ?? "manual")
5224
+ }));
5225
+ } catch (payErr) {
5226
+ console.error("[crud] failed to create initial payment for order", payErr);
5227
+ }
5228
+ }
5192
5229
  const orderIdForNotify = created.id;
5193
- const initialPayStatus = String(persistBody.paymentStatus ?? "unpaid").toLowerCase();
5194
- void import('./emit-order-notification-trigger-CZU3V2WE.js').then(({ fireOrderNotificationTrigger }) => {
5195
- fireOrderNotificationTrigger("order_placed", orderIdForNotify, {
5196
- dataSource,
5197
- entityMap
5198
- });
5199
- if (initialPayStatus === "paid" || initialPayStatus === "captured") {
5200
- fireOrderNotificationTrigger("payment_success", orderIdForNotify, {
5230
+ const finalCreatedStatus = String(created.status ?? createdStatus ?? "pending").toLowerCase();
5231
+ const initialPayStatus = String(persistBody.paymentStatus ?? body.paymentStatus ?? "unpaid").toLowerCase();
5232
+ void import('./emit-order-notification-trigger-XVG2B5ZF.js').then(({ fireOrderNotificationTrigger }) => {
5233
+ if (finalCreatedStatus === "pending") {
5234
+ if (initialPayStatus === "failed") {
5235
+ fireOrderNotificationTrigger("payment_failed", orderIdForNotify, {
5236
+ dataSource,
5237
+ entityMap
5238
+ });
5239
+ } else {
5240
+ fireOrderNotificationTrigger("order_pending", orderIdForNotify, {
5241
+ dataSource,
5242
+ entityMap
5243
+ });
5244
+ }
5245
+ } else if (finalCreatedStatus === "confirmed") {
5246
+ fireOrderNotificationTrigger("order_placed", orderIdForNotify, {
5247
+ dataSource,
5248
+ entityMap
5249
+ });
5250
+ if (initialPayStatus === "paid" || initialPayStatus === "captured") {
5251
+ fireOrderNotificationTrigger("payment_success", orderIdForNotify, {
5252
+ dataSource,
5253
+ entityMap
5254
+ });
5255
+ } else if (initialPayStatus === "failed") {
5256
+ fireOrderNotificationTrigger("payment_failed", orderIdForNotify, {
5257
+ dataSource,
5258
+ entityMap
5259
+ });
5260
+ }
5261
+ } else if (finalCreatedStatus === "processing") {
5262
+ fireOrderNotificationTrigger("order_processing", orderIdForNotify, {
5263
+ dataSource,
5264
+ entityMap
5265
+ });
5266
+ if (initialPayStatus === "failed") {
5267
+ fireOrderNotificationTrigger("payment_failed", orderIdForNotify, {
5268
+ dataSource,
5269
+ entityMap
5270
+ });
5271
+ }
5272
+ } else if (finalCreatedStatus === "completed") {
5273
+ fireOrderNotificationTrigger("order_completed", orderIdForNotify, {
5201
5274
  dataSource,
5202
5275
  entityMap
5203
5276
  });
5277
+ if (initialPayStatus === "failed") {
5278
+ fireOrderNotificationTrigger("payment_failed", orderIdForNotify, {
5279
+ dataSource,
5280
+ entityMap
5281
+ });
5282
+ }
5283
+ } else if (finalCreatedStatus === "cancelled") {
5284
+ if (initialPayStatus === "failed") {
5285
+ fireOrderNotificationTrigger("payment_failed", orderIdForNotify, {
5286
+ dataSource,
5287
+ entityMap
5288
+ });
5289
+ } else {
5290
+ fireOrderNotificationTrigger("order_cancelled", orderIdForNotify, {
5291
+ dataSource,
5292
+ entityMap
5293
+ });
5294
+ if (initialPayStatus === "paid" || initialPayStatus === "refunded") {
5295
+ fireOrderNotificationTrigger("payment_refund_initiated", orderIdForNotify, {
5296
+ dataSource,
5297
+ entityMap
5298
+ });
5299
+ }
5300
+ }
5204
5301
  }
5205
5302
  });
5206
5303
  }
@@ -5551,8 +5648,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
5551
5648
  const scope2 = await resolveScopeById();
5552
5649
  const order = await repo.findOne({
5553
5650
  where: {
5554
- id: Number(id),
5555
- deleted: false
5651
+ id: Number(id)
5556
5652
  },
5557
5653
  relations: [
5558
5654
  "contact",
@@ -5561,7 +5657,8 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
5561
5657
  "items",
5562
5658
  "items.product",
5563
5659
  "items.product.collection",
5564
- "payments"
5660
+ "payments",
5661
+ "assignedUser"
5565
5662
  ]
5566
5663
  });
5567
5664
  if (order) {
@@ -5571,8 +5668,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
5571
5668
  if (orderDenied) return orderDenied;
5572
5669
  const relatedOrders = await repo.find({
5573
5670
  where: {
5574
- parentOrderId: Number(id),
5575
- deleted: false
5671
+ parentOrderId: Number(id)
5576
5672
  },
5577
5673
  order: {
5578
5674
  id: "ASC"
@@ -5951,6 +6047,36 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
5951
6047
  lines: []
5952
6048
  } : await calculateOrderTotalsFromLines(dataSource, entityMap, orderLinesNorm, effectiveCurrency, putDiscountId, Number.isFinite(putOrderVendorId) ? putOrderVendorId : null);
5953
6049
  const scalarUpdate = pickColumnUpdates(repo, rawBody);
6050
+ if (rawBody && typeof rawBody === "object" && "assignedUserId" in rawBody && rawBody.assignedUserId !== void 0) {
6051
+ const aId = Number(rawBody.assignedUserId);
6052
+ if (Number.isFinite(aId) && aId > 0) {
6053
+ scalarUpdate.assignedUserId = aId;
6054
+ scalarUpdate.assignedAt = /* @__PURE__ */ new Date();
6055
+ if (!scalarUpdate.status && (orderInvPrev?.status === "confirmed" || orderInvPrev?.status === "pending")) {
6056
+ scalarUpdate.status = "processing";
6057
+ }
6058
+ } else {
6059
+ scalarUpdate.assignedUserId = null;
6060
+ scalarUpdate.assignedAt = null;
6061
+ }
6062
+ }
6063
+ if (scalarUpdate.status === "processing") {
6064
+ const effectiveAssignee = scalarUpdate.assignedUserId !== void 0 ? scalarUpdate.assignedUserId : orderInvPrev?.assignedUserId;
6065
+ if (!effectiveAssignee) {
6066
+ return json({
6067
+ error: "Cannot start processing without assigning a teammate. Please assign a teammate first."
6068
+ }, {
6069
+ status: 400
6070
+ });
6071
+ }
6072
+ }
6073
+ if (scalarUpdate.status === "completed" && orderInvPrev?.status !== "completed" && !rawBody?.__internalBypassOtp) {
6074
+ return json({
6075
+ error: "Direct completion is disabled. Please complete the order via the customer OTP verification flow."
6076
+ }, {
6077
+ status: 400
6078
+ });
6079
+ }
5954
6080
  const nextStatus = typeof scalarUpdate.status === "string" && scalarUpdate.status ? String(scalarUpdate.status) : orderInvPrev?.status ?? "pending";
5955
6081
  if (orderStatusHoldsStock(nextStatus) && lines.length > 0) {
5956
6082
  const verr = await validateInventoryForOrderBecomingConfirmed(dataSource, entityMap, orderInvPrev, lines.filter((l) => l.found && l.productId != null).map((l) => ({
@@ -6138,6 +6264,128 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
6138
6264
  }
6139
6265
  }
6140
6266
  }
6267
+ if (rawBody && entityMap["payments"]) {
6268
+ try {
6269
+ const bodyPayStatusRaw = rawBody.paymentStatus;
6270
+ if (bodyPayStatusRaw != null && typeof bodyPayStatusRaw === "string") {
6271
+ const payStatus = bodyPayStatusRaw.trim().toLowerCase();
6272
+ const paymentRepo = dataSource.getRepository(entityMap["payments"]);
6273
+ const existingPay = await paymentRepo.findOne({
6274
+ where: {
6275
+ orderId: numericId
6276
+ },
6277
+ order: {
6278
+ id: "DESC"
6279
+ }
6280
+ });
6281
+ const isPaid = payStatus === "paid" || payStatus === "captured";
6282
+ if (existingPay) {
6283
+ await paymentRepo.update(existingPay.id, {
6284
+ status: payStatus,
6285
+ paidAt: isPaid && !existingPay.paidAt ? /* @__PURE__ */ new Date() : existingPay.paidAt
6286
+ });
6287
+ } else {
6288
+ const orderRow = updatedOrder;
6289
+ const orderTotal = Number(orderRow?.total ?? 0);
6290
+ const orderCurrency = String(orderRow?.currency ?? "INR");
6291
+ const vId = Number(orderRow?.vendorId ?? 1);
6292
+ const cId = orderRow?.contactId ? Number(orderRow.contactId) : null;
6293
+ await paymentRepo.save(paymentRepo.create({
6294
+ vendorId: vId,
6295
+ contactId: cId,
6296
+ orderId: numericId,
6297
+ status: payStatus,
6298
+ amount: orderTotal,
6299
+ currency: orderCurrency,
6300
+ paidAt: isPaid ? /* @__PURE__ */ new Date() : null,
6301
+ method: "manual"
6302
+ }));
6303
+ }
6304
+ }
6305
+ } catch (payErr) {
6306
+ console.error("[crud] failed to update/create payment on order update", payErr);
6307
+ }
6308
+ }
6309
+ const statusUpdated = Boolean(scalarUpdate.status || rawBody.status);
6310
+ const paymentUpdated = Boolean(rawBody && typeof rawBody === "object" && rawBody.paymentStatus != null);
6311
+ if (statusUpdated || paymentUpdated) {
6312
+ const newStatus = scalarUpdate.status ? String(scalarUpdate.status).toLowerCase() : rawBody.status ? String(rawBody.status).toLowerCase() : String(updatedOrder.status || "pending").toLowerCase();
6313
+ const payments = Array.isArray(updatedOrder.payments) ? updatedOrder.payments : [];
6314
+ const bodyPayStatus = rawBody && typeof rawBody === "object" && rawBody.paymentStatus != null ? String(rawBody.paymentStatus).toLowerCase() : null;
6315
+ const curPayStatus = bodyPayStatus || String(payments[0]?.status || "unpaid").toLowerCase();
6316
+ void import('./emit-order-notification-trigger-XVG2B5ZF.js').then(({ fireOrderNotificationTrigger }) => {
6317
+ if (newStatus === "pending") {
6318
+ if (curPayStatus === "failed") {
6319
+ fireOrderNotificationTrigger("payment_failed", updatedOrder.id, {
6320
+ dataSource,
6321
+ entityMap
6322
+ });
6323
+ } else {
6324
+ fireOrderNotificationTrigger("order_pending", updatedOrder.id, {
6325
+ dataSource,
6326
+ entityMap
6327
+ });
6328
+ }
6329
+ } else if (newStatus === "confirmed") {
6330
+ fireOrderNotificationTrigger("order_placed", updatedOrder.id, {
6331
+ dataSource,
6332
+ entityMap
6333
+ });
6334
+ if (curPayStatus === "paid" || curPayStatus === "captured") {
6335
+ fireOrderNotificationTrigger("payment_success", updatedOrder.id, {
6336
+ dataSource,
6337
+ entityMap
6338
+ });
6339
+ } else if (curPayStatus === "failed") {
6340
+ fireOrderNotificationTrigger("payment_failed", updatedOrder.id, {
6341
+ dataSource,
6342
+ entityMap
6343
+ });
6344
+ }
6345
+ } else if (newStatus === "processing") {
6346
+ fireOrderNotificationTrigger("order_processing", updatedOrder.id, {
6347
+ dataSource,
6348
+ entityMap
6349
+ });
6350
+ if (curPayStatus === "failed") {
6351
+ fireOrderNotificationTrigger("payment_failed", updatedOrder.id, {
6352
+ dataSource,
6353
+ entityMap
6354
+ });
6355
+ }
6356
+ } else if (newStatus === "completed") {
6357
+ fireOrderNotificationTrigger("order_completed", updatedOrder.id, {
6358
+ dataSource,
6359
+ entityMap
6360
+ });
6361
+ if (curPayStatus === "failed") {
6362
+ fireOrderNotificationTrigger("payment_failed", updatedOrder.id, {
6363
+ dataSource,
6364
+ entityMap
6365
+ });
6366
+ }
6367
+ } else if (newStatus === "cancelled") {
6368
+ if (curPayStatus === "failed") {
6369
+ fireOrderNotificationTrigger("payment_failed", updatedOrder.id, {
6370
+ dataSource,
6371
+ entityMap
6372
+ });
6373
+ } else {
6374
+ fireOrderNotificationTrigger("order_cancelled", updatedOrder.id, {
6375
+ dataSource,
6376
+ entityMap
6377
+ });
6378
+ if (curPayStatus === "paid" || curPayStatus === "refunded") {
6379
+ fireOrderNotificationTrigger("payment_refund_initiated", updatedOrder.id, {
6380
+ dataSource,
6381
+ entityMap
6382
+ });
6383
+ }
6384
+ }
6385
+ }
6386
+ }).catch(() => {
6387
+ });
6388
+ }
6141
6389
  return json(updatedOrder);
6142
6390
  }
6143
6391
  }
@@ -6614,7 +6862,37 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
6614
6862
  if (k in merged) updatePayload[k] = merged[k];
6615
6863
  }
6616
6864
  }
6617
- if (resource === "orders" && orderInvPrev) {
6865
+ if (resource === "orders" && orderInvPrev && rawBody && typeof rawBody === "object") {
6866
+ if ("assignedUserId" in rawBody && rawBody.assignedUserId !== void 0) {
6867
+ const aId = Number(rawBody.assignedUserId);
6868
+ if (Number.isFinite(aId) && aId > 0) {
6869
+ updatePayload.assignedUserId = aId;
6870
+ updatePayload.assignedAt = /* @__PURE__ */ new Date();
6871
+ if (!updatePayload.status && (orderInvPrev.status === "confirmed" || orderInvPrev.status === "pending")) {
6872
+ updatePayload.status = "processing";
6873
+ }
6874
+ } else {
6875
+ updatePayload.assignedUserId = null;
6876
+ updatePayload.assignedAt = null;
6877
+ }
6878
+ }
6879
+ if (updatePayload.status === "processing") {
6880
+ const effectiveAssignee = updatePayload.assignedUserId !== void 0 ? updatePayload.assignedUserId : orderInvPrev?.assignedUserId;
6881
+ if (!effectiveAssignee) {
6882
+ return json({
6883
+ error: "Cannot start processing without assigning a teammate. Please assign a teammate first."
6884
+ }, {
6885
+ status: 400
6886
+ });
6887
+ }
6888
+ }
6889
+ if (updatePayload.status === "completed" && orderInvPrev.status !== "completed" && !rawBody.__internalBypassOtp) {
6890
+ return json({
6891
+ error: "Direct completion is disabled. Please complete the order via the customer OTP verification flow."
6892
+ }, {
6893
+ status: 400
6894
+ });
6895
+ }
6618
6896
  const nextSt = typeof updatePayload.status === "string" && updatePayload.status ? String(updatePayload.status) : orderInvPrev.status;
6619
6897
  if (orderStatusHoldsStock(nextSt) && orderInvPrev.lines.length > 0) {
6620
6898
  const verr = await validateInventoryForOrderBecomingConfirmed(dataSource, entityMap, orderInvPrev, orderInvPrev.lines);
@@ -6679,24 +6957,43 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
6679
6957
  if (pOrder && Number.isFinite(pOrder)) {
6680
6958
  if (newPayStatus === "paid" || newPayStatus === "captured") {
6681
6959
  if (entityMap.orders) {
6682
- await dataSource.getRepository(entityMap.orders).update(pOrder, {
6683
- status: "confirmed"
6960
+ const ordRepo = dataSource.getRepository(entityMap.orders);
6961
+ const currentOrd = await ordRepo.findOne({
6962
+ where: {
6963
+ id: pOrder
6964
+ }
6684
6965
  });
6966
+ const ordStatus = String(currentOrd?.status || "pending").toLowerCase();
6967
+ if (ordStatus === "pending") {
6968
+ await ordRepo.update(pOrder, {
6969
+ status: "confirmed"
6970
+ });
6971
+ }
6972
+ if (ordStatus === "pending" || ordStatus === "confirmed") {
6973
+ void import('./emit-order-notification-trigger-XVG2B5ZF.js').then(({ fireOrderNotificationTrigger }) => {
6974
+ fireOrderNotificationTrigger("order_placed", pOrder, {
6975
+ dataSource,
6976
+ entityMap
6977
+ });
6978
+ fireOrderNotificationTrigger("payment_success", pOrder, {
6979
+ dataSource,
6980
+ entityMap
6981
+ });
6982
+ }).catch(() => {
6983
+ });
6984
+ }
6685
6985
  }
6686
- void import('./emit-order-notification-trigger-CZU3V2WE.js').then(({ fireOrderNotificationTrigger }) => {
6687
- fireOrderNotificationTrigger("order_placed", pOrder, {
6688
- dataSource,
6689
- entityMap
6690
- });
6691
- fireOrderNotificationTrigger("payment_success", pOrder, {
6986
+ } else if (newPayStatus === "failed") {
6987
+ void import('./emit-order-notification-trigger-XVG2B5ZF.js').then(({ fireOrderNotificationTrigger }) => {
6988
+ fireOrderNotificationTrigger("payment_failed", pOrder, {
6692
6989
  dataSource,
6693
6990
  entityMap
6694
6991
  });
6695
6992
  }).catch(() => {
6696
6993
  });
6697
- } else if (newPayStatus === "failed") {
6698
- void import('./emit-order-notification-trigger-CZU3V2WE.js').then(({ fireOrderNotificationTrigger }) => {
6699
- fireOrderNotificationTrigger("payment_failed", pOrder, {
6994
+ } else if (newPayStatus === "refunded") {
6995
+ void import('./emit-order-notification-trigger-XVG2B5ZF.js').then(({ fireOrderNotificationTrigger }) => {
6996
+ fireOrderNotificationTrigger("payment_refund_initiated", pOrder, {
6700
6997
  dataSource,
6701
6998
  entityMap
6702
6999
  });
@@ -6716,6 +7013,52 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
6716
7013
  throw err;
6717
7014
  }
6718
7015
  }
7016
+ if (resource === "orders" && rawBody && entityMap["payments"]) {
7017
+ try {
7018
+ const bodyPayStatusRaw = rawBody.paymentStatus;
7019
+ if (bodyPayStatusRaw != null && typeof bodyPayStatusRaw === "string") {
7020
+ const payStatus = bodyPayStatusRaw.trim().toLowerCase();
7021
+ const paymentRepo = dataSource.getRepository(entityMap["payments"]);
7022
+ const existingPay = await paymentRepo.findOne({
7023
+ where: {
7024
+ orderId: numericId
7025
+ },
7026
+ order: {
7027
+ id: "DESC"
7028
+ }
7029
+ });
7030
+ const isPaid = payStatus === "paid" || payStatus === "captured";
7031
+ if (existingPay) {
7032
+ await paymentRepo.update(existingPay.id, {
7033
+ status: payStatus,
7034
+ paidAt: isPaid && !existingPay.paidAt ? /* @__PURE__ */ new Date() : existingPay.paidAt
7035
+ });
7036
+ } else {
7037
+ const orderRow = await repo.findOne({
7038
+ where: {
7039
+ id: numericId
7040
+ }
7041
+ });
7042
+ const orderTotal = Number(orderRow?.total ?? 0);
7043
+ const orderCurrency = String(orderRow?.currency ?? "INR");
7044
+ const vId = Number(orderRow?.vendorId ?? 1);
7045
+ const cId = orderRow?.contactId ? Number(orderRow.contactId) : null;
7046
+ await paymentRepo.save(paymentRepo.create({
7047
+ vendorId: vId,
7048
+ contactId: cId,
7049
+ orderId: numericId,
7050
+ status: payStatus,
7051
+ amount: orderTotal,
7052
+ currency: orderCurrency,
7053
+ paidAt: isPaid ? /* @__PURE__ */ new Date() : null,
7054
+ method: "manual"
7055
+ }));
7056
+ }
7057
+ }
7058
+ } catch (payErr) {
7059
+ console.error("[crud] failed to update/create payment on order update", payErr);
7060
+ }
7061
+ }
6719
7062
  if (resource === "orders" && rawBody && entityMap["order_addresses"]) {
6720
7063
  const addressRawScalar = String(rawBody["contact.address"] ?? "").trim();
6721
7064
  if (addressRawScalar) {
@@ -6754,17 +7097,105 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
6754
7097
  }
6755
7098
  let updated = resource === "orders" ? await repo.findOne({
6756
7099
  where: {
6757
- id: numericId,
6758
- deleted: false
7100
+ id: numericId
6759
7101
  },
6760
7102
  relations: [
6761
- "items"
7103
+ "contact",
7104
+ "billingAddress",
7105
+ "shippingAddress",
7106
+ "items",
7107
+ "items.product",
7108
+ "items.product.collection",
7109
+ "payments"
6762
7110
  ]
6763
7111
  }) : await repo.findOne({
6764
7112
  where: {
6765
7113
  id: numericId
6766
7114
  }
6767
7115
  });
7116
+ if (resource === "orders" && updated) {
7117
+ const ord = updated;
7118
+ const statusUpdated = Boolean(updatePayload.status);
7119
+ const paymentUpdated = Boolean(rawBody && typeof rawBody === "object" && rawBody.paymentStatus != null);
7120
+ if (statusUpdated || paymentUpdated) {
7121
+ const newStatus = updatePayload.status ? String(updatePayload.status).toLowerCase() : String(ord.status || "pending").toLowerCase();
7122
+ const payments = Array.isArray(ord.payments) ? ord.payments : [];
7123
+ const bodyPayStatus = rawBody && typeof rawBody === "object" && rawBody.paymentStatus != null ? String(rawBody.paymentStatus).toLowerCase() : null;
7124
+ const curPayStatus = bodyPayStatus || String(payments[0]?.status || "unpaid").toLowerCase();
7125
+ void import('./emit-order-notification-trigger-XVG2B5ZF.js').then(({ fireOrderNotificationTrigger }) => {
7126
+ if (newStatus === "pending") {
7127
+ if (curPayStatus === "failed") {
7128
+ fireOrderNotificationTrigger("payment_failed", ord.id, {
7129
+ dataSource,
7130
+ entityMap
7131
+ });
7132
+ } else {
7133
+ fireOrderNotificationTrigger("order_pending", ord.id, {
7134
+ dataSource,
7135
+ entityMap
7136
+ });
7137
+ }
7138
+ } else if (newStatus === "confirmed") {
7139
+ fireOrderNotificationTrigger("order_placed", ord.id, {
7140
+ dataSource,
7141
+ entityMap
7142
+ });
7143
+ if (curPayStatus === "paid" || curPayStatus === "captured") {
7144
+ fireOrderNotificationTrigger("payment_success", ord.id, {
7145
+ dataSource,
7146
+ entityMap
7147
+ });
7148
+ } else if (curPayStatus === "failed") {
7149
+ fireOrderNotificationTrigger("payment_failed", ord.id, {
7150
+ dataSource,
7151
+ entityMap
7152
+ });
7153
+ }
7154
+ } else if (newStatus === "processing") {
7155
+ fireOrderNotificationTrigger("order_processing", ord.id, {
7156
+ dataSource,
7157
+ entityMap
7158
+ });
7159
+ if (curPayStatus === "failed") {
7160
+ fireOrderNotificationTrigger("payment_failed", ord.id, {
7161
+ dataSource,
7162
+ entityMap
7163
+ });
7164
+ }
7165
+ } else if (newStatus === "completed") {
7166
+ fireOrderNotificationTrigger("order_completed", ord.id, {
7167
+ dataSource,
7168
+ entityMap
7169
+ });
7170
+ if (curPayStatus === "failed") {
7171
+ fireOrderNotificationTrigger("payment_failed", ord.id, {
7172
+ dataSource,
7173
+ entityMap
7174
+ });
7175
+ }
7176
+ } else if (newStatus === "cancelled") {
7177
+ if (curPayStatus === "failed") {
7178
+ fireOrderNotificationTrigger("payment_failed", ord.id, {
7179
+ dataSource,
7180
+ entityMap
7181
+ });
7182
+ } else {
7183
+ fireOrderNotificationTrigger("order_cancelled", ord.id, {
7184
+ dataSource,
7185
+ entityMap
7186
+ });
7187
+ if (curPayStatus === "paid" || curPayStatus === "refunded") {
7188
+ fireOrderNotificationTrigger("payment_refund_initiated", ord.id, {
7189
+ dataSource,
7190
+ entityMap
7191
+ });
7192
+ }
7193
+ }
7194
+ }
7195
+ }).catch(() => {
7196
+ });
7197
+ }
7198
+ }
6768
7199
  if (resource === "orders" && orderInvPrev && updated) {
6769
7200
  const invErr = await reconcileOrderInventoryBetweenSnapshots(dataSource, entityMap, orderInvPrev, orderInventorySnapshotFromRow(updated));
6770
7201
  if (invErr) return json({
@@ -18246,6 +18677,9 @@ var Order = class {
18246
18677
  customerContact;
18247
18678
  billingAddress;
18248
18679
  shippingAddress;
18680
+ assignedUserId;
18681
+ assignedAt;
18682
+ assignedUser;
18249
18683
  items;
18250
18684
  payments;
18251
18685
  };
@@ -18458,6 +18892,29 @@ _ts_decorate21([
18458
18892
  }),
18459
18893
  _ts_metadata21("design:type", Object)
18460
18894
  ], Order.prototype, "shippingAddress", void 0);
18895
+ _ts_decorate21([
18896
+ Column("int", {
18897
+ nullable: true
18898
+ }),
18899
+ _ts_metadata21("design:type", Object)
18900
+ ], Order.prototype, "assignedUserId", void 0);
18901
+ _ts_decorate21([
18902
+ Column({
18903
+ type: "timestamp",
18904
+ nullable: true
18905
+ }),
18906
+ _ts_metadata21("design:type", Object)
18907
+ ], Order.prototype, "assignedAt", void 0);
18908
+ _ts_decorate21([
18909
+ ManyToOne(() => User, {
18910
+ nullable: true,
18911
+ onDelete: "SET NULL"
18912
+ }),
18913
+ JoinColumn({
18914
+ name: "assignedUserId"
18915
+ }),
18916
+ _ts_metadata21("design:type", Object)
18917
+ ], Order.prototype, "assignedUser", void 0);
18461
18918
  _ts_decorate21([
18462
18919
  OneToMany("OrderItem", "order"),
18463
18920
  _ts_metadata21("design:type", Array)
@@ -24489,6 +24946,7 @@ var NotificationChannel = /* @__PURE__ */ (function(NotificationChannel2) {
24489
24946
  NotificationChannel2["WHATSAPP"] = "whatsapp";
24490
24947
  NotificationChannel2["EMAIL"] = "email";
24491
24948
  NotificationChannel2["MOBILE"] = "mobile";
24949
+ NotificationChannel2["SMS"] = "sms";
24492
24950
  return NotificationChannel2;
24493
24951
  })({});
24494
24952
  var NotificationAudienceType = /* @__PURE__ */ (function(NotificationAudienceType2) {
@@ -28143,21 +28601,37 @@ function whatsappPlugin(config = {}) {
28143
28601
  async init(context) {
28144
28602
  const env = context.config;
28145
28603
  const { getWhatsAppSettings, getMessageTemplateRow, ...staticRest } = config;
28604
+ let settingsLoader = getWhatsAppSettings;
28605
+ if (!settingsLoader && context.dataSource) {
28606
+ settingsLoader = /* @__PURE__ */ __name(async () => {
28607
+ try {
28608
+ const ds = context.dataSource;
28609
+ const repo = ds.getRepository("configs");
28610
+ const rows = await repo.find({
28611
+ where: {
28612
+ settings: "whatsapp",
28613
+ deleted: false
28614
+ }
28615
+ });
28616
+ return Object.fromEntries(rows.map((r) => [
28617
+ r.key,
28618
+ r.value
28619
+ ]));
28620
+ } catch {
28621
+ return {};
28622
+ }
28623
+ }, "settingsLoader");
28624
+ }
28146
28625
  let db = {};
28147
28626
  try {
28148
- db = await getWhatsAppSettings?.() ?? {};
28627
+ db = await settingsLoader?.() ?? {};
28149
28628
  } catch {
28150
28629
  }
28151
28630
  if (!isWhatsAppPluginEnabled(db)) {
28152
28631
  context.logger.warn("WhatsApp plugin skipped: disabled in Plugins \u2192 WhatsApp");
28153
28632
  return null;
28154
28633
  }
28155
- const merged = mergeWhatsAppConfigLayers(env, db, staticRest);
28156
- if (!getWhatsAppSettings && !whatsAppConfigured(merged)) {
28157
- context.logger.warn("WhatsApp plugin skipped: set WHATSAPP_ACCESS_TOKEN and WHATSAPP_PHONE_NUMBER_ID, or pass getWhatsAppSettings");
28158
- return null;
28159
- }
28160
- const svc = new WhatsAppService(env, staticRest, getWhatsAppSettings, getMessageTemplateRow);
28634
+ const svc = new WhatsAppService(env, staticRest, settingsLoader, getMessageTemplateRow);
28161
28635
  return {
28162
28636
  send: /* @__PURE__ */ __name((opts) => svc.send(opts), "send")
28163
28637
  };
@@ -28531,7 +29005,7 @@ function createCmsApiHandler(config) {
28531
29005
  companyDetails
28532
29006
  };
28533
29007
  if (queue) {
28534
- const { queueEmail: queueEmail2 } = await import('./email-queue-OI2HSCGE.js');
29008
+ const { queueEmail: queueEmail2 } = await import('./email-queue-YPRSVG56.js');
28535
29009
  await queueEmail2(cms, {
28536
29010
  to: opts.to,
28537
29011
  templateName: "passwordReset",
@@ -29831,7 +30305,7 @@ function createCmsApiHandler(config) {
29831
30305
  const pe = await requireEntityPermissionEffective(req, "orders", "read");
29832
30306
  if (pe) return pe;
29833
30307
  const cms = await getCms();
29834
- const { streamOrderInvoicePdf: streamOrderInvoicePdf2 } = await import('./erp-order-invoice-3GXDE443.js');
30308
+ const { streamOrderInvoicePdf: streamOrderInvoicePdf2 } = await import('./erp-order-invoice-3UGWLICU.js');
29835
30309
  const oid = Number(path2[1]);
29836
30310
  if (!Number.isFinite(oid)) return config.json({
29837
30311
  error: "Invalid id"
@@ -29980,6 +30454,11 @@ function createCmsApiHandler(config) {
29980
30454
  });
29981
30455
  }
29982
30456
  }
30457
+ if (path2[0] === "sms-notification-templates" && path2.length === 1 && m === "GET") {
30458
+ const { createSmsNotificationTemplatesHandlers } = await import('./sms-notification-templates-handlers-SJLO7JGZ.js');
30459
+ const handlers = createSmsNotificationTemplatesHandlers(dataSource, entityMap);
30460
+ return handlers.GET(req);
30461
+ }
29983
30462
  if (path2[0] === "orders" && path2[1] === "calculate" && path2.length === 2 && m === "POST") {
29984
30463
  const a = await config.requireAuth(req);
29985
30464
  if (a) return a;
@@ -30208,7 +30687,7 @@ function createCmsApiHandler(config) {
30208
30687
  status: 400
30209
30688
  });
30210
30689
  }
30211
- const { resendOrderNotification } = await import('./order-notification-dispatcher-ZSFKEYMP.js');
30690
+ const { resendOrderNotification } = await import('./order-notification-dispatcher-JKFQJYGG.js');
30212
30691
  const result = await resendOrderNotification(triggerKey, orderId, {
30213
30692
  dataSource,
30214
30693
  entityMap,
@@ -30307,25 +30786,20 @@ function createCmsApiHandler(config) {
30307
30786
  status: "cancelled"
30308
30787
  });
30309
30788
  const fireOrderCancelledNotification = /* @__PURE__ */ __name((refundAmount) => {
30310
- void import('./emit-order-notification-trigger-CZU3V2WE.js').then(({ fireOrderNotificationTrigger }) => {
30789
+ void import('./emit-order-notification-trigger-XVG2B5ZF.js').then(({ fireOrderNotificationTrigger }) => {
30311
30790
  fireOrderNotificationTrigger("order_cancelled", orderId, {
30312
30791
  dataSource,
30313
30792
  entityMap
30314
30793
  }, refundAmount != null && refundAmount > 0 ? {
30315
30794
  refundAmount
30316
30795
  } : void 0);
30317
- if (paymentStatus === "paid" || paymentStatus === "captured") {
30796
+ if (paymentStatus === "paid" || paymentStatus === "captured" || paymentStatus === "refunded") {
30318
30797
  fireOrderNotificationTrigger("payment_refund_initiated", orderId, {
30319
30798
  dataSource,
30320
30799
  entityMap
30321
30800
  }, refundAmount != null && refundAmount > 0 ? {
30322
30801
  refundAmount
30323
30802
  } : void 0);
30324
- } else {
30325
- fireOrderNotificationTrigger("payment_failed", orderId, {
30326
- dataSource,
30327
- entityMap
30328
- });
30329
30803
  }
30330
30804
  });
30331
30805
  }, "fireOrderCancelledNotification");
@@ -30546,6 +31020,66 @@ function createCmsApiHandler(config) {
30546
31020
  finalRefund: 0
30547
31021
  });
30548
31022
  }
31023
+ if (path2[0] === "orders" && path2.length === 4 && path2[2] === "completion-otp" && path2[3] === "channels" && m === "GET" && getCms) {
31024
+ const a = await config.requireAuth(req);
31025
+ if (a) return a;
31026
+ const pe = await requireEntityPermissionEffective(req, "orders", "read");
31027
+ if (pe) return pe;
31028
+ const orderId = Number(path2[1]);
31029
+ if (!Number.isFinite(orderId)) return config.json({
31030
+ error: "Invalid order ID"
31031
+ }, {
31032
+ status: 400
31033
+ });
31034
+ const { createOrderCompletionOtpHandlers } = await import('./order-completion-otp-handlers-WGM7HWG4.js');
31035
+ const handlers = createOrderCompletionOtpHandlers(dataSource, entityMap, getCms);
31036
+ return handlers.getChannels(req, orderId);
31037
+ }
31038
+ if (path2[0] === "orders" && path2.length === 4 && path2[2] === "completion-otp" && path2[3] === "send" && m === "POST" && getCms) {
31039
+ const a = await config.requireAuth(req);
31040
+ if (a) return a;
31041
+ const pe = await requireEntityPermissionEffective(req, "orders", "update");
31042
+ if (pe) return pe;
31043
+ const orderId = Number(path2[1]);
31044
+ if (!Number.isFinite(orderId)) return config.json({
31045
+ error: "Invalid order ID"
31046
+ }, {
31047
+ status: 400
31048
+ });
31049
+ const { createOrderCompletionOtpHandlers } = await import('./order-completion-otp-handlers-WGM7HWG4.js');
31050
+ const handlers = createOrderCompletionOtpHandlers(dataSource, entityMap, getCms);
31051
+ return handlers.sendOtp(req, orderId);
31052
+ }
31053
+ if (path2[0] === "orders" && path2.length === 4 && path2[2] === "completion-otp" && path2[3] === "verify" && m === "POST" && getCms) {
31054
+ const a = await config.requireAuth(req);
31055
+ if (a) return a;
31056
+ const pe = await requireEntityPermissionEffective(req, "orders", "update");
31057
+ if (pe) return pe;
31058
+ const orderId = Number(path2[1]);
31059
+ if (!Number.isFinite(orderId)) return config.json({
31060
+ error: "Invalid order ID"
31061
+ }, {
31062
+ status: 400
31063
+ });
31064
+ const { createOrderCompletionOtpHandlers } = await import('./order-completion-otp-handlers-WGM7HWG4.js');
31065
+ const handlers = createOrderCompletionOtpHandlers(dataSource, entityMap, getCms);
31066
+ return handlers.verifyOtp(req, orderId);
31067
+ }
31068
+ if (path2[0] === "orders" && path2.length === 3 && path2[2] === "eligible-assignees" && m === "GET") {
31069
+ const a = await config.requireAuth(req);
31070
+ if (a) return a;
31071
+ const pe = await requireEntityPermissionEffective(req, "orders", "read");
31072
+ if (pe) return pe;
31073
+ const orderId = Number(path2[1]);
31074
+ if (!Number.isFinite(orderId)) return config.json({
31075
+ error: "Invalid order ID"
31076
+ }, {
31077
+ status: 400
31078
+ });
31079
+ const { createOrderAssigneesHandlers } = await import('./order-assignees-handlers-LKMAGLG6.js');
31080
+ const handlers = createOrderAssigneesHandlers(dataSource, entityMap, getHydratedSessionUser);
31081
+ return handlers.listEligibleAssignees(req, orderId);
31082
+ }
30549
31083
  if (path2[0] === "refund-policies") {
30550
31084
  if (path2.length === 1) {
30551
31085
  if (m === "GET") {
@@ -31062,63 +31596,6 @@ async function tryRefreshOrderFromErpForStorefront(cms, dataSource, entityMap, o
31062
31596
  }
31063
31597
  __name(tryRefreshOrderFromErpForStorefront, "tryRefreshOrderFromErpForStorefront");
31064
31598
 
31065
- // src/plugins/sms/sms-queue.ts
31066
- var SMS_QUEUE_NAME = "sms";
31067
- function registerSmsQueueProcessor(cms) {
31068
- const queue = cms.getPlugin("queue");
31069
- const sms = cms.getPlugin("sms");
31070
- if (!queue || !sms || typeof sms.send !== "function") return;
31071
- queue.registerProcessor(SMS_QUEUE_NAME, async (data) => {
31072
- const payload = data;
31073
- if (!payload.to) return;
31074
- if (payload.templateKey?.trim()) {
31075
- await sms.send({
31076
- to: payload.to,
31077
- templateKey: payload.templateKey.trim(),
31078
- variables: payload.variables,
31079
- otpCode: payload.otpCode
31080
- });
31081
- return;
31082
- }
31083
- if (!payload.body?.trim()) return;
31084
- await sms.send({
31085
- to: payload.to,
31086
- body: payload.body,
31087
- otpCode: payload.otpCode,
31088
- variables: payload.variables
31089
- });
31090
- });
31091
- }
31092
- __name(registerSmsQueueProcessor, "registerSmsQueueProcessor");
31093
- async function queueSms(cms, payload) {
31094
- const queue = cms.getPlugin("queue");
31095
- const sms = cms.getPlugin("sms");
31096
- if (queue) {
31097
- await queue.add(SMS_QUEUE_NAME, payload);
31098
- return;
31099
- }
31100
- if (sms && typeof sms.send === "function") {
31101
- if (payload.templateKey?.trim()) {
31102
- await sms.send({
31103
- to: payload.to,
31104
- templateKey: payload.templateKey.trim(),
31105
- variables: payload.variables,
31106
- otpCode: payload.otpCode
31107
- });
31108
- return;
31109
- }
31110
- if (payload.body?.trim()) {
31111
- await sms.send({
31112
- to: payload.to,
31113
- body: payload.body,
31114
- otpCode: payload.otpCode,
31115
- variables: payload.variables
31116
- });
31117
- }
31118
- }
31119
- }
31120
- __name(queueSms, "queueSms");
31121
-
31122
31599
  // src/lib/storefront-product-pricing.ts
31123
31600
  function eventPricingFromRow(row) {
31124
31601
  const defaultCurrency = normalizeCurrencyCode(String(row?.defaultCurrency ?? "INR")) || "INR";
@@ -31187,143 +31664,6 @@ async function buildPricesForSupportedCurrencies(dataSource, entityMap, basePric
31187
31664
  return rows;
31188
31665
  }
31189
31666
  __name(buildPricesForSupportedCurrencies, "buildPricesForSupportedCurrencies");
31190
- var OTP_TTL_MS = 10 * 60 * 1e3;
31191
- var MAX_SENDS_PER_HOUR = 5;
31192
- var MAX_VERIFY_ATTEMPTS = 8;
31193
- function getPepper(explicit) {
31194
- return (explicit || process.env.OTP_PEPPER || process.env.NEXTAUTH_SECRET || "dev-otp-pepper").trim();
31195
- }
31196
- __name(getPepper, "getPepper");
31197
- function hashOtpCode(code, purpose, identifier, pepper) {
31198
- return createHmac("sha256", getPepper(pepper)).update(`${purpose}|${identifier}|${code}`).digest("hex");
31199
- }
31200
- __name(hashOtpCode, "hashOtpCode");
31201
- function verifyOtpCodeHash(code, storedHash, purpose, identifier, pepper) {
31202
- const h = hashOtpCode(code, purpose, identifier, pepper);
31203
- try {
31204
- return timingSafeEqual(Buffer.from(h, "utf8"), Buffer.from(storedHash, "utf8"));
31205
- } catch {
31206
- return false;
31207
- }
31208
- }
31209
- __name(verifyOtpCodeHash, "verifyOtpCodeHash");
31210
- function generateNumericOtp(length = 6) {
31211
- const max = 10 ** length;
31212
- return randomInt(0, max).toString().padStart(length, "0");
31213
- }
31214
- __name(generateNumericOtp, "generateNumericOtp");
31215
- function normalizePhoneE164(raw, defaultCountryCode) {
31216
- const t = raw.trim();
31217
- const digitsOnly = t.replace(/\D/g, "");
31218
- if (digitsOnly.length < 10) return null;
31219
- if (t.startsWith("+")) return `+${digitsOnly}`;
31220
- const cc = (defaultCountryCode || process.env.DEFAULT_PHONE_COUNTRY_CODE || "91").replace(/\D/g, "");
31221
- if (digitsOnly.length > 10) return `+${digitsOnly}`;
31222
- return `+${cc}${digitsOnly}`;
31223
- }
31224
- __name(normalizePhoneE164, "normalizePhoneE164");
31225
- async function countRecentOtpSends(dataSource, entityMap, purpose, identifier, since) {
31226
- const repo = dataSource.getRepository(entityMap.otp_challenges);
31227
- return repo.count({
31228
- where: {
31229
- purpose,
31230
- identifier,
31231
- createdAt: MoreThan(since)
31232
- }
31233
- });
31234
- }
31235
- __name(countRecentOtpSends, "countRecentOtpSends");
31236
- async function createOtpChallenge(dataSource, entityMap, input) {
31237
- const { purpose, channel, identifier, code, pepper } = input;
31238
- const since = new Date(Date.now() - 60 * 60 * 1e3);
31239
- const recent = await countRecentOtpSends(dataSource, entityMap, purpose, identifier, since);
31240
- if (recent >= MAX_SENDS_PER_HOUR) {
31241
- return {
31242
- ok: false,
31243
- error: "Too many codes sent. Try again later.",
31244
- status: 429
31245
- };
31246
- }
31247
- const repo = dataSource.getRepository(entityMap.otp_challenges);
31248
- await repo.delete({
31249
- purpose,
31250
- identifier,
31251
- consumedAt: IsNull()
31252
- });
31253
- const expiresAt = new Date(Date.now() + OTP_TTL_MS);
31254
- const codeHash = hashOtpCode(code, purpose, identifier, pepper);
31255
- await repo.save(repo.create({
31256
- purpose,
31257
- channel,
31258
- identifier,
31259
- codeHash,
31260
- expiresAt,
31261
- attempts: 0,
31262
- consumedAt: null
31263
- }));
31264
- return {
31265
- ok: true
31266
- };
31267
- }
31268
- __name(createOtpChallenge, "createOtpChallenge");
31269
- async function verifyAndConsumeOtpChallenge(dataSource, entityMap, input) {
31270
- const { purpose, identifier, code, pepper } = input;
31271
- const repo = dataSource.getRepository(entityMap.otp_challenges);
31272
- const row = await repo.findOne({
31273
- where: {
31274
- purpose,
31275
- identifier,
31276
- consumedAt: IsNull()
31277
- },
31278
- order: {
31279
- id: "DESC"
31280
- }
31281
- });
31282
- if (!row) {
31283
- return {
31284
- ok: false,
31285
- error: "Invalid or expired code",
31286
- status: 400
31287
- };
31288
- }
31289
- const r = row;
31290
- if (new Date(r.expiresAt) < /* @__PURE__ */ new Date()) {
31291
- await repo.delete(row.id);
31292
- return {
31293
- ok: false,
31294
- error: "Invalid or expired code",
31295
- status: 400
31296
- };
31297
- }
31298
- const attempts = r.attempts || 0;
31299
- if (attempts >= MAX_VERIFY_ATTEMPTS) {
31300
- await repo.delete(row.id);
31301
- return {
31302
- ok: false,
31303
- error: "Too many attempts",
31304
- status: 400
31305
- };
31306
- }
31307
- const valid = verifyOtpCodeHash(code, r.codeHash, purpose, identifier, pepper);
31308
- if (!valid) {
31309
- await repo.update(row.id, {
31310
- attempts: attempts + 1
31311
- });
31312
- return {
31313
- ok: false,
31314
- error: "Invalid or expired code",
31315
- status: 400
31316
- };
31317
- }
31318
- await repo.update(row.id, {
31319
- consumedAt: /* @__PURE__ */ new Date(),
31320
- attempts: attempts + 1
31321
- });
31322
- return {
31323
- ok: true
31324
- };
31325
- }
31326
- __name(verifyAndConsumeOtpChallenge, "verifyAndConsumeOtpChallenge");
31327
31667
 
31328
31668
  // src/api/storefront-handlers.ts
31329
31669
  var GUEST_COOKIE = "guest_id";
@@ -31353,7 +31693,7 @@ function createStorefrontApiHandler(config) {
31353
31693
  const otpPepper = config.otpPepper;
31354
31694
  const defaultPhoneCc = config.defaultPhoneCountryCode;
31355
31695
  function fireOrderPlacedNotification(orderId, isPaid) {
31356
- void import('./emit-order-notification-trigger-CZU3V2WE.js').then(({ fireOrderNotificationTrigger }) => {
31696
+ void import('./emit-order-notification-trigger-XVG2B5ZF.js').then(({ fireOrderNotificationTrigger }) => {
31357
31697
  fireOrderNotificationTrigger("order_placed", orderId, {
31358
31698
  dataSource,
31359
31699
  entityMap
@@ -31424,9 +31764,21 @@ function createStorefrontApiHandler(config) {
31424
31764
  },
31425
31765
  select: [
31426
31766
  "id",
31427
- "vendorId"
31767
+ "vendorId",
31768
+ "eventId"
31428
31769
  ]
31429
31770
  });
31771
+ const comboEventId = Number(combo?.eventId);
31772
+ if (Number.isInteger(comboEventId) && comboEventId > 0 && entityMap.events) {
31773
+ const evRows = await dataSource.query(`SELECT "vendorId" FROM events WHERE id = $1 AND deleted = false LIMIT 1`, [
31774
+ comboEventId
31775
+ ]);
31776
+ const evVid = Number(evRows[0]?.vendorId);
31777
+ if (Number.isInteger(evVid) && evVid > 0) {
31778
+ comboVendorCache.set(comboId, evVid);
31779
+ return evVid;
31780
+ }
31781
+ }
31430
31782
  const vid = Number(combo?.vendorId);
31431
31783
  if (Number.isInteger(vid) && vid > 0) {
31432
31784
  comboVendorCache.set(comboId, vid);
@@ -31446,9 +31798,30 @@ function createStorefrontApiHandler(config) {
31446
31798
  }
31447
31799
  const p = it.product;
31448
31800
  if (!p || p.deleted || p.status !== "available") continue;
31449
- const vid = Number(p.vendorId);
31801
+ let vid = Number(p.vendorId);
31802
+ if (!Number.isInteger(vid) || vid <= 0) {
31803
+ const prodId = Number(p.id);
31804
+ if (Number.isInteger(prodId) && prodId > 0 && entityMap.event_products) {
31805
+ const epRows = await dataSource.query(`SELECT e."vendorId" FROM event_products ep
31806
+ JOIN events e ON e.id = ep."eventId"
31807
+ WHERE ep."productId" = $1 AND e.deleted = false LIMIT 1`, [
31808
+ prodId
31809
+ ]);
31810
+ const evVid = Number(epRows[0]?.vendorId);
31811
+ if (Number.isInteger(evVid) && evVid > 0) vid = evVid;
31812
+ }
31813
+ }
31450
31814
  if (Number.isInteger(vid) && vid > 0) vendorIds.add(vid);
31451
31815
  }
31816
+ if (vendorIds.size > 1) {
31817
+ const nonDefault = [
31818
+ ...vendorIds
31819
+ ].filter((id) => id !== 1);
31820
+ if (nonDefault.length === 1) {
31821
+ vendorIds.clear();
31822
+ vendorIds.add(nonDefault[0]);
31823
+ }
31824
+ }
31452
31825
  if (vendorIds.size === 0) return {
31453
31826
  error: "Cart has no valid products",
31454
31827
  status: 400
@@ -34257,7 +34630,7 @@ function createStorefrontApiHandler(config) {
34257
34630
  } catch {
34258
34631
  }
34259
34632
  try {
34260
- void import('./emit-order-notification-trigger-CZU3V2WE.js').then(({ fireOrderNotificationTrigger }) => {
34633
+ void import('./emit-order-notification-trigger-XVG2B5ZF.js').then(({ fireOrderNotificationTrigger }) => {
34261
34634
  fireOrderNotificationTrigger("order_cancelled", orderId, {
34262
34635
  dataSource,
34263
34636
  entityMap
@@ -34294,4 +34667,4 @@ function createStorefrontApiHandler(config) {
34294
34667
  }
34295
34668
  __name(createStorefrontApiHandler, "createStorefrontApiHandler");
34296
34669
 
34297
- export { Address, Attendee, Attribute, BLOG_GENERATOR_AGENT_NAME, BLOG_GENERATOR_DEFAULT_SYSTEM_INSTRUCTION, BLOG_GENERATOR_DEFAULT_VALIDATION_RULES, BLOG_GENERATOR_LLM_AGENT_SLUG, BLOG_GENERATOR_MARKDOWN_ARTICLE_SEPARATOR, BLOG_METADATA_ENRICHER_AGENT_NAME, BLOG_METADATA_ENRICHER_DEFAULT_SYSTEM_INSTRUCTION, BLOG_METADATA_ENRICHER_DEFAULT_VALIDATION_RULES, BLOG_METADATA_ENRICHER_LLM_AGENT_SLUG, Blog, BlogGeneratorService, Brand, CMS_ENTITY_MAP, Cart, CartItem, Category, ChatConversation, ChatMessage, Collection, Combo, ComboItem, Comment, Config, Contact, Currency, CurrencyExchange, Customer, Customer_Contacts, Discount, DiscountRules, Event, EventProduct, Form, FormField, FormSubmission, JobSchedule, JobScheduleRun, KnowledgeBaseChunk, KnowledgeBaseDocument, LlmAgent, LlmAgentKnowledgeDocument, Media, MessageTemplate, Order, OrderAddresses, OrderDiscounts, OrderItem, OrderNotificationBinding, OrderNotificationTrigger, OtpChallenge, Page, PasswordResetToken, Payment, Permission, Product, ProductAttribute, ProductCategory, ProductConfig, ProductVariant, RefundPolicy, RefundRequest, RssArticle, RssFeed, Seo, Tag, Tax, User, UserDeviceToken, UserGroup, Vendor, VendorCustomer, VendorRole, VendorRolePermission, VendorUser, VendorUserProfile, Wishlist, WishlistItem, ZIP_MIME_TYPES, applyApprovalStatusSideEffects, applyEventApprovalStatusSideEffects, applyRotatingVendorInvite, applyVendorCustomersContactFilter, applyVendorEventCreateApproval, applyVendorProductCreateApproval, assertCaptchaOk, assertContactAllowedForVendorOrder, assertEventApprovalUpdate, assertProductApprovalUpdate, autoExpireOrderIfPaymentTimeExceeded, buildBlogMetadataUserPrompt, buildCronFromSchedule, buildRssUserPromptFromFeeds, buildUserInviteLink, buildVendorInviteLink, calculateOrderRefundPreview, calculateRefundFromPolicy, checkAndIncrementDiscountUsage, checkEventsEnabled, checkMultiVendorEnabled, completeUserInviteAccept, consumeAppliedDiscountUsages, contactIsVendorCustomer, countDiscountOrdersForContact, countRecentOtpSends, createAnalyticsHandlers, createBlogBySlugHandler, createChangePasswordHandler, createCmsApiHandler, createCmsApp, createCmsAppWithMessaging, createCrudByIdHandler, createCrudHandler, createDashboardStatsHandler, createEcommerceAnalyticsHandler, createEventOrderMessageTemplateHandlers, createForgotPasswordHandler, createFormBySlugHandler, createInviteAcceptHandler, createJobScheduleHandlers, createLlmAgentKnowledgeHandlers, createMediaZipExtractHandler, createMessageTemplateRowLoader, createOtpChallenge, createSetPasswordHandler, createSettingsApiHandlers, createSocialMediaHandlers, createStorefrontApiHandler, createUploadHandler, createUserAuthApiRouter, createUserAvatarHandler, createUserProfileHandler, createUsersApiHandlers, createVendorDashboardHandler, createVendorOnboardHandlers, daysBeforeEventStart, decrementDiscountUsage, describeEventTierPolicy, ensureMessagingPluginsOnCms, ensureScheduleQueueWorker, ensureVendorCustomerForOrderContact, ensureVendorCustomersForOrder, findActiveRefundPolicyForVendor, findUserByInviteToken, findVendorByInviteToken, formatTierRange, generateNumericOtp, getPublicSettingsGroup, getRequireEventApproval, getRequireProductApproval, getRssArticleSummaryFromItem, getVendorCatalogCreateFlags, hashOtpCode, hydrateVendorSessionUser, invalidateEventsCache, invalidateMultiVendorCache, invalidateRequireEventApprovalCache, invalidateRequireProductApprovalCache, invalidateVendorCatalogCreateFlagsCache, isCustomerTypeContact, isMaxPerUserUsageReached, isMaxTotalUsageReached, isZipMedia, llmAgentToChatAgentOptions, loadSettingsGroupFromDb, loadUserVendorContext, mergeGuardrailsIntoSystemPrompt, messagingPlugins, metaFetchUserManagedPages, metaPostPageFeed, metaPostPagePhoto, metaResolvePageAccessToken, newUserInviteToken, normalizePhoneE164, normalizeRefundTiers, overlayCmsPlugins, parseBlogGeneratorAgentContent, parseBlogGeneratorModelOutput, parseBlogMetadataEnrichmentJson, parseLlmAgentValidationRules, pgBossScheduleNameForId, queueErpCreateContactIfEnabled, queueJobScheduleNow, queuePlugin, queueSms, recordDiscountUsage, registerJobRunnerWorker, registerMessagingQueueProcessors, registerSmsQueueProcessor, relativePathFromMediaParentId, resolveBlogCategoryIdByName, resolveSettingsEncryptionKey, resolveVendorIdForContactCheck, sanitizeMediaFolderPath, sanitizeStorageSegment, sendVendorOnboardEmails, simpleDecrypt, simpleEncrypt, syncJobScheduleToPgBoss, validateRefundTiers, validateScheduleInput, validateUserMessageAgainstAgentRules, validateUserMessageAgainstStructuredRules, verifyAndConsumeOtpChallenge, verifyOtpCodeHash, whatsappPlugin, wrapGetCmsWithMessaging };
34670
+ export { Address, Attendee, Attribute, BLOG_GENERATOR_AGENT_NAME, BLOG_GENERATOR_DEFAULT_SYSTEM_INSTRUCTION, BLOG_GENERATOR_DEFAULT_VALIDATION_RULES, BLOG_GENERATOR_LLM_AGENT_SLUG, BLOG_GENERATOR_MARKDOWN_ARTICLE_SEPARATOR, BLOG_METADATA_ENRICHER_AGENT_NAME, BLOG_METADATA_ENRICHER_DEFAULT_SYSTEM_INSTRUCTION, BLOG_METADATA_ENRICHER_DEFAULT_VALIDATION_RULES, BLOG_METADATA_ENRICHER_LLM_AGENT_SLUG, Blog, BlogGeneratorService, Brand, CMS_ENTITY_MAP, Cart, CartItem, Category, ChatConversation, ChatMessage, Collection, Combo, ComboItem, Comment, Config, Contact, Currency, CurrencyExchange, Customer, Customer_Contacts, Discount, DiscountRules, Event, EventProduct, Form, FormField, FormSubmission, JobSchedule, JobScheduleRun, KnowledgeBaseChunk, KnowledgeBaseDocument, LlmAgent, LlmAgentKnowledgeDocument, Media, MessageTemplate, Order, OrderAddresses, OrderDiscounts, OrderItem, OrderNotificationBinding, OrderNotificationTrigger, OtpChallenge, Page, PasswordResetToken, Payment, Permission, Product, ProductAttribute, ProductCategory, ProductConfig, ProductVariant, RefundPolicy, RefundRequest, RssArticle, RssFeed, Seo, Tag, Tax, User, UserDeviceToken, UserGroup, Vendor, VendorCustomer, VendorRole, VendorRolePermission, VendorUser, VendorUserProfile, Wishlist, WishlistItem, ZIP_MIME_TYPES, applyApprovalStatusSideEffects, applyEventApprovalStatusSideEffects, applyRotatingVendorInvite, applyVendorCustomersContactFilter, applyVendorEventCreateApproval, applyVendorProductCreateApproval, assertCaptchaOk, assertContactAllowedForVendorOrder, assertEventApprovalUpdate, assertProductApprovalUpdate, autoExpireOrderIfPaymentTimeExceeded, buildBlogMetadataUserPrompt, buildCronFromSchedule, buildRssUserPromptFromFeeds, buildUserInviteLink, buildVendorInviteLink, calculateOrderRefundPreview, calculateRefundFromPolicy, checkAndIncrementDiscountUsage, checkEventsEnabled, checkMultiVendorEnabled, completeUserInviteAccept, consumeAppliedDiscountUsages, contactIsVendorCustomer, countDiscountOrdersForContact, createAnalyticsHandlers, createBlogBySlugHandler, createChangePasswordHandler, createCmsApiHandler, createCmsApp, createCmsAppWithMessaging, createCrudByIdHandler, createCrudHandler, createDashboardStatsHandler, createEcommerceAnalyticsHandler, createEventOrderMessageTemplateHandlers, createForgotPasswordHandler, createFormBySlugHandler, createInviteAcceptHandler, createJobScheduleHandlers, createLlmAgentKnowledgeHandlers, createMediaZipExtractHandler, createMessageTemplateRowLoader, createSetPasswordHandler, createSettingsApiHandlers, createSocialMediaHandlers, createStorefrontApiHandler, createUploadHandler, createUserAuthApiRouter, createUserAvatarHandler, createUserProfileHandler, createUsersApiHandlers, createVendorDashboardHandler, createVendorOnboardHandlers, daysBeforeEventStart, decrementDiscountUsage, describeEventTierPolicy, ensureMessagingPluginsOnCms, ensureScheduleQueueWorker, ensureVendorCustomerForOrderContact, ensureVendorCustomersForOrder, findActiveRefundPolicyForVendor, findUserByInviteToken, findVendorByInviteToken, formatTierRange, getPublicSettingsGroup, getRequireEventApproval, getRequireProductApproval, getRssArticleSummaryFromItem, getVendorCatalogCreateFlags, hydrateVendorSessionUser, invalidateEventsCache, invalidateMultiVendorCache, invalidateRequireEventApprovalCache, invalidateRequireProductApprovalCache, invalidateVendorCatalogCreateFlagsCache, isCustomerTypeContact, isMaxPerUserUsageReached, isMaxTotalUsageReached, isZipMedia, llmAgentToChatAgentOptions, loadSettingsGroupFromDb, loadUserVendorContext, mergeGuardrailsIntoSystemPrompt, messagingPlugins, metaFetchUserManagedPages, metaPostPageFeed, metaPostPagePhoto, metaResolvePageAccessToken, newUserInviteToken, normalizeRefundTiers, overlayCmsPlugins, parseBlogGeneratorAgentContent, parseBlogGeneratorModelOutput, parseBlogMetadataEnrichmentJson, parseLlmAgentValidationRules, pgBossScheduleNameForId, queueErpCreateContactIfEnabled, queueJobScheduleNow, queuePlugin, recordDiscountUsage, registerJobRunnerWorker, registerMessagingQueueProcessors, relativePathFromMediaParentId, resolveBlogCategoryIdByName, resolveSettingsEncryptionKey, resolveVendorIdForContactCheck, sanitizeMediaFolderPath, sanitizeStorageSegment, sendVendorOnboardEmails, simpleDecrypt, simpleEncrypt, syncJobScheduleToPgBoss, validateRefundTiers, validateScheduleInput, validateUserMessageAgainstAgentRules, validateUserMessageAgainstStructuredRules, whatsappPlugin, wrapGetCmsWithMessaging };