fix(medusa, core-flows): Update TIP on promotions (#12885)

* fix: Update TIP on promotions

* Create warm-rings-look.md

* only show for fixed discounts

* fix: handle type change

---------

Co-authored-by: fPolic <mainacc.polic@gmail.com>
Co-authored-by: Frane Polić <16856471+fPolic@users.noreply.github.com>
This commit is contained in:
Oli Juhl
2025-07-08 19:20:29 +02:00
committed by GitHub
parent 1438b394ae
commit 42be9a88d6
7 changed files with 59 additions and 5 deletions

View File

@@ -0,0 +1,7 @@
---
"@medusajs/medusa": patch
"@medusajs/types": patch
"@medusajs/dashboard": patch
---
fix: Update TIP on promotions

View File

@@ -1731,6 +1731,7 @@ medusaIntegrationTestRunner({
{
code: "TEST_TWO",
application_method: { value: 200 },
is_tax_inclusive: true,
},
adminHeaders
)
@@ -1743,6 +1744,7 @@ medusaIntegrationTestRunner({
application_method: expect.objectContaining({
value: 200,
}),
is_tax_inclusive: true,
})
)
})

View File

@@ -2074,7 +2074,7 @@
},
"taxInclusive": {
"title": "Does promotion include taxes?",
"description": "Enable this field to apply the promotion after taxes. If disabled, the promotion will be applied before taxes."
"description": "Enable this field to apply the promotion after taxes"
},
"status": {
"label": "Status",
@@ -2697,7 +2697,10 @@
"placeholder": "wrong_size",
"tooltip": "The value should be a unique identifier for the return reason."
},
"label": { "label": "Label", "placeholder": "Wrong size" },
"label": {
"label": "Label",
"placeholder": "Wrong size"
},
"description": {
"label": "Description",
"placeholder": "Customer received the wrong size"
@@ -3048,4 +3051,4 @@
"seconds_one": "Second",
"seconds_other": "Seconds"
}
}
}

View File

@@ -1,8 +1,16 @@
import { zodResolver } from "@hookform/resolvers/zod"
import { AdminPromotion } from "@medusajs/types"
import { Button, CurrencyInput, Input, RadioGroup, Text } from "@medusajs/ui"
import {
Button,
CurrencyInput,
Input,
RadioGroup,
Switch,
Text,
} from "@medusajs/ui"
import { useForm, useWatch } from "react-hook-form"
import { Trans, useTranslation } from "react-i18next"
import { useEffect } from "react"
import * as zod from "zod"
import { Form } from "../../../../../components/common/form"
@@ -11,6 +19,7 @@ import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
import { useUpdatePromotion } from "../../../../../hooks/api/promotions"
import { getCurrencySymbol } from "../../../../../lib/data/currencies"
import { SwitchBox } from "../../../../../components/common/switch-box"
type EditPromotionFormProps = {
promotion: AdminPromotion
@@ -19,6 +28,7 @@ type EditPromotionFormProps = {
const EditPromotionSchema = zod.object({
is_automatic: zod.string().toLowerCase(),
code: zod.string().min(1),
is_tax_inclusive: zod.boolean().optional(),
status: zod.enum(["active", "inactive", "draft"]),
value_type: zod.enum(["fixed", "percentage"]),
value: zod.number(),
@@ -34,6 +44,7 @@ export const EditPromotionDetailsForm = ({
const form = useForm<zod.infer<typeof EditPromotionSchema>>({
defaultValues: {
is_automatic: promotion.is_automatic!.toString(),
is_tax_inclusive: promotion.is_tax_inclusive,
code: promotion.code,
status: promotion.status,
value: promotion.application_method!.value,
@@ -58,6 +69,7 @@ export const EditPromotionDetailsForm = ({
is_automatic: data.is_automatic === "true",
code: data.code,
status: data.status,
is_tax_inclusive: data.is_tax_inclusive,
application_method: {
value: data.value,
type: data.value_type as any,
@@ -72,6 +84,17 @@ export const EditPromotionDetailsForm = ({
)
})
const allocationWatchValue = useWatch({
control: form.control,
name: "value_type",
})
useEffect(() => {
if (!(allocationWatchValue === "fixed" && promotion.type === "standard")) {
form.setValue("is_tax_inclusive", false)
}
}, [allocationWatchValue, form, promotion])
return (
<RouteDrawer.Form form={form}>
<KeyboundForm
@@ -161,6 +184,16 @@ export const EditPromotionDetailsForm = ({
}}
/>
{allocationWatchValue === "fixed" &&
promotion.type === "standard" && (
<SwitchBox
control={form.control}
name="is_tax_inclusive"
label={t("promotions.form.taxInclusive.title")}
description={t("promotions.form.taxInclusive.description")}
/>
)}
<div className="flex flex-col gap-y-4">
<Form.Field
control={form.control}
@@ -169,7 +202,6 @@ export const EditPromotionDetailsForm = ({
return (
<Form.Item>
<Form.Label>{t("promotions.form.code.title")}</Form.Label>
<Form.Control>
<Input {...field} />
</Form.Control>

View File

@@ -197,6 +197,10 @@ export interface AdminUpdatePromotion {
* by entering the code at checkout.
*/
is_automatic?: boolean
/**
* Whether the promotion is tax inclusive.
*/
is_tax_inclusive?: boolean
/**
* The type of promotion.
*/

View File

@@ -168,6 +168,11 @@ export interface UpdatePromotionDTO {
*/
type?: PromotionTypeValues
/**
* Whether the promotion is tax inclusive.
*/
is_tax_inclusive?: boolean
/**
* The status of the promotion:
*

View File

@@ -187,6 +187,7 @@ export const UpdatePromotion = z
.object({
code: z.string().optional(),
is_automatic: z.boolean().optional(),
is_tax_inclusive: z.boolean().optional(),
type: z.nativeEnum(PromotionType).optional(),
status: z.nativeEnum(PromotionStatus).optional(),
campaign_id: z.string().nullish(),