chore(core-flows): Cleanup old code (#7547)

Remove the old handlers and definitions that does not work anymore or are not used anymore. This legacy was bothering a refactoring we have with @thetutlage
This commit is contained in:
Adrien de Peretti
2024-05-30 14:53:42 +02:00
committed by GitHub
parent eeb8225b5e
commit 4e20588522
55 changed files with 0 additions and 3189 deletions

View File

@@ -1,5 +1,3 @@
export * from "./cart"
export * from "./inventory"
export * from "./line-item"
export * from "./payment-collection"
export * from "./product"

View File

@@ -1,64 +0,0 @@
import { Workflows } from "../../definitions"
import {
TransactionStepsDefinition,
WorkflowManager,
} from "@medusajs/orchestration"
import { exportWorkflow, pipe } from "@medusajs/workflows-sdk"
import { InventoryTypes, WorkflowTypes } from "@medusajs/types"
import { InventoryHandlers } from "../../handlers"
export enum CreateInventoryItemActions {
prepare = "prepare",
createInventoryItems = "createInventoryItems",
}
const workflowSteps: TransactionStepsDefinition = {
next: {
action: CreateInventoryItemActions.createInventoryItems,
},
}
const handlers = new Map([
[
CreateInventoryItemActions.createInventoryItems,
{
invoke: pipe(
{
inputAlias: CreateInventoryItemActions.prepare,
merge: true,
invoke: {
from: CreateInventoryItemActions.prepare,
},
},
InventoryHandlers.createInventoryItems
),
compensate: pipe(
{
merge: true,
invoke: {
from: CreateInventoryItemActions.createInventoryItems,
alias:
InventoryHandlers.removeInventoryItems.aliases.inventoryItems,
},
},
InventoryHandlers.removeInventoryItems
),
},
],
])
WorkflowManager.register(
Workflows.CreateInventoryItems,
workflowSteps,
handlers
)
export const createInventoryItems = exportWorkflow<
WorkflowTypes.InventoryWorkflow.CreateInventoryItemsWorkflowInputDTO,
{ tag: string; inventoryItem: InventoryTypes.InventoryItemDTO }[]
>(
Workflows.CreateInventoryItems,
CreateInventoryItemActions.createInventoryItems,
async (data) => data
)

View File

@@ -1 +0,0 @@
export * from "./create-inventory-item"

View File

@@ -1,121 +0,0 @@
import {
TransactionStepsDefinition,
WorkflowManager,
} from "@medusajs/orchestration"
import { InputAlias, Workflows } from "../../definitions"
import { exportWorkflow, pipe } from "@medusajs/workflows-sdk"
import { ProductTypes, WorkflowTypes } from "@medusajs/types"
import { ProductHandlers } from "../../handlers"
export enum CreateProductVariantsActions {
prepare = "prepare",
createProductVariants = "createProductVariants",
revertProductVariantsCreate = "revertProductVariantsCreate",
upsertPrices = "upsertPrices",
}
export const workflowSteps: TransactionStepsDefinition = {
next: {
action: CreateProductVariantsActions.prepare,
noCompensation: true,
next: {
action: CreateProductVariantsActions.createProductVariants,
next: [
{
action: CreateProductVariantsActions.upsertPrices,
},
],
},
},
}
const handlers = new Map([
[
CreateProductVariantsActions.prepare,
{
invoke: pipe(
{
merge: true,
inputAlias: InputAlias.ProductVariantsCreateInputData,
invoke: {
from: InputAlias.ProductVariantsCreateInputData,
},
},
ProductHandlers.createProductVariantsPrepareData
),
},
],
[
CreateProductVariantsActions.createProductVariants,
{
invoke: pipe(
{
merge: true,
invoke: {
from: CreateProductVariantsActions.prepare,
},
},
ProductHandlers.createProductVariants
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: CreateProductVariantsActions.prepare,
},
{
from: CreateProductVariantsActions.createProductVariants,
},
],
},
ProductHandlers.removeProductVariants
),
},
],
[
CreateProductVariantsActions.upsertPrices,
{
invoke: pipe(
{
merge: true,
invoke: [
{
from: CreateProductVariantsActions.createProductVariants,
},
],
},
ProductHandlers.upsertVariantPrices
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: CreateProductVariantsActions.prepare,
},
{
from: CreateProductVariantsActions.upsertPrices,
},
],
},
ProductHandlers.revertVariantPrices
),
},
],
])
WorkflowManager.register(
Workflows.CreateProductVariants,
workflowSteps,
handlers
)
export const createProductVariants = exportWorkflow<
WorkflowTypes.ProductWorkflow.CreateProductVariantsWorkflowInputDTO,
ProductTypes.ProductVariantDTO[]
>(
Workflows.CreateProductVariants,
CreateProductVariantsActions.createProductVariants
)

View File

@@ -1,274 +0,0 @@
import { InputAlias, Workflows } from "../../definitions"
import {
TransactionStepsDefinition,
WorkflowManager,
} from "@medusajs/orchestration"
import { exportWorkflow, pipe } from "@medusajs/workflows-sdk"
import { ProductTypes, WorkflowTypes } from "@medusajs/types"
import {
InventoryHandlers,
MiddlewaresHandlers,
ProductHandlers,
} from "../../handlers"
import { prepareCreateInventoryItems } from "./prepare-create-inventory-items"
export enum CreateProductsActions {
prepare = "prepare",
createProducts = "createProducts",
attachToSalesChannel = "attachToSalesChannel",
attachShippingProfile = "attachShippingProfile",
createPrices = "createPrices",
createInventoryItems = "createInventoryItems",
attachInventoryItems = "attachInventoryItems",
}
export const workflowSteps: TransactionStepsDefinition = {
next: {
action: CreateProductsActions.prepare,
noCompensation: true,
next: {
action: CreateProductsActions.createProducts,
next: [
{
action: CreateProductsActions.attachShippingProfile,
saveResponse: false,
},
{
action: CreateProductsActions.attachToSalesChannel,
saveResponse: false,
},
{
action: CreateProductsActions.createPrices,
next: {
action: CreateProductsActions.createInventoryItems,
next: {
action: CreateProductsActions.attachInventoryItems,
},
},
},
],
},
},
}
const handlers = new Map([
[
CreateProductsActions.prepare,
{
invoke: pipe(
{
merge: true,
inputAlias: InputAlias.ProductsInputData,
invoke: {
from: InputAlias.ProductsInputData,
},
},
ProductHandlers.createProductsPrepareData
),
},
],
[
CreateProductsActions.createProducts,
{
invoke: pipe(
{
merge: true,
invoke: {
from: CreateProductsActions.prepare,
},
},
ProductHandlers.createProducts
),
compensate: pipe(
{
merge: true,
invoke: {
from: CreateProductsActions.createProducts,
alias: ProductHandlers.removeProducts.aliases.products,
},
},
ProductHandlers.removeProducts
),
},
],
[
CreateProductsActions.attachShippingProfile,
{
invoke: pipe(
{
merge: true,
invoke: [
{
from: CreateProductsActions.prepare,
},
{
from: CreateProductsActions.createProducts,
alias:
ProductHandlers.attachShippingProfileToProducts.aliases
.products,
},
],
},
ProductHandlers.attachShippingProfileToProducts
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: CreateProductsActions.prepare,
},
{
from: CreateProductsActions.createProducts,
alias:
ProductHandlers.detachShippingProfileFromProducts.aliases
.products,
},
],
},
ProductHandlers.detachShippingProfileFromProducts
),
},
],
[
CreateProductsActions.attachToSalesChannel,
{
invoke: pipe(
{
merge: true,
invoke: [
{
from: CreateProductsActions.prepare,
},
{
from: CreateProductsActions.createProducts,
alias:
ProductHandlers.attachSalesChannelToProducts.aliases.products,
},
],
},
ProductHandlers.attachSalesChannelToProducts
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: CreateProductsActions.prepare,
},
{
from: CreateProductsActions.createProducts,
alias:
ProductHandlers.detachSalesChannelFromProducts.aliases.products,
},
],
},
ProductHandlers.detachSalesChannelFromProducts
),
},
],
[
CreateProductsActions.createInventoryItems,
{
invoke: pipe(
{
merge: true,
invoke: {
from: CreateProductsActions.createProducts,
alias: prepareCreateInventoryItems.aliases.products,
},
},
prepareCreateInventoryItems,
InventoryHandlers.createInventoryItems
),
compensate: pipe(
{
merge: true,
invoke: {
from: CreateProductsActions.createInventoryItems,
alias:
InventoryHandlers.removeInventoryItems.aliases.inventoryItems,
},
},
InventoryHandlers.removeInventoryItems
),
},
],
[
CreateProductsActions.attachInventoryItems,
{
invoke: pipe(
{
merge: true,
invoke: {
from: CreateProductsActions.createInventoryItems,
alias:
InventoryHandlers.attachInventoryItems.aliases.inventoryItems,
},
},
InventoryHandlers.attachInventoryItems
),
compensate: pipe(
{
merge: true,
invoke: {
from: CreateProductsActions.createInventoryItems,
alias:
InventoryHandlers.detachInventoryItems.aliases.inventoryItems,
},
},
InventoryHandlers.detachInventoryItems
),
},
],
[
CreateProductsActions.createPrices,
{
invoke: pipe(
{
merge: true,
invoke: [
{
from: CreateProductsActions.prepare,
},
{
from: CreateProductsActions.createProducts,
alias:
ProductHandlers.updateProductsVariantsPrices.aliases.products,
},
],
},
ProductHandlers.updateProductsVariantsPrices
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: CreateProductsActions.prepare,
alias:
MiddlewaresHandlers
.createProductsPrepareCreatePricesCompensation.aliases
.preparedData,
},
{
from: CreateProductsActions.createProducts,
alias:
ProductHandlers.updateProductsVariantsPrices.aliases.products,
},
],
},
MiddlewaresHandlers.createProductsPrepareCreatePricesCompensation,
ProductHandlers.updateProductsVariantsPrices
),
},
],
])
WorkflowManager.register(Workflows.CreateProducts, workflowSteps, handlers)
export const createProducts = exportWorkflow<
WorkflowTypes.ProductWorkflow.CreateProductsWorkflowInputDTO,
ProductTypes.ProductDTO[]
>(Workflows.CreateProducts, CreateProductsActions.createProducts)

