feat: Sales Channels API routes + workflows (#6722)

**What**
- Admin sales channels API routes
- Workflows for creating, updating, and deleting sales channels
- Align `ISalesChannelModuleService` interface with update + upsert conventions
- Integrate v2 tests into v1 sales channels integration test suite
- Add metadata to sales channel entity

Sales channel <> Product management will come in a follow-up PR.

On the integration tests, creating, updating, and deleting are passing with the V2 flag enabled. You'll have to take my word for it (or run them yourself), as they are not included in the CI.
This commit is contained in:
Oli Juhl authored and GitHub committed 2024-03-18 20:57:29 +00:00
1 parent 4b06c17dc0
commit 0219a8677b
28 files changed
+1640 -1146

No files matched your search

@@ -2,6 +2,7 @@ import {
Context,
CreateSalesChannelDTO,
DAL,
FilterableSalesChannelProps,
InternalModuleDeclaration,
ISalesChannelModuleService,
ModuleJoinerConfig,
@@ -9,10 +10,19 @@ import {
SalesChannelDTO,
UpdateSalesChannelDTO,
} from "@medusajs/types"
import { MedusaContext, ModulesSdkUtils } from "@medusajs/utils"
import {
InjectManager,
InjectTransactionManager,
isString,
MedusaContext,
ModulesSdkUtils,
promiseAll,
} from "@medusajs/utils"
import { SalesChannel } from "@models"
import { UpsertSalesChannelDTO } from "@medusajs/types"
import { UpdateSalesChanneInput } from "@types"
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
type InjectedDependencies = {
@@ -51,19 +61,18 @@ export default class SalesChannelModuleService<
data: CreateSalesChannelDTO[],
sharedContext?: Context
): Promise<SalesChannelDTO[]>
async create(
data: CreateSalesChannelDTO,
sharedContext?: Context
): Promise<SalesChannelDTO>
@InjectManager("baseRepository_")
async create(
data: CreateSalesChannelDTO | CreateSalesChannelDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<SalesChannelDTO | SalesChannelDTO[]> {
const input = Array.isArray(data) ? data : [data]
const result = await this.salesChannelService_.create(input, sharedContext)
const result = await this.create_(input, sharedContext)
return await this.baseRepository_.serialize<SalesChannelDTO[]>(
Array.isArray(data) ? result : result[0],
@@ -73,23 +82,47 @@ export default class SalesChannelModuleService<
)
}
async update(
data: UpdateSalesChannelDTO[],
sharedContext?: Context
): Promise<SalesChannelDTO[]>
@InjectTransactionManager("baseRepository_")
async create_(
data: CreateSalesChannelDTO[],
@MedusaContext() sharedContext: Context
): Promise<SalesChannel[]> {
return await this.salesChannelService_.create(data, sharedContext)
}
async update(
id: string,
data: UpdateSalesChannelDTO,
sharedContext?: Context
): Promise<SalesChannelDTO>
async update(
selector: FilterableSalesChannelProps,
data: UpdateSalesChannelDTO,
sharedContext?: Context
): Promise<SalesChannelDTO[]>
@InjectManager("baseRepository_")
async update(
idOrSelector: string | FilterableSalesChannelProps,
data: UpdateSalesChannelDTO | UpdateSalesChannelDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<SalesChannelDTO | SalesChannelDTO[]> {
const input = Array.isArray(data) ? data : [data]
let normalizedInput: UpdateSalesChanneInput[] = []
if (isString(idOrSelector)) {
normalizedInput = [{ id: idOrSelector, ...data }]
} else {
const channels = await this.salesChannelService_.list(
idOrSelector,
{},
sharedContext
)
const result = await this.salesChannelService_.update(input, sharedContext)
normalizedInput = channels.map((channel) => ({
id: channel.id,
...data,
}))
}
const result = await this.update_(normalizedInput, sharedContext)
return await this.baseRepository_.serialize<SalesChannelDTO[]>(
Array.isArray(data) ? result : result[0],
@@ -98,4 +131,45 @@ export default class SalesChannelModuleService<
}
)
}
@InjectTransactionManager("baseRepository_")
async update_(data: UpdateSalesChannelDTO[], sharedContext: Context) {
return await this.salesChannelService_.update(data, sharedContext)
}
async upsert(
data: UpsertSalesChannelDTO[],
sharedContext?: Context
): Promise<SalesChannelDTO[]>
async upsert(
data: UpsertSalesChannelDTO,
sharedContext?: Context
): Promise<SalesChannelDTO>
@InjectTransactionManager("baseRepository_")
async upsert(
data: UpsertSalesChannelDTO | UpsertSalesChannelDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<SalesChannelDTO | SalesChannelDTO[]> {
const input = Array.isArray(data) ? data : [data]
const forUpdate = input.filter(
(channel): channel is UpdateSalesChannelDTO => !!channel.id
)
const forCreate = input.filter(
(channel): channel is CreateSalesChannelDTO => !channel.id
)
const operations: Promise<SalesChannel[]>[] = []
if (forCreate.length) {
operations.push(this.create_(forCreate, sharedContext))
}
if (forUpdate.length) {
operations.push(this.update_(forUpdate, sharedContext))
}
const result = (await promiseAll(operations)).flat()
return await this.baseRepository_.serialize<
SalesChannelDTO[] | SalesChannelDTO
>(Array.isArray(data) ? result : result[0])
}
}