feat:Add confirmation step to product import (#8284)

CLOSES CC-251
This commit is contained in:
Stevche Radevski
2024-07-25 16:54:31 +02:00
committed by GitHub
parent 7f4b085964
commit 6d0650818a
11 changed files with 100 additions and 14 deletions

View File

@@ -168,8 +168,8 @@ medusaIntegrationTestRunner({
adminHeaders
)
const workflowId = batchJobRes.data.workflow_id
expect(workflowId).toBeTruthy()
const transactionId = batchJobRes.data.transaction_id
expect(transactionId).toBeTruthy()
await subscriberExecution
const notifications = (
@@ -214,8 +214,8 @@ medusaIntegrationTestRunner({
adminHeaders
)
const workflowId = batchJobRes.data.workflow_id
expect(workflowId).toBeTruthy()
const transactionId = batchJobRes.data.transaction_id
expect(transactionId).toBeTruthy()
await subscriberExecution
const notifications = (

View File

@@ -101,8 +101,18 @@ medusaIntegrationTestRunner({
// BREAKING: The batch endpoints moved to the domain routes (admin/batch-jobs -> /admin/products/import). The payload and response changed as well.
const batchJobRes = await api.post("/admin/products/import", form, meta)
const workflowId = batchJobRes.data.workflow_id
expect(workflowId).toBeTruthy()
const transactionId = batchJobRes.data.transaction_id
expect(transactionId).toBeTruthy()
expect(batchJobRes.data.summary).toEqual({
toCreate: 1,
toUpdate: 1,
})
await api.post(
`/admin/products/import/${transactionId}/confirm`,
{},
meta
)
await subscriberExecution
const notifications = (

View File

@@ -23,3 +23,4 @@ export * from "./delete-product-tags"
export * from "./generate-product-csv"
export * from "./parse-product-csv"
export * from "./group-products-for-batch"
export * from "./wait-confirmation-product-import"

View File

@@ -0,0 +1,13 @@
import { createStep } from "@medusajs/workflows-sdk"
export const waitConfirmationProductImportStepId =
"wait-confirmation-product-import"
export const waitConfirmationProductImportStep = createStep(
{
name: waitConfirmationProductImportStepId,
async: true,
// After an hour we want to timeout and cancel the import so we don't have orphaned workflows
timeout: 60 * 60 * 1 * 1000,
},
async () => {}
)

View File

@@ -5,7 +5,11 @@ import {
} from "@medusajs/workflows-sdk"
import { WorkflowTypes } from "@medusajs/types"
import { sendNotificationsStep } from "../../notification"
import { groupProductsForBatchStep, parseProductCsvStep } from "../steps"
import {
waitConfirmationProductImportStep,
groupProductsForBatchStep,
parseProductCsvStep,
} from "../steps"
import { batchProductsWorkflow } from "./batch-products"
export const importProductsWorkflowId = "import-products"
@@ -13,11 +17,18 @@ export const importProductsWorkflow = createWorkflow(
importProductsWorkflowId,
(
input: WorkflowData<WorkflowTypes.ProductWorkflow.ImportProductsDTO>
): WorkflowData<void> => {
): WorkflowData<WorkflowTypes.ProductWorkflow.ImportProductsSummary> => {
const products = parseProductCsvStep(input.fileContent)
const batchRequest = groupProductsForBatchStep(products)
// TODO: Add async confirmation step here
const summary = transform({ batchRequest }, (data) => {
return {
toCreate: data.batchRequest.create.length,
toUpdate: data.batchRequest.update.length,
}
})
waitConfirmationProductImportStep()
batchProductsWorkflow.runAsStep({ input: batchRequest })
@@ -37,5 +48,6 @@ export const importProductsWorkflow = createWorkflow(
})
sendNotificationsStep(notifications)
return summary
}
)

View File

@@ -32,11 +32,15 @@ export interface AdminProductVariantDeleteResponse
extends DeleteResponse<"variant", AdminProduct> {}
export interface AdminExportProductResponse {
workflow_id: string
transaction_id: string
}
export interface AdminImportProductResponse {
workflow_id: string
transaction_id: string
summary: {
toCreate: number
toUpdate: number
}
}
export interface AdminBatchProductVariantResponse

View File

@@ -2,3 +2,8 @@ export interface ImportProductsDTO {
fileContent: string
filename: string
}
export interface ImportProductsSummary {
toCreate: number
toUpdate: number
}

View File

@@ -17,5 +17,5 @@ export const POST = async (
input,
})
res.status(202).json({ workflow_id: transaction.transactionId })
res.status(202).json({ transaction_id: transaction.transactionId })
}

View File

@@ -0,0 +1,34 @@
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../../../../types/routing"
import { IWorkflowEngineService } from "@medusajs/types"
import { ModuleRegistrationName, TransactionHandlerType } from "@medusajs/utils"
import {
importProductsWorkflowId,
waitConfirmationProductImportStepId,
} from "@medusajs/core-flows"
import { StepResponse } from "@medusajs/workflows-sdk"
export const POST = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const workflowEngineService: IWorkflowEngineService = req.scope.resolve(
ModuleRegistrationName.WORKFLOW_ENGINE
)
const transactionId = req.params.transaction_id
await workflowEngineService.setStepSuccess({
idempotencyKey: {
action: TransactionHandlerType.INVOKE,
transactionId,
stepId: waitConfirmationProductImportStepId,
workflowId: importProductsWorkflowId,
},
stepResponse: new StepResponse(true),
})
res.status(202).json({})
}

View File

@@ -19,12 +19,14 @@ export const POST = async (
)
}
const { transaction } = await importProductsWorkflow(req.scope).run({
const { result, transaction } = await importProductsWorkflow(req.scope).run({
input: {
filename: input.originalname,
fileContent: input.buffer.toString("utf-8"),
},
})
res.status(202).json({ workflow_id: transaction.transactionId })
res
.status(202)
.json({ transaction_id: transaction.transactionId, summary: result })
}

View File

@@ -92,6 +92,11 @@ export const adminProductRoutesMiddlewares: MiddlewareRoute[] = [
matcher: "/admin/products/import",
middlewares: [upload.single("file")],
},
{
method: ["POST"],
matcher: "/admin/products/import/:transaction_id/confirm",
middlewares: [],
},
{
method: ["GET"],
matcher: "/admin/products/:id",