View File

@@ -1,4 +0,0 @@
export * as CreateProductVariants from "./create-product-variants"
export * from "./create-products"
export * as UpdateProductVariants from "./update-product-variants"
export * from "./update-products"

View File

@@ -1,46 +0,0 @@
import { ProductTypes } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type AssociationTaggedVariant = ProductTypes.ProductVariantDTO & {
_associationTag?: string
}
type ObjectWithVariant = { variants: ProductTypes.ProductVariantDTO[] }
export async function prepareCreateInventoryItems({
data,
}: WorkflowArguments<{
products: ObjectWithVariant[]
}>) {
const taggedVariants = data.products.reduce<AssociationTaggedVariant[]>(
(acc, product: ObjectWithVariant) => {
const cleanVariants = product.variants.reduce<AssociationTaggedVariant[]>(
(acc, variant: AssociationTaggedVariant) => {
if (!variant.manage_inventory) {
return acc
}
variant._associationTag = variant.id
acc.push(variant)
return acc
},
[]
)
return acc.concat(cleanVariants)
},
[]
)
return {
alias: prepareCreateInventoryItems.aliases.output,
value: {
inventoryItems: taggedVariants,
},
}
}
prepareCreateInventoryItems.aliases = {
products: "products",
output: "prepareCreateInventoryItemsOutput",
}

View File

@@ -1,108 +0,0 @@
import {
TransactionStepsDefinition,
WorkflowManager,
} from "@medusajs/orchestration"
import { InputAlias, Workflows } from "../../definitions"
import { exportWorkflow, pipe } from "@medusajs/workflows-sdk"
import { ProductTypes, WorkflowTypes } from "@medusajs/types"
import { ProductHandlers } from "../../handlers"
export enum UpdateProductVariantsActions {
prepare = "prepare",
updateProductVariants = "updateProductVariants",
revertProductVariantsUpdate = "revertProductVariantsUpdate",
upsertPrices = "upsertPrices",
}
export const workflowSteps: TransactionStepsDefinition = {
next: {
action: UpdateProductVariantsActions.prepare,
noCompensation: true,
next: {
action: UpdateProductVariantsActions.updateProductVariants,
noCompensation: true,
next: [
{
action: UpdateProductVariantsActions.upsertPrices,
},
],
},
},
}
const handlers = new Map([
[
UpdateProductVariantsActions.prepare,
{
invoke: pipe(
{
merge: true,
inputAlias: InputAlias.ProductVariantsUpdateInputData,
invoke: {
from: InputAlias.ProductVariantsUpdateInputData,
},
},
ProductHandlers.updateProductVariantsPrepareData
),
},
],
[
UpdateProductVariantsActions.updateProductVariants,
{
invoke: pipe(
{
merge: true,
invoke: {
from: UpdateProductVariantsActions.prepare,
},
},
ProductHandlers.updateProductVariants
),
},
],
[
UpdateProductVariantsActions.upsertPrices,
{
invoke: pipe(
{
merge: true,
invoke: [
{
from: UpdateProductVariantsActions.prepare,
},
],
},
ProductHandlers.upsertVariantPrices
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: UpdateProductVariantsActions.prepare,
},
{
from: UpdateProductVariantsActions.upsertPrices,
},
],
},
ProductHandlers.revertVariantPrices
),
},
],
])
WorkflowManager.register(
Workflows.UpdateProductVariants,
workflowSteps,
handlers
)
export const updateProductVariants = exportWorkflow<
WorkflowTypes.ProductWorkflow.UpdateProductVariantsWorkflowInputDTO,
ProductTypes.ProductVariantDTO[]
>(
Workflows.UpdateProductVariants,
UpdateProductVariantsActions.updateProductVariants
)

View File

@@ -1,400 +0,0 @@
import { ProductTypes, WorkflowTypes } from "@medusajs/types"
import {
TransactionStepsDefinition,
WorkflowManager,
} from "@medusajs/orchestration"
import { InputAlias, Workflows } from "../../definitions"
import { InventoryHandlers, ProductHandlers } from "../../handlers"
import * as MiddlewareHandlers from "../../handlers/middlewares"
import { detachSalesChannelFromProducts } from "../../handlers/product"
import { exportWorkflow, pipe } from "@medusajs/workflows-sdk"
import { CreateProductsActions } from "./create-products"
import { prepareCreateInventoryItems } from "./prepare-create-inventory-items"
import { UpdateProductVariantsActions } from "./update-product-variants"
export enum UpdateProductsActions {
prepare = "prepare",
updateProducts = "updateProducts",
attachSalesChannels = "attachSalesChannels",
detachSalesChannels = "detachSalesChannels",
createInventoryItems = "createInventoryItems",
attachInventoryItems = "attachInventoryItems",
detachInventoryItems = "detachInventoryItems",
removeInventoryItems = "removeInventoryItems",
}
export const updateProductsWorkflowSteps: TransactionStepsDefinition = {
next: {
action: CreateProductsActions.prepare,
noCompensation: true,
next: {
action: UpdateProductsActions.updateProducts,
next: [
{
action: UpdateProductVariantsActions.upsertPrices,
saveResponse: false,
},
{
action: UpdateProductsActions.attachSalesChannels,
saveResponse: false,
},
{
action: UpdateProductsActions.detachSalesChannels,
saveResponse: false,
},
{
// for created variants
action: UpdateProductsActions.createInventoryItems,
next: {
action: UpdateProductsActions.attachInventoryItems,
},
},
{
// for deleted variants
action: UpdateProductsActions.detachInventoryItems,
next: {
action: UpdateProductsActions.removeInventoryItems,
},
},
],
},
},
}
const handlers = new Map<string, any>([
[
UpdateProductsActions.prepare,
{
invoke: pipe(
{
merge: true,
inputAlias: InputAlias.ProductsInputData,
invoke: {
from: InputAlias.ProductsInputData,
},
},
ProductHandlers.updateProductsPrepareData
),
},
],
[
UpdateProductsActions.updateProducts,
{
invoke: pipe(
{
merge: true,
invoke: [
{
from: InputAlias.ProductsInputData,
alias: ProductHandlers.updateProducts.aliases.products,
},
{
from: UpdateProductsActions.prepare,
},
],
},
ProductHandlers.updateProducts
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: UpdateProductsActions.prepare,
alias: ProductHandlers.revertUpdateProducts.aliases.preparedData,
},
{
from: UpdateProductsActions.updateProducts,
alias:
MiddlewareHandlers.updateProductsExtractDeletedVariants.aliases
.products,
},
],
},
MiddlewareHandlers.updateProductsExtractDeletedVariants,
ProductHandlers.revertUpdateProducts
),
},
],
[
UpdateProductsActions.attachSalesChannels,
{
invoke: pipe(
{
merge: true,
invoke: [
{
from: UpdateProductsActions.prepare,
alias: "preparedData",
},
{
from: UpdateProductsActions.updateProducts,
alias:
ProductHandlers.attachSalesChannelToProducts.aliases.products,
},
],
},
MiddlewareHandlers.mapData((d: any) => ({
productsHandleSalesChannelsMap:
d.preparedData.productHandleAddedChannelsMap,
})),
ProductHandlers.attachSalesChannelToProducts
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: UpdateProductsActions.prepare,
alias: "preparedData",
},
{
from: UpdateProductsActions.updateProducts,
alias: detachSalesChannelFromProducts.aliases.products,
},
],
},
MiddlewareHandlers.mapData((d: any) => ({
productsHandleSalesChannelsMap:
d.preparedData.productHandleAddedChannelsMap,
})),
ProductHandlers.detachSalesChannelFromProducts
),
},
],
[
UpdateProductsActions.detachSalesChannels,
{
invoke: pipe(
{
merge: true,
invoke: [
{
from: UpdateProductsActions.prepare,
alias: "preparedData",
},
{
from: UpdateProductsActions.updateProducts,
alias:
ProductHandlers.detachSalesChannelFromProducts.aliases.products,
},
],
},
MiddlewareHandlers.mapData((d: any) => ({
productsHandleSalesChannelsMap:
d.preparedData.productHandleRemovedChannelsMap,
})),
ProductHandlers.detachSalesChannelFromProducts
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: UpdateProductsActions.prepare,
alias: "preparedData",
},
{
from: UpdateProductsActions.updateProducts,
alias:
ProductHandlers.attachSalesChannelToProducts.aliases.products,
},
],
},
MiddlewareHandlers.mapData((d: any) => ({
productsHandleSalesChannelsMap:
d.preparedData.productHandleRemovedChannelsMap,
})),
ProductHandlers.attachSalesChannelToProducts
),
},
],
[
UpdateProductsActions.createInventoryItems,
{
invoke: pipe(
{
merge: true,
invoke: [
{
from: UpdateProductsActions.prepare,
alias:
MiddlewareHandlers.updateProductsExtractCreatedVariants.aliases
.preparedData,
},
{
from: UpdateProductsActions.updateProducts,
alias:
MiddlewareHandlers.updateProductsExtractCreatedVariants.aliases
.products,
},
],
},
MiddlewareHandlers.updateProductsExtractCreatedVariants,
prepareCreateInventoryItems,
InventoryHandlers.createInventoryItems
),
compensate: pipe(
{
merge: true,
invoke: {
from: UpdateProductsActions.createInventoryItems,
alias:
InventoryHandlers.removeInventoryItems.aliases.inventoryItems,
},
},
InventoryHandlers.removeInventoryItems
),
},
],
[
UpdateProductsActions.attachInventoryItems,
{
invoke: pipe(
{
merge: true,
invoke: {
from: UpdateProductsActions.createInventoryItems,
alias:
InventoryHandlers.attachInventoryItems.aliases.inventoryItems,
},
},
InventoryHandlers.attachInventoryItems
),
compensate: pipe(
{
merge: true,
invoke: {
from: UpdateProductsActions.attachInventoryItems,
alias:
InventoryHandlers.detachInventoryItems.aliases.inventoryItems,
},
},
InventoryHandlers.detachInventoryItems
),
},
],
[
UpdateProductsActions.detachInventoryItems,
{
invoke: pipe(
{
merge: true,
invoke: [
{
from: UpdateProductsActions.prepare,
alias:
MiddlewareHandlers.updateProductsExtractDeletedVariants.aliases
.preparedData,
},
{
from: UpdateProductsActions.updateProducts,
alias:
MiddlewareHandlers.updateProductsExtractDeletedVariants.aliases
.products,
},
],
},
MiddlewareHandlers.updateProductsExtractDeletedVariants,
MiddlewareHandlers.useVariantsInventoryItems,
InventoryHandlers.detachInventoryItems
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: UpdateProductsActions.prepare,
alias:
MiddlewareHandlers.updateProductsExtractDeletedVariants.aliases
.preparedData,
},
{
from: UpdateProductsActions.updateProducts,
alias:
MiddlewareHandlers.updateProductsExtractDeletedVariants.aliases
.products,
},
],
},
MiddlewareHandlers.updateProductsExtractDeletedVariants,
MiddlewareHandlers.useVariantsInventoryItems,
InventoryHandlers.attachInventoryItems
),
},
],
[
UpdateProductsActions.removeInventoryItems,
{
invoke: pipe(
{
merge: true,
invoke: {
from: UpdateProductsActions.detachInventoryItems,
alias:
InventoryHandlers.removeInventoryItems.aliases.inventoryItems,
},
},
InventoryHandlers.removeInventoryItems
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: UpdateProductsActions.removeInventoryItems,
alias:
InventoryHandlers.restoreInventoryItems.aliases.inventoryItems,
},
],
},
InventoryHandlers.restoreInventoryItems
),
},
],
[
UpdateProductVariantsActions.upsertPrices,
{
invoke: pipe(
{
merge: true,
invoke: [
{
from: InputAlias.ProductsInputData,
alias: ProductHandlers.updateProducts.aliases.products,
},
{
from: UpdateProductsActions.prepare,
},
],
},
ProductHandlers.upsertVariantPrices
),
compensate: pipe(
{
merge: true,
invoke: [
{
from: UpdateProductVariantsActions.upsertPrices,
},
],
},
ProductHandlers.revertVariantPrices
),
},
],
])
WorkflowManager.register(
Workflows.UpdateProducts,
updateProductsWorkflowSteps,
handlers
)
export const updateProducts = exportWorkflow<
WorkflowTypes.ProductWorkflow.UpdateProductsWorkflowInputDTO,
ProductTypes.ProductDTO[]
>(Workflows.UpdateProducts, UpdateProductsActions.updateProducts)

