feat(medusa-js, medusa-react, medusa): Prepare API for admin implementations (#3110)
********What********
Add `joinSalesChannels util to stock locations
Add the following endpoints to medusa-react
- inventory items
- mutations
- update
- delete
- update location level
- delete location level
- create location level
- queries
- list inventory items
- get inventory item
- list location levels
- Stock locations
- mutations
- create stock location
- update stock location
- delete stock location
- queries
- list stock locations
- get stock locatoin
- Variants
- queries
- get inventory
- Reservations
- mutations
- create reservation
- update reservation
- delete reservation
- queries
- list reservations
- get reservation
- sales channels
- mutations
- associate location with sc
- remove location association
**Why**
- Update clients to reflect new api endpoints in the core with inventory modules
Co-authored-by: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com>
This commit is contained in:
1 parent
121b42acfe
commit
12d304307a
48 files changed
+1756
-57
No files matched your search
@@ -43,6 +43,7 @@ export * from "./routes/admin/publishable-api-keys"
|
||||
export * from "./routes/admin/regions"
|
||||
export * from "./routes/admin/return-reasons"
|
||||
export * from "./routes/admin/returns"
|
||||
export * from "./routes/admin/reservations"
|
||||
export * from "./routes/admin/sales-channels"
|
||||
export * from "./routes/admin/shipping-options"
|
||||
export * from "./routes/admin/shipping-profiles"
|
||||
|
||||
@@ -82,7 +82,6 @@ export default async (req, res) => {
|
||||
* @schema AdminPostReservationsReq
|
||||
* type: object
|
||||
* required:
|
||||
* - line_item_id
|
||||
* - location_id
|
||||
* - inventory_item_id
|
||||
* - quantity
|
||||
|
||||
@@ -109,3 +109,4 @@ export * from "./create-reservation"
|
||||
export * from "./delete-reservation"
|
||||
export * from "./get-reservation"
|
||||
export * from "./update-reservation"
|
||||
export * from "./list-reservations"
|
||||
@@ -15,6 +15,7 @@ import { AdminGetSalesChannelsParams } from "./list-sales-channels"
|
||||
import { AdminPostSalesChannelsSalesChannelReq } from "./update-sales-channel"
|
||||
import { AdminPostSalesChannelsChannelStockLocationsReq } from "./associate-stock-location"
|
||||
import { AdminDeleteSalesChannelsChannelStockLocationsReq } from "./remove-stock-location"
|
||||
import { checkRegisteredModules } from "../../../middlewares/check-registered-modules"
|
||||
|
||||
const route = Router()
|
||||
|
||||
@@ -47,11 +48,19 @@ export default (app) => {
|
||||
)
|
||||
salesChannelRouter.post(
|
||||
"/stock-locations",
|
||||
checkRegisteredModules({
|
||||
stockLocationService:
|
||||
"Stock Locations are not enabled. Please add a Stock Location module to enable this functionality.",
|
||||
}),
|
||||
transformBody(AdminPostSalesChannelsChannelStockLocationsReq),
|
||||
middlewares.wrap(require("./associate-stock-location").default)
|
||||
)
|
||||
salesChannelRouter.delete(
|
||||
"/stock-locations",
|
||||
checkRegisteredModules({
|
||||
stockLocationService:
|
||||
"Stock Locations are not enabled. Please add a Stock Location module to enable this functionality.",
|
||||
}),
|
||||
transformBody(AdminDeleteSalesChannelsChannelStockLocationsReq),
|
||||
middlewares.wrap(require("./remove-stock-location").default)
|
||||
)
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { IStockLocationService } from "../../../../interfaces"
|
||||
import { Request, Response } from "express"
|
||||
import { FindParams } from "../../../../types/common"
|
||||
import { joinSalesChannels } from "./utils/join-sales-channels"
|
||||
import {
|
||||
SalesChannelLocationService,
|
||||
SalesChannelService,
|
||||
} from "../../../../services"
|
||||
|
||||
/**
|
||||
* @oas [get] /stock-locations/{id}
|
||||
@@ -50,7 +55,34 @@ export default async (req: Request, res: Response) => {
|
||||
const locationService: IStockLocationService = req.scope.resolve(
|
||||
"stockLocationService"
|
||||
)
|
||||
const stockLocation = await locationService.retrieve(id, req.retrieveConfig)
|
||||
const channelLocationService: SalesChannelLocationService = req.scope.resolve(
|
||||
"salesChannelLocationService"
|
||||
)
|
||||
const salesChannelService: SalesChannelService = req.scope.resolve(
|
||||
"salesChannelService"
|
||||
)
|
||||
|
||||
const { retrieveConfig } = req
|
||||
|
||||
const includeSalesChannels =
|
||||
!!retrieveConfig.relations?.includes("sales_channels")
|
||||
|
||||
if (includeSalesChannels) {
|
||||
retrieveConfig.relations = retrieveConfig.relations?.filter(
|
||||
(r) => r !== "sales_channels"
|
||||
)
|
||||
}
|
||||
|
||||
let stockLocation = await locationService.retrieve(id, retrieveConfig)
|
||||
|
||||
if (includeSalesChannels) {
|
||||
const [location] = await joinSalesChannels(
|
||||
[stockLocation],
|
||||
channelLocationService,
|
||||
salesChannelService
|
||||
)
|
||||
stockLocation = location
|
||||
}
|
||||
|
||||
res.status(200).json({ stock_location: stockLocation })
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Router } from "express"
|
||||
import "reflect-metadata"
|
||||
import { DeleteResponse, PaginatedResponse } from "../../../../types/common"
|
||||
import { StockLocationDTO } from "../../../../types/stock-location"
|
||||
import {
|
||||
StockLocationDTO,
|
||||
StockLocationExpandedDTO,
|
||||
} from "../../../../types/stock-location"
|
||||
import middlewares, {
|
||||
transformBody,
|
||||
transformQuery,
|
||||
@@ -113,10 +116,10 @@ export type AdminStockLocationsDeleteRes = DeleteResponse
|
||||
* type: object
|
||||
* properties:
|
||||
* stock_location:
|
||||
* $ref: "#/components/schemas/StockLocationDTO"
|
||||
* $ref: "#/components/schemas/StockLocationExpandedDTO"
|
||||
*/
|
||||
export type AdminStockLocationsRes = {
|
||||
stock_location: StockLocationDTO
|
||||
stock_location: StockLocationExpandedDTO
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,7 +129,7 @@ export type AdminStockLocationsRes = {
|
||||
* stock_locations:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: "#/components/schemas/StockLocationDTO"
|
||||
* $ref: "#/components/schemas/StockLocationExpandedDTO"
|
||||
* count:
|
||||
* type: integer
|
||||
* description: The total number of items available
|
||||
@@ -138,7 +141,7 @@ export type AdminStockLocationsRes = {
|
||||
* description: The number of items per page
|
||||
*/
|
||||
export type AdminStockLocationsListRes = PaginatedResponse & {
|
||||
stock_locations: StockLocationDTO[]
|
||||
stock_locations: StockLocationExpandedDTO[]
|
||||
}
|
||||
|
||||
export * from "./list-stock-locations"
|
||||
|
||||
@@ -4,6 +4,11 @@ import { IsType } from "../../../../utils/validators/is-type"
|
||||
import { IStockLocationService } from "../../../../interfaces"
|
||||
import { extendedFindParamsMixin } from "../../../../types/common"
|
||||
import { Request, Response } from "express"
|
||||
import {
|
||||
SalesChannelLocationService,
|
||||
SalesChannelService,
|
||||
} from "../../../../services"
|
||||
import { joinSalesChannels } from "./utils/join-sales-channels"
|
||||
|
||||
/**
|
||||
* @oas [get] /stock-locations
|
||||
@@ -133,15 +138,38 @@ export default async (req: Request, res: Response) => {
|
||||
const stockLocationService: IStockLocationService = req.scope.resolve(
|
||||
"stockLocationService"
|
||||
)
|
||||
const channelLocationService: SalesChannelLocationService = req.scope.resolve(
|
||||
"salesChannelLocationService"
|
||||
)
|
||||
const salesChannelService: SalesChannelService = req.scope.resolve(
|
||||
"salesChannelService"
|
||||
)
|
||||
|
||||
const { filterableFields, listConfig } = req
|
||||
const { skip, take } = listConfig
|
||||
|
||||
const [locations, count] = await stockLocationService.listAndCount(
|
||||
const includeSalesChannels =
|
||||
!!listConfig.relations?.includes("sales_channels")
|
||||
|
||||
if (includeSalesChannels) {
|
||||
listConfig.relations = listConfig.relations?.filter(
|
||||
(r) => r !== "sales_channels"
|
||||
)
|
||||
}
|
||||
|
||||
let [locations, count] = await stockLocationService.listAndCount(
|
||||
filterableFields,
|
||||
listConfig
|
||||
)
|
||||
|
||||
if (includeSalesChannels) {
|
||||
locations = await joinSalesChannels(
|
||||
locations,
|
||||
channelLocationService,
|
||||
salesChannelService
|
||||
)
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
stock_locations: locations,
|
||||
count,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import {
|
||||
SalesChannelLocationService,
|
||||
SalesChannelService,
|
||||
} from "../../../../../services"
|
||||
import {
|
||||
StockLocationDTO,
|
||||
StockLocationExpandedDTO,
|
||||
} from "../../../../../types/stock-location"
|
||||
|
||||
const joinSalesChannels = async (
|
||||
locations: StockLocationDTO[],
|
||||
channelLocationService: SalesChannelLocationService,
|
||||
salesChannelService: SalesChannelService
|
||||
): Promise<StockLocationExpandedDTO[]> => {
|
||||
return await Promise.all(
|
||||
locations.map(async (location: StockLocationExpandedDTO) => {
|
||||
const salesChannelIds = await channelLocationService.listSalesChannelIds(
|
||||
location.id
|
||||
)
|
||||
const [salesChannels] = await salesChannelService.listAndCount({
|
||||
id: salesChannelIds,
|
||||
})
|
||||
|
||||
location.sales_channels = salesChannels
|
||||
|
||||
return location
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
export { joinSalesChannels }
|
||||
@@ -1,11 +1,9 @@
|
||||
import { FulfillmentProvider, PaymentProvider, Store } from "../../../../models"
|
||||
import {
|
||||
FulfillmentProviderService,
|
||||
PaymentProviderService,
|
||||
StoreService,
|
||||
} from "../../../../services"
|
||||
import { FeatureFlagsResponse } from "../../../../types/feature-flags"
|
||||
import { ModulesResponse } from "../../../../types/modules"
|
||||
import { ExtendedStoreDTO } from "../../../../types/store"
|
||||
import { FlagRouter } from "../../../../utils/flag-router"
|
||||
import { ModulesHelper } from "../../../../utils/module-helper"
|
||||
|
||||
@@ -77,12 +75,7 @@ export default async (req, res) => {
|
||||
|
||||
const data = (await storeService.retrieve({
|
||||
relations,
|
||||
})) as Store & {
|
||||
payment_providers: PaymentProvider[]
|
||||
fulfillment_providers: FulfillmentProvider[]
|
||||
feature_flags: FeatureFlagsResponse
|
||||
modules: ModulesResponse
|
||||
}
|
||||
})) as ExtendedStoreDTO
|
||||
|
||||
data.feature_flags = featureFlagRouter.listFlags()
|
||||
data.modules = modulesHelper.modules
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Router } from "express"
|
||||
import { PaymentProvider, Store, TaxProvider } from "./../../../../"
|
||||
import { PaymentProvider, TaxProvider } from "./../../../../"
|
||||
import middlewares from "../../../middlewares"
|
||||
import { ExtendedStoreDTO } from "../../../../types/store"
|
||||
|
||||
const route = Router()
|
||||
|
||||
@@ -34,10 +35,10 @@ export default (app) => {
|
||||
* type: object
|
||||
* properties:
|
||||
* store:
|
||||
* $ref: "#/components/schemas/Store"
|
||||
* $ref: "#/components/schemas/ExtendedStoreDTO"
|
||||
*/
|
||||
export type AdminStoresRes = {
|
||||
store: Store
|
||||
store: ExtendedStoreDTO
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -72,7 +72,9 @@ export default async (req, res) => {
|
||||
|
||||
const inventoryService: IInventoryService =
|
||||
req.scope.resolve("inventoryService")
|
||||
|
||||
const channelLocationService: SalesChannelLocationService = req.scope.resolve(
|
||||
"salesChannelLocationService"
|
||||
)
|
||||
const channelService: SalesChannelService = req.scope.resolve(
|
||||
"salesChannelService"
|
||||
)
|
||||
@@ -91,11 +93,17 @@ export default async (req, res) => {
|
||||
sales_channel_availability: [],
|
||||
}
|
||||
|
||||
const [channels] = await channelService.listAndCount(
|
||||
{},
|
||||
{
|
||||
relations: ["locations"],
|
||||
}
|
||||
const [rawChannels] = await channelService.listAndCount({})
|
||||
const channels: SalesChannelDTO[] = await Promise.all(
|
||||
rawChannels.map(async (channel) => {
|
||||
const locationIds = await channelLocationService.listLocationIds(
|
||||
channel.id
|
||||
)
|
||||
return {
|
||||
...channel,
|
||||
locations: locationIds,
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
const inventory =
|
||||
@@ -116,7 +124,7 @@ export default async (req, res) => {
|
||||
|
||||
const quantity = await inventoryService.retrieveAvailableQuantity(
|
||||
inventory[0].id,
|
||||
channel.locations.map((loc) => loc.id)
|
||||
channel.locations
|
||||
)
|
||||
|
||||
return {
|
||||
@@ -133,6 +141,10 @@ export default async (req, res) => {
|
||||
})
|
||||
}
|
||||
|
||||
type SalesChannelDTO = Omit<SalesChannel, "beforeInsert" | "locations"> & {
|
||||
locations: string[]
|
||||
}
|
||||
|
||||
type ResponseInventoryItem = Partial<InventoryItemDTO> & {
|
||||
location_levels?: InventoryLevelDTO[]
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user