feat(medusa, medusa-js, medusa-react): Implement Sales Channel retrieval (#1793)
This commit is contained in:
1 parent
e115518dda
commit
263a661031
26 files changed
+511
-34
No files matched your search
@@ -0,0 +1,13 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`sales channels GET /admin/sales-channels/:id should retrieve the requested sales channel 1`] = `
|
||||||
|
Object {
|
||||||
|
"created_at": Any<String>,
|
||||||
|
"deleted_at": null,
|
||||||
|
"description": "test description",
|
||||||
|
"id": Any<String>,
|
||||||
|
"is_disabled": false,
|
||||||
|
"name": "test name",
|
||||||
|
"updated_at": Any<String>,
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -2,10 +2,19 @@ const path = require("path")
|
|||||||
|
|
||||||
const { useApi } = require("../../../helpers/use-api")
|
const { useApi } = require("../../../helpers/use-api")
|
||||||
const { useDb } = require("../../../helpers/use-db")
|
const { useDb } = require("../../../helpers/use-db")
|
||||||
|
|
||||||
const adminSeeder = require("../../helpers/admin-seeder")
|
const adminSeeder = require("../../helpers/admin-seeder")
|
||||||
|
const { simpleSalesChannelFactory, } = require("../../factories")
|
||||||
|
|
||||||
const startServerWithEnvironment =
|
const startServerWithEnvironment =
|
||||||
require("../../../helpers/start-server-with-environment").default
|
require("../../../helpers/start-server-with-environment").default
|
||||||
|
|
||||||
|
const adminReqConfig = {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer test_token",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
jest.setTimeout(30000)
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
describe("sales channels", () => {
|
describe("sales channels", () => {
|
||||||
@@ -36,7 +45,46 @@ describe("sales channels", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe("POST /admin/sales-channels", () => {})
|
describe("POST /admin/sales-channels", () => {})
|
||||||
describe("GET /admin/sales-channels/:id", () => {})
|
|
||||||
|
describe("GET /admin/sales-channels/:id", () => {
|
||||||
|
let salesChannel
|
||||||
|
|
||||||
|
beforeEach(async() => {
|
||||||
|
try {
|
||||||
|
await adminSeeder(dbConnection)
|
||||||
|
salesChannel = await simpleSalesChannelFactory(dbConnection, {
|
||||||
|
name: "test name",
|
||||||
|
description: "test description",
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async() => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.teardown()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should retrieve the requested sales channel", async() => {
|
||||||
|
const api = useApi()
|
||||||
|
const response = await api.get(
|
||||||
|
`/admin/sales-channels/${salesChannel.id}`,
|
||||||
|
adminReqConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.sales_channel).toBeTruthy()
|
||||||
|
expect(response.data.sales_channel).toMatchSnapshot({
|
||||||
|
id: expect.any(String),
|
||||||
|
name: salesChannel.name,
|
||||||
|
description: salesChannel.description,
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("POST /admin/sales-channels/:id", () => {})
|
describe("POST /admin/sales-channels/:id", () => {})
|
||||||
describe("DELETE /admin/sales-channels/:id", () => {})
|
describe("DELETE /admin/sales-channels/:id", () => {})
|
||||||
})
|
})
|
||||||
@@ -15,3 +15,4 @@ export * from "./simple-shipping-method-factory"
|
|||||||
export * from "./simple-product-type-tax-rate-factory"
|
export * from "./simple-product-type-tax-rate-factory"
|
||||||
export * from "./simple-price-list-factory"
|
export * from "./simple-price-list-factory"
|
||||||
export * from "./simple-batch-job-factory"
|
export * from "./simple-batch-job-factory"
|
||||||
|
export * from "./simple-sales-channel-factory"
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { Connection } from "typeorm"
|
||||||
|
import faker from "faker"
|
||||||
|
import { SalesChannel } from "@medusajs/medusa"
|
||||||
|
|
||||||
|
export type SalesChannelFactoryData = {
|
||||||
|
name?: string
|
||||||
|
description?: string
|
||||||
|
is_disabled?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const simpleSalesChannelFactory = async (
|
||||||
|
connection: Connection,
|
||||||
|
data: SalesChannelFactoryData = {},
|
||||||
|
seed?: number
|
||||||
|
): Promise<SalesChannel> => {
|
||||||
|
if (typeof seed !== "undefined") {
|
||||||
|
faker.seed(seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
const manager = connection.manager
|
||||||
|
|
||||||
|
const salesChannel = manager.create(SalesChannel, {
|
||||||
|
id: `simple-id-${Math.random() * 1000}`,
|
||||||
|
name: data.name || faker.name.firstName(),
|
||||||
|
description: data.description || faker.name.lastName(),
|
||||||
|
is_disabled:
|
||||||
|
typeof data.is_disabled !== undefined ? data.is_disabled : false,
|
||||||
|
})
|
||||||
|
|
||||||
|
return await manager.save(salesChannel)
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ import AdminProductsResource from "./products"
|
|||||||
import AdminRegionsResource from "./regions"
|
import AdminRegionsResource from "./regions"
|
||||||
import AdminReturnReasonsResource from "./return-reasons"
|
import AdminReturnReasonsResource from "./return-reasons"
|
||||||
import AdminReturnsResource from "./returns"
|
import AdminReturnsResource from "./returns"
|
||||||
|
import AdminSalesChannelsResource from "./sales-channels"
|
||||||
import AdminShippingOptionsResource from "./shipping-options"
|
import AdminShippingOptionsResource from "./shipping-options"
|
||||||
import AdminShippingProfilesResource from "./shipping-profiles"
|
import AdminShippingProfilesResource from "./shipping-profiles"
|
||||||
import AdminStoresResource from "./store"
|
import AdminStoresResource from "./store"
|
||||||
@@ -47,6 +48,7 @@ class Admin extends BaseResource {
|
|||||||
public orders = new AdminOrdersResource(this.client)
|
public orders = new AdminOrdersResource(this.client)
|
||||||
public returnReasons = new AdminReturnReasonsResource(this.client)
|
public returnReasons = new AdminReturnReasonsResource(this.client)
|
||||||
public variants = new AdminVariantsResource(this.client)
|
public variants = new AdminVariantsResource(this.client)
|
||||||
|
public salesChannels = new AdminSalesChannelsResource(this.client)
|
||||||
public swaps = new AdminSwapsResource(this.client)
|
public swaps = new AdminSwapsResource(this.client)
|
||||||
public shippingProfiles = new AdminShippingProfilesResource(this.client)
|
public shippingProfiles = new AdminShippingProfilesResource(this.client)
|
||||||
public store = new AdminStoresResource(this.client)
|
public store = new AdminStoresResource(this.client)
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import {
|
||||||
|
AdminSalesChannelRes,
|
||||||
|
} from "@medusajs/medusa"
|
||||||
|
import { ResponsePromise } from "../../typings"
|
||||||
|
import BaseResource from "../base"
|
||||||
|
|
||||||
|
class AdminSalesChannelsResource extends BaseResource {
|
||||||
|
/**
|
||||||
|
* @description gets a sales channel
|
||||||
|
* @returns a medusa sales channel
|
||||||
|
*/
|
||||||
|
retrieve(
|
||||||
|
salesChannelId: string,
|
||||||
|
customHeaders: Record<string, any> = {}
|
||||||
|
): ResponsePromise<AdminSalesChannelRes> {
|
||||||
|
const path = `/admin/sales-channels/${salesChannelId}`
|
||||||
|
return this.client.request("GET", path, {}, {}, customHeaders)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*create(
|
||||||
|
payload: any,
|
||||||
|
customHeaders: Record<string, any> = {}
|
||||||
|
): ResponsePromise<any> {}*/
|
||||||
|
|
||||||
|
/*update(
|
||||||
|
id: string,
|
||||||
|
payload: any,
|
||||||
|
customHeaders: Record<string, any> = {}
|
||||||
|
): ResponsePromise<any> {}*/
|
||||||
|
|
||||||
|
/*delete(
|
||||||
|
id: string,
|
||||||
|
customHeaders: Record<string, any> = {}
|
||||||
|
): ResponsePromise<any> {
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/*list(
|
||||||
|
query?: any,
|
||||||
|
customHeaders: Record<string, any> = {}
|
||||||
|
): ResponsePromise<any> {
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AdminSalesChannelsResource
|
||||||
@@ -1261,6 +1261,15 @@
|
|||||||
},
|
},
|
||||||
"upload": {
|
"upload": {
|
||||||
"url": "test-url"
|
"url": "test-url"
|
||||||
|
},
|
||||||
|
"sales_channel": {
|
||||||
|
"id": "sc_01F0YES4R67TXXC1QBQ8P54A8Y",
|
||||||
|
"name": "sales channel 1 name",
|
||||||
|
"description": "sales channel 1 description",
|
||||||
|
"is_disabled": false,
|
||||||
|
"updated_at": "2022-07-05T15:16:01.959Z",
|
||||||
|
"created_at": "2022-07-05T15:16:01.959Z",
|
||||||
|
"deleted_at": null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1672,4 +1672,13 @@ export const adminHandlers = [
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
rest.get("/admin/sales-channels/:id", (req, res, ctx) => {
|
||||||
|
return res(
|
||||||
|
ctx.status(200),
|
||||||
|
ctx.json({
|
||||||
|
sales_channel: fixtures.get("sales_channel"),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}),
|
||||||
]
|
]
|
||||||
@@ -18,6 +18,7 @@ export * from "./products"
|
|||||||
export * from "./regions"
|
export * from "./regions"
|
||||||
export * from "./return-reasons"
|
export * from "./return-reasons"
|
||||||
export * from "./returns"
|
export * from "./returns"
|
||||||
|
export * from "./sales-channels"
|
||||||
export * from "./shipping-options"
|
export * from "./shipping-options"
|
||||||
export * from "./shipping-profiles"
|
export * from "./shipping-profiles"
|
||||||
export * from "./store"
|
export * from "./store"
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export * from "./queries"
|
||||||
|
export * from "./mutations"
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
export {}
|
||||||
|
/*export const useAdminCreateSalesChannel = (
|
||||||
|
options?: UseMutationOptions<
|
||||||
|
Response<AdminSalesChannelsRes>,
|
||||||
|
Error,
|
||||||
|
AdminPostSalesChannelsReq
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
return useMutation(
|
||||||
|
(payload: AdminPostSalesChannelsReq) => client.admin.salesChannels.create(payload),
|
||||||
|
buildOptions(queryClient, adminSalesChannelsKeys.lists(), options)
|
||||||
|
)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/*export const useAdminUpdateSalesChannel = (
|
||||||
|
id: string,
|
||||||
|
options?: UseMutationOptions<
|
||||||
|
Response<AdminSalesChannelsRes>,
|
||||||
|
Error,
|
||||||
|
AdminPostSalesChannelsSalesChannelReq
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
|
return useMutation(
|
||||||
|
(payload: AdminPostSalesChannelsSalesChannelReq) =>
|
||||||
|
client.admin.salesChannels.update(id, payload),
|
||||||
|
buildOptions(
|
||||||
|
queryClient,
|
||||||
|
[adminSalesChannelsKeys.lists(), adminSalesChannelsKeys.detail(id)],
|
||||||
|
options
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/*export const useAdminDeleteSalesChannel = (
|
||||||
|
id: string,
|
||||||
|
options?: UseMutationOptions<Response<AdminSalesChannelsDeleteRes>, Error, void>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
|
return useMutation(
|
||||||
|
() => client.admin.salesChannels.delete(id),
|
||||||
|
buildOptions(
|
||||||
|
queryClient,
|
||||||
|
[adminSalesChannelsKeys.lists(), adminSalesChannelsKeys.detail(id)],
|
||||||
|
options
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}*/
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import {
|
||||||
|
AdminSalesChannelRes
|
||||||
|
} from "@medusajs/medusa"
|
||||||
|
import { Response } from "@medusajs/medusa-js"
|
||||||
|
import { useQuery } from "react-query"
|
||||||
|
import { useMedusa } from "../../../contexts"
|
||||||
|
import { UseQueryOptionsWrapper } from "../../../types"
|
||||||
|
import { queryKeysFactory } from "../../utils"
|
||||||
|
|
||||||
|
const ADMIN_SALES_CHANNELS_QUERY_KEY = `admin_sales_channels` as const
|
||||||
|
|
||||||
|
export const adminSalesChannelsKeys = queryKeysFactory(ADMIN_SALES_CHANNELS_QUERY_KEY)
|
||||||
|
|
||||||
|
type SalesChannelsQueryKeys = typeof adminSalesChannelsKeys
|
||||||
|
|
||||||
|
export const useAdminSalesChannel = (
|
||||||
|
id: string,
|
||||||
|
options?: UseQueryOptionsWrapper<
|
||||||
|
Response<AdminSalesChannelRes>,
|
||||||
|
Error,
|
||||||
|
ReturnType<SalesChannelsQueryKeys["detail"]>
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const { data, ...rest } = useQuery(
|
||||||
|
adminSalesChannelsKeys.detail(id),
|
||||||
|
() => client.admin.salesChannels.retrieve(id),
|
||||||
|
options
|
||||||
|
)
|
||||||
|
return { ...data, ...rest } as const
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
export const useAdminSalesChannels = (
|
||||||
|
query?: AdminGetSalesChannelsParams,
|
||||||
|
options?: UseQueryOptionsWrapper<
|
||||||
|
Response<AdminProductsListRes>,
|
||||||
|
Error,
|
||||||
|
ReturnType<SalesChannelsQueryKeys["list"]>
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const { data, ...rest } = useQuery(
|
||||||
|
adminProductKeys.list(query),
|
||||||
|
() => client.admin.salesChannels.list(query),
|
||||||
|
options
|
||||||
|
)
|
||||||
|
return { ...data, ...rest } as const
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import {
|
||||||
|
useAdminSalesChannel,
|
||||||
|
} from "../../../../src"
|
||||||
|
import { renderHook } from "@testing-library/react-hooks"
|
||||||
|
import { fixtures } from "../../../../mocks/data"
|
||||||
|
import { createWrapper } from "../../../utils"
|
||||||
|
|
||||||
|
describe("useAdminSalesChannel hook", () => {
|
||||||
|
test("returns a product", async () => {
|
||||||
|
const salesChannel = fixtures.get("sales_channel")
|
||||||
|
const { result, waitFor } = renderHook(() => useAdminSalesChannel(salesChannel.id), {
|
||||||
|
wrapper: createWrapper(),
|
||||||
|
})
|
||||||
|
|
||||||
|
await waitFor(() => result.current.isSuccess)
|
||||||
|
|
||||||
|
expect(result.current.response.status).toEqual(200)
|
||||||
|
expect(result.current.sales_channel).toEqual(salesChannel)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -35,6 +35,7 @@ export * from "./routes/admin/products"
|
|||||||
export * from "./routes/admin/regions"
|
export * from "./routes/admin/regions"
|
||||||
export * from "./routes/admin/return-reasons"
|
export * from "./routes/admin/return-reasons"
|
||||||
export * from "./routes/admin/returns"
|
export * from "./routes/admin/returns"
|
||||||
|
export * from "./routes/admin/sales-channels"
|
||||||
export * from "./routes/admin/shipping-options"
|
export * from "./routes/admin/shipping-options"
|
||||||
export * from "./routes/admin/shipping-profiles"
|
export * from "./routes/admin/shipping-profiles"
|
||||||
export * from "./routes/admin/store"
|
export * from "./routes/admin/store"
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import productTypesRoutes from "./product-types"
|
|||||||
import productRoutes from "./products"
|
import productRoutes from "./products"
|
||||||
import regionRoutes from "./regions"
|
import regionRoutes from "./regions"
|
||||||
import returnReasonRoutes from "./return-reasons"
|
import returnReasonRoutes from "./return-reasons"
|
||||||
|
import salesChannelRoutes from "./sales-channels"
|
||||||
import returnRoutes from "./returns"
|
import returnRoutes from "./returns"
|
||||||
import shippingOptionRoutes from "./shipping-options"
|
import shippingOptionRoutes from "./shipping-options"
|
||||||
import shippingProfileRoutes from "./shipping-profiles"
|
import shippingProfileRoutes from "./shipping-profiles"
|
||||||
@@ -63,32 +64,33 @@ export default (app, container, config) => {
|
|||||||
middlewareService.usePostAuthentication(app)
|
middlewareService.usePostAuthentication(app)
|
||||||
|
|
||||||
appRoutes(route)
|
appRoutes(route)
|
||||||
productRoutes(route)
|
|
||||||
batchRoutes(route)
|
batchRoutes(route)
|
||||||
userRoutes(route)
|
|
||||||
regionRoutes(route)
|
|
||||||
shippingOptionRoutes(route)
|
|
||||||
shippingProfileRoutes(route)
|
|
||||||
discountRoutes(route)
|
|
||||||
giftCardRoutes(route)
|
|
||||||
orderRoutes(route)
|
|
||||||
storeRoutes(route)
|
|
||||||
uploadRoutes(route)
|
|
||||||
customerRoutes(route)
|
|
||||||
swapRoutes(route)
|
|
||||||
returnRoutes(route)
|
|
||||||
variantRoutes(route)
|
|
||||||
draftOrderRoutes(route)
|
|
||||||
collectionRoutes(route)
|
collectionRoutes(route)
|
||||||
|
customerGroupRoutes(route)
|
||||||
|
customerRoutes(route)
|
||||||
|
discountRoutes(route)
|
||||||
|
draftOrderRoutes(route)
|
||||||
|
giftCardRoutes(route)
|
||||||
|
inviteRoutes(route)
|
||||||
|
noteRoutes(route)
|
||||||
notificationRoutes(route)
|
notificationRoutes(route)
|
||||||
returnReasonRoutes(route)
|
orderRoutes(route)
|
||||||
|
priceListRoutes(route)
|
||||||
|
productRoutes(route)
|
||||||
productTagRoutes(route)
|
productTagRoutes(route)
|
||||||
productTypesRoutes(route)
|
productTypesRoutes(route)
|
||||||
noteRoutes(route)
|
regionRoutes(route)
|
||||||
inviteRoutes(route)
|
returnReasonRoutes(route)
|
||||||
|
returnRoutes(route)
|
||||||
|
salesChannelRoutes(route)
|
||||||
|
shippingOptionRoutes(route)
|
||||||
|
shippingProfileRoutes(route)
|
||||||
|
storeRoutes(route)
|
||||||
|
swapRoutes(route)
|
||||||
taxRateRoutes(route)
|
taxRateRoutes(route)
|
||||||
customerGroupRoutes(route)
|
uploadRoutes(route)
|
||||||
priceListRoutes(route)
|
userRoutes(route)
|
||||||
|
variantRoutes(route)
|
||||||
|
|
||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { IdMap } from "medusa-test-utils"
|
||||||
|
import { request } from "../../../../../helpers/test-request"
|
||||||
|
import { SalesChannelServiceMock } from "../../../../../services/__mocks__/sales-channel"
|
||||||
|
|
||||||
|
describe("GET /admin/sales-channels/:id", () => {
|
||||||
|
describe("successfully get a sales channel", () => {
|
||||||
|
let subject
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
subject = await request(
|
||||||
|
"GET",
|
||||||
|
`/admin/sales-channels/${IdMap.getId("sales_channel_1")}`,
|
||||||
|
{
|
||||||
|
adminSession: {
|
||||||
|
jwt: {
|
||||||
|
userId: IdMap.getId("admin_user"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: ["sales_channels"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls the retrieve method from the sales channel service", () => {
|
||||||
|
expect(SalesChannelServiceMock.retrieve).toHaveBeenCalledTimes(1)
|
||||||
|
expect(SalesChannelServiceMock.retrieve).toHaveBeenCalledWith(
|
||||||
|
IdMap.getId("sales_channel_1"),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns the expected sales channel", () => {
|
||||||
|
expect(subject.body.sales_channel).toEqual({
|
||||||
|
id: IdMap.getId("sales_channel_1"),
|
||||||
|
name: "sales channel 1 name",
|
||||||
|
description: "sales channel 1 description",
|
||||||
|
is_disabled: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { Request, Response } from "express"
|
||||||
|
import SalesChannelService from "../../../../services/sales-channel"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @oas [get] /sales-channels/{id}
|
||||||
|
* operationId: "GetSalesChannelsSalesChannel"
|
||||||
|
* summary: "Retrieve a sales channel"
|
||||||
|
* description: "Retrieves the sales channel."
|
||||||
|
* x-authenticated: true
|
||||||
|
* parameters:
|
||||||
|
* - (path) id=* {string} The id of the Sales channel.
|
||||||
|
* tags:
|
||||||
|
* - Sales channel
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: OK
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* sales_channel:
|
||||||
|
* $ref: "#/components/schemas/sales-channel"
|
||||||
|
*/
|
||||||
|
export default async (req: Request, res: Response): Promise<void> => {
|
||||||
|
const { id } = req.params
|
||||||
|
|
||||||
|
const salesChannelService: SalesChannelService = req.scope.resolve(
|
||||||
|
"salesChannelService"
|
||||||
|
)
|
||||||
|
|
||||||
|
const salesChannel = await salesChannelService.retrieve(id)
|
||||||
|
res.status(200).json({ sales_channel: salesChannel })
|
||||||
|
}
|
||||||
@@ -1,17 +1,22 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
||||||
import { Router } from "express"
|
import { Router } from "express"
|
||||||
import { DeleteResponse, PaginatedResponse } from "../../../../types/common"
|
import { DeleteResponse, PaginatedResponse } from "../../../../types/common"
|
||||||
import middlewares from "../../../middlewares"
|
|
||||||
import "reflect-metadata"
|
import "reflect-metadata"
|
||||||
import { isFeatureFlagEnabled } from "../../../middlewares/feature-flag-enabled"
|
import { isFeatureFlagEnabled } from "../../../middlewares/feature-flag-enabled"
|
||||||
import { SalesChannel } from "../../../../models/sales-channel"
|
import { SalesChannel } from "../../../../models"
|
||||||
|
import middlewares from "../../../middlewares"
|
||||||
|
|
||||||
const route = Router()
|
const route = Router()
|
||||||
|
|
||||||
export default (app) => {
|
export default (app) => {
|
||||||
app.use("/sales-channels", isFeatureFlagEnabled("sales_channels"), route)
|
app.use("/sales-channels", isFeatureFlagEnabled("sales_channels"), route)
|
||||||
|
|
||||||
route.get("/:id", (req, res) => {})
|
const salesChannelRouter = Router({ mergeParams: true })
|
||||||
|
route.use("/:id", salesChannelRouter)
|
||||||
|
|
||||||
|
salesChannelRouter.get(
|
||||||
|
"/",
|
||||||
|
middlewares.wrap(require("./get-sales-channel").default)
|
||||||
|
)
|
||||||
|
|
||||||
route.get("/", (req, res) => {})
|
route.get("/", (req, res) => {})
|
||||||
|
|
||||||
@@ -24,7 +29,7 @@ export default (app) => {
|
|||||||
return app
|
return app
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AdminSalesChanenlRes = {
|
export type AdminSalesChannelRes = {
|
||||||
sales_channel: SalesChannel
|
sales_channel: SalesChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +39,7 @@ export type AdminSalesChannelListRes = PaginatedResponse & {
|
|||||||
sales_channels: SalesChannel[]
|
sales_channels: SalesChannel[]
|
||||||
}
|
}
|
||||||
|
|
||||||
// export * from './'
|
export * from "./get-sales-channel"
|
||||||
// export * from './'
|
// export * from './'
|
||||||
// export * from './'
|
// export * from './'
|
||||||
// export * from './'
|
// export * from './'
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ export default (
|
|||||||
): FlagRouter => {
|
): FlagRouter => {
|
||||||
const { featureFlags: projectConfigFlags = {} } = configModule
|
const { featureFlags: projectConfigFlags = {} } = configModule
|
||||||
|
|
||||||
const flagDir = path.join(flagDirectory || __dirname, "*.js")
|
const flagDir = path.join(flagDirectory || __dirname, "*.{j,t}s")
|
||||||
const supportedFlags = glob.sync(flagDir, {
|
const supportedFlags = glob.sync(flagDir, {
|
||||||
ignore: ["**/index.js"],
|
ignore: ["**/index.js", "**/index.ts", "**/*.d.ts"],
|
||||||
})
|
})
|
||||||
|
|
||||||
const flagConfig: Record<string, boolean> = {}
|
const flagConfig: Record<string, boolean> = {}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export * from "./region"
|
|||||||
export * from "./return"
|
export * from "./return"
|
||||||
export * from "./return-item"
|
export * from "./return-item"
|
||||||
export * from "./return-reason"
|
export * from "./return-reason"
|
||||||
|
export * from "./sales-channel"
|
||||||
export * from "./shipping-method"
|
export * from "./shipping-method"
|
||||||
export * from "./shipping-method-tax-line"
|
export * from "./shipping-method-tax-line"
|
||||||
export * from "./shipping-option"
|
export * from "./shipping-option"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { EntityRepository, Repository } from "typeorm"
|
import { EntityRepository, Repository } from "typeorm"
|
||||||
import { SalesChannel } from "../models/sales-channel"
|
import { SalesChannel } from "../models"
|
||||||
|
|
||||||
@EntityRepository(SalesChannel)
|
@EntityRepository(SalesChannel)
|
||||||
export class SalesChannelRepository extends Repository<SalesChannel> {}
|
export class SalesChannelRepository extends Repository<SalesChannel> {}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export const SalesChannelServiceMock = {
|
||||||
|
withTransaction: function () {
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
|
||||||
|
retrieve: jest.fn().mockImplementation((id, config) => {
|
||||||
|
return Promise.resolve({
|
||||||
|
id: id,
|
||||||
|
name: "sales channel 1 name",
|
||||||
|
description: "sales channel 1 description",
|
||||||
|
is_disabled: false,
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
const mock = jest.fn().mockImplementation(() => {
|
||||||
|
return SalesChannelServiceMock
|
||||||
|
})
|
||||||
|
|
||||||
|
export default mock
|
||||||
@@ -22,7 +22,7 @@ describe('BatchJobService', () => {
|
|||||||
manager: MockManager,
|
manager: MockManager,
|
||||||
eventBusService: eventBusServiceMock,
|
eventBusService: eventBusServiceMock,
|
||||||
batchJobRepository: batchJobRepositoryMock
|
batchJobRepository: batchJobRepositoryMock
|
||||||
})
|
} as any)
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { IdMap, MockManager, MockRepository } from "medusa-test-utils"
|
||||||
|
import SalesChannelService from "../sales-channel"
|
||||||
|
import { EventBusServiceMock } from "../__mocks__/event-bus"
|
||||||
|
import { EventBusService } from "../index"
|
||||||
|
import { FindConditions, FindOneOptions } from "typeorm"
|
||||||
|
import { SalesChannel } from "../../models"
|
||||||
|
|
||||||
|
describe('SalesChannelService', () => {
|
||||||
|
describe("retrieve", () => {
|
||||||
|
const salesChannelData = {
|
||||||
|
name: "sales channel 1 name",
|
||||||
|
description: "sales channel 1 description",
|
||||||
|
is_disabled: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
const salesChannelRepositoryMock = MockRepository({
|
||||||
|
findOne: jest.fn().mockImplementation((queryOrId: string | FindOneOptions<SalesChannel>): any => {
|
||||||
|
return Promise.resolve({
|
||||||
|
id:
|
||||||
|
typeof queryOrId === "string"
|
||||||
|
? queryOrId
|
||||||
|
: ((queryOrId?.where as FindConditions<SalesChannel>)?.id ?? IdMap.getId("sc_adjhlukiaeswhfae")),
|
||||||
|
...salesChannelData
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
const salesChannelService = new SalesChannelService({
|
||||||
|
manager: MockManager,
|
||||||
|
eventBusService: EventBusServiceMock as unknown as EventBusService,
|
||||||
|
salesChannelRepository: salesChannelRepositoryMock
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should retrieve a sales channel', async () => {
|
||||||
|
const salesChannel = await salesChannelService.retrieve(
|
||||||
|
IdMap.getId("sales_channel_1")
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(salesChannel).toBeTruthy()
|
||||||
|
expect(salesChannel).toEqual({
|
||||||
|
id: IdMap.getId("sales_channel_1"),
|
||||||
|
...salesChannelData
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(salesChannelRepositoryMock.findOne)
|
||||||
|
.toHaveBeenCalledTimes(1)
|
||||||
|
expect(salesChannelRepositoryMock.findOne)
|
||||||
|
.toHaveBeenLastCalledWith(
|
||||||
|
{ where: { id: IdMap.getId("sales_channel_1") } },
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { EntityManager } from "typeorm"
|
import { EntityManager } from "typeorm"
|
||||||
import { TransactionBaseService } from "../interfaces"
|
import { TransactionBaseService } from "../interfaces"
|
||||||
import { SalesChannel } from "../models/sales-channel"
|
import { SalesChannel } from "../models"
|
||||||
import { SalesChannelRepository } from "../repositories/sales-channel"
|
import { SalesChannelRepository } from "../repositories/sales-channel"
|
||||||
import { FindConfig, QuerySelector } from "../types/common"
|
import { FindConfig, QuerySelector } from "../types/common"
|
||||||
import {
|
import {
|
||||||
@@ -8,6 +8,8 @@ import {
|
|||||||
UpdateSalesChannelInput,
|
UpdateSalesChannelInput,
|
||||||
} from "../types/sales-channels"
|
} from "../types/sales-channels"
|
||||||
import EventBusService from "./event-bus"
|
import EventBusService from "./event-bus"
|
||||||
|
import { buildQuery } from "../utils"
|
||||||
|
import { MedusaError } from "medusa-core-utils"
|
||||||
|
|
||||||
type InjectedDependencies = {
|
type InjectedDependencies = {
|
||||||
salesChannelRepository: typeof SalesChannelRepository
|
salesChannelRepository: typeof SalesChannelRepository
|
||||||
@@ -35,8 +37,33 @@ class SalesChannelService extends TransactionBaseService<SalesChannelService> {
|
|||||||
this.eventBusService_ = eventBusService
|
this.eventBusService_ = eventBusService
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrieve(id: string): Promise<SalesChannel> {
|
async retrieve(
|
||||||
throw new Error("Method not implemented.")
|
salesChannelId: string,
|
||||||
|
config: FindConfig<SalesChannel> = {}
|
||||||
|
): Promise<SalesChannel | never> {
|
||||||
|
return await this.atomicPhase_(async (manager) => {
|
||||||
|
const salesChannelRepo = manager.getCustomRepository(
|
||||||
|
this.salesChannelRepository_
|
||||||
|
)
|
||||||
|
|
||||||
|
const query = buildQuery(
|
||||||
|
{
|
||||||
|
id: salesChannelId,
|
||||||
|
},
|
||||||
|
config
|
||||||
|
)
|
||||||
|
|
||||||
|
const salesChannel = await salesChannelRepo.findOne(query)
|
||||||
|
|
||||||
|
if (!salesChannel) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_FOUND,
|
||||||
|
`Sales channel with id ${salesChannelId} was not found`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return salesChannel
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async listAndCount(
|
async listAndCount(
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Logger as _Logger } from "winston"
|
|||||||
import { LoggerOptions } from "typeorm"
|
import { LoggerOptions } from "typeorm"
|
||||||
import { Customer, User } from "../models"
|
import { Customer, User } from "../models"
|
||||||
import { FindConfig, RequestQueryFields } from "./common"
|
import { FindConfig, RequestQueryFields } from "./common"
|
||||||
|
import { Request } from "express"
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
@@ -19,6 +20,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ExtendedRequest<TEntity> = Request & { resource: TEntity }
|
||||||
|
|
||||||
export type ClassConstructor<T> = {
|
export type ClassConstructor<T> = {
|
||||||
new (...args: unknown[]): T
|
new (...args: unknown[]): T
|
||||||
|
|||||||
Reference in new issue
Block a user