View File

@@ -1,40 +0,0 @@
export enum Workflows {
// Product workflows
CreateProducts = "create-products-old",
UpdateProducts = "update-products-old",
// Product Variant workflows
CreateProductVariants = "create-product-variants-old",
UpdateProductVariants = "update-product-variants-old",
// Cart workflows
CreateCart = "create-cart-old",
CreateInventoryItems = "create-inventory-items-old",
// Price list workflows
CreatePriceList = "create-price-list-old",
UpdatePriceLists = "update-price-lists-old",
DeletePriceLists = "delete-price-lists-old",
RemovePriceListProductPrices = "remove-price-list-products-old",
RemovePriceListVariantPrices = "remove-price-list-variants-old",
RemovePriceListPrices = "remove-price-list-prices-old",
}
export enum InputAlias {
Products = "products",
ProductsInputData = "productsInputData",
RemovedProducts = "removedProducts",
ProductVariants = "productVariants",
ProductVariantsUpdateInputData = "productVariantsUpdateInputData",
ProductVariantsCreateInputData = "productVariantsCreateInputData",
InventoryItems = "inventoryItems",
RemovedInventoryItems = "removedInventoryItems",
AttachedInventoryItems = "attachedInventoryItems",
DetachedInventoryItems = "detachedInventoryItems",
InventoryItemsInputData = "inventoryItemsInputData",
}

View File

@@ -1,117 +0,0 @@
import { AddressDTO } from "@medusajs/types"
import { MedusaError } from "@medusajs/utils"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type AddressesDTO = {
shipping_address_id?: string
shipping_address?: AddressDTO
billing_address_id?: string
billing_address?: AddressDTO
}
type HandlerInputData = {
addresses: AddressesDTO & {
billing_address?: AddressDTO
shipping_address?: AddressDTO
}
region: {
region_id?: string
}
}
enum Aliases {
Addresses = "addresses",
Region = "region",
}
export async function findOrCreateAddresses({
container,
data,
}: WorkflowArguments<HandlerInputData>): Promise<AddressesDTO> {
const regionService = container.resolve("regionService")
const addressRepository = container.resolve("addressRepository")
const shippingAddress = data[Aliases.Addresses].shipping_address
const shippingAddressId = data[Aliases.Addresses].shipping_address_id
const billingAddress = data[Aliases.Addresses].billing_address
const billingAddressId = data[Aliases.Addresses].billing_address_id
const addressesDTO: AddressesDTO = {}
const region = await regionService.retrieve(data[Aliases.Region].region_id, {
relations: ["countries"],
})
const regionCountries = region.countries.map(({ iso_2 }) => iso_2)
if (!shippingAddress && !shippingAddressId) {
if (region.countries.length === 1) {
const shippingAddress = addressRepository.create({
country_code: regionCountries[0],
})
addressesDTO.shipping_address = shippingAddress
addressesDTO.shipping_address_id = shippingAddress?.id
}
} else {
if (shippingAddress) {
if (!regionCountries.includes(shippingAddress.country_code!)) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"Shipping country not in region"
)
}
}
if (shippingAddressId) {
const address = await regionService.findOne({
where: { id: shippingAddressId },
})
if (
address?.country_code &&
!regionCountries.includes(address.country_code)
) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"Shipping country not in region"
)
}
addressesDTO.shipping_address = address
addressesDTO.shipping_address_id = address.id
}
}
if (billingAddress) {
if (!regionCountries.includes(billingAddress.country_code!)) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"Billing country not in region"
)
}
}
if (billingAddressId) {
const address = await regionService.findOne({
where: { id: billingAddressId },
})
if (
address?.country_code &&
!regionCountries.includes(address.country_code)
) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"Billing country not in region"
)
}
addressesDTO.billing_address = address
addressesDTO.billing_address_id = billingAddressId
}
return addressesDTO
}
findOrCreateAddresses.aliases = Aliases

View File

@@ -1 +0,0 @@
export * from "./find-or-create-addresses"

View File

@@ -1 +0,0 @@
export * from "./set-context"

View File

@@ -1,27 +0,0 @@
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type ContextDTO = {
context?: Record<any, any>
}
enum Aliases {
Context = "context",
}
type HandlerInputData = {
context: {
context?: Record<any, any>
}
}
export async function setContext({
data,
}: WorkflowArguments<HandlerInputData>): Promise<ContextDTO> {
const contextDTO: ContextDTO = {
context: data[Aliases.Context].context,
}
return contextDTO
}
setContext.aliases = Aliases

View File

@@ -1,67 +0,0 @@
import { validateEmail } from "@medusajs/utils"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
import { CustomerTypes } from "@medusajs/types"
type CustomerResultDTO = {
customer?: CustomerTypes.CustomerDTO
customer_id?: string
email?: string
}
type HandlerInputData = {
customer: {
customer_id?: string
email?: string
}
}
enum Aliases {
Customer = "customer",
}
export async function findOrCreateCustomer({
container,
context,
data,
}: WorkflowArguments<HandlerInputData>): Promise<CustomerResultDTO> {
const { manager } = context
const customerService = container.resolve("customerService")
const customerDataDTO: CustomerResultDTO = {}
const customerId = data[Aliases.Customer].customer_id
const customerServiceTx = customerService.withTransaction(manager)
if (customerId) {
const customer = await customerServiceTx
.retrieve(customerId)
.catch(() => undefined)
customerDataDTO.customer = customer
customerDataDTO.customer_id = customer?.id
customerDataDTO.email = customer?.email
}
const customerEmail = data[Aliases.Customer].email
if (customerEmail) {
const validatedEmail = validateEmail(customerEmail)
let customer = await customerServiceTx
.retrieveUnregisteredByEmail(validatedEmail)
.catch(() => undefined)
if (!customer) {
customer = await customerServiceTx.create({ email: validatedEmail })
}
customerDataDTO.customer = customer
customerDataDTO.customer_id = customer.id
customerDataDTO.email = customer.email
}
return customerDataDTO
}
findOrCreateCustomer.aliases = Aliases

View File

@@ -1 +0,0 @@
export * from "./find-or-create-customer"

View File

@@ -1,8 +0,0 @@
export * as AddressHandlers from "./address"
export * as CommonHandlers from "./common"
export * as CustomerHandlers from "./customer"
export * as InventoryHandlers from "./inventory"
export * as MiddlewaresHandlers from "./middlewares"
export * as ProductHandlers from "./product"
export * as RegionHandlers from "./region"
export * as SalesChannelHandlers from "./sales-channel"

View File

@@ -1,35 +0,0 @@
import { InventoryItemDTO } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
export async function attachInventoryItems({
container,
context,
data,
}: WorkflowArguments<{
inventoryItems: {
tag: string
inventoryItem: InventoryItemDTO
}[]
}>) {
const { manager } = context
const productVariantInventoryService = container
.resolve("productVariantInventoryService")
.withTransaction(manager)
if (!data?.inventoryItems?.length) {
return []
}
const inventoryData = data.inventoryItems.map(({ tag, inventoryItem }) => ({
variantId: tag,
inventoryItemId: inventoryItem.id,
}))
await productVariantInventoryService.attachInventoryItem(inventoryData)
return data.inventoryItems
}
attachInventoryItems.aliases = {
inventoryItems: "inventoryItems",
}

