@infuro/cms-core 1.0.66 → 1.0.68

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 (57) hide show
  1. package/dist/admin.cjs +214 -32
  2. package/dist/admin.js +214 -32
  3. package/dist/api.cjs +45 -42
  4. package/dist/api.js +12 -9
  5. package/dist/auth.cjs +51 -51
  6. package/dist/auth.js +3 -3
  7. package/dist/{chunk-QYRXLURF.cjs → chunk-22XKONB5.cjs} +640 -145
  8. package/dist/{chunk-MVHDC3XF.js → chunk-5NOZSG6J.js} +22 -11
  9. package/dist/{chunk-TU23GJPJ.js → chunk-7JCCPQEF.js} +1 -1
  10. package/dist/{chunk-WMMZZRDJ.cjs → chunk-GN4LKG4V.cjs} +1 -1
  11. package/dist/{chunk-KM2I6AFP.cjs → chunk-HBUV73RB.cjs} +9 -9
  12. package/dist/chunk-IKTBZJHT.js +16 -0
  13. package/dist/chunk-M5GPOPGX.cjs +49 -0
  14. package/dist/{chunk-T33KU5G5.js → chunk-MYUGQHU4.js} +548 -53
  15. package/dist/{chunk-NV5IRHI3.js → chunk-N4LBZXBG.js} +2 -2
  16. package/dist/{chunk-J7FMZK66.cjs → chunk-O4AFPDQ4.cjs} +22 -11
  17. package/dist/{chunk-4U6DATGZ.cjs → chunk-OV5TRZET.cjs} +7 -7
  18. package/dist/chunk-P6S4XFZO.cjs +18 -0
  19. package/dist/{chunk-RCE5SJBA.js → chunk-SKJH7PX4.js} +1 -1
  20. package/dist/{chunk-5MZFQRDW.cjs → chunk-SMHQV3WL.cjs} +4 -4
  21. package/dist/chunk-SUUD7OUG.cjs +455 -0
  22. package/dist/{chunk-XFDIIVZB.cjs → chunk-UMC7W5G3.cjs} +3 -3
  23. package/dist/chunk-WKDBMDUX.js +45 -0
  24. package/dist/{chunk-6DBDJ4VD.js → chunk-Z5G54EGD.js} +2 -2
  25. package/dist/chunk-Z5OB5QGN.js +465 -0
  26. package/dist/chunk-ZIT4IP6N.js +445 -0
  27. package/dist/chunk-ZX5U3VCB.cjs +471 -0
  28. package/dist/{chunk-NR44CK5E.js → chunk-ZY64VJMS.js} +1 -1
  29. package/dist/email-queue-3QBQ63F7.js +8 -0
  30. package/dist/{email-queue-4OY45JIU.cjs → email-queue-K4E4OFI7.cjs} +9 -6
  31. package/dist/{emit-order-notification-trigger-ZD5YN3JM.cjs → emit-order-notification-trigger-ROASTYQP.cjs} +3 -3
  32. package/dist/{emit-order-notification-trigger-EJJZ6XTS.js → emit-order-notification-trigger-YUQTPELC.js} +1 -1
  33. package/dist/{erp-order-invoice-YUSPZ7CE.cjs → erp-order-invoice-AZ5MX2JB.cjs} +8 -5
  34. package/dist/{erp-order-invoice-H6HCJ7YS.js → erp-order-invoice-XSYHAMBS.js} +4 -1
  35. package/dist/generate-local-invoice-pdf-BQTCL5MW.cjs +12 -0
  36. package/dist/generate-local-invoice-pdf-OCFG47SE.js +3 -0
  37. package/dist/index.cjs +337 -330
  38. package/dist/index.d.cts +21 -2
  39. package/dist/index.d.ts +21 -2
  40. package/dist/index.js +18 -15
  41. package/dist/invoice-templates-GZ33OENC.js +2 -0
  42. package/dist/invoice-templates-RB462AQN.cjs +19 -0
  43. package/dist/migrations/1783300000000-CreateOrderAssigneesTable.ts +43 -0
  44. package/dist/{order-assignees-handlers-NPKD64P6.cjs → order-assignees-handlers-KF7RMTV5.cjs} +77 -8
  45. package/dist/{order-assignees-handlers-LKMAGLG6.js → order-assignees-handlers-L3RVKUBS.js} +77 -8
  46. package/dist/{order-completion-otp-handlers-NK65LOLV.cjs → order-completion-otp-handlers-DDQREULW.cjs} +75 -18
  47. package/dist/{order-completion-otp-handlers-LFRHXWK4.js → order-completion-otp-handlers-NROWBGXN.js} +73 -16
  48. package/dist/{order-notification-dispatcher-LL7ETKLU.cjs → order-notification-dispatcher-6HCJ6Q75.cjs} +12 -9
  49. package/dist/{order-notification-dispatcher-ECPFI7CD.js → order-notification-dispatcher-KM2SY7TX.js} +7 -4
  50. package/dist/{rbac-debug-db-5R6XFPSV.js → rbac-debug-db-DFZWZ6GV.js} +1 -1
  51. package/dist/{rbac-debug-db-JKK2MCWF.cjs → rbac-debug-db-KWV7D5PQ.cjs} +2 -2
  52. package/dist/resolve-invoice-asset-url-JEZRENJW.cjs +11 -0
  53. package/dist/resolve-invoice-asset-url-QZ2FRDHI.js +2 -0
  54. package/package.json +1 -1
  55. package/dist/chunk-GLD263KW.cjs +0 -862
  56. package/dist/chunk-OPJEV44S.js +0 -847
  57. package/dist/email-queue-HGXB2FIS.js +0 -5
