diff --git a/integration-tests/http/__tests__/cart/store/cart.spec.ts b/integration-tests/http/__tests__/cart/store/cart.spec.ts index c1edc4c5c0..2ad8995c56 100644 --- a/integration-tests/http/__tests__/cart/store/cart.spec.ts +++ b/integration-tests/http/__tests__/cart/store/cart.spec.ts @@ -43,7 +43,8 @@ medusaIntegrationTestRunner({ salesChannel, cart, customer, - promotion + promotion, + shippingProfile beforeAll(async () => { appContainer = getContainer() @@ -68,6 +69,14 @@ medusaIntegrationTestRunner({ }, } + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "default", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + await setupTaxStructure(appContainer.resolve(Modules.TAX)) region = ( @@ -87,7 +96,7 @@ medusaIntegrationTestRunner({ ).data.region product = ( - await api.post("/admin/products", medusaTshirtProduct, adminHeaders) + await api.post("/admin/products", { ...medusaTshirtProduct, shipping_profile_id: shippingProfile.id }, adminHeaders) ).data.product salesChannel = ( diff --git a/integration-tests/http/__tests__/claims/claims.spec.ts b/integration-tests/http/__tests__/claims/claims.spec.ts index eaf4cb1c8d..5227da265f 100644 --- a/integration-tests/http/__tests__/claims/claims.spec.ts +++ b/integration-tests/http/__tests__/claims/claims.spec.ts @@ -34,6 +34,17 @@ medusaIntegrationTestRunner({ const container = getContainer() await createAdminUser(dbConnection, adminHeaders, container) + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { + name: "Test", + type: "default", + }, + adminHeaders + ) + ).data.shipping_profile + const region = ( await api.post( "/admin/regions", @@ -72,6 +83,7 @@ medusaIntegrationTestRunner({ { title: "Test product", options: [{ title: "size", values: ["large", "small"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Test variant", @@ -96,6 +108,7 @@ medusaIntegrationTestRunner({ { title: "Extra product", options: [{ title: "size", values: ["large", "small"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "my variant", @@ -213,17 +226,6 @@ medusaIntegrationTestRunner({ customer_id: customer.id, }) - shippingProfile = ( - await api.post( - `/admin/shipping-profiles`, - { - name: "Test", - type: "default", - }, - adminHeaders - ) - ).data.shipping_profile - location = ( await api.post( `/admin/stock-locations`, diff --git a/integration-tests/http/__tests__/collection/admin/colllection.spec.ts b/integration-tests/http/__tests__/collection/admin/colllection.spec.ts index 85d32a55b6..0c3261fb94 100644 --- a/integration-tests/http/__tests__/collection/admin/colllection.spec.ts +++ b/integration-tests/http/__tests__/collection/admin/colllection.spec.ts @@ -16,6 +16,8 @@ medusaIntegrationTestRunner({ let baseProduct let baseProduct1 + let shippingProfile + beforeEach(async () => { const container = getContainer() await createAdminUser(dbConnection, adminHeaders, container) @@ -44,12 +46,21 @@ medusaIntegrationTestRunner({ ) ).data.collection + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + baseProduct = ( await api.post( "/admin/products", { title: "test-product", options: [{ title: "size", values: ["x", "l"] }], + shipping_profile_id: shippingProfile.id, }, adminHeaders ) @@ -61,6 +72,7 @@ medusaIntegrationTestRunner({ { title: "test-product1", options: [{ title: "size", values: ["x", "l"] }], + shipping_profile_id: shippingProfile.id, }, adminHeaders ) diff --git a/integration-tests/http/__tests__/exchanges/exchanges.spec.ts b/integration-tests/http/__tests__/exchanges/exchanges.spec.ts index 50ab7f65d9..afd731faef 100644 --- a/integration-tests/http/__tests__/exchanges/exchanges.spec.ts +++ b/integration-tests/http/__tests__/exchanges/exchanges.spec.ts @@ -41,6 +41,17 @@ medusaIntegrationTestRunner({ ) ).data.region + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { + name: "Test", + type: "default", + }, + adminHeaders + ) + ).data.shipping_profile + const customer = ( await api.post( "/admin/customers", @@ -67,6 +78,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Test product", + shipping_profile_id: shippingProfile.id, options: [{ title: "size", values: ["large", "small"] }], variants: [ { @@ -91,6 +103,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Extra product", + shipping_profile_id: shippingProfile.id, options: [{ title: "size", values: ["large", "small"] }], variants: [ { @@ -203,17 +216,6 @@ medusaIntegrationTestRunner({ customer_id: customer.id, }) - shippingProfile = ( - await api.post( - `/admin/shipping-profiles`, - { - name: "Test", - type: "default", - }, - adminHeaders - ) - ).data.shipping_profile - location = ( await api.post( `/admin/stock-locations`, diff --git a/integration-tests/http/__tests__/fixtures/order.ts b/integration-tests/http/__tests__/fixtures/order.ts index 53070fe023..7b4c7ca31e 100644 --- a/integration-tests/http/__tests__/fixtures/order.ts +++ b/integration-tests/http/__tests__/fixtures/order.ts @@ -1,6 +1,7 @@ import { AdminInventoryItem, AdminProduct, + AdminShippingProfile, AdminStockLocation, MedusaContainer, } from "@medusajs/types" @@ -18,6 +19,8 @@ export async function createOrderSeeder({ additionalProducts, stockChannelOverride, inventoryItemOverride, + shippingProfileOverride, + withoutShipping, }: { api: any container: MedusaContainer @@ -26,6 +29,8 @@ export async function createOrderSeeder({ stockChannelOverride?: AdminStockLocation additionalProducts?: { variant_id: string; quantity: number }[] inventoryItemOverride?: AdminInventoryItem + shippingProfileOverride?: AdminShippingProfile + withoutShipping?: boolean }) { const publishableKey = await generatePublishableKey(container) @@ -86,13 +91,15 @@ export async function createOrderSeeder({ adminHeaders ) - const shippingProfile = ( - await api.post( - `/admin/shipping-profiles`, - { name: `test-${stockLocation.id}`, type: "default" }, - adminHeaders - ) - ).data.shipping_profile + const shippingProfile = + shippingProfileOverride ?? + ( + await api.post( + `/admin/shipping-profiles`, + { name: `test-${stockLocation.id}`, type: "default" }, + adminHeaders + ) + ).data.shipping_profile const product = productOverride ?? @@ -101,6 +108,7 @@ export async function createOrderSeeder({ "/admin/products", { title: `Test fixture ${shippingProfile.id}`, + shipping_profile_id: shippingProfile.id, options: [ { title: "size", values: ["large", "small"] }, { title: "color", values: ["green"] }, @@ -217,6 +225,14 @@ export async function createOrderSeeder({ ) ).data.cart + if (!withoutShipping) { + await api.post( + `/store/carts/${cart.id}/shipping-methods`, + { option_id: shippingOption.id }, + storeHeaders + ) + } + const paymentCollection = ( await api.post( `/store/payment-collections`, diff --git a/integration-tests/http/__tests__/inventory/admin/inventory.spec.ts b/integration-tests/http/__tests__/inventory/admin/inventory.spec.ts index 9a62749b3c..aa082040e9 100644 --- a/integration-tests/http/__tests__/inventory/admin/inventory.spec.ts +++ b/integration-tests/http/__tests__/inventory/admin/inventory.spec.ts @@ -13,9 +13,19 @@ medusaIntegrationTestRunner({ let stockLocation1 let stockLocation2 let stockLocation3 + + let shippingProfile beforeEach(async () => { await createAdminUser(dbConnection, adminHeaders, getContainer()) + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + stockLocation1 = ( await api.post(`/admin/stock-locations`, { name: "loc1" }, adminHeaders) ).data.stock_location @@ -990,6 +1000,7 @@ medusaIntegrationTestRunner({ { title: "product 1", options: [{ title: "size", values: ["large"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "variant 1", diff --git a/integration-tests/http/__tests__/order-edits/order-edits.spec.ts b/integration-tests/http/__tests__/order-edits/order-edits.spec.ts index 80f4fa4d7b..ad21bbfe5f 100644 --- a/integration-tests/http/__tests__/order-edits/order-edits.spec.ts +++ b/integration-tests/http/__tests__/order-edits/order-edits.spec.ts @@ -85,12 +85,24 @@ medusaIntegrationTestRunner({ ) ).data.sales_channel + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { + name: "Test", + type: "default", + }, + adminHeaders + ) + ).data.shipping_profile + const product = ( await api.post( "/admin/products", { title: "Test product", options: [{ title: "size", values: ["large", "small"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Test variant", @@ -115,6 +127,7 @@ medusaIntegrationTestRunner({ { title: "Extra product", options: [{ title: "size", values: ["large", "small"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "my variant", @@ -174,17 +187,6 @@ medusaIntegrationTestRunner({ customer_id: customer.id, }) - shippingProfile = ( - await api.post( - `/admin/shipping-profiles`, - { - name: "Test", - type: "default", - }, - adminHeaders - ) - ).data.shipping_profile - location = ( await api.post( `/admin/stock-locations`, diff --git a/integration-tests/http/__tests__/order/admin/order.spec.ts b/integration-tests/http/__tests__/order/admin/order.spec.ts index 0e548219c0..1ffb6e02ca 100644 --- a/integration-tests/http/__tests__/order/admin/order.spec.ts +++ b/integration-tests/http/__tests__/order/admin/order.spec.ts @@ -11,13 +11,21 @@ jest.setTimeout(300000) medusaIntegrationTestRunner({ testSuite: ({ dbConnection, getContainer, api }) => { - let order, seeder, inventoryItemOverride3, productOverride3 + let order, seeder, inventoryItemOverride3, productOverride3, shippingProfile beforeEach(async () => { const container = getContainer() await setupTaxStructure(container.resolve(ModuleRegistrationName.TAX)) await createAdminUser(dbConnection, adminHeaders, container) + + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile }) describe("POST /orders/:id", () => { @@ -345,9 +353,19 @@ medusaIntegrationTestRunner({ describe("POST /orders/:id/cancel", () => { beforeEach(async () => { + const inventoryItemOverride = ( + await api.post( + `/admin/inventory-items`, + { sku: "test-variant", requires_shipping: false }, + adminHeaders + ) + ).data.inventory_item + seeder = await createOrderSeeder({ api, container: getContainer(), + inventoryItemOverride, + withoutShipping: true, }) order = seeder.order @@ -536,8 +554,12 @@ medusaIntegrationTestRunner({ }) describe("POST /orders/:id/fulfillments", () => { + let productOverride4WithOverrideShippingProfile, + shippingProfileOverride, + stockChannelOverride + beforeEach(async () => { - const stockChannelOverride = ( + stockChannelOverride = ( await api.post( `/admin/stock-locations`, { name: "test location" }, @@ -558,6 +580,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: `Test fixture`, + shipping_profile_id: shippingProfile.id, options: [ { title: "size", values: ["large", "small"] }, { title: "color", values: ["green"] }, @@ -605,6 +628,14 @@ medusaIntegrationTestRunner({ ) ).data.inventory_item + const inventoryItemOverride4RequiresShipping = ( + await api.post( + `/admin/inventory-items`, + { sku: "test-variant-4", requires_shipping: true }, + adminHeaders + ) + ).data.inventory_item + await api.post( `/admin/inventory-items/${inventoryItemOverride2.id}/location-levels`, { @@ -623,11 +654,21 @@ medusaIntegrationTestRunner({ adminHeaders ) + await api.post( + `/admin/inventory-items/${inventoryItemOverride4RequiresShipping.id}/location-levels`, + { + location_id: stockChannelOverride.id, + stocked_quantity: 10, + }, + adminHeaders + ) + const productOverride2 = ( await api.post( "/admin/products", { title: `Test fixture 2`, + shipping_profile_id: shippingProfile.id, options: [ { title: "size", values: ["large", "small"] }, { title: "color", values: ["green"] }, @@ -664,6 +705,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: `Test fixture 3`, + shipping_profile_id: shippingProfile.id, options: [ { title: "size", values: ["large", "small"] }, { title: "color", values: ["green"] }, @@ -695,6 +737,52 @@ medusaIntegrationTestRunner({ ) ).data.product + shippingProfileOverride = ( + await api.post( + `/admin/shipping-profiles`, + { name: `test-${stockChannelOverride.id}`, type: "default" }, + adminHeaders + ) + ).data.shipping_profile + + productOverride4WithOverrideShippingProfile = ( + await api.post( + "/admin/products", + { + title: `Test fixture 4`, + shipping_profile_id: shippingProfileOverride.id, + options: [ + { title: "size", values: ["large", "small"] }, + { title: "color", values: ["green"] }, + ], + variants: [ + { + title: "Test variant 4", + sku: "test-variant-4", + inventory_items: [ + { + inventory_item_id: + inventoryItemOverride4RequiresShipping.id, + required_quantity: 1, + }, + ], + prices: [ + { + currency_code: "usd", + amount: 100, + }, + ], + options: { + size: "small", + color: "green", + }, + }, + ], + }, + adminHeaders + ) + ).data.product + seeder = await createOrderSeeder({ api, container: getContainer(), @@ -702,9 +790,15 @@ medusaIntegrationTestRunner({ additionalProducts: [ { variant_id: productOverride2.variants[0].id, quantity: 1 }, { variant_id: productOverride3.variants[0].id, quantity: 3 }, + { + variant_id: + productOverride4WithOverrideShippingProfile.variants[0].id, + quantity: 1, + }, ], stockChannelOverride, inventoryItemOverride, + shippingProfileOverride: shippingProfile, }) order = seeder.order order = (await api.get(`/admin/orders/${order.id}`, adminHeaders)).data @@ -827,6 +921,30 @@ medusaIntegrationTestRunner({ ) }) + it("should throw if shipping profile of the product doesn't match the shipping profile of the shipping option", async () => { + const orderItemId = order.items.find( + (i) => + i.variant_id === + productOverride4WithOverrideShippingProfile.variants[0].id + ).id + + const res = await api + .post( + `/admin/orders/${order.id}/fulfillments`, + { + location_id: stockChannelOverride.id, + items: [{ id: orderItemId, quantity: 1 }], + }, + adminHeaders + ) + .catch((e) => e) + + expect(res.response.status).toBe(400) + expect(res.response.data.message).toBe( + `Shipping profile ${seeder.shippingProfile.id} does not match the shipping profile of the order item ${orderItemId}` + ) + }) + it("should only create fulfillments grouped by shipping requirement", async () => { const { response: { data }, diff --git a/integration-tests/http/__tests__/order/admin/rma-flows.spec.ts b/integration-tests/http/__tests__/order/admin/rma-flows.spec.ts index 58354afa7b..f2ac856311 100644 --- a/integration-tests/http/__tests__/order/admin/rma-flows.spec.ts +++ b/integration-tests/http/__tests__/order/admin/rma-flows.spec.ts @@ -24,7 +24,21 @@ medusaIntegrationTestRunner({ await setupTaxStructure(container.resolve(Modules.TAX)) await createAdminUser(dbConnection, adminHeaders, container) - const seeders = await createOrderSeeder({ api, container }) + + const inventoryItemOverride = ( + await api.post( + `/admin/inventory-items`, + { sku: "test-variant", requires_shipping: false }, + adminHeaders + ) + ).data.inventory_item + + const seeders = await createOrderSeeder({ + api, + container, + inventoryItemOverride, + withoutShipping: true, + }) order = seeders.order shippingProfile = ( diff --git a/integration-tests/http/__tests__/payment-collection/admin/payment-sessions.spec.ts b/integration-tests/http/__tests__/payment-collection/admin/payment-sessions.spec.ts index faa94b8479..2e2b083dec 100644 --- a/integration-tests/http/__tests__/payment-collection/admin/payment-sessions.spec.ts +++ b/integration-tests/http/__tests__/payment-collection/admin/payment-sessions.spec.ts @@ -24,6 +24,7 @@ medusaIntegrationTestRunner({ let region let product let cart + let shippingProfile beforeEach(async () => { region = ( @@ -34,12 +35,21 @@ medusaIntegrationTestRunner({ ) ).data.region + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + product = ( await api.post( "/admin/products", getProductFixture({ title: "test", status: "published", + shipping_profile_id: shippingProfile.id, variants: [ { title: "Test variant", diff --git a/integration-tests/http/__tests__/payment/admin/payment.spec.ts b/integration-tests/http/__tests__/payment/admin/payment.spec.ts index 3b6ff5741d..1c27bcb5c7 100644 --- a/integration-tests/http/__tests__/payment/admin/payment.spec.ts +++ b/integration-tests/http/__tests__/payment/admin/payment.spec.ts @@ -38,7 +38,22 @@ medusaIntegrationTestRunner({ beforeEach(async () => { container = getContainer() await createAdminUser(dbConnection, adminHeaders, container) - const seeders = await createOrderSeeder({ api, container }) + + const inventoryItemOverride = ( + await api.post( + `/admin/inventory-items`, + { sku: "test-variant", requires_shipping: false }, + adminHeaders + ) + ).data.inventory_item + + const seeders = await createOrderSeeder({ + api, + container, + inventoryItemOverride, + withoutShipping: true, + }) + order = seeders.order await api.post( diff --git a/integration-tests/http/__tests__/price-list/admin/price-list.spec.ts b/integration-tests/http/__tests__/price-list/admin/price-list.spec.ts index 5dbfb2c47f..06b9c3e2ed 100644 --- a/integration-tests/http/__tests__/price-list/admin/price-list.spec.ts +++ b/integration-tests/http/__tests__/price-list/admin/price-list.spec.ts @@ -18,6 +18,7 @@ medusaIntegrationTestRunner({ let region1 let product1 let customerGroup1 + let shippingProfile beforeEach(async () => { const container = getContainer() @@ -34,10 +35,21 @@ medusaIntegrationTestRunner({ ) ).data.region + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + product1 = ( await api.post( "/admin/products", - getProductFixture({ title: "Test product" }), + getProductFixture({ + title: "Test product", + shipping_profile_id: shippingProfile.id, + }), adminHeaders ) ).data.product diff --git a/integration-tests/http/__tests__/product-category/admin/product-category.spec.ts b/integration-tests/http/__tests__/product-category/admin/product-category.spec.ts index 9e8634ca03..25b5ead48b 100644 --- a/integration-tests/http/__tests__/product-category/admin/product-category.spec.ts +++ b/integration-tests/http/__tests__/product-category/admin/product-category.spec.ts @@ -18,9 +18,19 @@ medusaIntegrationTestRunner({ let productCategoryChild2 let productCategoryChild3 + let shippingProfile + beforeEach(async () => { const appContainer = getContainer() await createAdminUser(dbConnection, adminHeaders, appContainer) + + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "default", type: "default" }, + adminHeaders + ) + ).data.shipping_profile }) describe("GET /admin/product-categories/:id", () => { @@ -1349,6 +1359,7 @@ medusaIntegrationTestRunner({ title: "product 1", options: [{ title: "size", values: ["x", "l"] }], categories: [{ id: productCategory.id }], + shipping_profile_id: shippingProfile.id, }, adminHeaders ) @@ -1358,6 +1369,7 @@ medusaIntegrationTestRunner({ { title: "product 2", options: [{ title: "color", values: ["r", "g"] }], + shipping_profile_id: shippingProfile.id, }, adminHeaders ) diff --git a/integration-tests/http/__tests__/product/admin/__fixtures__/exported-products-comma.csv b/integration-tests/http/__tests__/product/admin/__fixtures__/exported-products-comma.csv index 2c55514fd1..24d233e30c 100644 --- a/integration-tests/http/__tests__/product/admin/__fixtures__/exported-products-comma.csv +++ b/integration-tests/http/__tests__/product/admin/__fixtures__/exported-products-comma.csv @@ -1,6 +1,6 @@ -Product Id,Product Handle,Product Title,Product Status,Product Description,Product Subtitle,Product External Id,Product Thumbnail,Product Collection Id,Product Type Id,Product Created At,Product Deleted At,Product Discountable,Product Height,Product Hs Code,Product Image 1,Product Image 2,Product Is Giftcard,Product Length,Product Material,Product Mid Code,Product Origin Country,Product Tag 1,Product Tag 2,Product Updated At,Product Weight,Product Width,Variant Id,Variant Title,Variant Sku,Variant Upc,Variant Ean,Variant Hs Code,Variant Mid Code,Variant Manage Inventory,Variant Allow Backorder,Variant Barcode,Variant Created At,Variant Deleted At,Variant Height,Variant Length,Variant Material,Variant Metadata,Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value,Variant Origin Country,Variant Price DKK,Variant Price EUR,Variant Price USD,Variant Product Id,Variant Updated At,Variant Variant Rank,Variant Weight,Variant Width +Product Id,Product Handle,Product Title,Product Status,Product Description,Product Subtitle,Product External Id,Product Thumbnail,Product Collection Id,Product Type Id,Product Created At,Product Deleted At,Product Discountable,Product Height,Product Hs Code,Product Image 1,Product Image 2,Product Is Giftcard,Product Length,Product Material,Product Mid Code,Product Origin Country,Product Tag 1,Product Tag 2,Product Updated At,Product Weight,Product Width,Variant Id,Variant Title,Variant Sku,Variant Upc,Variant Ean,Variant Hs Code,Variant Mid Code,Variant Manage Inventory,Variant Allow Backorder,Variant Barcode,Variant Created At,Variant Deleted At,Variant Height,Variant Length,Variant Material,Variant Metadata,Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value,Variant Origin Country,Variant Price DKK,Variant Price EUR,Variant Price USD,Variant Product Id,Variant Updated At,Variant Variant Rank,Variant Weight,Variant Width,Shipping Profile Id prod_01J44RRJZ3M5F63NY82434RNM5,base-product,Base product,draft,"test-product-description -test line 2",,,test-image.png,pcol_01J44RRJXM6AM3YS5PMJDMH3YF,ptyp_01J44RRJYAFEBZ2EY1KE1JM3XD,2024-07-31T16:07:55.102Z,,true,,,test-image.png,test-image-2.png,false,,,,,123,456,2024-07-31T16:07:55.102Z,,,variant_01J44RRJZW1T9KQB6XG7Q6K61F,Test variant,,,,,,true,false,,2024-07-31T16:07:55.133Z,,,,,,size,large,color,green,,30,45,100,prod_01J44RRJZ3M5F63NY82434RNM5,2024-07-31T16:07:55.133Z,0,, +test line 2",,,test-image.png,pcol_01J44RRJXM6AM3YS5PMJDMH3YF,ptyp_01J44RRJYAFEBZ2EY1KE1JM3XD,2024-07-31T16:07:55.102Z,,true,,,test-image.png,test-image-2.png,false,,,,,123,456,2024-07-31T16:07:55.102Z,,,variant_01J44RRJZW1T9KQB6XG7Q6K61F,Test variant,,,,,,true,false,,2024-07-31T16:07:55.133Z,,,,,,size,large,color,green,,30,45,100,prod_01J44RRJZ3M5F63NY82434RNM5,2024-07-31T16:07:55.133Z,0,,,import-shipping-profile prod_01J44RRJZ3M5F63NY82434RNM5,base-product,Base product,draft,"test-product-description -test line 2",,,test-image.png,pcol_01J44RRJXM6AM3YS5PMJDMH3YF,ptyp_01J44RRJYAFEBZ2EY1KE1JM3XD,2024-07-31T16:07:55.102Z,,true,,,test-image.png,test-image-2.png,false,,,,,123,456,2024-07-31T16:07:55.102Z,,,variant_01J44RRJZW5GNQKT1FEDACEESW,Test variant 2,,,,,,true,false,,2024-07-31T16:07:55.133Z,,,,,,size,small,color,green,,50,65,200,prod_01J44RRJZ3M5F63NY82434RNM5,2024-07-31T16:07:55.133Z,0,, -prod_01J44RRK2GJJVMQQXT67TJCV08,proposed-product,Proposed product,proposed,test-product-description,,,test-image.png,,ptyp_01J44RRJYAFEBZ2EY1KE1JM3XD,2024-07-31T16:07:55.213Z,,true,,,test-image.png,test-image-2.png,false,,,,,new-tag,,2024-07-31T16:07:55.213Z,,,variant_01J44RRK2WYHH0RDEK8BBGP7CY,Test variant,,,,,,true,false,,2024-07-31T16:07:55.228Z,,,,,,size,large,color,green,,30,45,100,prod_01J44RRK2GJJVMQQXT67TJCV08,2024-07-31T16:07:55.228Z,0,, \ No newline at end of file +test line 2",,,test-image.png,pcol_01J44RRJXM6AM3YS5PMJDMH3YF,ptyp_01J44RRJYAFEBZ2EY1KE1JM3XD,2024-07-31T16:07:55.102Z,,true,,,test-image.png,test-image-2.png,false,,,,,123,456,2024-07-31T16:07:55.102Z,,,variant_01J44RRJZW5GNQKT1FEDACEESW,Test variant 2,,,,,,true,false,,2024-07-31T16:07:55.133Z,,,,,,size,small,color,green,,50,65,200,prod_01J44RRJZ3M5F63NY82434RNM5,2024-07-31T16:07:55.133Z,0,,,import-shipping-profile +prod_01J44RRK2GJJVMQQXT67TJCV08,proposed-product,Proposed product,proposed,test-product-description,,,test-image.png,,ptyp_01J44RRJYAFEBZ2EY1KE1JM3XD,2024-07-31T16:07:55.213Z,,true,,,test-image.png,test-image-2.png,false,,,,,new-tag,,2024-07-31T16:07:55.213Z,,,variant_01J44RRK2WYHH0RDEK8BBGP7CY,Test variant,,,,,,true,false,,2024-07-31T16:07:55.228Z,,,,,,size,large,color,green,,30,45,100,prod_01J44RRK2GJJVMQQXT67TJCV08,2024-07-31T16:07:55.228Z,0,,,import-shipping-profile \ No newline at end of file diff --git a/integration-tests/http/__tests__/product/admin/__fixtures__/exported-products-semicolon.csv b/integration-tests/http/__tests__/product/admin/__fixtures__/exported-products-semicolon.csv index dd78384423..9b0d8e7b47 100644 --- a/integration-tests/http/__tests__/product/admin/__fixtures__/exported-products-semicolon.csv +++ b/integration-tests/http/__tests__/product/admin/__fixtures__/exported-products-semicolon.csv @@ -1,6 +1,6 @@ -Product Id;Product Handle;Product Title;Product Status;Product Description;Product Subtitle;Product External Id;Product Thumbnail;Product Collection Id;Product Type Id;Product Created At;Product Deleted At;Product Discountable;Product Height;Product Hs Code;Product Image 1;Product Image 2;Product Is Giftcard;Product Length;Product Material;Product Mid Code;Product Origin Country;Product Tag 1;Product Tag 2;Product Updated At;Product Weight;Product Width;Variant Id;Variant Title;Variant Sku;Variant Upc;Variant Ean;Variant Hs Code;Variant Mid Code;Variant Manage Inventory;Variant Allow Backorder;Variant Barcode;Variant Created At;Variant Deleted At;Variant Height;Variant Length;Variant Material;Variant Metadata;Variant Option 1 Name;Variant Option 1 Value;Variant Option 2 Name;Variant Option 2 Value;Variant Origin Country;Variant Price DKK;Variant Price EUR;Variant Price USD;Variant Product Id;Variant Updated At;Variant Variant Rank;Variant Weight;Variant Width +Product Id;Product Handle;Product Title;Product Status;Product Description;Product Subtitle;Product External Id;Product Thumbnail;Product Collection Id;Product Type Id;Product Created At;Product Deleted At;Product Discountable;Product Height;Product Hs Code;Product Image 1;Product Image 2;Product Is Giftcard;Product Length;Product Material;Product Mid Code;Product Origin Country;Product Tag 1;Product Tag 2;Product Updated At;Product Weight;Product Width;Variant Id;Variant Title;Variant Sku;Variant Upc;Variant Ean;Variant Hs Code;Variant Mid Code;Variant Manage Inventory;Variant Allow Backorder;Variant Barcode;Variant Created At;Variant Deleted At;Variant Height;Variant Length;Variant Material;Variant Metadata;Variant Option 1 Name;Variant Option 1 Value;Variant Option 2 Name;Variant Option 2 Value;Variant Origin Country;Variant Price DKK;Variant Price EUR;Variant Price USD;Variant Product Id;Variant Updated At;Variant Variant Rank;Variant Weight;Variant Width;Shipping Profile Id prod_01J44RRJZ3M5F63NY82434RNM5;base-product;Base product;draft;"test-product-description -test line 2";;;test-image.png;pcol_01J44RRJXM6AM3YS5PMJDMH3YF;ptyp_01J44RRJYAFEBZ2EY1KE1JM3XD;2024-07-31T16:07:55.102Z;;true;;;test-image.png;test-image-2.png;false;;;;;123;456;2024-07-31T16:07:55.102Z;;;variant_01J44RRJZW1T9KQB6XG7Q6K61F;Test variant;;;;;;true;false;;2024-07-31T16:07:55.133Z;;;;;;size;large;color;green;;30;45;100;prod_01J44RRJZ3M5F63NY82434RNM5;2024-07-31T16:07:55.133Z;0;; +test line 2";;;test-image.png;pcol_01J44RRJXM6AM3YS5PMJDMH3YF;ptyp_01J44RRJYAFEBZ2EY1KE1JM3XD;2024-07-31T16:07:55.102Z;;true;;;test-image.png;test-image-2.png;false;;;;;123;456;2024-07-31T16:07:55.102Z;;;variant_01J44RRJZW1T9KQB6XG7Q6K61F;Test variant;;;;;;true;false;;2024-07-31T16:07:55.133Z;;;;;;size;large;color;green;;30;45;100;prod_01J44RRJZ3M5F63NY82434RNM5;2024-07-31T16:07:55.133Z;0;;;import-shipping-profile prod_01J44RRJZ3M5F63NY82434RNM5;base-product;Base product;draft;"test-product-description -test line 2";;;test-image.png;pcol_01J44RRJXM6AM3YS5PMJDMH3YF;ptyp_01J44RRJYAFEBZ2EY1KE1JM3XD;2024-07-31T16:07:55.102Z;;true;;;test-image.png;test-image-2.png;false;;;;;123;456;2024-07-31T16:07:55.102Z;;;variant_01J44RRJZW5GNQKT1FEDACEESW;Test variant 2;;;;;;true;false;;2024-07-31T16:07:55.133Z;;;;;;size;small;color;green;;50;65;200;prod_01J44RRJZ3M5F63NY82434RNM5;2024-07-31T16:07:55.133Z;0;; -prod_01J44RRK2GJJVMQQXT67TJCV08;proposed-product;Proposed product;proposed;test-product-description;;;test-image.png;;ptyp_01J44RRJYAFEBZ2EY1KE1JM3XD;2024-07-31T16:07:55.213Z;;true;;;test-image.png;test-image-2.png;false;;;;;new-tag;;2024-07-31T16:07:55.213Z;;;variant_01J44RRK2WYHH0RDEK8BBGP7CY;Test variant;;;;;;true;false;;2024-07-31T16:07:55.228Z;;;;;;size;large;color;green;;30;45;100;prod_01J44RRK2GJJVMQQXT67TJCV08;2024-07-31T16:07:55.228Z;0;; \ No newline at end of file +test line 2";;;test-image.png;pcol_01J44RRJXM6AM3YS5PMJDMH3YF;ptyp_01J44RRJYAFEBZ2EY1KE1JM3XD;2024-07-31T16:07:55.102Z;;true;;;test-image.png;test-image-2.png;false;;;;;123;456;2024-07-31T16:07:55.102Z;;;variant_01J44RRJZW5GNQKT1FEDACEESW;Test variant 2;;;;;;true;false;;2024-07-31T16:07:55.133Z;;;;;;size;small;color;green;;50;65;200;prod_01J44RRJZ3M5F63NY82434RNM5;2024-07-31T16:07:55.133Z;0;;;import-shipping-profile +prod_01J44RRK2GJJVMQQXT67TJCV08;proposed-product;Proposed product;proposed;test-product-description;;;test-image.png;;ptyp_01J44RRJYAFEBZ2EY1KE1JM3XD;2024-07-31T16:07:55.213Z;;true;;;test-image.png;test-image-2.png;false;;;;;new-tag;;2024-07-31T16:07:55.213Z;;;variant_01J44RRK2WYHH0RDEK8BBGP7CY;Test variant;;;;;;true;false;;2024-07-31T16:07:55.228Z;;;;;;size;large;color;green;;30;45;100;prod_01J44RRK2GJJVMQQXT67TJCV08;2024-07-31T16:07:55.228Z;0;;;import-shipping-profile \ No newline at end of file diff --git a/integration-tests/http/__tests__/product/admin/__fixtures__/filtered-products.csv b/integration-tests/http/__tests__/product/admin/__fixtures__/filtered-products.csv index 1b40f54ef2..9385f06b2e 100644 --- a/integration-tests/http/__tests__/product/admin/__fixtures__/filtered-products.csv +++ b/integration-tests/http/__tests__/product/admin/__fixtures__/filtered-products.csv @@ -1,2 +1,2 @@ -Product Id,Product Handle,Product Title,Product Status,Product Description,Product Subtitle,Product External Id,Product Thumbnail,Product Collection Id,Product Type Id,Product Created At,Product Deleted At,Product Discountable,Product Height,Product Hs Code,Product Image 1,Product Image 2,Product Is Giftcard,Product Length,Product Material,Product Mid Code,Product Origin Country,Product Tag 1,Product Updated At,Product Weight,Product Width,Variant Id,Variant Title,Variant Sku,Variant Upc,Variant Ean,Variant Hs Code,Variant Mid Code,Variant Manage Inventory,Variant Allow Backorder,Variant Barcode,Variant Created At,Variant Deleted At,Variant Height,Variant Length,Variant Material,Variant Metadata,Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value,Variant Origin Country,Variant Price DKK,Variant Price EUR,Variant Price USD,Variant Product Id,Variant Updated At,Variant Variant Rank,Variant Weight,Variant Width -prod_01J44RRMJ7H2K9JAD9AQHA724B,proposed-product,Proposed product,proposed,test-product-description,,,test-image.png,,ptyp_01J44RRMF4J9SG6F7FG3B16A7F,2024-07-31T16:07:56.741Z,,true,,,test-image.png,test-image-2.png,false,,,,,new-tag,2024-07-31T16:07:56.741Z,,,variant_01J44RRMJJT9HSEGFJHTY2SX2P,Test variant,,,,,,true,false,,2024-07-31T16:07:56.754Z,,,,,,size,large,color,green,,30,45,100,prod_01J44RRMJ7H2K9JAD9AQHA724B,2024-07-31T16:07:56.754Z,0,, \ No newline at end of file +Product Id,Product Handle,Product Title,Product Status,Product Description,Product Subtitle,Product External Id,Product Thumbnail,Product Collection Id,Product Type Id,Product Created At,Product Deleted At,Product Discountable,Product Height,Product Hs Code,Product Image 1,Product Image 2,Product Is Giftcard,Product Length,Product Material,Product Mid Code,Product Origin Country,Product Tag 1,Product Updated At,Product Weight,Product Width,Variant Id,Variant Title,Variant Sku,Variant Upc,Variant Ean,Variant Hs Code,Variant Mid Code,Variant Manage Inventory,Variant Allow Backorder,Variant Barcode,Variant Created At,Variant Deleted At,Variant Height,Variant Length,Variant Material,Variant Metadata,Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value,Variant Origin Country,Variant Price DKK,Variant Price EUR,Variant Price USD,Variant Product Id,Variant Updated At,Variant Variant Rank,Variant Weight,Variant Width,Shipping Profile Id +prod_01J44RRMJ7H2K9JAD9AQHA724B,proposed-product,Proposed product,proposed,test-product-description,,,test-image.png,,ptyp_01J44RRMF4J9SG6F7FG3B16A7F,2024-07-31T16:07:56.741Z,,true,,,test-image.png,test-image-2.png,false,,,,,new-tag,2024-07-31T16:07:56.741Z,,,variant_01J44RRMJJT9HSEGFJHTY2SX2P,Test variant,,,,,,true,false,,2024-07-31T16:07:56.754Z,,,,,,size,large,color,green,,30,45,100,prod_01J44RRMJ7H2K9JAD9AQHA724B,2024-07-31T16:07:56.754Z,0,,,import-shipping-profile \ No newline at end of file diff --git a/integration-tests/http/__tests__/product/admin/__fixtures__/invalid-column.csv b/integration-tests/http/__tests__/product/admin/__fixtures__/invalid-column.csv index 510649018b..007c4e0110 100644 --- a/integration-tests/http/__tests__/product/admin/__fixtures__/invalid-column.csv +++ b/integration-tests/http/__tests__/product/admin/__fixtures__/invalid-column.csv @@ -1,2 +1,2 @@ -Product Id,Product Title,Product Subtitle,Product Status,Product External Id,Product Description,Product Handle,Product Is Giftcard,Product Discountable,Product Thumbnail,Product Collection Id,Product Type Id,Product Weight,Product Length,Product Height,Product Width,Product Hs Code,Product Origin Country,Product Mid Code,Product Material,Product Created At,Product Updated At,Product Deleted At,Product Image 1,Product Image 2,Product Tag 1,Variant Id,Variant Title,Variant Sku,Variant Barcode,Variant Ean,Variant Upc,Variant Allow Backorder,Variant Manage Inventory,Variant Hs Code,Variant Origin Country,Variant Mid Code,Variant Material,Variant Weight,Variant Length,Variant Height,Variant Width,Variant Metadata,Variant Variant Rank,Variant Product Id,Variant Created At,Variant Updated At,Variant Deleted At,Variant Price USD,Variant Price EUR,Variant Price DKK,Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value,Product field -prod_01J3CSN791SN1RN7X155Z8S9CN,Proposed product,,proposed,,test-product-description,proposed-product,false,true,test-image.png,,ptyp_01J3CSN76GCRSCDV9V489B5FWQ,,,,,,,,,2024-07-22T08:41:47.040Z,2024-07-22T08:41:47.040Z,,test-image.png,test-image-2.png,new-tag,variant_01J3CSN79CQ2ND94SRJSXMEMNH,Test variant,,,,,false,true,,,,,,,,,,0,prod_01J3CSN791SN1RN7X155Z8S9CN,2024-07-22T08:41:47.053Z,2024-07-22T08:41:47.053Z,,100,45,30,size,large,color,green,someval \ No newline at end of file +Product Id,Product Title,Product Subtitle,Product Status,Product External Id,Product Description,Product Handle,Product Is Giftcard,Product Discountable,Product Thumbnail,Product Collection Id,Product Type Id,Product Weight,Product Length,Product Height,Product Width,Product Hs Code,Product Origin Country,Product Mid Code,Product Material,Product Created At,Product Updated At,Product Deleted At,Product Image 1,Product Image 2,Product Tag 1,Variant Id,Variant Title,Variant Sku,Variant Barcode,Variant Ean,Variant Upc,Variant Allow Backorder,Variant Manage Inventory,Variant Hs Code,Variant Origin Country,Variant Mid Code,Variant Material,Variant Weight,Variant Length,Variant Height,Variant Width,Variant Metadata,Variant Variant Rank,Variant Product Id,Variant Created At,Variant Updated At,Variant Deleted At,Variant Price USD,Variant Price EUR,Variant Price DKK,Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value,Product field,Shipping Profile Id +prod_01J3CSN791SN1RN7X155Z8S9CN,Proposed product,,proposed,,test-product-description,proposed-product,false,true,test-image.png,,ptyp_01J3CSN76GCRSCDV9V489B5FWQ,,,,,,,,,2024-07-22T08:41:47.040Z,2024-07-22T08:41:47.040Z,,test-image.png,test-image-2.png,new-tag,variant_01J3CSN79CQ2ND94SRJSXMEMNH,Test variant,,,,,false,true,,,,,,,,,,0,prod_01J3CSN791SN1RN7X155Z8S9CN,2024-07-22T08:41:47.053Z,2024-07-22T08:41:47.053Z,,100,45,30,size,large,color,green,someval,import-shipping-profile \ No newline at end of file diff --git a/integration-tests/http/__tests__/product/admin/__fixtures__/invalid-prices.csv b/integration-tests/http/__tests__/product/admin/__fixtures__/invalid-prices.csv index 85b62739f1..34becbbda1 100644 --- a/integration-tests/http/__tests__/product/admin/__fixtures__/invalid-prices.csv +++ b/integration-tests/http/__tests__/product/admin/__fixtures__/invalid-prices.csv @@ -1,2 +1,2 @@ -Product Id,Product Title,Product Subtitle,Product Status,Product External Id,Product Description,Product Handle,Product Is Giftcard,Product Discountable,Product Thumbnail,Product Collection Id,Product Type Id,Product Weight,Product Length,Product Height,Product Width,Product Hs Code,Product Origin Country,Product Mid Code,Product Material,Product Created At,Product Updated At,Product Deleted At,Product Image 1,Product Image 2,Product Tag 1,Variant Id,Variant Title,Variant Sku,Variant Barcode,Variant Ean,Variant Upc,Variant Allow Backorder,Variant Manage Inventory,Variant Hs Code,Variant Origin Country,Variant Mid Code,Variant Material,Variant Weight,Variant Length,Variant Height,Variant Width,Variant Metadata,Variant Variant Rank,Variant Product Id,Variant Created At,Variant Updated At,Variant Deleted At,Variant Price USD,Variant Price EUR,Variant Price nonexistent [EUR],Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value -prod_01J3CSN791SN1RN7X155Z8S9CN,Proposed product,,proposed,,test-product-description,proposed-product,false,true,test-image.png,,ptyp_01J3CSN76GCRSCDV9V489B5FWQ,,,,,,,,,2024-07-22T08:41:47.040Z,2024-07-22T08:41:47.040Z,,test-image.png,test-image-2.png,new-tag,variant_01J3CSN79CQ2ND94SRJSXMEMNH,Test variant,,,,,false,true,,,,,,,,,,0,prod_01J3CSN791SN1RN7X155Z8S9CN,2024-07-22T08:41:47.053Z,2024-07-22T08:41:47.053Z,,100,45,30,size,large,color,green \ No newline at end of file +Product Id,Product Title,Product Subtitle,Product Status,Product External Id,Product Description,Product Handle,Product Is Giftcard,Product Discountable,Product Thumbnail,Product Collection Id,Product Type Id,Product Weight,Product Length,Product Height,Product Width,Product Hs Code,Product Origin Country,Product Mid Code,Product Material,Product Created At,Product Updated At,Product Deleted At,Product Image 1,Product Image 2,Product Tag 1,Variant Id,Variant Title,Variant Sku,Variant Barcode,Variant Ean,Variant Upc,Variant Allow Backorder,Variant Manage Inventory,Variant Hs Code,Variant Origin Country,Variant Mid Code,Variant Material,Variant Weight,Variant Length,Variant Height,Variant Width,Variant Metadata,Variant Variant Rank,Variant Product Id,Variant Created At,Variant Updated At,Variant Deleted At,Variant Price USD,Variant Price EUR,Variant Price nonexistent [EUR],Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value,Shipping Profile Id +prod_01J3CSN791SN1RN7X155Z8S9CN,Proposed product,,proposed,,test-product-description,proposed-product,false,true,test-image.png,,ptyp_01J3CSN76GCRSCDV9V489B5FWQ,,,,,,,,,2024-07-22T08:41:47.040Z,2024-07-22T08:41:47.040Z,,test-image.png,test-image-2.png,new-tag,variant_01J3CSN79CQ2ND94SRJSXMEMNH,Test variant,,,,,false,true,,,,,,,,,,0,prod_01J3CSN791SN1RN7X155Z8S9CN,2024-07-22T08:41:47.053Z,2024-07-22T08:41:47.053Z,,100,45,30,size,large,color,green,import-shipping-profile \ No newline at end of file diff --git a/integration-tests/http/__tests__/product/admin/__fixtures__/prices-with-region.csv b/integration-tests/http/__tests__/product/admin/__fixtures__/prices-with-region.csv index 591f8a7d99..e760a8d269 100644 --- a/integration-tests/http/__tests__/product/admin/__fixtures__/prices-with-region.csv +++ b/integration-tests/http/__tests__/product/admin/__fixtures__/prices-with-region.csv @@ -1,2 +1,2 @@ -Product Id,Product Handle,Product Title,Product Status,Product Description,Product Subtitle,Product External Id,Product Thumbnail,Product Collection Id,Product Type Id,Product Created At,Product Deleted At,Product Discountable,Product Height,Product Hs Code,Product Image 1,Product Image 2,Product Is Giftcard,Product Length,Product Material,Product Mid Code,Product Origin Country,Product Tag 1,Product Tag 2,Product Updated At,Product Weight,Product Width,Variant Id,Variant Title,Variant Sku,Variant Upc,Variant Ean,Variant Hs Code,Variant Mid Code,Variant Manage Inventory,Variant Allow Backorder,Variant Barcode,Variant Created At,Variant Deleted At,Variant Height,Variant Length,Variant Material,Variant Metadata,Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value,Variant Origin Country,Variant Price Test Region [USD],Variant Price USD,Variant Product Id,Variant Updated At,Variant Variant Rank,Variant Weight,Variant Width -prod_01J44RRM579P1EY2ZNQVGN1THT,product-with-prices,Product with prices,draft,test-product-description,,,test-image.png,,,2024-07-31T16:07:56.325Z,,true,,,test-image.png,test-image-2.png,false,,,,,123,456,2024-07-31T16:07:56.325Z,,,variant_01J44RRM5J1569XJD39DM3PNFN,Test variant,,,,,,true,false,,2024-07-31T16:07:56.338Z,,,,,,size,large,color,green,,45,100,prod_01J44RRM579P1EY2ZNQVGN1THT,2024-07-31T16:07:56.338Z,0,, \ No newline at end of file +Product Id,Product Handle,Product Title,Product Status,Product Description,Product Subtitle,Product External Id,Product Thumbnail,Product Collection Id,Product Type Id,Product Created At,Product Deleted At,Product Discountable,Product Height,Product Hs Code,Product Image 1,Product Image 2,Product Is Giftcard,Product Length,Product Material,Product Mid Code,Product Origin Country,Product Tag 1,Product Tag 2,Product Updated At,Product Weight,Product Width,Variant Id,Variant Title,Variant Sku,Variant Upc,Variant Ean,Variant Hs Code,Variant Mid Code,Variant Manage Inventory,Variant Allow Backorder,Variant Barcode,Variant Created At,Variant Deleted At,Variant Height,Variant Length,Variant Material,Variant Metadata,Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value,Variant Origin Country,Variant Price Test Region [USD],Variant Price USD,Variant Product Id,Variant Updated At,Variant Variant Rank,Variant Weight,Variant Width,Shipping Profile Id +prod_01J44RRM579P1EY2ZNQVGN1THT,product-with-prices,Product with prices,draft,test-product-description,,,test-image.png,,,2024-07-31T16:07:56.325Z,,true,,,test-image.png,test-image-2.png,false,,,,,123,456,2024-07-31T16:07:56.325Z,,,variant_01J44RRM5J1569XJD39DM3PNFN,Test variant,,,,,,true,false,,2024-07-31T16:07:56.338Z,,,,,,size,large,color,green,,45,100,prod_01J44RRM579P1EY2ZNQVGN1THT,2024-07-31T16:07:56.338Z,0,,,import-shipping-profile \ No newline at end of file diff --git a/integration-tests/http/__tests__/product/admin/__fixtures__/product-with-categories.csv b/integration-tests/http/__tests__/product/admin/__fixtures__/product-with-categories.csv index 87499b7980..4a3524cce0 100644 --- a/integration-tests/http/__tests__/product/admin/__fixtures__/product-with-categories.csv +++ b/integration-tests/http/__tests__/product/admin/__fixtures__/product-with-categories.csv @@ -1,5 +1,5 @@ -Product Id,Product Handle,Product Title,Product Status,Product Description,Product Subtitle,Product External Id,Product Thumbnail,Product Collection Id,Product Type Id,Product Category 1,Product Created At,Product Deleted At,Product Discountable,Product Height,Product Hs Code,Product Image 1,Product Image 2,Product Is Giftcard,Product Length,Product Material,Product Mid Code,Product Origin Country,Product Tag 1,Product Tag 2,Product Updated At,Product Weight,Product Width,Variant Id,Variant Title,Variant Sku,Variant Upc,Variant Ean,Variant Hs Code,Variant Mid Code,Variant Manage Inventory,Variant Allow Backorder,Variant Barcode,Variant Created At,Variant Deleted At,Variant Height,Variant Length,Variant Material,Variant Metadata,Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value,Variant Origin Country,Variant Price DKK,Variant Price EUR,Variant Price USD,Variant Product Id,Variant Updated At,Variant Variant Rank,Variant Weight,Variant Width +Product Id,Product Handle,Product Title,Product Status,Product Description,Product Subtitle,Product External Id,Product Thumbnail,Product Collection Id,Product Type Id,Product Category 1,Product Created At,Product Deleted At,Product Discountable,Product Height,Product Hs Code,Product Image 1,Product Image 2,Product Is Giftcard,Product Length,Product Material,Product Mid Code,Product Origin Country,Product Tag 1,Product Tag 2,Product Updated At,Product Weight,Product Width,Variant Id,Variant Title,Variant Sku,Variant Upc,Variant Ean,Variant Hs Code,Variant Mid Code,Variant Manage Inventory,Variant Allow Backorder,Variant Barcode,Variant Created At,Variant Deleted At,Variant Height,Variant Length,Variant Material,Variant Metadata,Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value,Variant Origin Country,Variant Price DKK,Variant Price EUR,Variant Price USD,Variant Product Id,Variant Updated At,Variant Variant Rank,Variant Weight,Variant Width,Shipping Profile Id prod_01J44RRKH4HH2SANJ0S05YM853,base-product,Base product,draft,"test-product-description -test line 2",,,test-image.png,pcol_01J44RRKG4P1RZ3CKAMBS760TD,ptyp_01J44RRKGHPQMJ1CRMW7MEN3P1,pcat_01J44RRKGS2N86A8V37ZJD877K,2024-07-31T16:07:55.681Z,,true,,,test-image.png,test-image-2.png,false,,,,,123,456,2024-07-31T16:07:55.681Z,,,variant_01J44RRKHRQ7WJ902X4936GEK7,Test variant,,,,,,true,false,,2024-07-31T16:07:55.704Z,,,,,,size,large,color,green,,30,45,100,prod_01J44RRKH4HH2SANJ0S05YM853,2024-07-31T16:07:55.704Z,0,, +test line 2",,,test-image.png,pcol_01J44RRKG4P1RZ3CKAMBS760TD,ptyp_01J44RRKGHPQMJ1CRMW7MEN3P1,pcat_01J44RRKGS2N86A8V37ZJD877K,2024-07-31T16:07:55.681Z,,true,,,test-image.png,test-image-2.png,false,,,,,123,456,2024-07-31T16:07:55.681Z,,,variant_01J44RRKHRQ7WJ902X4936GEK7,Test variant,,,,,,true,false,,2024-07-31T16:07:55.704Z,,,,,,size,large,color,green,,30,45,100,prod_01J44RRKH4HH2SANJ0S05YM853,2024-07-31T16:07:55.704Z,0,,,import-shipping-profile prod_01J44RRKH4HH2SANJ0S05YM853,base-product,Base product,draft,"test-product-description -test line 2",,,test-image.png,pcol_01J44RRKG4P1RZ3CKAMBS760TD,ptyp_01J44RRKGHPQMJ1CRMW7MEN3P1,pcat_01J44RRKGS2N86A8V37ZJD877K,2024-07-31T16:07:55.681Z,,true,,,test-image.png,test-image-2.png,false,,,,,123,456,2024-07-31T16:07:55.681Z,,,variant_01J44RRKHRAYY7Q7NTXNNMDA1S,Test variant 2,,,,,,true,false,,2024-07-31T16:07:55.704Z,,,,,,size,small,color,green,,50,65,200,prod_01J44RRKH4HH2SANJ0S05YM853,2024-07-31T16:07:55.704Z,0,, \ No newline at end of file +test line 2",,,test-image.png,pcol_01J44RRKG4P1RZ3CKAMBS760TD,ptyp_01J44RRKGHPQMJ1CRMW7MEN3P1,pcat_01J44RRKGS2N86A8V37ZJD877K,2024-07-31T16:07:55.681Z,,true,,,test-image.png,test-image-2.png,false,,,,,123,456,2024-07-31T16:07:55.681Z,,,variant_01J44RRKHRAYY7Q7NTXNNMDA1S,Test variant 2,,,,,,true,false,,2024-07-31T16:07:55.704Z,,,,,,size,small,color,green,,50,65,200,prod_01J44RRKH4HH2SANJ0S05YM853,2024-07-31T16:07:55.704Z,0,,,import-shipping-profile \ No newline at end of file diff --git a/integration-tests/http/__tests__/product/admin/__fixtures__/unrelated-column.csv b/integration-tests/http/__tests__/product/admin/__fixtures__/unrelated-column.csv index ce999700e7..f9c4ec0766 100644 --- a/integration-tests/http/__tests__/product/admin/__fixtures__/unrelated-column.csv +++ b/integration-tests/http/__tests__/product/admin/__fixtures__/unrelated-column.csv @@ -1,2 +1,2 @@ -Product Id,Product Title,Product Subtitle,Product Status,Product External Id,Product Description,Product Handle,Product Is Giftcard,Product Discountable,Product Thumbnail,Product Collection Id,Product Type Id,Product Weight,Product Length,Product Height,Product Width,Product Hs Code,Product Origin Country,Product Mid Code,Product Material,Product Created At,Product Updated At,Product Deleted At,Product Image 1,Product Image 2,Product Tag 1,Variant Id,Variant Title,Variant Sku,Variant Barcode,Variant Ean,Variant Upc,Variant Allow Backorder,Variant Manage Inventory,Variant Hs Code,Variant Origin Country,Variant Mid Code,Variant Material,Variant Weight,Variant Length,Variant Height,Variant Width,Variant Metadata,Variant Variant Rank,Variant Product Id,Variant Created At,Variant Updated At,Variant Deleted At,Variant Price USD,Variant Price EUR,Variant Price DKK,Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value,Some field -prod_01J3CSN791SN1RN7X155Z8S9CN,Proposed product,,proposed,,test-product-description,proposed-product,false,true,test-image.png,,ptyp_01J3CSN76GCRSCDV9V489B5FWQ,,,,,,,,,2024-07-22T08:41:47.040Z,2024-07-22T08:41:47.040Z,,test-image.png,test-image-2.png,new-tag,variant_01J3CSN79CQ2ND94SRJSXMEMNH,Test variant,,,,,false,true,,,,,,,,,,0,prod_01J3CSN791SN1RN7X155Z8S9CN,2024-07-22T08:41:47.053Z,2024-07-22T08:41:47.053Z,,100,45,30,size,large,color,green,someval \ No newline at end of file +Product Id,Product Title,Product Subtitle,Product Status,Product External Id,Product Description,Product Handle,Product Is Giftcard,Product Discountable,Product Thumbnail,Product Collection Id,Product Type Id,Product Weight,Product Length,Product Height,Product Width,Product Hs Code,Product Origin Country,Product Mid Code,Product Material,Product Created At,Product Updated At,Product Deleted At,Product Image 1,Product Image 2,Product Tag 1,Variant Id,Variant Title,Variant Sku,Variant Barcode,Variant Ean,Variant Upc,Variant Allow Backorder,Variant Manage Inventory,Variant Hs Code,Variant Origin Country,Variant Mid Code,Variant Material,Variant Weight,Variant Length,Variant Height,Variant Width,Variant Metadata,Variant Variant Rank,Variant Product Id,Variant Created At,Variant Updated At,Variant Deleted At,Variant Price USD,Variant Price EUR,Variant Price DKK,Variant Option 1 Name,Variant Option 1 Value,Variant Option 2 Name,Variant Option 2 Value,Some field,Shipping Profile Id +prod_01J3CSN791SN1RN7X155Z8S9CN,Proposed product,,proposed,,test-product-description,proposed-product,false,true,test-image.png,,ptyp_01J3CSN76GCRSCDV9V489B5FWQ,,,,,,,,,2024-07-22T08:41:47.040Z,2024-07-22T08:41:47.040Z,,test-image.png,test-image-2.png,new-tag,variant_01J3CSN79CQ2ND94SRJSXMEMNH,Test variant,,,,,false,true,,,,,,,,,,0,prod_01J3CSN791SN1RN7X155Z8S9CN,2024-07-22T08:41:47.053Z,2024-07-22T08:41:47.053Z,,100,45,30,size,large,color,green,someval,import-shipping-profile \ No newline at end of file diff --git a/integration-tests/http/__tests__/product/admin/__fixtures__/v1-template.csv b/integration-tests/http/__tests__/product/admin/__fixtures__/v1-template.csv index 337cc96044..188e7def72 100644 --- a/integration-tests/http/__tests__/product/admin/__fixtures__/v1-template.csv +++ b/integration-tests/http/__tests__/product/admin/__fixtures__/v1-template.csv @@ -1,6 +1,6 @@ -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 Test region [USD],Price USD,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,,123_1,TRUE,,,Test variant,test-sku-1,test-barcode-1,10,FALSE,TRUE,,,,,,,,,1.00,1.10,test-option-1,option 1 value red,test-option-2,option 2 value 1,test-image.png -,test-product-product-1-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,,,TRUE,,,Test variant,test-sku-1-1,test-barcode-1-1,10,FALSE,TRUE,,,,,,,,,1.00,1.10,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 +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 Test region [USD],Price USD,Option 1 Name,Option 1 Value,Option 2 Name,Option 2 Value,Image 1 Url,Shipping Profile 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,,123_1,TRUE,,,Test variant,test-sku-1,test-barcode-1,10,FALSE,TRUE,,,,,,,,,1.00,1.10,test-option-1,option 1 value red,test-option-2,option 2 value 1,test-image.png,import-shipping-profile +,test-product-product-1-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,,,TRUE,,,Test variant,test-sku-1-1,test-barcode-1-1,10,FALSE,TRUE,,,,,,,,,1.00,1.10,test-option-1,option 1 value red,test-option-2,option 2 value 1,test-image.png,import-shipping-profile +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,import-shipping-profile +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,import-shipping-profile +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,import-shipping-profile \ No newline at end of file diff --git a/integration-tests/http/__tests__/product/admin/product-export.spec.ts b/integration-tests/http/__tests__/product/admin/product-export.spec.ts index 5c227467a2..2f96e7b4d4 100644 --- a/integration-tests/http/__tests__/product/admin/product-export.spec.ts +++ b/integration-tests/http/__tests__/product/admin/product-export.spec.ts @@ -39,6 +39,9 @@ const compareCSVs = async (filePath, expectedFilePath) => { fileContent = fileContent.replace(dateRegex, "") fixturesContent = fixturesContent.replace(dateRegex, "") + fixturesContent = fixturesContent.replace(/,Shipping Profile Id*/g, "") + fixturesContent = fixturesContent.replace(/,import-shipping-profile*/g, "") + expect(fileContent).toEqual(fixturesContent) } @@ -56,6 +59,7 @@ medusaIntegrationTestRunner({ let baseTag1 let baseTag2 let newTag + let shippingProfile let eventBus: IEventBusModuleService beforeAll(async () => { @@ -92,6 +96,14 @@ medusaIntegrationTestRunner({ ) ).data.collection + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + baseType = ( await api.post( "/admin/product-types", @@ -130,6 +142,7 @@ medusaIntegrationTestRunner({ getProductFixture({ title: "Base product", description: "test-product-description\ntest line 2", + shipping_profile_id: shippingProfile.id, collection_id: baseCollection.id, type_id: baseType.id, categories: [{ id: baseCategory.id }], @@ -191,6 +204,7 @@ medusaIntegrationTestRunner({ status: "proposed", tags: [{ id: newTag.id }], type_id: baseType.id, + shipping_profile_id: shippingProfile.id, }), adminHeaders ) @@ -281,6 +295,7 @@ medusaIntegrationTestRunner({ "/admin/products", getProductFixture({ title: "Product with prices", + shipping_profile_id: shippingProfile.id, tags: [{ id: baseTag1.id }, { id: baseTag2.id }], variants: [ { diff --git a/integration-tests/http/__tests__/product/admin/product-import.spec.ts b/integration-tests/http/__tests__/product/admin/product-import.spec.ts index 77085205fb..87c3c80373 100644 --- a/integration-tests/http/__tests__/product/admin/product-import.spec.ts +++ b/integration-tests/http/__tests__/product/admin/product-import.spec.ts @@ -40,6 +40,7 @@ medusaIntegrationTestRunner({ let baseTag2 let baseTag3 let newTag + let shippingProfile let eventBus: IEventBusModuleService beforeAll(async () => { @@ -84,12 +85,21 @@ medusaIntegrationTestRunner({ ) ).data.product_tag + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + baseProduct = ( await api.post( "/admin/products", getProductFixture({ title: "Base product", tags: [{ id: baseTag1.id }, { id: baseTag2.id }], + shipping_profile_id: shippingProfile.id, }), adminHeaders ) @@ -150,6 +160,11 @@ medusaIntegrationTestRunner({ fileContent = fileContent.replace(/pcol_\w*\d*/g, baseCollection.id) fileContent = fileContent.replace(/ptyp_\w*\d*/g, baseType.id) + fileContent = fileContent.replace( + /import-shipping-profile*/g, + shippingProfile.id + ) + const { form, meta } = getUploadReq({ name: "test.csv", content: fileContent, @@ -400,6 +415,11 @@ medusaIntegrationTestRunner({ fileContent = fileContent.replace(/ptyp_\w*\d*/g, baseType.id) fileContent = fileContent.replace(/pcat_\w*\d*/g, baseCategory.id) + fileContent = fileContent.replace( + /import-shipping-profile*/g, + shippingProfile.id + ) + const { form, meta } = getUploadReq({ name: "test.csv", content: fileContent, @@ -440,6 +460,11 @@ medusaIntegrationTestRunner({ { encoding: "utf-8" } ) + fileContent = fileContent.replace( + /import-shipping-profile*/g, + shippingProfile.id + ) + const { form, meta } = getUploadReq({ name: "test.csv", content: fileContent, @@ -467,6 +492,11 @@ medusaIntegrationTestRunner({ fileContent = fileContent.replace(/pcol_\w*\d*/g, baseCollection.id) fileContent = fileContent.replace(/ptyp_\w*\d*/g, baseType.id) + fileContent = fileContent.replace( + /import-shipping-profile*/g, + shippingProfile.id + ) + const { form, meta } = getUploadReq({ name: "test.csv", content: fileContent, @@ -517,6 +547,11 @@ medusaIntegrationTestRunner({ fileContent = fileContent.replace(/pcol_\w*\d*/g, baseCollection.id) fileContent = fileContent.replace(/ptyp_\w*\d*/g, baseType.id) + fileContent = fileContent.replace( + /import-shipping-profile*/g, + shippingProfile.id + ) + const { form, meta } = getUploadReq({ name: "test.csv", content: fileContent, @@ -582,6 +617,11 @@ medusaIntegrationTestRunner({ baseCollection.handle ) + fileContent = fileContent.replace( + /import-shipping-profile*/g, + shippingProfile.id + ) + const { form, meta } = getUploadReq({ name: "test.csv", content: fileContent, diff --git a/integration-tests/http/__tests__/product/admin/product.spec.ts b/integration-tests/http/__tests__/product/admin/product.spec.ts index 4a09504938..34169302b5 100644 --- a/integration-tests/http/__tests__/product/admin/product.spec.ts +++ b/integration-tests/http/__tests__/product/admin/product.spec.ts @@ -22,6 +22,8 @@ medusaIntegrationTestRunner({ let baseTag2 let newTag + let shippingProfile + beforeEach(async () => { await createAdminUser(dbConnection, adminHeaders, getContainer()) @@ -65,6 +67,14 @@ medusaIntegrationTestRunner({ ) ).data.product_tag + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "default", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + baseProduct = ( await api.post( "/admin/products", @@ -74,6 +84,7 @@ medusaIntegrationTestRunner({ // BREAKING: Type input changed from {type: {value: string}} to {type_id: string} type_id: baseType.id, tags: [{ id: baseTag1.id }, { id: baseTag2.id }], + shipping_profile_id: shippingProfile.id, images: [ { url: "image-one", @@ -95,6 +106,7 @@ medusaIntegrationTestRunner({ status: "proposed", tags: [{ id: newTag.id }], type_id: baseType.id, + shipping_profile_id: shippingProfile.id, }), adminHeaders ) @@ -108,6 +120,7 @@ medusaIntegrationTestRunner({ status: "published", collection_id: publishedCollection.id, tags: [{ id: baseTag1.id }, { id: baseTag2.id }], + shipping_profile_id: shippingProfile.id, }), adminHeaders ) @@ -115,7 +128,10 @@ medusaIntegrationTestRunner({ deletedProduct = ( await api.post( "/admin/products", - getProductFixture({ title: "Deleted product" }), + getProductFixture({ + title: "Deleted product", + shipping_profile_id: shippingProfile.id, + }), adminHeaders ) ).data.product @@ -605,6 +621,7 @@ medusaIntegrationTestRunner({ is_giftcard: true, description: "test-giftcard-description", options: [{ title: "Denominations", values: ["100"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Test variant", @@ -693,6 +710,7 @@ medusaIntegrationTestRunner({ is_giftcard: true, description: "test-giftcard-description", options: [{ title: "size", values: ["x", "l"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Test variant", @@ -912,6 +930,7 @@ medusaIntegrationTestRunner({ getProductFixture({ title: "Test saleschannel", sales_channels: [{ id: salesChannel.id }], + shipping_profile_id: shippingProfile.id, }), adminHeaders ) @@ -1098,6 +1117,7 @@ medusaIntegrationTestRunner({ title: "Test product - 1", handle: "test-1", options: [{ title: "size", values: ["x", "l"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Custom inventory 1", @@ -1141,6 +1161,7 @@ medusaIntegrationTestRunner({ title: "Test product - 1", handle: "test-1", options: [{ title: "size", values: ["x", "l"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Custom inventory 1", @@ -1202,6 +1223,7 @@ medusaIntegrationTestRunner({ collection_id: baseCollection.id, type_id: baseType.id, tags: [{ id: baseTag1.id }, { id: baseTag2.id }], + shipping_profile_id: shippingProfile.id, }), adminHeaders @@ -1341,6 +1363,7 @@ medusaIntegrationTestRunner({ { title: "Test create", options: [{ title: "size", values: ["x", "l"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Price with rules", @@ -1394,6 +1417,7 @@ medusaIntegrationTestRunner({ collection_id: baseCollection.id, tags: [{ id: baseTag1.id }, { id: baseTag2.id }], options: [{ title: "size", values: ["large"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Test variant", @@ -1425,7 +1449,8 @@ medusaIntegrationTestRunner({ images: [{ url: "test-image.png" }, { url: "test-image-2.png" }], collection_id: baseCollection.id, tags: [{ id: baseTag1.id }, { id: baseTag2.id }], - options: [{ title: "size", values: ["l", x] }], + options: [{ title: "size", values: ["l", "x"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Test variant 1", @@ -1477,6 +1502,7 @@ medusaIntegrationTestRunner({ is_giftcard: true, description: "test-giftcard-description", options: [{ title: "size", values: ["large"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Test variant", @@ -1637,6 +1663,7 @@ medusaIntegrationTestRunner({ it("updates product variants (update price on existing variant, create new variant)", async () => { const payload = { + shipping_profile_id: shippingProfile.id, variants: [ { id: baseProduct.variants[0].id, @@ -1815,6 +1842,7 @@ medusaIntegrationTestRunner({ "/admin/products", getProductFixture({ title: "Test metadata", + shipping_profile_id: shippingProfile.id, metadata: { "test-key": "test-value", "test-key-2": "test-value-2", @@ -1877,6 +1905,7 @@ medusaIntegrationTestRunner({ getProductFixture({ title: "Test saleschannel", sales_channels: [{ id: salesChannel1.id }], + shipping_profile_id: shippingProfile.id, }), adminHeaders ) @@ -2045,7 +2074,10 @@ medusaIntegrationTestRunner({ const plainProduct = ( await api.post( "/admin/products", - { title: "Test variant order" }, + { + title: "Test variant order", + shipping_profile_id: shippingProfile.id, + }, adminHeaders ) ).data.product @@ -2152,6 +2184,7 @@ medusaIntegrationTestRunner({ title: "Test product - 1", handle: "test-1", options: [{ title: "size", values: ["x", "l"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Custom inventory 1", @@ -2265,6 +2298,7 @@ medusaIntegrationTestRunner({ title: "Test product - 1", handle: "test-1", options: [{ title: "size", values: ["x", "l"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Custom inventory 1", @@ -2316,6 +2350,7 @@ medusaIntegrationTestRunner({ title: "Test product - 1", handle: "test-1", options: [{ title: "size", values: ["x", "l"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Custom inventory 1", @@ -2490,6 +2525,7 @@ medusaIntegrationTestRunner({ title: "Test product - 1", handle: "test-1", options: [{ title: "size", values: ["l"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Custom inventory 1", @@ -2520,6 +2556,7 @@ medusaIntegrationTestRunner({ title: "Test product - 2", handle: "test-2", options: [{ title: "size", values: ["l"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "W/ shared inventory item", @@ -2604,6 +2641,7 @@ medusaIntegrationTestRunner({ title: "Test product - 1", handle: "test-1", options: [{ title: "size", values: ["l"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Custom inventory 1", @@ -2740,6 +2778,7 @@ medusaIntegrationTestRunner({ title: baseProduct.title, handle: baseProduct.handle, options: [{ title: "size", values: ["x", "l"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Test variant", @@ -2772,6 +2811,7 @@ medusaIntegrationTestRunner({ handle: baseProduct.handle, description: "test-product-description", options: [{ title: "size", values: ["x", "l"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Test variant", @@ -2948,6 +2988,7 @@ medusaIntegrationTestRunner({ const createPayload = getProductFixture({ title: "Test batch create", handle: "test-batch-create", + shipping_profile_id: shippingProfile.id, }) const updatePayload = { @@ -3006,6 +3047,7 @@ medusaIntegrationTestRunner({ const productWithMultipleVariants = getProductFixture({ title: "Test batch variants", handle: "test-batch-variants", + shipping_profile_id: shippingProfile.id, variants: [ { title: "Variant 1", diff --git a/integration-tests/http/__tests__/product/admin/variant.spec.ts b/integration-tests/http/__tests__/product/admin/variant.spec.ts index 4e11d9a477..1703aaa5a7 100644 --- a/integration-tests/http/__tests__/product/admin/variant.spec.ts +++ b/integration-tests/http/__tests__/product/admin/variant.spec.ts @@ -11,7 +11,7 @@ medusaIntegrationTestRunner({ testSuite: ({ dbConnection, getContainer, api }) => { let baseProduct let baseRegion - + let shippingProfile beforeEach(async () => { await createAdminUser(dbConnection, adminHeaders, getContainer()) // BREAKING: Creating a region no longer takes tax_rate, payment_providers, fulfillment_providers, countriesr @@ -26,11 +26,20 @@ medusaIntegrationTestRunner({ ) ).data.region + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "default", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + baseProduct = ( await api.post( "/admin/products", getProductFixture({ title: "Base product", + shipping_profile_id: shippingProfile.id, }), adminHeaders ) @@ -67,6 +76,7 @@ medusaIntegrationTestRunner({ { title: "First variant", prices: [] }, { title: "Second variant", prices: [] }, ], + shipping_profile_id: shippingProfile.id, }), adminHeaders ) @@ -801,6 +811,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "product 1", + shipping_profile_id: shippingProfile.id, options: [ { title: "size", values: ["large", "medium", "small"] }, ], diff --git a/integration-tests/http/__tests__/product/store/product.spec.ts b/integration-tests/http/__tests__/product/store/product.spec.ts index 248ab71826..edf11b52df 100644 --- a/integration-tests/http/__tests__/product/store/product.spec.ts +++ b/integration-tests/http/__tests__/product/store/product.spec.ts @@ -41,6 +41,7 @@ medusaIntegrationTestRunner({ let publishableKey let storeHeadersWithCustomer let customer + let shippingProfile const createProducts = async (data) => { const response = await api.post( @@ -135,6 +136,14 @@ medusaIntegrationTestRunner({ adminHeaders ) ).data.region + + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "default", type: "default" }, + adminHeaders + ) + ).data.shipping_profile }) describe("Get products based on publishable key", () => { @@ -145,7 +154,11 @@ medusaIntegrationTestRunner({ product1 = ( await api.post( "/admin/products", - getProductFixture({ title: "test1", status: "published" }), + getProductFixture({ + title: "test1", + status: "published", + shipping_profile_id: shippingProfile.id, + }), adminHeaders ) ).data.product @@ -153,7 +166,11 @@ medusaIntegrationTestRunner({ product2 = ( await api.post( "/admin/products", - getProductFixture({ title: "test2", status: "published" }), + getProductFixture({ + title: "test2", + status: "published", + shipping_profile_id: shippingProfile.id, + }), adminHeaders ) ).data.product @@ -161,7 +178,11 @@ medusaIntegrationTestRunner({ product3 = ( await api.post( "/admin/products", - getProductFixture({ title: "test3", status: "published" }), + getProductFixture({ + title: "test3", + status: "published", + shipping_profile_id: shippingProfile.id, + }), adminHeaders ) ).data.product @@ -500,6 +521,7 @@ medusaIntegrationTestRunner({ title: "test product 1", collection_id: collection.id, status: ProductStatus.PUBLISHED, + shipping_profile_id: shippingProfile.id, options: [ { title: "size", values: ["large", "small"] }, { title: "color", values: ["green"] }, @@ -538,6 +560,7 @@ medusaIntegrationTestRunner({ ;[product2, [variant2]] = await createProducts({ title: "test product 2 uniquely", status: ProductStatus.PUBLISHED, + shipping_profile_id: shippingProfile.id, options: [ { title: "size", values: ["large", "small"] }, { title: "material", values: ["cotton", "polyester"] }, @@ -557,6 +580,7 @@ medusaIntegrationTestRunner({ ;[product3, [variant3]] = await createProducts({ title: "product not in price list", status: ProductStatus.PUBLISHED, + shipping_profile_id: shippingProfile.id, options: [{ title: "size", values: ["large", "small"] }], variants: [ { title: "test variant 3", prices: [], options: { size: "large" } }, @@ -565,6 +589,7 @@ medusaIntegrationTestRunner({ ;[product4, [variant4]] = await createProducts({ title: "draft product", status: ProductStatus.DRAFT, + shipping_profile_id: shippingProfile.id, options: [{ title: "size", values: ["large", "small"] }], variants: [ { title: "test variant 4", prices: [], options: { size: "large" } }, @@ -1727,6 +1752,7 @@ medusaIntegrationTestRunner({ ;[product, [variant]] = await createProducts({ title: "test product 1", status: ProductStatus.PUBLISHED, + shipping_profile_id: shippingProfile.id, options: [{ title: "size", values: ["large"] }], variants: [ { @@ -2206,6 +2232,7 @@ medusaIntegrationTestRunner({ getProductFixture({ title: "test1", status: "published", + shipping_profile_id: shippingProfile.id, variants: [ { title: "Test taxes", @@ -2239,6 +2266,7 @@ medusaIntegrationTestRunner({ getProductFixture({ title: "test2", status: "published", + shipping_profile_id: shippingProfile.id, }), adminHeaders ) diff --git a/integration-tests/http/__tests__/promotions/admin/promotions.spec.ts b/integration-tests/http/__tests__/promotions/admin/promotions.spec.ts index 5806d89bd8..9745483696 100644 --- a/integration-tests/http/__tests__/promotions/admin/promotions.spec.ts +++ b/integration-tests/http/__tests__/promotions/admin/promotions.spec.ts @@ -56,6 +56,7 @@ medusaIntegrationTestRunner({ let appContainer let promotion let standardPromotion + let shippingProfile const promotionRule = { operator: "eq", @@ -90,6 +91,14 @@ medusaIntegrationTestRunner({ adminHeaders ) ).data.promotion + + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "default", type: "default" }, + adminHeaders + ) + ).data.shipping_profile }) describe("GET /admin/promotions/:id", () => { @@ -512,7 +521,10 @@ medusaIntegrationTestRunner({ const product = ( await api.post( "/admin/products", - medusaTshirtProduct, + { + ...medusaTshirtProduct, + shipping_profile_id: shippingProfile.id, + }, adminHeaders ) ).data.product @@ -1494,6 +1506,7 @@ medusaIntegrationTestRunner({ { title: "Test product 1", options: [{ title: "size", values: ["large", "small"] }], + shipping_profile_id: shippingProfile.id, }, adminHeaders ) @@ -1505,6 +1518,7 @@ medusaIntegrationTestRunner({ { title: "Test product 2", options: [{ title: "size", values: ["large", "small"] }], + shipping_profile_id: shippingProfile.id, }, adminHeaders ) diff --git a/integration-tests/http/__tests__/returns/returns.spec.ts b/integration-tests/http/__tests__/returns/returns.spec.ts index c83ce8a012..dda188fbf7 100644 --- a/integration-tests/http/__tests__/returns/returns.spec.ts +++ b/integration-tests/http/__tests__/returns/returns.spec.ts @@ -25,12 +25,24 @@ medusaIntegrationTestRunner({ const container = getContainer() await createAdminUser(dbConnection, adminHeaders, container) + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { + name: "Test", + type: "default", + }, + adminHeaders + ) + ).data.shipping_profile + const product = ( await api.post( "/admin/products", { title: "Test product", options: [{ title: "size", values: ["x", "l"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Test variant", @@ -149,17 +161,6 @@ medusaIntegrationTestRunner({ ], }) - shippingProfile = ( - await api.post( - `/admin/shipping-profiles`, - { - name: "Test", - type: "default", - }, - adminHeaders - ) - ).data.shipping_profile - location = ( await api.post( `/admin/stock-locations`, diff --git a/integration-tests/http/__tests__/sales-channel/admin/sales-channel.spec.ts b/integration-tests/http/__tests__/sales-channel/admin/sales-channel.spec.ts index 50261a2c88..53b3b4ae52 100644 --- a/integration-tests/http/__tests__/sales-channel/admin/sales-channel.spec.ts +++ b/integration-tests/http/__tests__/sales-channel/admin/sales-channel.spec.ts @@ -354,11 +354,20 @@ medusaIntegrationTestRunner({ // to: /admin/sales-channels/:id/products let product beforeEach(async () => { + const shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + product = ( await api.post( "/admin/products", { title: "test name", + shipping_profile_id: shippingProfile.id, options: [{ title: "size", values: ["large"] }], }, adminHeaders diff --git a/integration-tests/http/__tests__/shipping-option/store/shipping-option-calculated.spec.ts b/integration-tests/http/__tests__/shipping-option/store/shipping-option-calculated.spec.ts index 0294dfaf66..464365515a 100644 --- a/integration-tests/http/__tests__/shipping-option/store/shipping-option-calculated.spec.ts +++ b/integration-tests/http/__tests__/shipping-option/store/shipping-option-calculated.spec.ts @@ -58,6 +58,14 @@ medusaIntegrationTestRunner({ ) ).data.region + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + salesChannel = ( await api.post( "/admin/sales-channels", @@ -71,6 +79,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Test fixture", + shipping_profile_id: shippingProfile.id, options: [ { title: "size", values: ["large", "small"] }, { title: "color", values: ["green"] }, @@ -114,14 +123,6 @@ medusaIntegrationTestRunner({ adminHeaders ) - shippingProfile = ( - await api.post( - `/admin/shipping-profiles`, - { name: "Test", type: "default" }, - adminHeaders - ) - ).data.shipping_profile - const fulfillmentSets = ( await api.post( `/admin/stock-locations/${stockLocation.id}/fulfillment-sets?fields=*fulfillment_sets`, diff --git a/integration-tests/http/__tests__/shipping-option/store/shipping-option.spec.ts b/integration-tests/http/__tests__/shipping-option/store/shipping-option.spec.ts index c2479ffde4..520a946eef 100644 --- a/integration-tests/http/__tests__/shipping-option/store/shipping-option.spec.ts +++ b/integration-tests/http/__tests__/shipping-option/store/shipping-option.spec.ts @@ -57,6 +57,14 @@ medusaIntegrationTestRunner({ ) ).data.region + shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + salesChannel = ( await api.post( "/admin/sales-channels", @@ -74,6 +82,7 @@ medusaIntegrationTestRunner({ { title: "size", values: ["large", "small"] }, { title: "color", values: ["green"] }, ], + shipping_profile_id: shippingProfile.id, variants: [ { title: "Test variant", @@ -113,14 +122,6 @@ medusaIntegrationTestRunner({ adminHeaders ) - shippingProfile = ( - await api.post( - `/admin/shipping-profiles`, - { name: "Test", type: "default" }, - adminHeaders - ) - ).data.shipping_profile - const fulfillmentSets = ( await api.post( `/admin/stock-locations/${stockLocation.id}/fulfillment-sets?fields=*fulfillment_sets`, diff --git a/integration-tests/modules/__tests__/cart/store/carts.spec.ts b/integration-tests/modules/__tests__/cart/store/carts.spec.ts index cf2e908c8a..a09050380c 100644 --- a/integration-tests/modules/__tests__/cart/store/carts.spec.ts +++ b/integration-tests/modules/__tests__/cart/store/carts.spec.ts @@ -658,6 +658,7 @@ medusaIntegrationTestRunner({ describe("POST /store/carts/:id/line-items", () => { let region + const productData = { title: "Medusa T-Shirt", handle: "t-shirt", @@ -716,8 +717,21 @@ medusaIntegrationTestRunner({ }) it("adding an existing variant should update or create line item depending on metadata", async () => { + const shippingProfile = + await fulfillmentModule.createShippingProfiles({ + name: "Test", + type: "default", + }) + const product = ( - await api.post(`/admin/products`, productData, adminHeaders) + await api.post( + `/admin/products`, + { + ...productData, + shipping_profile_id: shippingProfile.id, + }, + adminHeaders + ) ).data.product const cart = ( @@ -1203,6 +1217,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Test fixture", + shipping_profile_id: shippingProfile.id, options: [ { title: "size", values: ["large", "small"] }, { title: "color", values: ["green"] }, diff --git a/integration-tests/modules/__tests__/common/workflows.spec.ts b/integration-tests/modules/__tests__/common/workflows.spec.ts index 04191ddbd9..b21620a8cc 100644 --- a/integration-tests/modules/__tests__/common/workflows.spec.ts +++ b/integration-tests/modules/__tests__/common/workflows.spec.ts @@ -30,11 +30,20 @@ medusaIntegrationTestRunner({ beforeEach(async () => { await createAdminUser(dbConnection, adminHeaders, getContainer()) + const shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + product = ( await api.post( "/admin/products", { title: "product 1", + shipping_profile_id: shippingProfile.id, options: [{ title: "size", values: ["x", "l"] }], variants: [ { diff --git a/integration-tests/modules/__tests__/index/search.spec.ts b/integration-tests/modules/__tests__/index/search.spec.ts index 512907a1bb..cfddbef986 100644 --- a/integration-tests/modules/__tests__/index/search.spec.ts +++ b/integration-tests/modules/__tests__/index/search.spec.ts @@ -31,9 +31,18 @@ medusaIntegrationTestRunner({ describe("Index engine", () => { it("should search through the indexed data and return the correct results ordered and filtered [1]", async () => { + const shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + const payload = { title: "Test Giftcard", is_giftcard: true, + shipping_profile_id: shippingProfile.id, description: "test-giftcard-description", options: [{ title: "Denominations", values: ["100"] }], variants: new Array(10).fill(0).map((_, i) => ({ @@ -101,10 +110,19 @@ medusaIntegrationTestRunner({ }) it("should search through the indexed data and return the correct results ordered and filtered [2]", async () => { + const shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + const payload = { title: "Test Giftcard", is_giftcard: true, description: "test-giftcard-description", + shipping_profile_id: shippingProfile.id, options: [{ title: "Denominations", values: ["100"] }], variants: new Array(10).fill(0).map((_, i) => ({ title: `Test variant ${i}`, @@ -171,9 +189,18 @@ medusaIntegrationTestRunner({ }) it.skip("should search through the indexed data and return the correct results ordered and filtered [3]", async () => { + const shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + const payloads = new Array(50).fill(0).map((_, a) => ({ title: "Test Giftcard-" + a, is_giftcard: true, + shipping_profile_id: shippingProfile.id, description: "test-giftcard-description" + a, options: [{ title: "Denominations", values: ["100"] }], variants: new Array(10).fill(0).map((_, i) => ({ diff --git a/integration-tests/modules/__tests__/modules/remote-query.spec.ts b/integration-tests/modules/__tests__/modules/remote-query.spec.ts index 1ba5eda80a..7256ff4ee1 100644 --- a/integration-tests/modules/__tests__/modules/remote-query.spec.ts +++ b/integration-tests/modules/__tests__/modules/remote-query.spec.ts @@ -209,9 +209,18 @@ medusaIntegrationTestRunner({ beforeEach(async () => { await createAdminUser(dbConnection, adminHeaders, appContainer) + const shippingProfile = ( + await api.post( + `/admin/shipping-profiles`, + { name: "Test", type: "default" }, + adminHeaders + ) + ).data.shipping_profile + const payload = { title: "Test Giftcard", is_giftcard: true, + shipping_profile_id: shippingProfile.id, description: "test-giftcard-description", options: [{ title: "Denominations", values: ["100"] }], variants: [ diff --git a/integration-tests/modules/__tests__/order/workflows/create-fulfillment.spec.ts b/integration-tests/modules/__tests__/order/workflows/create-fulfillment.spec.ts index d770eb3c4a..6a9e025c6e 100644 --- a/integration-tests/modules/__tests__/order/workflows/create-fulfillment.spec.ts +++ b/integration-tests/modules/__tests__/order/workflows/create-fulfillment.spec.ts @@ -130,6 +130,17 @@ async function prepareDataFixtures({ container }) { }, ]) + await remoteLink.create([ + { + [Modules.PRODUCT]: { + product_id: product.id, + }, + [Modules.FULFILLMENT]: { + shipping_profile_id: shippingProfile.id, + }, + }, + ]) + await remoteLink.create([ { [Modules.STOCK_LOCATION]: { diff --git a/integration-tests/modules/__tests__/order/workflows/create-shipment.spec.ts b/integration-tests/modules/__tests__/order/workflows/create-shipment.spec.ts index 7e31f754f1..477bc76d75 100644 --- a/integration-tests/modules/__tests__/order/workflows/create-shipment.spec.ts +++ b/integration-tests/modules/__tests__/order/workflows/create-shipment.spec.ts @@ -124,6 +124,17 @@ async function prepareDataFixtures({ container }) { }, ]) + await remoteLink.create([ + { + [Modules.PRODUCT]: { + product_id: product.id, + }, + [Modules.FULFILLMENT]: { + shipping_profile_id: shippingProfile.id, + }, + }, + ]) + await remoteLink.create([ { [Modules.STOCK_LOCATION]: { diff --git a/integration-tests/modules/__tests__/product/workflows/batch-products.spec.ts b/integration-tests/modules/__tests__/product/workflows/batch-products.spec.ts index 024e0cd8f7..f9d8f07836 100644 --- a/integration-tests/modules/__tests__/product/workflows/batch-products.spec.ts +++ b/integration-tests/modules/__tests__/product/workflows/batch-products.spec.ts @@ -4,7 +4,10 @@ import { batchProductVariantsWorkflow, batchProductVariantsWorkflowId, } from "@medusajs/core-flows" -import { IProductModuleService } from "@medusajs/types" +import { + IFulfillmentModuleService, + IProductModuleService, +} from "@medusajs/types" import { Modules } from "@medusajs/utils" import { medusaIntegrationTestRunner } from "@medusajs/test-utils" @@ -17,9 +20,20 @@ medusaIntegrationTestRunner({ let appContainer let service: IProductModuleService + let fulfullmentService: IFulfillmentModuleService + let shippingProfile + beforeAll(async () => { appContainer = getContainer() service = appContainer.resolve(Modules.PRODUCT) + fulfullmentService = appContainer.resolve(Modules.FULFILLMENT) + }) + + beforeEach(async () => { + shippingProfile = await fulfullmentService.createShippingProfiles({ + name: "Test", + type: "default", + }) }) describe("batchProductWorkflow", () => { @@ -43,7 +57,8 @@ medusaIntegrationTestRunner({ create: [ { title: "test3", - options: [{ title: "size", options: ["x"] }], + shipping_profile_id: shippingProfile.id, + options: [{ title: "size", values: ["x"] }], }, ], update: [{ id: product1.id, title: "test1-updated" }], @@ -94,6 +109,7 @@ medusaIntegrationTestRunner({ { title: "test1", options: [{ title: "size", values: ["x", "l", "m"] }], + shipping_profile_id: shippingProfile.id, variants: [ { title: "variant1", diff --git a/packages/admin/dashboard/src/components/common/sidebar-link/indext.ts b/packages/admin/dashboard/src/components/common/sidebar-link/indext.ts new file mode 100644 index 0000000000..e5d1811287 --- /dev/null +++ b/packages/admin/dashboard/src/components/common/sidebar-link/indext.ts @@ -0,0 +1 @@ +export * from "./sidebar-link" diff --git a/packages/admin/dashboard/src/components/common/sidebar-link/sidebar-link.tsx b/packages/admin/dashboard/src/components/common/sidebar-link/sidebar-link.tsx new file mode 100644 index 0000000000..cb2f9ffba6 --- /dev/null +++ b/packages/admin/dashboard/src/components/common/sidebar-link/sidebar-link.tsx @@ -0,0 +1,47 @@ +import { ReactNode } from "react" +import { Link } from "react-router-dom" + +import { IconAvatar } from "../icon-avatar" +import { Text } from "@medusajs/ui" +import { TriangleRightMini } from "@medusajs/icons" + +export interface SidebarLinkProps { + to: string + labelKey: string + descriptionKey: string + icon: ReactNode +} + +export const SidebarLink = ({ + to, + labelKey, + descriptionKey, + icon, +}: SidebarLinkProps) => { + return ( + +
+
+
+ {icon} +
+ + {labelKey} + + + {descriptionKey} + +
+
+ +
+
+
+
+ + ) +} diff --git a/packages/admin/dashboard/src/i18n/translations/$schema.json b/packages/admin/dashboard/src/i18n/translations/$schema.json index 4074870b15..63865d98f5 100644 --- a/packages/admin/dashboard/src/i18n/translations/$schema.json +++ b/packages/admin/dashboard/src/i18n/translations/$schema.json @@ -258,7 +258,11 @@ "type": "string" } }, - "required": ["header_one", "header_other", "description"], + "required": [ + "header_one", + "header_other", + "description" + ], "additionalProperties": false } }, @@ -307,7 +311,11 @@ "type": "string" } }, - "required": ["insertRowAbove", "insertRowBelow", "deleteRow"], + "required": [ + "insertRowAbove", + "insertRowBelow", + "deleteRow" + ], "additionalProperties": false }, "labels": { @@ -320,7 +328,10 @@ "type": "string" } }, - "required": ["key", "value"], + "required": [ + "key", + "value" + ], "additionalProperties": false }, "complexRow": { @@ -336,7 +347,11 @@ "type": "string" } }, - "required": ["label", "description", "tooltip"], + "required": [ + "label", + "description", + "tooltip" + ], "additionalProperties": false } }, @@ -351,7 +366,12 @@ "additionalProperties": false } }, - "required": ["header", "numberOfKeys_one", "numberOfKeys_other", "edit"], + "required": [ + "header", + "numberOfKeys_one", + "numberOfKeys_other", + "edit" + ], "additionalProperties": false }, "validation": { @@ -364,7 +384,10 @@ "type": "string" } }, - "required": ["mustBeInt", "mustBePositive"], + "required": [ + "mustBeInt", + "mustBePositive" + ], "additionalProperties": false }, "actions": { @@ -550,7 +573,9 @@ "type": "string" } }, - "required": ["in"], + "required": [ + "in" + ], "additionalProperties": false }, "app": { @@ -901,7 +926,12 @@ "type": "string" } }, - "required": ["label", "dark", "light", "system"], + "required": [ + "label", + "dark", + "light", + "system" + ], "additionalProperties": false } }, @@ -924,7 +954,10 @@ "type": "string" } }, - "required": ["label", "storeSettings"], + "required": [ + "label", + "storeSettings" + ], "additionalProperties": false }, "actions": { @@ -934,11 +967,17 @@ "type": "string" } }, - "required": ["logout"], + "required": [ + "logout" + ], "additionalProperties": false } }, - "required": ["user", "store", "actions"], + "required": [ + "user", + "store", + "actions" + ], "additionalProperties": false }, "nav": { @@ -954,7 +993,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "common": { @@ -964,7 +1006,9 @@ "type": "string" } }, - "required": ["extensions"], + "required": [ + "extensions" + ], "additionalProperties": false }, "main": { @@ -977,7 +1021,10 @@ "type": "string" } }, - "required": ["store", "storeSettings"], + "required": [ + "store", + "storeSettings" + ], "additionalProperties": false }, "settings": { @@ -996,15 +1043,30 @@ "type": "string" } }, - "required": ["header", "general", "developer", "myAccount"], + "required": [ + "header", + "general", + "developer", + "myAccount" + ], "additionalProperties": false } }, - "required": ["accessibility", "common", "main", "settings"], + "required": [ + "accessibility", + "common", + "main", + "settings" + ], "additionalProperties": false } }, - "required": ["search", "keyboardShortcuts", "menus", "nav"], + "required": [ + "search", + "keyboardShortcuts", + "menus", + "nav" + ], "additionalProperties": false }, "dataGrid": { @@ -1023,7 +1085,11 @@ "type": "string" } }, - "required": ["view", "resetToDefault", "disabled"], + "required": [ + "view", + "resetToDefault", + "disabled" + ], "additionalProperties": false }, "shortcuts": { @@ -1117,7 +1183,10 @@ "additionalProperties": false } }, - "required": ["label", "commands"], + "required": [ + "label", + "commands" + ], "additionalProperties": false }, "errors": { @@ -1133,11 +1202,19 @@ "type": "string" } }, - "required": ["fixError", "count_one", "count_other"], + "required": [ + "fixError", + "count_one", + "count_other" + ], "additionalProperties": false } }, - "required": ["columns", "shortcuts", "errors"], + "required": [ + "columns", + "shortcuts", + "errors" + ], "additionalProperties": false }, "filters": { @@ -1276,7 +1353,12 @@ "type": "string" } }, - "required": ["yes", "no", "true", "false"], + "required": [ + "yes", + "no", + "true", + "false" + ], "additionalProperties": false }, "addFilter": { @@ -1362,7 +1444,12 @@ "type": "string" } }, - "required": ["header", "editHeader", "editLabel", "label"], + "required": [ + "header", + "editHeader", + "editLabel", + "label" + ], "additionalProperties": false }, "billingAddress": { @@ -1421,7 +1508,11 @@ "type": "string" } }, - "required": ["editHeader", "editLabel", "label"], + "required": [ + "editHeader", + "editLabel", + "label" + ], "additionalProperties": false }, "transferOwnership": { @@ -1443,7 +1534,10 @@ "type": "string" } }, - "required": ["order", "draft"], + "required": [ + "order", + "draft" + ], "additionalProperties": false }, "currentOwner": { @@ -1456,7 +1550,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "newOwner": { @@ -1469,7 +1566,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "validation": { @@ -1482,7 +1582,10 @@ "type": "string" } }, - "required": ["mustBeDifferent", "required"], + "required": [ + "mustBeDifferent", + "required" + ], "additionalProperties": false } }, @@ -1503,7 +1606,9 @@ "type": "string" } }, - "required": ["availableIn"], + "required": [ + "availableIn" + ], "additionalProperties": false }, "products": { @@ -1519,7 +1624,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "edit": { @@ -1535,7 +1642,11 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false }, "create": { @@ -1566,7 +1677,12 @@ "type": "string" } }, - "required": ["details", "organize", "variants", "inventory"], + "required": [ + "details", + "organize", + "variants", + "inventory" + ], "additionalProperties": false }, "errors": { @@ -1582,7 +1698,11 @@ "type": "string" } }, - "required": ["variants", "options", "uniqueSku"], + "required": [ + "variants", + "options", + "uniqueSku" + ], "additionalProperties": false }, "inventory": { @@ -1628,7 +1748,9 @@ "type": "string" } }, - "required": ["placeholder"], + "required": [ + "placeholder" + ], "additionalProperties": false }, "optionValues": { @@ -1638,7 +1760,9 @@ "type": "string" } }, - "required": ["placeholder"], + "required": [ + "placeholder" + ], "additionalProperties": false }, "productVariants": { @@ -1657,7 +1781,12 @@ "type": "string" } }, - "required": ["label", "hint", "alert", "tip"], + "required": [ + "label", + "hint", + "alert", + "tip" + ], "additionalProperties": false }, "productOptions": { @@ -1670,7 +1799,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false } }, @@ -1720,7 +1852,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "filters": { @@ -1733,7 +1868,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "columns": { @@ -1746,7 +1884,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -1784,7 +1925,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "upload": { @@ -1825,7 +1969,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -1859,7 +2006,10 @@ "type": "string" } }, - "required": ["heading", "description"], + "required": [ + "heading", + "description" + ], "additionalProperties": false }, "filtered": { @@ -1872,11 +2022,18 @@ "type": "string" } }, - "required": ["heading", "description"], + "required": [ + "heading", + "description" + ], "additionalProperties": false } }, - "required": ["header", "empty", "filtered"], + "required": [ + "header", + "empty", + "filtered" + ], "additionalProperties": false }, "attributes": { @@ -1952,7 +2109,11 @@ "type": "string" } }, - "required": ["header", "description", "action"], + "required": [ + "header", + "description", + "action" + ], "additionalProperties": false }, "successToast": { @@ -2011,7 +2172,12 @@ "type": "string" } }, - "required": ["draft", "published", "proposed", "rejected"], + "required": [ + "draft", + "published", + "proposed", + "rejected" + ], "additionalProperties": false }, "fields": { @@ -2027,7 +2193,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "subtitle": { @@ -2037,7 +2206,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "handle": { @@ -2050,7 +2221,10 @@ "type": "string" } }, - "required": ["label", "tooltip"], + "required": [ + "label", + "tooltip" + ], "additionalProperties": false }, "description": { @@ -2063,7 +2237,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "discountable": { @@ -2076,7 +2253,26 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], + "additionalProperties": false + }, + "shipping_profile": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "hint": { + "type": "string" + } + }, + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "type": { @@ -2086,7 +2282,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "collection": { @@ -2096,7 +2294,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "categories": { @@ -2106,7 +2306,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "tags": { @@ -2116,7 +2318,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "sales_channels": { @@ -2129,7 +2333,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "countryOrigin": { @@ -2139,7 +2346,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "material": { @@ -2149,7 +2358,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "width": { @@ -2159,7 +2370,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "length": { @@ -2169,7 +2382,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "height": { @@ -2179,7 +2394,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "weight": { @@ -2189,7 +2406,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "options": { @@ -2238,7 +2457,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "mid_code": { @@ -2248,7 +2470,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "hs_code": { @@ -2258,7 +2482,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false } }, @@ -2268,6 +2494,7 @@ "handle", "description", "discountable", + "shipping_profile", "type", "collection", "categories", @@ -2299,7 +2526,10 @@ "type": "string" } }, - "required": ["header", "success"], + "required": [ + "header", + "success" + ], "additionalProperties": false }, "create": { @@ -2309,7 +2539,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "deleteWarning": { @@ -2355,7 +2587,10 @@ "type": "string" } }, - "required": ["inventoryItems", "inventoryKit"], + "required": [ + "inventoryItems", + "inventoryKit" + ], "additionalProperties": false }, "inventoryKit": { @@ -2374,7 +2609,10 @@ "type": "string" } }, - "required": ["itemId", "quantity"], + "required": [ + "itemId", + "quantity" + ], "additionalProperties": false }, "header": { @@ -2469,7 +2707,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "create": { @@ -2482,14 +2723,22 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "deleteWarning": { "type": "string" } }, - "required": ["header", "edit", "create", "deleteWarning"], + "required": [ + "header", + "edit", + "create", + "deleteWarning" + ], "additionalProperties": false }, "organization": { @@ -2511,15 +2760,23 @@ "type": "string" } }, - "required": ["success"], + "required": [ + "success" + ], "additionalProperties": false } }, - "required": ["header", "toasts"], + "required": [ + "header", + "toasts" + ], "additionalProperties": false } }, - "required": ["header", "edit"], + "required": [ + "header", + "edit" + ], "additionalProperties": false }, "stock": { @@ -2544,11 +2801,79 @@ "type": "string" } }, - "required": ["alreadyManaged", "alreadyManagedWithSku"], + "required": [ + "alreadyManaged", + "alreadyManagedWithSku" + ], "additionalProperties": false } }, - "required": ["heading", "description", "loading", "tooltips"], + "required": [ + "heading", + "description", + "loading", + "tooltips" + ], + "additionalProperties": false + }, + "shippingProfile": { + "type": "object", + "properties": { + "header": { + "type": "string" + }, + "edit": { + "type": "object", + "properties": { + "header": { + "type": "string" + }, + "toasts": { + "type": "object", + "properties": { + "success": { + "type": "string" + } + }, + "required": [ + "success" + ], + "additionalProperties": false + } + }, + "required": [ + "header", + "toasts" + ], + "additionalProperties": false + }, + "create": { + "type": "object", + "properties": { + "errors": { + "type": "object", + "properties": { + "required": { + "type": "string" + } + }, + "required": [ + "required" + ], + "additionalProperties": false + } + }, + "required": [ + "errors" + ], + "additionalProperties": false + } + }, + "required": [ + "header", + "edit", + "create" + ], "additionalProperties": false }, "toasts": { @@ -2567,7 +2892,10 @@ "type": "string" } }, - "required": ["header", "description"], + "required": [ + "header", + "description" + ], "additionalProperties": false }, "error": { @@ -2577,15 +2905,22 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false } }, - "required": ["success", "error"], + "required": [ + "success", + "error" + ], "additionalProperties": false } }, - "required": ["delete"], + "required": [ + "delete" + ], "additionalProperties": false } }, @@ -2614,6 +2949,7 @@ "options", "organization", "stock", + "shippingProfile", "toasts" ], "additionalProperties": false @@ -2664,7 +3000,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "add": { @@ -2677,7 +3015,10 @@ "type": "string" } }, - "required": ["successToast_one", "successToast_other"], + "required": [ + "successToast_one", + "successToast_other" + ], "additionalProperties": false }, "remove": { @@ -2690,11 +3031,18 @@ "type": "string" } }, - "required": ["successToast_one", "successToast_other"], + "required": [ + "successToast_one", + "successToast_other" + ], "additionalProperties": false } }, - "required": ["list", "add", "remove"], + "required": [ + "list", + "add", + "remove" + ], "additionalProperties": false } }, @@ -2742,14 +3090,22 @@ "type": "string" } }, - "required": ["details", "organize"], + "required": [ + "details", + "organize" + ], "additionalProperties": false }, "successToast": { "type": "string" } }, - "required": ["header", "hint", "tabs", "successToast"], + "required": [ + "header", + "hint", + "tabs", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -2765,7 +3121,11 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -2778,7 +3138,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "products": { @@ -2835,11 +3198,17 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["add", "remove", "list"], + "required": [ + "add", + "remove", + "list" + ], "additionalProperties": false }, "organize": { @@ -2852,7 +3221,10 @@ "type": "string" } }, - "required": ["header", "action"], + "required": [ + "header", + "action" + ], "additionalProperties": false }, "fields": { @@ -2871,7 +3243,11 @@ "type": "string" } }, - "required": ["label", "internal", "public"], + "required": [ + "label", + "internal", + "public" + ], "additionalProperties": false }, "status": { @@ -2887,7 +3263,11 @@ "type": "string" } }, - "required": ["label", "active", "inactive"], + "required": [ + "label", + "active", + "inactive" + ], "additionalProperties": false }, "path": { @@ -2900,7 +3280,10 @@ "type": "string" } }, - "required": ["label", "tooltip"], + "required": [ + "label", + "tooltip" + ], "additionalProperties": false }, "children": { @@ -2910,7 +3293,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "new": { @@ -2920,11 +3305,19 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false } }, - "required": ["visibility", "status", "path", "children", "new"], + "required": [ + "visibility", + "status", + "path", + "children", + "new" + ], "additionalProperties": false } }, @@ -3074,7 +3467,10 @@ "type": "string" } }, - "required": ["noAvaliableQuantity", "quantityOutOfRange"], + "required": [ + "noAvaliableQuantity", + "quantityOutOfRange" + ], "additionalProperties": false } }, @@ -3110,11 +3506,15 @@ "type": "string" } }, - "required": ["stockedQuantity"], + "required": [ + "stockedQuantity" + ], "additionalProperties": false } }, - "required": ["errors"], + "required": [ + "errors" + ], "additionalProperties": false }, "toast": { @@ -3130,7 +3530,11 @@ "type": "string" } }, - "required": ["updateLocations", "updateLevel", "updateItem"], + "required": [ + "updateLocations", + "updateLevel", + "updateItem" + ], "additionalProperties": false }, "stock": { @@ -3277,7 +3681,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "create": { @@ -3293,7 +3699,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "groups": { @@ -3318,7 +3728,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "add": { @@ -3334,11 +3746,16 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["success", "list"], + "required": [ + "success", + "list" + ], "additionalProperties": false }, "removed": { @@ -3354,11 +3771,16 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["success", "list"], + "required": [ + "success", + "list" + ], "additionalProperties": false } }, @@ -3386,7 +3808,11 @@ "type": "string" } }, - "required": ["header", "emailDisabledTooltip", "successToast"], + "required": [ + "header", + "emailDisabledTooltip", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -3402,7 +3828,11 @@ "type": "string" } }, - "required": ["title", "description", "successToast"], + "required": [ + "title", + "description", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -3418,7 +3848,11 @@ "type": "string" } }, - "required": ["guest", "registered", "groups"], + "required": [ + "guest", + "registered", + "groups" + ], "additionalProperties": false }, "registered": { @@ -3467,7 +3901,10 @@ "type": "string" } }, - "required": ["heading", "description"], + "required": [ + "heading", + "description" + ], "additionalProperties": false }, "filtered": { @@ -3480,11 +3917,17 @@ "type": "string" } }, - "required": ["heading", "description"], + "required": [ + "heading", + "description" + ], "additionalProperties": false } }, - "required": ["empty", "filtered"], + "required": [ + "empty", + "filtered" + ], "additionalProperties": false }, "create": { @@ -3500,7 +3943,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -3513,7 +3960,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -3529,7 +3979,11 @@ "type": "string" } }, - "required": ["title", "description", "successToast"], + "required": [ + "title", + "description", + "successToast" + ], "additionalProperties": false }, "customers": { @@ -3554,11 +4008,17 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["successToast_one", "successToast_other", "list"], + "required": [ + "successToast_one", + "successToast_other", + "list" + ], "additionalProperties": false }, "remove": { @@ -3592,11 +4052,18 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["alreadyAddedTooltip", "add", "remove", "list"], + "required": [ + "alreadyAddedTooltip", + "add", + "remove", + "list" + ], "additionalProperties": false } }, @@ -3642,7 +4109,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "status": { @@ -3970,7 +4439,10 @@ "type": "string" } }, - "required": ["title", "titlePending"], + "required": [ + "title", + "titlePending" + ], "additionalProperties": false }, "toast": { @@ -3983,7 +4455,10 @@ "type": "string" } }, - "required": ["canceledSuccessfully", "confirmedSuccessfully"], + "required": [ + "canceledSuccessfully", + "confirmedSuccessfully" + ], "additionalProperties": false }, "validation": { @@ -3993,7 +4468,9 @@ "type": "string" } }, - "required": ["quantityLowerThanFulfillment"], + "required": [ + "quantityLowerThanFulfillment" + ], "additionalProperties": false } }, @@ -4034,7 +4511,10 @@ "type": "string" } }, - "required": ["title", "requestSuccess"], + "required": [ + "title", + "requestSuccess" + ], "additionalProperties": false }, "shippingAddress": { @@ -4047,7 +4527,10 @@ "type": "string" } }, - "required": ["title", "requestSuccess"], + "required": [ + "title", + "requestSuccess" + ], "additionalProperties": false }, "billingAddress": { @@ -4060,11 +4543,18 @@ "type": "string" } }, - "required": ["title", "requestSuccess"], + "required": [ + "title", + "requestSuccess" + ], "additionalProperties": false } }, - "required": ["email", "shippingAddress", "billingAddress"], + "required": [ + "email", + "shippingAddress", + "billingAddress" + ], "additionalProperties": false }, "returns": { @@ -4170,7 +4660,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "placeholders": { @@ -4186,7 +4679,10 @@ "type": "string" } }, - "required": ["title", "hint"], + "required": [ + "title", + "hint" + ], "additionalProperties": false }, "outboundShippingOptions": { @@ -4199,7 +4695,10 @@ "type": "string" } }, - "required": ["title", "hint"], + "required": [ + "title", + "hint" + ], "additionalProperties": false } }, @@ -4284,7 +4783,10 @@ "type": "string" } }, - "required": ["canceledSuccessfully", "confirmedSuccessfully"], + "required": [ + "canceledSuccessfully", + "confirmedSuccessfully" + ], "additionalProperties": false }, "panel": { @@ -4297,7 +4799,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -4386,11 +4891,15 @@ "type": "string" } }, - "required": ["successToast"], + "required": [ + "successToast" + ], "additionalProperties": false } }, - "required": ["cancelClaim"], + "required": [ + "cancelClaim" + ], "additionalProperties": false }, "cancel": { @@ -4403,7 +4912,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "tooltips": { @@ -4413,7 +4925,9 @@ "type": "string" } }, - "required": ["onlyReturnShippingOptions"], + "required": [ + "onlyReturnShippingOptions" + ], "additionalProperties": false }, "toast": { @@ -4426,7 +4940,10 @@ "type": "string" } }, - "required": ["canceledSuccessfully", "confirmedSuccessfully"], + "required": [ + "canceledSuccessfully", + "confirmedSuccessfully" + ], "additionalProperties": false }, "panel": { @@ -4439,7 +4956,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -4509,11 +5029,15 @@ "type": "string" } }, - "required": ["successToast"], + "required": [ + "successToast" + ], "additionalProperties": false } }, - "required": ["cancelExchange"], + "required": [ + "cancelExchange" + ], "additionalProperties": false }, "cancel": { @@ -4526,7 +5050,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "tooltips": { @@ -4536,7 +5063,9 @@ "type": "string" } }, - "required": ["onlyReturnShippingOptions"], + "required": [ + "onlyReturnShippingOptions" + ], "additionalProperties": false }, "toast": { @@ -4549,7 +5078,10 @@ "type": "string" } }, - "required": ["canceledSuccessfully", "confirmedSuccessfully"], + "required": [ + "canceledSuccessfully", + "confirmedSuccessfully" + ], "additionalProperties": false }, "panel": { @@ -4562,7 +5094,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -4596,7 +5131,10 @@ "type": "string" } }, - "required": ["allocatedLabel", "notAllocatedLabel"], + "required": [ + "allocatedLabel", + "notAllocatedLabel" + ], "additionalProperties": false }, "allocateItems": { @@ -4633,7 +5171,9 @@ "type": "string" } }, - "required": ["created"], + "required": [ + "created" + ], "additionalProperties": false }, "error": { @@ -4643,7 +5183,9 @@ "type": "string" } }, - "required": ["quantityNotAllocated"], + "required": [ + "quantityNotAllocated" + ], "additionalProperties": false } }, @@ -4702,6 +5244,12 @@ "markAsDeliveredWarning": { "type": "string" }, + "differentOptionSelected": { + "type": "string" + }, + "disabledItemTooltip": { + "type": "string" + }, "unfulfilledItems": { "type": "string" }, @@ -4764,9 +5312,21 @@ }, "noItems": { "type": "string" + }, + "noShippingOption": { + "type": "string" + }, + "noLocation": { + "type": "string" } }, - "required": ["wrongQuantity", "wrongQuantity_other", "noItems"], + "required": [ + "wrongQuantity", + "wrongQuantity_other", + "noItems", + "noShippingOption", + "noLocation" + ], "additionalProperties": false }, "status": { @@ -4858,6 +5418,8 @@ "required": [ "cancelWarning", "markAsDeliveredWarning", + "differentOptionSelected", + "disabledItemTooltip", "unfulfilledItems", "statusLabel", "statusTitle", @@ -4912,7 +5474,11 @@ "type": "string" } }, - "required": ["amountToLarge", "amountNegative", "reasonRequired"], + "required": [ + "amountToLarge", + "amountNegative", + "reasonRequired" + ], "additionalProperties": false } }, @@ -5008,7 +5574,10 @@ "type": "string" } }, - "required": ["toReturn", "toSend"], + "required": [ + "toReturn", + "toSend" + ], "additionalProperties": false }, "placed": { @@ -5021,7 +5590,10 @@ "type": "string" } }, - "required": ["title", "fromSalesChannel"], + "required": [ + "title", + "fromSalesChannel" + ], "additionalProperties": false }, "canceled": { @@ -5031,7 +5603,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "payment": { @@ -5050,7 +5624,12 @@ "type": "string" } }, - "required": ["awaiting", "captured", "canceled", "refunded"], + "required": [ + "awaiting", + "captured", + "canceled", + "refunded" + ], "additionalProperties": false }, "fulfillment": { @@ -5123,7 +5702,10 @@ "type": "string" } }, - "required": ["comment", "byLine"], + "required": [ + "comment", + "byLine" + ], "additionalProperties": false }, "claim": { @@ -5184,7 +5766,10 @@ "type": "string" } }, - "required": ["requested", "confirmed"], + "required": [ + "requested", + "confirmed" + ], "additionalProperties": false }, "transfer": { @@ -5200,7 +5785,11 @@ "type": "string" } }, - "required": ["requested", "confirmed", "declined"], + "required": [ + "requested", + "confirmed", + "declined" + ], "additionalProperties": false }, "update_order": { @@ -5216,7 +5805,11 @@ "type": "string" } }, - "required": ["shipping_address", "billing_address", "email"], + "required": [ + "shipping_address", + "billing_address", + "email" + ], "additionalProperties": false } }, @@ -5261,7 +5854,11 @@ "type": "string" } }, - "required": ["displayId", "refundableAmount", "returnableQuantity"], + "required": [ + "displayId", + "refundableAmount", + "returnableQuantity" + ], "additionalProperties": false } }, @@ -5322,7 +5919,11 @@ "type": "string" } }, - "required": ["label", "warningTitle", "warningDescription"], + "required": [ + "label", + "warningTitle", + "warningDescription" + ], "additionalProperties": false }, "status": { @@ -5335,7 +5936,10 @@ "type": "string" } }, - "required": ["open", "completed"], + "required": [ + "open", + "completed" + ], "additionalProperties": false }, "create": { @@ -5476,7 +6080,9 @@ "type": "string" } }, - "required": ["description"], + "required": [ + "description" + ], "additionalProperties": false }, "create": { @@ -5492,7 +6098,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -5508,7 +6118,11 @@ "type": "string" } }, - "required": ["header", "viewInventory", "successToast"], + "required": [ + "header", + "viewInventory", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -5518,7 +6132,9 @@ "type": "string" } }, - "required": ["confirmation"], + "required": [ + "confirmation" + ], "additionalProperties": false }, "fulfillmentProviders": { @@ -5567,7 +6183,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "shipping": { @@ -5577,7 +6195,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "disable": { @@ -5593,7 +6213,11 @@ "type": "string" } }, - "required": ["confirmation", "pickup", "shipping"], + "required": [ + "confirmation", + "pickup", + "shipping" + ], "additionalProperties": false }, "enable": { @@ -5606,11 +6230,19 @@ "type": "string" } }, - "required": ["pickup", "shipping"], + "required": [ + "pickup", + "shipping" + ], "additionalProperties": false } }, - "required": ["pickup", "shipping", "disable", "enable"], + "required": [ + "pickup", + "shipping", + "disable", + "enable" + ], "additionalProperties": false }, "sidebar": { @@ -5629,11 +6261,17 @@ "type": "string" } }, - "required": ["label", "description"], + "required": [ + "label", + "description" + ], "additionalProperties": false } }, - "required": ["header", "shippingProfiles"], + "required": [ + "header", + "shippingProfiles" + ], "additionalProperties": false }, "salesChannels": { @@ -5690,7 +6328,12 @@ "type": "string" } }, - "required": ["header", "hint", "label", "successToast"], + "required": [ + "header", + "hint", + "label", + "successToast" + ], "additionalProperties": false }, "returns": { @@ -5709,7 +6352,12 @@ "type": "string" } }, - "required": ["header", "hint", "label", "successToast"], + "required": [ + "header", + "hint", + "label", + "successToast" + ], "additionalProperties": false }, "tabs": { @@ -5722,14 +6370,22 @@ "type": "string" } }, - "required": ["details", "prices"], + "required": [ + "details", + "prices" + ], "additionalProperties": false }, "action": { "type": "string" } }, - "required": ["shipping", "returns", "tabs", "action"], + "required": [ + "shipping", + "returns", + "tabs", + "action" + ], "additionalProperties": false }, "delete": { @@ -5742,7 +6398,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -5758,7 +6417,11 @@ "type": "string" } }, - "required": ["header", "action", "successToast"], + "required": [ + "header", + "action", + "successToast" + ], "additionalProperties": false }, "pricing": { @@ -5768,7 +6431,9 @@ "type": "string" } }, - "required": ["action"], + "required": [ + "action" + ], "additionalProperties": false }, "conditionalPrices": { @@ -5787,7 +6452,9 @@ "type": "string" } }, - "required": ["cartItemTotal"], + "required": [ + "cartItemTotal" + ], "additionalProperties": false }, "summaries": { @@ -5803,7 +6470,11 @@ "type": "string" } }, - "required": ["range", "greaterThan", "lessThan"], + "required": [ + "range", + "greaterThan", + "lessThan" + ], "additionalProperties": false }, "actions": { @@ -5816,7 +6487,10 @@ "type": "string" } }, - "required": ["addPrice", "manageConditionalPrices"], + "required": [ + "addPrice", + "manageConditionalPrices" + ], "additionalProperties": false }, "rules": { @@ -5832,7 +6506,11 @@ "type": "string" } }, - "required": ["amount", "gte", "lte"], + "required": [ + "amount", + "gte", + "lte" + ], "additionalProperties": false }, "customRules": { @@ -5854,7 +6532,13 @@ "type": "string" } }, - "required": ["label", "tooltip", "eq", "gt", "lt"], + "required": [ + "label", + "tooltip", + "eq", + "gt", + "lt" + ], "additionalProperties": false }, "errors": { @@ -5944,7 +6628,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "calculated": { @@ -5957,15 +6644,24 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false } }, - "required": ["fixed", "calculated"], + "required": [ + "fixed", + "calculated" + ], "additionalProperties": false } }, - "required": ["label", "options"], + "required": [ + "label", + "options" + ], "additionalProperties": false }, "enableInStore": { @@ -5978,7 +6674,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "provider": { @@ -6049,7 +6748,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -6062,7 +6764,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "manageAreas": { @@ -6084,7 +6789,13 @@ "type": "string" } }, - "required": ["header", "action", "label", "hint", "successToast"], + "required": [ + "header", + "action", + "label", + "hint", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -6097,11 +6808,20 @@ "type": "string" } }, - "required": ["noRecords", "tip"], + "required": [ + "noRecords", + "tip" + ], "additionalProperties": false } }, - "required": ["create", "edit", "delete", "manageAreas", "fields"], + "required": [ + "create", + "edit", + "delete", + "manageAreas", + "fields" + ], "additionalProperties": false } }, @@ -6142,7 +6862,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -6158,7 +6882,11 @@ "type": "string" } }, - "required": ["title", "description", "successToast"], + "required": [ + "title", + "description", + "successToast" + ], "additionalProperties": false }, "tooltip": { @@ -6168,11 +6896,19 @@ "type": "string" } }, - "required": ["type"], + "required": [ + "type" + ], "additionalProperties": false } }, - "required": ["domain", "subtitle", "create", "delete", "tooltip"], + "required": [ + "domain", + "subtitle", + "create", + "delete", + "tooltip" + ], "additionalProperties": false }, "taxRegions": { @@ -6188,7 +6924,9 @@ "type": "string" } }, - "required": ["hint"], + "required": [ + "hint" + ], "additionalProperties": false }, "delete": { @@ -6201,7 +6939,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "create": { @@ -6223,14 +6964,22 @@ "type": "string" } }, - "required": ["rateIsRequired", "nameIsRequired"], + "required": [ + "rateIsRequired", + "nameIsRequired" + ], "additionalProperties": false }, "successToast": { "type": "string" } }, - "required": ["header", "hint", "errors", "successToast"], + "required": [ + "header", + "hint", + "errors", + "successToast" + ], "additionalProperties": false }, "province": { @@ -6249,11 +6998,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "state": { @@ -6272,11 +7027,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "stateOrTerritory": { @@ -6295,11 +7056,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "county": { @@ -6318,11 +7085,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "region": { @@ -6341,11 +7114,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "department": { @@ -6364,11 +7143,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "territory": { @@ -6387,11 +7172,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "prefecture": { @@ -6410,11 +7201,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "district": { @@ -6433,11 +7230,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "governorate": { @@ -6456,11 +7259,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "canton": { @@ -6479,11 +7288,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "emirate": { @@ -6502,11 +7317,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "sublevel": { @@ -6525,11 +7346,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "taxOverrides": { @@ -6548,7 +7375,10 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false }, "edit": { @@ -6561,11 +7391,18 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create", "edit"], + "required": [ + "header", + "create", + "edit" + ], "additionalProperties": false }, "taxRates": { @@ -6584,7 +7421,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -6600,7 +7441,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -6613,11 +7458,18 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false } }, - "required": ["create", "edit", "delete"], + "required": [ + "create", + "edit", + "delete" + ], "additionalProperties": false }, "fields": { @@ -6639,7 +7491,12 @@ "type": "string" } }, - "required": ["label", "hint", "true", "false"], + "required": [ + "label", + "hint", + "true", + "false" + ], "additionalProperties": false }, "defaultTaxRate": { @@ -6655,7 +7512,11 @@ "type": "string" } }, - "required": ["label", "tooltip", "action"], + "required": [ + "label", + "tooltip", + "action" + ], "additionalProperties": false }, "taxRate": { @@ -6714,7 +7575,11 @@ "type": "string" } }, - "required": ["in", "on", "and"], + "required": [ + "in", + "on", + "and" + ], "additionalProperties": false }, "placeholders": { @@ -6780,7 +7645,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "values_one": { @@ -6952,7 +7819,10 @@ "type": "string" } }, - "required": ["sublevel", "notPartOfCountry"], + "required": [ + "sublevel", + "notPartOfCountry" + ], "additionalProperties": false }, "alert": { @@ -6968,11 +7838,20 @@ "type": "string" } }, - "required": ["header", "description", "action"], + "required": [ + "header", + "description", + "action" + ], "additionalProperties": false } }, - "required": ["labels", "placeholders", "tooltips", "alert"], + "required": [ + "labels", + "placeholders", + "tooltips", + "alert" + ], "additionalProperties": false }, "noDefaultRate": { @@ -6985,7 +7864,10 @@ "type": "string" } }, - "required": ["label", "tooltip"], + "required": [ + "label", + "tooltip" + ], "additionalProperties": false } }, @@ -7038,7 +7920,9 @@ "type": "string" } }, - "required": ["details"], + "required": [ + "details" + ], "additionalProperties": false }, "tabs": { @@ -7054,7 +7938,11 @@ "type": "string" } }, - "required": ["template", "details", "campaign"], + "required": [ + "template", + "details", + "campaign" + ], "additionalProperties": false }, "fields": { @@ -7091,7 +7979,9 @@ "type": "string" } }, - "required": ["tooltip"], + "required": [ + "tooltip" + ], "additionalProperties": false }, "conditions": { @@ -7107,7 +7997,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "target-rules": { @@ -7120,7 +8013,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "buy-rules": { @@ -7133,11 +8029,18 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["rules", "target-rules", "buy-rules"], + "required": [ + "rules", + "target-rules", + "buy-rules" + ], "additionalProperties": false } }, @@ -7162,7 +8065,9 @@ "type": "string" } }, - "required": ["campaignType"], + "required": [ + "campaignType" + ], "additionalProperties": false }, "errors": { @@ -7175,7 +8080,10 @@ "type": "string" } }, - "required": ["requiredField", "promotionTabError"], + "required": [ + "requiredField", + "promotionTabError" + ], "additionalProperties": false }, "toasts": { @@ -7185,7 +8093,9 @@ "type": "string" } }, - "required": ["promotionCreateSuccess"], + "required": [ + "promotionCreateSuccess" + ], "additionalProperties": false }, "create": { @@ -7207,7 +8117,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "target-rules": { @@ -7217,7 +8129,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "buy-rules": { @@ -7227,11 +8141,18 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false } }, - "required": ["title", "rules", "target-rules", "buy-rules"], + "required": [ + "title", + "rules", + "target-rules", + "buy-rules" + ], "additionalProperties": false }, "campaign": { @@ -7250,7 +8171,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "actions": { @@ -7260,11 +8184,17 @@ "type": "string" } }, - "required": ["goToCampaign"], + "required": [ + "goToCampaign" + ], "additionalProperties": false } }, - "required": ["header", "edit", "actions"], + "required": [ + "header", + "edit", + "actions" + ], "additionalProperties": false }, "campaign_currency": { @@ -7274,7 +8204,9 @@ "type": "string" } }, - "required": ["tooltip"], + "required": [ + "tooltip" + ], "additionalProperties": false }, "form": { @@ -7311,11 +8243,18 @@ "type": "string" } }, - "required": ["title", "desc"], + "required": [ + "title", + "desc" + ], "additionalProperties": false } }, - "required": ["title", "description", "placeholder"], + "required": [ + "title", + "description", + "placeholder" + ], "additionalProperties": false }, "new": { @@ -7328,7 +8267,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "none": { @@ -7341,11 +8283,18 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["existing", "new", "none"], + "required": [ + "existing", + "new", + "none" + ], "additionalProperties": false }, "status": { @@ -7364,7 +8313,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "active": { @@ -7377,7 +8329,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "inactive": { @@ -7390,11 +8345,19 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["label", "draft", "active", "inactive"], + "required": [ + "label", + "draft", + "active", + "inactive" + ], "additionalProperties": false }, "method": { @@ -7413,7 +8376,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "automatic": { @@ -7426,11 +8392,18 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["label", "code", "automatic"], + "required": [ + "label", + "code", + "automatic" + ], "additionalProperties": false }, "max_quantity": { @@ -7443,7 +8416,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "type": { @@ -7459,7 +8435,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "buyget": { @@ -7472,11 +8451,17 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["standard", "buyget"], + "required": [ + "standard", + "buyget" + ], "additionalProperties": false }, "allocation": { @@ -7492,7 +8477,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "across": { @@ -7505,11 +8493,17 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["each", "across"], + "required": [ + "each", + "across" + ], "additionalProperties": false }, "code": { @@ -7522,7 +8516,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "value": { @@ -7532,7 +8529,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "value_type": { @@ -7548,7 +8547,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "percentage": { @@ -7561,11 +8563,17 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["fixed", "percentage"], + "required": [ + "fixed", + "percentage" + ], "additionalProperties": false } }, @@ -7607,11 +8615,16 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["add", "list"], + "required": [ + "add", + "list" + ], "additionalProperties": false } }, @@ -7657,7 +8670,11 @@ "type": "string" } }, - "required": ["active", "expired", "scheduled"], + "required": [ + "active", + "expired", + "scheduled" + ], "additionalProperties": false }, "delete": { @@ -7673,7 +8690,11 @@ "type": "string" } }, - "required": ["title", "description", "successToast"], + "required": [ + "title", + "description", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -7689,7 +8710,11 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false }, "configuration": { @@ -7711,11 +8736,18 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false } }, - "required": ["header", "edit"], + "required": [ + "header", + "edit" + ], "additionalProperties": false }, "create": { @@ -7777,7 +8809,9 @@ "type": "string" } }, - "required": ["hint"], + "required": [ + "hint" + ], "additionalProperties": false } }, @@ -7806,7 +8840,10 @@ "type": "string" } }, - "required": ["hint", "header"], + "required": [ + "hint", + "header" + ], "additionalProperties": false }, "details": { @@ -7828,7 +8865,12 @@ "type": "string" } }, - "required": ["type", "currency", "limit", "used"], + "required": [ + "type", + "currency", + "limit", + "used" + ], "additionalProperties": false }, "type": { @@ -7844,7 +8886,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "usage": { @@ -7857,11 +8902,17 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["spend", "usage"], + "required": [ + "spend", + "usage" + ], "additionalProperties": false }, "edit": { @@ -7871,11 +8922,19 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false } }, - "required": ["create", "details", "fields", "type", "edit"], + "required": [ + "create", + "details", + "fields", + "type", + "edit" + ], "additionalProperties": false }, "promotions": { @@ -7891,7 +8950,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "alreadyAdded": { @@ -7910,7 +8972,9 @@ "type": "string" } }, - "required": ["success"], + "required": [ + "success" + ], "additionalProperties": false }, "add": { @@ -7923,11 +8987,15 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["list"], + "required": [ + "list" + ], "additionalProperties": false }, "list": { @@ -7937,7 +9005,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, @@ -7994,7 +9064,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "create": { @@ -8019,7 +9092,11 @@ "type": "string" } }, - "required": ["details", "products", "prices"], + "required": [ + "details", + "products", + "prices" + ], "additionalProperties": false }, "successToast": { @@ -8035,11 +9112,15 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["list"], + "required": [ + "list" + ], "additionalProperties": false } }, @@ -8062,7 +9143,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "configuration": { @@ -8084,11 +9168,18 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false } }, - "required": ["header", "edit"], + "required": [ + "header", + "edit" + ], "additionalProperties": false }, "products": { @@ -8107,7 +9198,10 @@ "type": "string" } }, - "required": ["addProducts", "editPrices"], + "required": [ + "addProducts", + "editPrices" + ], "additionalProperties": false }, "delete": { @@ -8141,7 +9235,9 @@ "type": "string" } }, - "required": ["successToast"], + "required": [ + "successToast" + ], "additionalProperties": false }, "edit": { @@ -8151,11 +9247,19 @@ "type": "string" } }, - "required": ["successToast"], + "required": [ + "successToast" + ], "additionalProperties": false } }, - "required": ["header", "actions", "delete", "add", "edit"], + "required": [ + "header", + "actions", + "delete", + "add", + "edit" + ], "additionalProperties": false }, "fields": { @@ -8171,7 +9275,10 @@ "type": "string" } }, - "required": ["label", "header"], + "required": [ + "label", + "header" + ], "additionalProperties": false }, "status": { @@ -8196,11 +9303,19 @@ "type": "string" } }, - "required": ["active", "draft", "expired", "scheduled"], + "required": [ + "active", + "draft", + "expired", + "scheduled" + ], "additionalProperties": false } }, - "required": ["label", "options"], + "required": [ + "label", + "options" + ], "additionalProperties": false }, "type": { @@ -8225,7 +9340,10 @@ "type": "string" } }, - "required": ["label", "description"], + "required": [ + "label", + "description" + ], "additionalProperties": false }, "override": { @@ -8238,15 +9356,25 @@ "type": "string" } }, - "required": ["label", "description"], + "required": [ + "label", + "description" + ], "additionalProperties": false } }, - "required": ["sale", "override"], + "required": [ + "sale", + "override" + ], "additionalProperties": false } }, - "required": ["label", "hint", "options"], + "required": [ + "label", + "hint", + "options" + ], "additionalProperties": false }, "startsAt": { @@ -8259,7 +9387,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "endsAt": { @@ -8272,7 +9403,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "customerAvailability": { @@ -8346,7 +9480,10 @@ "type": "string" } }, - "required": ["languageLabel", "usageInsightsLabel"], + "required": [ + "languageLabel", + "usageInsightsLabel" + ], "additionalProperties": false }, "edit": { @@ -8380,7 +9517,9 @@ "type": "string" } }, - "required": ["edit"], + "required": [ + "edit" + ], "additionalProperties": false } }, @@ -8445,7 +9584,11 @@ "type": "string" } }, - "required": ["accepted", "pending", "expired"], + "required": [ + "accepted", + "pending", + "expired" + ], "additionalProperties": false }, "roles": { @@ -8461,7 +9604,11 @@ "type": "string" } }, - "required": ["admin", "developer", "member"], + "required": [ + "admin", + "developer", + "member" + ], "additionalProperties": false }, "list": { @@ -8477,7 +9624,10 @@ "type": "string" } }, - "required": ["heading", "description"], + "required": [ + "heading", + "description" + ], "additionalProperties": false }, "filtered": { @@ -8490,11 +9640,17 @@ "type": "string" } }, - "required": ["heading", "description"], + "required": [ + "heading", + "description" + ], "additionalProperties": false } }, - "required": ["empty", "filtered"], + "required": [ + "empty", + "filtered" + ], "additionalProperties": false }, "deleteUserWarning": { @@ -8584,7 +9740,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "toast": { @@ -8706,7 +9864,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "toast": { @@ -8725,7 +9885,12 @@ "type": "string" } }, - "required": ["delete", "edit", "create", "countries"], + "required": [ + "delete", + "edit", + "create", + "countries" + ], "additionalProperties": false }, "shippingOption": { @@ -8759,7 +9924,12 @@ "type": "string" } }, - "required": ["outbound", "outboundHint", "return", "returnHint"], + "required": [ + "outbound", + "outboundHint", + "return", + "returnHint" + ], "additionalProperties": false }, "priceType": { @@ -8775,7 +9945,11 @@ "type": "string" } }, - "required": ["label", "flatRate", "calculated"], + "required": [ + "label", + "flatRate", + "calculated" + ], "additionalProperties": false }, "availability": { @@ -8788,7 +9962,10 @@ "type": "string" } }, - "required": ["adminOnly", "adminOnlyHint"], + "required": [ + "adminOnly", + "adminOnlyHint" + ], "additionalProperties": false }, "taxInclusiveHint": { @@ -8804,7 +9981,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false } }, @@ -8866,7 +10046,9 @@ "type": "string" } }, - "required": ["taxCountriesHint"], + "required": [ + "taxCountriesHint" + ], "additionalProperties": false }, "settings": { @@ -8920,7 +10102,9 @@ "type": "string" } }, - "required": ["sectionTitle"], + "required": [ + "sectionTitle" + ], "additionalProperties": false }, "taxRate": { @@ -9070,7 +10254,11 @@ "type": "string" } }, - "required": ["create", "update", "removeChannel"], + "required": [ + "create", + "update", + "removeChannel" + ], "additionalProperties": false } }, @@ -9100,7 +10288,11 @@ "type": "string" } }, - "required": ["domain", "subtitle", "deleteWarning"], + "required": [ + "domain", + "subtitle", + "deleteWarning" + ], "additionalProperties": false }, "salesChannels": { @@ -9152,7 +10344,11 @@ "type": "string" } }, - "required": ["create", "update", "delete"], + "required": [ + "create", + "update", + "delete" + ], "additionalProperties": false }, "tooltip": { @@ -9162,7 +10358,9 @@ "type": "string" } }, - "required": ["cannotDeleteDefault"], + "required": [ + "cannotDeleteDefault" + ], "additionalProperties": false }, "products": { @@ -9175,7 +10373,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "add": { @@ -9188,15 +10388,22 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["list"], + "required": [ + "list" + ], "additionalProperties": false } }, - "required": ["list", "add"], + "required": [ + "list", + "add" + ], "additionalProperties": false } }, @@ -9231,7 +10438,10 @@ "type": "string" } }, - "required": ["publishable", "secret"], + "required": [ + "publishable", + "secret" + ], "additionalProperties": false }, "subtitle": { @@ -9244,7 +10454,10 @@ "type": "string" } }, - "required": ["publishable", "secret"], + "required": [ + "publishable", + "secret" + ], "additionalProperties": false }, "status": { @@ -9257,7 +10470,10 @@ "type": "string" } }, - "required": ["active", "revoked"], + "required": [ + "active", + "revoked" + ], "additionalProperties": false }, "type": { @@ -9270,7 +10486,10 @@ "type": "string" } }, - "required": ["publishable", "secret"], + "required": [ + "publishable", + "secret" + ], "additionalProperties": false }, "create": { @@ -9330,7 +10549,11 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false }, "salesChannels": { @@ -9358,7 +10581,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, @@ -9382,7 +10607,10 @@ "type": "string" } }, - "required": ["warning", "successToast"], + "required": [ + "warning", + "successToast" + ], "additionalProperties": false }, "revoke": { @@ -9395,7 +10623,10 @@ "type": "string" } }, - "required": ["warning", "successToast"], + "required": [ + "warning", + "successToast" + ], "additionalProperties": false }, "addSalesChannels": { @@ -9408,11 +10639,15 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["list"], + "required": [ + "list" + ], "additionalProperties": false }, "removeSalesChannel": { @@ -9460,7 +10695,11 @@ "type": "string" } }, - "required": ["revoke", "copy", "copySuccessToast"], + "required": [ + "revoke", + "copy", + "copySuccessToast" + ], "additionalProperties": false }, "table": { @@ -9473,7 +10712,10 @@ "type": "string" } }, - "required": ["lastUsedAtHeader", "createdAtHeader"], + "required": [ + "lastUsedAtHeader", + "createdAtHeader" + ], "additionalProperties": false }, "fields": { @@ -9550,7 +10792,12 @@ "type": "string" } }, - "required": ["header", "subtitle", "hint", "successToast"], + "required": [ + "header", + "subtitle", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -9566,7 +10813,11 @@ "type": "string" } }, - "required": ["header", "subtitle", "successToast"], + "required": [ + "header", + "subtitle", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -9579,7 +10830,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -9598,7 +10852,11 @@ "type": "string" } }, - "required": ["label", "placeholder", "tooltip"], + "required": [ + "label", + "placeholder", + "tooltip" + ], "additionalProperties": false }, "label": { @@ -9611,7 +10869,10 @@ "type": "string" } }, - "required": ["label", "placeholder"], + "required": [ + "label", + "placeholder" + ], "additionalProperties": false }, "description": { @@ -9624,11 +10885,18 @@ "type": "string" } }, - "required": ["label", "placeholder"], + "required": [ + "label", + "placeholder" + ], "additionalProperties": false } }, - "required": ["value", "label", "description"], + "required": [ + "value", + "label", + "description" + ], "additionalProperties": false } }, @@ -9657,7 +10925,11 @@ "type": "string" } }, - "required": ["forgotPassword", "title", "hint"], + "required": [ + "forgotPassword", + "title", + "hint" + ], "additionalProperties": false }, "invite": { @@ -9709,7 +10981,9 @@ "type": "string" } }, - "required": ["accepted"], + "required": [ + "accepted" + ], "additionalProperties": false } }, @@ -9854,7 +11128,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "history": { @@ -9951,11 +11227,15 @@ "type": "string" } }, - "required": ["waitingToCompensate"], + "required": [ + "waitingToCompensate" + ], "additionalProperties": false } }, - "required": ["state"], + "required": [ + "state" + ], "additionalProperties": false }, "step": { @@ -9977,11 +11257,18 @@ "type": "string" } }, - "required": ["skipped", "skippedFailure", "dormant", "timeout"], + "required": [ + "skipped", + "skippedFailure", + "dormant", + "timeout" + ], "additionalProperties": false } }, - "required": ["state"], + "required": [ + "state" + ], "additionalProperties": false } }, @@ -10023,7 +11310,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -10036,7 +11327,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -10049,7 +11343,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -10059,11 +11356,20 @@ "type": "string" } }, - "required": ["value"], + "required": [ + "value" + ], "additionalProperties": false } }, - "required": ["domain", "subtitle", "create", "edit", "delete", "fields"], + "required": [ + "domain", + "subtitle", + "create", + "edit", + "delete", + "fields" + ], "additionalProperties": false }, "productTags": { @@ -10085,7 +11391,11 @@ "type": "string" } }, - "required": ["header", "subtitle", "successToast"], + "required": [ + "header", + "subtitle", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -10101,7 +11411,11 @@ "type": "string" } }, - "required": ["header", "subtitle", "successToast"], + "required": [ + "header", + "subtitle", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -10114,7 +11428,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -10124,11 +11441,19 @@ "type": "string" } }, - "required": ["value"], + "required": [ + "value" + ], "additionalProperties": false } }, - "required": ["domain", "create", "edit", "delete", "fields"], + "required": [ + "domain", + "create", + "edit", + "delete", + "fields" + ], "additionalProperties": false }, "notifications": { @@ -10147,7 +11472,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "accessibility": { @@ -10157,11 +11485,17 @@ "type": "string" } }, - "required": ["description"], + "required": [ + "description" + ], "additionalProperties": false } }, - "required": ["domain", "emptyState", "accessibility"], + "required": [ + "domain", + "emptyState", + "accessibility" + ], "additionalProperties": false }, "errors": { @@ -10174,7 +11508,10 @@ "type": "string" } }, - "required": ["serverError", "invalidCredentials"], + "required": [ + "serverError", + "invalidCredentials" + ], "additionalProperties": false }, "statuses": { @@ -10239,6 +11576,12 @@ }, "to": { "type": "string" + }, + "beaware": { + "type": "string" + }, + "loading": { + "type": "string" } }, "required": [ @@ -10249,7 +11592,9 @@ "added", "removed", "from", - "to" + "to", + "beaware", + "loading" ], "additionalProperties": false }, @@ -11005,4 +12350,4 @@ "dateTime" ], "additionalProperties": false -} +} \ No newline at end of file diff --git a/packages/admin/dashboard/src/i18n/translations/en.json b/packages/admin/dashboard/src/i18n/translations/en.json index 211c8d5855..f448d6bd2b 100644 --- a/packages/admin/dashboard/src/i18n/translations/en.json +++ b/packages/admin/dashboard/src/i18n/translations/en.json @@ -554,6 +554,10 @@ "label": "Discountable", "hint": "When unchecked, discounts will not be applied to this product" }, + "shipping_profile": { + "label": "Shipping profile", + "hint": "Connect the product to a shipping profile" + }, "type": { "label": "Type" }, @@ -681,6 +685,20 @@ "alreadyManagedWithSku": "This inventory item is already editable under {{title}} ({{sku}})." } }, + "shippingProfile": { + "header": "Shipping configuration", + "edit": { + "header": "Shipping Configuration", + "toasts": { + "success": "Successfully updated the shipping profile for {{title}}." + } + }, + "create": { + "errors": { + "required": "Shipping profile is required" + } + } + }, "toasts": { "delete": { "success": { @@ -1249,6 +1267,8 @@ "fulfillment": { "cancelWarning": "You are about to cancel a fulfillment. This action cannot be undone.", "markAsDeliveredWarning": "You are about to mark fulfillment as delivered. This action cannot be undone.", + "differentOptionSelected": "The selected shipping option is different from the one selected by the customer.", + "disabledItemTooltip": "The shipping option you have selected don’t allow fulfillment of this item", "unfulfilledItems": "Unfulfilled Items", "statusLabel": "Fulfillment status", "statusTitle": "Fulfillment Status", @@ -1269,7 +1289,9 @@ "error": { "wrongQuantity": "Only one item is available for fulfillment", "wrongQuantity_other": "Quantity should be a number between 1 and {{number}}", - "noItems": "No items to fulfill." + "noItems": "No items to fulfill.", + "noShippingOption": "Shipping option is required", + "noLocation": "Location is required" }, "status": { "notFulfilled": "Not fulfilled", @@ -2749,7 +2771,9 @@ "added": "Added", "removed": "Removed", "from": "From", - "to": "To" + "to": "To", + "beaware": "Be aware", + "loading": "Loading" }, "fields": { "amount": "Amount", diff --git a/packages/admin/dashboard/src/providers/router-provider/route-map.tsx b/packages/admin/dashboard/src/providers/router-provider/route-map.tsx index b00688df4b..fbcf8fab74 100644 --- a/packages/admin/dashboard/src/providers/router-provider/route-map.tsx +++ b/packages/admin/dashboard/src/providers/router-provider/route-map.tsx @@ -102,6 +102,13 @@ export const RouteMap: RouteObject[] = [ lazy: () => import("../../routes/products/product-organization"), }, + { + path: "shipping-profile", + lazy: () => + import( + "../../routes/products/product-shipping-profile" + ), + }, { path: "media", lazy: () => diff --git a/packages/admin/dashboard/src/routes/locations/location-list/location-list.tsx b/packages/admin/dashboard/src/routes/locations/location-list/location-list.tsx index e95b0bca3f..1f99f9241b 100644 --- a/packages/admin/dashboard/src/routes/locations/location-list/location-list.tsx +++ b/packages/admin/dashboard/src/routes/locations/location-list/location-list.tsx @@ -13,6 +13,7 @@ import { IconAvatar } from "../../../components/common/icon-avatar" import { TwoColumnPage } from "../../../components/layout/pages" import { useDashboardExtension } from "../../../extensions" import { LocationListHeader } from "./components/location-list-header" +import { SidebarLink } from "../../../components/common/sidebar-link/sidebar-link" export function LocationList() { const initialData = useLoaderData() as Awaited< @@ -61,47 +62,6 @@ export function LocationList() { ) } -interface SidebarLinkProps { - to: string - labelKey: string - descriptionKey: string - icon: ReactNode -} - -const SidebarLink = ({ - to, - labelKey, - descriptionKey, - icon, -}: SidebarLinkProps) => { - return ( - -
-
-
- {icon} -
- - {labelKey} - - - {descriptionKey} - -
-
- -
-
-
-
- - ) -} - const LinksSection = () => { const { t } = useTranslation() diff --git a/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/constants.ts b/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/constants.ts index ff4d473703..3b910980bf 100644 --- a/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/constants.ts +++ b/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/constants.ts @@ -2,7 +2,6 @@ import { z } from "zod" export const CreateFulfillmentSchema = z.object({ quantity: z.record(z.string(), z.number()), - location_id: z.string(), shipping_option_id: z.string().optional(), send_notification: z.boolean().optional(), diff --git a/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/order-create-fulfillment-form.tsx b/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/order-create-fulfillment-form.tsx index 96bd533159..fc69ea2610 100644 --- a/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/order-create-fulfillment-form.tsx +++ b/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/order-create-fulfillment-form.tsx @@ -3,7 +3,7 @@ import { useEffect, useMemo, useState } from "react" import { useTranslation } from "react-i18next" import * as zod from "zod" -import { AdminOrder } from "@medusajs/types" +import { AdminOrder, HttpTypes } from "@medusajs/types" import { Alert, Button, Select, Switch, toast } from "@medusajs/ui" import { useForm, useWatch } from "react-hook-form" @@ -19,7 +19,10 @@ import { useStockLocations } from "../../../../../hooks/api/stock-locations" import { getFulfillableQuantity } from "../../../../../lib/order-item" import { CreateFulfillmentSchema } from "./constants" import { OrderCreateFulfillmentItem } from "./order-create-fulfillment-item" -import { useReservationItems } from "../../../../../hooks/api" +import { + useReservationItems, + useShippingOptions, +} from "../../../../../hooks/api" type OrderCreateFulfillmentFormProps = { order: AdminOrder @@ -56,30 +59,86 @@ export function OrderCreateFulfillmentForm({ const form = useForm>({ defaultValues: { - quantity: fulfillableItems.reduce((acc, item) => { - acc[item.id] = getFulfillableQuantity(item) - return acc - }, {} as Record), + quantity: fulfillableItems.reduce( + (acc, item) => { + acc[item.id] = getFulfillableQuantity(item) + return acc + }, + {} as Record + ), send_notification: !order.no_notification, }, resolver: zodResolver(CreateFulfillmentSchema), }) + const selectedLocationId = useWatch({ + name: "location_id", + control: form.control, + }) + const { stock_locations = [] } = useStockLocations() + const { shipping_options = [], isLoading: isShippingOptionsLoading } = + useShippingOptions({ + stock_location_id: selectedLocationId, + // is_return: false, // TODO: 500 when enabled + fields: "+service_zone.fulfillment_set.location.id", + }) + + const shippingOptionId = useWatch({ + name: "shipping_option_id", + control: form.control, + }) + const handleSubmit = form.handleSubmit(async (data) => { - try { - await createOrderFulfillment({ - location_id: data.location_id, - // shipping_option_id: data.shipping_option_id, - no_notification: !data.send_notification, - items: Object.entries(data.quantity) - .filter(([, value]) => !!value) - .map(([id, quantity]) => ({ - id, - quantity, - })), + const selectedShippingOption = shipping_options.find( + (o) => o.id === shippingOptionId + ) + + if (!selectedShippingOption) { + form.setError("shipping_option_id", { + type: "manual", + message: t("orders.fulfillment.error.noShippingOption"), }) + return + } + + if (!selectedLocationId) { + form.setError("location_id", { + type: "manual", + message: t("orders.fulfillment.error.noLocation"), + }) + return + } + + const selectedShippingProfileId = + selectedShippingOption?.shipping_profile_id + + const itemShippingProfileMap = order.items.reduce( + (acc, item) => { + acc[item.id] = item.variant?.product?.shipping_profile?.id + return acc + }, + {} as Record + ) + + const payload: HttpTypes.AdminCreateOrderFulfillment = { + location_id: selectedLocationId, + shipping_option_id: shippingOptionId, + no_notification: !data.send_notification, + items: Object.entries(data.quantity) + .filter( + ([id, value]) => + !!value && itemShippingProfileMap[id] === selectedShippingProfileId + ) + .map(([id, quantity]) => ({ + id, + quantity, + })), + } + + try { + await createOrderFulfillment(payload) toast.success(t("orders.fulfillment.toast.created")) handleSuccess(`/orders/${order.id}`) @@ -89,15 +148,28 @@ export function OrderCreateFulfillmentForm({ }) useEffect(() => { - if (stock_locations?.length) { - form.setValue("location_id", stock_locations[0].id) - } - }, [stock_locations?.length]) + if (stock_locations?.length && shipping_options?.length) { + const initialShippingOptionId = + order.shipping_methods?.[0]?.shipping_option_id - const selectedLocationId = useWatch({ - name: "location_id", - control: form.control, - }) + if (initialShippingOptionId) { + const shippingOption = shipping_options.find( + (o) => o.id === initialShippingOptionId + ) + + if (shippingOption) { + const locationId = + shippingOption.service_zone.fulfillment_set.location.id + + form.setValue("location_id", locationId) + form.setValue( + "shipping_option_id", + initialShippingOptionId || undefined + ) + } // else -> TODO: what if original shipping option is deleted? + } + } + }, [stock_locations?.length, shipping_options?.length]) const fulfilledQuantityArray = (order.items || []).map( (item) => @@ -124,14 +196,21 @@ export function OrderCreateFulfillmentForm({ }) } - const quantityMap = itemsToFulfill.reduce((acc, item) => { - acc[item.id] = getFulfillableQuantity(item as OrderLineItemDTO) - return acc - }, {} as Record) + const quantityMap = itemsToFulfill.reduce( + (acc, item) => { + acc[item.id] = getFulfillableQuantity(item as OrderLineItemDTO) + return acc + }, + {} as Record + ) form.setValue("quantity", quantityMap) }, [...fulfilledQuantityArray, requiresShipping]) + const differentOptionSelected = + shippingOptionId && + order.shipping_methods?.[0]?.shipping_option_id !== shippingOptionId + return ( - {/*
*/} - {/* {*/} - {/* return (*/} - {/* */} - {/*
*/} - {/*
*/} - {/* */} - {/* {t("fields.shippingMethod")}*/} - {/* */} - {/* */} - {/* {t("orders.fulfillment.methodDescription")}*/} - {/* */} - {/*
*/} - {/*
*/} - {/* */} - {/* */} - {/* */} - {/*
*/} - {/*
*/} - {/* */} - {/*
*/} - {/* )*/} - {/* }}*/} - {/* />*/} - {/*
*/} +
+ { + return ( + +
+
+ + {t("fields.shippingMethod")} + + + {t("orders.fulfillment.methodDescription")} + +
+
+ + + +
+
+ +
+ ) + }} + /> + + {differentOptionSelected && ( + + + {t("labels.beaware")} + + + {t("orders.fulfillment.differentOptionSelected")} + + + )} +
@@ -238,12 +338,19 @@ export function OrderCreateFulfillmentForm({
{fulfillableItems.map((item) => { + const isShippingProfileMatching = + shipping_options.find( + (o) => o.id === shippingOptionId + )?.shipping_profile_id === + item.variant?.product?.shipping_profile?.id + return ( -
diff --git a/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/order-create-fulfillment-item.tsx b/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/order-create-fulfillment-item.tsx index 307c3516c1..a3d335519f 100644 --- a/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/order-create-fulfillment-item.tsx +++ b/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/order-create-fulfillment-item.tsx @@ -1,7 +1,7 @@ import { useMemo } from "react" import { useTranslation } from "react-i18next" import * as zod from "zod" -import { Input, Text } from "@medusajs/ui" +import { clx, Input, Text, Tooltip } from "@medusajs/ui" import { UseFormReturn } from "react-hook-form" import { HttpTypes } from "@medusajs/types" @@ -10,6 +10,7 @@ import { Thumbnail } from "../../../../../components/common/thumbnail/index" import { useProductVariant } from "../../../../../hooks/api/products" import { getFulfillableQuantity } from "../../../../../lib/order-item" import { CreateFulfillmentSchema } from "./constants" +import { InformationCircleSolid } from "@medusajs/icons" type OrderEditItemProps = { item: HttpTypes.AdminOrderLineItem @@ -18,6 +19,7 @@ type OrderEditItemProps = { onItemRemove: (itemId: string) => void itemReservedQuantitiesMap: Map form: UseFormReturn> + disabled: boolean } export function OrderCreateFulfillmentItem({ @@ -25,6 +27,7 @@ export function OrderCreateFulfillmentItem({ form, locationId, itemReservedQuantitiesMap, + disabled, }: OrderEditItemProps) { const { t } = useTranslation() @@ -70,102 +73,120 @@ export function OrderCreateFulfillmentItem({ ) return ( -
-
-
- -
-
- - {item.title} - - {item.variant_sku && ({item.variant_sku})} -
- - {item.variant_title} - +
+
+ {disabled && ( +
+ + +
-
+ )} -
-
- -
- - {t("orders.fulfillment.available")} - - - {availableQuantity || "N/A"} - +
+
+ +
+
+ + {item.title} + + {item.variant_sku && ({item.variant_sku})} +
+ + {item.variant_title} + +
-
+
- {t("orders.fulfillment.inStock")} + {t("orders.fulfillment.available")} - {inStockQuantity || "N/A"}{" "} - {inStockQuantity && ( - - -{form.getValues(`quantity.${item.id}`)} - - )} + {availableQuantity || "N/A"}
-
-
- { - return ( - - - { - const val = - e.target.value === "" - ? null - : Number(e.target.value) +
+
- field.onChange(val) +
+ + {t("orders.fulfillment.inStock")} + + + {inStockQuantity || "N/A"}{" "} + {inStockQuantity && ( + + -{form.getValues(`quantity.${item.id}`)} + + )} + +
+
- if (!isNaN(val)) { - if (val < minValue || val > maxValue) { - form.setError(`quantity.${item.id}`, { - type: "manual", - message: t( - "orders.fulfillment.error.wrongQuantity", - { - count: maxValue, - number: maxValue, - } - ), - }) - } else { - form.clearErrors(`quantity.${item.id}`) +
+ { + return ( + + + { + const val = + e.target.value === "" + ? null + : Number(e.target.value) + + field.onChange(val) + + if (!isNaN(val)) { + if (val < minValue || val > maxValue) { + form.setError(`quantity.${item.id}`, { + type: "manual", + message: t( + "orders.fulfillment.error.wrongQuantity", + { + count: maxValue, + number: maxValue, + } + ), + }) + } else { + form.clearErrors(`quantity.${item.id}`) + } } - } - }} - /> - - - - ) - }} - /> + }} + /> + + + + ) + }} + /> - - / {item.quantity} {t("fields.qty")} - + + / {item.quantity} {t("fields.qty")} + +
diff --git a/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/order-create-fulfillments.tsx b/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/order-create-fulfillments.tsx index a79277383b..770c455c2c 100644 --- a/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/order-create-fulfillments.tsx +++ b/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/order-create-fulfillments.tsx @@ -10,7 +10,8 @@ export function OrderCreateFulfillment() { const requiresShipping = searchParams.get("requires_shipping") === "true" const { order, isLoading, isError, error } = useOrder(id!, { - fields: "currency_code,*items,*items.variant,*shipping_address", + fields: + "currency_code,*items,*items.variant,+items.variant.product.shipping_profile.id,*shipping_address,+shipping_methods.shipping_option_id", }) if (isError) { diff --git a/packages/admin/dashboard/src/routes/products/product-create/components/product-create-form/product-create-form.tsx b/packages/admin/dashboard/src/routes/products/product-create/components/product-create-form/product-create-form.tsx index f8bdcdc76c..a366cc195d 100644 --- a/packages/admin/dashboard/src/routes/products/product-create/components/product-create-form/product-create-form.tsx +++ b/packages/admin/dashboard/src/routes/products/product-create/components/product-create-form/product-create-form.tsx @@ -79,10 +79,13 @@ export const ProductCreateForm = ({ return {} } - return regions.reduce((acc, reg) => { - acc[reg.id] = reg.currency_code - return acc - }, {} as Record) + return regions.reduce( + (acc, reg) => { + acc[reg.id] = reg.currency_code + return acc + }, + {} as Record + ) }, [regions]) /** @@ -178,6 +181,15 @@ export const ProductCreateForm = ({ } if (currentTab === Tab.ORGANIZE) { + // TODO: this is temp until we add partial validation per tab + if (!form.getValues("shipping_profile_id")) { + form.setError("shipping_profile_id", { + type: "required", + message: t("products.shippingProfile.create.errors.required"), + }) + return + } + setTab(Tab.VARIANTS) } @@ -208,7 +220,8 @@ export const ProductCreateForm = ({ } setTabState({ ...currentState }) - }, [tab, tabState]) + // eslint-disable-next-line react-hooks/exhaustive-deps -- we only want this effect to run when the tab changes + }, [tab]) return ( diff --git a/packages/admin/dashboard/src/routes/products/product-create/components/product-create-organize-form/components/product-create-organize-section/product-create-details-organize-section.tsx b/packages/admin/dashboard/src/routes/products/product-create/components/product-create-organize-form/components/product-create-organize-section/product-create-details-organize-section.tsx index b5ff5a206c..dcd2a4f452 100644 --- a/packages/admin/dashboard/src/routes/products/product-create/components/product-create-organize-form/components/product-create-organize-section/product-create-details-organize-section.tsx +++ b/packages/admin/dashboard/src/routes/products/product-create/components/product-create-organize-form/components/product-create-organize-section/product-create-details-organize-section.tsx @@ -51,6 +51,16 @@ export const ProductCreateOrganizationSection = ({ })), }) + const shippingProfiles = useComboboxData({ + queryKey: ["shipping_profiles"], + queryFn: (params) => sdk.admin.shippingProfile.list(params), + getOptions: (data) => + data.shipping_profiles.map((shippingProfile) => ({ + label: shippingProfile.name, + value: shippingProfile.id, + })), + }) + const { fields, remove, replace } = useFieldArray({ control: form.control, name: "sales_channels", @@ -161,6 +171,34 @@ export const ProductCreateOrganizationSection = ({ }} />
+
+
+ {t("products.fields.shipping_profile.label")} + + + +
+ { + return ( + + + + + + + ) + }} + /> +
({ id })), type_id: values.type_id || undefined, handle: values.handle || undefined, diff --git a/packages/admin/dashboard/src/routes/products/product-detail/components/product-shipping-profile-section/index.ts b/packages/admin/dashboard/src/routes/products/product-detail/components/product-shipping-profile-section/index.ts new file mode 100644 index 0000000000..9ff25fe9b3 --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-detail/components/product-shipping-profile-section/index.ts @@ -0,0 +1 @@ +export * from "./product-shipping-profile-section" diff --git a/packages/admin/dashboard/src/routes/products/product-detail/components/product-shipping-profile-section/product-shipping-profile-section.tsx b/packages/admin/dashboard/src/routes/products/product-detail/components/product-shipping-profile-section/product-shipping-profile-section.tsx new file mode 100644 index 0000000000..23bead55d7 --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-detail/components/product-shipping-profile-section/product-shipping-profile-section.tsx @@ -0,0 +1,53 @@ +import { PencilSquare, ShoppingBag } from "@medusajs/icons" +import { HttpTypes } from "@medusajs/types" +import { Container, Heading } from "@medusajs/ui" +import { useTranslation } from "react-i18next" + +import { SidebarLink } from "../../../../../components/common/sidebar-link/sidebar-link" +import { ActionMenu } from "../../../../../components/common/action-menu" + +type ProductShippingProfileSectionProps = { + product: HttpTypes.AdminProduct & { + shipping_profile: HttpTypes.AdminShippingProfile + } +} + +export const ProductShippingProfileSection = ({ + product, +}: ProductShippingProfileSectionProps) => { + const { t } = useTranslation() + + const shippingProfile = product.shipping_profile + + if (!shippingProfile) { + return null + } + + return ( + +
+ {t("products.shippingProfile.header")} + , + }, + ], + }, + ]} + /> +
+ + } + /> +
+ ) +} diff --git a/packages/admin/dashboard/src/routes/products/product-detail/constants.ts b/packages/admin/dashboard/src/routes/products/product-detail/constants.ts index bb615be74c..fcc4006988 100644 --- a/packages/admin/dashboard/src/routes/products/product-detail/constants.ts +++ b/packages/admin/dashboard/src/routes/products/product-detail/constants.ts @@ -2,5 +2,5 @@ import { getLinkedFields } from "../../../extensions" export const PRODUCT_DETAIL_FIELDS = getLinkedFields( "product", - "*categories,-variants" + "*categories,*shipping_profile,-variants" ) diff --git a/packages/admin/dashboard/src/routes/products/product-detail/product-detail.tsx b/packages/admin/dashboard/src/routes/products/product-detail/product-detail.tsx index 4f8db3e2f5..78ece96f60 100644 --- a/packages/admin/dashboard/src/routes/products/product-detail/product-detail.tsx +++ b/packages/admin/dashboard/src/routes/products/product-detail/product-detail.tsx @@ -14,6 +14,7 @@ import { PRODUCT_DETAIL_FIELDS } from "./constants" import { productLoader } from "./loader" import { useDashboardExtension } from "../../../extensions" +import { ProductShippingProfileSection } from "./components/product-shipping-profile-section" export const ProductDetail = () => { const initialData = useLoaderData() as Awaited< @@ -71,6 +72,7 @@ export const ProductDetail = () => { + diff --git a/packages/admin/dashboard/src/routes/products/product-shipping-profile/components/product-organization-form/index.ts b/packages/admin/dashboard/src/routes/products/product-shipping-profile/components/product-organization-form/index.ts new file mode 100644 index 0000000000..7f9da9dbad --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-shipping-profile/components/product-organization-form/index.ts @@ -0,0 +1 @@ +export * from "./product-shipping-profile-form" diff --git a/packages/admin/dashboard/src/routes/products/product-shipping-profile/components/product-organization-form/product-shipping-profile-form.tsx b/packages/admin/dashboard/src/routes/products/product-shipping-profile/components/product-organization-form/product-shipping-profile-form.tsx new file mode 100644 index 0000000000..ef15e13326 --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-shipping-profile/components/product-organization-form/product-shipping-profile-form.tsx @@ -0,0 +1,122 @@ +import { HttpTypes } from "@medusajs/types" +import { Button, toast } from "@medusajs/ui" +import { useTranslation } from "react-i18next" +import * as zod from "zod" + +import { Form } from "../../../../../components/common/form" +import { Combobox } from "../../../../../components/inputs/combobox" +import { RouteDrawer, useRouteModal } from "../../../../../components/modals" +import { KeyboundForm } from "../../../../../components/utilities/keybound-form" +import { useExtendableForm } from "../../../../../extensions" +import { useUpdateProduct } from "../../../../../hooks/api/products" +import { useComboboxData } from "../../../../../hooks/use-combobox-data" +import { sdk } from "../../../../../lib/client" +import { useForm } from "react-hook-form" +import { zodResolver } from "@hookform/resolvers/zod" + +type ProductShippingProfileFormProps = { + product: HttpTypes.AdminProduct & { + shipping_profile?: HttpTypes.AdminShippingProfile + } +} + +const ProductShippingProfileSchema = zod.object({ + shipping_profile_id: zod.string(), +}) + +export const ProductShippingProfileForm = ({ + product, +}: ProductShippingProfileFormProps) => { + const { t } = useTranslation() + const { handleSuccess } = useRouteModal() + + const shippingProfiles = useComboboxData({ + queryKey: ["shipping_profiles"], + queryFn: (params) => sdk.admin.shippingProfile.list(params), + getOptions: (data) => + data.shipping_profiles.map((shippingProfile) => ({ + label: shippingProfile.name, + value: shippingProfile.id, + })), + }) + + const form = useForm({ + defaultValues: { + shipping_profile_id: product.shipping_profile?.id ?? "", + }, + resolver: zodResolver(ProductShippingProfileSchema), + }) + + const { mutateAsync, isPending } = useUpdateProduct(product.id) + + const handleSubmit = form.handleSubmit(async (data) => { + await mutateAsync( + { + shipping_profile_id: data.shipping_profile_id, + }, + { + onSuccess: ({ product }) => { + toast.success( + t("products.shippingProfile.edit.toasts.success", { + title: product.title, + }) + ) + handleSuccess() + }, + onError: (error) => { + toast.error(error.message) + }, + } + ) + }) + + return ( + + + +
+ { + return ( + + + {t("products.fields.shipping_profile.label")} + + + + + + + ) + }} + /> + + {/* */} +
+
+ +
+ + + + +
+
+
+
+ ) +} diff --git a/packages/admin/dashboard/src/routes/products/product-shipping-profile/index.ts b/packages/admin/dashboard/src/routes/products/product-shipping-profile/index.ts new file mode 100644 index 0000000000..8c833001df --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-shipping-profile/index.ts @@ -0,0 +1 @@ +export { ProductShippingProfile as Component } from "./product-shipping-profile" diff --git a/packages/admin/dashboard/src/routes/products/product-shipping-profile/product-shipping-profile.tsx b/packages/admin/dashboard/src/routes/products/product-shipping-profile/product-shipping-profile.tsx new file mode 100644 index 0000000000..e3d09d5f8c --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-shipping-profile/product-shipping-profile.tsx @@ -0,0 +1,34 @@ +import { Heading } from "@medusajs/ui" +import { useTranslation } from "react-i18next" +import { useParams } from "react-router-dom" + +import { RouteDrawer } from "../../../components/modals" +import { useProduct } from "../../../hooks/api/products" +import { PRODUCT_DETAIL_FIELDS } from "../product-detail/constants" +import { ProductShippingProfileForm } from "./components/product-organization-form" + +export const ProductShippingProfile = () => { + const { id } = useParams() + const { t } = useTranslation() + + const { product, isLoading, isError, error } = useProduct(id!, { + fields: PRODUCT_DETAIL_FIELDS, + }) + + if (isError) { + throw error + } + + return ( + + + + {t("products.shippingProfile.edit.header")} + + + {!isLoading && product && ( + + )} + + ) +} diff --git a/packages/core/core-flows/src/order/workflows/create-fulfillment.ts b/packages/core/core-flows/src/order/workflows/create-fulfillment.ts index d46b351ecf..8f4304eacb 100644 --- a/packages/core/core-flows/src/order/workflows/create-fulfillment.ts +++ b/packages/core/core-flows/src/order/workflows/create-fulfillment.ts @@ -58,14 +58,14 @@ export type CreateFulfillmentValidateOrderStepInput = { * This step validates that a fulfillment can be created for an order. If the order * is canceled, the items don't exist in the order, or the items aren't grouped by * shipping requirement, the step throws an error. - * + * * :::note - * + * * You can retrieve an order's details using [Query](https://docs.medusajs.com/learn/fundamentals/module-links/query), * or [useQueryGraphStep](https://docs.medusajs.com/resources/references/medusa-workflows/steps/useQueryGraphStep). - * + * * ::: - * + * * @example * const data = createFulfillmentValidateOrder({ * order: { @@ -82,10 +82,7 @@ export type CreateFulfillmentValidateOrderStepInput = { */ export const createFulfillmentValidateOrder = createStep( "create-fulfillment-validate-order", - ({ - order, - inputItems, - }: CreateFulfillmentValidateOrderStepInput) => { + ({ order, inputItems }: CreateFulfillmentValidateOrderStepInput) => { throwIfOrderIsCancelled({ order }) throwIfItemsDoesNotExistsInOrder({ order, inputItems }) throwIfItemsAreNotGroupedByShippingRequirement({ order, inputItems }) @@ -128,6 +125,7 @@ function prepareFulfillmentData({ id: string provider_id: string service_zone: { fulfillment_set: { location?: { id: string } } } + shipping_profile_id: string } shippingMethod: { data?: Record | null } reservations: ReservationItemDTO[] @@ -156,6 +154,18 @@ function prepareFulfillmentData({ const orderItem = orderItemsMap.get(i.id)! const reservation = reservationItemMap.get(i.id)! + if ( + orderItem.requires_shipping && + (orderItem as any).variant?.product && + (orderItem as any).variant?.product.shipping_profile?.id !== + shippingOption.shipping_profile_id + ) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Shipping profile ${shippingOption.shipping_profile_id} does not match the shipping profile of the order item ${orderItem.id}` + ) + } + return { line_item_id: i.id, inventory_item_id: reservation?.inventory_item_id, @@ -273,17 +283,18 @@ function prepareInventoryUpdate({ /** * The details of the fulfillment to create, along with custom data that's passed to the workflow's hooks. */ -export type CreateOrderFulfillmentWorkflowInput = OrderWorkflow.CreateOrderFulfillmentWorkflowInput & AdditionalData +export type CreateOrderFulfillmentWorkflowInput = + OrderWorkflow.CreateOrderFulfillmentWorkflowInput & AdditionalData export const createOrderFulfillmentWorkflowId = "create-order-fulfillment" /** * This workflow creates a fulfillment for an order. It's used by the [Create Order Fulfillment Admin API Route](https://docs.medusajs.com/api/admin#orders_postordersidfulfillments). - * - * This workflow has a hook that allows you to perform custom actions on the created fulfillment. For example, you can pass under `additional_data` custom data that + * + * This workflow has a hook that allows you to perform custom actions on the created fulfillment. For example, you can pass under `additional_data` custom data that * allows you to create custom data models linked to the fulfillment. - * + * * You can also use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around creating a fulfillment. - * + * * @example * const { result } = await createOrderFulfillmentWorkflow(container) * .run({ @@ -300,18 +311,16 @@ export const createOrderFulfillmentWorkflowId = "create-order-fulfillment" * } * } * }) - * + * * @summary - * + * * Creates a fulfillment for an order. - * + * * @property hooks.fulfillmentCreated - This hook is executed after the fulfillment is created. You can consume this hook to perform custom actions on the created fulfillment. */ export const createOrderFulfillmentWorkflow = createWorkflow( createOrderFulfillmentWorkflowId, - ( - input: WorkflowData - ) => { + (input: WorkflowData) => { const order: OrderDTO = useRemoteQueryStep({ entry_point: "orders", fields: [ @@ -323,12 +332,14 @@ export const createOrderFulfillmentWorkflow = createWorkflow( "items.variant.manage_inventory", "items.variant.allow_backorder", "items.variant.product.id", + "items.variant.product.shipping_profile.id", "items.variant.weight", "items.variant.length", "items.variant.height", "items.variant.width", "items.variant.material", "shipping_address.*", + "shipping_methods.id", "shipping_methods.shipping_option_id", "shipping_methods.data", ], @@ -346,17 +357,29 @@ export const createOrderFulfillmentWorkflow = createWorkflow( }, {}) }) - const shippingMethod = transform(order, (data) => { - return { data: data.shipping_methods?.[0]?.data } + const shippingOptionId = transform({ order, input }, (data) => { + return ( + data.input.shipping_option_id ?? + data.order.shipping_methods?.[0]?.shipping_option_id + ) }) - const shippingOptionId = transform(order, (data) => { - return data.shipping_methods?.[0]?.shipping_option_id + const shippingMethod = transform({ order, shippingOptionId }, (data) => { + return { + data: data.order.shipping_methods?.find( + (sm) => sm.shipping_option_id === data.shippingOptionId + )?.data, + } }) const shippingOption = useRemoteQueryStep({ entry_point: "shipping_options", - fields: ["id", "provider_id", "service_zone.fulfillment_set.location.id"], + fields: [ + "id", + "provider_id", + "service_zone.fulfillment_set.location.id", + "shipping_profile_id", + ], variables: { id: shippingOptionId, }, diff --git a/packages/core/core-flows/src/product/helpers/normalize-for-import.ts b/packages/core/core-flows/src/product/helpers/normalize-for-import.ts index 0b8e8b0c18..67bbf55473 100644 --- a/packages/core/core-flows/src/product/helpers/normalize-for-import.ts +++ b/packages/core/core-flows/src/product/helpers/normalize-for-import.ts @@ -136,6 +136,11 @@ const normalizeProductForImport = ( return } + if (normalizedKey.startsWith("shipping_profile_id")) { + response["shipping_profile_id"] = normalizedValue + return + } + if (normalizedKey.startsWith("product_category_")) { response["categories"] = [ ...(response["categories"] || []), diff --git a/packages/core/core-flows/src/product/helpers/normalize-v1-import.ts b/packages/core/core-flows/src/product/helpers/normalize-v1-import.ts index 5b7b021324..5a78c95ceb 100644 --- a/packages/core/core-flows/src/product/helpers/normalize-v1-import.ts +++ b/packages/core/core-flows/src/product/helpers/normalize-v1-import.ts @@ -1,4 +1,8 @@ -import { ProductTypes, SalesChannelTypes } from "@medusajs/framework/types" +import { + ProductTypes, + SalesChannelTypes, + ShippingProfileDTO, +} from "@medusajs/framework/types" import { MedusaError } from "@medusajs/framework/utils" const basicFieldsToOmit = [ @@ -32,6 +36,7 @@ export const normalizeV1Products = ( productTypes: ProductTypes.ProductTypeDTO[] productCollections: ProductTypes.ProductCollectionDTO[] salesChannels: SalesChannelTypes.SalesChannelDTO[] + shippingProfiles: ShippingProfileDTO[] } ): object[] => { const productTypesMap = new Map( @@ -43,6 +48,9 @@ export const normalizeV1Products = ( const salesChannelsMap = new Map( supportingData.salesChannels.map((sc) => [sc.name, sc.id]) ) + const shippingProfilesIds = new Set( + supportingData.shippingProfiles.map((sp) => sp.id) + ) return rawProducts.map((product) => { let finalRes = { @@ -140,6 +148,21 @@ export const normalizeV1Products = ( } } + if (key.startsWith("Shipping Profile Id")) { + if (!value) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + "Shipping Profile Id is required when importing products" + ) + } + if (!shippingProfilesIds.has(value)) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Shipping profile: '${value}' does not exist` + ) + } + } + if ( key.startsWith("Product Category") && (key.endsWith("Handle") || diff --git a/packages/core/core-flows/src/product/steps/parse-product-csv.ts b/packages/core/core-flows/src/product/steps/parse-product-csv.ts index 933de4ba1e..79657c19c3 100644 --- a/packages/core/core-flows/src/product/steps/parse-product-csv.ts +++ b/packages/core/core-flows/src/product/steps/parse-product-csv.ts @@ -1,4 +1,5 @@ import { + IFulfillmentModuleService, IProductModuleService, IRegionModuleService, ISalesChannelModuleService, @@ -16,9 +17,9 @@ export type ParseProductCsvStepInput = string export const parseProductCsvStepId = "parse-product-csv" /** - * This step parses a CSV file holding products to import, returning the products as + * This step parses a CSV file holding products to import, returning the products as * objects that can be imported. - * + * * @example * const data = parseProductCsvStep("products.csv") */ @@ -35,20 +36,25 @@ export const parseProductCsvStep = createStep( Modules.SALES_CHANNEL ) + const fulfillmentService = container.resolve( + Modules.FULFILLMENT + ) + const csvProducts = convertCsvToJson(fileContent) - const [productTypes, productCollections, salesChannels] = await Promise.all( - [ + const [productTypes, productCollections, salesChannels, shippingProfiles] = + await Promise.all([ productService.listProductTypes({}, {}), productService.listProductCollections({}, {}), salesChannelService.listSalesChannels({}, {}), - ] - ) + fulfillmentService.listShippingProfiles({}, {}), + ]) const v1Normalized = normalizeV1Products(csvProducts, { productTypes, productCollections, salesChannels, + shippingProfiles, }) // We use the handle to group products and variants correctly. diff --git a/packages/core/core-flows/src/product/workflows/create-products.ts b/packages/core/core-flows/src/product/workflows/create-products.ts index e475810d82..f837533ea2 100644 --- a/packages/core/core-flows/src/product/workflows/create-products.ts +++ b/packages/core/core-flows/src/product/workflows/create-products.ts @@ -1,6 +1,7 @@ import { AdditionalData, CreateProductWorkflowInputDTO, + LinkDefinition, PricingTypes, ProductTypes, } from "@medusajs/framework/types" @@ -8,6 +9,7 @@ import { ProductWorkflowEvents, isPresent, MedusaError, + Modules, } from "@medusajs/framework/utils" import { WorkflowData, @@ -17,7 +19,11 @@ import { transform, createStep, } from "@medusajs/framework/workflows-sdk" -import { emitEventStep } from "../../common" +import { + createRemoteLinkStep, + emitEventStep, + useQueryGraphStep, +} from "../../common" import { associateProductsWithSalesChannelsStep } from "../../sales-channel" import { createProductsStep } from "../steps/create-products" import { createProductVariantsWorkflow } from "./create-product-variants" @@ -29,14 +35,19 @@ export interface ValidateProductInputStepInput { /** * The products to validate. */ - products: CreateProductWorkflowInputDTO[] + products: Omit[] + + /** + * The shipping profiles to validate. + */ + shippingProfiles: { id: string }[] } const validateProductInputStepId = "validate-product-input" /** * This step validates that all provided products have options. * If a product is missing options, an error is thrown. - * + * * @example * const data = validateProductInputStep({ * products: [ @@ -71,7 +82,7 @@ const validateProductInputStepId = "validate-product-input" export const validateProductInputStep = createStep( validateProductInputStepId, async (data: ValidateProductInputStepInput) => { - const { products } = data + const { products, shippingProfiles } = data const missingOptionsProductTitles = products .filter((product) => !product.options?.length) @@ -85,6 +96,25 @@ export const validateProductInputStep = createStep( )}].` ) } + + const existingProfileIds = new Set(shippingProfiles.map((p) => p.id)) + + const missingShippingProfileProductTitles = products + .filter( + (product) => + !product.shipping_profile_id || + !existingProfileIds.has(product.shipping_profile_id) + ) + .map((product) => product.title) + + if (missingShippingProfileProductTitles.length) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Shipping profile is not provided for: [${missingShippingProfileProductTitles.join( + ", " + )}].` + ) + } } ) @@ -102,11 +132,11 @@ export const createProductsWorkflowId = "create-products" /** * This workflow creates one or more products. It's used by the [Create Product Admin API Route](https://docs.medusajs.com/api/admin#products_postproducts). * It can also be useful to you when creating [seed scripts](https://docs.medusajs.com/learn/fundamentals/custom-cli-scripts/seed-data), for example. - * + * * This workflow has a hook that allows you to perform custom actions on the created products. You can see an example in [this guide](https://docs.medusajs.com/resources/commerce-modules/product/extend). - * + * * You can also use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around product creation. - * + * * @example * const { result } = await createProductsWorkflow(container) * .run({ @@ -143,26 +173,45 @@ export const createProductsWorkflowId = "create-products" * } * } * }) - * + * * @summary - * + * * Create one or more products with options and variants. - * + * * @property hooks.productCreated - This hook is executed after the products are created. You can consume this hook to perform custom actions on the created products. */ export const createProductsWorkflow = createWorkflow( createProductsWorkflowId, (input: WorkflowData) => { // Passing prices to the product module will fail, we want to keep them for after the product is created. - const productWithoutExternalRelations = transform({ input }, (data) => - data.input.products.map((p) => ({ - ...p, - sales_channels: undefined, - variants: undefined, - })) - ) + const { products: productWithoutExternalRelations, shippingPorfileIds } = + transform({ input }, (data) => { + const shippingPorfileIds: string[] = [] + const productsData = data.input.products.map((p) => { + if (p.shipping_profile_id) { + shippingPorfileIds.push(p.shipping_profile_id) + } - validateProductInputStep({ products: productWithoutExternalRelations }) + return { + ...p, + sales_channels: undefined, + shipping_profile_id: undefined, + variants: undefined, + } + }) + + return { products: productsData, shippingPorfileIds } + }) + + const { data: shippingProfiles } = useQueryGraphStep({ + entity: "shipping_profile", + fields: ["id"], + filters: { + id: shippingPorfileIds, + }, + }) + + validateProductInputStep({ products: input.products, shippingProfiles }) const createdProducts = createProductsStep(productWithoutExternalRelations) @@ -182,6 +231,24 @@ export const createProductsWorkflow = createWorkflow( associateProductsWithSalesChannelsStep({ links: salesChannelLinks }) + const shippingProfileLinks = transform( + { input, createdProducts }, + (data) => { + return data.createdProducts.map((createdProduct, i) => { + return { + [Modules.PRODUCT]: { + product_id: createdProduct.id, + }, + [Modules.FULFILLMENT]: { + shipping_profile_id: data.input.products[i].shipping_profile_id, + }, + } + }) + } + ) + + createRemoteLinkStep(shippingProfileLinks as LinkDefinition[]) + const variantsInput = transform({ input, createdProducts }, (data) => { // TODO: Move this to a unified place for all product workflow types const productVariants: (ProductTypes.CreateProductVariantDTO & { diff --git a/packages/core/core-flows/src/product/workflows/update-products.ts b/packages/core/core-flows/src/product/workflows/update-products.ts index e92d86fbdd..ae5ece69f9 100644 --- a/packages/core/core-flows/src/product/workflows/update-products.ts +++ b/packages/core/core-flows/src/product/workflows/update-products.ts @@ -47,6 +47,10 @@ export type UpdateProductsWorkflowInputSelector = { * The variants to update. */ variants?: UpdateProductVariantWorkflowInputDTO[] + /** + * The shipping profile to set. + */ + shipping_profile_id?: string } } & AdditionalData @@ -66,6 +70,10 @@ export type UpdateProductsWorkflowInputProducts = { * The variants to update. */ variants?: UpdateProductVariantWorkflowInputDTO[] + /** + * The shipping profile to set. + */ + shipping_profile_id?: string })[] } & AdditionalData @@ -90,6 +98,7 @@ function prepareUpdateProductInput({ products: input.products.map((p) => ({ ...p, sales_channels: undefined, + shipping_profile_id: undefined, variants: p.variants?.map((v) => ({ ...v, prices: undefined, @@ -103,6 +112,7 @@ function prepareUpdateProductInput({ update: { ...input.update, sales_channels: undefined, + shipping_profile_id: undefined, variants: input.update?.variants?.map((v) => ({ ...v, prices: undefined, @@ -173,6 +183,44 @@ function prepareSalesChannelLinks({ return [] } +function prepareShippingProfileLinks({ + input, + updatedProducts, +}: { + updatedProducts: ProductTypes.ProductDTO[] + input: UpdateProductWorkflowInput +}): Record>[] { + if ("products" in input) { + if (!input.products.length) { + return [] + } + + return input.products + .filter((p) => p.shipping_profile_id) + .map((p) => ({ + [Modules.PRODUCT]: { + product_id: p.id, + }, + [Modules.FULFILLMENT]: { + shipping_profile_id: p.shipping_profile_id, + }, + })) + } + + if (input.selector && input.update?.shipping_profile_id) { + return updatedProducts.map((p) => ({ + [Modules.PRODUCT]: { + product_id: p.id, + }, + [Modules.FULFILLMENT]: { + shipping_profile_id: input.update.shipping_profile_id, + }, + })) + } + + return [] +} + function prepareVariantPrices({ input, updatedProducts, @@ -243,18 +291,42 @@ function prepareToDeleteSalesChannelLinks({ })) } +function prepareToDeleteShippingProfileLinks({ + currentShippingProfileLinks, +}: { + currentShippingProfileLinks: { + product_id: string + shipping_profile_id: string + }[] +}) { + if (!currentShippingProfileLinks.length) { + return [] + } + + return currentShippingProfileLinks.map( + ({ product_id, shipping_profile_id }) => ({ + [Modules.PRODUCT]: { + product_id, + }, + [Modules.FULFILLMENT]: { + shipping_profile_id, + }, + }) + ) +} + export const updateProductsWorkflowId = "update-products" /** * This workflow updates one or more products. It's used by the [Update Product Admin API Route](https://docs.medusajs.com/api/admin#products_postproductsid). - * - * This workflow has a hook that allows you to perform custom actions on the updated products. For example, you can pass under `additional_data` custom data that + * + * This workflow has a hook that allows you to perform custom actions on the updated products. For example, you can pass under `additional_data` custom data that * allows you to update custom data models linked to the products. - * + * * You can also use this workflow within your customizations or your own custom workflows, allowing you to wrap custom logic around product update. - * + * * @example * To update products by their IDs: - * + * * ```ts * const { result } = await updateProductsWorkflow(container) * .run({ @@ -282,9 +354,9 @@ export const updateProductsWorkflowId = "update-products" * } * }) * ``` - * + * * You can also update products by a selector: - * + * * ```ts * const { result } = await updateProductsWorkflow(container) * .run({ @@ -301,11 +373,11 @@ export const updateProductsWorkflowId = "update-products" * } * }) * ``` - * + * * @summary - * + * * Update one or more products with options and variants. - * + * * @property hooks.productsUpdated - This hook is executed after the products are updated. You can consume this hook to perform custom actions on the updated products. */ export const updateProductsWorkflow = createWorkflow( @@ -345,11 +417,20 @@ export const updateProductsWorkflow = createWorkflow( const toUpdateInput = transform({ input }, prepareUpdateProductInput) const updatedProducts = updateProductsStep(toUpdateInput) + const updatedPorductIds = transform({ updatedProducts }, (data) => { + return data.updatedProducts.map((p) => p.id) + }) + const salesChannelLinks = transform( { input, updatedProducts }, prepareSalesChannelLinks ) + const shippingProfileLinks = transform( + { input, updatedProducts }, + prepareShippingProfileLinks + ) + const variantPrices = transform( { input, updatedProducts }, prepareVariantPrices @@ -366,16 +447,33 @@ export const updateProductsWorkflow = createWorkflow( variables: { filters: { product_id: productsWithSalesChannels } }, }).config({ name: "get-current-sales-channel-links-step" }) + const currentShippingProfileLinks = useRemoteQueryStep({ + entry_point: "product_shipping_profile", + fields: ["product_id", "shipping_profile_id"], + variables: { filters: { product_id: updatedPorductIds } }, + }).config({ name: "get-current-shipping-profile-links-step" }) + const toDeleteSalesChannelLinks = transform( { currentSalesChannelLinks }, prepareToDeleteSalesChannelLinks ) + const toDeleteShippingProfileLinks = transform( + { currentShippingProfileLinks }, + prepareToDeleteShippingProfileLinks + ) + upsertVariantPricesWorkflow.runAsStep({ input: { variantPrices, previousVariantIds }, }) - dismissRemoteLinkStep(toDeleteSalesChannelLinks) + dismissRemoteLinkStep(toDeleteSalesChannelLinks).config({ + name: "delete-sales-channel-links-step", + }) + + dismissRemoteLinkStep(toDeleteShippingProfileLinks).config({ + name: "delete-shipping-profile-links-step", + }) const productIdEvents = transform( { updatedProducts }, @@ -387,7 +485,12 @@ export const updateProductsWorkflow = createWorkflow( ) parallelize( - createRemoteLinkStep(salesChannelLinks), + createRemoteLinkStep(salesChannelLinks).config({ + name: "create-sales-channel-links-step", + }), + createRemoteLinkStep(shippingProfileLinks).config({ + name: "create-shipping-profile-links-step", + }), emitEventStep({ eventName: ProductWorkflowEvents.UPDATED, data: productIdEvents, diff --git a/packages/core/core-flows/src/shipping-profile/workflows/delete-shipping-profile.ts b/packages/core/core-flows/src/shipping-profile/workflows/delete-shipping-profile.ts index c70576fa0d..4ddbe6a8f7 100644 --- a/packages/core/core-flows/src/shipping-profile/workflows/delete-shipping-profile.ts +++ b/packages/core/core-flows/src/shipping-profile/workflows/delete-shipping-profile.ts @@ -1,8 +1,31 @@ -import { createWorkflow, WorkflowData } from "@medusajs/framework/workflows-sdk" +import { + createStep, + createWorkflow, + WorkflowData, +} from "@medusajs/framework/workflows-sdk" +import { MedusaError, Modules } from "@medusajs/framework/utils" import { deleteShippingProfilesStep } from "../steps" -import { removeRemoteLinkStep } from "../../common" -import { Modules } from "@medusajs/framework/utils" +import { removeRemoteLinkStep, useQueryGraphStep } from "../../common" + +/** + * This step validates that the shipping profiles to delete are not linked to any products. + */ +const validateStepShippingProfileDelete = createStep( + "validate-step-shipping-profile-delete", + (data: { links: { product_id: string; shipping_profile_id: string }[] }) => { + const { links } = data + + if (links.length > 0) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Cannot delete following shipping profiles because they are linked to products: ${links + .map((l) => l.product_id) + .join(", ")}` + ) + } + } +) /** * The data to delete shipping profiles. @@ -19,10 +42,11 @@ export const deleteShippingProfileWorkflowId = /** * This workflow deletes one or more shipping profiles. It's used by the * [Delete Shipping Profile Admin API Route](https://docs.medusajs.com/api/admin#shipping-profiles_deleteshippingprofilesid). - * + * Shipping profiles that are linked to products cannot be deleted. + * * You can use this workflow within your customizations or your own custom workflows, allowing you to * delete shipping profiles within your custom flows. - * + * * @example * const { result } = await deleteShippingProfileWorkflow(container) * .run({ @@ -30,14 +54,24 @@ export const deleteShippingProfileWorkflowId = * ids: ["sp_123"] * } * }) - * + * * @summary - * + * * Delete shipping profiles. */ export const deleteShippingProfileWorkflow = createWorkflow( deleteShippingProfileWorkflowId, (input: WorkflowData) => { + const currentShippingProfileLinks = useQueryGraphStep({ + entity: "product_shipping_profile", + fields: ["product_id", "shipping_profile_id"], + filters: { shipping_profile_id: input.ids }, + }) + + validateStepShippingProfileDelete({ + links: currentShippingProfileLinks.data, + }) + deleteShippingProfilesStep(input.ids) removeRemoteLinkStep({ diff --git a/packages/core/types/src/http/order/admin/payload.ts b/packages/core/types/src/http/order/admin/payload.ts index c9d0a75be8..5c93ba55ec 100644 --- a/packages/core/types/src/http/order/admin/payload.ts +++ b/packages/core/types/src/http/order/admin/payload.ts @@ -32,6 +32,11 @@ export interface AdminCreateOrderFulfillment { * to fulfill the items from. */ location_id?: string + /** + * The ID of the shipping option to use for the fulfillment. + * Overrides the shipping option selected by the customer. + */ + shipping_option_id?: string /** * Whether to notify the customer about this change. */ diff --git a/packages/core/types/src/http/product/admin/payloads.ts b/packages/core/types/src/http/product/admin/payloads.ts index 40e42d615a..678f135c06 100644 --- a/packages/core/types/src/http/product/admin/payloads.ts +++ b/packages/core/types/src/http/product/admin/payloads.ts @@ -5,7 +5,7 @@ export interface AdminExportProductRequest {} export interface AdminImportProductRequest { /** * The CSV file to import the products from. - * + * * It's an uploaded file of type [File](https://developer.mozilla.org/en-US/docs/Web/API/File). */ file: File @@ -35,7 +35,7 @@ export interface AdminBatchProductVariantInventoryItemRequest export interface AdminCreateProductVariantPrice { /** * The price's currency code. - * + * * @example * usd */ @@ -54,11 +54,11 @@ export interface AdminCreateProductVariantPrice { max_quantity?: number | null /** * The price's rules. - * + * * @privateRemarks * Note: Although the BE is generic, we only use region_id for price rules for now, so it's better to keep the typings stricter. */ - rules?: { + rules?: { /** * The ID of the region that the price applies in. */ @@ -180,11 +180,11 @@ export interface AdminCreateProduct { /** * The product's images. */ - images?: { + images?: { /** * The image's URL. */ - url: string + url: string }[] /** * The product's thumbnail URL. @@ -210,10 +210,14 @@ export interface AdminCreateProduct { * The ID of the product's collection. */ collection_id?: string + /** + * The ID of the product's shipping profile. + */ + shipping_profile_id: string /** * The product's categories. */ - categories?: { + categories?: { /** * The ID of a product category that the product belongs to. */ @@ -222,7 +226,7 @@ export interface AdminCreateProduct { /** * The product's tags. */ - tags?: { + tags?: { /** * The ID of the associated product tag. */ @@ -239,7 +243,7 @@ export interface AdminCreateProduct { /** * The sales channels that the product is available in. */ - sales_channels?: { + sales_channels?: { /** * The ID of a sales channel that the product is available in. */ @@ -363,7 +367,8 @@ export interface AdminUpdateProductVariant { options?: Record } -export interface AdminBatchUpdateProductVariant extends AdminUpdateProductVariant { +export interface AdminBatchUpdateProductVariant + extends AdminUpdateProductVariant { /** * The ID of the variant to update. */ @@ -394,7 +399,7 @@ export interface AdminUpdateProduct { /** * The product's images. */ - images?: { + images?: { /** * The image's URL. */ @@ -427,20 +432,20 @@ export interface AdminUpdateProduct { /** * The product's categories. */ - categories?: { + categories?: { /** * The ID of the category that the product belongs to. */ - id: string + id: string }[] /** * The product's tags. */ - tags?: { + tags?: { /** * The ID of a tag that the product is associated with. */ - id: string + id: string }[] /** * The product's options. @@ -453,12 +458,16 @@ export interface AdminUpdateProduct { /** * The sales channels that the product is available in. */ - sales_channels?: { + sales_channels?: { /** * The ID of a sales channel that the product is available in. */ - id: string + id: string }[] + /** + * The ID of the product's shipping profile. + */ + shipping_profile_id?: string /** * The product's weight. */ diff --git a/packages/core/types/src/workflow/order/create-fulfillment.ts b/packages/core/types/src/workflow/order/create-fulfillment.ts index db479d7d26..d05eb65ecd 100644 --- a/packages/core/types/src/workflow/order/create-fulfillment.ts +++ b/packages/core/types/src/workflow/order/create-fulfillment.ts @@ -62,6 +62,11 @@ export interface CreateOrderFulfillmentWorkflowInput { */ metadata?: Record | null + /** + * Shipping option to be used for the fulfillment. + */ + shipping_option_id?: string + /** * Whether the fulfillment should be shipped. */ diff --git a/packages/core/types/src/workflows/products/mutations.ts b/packages/core/types/src/workflows/products/mutations.ts index 8000889953..b62015107a 100644 --- a/packages/core/types/src/workflows/products/mutations.ts +++ b/packages/core/types/src/workflows/products/mutations.ts @@ -33,6 +33,10 @@ export type CreateProductWorkflowInputDTO = Omit< * The sales channels that the product is available in. */ sales_channels?: { id: string }[] + /** + * The product's shipping profile. + */ + shipping_profile_id: string /** * The product's variants. */ @@ -41,4 +45,5 @@ export type CreateProductWorkflowInputDTO = Omit< export type UpdateProductWorkflowInputDTO = ProductTypes.UpsertProductDTO & { sales_channels?: { id: string }[] + shipping_profile_id?: string } diff --git a/packages/core/utils/src/link/links.ts b/packages/core/utils/src/link/links.ts index 71ace47c6a..7db6c00ae5 100644 --- a/packages/core/utils/src/link/links.ts +++ b/packages/core/utils/src/link/links.ts @@ -116,4 +116,10 @@ export const LINKS = { Modules.FULFILLMENT, "fulfillment_id" ), + ProductShippingProfile: composeLinkName( + Modules.PRODUCT, + "product_id", + Modules.FULFILLMENT, + "shipping_profile_id" + ), } diff --git a/packages/medusa/src/api/admin/orders/validators.ts b/packages/medusa/src/api/admin/orders/validators.ts index 9d39cd3343..49a260d896 100644 --- a/packages/medusa/src/api/admin/orders/validators.ts +++ b/packages/medusa/src/api/admin/orders/validators.ts @@ -75,6 +75,7 @@ export type AdminOrderCreateFulfillmentType = z.infer< export const OrderCreateFulfillment = z.object({ items: z.array(Item), location_id: z.string().nullish(), + shipping_option_id: z.string().optional(), no_notification: z.boolean().optional(), metadata: z.record(z.unknown()).nullish(), }) diff --git a/packages/medusa/src/api/admin/products/validators.ts b/packages/medusa/src/api/admin/products/validators.ts index 6c790219a4..2ddeb2859d 100644 --- a/packages/medusa/src/api/admin/products/validators.ts +++ b/packages/medusa/src/api/admin/products/validators.ts @@ -232,6 +232,7 @@ export const CreateProduct = z options: z.array(CreateProductOption).optional(), variants: z.array(CreateProductVariant).optional(), sales_channels: z.array(z.object({ id: z.string() })).optional(), + shipping_profile_id: z.string(), weight: z.number().nullish(), length: z.number().nullish(), height: z.number().nullish(), @@ -266,6 +267,7 @@ export const UpdateProduct = z categories: z.array(IdAssociation).optional(), tags: z.array(IdAssociation).optional(), sales_channels: z.array(z.object({ id: z.string() })).optional(), + shipping_profile_id: z.string().optional(), weight: z.number().nullish(), length: z.number().nullish(), height: z.number().nullish(), diff --git a/packages/medusa/src/migration-scripts/migrate-product-shipping-profile.ts b/packages/medusa/src/migration-scripts/migrate-product-shipping-profile.ts new file mode 100644 index 0000000000..402d2c606d --- /dev/null +++ b/packages/medusa/src/migration-scripts/migrate-product-shipping-profile.ts @@ -0,0 +1,88 @@ +import { + createRemoteLinkStep, + createShippingProfilesStep, + useQueryGraphStep, +} from "@medusajs/core-flows" +import { ExecArgs } from "@medusajs/framework/types" +import { ContainerRegistrationKeys, Modules } from "@medusajs/framework/utils" +import { + transform, + when, + WorkflowResponse, +} from "@medusajs/framework/workflows-sdk" +import { createWorkflow } from "@medusajs/framework/workflows-sdk" + +const assignProductsToShippingProfileWorkflow = createWorkflow( + "assign-products-to-shipping-profile", + () => { + const { data: shippingProfiles } = useQueryGraphStep({ + entity: "shipping_profile", + fields: ["id", "name"], + }).config({ name: "get-shipping-profiles" }) + + const { data: products } = useQueryGraphStep({ + entity: "product", + fields: ["id"], + }).config({ name: "get-products" }) + + const shippingProfileId = transform( + { shippingProfiles }, + ({ shippingProfiles }) => + shippingProfiles.find((sp) => + sp.name.toLocaleLowerCase().includes("default") + )?.id ?? shippingProfiles[0]?.id + ) + + const createdShippingProfileId = when( + "create-shipping-profile", + { + shippingProfileId, + }, + ({ shippingProfileId }) => !shippingProfileId + ).then(() => { + const createdShippingProfiles = createShippingProfilesStep([ + { + name: "Default Shipping Profile", + type: "default", + }, + ]) + + return createdShippingProfiles[0].id + }) + + const links = transform( + { products, shippingProfileId, createdShippingProfileId }, + ({ products, shippingProfileId, createdShippingProfileId }) => { + return products.map((product) => ({ + [Modules.PRODUCT]: { + product_id: product.id, + }, + [Modules.FULFILLMENT]: { + shipping_profile_id: shippingProfileId ?? createdShippingProfileId, + }, + })) + } + ) + + createRemoteLinkStep(links) + + return new WorkflowResponse(void 0) + } +) + +export default async function assignProductsToShippingProfile({ + container, +}: ExecArgs) { + const logger = container.resolve(ContainerRegistrationKeys.LOGGER) + + logger.info("Assigning products to shipping profile") + + await assignProductsToShippingProfileWorkflow(container) + .run() + .then(() => { + logger.info("Products assigned to shipping profile") + }) + .catch((e) => { + logger.error(e) + }) +} diff --git a/packages/modules/link-modules/src/definitions/index.ts b/packages/modules/link-modules/src/definitions/index.ts index 00fdf9f07b..98152c83c1 100644 --- a/packages/modules/link-modules/src/definitions/index.ts +++ b/packages/modules/link-modules/src/definitions/index.ts @@ -15,3 +15,4 @@ export * from "./readonly" export * from "./region-payment-provider" export * from "./sales-channel-location" export * from "./shipping-option-price-set" +export * from "./product-shipping-profile" diff --git a/packages/modules/link-modules/src/definitions/product-shipping-profile.ts b/packages/modules/link-modules/src/definitions/product-shipping-profile.ts new file mode 100644 index 0000000000..63654a6036 --- /dev/null +++ b/packages/modules/link-modules/src/definitions/product-shipping-profile.ts @@ -0,0 +1,72 @@ +import { ModuleJoinerConfig } from "@medusajs/framework/types" +import { LINKS, Modules } from "@medusajs/framework/utils" + +export const ProductShippingProfile: ModuleJoinerConfig = { + serviceName: LINKS.ProductShippingProfile, + isLink: true, + databaseConfig: { + tableName: "product_shipping_profile", + idPrefix: "prodsp", + }, + alias: [ + { + name: "product_shipping_profile", + }, + { + name: "product_shipping_profiles", + }, + ], + primaryKeys: ["id", "product_id", "shipping_profile_id"], + relationships: [ + { + serviceName: Modules.PRODUCT, + entity: "Product", + primaryKey: "id", + foreignKey: "product_id", + alias: "product", + args: { + methodSuffix: "Products", + }, + }, + { + serviceName: Modules.FULFILLMENT, + entity: "ShippingProfile", + primaryKey: "id", + foreignKey: "shipping_profile_id", + alias: "shipping_profile", + args: { + methodSuffix: "ShippingProfiles", + }, + }, + ], + extends: [ + { + serviceName: Modules.PRODUCT, + entity: "Product", + fieldAlias: { + shipping_profile: { + path: "shipping_profiles_link.shipping_profile", + isList: false, + }, + }, + relationship: { + serviceName: LINKS.ProductShippingProfile, + primaryKey: "product_id", + foreignKey: "id", + alias: "shipping_profiles_link", + isList: false, + }, + }, + { + serviceName: Modules.FULFILLMENT, + entity: "ShippingProfile", + relationship: { + serviceName: LINKS.ProductShippingProfile, + primaryKey: "shipping_profile_id", + foreignKey: "id", + alias: "products_link", + isList: true, + }, + }, + ], +}