View File

@@ -1,48 +0,0 @@
import { IInventoryService, InventoryItemDTO } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
import { promiseAll } from "@medusajs/utils"
type Result = {
tag: string
inventoryItem: InventoryItemDTO
}[]
export async function createInventoryItems({
container,
data,
}: WorkflowArguments<{
inventoryItems: (InventoryItemDTO & { _associationTag?: string })[]
}>): Promise<Result | void> {
const inventoryService: IInventoryService =
container.resolve("inventoryService")
if (!inventoryService) {
const logger = container.resolve("logger")
logger.warn(
`Inventory service not found. You should install the @medusajs/inventory package to use inventory. The 'createInventoryItems' will be skipped.`
)
return void 0
}
return await promiseAll(
data.inventoryItems.map(async (item) => {
const inventoryItem = await inventoryService!.createInventoryItem({
sku: item.sku!,
origin_country: item.origin_country!,
hs_code: item.hs_code!,
mid_code: item.mid_code!,
material: item.material!,
weight: item.weight!,
length: item.length!,
height: item.height!,
width: item.width!,
})
return { tag: item._associationTag ?? inventoryItem.id, inventoryItem }
})
)
}
createInventoryItems.aliases = {
payload: "payload",
}

View File

@@ -1,39 +0,0 @@
import { InventoryItemDTO } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
import { promiseAll } from "@medusajs/utils"
export async function detachInventoryItems({
container,
context,
data,
}: WorkflowArguments<{
inventoryItems: {
tag: string
inventoryItem: InventoryItemDTO
}[]
}>) {
const { manager } = context
const productVariantInventoryService = container
.resolve("productVariantInventoryService")
.withTransaction(manager)
if (!data?.inventoryItems?.length) {
return []
}
await promiseAll(
data.inventoryItems.map(async ({ tag, inventoryItem }) => {
return await productVariantInventoryService.detachInventoryItem(
inventoryItem.id,
tag
)
})
)
return data.inventoryItems
}
detachInventoryItems.aliases = {
inventoryItems: "inventoryItems",
}

View File

@@ -1,5 +0,0 @@
export * from "./detach-inventory-items"
export * from "./attach-inventory-items"
export * from "./create-inventory-items"
export * from "./remove-inventory-items"
export * from "./restore-inventory-items"

View File

@@ -1,29 +0,0 @@
import { InventoryItemDTO } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
export async function removeInventoryItems({
container,
data,
}: WorkflowArguments<{
inventoryItems: { inventoryItem: InventoryItemDTO }[]
}>) {
const inventoryService = container.resolve("inventoryService")
if (!inventoryService) {
const logger = container.resolve("logger")
logger.warn(
`Inventory service not found. You should install the @medusajs/inventory package to use inventory. The 'removeInventoryItems' will be skipped.`
)
return []
}
await inventoryService!.deleteInventoryItem(
data.inventoryItems.map(({ inventoryItem }) => inventoryItem.id)
)
return data.inventoryItems
}
removeInventoryItems.aliases = {
inventoryItems: "inventoryItems",
}

View File

@@ -1,35 +0,0 @@
import {
IInventoryService,
InventoryItemDTO,
SharedContext,
} from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
export async function restoreInventoryItems({
container,
context,
data,
}: WorkflowArguments<{
inventoryItems: { inventoryItem: InventoryItemDTO }[]
}>) {
const { manager } = context as SharedContext
const inventoryService: IInventoryService =
container.resolve("inventoryService")
if (!inventoryService) {
const logger = container.resolve("logger")
logger.warn(
`Inventory service not found. You should install the @medusajs/inventory package to use inventory. The 'removeInventoryItems' will be skipped.`
)
return
}
return await inventoryService!.restoreInventoryItem(
data.inventoryItems.map(({ inventoryItem }) => inventoryItem.id),
{ transactionManager: manager }
)
}
restoreInventoryItems.aliases = {
inventoryItems: "inventoryItems",
}

View File

@@ -1,55 +0,0 @@
import { ProductTypes, WorkflowTypes } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type ProductHandle = string
type VariantIndexAndPrices = {
index: number
prices: WorkflowTypes.ProductWorkflow.CreateProductVariantPricesInputDTO[]
}
export async function createProductsPrepareCreatePricesCompensation({
data,
}: WorkflowArguments<{
preparedData: {
productsHandleVariantsIndexPricesMap: Map<
ProductHandle,
VariantIndexAndPrices[]
>
}
products: ProductTypes.ProductDTO[]
}>) {
const productsHandleVariantsIndexPricesMap =
data.preparedData.productsHandleVariantsIndexPricesMap
const products = data.products
const updatedProductsHandleVariantsIndexPricesMap = new Map()
productsHandleVariantsIndexPricesMap.forEach(
(existingItems, productHandle) => {
const items =
updatedProductsHandleVariantsIndexPricesMap.get(productHandle) ?? []
existingItems.forEach(({ index }) => {
items.push({
index,
prices: [],
})
})
updatedProductsHandleVariantsIndexPricesMap.set(productHandle, items)
}
)
return {
alias: createProductsPrepareCreatePricesCompensation.aliases.output,
value: {
productsHandleVariantsIndexPricesMap:
updatedProductsHandleVariantsIndexPricesMap,
products,
},
}
}
createProductsPrepareCreatePricesCompensation.aliases = {
preparedData: "preparedData",
output: "createProductsPrepareCreatePricesCompensationOutput",
}

View File

@@ -1,28 +0,0 @@
import { ProductTypes } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
export async function extractVariants({
data,
}: WorkflowArguments<{
object: { variants?: ProductTypes.ProductVariantDTO[] }[]
}>) {
const variants = data.object.reduce((acc, object) => {
if (object.variants?.length) {
return acc.concat(object.variants)
}
return acc
}, [] as ProductTypes.ProductVariantDTO[])
return {
alias: extractVariants.aliases.output,
value: {
variants,
},
}
}
extractVariants.aliases = {
output: "extractVariantsFromProductOutput",
object: "object",
}

View File

@@ -1,6 +0,0 @@
export * from "./create-products-prepare-create-prices-compensation"
export * from "./update-products-extract-created-variants"
export * from "./update-products-extract-deleted-variants"
export * from "./use-variants-inventory-items"
export * from "./extract-variants"
export * from "./map-data"

View File

@@ -1,16 +0,0 @@
import { WorkflowArguments } from "@medusajs/workflows-sdk"
/**
* Middleware for map input data to a key/s.
*
* @param mapFn - apply function on the input data and return result as the middleware output
* @param alias - key to save output under (if `merge === false`)
*/
export function mapData<T, S>(mapFn: (arg: T) => S, alias = "mapData") {
return async function ({ data }: WorkflowArguments<T>) {
return {
alias,
value: mapFn(data),
}
}
}

View File

@@ -1,40 +0,0 @@
import { ProductTypes, ProductVariantDTO } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
import { UpdateProductsPreparedData } from "../product"
export async function updateProductsExtractCreatedVariants({
data,
}: WorkflowArguments<{
preparedData: UpdateProductsPreparedData // products state before the update
products: ProductTypes.ProductDTO[] // updated products
}>) {
const createdVariants: ProductVariantDTO[] = []
data.products.forEach((product) => {
const addedVariants: ProductVariantDTO[] = []
const originalProduct = data.preparedData.originalProducts.find(
(p) => p.id === product.id
)!
product.variants.forEach((variant) => {
if (!originalProduct.variants.find((v) => v.id === variant.id)) {
addedVariants.push(variant)
}
})
createdVariants.push(...addedVariants)
})
return {
alias: updateProductsExtractCreatedVariants.aliases.output,
value: [{ variants: createdVariants }],
}
}
updateProductsExtractCreatedVariants.aliases = {
preparedData: "preparedData",
products: "products",
output: "products",
}

View File

@@ -1,43 +0,0 @@
import { ProductTypes, ProductVariantDTO } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
import { UpdateProductsPreparedData } from "../product"
export async function updateProductsExtractDeletedVariants({
data,
container,
}: WorkflowArguments<{
preparedData: UpdateProductsPreparedData // products state before the update
products: ProductTypes.ProductDTO[] // updated products
}>) {
const deletedVariants: ProductVariantDTO[] = []
data.products.forEach((product) => {
const removedVariants: ProductVariantDTO[] = []
const originalProduct = data.preparedData.originalProducts.find(
(p) => p.id === product.id
)!
originalProduct.variants.forEach((variant) => {
if (!product.variants.find((v) => v.id === variant.id)) {
removedVariants.push(variant)
}
})
deletedVariants.push(...removedVariants)
})
return {
alias: updateProductsExtractDeletedVariants.aliases.output,
value: {
variants: deletedVariants,
},
}
}
updateProductsExtractDeletedVariants.aliases = {
preparedData: "preparedData",
products: "products",
output: "updateProductsExtractDeletedVariantsOutput",
}

View File

@@ -1,46 +0,0 @@
import { WorkflowArguments } from "@medusajs/workflows-sdk"
import { IInventoryService, ProductVariantDTO } from "@medusajs/types"
export async function useVariantsInventoryItems({
data,
container,
}: WorkflowArguments<{
updateProductsExtractDeletedVariantsOutput: { variants: ProductVariantDTO[] }
}>) {
const inventoryService: IInventoryService =
container.resolve("inventoryService")
if (!inventoryService) {
const logger = container.resolve("logger")
logger.warn(
`Inventory service not found. You should install the @medusajs/inventory package to use inventory. The 'useVariantsInventoryItems' will be skipped.`
)
return {
alias: useVariantsInventoryItems.aliases.output,
value: null,
}
}
const [inventoryItems] = await inventoryService!.listInventoryItems({
sku: data.updateProductsExtractDeletedVariantsOutput.variants.map(
(v) => v.id
),
})
const variantItems = inventoryItems.map((item) => ({
inventoryItem: item,
tag: data.updateProductsExtractDeletedVariantsOutput.variants.find(
(variant) => variant.sku === item.sku
)!.id,
}))
return {
alias: useVariantsInventoryItems.aliases.output,
value: { inventoryItems: variantItems },
}
}
useVariantsInventoryItems.aliases = {
variants: "variants",
output: "useVariantsInventoryItemsOutput",
}

