@medusajs/core-flows
Version:
Set of workflow definitions for Medusa
221 lines • 9.79 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.createProductVariantsWorkflow = exports.createProductVariantsWorkflowId = void 0;
const utils_1 = require("@medusajs/framework/utils");
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
const common_1 = require("../../common");
const create_links_1 = require("../../common/workflows/create-links");
const validate_inventory_items_1 = require("../../inventory/steps/validate-inventory-items");
const create_inventory_items_1 = require("../../inventory/workflows/create-inventory-items");
const pricing_1 = require("../../pricing");
const create_product_variants_1 = require("../steps/create-product-variants");
const create_variant_pricing_link_1 = require("../steps/create-variant-pricing-link");
const buildLink = (variant_id, inventory_item_id, required_quantity) => {
const link = {
[utils_1.Modules.PRODUCT]: { variant_id },
[utils_1.Modules.INVENTORY]: { inventory_item_id: inventory_item_id },
data: { required_quantity: required_quantity },
};
return link;
};
const validateVariantsDuplicateInventoryItemIds = (variantsData) => {
const erroredVariantIds = [];
for (const variantData of variantsData) {
const inventoryItemIds = variantData.inventory_items.map((item) => item.inventory_item_id);
const duplicatedInventoryItemIds = inventoryItemIds.filter((id, index) => inventoryItemIds.indexOf(id) !== index);
if (duplicatedInventoryItemIds.length) {
erroredVariantIds.push(variantData.variantId);
}
}
if (erroredVariantIds.length) {
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, `Cannot associate duplicate inventory items to variant(s) ${erroredVariantIds.join("\n")}`);
}
};
const buildLinksToCreate = (data) => {
let index = 0;
const linksToCreate = [];
validateVariantsDuplicateInventoryItemIds((data.createdVariants ?? []).map((variant, index) => {
const variantInput = data.input.product_variants[index];
const inventoryItems = variantInput.inventory_items || [];
return {
variantId: variant.id,
inventory_items: inventoryItems,
};
}));
for (const variant of data.createdVariants) {
const variantInput = data.input.product_variants[index];
const shouldManageInventory = variant.manage_inventory;
const hasInventoryItems = variantInput.inventory_items?.length;
index += 1;
if (!shouldManageInventory) {
continue;
}
if (!hasInventoryItems) {
const inventoryItem = data.inventoryIndexMap[index];
linksToCreate.push(buildLink(variant.id, inventoryItem.id, 1));
continue;
}
for (const inventoryInput of variantInput.inventory_items || []) {
linksToCreate.push(buildLink(variant.id, inventoryInput.inventory_item_id, inventoryInput.required_quantity ?? 1));
}
}
return linksToCreate;
};
const buildVariantItemCreateMap = (data) => {
let index = 0;
const map = {};
for (const variant of data.createdVariants || []) {
const variantInput = data.input.product_variants[index];
const shouldManageInventory = variant.manage_inventory;
const hasInventoryItems = variantInput.inventory_items?.length;
index += 1;
if (!shouldManageInventory || hasInventoryItems) {
continue;
}
// Create a default inventory item if the above conditions arent met
map[index] = {
sku: variantInput.sku,
origin_country: variantInput.origin_country,
mid_code: variantInput.mid_code,
material: variantInput.material,
weight: variantInput.weight,
length: variantInput.length,
height: variantInput.height,
width: variantInput.width,
title: variantInput.title,
description: variantInput.title,
hs_code: variantInput.hs_code,
requires_shipping: true,
};
}
return map;
};
exports.createProductVariantsWorkflowId = "create-product-variants";
/**
* This workflow creates one or more product variants. It's used by the [Create Product Variant Admin API Route](https://docs.medusajs.com/api/admin#products_postproductsidvariants).
*
* This workflow has a hook that allows you to perform custom actions on the created product variants. For example, you can pass under `additional_data` custom data that
* allows you to create custom data models linked to the product variants.
*
* You can also use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around product-variant creation.
*
* :::note
*
* Learn more about adding rules to the product variant's prices in the Pricing Module's
* [Price Rules](https://docs.medusajs.com/resources/commerce-modules/pricing/price-rules) documentation.
*
* :::
*
* @example
* const { result } = await createProductVariantsWorkflow(container)
* .run({
* input: {
* product_variants: [
* {
* product_id: "prod_123",
* sku: "SHIRT-123",
* title: "Small Shirt",
* prices: [
* {
* amount: 10,
* currency_code: "USD",
* },
* ],
* options: {
* Size: "Small",
* },
* },
* ],
* additional_data: {
* erp_id: "123"
* }
* }
* })
*
* @summary
*
* Create one or more product variants.
*
* @property hooks.productVariantsCreated - This hook is executed after the product variants are created. You can consume this hook to perform custom actions on the created product variants.
*/
exports.createProductVariantsWorkflow = (0, workflows_sdk_1.createWorkflow)(exports.createProductVariantsWorkflowId, (input) => {
// Passing prices to the product module will fail, we want to keep them for after the variant is created.
const variantsWithoutPrices = (0, workflows_sdk_1.transform)({ input }, (data) => data.input.product_variants.map((v) => ({
...v,
prices: undefined,
})));
const createdVariants = (0, create_product_variants_1.createProductVariantsStep)(variantsWithoutPrices);
// Setup variants inventory
const inventoryItemIds = (0, workflows_sdk_1.transform)(input, (data) => {
return data.product_variants
.map((variant) => variant.inventory_items || [])
.flat()
.map((item) => item.inventory_item_id)
.flat();
});
(0, validate_inventory_items_1.validateInventoryItems)(inventoryItemIds);
const variantItemCreateMap = (0, workflows_sdk_1.transform)({ createdVariants, input }, buildVariantItemCreateMap);
const createdInventoryItems = create_inventory_items_1.createInventoryItemsWorkflow.runAsStep({
input: {
items: (0, workflows_sdk_1.transform)(variantItemCreateMap, (data) => Object.values(data)),
},
});
const inventoryIndexMap = (0, workflows_sdk_1.transform)({ createdInventoryItems, variantItemCreateMap }, (data) => {
const map = {};
let inventoryIndex = 0;
for (const variantIndex of Object.keys(data.variantItemCreateMap)) {
map[variantIndex] = data.createdInventoryItems[inventoryIndex];
inventoryIndex += 1;
}
return map;
});
const linksToCreate = (0, workflows_sdk_1.transform)({ createdVariants, inventoryIndexMap, input }, buildLinksToCreate);
create_links_1.createLinksWorkflow.runAsStep({ input: linksToCreate });
// Note: We rely on the same order of input and output when creating variants here, make sure that assumption holds
const pricesToCreate = (0, workflows_sdk_1.transform)({ input, createdVariants }, (data) => data.createdVariants.map((v, i) => {
return {
prices: data.input.product_variants[i]?.prices,
};
}));
const createdPriceSets = (0, pricing_1.createPriceSetsStep)(pricesToCreate);
const variantAndPriceSets = (0, workflows_sdk_1.transform)({ createdVariants, createdPriceSets }, (data) => {
return data.createdVariants.map((variant, i) => ({
variant: variant,
price_set: data.createdPriceSets[i],
}));
});
const variantAndPriceSetLinks = (0, workflows_sdk_1.transform)({ variantAndPriceSets }, (data) => {
return {
links: data.variantAndPriceSets.map((entry) => ({
variant_id: entry.variant.id,
price_set_id: entry.price_set.id,
})),
};
});
(0, create_variant_pricing_link_1.createVariantPricingLinkStep)(variantAndPriceSetLinks);
const response = (0, workflows_sdk_1.transform)({
variantAndPriceSets,
}, (data) => {
return data.variantAndPriceSets.map((variantAndPriceSet) => ({
...variantAndPriceSet.variant,
prices: variantAndPriceSet?.price_set?.prices || [],
}));
});
const variantIdEvents = (0, workflows_sdk_1.transform)({ response }, ({ response }) => {
return response.map((v) => {
return { id: v.id };
});
});
(0, common_1.emitEventStep)({
eventName: utils_1.ProductVariantWorkflowEvents.CREATED,
data: variantIdEvents,
});
const productVariantsCreated = (0, workflows_sdk_1.createHook)("productVariantsCreated", {
product_variants: response,
additional_data: input.additional_data,
});
return new workflows_sdk_1.WorkflowResponse(response, {
hooks: [productVariantsCreated],
});
});
//# sourceMappingURL=create-product-variants.js.map
;