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:
1 parent
4b06c17dc0
commit
0219a8677b
28 files changed
+1640
-1146
No files matched your search
+8
-13
@@ -4,8 +4,8 @@ import { ISalesChannelModuleService } from "@medusajs/types"
|
||||
|
||||
import { initialize } from "../../../src"
|
||||
|
||||
import { DB_URL, MikroOrmWrapper } from "../../utils"
|
||||
import { createSalesChannels } from "../../__fixtures__"
|
||||
import { DB_URL, MikroOrmWrapper } from "../../utils"
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
@@ -84,13 +84,10 @@ describe("Sales Channel Service", () => {
|
||||
const id = "channel-2"
|
||||
|
||||
it("should update the name of the SalesChannel successfully", async () => {
|
||||
await service.update([
|
||||
{
|
||||
id,
|
||||
name: "Update name 2",
|
||||
is_disabled: true,
|
||||
},
|
||||
])
|
||||
await service.update(id, {
|
||||
name: "Update name 2",
|
||||
is_disabled: true,
|
||||
})
|
||||
|
||||
const channel = await service.retrieve(id)
|
||||
|
||||
@@ -102,11 +99,9 @@ describe("Sales Channel Service", () => {
|
||||
let error
|
||||
|
||||
try {
|
||||
await service.update([
|
||||
{
|
||||
id: "does-not-exist",
|
||||
},
|
||||
])
|
||||
await service.update("does-not-exist", {
|
||||
name: "does-not-exist",
|
||||
})
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
|
||||
@@ -43,6 +43,15 @@
|
||||
"default": "false",
|
||||
"mappedType": "boolean"
|
||||
},
|
||||
"metadata": {
|
||||
"name": "metadata",
|
||||
"type": "jsonb",
|
||||
"unsigned": false,
|
||||
"autoincrement": false,
|
||||
"primary": false,
|
||||
"nullable": true,
|
||||
"mappedType": "json"
|
||||
},
|
||||
"created_at": {
|
||||
"name": "created_at",
|
||||
"type": "timestamptz",
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Migration } from "@mikro-orm/migrations"
|
||||
export class Migration20240115152146 extends Migration {
|
||||
async up(): Promise<void> {
|
||||
this.addSql(
|
||||
'create table if not exists "sales_channel" ("id" text not null, "name" text not null, "description" text null, "is_disabled" boolean not null default false, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "sales_channel_pkey" primary key ("id"));'
|
||||
'create table if not exists "sales_channel" ("id" text not null, "name" text not null, "description" text null, "is_disabled" boolean not null default false, "metadata" jsonb NULL, "created_at" timestamptz not null default now(), "updated_at" timestamptz not null default now(), "deleted_at" timestamptz null, constraint "sales_channel_pkey" primary key ("id"));'
|
||||
)
|
||||
this.addSql(
|
||||
'create index "IDX_sales_channel_deleted_at" on "sales_channel" ("deleted_at");'
|
||||
|
||||
@@ -38,6 +38,9 @@ export default class SalesChannel {
|
||||
})
|
||||
created_at: Date
|
||||
|
||||
@Property({ columnType: "jsonb", nullable: true })
|
||||
metadata: Record<string, unknown> | null = null
|
||||
|
||||
@Property({
|
||||
onCreate: () => new Date(),
|
||||
onUpdate: () => new Date(),
|
||||
|
||||
@@ -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])
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Logger } from "@medusajs/types"
|
||||
import { Logger, UpdateSalesChannelDTO } from "@medusajs/types"
|
||||
|
||||
export type InitializeModuleInjectableDependencies = {
|
||||
logger?: Logger
|
||||
}
|
||||
|
||||
export type UpdateSalesChanneInput = UpdateSalesChannelDTO & { id: string }
|
||||
Reference in new issue
Block a user