@mohasinac/appkit 2.7.43 → 2.7.44
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.
|
@@ -14,7 +14,7 @@ import { sendOrderConfirmationEmail } from "../../../../features/contact/server"
|
|
|
14
14
|
import { splitCartIntoOrderGroups } from "../../../../features/orders/index";
|
|
15
15
|
import { resolveDate } from "../../../../utils";
|
|
16
16
|
import { getAdminDb, getAdminRealtimeDb, RTDB_PATHS, } from "../../../../providers/db-firebase";
|
|
17
|
-
import { PRODUCT_COLLECTION } from "../../../../features/products/schemas/firestore";
|
|
17
|
+
import { PRODUCT_COLLECTION, PRODUCT_CODES_SUBCOLLECTION } from "../../../../features/products/schemas/firestore";
|
|
18
18
|
import { CART_COLLECTION } from "../../../../features/cart/schemas/index";
|
|
19
19
|
// S-SBUNI-RULES 2026-05-13 — bundle cart-line stock fan-out helpers.
|
|
20
20
|
import { getCartItemMemberIds, getExpandedDecrements, validateCartItemStock, } from "./bundle-expansion";
|
|
@@ -27,6 +27,36 @@ import { formatShippingAddress } from "./data";
|
|
|
27
27
|
import { enforceMaxPerUserForCart, computePrizeRevealDeadline, } from "./prize-bundle-gates";
|
|
28
28
|
import { getListingRule, runSyncPreflight, } from "../../../shared/checkout/rules";
|
|
29
29
|
import { cartIsDigitalOnly } from "../../../shared/listing-types/cart-shipping";
|
|
30
|
+
/**
|
|
31
|
+
* SB-UNI-N — Atomically claim the next available digital code for a confirmed
|
|
32
|
+
* order. Pre-fetches a candidate code outside the transaction then locks and
|
|
33
|
+
* verifies in a micro-transaction. Fire-and-forget safe (logs on exhaustion
|
|
34
|
+
* but never fails the already-created order).
|
|
35
|
+
*/
|
|
36
|
+
async function claimDigitalCodeForOrder(db, productId, orderId, userId) {
|
|
37
|
+
const codesRef = db
|
|
38
|
+
.collection(PRODUCT_COLLECTION)
|
|
39
|
+
.doc(productId)
|
|
40
|
+
.collection(PRODUCT_CODES_SUBCOLLECTION);
|
|
41
|
+
const snap = await codesRef.where("status", "==", "available").limit(1).get();
|
|
42
|
+
if (snap.empty) {
|
|
43
|
+
serverLogger.warn("claimDigitalCode: code pool exhausted", { productId, orderId });
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const codeRef = snap.docs[0].ref;
|
|
47
|
+
await db.runTransaction(async (tx) => {
|
|
48
|
+
const latest = await tx.get(codeRef);
|
|
49
|
+
if (!latest.exists || latest.data()?.status !== "available")
|
|
50
|
+
return;
|
|
51
|
+
tx.update(codeRef, {
|
|
52
|
+
status: "claimed",
|
|
53
|
+
orderId,
|
|
54
|
+
claimedByUserId: userId,
|
|
55
|
+
claimedAt: new Date(),
|
|
56
|
+
updatedAt: new Date(),
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
30
60
|
/**
|
|
31
61
|
* SB-UNI-O — Live-item jurisdiction guard.
|
|
32
62
|
* Throws ValidationError if any live cart item's allowed states don't include
|
|
@@ -470,6 +500,11 @@ export async function createCheckoutOrderAction(input) {
|
|
|
470
500
|
...extraOrderFields,
|
|
471
501
|
});
|
|
472
502
|
orderIds.push(order.id);
|
|
503
|
+
// SB-UNI-N — claim a digital code for digital-code orders (fire-and-forget,
|
|
504
|
+
// order is already persisted so a claim failure is logged, not thrown).
|
|
505
|
+
if ((group[0]?.product?.listingType ?? "standard") === "digital-code") {
|
|
506
|
+
claimDigitalCodeForOrder(getAdminDb(), firstItem.productId, order.id, uid).catch((e) => serverLogger.error("claimDigitalCode", e));
|
|
507
|
+
}
|
|
473
508
|
for (const code of groupCouponCodes) {
|
|
474
509
|
const entry = couponUsageAccumulator.get(code);
|
|
475
510
|
if (entry)
|
|
@@ -840,6 +875,11 @@ export async function verifyAndPlaceRazorpayOrderAction(input) {
|
|
|
840
875
|
...extraOrderFields,
|
|
841
876
|
});
|
|
842
877
|
orderIds.push(order.id);
|
|
878
|
+
// SB-UNI-N — claim a digital code for digital-code orders (fire-and-forget,
|
|
879
|
+
// order is already persisted so a claim failure is logged, not thrown).
|
|
880
|
+
if ((group[0]?.product?.listingType ?? "standard") === "digital-code") {
|
|
881
|
+
claimDigitalCodeForOrder(getAdminDb(), firstItem.productId, order.id, uid).catch((e) => serverLogger.error("claimDigitalCode", e));
|
|
882
|
+
}
|
|
843
883
|
if (userEmail) {
|
|
844
884
|
emailsToSend.push({
|
|
845
885
|
to: userEmail,
|