@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.
- package/dist/admin.cjs +214 -32
- package/dist/admin.js +214 -32
- package/dist/api.cjs +45 -42
- package/dist/api.js +12 -9
- package/dist/auth.cjs +51 -51
- package/dist/auth.js +3 -3
- package/dist/{chunk-QYRXLURF.cjs → chunk-22XKONB5.cjs} +640 -145
- package/dist/{chunk-MVHDC3XF.js → chunk-5NOZSG6J.js} +22 -11
- package/dist/{chunk-TU23GJPJ.js → chunk-7JCCPQEF.js} +1 -1
- package/dist/{chunk-WMMZZRDJ.cjs → chunk-GN4LKG4V.cjs} +1 -1
- package/dist/{chunk-KM2I6AFP.cjs → chunk-HBUV73RB.cjs} +9 -9
- package/dist/chunk-IKTBZJHT.js +16 -0
- package/dist/chunk-M5GPOPGX.cjs +49 -0
- package/dist/{chunk-T33KU5G5.js → chunk-MYUGQHU4.js} +548 -53
- package/dist/{chunk-NV5IRHI3.js → chunk-N4LBZXBG.js} +2 -2
- package/dist/{chunk-J7FMZK66.cjs → chunk-O4AFPDQ4.cjs} +22 -11
- package/dist/{chunk-4U6DATGZ.cjs → chunk-OV5TRZET.cjs} +7 -7
- package/dist/chunk-P6S4XFZO.cjs +18 -0
- package/dist/{chunk-RCE5SJBA.js → chunk-SKJH7PX4.js} +1 -1
- package/dist/{chunk-5MZFQRDW.cjs → chunk-SMHQV3WL.cjs} +4 -4
- package/dist/chunk-SUUD7OUG.cjs +455 -0
- package/dist/{chunk-XFDIIVZB.cjs → chunk-UMC7W5G3.cjs} +3 -3
- package/dist/chunk-WKDBMDUX.js +45 -0
- package/dist/{chunk-6DBDJ4VD.js → chunk-Z5G54EGD.js} +2 -2
- package/dist/chunk-Z5OB5QGN.js +465 -0
- package/dist/chunk-ZIT4IP6N.js +445 -0
- package/dist/chunk-ZX5U3VCB.cjs +471 -0
- package/dist/{chunk-NR44CK5E.js → chunk-ZY64VJMS.js} +1 -1
- package/dist/email-queue-3QBQ63F7.js +8 -0
- package/dist/{email-queue-4OY45JIU.cjs → email-queue-K4E4OFI7.cjs} +9 -6
- package/dist/{emit-order-notification-trigger-ZD5YN3JM.cjs → emit-order-notification-trigger-ROASTYQP.cjs} +3 -3
- package/dist/{emit-order-notification-trigger-EJJZ6XTS.js → emit-order-notification-trigger-YUQTPELC.js} +1 -1
- package/dist/{erp-order-invoice-YUSPZ7CE.cjs → erp-order-invoice-AZ5MX2JB.cjs} +8 -5
- package/dist/{erp-order-invoice-H6HCJ7YS.js → erp-order-invoice-XSYHAMBS.js} +4 -1
- package/dist/generate-local-invoice-pdf-BQTCL5MW.cjs +12 -0
- package/dist/generate-local-invoice-pdf-OCFG47SE.js +3 -0
- package/dist/index.cjs +337 -330
- package/dist/index.d.cts +21 -2
- package/dist/index.d.ts +21 -2
- package/dist/index.js +18 -15
- package/dist/invoice-templates-GZ33OENC.js +2 -0
- package/dist/invoice-templates-RB462AQN.cjs +19 -0
- package/dist/migrations/1783300000000-CreateOrderAssigneesTable.ts +43 -0
- package/dist/{order-assignees-handlers-NPKD64P6.cjs → order-assignees-handlers-KF7RMTV5.cjs} +77 -8
- package/dist/{order-assignees-handlers-LKMAGLG6.js → order-assignees-handlers-L3RVKUBS.js} +77 -8
- package/dist/{order-completion-otp-handlers-NK65LOLV.cjs → order-completion-otp-handlers-DDQREULW.cjs} +75 -18
- package/dist/{order-completion-otp-handlers-LFRHXWK4.js → order-completion-otp-handlers-NROWBGXN.js} +73 -16
- package/dist/{order-notification-dispatcher-LL7ETKLU.cjs → order-notification-dispatcher-6HCJ6Q75.cjs} +12 -9
- package/dist/{order-notification-dispatcher-ECPFI7CD.js → order-notification-dispatcher-KM2SY7TX.js} +7 -4
- package/dist/{rbac-debug-db-5R6XFPSV.js → rbac-debug-db-DFZWZ6GV.js} +1 -1
- package/dist/{rbac-debug-db-JKK2MCWF.cjs → rbac-debug-db-KWV7D5PQ.cjs} +2 -2
- package/dist/resolve-invoice-asset-url-JEZRENJW.cjs +11 -0
- package/dist/resolve-invoice-asset-url-QZ2FRDHI.js +2 -0
- package/package.json +1 -1
- package/dist/chunk-GLD263KW.cjs +0 -862
- package/dist/chunk-OPJEV44S.js +0 -847
- 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-
|
|
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)
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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)
|
|
203
|
-
|
|
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
|
-
|
|
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-
|
|
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
|
|
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
|
|
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 } =
|
|
368
|
-
|
|
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 (
|
|
400
|
+
if (chunkO4AFPDQ4_cjs.isVendorPortalUser(u)) return null;
|
|
401
401
|
if (u.adminAccess === true) return null;
|
|
402
402
|
if (u.adminAccess === false) {
|
|
403
|
-
|
|
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
|
-
|
|
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-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 (!
|
|
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
|
|
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,
|