@infuro/cms-core 1.0.45 → 1.0.46
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 +873 -214
- package/dist/admin.d.cts +7 -1
- package/dist/admin.d.ts +7 -1
- package/dist/admin.js +874 -215
- package/dist/api.cjs +40 -37
- package/dist/api.d.cts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +8 -5
- package/dist/auth.cjs +23 -23
- package/dist/auth.d.cts +1 -0
- package/dist/auth.d.ts +1 -0
- package/dist/auth.js +2 -2
- package/dist/chunk-2KUCQVAQ.js +936 -0
- package/dist/chunk-3K5AIEIZ.js +256 -0
- package/dist/{chunk-I6NH72MO.js → chunk-57O3HZPG.js} +9 -1
- package/dist/chunk-7PMHZRF3.cjs +872 -0
- package/dist/chunk-BXYZDMTZ.cjs +953 -0
- package/dist/chunk-CQHXW4TR.js +107 -0
- package/dist/{chunk-NNQBWDCI.js → chunk-CRYKVJTO.js} +55 -959
- package/dist/chunk-DBPSJYLZ.js +47 -0
- package/dist/{chunk-TAHX46EI.cjs → chunk-FBKDMRQL.cjs} +9 -1
- package/dist/chunk-GUSHM5HN.js +862 -0
- package/dist/chunk-HY3AXLOI.cjs +265 -0
- package/dist/chunk-L3525VXI.js +243 -0
- package/dist/{chunk-ZMRQ72F6.cjs → chunk-NBY4NVTY.cjs} +3 -3
- package/dist/chunk-OY2YTBMP.cjs +50 -0
- package/dist/{chunk-BLR6H5GL.js → chunk-SF2XKMCI.js} +3 -3
- package/dist/{chunk-22FFHLTO.cjs → chunk-TCSGFAWB.cjs} +56 -970
- package/dist/{chunk-F5XFHYTG.cjs → chunk-UDVLFVEC.cjs} +661 -382
- package/dist/{chunk-MVXLRANV.js → chunk-UKC3HYXI.js} +591 -323
- package/dist/chunk-V25RDUOU.cjs +248 -0
- package/dist/chunk-XMRMZ6NQ.cjs +109 -0
- 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/erp-order-invoice-3GXDE443.js +3 -0
- package/dist/erp-order-invoice-EYYNR526.cjs +24 -0
- package/dist/index.cjs +391 -364
- package/dist/index.d.cts +267 -14
- package/dist/index.d.ts +267 -14
- package/dist/index.js +12 -110
- 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/order-inventory-2MYRKEPC.cjs +39 -0
- package/dist/order-inventory-76V4XIGW.js +2 -0
- package/dist/order-notification-dispatcher-SBQAMM5V.cjs +21 -0
- package/dist/{order-notification-dispatcher-XWIJYDGA.js → order-notification-dispatcher-ZJZB2HUN.js} +5 -2
- package/dist/retire-soft-deleted-unique-5VXBA5XX.cjs +15 -0
- package/dist/retire-soft-deleted-unique-NXQIH4BC.js +2 -0
- package/dist/send-order-placed-emails-B5ZVJT7T.cjs +15 -0
- package/dist/send-order-placed-emails-WPI37KRZ.js +6 -0
- package/package.json +5 -4
- package/src/admin/admin.css +27 -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
- package/dist/order-notification-dispatcher-RU7BTGGX.cjs +0 -18
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { validateInventoryForConfirmedOrderLines, orderStatusHoldsStock, reconcileOrderInventoryBetweenSnapshots, orderInventorySnapshotFromRow, validateInventoryForOrderBecomingConfirmed } from './chunk-3K5AIEIZ.js';
|
|
2
|
+
import { retireSoftDeletedUniqueValue, activeUniqueValueExists } from './chunk-DBPSJYLZ.js';
|
|
3
|
+
import { isWhatsAppPluginEnabled, mergeWhatsAppConfigLayers, whatsAppConfigured, WhatsAppService, registerWhatsAppQueueProcessor, initWhatsappTriggerDispatcher } from './chunk-GUSHM5HN.js';
|
|
4
|
+
import { resolveChatEmailToolSettings, CHAT_EMAIL_LOG, detectChatLeadIntent, parseIntentRecipientEmails, sendChatLeadEmail, buildTranscriptForLeadEmail, buildChatbotSystemPromptWithEmailTool, parseEmailRecipientsFromConfig, emailPlugin } from './chunk-CRYKVJTO.js';
|
|
2
5
|
import { inviteStatusForActivation } from './chunk-JXF23MPG.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
6
|
+
import { queueEmail, queueVendorOnboardEmails, registerEmailQueueProcessor } from './chunk-L3525VXI.js';
|
|
7
|
+
import { mergeEmailLayoutCompanyDetails, unwrapErpReadData, mapErpPayloadToFulfillment, extractChildOrderRefsFromSalePayload, mapErpPayloadToInvoiceNumber, streamOrderInvoicePdf } from './chunk-2KUCQVAQ.js';
|
|
5
8
|
import { getSmsTemplateDefault, SMS_MESSAGE_TEMPLATE_DEFAULTS } from './chunk-MQBT33IV.js';
|
|
6
9
|
import { EVENT_ORDER_MESSAGE_TEMPLATE_DEFAULTS, EVENT_ORDER_TEMPLATE_KEY, EVENT_ORDER_TEMPLATE_VARIABLES } from './chunk-KFFB6EMZ.js';
|
|
7
10
|
import { JOB_RUNNER_QUEUE } from './chunk-GO7PPYNU.js';
|
|
8
|
-
import { canManageRoles, sessionHasEntityAccess } from './chunk-
|
|
11
|
+
import { canManageRoles, sessionHasEntityAccess } from './chunk-SF2XKMCI.js';
|
|
9
12
|
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
13
|
import { queueErp } from './chunk-SYBOCAWB.js';
|
|
11
14
|
import { isErpIntegrationEnabled } from './chunk-JC6DLWTE.js';
|
|
@@ -646,6 +649,144 @@ function applyEventApprovalStatusSideEffects(updatePayload, opts) {
|
|
|
646
649
|
}
|
|
647
650
|
__name(applyEventApprovalStatusSideEffects, "applyEventApprovalStatusSideEffects");
|
|
648
651
|
|
|
652
|
+
// src/lib/discount-usage.ts
|
|
653
|
+
async function countDiscountOrdersForContact(dataSource, discountId, contactId) {
|
|
654
|
+
try {
|
|
655
|
+
const rows = await dataSource.query(`SELECT COUNT(DISTINCT od."orderId")::int AS count
|
|
656
|
+
FROM order_discounts od
|
|
657
|
+
WHERE od."discountId" = $1 AND od."userId" = $2`, [
|
|
658
|
+
discountId,
|
|
659
|
+
contactId
|
|
660
|
+
]);
|
|
661
|
+
return Number(rows?.[0]?.count ?? 0);
|
|
662
|
+
} catch {
|
|
663
|
+
return 0;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
__name(countDiscountOrdersForContact, "countDiscountOrdersForContact");
|
|
667
|
+
function isMaxTotalUsageReached(discount) {
|
|
668
|
+
if (discount.maxTotalUsage == null) return false;
|
|
669
|
+
return Number(discount.usedCount ?? 0) >= Number(discount.maxTotalUsage);
|
|
670
|
+
}
|
|
671
|
+
__name(isMaxTotalUsageReached, "isMaxTotalUsageReached");
|
|
672
|
+
async function isMaxPerUserUsageReached(dataSource, discount, contactId) {
|
|
673
|
+
if (discount.maxUsagePerUser == null || contactId == null) return false;
|
|
674
|
+
const count = await countDiscountOrdersForContact(dataSource, discount.id, contactId);
|
|
675
|
+
return count >= Number(discount.maxUsagePerUser);
|
|
676
|
+
}
|
|
677
|
+
__name(isMaxPerUserUsageReached, "isMaxPerUserUsageReached");
|
|
678
|
+
async function checkAndIncrementDiscountUsage(dataSource, entityMap, discountId, contactId) {
|
|
679
|
+
if (!entityMap.discounts) return null;
|
|
680
|
+
const discountRepo = dataSource.getRepository(entityMap.discounts);
|
|
681
|
+
const discount = await discountRepo.findOne({
|
|
682
|
+
where: {
|
|
683
|
+
id: discountId
|
|
684
|
+
}
|
|
685
|
+
});
|
|
686
|
+
if (!discount) return `Discount #${discountId} not found`;
|
|
687
|
+
const d = discount;
|
|
688
|
+
if (d.maxUsagePerUser != null) {
|
|
689
|
+
const usageCount = await countDiscountOrdersForContact(dataSource, discountId, contactId);
|
|
690
|
+
if (usageCount >= Number(d.maxUsagePerUser)) {
|
|
691
|
+
return "You have reached the maximum usage limit for this discount";
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
const updated = await dataSource.query(`UPDATE discounts
|
|
695
|
+
SET "usedCount" = "usedCount" + 1
|
|
696
|
+
WHERE id = $1
|
|
697
|
+
AND ("maxTotalUsage" IS NULL OR "usedCount" < "maxTotalUsage")
|
|
698
|
+
RETURNING id`, [
|
|
699
|
+
discountId
|
|
700
|
+
]);
|
|
701
|
+
if (!Array.isArray(updated) || updated.length === 0) {
|
|
702
|
+
return "Discount usage limit has been reached";
|
|
703
|
+
}
|
|
704
|
+
return null;
|
|
705
|
+
}
|
|
706
|
+
__name(checkAndIncrementDiscountUsage, "checkAndIncrementDiscountUsage");
|
|
707
|
+
async function decrementDiscountUsage(dataSource, entityMap, discountId, orderId) {
|
|
708
|
+
if (!entityMap.discounts) return;
|
|
709
|
+
try {
|
|
710
|
+
await dataSource.query(`UPDATE discounts SET "usedCount" = GREATEST("usedCount" - 1, 0) WHERE id = $1`, [
|
|
711
|
+
discountId
|
|
712
|
+
]);
|
|
713
|
+
if (entityMap.order_discounts) {
|
|
714
|
+
await dataSource.getRepository(entityMap.order_discounts).delete({
|
|
715
|
+
orderId,
|
|
716
|
+
discountId
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
} catch (err) {
|
|
720
|
+
console.error("[discountEngine] decrementDiscountUsage failed:", err);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
__name(decrementDiscountUsage, "decrementDiscountUsage");
|
|
724
|
+
async function recordDiscountUsage(dataSource, entityMap, orderId, discountId, contactId, discountAmount) {
|
|
725
|
+
if (!entityMap.order_discounts) return;
|
|
726
|
+
try {
|
|
727
|
+
let discountCode = "";
|
|
728
|
+
if (entityMap.discounts) {
|
|
729
|
+
const discountRow = await dataSource.getRepository(entityMap.discounts).findOne({
|
|
730
|
+
where: {
|
|
731
|
+
id: discountId
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
discountCode = discountRow?.couponCode ?? "";
|
|
735
|
+
}
|
|
736
|
+
const odRepo = dataSource.getRepository(entityMap.order_discounts);
|
|
737
|
+
const orderItemRepo = dataSource.getRepository(entityMap.order_items);
|
|
738
|
+
const items = await orderItemRepo.find({
|
|
739
|
+
where: {
|
|
740
|
+
orderId
|
|
741
|
+
}
|
|
742
|
+
});
|
|
743
|
+
const discountedItems = items.filter((item) => Number(item.discount ?? 0) > 0);
|
|
744
|
+
if (discountedItems.length === 0) {
|
|
745
|
+
const firstItem = items[0];
|
|
746
|
+
if (!firstItem) return;
|
|
747
|
+
await odRepo.save(odRepo.create({
|
|
748
|
+
orderId,
|
|
749
|
+
orderItemId: firstItem.id,
|
|
750
|
+
discountId,
|
|
751
|
+
discountCode,
|
|
752
|
+
discountAmount,
|
|
753
|
+
userId: contactId
|
|
754
|
+
}));
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
for (const item of discountedItems) {
|
|
758
|
+
const i = item;
|
|
759
|
+
await odRepo.save(odRepo.create({
|
|
760
|
+
orderId,
|
|
761
|
+
orderItemId: i.id,
|
|
762
|
+
discountId,
|
|
763
|
+
discountCode,
|
|
764
|
+
discountAmount: Number(i.discount ?? 0),
|
|
765
|
+
userId: contactId
|
|
766
|
+
}));
|
|
767
|
+
}
|
|
768
|
+
} catch (err) {
|
|
769
|
+
console.error("[discountEngine] recordDiscountUsage failed:", err);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
__name(recordDiscountUsage, "recordDiscountUsage");
|
|
773
|
+
async function consumeAppliedDiscountUsages(dataSource, entityMap, orderId, contactId, applied) {
|
|
774
|
+
const unique = /* @__PURE__ */ new Map();
|
|
775
|
+
for (const row of applied) {
|
|
776
|
+
const id = Number(row.id);
|
|
777
|
+
if (!Number.isFinite(id) || id < 1) continue;
|
|
778
|
+
const amount = Math.max(0, Number(row.calculatedDiscount) || 0);
|
|
779
|
+
unique.set(id, (unique.get(id) ?? 0) + amount);
|
|
780
|
+
}
|
|
781
|
+
for (const [discountId, discountAmount] of unique) {
|
|
782
|
+
const usageErr = await checkAndIncrementDiscountUsage(dataSource, entityMap, discountId, contactId);
|
|
783
|
+
if (usageErr) return usageErr;
|
|
784
|
+
await recordDiscountUsage(dataSource, entityMap, orderId, discountId, contactId, discountAmount);
|
|
785
|
+
}
|
|
786
|
+
return null;
|
|
787
|
+
}
|
|
788
|
+
__name(consumeAppliedDiscountUsages, "consumeAppliedDiscountUsages");
|
|
789
|
+
|
|
649
790
|
// src/lib/default-vendor-id.ts
|
|
650
791
|
function getDefaultVendorId() {
|
|
651
792
|
const raw = process.env.DEFAULT_VENDOR_ID;
|
|
@@ -1989,6 +2130,7 @@ async function ensureUniqueProductSlug(repo, baseSlug, vendorId, excludeId) {
|
|
|
1989
2130
|
let slug = baseSlug;
|
|
1990
2131
|
let suffix = 0;
|
|
1991
2132
|
while (true) {
|
|
2133
|
+
await retireSoftDeletedUniqueValue(repo, "slug", slug);
|
|
1992
2134
|
const where = excludeId != null ? {
|
|
1993
2135
|
slug,
|
|
1994
2136
|
vendorId,
|
|
@@ -2008,6 +2150,21 @@ async function ensureUniqueProductSlug(repo, baseSlug, vendorId, excludeId) {
|
|
|
2008
2150
|
}
|
|
2009
2151
|
}
|
|
2010
2152
|
__name(ensureUniqueProductSlug, "ensureUniqueProductSlug");
|
|
2153
|
+
async function normalizeComboNameAndSlug(repo, body, vendorId, existing, excludeId) {
|
|
2154
|
+
const incomingName = typeof body.name === "string" ? body.name.trim() : "";
|
|
2155
|
+
const incomingSlugRaw = typeof body.slug === "string" ? body.slug.trim() : "";
|
|
2156
|
+
const existingName = typeof existing?.name === "string" ? existing.name.trim() : "";
|
|
2157
|
+
const existingSlug = typeof existing?.slug === "string" ? existing.slug.trim() : "";
|
|
2158
|
+
const name = incomingName || existingName;
|
|
2159
|
+
if (!name) return "Name is required";
|
|
2160
|
+
if (incomingName) body.name = name;
|
|
2161
|
+
const nameBasedSlug = slugifyProductLabel(name);
|
|
2162
|
+
const typedSlug = incomingSlugRaw ? slugifyProductLabel(incomingSlugRaw) : "";
|
|
2163
|
+
const slug = typedSlug || (excludeId != null ? existingSlug : "") || nameBasedSlug;
|
|
2164
|
+
body.slug = await ensureUniqueProductSlug(repo, slug, vendorId, excludeId);
|
|
2165
|
+
return null;
|
|
2166
|
+
}
|
|
2167
|
+
__name(normalizeComboNameAndSlug, "normalizeComboNameAndSlug");
|
|
2011
2168
|
async function hydrateProductEventNames(dataSource, entityMap, products) {
|
|
2012
2169
|
if (!products.length) return products;
|
|
2013
2170
|
if (!entityMap.event_products || !entityMap.events) {
|
|
@@ -2254,6 +2411,20 @@ async function normalizeProductNameAndSlug(repo, body, vendorId, existing, exclu
|
|
|
2254
2411
|
return null;
|
|
2255
2412
|
}
|
|
2256
2413
|
__name(normalizeProductNameAndSlug, "normalizeProductNameAndSlug");
|
|
2414
|
+
async function retireSoftDeletedUniquesFromBody(repo, body) {
|
|
2415
|
+
const cols = new Set(repo.metadata.columns.map((c) => c.propertyName));
|
|
2416
|
+
if (!cols.has("deleted")) return;
|
|
2417
|
+
for (const col of [
|
|
2418
|
+
"slug",
|
|
2419
|
+
"email"
|
|
2420
|
+
]) {
|
|
2421
|
+
if (!cols.has(col)) continue;
|
|
2422
|
+
const raw = body[col];
|
|
2423
|
+
if (typeof raw !== "string" || !raw.trim()) continue;
|
|
2424
|
+
await retireSoftDeletedUniqueValue(repo, col, raw.trim());
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
__name(retireSoftDeletedUniquesFromBody, "retireSoftDeletedUniquesFromBody");
|
|
2257
2428
|
function buildSoftDeletePayload(meta, deletedBy) {
|
|
2258
2429
|
const payload = {
|
|
2259
2430
|
deleted: true
|
|
@@ -2490,6 +2661,7 @@ function discountEvaluateRule(rule, cartLines, cartTotal) {
|
|
|
2490
2661
|
case "category":
|
|
2491
2662
|
case "cart":
|
|
2492
2663
|
case "paymentMethod":
|
|
2664
|
+
case "deviceType":
|
|
2493
2665
|
case "order": {
|
|
2494
2666
|
if (rule.subType === "nthOrder") {
|
|
2495
2667
|
return true;
|
|
@@ -2673,87 +2845,22 @@ function applyDiscountToOrderLines(lines, evalResult, maxDiscountAmount) {
|
|
|
2673
2845
|
return totalDiscountApplied;
|
|
2674
2846
|
}
|
|
2675
2847
|
__name(applyDiscountToOrderLines, "applyDiscountToOrderLines");
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
const discountRepo = dataSource.getRepository(entityMap["discounts"]);
|
|
2679
|
-
const discount = await discountRepo.findOne({
|
|
2680
|
-
where: {
|
|
2681
|
-
id: discountId
|
|
2682
|
-
}
|
|
2683
|
-
});
|
|
2684
|
-
if (!discount) return `Discount #${discountId} not found`;
|
|
2685
|
-
await dataSource.query(`UPDATE discounts SET "usedCount" = "usedCount" + 1 WHERE id = $1`, [
|
|
2686
|
-
discountId
|
|
2687
|
-
]);
|
|
2688
|
-
return null;
|
|
2848
|
+
function asDiscountUsageEntityMap(entityMap) {
|
|
2849
|
+
return entityMap;
|
|
2689
2850
|
}
|
|
2690
|
-
__name(
|
|
2691
|
-
async function
|
|
2692
|
-
|
|
2693
|
-
try {
|
|
2694
|
-
await dataSource.query(`UPDATE discounts SET "usedCount" = GREATEST("usedCount" - 1, 0) WHERE id = $1`, [
|
|
2695
|
-
discountId
|
|
2696
|
-
]);
|
|
2697
|
-
if (entityMap["order_discounts"]) {
|
|
2698
|
-
await dataSource.getRepository(entityMap["order_discounts"]).delete({
|
|
2699
|
-
orderId,
|
|
2700
|
-
discountId
|
|
2701
|
-
});
|
|
2702
|
-
}
|
|
2703
|
-
} catch (err) {
|
|
2704
|
-
console.error("[discountEngine] decrementDiscountUsage failed:", err);
|
|
2705
|
-
}
|
|
2851
|
+
__name(asDiscountUsageEntityMap, "asDiscountUsageEntityMap");
|
|
2852
|
+
async function checkAndIncrementDiscountUsage2(dataSource, entityMap, discountId, contactId) {
|
|
2853
|
+
return checkAndIncrementDiscountUsage(dataSource, asDiscountUsageEntityMap(entityMap), discountId, contactId);
|
|
2706
2854
|
}
|
|
2707
|
-
__name(
|
|
2708
|
-
async function
|
|
2709
|
-
|
|
2710
|
-
try {
|
|
2711
|
-
let discountCode = "";
|
|
2712
|
-
if (entityMap["discounts"]) {
|
|
2713
|
-
const discountRow = await dataSource.getRepository(entityMap["discounts"]).findOne({
|
|
2714
|
-
where: {
|
|
2715
|
-
id: discountId
|
|
2716
|
-
}
|
|
2717
|
-
});
|
|
2718
|
-
discountCode = discountRow?.couponCode ?? "";
|
|
2719
|
-
}
|
|
2720
|
-
const odRepo = dataSource.getRepository(entityMap["order_discounts"]);
|
|
2721
|
-
const orderItemRepo = dataSource.getRepository(entityMap.order_items);
|
|
2722
|
-
const items = await orderItemRepo.find({
|
|
2723
|
-
where: {
|
|
2724
|
-
orderId
|
|
2725
|
-
}
|
|
2726
|
-
});
|
|
2727
|
-
const discountedItems = items.filter((item) => Number(item.discount ?? 0) > 0);
|
|
2728
|
-
if (discountedItems.length === 0) {
|
|
2729
|
-
const firstItem = items[0];
|
|
2730
|
-
if (!firstItem) return;
|
|
2731
|
-
await odRepo.save(odRepo.create({
|
|
2732
|
-
orderId,
|
|
2733
|
-
orderItemId: firstItem.id,
|
|
2734
|
-
discountId,
|
|
2735
|
-
discountCode,
|
|
2736
|
-
discountAmount,
|
|
2737
|
-
userId: contactId
|
|
2738
|
-
}));
|
|
2739
|
-
return;
|
|
2740
|
-
}
|
|
2741
|
-
for (const item of discountedItems) {
|
|
2742
|
-
const i = item;
|
|
2743
|
-
await odRepo.save(odRepo.create({
|
|
2744
|
-
orderId,
|
|
2745
|
-
orderItemId: i.id,
|
|
2746
|
-
discountId,
|
|
2747
|
-
discountCode,
|
|
2748
|
-
discountAmount: Number(i.discount ?? 0),
|
|
2749
|
-
userId: contactId
|
|
2750
|
-
}));
|
|
2751
|
-
}
|
|
2752
|
-
} catch (err) {
|
|
2753
|
-
console.error("[discountEngine] recordDiscountUsage failed:", err);
|
|
2754
|
-
}
|
|
2855
|
+
__name(checkAndIncrementDiscountUsage2, "checkAndIncrementDiscountUsage");
|
|
2856
|
+
async function decrementDiscountUsage2(dataSource, entityMap, discountId, orderId) {
|
|
2857
|
+
return decrementDiscountUsage(dataSource, asDiscountUsageEntityMap(entityMap), discountId, orderId);
|
|
2755
2858
|
}
|
|
2756
|
-
__name(
|
|
2859
|
+
__name(decrementDiscountUsage2, "decrementDiscountUsage");
|
|
2860
|
+
async function recordDiscountUsage2(dataSource, entityMap, orderId, discountId, contactId, discountAmount) {
|
|
2861
|
+
return recordDiscountUsage(dataSource, asDiscountUsageEntityMap(entityMap), orderId, discountId, contactId, discountAmount);
|
|
2862
|
+
}
|
|
2863
|
+
__name(recordDiscountUsage2, "recordDiscountUsage");
|
|
2757
2864
|
async function validateCoupon(dataSource, entityMap, couponCode, orderLines, currency = "INR", contactId, isAutomatic, discountId, vendorId) {
|
|
2758
2865
|
if (!entityMap["discounts"]) return {
|
|
2759
2866
|
valid: false,
|
|
@@ -2798,21 +2905,12 @@ async function validateCoupon(dataSource, entityMap, couponCode, orderLines, cur
|
|
|
2798
2905
|
};
|
|
2799
2906
|
}
|
|
2800
2907
|
if (contactId != null && d.maxUsagePerUser != null) {
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
]);
|
|
2808
|
-
const usageCount = Number(userUsage?.[0]?.count ?? 0);
|
|
2809
|
-
if (usageCount >= d.maxUsagePerUser) {
|
|
2810
|
-
return {
|
|
2811
|
-
valid: false,
|
|
2812
|
-
error: "You have reached the maximum usage limit for this discount"
|
|
2813
|
-
};
|
|
2814
|
-
}
|
|
2815
|
-
} catch {
|
|
2908
|
+
const usageCount = await countDiscountOrdersForContact(dataSource, d.id, contactId);
|
|
2909
|
+
if (usageCount >= d.maxUsagePerUser) {
|
|
2910
|
+
return {
|
|
2911
|
+
valid: false,
|
|
2912
|
+
error: "You have reached the maximum usage limit for this discount"
|
|
2913
|
+
};
|
|
2816
2914
|
}
|
|
2817
2915
|
}
|
|
2818
2916
|
const flatRules = entityMap["discount_rules"] ? await dataSource.getRepository(entityMap["discount_rules"]).find({
|
|
@@ -2890,128 +2988,32 @@ function normalizeOrderLinesInput(raw) {
|
|
|
2890
2988
|
if (!Number.isFinite(productId) || productId <= 0) continue;
|
|
2891
2989
|
const qRaw = Number(r.quantity ?? 1);
|
|
2892
2990
|
const q = Number.isFinite(qRaw) ? Math.min(99999, Math.max(1, Math.floor(qRaw))) : 1;
|
|
2893
|
-
|
|
2991
|
+
const vidRaw = r.variantId ?? r.variant_id;
|
|
2992
|
+
const vid = vidRaw != null && String(vidRaw).trim() !== "" ? Number(vidRaw) : NaN;
|
|
2993
|
+
const variantId = Number.isFinite(vid) && vid > 0 ? vid : null;
|
|
2994
|
+
const key = `${productId}:${variantId ?? 0}`;
|
|
2995
|
+
const prev = merged.get(key);
|
|
2996
|
+
if (prev) prev.quantity += q;
|
|
2997
|
+
else merged.set(key, {
|
|
2998
|
+
productId,
|
|
2999
|
+
quantity: q,
|
|
3000
|
+
variantId
|
|
3001
|
+
});
|
|
2894
3002
|
}
|
|
2895
3003
|
return [
|
|
2896
|
-
...merged.
|
|
2897
|
-
]
|
|
2898
|
-
productId,
|
|
2899
|
-
quantity
|
|
2900
|
-
}));
|
|
3004
|
+
...merged.values()
|
|
3005
|
+
];
|
|
2901
3006
|
}
|
|
2902
3007
|
__name(normalizeOrderLinesInput, "normalizeOrderLinesInput");
|
|
2903
3008
|
var ORDER_STATUS_CONFIRMED = "confirmed";
|
|
2904
|
-
function
|
|
2905
|
-
|
|
2906
|
-
status: order.status ?? "pending",
|
|
2907
|
-
lines: (order.items ?? []).map((i) => ({
|
|
2908
|
-
productId: Number(i.productId),
|
|
2909
|
-
quantity: Math.max(0, Math.floor(Number(i.quantity) || 0))
|
|
2910
|
-
})).filter((l) => l.productId > 0 && l.quantity > 0)
|
|
2911
|
-
};
|
|
2912
|
-
}
|
|
2913
|
-
__name(orderInventorySnapshotFromRow, "orderInventorySnapshotFromRow");
|
|
2914
|
-
function mergeInventoryLinesByProduct(lines) {
|
|
2915
|
-
const m = /* @__PURE__ */ new Map();
|
|
2916
|
-
for (const { productId, quantity } of lines) {
|
|
2917
|
-
if (!Number.isFinite(productId) || productId <= 0 || quantity <= 0) continue;
|
|
2918
|
-
m.set(productId, (m.get(productId) ?? 0) + quantity);
|
|
2919
|
-
}
|
|
2920
|
-
return m;
|
|
2921
|
-
}
|
|
2922
|
-
__name(mergeInventoryLinesByProduct, "mergeInventoryLinesByProduct");
|
|
2923
|
-
async function validateInventoryForConfirmedOrderLines(dataSource, entityMap, calcLines) {
|
|
2924
|
-
const productRepo = dataSource.getRepository(entityMap.products);
|
|
2925
|
-
const merged = mergeInventoryLinesByProduct(calcLines.filter((l) => l.found && l.productId != null).map((l) => ({
|
|
3009
|
+
async function validateInventoryForConfirmedOrderLines2(dataSource, entityMap, calcLines) {
|
|
3010
|
+
const lines = calcLines.filter((l) => l.found && l.productId != null).map((l) => ({
|
|
2926
3011
|
productId: l.productId,
|
|
2927
3012
|
quantity: l.quantity
|
|
2928
|
-
}))
|
|
2929
|
-
|
|
2930
|
-
const row = await productRepo.findOne({
|
|
2931
|
-
where: {
|
|
2932
|
-
id: productId,
|
|
2933
|
-
deleted: false
|
|
2934
|
-
}
|
|
2935
|
-
});
|
|
2936
|
-
if (!row) return `Product #${productId} not found`;
|
|
2937
|
-
if (row.type === "service") continue;
|
|
2938
|
-
const cur = Number(row.quantity ?? 0);
|
|
2939
|
-
if (cur < qty) {
|
|
2940
|
-
const name = row.name ?? String(productId);
|
|
2941
|
-
return `Insufficient stock for ${name}: available ${cur}, required ${qty}`;
|
|
2942
|
-
}
|
|
2943
|
-
}
|
|
2944
|
-
return null;
|
|
2945
|
-
}
|
|
2946
|
-
__name(validateInventoryForConfirmedOrderLines, "validateInventoryForConfirmedOrderLines");
|
|
2947
|
-
async function applyInventoryDeltaForMergedLines(dataSource, entityMap, merged, sign, validateDeduct) {
|
|
2948
|
-
const productRepo = dataSource.getRepository(entityMap.products);
|
|
2949
|
-
for (const [productId, qty] of merged) {
|
|
2950
|
-
const row = await productRepo.findOne({
|
|
2951
|
-
where: {
|
|
2952
|
-
id: productId,
|
|
2953
|
-
deleted: false
|
|
2954
|
-
}
|
|
2955
|
-
});
|
|
2956
|
-
if (!row) return `Product #${productId} not found`;
|
|
2957
|
-
if (row.type === "service") continue;
|
|
2958
|
-
const cur = Number(row.quantity ?? 0);
|
|
2959
|
-
if (sign === -1) {
|
|
2960
|
-
if (validateDeduct && cur < qty) {
|
|
2961
|
-
const name = row.name ?? String(productId);
|
|
2962
|
-
return `Insufficient stock for ${name}: available ${cur}, required ${qty}`;
|
|
2963
|
-
}
|
|
2964
|
-
await productRepo.update(productId, {
|
|
2965
|
-
quantity: Math.max(0, cur - qty)
|
|
2966
|
-
});
|
|
2967
|
-
} else {
|
|
2968
|
-
await productRepo.update(productId, {
|
|
2969
|
-
quantity: cur + qty
|
|
2970
|
-
});
|
|
2971
|
-
}
|
|
2972
|
-
}
|
|
2973
|
-
return null;
|
|
2974
|
-
}
|
|
2975
|
-
__name(applyInventoryDeltaForMergedLines, "applyInventoryDeltaForMergedLines");
|
|
2976
|
-
async function validateInventoryForOrderBecomingConfirmed(dataSource, entityMap, prevSnap, nextLines) {
|
|
2977
|
-
const mergedNext = mergeInventoryLinesByProduct(nextLines);
|
|
2978
|
-
const productRepo = dataSource.getRepository(entityMap.products);
|
|
2979
|
-
const prevByProduct = prevSnap?.status === ORDER_STATUS_CONFIRMED ? mergeInventoryLinesByProduct(prevSnap.lines) : /* @__PURE__ */ new Map();
|
|
2980
|
-
for (const [productId, need] of mergedNext) {
|
|
2981
|
-
const row = await productRepo.findOne({
|
|
2982
|
-
where: {
|
|
2983
|
-
id: productId,
|
|
2984
|
-
deleted: false
|
|
2985
|
-
}
|
|
2986
|
-
});
|
|
2987
|
-
if (!row) return `Product #${productId} not found`;
|
|
2988
|
-
if (row.type === "service") continue;
|
|
2989
|
-
let available = Number(row.quantity ?? 0);
|
|
2990
|
-
available += prevByProduct.get(productId) ?? 0;
|
|
2991
|
-
if (available < need) {
|
|
2992
|
-
const name = row.name ?? String(productId);
|
|
2993
|
-
return `Insufficient stock for ${name}: available ${available}, required ${need}`;
|
|
2994
|
-
}
|
|
2995
|
-
}
|
|
2996
|
-
return null;
|
|
2997
|
-
}
|
|
2998
|
-
__name(validateInventoryForOrderBecomingConfirmed, "validateInventoryForOrderBecomingConfirmed");
|
|
2999
|
-
async function reconcileOrderInventoryBetweenSnapshots(dataSource, entityMap, prev, next) {
|
|
3000
|
-
const wasConfirmed = prev.status === ORDER_STATUS_CONFIRMED;
|
|
3001
|
-
const isConfirmed = next.status === ORDER_STATUS_CONFIRMED;
|
|
3002
|
-
if (wasConfirmed) {
|
|
3003
|
-
const merged = mergeInventoryLinesByProduct(prev.lines);
|
|
3004
|
-
const err = await applyInventoryDeltaForMergedLines(dataSource, entityMap, merged, 1, false);
|
|
3005
|
-
if (err) return err;
|
|
3006
|
-
}
|
|
3007
|
-
if (isConfirmed) {
|
|
3008
|
-
const merged = mergeInventoryLinesByProduct(next.lines);
|
|
3009
|
-
const err = await applyInventoryDeltaForMergedLines(dataSource, entityMap, merged, -1, true);
|
|
3010
|
-
if (err) return err;
|
|
3011
|
-
}
|
|
3012
|
-
return null;
|
|
3013
|
+
}));
|
|
3014
|
+
return validateInventoryForConfirmedOrderLines(dataSource, entityMap, lines);
|
|
3013
3015
|
}
|
|
3014
|
-
__name(
|
|
3016
|
+
__name(validateInventoryForConfirmedOrderLines2, "validateInventoryForConfirmedOrderLines");
|
|
3015
3017
|
async function resolveProductTaxRate(dataSource, entityMap, productId, productVendorId) {
|
|
3016
3018
|
if (!entityMap.product_config || !entityMap.taxes) {
|
|
3017
3019
|
return {
|
|
@@ -4997,6 +4999,22 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
4997
4999
|
status: 400
|
|
4998
5000
|
});
|
|
4999
5001
|
}
|
|
5002
|
+
if (resource === "combos") {
|
|
5003
|
+
const vendorIdForSlug = scopeCreate.type === "vendor" ? scopeCreate.vendorId : Number(persistBody.vendorId);
|
|
5004
|
+
if (!Number.isFinite(vendorIdForSlug) || vendorIdForSlug <= 0) {
|
|
5005
|
+
return json({
|
|
5006
|
+
error: "vendorId is required"
|
|
5007
|
+
}, {
|
|
5008
|
+
status: 400
|
|
5009
|
+
});
|
|
5010
|
+
}
|
|
5011
|
+
const comboSlugErr = await normalizeComboNameAndSlug(repo, persistBody, vendorIdForSlug);
|
|
5012
|
+
if (comboSlugErr) return json({
|
|
5013
|
+
error: comboSlugErr
|
|
5014
|
+
}, {
|
|
5015
|
+
status: 400
|
|
5016
|
+
});
|
|
5017
|
+
}
|
|
5000
5018
|
sanitizeBodyForEntity(repo, persistBody);
|
|
5001
5019
|
let created;
|
|
5002
5020
|
try {
|
|
@@ -5095,6 +5113,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
5095
5113
|
persistBody.orderNumber = `ORD00${randomPart}`;
|
|
5096
5114
|
persistBody.qrToken = crypto2.randomBytes(16).toString("hex");
|
|
5097
5115
|
}
|
|
5116
|
+
await retireSoftDeletedUniquesFromBody(repo, persistBody);
|
|
5098
5117
|
created = await repo.save(repo.create(persistBody));
|
|
5099
5118
|
if (resource === "orders") {
|
|
5100
5119
|
const orderItemRepo = dataSource.getRepository(entityMap.order_items);
|
|
@@ -5136,8 +5155,8 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
5136
5155
|
}
|
|
5137
5156
|
}
|
|
5138
5157
|
const createdStatus = String(persistBody.status ?? "pending");
|
|
5139
|
-
if (createdStatus
|
|
5140
|
-
const stockErr = await
|
|
5158
|
+
if (orderStatusHoldsStock(createdStatus)) {
|
|
5159
|
+
const stockErr = await validateInventoryForConfirmedOrderLines2(dataSource, entityMap, lines);
|
|
5141
5160
|
if (stockErr) {
|
|
5142
5161
|
await repo.delete(created.id);
|
|
5143
5162
|
return json({
|
|
@@ -5159,6 +5178,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
5159
5178
|
await orderItemRepo.save(orderItemRepo.create({
|
|
5160
5179
|
orderId: created.id,
|
|
5161
5180
|
productId: line.productId,
|
|
5181
|
+
variantId: null,
|
|
5162
5182
|
quantity: line.quantity,
|
|
5163
5183
|
unitPrice: line.unitPrice,
|
|
5164
5184
|
subTotal: line.subtotal,
|
|
@@ -5252,7 +5272,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
5252
5272
|
}
|
|
5253
5273
|
if (orderDiscountId) {
|
|
5254
5274
|
if (createdStatus === ORDER_STATUS_CONFIRMED) {
|
|
5255
|
-
const usageErr = await
|
|
5275
|
+
const usageErr = await checkAndIncrementDiscountUsage2(dataSource, entityMap, orderDiscountId, persistBody.contactId);
|
|
5256
5276
|
if (usageErr) {
|
|
5257
5277
|
await repo.delete(created.id);
|
|
5258
5278
|
return json({
|
|
@@ -5262,7 +5282,7 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
5262
5282
|
});
|
|
5263
5283
|
}
|
|
5264
5284
|
}
|
|
5265
|
-
await
|
|
5285
|
+
await recordDiscountUsage2(dataSource, entityMap, created.id, orderDiscountId, persistBody.contactId, discount);
|
|
5266
5286
|
}
|
|
5267
5287
|
const orderIdForNotify = created.id;
|
|
5268
5288
|
void import('./emit-order-notification-trigger-IVLWKKJL.js').then(({ fireOrderNotificationTrigger }) => {
|
|
@@ -5271,6 +5291,16 @@ function createCrudHandler(dataSource, entityMap, options) {
|
|
|
5271
5291
|
entityMap
|
|
5272
5292
|
});
|
|
5273
5293
|
});
|
|
5294
|
+
if (getCms) {
|
|
5295
|
+
void import('./send-order-placed-emails-WPI37KRZ.js').then(({ sendOrderPlacedEmailsAfterConfirmation }) => {
|
|
5296
|
+
return sendOrderPlacedEmailsAfterConfirmation(orderIdForNotify, {
|
|
5297
|
+
getDataSource: /* @__PURE__ */ __name(async () => dataSource, "getDataSource"),
|
|
5298
|
+
entityMap,
|
|
5299
|
+
getCms: /* @__PURE__ */ __name(async () => await getCms(), "getCms")
|
|
5300
|
+
});
|
|
5301
|
+
}).catch(() => {
|
|
5302
|
+
});
|
|
5303
|
+
}
|
|
5274
5304
|
}
|
|
5275
5305
|
} catch (err) {
|
|
5276
5306
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -5916,6 +5946,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
5916
5946
|
}
|
|
5917
5947
|
}
|
|
5918
5948
|
sanitizeBodyForEntity(repo, updatePayload2);
|
|
5949
|
+
await retireSoftDeletedUniquesFromBody(repo, updatePayload2);
|
|
5919
5950
|
await repo.update(numericId, updatePayload2);
|
|
5920
5951
|
if (Array.isArray(rawBody.tags)) {
|
|
5921
5952
|
const tagNames = rawBody.tags.map((t) => String(t).trim()).filter(Boolean);
|
|
@@ -6004,7 +6035,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6004
6035
|
} : await calculateOrderTotalsFromLines(dataSource, entityMap, orderLinesNorm, effectiveCurrency, putDiscountId, Number.isFinite(putOrderVendorId) ? putOrderVendorId : null);
|
|
6005
6036
|
const scalarUpdate = pickColumnUpdates(repo, rawBody);
|
|
6006
6037
|
const nextStatus = typeof scalarUpdate.status === "string" && scalarUpdate.status ? String(scalarUpdate.status) : orderInvPrev?.status ?? "pending";
|
|
6007
|
-
if (nextStatus
|
|
6038
|
+
if (orderStatusHoldsStock(nextStatus) && lines.length > 0) {
|
|
6008
6039
|
const verr = await validateInventoryForOrderBecomingConfirmed(dataSource, entityMap, orderInvPrev, lines.filter((l) => l.found && l.productId != null).map((l) => ({
|
|
6009
6040
|
productId: l.productId,
|
|
6010
6041
|
quantity: l.quantity
|
|
@@ -6133,17 +6164,17 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6133
6164
|
}) : null;
|
|
6134
6165
|
const existingDiscountId = existingOd ? existingOd.discountId : null;
|
|
6135
6166
|
if (!putDiscountId && existingDiscountId && wasConfirmed) {
|
|
6136
|
-
await
|
|
6167
|
+
await decrementDiscountUsage2(dataSource, entityMap, existingDiscountId, numericId);
|
|
6137
6168
|
if (entityMap["order_discounts"] && existingOd) {
|
|
6138
6169
|
await dataSource.getRepository(entityMap["order_discounts"]).delete(existingOd.id);
|
|
6139
6170
|
}
|
|
6140
6171
|
}
|
|
6141
6172
|
if (putDiscountId && existingDiscountId && putDiscountId !== existingDiscountId) {
|
|
6142
6173
|
if (wasConfirmed) {
|
|
6143
|
-
await
|
|
6174
|
+
await decrementDiscountUsage2(dataSource, entityMap, existingDiscountId, numericId);
|
|
6144
6175
|
}
|
|
6145
6176
|
if (isNowConfirmed) {
|
|
6146
|
-
const usageErr = await
|
|
6177
|
+
const usageErr = await checkAndIncrementDiscountUsage2(dataSource, entityMap, putDiscountId, cid);
|
|
6147
6178
|
if (usageErr) return json({
|
|
6148
6179
|
error: usageErr
|
|
6149
6180
|
}, {
|
|
@@ -6156,12 +6187,12 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6156
6187
|
discountAmount: discount
|
|
6157
6188
|
});
|
|
6158
6189
|
} else {
|
|
6159
|
-
await
|
|
6190
|
+
await recordDiscountUsage2(dataSource, entityMap, numericId, putDiscountId, cid, discount);
|
|
6160
6191
|
}
|
|
6161
6192
|
}
|
|
6162
6193
|
if (putDiscountId && existingDiscountId && putDiscountId === existingDiscountId) {
|
|
6163
6194
|
if (!wasConfirmed && isNowConfirmed) {
|
|
6164
|
-
const usageErr = await
|
|
6195
|
+
const usageErr = await checkAndIncrementDiscountUsage2(dataSource, entityMap, putDiscountId, cid);
|
|
6165
6196
|
if (usageErr) return json({
|
|
6166
6197
|
error: usageErr
|
|
6167
6198
|
}, {
|
|
@@ -6169,7 +6200,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6169
6200
|
});
|
|
6170
6201
|
}
|
|
6171
6202
|
if (wasConfirmed && !isNowConfirmed) {
|
|
6172
|
-
await
|
|
6203
|
+
await decrementDiscountUsage2(dataSource, entityMap, putDiscountId, numericId);
|
|
6173
6204
|
}
|
|
6174
6205
|
if (existingOd && entityMap["order_discounts"]) {
|
|
6175
6206
|
await dataSource.getRepository(entityMap["order_discounts"]).update(existingOd.id, {
|
|
@@ -6179,14 +6210,14 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6179
6210
|
}
|
|
6180
6211
|
if (putDiscountId && !existingDiscountId) {
|
|
6181
6212
|
if (isNowConfirmed) {
|
|
6182
|
-
const usageErr = await
|
|
6213
|
+
const usageErr = await checkAndIncrementDiscountUsage2(dataSource, entityMap, putDiscountId, cid);
|
|
6183
6214
|
if (usageErr) return json({
|
|
6184
6215
|
error: usageErr
|
|
6185
6216
|
}, {
|
|
6186
6217
|
status: 400
|
|
6187
6218
|
});
|
|
6188
6219
|
}
|
|
6189
|
-
await
|
|
6220
|
+
await recordDiscountUsage2(dataSource, entityMap, numericId, putDiscountId, cid, discount);
|
|
6190
6221
|
}
|
|
6191
6222
|
}
|
|
6192
6223
|
}
|
|
@@ -6657,7 +6688,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6657
6688
|
}
|
|
6658
6689
|
if (resource === "orders" && orderInvPrev) {
|
|
6659
6690
|
const nextSt = typeof updatePayload.status === "string" && updatePayload.status ? String(updatePayload.status) : orderInvPrev.status;
|
|
6660
|
-
if (nextSt
|
|
6691
|
+
if (orderStatusHoldsStock(nextSt) && orderInvPrev.lines.length > 0) {
|
|
6661
6692
|
const verr = await validateInventoryForOrderBecomingConfirmed(dataSource, entityMap, orderInvPrev, orderInvPrev.lines);
|
|
6662
6693
|
if (verr) return json({
|
|
6663
6694
|
error: verr
|
|
@@ -6666,6 +6697,33 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6666
6697
|
});
|
|
6667
6698
|
}
|
|
6668
6699
|
}
|
|
6700
|
+
if (resource === "combos") {
|
|
6701
|
+
const currentCombo = await repo.findOne({
|
|
6702
|
+
where: {
|
|
6703
|
+
id: numericId,
|
|
6704
|
+
deleted: false
|
|
6705
|
+
}
|
|
6706
|
+
});
|
|
6707
|
+
if (!currentCombo) return json({
|
|
6708
|
+
message: "Not found"
|
|
6709
|
+
}, {
|
|
6710
|
+
status: 404
|
|
6711
|
+
});
|
|
6712
|
+
const vendorIdForSlug = scopePut.type === "vendor" ? scopePut.vendorId : Number(currentCombo.vendorId);
|
|
6713
|
+
if (!Number.isFinite(vendorIdForSlug) || vendorIdForSlug <= 0) {
|
|
6714
|
+
return json({
|
|
6715
|
+
error: "vendorId is required"
|
|
6716
|
+
}, {
|
|
6717
|
+
status: 400
|
|
6718
|
+
});
|
|
6719
|
+
}
|
|
6720
|
+
const comboSlugErr = await normalizeComboNameAndSlug(repo, updatePayload, vendorIdForSlug, currentCombo, numericId);
|
|
6721
|
+
if (comboSlugErr) return json({
|
|
6722
|
+
error: comboSlugErr
|
|
6723
|
+
}, {
|
|
6724
|
+
status: 400
|
|
6725
|
+
});
|
|
6726
|
+
}
|
|
6669
6727
|
if (Object.keys(updatePayload).length > 0) {
|
|
6670
6728
|
if (resource === "payments" && updatePayload.status === "paid" && updatePayload.paidAt == null) {
|
|
6671
6729
|
const existingPayment = await repo.findOne({
|
|
@@ -6679,6 +6737,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6679
6737
|
}
|
|
6680
6738
|
}
|
|
6681
6739
|
sanitizeBodyForEntity(repo, updatePayload);
|
|
6740
|
+
await retireSoftDeletedUniquesFromBody(repo, updatePayload);
|
|
6682
6741
|
await repo.update(numericId, updatePayload);
|
|
6683
6742
|
}
|
|
6684
6743
|
if (resource === "orders" && rawBody && entityMap["order_addresses"]) {
|
|
@@ -6854,7 +6913,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6854
6913
|
});
|
|
6855
6914
|
if (od) {
|
|
6856
6915
|
const odRow = od;
|
|
6857
|
-
await
|
|
6916
|
+
await decrementDiscountUsage2(dataSource, entityMap, odRow.discountId, numericId);
|
|
6858
6917
|
}
|
|
6859
6918
|
}
|
|
6860
6919
|
}
|
|
@@ -6867,11 +6926,19 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
|
|
|
6867
6926
|
}
|
|
6868
6927
|
}
|
|
6869
6928
|
await repo.update(numericId, buildSoftDeletePayload(repo.metadata, deletedBy));
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6929
|
+
const softDeletedCols = repo.metadata.columns.map((c) => c.propertyName);
|
|
6930
|
+
const uniqueColsToRetire = [
|
|
6931
|
+
"slug",
|
|
6932
|
+
"email"
|
|
6933
|
+
].filter((col) => softDeletedCols.includes(col));
|
|
6934
|
+
if (existing && uniqueColsToRetire.length > 0) {
|
|
6935
|
+
for (const col of uniqueColsToRetire) {
|
|
6936
|
+
const raw = existing[col];
|
|
6937
|
+
if (typeof raw !== "string") continue;
|
|
6938
|
+
const value = raw.trim();
|
|
6939
|
+
if (!value || value.includes("__deleted_")) continue;
|
|
6873
6940
|
await repo.update(numericId, {
|
|
6874
|
-
|
|
6941
|
+
[col]: `${value}__deleted_${numericId}`
|
|
6875
6942
|
});
|
|
6876
6943
|
}
|
|
6877
6944
|
}
|
|
@@ -6919,6 +6986,49 @@ async function linkUnclaimedContactToUser(dataSource, contactsEntity, userId, em
|
|
|
6919
6986
|
});
|
|
6920
6987
|
}
|
|
6921
6988
|
__name(linkUnclaimedContactToUser, "linkUnclaimedContactToUser");
|
|
6989
|
+
function buildUserInviteLink(baseUrl, token) {
|
|
6990
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
6991
|
+
return `${base}/admin/invite?token=${encodeURIComponent(token)}`;
|
|
6992
|
+
}
|
|
6993
|
+
__name(buildUserInviteLink, "buildUserInviteLink");
|
|
6994
|
+
function newUserInviteToken() {
|
|
6995
|
+
return randomBytes(32).toString("hex");
|
|
6996
|
+
}
|
|
6997
|
+
__name(newUserInviteToken, "newUserInviteToken");
|
|
6998
|
+
async function findUserByInviteToken(dataSource, userEntity, token) {
|
|
6999
|
+
const trimmed = token.trim();
|
|
7000
|
+
if (!trimmed) return null;
|
|
7001
|
+
const repo = dataSource.getRepository(userEntity);
|
|
7002
|
+
const row = await repo.findOne({
|
|
7003
|
+
where: {
|
|
7004
|
+
inviteToken: trimmed,
|
|
7005
|
+
deleted: false
|
|
7006
|
+
},
|
|
7007
|
+
select: [
|
|
7008
|
+
"id",
|
|
7009
|
+
"email",
|
|
7010
|
+
"blocked",
|
|
7011
|
+
"password",
|
|
7012
|
+
"inviteStatus",
|
|
7013
|
+
"inviteToken"
|
|
7014
|
+
]
|
|
7015
|
+
});
|
|
7016
|
+
if (!row) return null;
|
|
7017
|
+
const u = row;
|
|
7018
|
+
return u;
|
|
7019
|
+
}
|
|
7020
|
+
__name(findUserByInviteToken, "findUserByInviteToken");
|
|
7021
|
+
async function completeUserInviteAccept(dataSource, userEntity, userId, passwordHash) {
|
|
7022
|
+
await dataSource.getRepository(userEntity).update(userId, {
|
|
7023
|
+
password: passwordHash,
|
|
7024
|
+
blocked: false,
|
|
7025
|
+
inviteStatus: "active",
|
|
7026
|
+
inviteToken: null
|
|
7027
|
+
});
|
|
7028
|
+
}
|
|
7029
|
+
__name(completeUserInviteAccept, "completeUserInviteAccept");
|
|
7030
|
+
|
|
7031
|
+
// src/lib/vendor-invite-token.ts
|
|
6922
7032
|
var VENDOR_INVITE_METADATA_TOKEN = "inviteToken";
|
|
6923
7033
|
var VENDOR_INVITE_METADATA_EXPIRES = "inviteExpiresAt";
|
|
6924
7034
|
var VENDOR_INVITE_METADATA_SENT = "inviteSentAt";
|
|
@@ -6943,6 +7053,13 @@ function invalidatedInviteMessage() {
|
|
|
6943
7053
|
return "This invitation is no longer valid. Ask an admin to resend the invite.";
|
|
6944
7054
|
}
|
|
6945
7055
|
__name(invalidatedInviteMessage, "invalidatedInviteMessage");
|
|
7056
|
+
function userAlreadyActive(user) {
|
|
7057
|
+
const hasPassword = !!(user.password && String(user.password).trim());
|
|
7058
|
+
if (user.inviteStatus === "active" && hasPassword) return true;
|
|
7059
|
+
if (user.inviteStatus === "pending") return false;
|
|
7060
|
+
return !user.blocked && hasPassword;
|
|
7061
|
+
}
|
|
7062
|
+
__name(userAlreadyActive, "userAlreadyActive");
|
|
6946
7063
|
async function validateInviteTokenForActivation(dataSource, entityMap, token) {
|
|
6947
7064
|
const trimmedToken = String(token ?? "").trim();
|
|
6948
7065
|
if (!trimmedToken) {
|
|
@@ -6989,15 +7106,15 @@ async function validateInviteTokenForActivation(dataSource, entityMap, token) {
|
|
|
6989
7106
|
"id",
|
|
6990
7107
|
"email",
|
|
6991
7108
|
"blocked",
|
|
6992
|
-
"password"
|
|
7109
|
+
"password",
|
|
7110
|
+
"inviteStatus"
|
|
6993
7111
|
]
|
|
6994
7112
|
});
|
|
6995
7113
|
if (!user2) return {
|
|
6996
7114
|
ok: false,
|
|
6997
7115
|
error: "User not found"
|
|
6998
7116
|
};
|
|
6999
|
-
|
|
7000
|
-
if (!user2.blocked && hasPassword2) {
|
|
7117
|
+
if (userAlreadyActive(user2)) {
|
|
7001
7118
|
return {
|
|
7002
7119
|
ok: false,
|
|
7003
7120
|
error: "User is already active"
|
|
@@ -7013,6 +7130,24 @@ async function validateInviteTokenForActivation(dataSource, entityMap, token) {
|
|
|
7013
7130
|
};
|
|
7014
7131
|
}
|
|
7015
7132
|
}
|
|
7133
|
+
if (userRepo && entityMap.users) {
|
|
7134
|
+
const userMatch = await findUserByInviteToken(dataSource, entityMap.users, trimmedToken);
|
|
7135
|
+
if (userMatch) {
|
|
7136
|
+
if (userMatch.inviteStatus === "active" || userAlreadyActive(userMatch)) {
|
|
7137
|
+
return {
|
|
7138
|
+
ok: false,
|
|
7139
|
+
error: "This invitation has already been accepted"
|
|
7140
|
+
};
|
|
7141
|
+
}
|
|
7142
|
+
return {
|
|
7143
|
+
ok: true,
|
|
7144
|
+
target: {
|
|
7145
|
+
userId: userMatch.id,
|
|
7146
|
+
email: userMatch.email
|
|
7147
|
+
}
|
|
7148
|
+
};
|
|
7149
|
+
}
|
|
7150
|
+
}
|
|
7016
7151
|
let email;
|
|
7017
7152
|
try {
|
|
7018
7153
|
email = Buffer.from(trimmedToken, "base64").toString("utf8").trim();
|
|
@@ -7042,22 +7177,30 @@ async function validateInviteTokenForActivation(dataSource, entityMap, token) {
|
|
|
7042
7177
|
"id",
|
|
7043
7178
|
"email",
|
|
7044
7179
|
"blocked",
|
|
7045
|
-
"password"
|
|
7180
|
+
"password",
|
|
7181
|
+
"inviteStatus",
|
|
7182
|
+
"inviteToken"
|
|
7046
7183
|
]
|
|
7047
7184
|
});
|
|
7048
7185
|
if (!user) return {
|
|
7049
7186
|
ok: false,
|
|
7050
7187
|
error: "User not found"
|
|
7051
7188
|
};
|
|
7052
|
-
const
|
|
7053
|
-
if (
|
|
7189
|
+
const u = user;
|
|
7190
|
+
if (userAlreadyActive(u)) {
|
|
7054
7191
|
return {
|
|
7055
7192
|
ok: false,
|
|
7056
7193
|
error: "User is already active"
|
|
7057
7194
|
};
|
|
7058
7195
|
}
|
|
7196
|
+
if (u.inviteToken && String(u.inviteToken).trim()) {
|
|
7197
|
+
return {
|
|
7198
|
+
ok: false,
|
|
7199
|
+
error: invalidatedInviteMessage()
|
|
7200
|
+
};
|
|
7201
|
+
}
|
|
7059
7202
|
if (entityMap.vendors) {
|
|
7060
|
-
const ownerVendor = await loadOwnerVendorForUser(dataSource, entityMap.vendors,
|
|
7203
|
+
const ownerVendor = await loadOwnerVendorForUser(dataSource, entityMap.vendors, u.id);
|
|
7061
7204
|
if (ownerVendor && readVendorInviteToken(ownerVendor.metadata)) {
|
|
7062
7205
|
return {
|
|
7063
7206
|
ok: false,
|
|
@@ -7068,8 +7211,8 @@ async function validateInviteTokenForActivation(dataSource, entityMap, token) {
|
|
|
7068
7211
|
return {
|
|
7069
7212
|
ok: true,
|
|
7070
7213
|
target: {
|
|
7071
|
-
userId:
|
|
7072
|
-
email: String(
|
|
7214
|
+
userId: u.id,
|
|
7215
|
+
email: String(u.email)
|
|
7073
7216
|
}
|
|
7074
7217
|
};
|
|
7075
7218
|
}
|
|
@@ -7287,10 +7430,7 @@ function createInviteAcceptHandler(config) {
|
|
|
7287
7430
|
}
|
|
7288
7431
|
if (beforeActivate) await beforeActivate(email, userId);
|
|
7289
7432
|
const hashedPassword = await hashPassword(password);
|
|
7290
|
-
await dataSource
|
|
7291
|
-
password: hashedPassword,
|
|
7292
|
-
blocked: false
|
|
7293
|
-
});
|
|
7433
|
+
await completeUserInviteAccept(dataSource, entityMap.users, userId, hashedPassword);
|
|
7294
7434
|
if (vendorId != null && entityMap.vendors) {
|
|
7295
7435
|
await completeVendorInviteAccept(dataSource, entityMap.vendors, vendorId);
|
|
7296
7436
|
}
|
|
@@ -7651,50 +7791,6 @@ async function findLlmAgentByScope(dataSource, entityMap, scope, options = {}) {
|
|
|
7651
7791
|
}
|
|
7652
7792
|
__name(findLlmAgentByScope, "findLlmAgentByScope");
|
|
7653
7793
|
|
|
7654
|
-
// src/lib/retire-soft-deleted-unique.ts
|
|
7655
|
-
async function retireSoftDeletedUniqueValue(repo, column, value) {
|
|
7656
|
-
const trimmed = typeof value === "string" ? value.trim() : "";
|
|
7657
|
-
if (!trimmed) return;
|
|
7658
|
-
const cols = new Set(repo.metadata.columns.map((c) => c.propertyName));
|
|
7659
|
-
if (!cols.has(column) || !cols.has("deleted")) return;
|
|
7660
|
-
const rows = await repo.find({
|
|
7661
|
-
where: {
|
|
7662
|
-
[column]: trimmed,
|
|
7663
|
-
deleted: true
|
|
7664
|
-
}
|
|
7665
|
-
});
|
|
7666
|
-
for (const row of rows) {
|
|
7667
|
-
const id = row.id;
|
|
7668
|
-
if (!Number.isFinite(id)) continue;
|
|
7669
|
-
const current = String(row[column] ?? "");
|
|
7670
|
-
if (current.includes("__deleted_")) continue;
|
|
7671
|
-
await repo.update(id, {
|
|
7672
|
-
[column]: `${trimmed}__deleted_${id}`
|
|
7673
|
-
});
|
|
7674
|
-
}
|
|
7675
|
-
}
|
|
7676
|
-
__name(retireSoftDeletedUniqueValue, "retireSoftDeletedUniqueValue");
|
|
7677
|
-
async function activeUniqueValueExists(repo, column, value, excludeId) {
|
|
7678
|
-
const trimmed = typeof value === "string" ? value.trim() : "";
|
|
7679
|
-
if (!trimmed) return false;
|
|
7680
|
-
const cols = new Set(repo.metadata.columns.map((c) => c.propertyName));
|
|
7681
|
-
if (!cols.has(column)) return false;
|
|
7682
|
-
const qb = repo.createQueryBuilder("row").where(`row.${column} = :value`, {
|
|
7683
|
-
value: trimmed
|
|
7684
|
-
});
|
|
7685
|
-
if (cols.has("deleted")) {
|
|
7686
|
-
qb.andWhere("row.deleted = false");
|
|
7687
|
-
}
|
|
7688
|
-
if (excludeId != null && Number.isFinite(excludeId) && excludeId > 0) {
|
|
7689
|
-
qb.andWhere("row.id != :excludeId", {
|
|
7690
|
-
excludeId
|
|
7691
|
-
});
|
|
7692
|
-
}
|
|
7693
|
-
const hit = await qb.getOne();
|
|
7694
|
-
return !!hit;
|
|
7695
|
-
}
|
|
7696
|
-
__name(activeUniqueValueExists, "activeUniqueValueExists");
|
|
7697
|
-
|
|
7698
7794
|
// src/lib/media-folder-path.ts
|
|
7699
7795
|
function sanitizeMediaFolderPath(input) {
|
|
7700
7796
|
if (input == null) return "";
|
|
@@ -8761,6 +8857,9 @@ function createUploadHandler(config) {
|
|
|
8761
8857
|
"image/png",
|
|
8762
8858
|
"image/gif",
|
|
8763
8859
|
"image/webp",
|
|
8860
|
+
"video/mp4",
|
|
8861
|
+
"video/webm",
|
|
8862
|
+
"video/quicktime",
|
|
8764
8863
|
"application/pdf",
|
|
8765
8864
|
"text/plain",
|
|
8766
8865
|
"application/zip",
|
|
@@ -8788,8 +8887,11 @@ function createUploadHandler(config) {
|
|
|
8788
8887
|
});
|
|
8789
8888
|
const defaultMax = 10 * 1024 * 1024;
|
|
8790
8889
|
const maxZipBytes = 80 * 1024 * 1024;
|
|
8890
|
+
const maxVideoBytes = 100 * 1024 * 1024;
|
|
8791
8891
|
const baseMax = maxSizeBytes ?? defaultMax;
|
|
8792
|
-
const
|
|
8892
|
+
const isZip = file.type === "application/zip" || file.type === "application/x-zip-compressed";
|
|
8893
|
+
const isVideo = file.type === "video/mp4" || file.type === "video/webm" || file.type === "video/quicktime";
|
|
8894
|
+
const effectiveMax = isZip ? Math.max(baseMax, maxZipBytes) : isVideo ? Math.max(baseMax, maxVideoBytes) : baseMax;
|
|
8793
8895
|
if (file.size > effectiveMax) return json({
|
|
8794
8896
|
error: "File size exceeds limit"
|
|
8795
8897
|
}, {
|
|
@@ -8862,12 +8964,20 @@ function createUploadHandler(config) {
|
|
|
8862
8964
|
parentId
|
|
8863
8965
|
});
|
|
8864
8966
|
} catch (err) {
|
|
8967
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
8865
8968
|
console.error("[upload] File upload failed", {
|
|
8866
|
-
error:
|
|
8969
|
+
error: message,
|
|
8867
8970
|
stack: err instanceof Error ? err.stack : void 0,
|
|
8868
8971
|
name: err instanceof Error ? err.name : void 0,
|
|
8869
8972
|
metadata: err && typeof err === "object" && "$metadata" in err ? err.$metadata : void 0
|
|
8870
8973
|
});
|
|
8974
|
+
if (/Failed to parse body as FormData/i.test(message)) {
|
|
8975
|
+
return json({
|
|
8976
|
+
error: "File upload failed: request body could not be read as FormData. Exclude /api/upload from middleware matcher and raise proxyClientMaxBodySize."
|
|
8977
|
+
}, {
|
|
8978
|
+
status: 500
|
|
8979
|
+
});
|
|
8980
|
+
}
|
|
8871
8981
|
return json({
|
|
8872
8982
|
error: "File upload failed"
|
|
8873
8983
|
}, {
|
|
@@ -9621,7 +9731,8 @@ function createUsersApiHandlers(config) {
|
|
|
9621
9731
|
"name",
|
|
9622
9732
|
"email",
|
|
9623
9733
|
"id",
|
|
9624
|
-
"blocked"
|
|
9734
|
+
"blocked",
|
|
9735
|
+
"inviteStatus"
|
|
9625
9736
|
]);
|
|
9626
9737
|
const sortField = allowedSort.has(sortFieldRaw) ? sortFieldRaw : "createdAt";
|
|
9627
9738
|
const sortOrder = url.searchParams.get("sortOrder") === "desc" ? "DESC" : "ASC";
|
|
@@ -9634,6 +9745,7 @@ function createUsersApiHandlers(config) {
|
|
|
9634
9745
|
"u.name",
|
|
9635
9746
|
"u.email",
|
|
9636
9747
|
"u.blocked",
|
|
9748
|
+
"u.inviteStatus",
|
|
9637
9749
|
"u.createdAt",
|
|
9638
9750
|
"u.updatedAt",
|
|
9639
9751
|
"u.groupId",
|
|
@@ -9729,6 +9841,7 @@ function createUsersApiHandlers(config) {
|
|
|
9729
9841
|
const isCustomer = !!(customerG && gid === customerG.id);
|
|
9730
9842
|
const adminAccess = isCustomer ? false : body.adminAccess === false ? false : true;
|
|
9731
9843
|
const blocked = body.blocked === true || body.blocked === "true" || body.blocked === 1 || body.blocked === "1";
|
|
9844
|
+
const inviteToken = newUserInviteToken();
|
|
9732
9845
|
const newUser = existing?.deleted ? await (async () => {
|
|
9733
9846
|
await userRepo().update(existing.id, {
|
|
9734
9847
|
deleted: false,
|
|
@@ -9738,6 +9851,8 @@ function createUsersApiHandlers(config) {
|
|
|
9738
9851
|
email,
|
|
9739
9852
|
password: null,
|
|
9740
9853
|
blocked,
|
|
9854
|
+
inviteStatus: "pending",
|
|
9855
|
+
inviteToken,
|
|
9741
9856
|
groupId: gid,
|
|
9742
9857
|
adminAccess,
|
|
9743
9858
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -9754,6 +9869,8 @@ function createUsersApiHandlers(config) {
|
|
|
9754
9869
|
email,
|
|
9755
9870
|
password: null,
|
|
9756
9871
|
blocked,
|
|
9872
|
+
inviteStatus: "pending",
|
|
9873
|
+
inviteToken,
|
|
9757
9874
|
groupId: gid,
|
|
9758
9875
|
adminAccess
|
|
9759
9876
|
}));
|
|
@@ -9771,13 +9888,12 @@ function createUsersApiHandlers(config) {
|
|
|
9771
9888
|
phone
|
|
9772
9889
|
});
|
|
9773
9890
|
}
|
|
9774
|
-
const
|
|
9775
|
-
const inviteLink = `${baseUrl}/admin/invite?token=${emailToken}`;
|
|
9776
|
-
await trySendInviteEmail(newUser.email, inviteLink, newUser.name ?? "");
|
|
9891
|
+
const inviteLink = buildUserInviteLink(baseUrl, inviteToken);
|
|
9777
9892
|
return json({
|
|
9778
|
-
message:
|
|
9893
|
+
message: "User created successfully. Invite is pending until they set a password.",
|
|
9779
9894
|
user: newUser,
|
|
9780
|
-
inviteLink
|
|
9895
|
+
inviteLink,
|
|
9896
|
+
emailSent: false
|
|
9781
9897
|
}, {
|
|
9782
9898
|
status: 201
|
|
9783
9899
|
});
|
|
@@ -9811,6 +9927,7 @@ function createUsersApiHandlers(config) {
|
|
|
9811
9927
|
"email",
|
|
9812
9928
|
"phone",
|
|
9813
9929
|
"blocked",
|
|
9930
|
+
"inviteStatus",
|
|
9814
9931
|
"createdAt",
|
|
9815
9932
|
"updatedAt",
|
|
9816
9933
|
"groupId"
|
|
@@ -9923,6 +10040,7 @@ function createUsersApiHandlers(config) {
|
|
|
9923
10040
|
"email",
|
|
9924
10041
|
"phone",
|
|
9925
10042
|
"blocked",
|
|
10043
|
+
"inviteStatus",
|
|
9926
10044
|
"createdAt",
|
|
9927
10045
|
"updatedAt",
|
|
9928
10046
|
"groupId"
|
|
@@ -9990,13 +10108,21 @@ function createUsersApiHandlers(config) {
|
|
|
9990
10108
|
});
|
|
9991
10109
|
}
|
|
9992
10110
|
},
|
|
9993
|
-
async regenerateInvite(
|
|
9994
|
-
const authErr = await requireAuth(new Request(
|
|
10111
|
+
async regenerateInvite(req, id) {
|
|
10112
|
+
const authErr = await requireAuth(new Request(req.url));
|
|
9995
10113
|
if (authErr) return authErr;
|
|
9996
10114
|
if (requireEntityPermission) {
|
|
9997
|
-
const pe = await requireEntityPermission(
|
|
10115
|
+
const pe = await requireEntityPermission(req, "users", "update");
|
|
9998
10116
|
if (pe) return pe;
|
|
9999
10117
|
}
|
|
10118
|
+
let sendEmail = true;
|
|
10119
|
+
let rotate = true;
|
|
10120
|
+
try {
|
|
10121
|
+
const body = await req.json().catch(() => ({}));
|
|
10122
|
+
if (body.sendEmail === false) sendEmail = false;
|
|
10123
|
+
if (body.rotate === false) rotate = false;
|
|
10124
|
+
} catch {
|
|
10125
|
+
}
|
|
10000
10126
|
try {
|
|
10001
10127
|
const user = await userRepo().findOne({
|
|
10002
10128
|
where: {
|
|
@@ -10006,7 +10132,11 @@ function createUsersApiHandlers(config) {
|
|
|
10006
10132
|
select: [
|
|
10007
10133
|
"id",
|
|
10008
10134
|
"email",
|
|
10009
|
-
"name"
|
|
10135
|
+
"name",
|
|
10136
|
+
"password",
|
|
10137
|
+
"inviteStatus",
|
|
10138
|
+
"inviteToken",
|
|
10139
|
+
"blocked"
|
|
10010
10140
|
]
|
|
10011
10141
|
});
|
|
10012
10142
|
if (!user) return json({
|
|
@@ -10014,34 +10144,75 @@ function createUsersApiHandlers(config) {
|
|
|
10014
10144
|
}, {
|
|
10015
10145
|
status: 404
|
|
10016
10146
|
});
|
|
10017
|
-
|
|
10147
|
+
const u = user;
|
|
10148
|
+
const hasPassword = !!(u.password && String(u.password).trim());
|
|
10149
|
+
if (u.inviteStatus === "active" && hasPassword) {
|
|
10150
|
+
return json({
|
|
10151
|
+
error: "User has already accepted the invite"
|
|
10152
|
+
}, {
|
|
10153
|
+
status: 400
|
|
10154
|
+
});
|
|
10155
|
+
}
|
|
10156
|
+
let inviteLink = "";
|
|
10018
10157
|
if (entityMap.vendors) {
|
|
10019
10158
|
const vendorRepo = dataSource.getRepository(entityMap.vendors);
|
|
10020
10159
|
const vendor = await vendorRepo.findOne({
|
|
10021
10160
|
where: {
|
|
10022
|
-
userId:
|
|
10161
|
+
userId: u.id,
|
|
10023
10162
|
deleted: false
|
|
10024
10163
|
}
|
|
10025
10164
|
});
|
|
10026
10165
|
const v = vendor;
|
|
10027
10166
|
if (v && (v.inviteStatus === "pending" || v.inviteStatus === "expired")) {
|
|
10028
|
-
const
|
|
10029
|
-
|
|
10030
|
-
|
|
10031
|
-
|
|
10032
|
-
|
|
10033
|
-
|
|
10167
|
+
const nextMetadata = rotate ? applyRotatingVendorInvite(v.metadata) : {
|
|
10168
|
+
...v.metadata ?? {}
|
|
10169
|
+
};
|
|
10170
|
+
if (rotate || v.inviteStatus !== "pending") {
|
|
10171
|
+
await vendorRepo.update(v.id, {
|
|
10172
|
+
metadata: nextMetadata,
|
|
10173
|
+
inviteStatus: "pending"
|
|
10174
|
+
});
|
|
10175
|
+
}
|
|
10176
|
+
const token = readVendorInviteToken(nextMetadata);
|
|
10034
10177
|
if (token) {
|
|
10035
10178
|
inviteLink = buildVendorInviteLink(baseUrl, token);
|
|
10036
10179
|
}
|
|
10180
|
+
const { markVendorInvitePendingForUser } = await import('./vendor-invite-status-PWJ3DE76.js');
|
|
10181
|
+
await markVendorInvitePendingForUser(dataSource, entityMap.vendors, u.id);
|
|
10182
|
+
}
|
|
10183
|
+
}
|
|
10184
|
+
if (!inviteLink) {
|
|
10185
|
+
let token = u.inviteToken?.trim() || "";
|
|
10186
|
+
if (rotate || !token) {
|
|
10187
|
+
token = newUserInviteToken();
|
|
10188
|
+
await userRepo().update(u.id, {
|
|
10189
|
+
inviteToken: token,
|
|
10190
|
+
inviteStatus: "pending",
|
|
10191
|
+
password: null
|
|
10192
|
+
});
|
|
10193
|
+
} else if (u.inviteStatus !== "pending") {
|
|
10194
|
+
await userRepo().update(u.id, {
|
|
10195
|
+
inviteStatus: "pending"
|
|
10196
|
+
});
|
|
10037
10197
|
}
|
|
10038
|
-
|
|
10039
|
-
|
|
10198
|
+
inviteLink = buildUserInviteLink(baseUrl, token);
|
|
10199
|
+
} else if (rotate) {
|
|
10200
|
+
await userRepo().update(u.id, {
|
|
10201
|
+
inviteStatus: "pending",
|
|
10202
|
+
password: null
|
|
10203
|
+
});
|
|
10040
10204
|
}
|
|
10041
|
-
|
|
10205
|
+
let emailSent = false;
|
|
10206
|
+
if (sendEmail && inviteLink) {
|
|
10207
|
+
await trySendInviteEmail(u.email, inviteLink, u.name ?? "");
|
|
10208
|
+
emailSent = true;
|
|
10209
|
+
}
|
|
10210
|
+
const rotatedNote = rotate ? " Previous invite link is no longer valid." : "";
|
|
10042
10211
|
return json({
|
|
10043
|
-
message: "New invite link
|
|
10044
|
-
|
|
10212
|
+
message: emailSent ? `Invite email sent.${rotatedNote}` : sendEmail ? `Invite link ready (email may not have been sent \u2014 check email plugin).${rotatedNote}` : rotate ? "New invite link created. Previous invite link is no longer valid." : "Invite link ready.",
|
|
10213
|
+
emailSent,
|
|
10214
|
+
inviteLink,
|
|
10215
|
+
inviteStatus: "pending"
|
|
10045
10216
|
});
|
|
10046
10217
|
} catch {
|
|
10047
10218
|
return json({
|
|
@@ -14746,6 +14917,13 @@ var User = class {
|
|
|
14746
14917
|
phoneVerifiedAt;
|
|
14747
14918
|
emailVerifiedAt;
|
|
14748
14919
|
password;
|
|
14920
|
+
/**
|
|
14921
|
+
* `pending` = invite outstanding (cannot sign in until password is set).
|
|
14922
|
+
* `active` = invite accepted / account usable (subject to `blocked`).
|
|
14923
|
+
*/
|
|
14924
|
+
inviteStatus;
|
|
14925
|
+
/** Rotating invite token; null when active or no invite outstanding. */
|
|
14926
|
+
inviteToken;
|
|
14749
14927
|
blocked;
|
|
14750
14928
|
adminAccess;
|
|
14751
14929
|
groupId;
|
|
@@ -14798,6 +14976,24 @@ _ts_decorate4([
|
|
|
14798
14976
|
}),
|
|
14799
14977
|
_ts_metadata4("design:type", Object)
|
|
14800
14978
|
], User.prototype, "password", void 0);
|
|
14979
|
+
_ts_decorate4([
|
|
14980
|
+
Column({
|
|
14981
|
+
type: "enum",
|
|
14982
|
+
enum: [
|
|
14983
|
+
"pending",
|
|
14984
|
+
"active"
|
|
14985
|
+
],
|
|
14986
|
+
enumName: "users_invitestatus_enum",
|
|
14987
|
+
default: "active"
|
|
14988
|
+
}),
|
|
14989
|
+
_ts_metadata4("design:type", typeof UserInviteStatus === "undefined" ? Object : UserInviteStatus)
|
|
14990
|
+
], User.prototype, "inviteStatus", void 0);
|
|
14991
|
+
_ts_decorate4([
|
|
14992
|
+
Column("varchar", {
|
|
14993
|
+
nullable: true
|
|
14994
|
+
}),
|
|
14995
|
+
_ts_metadata4("design:type", Object)
|
|
14996
|
+
], User.prototype, "inviteToken", void 0);
|
|
14801
14997
|
_ts_decorate4([
|
|
14802
14998
|
Column("boolean", {
|
|
14803
14999
|
default: false
|
|
@@ -19531,6 +19727,8 @@ var OrderItem = class {
|
|
|
19531
19727
|
id;
|
|
19532
19728
|
orderId;
|
|
19533
19729
|
productId;
|
|
19730
|
+
/** Selected product variant at order time (optional). */
|
|
19731
|
+
variantId;
|
|
19534
19732
|
discountIds;
|
|
19535
19733
|
vendorId;
|
|
19536
19734
|
vendor;
|
|
@@ -19566,6 +19764,12 @@ _ts_decorate39([
|
|
|
19566
19764
|
Column("int"),
|
|
19567
19765
|
_ts_metadata39("design:type", Number)
|
|
19568
19766
|
], OrderItem.prototype, "productId", void 0);
|
|
19767
|
+
_ts_decorate39([
|
|
19768
|
+
Column("int", {
|
|
19769
|
+
nullable: true
|
|
19770
|
+
}),
|
|
19771
|
+
_ts_metadata39("design:type", Object)
|
|
19772
|
+
], OrderItem.prototype, "variantId", void 0);
|
|
19569
19773
|
_ts_decorate39([
|
|
19570
19774
|
Column({
|
|
19571
19775
|
type: "int",
|
|
@@ -20375,6 +20579,7 @@ var Type = /* @__PURE__ */ (function(Type2) {
|
|
|
20375
20579
|
Type2["CATEGORY"] = "category";
|
|
20376
20580
|
Type2["CART"] = "cart";
|
|
20377
20581
|
Type2["PAYMENT_METHOD"] = "paymentMethod";
|
|
20582
|
+
Type2["DEVICE_TYPE"] = "deviceType";
|
|
20378
20583
|
Type2["ORDER"] = "order";
|
|
20379
20584
|
Type2["QUANTITY"] = "quantity";
|
|
20380
20585
|
Type2["TIME"] = "time";
|
|
@@ -22397,6 +22602,7 @@ var Combo = class {
|
|
|
22397
22602
|
vendorId;
|
|
22398
22603
|
vendor;
|
|
22399
22604
|
name;
|
|
22605
|
+
slug;
|
|
22400
22606
|
desc;
|
|
22401
22607
|
eventId;
|
|
22402
22608
|
event;
|
|
@@ -22440,6 +22646,12 @@ _ts_decorate63([
|
|
|
22440
22646
|
}),
|
|
22441
22647
|
_ts_metadata63("design:type", String)
|
|
22442
22648
|
], Combo.prototype, "name", void 0);
|
|
22649
|
+
_ts_decorate63([
|
|
22650
|
+
Column({
|
|
22651
|
+
type: "varchar"
|
|
22652
|
+
}),
|
|
22653
|
+
_ts_metadata63("design:type", String)
|
|
22654
|
+
], Combo.prototype, "slug", void 0);
|
|
22443
22655
|
_ts_decorate63([
|
|
22444
22656
|
Column({
|
|
22445
22657
|
type: "text",
|
|
@@ -22577,7 +22789,11 @@ _ts_decorate63([
|
|
|
22577
22789
|
_ts_metadata63("design:type", Number)
|
|
22578
22790
|
], Combo.prototype, "deletedBy", void 0);
|
|
22579
22791
|
Combo = _ts_decorate63([
|
|
22580
|
-
Entity("combos")
|
|
22792
|
+
Entity("combos"),
|
|
22793
|
+
Unique("UQ_combos_vendor_slug", [
|
|
22794
|
+
"vendorId",
|
|
22795
|
+
"slug"
|
|
22796
|
+
])
|
|
22581
22797
|
], Combo);
|
|
22582
22798
|
function _ts_decorate64(decorators, target, key, desc) {
|
|
22583
22799
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -26503,8 +26719,11 @@ function createMessageTemplateRowLoader(dataSource, entityMap) {
|
|
|
26503
26719
|
};
|
|
26504
26720
|
}
|
|
26505
26721
|
__name(createMessageTemplateRowLoader, "createMessageTemplateRowLoader");
|
|
26506
|
-
function registerMessagingQueueProcessors(cms) {
|
|
26507
|
-
registerEmailQueueProcessor(cms
|
|
26722
|
+
function registerMessagingQueueProcessors(cms, entityMap) {
|
|
26723
|
+
registerEmailQueueProcessor(cms, {
|
|
26724
|
+
getDataSource: /* @__PURE__ */ __name(async () => cms.dataSource, "getDataSource"),
|
|
26725
|
+
entityMap
|
|
26726
|
+
});
|
|
26508
26727
|
registerWhatsAppQueueProcessor(cms);
|
|
26509
26728
|
}
|
|
26510
26729
|
__name(registerMessagingQueueProcessors, "registerMessagingQueueProcessors");
|
|
@@ -26556,7 +26775,7 @@ async function ensureMessagingPluginsOnCms(base, options) {
|
|
|
26556
26775
|
}
|
|
26557
26776
|
}
|
|
26558
26777
|
const merged = Object.keys(overlay).length > 0 ? overlayCmsPlugins(cms, overlay) : cms;
|
|
26559
|
-
registerMessagingQueueProcessors(merged);
|
|
26778
|
+
registerMessagingQueueProcessors(merged, entityMap);
|
|
26560
26779
|
return merged;
|
|
26561
26780
|
}
|
|
26562
26781
|
__name(ensureMessagingPluginsOnCms, "ensureMessagingPluginsOnCms");
|
|
@@ -26605,7 +26824,7 @@ async function createCmsAppWithMessaging(options) {
|
|
|
26605
26824
|
logger,
|
|
26606
26825
|
plugins: mergedPlugins
|
|
26607
26826
|
});
|
|
26608
|
-
registerMessagingQueueProcessors(cms);
|
|
26827
|
+
registerMessagingQueueProcessors(cms, entityMap);
|
|
26609
26828
|
return cms;
|
|
26610
26829
|
}
|
|
26611
26830
|
__name(createCmsAppWithMessaging, "createCmsAppWithMessaging");
|
|
@@ -26802,7 +27021,7 @@ function createCmsApiHandler(config) {
|
|
|
26802
27021
|
companyDetails
|
|
26803
27022
|
};
|
|
26804
27023
|
if (queue) {
|
|
26805
|
-
const { queueEmail: queueEmail2 } = await import('./email-queue-
|
|
27024
|
+
const { queueEmail: queueEmail2 } = await import('./email-queue-OI2HSCGE.js');
|
|
26806
27025
|
await queueEmail2(cms, {
|
|
26807
27026
|
to: opts.to,
|
|
26808
27027
|
templateName: "passwordReset",
|
|
@@ -28056,14 +28275,27 @@ function createCmsApiHandler(config) {
|
|
|
28056
28275
|
const pe = await requireEntityPermissionEffective(req, "orders", "read");
|
|
28057
28276
|
if (pe) return pe;
|
|
28058
28277
|
const cms = await getCms();
|
|
28059
|
-
const { streamOrderInvoicePdf: streamOrderInvoicePdf2 } = await import('./erp-order-invoice-
|
|
28278
|
+
const { streamOrderInvoicePdf: streamOrderInvoicePdf2 } = await import('./erp-order-invoice-3GXDE443.js');
|
|
28060
28279
|
const oid = Number(path2[1]);
|
|
28061
28280
|
if (!Number.isFinite(oid)) return config.json({
|
|
28062
28281
|
error: "Invalid id"
|
|
28063
28282
|
}, {
|
|
28064
28283
|
status: 400
|
|
28065
28284
|
});
|
|
28066
|
-
|
|
28285
|
+
try {
|
|
28286
|
+
return await streamOrderInvoicePdf2(cms, dataSource, entityMap, oid, {});
|
|
28287
|
+
} catch (err) {
|
|
28288
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
28289
|
+
console.error("[invoice] route failed", {
|
|
28290
|
+
orderId: oid,
|
|
28291
|
+
error: msg
|
|
28292
|
+
});
|
|
28293
|
+
return config.json({
|
|
28294
|
+
error: `Invoice failed: ${msg}`
|
|
28295
|
+
}, {
|
|
28296
|
+
status: 500
|
|
28297
|
+
});
|
|
28298
|
+
}
|
|
28067
28299
|
}
|
|
28068
28300
|
if (path2[0] === "orders" && path2.length === 3 && path2[2] === "repost-erp" && getCms) {
|
|
28069
28301
|
const a = await config.requireAuth(req);
|
|
@@ -28410,7 +28642,7 @@ function createCmsApiHandler(config) {
|
|
|
28410
28642
|
status: 400
|
|
28411
28643
|
});
|
|
28412
28644
|
}
|
|
28413
|
-
const { resendOrderNotification } = await import('./order-notification-dispatcher-
|
|
28645
|
+
const { resendOrderNotification } = await import('./order-notification-dispatcher-ZJZB2HUN.js');
|
|
28414
28646
|
const result = await resendOrderNotification(triggerKey, orderId, {
|
|
28415
28647
|
dataSource,
|
|
28416
28648
|
entityMap,
|
|
@@ -28482,6 +28714,30 @@ function createCmsApiHandler(config) {
|
|
|
28482
28714
|
paymentId = Number(payment.id);
|
|
28483
28715
|
}
|
|
28484
28716
|
}
|
|
28717
|
+
const orderWithItems = await orderRepo.findOne({
|
|
28718
|
+
where: {
|
|
28719
|
+
id: orderId,
|
|
28720
|
+
deleted: false
|
|
28721
|
+
},
|
|
28722
|
+
relations: [
|
|
28723
|
+
"items"
|
|
28724
|
+
]
|
|
28725
|
+
});
|
|
28726
|
+
if (orderWithItems) {
|
|
28727
|
+
const { reconcileOrderInventoryBetweenSnapshots: reconcileOrderInventoryBetweenSnapshots2, orderInventorySnapshotFromRow: orderInventorySnapshotFromRow2 } = await import('./order-inventory-76V4XIGW.js');
|
|
28728
|
+
const prevSnap = orderInventorySnapshotFromRow2(orderWithItems);
|
|
28729
|
+
const invErr = await reconcileOrderInventoryBetweenSnapshots2(dataSource, entityMap, prevSnap, {
|
|
28730
|
+
status: "cancelled",
|
|
28731
|
+
lines: prevSnap.lines
|
|
28732
|
+
});
|
|
28733
|
+
if (invErr) {
|
|
28734
|
+
return config.json({
|
|
28735
|
+
error: invErr
|
|
28736
|
+
}, {
|
|
28737
|
+
status: 400
|
|
28738
|
+
});
|
|
28739
|
+
}
|
|
28740
|
+
}
|
|
28485
28741
|
await orderRepo.update(orderId, {
|
|
28486
28742
|
status: "cancelled"
|
|
28487
28743
|
});
|
|
@@ -29525,6 +29781,14 @@ function createStorefrontApiHandler(config) {
|
|
|
29525
29781
|
entityMap
|
|
29526
29782
|
});
|
|
29527
29783
|
}).catch((err) => console.error("[notification-triggers] import failed", err));
|
|
29784
|
+
if (!getCms) return;
|
|
29785
|
+
void import('./send-order-placed-emails-WPI37KRZ.js').then(({ sendOrderPlacedEmailsAfterConfirmation }) => {
|
|
29786
|
+
return sendOrderPlacedEmailsAfterConfirmation(orderId, {
|
|
29787
|
+
getDataSource: /* @__PURE__ */ __name(async () => dataSource, "getDataSource"),
|
|
29788
|
+
entityMap,
|
|
29789
|
+
getCms
|
|
29790
|
+
});
|
|
29791
|
+
}).catch((err) => console.error("[order-emails] sendOrderPlacedEmailsAfterConfirmation failed", err));
|
|
29528
29792
|
}
|
|
29529
29793
|
__name(fireOrderPlacedNotification, "fireOrderPlacedNotification");
|
|
29530
29794
|
const otpAllowPhoneLogin = config.otpAllowPhoneLogin !== false;
|
|
@@ -31293,9 +31557,12 @@ function createStorefrontApiHandler(config) {
|
|
|
31293
31557
|
}, {
|
|
31294
31558
|
status: 400
|
|
31295
31559
|
});
|
|
31560
|
+
const { retireSoftDeletedUniqueValue: retireSoftDeletedUniqueValue2 } = await import('./retire-soft-deleted-unique-NXQIH4BC.js');
|
|
31561
|
+
await retireSoftDeletedUniqueValue2(userRepo(), "email", email);
|
|
31296
31562
|
const existing = await userRepo().findOne({
|
|
31297
31563
|
where: {
|
|
31298
|
-
email
|
|
31564
|
+
email,
|
|
31565
|
+
deleted: false
|
|
31299
31566
|
}
|
|
31300
31567
|
});
|
|
31301
31568
|
if (existing) return json({
|
|
@@ -32176,6 +32443,7 @@ function createStorefrontApiHandler(config) {
|
|
|
32176
32443
|
unitPrice: line.unitPrice,
|
|
32177
32444
|
tax: line.tax,
|
|
32178
32445
|
total: line.total,
|
|
32446
|
+
metadata: line.metadata ?? null,
|
|
32179
32447
|
product: p ? {
|
|
32180
32448
|
name: p.name,
|
|
32181
32449
|
slug: p.slug,
|
|
@@ -32243,4 +32511,4 @@ function createStorefrontApiHandler(config) {
|
|
|
32243
32511
|
}
|
|
32244
32512
|
__name(createStorefrontApiHandler, "createStorefrontApiHandler");
|
|
32245
32513
|
|
|
32246
|
-
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, customerPhoneForEmail, customerPhoneForUser, daysBeforeEventStart, describeEventTierPolicy, ensureCustomerForUser, ensureCustomerRecord, ensureMessagingPluginsOnCms, ensureScheduleQueueWorker, ensureVendorCustomerForOrderContact, ensureVendorCustomersForOrder, findActiveRefundPolicyForVendor, findVendorByInviteToken, formatTierRange, generateNumericOtp, getPublicSettingsGroup, getRequireEventApproval, getRequireProductApproval, getRssArticleSummaryFromItem, getVendorCatalogCreateFlags, hashOtpCode, hydrateVendorSessionUser, invalidateEventsCache, invalidateMultiVendorCache, invalidateRequireEventApprovalCache, invalidateRequireProductApprovalCache, invalidateVendorCatalogCreateFlagsCache, isCustomerTypeContact, isSyntheticCustomerPhone, isZipMedia, linkUnclaimedContactToUser, llmAgentToChatAgentOptions, loadSettingsGroupFromDb, loadUserVendorContext, mergeGuardrailsIntoSystemPrompt, messagingPlugins, metaFetchUserManagedPages, metaPostPageFeed, metaPostPagePhoto, metaResolvePageAccessToken, normalizeCustomerPhone, 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 };
|
|
32514
|
+
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, buildUserInviteLink, buildVendorInviteLink, calculateOrderRefundPreview, calculateRefundFromPolicy, checkAndIncrementDiscountUsage, checkEventsEnabled, checkMultiVendorEnabled, completeUserInviteAccept, consumeAppliedDiscountUsages, contactIsVendorCustomer, countDiscountOrdersForContact, countRecentOtpSends, createAnalyticsHandlers, createBlogBySlugHandler, createChangePasswordHandler, createCmsApiHandler, createCmsApp, createCmsAppWithMessaging, createCrudByIdHandler, createCrudHandler, createDashboardStatsHandler, createEcommerceAnalyticsHandler, createEventOrderMessageTemplateHandlers, createForgotPasswordHandler, createFormBySlugHandler, createInviteAcceptHandler, createJobScheduleHandlers, createLlmAgentKnowledgeHandlers, createMediaZipExtractHandler, createMessageTemplateRowLoader, createOtpChallenge, createSetPasswordHandler, createSettingsApiHandlers, createSocialMediaHandlers, createStorefrontApiHandler, createUploadHandler, createUserAuthApiRouter, createUserAvatarHandler, createUserProfileHandler, createUsersApiHandlers, createVendorDashboardHandler, createVendorOnboardHandlers, customerPhoneForEmail, customerPhoneForUser, daysBeforeEventStart, decrementDiscountUsage, describeEventTierPolicy, ensureCustomerForUser, ensureCustomerRecord, ensureMessagingPluginsOnCms, ensureScheduleQueueWorker, ensureVendorCustomerForOrderContact, ensureVendorCustomersForOrder, findActiveRefundPolicyForVendor, findUserByInviteToken, findVendorByInviteToken, formatTierRange, generateNumericOtp, getPublicSettingsGroup, getRequireEventApproval, getRequireProductApproval, getRssArticleSummaryFromItem, getVendorCatalogCreateFlags, hashOtpCode, hydrateVendorSessionUser, invalidateEventsCache, invalidateMultiVendorCache, invalidateRequireEventApprovalCache, invalidateRequireProductApprovalCache, invalidateVendorCatalogCreateFlagsCache, isCustomerTypeContact, isMaxPerUserUsageReached, isMaxTotalUsageReached, isSyntheticCustomerPhone, isZipMedia, linkUnclaimedContactToUser, llmAgentToChatAgentOptions, loadSettingsGroupFromDb, loadUserVendorContext, mergeGuardrailsIntoSystemPrompt, messagingPlugins, metaFetchUserManagedPages, metaPostPageFeed, metaPostPagePhoto, metaResolvePageAccessToken, newUserInviteToken, normalizeCustomerPhone, normalizePhoneE164, normalizeRefundTiers, overlayCmsPlugins, parseBlogGeneratorAgentContent, parseBlogGeneratorModelOutput, parseBlogMetadataEnrichmentJson, parseLlmAgentValidationRules, pgBossScheduleNameForId, queueErpCreateContactIfEnabled, queueJobScheduleNow, queuePlugin, queueSms, recordDiscountUsage, registerJobRunnerWorker, registerMessagingQueueProcessors, registerSmsQueueProcessor, relativePathFromMediaParentId, resolveBlogCategoryIdByName, resolveSettingsEncryptionKey, resolveVendorIdForContactCheck, sanitizeMediaFolderPath, sanitizeStorageSegment, sendVendorOnboardEmails, simpleDecrypt, simpleEncrypt, syncJobScheduleToPgBoss, validateRefundTiers, validateScheduleInput, validateUserMessageAgainstAgentRules, validateUserMessageAgainstStructuredRules, verifyAndConsumeOtpChallenge, verifyOtpCodeHash, whatsappPlugin, wrapGetCmsWithMessaging };
|