View File

@@ -1,80 +0,0 @@
import { WorkflowArguments } from "@medusajs/workflows-sdk"
import { MedusaV2Flag, promiseAll } from "@medusajs/utils"
import { Modules } from "@medusajs/modules-sdk"
type ProductHandle = string
type SalesChannelId = string
type PartialProduct = { handle: string; id: string }
type HandlerInput = {
productsHandleSalesChannelsMap: Map<ProductHandle, SalesChannelId[]>
products: PartialProduct[]
}
export async function attachSalesChannelToProducts({
container,
context,
data,
}: WorkflowArguments<HandlerInput>): Promise<void> {
const { manager } = context
const featureFlagRouter = container.resolve("featureFlagRouter")
const productsHandleSalesChannelsMap = data.productsHandleSalesChannelsMap
const products = data.products
const salesChannelService = container.resolve("salesChannelService")
const salesChannelServiceTx = salesChannelService.withTransaction(manager)
const salesChannelIdProductIdsMap = new Map<ProductHandle, SalesChannelId[]>()
products.forEach((product) => {
const salesChannelIds = productsHandleSalesChannelsMap.get(product.handle!)
if (salesChannelIds) {
salesChannelIds.forEach((salesChannelId) => {
const productIds = salesChannelIdProductIdsMap.get(salesChannelId) || []
productIds.push(product.id)
salesChannelIdProductIdsMap.set(salesChannelId, productIds)
})
}
})
if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) {
const remoteLink = container.resolve("remoteLink")
const links: any[] = []
for (const [
salesChannelId,
productIds,
] of salesChannelIdProductIdsMap.entries()) {
productIds.forEach((id) =>
links.push({
[Modules.PRODUCT]: {
product_id: id,
},
[Modules.SALES_CHANNEL]: {
sales_channel_id: salesChannelId,
},
})
)
await remoteLink.create(links)
}
return
} else {
await promiseAll(
Array.from(salesChannelIdProductIdsMap.entries()).map(
async ([salesChannelId, productIds]) => {
return await salesChannelServiceTx.addProducts(
salesChannelId,
productIds
)
}
)
)
}
}
attachSalesChannelToProducts.aliases = {
products: "products",
}

View File

@@ -1,48 +0,0 @@
import { WorkflowArguments } from "@medusajs/workflows-sdk"
import { promiseAll } from "@medusajs/utils"
type ProductHandle = string
type ShippingProfileId = string
type PartialProduct = { handle: string; id: string }
type handlerInput = {
productsHandleShippingProfileIdMap: Map<ProductHandle, ShippingProfileId>
products: PartialProduct[]
}
export async function attachShippingProfileToProducts({
container,
context,
data,
}: WorkflowArguments<handlerInput>): Promise<void> {
const { manager } = context
const productsHandleShippingProfileIdMap =
data.productsHandleShippingProfileIdMap
const products = data.products
const shippingProfileService = container.resolve("shippingProfileService")
const shippingProfileServiceTx =
shippingProfileService.withTransaction(manager)
const profileIdProductIdsMap = new Map<ShippingProfileId, ProductHandle[]>()
products.forEach((product) => {
const profileId = productsHandleShippingProfileIdMap.get(product.handle!)
if (profileId) {
const productIds = profileIdProductIdsMap.get(profileId) || []
productIds.push(product.id)
profileIdProductIdsMap.set(profileId, productIds)
}
})
await promiseAll(
Array.from(profileIdProductIdsMap.entries()).map(
async ([profileId, productIds]) => {
return await shippingProfileServiceTx.addProducts(profileId, productIds)
}
)
)
}
attachShippingProfileToProducts.aliases = {
products: "products",
}

View File

@@ -1,66 +0,0 @@
import { BigNumberInput, ProductWorkflow, WorkflowTypes } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type VariantPrice = {
region_id?: string
currency_code?: string
amount: BigNumberInput
min_quantity?: BigNumberInput
max_quantity?: BigNumberInput
}
export type CreateProductVariantsPreparedData = {
productVariants: ProductWorkflow.CreateProductVariantsInputDTO[]
variantIndexPricesMap: Map<number, VariantPrice[]>
productVariantsMap: Map<
string,
ProductWorkflow.CreateProductVariantsInputDTO[]
>
}
export async function createProductVariantsPrepareData({
container,
data,
}: // eslint-disable-next-line max-len
WorkflowArguments<WorkflowTypes.ProductWorkflow.CreateProductVariantsWorkflowInputDTO>): Promise<CreateProductVariantsPreparedData> {
const productVariants: ProductWorkflow.CreateProductVariantsInputDTO[] =
data.productVariants || []
const variantIndexPricesMap = new Map<number, VariantPrice[]>()
const productVariantsMap = new Map<
string,
ProductWorkflow.CreateProductVariantsInputDTO[]
>()
for (const [index, productVariantData] of productVariants.entries()) {
if (!productVariantData.product_id) {
continue
}
variantIndexPricesMap.set(index, productVariantData.prices || [])
delete productVariantData.prices
const productVariants = productVariantsMap.get(
productVariantData.product_id
)
if (productVariants) {
productVariants.push(productVariantData)
} else {
productVariantsMap.set(productVariantData.product_id, [
productVariantData,
])
}
}
return {
productVariants,
variantIndexPricesMap,
productVariantsMap,
}
}
createProductVariantsPrepareData.aliases = {
payload: "payload",
}

View File

@@ -1,46 +0,0 @@
import { Modules, ModulesDefinition } from "@medusajs/modules-sdk"
import { BigNumberInput, ProductTypes } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type VariantPrice = {
region_id?: string
currency_code?: string
amount: BigNumberInput
min_quantity?: BigNumberInput
max_quantity?: BigNumberInput
}
type HandlerInput = {
productVariantsMap: Map<string, ProductTypes.CreateProductVariantDTO[]>
variantIndexPricesMap: Map<number, VariantPrice[]>
}
export async function createProductVariants({
container,
data,
}: WorkflowArguments<HandlerInput>): Promise<{
productVariants: ProductTypes.ProductVariantDTO[]
variantPricesMap: Map<string, VariantPrice[]>
}> {
const { productVariantsMap, variantIndexPricesMap } = data
const variantPricesMap = new Map<string, VariantPrice[]>()
const productModuleService: ProductTypes.IProductModuleService =
container.resolve(ModulesDefinition[Modules.PRODUCT].registrationName)
const productVariants = await productModuleService.createVariants(
[...productVariantsMap.values()].flat()
)
productVariants.forEach((variant, index) => {
variantPricesMap.set(variant.id, variantIndexPricesMap.get(index) || [])
})
return {
productVariants,
variantPricesMap,
}
}
createProductVariants.aliases = {
payload: "payload",
}

View File

@@ -1,151 +0,0 @@
import {
BigNumberInput,
ProductTypes,
SalesChannelTypes,
WorkflowTypes,
} from "@medusajs/types"
import {
FeatureFlagUtils,
ShippingProfileUtils,
kebabCase,
} from "@medusajs/utils"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type ShippingProfileId = string
type SalesChannelId = string
type ProductHandle = string
type VariantIndexAndPrices = {
index: number
prices: {
region_id?: string
currency_code?: string
amount: BigNumberInput
min_quantity?: BigNumberInput
max_quantity?: BigNumberInput
}[]
}
export type CreateProductsPreparedData = {
products: ProductTypes.CreateProductDTO[]
productsHandleShippingProfileIdMap: Map<ProductHandle, ShippingProfileId>
productsHandleSalesChannelsMap: Map<ProductHandle, SalesChannelId[]>
productsHandleVariantsIndexPricesMap: Map<
ProductHandle,
VariantIndexAndPrices[]
>
}
export async function createProductsPrepareData({
container,
context,
data,
}: WorkflowArguments<WorkflowTypes.ProductWorkflow.CreateProductsWorkflowInputDTO>): Promise<CreateProductsPreparedData> {
const { manager } = context
let products = data.products
const shippingProfileService = container
.resolve("shippingProfileService")
.withTransaction(manager)
const featureFlagRouter = container.resolve("featureFlagRouter")
const salesChannelService = container
.resolve("salesChannelService")
.withTransaction(manager)
const salesChannelFeatureFlagKey =
FeatureFlagUtils.SalesChannelFeatureFlag.key
const shippingProfileServiceTx =
shippingProfileService.withTransaction(manager)
const shippingProfiles = await shippingProfileServiceTx.list({
type: [
ShippingProfileUtils.ShippingProfileType.DEFAULT,
ShippingProfileUtils.ShippingProfileType.GIFT_CARD,
],
})
const defaultShippingProfile = shippingProfiles.find(
(sp) => sp.type === ShippingProfileUtils.ShippingProfileType.DEFAULT
)
const gitCardShippingProfile = shippingProfiles.find(
(sp) => sp.type === ShippingProfileUtils.ShippingProfileType.GIFT_CARD
)
let defaultSalesChannel: SalesChannelTypes.SalesChannelDTO | undefined
if (featureFlagRouter.isFeatureEnabled(salesChannelFeatureFlagKey)) {
defaultSalesChannel = await salesChannelService
.withTransaction(manager)
.retrieveDefault()
}
const productsHandleShippingProfileIdMap = new Map<
ProductHandle,
ShippingProfileId
>()
const productsHandleSalesChannelsMap = new Map<
ProductHandle,
SalesChannelId[]
>()
const productsHandleVariantsIndexPricesMap = new Map<
ProductHandle,
VariantIndexAndPrices[]
>()
for (const product of products) {
product.handle ??= kebabCase(product.title)
if (product.is_giftcard) {
productsHandleShippingProfileIdMap.set(
product.handle!,
gitCardShippingProfile!.id
)
} else {
productsHandleShippingProfileIdMap.set(
product.handle!,
defaultShippingProfile!.id
)
}
if (
featureFlagRouter.isFeatureEnabled(salesChannelFeatureFlagKey) &&
!product.sales_channels?.length
) {
productsHandleSalesChannelsMap.set(product.handle!, [
defaultSalesChannel!.id,
])
} else {
productsHandleSalesChannelsMap.set(
product.handle!,
product.sales_channels!.map((s) => s.id)
)
}
if (product.variants) {
const items =
productsHandleVariantsIndexPricesMap.get(product.handle!) ?? []
product.variants.forEach((variant, index) => {
items.push({
index,
prices: variant.prices!,
})
})
productsHandleVariantsIndexPricesMap.set(product.handle!, items)
}
}
products = products.map((productData) => {
delete productData.sales_channels
return productData
})
return {
products: products as ProductTypes.CreateProductDTO[],
productsHandleShippingProfileIdMap,
productsHandleSalesChannelsMap,
productsHandleVariantsIndexPricesMap,
}
}
createProductsPrepareData.aliases = {
payload: "payload",
}

