feat(core-flows,medusa,utils): promotion and campaign create/update endpoint (#6130)

what:

- adds create endpoint for promotions including workflows and endpoint (RESOLVES CORE-1678)
- adds update endpoint for promotions including workflows and endpoint (RESOLVES CORE-1679)
- adds create endpoint for campaigns including workflows and endpoint (RESOLVES CORE-1684)
- adds update endpoint for campaigns including workflows and endpoint (RESOLVES CORE-1685)
This commit is contained in:
Riqwan Thamir
2024-01-22 12:54:17 +01:00
committed by GitHub
parent a52586880c
commit da5cc4cf7f
30 changed files with 1240 additions and 50 deletions
@@ -1,3 +1,4 @@
import { updateCampaignsWorkflow } from "@medusajs/core-flows"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { IPromotionModuleService } from "@medusajs/types"
import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
@@ -17,3 +18,24 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
res.status(200).json({ campaign })
}
export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
const updateCampaigns = updateCampaignsWorkflow(req.scope)
const campaignsData = [
{
id: req.params.id,
...(req.validatedBody || {}),
},
]
const { result, errors } = await updateCampaigns.run({
input: { campaignsData },
throwOnError: false,
})
if (Array.isArray(errors) && errors[0]) {
throw errors[0].error
}
res.status(200).json({ campaign: result[0] })
}
@@ -1,10 +1,16 @@
import { MedusaV2Flag } from "@medusajs/utils"
import { isFeatureFlagEnabled, transformQuery } from "../../../api/middlewares"
import {
isFeatureFlagEnabled,
transformBody,
transformQuery,
} from "../../../api/middlewares"
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
import * as QueryConfig from "./query-config"
import {
AdminGetCampaignsCampaignParams,
AdminGetCampaignsParams,
AdminPostCampaignsCampaignReq,
AdminPostCampaignsReq,
} from "./validators"
export const adminCampaignRoutesMiddlewares: MiddlewareRoute[] = [
@@ -22,6 +28,11 @@ export const adminCampaignRoutesMiddlewares: MiddlewareRoute[] = [
),
],
},
{
method: ["POST"],
matcher: "/admin/campaigns",
middlewares: [transformBody(AdminPostCampaignsReq)],
},
{
method: ["GET"],
matcher: "/admin/campaigns/:id",
@@ -32,4 +43,9 @@ export const adminCampaignRoutesMiddlewares: MiddlewareRoute[] = [
),
],
},
{
method: ["POST"],
matcher: "/admin/campaigns/:id",
middlewares: [transformBody(AdminPostCampaignsCampaignReq)],
},
]
@@ -1,5 +1,6 @@
import { createCampaignsWorkflow } from "@medusajs/core-flows"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { IPromotionModuleService } from "@medusajs/types"
import { CreateCampaignDTO, IPromotionModuleService } from "@medusajs/types"
import { MedusaRequest, MedusaResponse } from "../../../types/routing"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
@@ -21,3 +22,19 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
limit,
})
}
export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
const createCampaigns = createCampaignsWorkflow(req.scope)
const campaignsData = [req.validatedBody as CreateCampaignDTO]
const { result, errors } = await createCampaigns.run({
input: { campaignsData },
throwOnError: false,
})
if (Array.isArray(errors) && errors[0]) {
throw errors[0].error
}
res.status(200).json({ campaign: result[0] })
}
@@ -1,4 +1,15 @@
import { IsOptional, IsString } from "class-validator"
import { CampaignBudgetType } from "@medusajs/utils"
import { Type } from "class-transformer"
import {
IsArray,
IsDateString,
IsEnum,
IsNotEmpty,
IsNumber,
IsOptional,
IsString,
ValidateNested,
} from "class-validator"
import { FindParams, extendedFindParamsMixin } from "../../../types/common"
export class AdminGetCampaignsCampaignParams extends FindParams {}
@@ -15,3 +26,93 @@ export class AdminGetCampaignsParams extends extendedFindParamsMixin({
@IsOptional()
currency?: string
}
export class AdminPostCampaignsReq {
@IsNotEmpty()
@IsString()
name: string
@IsOptional()
@IsNotEmpty()
campaign_identifier?: string
@IsOptional()
@IsString()
description?: string
@IsOptional()
@IsString()
currency?: string
@IsOptional()
@ValidateNested()
@Type(() => CampaignBudget)
budget?: CampaignBudget
@IsOptional()
@IsDateString()
starts_at?: string
@IsOptional()
@IsDateString()
ends_at?: string
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => IdObject)
promotions?: IdObject[]
}
export class IdObject {
@IsString()
@IsNotEmpty()
id: string
}
export class CampaignBudget {
@IsOptional()
@IsEnum(CampaignBudgetType)
type?: CampaignBudgetType
@IsOptional()
@IsNumber()
limit?: number
}
export class AdminPostCampaignsCampaignReq {
@IsOptional()
@IsString()
name?: string
@IsOptional()
@IsNotEmpty()
campaign_identifier?: string
@IsOptional()
@IsString()
description?: string
@IsOptional()
@IsString()
currency?: string
@IsOptional()
@ValidateNested()
@Type(() => CampaignBudget)
budget?: CampaignBudget
@IsOptional()
@IsDateString()
starts_at?: string
@IsOptional()
@IsDateString()
ends_at?: string
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => IdObject)
promotions?: IdObject[]
}
@@ -1,3 +1,4 @@
import { updatePromotionsWorkflow } from "@medusajs/core-flows"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { IPromotionModuleService } from "@medusajs/types"
import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
@@ -14,3 +15,24 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
res.status(200).json({ promotion })
}
export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
const updatePromotions = updatePromotionsWorkflow(req.scope)
const promotionsData = [
{
id: req.params.id,
...(req.validatedBody || {}),
},
]
const { result, errors } = await updatePromotions.run({
input: { promotionsData },
throwOnError: false,
})
if (Array.isArray(errors) && errors[0]) {
throw errors[0].error
}
res.status(200).json({ promotion: result[0] })
}
@@ -1,10 +1,17 @@
import { MedusaV2Flag } from "@medusajs/utils"
import { isFeatureFlagEnabled, transformQuery } from "../../../api/middlewares"
import {
isFeatureFlagEnabled,
transformBody,
transformQuery,
} from "../../../api/middlewares"
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
import * as QueryConfig from "./query-config"
import {
AdminGetPromotionsParams,
AdminGetPromotionsPromotionParams,
AdminPostPromotionsPromotionReq,
AdminPostPromotionsReq,
} from "./validators"
export const adminPromotionRoutesMiddlewares: MiddlewareRoute[] = [
@@ -22,6 +29,11 @@ export const adminPromotionRoutesMiddlewares: MiddlewareRoute[] = [
),
],
},
{
method: ["POST"],
matcher: "/admin/promotions",
middlewares: [transformBody(AdminPostPromotionsReq)],
},
{
method: ["GET"],
matcher: "/admin/promotions/:id",
@@ -32,4 +44,9 @@ export const adminPromotionRoutesMiddlewares: MiddlewareRoute[] = [
),
],
},
{
method: ["POST"],
matcher: "/admin/promotions/:id",
middlewares: [transformBody(AdminPostPromotionsPromotionReq)],
},
]
@@ -1,5 +1,6 @@
import { createPromotionsWorkflow } from "@medusajs/core-flows"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { IPromotionModuleService } from "@medusajs/types"
import { CreatePromotionDTO, IPromotionModuleService } from "@medusajs/types"
import { MedusaRequest, MedusaResponse } from "../../../types/routing"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
@@ -21,3 +22,19 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
limit,
})
}
export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
const createPromotions = createPromotionsWorkflow(req.scope)
const promotionsData = [req.validatedBody as CreatePromotionDTO]
const { result, errors } = await createPromotions.run({
input: { promotionsData },
throwOnError: false,
})
if (Array.isArray(errors) && errors[0]) {
throw errors[0].error
}
res.status(200).json({ promotion: result[0] })
}
@@ -1,5 +1,25 @@
import { IsOptional, IsString } from "class-validator"
import {
ApplicationMethodAllocation,
ApplicationMethodTargetType,
ApplicationMethodType,
PromotionRuleOperator,
PromotionType,
} from "@medusajs/utils"
import { Type } from "class-transformer"
import {
IsArray,
IsBoolean,
IsEnum,
IsNotEmpty,
IsNumber,
IsOptional,
IsString,
Validate,
ValidateNested,
} from "class-validator"
import { FindParams, extendedFindParamsMixin } from "../../../types/common"
import { XorConstraint } from "../../../types/validators/xor"
import { AdminPostCampaignsReq } from "../campaigns/validators"
export class AdminGetPromotionsPromotionParams extends FindParams {}
@@ -11,3 +31,122 @@ export class AdminGetPromotionsParams extends extendedFindParamsMixin({
@IsOptional()
code?: string
}
export class AdminPostPromotionsReq {
@IsNotEmpty()
@IsString()
code: string
@IsBoolean()
@IsOptional()
is_automatic?: boolean
@IsOptional()
@IsEnum(PromotionType)
type?: PromotionType
@IsOptional()
@IsString()
campaign_id?: string
@IsOptional()
@ValidateNested()
@Type(() => AdminPostCampaignsReq)
campaign?: AdminPostCampaignsReq
@IsNotEmpty()
@ValidateNested()
@Type(() => ApplicationMethod)
application_method: ApplicationMethod
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => PromotionRule)
rules?: PromotionRule[]
}
export class PromotionRule {
@IsEnum(PromotionRuleOperator)
operator: PromotionRuleOperator
@IsOptional()
@IsString()
description?: string | null
@IsNotEmpty()
@IsString()
attribute: string
@IsArray()
@Type(() => String)
values: string[]
}
export class ApplicationMethod {
@IsOptional()
@IsString()
description?: string
@IsOptional()
@IsString()
value?: string
@IsOptional()
@IsNumber()
max_quantity?: number
@IsOptional()
@IsEnum(ApplicationMethodType)
type?: ApplicationMethodType
@IsOptional()
@IsEnum(ApplicationMethodTargetType)
target_type?: ApplicationMethodTargetType
@IsOptional()
@IsEnum(ApplicationMethodAllocation)
allocation?: ApplicationMethodAllocation
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => PromotionRule)
target_rules?: PromotionRule[]
}
export class AdminPostPromotionsPromotionReq {
@IsOptional()
@IsString()
code?: string
@IsOptional()
@IsBoolean()
is_automatic?: boolean
@IsOptional()
@IsEnum(PromotionType)
type?: PromotionType
@IsOptional()
@Validate(XorConstraint, ["campaign"])
@IsString()
campaign_id?: string
@IsOptional()
@Validate(XorConstraint, ["campaign_id"])
@ValidateNested()
@Type(() => AdminPostCampaignsReq)
campaign?: AdminPostCampaignsReq
@IsOptional()
@ValidateNested()
@Type(() => ApplicationMethod)
application_method?: ApplicationMethod
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => PromotionRule)
rules?: PromotionRule[]
}