@infuro/cms-core 1.0.45 → 1.0.47
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/README.md +19 -2
- package/dist/admin.cjs +4249 -2872
- package/dist/admin.d.cts +24 -4
- package/dist/admin.d.ts +24 -4
- package/dist/admin.js +3179 -1804
- package/dist/api.cjs +41 -39
- package/dist/api.d.cts +10 -4
- package/dist/api.d.ts +10 -4
- package/dist/api.js +9 -7
- package/dist/auth.cjs +55 -51
- package/dist/auth.d.cts +6 -3
- package/dist/auth.d.ts +6 -3
- package/dist/auth.js +3 -3
- package/dist/{chunk-KFFB6EMZ.js → chunk-2HU5R2JE.js} +2 -0
- package/dist/chunk-2IAXTKQN.cjs +19 -0
- package/dist/chunk-2KUCQVAQ.js +936 -0
- package/dist/chunk-3K5AIEIZ.js +256 -0
- package/dist/{chunk-SPQFNIYJ.cjs → chunk-4PMK3RNA.cjs} +2 -0
- package/dist/{chunk-X6UQFV4X.cjs → chunk-77NUXO6A.cjs} +14 -12
- package/dist/chunk-BXYZDMTZ.cjs +953 -0
- package/dist/chunk-DBPSJYLZ.js +47 -0
- package/dist/chunk-EIZKW2PF.js +13 -0
- package/dist/chunk-HY3AXLOI.cjs +265 -0
- package/dist/{chunk-X47PBV4I.js → chunk-JE22VP6S.js} +1 -0
- package/dist/{chunk-DN65KDIA.js → chunk-JIWUVQ6B.js} +14 -13
- package/dist/{chunk-HT5DI3XW.cjs → chunk-KOTXDSQB.cjs} +1 -0
- package/dist/chunk-L3525VXI.js +243 -0
- package/dist/{chunk-22FFHLTO.cjs → chunk-LMJ7RKPF.cjs} +421 -150
- package/dist/chunk-OY2YTBMP.cjs +50 -0
- package/dist/{chunk-TAHX46EI.cjs → chunk-Q3HQEM4R.cjs} +15 -7
- package/dist/chunk-V25RDUOU.cjs +248 -0
- package/dist/{chunk-ZMRQ72F6.cjs → chunk-VUQFARRT.cjs} +10 -10
- package/dist/{chunk-MVXLRANV.js → chunk-W42UZLQO.js} +1977 -891
- package/dist/{chunk-F5XFHYTG.cjs → chunk-XUCKZPML.cjs} +2088 -991
- package/dist/{chunk-I6NH72MO.js → chunk-YC4NUZCS.js} +10 -2
- package/dist/{chunk-NNQBWDCI.js → chunk-YXH2UUEZ.js} +418 -146
- package/dist/{chunk-BLR6H5GL.js → chunk-ZF2RQWXB.js} +4 -4
- package/dist/cli.cjs +9 -4
- package/dist/cli.js +9 -4
- package/dist/{email-queue-TPZWLTIV.cjs → email-queue-6NJY6HNM.cjs} +7 -5
- package/dist/email-queue-OI2HSCGE.js +4 -0
- package/dist/{emit-order-notification-trigger-IVLWKKJL.js → emit-order-notification-trigger-6XX7LSC4.js} +1 -1
- package/dist/{emit-order-notification-trigger-D2N3KFHL.cjs → emit-order-notification-trigger-NASG7ZEO.cjs} +3 -3
- package/dist/erp-order-invoice-3GXDE443.js +3 -0
- package/dist/erp-order-invoice-EYYNR526.cjs +24 -0
- package/dist/{event-order-defaults-EMWBIGL3.cjs → event-order-defaults-7Z3UZOEH.cjs} +9 -9
- package/dist/{event-order-defaults-SDRNAZHC.js → event-order-defaults-XQ3IDPD7.js} +1 -1
- package/dist/hooks.cjs +43 -0
- package/dist/hooks.d.cts +10 -1
- package/dist/hooks.d.ts +10 -1
- package/dist/hooks.js +39 -1
- package/dist/index.cjs +429 -298
- package/dist/index.d.cts +317 -30
- package/dist/index.d.ts +317 -30
- package/dist/index.js +17 -13
- package/dist/migrations/1781810000000-OrderItemsVariantId.ts +44 -0
- package/dist/migrations/1781900000000-UserInviteStatusToken.ts +46 -0
- package/dist/migrations/1782000000000-ComboSlug.ts +58 -0
- package/dist/migrations/1782100000000-DiscountDeviceType.ts +20 -0
- package/dist/migrations/1782200000000-VendorTeamProfiles.ts +233 -0
- package/dist/migrations/1782300000000-AddTypeToOrderNotificationBindings.ts +75 -0
- package/dist/order-inventory-2MYRKEPC.cjs +39 -0
- package/dist/order-inventory-76V4XIGW.js +2 -0
- package/dist/{order-notification-dispatcher-XWIJYDGA.js → order-notification-dispatcher-6WNG24NY.js} +4 -2
- package/dist/{order-notification-dispatcher-RU7BTGGX.cjs → order-notification-dispatcher-6XSU3AR7.cjs} +6 -4
- package/dist/{rbac-debug-db-2SGNLANF.js → rbac-debug-db-6EMIVMGF.js} +1 -1
- package/dist/{rbac-debug-db-4Z6A425H.cjs → rbac-debug-db-6PWTLBEL.cjs} +2 -2
- package/dist/retire-soft-deleted-unique-5VXBA5XX.cjs +15 -0
- package/dist/retire-soft-deleted-unique-NXQIH4BC.js +2 -0
- package/dist/theme.cjs +6 -1
- package/dist/theme.d.cts +4 -1
- package/dist/theme.d.ts +4 -1
- package/dist/theme.js +3 -1
- package/package.json +5 -4
- package/src/admin/admin.css +34 -24
- package/dist/chunk-5ELSW2UP.js +0 -150
- package/dist/chunk-PNOKNSG2.cjs +0 -222
- package/dist/chunk-WEMDMVHQ.js +0 -216
- package/dist/chunk-XW5ATPRW.cjs +0 -155
- package/dist/email-queue-CGZBVVAS.js +0 -2
- package/dist/erp-order-invoice-3YISSOWW.js +0 -3
- package/dist/erp-order-invoice-ZR5F2KTA.cjs +0 -12
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { __name } from './chunk-SHUYVCID.js';
|
|
2
|
+
|
|
3
|
+
// src/lib/order-inventory.ts
|
|
4
|
+
var STOCK_HELD = /* @__PURE__ */ new Set([
|
|
5
|
+
"confirmed",
|
|
6
|
+
"completed"
|
|
7
|
+
]);
|
|
8
|
+
function orderStatusHoldsStock(status) {
|
|
9
|
+
return STOCK_HELD.has(String(status ?? "").trim().toLowerCase());
|
|
10
|
+
}
|
|
11
|
+
__name(orderStatusHoldsStock, "orderStatusHoldsStock");
|
|
12
|
+
function orderInventorySnapshotFromRow(order) {
|
|
13
|
+
return {
|
|
14
|
+
status: order.status ?? "pending",
|
|
15
|
+
lines: (order.items ?? []).map((i) => {
|
|
16
|
+
const meta = i.metadata && typeof i.metadata === "object" ? i.metadata : null;
|
|
17
|
+
const metaVid = meta?.variantId ?? meta?.variant_id;
|
|
18
|
+
const fromCol = i.variantId != null ? Number(i.variantId) : NaN;
|
|
19
|
+
const fromMeta = metaVid != null && String(metaVid).trim() !== "" ? Number(metaVid) : NaN;
|
|
20
|
+
const variantId = Number.isFinite(fromCol) && fromCol > 0 ? fromCol : Number.isFinite(fromMeta) && fromMeta > 0 ? fromMeta : null;
|
|
21
|
+
return {
|
|
22
|
+
productId: Number(i.productId),
|
|
23
|
+
quantity: Math.max(0, Math.floor(Number(i.quantity) || 0)),
|
|
24
|
+
variantId
|
|
25
|
+
};
|
|
26
|
+
}).filter((l) => l.productId > 0 && l.quantity > 0)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
__name(orderInventorySnapshotFromRow, "orderInventorySnapshotFromRow");
|
|
30
|
+
function lineKey(productId, variantId) {
|
|
31
|
+
const vid = variantId != null && Number.isFinite(Number(variantId)) && Number(variantId) > 0 ? Number(variantId) : 0;
|
|
32
|
+
return `${productId}:${vid}`;
|
|
33
|
+
}
|
|
34
|
+
__name(lineKey, "lineKey");
|
|
35
|
+
function mergeInventoryLines(lines) {
|
|
36
|
+
const m = /* @__PURE__ */ new Map();
|
|
37
|
+
for (const line of lines) {
|
|
38
|
+
const productId = Number(line.productId);
|
|
39
|
+
const quantity = Math.max(0, Math.floor(Number(line.quantity) || 0));
|
|
40
|
+
if (!Number.isFinite(productId) || productId <= 0 || quantity <= 0) continue;
|
|
41
|
+
const variantId = line.variantId != null && Number.isFinite(Number(line.variantId)) && Number(line.variantId) > 0 ? Number(line.variantId) : null;
|
|
42
|
+
const key = lineKey(productId, variantId);
|
|
43
|
+
const prev = m.get(key);
|
|
44
|
+
if (prev) {
|
|
45
|
+
prev.quantity += quantity;
|
|
46
|
+
} else {
|
|
47
|
+
m.set(key, {
|
|
48
|
+
productId,
|
|
49
|
+
quantity,
|
|
50
|
+
variantId
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return m;
|
|
55
|
+
}
|
|
56
|
+
__name(mergeInventoryLines, "mergeInventoryLines");
|
|
57
|
+
function productRepo(ds, entityMap) {
|
|
58
|
+
const target = entityMap.products;
|
|
59
|
+
if (!target) throw new Error("products entity not configured");
|
|
60
|
+
return ds.getRepository(target);
|
|
61
|
+
}
|
|
62
|
+
__name(productRepo, "productRepo");
|
|
63
|
+
function variantRepo(ds, entityMap) {
|
|
64
|
+
const target = entityMap.product_variants;
|
|
65
|
+
if (!target) return null;
|
|
66
|
+
return ds.getRepository(target);
|
|
67
|
+
}
|
|
68
|
+
__name(variantRepo, "variantRepo");
|
|
69
|
+
async function validateInventoryForConfirmedOrderLines(ds, entityMap, lines) {
|
|
70
|
+
const merged = mergeInventoryLines(lines);
|
|
71
|
+
const byProduct = /* @__PURE__ */ new Map();
|
|
72
|
+
for (const line of merged.values()) {
|
|
73
|
+
byProduct.set(line.productId, (byProduct.get(line.productId) ?? 0) + line.quantity);
|
|
74
|
+
}
|
|
75
|
+
const pRepo = productRepo(ds, entityMap);
|
|
76
|
+
const vRepo = variantRepo(ds, entityMap);
|
|
77
|
+
for (const [productId, qty] of byProduct) {
|
|
78
|
+
const row = await pRepo.findOne({
|
|
79
|
+
where: {
|
|
80
|
+
id: productId,
|
|
81
|
+
deleted: false
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
if (!row) return `Product #${productId} not found`;
|
|
85
|
+
if (row.type === "service") continue;
|
|
86
|
+
const name = row.name ?? String(productId);
|
|
87
|
+
const productQty = Number(row.quantity ?? 0);
|
|
88
|
+
if (productQty < qty) {
|
|
89
|
+
return `Insufficient stock for ${name}: available ${productQty}, required ${qty}`;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
for (const line of merged.values()) {
|
|
93
|
+
if (!line.variantId || !vRepo) continue;
|
|
94
|
+
const row = await pRepo.findOne({
|
|
95
|
+
where: {
|
|
96
|
+
id: line.productId,
|
|
97
|
+
deleted: false
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
if (!row) continue;
|
|
101
|
+
if (row.type === "service") continue;
|
|
102
|
+
const name = row.name ?? String(line.productId);
|
|
103
|
+
const variant = await vRepo.findOne({
|
|
104
|
+
where: {
|
|
105
|
+
id: line.variantId,
|
|
106
|
+
productId: line.productId
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
if (!variant) return `Variant #${line.variantId} not found for ${name}`;
|
|
110
|
+
const inv = Number(variant.inventory ?? 0);
|
|
111
|
+
if (inv < line.quantity) {
|
|
112
|
+
return `Insufficient variant stock for ${name}: available ${inv}, required ${line.quantity}`;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
__name(validateInventoryForConfirmedOrderLines, "validateInventoryForConfirmedOrderLines");
|
|
118
|
+
async function validateInventoryForOrderBecomingConfirmed(ds, entityMap, prevSnap, nextLines) {
|
|
119
|
+
const mergedNext = mergeInventoryLines(nextLines);
|
|
120
|
+
const prevByKey = prevSnap && orderStatusHoldsStock(prevSnap.status) ? mergeInventoryLines(prevSnap.lines) : /* @__PURE__ */ new Map();
|
|
121
|
+
const nextByProduct = /* @__PURE__ */ new Map();
|
|
122
|
+
for (const line of mergedNext.values()) {
|
|
123
|
+
nextByProduct.set(line.productId, (nextByProduct.get(line.productId) ?? 0) + line.quantity);
|
|
124
|
+
}
|
|
125
|
+
const prevByProduct = /* @__PURE__ */ new Map();
|
|
126
|
+
for (const line of prevByKey.values()) {
|
|
127
|
+
prevByProduct.set(line.productId, (prevByProduct.get(line.productId) ?? 0) + line.quantity);
|
|
128
|
+
}
|
|
129
|
+
const pRepo = productRepo(ds, entityMap);
|
|
130
|
+
const vRepo = variantRepo(ds, entityMap);
|
|
131
|
+
for (const [productId, need] of nextByProduct) {
|
|
132
|
+
const row = await pRepo.findOne({
|
|
133
|
+
where: {
|
|
134
|
+
id: productId,
|
|
135
|
+
deleted: false
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
if (!row) return `Product #${productId} not found`;
|
|
139
|
+
if (row.type === "service") continue;
|
|
140
|
+
const name = row.name ?? String(productId);
|
|
141
|
+
const available = Number(row.quantity ?? 0) + (prevByProduct.get(productId) ?? 0);
|
|
142
|
+
if (available < need) {
|
|
143
|
+
return `Insufficient stock for ${name}: available ${available}, required ${need}`;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
for (const line of mergedNext.values()) {
|
|
147
|
+
if (!line.variantId || !vRepo) continue;
|
|
148
|
+
const row = await pRepo.findOne({
|
|
149
|
+
where: {
|
|
150
|
+
id: line.productId,
|
|
151
|
+
deleted: false
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
if (!row || row.type === "service") continue;
|
|
155
|
+
const name = row.name ?? String(line.productId);
|
|
156
|
+
const key = lineKey(line.productId, line.variantId);
|
|
157
|
+
const variant = await vRepo.findOne({
|
|
158
|
+
where: {
|
|
159
|
+
id: line.variantId,
|
|
160
|
+
productId: line.productId
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
if (!variant) return `Variant #${line.variantId} not found for ${name}`;
|
|
164
|
+
let inv = Number(variant.inventory ?? 0);
|
|
165
|
+
inv += prevByKey.get(key)?.quantity ?? 0;
|
|
166
|
+
if (inv < line.quantity) {
|
|
167
|
+
return `Insufficient variant stock for ${name}: available ${inv}, required ${line.quantity}`;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
__name(validateInventoryForOrderBecomingConfirmed, "validateInventoryForOrderBecomingConfirmed");
|
|
173
|
+
async function applyInventoryDelta(ds, entityMap, lines, sign, validateDeduct) {
|
|
174
|
+
const merged = mergeInventoryLines(lines);
|
|
175
|
+
const pRepo = productRepo(ds, entityMap);
|
|
176
|
+
const vRepo = variantRepo(ds, entityMap);
|
|
177
|
+
for (const line of merged.values()) {
|
|
178
|
+
const row = await pRepo.findOne({
|
|
179
|
+
where: sign === 1 ? {
|
|
180
|
+
id: line.productId
|
|
181
|
+
} : {
|
|
182
|
+
id: line.productId,
|
|
183
|
+
deleted: false
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
if (!row) return `Product #${line.productId} not found`;
|
|
187
|
+
if (row.type === "service") continue;
|
|
188
|
+
const name = row.name ?? String(line.productId);
|
|
189
|
+
const cur = Number(row.quantity ?? 0);
|
|
190
|
+
if (line.variantId && vRepo) {
|
|
191
|
+
const variant = await vRepo.findOne({
|
|
192
|
+
where: {
|
|
193
|
+
id: line.variantId,
|
|
194
|
+
productId: line.productId
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
if (!variant) return `Variant #${line.variantId} not found for ${name}`;
|
|
198
|
+
const inv = Number(variant.inventory ?? 0);
|
|
199
|
+
if (sign === -1) {
|
|
200
|
+
if (validateDeduct && inv < line.quantity) {
|
|
201
|
+
return `Insufficient variant stock for ${name}: available ${inv}, required ${line.quantity}`;
|
|
202
|
+
}
|
|
203
|
+
await vRepo.update(line.variantId, {
|
|
204
|
+
inventory: Math.max(0, inv - line.quantity)
|
|
205
|
+
});
|
|
206
|
+
} else {
|
|
207
|
+
await vRepo.update(line.variantId, {
|
|
208
|
+
inventory: inv + line.quantity
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (sign === -1) {
|
|
213
|
+
if (validateDeduct && cur < line.quantity) {
|
|
214
|
+
return `Insufficient stock for ${name}: available ${cur}, required ${line.quantity}`;
|
|
215
|
+
}
|
|
216
|
+
await pRepo.update(line.productId, {
|
|
217
|
+
quantity: Math.max(0, cur - line.quantity)
|
|
218
|
+
});
|
|
219
|
+
} else {
|
|
220
|
+
await pRepo.update(line.productId, {
|
|
221
|
+
quantity: cur + line.quantity
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
__name(applyInventoryDelta, "applyInventoryDelta");
|
|
228
|
+
async function reconcileOrderInventoryBetweenSnapshots(ds, entityMap, prev, next) {
|
|
229
|
+
const wasHeld = orderStatusHoldsStock(prev.status);
|
|
230
|
+
const isHeld = orderStatusHoldsStock(next.status);
|
|
231
|
+
if (wasHeld) {
|
|
232
|
+
const err = await applyInventoryDelta(ds, entityMap, prev.lines, 1, false);
|
|
233
|
+
if (err) return err;
|
|
234
|
+
}
|
|
235
|
+
if (isHeld) {
|
|
236
|
+
const err = await applyInventoryDelta(ds, entityMap, next.lines, -1, true);
|
|
237
|
+
if (err) return err;
|
|
238
|
+
}
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
__name(reconcileOrderInventoryBetweenSnapshots, "reconcileOrderInventoryBetweenSnapshots");
|
|
242
|
+
async function deductInventoryForConfirmedOrder(ds, entityMap, lines, options) {
|
|
243
|
+
const validate = options?.validate !== false;
|
|
244
|
+
if (validate) {
|
|
245
|
+
const err = await validateInventoryForConfirmedOrderLines(ds, entityMap, lines);
|
|
246
|
+
if (err) return err;
|
|
247
|
+
}
|
|
248
|
+
return applyInventoryDelta(ds, entityMap, lines, -1, validate);
|
|
249
|
+
}
|
|
250
|
+
__name(deductInventoryForConfirmedOrder, "deductInventoryForConfirmedOrder");
|
|
251
|
+
async function restoreInventoryForCancelledOrder(ds, entityMap, lines) {
|
|
252
|
+
return applyInventoryDelta(ds, entityMap, lines, 1, false);
|
|
253
|
+
}
|
|
254
|
+
__name(restoreInventoryForCancelledOrder, "restoreInventoryForCancelledOrder");
|
|
255
|
+
|
|
256
|
+
export { deductInventoryForConfirmedOrder, mergeInventoryLines, orderInventorySnapshotFromRow, orderStatusHoldsStock, reconcileOrderInventoryBetweenSnapshots, restoreInventoryForCancelledOrder, validateInventoryForConfirmedOrderLines, validateInventoryForOrderBecomingConfirmed };
|
|
@@ -6,6 +6,7 @@ var chunkUSNT2KNT_cjs = require('./chunk-USNT2KNT.cjs');
|
|
|
6
6
|
var EVENT_ORDER_TEMPLATE_KEY = "eventOrderPlaced";
|
|
7
7
|
var EVENT_ORDER_TEMPLATE_VARIABLES = [
|
|
8
8
|
"eventName",
|
|
9
|
+
"vendorName",
|
|
9
10
|
"eventSlug",
|
|
10
11
|
"venue",
|
|
11
12
|
"startDate",
|
|
@@ -33,6 +34,7 @@ var EVENT_ORDER_WHATSAPP_PARAM_KEYS = [
|
|
|
33
34
|
];
|
|
34
35
|
var EVENT_ORDER_TEMPLATE_VARIABLE_HINTS = {
|
|
35
36
|
eventName: "Event title",
|
|
37
|
+
vendorName: "Vendor / store name",
|
|
36
38
|
eventSlug: "Event URL slug",
|
|
37
39
|
venue: "Venue name",
|
|
38
40
|
startDate: "Formatted event start",
|
|
@@ -50,12 +50,13 @@ chunkUSNT2KNT_cjs.__name(getPermissionableEntityKeys, "getPermissionableEntityKe
|
|
|
50
50
|
function permissionRowsToRecord(rows) {
|
|
51
51
|
const out = {};
|
|
52
52
|
if (!rows?.length) return out;
|
|
53
|
+
const flag = /* @__PURE__ */ chunkUSNT2KNT_cjs.__name((v) => v === true || v === 1 || v === "1" || v === "t" || v === "true", "flag");
|
|
53
54
|
for (const p of rows) {
|
|
54
55
|
out[p.entity] = {
|
|
55
|
-
c:
|
|
56
|
-
r:
|
|
57
|
-
u:
|
|
58
|
-
d:
|
|
56
|
+
c: flag(p.canCreate),
|
|
57
|
+
r: flag(p.canRead),
|
|
58
|
+
u: flag(p.canUpdate),
|
|
59
|
+
d: flag(p.canDelete)
|
|
59
60
|
};
|
|
60
61
|
}
|
|
61
62
|
return out;
|
|
@@ -138,11 +139,12 @@ var VENDOR_STORE_RBAC_ENTITIES = /* @__PURE__ */ new Set([
|
|
|
138
139
|
"order_addresses",
|
|
139
140
|
"event_products"
|
|
140
141
|
]);
|
|
141
|
-
var
|
|
142
|
+
var VENDOR_GROUP_NAME = "Vendor";
|
|
143
|
+
var VENDOR_OWNER_GROUP_NAME = VENDOR_GROUP_NAME;
|
|
142
144
|
function isVendorGroupName(name) {
|
|
143
145
|
if (!name?.trim()) return false;
|
|
144
146
|
const n = name.trim().toLowerCase();
|
|
145
|
-
return n ===
|
|
147
|
+
return n === "vendor" || n === "vendor owner" || n.includes("vendor");
|
|
146
148
|
}
|
|
147
149
|
chunkUSNT2KNT_cjs.__name(isVendorGroupName, "isVendorGroupName");
|
|
148
150
|
function isPlatformAdministrator(user) {
|
|
@@ -165,10 +167,8 @@ function isVendorOwner(user) {
|
|
|
165
167
|
if (user?.isVendorOwner === true) return true;
|
|
166
168
|
if (!user?.email || isPlatformAdministrator(user)) return false;
|
|
167
169
|
if (user.isVendorRoleOwner === true) return true;
|
|
168
|
-
if (user.vendorRole === "staff") return false;
|
|
169
170
|
if (user.vendorRole === "owner") return true;
|
|
170
|
-
|
|
171
|
-
return user.groupName?.trim().toLowerCase() === VENDOR_OWNER_GROUP_NAME.toLowerCase();
|
|
171
|
+
return false;
|
|
172
172
|
}
|
|
173
173
|
chunkUSNT2KNT_cjs.__name(isVendorOwner, "isVendorOwner");
|
|
174
174
|
function canManageVendorTeam(user) {
|
|
@@ -206,7 +206,7 @@ chunkUSNT2KNT_cjs.__name(resolveVendorScopeFromSessionUser, "resolveVendorScopeF
|
|
|
206
206
|
function vendorPortalFlagsFromUser(input) {
|
|
207
207
|
const vendorIds = input.vendorIds ?? [];
|
|
208
208
|
const isVendorPortal = !input.isRBACAdmin && (vendorIds.length > 0 || isVendorGroupName(input.groupName));
|
|
209
|
-
const isVendorOwner2 = isVendorPortal && (input.isVendorRoleOwner === true || input.vendorRole
|
|
209
|
+
const isVendorOwner2 = isVendorPortal && (input.isVendorRoleOwner === true || input.vendorRole === "owner");
|
|
210
210
|
return {
|
|
211
211
|
isVendorPortal,
|
|
212
212
|
isVendorOwner: isVendorOwner2
|
|
@@ -463,7 +463,8 @@ function explainSessionEntityAccess(user, entity, action) {
|
|
|
463
463
|
const isStaff = user.vendorRole === "staff";
|
|
464
464
|
const vendorPerms = user.vendorEntityPerms;
|
|
465
465
|
const hasVendorRolePerms = vendorPerms != null && Object.keys(vendorPerms).length > 0;
|
|
466
|
-
|
|
466
|
+
const enforceVendorRoleMatrix = vendorIds.length > 0 && (hasVendorRolePerms || user.vendorRoleId != null);
|
|
467
|
+
if (enforceVendorRoleMatrix) {
|
|
467
468
|
const vendorRbacSet = new Set(VENDOR_RBAC_ENTITIES);
|
|
468
469
|
if (vendorRbacSet.has(entity) || entity === "analytics") {
|
|
469
470
|
if (entity === "analytics" && action === "read") {
|
|
@@ -605,7 +606,7 @@ async function logEntityAccessDecision(dataSource, context, user, entity, action
|
|
|
605
606
|
const id = Number(user.id);
|
|
606
607
|
if (Number.isFinite(id)) {
|
|
607
608
|
try {
|
|
608
|
-
const { loadDbPermissionsForUser } = await import('./rbac-debug-db-
|
|
609
|
+
const { loadDbPermissionsForUser } = await import('./rbac-debug-db-6PWTLBEL.cjs');
|
|
609
610
|
dbPermissions = await loadDbPermissionsForUser(dataSource, id);
|
|
610
611
|
} catch (e) {
|
|
611
612
|
dbPermissions = {
|
|
@@ -630,6 +631,7 @@ exports.ADMIN_GROUP_NAME = ADMIN_GROUP_NAME;
|
|
|
630
631
|
exports.DEFAULT_VENDOR_ROLE_DEFS = DEFAULT_VENDOR_ROLE_DEFS;
|
|
631
632
|
exports.SUPER_ADMIN_GROUP_ID = SUPER_ADMIN_GROUP_ID;
|
|
632
633
|
exports.VENDOR_ADMIN_GROUP_ID = VENDOR_ADMIN_GROUP_ID;
|
|
634
|
+
exports.VENDOR_GROUP_NAME = VENDOR_GROUP_NAME;
|
|
633
635
|
exports.VENDOR_OWNER_GROUP_NAME = VENDOR_OWNER_GROUP_NAME;
|
|
634
636
|
exports.VENDOR_RBAC_ENTITIES = VENDOR_RBAC_ENTITIES;
|
|
635
637
|
exports.VENDOR_SCOPED_STORE_ENTITIES = VENDOR_SCOPED_STORE_ENTITIES;
|