View File

@@ -1,23 +0,0 @@
import { ProductTypes } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
import { Modules, ModulesDefinition } from "@medusajs/modules-sdk"
type HandlerInput = {
products: ProductTypes.CreateProductDTO[]
}
export async function createProducts({
container,
data,
}: WorkflowArguments<HandlerInput>): Promise<ProductTypes.ProductDTO[]> {
const data_ = data.products
const productModuleService: ProductTypes.IProductModuleService =
container.resolve(ModulesDefinition[Modules.PRODUCT].registrationName)
return await productModuleService.create(data_)
}
createProducts.aliases = {
payload: "payload",
}

View File

@@ -1,75 +0,0 @@
import { WorkflowArguments } from "@medusajs/workflows-sdk"
import { MedusaV2Flag, promiseAll } from "@medusajs/utils"
import { Modules } from "@medusajs/modules-sdk"
type ProductHandle = string
type SalesChannelId = string
type PartialProduct = { handle: string; id: string }
type HandlerInput = {
productsHandleSalesChannelsMap: Map<ProductHandle, SalesChannelId[]>
products: PartialProduct[]
}
export async function detachSalesChannelFromProducts({
container,
context,
data,
}: WorkflowArguments<HandlerInput>): Promise<void> {
const { manager } = context
const featureFlagRouter = container.resolve("featureFlagRouter")
const productsHandleSalesChannelsMap = data.productsHandleSalesChannelsMap
const products = data.products
const salesChannelService = container.resolve("salesChannelService")
const salesChannelServiceTx = salesChannelService.withTransaction(manager)
const salesChannelIdProductIdsMap = new Map<ProductHandle, SalesChannelId[]>()
products.forEach((product) => {
const salesChannelIds = productsHandleSalesChannelsMap.get(product.handle!)
if (salesChannelIds) {
salesChannelIds.forEach((salesChannelId) => {
const productIds = salesChannelIdProductIdsMap.get(salesChannelId) || []
productIds.push(product.id)
salesChannelIdProductIdsMap.set(salesChannelId, productIds)
})
}
})
if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) {
const remoteLink = container.resolve("remoteLink")
for (const [
salesChannelId,
productIds,
] of salesChannelIdProductIdsMap.entries()) {
await promiseAll(
productIds.map((id) =>
remoteLink.dismiss({
[Modules.PRODUCT]: {
product_id: id,
},
[Modules.SALES_CHANNEL]: {
sales_channel_id: salesChannelId,
},
})
)
)
}
} else {
await promiseAll(
Array.from(salesChannelIdProductIdsMap.entries()).map(
async ([salesChannelId, productIds]) => {
return await salesChannelServiceTx.removeProducts(
salesChannelId,
productIds
)
}
)
)
}
}
detachSalesChannelFromProducts.aliases = {
products: "products",
}

View File

@@ -1,50 +0,0 @@
import { WorkflowArguments } from "@medusajs/workflows-sdk"
import { promiseAll } from "@medusajs/utils"
type ProductHandle = string
type ShippingProfileId = string
type PartialProduct = { handle: string; id: string }
type HandlerInput = {
productsHandleShippingProfileIdMap: Map<ProductHandle, ShippingProfileId>
products: PartialProduct[]
}
export async function detachShippingProfileFromProducts({
container,
context,
data,
}: WorkflowArguments<HandlerInput>): Promise<void> {
const { manager } = context
const productsHandleShippingProfileIdMap =
data.productsHandleShippingProfileIdMap
const products = data.products
const shippingProfileService = container.resolve("shippingProfileService")
const shippingProfileServiceTx =
shippingProfileService.withTransaction(manager)
const profileIdProductIdsMap = new Map<ShippingProfileId, ProductHandle[]>()
products.forEach((product) => {
const profileId = productsHandleShippingProfileIdMap.get(product.handle!)
if (profileId) {
const productIds = profileIdProductIdsMap.get(profileId) || []
productIds.push(product.id)
profileIdProductIdsMap.set(profileId, productIds)
}
})
await promiseAll(
Array.from(profileIdProductIdsMap.entries()).map(
async ([profileId, productIds]) => {
return await shippingProfileServiceTx.removeProducts(
profileId,
productIds
)
}
)
)
}
detachShippingProfileFromProducts.aliases = {
products: "products",
}

View File

@@ -1,19 +0,0 @@
export * from "./attach-sales-channel-to-products"
export * from "./attach-shipping-profile-to-products"
export * from "./create-product-variants"
export * from "./create-product-variants-prepare-data"
export * from "./create-products"
export * from "./create-products-prepare-data"
export * from "./detach-sales-channel-from-products"
export * from "./detach-shipping-profile-from-products"
export * from "./list-products"
export * from "./remove-product-variants"
export * from "./remove-products"
export * from "./revert-update-products"
export * from "./revert-variant-prices"
export * from "./update-product-variants"
export * from "./update-product-variants-prepare-data"
export * from "./update-products"
export * from "./update-products-prepare-data"
export * from "./update-products-variants-prices"
export * from "./upsert-variant-prices"

View File

@@ -1,47 +0,0 @@
import { ProductTypes, WorkflowTypes } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type HandlerInput = {
ids: string[]
config?: WorkflowTypes.CommonWorkflow.WorkflowInputConfig
}
export async function listProducts({
container,
context,
data,
}: // TODO: should return product DTO or priced product but needs to be created in the types package
WorkflowArguments<HandlerInput>): Promise<ProductTypes.ProductDTO[]> {
const { manager } = context
const productIds = data.ids
const listConfig = data.config?.listConfig ?? {}
const productService = container.resolve("productService")
const pricingService = container.resolve("pricingService")
const config = {}
let shouldUseConfig = false
if (listConfig.select) {
shouldUseConfig = !!listConfig.select.length
Object.assign(config, { select: listConfig.select })
}
if (listConfig.relations) {
shouldUseConfig = shouldUseConfig || !!listConfig.relations.length
Object.assign(config, { relations: listConfig.relations })
}
const rawProducts = await productService
.withTransaction(manager as any)
.list({ id: productIds }, shouldUseConfig ? config : undefined)
return await pricingService
.withTransaction(manager as any)
.setProductPrices(rawProducts)
}
listProducts.aliases = {
ids: "ids",
}

View File

@@ -1,26 +0,0 @@
import { Modules, ModulesDefinition } from "@medusajs/modules-sdk"
import { IProductModuleService } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type HandlerInput = { productVariants: { id: string }[] }
export async function removeProductVariants({
container,
data,
}: WorkflowArguments<HandlerInput>): Promise<void> {
if (!data.productVariants.length) {
return
}
const productModuleService: IProductModuleService = container.resolve(
ModulesDefinition[Modules.PRODUCT].registrationName
)
await productModuleService.deleteVariants(
data.productVariants.map((p) => p.id)
)
}
removeProductVariants.aliases = {
productVariants: "productVariants",
}

View File

@@ -1,23 +0,0 @@
import { ProductTypes } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
import { Modules, ModulesDefinition } from "@medusajs/modules-sdk"
type HandlerInput = { products: { id: string }[] }
export async function removeProducts({
container,
data,
}: WorkflowArguments<HandlerInput>): Promise<void> {
if (!data.products.length) {
return
}
const productModuleService: ProductTypes.IProductModuleService =
container.resolve(ModulesDefinition[Modules.PRODUCT].registrationName)
await productModuleService.softDelete(data.products.map((p) => p.id))
}
removeProducts.aliases = {
products: "products",
}

View File

@@ -1,38 +0,0 @@
import { Modules, ModulesDefinition } from "@medusajs/modules-sdk"
import {
ProductDTO,
ProductTypes,
ProductVariantDTO,
UpdateProductDTO,
} from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
import { UpdateProductsPreparedData } from "./update-products-prepare-data"
type HandlerInput = UpdateProductsPreparedData & {
variants: ProductVariantDTO[]
}
export async function revertUpdateProducts({
container,
data,
}: WorkflowArguments<HandlerInput>): Promise<ProductDTO[]> {
const productModuleService: ProductTypes.IProductModuleService =
container.resolve(ModulesDefinition[Modules.PRODUCT].registrationName)
// restore variants that have been soft deleted during update products step
await productModuleService.restoreVariants(data.variants.map((v) => v.id))
data.originalProducts.forEach((product) => {
// @ts-ignore
product.variants = product.variants.map((v) => ({ id: v.id }))
})
return await productModuleService.upsert(
data.originalProducts as unknown as UpdateProductDTO[]
)
}
revertUpdateProducts.aliases = {
preparedData: "preparedData",
variants: "variants",
}

View File

