feat: promotion usage limit (#13760)

* feat: promotion usage limit

* fix: update, refactor tests, parallel case

* fix: batch update, cleanup unused map

* feat: paralel campaign and promotion tests

* chore: changesets, fix i18 schema

* fix: ui tweaks

* chore: refactor

---------

Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Frane Polić
2025-11-30 19:43:36 +01:00
committed by GitHub
co-authored by Oli Juhl
parent 5da51064d7
commit 536a3f802c
18 changed files with 1269 additions and 11 deletions
@@ -4,6 +4,8 @@ export const defaultAdminPromotionFields = [
"is_automatic",
"is_tax_inclusive",
"type",
"limit",
"used",
"status",
"created_at",
"updated_at",
@@ -175,16 +175,35 @@ export const CreatePromotion = z
campaign: CreateCampaign.optional(),
application_method: AdminCreateApplicationMethod,
rules: z.array(AdminCreatePromotionRule).optional(),
limit: z.number().int().min(1).nullable().optional(),
})
.strict()
export const AdminCreatePromotion = WithAdditionalData(
CreatePromotion,
(schema) => {
return schema.refine(promoRefinement, {
message:
"Buyget promotions require at least one buy rule and quantities to be defined",
})
return schema
.refine(promoRefinement, {
message:
"Buyget promotions require at least one buy rule and quantities to be defined",
})
.refine(
(data) => {
// Automatic promotions cannot have a limit
if (
data.is_automatic &&
data.limit !== null &&
data.limit !== undefined
) {
return false
}
return true
},
{
message: "Automatic promotions cannot have a usage limit",
path: ["limit"],
}
)
}
)
@@ -198,15 +217,34 @@ export const UpdatePromotion = z
status: z.nativeEnum(PromotionStatus).optional(),
campaign_id: z.string().nullish(),
application_method: AdminUpdateApplicationMethod.optional(),
limit: z.number().int().min(1).nullable().optional(),
})
.strict()
export const AdminUpdatePromotion = WithAdditionalData(
UpdatePromotion,
(schema) => {
return schema.refine(promoRefinement, {
message:
"Buyget promotions require at least one buy rule and quantities to be defined",
})
return schema
.refine(promoRefinement, {
message:
"Buyget promotions require at least one buy rule and quantities to be defined",
})
.refine(
(data) => {
// Automatic promotions cannot have a limit
if (
data.is_automatic &&
data.limit !== null &&
data.limit !== undefined
) {
return false
}
return true
},
{
message: "Automatic promotions cannot have a usage limit",
path: ["limit"],
}
)
}
)