@devx-commerce/plugin-loyalty
Version:
A starter for Medusa plugins.
119 lines • 9.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyLoyaltyOnCartWorkflow = void 0;
const utils_1 = require("@medusajs/framework/utils");
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
const core_flows_1 = require("@medusajs/medusa/core-flows");
const query_config_1 = require("../../api/store/carts/query-config");
const helper_1 = require("../../utils/helper");
const update_cart_promotion_1 = require("./custom/update-cart-promotion");
const calculate_points_on_cart_1 = require("./steps/calculate-points-on-cart");
const get_cart_promotion_1 = require("./steps/get-cart-promotion");
const validate_customer_exists_1 = require("./steps/validate-customer-exists");
exports.applyLoyaltyOnCartWorkflow = (0, workflows_sdk_1.createWorkflow)("apply-loyalty-on-cart", (input) => {
const { data: carts } = (0, core_flows_1.useQueryGraphStep)({
entity: "cart",
fields: query_config_1.cartFields,
filters: { id: input.cart_id },
options: { throwIfKeyNotFound: true },
});
const cart = (0, workflows_sdk_1.transform)({ carts }, ({ carts }) => carts[0]);
(0, validate_customer_exists_1.validateCustomerExistsStep)({
customer: cart.customer,
});
// Check if loyalty promotion already exists on cart.
(0, get_cart_promotion_1.getCartPromotionStep)({ cart, throwErrorOn: "found" });
// calculate amount that will be used to create loyalty promotion
const amount = (0, calculate_points_on_cart_1.calculatePointsOnCartStep)({
cart,
throwOnZeroPoints: input.throwOnZeroPoints,
});
// Only create and apply promotion if amount > 0
(0, workflows_sdk_1.when)({ amount }, ({ amount }) => amount > 0).then(() => {
// create promotion payload
const promotionPayload = (0, workflows_sdk_1.transform)({
cart,
amount,
}, (data) => {
const randomStr = Math.random().toString(36).substring(2, 8);
const idSuffix = (data.cart.customer?.id ||
data.cart.id ||
"CART").slice(-6);
const uniqueId = `LOYALTY-${idSuffix}-${randomStr}`.toUpperCase();
return {
code: uniqueId,
type: "standard",
status: "active",
application_method: {
type: "fixed",
value: data.amount,
target_type: "order",
currency_code: data.cart.currency_code,
allocation: "across",
},
rules: [
{
attribute: helper_1.CUSTOMER_ID_PROMOTION_RULE_ATTRIBUTE,
operator: "eq",
values: [data.cart.customer.id],
},
],
campaign: {
name: uniqueId,
description: "Loyalty points promotion for " + data.cart.customer.email,
campaign_identifier: uniqueId,
budget: {
type: "usage",
limit: 1,
},
},
};
});
// create promotion
const promotion = (0, core_flows_1.createPromotionsStep)([
promotionPayload,
]);
// update cart with promotion
const { metadata, ...updatePromoData } = (0, workflows_sdk_1.transform)({
cart,
promotionPayload,
promotion,
}, (data) => {
const promos = [
...(data.cart.promotions
?.map((promo) => promo?.code)
.filter(Boolean) || []),
data.promotionPayload.code,
];
return {
cart_id: data.cart.id,
promo_codes: promos,
action: utils_1.PromotionActions.ADD,
metadata: {
...(data.cart.metadata || {}),
loyalty_promo_id: data.promotion[0].id,
loyalty_amount_used: data.promotion?.[0]?.application_method?.value || 0,
},
};
});
// Write the metadata pointer BEFORE attaching the promotion.
//
// These are two separate commits and cannot be made one (the promotion
// engine owns the attach). Ordering them this way makes the intermediate
// state safe: the pointer may briefly name a promotion that is not yet
// attached, which every reader already tolerates. The reverse order left
// a promotion attached with no pointer — and under concurrency two runs
// could both attach before either wrote its pointer, orphaning the loser
// permanently.
//
// Correctness no longer depends on this ordering (readers resolve loyalty
// by `LOYALTY-` code, not by the pointer), but it keeps the window benign.
(0, core_flows_1.updateCartsStep)([{ id: input.cart_id, metadata }]);
update_cart_promotion_1.updateCartPromotionsWorkflow.runAsStep({ input: updatePromoData });
});
return new workflows_sdk_1.WorkflowResponse({
success: true,
message: "Loyalty applied on cart successfully",
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbHktbG95YWx0eS1vbi1jYXJ0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9jYXJ0L2FwcGx5LWxveWFsdHktb24tY2FydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxxREFBNkQ7QUFDN0QscUVBSzJDO0FBQzNDLDREQUlxQztBQUVyQyxxRUFBZ0U7QUFDaEUsK0NBRzRCO0FBRTVCLDBFQUE4RTtBQUM5RSwrRUFBNkU7QUFDN0UsbUVBQWtFO0FBQ2xFLCtFQUcwQztBQU83QixRQUFBLDBCQUEwQixHQUFHLElBQUEsOEJBQWMsRUFDdEQsdUJBQXVCLEVBQ3ZCLENBQUMsS0FBb0IsRUFBRSxFQUFFO0lBQ3ZCLE1BQU0sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEdBQUcsSUFBQSw4QkFBaUIsRUFBQztRQUN4QyxNQUFNLEVBQUUsTUFBTTtRQUNkLE1BQU0sRUFBRSx5QkFBVTtRQUNsQixPQUFPLEVBQUUsRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLE9BQU8sRUFBRTtRQUM5QixPQUFPLEVBQUUsRUFBRSxrQkFBa0IsRUFBRSxJQUFJLEVBQUU7S0FDdEMsQ0FBQyxDQUFDO0lBRUgsTUFBTSxJQUFJLEdBQUcsSUFBQSx5QkFBUyxFQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFhLENBQUMsQ0FBQztJQUV2RSxJQUFBLHFEQUEwQixFQUFDO1FBQ3pCLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUTtLQUNXLENBQUMsQ0FBQztJQUV0QyxxREFBcUQ7SUFDckQsSUFBQSx5Q0FBb0IsRUFBQyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUV0RCxpRUFBaUU7SUFDakUsTUFBTSxNQUFNLEdBQUcsSUFBQSxvREFBeUIsRUFBQztRQUN2QyxJQUFJO1FBQ0os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