@@ -1,49 +0,0 @@
import { PricingTypes } from "@medusajs/types"
import { MedusaV2Flag } from "@medusajs/utils"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type HandlerInput = {
createdLinks: Record<any, any>[]
originalMoneyAmounts: PricingTypes.MoneyAmountDTO[]
createdPriceSets: PricingTypes.PriceSetDTO[]
}
export async function revertVariantPrices({
container,
context,
data,
}: WorkflowArguments<HandlerInput>): Promise<void> {
const {
createdLinks = [],
originalMoneyAmounts = [],
createdPriceSets = [],
} = data
const featureFlagRouter = container.resolve("featureFlagRouter")
const isPricingDomainEnabled = featureFlagRouter.isFeatureEnabled(
MedusaV2Flag.key
)
if (!isPricingDomainEnabled) {
return
}
const pricingModuleService = container.resolve("pricingModuleService")
const remoteLink = container.resolve("remoteLink")
await remoteLink.remove(createdLinks)
if (originalMoneyAmounts.length) {
await pricingModuleService.updateMoneyAmounts(originalMoneyAmounts)
}
if (createdPriceSets.length) {
await pricingModuleService.delete({
id: createdPriceSets.map((cps) => cps.id),
})
}
}
revertVariantPrices.aliases = {
productVariantsPrices: "productVariantsPrices",
}

View File

@@ -1,101 +0,0 @@
import { Modules, ModulesDefinition } from "@medusajs/modules-sdk"
import {
BigNumberInput,
ProductTypes,
ProductWorkflow,
WorkflowTypes,
} from "@medusajs/types"
import { MedusaV2Flag } from "@medusajs/utils"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type VariantPrice = {
region_id?: string
currency_code?: string
amount: BigNumberInput
min_quantity?: BigNumberInput
max_quantity?: BigNumberInput
}
export type UpdateProductVariantsPreparedData = {
productVariants: ProductWorkflow.UpdateProductVariantsInputDTO[]
variantPricesMap: Map<string, VariantPrice[]>
productVariantsMap: Map<
string,
ProductWorkflow.UpdateProductVariantsInputDTO[]
>
}
export async function updateProductVariantsPrepareData({
container,
context,
data,
}: WorkflowArguments<WorkflowTypes.ProductWorkflow.UpdateProductVariantsWorkflowInputDTO>): Promise<UpdateProductVariantsPreparedData> {
const featureFlagRouter = container.resolve("featureFlagRouter")
const isPricingDomainEnabled = featureFlagRouter.isFeatureEnabled(
MedusaV2Flag.key
)
let productVariants: ProductWorkflow.UpdateProductVariantsInputDTO[] =
data.productVariants || []
const variantsDataMap = new Map<
string,
ProductWorkflow.UpdateProductVariantsInputDTO
>(
productVariants.map((productVariantData) => [
productVariantData.id,
productVariantData,
])
)
const variantIds = productVariants.map((pv) => pv.id) as string[]
const productVariantsMap = new Map<
string,
ProductWorkflow.UpdateProductVariantsInputDTO[]
>()
const variantPricesMap = new Map<string, VariantPrice[]>()
const productModuleService: ProductTypes.IProductModuleService =
container.resolve(ModulesDefinition[Modules.PRODUCT].registrationName)
const variantsWithProductIds = await productModuleService.listVariants(
{
id: variantIds,
},
{
select: ["id", "product_id"],
take: null,
}
)
for (const variantWithProductID of variantsWithProductIds) {
const variantData = variantsDataMap.get(variantWithProductID.id)
if (!variantData) {
continue
}
variantPricesMap.set(variantWithProductID.id, variantData.prices || [])
if (isPricingDomainEnabled) {
delete variantData.prices
}
const variantsData: ProductWorkflow.UpdateProductVariantsInputDTO[] =
productVariantsMap.get(variantWithProductID.product_id!) || []
if (variantData) {
variantsData.push(variantData)
}
productVariantsMap.set(variantWithProductID.product_id!, variantsData)
}
return {
productVariants,
variantPricesMap,
productVariantsMap,
}
}
updateProductVariantsPrepareData.aliases = {
payload: "payload",
}

View File

@@ -1,38 +0,0 @@
import { Modules, ModulesDefinition } from "@medusajs/modules-sdk"
import { ProductTypes, UpdateProductVariantDTO } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type HandlerInput = {
productVariantsMap: Map<string, ProductTypes.UpdateProductVariantDTO[]>
}
export async function updateProductVariants({
container,
data,
}: WorkflowArguments<HandlerInput>): Promise<
ProductTypes.UpdateProductVariantDTO[]
> {
const { productVariantsMap } = data
const productsVariants: ProductTypes.UpdateProductVariantDTO[] = []
const updateVariantsData: ProductTypes.UpdateProductVariantDTO[] = []
const productModuleService: ProductTypes.IProductModuleService =
container.resolve(ModulesDefinition[Modules.PRODUCT].registrationName)
for (const [product_id, variantsUpdateData = []] of productVariantsMap) {
updateVariantsData.push(
...variantsUpdateData.map((update) => ({ ...update, product_id }))
)
productsVariants.push(...variantsUpdateData)
}
if (updateVariantsData.length) {
await productModuleService.upsertVariants(updateVariantsData)
}
return productsVariants
}
updateProductVariants.aliases = {
payload: "payload",
}

View File

@@ -1,115 +0,0 @@
import {
BigNumberInput,
ProductDTO,
SalesChannelDTO,
WorkflowTypes,
} from "@medusajs/types"
import { MedusaV2Flag } from "@medusajs/utils"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type ProductWithSalesChannelsDTO = ProductDTO & {
sales_channels?: SalesChannelDTO[]
}
type VariantPrice = {
region_id?: string
currency_code?: string
amount: BigNumberInput
min_quantity?: BigNumberInput
max_quantity?: BigNumberInput
}
export type UpdateProductsPreparedData = {
originalProducts: ProductWithSalesChannelsDTO[]
productHandleAddedChannelsMap: Map<string, string[]>
productHandleRemovedChannelsMap: Map<string, string[]>
variantPricesMap: Map<string, VariantPrice[]>
}
export async function updateProductsPrepareData({
container,
context,
data,
}: WorkflowArguments<WorkflowTypes.ProductWorkflow.UpdateProductsWorkflowInputDTO>): Promise<UpdateProductsPreparedData> {
const featureFlagRouter = container.resolve("featureFlagRouter")
const isPricingDomainEnabled = featureFlagRouter.isFeatureEnabled(
MedusaV2Flag.key
)
const variantPricesMap = new Map<string, VariantPrice[]>()
const ids = data.products.map((product) => product.id)
const productHandleAddedChannelsMap = new Map<string, string[]>()
const productHandleRemovedChannelsMap = new Map<string, string[]>()
const productService = container.resolve("productService")
const productServiceTx = productService.withTransaction(context.manager)
const products = await productServiceTx.list(
// TODO: use RemoteQuery - sales_channels needs to be added to the joiner config
{ id: ids },
{
relations: [
"variants",
"variants.options",
"images",
"options",
"tags",
"collection",
"sales_channels",
],
take: null,
}
)
const productsMap = new Map(products.map((product) => [product.id, product]))
data.products.forEach((productInput) => {
const removedChannels: string[] = []
const addedChannels: string[] = []
const currentProduct = productsMap.get(
productInput.id
) as unknown as ProductWithSalesChannelsDTO
if (productInput.sales_channels) {
productInput.sales_channels.forEach((channel) => {
if (
!currentProduct.sales_channels?.find((sc) => sc.id === channel.id)
) {
addedChannels.push(channel.id)
}
})
currentProduct.sales_channels?.forEach((channel) => {
if (!productInput.sales_channels!.find((sc) => sc.id === channel.id)) {
removedChannels.push(channel.id)
}
})
}
for (const variantInput of productInput.variants || []) {
if (variantInput.id) {
variantPricesMap.set(variantInput.id, variantInput.prices || [])
}
if (isPricingDomainEnabled) {
delete variantInput.prices
}
}
productHandleAddedChannelsMap.set(currentProduct.handle!, addedChannels)
productHandleRemovedChannelsMap.set(currentProduct.handle!, removedChannels)
})
return {
originalProducts: products,
productHandleAddedChannelsMap,
productHandleRemovedChannelsMap,
variantPricesMap,
}
}
updateProductsPrepareData.aliases = {
preparedData: "preparedData",
}

View File

