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
co-authored by fPolic Frane Polić
parent 1438b394ae
commit 42be9a88d6
7 changed files with 59 additions and 5 deletions
+7
View File
@@ -0,0 +1,7 @@
---
"@medusajs/medusa": patch
"@medusajs/types": patch
"@medusajs/dashboard": patch
---
fix: Update TIP on promotions
@@ -1731,6 +1731,7 @@ medusaIntegrationTestRunner({
{ {
code: "TEST_TWO", code: "TEST_TWO",
application_method: { value: 200 }, application_method: { value: 200 },
is_tax_inclusive: true,
}, },
adminHeaders adminHeaders
) )
@@ -1743,6 +1744,7 @@ medusaIntegrationTestRunner({
application_method: expect.objectContaining({ application_method: expect.objectContaining({
value: 200, value: 200,
}), }),
is_tax_inclusive: true,
}) })
) )
}) })
@@ -2074,7 +2074,7 @@
}, },
"taxInclusive": { "taxInclusive": {
"title": "Does promotion include taxes?", "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": { "status": {
"label": "Status", "label": "Status",
@@ -2697,7 +2697,10 @@
"placeholder": "wrong_size", "placeholder": "wrong_size",
"tooltip": "The value should be a unique identifier for the return reason." "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": { "description": {
"label": "Description", "label": "Description",
"placeholder": "Customer received the wrong size" "placeholder": "Customer received the wrong size"
@@ -1,8 +1,16 @@
import { zodResolver } from "@hookform/resolvers/zod" import { zodResolver } from "@hookform/resolvers/zod"
import { AdminPromotion } from "@medusajs/types" 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 { useForm, useWatch } from "react-hook-form"
import { Trans, useTranslation } from "react-i18next" import { Trans, useTranslation } from "react-i18next"
import { useEffect } from "react"
import * as zod from "zod" import * as zod from "zod"
import { Form } from "../../../../../components/common/form" import { Form } from "../../../../../components/common/form"
@@ -11,6 +19,7 @@ import { RouteDrawer, useRouteModal } from "../../../../../components/modals"
import { KeyboundForm } from "../../../../../components/utilities/keybound-form" import { KeyboundForm } from "../../../../../components/utilities/keybound-form"
import { useUpdatePromotion } from "../../../../../hooks/api/promotions" import { useUpdatePromotion } from "../../../../../hooks/api/promotions"
import { getCurrencySymbol } from "../../../../../lib/data/currencies" import { getCurrencySymbol } from "../../../../../lib/data/currencies"
import { SwitchBox } from "../../../../../components/common/switch-box"
type EditPromotionFormProps = { type EditPromotionFormProps = {
promotion: AdminPromotion promotion: AdminPromotion
@@ -19,6 +28,7 @@ type EditPromotionFormProps = {
const EditPromotionSchema = zod.object({ const EditPromotionSchema = zod.object({
is_automatic: zod.string().toLowerCase(), is_automatic: zod.string().toLowerCase(),
code: zod.string().min(1), code: zod.string().min(1),
is_tax_inclusive: zod.boolean().optional(),
status: zod.enum(["active", "inactive", "draft"]), status: zod.enum(["active", "inactive", "draft"]),
value_type: zod.enum(["fixed", "percentage"]), value_type: zod.enum(["fixed", "percentage"]),
value: zod.number(), value: zod.number(),
@@ -34,6 +44,7 @@ export const EditPromotionDetailsForm = ({
const form = useForm<zod.infer<typeof EditPromotionSchema>>({ const form = useForm<zod.infer<typeof EditPromotionSchema>>({
defaultValues: { defaultValues: {
is_automatic: promotion.is_automatic!.toString(), is_automatic: promotion.is_automatic!.toString(),
is_tax_inclusive: promotion.is_tax_inclusive,
code: promotion.code, code: promotion.code,
status: promotion.status, status: promotion.status,
value: promotion.application_method!.value, value: promotion.application_method!.value,
@@ -58,6 +69,7 @@ export const EditPromotionDetailsForm = ({
is_automatic: data.is_automatic === "true", is_automatic: data.is_automatic === "true",
code: data.code, code: data.code,
status: data.status, status: data.status,
is_tax_inclusive: data.is_tax_inclusive,
application_method: { application_method: {
value: data.value, value: data.value,
type: data.value_type as any, 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 ( return (
<RouteDrawer.Form form={form}> <RouteDrawer.Form form={form}>
<KeyboundForm <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"> <div className="flex flex-col gap-y-4">
<Form.Field <Form.Field
control={form.control} control={form.control}
@@ -169,7 +202,6 @@ export const EditPromotionDetailsForm = ({
return ( return (
<Form.Item> <Form.Item>
<Form.Label>{t("promotions.form.code.title")}</Form.Label> <Form.Label>{t("promotions.form.code.title")}</Form.Label>
<Form.Control> <Form.Control>
<Input {...field} /> <Input {...field} />
</Form.Control> </Form.Control>
@@ -197,6 +197,10 @@ export interface AdminUpdatePromotion {
* by entering the code at checkout. * by entering the code at checkout.
*/ */
is_automatic?: boolean is_automatic?: boolean
/**
* Whether the promotion is tax inclusive.
*/
is_tax_inclusive?: boolean
/** /**
* The type of promotion. * The type of promotion.
*/ */
@@ -168,6 +168,11 @@ export interface UpdatePromotionDTO {
*/ */
type?: PromotionTypeValues type?: PromotionTypeValues
/**
* Whether the promotion is tax inclusive.
*/
is_tax_inclusive?: boolean
/** /**
* The status of the promotion: * The status of the promotion:
* *
@@ -187,6 +187,7 @@ export const UpdatePromotion = z
.object({ .object({
code: z.string().optional(), code: z.string().optional(),
is_automatic: z.boolean().optional(), is_automatic: z.boolean().optional(),
is_tax_inclusive: z.boolean().optional(),
type: z.nativeEnum(PromotionType).optional(), type: z.nativeEnum(PromotionType).optional(),
status: z.nativeEnum(PromotionStatus).optional(), status: z.nativeEnum(PromotionStatus).optional(),
campaign_id: z.string().nullish(), campaign_id: z.string().nullish(),