diff --git a/.changeset/khaki-pets-repeat.md b/.changeset/khaki-pets-repeat.md new file mode 100644 index 0000000000..a777100f8f --- /dev/null +++ b/.changeset/khaki-pets-repeat.md @@ -0,0 +1,6 @@ +--- +"@medusajs/medusa": patch +--- + +Fix wrongly referenced product id in ProductImportStrategy +Fix assigning nested objects properly diff --git a/integration-tests/api/__tests__/batch-jobs/product/ff-sales-channel.js b/integration-tests/api/__tests__/batch-jobs/product/ff-sales-channel.js index 61f13e45e6..10645e26fc 100644 --- a/integration-tests/api/__tests__/batch-jobs/product/ff-sales-channel.js +++ b/integration-tests/api/__tests__/batch-jobs/product/ff-sales-channel.js @@ -118,17 +118,16 @@ describe("Product import - Sales Channel", () => { const productsResponse = await api.get("/admin/products", adminReqConfig) - expect(productsResponse.data.count).toBe(2) + expect(productsResponse.data.count).toBe(1) expect(productsResponse.data.products).toEqual([ expect.objectContaining({ - id: "O6S1YQ6mKm", title: "Test product", - description: "test-product-description-1", + description: + "Hopper Stripes Bedding, available as duvet cover, pillow sham and sheet.\\n100% organic cotton, soft and crisp to the touch. Made in Portugal.", handle: "test-product-product-1", variants: [ expect.objectContaining({ title: "Test variant", - product_id: "O6S1YQ6mKm", sku: "test-sku-1", }), ], @@ -143,25 +142,6 @@ describe("Product import - Sales Channel", () => { }), ], }), - expect.objectContaining({ - id: "5VxiEkmnPV", - title: "Test product", - description: "test-product-description", - handle: "test-product-product-2", - variants: [ - expect.objectContaining({ - title: "Test variant", - product_id: "5VxiEkmnPV", - sku: "test-sku-2", - }), - expect.objectContaining({ - title: "Test variant", - product_id: "5VxiEkmnPV", - sku: "test-sku-3", - }), - ], - sales_channels: [], - }), ]) }) }) diff --git a/integration-tests/api/__tests__/batch-jobs/product/import.js b/integration-tests/api/__tests__/batch-jobs/product/import.js index c424237ae1..6537122618 100644 --- a/integration-tests/api/__tests__/batch-jobs/product/import.js +++ b/integration-tests/api/__tests__/batch-jobs/product/import.js @@ -8,6 +8,7 @@ const { initDb, useDb } = require("../../../../helpers/use-db") const adminSeeder = require("../../../helpers/admin-seeder") const batchJobSeeder = require("../../../helpers/batch-job-seeder") const userSeeder = require("../../../helpers/user-seeder") +const { simpleProductFactory } = require("../../../factories") const adminReqConfig = { headers: { @@ -71,6 +72,29 @@ describe("Product import batch job", () => { jest.setTimeout(1000000) const api = useApi() + const existingProductToBeUpdated = await simpleProductFactory( + dbConnection, + { + id: "existing-product-id", + title: "Test product", + options: [{ id: "opt-1-id", title: "Size" }], + variants: [ + { + id: "existing-variant-id", + title: "Initial tile", + sku: "test-sku-4", + barde: "test-barcode-4", + options: [ + { + option_id: "opt-1-id", + value: "Large", + }, + ], + }, + ], + } + ) + const response = await api.post( "/admin/batch-jobs", { @@ -113,8 +137,8 @@ describe("Product import batch job", () => { expect(productsResponse.data.count).toBe(2) expect(productsResponse.data.products).toEqual( expect.arrayContaining([ + // NEW PRODUCT expect.objectContaining({ - id: "O6S1YQ6mKm", title: "Test product", description: "Hopper Stripes Bedding, available as duvet cover, pillow sham and sheet.\\n100% organic cotton, soft and crisp to the touch. Made in Portugal.", @@ -123,9 +147,9 @@ describe("Product import batch job", () => { status: "draft", thumbnail: "test-image.png", variants: [ + // NEW VARIANT expect.objectContaining({ title: "Test variant", - product_id: "O6S1YQ6mKm", sku: "test-sku-1", barcode: "test-barcode-1", ean: null, @@ -147,14 +171,14 @@ describe("Product import batch job", () => { region_id: "region-product-import-1", }), ], - options: [ + options: expect.arrayContaining([ expect.objectContaining({ value: "option 1 value red", }), expect.objectContaining({ value: "option 2 value 1", }), - ], + ]), }), ], images: [ @@ -165,11 +189,9 @@ describe("Product import batch job", () => { options: [ expect.objectContaining({ title: "test-option-1", - product_id: "O6S1YQ6mKm", }), expect.objectContaining({ title: "test-option-2", - product_id: "O6S1YQ6mKm", }), ], tags: [ @@ -178,8 +200,9 @@ describe("Product import batch job", () => { }), ], }), + // UPDATED PRODUCT expect.objectContaining({ - id: "5VxiEkmnPV", + id: existingProductToBeUpdated.id, title: "Test product", description: "test-product-description", handle: "test-product-product-2", @@ -187,10 +210,24 @@ describe("Product import batch job", () => { status: "draft", thumbnail: "test-image.png", profile_id: expect.any(String), - variants: [ + variants: expect.arrayContaining([ + // UPDATED VARIANT + expect.objectContaining({ + id: "existing-variant-id", + title: "Test variant changed", + sku: "test-sku-4", + barcode: "test-barcode-4", + options: [ + expect.objectContaining({ + value: "Large", + option_id: "opt-1-id", + }), + ], + }), + // CREATED VARIANT expect.objectContaining({ title: "Test variant", - product_id: "5VxiEkmnPV", + product_id: existingProductToBeUpdated.id, sku: "test-sku-2", barcode: "test-barcode-2", ean: null, @@ -207,13 +244,15 @@ describe("Product import batch job", () => { ], options: [ expect.objectContaining({ - value: "Option 1 value 1", + value: "Small", + option_id: "opt-1-id", }), ], }), + // CREATED VARIANT expect.objectContaining({ title: "Test variant", - product_id: "5VxiEkmnPV", + product_id: existingProductToBeUpdated.id, sku: "test-sku-3", barcode: "test-barcode-3", ean: null, @@ -230,11 +269,12 @@ describe("Product import batch job", () => { ], options: [ expect.objectContaining({ - value: "Option 1 Value blue", + value: "Medium", + option_id: "opt-1-id", }), ], }), - ], + ]), images: [ expect.objectContaining({ url: "test-image.png", @@ -242,8 +282,9 @@ describe("Product import batch job", () => { ], options: [ expect.objectContaining({ - title: "test-option", - product_id: "5VxiEkmnPV", + product_id: existingProductToBeUpdated.id, + id: "opt-1-id", + title: "Size", }), ], tags: [ diff --git a/integration-tests/api/__tests__/batch-jobs/product/product-import-ss.csv b/integration-tests/api/__tests__/batch-jobs/product/product-import-ss.csv index f4ec2425af..f2933ab938 100644 --- a/integration-tests/api/__tests__/batch-jobs/product/product-import-ss.csv +++ b/integration-tests/api/__tests__/batch-jobs/product/product-import-ss.csv @@ -1,4 +1,2 @@ -Product id,Product Handle,Product Title,Product Subtitle,Product Description,Product Status,Product Thumbnail,Product Weight,Product Length,Product Width,Product Height,Product HS Code,Product Origin Country,Product MID Code,Product Material,Product Collection Title,Product Collection Handle,Product Type,Product Tags,Product Discountable,Product External ID,Product Profile Name,Product Profile Type,Variant id,Variant Title,Variant SKU,Variant Barcode,Variant Inventory Quantity,Variant Allow backorder,Variant Manage inventory,Variant Weight,Variant Length,Variant Width,Variant Height,Variant HS Code,Variant Origin Country,Variant MID Code,Variant Material,Price ImportLand [EUR],Price USD,Price denmark [DKK],Price Denmark [DKK],Option 1 Name,Option 1 Value,Option 2 Name,Option 2 Value,Image 1 Url,Sales Channel 1 Name,Sales Channel 2 Name,Sales Channel 1 Id,Sales Channel 2 Id -O6S1YQ6mKm,test-product-product-1,Test product,,test-product-description-1,draft,,,,,,,,,,Test collection 1,test-collection1,test-type-1,123_1,TRUE,,profile_1,profile_type_1,,Test variant,test-sku-1,test-barcode-1,10,FALSE,TRUE,,,,,,,,,1.00,1.10,1.30,,test-option-1,option 1 value red,test-option-2,option 2 value 1,test-image.png,Import Sales Channel 1,Import Sales Channel 2,, -5VxiEkmnPV,test-product-product-2,Test product,,test-product-description,draft,,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,profile_2,profile_type_2,,Test variant,test-sku-2,test-barcode-2,10,FALSE,TRUE,,,,,,,,,,,,1.10,test-option,Option 1 value 1,,,test-image.png,,,, -5VxiEkmnPV,test-product-product-2,Test product,,test-product-description,draft,,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,profile_2,profile_type_2,,Test variant,test-sku-3,test-barcode-3,10,FALSE,TRUE,,,,,,,,,,1.20,,,test-option,Option 1 Value blue,,,test-image.png,,,, +Product id,Product Handle,Product Title,Product Subtitle,Product Description,Product Status,Product Thumbnail,Product Weight,Product Length,Product Width,Product Height,Product HS Code,Product Origin Country,Product MID Code,Product Material,Product Collection Title,Product Collection Handle,Product Type,Product Tags,Product Discountable,Product External ID,Variant id,Variant Title,Variant SKU,Variant Barcode,Variant Inventory Quantity,Variant Allow backorder,Variant Manage inventory,Variant Weight,Variant Length,Variant Width,Variant Height,Variant HS Code,Variant Origin Country,Variant MID Code,Variant Material,Price ImportLand [EUR],Price USD,Price denmark [DKK],Price Denmark [DKK],Option 1 Name,Option 1 Value,Option 2 Name,Option 2 Value,Image 1 Url,Sales Channel 1 Name,Sales Channel 2 Name,Sales Channel 1 Id,Sales Channel 2 Id +,test-product-product-1,Test product,,"Hopper Stripes Bedding, available as duvet cover, pillow sham and sheet.\n100% organic cotton, soft and crisp to the touch. Made in Portugal.",draft,,,,,,,,,,Test collection 1,test-collection1,test-type-1,123_1,TRUE,,,Test variant,test-sku-1,test-barcode-1,10,FALSE,TRUE,,,,,,,,,1.00,1.10,1.30,,test-option-1,option 1 value red,test-option-2,option 2 value 1,test-image.png,Import Sales Channel 1,Import Sales Channel 2,, \ No newline at end of file diff --git a/integration-tests/api/__tests__/batch-jobs/product/product-import.csv b/integration-tests/api/__tests__/batch-jobs/product/product-import.csv index ebc8d3d61f..069701653b 100644 --- a/integration-tests/api/__tests__/batch-jobs/product/product-import.csv +++ b/integration-tests/api/__tests__/batch-jobs/product/product-import.csv @@ -1,4 +1,5 @@ -Product id,Product Handle,Product Title,Product Subtitle,Product Description,Product Status,Product Thumbnail,Product Weight,Product Length,Product Width,Product Height,Product HS Code,Product Origin Country,Product MID Code,Product Material,Product Collection Title,Product Collection Handle,Product Type,Product Tags,Product Discountable,Product External ID,Product Profile Name,Product Profile Type,Variant id,Variant Title,Variant SKU,Variant Barcode,Variant Inventory Quantity,Variant Allow backorder,Variant Manage inventory,Variant Weight,Variant Length,Variant Width,Variant Height,Variant HS Code,Variant Origin Country,Variant MID Code,Variant Material,Price ImportLand [EUR],Price USD,Price denmark [DKK],Price Denmark [DKK],Option 1 Name,Option 1 Value,Option 2 Name,Option 2 Value,Image 1 Url -O6S1YQ6mKm,test-product-product-1,Test product,,"Hopper Stripes Bedding, available as duvet cover, pillow sham and sheet.\n100% organic cotton, soft and crisp to the touch. Made in Portugal.",draft,,,,,,,,,,Test collection 1,test-collection1,test-type-1,123_1,TRUE,,profile_1,profile_type_1,,Test variant,test-sku-1,test-barcode-1,10,FALSE,TRUE,,,,,,,,,1.00,1.10,1.30,,test-option-1,option 1 value red,test-option-2,option 2 value 1,test-image.png -5VxiEkmnPV,test-product-product-2,Test product,,test-product-description,draft,,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,profile_2,profile_type_2,,Test variant,test-sku-2,test-barcode-2,10,FALSE,TRUE,,,,,,,,,,,,1.10,test-option,Option 1 value 1,,,test-image.png -5VxiEkmnPV,test-product-product-2,Test product,,test-product-description,draft,,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,profile_2,profile_type_2,,Test variant,test-sku-3,test-barcode-3,10,FALSE,TRUE,,,,,,,,,,1.20,,,test-option,Option 1 Value blue,,,test-image.png +Product id,Product Handle,Product Title,Product Subtitle,Product Description,Product Status,Product Thumbnail,Product Weight,Product Length,Product Width,Product Height,Product HS Code,Product Origin Country,Product MID Code,Product Material,Product Collection Title,Product Collection Handle,Product Type,Product Tags,Product Discountable,Product External ID,Variant id,Variant Title,Variant SKU,Variant Barcode,Variant Inventory Quantity,Variant Allow backorder,Variant Manage inventory,Variant Weight,Variant Length,Variant Width,Variant Height,Variant HS Code,Variant Origin Country,Variant MID Code,Variant Material,Price ImportLand [EUR],Price USD,Price denmark [DKK],Price Denmark [DKK],Option 1 Name,Option 1 Value,Option 2 Name,Option 2 Value,Image 1 Url +,test-product-product-1,Test product,,"Hopper Stripes Bedding, available as duvet cover, pillow sham and sheet.\n100% organic cotton, soft and crisp to the touch. Made in Portugal.",draft,,,,,,,,,,Test collection 1,test-collection1,test-type-1,123_1,TRUE,,,Test variant,test-sku-1,test-barcode-1,10,FALSE,TRUE,,,,,,,,,1.00,1.10,1.30,,test-option-1,option 1 value red,test-option-2,option 2 value 1,test-image.png +existing-product-id,test-product-product-2,Test product,,test-product-description,draft,test-image.png,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,,Test variant,test-sku-2,test-barcode-2,10,FALSE,TRUE,,,,,,,,,,,,1.10,Size,Small,,,test-image.png +existing-product-id,test-product-product-2,Test product,,test-product-description,draft,,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,,Test variant,test-sku-3,test-barcode-3,10,FALSE,TRUE,,,,,,,,,,1.20,,,Size,Medium,,,test-image.png +existing-product-id,test-product-product-2,Test product,,test-product-description,draft,,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,existing-variant-id,Test variant changed,test-sku-4,test-barcode-4,10,FALSE,TRUE,,,,,,,,,,,,,Size,Large,,,test-image.png \ No newline at end of file diff --git a/packages/medusa/src/strategies/__tests__/batch-jobs/product/import.ts b/packages/medusa/src/strategies/__tests__/batch-jobs/product/import.ts index f13463ad50..39af7bcff6 100644 --- a/packages/medusa/src/strategies/__tests__/batch-jobs/product/import.ts +++ b/packages/medusa/src/strategies/__tests__/batch-jobs/product/import.ts @@ -1,12 +1,10 @@ -import { Readable, PassThrough } from "stream" +import { PassThrough, Readable } from "stream" import { EntityManager } from "typeorm" import { FileService } from "medusa-interfaces" import { IdMap, MockManager } from "medusa-test-utils" import { User } from "../../../../models" -import { BatchJobStatus } from "../../../../types/batch-job" -import ProductImportStrategy from "../../../batch-jobs/product/import" import { BatchJobService, ProductService, @@ -14,8 +12,10 @@ import { RegionService, ShippingProfileService, } from "../../../../services" -import { InjectedProps } from "../../../batch-jobs/product/types" +import { BatchJobStatus } from "../../../../types/batch-job" import { FlagRouter } from "../../../../utils/flag-router" +import ProductImportStrategy from "../../../batch-jobs/product/import" +import { InjectedProps } from "../../../batch-jobs/product/types" let fakeJob = { id: IdMap.getId("product-import-job"), @@ -32,10 +32,10 @@ let fakeJob = { } async function* generateCSVDataForStream() { - yield "Product id,Product Handle,Product Title,Product Subtitle,Product Description,Product Status,Product Thumbnail,Product Weight,Product Length,Product Width,Product Height,Product HS Code,Product Origin Country,Product MID Code,Product Material,Product Collection Title,Product Collection Handle,Product Type,Product Tags,Product Discountable,Product External ID,Product Profile Name,Product Profile Type,Variant id,Variant Title,Variant SKU,Variant Barcode,Variant Inventory Quantity,Variant Allow backorder,Variant Manage inventory,Variant Weight,Variant Length,Variant Width,Variant Height,Variant HS Code,Variant Origin Country,Variant MID Code,Variant Material,Price france [USD],Price USD,Price denmark [DKK],Price Denmark [DKK],Option 1 Name,Option 1 Value,Option 2 Name,Option 2 Value,Image 1 Url\n" - yield "O6S1YQ6mKm,test-product-product-1,Test product,,test-product-description-1,draft,,,,,,,,,,Test collection 1,test-collection1,test-type-1,123_1,TRUE,,profile_1,profile_type_1,SebniWTDeC,Test variant,test-sku-1,test-barcode-1,10,FALSE,TRUE,,,,,,,,,100,110,130,,test-option-1,option 1 value red,test-option-2,option 2 value 1,test-image.png\n" - yield "5VxiEkmnPV,test-product-product-2,Test product,,test-product-description,draft,,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,profile_2,profile_type_2,CaBp7amx3r,Test variant,test-sku-2,test-barcode-2,10,FALSE,TRUE,,,,,,,,,,,,110,test-option,Option 1 value 1,,,test-image.png\n" - yield "5VxiEkmnPV,test-product-product-2,Test product,,test-product-description,draft,,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,profile_2,profile_type_2,3SS1MHGDEJ,Test variant,test-sku-3,test-barcode-3,10,FALSE,TRUE,,,,,,,,,,120,,,test-option,Option 1 Value blue,,,test-image.png\n" + yield "Product id,Product Handle,Product Title,Product Subtitle,Product Description,Product Status,Product Thumbnail,Product Weight,Product Length,Product Width,Product Height,Product HS Code,Product Origin Country,Product MID Code,Product Material,Product Collection Title,Product Collection Handle,Product Type,Product Tags,Product Discountable,Product External ID,Variant id,Variant Title,Variant SKU,Variant Barcode,Variant Inventory Quantity,Variant Allow backorder,Variant Manage inventory,Variant Weight,Variant Length,Variant Width,Variant Height,Variant HS Code,Variant Origin Country,Variant MID Code,Variant Material,Price france [USD],Price USD,Price denmark [DKK],Price Denmark [DKK],Option 1 Name,Option 1 Value,Option 2 Name,Option 2 Value,Image 1 Url\n" + yield ",test-product-product-1,Test product,,test-product-description-1,draft,,,,,,,,,,Test collection 1,test-collection1,test-type-1,123_1,TRUE,,SebniWTDeC,Test variant,test-sku-1,test-barcode-1,10,FALSE,TRUE,,,,,,,,,100,110,130,,test-option-1,option 1 value red,test-option-2,option 2 value 1,test-image.png\n" + yield "5VxiEkmnPV,test-product-product-2,Test product,,test-product-description,draft,,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,,Test variant,test-sku-2,test-barcode-2,10,FALSE,TRUE,,,,,,,,,,,,110,test-option,Option 1 value 1,,,test-image.png\n" + yield "5VxiEkmnPV,test-product-product-2,Test product,,test-product-description,draft,,,,,,,,,,Test collection,test-collection2,test-type,123,TRUE,,3SS1MHGDEJ,Test variant,test-sku-3,test-barcode-3,10,FALSE,TRUE,,,,,,,,,,120,,,test-option,Option 1 Value blue,,,test-image.png\n" } /* ******************** SERVICES MOCK ******************** */ @@ -159,7 +159,7 @@ describe("Product import strategy", () => { expect(getImportInstructionsSpy).toBeCalledTimes(1) - expect(fileServiceMock.getUploadStreamDescriptor).toBeCalledTimes(2) + expect(fileServiceMock.getUploadStreamDescriptor).toBeCalledTimes(4) expect(fileServiceMock.getUploadStreamDescriptor).toHaveBeenNthCalledWith( 1, @@ -170,6 +170,20 @@ describe("Product import strategy", () => { ) expect(fileServiceMock.getUploadStreamDescriptor).toHaveBeenNthCalledWith( 2, + { + ext: "json", + name: `imports/products/ops/${fakeJob.id}-VARIANT_CREATE`, + } + ) + expect(fileServiceMock.getUploadStreamDescriptor).toHaveBeenNthCalledWith( + 3, + { + ext: "json", + name: `imports/products/ops/${fakeJob.id}-PRODUCT_UPDATE`, + } + ) + expect(fileServiceMock.getUploadStreamDescriptor).toHaveBeenNthCalledWith( + 4, { ext: "json", name: `imports/products/ops/${fakeJob.id}-VARIANT_UPDATE`, // because row data has variant.id diff --git a/packages/medusa/src/strategies/batch-jobs/product/import.ts b/packages/medusa/src/strategies/batch-jobs/product/import.ts index e85f351464..99f8a2ff2d 100644 --- a/packages/medusa/src/strategies/batch-jobs/product/import.ts +++ b/packages/medusa/src/strategies/batch-jobs/product/import.ts @@ -26,7 +26,7 @@ import { TBuiltProductImportLine, TParsedProductImportRowData, } from "./types" -import { BatchJob, SalesChannel } from "../../../models" +import { BatchJob, Product, SalesChannel } from "../../../models" import { FlagRouter } from "../../../utils/flag-router" import { transformProductData, transformVariantData } from "./utils" import SalesChannelFeatureFlag from "../../../loaders/feature-flags/sales-channels" @@ -163,7 +163,7 @@ class ProductImportStrategy extends AbstractBatchJobStrategy { // save only first occurrence if (!seenProducts[row["product.handle"] as string]) { row["product.profile_id"] = shippingProfile!.id - if (row["product.product.id"]) { + if (row["product.id"]) { productsUpdate.push(row) } else { productsCreate.push(row) @@ -306,7 +306,6 @@ class ProductImportStrategy extends AbstractBatchJobStrategy { await this.updateProducts(batchJob) await this.createVariants(batchJob) await this.updateVariants(batchJob) - await this.finalize(batchJob) }) } @@ -443,6 +442,8 @@ class ProductImportStrategy extends AbstractBatchJobStrategy { ) } + delete productData.options // for now not supported in the update method + await productServiceTx.update( productOp["product.id"] as string, productData @@ -489,7 +490,7 @@ class ProductImportStrategy extends AbstractBatchJobStrategy { product!.options.find( (createdProductOption) => createdProductOption.title === variantOption.title - )!.id + )?.id ) || [] variant.options = @@ -498,6 +499,9 @@ class ProductImportStrategy extends AbstractBatchJobStrategy { option_id: optionIds[index], })) || [] + delete variant.id + delete variant.product + await this.productVariantService_ .withTransaction(transactionManager) .create(product!, variant as unknown as CreateProductVariantInput) @@ -700,7 +704,6 @@ class ProductImportStrategy extends AbstractBatchJobStrategy { private async updateProgress(batchJobId: string): Promise { const newCount = (this.processedCounter[batchJobId] || 0) + 1 this.processedCounter[batchJobId] = newCount - if (newCount % BATCH_SIZE !== 0) { return } @@ -769,9 +772,7 @@ const CSVSchema: ProductImportCsvSchema = { // { name: "Product Discountable", mapTo: "product.discountable" }, { name: "Product External ID", mapTo: "product.external_id" }, - // PRODUCT-SHIPPING_PROFILE - { name: "Product Profile Name", mapTo: "product.profile.name" }, - { name: "Product Profile Type", mapTo: "product.profile.type" }, + // VARIANTS { name: "Variant id", diff --git a/packages/medusa/src/strategies/batch-jobs/product/types.ts b/packages/medusa/src/strategies/batch-jobs/product/types.ts index f72fa597d9..1fa30133e1 100644 --- a/packages/medusa/src/strategies/batch-jobs/product/types.ts +++ b/packages/medusa/src/strategies/batch-jobs/product/types.ts @@ -42,7 +42,7 @@ export type InjectedProps = { */ export type TParsedProductImportRowData = Record< string, - string | number | (string | number | object)[] + string | number | object | (string | number | object)[] > /** diff --git a/packages/medusa/src/strategies/batch-jobs/product/utils.ts b/packages/medusa/src/strategies/batch-jobs/product/utils.ts index 5e4f7459fc..0df977a399 100644 --- a/packages/medusa/src/strategies/batch-jobs/product/utils.ts +++ b/packages/medusa/src/strategies/batch-jobs/product/utils.ts @@ -1,3 +1,5 @@ +import set from "lodash/set" + import { TParsedProductImportRowData } from "./types" import { csvRevertCellContentFormatter } from "../../../utils" @@ -37,7 +39,7 @@ export function transformProductData( Object.keys(productData).forEach((k) => { const key = k.split("product.")[1] - ret[key] = productData[k] + set(ret, key, productData[k]) }) return ret @@ -54,12 +56,12 @@ export function transformVariantData( Object.keys(productData).forEach((k) => { const key = k.split("variant.")[1] - ret[key] = productData[k] + set(ret, key, productData[k]) }) // include product handle to keep track of associated product ret["product.handle"] = data["product.handle"] - ret["product.options"] = data["product.options"] + set(ret, "product.options", data["product.options"]) return ret }