feat: Admin Shipping Profiles API (#7019)
This commit is contained in:
@@ -1,346 +0,0 @@
|
|||||||
const path = require("path")
|
|
||||||
|
|
||||||
const setupServer = require("../../../environment-helpers/setup-server")
|
|
||||||
const { useApi } = require("../../../environment-helpers/use-api")
|
|
||||||
const { initDb, useDb } = require("../../../environment-helpers/use-db")
|
|
||||||
const {
|
|
||||||
simpleProductFactory,
|
|
||||||
simpleShippingOptionFactory,
|
|
||||||
simpleShippingProfileFactory,
|
|
||||||
} = require("../../../factories")
|
|
||||||
const adminSeeder = require("../../../helpers/admin-seeder")
|
|
||||||
|
|
||||||
const adminReqConfig = {
|
|
||||||
headers: {
|
|
||||||
"x-medusa-access-token": "test_token",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
jest.setTimeout(30000)
|
|
||||||
|
|
||||||
describe("/admin/shipping-profiles", () => {
|
|
||||||
let medusaProcess
|
|
||||||
let dbConnection
|
|
||||||
|
|
||||||
beforeAll(async () => {
|
|
||||||
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
|
||||||
dbConnection = await initDb({ cwd })
|
|
||||||
medusaProcess = await setupServer({ cwd })
|
|
||||||
})
|
|
||||||
|
|
||||||
afterAll(async () => {
|
|
||||||
const db = useDb()
|
|
||||||
await db.shutdown()
|
|
||||||
|
|
||||||
medusaProcess.kill()
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("GET /admin/shipping-profiles", () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await adminSeeder(dbConnection)
|
|
||||||
})
|
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
const db = useDb()
|
|
||||||
await db.teardown()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("lists shipping profiles", async () => {
|
|
||||||
const api = useApi()
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: { shipping_profiles },
|
|
||||||
status,
|
|
||||||
} = await api.get("/admin/shipping-profiles", adminReqConfig)
|
|
||||||
|
|
||||||
expect(status).toEqual(200)
|
|
||||||
|
|
||||||
// Should contain default and gift_card profiles
|
|
||||||
expect(shipping_profiles.length).toEqual(2)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("gets a shipping profile by id", async () => {
|
|
||||||
const api = useApi()
|
|
||||||
|
|
||||||
const profile = await simpleShippingProfileFactory(dbConnection)
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: { shipping_profile },
|
|
||||||
status,
|
|
||||||
} = await api.get(
|
|
||||||
`/admin/shipping-profiles/${profile.id}`,
|
|
||||||
adminReqConfig
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(status).toEqual(200)
|
|
||||||
expect(shipping_profile).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
...profile,
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("POST /admin/shipping-profiles", () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await adminSeeder(dbConnection)
|
|
||||||
})
|
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
const db = useDb()
|
|
||||||
await db.teardown()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("creates a custom shipping profile", async () => {
|
|
||||||
const api = useApi()
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
name: "test-profile-2023",
|
|
||||||
type: "custom",
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: { shipping_profile },
|
|
||||||
status,
|
|
||||||
} = await api.post("/admin/shipping-profiles", payload, adminReqConfig)
|
|
||||||
|
|
||||||
expect(status).toEqual(200)
|
|
||||||
expect(shipping_profile).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
...payload,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("creates a default shipping profile", async () => {
|
|
||||||
const api = useApi()
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
name: "test-profile-2023",
|
|
||||||
type: "default",
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: { shipping_profile },
|
|
||||||
status,
|
|
||||||
} = await api.post("/admin/shipping-profiles", payload, adminReqConfig)
|
|
||||||
|
|
||||||
expect(status).toEqual(200)
|
|
||||||
expect(shipping_profile).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
...payload,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("creates a gift_card shipping profile", async () => {
|
|
||||||
const api = useApi()
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
name: "test-profile-2023",
|
|
||||||
type: "gift_card",
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: { shipping_profile },
|
|
||||||
status,
|
|
||||||
} = await api.post("/admin/shipping-profiles", payload, adminReqConfig)
|
|
||||||
|
|
||||||
expect(status).toEqual(200)
|
|
||||||
expect(shipping_profile).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
...payload,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("creates a shipping profile with metadata", async () => {
|
|
||||||
const api = useApi()
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
name: "test-profile-2023",
|
|
||||||
type: "default",
|
|
||||||
metadata: {
|
|
||||||
custom_key: "custom_value",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: { shipping_profile },
|
|
||||||
status,
|
|
||||||
} = await api.post("/admin/shipping-profiles", payload, adminReqConfig)
|
|
||||||
|
|
||||||
expect(status).toEqual(200)
|
|
||||||
expect(shipping_profile).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
id: expect.any(String),
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
deleted_at: null,
|
|
||||||
...payload,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("fails to create a shipping profile with invalid type", async () => {
|
|
||||||
const api = useApi()
|
|
||||||
expect.assertions(2)
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
name: "test-profile-2023",
|
|
||||||
type: "invalid",
|
|
||||||
}
|
|
||||||
|
|
||||||
await api
|
|
||||||
.post("/admin/shipping-profiles", payload, adminReqConfig)
|
|
||||||
.catch((err) => {
|
|
||||||
expect(err.response.status).toEqual(400)
|
|
||||||
expect(err.response.data.message).toEqual(
|
|
||||||
"type must be one of 'default', 'custom', 'gift_card'"
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("updates a shipping profile", async () => {
|
|
||||||
const api = useApi()
|
|
||||||
|
|
||||||
const testProducts = await Promise.all(
|
|
||||||
[...Array(5).keys()].map(async () => {
|
|
||||||
return await simpleProductFactory(dbConnection)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
const testShippingOptions = await Promise.all(
|
|
||||||
[...Array(5).keys()].map(async () => {
|
|
||||||
return await simpleShippingOptionFactory(dbConnection)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
name: "test-profile-2023",
|
|
||||||
type: "custom",
|
|
||||||
metadata: {
|
|
||||||
my_key: "my_value",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: { shipping_profile: created },
|
|
||||||
} = await api.post("/admin/shipping-profiles", payload, adminReqConfig)
|
|
||||||
|
|
||||||
const updatePayload = {
|
|
||||||
name: "test-profile-2023-updated",
|
|
||||||
products: testProducts.map((p) => p.id),
|
|
||||||
shipping_options: testShippingOptions.map((o) => o.id),
|
|
||||||
metadata: {
|
|
||||||
my_key: "",
|
|
||||||
my_new_key: "my_new_value",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: { shipping_profile },
|
|
||||||
status,
|
|
||||||
} = await api.post(
|
|
||||||
`/admin/shipping-profiles/${created.id}`,
|
|
||||||
updatePayload,
|
|
||||||
adminReqConfig
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(status).toEqual(200)
|
|
||||||
expect(shipping_profile).toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
name: "test-profile-2023-updated",
|
|
||||||
created_at: expect.any(String),
|
|
||||||
updated_at: expect.any(String),
|
|
||||||
metadata: {
|
|
||||||
my_new_key: "my_new_value",
|
|
||||||
},
|
|
||||||
deleted_at: null,
|
|
||||||
type: "custom",
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: { products },
|
|
||||||
} = await api.get(`/admin/products`, adminReqConfig)
|
|
||||||
|
|
||||||
expect(products.length).toEqual(5)
|
|
||||||
expect(products).toEqual(
|
|
||||||
expect.arrayContaining(
|
|
||||||
testProducts.map((p) => {
|
|
||||||
return expect.objectContaining({
|
|
||||||
id: p.id,
|
|
||||||
profile_id: shipping_profile.id,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
const {
|
|
||||||
data: { shipping_options },
|
|
||||||
} = await api.get(`/admin/shipping-options`, adminReqConfig)
|
|
||||||
|
|
||||||
const numberOfShippingOptionsWithProfile = shipping_options.filter(
|
|
||||||
(so) => so.profile_id === shipping_profile.id
|
|
||||||
).length
|
|
||||||
|
|
||||||
expect(numberOfShippingOptionsWithProfile).toEqual(5)
|
|
||||||
expect(shipping_options).toEqual(
|
|
||||||
expect.arrayContaining(
|
|
||||||
testShippingOptions.map((o) => {
|
|
||||||
return expect.objectContaining({
|
|
||||||
id: o.id,
|
|
||||||
profile_id: shipping_profile.id,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("DELETE /admin/shipping-profiles", () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await adminSeeder(dbConnection)
|
|
||||||
})
|
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
const db = useDb()
|
|
||||||
await db.teardown()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("deletes a shipping profile", async () => {
|
|
||||||
expect.assertions(2)
|
|
||||||
|
|
||||||
const api = useApi()
|
|
||||||
|
|
||||||
const profile = await simpleShippingProfileFactory(dbConnection)
|
|
||||||
|
|
||||||
const { status } = await api.delete(
|
|
||||||
`/admin/shipping-profiles/${profile.id}`,
|
|
||||||
adminReqConfig
|
|
||||||
)
|
|
||||||
|
|
||||||
expect(status).toEqual(200)
|
|
||||||
await api
|
|
||||||
.get(`/admin/shipping-profiles/${profile.id}`, adminReqConfig)
|
|
||||||
.catch((err) => {
|
|
||||||
expect(err.response.status).toEqual(404)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
import { medusaIntegrationTestRunner } from "medusa-test-utils"
|
||||||
|
import { breaking } from "../../../helpers/breaking"
|
||||||
|
import {
|
||||||
|
adminHeaders,
|
||||||
|
createAdminUser,
|
||||||
|
} from "../../../helpers/create-admin-user"
|
||||||
|
|
||||||
|
let {
|
||||||
|
simpleProductFactory,
|
||||||
|
simpleShippingOptionFactory,
|
||||||
|
simpleShippingProfileFactory,
|
||||||
|
} = {}
|
||||||
|
|
||||||
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
|
medusaIntegrationTestRunner({
|
||||||
|
env: {
|
||||||
|
// MEDUSA_FF_MEDUSA_V2: true,
|
||||||
|
},
|
||||||
|
testSuite: ({ dbConnection, getContainer, api }) => {
|
||||||
|
let appContainer
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
;({
|
||||||
|
simpleProductFactory,
|
||||||
|
simpleShippingOptionFactory,
|
||||||
|
simpleShippingProfileFactory,
|
||||||
|
} = require("../../../factories"))
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
appContainer = getContainer()
|
||||||
|
|
||||||
|
await createAdminUser(dbConnection, adminHeaders, appContainer)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("Admin - Shipping Profiles", () => {
|
||||||
|
// TODO: Missing update and delete tests
|
||||||
|
it("should test the entire lifecycle of a shipping profile", async () => {
|
||||||
|
const payload = {
|
||||||
|
name: "test-profile-2023",
|
||||||
|
type: "custom",
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: { shipping_profile },
|
||||||
|
status,
|
||||||
|
} = await api.post("/admin/shipping-profiles", payload, adminHeaders)
|
||||||
|
|
||||||
|
expect(status).toEqual(200)
|
||||||
|
expect(shipping_profile).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
...payload,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: { shipping_profiles },
|
||||||
|
} = await api.get("/admin/shipping-profiles", adminHeaders)
|
||||||
|
|
||||||
|
// In V1, response should contain default and gift_card profiles too
|
||||||
|
expect(shipping_profiles.length).toEqual(
|
||||||
|
breaking(
|
||||||
|
() => 3,
|
||||||
|
() => 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: { shipping_profile: retrievedProfile },
|
||||||
|
} = await api.get(
|
||||||
|
`/admin/shipping-profiles/${shipping_profile.id}`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(status).toEqual(200)
|
||||||
|
expect(retrievedProfile).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: shipping_profile.id,
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
created_at: expect.any(String),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("POST /admin/shipping-profiles", () => {
|
||||||
|
// TODO: There is no invalid types in V2 yet, so this will fail
|
||||||
|
it("fails to create a shipping profile with invalid type", async () => {
|
||||||
|
expect.assertions(2)
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
name: "test-profile-2023",
|
||||||
|
type: "invalid",
|
||||||
|
}
|
||||||
|
|
||||||
|
await api
|
||||||
|
.post("/admin/shipping-profiles", payload, adminHeaders)
|
||||||
|
.catch((err) => {
|
||||||
|
expect(err.response.status).toEqual(400)
|
||||||
|
expect(err.response.data.message).toEqual(
|
||||||
|
"type must be one of 'default', 'custom', 'gift_card'"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("updates a shipping profile", async () => {
|
||||||
|
// TODO: Update is not added yet
|
||||||
|
const testProducts = await Promise.all(
|
||||||
|
[...Array(5).keys()].map(async () => {
|
||||||
|
return await simpleProductFactory(dbConnection)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const testShippingOptions = await Promise.all(
|
||||||
|
[...Array(5).keys()].map(async () => {
|
||||||
|
return await simpleShippingOptionFactory(dbConnection)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
name: "test-profile-2023",
|
||||||
|
type: "custom",
|
||||||
|
metadata: {
|
||||||
|
my_key: "my_value",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: { shipping_profile: created },
|
||||||
|
} = await api.post("/admin/shipping-profiles", payload, adminHeaders)
|
||||||
|
|
||||||
|
const updatePayload = {
|
||||||
|
name: "test-profile-2023-updated",
|
||||||
|
products: testProducts.map((p) => p.id),
|
||||||
|
shipping_options: testShippingOptions.map((o) => o.id),
|
||||||
|
metadata: {
|
||||||
|
my_key: "",
|
||||||
|
my_new_key: "my_new_value",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: { shipping_profile },
|
||||||
|
status,
|
||||||
|
} = await api.post(
|
||||||
|
`/admin/shipping-profiles/${created.id}`,
|
||||||
|
updatePayload,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(status).toEqual(200)
|
||||||
|
expect(shipping_profile).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
name: "test-profile-2023-updated",
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
metadata: {
|
||||||
|
my_new_key: "my_new_value",
|
||||||
|
},
|
||||||
|
deleted_at: null,
|
||||||
|
type: "custom",
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: { products },
|
||||||
|
} = await api.get(`/admin/products`, adminHeaders)
|
||||||
|
|
||||||
|
expect(products.length).toEqual(5)
|
||||||
|
expect(products).toEqual(
|
||||||
|
expect.arrayContaining(
|
||||||
|
testProducts.map((p) => {
|
||||||
|
return expect.objectContaining({
|
||||||
|
id: p.id,
|
||||||
|
profile_id: shipping_profile.id,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: { shipping_options },
|
||||||
|
} = await api.get(`/admin/shipping-options`, adminHeaders)
|
||||||
|
|
||||||
|
const numberOfShippingOptionsWithProfile = shipping_options.filter(
|
||||||
|
(so) => so.profile_id === shipping_profile.id
|
||||||
|
).length
|
||||||
|
|
||||||
|
expect(numberOfShippingOptionsWithProfile).toEqual(5)
|
||||||
|
expect(shipping_options).toEqual(
|
||||||
|
expect.arrayContaining(
|
||||||
|
testShippingOptions.map((o) => {
|
||||||
|
return expect.objectContaining({
|
||||||
|
id: o.id,
|
||||||
|
profile_id: shipping_profile.id,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("DELETE /admin/shipping-profiles", () => {
|
||||||
|
// TODO: Delete is not added yet
|
||||||
|
it("deletes a shipping profile", async () => {
|
||||||
|
expect.assertions(2)
|
||||||
|
|
||||||
|
const profile = await simpleShippingProfileFactory(dbConnection)
|
||||||
|
|
||||||
|
const { status } = await api.delete(
|
||||||
|
`/admin/shipping-profiles/${profile.id}`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(status).toEqual(200)
|
||||||
|
await api
|
||||||
|
.get(`/admin/shipping-profiles/${profile.id}`, adminHeaders)
|
||||||
|
.catch((err) => {
|
||||||
|
expect(err.response.status).toEqual(404)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||||
|
import {
|
||||||
|
CreateShippingProfileDTO,
|
||||||
|
IFulfillmentModuleService,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||||
|
|
||||||
|
type StepInput = CreateShippingProfileDTO[]
|
||||||
|
|
||||||
|
export const createShippingProfilesStepId = "create-shipping-profiles"
|
||||||
|
export const createShippingProfilesStep = createStep(
|
||||||
|
createShippingProfilesStepId,
|
||||||
|
async (input: StepInput, { container }) => {
|
||||||
|
const service = container.resolve<IFulfillmentModuleService>(
|
||||||
|
ModuleRegistrationName.FULFILLMENT
|
||||||
|
)
|
||||||
|
|
||||||
|
const createdShippingProfiles = await service.createShippingProfiles(input)
|
||||||
|
|
||||||
|
return new StepResponse(
|
||||||
|
createdShippingProfiles,
|
||||||
|
createdShippingProfiles.map((created) => created.id)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
async (createdShippingProfiles, { container }) => {
|
||||||
|
if (!createdShippingProfiles?.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const service = container.resolve<IFulfillmentModuleService>(
|
||||||
|
ModuleRegistrationName.FULFILLMENT
|
||||||
|
)
|
||||||
|
|
||||||
|
await service.deleteShippingProfiles(createdShippingProfiles)
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -4,4 +4,5 @@ export * from "./create-fulfillment-set"
|
|||||||
export * from "./create-service-zones"
|
export * from "./create-service-zones"
|
||||||
export * from "./upsert-shipping-options"
|
export * from "./upsert-shipping-options"
|
||||||
export * from "./delete-service-zones"
|
export * from "./delete-service-zones"
|
||||||
|
export * from "./create-shipping-profiles"
|
||||||
export * from "./remove-rules-from-fulfillment-shipping-option"
|
export * from "./remove-rules-from-fulfillment-shipping-option"
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { FulfillmentWorkflow } from "@medusajs/types"
|
||||||
|
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
|
||||||
|
import { createShippingProfilesStep } from "../steps"
|
||||||
|
|
||||||
|
export const createShippingProfilesWorkflowId =
|
||||||
|
"create-shipping-profiles-workflow"
|
||||||
|
export const createShippingProfilesWorkflow = createWorkflow(
|
||||||
|
createShippingProfilesWorkflowId,
|
||||||
|
(
|
||||||
|
input: WorkflowData<FulfillmentWorkflow.CreateShippingProfilesWorkflowInput>
|
||||||
|
): WorkflowData => {
|
||||||
|
const shippingProfiles = createShippingProfilesStep(input.data)
|
||||||
|
|
||||||
|
return shippingProfiles
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
export * from "./add-rules-to-fulfillment-shipping-option"
|
export * from "./add-rules-to-fulfillment-shipping-option"
|
||||||
export * from "./create-service-zones"
|
export * from "./create-service-zones"
|
||||||
export * from "./create-shipping-options"
|
export * from "./create-shipping-options"
|
||||||
export * from "./update-shipping-options"
|
export * from "./create-shipping-profiles"
|
||||||
export * from "./delete-service-zones"
|
export * from "./delete-service-zones"
|
||||||
export * from "./remove-rules-from-fulfillment-shipping-option"
|
export * from "./remove-rules-from-fulfillment-shipping-option"
|
||||||
export * from "./update-service-zones"
|
export * from "./update-service-zones"
|
||||||
|
export * from "./update-shipping-options"
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ export const GET = async (
|
|||||||
if (!service_zone) {
|
if (!service_zone) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.Types.NOT_FOUND,
|
MedusaError.Types.NOT_FOUND,
|
||||||
`Service zone with id ${req.params.zone_id} not found`
|
`Service zone with id: ${req.params.zone_id} not found`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { AdminShippingProfileResponse } from "@medusajs/types"
|
||||||
|
import {
|
||||||
|
ContainerRegistrationKeys,
|
||||||
|
remoteQueryObjectFromString,
|
||||||
|
} from "@medusajs/utils"
|
||||||
|
import {
|
||||||
|
AuthenticatedMedusaRequest,
|
||||||
|
MedusaResponse,
|
||||||
|
} from "../../../../types/routing"
|
||||||
|
|
||||||
|
export const GET = async (
|
||||||
|
req: AuthenticatedMedusaRequest,
|
||||||
|
res: MedusaResponse<AdminShippingProfileResponse>
|
||||||
|
) => {
|
||||||
|
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||||
|
|
||||||
|
const query = remoteQueryObjectFromString({
|
||||||
|
entryPoint: "shipping_profiles",
|
||||||
|
variables: { id: req.params.id },
|
||||||
|
fields: req.remoteQueryConfig.fields,
|
||||||
|
})
|
||||||
|
|
||||||
|
const [shippingProfile] = await remoteQuery(query)
|
||||||
|
|
||||||
|
res.status(200).json({ shipping_profile: shippingProfile })
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
|
||||||
|
import { authenticate } from "../../../utils/authenticate-middleware"
|
||||||
|
import { validateAndTransformBody } from "../../utils/validate-body"
|
||||||
|
import { validateAndTransformQuery } from "../../utils/validate-query"
|
||||||
|
import {
|
||||||
|
listTransformQueryConfig,
|
||||||
|
retrieveTransformQueryConfig,
|
||||||
|
} from "./query-config"
|
||||||
|
import {
|
||||||
|
AdminCreateShippingProfile,
|
||||||
|
AdminShippingProfileParams,
|
||||||
|
AdminShippingProfilesParams,
|
||||||
|
} from "./validators"
|
||||||
|
|
||||||
|
export const adminShippingProfilesMiddlewares: MiddlewareRoute[] = [
|
||||||
|
{
|
||||||
|
matcher: "/admin/shipping-profiles*",
|
||||||
|
middlewares: [authenticate("admin", ["bearer", "session", "api-key"])],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: ["POST"],
|
||||||
|
matcher: "/admin/shipping-profiles",
|
||||||
|
middlewares: [
|
||||||
|
validateAndTransformQuery(
|
||||||
|
AdminShippingProfilesParams,
|
||||||
|
retrieveTransformQueryConfig
|
||||||
|
),
|
||||||
|
validateAndTransformBody(AdminCreateShippingProfile),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: ["GET"],
|
||||||
|
matcher: "/admin/shipping-profiles",
|
||||||
|
middlewares: [
|
||||||
|
validateAndTransformQuery(
|
||||||
|
AdminShippingProfilesParams,
|
||||||
|
listTransformQueryConfig
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: ["GET"],
|
||||||
|
matcher: "/admin/shipping-profiles/:id",
|
||||||
|
middlewares: [
|
||||||
|
validateAndTransformQuery(
|
||||||
|
AdminShippingProfileParams,
|
||||||
|
retrieveTransformQueryConfig
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
export const defaultAdminShippingProfileFields = [
|
||||||
|
"id",
|
||||||
|
"name",
|
||||||
|
"type",
|
||||||
|
"metadata",
|
||||||
|
"created_at",
|
||||||
|
"updated_at",
|
||||||
|
]
|
||||||
|
|
||||||
|
export const retrieveTransformQueryConfig = {
|
||||||
|
defaults: defaultAdminShippingProfileFields,
|
||||||
|
isList: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const listTransformQueryConfig = {
|
||||||
|
...retrieveTransformQueryConfig,
|
||||||
|
isList: true,
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { createShippingProfilesWorkflow } from "@medusajs/core-flows"
|
||||||
|
import {
|
||||||
|
AdminShippingProfileResponse,
|
||||||
|
AdminShippingProfilesResponse,
|
||||||
|
} from "@medusajs/types"
|
||||||
|
import {
|
||||||
|
ContainerRegistrationKeys,
|
||||||
|
remoteQueryObjectFromString,
|
||||||
|
} from "@medusajs/utils"
|
||||||
|
import {
|
||||||
|
AuthenticatedMedusaRequest,
|
||||||
|
MedusaResponse,
|
||||||
|
} from "../../../types/routing"
|
||||||
|
import { AdminCreateShippingProfileType } from "./validators"
|
||||||
|
|
||||||
|
export const POST = async (
|
||||||
|
req: AuthenticatedMedusaRequest<AdminCreateShippingProfileType>,
|
||||||
|
res: MedusaResponse<AdminShippingProfileResponse>
|
||||||
|
) => {
|
||||||
|
const shippingProfilePayload = req.validatedBody
|
||||||
|
|
||||||
|
const { result, errors } = await createShippingProfilesWorkflow(
|
||||||
|
req.scope
|
||||||
|
).run({
|
||||||
|
input: { data: [shippingProfilePayload] },
|
||||||
|
throwOnError: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (Array.isArray(errors) && errors[0]) {
|
||||||
|
throw errors[0].error
|
||||||
|
}
|
||||||
|
|
||||||
|
const shippingProfileId = result?.[0].id
|
||||||
|
|
||||||
|
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||||
|
|
||||||
|
const query = remoteQueryObjectFromString({
|
||||||
|
entryPoint: "shipping_profiles",
|
||||||
|
variables: { id: shippingProfileId },
|
||||||
|
fields: req.remoteQueryConfig.fields,
|
||||||
|
})
|
||||||
|
|
||||||
|
const [shippingProfile] = await remoteQuery(query)
|
||||||
|
|
||||||
|
res.status(200).json({ shipping_profile: shippingProfile })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GET = async (
|
||||||
|
req: AuthenticatedMedusaRequest,
|
||||||
|
res: MedusaResponse<AdminShippingProfilesResponse>
|
||||||
|
) => {
|
||||||
|
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||||
|
|
||||||
|
const query = remoteQueryObjectFromString({
|
||||||
|
entryPoint: "shipping_profiles",
|
||||||
|
variables: {
|
||||||
|
filters: req.filterableFields,
|
||||||
|
...req.remoteQueryConfig.pagination,
|
||||||
|
},
|
||||||
|
fields: req.remoteQueryConfig.fields,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { rows: shippingProfiles, metadata } = await remoteQuery(query)
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
shipping_profiles: shippingProfiles,
|
||||||
|
count: metadata.count,
|
||||||
|
offset: metadata.skip,
|
||||||
|
limit: metadata.take,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { z } from "zod"
|
||||||
|
import { createFindParams, createSelectParams } from "../../utils/validators"
|
||||||
|
|
||||||
|
export const AdminShippingProfileParams = createSelectParams()
|
||||||
|
export const AdminShippingProfilesParams = createFindParams({
|
||||||
|
limit: 20,
|
||||||
|
offset: 0,
|
||||||
|
}).merge(
|
||||||
|
z.object({
|
||||||
|
type: z.string().optional(),
|
||||||
|
name: z.string().optional(),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
export const AdminCreateShippingProfile = z
|
||||||
|
.object({
|
||||||
|
name: z.string(),
|
||||||
|
type: z.string(),
|
||||||
|
metadata: z.record(z.string(), z.unknown()).optional(),
|
||||||
|
})
|
||||||
|
.strict()
|
||||||
|
|
||||||
|
export type AdminCreateShippingProfileType = z.infer<
|
||||||
|
typeof AdminCreateShippingProfile
|
||||||
|
>
|
||||||
@@ -19,6 +19,7 @@ import { adminPromotionRoutesMiddlewares } from "./admin/promotions/middlewares"
|
|||||||
import { adminRegionRoutesMiddlewares } from "./admin/regions/middlewares"
|
import { adminRegionRoutesMiddlewares } from "./admin/regions/middlewares"
|
||||||
import { adminSalesChannelRoutesMiddlewares } from "./admin/sales-channels/middlewares"
|
import { adminSalesChannelRoutesMiddlewares } from "./admin/sales-channels/middlewares"
|
||||||
import { adminShippingOptionRoutesMiddlewares } from "./admin/shipping-options/middlewares"
|
import { adminShippingOptionRoutesMiddlewares } from "./admin/shipping-options/middlewares"
|
||||||
|
import { adminShippingProfilesMiddlewares } from "./admin/shipping-profiles/middlewares"
|
||||||
import { adminStockLocationRoutesMiddlewares } from "./admin/stock-locations/middlewares"
|
import { adminStockLocationRoutesMiddlewares } from "./admin/stock-locations/middlewares"
|
||||||
import { adminStoreRoutesMiddlewares } from "./admin/stores/middlewares"
|
import { adminStoreRoutesMiddlewares } from "./admin/stores/middlewares"
|
||||||
import { adminTaxRateRoutesMiddlewares } from "./admin/tax-rates/middlewares"
|
import { adminTaxRateRoutesMiddlewares } from "./admin/tax-rates/middlewares"
|
||||||
@@ -69,5 +70,6 @@ export const config: MiddlewaresConfig = {
|
|||||||
...adminUploadRoutesMiddlewares,
|
...adminUploadRoutesMiddlewares,
|
||||||
...adminFulfillmentSetsRoutesMiddlewares,
|
...adminFulfillmentSetsRoutesMiddlewares,
|
||||||
...adminProductCategoryRoutesMiddlewares,
|
...adminProductCategoryRoutesMiddlewares,
|
||||||
|
...adminShippingProfilesMiddlewares,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ export * from "./api"
|
|||||||
export * from "./api-v2"
|
export * from "./api-v2"
|
||||||
export * from "./api/middlewares"
|
export * from "./api/middlewares"
|
||||||
export * from "./interfaces"
|
export * from "./interfaces"
|
||||||
export * from "./joiner-config"
|
|
||||||
export * from "./models"
|
export * from "./models"
|
||||||
export * from "./modules-config"
|
export * from "./modules-config"
|
||||||
export * from "./services"
|
export * from "./services"
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
import * as joinerConfigs from "./joiner-configs"
|
|
||||||
|
|
||||||
export const joinerConfig = Object.values(joinerConfigs).map(
|
|
||||||
(config) => config.default
|
|
||||||
)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export * as shippingProfile from "./shipping-profile-service"
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import { ModuleJoinerConfig } from "@medusajs/types"
|
|
||||||
|
|
||||||
export default {
|
|
||||||
serviceName: "shippingProfileService",
|
|
||||||
primaryKeys: ["id"],
|
|
||||||
linkableKeys: { profile_id: "ShippingProfile" },
|
|
||||||
schema: `
|
|
||||||
scalar Date
|
|
||||||
scalar JSON
|
|
||||||
|
|
||||||
type ShippingProfile {
|
|
||||||
id: ID!
|
|
||||||
name: String!
|
|
||||||
type: String!
|
|
||||||
created_at: Date!
|
|
||||||
updated_at: Date!
|
|
||||||
deleted_at: Date
|
|
||||||
metadata: JSON
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
alias: [
|
|
||||||
{
|
|
||||||
name: ["shipping_profile", "shipping_profiles"],
|
|
||||||
args: {
|
|
||||||
entity: "ShippingProfile",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
} as ModuleJoinerConfig
|
|
||||||
@@ -1,3 +1,12 @@
|
|||||||
|
import {
|
||||||
|
MODULE_PACKAGE_NAMES,
|
||||||
|
MedusaApp,
|
||||||
|
MedusaAppMigrateUp,
|
||||||
|
MedusaAppOutput,
|
||||||
|
MedusaModule,
|
||||||
|
Modules,
|
||||||
|
ModulesDefinition,
|
||||||
|
} from "@medusajs/modules-sdk"
|
||||||
import {
|
import {
|
||||||
CommonTypes,
|
CommonTypes,
|
||||||
InternalModuleDeclaration,
|
InternalModuleDeclaration,
|
||||||
@@ -8,21 +17,11 @@ import {
|
|||||||
import {
|
import {
|
||||||
ContainerRegistrationKeys,
|
ContainerRegistrationKeys,
|
||||||
FlagRouter,
|
FlagRouter,
|
||||||
isObject,
|
|
||||||
MedusaV2Flag,
|
MedusaV2Flag,
|
||||||
|
isObject,
|
||||||
} from "@medusajs/utils"
|
} from "@medusajs/utils"
|
||||||
import {
|
|
||||||
MedusaApp,
|
|
||||||
MedusaAppMigrateUp,
|
|
||||||
MedusaAppOutput,
|
|
||||||
MedusaModule,
|
|
||||||
MODULE_PACKAGE_NAMES,
|
|
||||||
Modules,
|
|
||||||
ModulesDefinition,
|
|
||||||
} from "@medusajs/modules-sdk"
|
|
||||||
|
|
||||||
import { asValue } from "awilix"
|
import { asValue } from "awilix"
|
||||||
import { joinerConfig } from "../joiner-config"
|
|
||||||
import { remoteQueryFetchData } from "../utils/remote-query-fetch-data"
|
import { remoteQueryFetchData } from "../utils/remote-query-fetch-data"
|
||||||
|
|
||||||
export function mergeDefaultModules(
|
export function mergeDefaultModules(
|
||||||
@@ -101,7 +100,6 @@ export async function migrateMedusaApp(
|
|||||||
|
|
||||||
await MedusaAppMigrateUp({
|
await MedusaAppMigrateUp({
|
||||||
modulesConfig: configModules,
|
modulesConfig: configModules,
|
||||||
servicesConfig: joinerConfig,
|
|
||||||
remoteFetchData: remoteQueryFetchData(container),
|
remoteFetchData: remoteQueryFetchData(container),
|
||||||
sharedContainer: container,
|
sharedContainer: container,
|
||||||
sharedResourcesConfig,
|
sharedResourcesConfig,
|
||||||
@@ -170,7 +168,6 @@ export const loadMedusaApp = async (
|
|||||||
const medusaApp = await MedusaApp({
|
const medusaApp = await MedusaApp({
|
||||||
workerMode: configModule.projectConfig.worker_mode,
|
workerMode: configModule.projectConfig.worker_mode,
|
||||||
modulesConfig: configModules,
|
modulesConfig: configModules,
|
||||||
servicesConfig: joinerConfig,
|
|
||||||
remoteFetchData: remoteQueryFetchData(container),
|
remoteFetchData: remoteQueryFetchData(container),
|
||||||
sharedContainer: container,
|
sharedContainer: container,
|
||||||
sharedResourcesConfig,
|
sharedResourcesConfig,
|
||||||
@@ -291,7 +288,6 @@ export async function runModulesLoader({
|
|||||||
|
|
||||||
await MedusaApp({
|
await MedusaApp({
|
||||||
modulesConfig: configModules,
|
modulesConfig: configModules,
|
||||||
servicesConfig: joinerConfig,
|
|
||||||
remoteFetchData: remoteQueryFetchData(container),
|
remoteFetchData: remoteQueryFetchData(container),
|
||||||
sharedContainer: container,
|
sharedContainer: container,
|
||||||
sharedResourcesConfig,
|
sharedResourcesConfig,
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
import { PaginatedResponse } from "../../../common"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @experimental
|
* @experimental
|
||||||
*/
|
*/
|
||||||
export interface AdminShippingProfileResponse {
|
export interface ShippingProfileResponse {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
type: string
|
type: string
|
||||||
@@ -10,3 +12,11 @@ export interface AdminShippingProfileResponse {
|
|||||||
updated_at: Date
|
updated_at: Date
|
||||||
deleted_at: Date | null
|
deleted_at: Date | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AdminShippingProfileResponse {
|
||||||
|
shipping_profile: ShippingProfileResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AdminShippingProfilesResponse extends PaginatedResponse {
|
||||||
|
shipping_profiles: ShippingProfileResponse[]
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
export * from "./create-shipping-options"
|
export * from "./create-shipping-options"
|
||||||
export * from "./update-shipping-options"
|
|
||||||
export * from "./service-zones"
|
export * from "./service-zones"
|
||||||
|
export * from "./shipping-profiles"
|
||||||
|
export * from "./update-shipping-options"
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { FilterableShippingProfileProps } from "../../fulfillment"
|
||||||
|
|
||||||
|
interface CreateShippingProfile {
|
||||||
|
name: string
|
||||||
|
type: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreateShippingProfilesWorkflowInput {
|
||||||
|
data: CreateShippingProfile[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UpdateShippingProfile {
|
||||||
|
name?: string
|
||||||
|
type?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateShippingProfilesWorkflowInput {
|
||||||
|
selector: FilterableShippingProfileProps
|
||||||
|
update: UpdateShippingProfile
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user