@infuro/cms-core 1.0.41 → 1.0.42
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 +5 -18
- package/dist/admin.cjs +903 -287
- package/dist/admin.d.cts +11 -1
- package/dist/admin.d.ts +11 -1
- package/dist/admin.js +903 -287
- package/dist/api.cjs +35 -35
- package/dist/api.js +3 -3
- package/dist/auth.cjs +51 -51
- package/dist/auth.js +3 -3
- package/dist/{chunk-UXMDSNIG.js → chunk-BLR6H5GL.js} +1 -1
- package/dist/{chunk-P7QCLE5W.js → chunk-DN65KDIA.js} +11 -1
- package/dist/{chunk-QU554KAZ.cjs → chunk-GINYYPXK.cjs} +796 -149
- package/dist/{chunk-4BG7XYSH.js → chunk-I6NH72MO.js} +1 -1
- package/dist/{chunk-ETZN4OQI.cjs → chunk-TAHX46EI.cjs} +6 -6
- package/dist/{chunk-EG4ICILK.js → chunk-W2NL365N.js} +745 -110
- package/dist/{chunk-WMXPKKXU.cjs → chunk-X6UQFV4X.cjs} +11 -1
- package/dist/{chunk-OIGCAGH7.cjs → chunk-ZMRQ72F6.cjs} +7 -7
- package/dist/index.cjs +290 -242
- package/dist/index.d.cts +110 -5
- package/dist/index.d.ts +110 -5
- package/dist/index.js +6 -6
- package/dist/migrations/1781300000000-BrandIsCatalog.ts +61 -0
- package/dist/migrations/1781400000000-ComboEventIdNullable.ts +30 -0
- package/dist/migrations/1781500000000-ProductApprovalWorkflow.ts +30 -0
- package/dist/migrations/1781600000000-ProductApprovalStatusColumn.ts +53 -0
- package/dist/migrations/1781700000000-EventApprovalWorkflow.ts +32 -0
- package/dist/{rbac-debug-db-QWHOENBR.js → rbac-debug-db-2SGNLANF.js} +1 -1
- package/dist/{rbac-debug-db-KHG4FJC3.cjs → rbac-debug-db-4Z6A425H.cjs} +2 -2
- package/package.json +1 -1
|
@@ -5,8 +5,8 @@ import { queueEmail, queueVendorOnboardEmails, registerEmailQueueProcessor } fro
|
|
|
5
5
|
import { getSmsTemplateDefault, SMS_MESSAGE_TEMPLATE_DEFAULTS } from './chunk-MQBT33IV.js';
|
|
6
6
|
import { EVENT_ORDER_MESSAGE_TEMPLATE_DEFAULTS, EVENT_ORDER_TEMPLATE_KEY, EVENT_ORDER_TEMPLATE_VARIABLES } from './chunk-KFFB6EMZ.js';
|
|
7
7
|
import { JOB_RUNNER_QUEUE } from './chunk-GO7PPYNU.js';
|
|
8
|
-
import { canManageRoles, sessionHasEntityAccess } from './chunk-
|
|
9
|
-
import { permissionRowsToRecord, logRbac, isSuperAdmin, vendorPortalFlagsFromUser, VENDOR_SCOPED_STORE_ENTITIES, isVendorPortalUser, getPermissionableEntityKeys, VENDOR_STORE_RBAC_ENTITIES, isSuperAdminGroupName, VENDOR_RBAC_ENTITIES, VENDOR_VIEWER_ROLE_NAME, DEFAULT_VENDOR_ROLE_DEFS, VENDOR_OWNER_GROUP_NAME, resolveVendorScopeFromSessionUser, canManageVendorRoles, isPlatformAdministrator, canManageVendorTeam, resolveDisabledMultiVendorScope, logEntityAccessDecision, explainSessionEntityAccess } from './chunk-
|
|
8
|
+
import { canManageRoles, sessionHasEntityAccess } from './chunk-BLR6H5GL.js';
|
|
9
|
+
import { permissionRowsToRecord, logRbac, isSuperAdmin, vendorPortalFlagsFromUser, VENDOR_SCOPED_STORE_ENTITIES, isVendorPortalUser, getPermissionableEntityKeys, VENDOR_STORE_RBAC_ENTITIES, isSuperAdminGroupName, VENDOR_RBAC_ENTITIES, VENDOR_VIEWER_ROLE_NAME, DEFAULT_VENDOR_ROLE_DEFS, VENDOR_OWNER_GROUP_NAME, resolveVendorScopeFromSessionUser, canManageVendorRoles, isPlatformAdministrator, canManageVendorTeam, resolveDisabledMultiVendorScope, logEntityAccessDecision, explainSessionEntityAccess } from './chunk-DN65KDIA.js';
|
|
10
10
|
import { queueErp } from './chunk-SYBOCAWB.js';
|
|
11
11
|
import { isErpIntegrationEnabled } from './chunk-JC6DLWTE.js';
|
|
12
12
|
import { __name } from './chunk-SHUYVCID.js';
|
|
@@ -94,6 +94,79 @@ async function loadUserVendorContext(dataSource, userId, preferredVendorId) {
|
|
|
94
94
|
}
|
|
95
95
|
__name(loadUserVendorContext, "loadUserVendorContext");
|
|
96
96
|
|
|
97
|
+
// src/lib/vendor-catalog-create-flags.ts
|
|
98
|
+
var ALL_OFF = {
|
|
99
|
+
categories: false,
|
|
100
|
+
collections: false,
|
|
101
|
+
brands: false
|
|
102
|
+
};
|
|
103
|
+
var cachedFlags = null;
|
|
104
|
+
function invalidateVendorCatalogCreateFlagsCache() {
|
|
105
|
+
cachedFlags = null;
|
|
106
|
+
}
|
|
107
|
+
__name(invalidateVendorCatalogCreateFlagsCache, "invalidateVendorCatalogCreateFlagsCache");
|
|
108
|
+
function parseTrue(value) {
|
|
109
|
+
return value === "true";
|
|
110
|
+
}
|
|
111
|
+
__name(parseTrue, "parseTrue");
|
|
112
|
+
async function isMultiVendorEnabled(dataSource) {
|
|
113
|
+
try {
|
|
114
|
+
const rows = await dataSource.query(`
|
|
115
|
+
SELECT value FROM configs
|
|
116
|
+
WHERE settings = 'multi_vendor' AND key = 'enabled' AND deleted = false
|
|
117
|
+
LIMIT 1
|
|
118
|
+
`);
|
|
119
|
+
return rows.length === 0 || rows[0].value !== "false";
|
|
120
|
+
} catch {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
__name(isMultiVendorEnabled, "isMultiVendorEnabled");
|
|
125
|
+
async function getVendorCatalogCreateFlags(dataSource) {
|
|
126
|
+
if (cachedFlags !== null) return cachedFlags;
|
|
127
|
+
const multiVendorEnabled = await isMultiVendorEnabled(dataSource);
|
|
128
|
+
if (!multiVendorEnabled) {
|
|
129
|
+
cachedFlags = {
|
|
130
|
+
...ALL_OFF
|
|
131
|
+
};
|
|
132
|
+
return cachedFlags;
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
const rows = await dataSource.query(`
|
|
136
|
+
SELECT key, value FROM configs
|
|
137
|
+
WHERE settings = 'multi_vendor'
|
|
138
|
+
AND key IN (
|
|
139
|
+
'vendorCanCreateCategories',
|
|
140
|
+
'vendorCanCreateCollections',
|
|
141
|
+
'vendorCanCreateBrands'
|
|
142
|
+
)
|
|
143
|
+
AND deleted = false
|
|
144
|
+
`);
|
|
145
|
+
const map = new Map(rows.map((r) => [
|
|
146
|
+
r.key,
|
|
147
|
+
r.value
|
|
148
|
+
]));
|
|
149
|
+
cachedFlags = {
|
|
150
|
+
categories: parseTrue(map.get("vendorCanCreateCategories")),
|
|
151
|
+
collections: parseTrue(map.get("vendorCanCreateCollections")),
|
|
152
|
+
brands: parseTrue(map.get("vendorCanCreateBrands"))
|
|
153
|
+
};
|
|
154
|
+
} catch {
|
|
155
|
+
cachedFlags = {
|
|
156
|
+
...ALL_OFF
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
return cachedFlags;
|
|
160
|
+
}
|
|
161
|
+
__name(getVendorCatalogCreateFlags, "getVendorCatalogCreateFlags");
|
|
162
|
+
function vendorCanCreateResource(resource, flags) {
|
|
163
|
+
if (resource === "product_categories") return flags.categories;
|
|
164
|
+
if (resource === "collections") return flags.collections;
|
|
165
|
+
if (resource === "brands") return flags.brands;
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
__name(vendorCanCreateResource, "vendorCanCreateResource");
|
|
169
|
+
|
|
97
170
|
// src/lib/hydrate-vendor-session-user.ts
|
|
98
171
|
async function hydrateVendorSessionUser(dataSource, user) {
|
|
99
172
|
if (!user?.email) return user;
|
|
@@ -196,6 +269,7 @@ __name(hydrateVendorSessionUser, "hydrateVendorSessionUser");
|
|
|
196
269
|
var cachedMultiVendorEnabled = null;
|
|
197
270
|
function invalidateMultiVendorCache() {
|
|
198
271
|
cachedMultiVendorEnabled = null;
|
|
272
|
+
invalidateVendorCatalogCreateFlagsCache();
|
|
199
273
|
}
|
|
200
274
|
__name(invalidateMultiVendorCache, "invalidateMultiVendorCache");
|
|
201
275
|
async function checkMultiVendorEnabled(dataSource) {
|
|
@@ -234,6 +308,279 @@ async function checkEventsEnabled(dataSource) {
|
|
|
234
308
|
}
|
|
235
309
|
__name(checkEventsEnabled, "checkEventsEnabled");
|
|
236
310
|
|
|
311
|
+
// src/lib/product-approval.ts
|
|
312
|
+
var PRODUCT_APPROVAL_STATUSES = [
|
|
313
|
+
"pending",
|
|
314
|
+
"approved",
|
|
315
|
+
"rejected"
|
|
316
|
+
];
|
|
317
|
+
var APPROVAL_SET = new Set(PRODUCT_APPROVAL_STATUSES);
|
|
318
|
+
var PRODUCT_STATUSES = /* @__PURE__ */ new Set([
|
|
319
|
+
"draft",
|
|
320
|
+
"available",
|
|
321
|
+
"reserved",
|
|
322
|
+
"sold"
|
|
323
|
+
]);
|
|
324
|
+
var cachedRequireApproval = null;
|
|
325
|
+
function invalidateRequireProductApprovalCache() {
|
|
326
|
+
cachedRequireApproval = null;
|
|
327
|
+
}
|
|
328
|
+
__name(invalidateRequireProductApprovalCache, "invalidateRequireProductApprovalCache");
|
|
329
|
+
function parseTrue2(value) {
|
|
330
|
+
return value === "true";
|
|
331
|
+
}
|
|
332
|
+
__name(parseTrue2, "parseTrue");
|
|
333
|
+
async function getRequireProductApproval(dataSource) {
|
|
334
|
+
if (cachedRequireApproval !== null) return cachedRequireApproval;
|
|
335
|
+
const multiVendorEnabled = await checkMultiVendorEnabled(dataSource);
|
|
336
|
+
if (!multiVendorEnabled) {
|
|
337
|
+
cachedRequireApproval = false;
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
try {
|
|
341
|
+
const rows = await dataSource.query(`
|
|
342
|
+
SELECT value FROM configs
|
|
343
|
+
WHERE settings = 'multi_vendor' AND key = 'requireProductApproval' AND deleted = false
|
|
344
|
+
LIMIT 1
|
|
345
|
+
`);
|
|
346
|
+
cachedRequireApproval = rows.length > 0 && parseTrue2(rows[0].value);
|
|
347
|
+
} catch {
|
|
348
|
+
cachedRequireApproval = false;
|
|
349
|
+
}
|
|
350
|
+
return cachedRequireApproval;
|
|
351
|
+
}
|
|
352
|
+
__name(getRequireProductApproval, "getRequireProductApproval");
|
|
353
|
+
function applyVendorProductCreateApproval(persistBody, opts) {
|
|
354
|
+
if (!opts.isVendor || !opts.requireApproval) return;
|
|
355
|
+
persistBody.approvalStatus = "pending";
|
|
356
|
+
if (persistBody.status === "available") persistBody.status = "draft";
|
|
357
|
+
persistBody.rejectionReason = null;
|
|
358
|
+
persistBody.rejectedAt = null;
|
|
359
|
+
persistBody.rejectedBy = null;
|
|
360
|
+
}
|
|
361
|
+
__name(applyVendorProductCreateApproval, "applyVendorProductCreateApproval");
|
|
362
|
+
function assertProductApprovalUpdate(opts) {
|
|
363
|
+
const fromApproval = opts.fromApproval == null || opts.fromApproval === "" ? null : String(opts.fromApproval);
|
|
364
|
+
const toApproval = opts.toApproval == null || opts.toApproval === "" ? null : String(opts.toApproval);
|
|
365
|
+
const fromStatus = String(opts.fromStatus || "draft");
|
|
366
|
+
const toStatus = String(opts.toStatus || fromStatus);
|
|
367
|
+
if (opts.statusChanged && !PRODUCT_STATUSES.has(toStatus)) {
|
|
368
|
+
return {
|
|
369
|
+
ok: false,
|
|
370
|
+
error: `Invalid product status: ${toStatus}`
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
if (opts.approvalChanged && toApproval != null && !APPROVAL_SET.has(toApproval)) {
|
|
374
|
+
return {
|
|
375
|
+
ok: false,
|
|
376
|
+
error: `Invalid approval status: ${toApproval}`
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
if (!opts.requireApproval) {
|
|
380
|
+
if (opts.isVendor && opts.approvalChanged) {
|
|
381
|
+
return {
|
|
382
|
+
ok: false,
|
|
383
|
+
error: "Vendors cannot change approval status"
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
return {
|
|
387
|
+
ok: true
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
if (opts.isVendor) {
|
|
391
|
+
if (opts.approvalChanged) {
|
|
392
|
+
return {
|
|
393
|
+
ok: false,
|
|
394
|
+
error: "Vendors cannot change approval status"
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
if (opts.statusChanged && toStatus === "available" && fromApproval !== "approved") {
|
|
398
|
+
return {
|
|
399
|
+
ok: false,
|
|
400
|
+
error: "Product must be approved before it can be available"
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
if (fromApproval === "rejected" && opts.statusChanged && toStatus === "available") {
|
|
404
|
+
return {
|
|
405
|
+
ok: false,
|
|
406
|
+
error: "Rejected product cannot be made available"
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
return {
|
|
410
|
+
ok: true
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
if (opts.approvalChanged && toApproval === "rejected") {
|
|
414
|
+
const reason = String(opts.rejectionReason ?? "").trim();
|
|
415
|
+
if (!reason) return {
|
|
416
|
+
ok: false,
|
|
417
|
+
error: "Rejection reason is required"
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
return {
|
|
421
|
+
ok: true
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
__name(assertProductApprovalUpdate, "assertProductApprovalUpdate");
|
|
425
|
+
function applyApprovalStatusSideEffects(updatePayload, opts) {
|
|
426
|
+
const to = opts.toApproval == null || opts.toApproval === "" ? null : String(opts.toApproval);
|
|
427
|
+
if (to == null) return;
|
|
428
|
+
if (to === "approved") {
|
|
429
|
+
updatePayload.approvalStatus = "approved";
|
|
430
|
+
updatePayload.status = "available";
|
|
431
|
+
updatePayload.rejectionReason = null;
|
|
432
|
+
updatePayload.rejectedAt = null;
|
|
433
|
+
updatePayload.rejectedBy = null;
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
if (to === "rejected") {
|
|
437
|
+
updatePayload.approvalStatus = "rejected";
|
|
438
|
+
updatePayload.rejectionReason = String(opts.rejectionReason ?? "").trim();
|
|
439
|
+
updatePayload.rejectedAt = /* @__PURE__ */ new Date();
|
|
440
|
+
updatePayload.rejectedBy = opts.rejectedBy != null && Number.isFinite(opts.rejectedBy) ? opts.rejectedBy : null;
|
|
441
|
+
const nextStatus = "status" in updatePayload ? String(updatePayload.status) : opts.currentStatus;
|
|
442
|
+
if (nextStatus === "available") updatePayload.status = "draft";
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
if (to === "pending") {
|
|
446
|
+
updatePayload.approvalStatus = "pending";
|
|
447
|
+
updatePayload.rejectionReason = null;
|
|
448
|
+
updatePayload.rejectedAt = null;
|
|
449
|
+
updatePayload.rejectedBy = null;
|
|
450
|
+
const nextStatus = "status" in updatePayload ? String(updatePayload.status) : opts.currentStatus;
|
|
451
|
+
if (nextStatus === "available") updatePayload.status = "draft";
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
__name(applyApprovalStatusSideEffects, "applyApprovalStatusSideEffects");
|
|
455
|
+
|
|
456
|
+
// src/lib/event-approval.ts
|
|
457
|
+
var EVENT_APPROVAL_STATUSES = [
|
|
458
|
+
"pending",
|
|
459
|
+
"approved",
|
|
460
|
+
"rejected"
|
|
461
|
+
];
|
|
462
|
+
var APPROVAL_SET2 = new Set(EVENT_APPROVAL_STATUSES);
|
|
463
|
+
var cachedRequireApproval2 = null;
|
|
464
|
+
function invalidateRequireEventApprovalCache() {
|
|
465
|
+
cachedRequireApproval2 = null;
|
|
466
|
+
}
|
|
467
|
+
__name(invalidateRequireEventApprovalCache, "invalidateRequireEventApprovalCache");
|
|
468
|
+
function parseTrue3(value) {
|
|
469
|
+
return value === "true";
|
|
470
|
+
}
|
|
471
|
+
__name(parseTrue3, "parseTrue");
|
|
472
|
+
async function getRequireEventApproval(dataSource) {
|
|
473
|
+
if (cachedRequireApproval2 !== null) return cachedRequireApproval2;
|
|
474
|
+
const [eventsOn, multiVendorOn] = await Promise.all([
|
|
475
|
+
checkEventsEnabled(dataSource),
|
|
476
|
+
checkMultiVendorEnabled(dataSource)
|
|
477
|
+
]);
|
|
478
|
+
if (!eventsOn || !multiVendorOn) {
|
|
479
|
+
cachedRequireApproval2 = false;
|
|
480
|
+
return false;
|
|
481
|
+
}
|
|
482
|
+
try {
|
|
483
|
+
const rows = await dataSource.query(`
|
|
484
|
+
SELECT value FROM configs
|
|
485
|
+
WHERE settings = 'events' AND key = 'requireEventApproval' AND deleted = false
|
|
486
|
+
LIMIT 1
|
|
487
|
+
`);
|
|
488
|
+
cachedRequireApproval2 = rows.length > 0 && parseTrue3(rows[0].value);
|
|
489
|
+
} catch {
|
|
490
|
+
cachedRequireApproval2 = false;
|
|
491
|
+
}
|
|
492
|
+
return cachedRequireApproval2;
|
|
493
|
+
}
|
|
494
|
+
__name(getRequireEventApproval, "getRequireEventApproval");
|
|
495
|
+
function applyVendorEventCreateApproval(persistBody, opts) {
|
|
496
|
+
if (!opts.isVendor || !opts.requireApproval) return;
|
|
497
|
+
persistBody.approvalStatus = "pending";
|
|
498
|
+
persistBody.isActive = false;
|
|
499
|
+
persistBody.rejectionReason = null;
|
|
500
|
+
persistBody.rejectedAt = null;
|
|
501
|
+
persistBody.rejectedBy = null;
|
|
502
|
+
}
|
|
503
|
+
__name(applyVendorEventCreateApproval, "applyVendorEventCreateApproval");
|
|
504
|
+
function assertEventApprovalUpdate(opts) {
|
|
505
|
+
const fromApproval = opts.fromApproval == null || opts.fromApproval === "" ? null : String(opts.fromApproval);
|
|
506
|
+
const toApproval = opts.toApproval == null || opts.toApproval === "" ? null : String(opts.toApproval);
|
|
507
|
+
if (opts.approvalChanged && toApproval != null && !APPROVAL_SET2.has(toApproval)) {
|
|
508
|
+
return {
|
|
509
|
+
ok: false,
|
|
510
|
+
error: `Invalid approval status: ${toApproval}`
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
if (!opts.requireApproval) {
|
|
514
|
+
if (opts.isVendor && opts.approvalChanged) {
|
|
515
|
+
return {
|
|
516
|
+
ok: false,
|
|
517
|
+
error: "Vendors cannot change approval status"
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
return {
|
|
521
|
+
ok: true
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
if (opts.isVendor) {
|
|
525
|
+
if (opts.approvalChanged) {
|
|
526
|
+
return {
|
|
527
|
+
ok: false,
|
|
528
|
+
error: "Vendors cannot change approval status"
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
if (opts.activeChanged && opts.toActive && fromApproval !== "approved") {
|
|
532
|
+
return {
|
|
533
|
+
ok: false,
|
|
534
|
+
error: "Event must be approved before it can be activated"
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
return {
|
|
538
|
+
ok: true
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
if (opts.approvalChanged && toApproval === "rejected") {
|
|
542
|
+
const reason = String(opts.rejectionReason ?? "").trim();
|
|
543
|
+
if (!reason) return {
|
|
544
|
+
ok: false,
|
|
545
|
+
error: "Rejection reason is required"
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
return {
|
|
549
|
+
ok: true
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
__name(assertEventApprovalUpdate, "assertEventApprovalUpdate");
|
|
553
|
+
function applyEventApprovalStatusSideEffects(updatePayload, opts) {
|
|
554
|
+
const to = opts.toApproval == null || opts.toApproval === "" ? null : String(opts.toApproval);
|
|
555
|
+
if (to == null) return;
|
|
556
|
+
if (to === "approved") {
|
|
557
|
+
updatePayload.approvalStatus = "approved";
|
|
558
|
+
updatePayload.isActive = true;
|
|
559
|
+
updatePayload.rejectionReason = null;
|
|
560
|
+
updatePayload.rejectedAt = null;
|
|
561
|
+
updatePayload.rejectedBy = null;
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
if (to === "rejected") {
|
|
565
|
+
updatePayload.approvalStatus = "rejected";
|
|
566
|
+
updatePayload.rejectionReason = String(opts.rejectionReason ?? "").trim();
|
|
567
|
+
updatePayload.rejectedAt = /* @__PURE__ */ new Date();
|
|
568
|
+
updatePayload.rejectedBy = opts.rejectedBy != null && Number.isFinite(opts.rejectedBy) ? opts.rejectedBy : null;
|
|
569
|
+
const nextActive = "isActive" in updatePayload ? Boolean(updatePayload.isActive) : opts.currentActive;
|
|
570
|
+
if (nextActive) updatePayload.isActive = false;
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
if (to === "pending") {
|
|
574
|
+
updatePayload.approvalStatus = "pending";
|
|
575
|
+
updatePayload.rejectionReason = null;
|
|
576
|
+
updatePayload.rejectedAt = null;
|
|
577
|
+
updatePayload.rejectedBy = null;
|
|
578
|
+
const nextActive = "isActive" in updatePayload ? Boolean(updatePayload.isActive) : opts.currentActive;
|
|
579
|
+
if (nextActive) updatePayload.isActive = false;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
__name(applyEventApprovalStatusSideEffects, "applyEventApprovalStatusSideEffects");
|
|
583
|
+
|
|
237
584
|
// src/lib/default-vendor-id.ts
|
|
238
585
|
function getDefaultVendorId() {
|
|
239
586
|
const raw = process.env.DEFAULT_VENDOR_ID;
|
|
@@ -269,17 +616,20 @@ async function assertCatalogCategoryId(dataSource, categoriesEntity, categoryId,
|
|
|
269
616
|
const row = await repo.findOne({
|
|
270
617
|
where: {
|
|
271
618
|
id,
|
|
272
|
-
deleted: false
|
|
273
|
-
isCatalog: true
|
|
619
|
+
deleted: false
|
|
274
620
|
}
|
|
275
621
|
});
|
|
276
622
|
if (!row) {
|
|
277
623
|
return "Invalid catalog category. Choose one of the platform product category types.";
|
|
278
624
|
}
|
|
279
|
-
return null;
|
|
625
|
+
if (row.isCatalog === true) return null;
|
|
626
|
+
if (options?.allowVendorId != null && Number(row.vendorId) === options.allowVendorId && row.isCatalog !== true) {
|
|
627
|
+
return null;
|
|
628
|
+
}
|
|
629
|
+
return "Invalid catalog category. Choose one of the platform product category types.";
|
|
280
630
|
}
|
|
281
631
|
__name(assertCatalogCategoryId, "assertCatalogCategoryId");
|
|
282
|
-
async function
|
|
632
|
+
async function assertCollectionForVendorProduct(dataSource, collectionsEntity, collectionId, categoryId, vendorId, options) {
|
|
283
633
|
const cid = Number(collectionId);
|
|
284
634
|
if (!Number.isFinite(cid) || cid <= 0) return null;
|
|
285
635
|
if (!collectionsEntity) return "Collections are not configured";
|
|
@@ -290,11 +640,13 @@ async function assertVendorOwnedCollectionForProduct(dataSource, collectionsEnti
|
|
|
290
640
|
deleted: false
|
|
291
641
|
}
|
|
292
642
|
});
|
|
293
|
-
if (!row
|
|
294
|
-
return "Invalid collection. Choose
|
|
643
|
+
if (!row) {
|
|
644
|
+
return "Invalid collection. Choose a valid collection in this category.";
|
|
295
645
|
}
|
|
296
|
-
|
|
297
|
-
|
|
646
|
+
const isCatalog = row.isCatalog === true;
|
|
647
|
+
const isOwn = Number(row.vendorId) === vendorId && !isCatalog;
|
|
648
|
+
if (!isCatalog && !(options?.allowVendorOwned && isOwn)) {
|
|
649
|
+
return "Invalid collection. Choose one of the platform collections (or your own if allowed).";
|
|
298
650
|
}
|
|
299
651
|
const catId = Number(categoryId);
|
|
300
652
|
if (Number.isFinite(catId) && catId > 0 && Number(row.categoryId) !== catId) {
|
|
@@ -302,7 +654,7 @@ async function assertVendorOwnedCollectionForProduct(dataSource, collectionsEnti
|
|
|
302
654
|
}
|
|
303
655
|
return null;
|
|
304
656
|
}
|
|
305
|
-
__name(
|
|
657
|
+
__name(assertCollectionForVendorProduct, "assertCollectionForVendorProduct");
|
|
306
658
|
|
|
307
659
|
// src/lib/catalog-collection.ts
|
|
308
660
|
function isCatalogCollectionRow(row) {
|
|
@@ -316,7 +668,24 @@ function applyPlatformCatalogCollectionFields(persistBody) {
|
|
|
316
668
|
}
|
|
317
669
|
__name(applyPlatformCatalogCollectionFields, "applyPlatformCatalogCollectionFields");
|
|
318
670
|
|
|
671
|
+
// src/lib/catalog-brand.ts
|
|
672
|
+
function isCatalogBrandRow(row) {
|
|
673
|
+
return row?.isCatalog === true;
|
|
674
|
+
}
|
|
675
|
+
__name(isCatalogBrandRow, "isCatalogBrandRow");
|
|
676
|
+
function applyPlatformCatalogBrandFields(persistBody) {
|
|
677
|
+
persistBody.isCatalog = true;
|
|
678
|
+
delete persistBody.vendorId;
|
|
679
|
+
persistBody.vendorId = getDefaultVendorId();
|
|
680
|
+
}
|
|
681
|
+
__name(applyPlatformCatalogBrandFields, "applyPlatformCatalogBrandFields");
|
|
682
|
+
|
|
319
683
|
// src/api/vendor-scope-crud.ts
|
|
684
|
+
var CATALOG_LIST_RESOURCES = /* @__PURE__ */ new Set([
|
|
685
|
+
"product_categories",
|
|
686
|
+
"collections",
|
|
687
|
+
"brands"
|
|
688
|
+
]);
|
|
320
689
|
function repoHasVendorIdColumn(repo) {
|
|
321
690
|
return repo.metadata.columns.some((c) => c.propertyName === "vendorId");
|
|
322
691
|
}
|
|
@@ -325,7 +694,43 @@ function resourceUsesVendorScope(resource) {
|
|
|
325
694
|
return resource === "vendors" || VENDOR_SCOPED_STORE_ENTITIES.has(resource);
|
|
326
695
|
}
|
|
327
696
|
__name(resourceUsesVendorScope, "resourceUsesVendorScope");
|
|
328
|
-
function
|
|
697
|
+
function mergeWhereClause(where, extra) {
|
|
698
|
+
if (Array.isArray(where)) {
|
|
699
|
+
return where.map((w) => ({
|
|
700
|
+
...w,
|
|
701
|
+
...extra
|
|
702
|
+
}));
|
|
703
|
+
}
|
|
704
|
+
if (where && typeof where === "object" && Object.keys(where).length > 0) {
|
|
705
|
+
return {
|
|
706
|
+
...where,
|
|
707
|
+
...extra
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
return extra;
|
|
711
|
+
}
|
|
712
|
+
__name(mergeWhereClause, "mergeWhereClause");
|
|
713
|
+
function mergeCatalogOrOwnWhere(where, vendorId) {
|
|
714
|
+
const catalog = mergeWhereClause(where, {
|
|
715
|
+
isCatalog: true
|
|
716
|
+
});
|
|
717
|
+
const own = mergeWhereClause(where, {
|
|
718
|
+
vendorId,
|
|
719
|
+
isCatalog: false
|
|
720
|
+
});
|
|
721
|
+
const catalogArr = Array.isArray(catalog) ? catalog : [
|
|
722
|
+
catalog
|
|
723
|
+
];
|
|
724
|
+
const ownArr = Array.isArray(own) ? own : [
|
|
725
|
+
own
|
|
726
|
+
];
|
|
727
|
+
return [
|
|
728
|
+
...catalogArr,
|
|
729
|
+
...ownArr
|
|
730
|
+
];
|
|
731
|
+
}
|
|
732
|
+
__name(mergeCatalogOrOwnWhere, "mergeCatalogOrOwnWhere");
|
|
733
|
+
function mergeVendorScopeIntoWhere(where, scope, resource, flags) {
|
|
329
734
|
if (scope.type === "all") return where;
|
|
330
735
|
if (scope.type === "deny") {
|
|
331
736
|
if (resource === "vendors") {
|
|
@@ -342,38 +747,20 @@ function mergeVendorScopeIntoWhere(where, scope, resource) {
|
|
|
342
747
|
id: In(scope.vendorIds)
|
|
343
748
|
});
|
|
344
749
|
}
|
|
345
|
-
if (resource
|
|
750
|
+
if (CATALOG_LIST_RESOURCES.has(resource) && scope.type === "vendor") {
|
|
751
|
+
const canCreate = flags ? vendorCanCreateResource(resource, flags) : false;
|
|
752
|
+
if (canCreate) {
|
|
753
|
+
return mergeCatalogOrOwnWhere(where, scope.vendorId);
|
|
754
|
+
}
|
|
346
755
|
return mergeWhereClause(where, {
|
|
347
756
|
isCatalog: true
|
|
348
757
|
});
|
|
349
758
|
}
|
|
350
|
-
if (resource === "collections" && scope.type === "vendor") {
|
|
351
|
-
return mergeWhereClause(where, {
|
|
352
|
-
vendorId: scope.vendorId,
|
|
353
|
-
isCatalog: false
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
759
|
return mergeWhereClause(where, {
|
|
357
760
|
vendorId: scope.vendorId
|
|
358
761
|
});
|
|
359
762
|
}
|
|
360
763
|
__name(mergeVendorScopeIntoWhere, "mergeVendorScopeIntoWhere");
|
|
361
|
-
function mergeWhereClause(where, extra) {
|
|
362
|
-
if (Array.isArray(where)) {
|
|
363
|
-
return where.map((w) => ({
|
|
364
|
-
...w,
|
|
365
|
-
...extra
|
|
366
|
-
}));
|
|
367
|
-
}
|
|
368
|
-
if (where && typeof where === "object" && Object.keys(where).length > 0) {
|
|
369
|
-
return {
|
|
370
|
-
...where,
|
|
371
|
-
...extra
|
|
372
|
-
};
|
|
373
|
-
}
|
|
374
|
-
return extra;
|
|
375
|
-
}
|
|
376
|
-
__name(mergeWhereClause, "mergeWhereClause");
|
|
377
764
|
function applyVendorScopeToQueryBuilder(qb, alias, scope) {
|
|
378
765
|
if (scope.type === "all") return;
|
|
379
766
|
if (scope.type === "deny") {
|
|
@@ -385,7 +772,7 @@ function applyVendorScopeToQueryBuilder(qb, alias, scope) {
|
|
|
385
772
|
});
|
|
386
773
|
}
|
|
387
774
|
__name(applyVendorScopeToQueryBuilder, "applyVendorScopeToQueryBuilder");
|
|
388
|
-
function rowMatchesVendorScope(row, scope, resource) {
|
|
775
|
+
function rowMatchesVendorScope(row, scope, resource, flags) {
|
|
389
776
|
if (!row) return false;
|
|
390
777
|
if (scope.type === "all") return true;
|
|
391
778
|
if (scope.type === "deny") return false;
|
|
@@ -393,27 +780,32 @@ function rowMatchesVendorScope(row, scope, resource) {
|
|
|
393
780
|
const id = Number(row.id);
|
|
394
781
|
return scope.vendorIds.includes(id);
|
|
395
782
|
}
|
|
396
|
-
if (resource
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
return Number(row.vendorId) === scope.vendorId && !
|
|
783
|
+
if (CATALOG_LIST_RESOURCES.has(resource) && scope.type === "vendor") {
|
|
784
|
+
const isCatalog = resource === "product_categories" ? isCatalogCategoryRow(row) : resource === "collections" ? isCatalogCollectionRow(row) : isCatalogBrandRow(row);
|
|
785
|
+
if (isCatalog) return true;
|
|
786
|
+
const canCreate = flags ? vendorCanCreateResource(resource, flags) : false;
|
|
787
|
+
return canCreate && Number(row.vendorId) === scope.vendorId && !isCatalog;
|
|
401
788
|
}
|
|
402
789
|
return Number(row.vendorId) === scope.vendorId;
|
|
403
790
|
}
|
|
404
791
|
__name(rowMatchesVendorScope, "rowMatchesVendorScope");
|
|
405
|
-
function
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
__name(vendorCannotMutateCatalogCategories, "vendorCannotMutateCatalogCategories");
|
|
409
|
-
function vendorCannotMutateCatalogCollections(resource, scope, body) {
|
|
410
|
-
if (resource !== "collections" || scope.type !== "vendor") return false;
|
|
792
|
+
function vendorCannotMutateCatalogResource(resource, scope, flags, body) {
|
|
793
|
+
if (scope.type !== "vendor" || !CATALOG_LIST_RESOURCES.has(resource)) return false;
|
|
794
|
+
if (!vendorCanCreateResource(resource, flags)) return true;
|
|
411
795
|
return body?.isCatalog === true;
|
|
412
796
|
}
|
|
413
|
-
__name(
|
|
414
|
-
function
|
|
797
|
+
__name(vendorCannotMutateCatalogResource, "vendorCannotMutateCatalogResource");
|
|
798
|
+
function vendorCannotMutateExistingCatalogRow(resource, scope, row) {
|
|
799
|
+
if (scope.type !== "vendor" || !CATALOG_LIST_RESOURCES.has(resource) || !row) return false;
|
|
800
|
+
if (resource === "product_categories") return isCatalogCategoryRow(row);
|
|
801
|
+
if (resource === "collections") return isCatalogCollectionRow(row);
|
|
802
|
+
if (resource === "brands") return isCatalogBrandRow(row);
|
|
803
|
+
return false;
|
|
804
|
+
}
|
|
805
|
+
__name(vendorCannotMutateExistingCatalogRow, "vendorCannotMutateExistingCatalogRow");
|
|
806
|
+
function vendorScopeRowAccess(row, scope, resource, flags) {
|
|
415
807
|
if (!row) return "not_found";
|
|
416
|
-
if (rowMatchesVendorScope(row, scope, resource)) return "ok";
|
|
808
|
+
if (rowMatchesVendorScope(row, scope, resource, flags)) return "ok";
|
|
417
809
|
return scope.type === "vendor" ? "forbidden" : "not_found";
|
|
418
810
|
}
|
|
419
811
|
__name(vendorScopeRowAccess, "vendorScopeRowAccess");
|
|
@@ -445,14 +837,7 @@ function requireVendorIdForScopedCreate(resource, persistBody, scope, repo, cont
|
|
|
445
837
|
ok: true
|
|
446
838
|
};
|
|
447
839
|
}
|
|
448
|
-
if (resource === "collections" && persistBody.isCatalog === true) {
|
|
449
|
-
delete persistBody.vendorId;
|
|
450
|
-
persistBody.vendorId = getDefaultVendorId();
|
|
451
|
-
return {
|
|
452
|
-
ok: true
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
if (resource === "product_categories" && persistBody.isCatalog === true) {
|
|
840
|
+
if ((resource === "collections" || resource === "product_categories" || resource === "brands") && persistBody.isCatalog === true) {
|
|
456
841
|
delete persistBody.vendorId;
|
|
457
842
|
persistBody.vendorId = getDefaultVendorId();
|
|
458
843
|
return {
|
|
@@ -464,7 +849,7 @@ function requireVendorIdForScopedCreate(resource, persistBody, scope, repo, cont
|
|
|
464
849
|
};
|
|
465
850
|
enforceVendorIdOnCreateBody(persistBody, scope, repo);
|
|
466
851
|
if (scope.type === "vendor") {
|
|
467
|
-
if (resource === "collections") {
|
|
852
|
+
if (resource === "collections" || resource === "product_categories" || resource === "brands") {
|
|
468
853
|
persistBody.isCatalog = false;
|
|
469
854
|
}
|
|
470
855
|
return {
|
|
@@ -3411,6 +3796,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
3411
3796
|
const scope = await resolveScope();
|
|
3412
3797
|
const repo2 = dataSource.getRepository(entity);
|
|
3413
3798
|
const statusFilter = searchParams.get("status")?.trim();
|
|
3799
|
+
const approvalStatusFilter = searchParams.get("approvalStatus")?.trim();
|
|
3414
3800
|
const inventory = searchParams.get("inventory")?.trim();
|
|
3415
3801
|
let productWhere = {
|
|
3416
3802
|
deleted: false,
|
|
@@ -3418,6 +3804,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
3418
3804
|
};
|
|
3419
3805
|
productWhere = mergeVendorScopeIntoWhere(productWhere, scope, resource);
|
|
3420
3806
|
if (statusFilter) productWhere.status = statusFilter;
|
|
3807
|
+
if (approvalStatusFilter) productWhere.approvalStatus = approvalStatusFilter;
|
|
3421
3808
|
if (inventory === "in_stock") productWhere.quantity = MoreThan(0);
|
|
3422
3809
|
if (inventory === "out_of_stock") productWhere.quantity = 0;
|
|
3423
3810
|
for (const key of [
|
|
@@ -3718,6 +4105,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
3718
4105
|
where = mergeDeletedFalseWhere(repo, where);
|
|
3719
4106
|
if (resourceUsesVendorScope(resource)) {
|
|
3720
4107
|
const scope = await resolveScope();
|
|
4108
|
+
const catalogFlags = await getVendorCatalogCreateFlags(dataSource);
|
|
3721
4109
|
if (scope.type === "deny") {
|
|
3722
4110
|
where = resource === "vendors" ? {
|
|
3723
4111
|
id: -1
|
|
@@ -3726,7 +4114,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
3726
4114
|
};
|
|
3727
4115
|
} else if (resource === "collections") {
|
|
3728
4116
|
if (scope.type === "vendor") {
|
|
3729
|
-
where = mergeVendorScopeIntoWhere(where, scope, resource);
|
|
4117
|
+
where = mergeVendorScopeIntoWhere(where, scope, resource, catalogFlags);
|
|
3730
4118
|
} else if (searchParams.get("isCatalog") !== "true") {
|
|
3731
4119
|
where = mergeListWhereAnd(where, {
|
|
3732
4120
|
isCatalog: false
|
|
@@ -3734,14 +4122,22 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
3734
4122
|
}
|
|
3735
4123
|
} else if (resource === "product_categories") {
|
|
3736
4124
|
if (scope.type === "vendor") {
|
|
3737
|
-
where = mergeVendorScopeIntoWhere(where, scope, resource);
|
|
4125
|
+
where = mergeVendorScopeIntoWhere(where, scope, resource, catalogFlags);
|
|
4126
|
+
} else if (searchParams.get("isCatalog") !== "false") {
|
|
4127
|
+
where = mergeListWhereAnd(where, {
|
|
4128
|
+
isCatalog: true
|
|
4129
|
+
});
|
|
4130
|
+
}
|
|
4131
|
+
} else if (resource === "brands") {
|
|
4132
|
+
if (scope.type === "vendor") {
|
|
4133
|
+
where = mergeVendorScopeIntoWhere(where, scope, resource, catalogFlags);
|
|
3738
4134
|
} else if (searchParams.get("isCatalog") !== "false") {
|
|
3739
4135
|
where = mergeListWhereAnd(where, {
|
|
3740
4136
|
isCatalog: true
|
|
3741
4137
|
});
|
|
3742
4138
|
}
|
|
3743
4139
|
} else {
|
|
3744
|
-
where = mergeVendorScopeIntoWhere(where, scope, resource);
|
|
4140
|
+
where = mergeVendorScopeIntoWhere(where, scope, resource, catalogFlags);
|
|
3745
4141
|
}
|
|
3746
4142
|
}
|
|
3747
4143
|
let data;
|
|
@@ -3811,16 +4207,11 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
3811
4207
|
});
|
|
3812
4208
|
}
|
|
3813
4209
|
const body = rawPostBody;
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
}, {
|
|
3818
|
-
status: 403
|
|
3819
|
-
});
|
|
3820
|
-
}
|
|
3821
|
-
if (vendorCannotMutateCatalogCollections(resource, scopePost, body)) {
|
|
4210
|
+
const catalogFlagsPost = await getVendorCatalogCreateFlags(dataSource);
|
|
4211
|
+
if (vendorCannotMutateCatalogResource(resource, scopePost, catalogFlagsPost, body)) {
|
|
4212
|
+
const label = resource === "product_categories" ? "Categories" : resource === "collections" ? "Collections" : resource === "brands" ? "Brands" : "This resource";
|
|
3822
4213
|
return json({
|
|
3823
|
-
error:
|
|
4214
|
+
error: `${label} are managed by the platform administrator`
|
|
3824
4215
|
}, {
|
|
3825
4216
|
status: 403
|
|
3826
4217
|
});
|
|
@@ -4205,8 +4596,15 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
4205
4596
|
}
|
|
4206
4597
|
if (resource === "products") {
|
|
4207
4598
|
const scopeForProduct = await resolveScope();
|
|
4599
|
+
const productFlags = await getVendorCatalogCreateFlags(dataSource);
|
|
4600
|
+
const requireApproval = await getRequireProductApproval(dataSource);
|
|
4601
|
+
applyVendorProductCreateApproval(persistBody, {
|
|
4602
|
+
isVendor: scopeForProduct.type === "vendor",
|
|
4603
|
+
requireApproval
|
|
4604
|
+
});
|
|
4208
4605
|
const categoryErr = await assertCatalogCategoryId(dataSource, entityMap.product_categories, persistBody.categoryId, {
|
|
4209
|
-
required: scopeForProduct.type === "vendor"
|
|
4606
|
+
required: scopeForProduct.type === "vendor",
|
|
4607
|
+
allowVendorId: scopeForProduct.type === "vendor" && productFlags.categories ? scopeForProduct.vendorId : void 0
|
|
4210
4608
|
});
|
|
4211
4609
|
if (categoryErr) return json({
|
|
4212
4610
|
error: categoryErr
|
|
@@ -4215,7 +4613,9 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
4215
4613
|
});
|
|
4216
4614
|
if (scopeForProduct.type === "vendor") {
|
|
4217
4615
|
if (entityMap.collections && persistBody.collectionId != null && persistBody.collectionId !== "") {
|
|
4218
|
-
const collectionErr = await
|
|
4616
|
+
const collectionErr = await assertCollectionForVendorProduct(dataSource, entityMap.collections, persistBody.collectionId, persistBody.categoryId, scopeForProduct.vendorId, {
|
|
4617
|
+
allowVendorOwned: productFlags.collections
|
|
4618
|
+
});
|
|
4219
4619
|
if (collectionErr) return json({
|
|
4220
4620
|
error: collectionErr
|
|
4221
4621
|
}, {
|
|
@@ -4224,6 +4624,14 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
4224
4624
|
}
|
|
4225
4625
|
}
|
|
4226
4626
|
}
|
|
4627
|
+
if (resource === "events") {
|
|
4628
|
+
const scopeForEvent = await resolveScope();
|
|
4629
|
+
const requireEventApproval = await getRequireEventApproval(dataSource);
|
|
4630
|
+
applyVendorEventCreateApproval(persistBody, {
|
|
4631
|
+
isVendor: scopeForEvent.type === "vendor",
|
|
4632
|
+
requireApproval: requireEventApproval
|
|
4633
|
+
});
|
|
4634
|
+
}
|
|
4227
4635
|
if (resource === "collections" && scopePost.type === "vendor") {
|
|
4228
4636
|
const categoryErr = await assertCatalogCategoryId(dataSource, entityMap.product_categories, persistBody.categoryId, {
|
|
4229
4637
|
required: true
|
|
@@ -4428,7 +4836,27 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
4428
4836
|
}
|
|
4429
4837
|
}
|
|
4430
4838
|
}
|
|
4431
|
-
if (
|
|
4839
|
+
if (resource === "brands" && scopeCreate.type === "all") {
|
|
4840
|
+
applyPlatformCatalogBrandFields(persistBody);
|
|
4841
|
+
const slug = String(persistBody.slug ?? "").trim();
|
|
4842
|
+
if (slug) {
|
|
4843
|
+
const dup = await repo.findOne({
|
|
4844
|
+
where: {
|
|
4845
|
+
slug,
|
|
4846
|
+
isCatalog: true,
|
|
4847
|
+
deleted: false
|
|
4848
|
+
}
|
|
4849
|
+
});
|
|
4850
|
+
if (dup) {
|
|
4851
|
+
return json({
|
|
4852
|
+
error: "A catalog brand with this slug already exists"
|
|
4853
|
+
}, {
|
|
4854
|
+
status: 400
|
|
4855
|
+
});
|
|
4856
|
+
}
|
|
4857
|
+
}
|
|
4858
|
+
}
|
|
4859
|
+
if (!((resource === "collections" || resource === "product_categories" || resource === "brands") && persistBody.isCatalog === true)) {
|
|
4432
4860
|
await tryAssignSingleVendorOnAdminCreate(resource, scopeCreate, persistBody);
|
|
4433
4861
|
}
|
|
4434
4862
|
const vendorIdCheck = requireVendorIdForScopedCreate(resource, persistBody, scopeCreate, repo, await vendorCreateContext(body));
|
|
@@ -4908,13 +5336,14 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
4908
5336
|
}
|
|
4909
5337
|
__name(createCrudHandler, "createCrudHandler");
|
|
4910
5338
|
function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
4911
|
-
const { requireAuth, json, requireEntityPermission: reqPerm, getCms, getDeletedByUserId, getVendorScope } = options;
|
|
5339
|
+
const { requireAuth, json, requireEntityPermission: reqPerm, getCms, getDeletedByUserId, getVendorScope, getHydratedSessionUser } = options;
|
|
4912
5340
|
const syncContactRowToErp = makeContactErpSync(dataSource, entityMap, getCms);
|
|
4913
5341
|
const resolveScopeById = getVendorScope ?? (async () => ({
|
|
4914
5342
|
type: "all"
|
|
4915
5343
|
}));
|
|
4916
|
-
function vendorScopeAccessJson(row, scope, resource) {
|
|
4917
|
-
const
|
|
5344
|
+
async function vendorScopeAccessJson(row, scope, resource) {
|
|
5345
|
+
const flags = await getVendorCatalogCreateFlags(dataSource);
|
|
5346
|
+
const access = vendorScopeRowAccess(row, scope, resource, flags);
|
|
4918
5347
|
if (access === "ok") return null;
|
|
4919
5348
|
if (access === "forbidden") return json({
|
|
4920
5349
|
error: "Forbidden"
|
|
@@ -4994,7 +5423,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
4994
5423
|
"rules"
|
|
4995
5424
|
]
|
|
4996
5425
|
});
|
|
4997
|
-
const discountDenied = vendorScopeAccessJson(discount, scope2, resource);
|
|
5426
|
+
const discountDenied = await vendorScopeAccessJson(discount, scope2, resource);
|
|
4998
5427
|
if (discountDenied) return discountDenied;
|
|
4999
5428
|
const flatRules = discount.rules ?? [];
|
|
5000
5429
|
const nestedRules = nestDiscountRules2(flatRules);
|
|
@@ -5052,7 +5481,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5052
5481
|
"payments"
|
|
5053
5482
|
]
|
|
5054
5483
|
});
|
|
5055
|
-
const orderDenied = vendorScopeAccessJson(order, scope2, resource);
|
|
5484
|
+
const orderDenied = await vendorScopeAccessJson(order, scope2, resource);
|
|
5056
5485
|
if (orderDenied) return orderDenied;
|
|
5057
5486
|
const relatedOrders = await repo.find({
|
|
5058
5487
|
where: {
|
|
@@ -5116,7 +5545,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5116
5545
|
"contact"
|
|
5117
5546
|
]
|
|
5118
5547
|
});
|
|
5119
|
-
const paymentDenied = vendorScopeAccessJson(payment, scope2, resource);
|
|
5548
|
+
const paymentDenied = await vendorScopeAccessJson(payment, scope2, resource);
|
|
5120
5549
|
if (paymentDenied) return paymentDenied;
|
|
5121
5550
|
const p = payment;
|
|
5122
5551
|
const order = p.order;
|
|
@@ -5155,7 +5584,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5155
5584
|
"attributes.attribute"
|
|
5156
5585
|
]
|
|
5157
5586
|
});
|
|
5158
|
-
const productDenied = vendorScopeAccessJson(product, scope2, resource);
|
|
5587
|
+
const productDenied = await vendorScopeAccessJson(product, scope2, resource);
|
|
5159
5588
|
if (productDenied) return productDenied;
|
|
5160
5589
|
return product ? json(hydrateProductDisplayName(product)) : json({
|
|
5161
5590
|
message: "Not found"
|
|
@@ -5173,7 +5602,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5173
5602
|
"contact"
|
|
5174
5603
|
]
|
|
5175
5604
|
});
|
|
5176
|
-
const vcDenied = vendorScopeAccessJson(row, scope2, resource);
|
|
5605
|
+
const vcDenied = await vendorScopeAccessJson(row, scope2, resource);
|
|
5177
5606
|
if (vcDenied) return vcDenied;
|
|
5178
5607
|
const contact = row.contact;
|
|
5179
5608
|
return json({
|
|
@@ -5196,7 +5625,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5196
5625
|
"items.product"
|
|
5197
5626
|
]
|
|
5198
5627
|
});
|
|
5199
|
-
const comboDenied = vendorScopeAccessJson(combo, scope2, resource);
|
|
5628
|
+
const comboDenied = await vendorScopeAccessJson(combo, scope2, resource);
|
|
5200
5629
|
if (comboDenied) return comboDenied;
|
|
5201
5630
|
return combo ? json(combo) : json({
|
|
5202
5631
|
message: "Not found"
|
|
@@ -5233,7 +5662,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5233
5662
|
where: idWhere
|
|
5234
5663
|
});
|
|
5235
5664
|
if (resourceUsesVendorScope(resource)) {
|
|
5236
|
-
const itemDenied = vendorScopeAccessJson(item, scope, resource);
|
|
5665
|
+
const itemDenied = await vendorScopeAccessJson(item, scope, resource);
|
|
5237
5666
|
if (itemDenied) return itemDenied;
|
|
5238
5667
|
} else if (!item) {
|
|
5239
5668
|
return json({
|
|
@@ -5262,16 +5691,11 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5262
5691
|
}
|
|
5263
5692
|
const rawBody = await req.json();
|
|
5264
5693
|
const scopePutEarly = await resolveScopeById();
|
|
5265
|
-
|
|
5694
|
+
const catalogFlagsPut = await getVendorCatalogCreateFlags(dataSource);
|
|
5695
|
+
if (vendorCannotMutateCatalogResource(resource, scopePutEarly, catalogFlagsPut, rawBody ?? void 0)) {
|
|
5696
|
+
const label = resource === "product_categories" ? "Categories" : resource === "collections" ? "Collections" : resource === "brands" ? "Brands" : "This resource";
|
|
5266
5697
|
return json({
|
|
5267
|
-
error:
|
|
5268
|
-
}, {
|
|
5269
|
-
status: 403
|
|
5270
|
-
});
|
|
5271
|
-
}
|
|
5272
|
-
if (vendorCannotMutateCatalogCollections(resource, scopePutEarly, rawBody ?? void 0)) {
|
|
5273
|
-
return json({
|
|
5274
|
-
error: "Collections are managed by the platform administrator"
|
|
5698
|
+
error: `${label} are managed by the platform administrator`
|
|
5275
5699
|
}, {
|
|
5276
5700
|
status: 403
|
|
5277
5701
|
});
|
|
@@ -5637,7 +6061,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5637
6061
|
id: numericId
|
|
5638
6062
|
}
|
|
5639
6063
|
});
|
|
5640
|
-
const discountPutDenied = vendorScopeAccessJson(existing, scopePut2, resource);
|
|
6064
|
+
const discountPutDenied = await vendorScopeAccessJson(existing, scopePut2, resource);
|
|
5641
6065
|
if (discountPutDenied) return discountPutDenied;
|
|
5642
6066
|
const updatePayload2 = pickColumnUpdates(repo, rawBody);
|
|
5643
6067
|
delete updatePayload2.vendorId;
|
|
@@ -5695,8 +6119,16 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5695
6119
|
const existingScope = await repo.findOne({
|
|
5696
6120
|
where: idWhereCheck
|
|
5697
6121
|
});
|
|
5698
|
-
const scopePutDenied = vendorScopeAccessJson(existingScope, scopePut, resource);
|
|
6122
|
+
const scopePutDenied = await vendorScopeAccessJson(existingScope, scopePut, resource);
|
|
5699
6123
|
if (scopePutDenied) return scopePutDenied;
|
|
6124
|
+
if (vendorCannotMutateExistingCatalogRow(resource, scopePut, existingScope)) {
|
|
6125
|
+
const label = resource === "product_categories" ? "Categories" : resource === "collections" ? "Collections" : "Brands";
|
|
6126
|
+
return json({
|
|
6127
|
+
error: `${label} are managed by the platform administrator`
|
|
6128
|
+
}, {
|
|
6129
|
+
status: 403
|
|
6130
|
+
});
|
|
6131
|
+
}
|
|
5700
6132
|
}
|
|
5701
6133
|
const updatePayload = rawBody && typeof rawBody === "object" ? pickColumnUpdates(repo, rawBody) : {};
|
|
5702
6134
|
if (resourceUsesVendorScope(resource)) {
|
|
@@ -5843,7 +6275,8 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5843
6275
|
});
|
|
5844
6276
|
const mergedCategoryId = "categoryId" in updatePayload ? updatePayload.categoryId : currentRow.categoryId;
|
|
5845
6277
|
const categoryErr = await assertCatalogCategoryId(dataSource, entityMap.product_categories, "categoryId" in updatePayload ? updatePayload.categoryId : mergedCategoryId, {
|
|
5846
|
-
required: scopePut.type === "vendor"
|
|
6278
|
+
required: scopePut.type === "vendor",
|
|
6279
|
+
allowVendorId: scopePut.type === "vendor" && catalogFlagsPut.categories ? scopePut.vendorId : void 0
|
|
5847
6280
|
});
|
|
5848
6281
|
if (categoryErr) return json({
|
|
5849
6282
|
error: categoryErr
|
|
@@ -5852,7 +6285,9 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5852
6285
|
});
|
|
5853
6286
|
if (scopePut.type === "vendor") {
|
|
5854
6287
|
if (entityMap.collections && "collectionId" in updatePayload && updatePayload.collectionId != null) {
|
|
5855
|
-
const collectionErr = await
|
|
6288
|
+
const collectionErr = await assertCollectionForVendorProduct(dataSource, entityMap.collections, updatePayload.collectionId, mergedCategoryId, scopePut.vendorId, {
|
|
6289
|
+
allowVendorOwned: catalogFlagsPut.collections
|
|
6290
|
+
});
|
|
5856
6291
|
if (collectionErr) return json({
|
|
5857
6292
|
error: collectionErr
|
|
5858
6293
|
}, {
|
|
@@ -5860,6 +6295,88 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5860
6295
|
});
|
|
5861
6296
|
}
|
|
5862
6297
|
}
|
|
6298
|
+
if ("status" in updatePayload || "approvalStatus" in updatePayload || "rejectionReason" in updatePayload) {
|
|
6299
|
+
const fromStatus = String(currentRow.status ?? "draft");
|
|
6300
|
+
const toStatus = String("status" in updatePayload ? updatePayload.status ?? fromStatus : fromStatus);
|
|
6301
|
+
const fromApproval = currentRow.approvalStatus;
|
|
6302
|
+
const toApproval = "approvalStatus" in updatePayload ? updatePayload.approvalStatus : fromApproval;
|
|
6303
|
+
const requireApproval = await getRequireProductApproval(dataSource);
|
|
6304
|
+
const reasonFromBody = "rejectionReason" in updatePayload ? updatePayload.rejectionReason : currentRow.rejectionReason;
|
|
6305
|
+
const reasonStr = typeof reasonFromBody === "string" ? reasonFromBody : reasonFromBody == null ? null : String(reasonFromBody);
|
|
6306
|
+
const transition = assertProductApprovalUpdate({
|
|
6307
|
+
fromApproval,
|
|
6308
|
+
toApproval,
|
|
6309
|
+
fromStatus,
|
|
6310
|
+
toStatus,
|
|
6311
|
+
isVendor: scopePut.type === "vendor",
|
|
6312
|
+
requireApproval,
|
|
6313
|
+
approvalChanged: "approvalStatus" in updatePayload,
|
|
6314
|
+
statusChanged: "status" in updatePayload,
|
|
6315
|
+
rejectionReason: reasonStr
|
|
6316
|
+
});
|
|
6317
|
+
if (!transition.ok) return json({
|
|
6318
|
+
error: transition.error
|
|
6319
|
+
}, {
|
|
6320
|
+
status: 400
|
|
6321
|
+
});
|
|
6322
|
+
if ("approvalStatus" in updatePayload && scopePut.type !== "vendor") {
|
|
6323
|
+
const session = await getHydratedSessionUser?.() ?? null;
|
|
6324
|
+
const rejectedByRaw = session?.id != null ? Number(session.id) : null;
|
|
6325
|
+
applyApprovalStatusSideEffects(updatePayload, {
|
|
6326
|
+
toApproval,
|
|
6327
|
+
currentStatus: fromStatus,
|
|
6328
|
+
rejectionReason: reasonStr,
|
|
6329
|
+
rejectedBy: Number.isFinite(rejectedByRaw) ? rejectedByRaw : null
|
|
6330
|
+
});
|
|
6331
|
+
}
|
|
6332
|
+
}
|
|
6333
|
+
}
|
|
6334
|
+
if (resource === "events") {
|
|
6335
|
+
const currentEvent = await repo.findOne({
|
|
6336
|
+
where: {
|
|
6337
|
+
id: numericId,
|
|
6338
|
+
deleted: false
|
|
6339
|
+
}
|
|
6340
|
+
});
|
|
6341
|
+
if (!currentEvent) return json({
|
|
6342
|
+
message: "Not found"
|
|
6343
|
+
}, {
|
|
6344
|
+
status: 404
|
|
6345
|
+
});
|
|
6346
|
+
if ("isActive" in updatePayload || "approvalStatus" in updatePayload || "rejectionReason" in updatePayload) {
|
|
6347
|
+
const fromActive = Boolean(currentEvent.isActive);
|
|
6348
|
+
const toActive = "isActive" in updatePayload ? Boolean(updatePayload.isActive) : fromActive;
|
|
6349
|
+
const fromApproval = currentEvent.approvalStatus;
|
|
6350
|
+
const toApproval = "approvalStatus" in updatePayload ? updatePayload.approvalStatus : fromApproval;
|
|
6351
|
+
const requireEventApproval = await getRequireEventApproval(dataSource);
|
|
6352
|
+
const reasonFromBody = "rejectionReason" in updatePayload ? updatePayload.rejectionReason : currentEvent.rejectionReason;
|
|
6353
|
+
const reasonStr = typeof reasonFromBody === "string" ? reasonFromBody : reasonFromBody == null ? null : String(reasonFromBody);
|
|
6354
|
+
const transition = assertEventApprovalUpdate({
|
|
6355
|
+
fromApproval,
|
|
6356
|
+
toApproval,
|
|
6357
|
+
toActive,
|
|
6358
|
+
isVendor: scopePut.type === "vendor",
|
|
6359
|
+
requireApproval: requireEventApproval,
|
|
6360
|
+
approvalChanged: "approvalStatus" in updatePayload,
|
|
6361
|
+
activeChanged: "isActive" in updatePayload,
|
|
6362
|
+
rejectionReason: reasonStr
|
|
6363
|
+
});
|
|
6364
|
+
if (!transition.ok) return json({
|
|
6365
|
+
error: transition.error
|
|
6366
|
+
}, {
|
|
6367
|
+
status: 400
|
|
6368
|
+
});
|
|
6369
|
+
if ("approvalStatus" in updatePayload && scopePut.type !== "vendor") {
|
|
6370
|
+
const session = await getHydratedSessionUser?.() ?? null;
|
|
6371
|
+
const rejectedByRaw = session?.id != null ? Number(session.id) : null;
|
|
6372
|
+
applyEventApprovalStatusSideEffects(updatePayload, {
|
|
6373
|
+
toApproval,
|
|
6374
|
+
currentActive: fromActive,
|
|
6375
|
+
rejectionReason: reasonStr,
|
|
6376
|
+
rejectedBy: Number.isFinite(rejectedByRaw) ? rejectedByRaw : null
|
|
6377
|
+
});
|
|
6378
|
+
}
|
|
6379
|
+
}
|
|
5863
6380
|
}
|
|
5864
6381
|
if (resource === "product_categories" && scopePut.type === "all") {
|
|
5865
6382
|
const existingCatalogCat = await repo.findOne({
|
|
@@ -5917,6 +6434,34 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5917
6434
|
}
|
|
5918
6435
|
}
|
|
5919
6436
|
}
|
|
6437
|
+
if (resource === "brands" && scopePut.type === "all") {
|
|
6438
|
+
const existingCatalogBrand = await repo.findOne({
|
|
6439
|
+
where: {
|
|
6440
|
+
id: numericId,
|
|
6441
|
+
deleted: false
|
|
6442
|
+
}
|
|
6443
|
+
});
|
|
6444
|
+
if (existingCatalogBrand && existingCatalogBrand.isCatalog === true) {
|
|
6445
|
+
applyPlatformCatalogBrandFields(updatePayload);
|
|
6446
|
+
const slug = String(updatePayload.slug ?? existingCatalogBrand.slug ?? "").trim();
|
|
6447
|
+
if (slug && "slug" in updatePayload) {
|
|
6448
|
+
const dup = await repo.findOne({
|
|
6449
|
+
where: {
|
|
6450
|
+
slug,
|
|
6451
|
+
isCatalog: true,
|
|
6452
|
+
deleted: false
|
|
6453
|
+
}
|
|
6454
|
+
});
|
|
6455
|
+
if (dup && Number(dup.id) !== numericId) {
|
|
6456
|
+
return json({
|
|
6457
|
+
error: "A catalog brand with this slug already exists"
|
|
6458
|
+
}, {
|
|
6459
|
+
status: 400
|
|
6460
|
+
});
|
|
6461
|
+
}
|
|
6462
|
+
}
|
|
6463
|
+
}
|
|
6464
|
+
}
|
|
5920
6465
|
if (resource === "addresses" && Object.keys(updatePayload).length > 0) {
|
|
5921
6466
|
const currentRow = await repo.findOne({
|
|
5922
6467
|
where: {
|
|
@@ -6072,9 +6617,11 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6072
6617
|
const authError = await authz(req, resource, "delete");
|
|
6073
6618
|
if (authError) return authError;
|
|
6074
6619
|
const scopeDeleteEarly = await resolveScopeById();
|
|
6075
|
-
|
|
6620
|
+
const catalogFlagsDelete = await getVendorCatalogCreateFlags(dataSource);
|
|
6621
|
+
if (vendorCannotMutateCatalogResource(resource, scopeDeleteEarly, catalogFlagsDelete)) {
|
|
6622
|
+
const label = resource === "product_categories" ? "Categories" : resource === "collections" ? "Collections" : resource === "brands" ? "Brands" : "This resource";
|
|
6076
6623
|
return json({
|
|
6077
|
-
error:
|
|
6624
|
+
error: `${label} are managed by the platform administrator`
|
|
6078
6625
|
}, {
|
|
6079
6626
|
status: 403
|
|
6080
6627
|
});
|
|
@@ -6103,7 +6650,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6103
6650
|
}
|
|
6104
6651
|
});
|
|
6105
6652
|
if (resourceUsesVendorScope(resource)) {
|
|
6106
|
-
const deleteDenied = vendorScopeAccessJson(existing, scopeDelete, resource);
|
|
6653
|
+
const deleteDenied = await vendorScopeAccessJson(existing, scopeDelete, resource);
|
|
6107
6654
|
if (deleteDenied) return deleteDenied;
|
|
6108
6655
|
} else if (!existing) {
|
|
6109
6656
|
return json({
|
|
@@ -6161,7 +6708,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6161
6708
|
id: numericId
|
|
6162
6709
|
}
|
|
6163
6710
|
});
|
|
6164
|
-
const hardDeleteDenied = vendorScopeAccessJson(existingHard, scopeDelete, resource);
|
|
6711
|
+
const hardDeleteDenied = await vendorScopeAccessJson(existingHard, scopeDelete, resource);
|
|
6165
6712
|
if (hardDeleteDenied) return hardDeleteDenied;
|
|
6166
6713
|
}
|
|
6167
6714
|
const result = await repo.delete(numericId);
|
|
@@ -17034,6 +17581,7 @@ var Brand = class {
|
|
|
17034
17581
|
__name(this, "Brand");
|
|
17035
17582
|
}
|
|
17036
17583
|
id;
|
|
17584
|
+
/** Null for platform catalog brands (`isCatalog`). */
|
|
17037
17585
|
vendorId;
|
|
17038
17586
|
name;
|
|
17039
17587
|
slug;
|
|
@@ -17041,6 +17589,8 @@ var Brand = class {
|
|
|
17041
17589
|
metadata;
|
|
17042
17590
|
description;
|
|
17043
17591
|
active;
|
|
17592
|
+
/** Platform-wide catalog brand — vendors pick these on products unless allowed to create their own. */
|
|
17593
|
+
isCatalog;
|
|
17044
17594
|
sortOrder;
|
|
17045
17595
|
createdAt;
|
|
17046
17596
|
updatedAt;
|
|
@@ -17060,8 +17610,10 @@ _ts_decorate30([
|
|
|
17060
17610
|
_ts_metadata30("design:type", Number)
|
|
17061
17611
|
], Brand.prototype, "id", void 0);
|
|
17062
17612
|
_ts_decorate30([
|
|
17063
|
-
Column("int"
|
|
17064
|
-
|
|
17613
|
+
Column("int", {
|
|
17614
|
+
nullable: true
|
|
17615
|
+
}),
|
|
17616
|
+
_ts_metadata30("design:type", Object)
|
|
17065
17617
|
], Brand.prototype, "vendorId", void 0);
|
|
17066
17618
|
_ts_decorate30([
|
|
17067
17619
|
Column("varchar"),
|
|
@@ -17095,6 +17647,12 @@ _ts_decorate30([
|
|
|
17095
17647
|
}),
|
|
17096
17648
|
_ts_metadata30("design:type", Boolean)
|
|
17097
17649
|
], Brand.prototype, "active", void 0);
|
|
17650
|
+
_ts_decorate30([
|
|
17651
|
+
Column("boolean", {
|
|
17652
|
+
default: false
|
|
17653
|
+
}),
|
|
17654
|
+
_ts_metadata30("design:type", Boolean)
|
|
17655
|
+
], Brand.prototype, "isCatalog", void 0);
|
|
17098
17656
|
_ts_decorate30([
|
|
17099
17657
|
Column("int", {
|
|
17100
17658
|
default: 0
|
|
@@ -17154,12 +17712,13 @@ _ts_decorate30([
|
|
|
17154
17712
|
], Brand.prototype, "seoId", void 0);
|
|
17155
17713
|
_ts_decorate30([
|
|
17156
17714
|
ManyToOne(() => Vendor, {
|
|
17157
|
-
onDelete: "RESTRICT"
|
|
17715
|
+
onDelete: "RESTRICT",
|
|
17716
|
+
nullable: true
|
|
17158
17717
|
}),
|
|
17159
17718
|
JoinColumn({
|
|
17160
17719
|
name: "vendorId"
|
|
17161
17720
|
}),
|
|
17162
|
-
_ts_metadata30("design:type",
|
|
17721
|
+
_ts_metadata30("design:type", Object)
|
|
17163
17722
|
], Brand.prototype, "vendor", void 0);
|
|
17164
17723
|
_ts_decorate30([
|
|
17165
17724
|
ManyToOne(() => Seo, {
|
|
@@ -17443,6 +18002,14 @@ var Product = class {
|
|
|
17443
18002
|
currencyPrices;
|
|
17444
18003
|
quantity;
|
|
17445
18004
|
status;
|
|
18005
|
+
/**
|
|
18006
|
+
* Separate from catalog status. Used when multi_vendor.requireProductApproval is on.
|
|
18007
|
+
* `approved` also forces `status = available` (live).
|
|
18008
|
+
*/
|
|
18009
|
+
approvalStatus;
|
|
18010
|
+
rejectionReason;
|
|
18011
|
+
rejectedAt;
|
|
18012
|
+
rejectedBy;
|
|
17446
18013
|
featured;
|
|
17447
18014
|
metadata;
|
|
17448
18015
|
createdAt;
|
|
@@ -17566,6 +18133,31 @@ _ts_decorate32([
|
|
|
17566
18133
|
}),
|
|
17567
18134
|
_ts_metadata32("design:type", String)
|
|
17568
18135
|
], Product.prototype, "status", void 0);
|
|
18136
|
+
_ts_decorate32([
|
|
18137
|
+
Column("varchar", {
|
|
18138
|
+
nullable: true
|
|
18139
|
+
}),
|
|
18140
|
+
_ts_metadata32("design:type", Object)
|
|
18141
|
+
], Product.prototype, "approvalStatus", void 0);
|
|
18142
|
+
_ts_decorate32([
|
|
18143
|
+
Column("text", {
|
|
18144
|
+
nullable: true
|
|
18145
|
+
}),
|
|
18146
|
+
_ts_metadata32("design:type", Object)
|
|
18147
|
+
], Product.prototype, "rejectionReason", void 0);
|
|
18148
|
+
_ts_decorate32([
|
|
18149
|
+
Column({
|
|
18150
|
+
type: "timestamptz",
|
|
18151
|
+
nullable: true
|
|
18152
|
+
}),
|
|
18153
|
+
_ts_metadata32("design:type", Object)
|
|
18154
|
+
], Product.prototype, "rejectedAt", void 0);
|
|
18155
|
+
_ts_decorate32([
|
|
18156
|
+
Column("int", {
|
|
18157
|
+
nullable: true
|
|
18158
|
+
}),
|
|
18159
|
+
_ts_metadata32("design:type", Object)
|
|
18160
|
+
], Product.prototype, "rejectedBy", void 0);
|
|
17569
18161
|
_ts_decorate32([
|
|
17570
18162
|
Column("boolean", {
|
|
17571
18163
|
default: false
|
|
@@ -20654,6 +21246,14 @@ var Event = class {
|
|
|
20654
21246
|
expectedSpeakers;
|
|
20655
21247
|
expectedParticipants;
|
|
20656
21248
|
isActive;
|
|
21249
|
+
/**
|
|
21250
|
+
* Separate from isActive. Used when events.requireEventApproval is on.
|
|
21251
|
+
* `approved` also forces `isActive = true` (live).
|
|
21252
|
+
*/
|
|
21253
|
+
approvalStatus;
|
|
21254
|
+
rejectionReason;
|
|
21255
|
+
rejectedAt;
|
|
21256
|
+
rejectedBy;
|
|
20657
21257
|
comingSoon;
|
|
20658
21258
|
bannerImageUrl;
|
|
20659
21259
|
logoUrl;
|
|
@@ -20748,6 +21348,31 @@ _ts_decorate60([
|
|
|
20748
21348
|
}),
|
|
20749
21349
|
_ts_metadata60("design:type", Boolean)
|
|
20750
21350
|
], Event.prototype, "isActive", void 0);
|
|
21351
|
+
_ts_decorate60([
|
|
21352
|
+
Column("varchar", {
|
|
21353
|
+
nullable: true
|
|
21354
|
+
}),
|
|
21355
|
+
_ts_metadata60("design:type", Object)
|
|
21356
|
+
], Event.prototype, "approvalStatus", void 0);
|
|
21357
|
+
_ts_decorate60([
|
|
21358
|
+
Column("text", {
|
|
21359
|
+
nullable: true
|
|
21360
|
+
}),
|
|
21361
|
+
_ts_metadata60("design:type", Object)
|
|
21362
|
+
], Event.prototype, "rejectionReason", void 0);
|
|
21363
|
+
_ts_decorate60([
|
|
21364
|
+
Column({
|
|
21365
|
+
type: "timestamptz",
|
|
21366
|
+
nullable: true
|
|
21367
|
+
}),
|
|
21368
|
+
_ts_metadata60("design:type", Object)
|
|
21369
|
+
], Event.prototype, "rejectedAt", void 0);
|
|
21370
|
+
_ts_decorate60([
|
|
21371
|
+
Column("int", {
|
|
21372
|
+
nullable: true
|
|
21373
|
+
}),
|
|
21374
|
+
_ts_metadata60("design:type", Object)
|
|
21375
|
+
], Event.prototype, "rejectedBy", void 0);
|
|
20751
21376
|
_ts_decorate60([
|
|
20752
21377
|
Column("boolean", {
|
|
20753
21378
|
default: false
|
|
@@ -21308,18 +21933,20 @@ _ts_decorate63([
|
|
|
21308
21933
|
], Combo.prototype, "desc", void 0);
|
|
21309
21934
|
_ts_decorate63([
|
|
21310
21935
|
Column({
|
|
21311
|
-
type: "integer"
|
|
21936
|
+
type: "integer",
|
|
21937
|
+
nullable: true
|
|
21312
21938
|
}),
|
|
21313
|
-
_ts_metadata63("design:type",
|
|
21939
|
+
_ts_metadata63("design:type", Object)
|
|
21314
21940
|
], Combo.prototype, "eventId", void 0);
|
|
21315
21941
|
_ts_decorate63([
|
|
21316
21942
|
ManyToOne(() => Event, {
|
|
21317
|
-
onDelete: "CASCADE"
|
|
21943
|
+
onDelete: "CASCADE",
|
|
21944
|
+
nullable: true
|
|
21318
21945
|
}),
|
|
21319
21946
|
JoinColumn({
|
|
21320
21947
|
name: "eventId"
|
|
21321
21948
|
}),
|
|
21322
|
-
_ts_metadata63("design:type",
|
|
21949
|
+
_ts_metadata63("design:type", Object)
|
|
21323
21950
|
], Combo.prototype, "event", void 0);
|
|
21324
21951
|
_ts_decorate63([
|
|
21325
21952
|
Column({
|
|
@@ -26632,16 +27259,24 @@ function createCmsApiHandler(config) {
|
|
|
26632
27259
|
if (pe) return pe;
|
|
26633
27260
|
if (group === "multi_vendor") {
|
|
26634
27261
|
invalidateMultiVendorCache();
|
|
27262
|
+
invalidateVendorCatalogCreateFlagsCache();
|
|
27263
|
+
invalidateRequireProductApprovalCache();
|
|
27264
|
+
invalidateRequireEventApprovalCache();
|
|
26635
27265
|
}
|
|
26636
27266
|
if (group === "events") {
|
|
26637
27267
|
invalidateEventsCache();
|
|
27268
|
+
invalidateRequireEventApprovalCache();
|
|
26638
27269
|
}
|
|
26639
27270
|
const res = await settingsHandlers.PUT(req, group);
|
|
26640
27271
|
if (group === "multi_vendor") {
|
|
26641
27272
|
invalidateMultiVendorCache();
|
|
27273
|
+
invalidateVendorCatalogCreateFlagsCache();
|
|
27274
|
+
invalidateRequireProductApprovalCache();
|
|
27275
|
+
invalidateRequireEventApprovalCache();
|
|
26642
27276
|
}
|
|
26643
27277
|
if (group === "events") {
|
|
26644
27278
|
invalidateEventsCache();
|
|
27279
|
+
invalidateRequireEventApprovalCache();
|
|
26645
27280
|
}
|
|
26646
27281
|
return res;
|
|
26647
27282
|
}
|
|
@@ -30946,4 +31581,4 @@ function createStorefrontApiHandler(config) {
|
|
|
30946
31581
|
}
|
|
30947
31582
|
__name(createStorefrontApiHandler, "createStorefrontApiHandler");
|
|
30948
31583
|
|
|
30949
|
-
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, 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, UserGroup, Vendor, VendorCustomer, VendorRole, VendorRolePermission, VendorUser, Wishlist, WishlistItem, ZIP_MIME_TYPES, applyRotatingVendorInvite, applyVendorCustomersContactFilter, assertCaptchaOk, assertContactAllowedForVendorOrder, buildBlogMetadataUserPrompt, buildCronFromSchedule, buildRssUserPromptFromFeeds, buildVendorInviteLink, calculateOrderRefundPreview, calculateRefundFromPolicy, checkEventsEnabled, checkMultiVendorEnabled, contactIsVendorCustomer, 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, customerPhoneForUser, daysBeforeEventStart, describeEventTierPolicy, ensureCustomerForUser, ensureMessagingPluginsOnCms, ensureScheduleQueueWorker, ensureVendorCustomerForOrderContact, findActiveRefundPolicyForVendor, findVendorByInviteToken, formatTierRange, generateNumericOtp, getPublicSettingsGroup, getRssArticleSummaryFromItem, hashOtpCode, hydrateVendorSessionUser, invalidateEventsCache, invalidateMultiVendorCache, isCustomerTypeContact, isZipMedia, linkUnclaimedContactToUser, llmAgentToChatAgentOptions, loadSettingsGroupFromDb, loadUserVendorContext, mergeGuardrailsIntoSystemPrompt, messagingPlugins, metaFetchUserManagedPages, metaPostPageFeed, metaPostPagePhoto, metaResolvePageAccessToken, normalizePhoneE164, normalizeRefundTiers, overlayCmsPlugins, parseBlogGeneratorAgentContent, parseBlogGeneratorModelOutput, parseBlogMetadataEnrichmentJson, parseLlmAgentValidationRules, pgBossScheduleNameForId, queueErpCreateContactIfEnabled, queueJobScheduleNow, queuePlugin, queueSms, registerJobRunnerWorker, registerMessagingQueueProcessors, registerSmsQueueProcessor, relativePathFromMediaParentId, resolveBlogCategoryIdByName, resolveSettingsEncryptionKey, resolveVendorIdForContactCheck, sanitizeMediaFolderPath, sanitizeStorageSegment, sendVendorOnboardEmails, simpleDecrypt, simpleEncrypt, syncJobScheduleToPgBoss, validateRefundTiers, validateScheduleInput, validateUserMessageAgainstAgentRules, validateUserMessageAgainstStructuredRules, verifyAndConsumeOtpChallenge, verifyOtpCodeHash, whatsappPlugin, wrapGetCmsWithMessaging };
|
|
31584
|
+
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, 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, UserGroup, Vendor, VendorCustomer, VendorRole, VendorRolePermission, VendorUser, Wishlist, WishlistItem, ZIP_MIME_TYPES, applyApprovalStatusSideEffects, applyEventApprovalStatusSideEffects, applyRotatingVendorInvite, applyVendorCustomersContactFilter, applyVendorEventCreateApproval, applyVendorProductCreateApproval, assertCaptchaOk, assertContactAllowedForVendorOrder, assertEventApprovalUpdate, assertProductApprovalUpdate, buildBlogMetadataUserPrompt, buildCronFromSchedule, buildRssUserPromptFromFeeds, buildVendorInviteLink, calculateOrderRefundPreview, calculateRefundFromPolicy, checkEventsEnabled, checkMultiVendorEnabled, contactIsVendorCustomer, 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, customerPhoneForUser, daysBeforeEventStart, describeEventTierPolicy, ensureCustomerForUser, ensureMessagingPluginsOnCms, ensureScheduleQueueWorker, ensureVendorCustomerForOrderContact, findActiveRefundPolicyForVendor, findVendorByInviteToken, formatTierRange, generateNumericOtp, getPublicSettingsGroup, getRequireEventApproval, getRequireProductApproval, getRssArticleSummaryFromItem, getVendorCatalogCreateFlags, hashOtpCode, hydrateVendorSessionUser, invalidateEventsCache, invalidateMultiVendorCache, invalidateRequireEventApprovalCache, invalidateRequireProductApprovalCache, invalidateVendorCatalogCreateFlagsCache, isCustomerTypeContact, isZipMedia, linkUnclaimedContactToUser, llmAgentToChatAgentOptions, loadSettingsGroupFromDb, loadUserVendorContext, mergeGuardrailsIntoSystemPrompt, messagingPlugins, metaFetchUserManagedPages, metaPostPageFeed, metaPostPagePhoto, metaResolvePageAccessToken, normalizePhoneE164, normalizeRefundTiers, overlayCmsPlugins, parseBlogGeneratorAgentContent, parseBlogGeneratorModelOutput, parseBlogMetadataEnrichmentJson, parseLlmAgentValidationRules, pgBossScheduleNameForId, queueErpCreateContactIfEnabled, queueJobScheduleNow, queuePlugin, queueSms, registerJobRunnerWorker, registerMessagingQueueProcessors, registerSmsQueueProcessor, relativePathFromMediaParentId, resolveBlogCategoryIdByName, resolveSettingsEncryptionKey, resolveVendorIdForContactCheck, sanitizeMediaFolderPath, sanitizeStorageSegment, sendVendorOnboardEmails, simpleDecrypt, simpleEncrypt, syncJobScheduleToPgBoss, validateRefundTiers, validateScheduleInput, validateUserMessageAgainstAgentRules, validateUserMessageAgainstStructuredRules, verifyAndConsumeOtpChallenge, verifyOtpCodeHash, whatsappPlugin, wrapGetCmsWithMessaging };
|