@medusajs/core-flows
Version:
Set of workflow definitions for Medusa
197 lines • 8.2 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.addToCartWorkflow = exports.addToCartWorkflowId = void 0;
const utils_1 = require("@medusajs/framework/utils");
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
const common_1 = require("../../common");
const emit_event_1 = require("../../common/steps/emit-event");
const use_remote_query_1 = require("../../common/steps/use-remote-query");
const steps_1 = require("../steps");
const validate_cart_1 = require("../steps/validate-cart");
const validate_line_item_prices_1 = require("../steps/validate-line-item-prices");
const validate_variant_prices_1 = require("../steps/validate-variant-prices");
const fields_1 = require("../utils/fields");
const prepare_line_item_data_1 = require("../utils/prepare-line-item-data");
const confirm_variant_inventory_1 = require("./confirm-variant-inventory");
const refresh_cart_items_1 = require("./refresh-cart-items");
const schemas_1 = require("../utils/schemas");
const cartFields = ["completed_at"].concat(fields_1.cartFieldsForPricingContext);
exports.addToCartWorkflowId = "add-to-cart";
/**
* This workflow adds a product variant to a cart as a line item. It's executed by the
* [Add Line Item Store API Route](https://docs.medusajs.com/api/store#carts_postcartsidlineitems).
*
* You can use this workflow within your own customizations or custom workflows, allowing you to wrap custom logic around adding an item to the cart.
* For example, you can use this workflow to add a line item to the cart with a custom price.
*
* @example
* const { result } = await addToCartWorkflow(container)
* .run({
* input: {
* cart_id: "cart_123",
* items: [
* {
* variant_id: "variant_123",
* quantity: 1,
* },
* {
* variant_id: "variant_456",
* quantity: 1,
* unit_price: 20
* }
* ]
* }
* })
*
* @summary
*
* Add a line item to a cart.
*
* @property hooks.validate - This hook is executed before all operations. You can consume this hook to perform any custom validation. If validation fails, you can throw an error to stop the workflow execution.
* @property hooks.setPricingContext - This hook is executed after the cart is retrieved and before the line items are created. You can consume this hook to return any custom context useful for the prices retrieval of the variants to be added to the cart.
*
* For example, assuming you have the following custom pricing rule:
*
* ```json
* {
* "attribute": "location_id",
* "operator": "eq",
* "value": "sloc_123",
* }
* ```
*
* You can consume the `setPricingContext` hook to add the `location_id` context to the prices calculation:
*
* ```ts
* import { addToCartWorkflow } from "@medusajs/medusa/core-flows";
* import { StepResponse } from "@medusajs/workflows-sdk";
*
* addToCartWorkflow.hooks.setPricingContext((
* { cart, variantIds, items, additional_data }, { container }
* ) => {
* return new StepResponse({
* location_id: "sloc_123", // Special price for in-store purchases
* });
* });
* ```
*
* The variants' prices will now be retrieved using the context you return.
*
* :::note
*
* Learn more about prices calculation context in the [Prices Calculation](https://docs.medusajs.com/resources/commerce-modules/pricing/price-calculation) documentation.
*
* :::
*/
exports.addToCartWorkflow = (0, workflows_sdk_1.createWorkflow)(exports.addToCartWorkflowId, (input) => {
const cartQuery = (0, common_1.useQueryGraphStep)({
entity: "cart",
filters: { id: input.cart_id },
fields: cartFields,
options: { throwIfKeyNotFound: true },
}).config({ name: "get-cart" });
const cart = (0, workflows_sdk_1.transform)({ cartQuery }, ({ cartQuery }) => {
return cartQuery.data[0];
});
(0, validate_cart_1.validateCartStep)({ cart });
const validate = (0, workflows_sdk_1.createHook)("validate", {
input,
cart,
});
const variantIds = (0, workflows_sdk_1.transform)({ input }, (data) => {
return (data.input.items ?? []).map((i) => i.variant_id).filter(Boolean);
});
const setPricingContext = (0, workflows_sdk_1.createHook)("setPricingContext", {
cart,
variantIds,
items: input.items,
additional_data: input.additional_data,
}, {
resultValidator: schemas_1.pricingContextResult,
});
const setPricingContextResult = setPricingContext.getResult();
const pricingContext = (0, workflows_sdk_1.transform)({ cart, setPricingContextResult }, (data) => {
return {
...data.cart,
...(data.setPricingContextResult ? data.setPricingContextResult : {}),
currency_code: data.cart.currency_code,
region_id: data.cart.region_id,
region: data.cart.region,
customer_id: data.cart.customer_id,
customer: data.cart.customer,
};
});
const variants = (0, workflows_sdk_1.when)({ variantIds }, ({ variantIds }) => {
return !!variantIds.length;
}).then(() => {
return (0, use_remote_query_1.useRemoteQueryStep)({
entry_point: "variants",
fields: fields_1.productVariantsFields,
variables: {
id: variantIds,
calculated_price: {
context: pricingContext,
},
},
});
});
(0, validate_variant_prices_1.validateVariantPricesStep)({ variants });
const lineItems = (0, workflows_sdk_1.transform)({ input, variants }, (data) => {
const items = (data.input.items ?? []).map((item) => {
const variant = (data.variants ?? []).find((v) => v.id === item.variant_id);
const input = {
item,
variant: variant,
cartId: data.input.cart_id,
unitPrice: item.unit_price,
isTaxInclusive: item.is_tax_inclusive ??
variant?.calculated_price?.is_calculated_price_tax_inclusive,
isCustomPrice: (0, utils_1.isDefined)(item?.unit_price),
};
if (variant && !(0, utils_1.isDefined)(input.unitPrice)) {
input.unitPrice = variant.calculated_price?.calculated_amount;
}
return (0, prepare_line_item_data_1.prepareLineItemData)(input);
});
return items;
});
(0, validate_line_item_prices_1.validateLineItemPricesStep)({ items: lineItems });
const { itemsToCreate = [], itemsToUpdate = [] } = (0, steps_1.getLineItemActionsStep)({
id: cart.id,
items: lineItems,
});
const itemsToConfirmInventory = (0, workflows_sdk_1.transform)({ itemsToUpdate, itemsToCreate }, (data) => {
return data.itemsToUpdate
.concat(data.itemsToCreate)
.filter((item) => (0, utils_1.isDefined)("data" in item ? item.data?.variant_id : item.variant_id));
});
confirm_variant_inventory_1.confirmVariantInventoryWorkflow.runAsStep({
input: {
sales_channel_id: cart.sales_channel_id,
variants,
items: input.items,
itemsToUpdate: itemsToConfirmInventory,
},
});
const [createdLineItems, updatedLineItems] = (0, workflows_sdk_1.parallelize)((0, steps_1.createLineItemsStep)({
id: cart.id,
items: itemsToCreate,
}), (0, steps_1.updateLineItemsStep)({
id: cart.id,
items: itemsToUpdate,
}));
const allItems = (0, workflows_sdk_1.transform)({ createdLineItems, updatedLineItems }, ({ createdLineItems = [], updatedLineItems = [] }) => {
return createdLineItems.concat(updatedLineItems);
});
refresh_cart_items_1.refreshCartItemsWorkflow.runAsStep({
input: { cart_id: cart.id, items: allItems },
});
(0, emit_event_1.emitEventStep)({
eventName: utils_1.CartWorkflowEvents.UPDATED,
data: { id: cart.id },
});
return new workflows_sdk_1.WorkflowResponse(void 0, {
hooks: [validate, setPricingContext],
});
});
//# sourceMappingURL=add-to-cart.js.map
;