@@ -1,131 +0,0 @@
import { ProductTypes, WorkflowTypes } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { MedusaError, MedusaV2Flag } from "@medusajs/utils"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type ProductHandle = string
type VariantIndexAndPrices = {
index: number
prices: WorkflowTypes.ProductWorkflow.CreateProductVariantPricesInputDTO[]
}
type HandlerInput = {
productsHandleVariantsIndexPricesMap: Map<
ProductHandle,
VariantIndexAndPrices[]
>
products: ProductTypes.ProductDTO[]
}
export async function updateProductsVariantsPrices({
container,
context,
data,
}: WorkflowArguments<HandlerInput>) {
const { manager } = context
const products = data.products
const productsHandleVariantsIndexPricesMap =
data.productsHandleVariantsIndexPricesMap
const productVariantService = container.resolve("productVariantService")
const regionService = container.resolve("regionService")
const featureFlagRouter = container.resolve("featureFlagRouter")
const productVariantServiceTx = productVariantService.withTransaction(manager)
const variantIdsPricesData: any[] = []
const variantPricesMap = new Map<string, any[]>()
const productsMap = new Map<string, ProductTypes.ProductDTO>(
products.map((p) => [p.handle!, p])
)
const regionIds = new Set()
for (const mapData of productsHandleVariantsIndexPricesMap.entries()) {
const [handle, variantData] = mapData
const product = productsMap.get(handle)
if (!product) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Product with handle ${handle} not found`
)
}
variantData.forEach((item, index) => {
const variant = product.variants[index]
variantIdsPricesData.push({
variantId: variant.id,
prices: item.prices,
})
const prices: any[] = []
variantPricesMap.set(variant.id, prices)
item.prices.forEach((price) => {
const obj = {
amount: price.amount,
currency_code: price.currency_code,
}
if (price.region_id) {
regionIds.add(price.region_id)
;(obj as any).region_id = price.region_id
}
prices.push(obj)
})
})
}
if (regionIds.size) {
const regions = await regionService.list({
id: [...regionIds],
})
const regionMap = new Map<string, any>(regions.map((r) => [r.id, r]))
for (const [, prices] of variantPricesMap.entries()) {
prices.forEach((price) => {
if (price.region_id) {
const region = regionMap.get(price.region_id)
price.currency_code = region?.currency_code
price.rules = {
region_id: price.region_id,
}
delete price.region_id
}
})
}
}
if (featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) {
const remoteLink = container.resolve("remoteLink")
const pricingModuleService = container.resolve(
ModuleRegistrationName.PRICING
)
const priceSetsToCreate = variantIdsPricesData.map(({ variantId }) => ({
rules: [{ rule_attribute: "region_id" }],
prices: variantPricesMap.get(variantId),
}))
const priceSets = await pricingModuleService.create(priceSetsToCreate)
const links = priceSets.map((priceSet, index) => ({
productService: {
variant_id: variantIdsPricesData[index].variantId,
},
pricingService: {
price_set_id: priceSet.id,
},
}))
await remoteLink.create(links)
} else {
await productVariantServiceTx.updateVariantPrices(variantIdsPricesData)
}
}
updateProductsVariantsPrices.aliases = {
products: "products",
}

View File

@@ -1,45 +0,0 @@
import { Modules, ModulesDefinition } from "@medusajs/modules-sdk"
import { ProductDTO, ProductTypes } from "@medusajs/types"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type HandlerInput = {
products: ProductTypes.UpdateProductDTO[]
}
export async function updateProducts({
container,
context,
data,
}: WorkflowArguments<HandlerInput>): Promise<ProductDTO[]> {
if (!data.products.length) {
return []
}
const productModuleService: ProductTypes.IProductModuleService =
container.resolve(ModulesDefinition[Modules.PRODUCT].registrationName)
const products = await productModuleService.upsert(data.products)
return await productModuleService.list(
{ id: products.map((p) => p.id) },
{
relations: [
"variants",
"variants.options",
"images",
"options",
"tags",
// "type",
"collection",
// "profiles",
// "sales_channels",
],
take: null,
}
)
}
updateProducts.aliases = {
products: "products",
}

View File

@@ -1,176 +0,0 @@
import { BigNumberInput, PricingTypes } from "@medusajs/types"
import { MedusaV2Flag } from "@medusajs/utils"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type VariantPrice = {
id?: string
region_id?: string
currency_code: string
amount: BigNumberInput
min_quantity?: BigNumberInput
max_quantity?: BigNumberInput
rules: Record<string, string>
}
type RegionDTO = {
id: string
currency_code: string
}
type HandlerInput = {
variantPricesMap: Map<string, VariantPrice[]>
}
export async function upsertVariantPrices({
container,
data,
}: WorkflowArguments<HandlerInput>) {
const { variantPricesMap } = data
const featureFlagRouter = container.resolve("featureFlagRouter")
if (!featureFlagRouter.isFeatureEnabled(MedusaV2Flag.key)) {
return {
createdLinks: [],
originalMoneyAmounts: [],
createdPriceSets: [],
}
}
const pricingModuleService = container.resolve("pricingModuleService")
const regionService = container.resolve("regionService")
const remoteLink = container.resolve("remoteLink")
const remoteQuery = container.resolve("remoteQuery")
const variables = {
variant_id: [...variantPricesMap.keys()],
}
const query = {
product_variant_price_set: {
__args: variables,
fields: ["variant_id", "price_set_id"],
},
}
const variantPriceSets = await remoteQuery(query)
const variantIdToPriceSetIdMap: Map<string, string> = new Map(
variantPriceSets.map((variantPriceSet) => [
variantPriceSet.variant_id,
variantPriceSet.price_set_id,
])
)
const moneyAmountsToUpdate: PricingTypes.UpdateMoneyAmountDTO[] = []
const createdPriceSets: PricingTypes.PriceSetDTO[] = []
const ruleSetPricesToAdd: PricingTypes.CreatePricesDTO[] = []
const linksToCreate: any[] = []
for (const [variantId, prices = []] of variantPricesMap) {
const priceSetToCreate: PricingTypes.CreatePriceSetDTO = {
rules: [{ rule_attribute: "region_id" }],
prices: [],
}
const regionIds = prices.map((price) => price.region_id)
const regions = await regionService.list({ id: regionIds })
const regionsMap: Map<string, RegionDTO> = new Map(
regions.map((region: RegionDTO) => [region.id, region])
)
for (const price of prices) {
const region = price.region_id && regionsMap.get(price.region_id)
let region_currency_code: string | undefined
let region_rules: Record<string, string> | undefined
if (region) {
region_currency_code = region.currency_code
region_rules = {
region_id: region.id,
}
}
if (price.id) {
const priceToUpdate = {
id: price.id,
min_quantity: price.min_quantity,
max_quantity: price.max_quantity,
amount: price.amount,
currency_code: (
region_currency_code ?? price.currency_code
).toLowerCase(),
}
moneyAmountsToUpdate.push(priceToUpdate)
} else {
const variantPrice: PricingTypes.CreatePricesDTO = {
min_quantity: price.min_quantity,
max_quantity: price.max_quantity,
amount: price.amount,
currency_code: (
region_currency_code ?? price.currency_code
).toLowerCase(),
rules: region_rules ?? {},
}
delete price.region_id
if (variantIdToPriceSetIdMap.get(variantId)) {
ruleSetPricesToAdd.push(variantPrice)
} else {
priceSetToCreate.prices?.push(variantPrice)
}
}
}
let priceSetId = variantIdToPriceSetIdMap.get(variantId)
if (priceSetId) {
await pricingModuleService.addPrices({
priceSetId,
prices: ruleSetPricesToAdd,
})
} else {
const createdPriceSet = await pricingModuleService.create(
priceSetToCreate
)
priceSetId = createdPriceSet?.id
createdPriceSets.push(createdPriceSet)
linksToCreate.push({
productService: {
variant_id: variantId,
},
pricingService: {
price_set_id: priceSetId,
},
})
}
}
const createdLinks = await remoteLink.create(linksToCreate)
let originalMoneyAmounts = await pricingModuleService.listMoneyAmounts(
{
id: moneyAmountsToUpdate.map((matu) => matu.id),
},
{
select: ["id", "currency_code", "amount", "min_quantity", "max_quantity"],
take: null,
}
)
if (moneyAmountsToUpdate.length) {
await pricingModuleService.updateMoneyAmounts(moneyAmountsToUpdate)
}
return {
createdLinks,
originalMoneyAmounts,
createdPriceSets,
}
}
upsertVariantPrices.aliases = {
productVariantsPrices: "productVariantsPrices",
}

View File

@@ -1,58 +0,0 @@
import { RegionTypes } from "@medusajs/types"
import { isDefined, MedusaError } from "@medusajs/utils"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type RegionResultDTO = {
region_id?: string
// TODO: Replace with RegionDTO from Region Module
region?: RegionTypes.RegionDTO__legacy
}
type HandlerInputData = {
region: {
region_id: string
}
}
enum Aliases {
Region = "region",
}
export async function findRegion({
container,
data,
}: WorkflowArguments<HandlerInputData>): Promise<RegionResultDTO> {
const regionService = container.resolve("regionService")
let regionId: string
const regionDTO: RegionResultDTO = {}
if (isDefined(data[Aliases.Region].region_id)) {
regionDTO.region_id = data[Aliases.Region].region_id
regionDTO.region = await regionService.retrieve(regionDTO.region_id, {
relations: ["countries"],
})
} else {
const regions = await regionService.list(
{},
{
relations: ["countries"],
}
)
if (!regions?.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`A region is required to create a cart`
)
}
regionDTO.region_id = regions[0].id
regionDTO.region = regions[0]
}
return regionDTO
}
findRegion.aliases = Aliases

View File

@@ -1 +0,0 @@
export * from "./find-region"

View File

@@ -1,73 +0,0 @@
import { isDefined, MedusaError } from "@medusajs/utils"
import { WorkflowArguments } from "@medusajs/workflows-sdk"
type AttachSalesChannelDTO = {
sales_channel_id?: string
}
type HandlerInputData = {
sales_channel: {
sales_channel_id?: string
publishableApiKeyScopes?: {
sales_channel_ids?: string[]
}
}
}
enum Aliases {
SalesChannel = "sales_channel",
}
export async function findSalesChannel({
container,
data,
}: WorkflowArguments<HandlerInputData>): Promise<AttachSalesChannelDTO> {
const salesChannelService = container.resolve("salesChannelService")
const storeService = container.resolve("storeService")
let salesChannelId = data[Aliases.SalesChannel].sales_channel_id
let salesChannel
const salesChannelDTO: AttachSalesChannelDTO = {}
const publishableApiKeyScopes =
data[Aliases.SalesChannel].publishableApiKeyScopes || {}
delete data[Aliases.SalesChannel].publishableApiKeyScopes
if (
!isDefined(salesChannelId) &&
publishableApiKeyScopes?.sales_channel_ids?.length
) {
if (publishableApiKeyScopes.sales_channel_ids.length > 1) {
throw new MedusaError(
MedusaError.Types.UNEXPECTED_STATE,
"The provided PublishableApiKey has multiple associated sales channels."
)
}
salesChannelId = publishableApiKeyScopes.sales_channel_ids[0]
}
if (isDefined(salesChannelId)) {
salesChannel = await salesChannelService.retrieve(salesChannelId)
} else {
salesChannel = (
await storeService.retrieve({
relations: ["default_sales_channel"],
})
).default_sales_channel
}
if (salesChannel.is_disabled) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Unable to assign the cart to a disabled Sales Channel "${salesChannel.name}"`
)
}
salesChannelDTO.sales_channel_id = salesChannel?.id
return salesChannelDTO
}
findSalesChannel.aliases = Aliases

View File

@@ -1 +0,0 @@
export * from "./find-sales-channel"

View File

@@ -5,10 +5,8 @@ export * from "./customer"
export * from "./customer-group"
export * from "./defaults"
export * from "./definition"
export * from "./definitions"
export * from "./file"
export * from "./fulfillment"
export * as Handlers from "./handlers"
export * from "./inventory"
export * from "./invite"
export * from "./order"