@@ -1,9 +1,9 @@
1
1
  import { queueWhatsApp } from './chunk-GWDI752Q.js';
2
2
  import { notifyLog, logFcmToken, maskNotifyEmail, maskNotifyPhone, notificationTriggerEmitter } from './chunk-FLUF2GZH.js';
3
+ import { applyTemplateVars } from './chunk-CRFV5WJK.js';
3
4
  import { sesRegionSupportsSmtp, sesSmtpHost, EmailService, renderLayout } from './chunk-6YOQ7G5O.js';
4
- import { queueEmail } from './chunk-TU23GJPJ.js';
5
+ import { queueEmail } from './chunk-7JCCPQEF.js';
5
6
  import { mergeEmailLayoutCompanyDetails } from './chunk-YRCKEGL2.js';
6
- import { applyTemplateVars } from './chunk-CRFV5WJK.js';
7
7
  import { __name } from './chunk-SHUYVCID.js';
8
8
  import * as crypto from 'crypto';
9
9
 
@@ -192,23 +192,34 @@ function canOnboardVendors(user) {
192
192
  }
193
193
  chunkUSNT2KNT_cjs.__name(canOnboardVendors, "canOnboardVendors");
194
194
  function resolveVendorScopeFromSessionUser(user) {
195
- if (!user?.email) return {
196
- type: "deny"
197
- };
198
- if (isPlatformAdministrator(user)) return {
199
- type: "all"
200
- };
195
+ if (!user?.email) {
196
+ console.log("[ORDERS-DEBUG][RESOLVE_VENDOR_SCOPE] No user email -> deny");
197
+ return {
198
+ type: "deny"
199
+ };
200
+ }
201
+ if (isPlatformAdministrator(user)) {
202
+ console.log("[ORDERS-DEBUG][RESOLVE_VENDOR_SCOPE] User is Platform Admin -> all");
203
+ return {
204
+ type: "all"
205
+ };
206
+ }
201
207
  const vendorIds = user.vendorIds ?? [];
202
- if (vendorIds.length === 0) return {
203
- type: "deny"
204
- };
208
+ if (vendorIds.length === 0) {
209
+ console.log("[ORDERS-DEBUG][RESOLVE_VENDOR_SCOPE] User has 0 vendorIds -> deny. User:", user.email);
210
+ return {
211
+ type: "deny"
212
+ };
213
+ }
205
214
  const preferred = user.activeVendorId ?? vendorIds[0];
206
215
  const vendorId = vendorIds.includes(preferred) ? preferred : vendorIds[0];
207
- return {
216
+ const res = {
208
217
  type: "vendor",
209
218
  vendorId,
210
219
  vendorIds
211
220
  };
221
+ console.log("[ORDERS-DEBUG][RESOLVE_VENDOR_SCOPE] User:", user.email, "-> scope:", res);
222
+ return res;
212
223
  }
213
224
  chunkUSNT2KNT_cjs.__name(resolveVendorScopeFromSessionUser, "resolveVendorScopeFromSessionUser");
214
225
  function vendorPortalFlagsFromUser(input) {
@@ -614,7 +625,7 @@ async function logEntityAccessDecision(dataSource, context, user, entity, action
614
625
  const id = Number(user.id);
615
626
  if (Number.isFinite(id)) {
616
627
  try {
617
- const { loadDbPermissionsForUser } = await import('./rbac-debug-db-JKK2MCWF.cjs');
628
+ const { loadDbPermissionsForUser } = await import('./rbac-debug-db-KWV7D5PQ.cjs');
618
629
  dbPermissions = await loadDbPermissionsForUser(dataSource, id);
619
630
  } catch (e) {
620
631
  dbPermissions = {
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkJ7FMZK66_cjs = require('./chunk-J7FMZK66.cjs');
3
+ var chunkO4AFPDQ4_cjs = require('./chunk-O4AFPDQ4.cjs');
4
4
  var chunkUSNT2KNT_cjs = require('./chunk-USNT2KNT.cjs');
5
5
  var typeorm = require('typeorm');
6
6
 
@@ -273,7 +273,7 @@ var RBAC_ADMIN_ONLY_ENTITIES = /* @__PURE__ */ new Set([
273
273
  "permissions"
274
274
  ]);
275
275
  function sessionHasEntityAccess(user, entity, action) {
276
- return chunkJ7FMZK66_cjs.explainSessionEntityAccess(user, entity, action).allowed;
276
+ return chunkO4AFPDQ4_cjs.explainSessionEntityAccess(user, entity, action).allowed;
277
277
  }
278
278
  chunkUSNT2KNT_cjs.__name(sessionHasEntityAccess, "sessionHasEntityAccess");
279
279
  function canManageRoles(user) {
@@ -364,8 +364,8 @@ function createAuthHelpersFromGetSession(getSession, NextResponse) {
364
364
  }
365
365
  const u = session.user;
366
366
  const allowed = sessionHasEntityAccess(u, entity, action);
367
- const { reason } = chunkJ7FMZK66_cjs.explainSessionEntityAccess(u, entity, action);
368
- chunkJ7FMZK66_cjs.logRbac("authHelpers.requireEntityPermission", {
367
+ const { reason } = chunkO4AFPDQ4_cjs.explainSessionEntityAccess(u, entity, action);
368
+ chunkO4AFPDQ4_cjs.logRbac("authHelpers.requireEntityPermission", {
369
369
  entity,
370
370
  action,
371
371
  allowed,
@@ -397,10 +397,10 @@ function createAuthHelpersFromGetSession(getSession, NextResponse) {
397
397
  }
398
398
  const u = session.user;
399
399
  if (u.isRBACAdmin) return null;
400
- if (chunkJ7FMZK66_cjs.isVendorPortalUser(u)) return null;
400
+ if (chunkO4AFPDQ4_cjs.isVendorPortalUser(u)) return null;
401
401
  if (u.adminAccess === true) return null;
402
402
  if (u.adminAccess === false) {
403
- chunkJ7FMZK66_cjs.logRbac("requireAdminAccess denied (adminAccess:false)", {
403
+ chunkO4AFPDQ4_cjs.logRbac("requireAdminAccess denied (adminAccess:false)", {
404
404
  email: u.email,
405
405
  groupName: u.groupName,
406
406
  isVendorPortal: u.isVendorPortal
@@ -412,7 +412,7 @@ function createAuthHelpersFromGetSession(getSession, NextResponse) {
412
412
  status: 403
413
413
  });
414
414
  }
415
- chunkJ7FMZK66_cjs.logRbac("requireAdminAccess denied (no matching rule)", {
415
+ chunkO4AFPDQ4_cjs.logRbac("requireAdminAccess denied (no matching rule)", {
416
416
  email: u.email,
417
417
  adminAccess: u.adminAccess,
418
418
  groupName: u.groupName,
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ var chunkUSNT2KNT_cjs = require('./chunk-USNT2KNT.cjs');
4
+
5
+ // src/lib/invoice/resolve-invoice-asset-url.ts
6
+ function resolveInvoiceAssetUrl(raw) {
7
+ const t = String(raw ?? "").trim();
8
+ if (!t) return null;
9
+ if (/^https?:\/\//i.test(t)) return t;
10
+ if (t.startsWith("//")) return `https:${t}`;
11
+ const base = (process.env.CMS_PUBLIC_URL || process.env.NEXT_PUBLIC_SITE_URL || process.env.NEXTAUTH_URL || "").trim().replace(/\/+$/, "");
12
+ if (!base) return null;
13
+ if (t.startsWith("/")) return `${base}${t}`;
14
+ return `${base}/${t}`;
15
+ }
16
+ chunkUSNT2KNT_cjs.__name(resolveInvoiceAssetUrl, "resolveInvoiceAssetUrl");
17
+
18
+ exports.resolveInvoiceAssetUrl = resolveInvoiceAssetUrl;
@@ -94,7 +94,7 @@ async function emitOrderNotificationTrigger(triggerKey, orderId, deps, extra) {
94
94
  orderId
95
95
  });
96
96
  try {
97
- const { dispatchOrderNotificationDirectly } = await import('./order-notification-dispatcher-ECPFI7CD.js');
97
+ const { dispatchOrderNotificationDirectly } = await import('./order-notification-dispatcher-KM2SY7TX.js');
98
98
  await dispatchOrderNotificationDirectly(triggerKey, triggerPayload, deps.dataSource, deps.entityMap);
99
99
  } catch (err) {
100
100
  notifyLog.error("TRIGGER", "direct dispatch failed", {
@@ -2,10 +2,10 @@
2
2
 
3
3
  var chunkH3IVLIPR_cjs = require('./chunk-H3IVLIPR.cjs');
4
4
  var chunkPA6YDMFZ_cjs = require('./chunk-PA6YDMFZ.cjs');
5
+ var chunkOOTLNH63_cjs = require('./chunk-OOTLNH63.cjs');
5
6
  var chunkVM6OVUUM_cjs = require('./chunk-VM6OVUUM.cjs');
6
- var chunkXFDIIVZB_cjs = require('./chunk-XFDIIVZB.cjs');
7
+ var chunkUMC7W5G3_cjs = require('./chunk-UMC7W5G3.cjs');
7
8
  var chunkTZEMLHSP_cjs = require('./chunk-TZEMLHSP.cjs');
8
- var chunkOOTLNH63_cjs = require('./chunk-OOTLNH63.cjs');
9
9
  var chunkUSNT2KNT_cjs = require('./chunk-USNT2KNT.cjs');
10
10
  var crypto = require('crypto');
11
11
 
@@ -1060,7 +1060,7 @@ async function sendChatLeadEmail(cms, emailSettings, brandingSettings, input) {
1060
1060
  };
1061
1061
  let anySent = false;
1062
1062
  for (const to of recipients) {
1063
- await chunkXFDIIVZB_cjs.queueEmail(cms, {
1063
+ await chunkUMC7W5G3_cjs.queueEmail(cms, {
1064
1064
  to,
1065
1065
  templateName: "chatLead",
1066
1066
  ctx
@@ -1933,7 +1933,7 @@ async function sendEmailForTrigger(triggerKey, orderId, audienceType, variables,
1933
1933
  companyDetails
1934
1934
  });
1935
1935
  const cms = await getCms();
1936
- await chunkXFDIIVZB_cjs.queueEmail(cms, {
1936
+ await chunkUMC7W5G3_cjs.queueEmail(cms, {
1937
1937
  to: contactEmail,
1938
1938
  subject,
1939
1939
  html,
@@ -0,0 +1,455 @@
1
+ 'use strict';
2
+
3
+ var chunkUPLVMVRX_cjs = require('./chunk-UPLVMVRX.cjs');
4
+ var chunkZX5U3VCB_cjs = require('./chunk-ZX5U3VCB.cjs');
5
+ var chunkM5GPOPGX_cjs = require('./chunk-M5GPOPGX.cjs');
6
+ var chunkP6S4XFZO_cjs = require('./chunk-P6S4XFZO.cjs');
7
+ var chunkTZEMLHSP_cjs = require('./chunk-TZEMLHSP.cjs');
8
+ var chunkUSNT2KNT_cjs = require('./chunk-USNT2KNT.cjs');
9
+
10
+ // src/plugins/erp/erp-response-map.ts
11
+ function pickString(o, keys) {
12
+ for (const k of keys) {
13
+ const v = o[k];
14
+ if (typeof v === "string" && v.trim()) return v.trim();
15
+ }
16
+ return void 0;
17
+ }
18
+ chunkUSNT2KNT_cjs.__name(pickString, "pickString");
19
+ function unwrapErpReadData(json) {
20
+ if (!json || typeof json !== "object") return null;
21
+ const o = json;
22
+ const d = o.data;
23
+ if (d && typeof d === "object" && !Array.isArray(d)) return d;
24
+ return o;
25
+ }
26
+ chunkUSNT2KNT_cjs.__name(unwrapErpReadData, "unwrapErpReadData");
27
+ function firstObject(data, keys) {
28
+ for (const k of keys) {
29
+ const v = data[k];
30
+ if (v && typeof v === "object" && !Array.isArray(v)) return v;
31
+ }
32
+ return null;
33
+ }
34
+ chunkUSNT2KNT_cjs.__name(firstObject, "firstObject");
35
+ function extractEvents(src) {
36
+ const timeline = src.timeline ?? src.events ?? src.history ?? src.trackingEvents;
37
+ if (!Array.isArray(timeline) || !timeline.length) return void 0;
38
+ const events = [];
39
+ for (const row of timeline) {
40
+ if (!row || typeof row !== "object") continue;
41
+ const r = row;
42
+ const at = pickString(r, [
43
+ "at",
44
+ "timestamp",
45
+ "date",
46
+ "occurredAt"
47
+ ]) ?? (r.at instanceof Date ? r.at.toISOString() : void 0);
48
+ const label = pickString(r, [
49
+ "label",
50
+ "status",
51
+ "title",
52
+ "message",
53
+ "description"
54
+ ]);
55
+ const detail = pickString(r, [
56
+ "detail",
57
+ "notes",
58
+ "description"
59
+ ]);
60
+ if (at || label || detail) events.push({
61
+ at,
62
+ label,
63
+ detail
64
+ });
65
+ }
66
+ return events.length ? events : void 0;
67
+ }
68
+ chunkUSNT2KNT_cjs.__name(extractEvents, "extractEvents");
69
+ function mapErpPayloadToFulfillment(data) {
70
+ const nested = firstObject(data, [
71
+ "fulfillment",
72
+ "packaging",
73
+ "shipment",
74
+ "shipping",
75
+ "delivery"
76
+ ]);
77
+ const src = nested || data;
78
+ const status = pickString(src, [
79
+ "status",
80
+ "fulfillmentStatus",
81
+ "state",
82
+ "label",
83
+ "packagingStatus"
84
+ ]);
85
+ const trackingId = pickString(src, [
86
+ "trackingId",
87
+ "tracking_id",
88
+ "trackingNumber",
89
+ "awb",
90
+ "trackingUrl"
91
+ ]);
92
+ const events = extractEvents(src);
93
+ if (!status && !trackingId && !(events && events.length)) return void 0;
94
+ return {
95
+ status,
96
+ trackingId,
97
+ events
98
+ };
99
+ }
100
+ chunkUSNT2KNT_cjs.__name(mapErpPayloadToFulfillment, "mapErpPayloadToFulfillment");
101
+ function mapErpPayloadToInvoiceNumber(data) {
102
+ const nested = firstObject(data, [
103
+ "invoice",
104
+ "latestInvoice",
105
+ "postedInvoice"
106
+ ]);
107
+ const src = nested || data;
108
+ return pickString(src, [
109
+ "invoiceNumber",
110
+ "invoice_number",
111
+ "number",
112
+ "name",
113
+ "id"
114
+ ]);
115
+ }
116
+ chunkUSNT2KNT_cjs.__name(mapErpPayloadToInvoiceNumber, "mapErpPayloadToInvoiceNumber");
117
+ function extractChildOrderRefsFromSalePayload(data) {
118
+ const lists = [
119
+ data.returns,
120
+ data.returnOrders,
121
+ data.relatedReturns,
122
+ data.childOrders,
123
+ data.children
124
+ ];
125
+ const seen = /* @__PURE__ */ new Set();
126
+ const out = [];
127
+ for (const list of lists) {
128
+ if (!Array.isArray(list)) continue;
129
+ for (const item of list) {
130
+ if (!item || typeof item !== "object") continue;
131
+ const o = item;
132
+ const ref = pickString(o, [
133
+ "platformReturnId",
134
+ "platform_return_id",
135
+ "refId",
136
+ "ref_id"
137
+ ]) ?? (typeof o.id === "string" ? o.id : void 0);
138
+ if (!ref || seen.has(ref)) continue;
139
+ seen.add(ref);
140
+ const t = (pickString(o, [
141
+ "kind",
142
+ "type",
143
+ "orderKind"
144
+ ]) || "").toLowerCase();
145
+ const orderKind = /replac/.test(t) ? "replacement" : "return";
146
+ out.push({
147
+ ref,
148
+ orderKind
149
+ });
150
+ }
151
+ }
152
+ return out;
153
+ }
154
+ chunkUSNT2KNT_cjs.__name(extractChildOrderRefsFromSalePayload, "extractChildOrderRefsFromSalePayload");
155
+
156
+ // src/lib/invoice/build-local-invoice-for-order.ts
157
+ async function loadSettingsGroup(ds, entityMap, group) {
158
+ if (!entityMap.configs) return {};
159
+ const rows = await ds.getRepository(entityMap.configs).find({
160
+ where: {
161
+ settings: group,
162
+ deleted: false
163
+ }
164
+ });
165
+ return Object.fromEntries(rows.map((r) => [
166
+ r.key,
167
+ String(r.value ?? "")
168
+ ]));
169
+ }
170
+ chunkUSNT2KNT_cjs.__name(loadSettingsGroup, "loadSettingsGroup");
171
+ function addrFromRow(row) {
172
+ if (!row || typeof row !== "object") return null;
173
+ const a = row;
174
+ return {
175
+ line1: String(a.line1 ?? "").trim() || void 0,
176
+ line2: a.line2 != null ? String(a.line2).trim() || null : null,
177
+ city: String(a.city ?? "").trim() || void 0,
178
+ state: String(a.state ?? "").trim() || void 0,
179
+ postalCode: String(a.postalCode ?? "").trim() || void 0,
180
+ country: String(a.country ?? "").trim() || void 0
181
+ };
182
+ }
183
+ chunkUSNT2KNT_cjs.__name(addrFromRow, "addrFromRow");
184
+ async function buildLocalInvoicePdfForOrder(ds, entityMap, orderId) {
185
+ if (!entityMap.orders || !entityMap.order_items) {
186
+ return {
187
+ error: "Orders not configured",
188
+ status: 503
189
+ };
190
+ }
191
+ const orderRepo = ds.getRepository(entityMap.orders);
192
+ let order = null;
193
+ try {
194
+ order = await orderRepo.findOne({
195
+ where: {
196
+ id: orderId,
197
+ deleted: false
198
+ },
199
+ relations: [
200
+ "contact",
201
+ "billingAddress",
202
+ "shippingAddress",
203
+ "items",
204
+ "items.product",
205
+ "assignedUser"
206
+ ]
207
+ });
208
+ } catch {
209
+ try {
210
+ order = await orderRepo.findOne({
211
+ where: {
212
+ id: orderId,
213
+ deleted: false
214
+ },
215
+ relations: [
216
+ "contact",
217
+ "billingAddress",
218
+ "shippingAddress",
219
+ "items",
220
+ "assignedUser"
221
+ ]
222
+ });
223
+ } catch {
224
+ order = await orderRepo.findOne({
225
+ where: {
226
+ id: orderId,
227
+ deleted: false
228
+ },
229
+ relations: [
230
+ "contact",
231
+ "billingAddress",
232
+ "shippingAddress",
233
+ "items"
234
+ ]
235
+ });
236
+ }
237
+ }
238
+ if (!order) return {
239
+ error: "Not found",
240
+ status: 404
241
+ };
242
+ const o = order;
243
+ const kind = o.orderKind || "sale";
244
+ if (kind !== "sale") return {
245
+ error: "Invoice only for sale orders",
246
+ status: 400
247
+ };
248
+ const [store, branding, email] = await Promise.all([
249
+ loadSettingsGroup(ds, entityMap, "store"),
250
+ loadSettingsGroup(ds, entityMap, "branding"),
251
+ loadSettingsGroup(ds, entityMap, "email")
252
+ ]);
253
+ const companyDetails = chunkTZEMLHSP_cjs.mergeEmailLayoutCompanyDetails(branding, email, store);
254
+ const fromBranding = chunkTZEMLHSP_cjs.getCompanyDetailsFromSettings(branding);
255
+ const rawLogo = store.invoiceLogoUrl || store.companyLogo || store.logo || companyDetails.logoUrl || fromBranding.logoUrl || null;
256
+ const logoUrl = chunkP6S4XFZO_cjs.resolveInvoiceAssetUrl(rawLogo);
257
+ const companyName = store.companyName || store.invoiceCompanyName || store.name || companyDetails.companyName || fromBranding.companyName || "Store";
258
+ const supportEmail = store.companyEmail || store.invoiceEmail || store.email || companyDetails.supportEmail || fromBranding.supportEmail;
259
+ const supportPhone = store.companyPhone || store.invoicePhone || store.phone || companyDetails.supportPhone;
260
+ const address = store.companyAddress || store.invoiceAddress || store.address;
261
+ const lineItems = (o.items ?? []).map((it) => {
262
+ const name = it.product?.name && String(it.product.name).trim() || `Product #${it.productId ?? ""}`;
263
+ return {
264
+ name,
265
+ quantity: Math.max(0, Math.floor(Number(it.quantity) || 0)),
266
+ unitPrice: Number(it.unitPrice) || 0,
267
+ tax: Number(it.tax) || 0,
268
+ total: Number(it.total) || 0,
269
+ sku: it.product?.sku ?? null
270
+ };
271
+ });
272
+ const rawMeta = o.metadata || {};
273
+ const serviceDate = rawMeta.serviceDate || rawMeta.bookingDate || rawMeta.date || null;
274
+ const timeSlot = rawMeta.timeSlot || rawMeta.slot || rawMeta.time || null;
275
+ const assignedTo = o.assignedUser?.name || null;
276
+ const qrToken = o.qrToken || null;
277
+ const baseUrl = process.env.NEXTAUTH_URL || process.env.PUBLIC_APP_URL || "";
278
+ const qrData = qrToken ? baseUrl ? `${baseUrl.replace(/\/$/, "")}/track/${qrToken}` : `/track/${qrToken}` : String(o.orderNumber || orderId);
279
+ const includeQrCode = store.invoice_include_qr === "true" || store.invoiceIncludeQr === "true";
280
+ const bytes = await chunkZX5U3VCB_cjs.generateLocalInvoicePdf({
281
+ templateId: chunkM5GPOPGX_cjs.normalizeInvoiceTemplateId(store.invoiceTemplate),
282
+ orderNumber: String(o.orderNumber || orderId),
283
+ orderDate: o.createdAt || /* @__PURE__ */ new Date(),
284
+ serviceDate,
285
+ timeSlot,
286
+ assignedTo,
287
+ qrToken,
288
+ qrData,
289
+ includeQrCode,
290
+ currency: String(o.currency || store.currency || "INR"),
291
+ customerName: String(o.contact?.name ?? "").trim() || "Customer",
292
+ customerEmail: o.contact?.email ?? null,
293
+ customerPhone: o.contact?.phone ?? null,
294
+ billingAddress: addrFromRow(o.billingAddress),
295
+ shippingAddress: addrFromRow(o.shippingAddress),
296
+ lineItems,
297
+ subtotal: Number(o.subtotal) || 0,
298
+ tax: Number(o.tax) || 0,
299
+ discount: Number(o.discount) || 0,
300
+ total: Number(o.total) || 0,
301
+ company: {
302
+ name: companyName,
303
+ logoUrl,
304
+ supportEmail,
305
+ supportPhone,
306
+ address
307
+ }
308
+ });
309
+ return {
310
+ bytes,
311
+ filename: `invoice-${String(o.orderNumber || orderId).replace(/[^\w.-]+/g, "_")}.pdf`
312
+ };
313
+ }
314
+ chunkUSNT2KNT_cjs.__name(buildLocalInvoicePdfForOrder, "buildLocalInvoicePdfForOrder");
315
+
316
+ // src/plugins/erp/erp-order-invoice.ts
317
+ function pickInvoiceId(data) {
318
+ const nested = data.invoice && typeof data.invoice === "object" && !Array.isArray(data.invoice) ? data.invoice : null;
319
+ const src = nested || data;
320
+ for (const k of [
321
+ "invoiceId",
322
+ "invoice_id",
323
+ "id"
324
+ ]) {
325
+ const v = src[k];
326
+ if (typeof v === "string" && v.trim()) return v.trim();
327
+ }
328
+ return void 0;
329
+ }
330
+ chunkUSNT2KNT_cjs.__name(pickInvoiceId, "pickInvoiceId");
331
+ function jsonErr(msg, status) {
332
+ return new Response(JSON.stringify({
333
+ error: msg
334
+ }), {
335
+ status,
336
+ headers: {
337
+ "Content-Type": "application/json"
338
+ }
339
+ });
340
+ }
341
+ chunkUSNT2KNT_cjs.__name(jsonErr, "jsonErr");
342
+ var ORDER_INVOICE_EMAIL_ELIGIBLE_STATUSES = /* @__PURE__ */ new Set([
343
+ "pending",
344
+ "placed",
345
+ "confirmed",
346
+ "processing",
347
+ "completed"
348
+ ]);
349
+ function isOrderEligibleForInvoiceEmail(status, orderKind) {
350
+ const kind = (orderKind || "sale").trim().toLowerCase();
351
+ if (kind !== "sale") return false;
352
+ return ORDER_INVOICE_EMAIL_ELIGIBLE_STATUSES.has(String(status ?? "").trim().toLowerCase());
353
+ }
354
+ chunkUSNT2KNT_cjs.__name(isOrderEligibleForInvoiceEmail, "isOrderEligibleForInvoiceEmail");
355
+ async function resolveOrderInvoicePdfBytes(cms, dataSource, entityMap, orderId, options = {}) {
356
+ try {
357
+ const orderRepo = dataSource.getRepository(entityMap.orders);
358
+ const order = await orderRepo.findOne({
359
+ where: {
360
+ id: orderId,
361
+ deleted: false
362
+ }
363
+ });
364
+ if (!order) return {
365
+ error: "Not found",
366
+ status: 404
367
+ };
368
+ const kind = order.orderKind || "sale";
369
+ if (kind !== "sale") return {
370
+ error: "Invoice only for sale orders",
371
+ status: 400
372
+ };
373
+ if (options.ownerContactId != null && order.contactId !== options.ownerContactId) {
374
+ return {
375
+ error: "Not found",
376
+ status: 404
377
+ };
378
+ }
379
+ const on = await chunkUPLVMVRX_cjs.isErpIntegrationEnabled(cms, dataSource, entityMap);
380
+ const erp = cms.getPlugin("erp");
381
+ if (on && erp?.submission) {
382
+ const meta = order.metadata && typeof order.metadata === "object" && !Array.isArray(order.metadata) ? order.metadata : {};
383
+ const inv = meta.invoice && typeof meta.invoice === "object" && !Array.isArray(meta.invoice) ? meta.invoice : {};
384
+ let invoiceId = typeof inv.invoiceId === "string" ? inv.invoiceId.trim() : "";
385
+ if (!invoiceId) {
386
+ const refId = String(order.orderNumber || "");
387
+ try {
388
+ const r = await erp.submission.postErpReadAction("get-invoice", {
389
+ platformOrderId: refId
390
+ });
391
+ const d = r.ok ? unwrapErpReadData(r.json) : null;
392
+ invoiceId = d ? pickInvoiceId(d) || "" : "";
393
+ } catch {
394
+ invoiceId = "";
395
+ }
396
+ }
397
+ if (invoiceId) {
398
+ const pdf = await erp.submission.fetchInvoicePdf(invoiceId);
399
+ if (pdf.ok && pdf.buffer) {
400
+ return {
401
+ bytes: new Uint8Array(pdf.buffer),
402
+ filename: `order-invoice-${orderId}.pdf`,
403
+ contentType: pdf.contentType || "application/pdf",
404
+ source: "erp"
405
+ };
406
+ }
407
+ }
408
+ }
409
+ const local = await buildLocalInvoicePdfForOrder(dataSource, entityMap, orderId);
410
+ if ("error" in local) return {
411
+ error: local.error,
412
+ status: local.status
413
+ };
414
+ return {
415
+ bytes: local.bytes,
416
+ filename: local.filename.startsWith("invoice-") ? local.filename.replace(/^invoice-/, "order-invoice-") : local.filename,
417
+ contentType: "application/pdf",
418
+ source: "local"
419
+ };
420
+ } catch (err) {
421
+ const msg = err instanceof Error ? err.message : String(err);
422
+ console.error("[invoice] resolveOrderInvoicePdfBytes failed", {
423
+ orderId,
424
+ error: msg
425
+ });
426
+ return {
427
+ error: `Invoice failed: ${msg}`,
428
+ status: 500
429
+ };
430
+ }
431
+ }
432
+ chunkUSNT2KNT_cjs.__name(resolveOrderInvoicePdfBytes, "resolveOrderInvoicePdfBytes");
433
+ async function streamOrderInvoicePdf(cms, dataSource, entityMap, orderId, options) {
434
+ const resolved = await resolveOrderInvoicePdfBytes(cms, dataSource, entityMap, orderId, options);
435
+ if ("error" in resolved) return jsonErr(resolved.error, resolved.status);
436
+ return new Response(Buffer.from(resolved.bytes), {
437
+ status: 200,
438
+ headers: {
439
+ "Content-Type": resolved.contentType,
440
+ "Content-Disposition": `attachment; filename="${resolved.filename}"`,
441
+ "X-Invoice-Source": resolved.source
442
+ }
443
+ });
444
+ }
445
+ chunkUSNT2KNT_cjs.__name(streamOrderInvoicePdf, "streamOrderInvoicePdf");
446
+
447
+ exports.ORDER_INVOICE_EMAIL_ELIGIBLE_STATUSES = ORDER_INVOICE_EMAIL_ELIGIBLE_STATUSES;
448
+ exports.buildLocalInvoicePdfForOrder = buildLocalInvoicePdfForOrder;
449
+ exports.extractChildOrderRefsFromSalePayload = extractChildOrderRefsFromSalePayload;
450
+ exports.isOrderEligibleForInvoiceEmail = isOrderEligibleForInvoiceEmail;
451
+ exports.mapErpPayloadToFulfillment = mapErpPayloadToFulfillment;
452
+ exports.mapErpPayloadToInvoiceNumber = mapErpPayloadToInvoiceNumber;
453
+ exports.resolveOrderInvoicePdfBytes = resolveOrderInvoicePdfBytes;
454
+ exports.streamOrderInvoicePdf = streamOrderInvoicePdf;
455
+ exports.unwrapErpReadData = unwrapErpReadData;
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkGLD263KW_cjs = require('./chunk-GLD263KW.cjs');
3
+ var chunkSUUD7OUG_cjs = require('./chunk-SUUD7OUG.cjs');
4
4
  var chunkUSNT2KNT_cjs = require('./chunk-USNT2KNT.cjs');
5
5
 
6
6
  // src/plugins/email/email-queue.ts
@@ -50,13 +50,13 @@ async function resolveInvoiceAttachmentForJob(cms, payload, options) {
50
50
  invoiceAttached: false
51
51
  };
52
52
  const o = order;
53
- if (!chunkGLD263KW_cjs.isOrderEligibleForInvoiceEmail(o.status, o.orderKind)) {
53
+ if (!chunkSUUD7OUG_cjs.isOrderEligibleForInvoiceEmail(o.status, o.orderKind)) {
54
54
  return {
55
55
  attachments: payload.attachments,
56
56
  invoiceAttached: false
57
57
  };
58
58
  }
59
- const resolved = await chunkGLD263KW_cjs.resolveOrderInvoicePdfBytes(cms, dataSource, entityMap, payload.orderId);
59
+ const resolved = await chunkSUUD7OUG_cjs.resolveOrderInvoicePdfBytes(cms, dataSource, entityMap, payload.orderId);
60
60
  if ("error" in resolved) {
61
61
  console.warn("[email] order invoice attach failed", {
62
62
  orderId: payload.orderId,