feat(dashboard,cart,types,utils): refine order details summary (#13313)

* feat(dashboard,types,utils): refine order details summary

* fix tests

* changeset

* ui corrections

* tests again

* weird tests failing

* revert update to subtotal

* revert http tests too

* comments

* move credit lines so it makes more sense

* remove currency codes and add bold prices

* add new properties in default for storefront

* minor to patch

* remove bold on things that should be

* olis comment about taxes

* remove bold from shipping
This commit is contained in:
William Bouchard
2025-09-02 20:50:37 +02:00
committed by GitHub
parent 753e8081c4
commit 2f6edf367a
13 changed files with 348 additions and 214 deletions
+7
View File
@@ -0,0 +1,7 @@
---
"@medusajs/utils": patch
"@medusajs/dashboard": patch
"@medusajs/types": patch
---
feat(dashboard,cart,types,utils): refine order details summary
@@ -1,10 +1,7 @@
import { medusaIntegrationTestRunner } from "@medusajs/test-utils" import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
import { HttpTypes } from "@medusajs/types" import { HttpTypes } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/utils" import { ModuleRegistrationName } from "@medusajs/utils"
import { import { adminHeaders, createAdminUser, } from "../../../../helpers/create-admin-user"
adminHeaders,
createAdminUser,
} from "../../../../helpers/create-admin-user"
import { setupTaxStructure } from "../../../../modules/__tests__/fixtures" import { setupTaxStructure } from "../../../../modules/__tests__/fixtures"
jest.setTimeout(300000) jest.setTimeout(300000)
@@ -3987,6 +3987,9 @@
}, },
"taxTotal": { "taxTotal": {
"type": "string" "type": "string"
},
"totalAfterDiscount": {
"type": "string"
} }
}, },
"required": [ "required": [
@@ -4002,7 +4005,8 @@
"itemSubtotal", "itemSubtotal",
"shippingSubtotal", "shippingSubtotal",
"discountSubtotal", "discountSubtotal",
"taxTotal" "taxTotal",
"totalAfterDiscount"
], ],
"additionalProperties": false "additionalProperties": false
}, },
@@ -1067,7 +1067,8 @@
"itemSubtotal": "Item Subtotal", "itemSubtotal": "Item Subtotal",
"shippingSubtotal": "Shipping Subtotal", "shippingSubtotal": "Shipping Subtotal",
"discountSubtotal": "Discount Subtotal", "discountSubtotal": "Discount Subtotal",
"taxTotal": "Tax Total" "taxTotal": "Tax Total",
"totalAfterDiscount": "Total After Discount"
}, },
"transfer": { "transfer": {
"title": "Transfer ownership", "title": "Transfer ownership",
@@ -63,6 +63,7 @@ import { getReturnableQuantity } from "../../../../../lib/rma"
import { CopyPaymentLink } from "../copy-payment-link/copy-payment-link" import { CopyPaymentLink } from "../copy-payment-link/copy-payment-link"
import ReturnInfoPopover from "./return-info-popover" import ReturnInfoPopover from "./return-info-popover"
import ShippingInfoPopover from "./shipping-info-popover" import ShippingInfoPopover from "./shipping-info-popover"
import { formatPercentage } from "../../../../../lib/percentage-helpers.ts"
type OrderSummarySectionProps = { type OrderSummarySectionProps = {
order: AdminOrder order: AdminOrder
@@ -191,7 +192,7 @@ export const OrderSummarySection = ({
<Header order={order} orderPreview={orderPreview} /> <Header order={order} orderPreview={orderPreview} />
<ItemBreakdown order={order} reservations={reservations!} /> <ItemBreakdown order={order} reservations={reservations!} />
<CostBreakdown order={order} /> <CostBreakdown order={order} />
<CreditLinesBreakdown order={order} plugins={plugins} /> <DiscountAndTotalBreakdown order={order} plugins={plugins} />
<Total order={order} /> <Total order={order} />
{(showAllocateButton || showReturns || showPayment || showRefund) && ( {(showAllocateButton || showReturns || showPayment || showRefund) && (
@@ -569,51 +570,39 @@ const CostBreakdown = ({
const [isTaxOpen, setIsTaxOpen] = useState(false) const [isTaxOpen, setIsTaxOpen] = useState(false)
const [isShippingOpen, setIsShippingOpen] = useState(false) const [isShippingOpen, setIsShippingOpen] = useState(false)
const discountCodes = useMemo(() => {
const codes = new Set()
order.items.forEach((item) =>
item.adjustments?.forEach((adj) => {
codes.add(adj.code)
})
)
return Array.from(codes).sort()
}, [order])
const taxCodes = useMemo(() => { const taxCodes = useMemo(() => {
const taxCodeMap = {} const taxCodeMap: { [key: string]: { total: number; rate: number } } = {}
order.items.forEach((item) => { order.items.forEach((item) => {
item.tax_lines?.forEach((line) => { item.tax_lines?.forEach((line) => {
taxCodeMap[line.code] = (taxCodeMap[line.code] || 0) + line.total const prevTotal = taxCodeMap[line.code]?.total || 0
taxCodeMap[line.code] = {
total: prevTotal + line.subtotal,
rate: line.rate,
}
}) })
}) })
order.shipping_methods.forEach((sm) => { order.shipping_methods.forEach((sm) => {
sm.tax_lines?.forEach((line) => { sm.tax_lines?.forEach((line) => {
taxCodeMap[line.code] = (taxCodeMap[line.code] || 0) + line.total const prevTotal = taxCodeMap[line.code]?.total || 0
taxCodeMap[line.code] = {
total: prevTotal + line.subtotal,
rate: line.rate,
}
}) })
}) })
return taxCodeMap return taxCodeMap
}, [order]) }, [order])
const automaticTaxesOn = !!order.region?.automatic_taxes const hasTaxes = !!Object.keys(taxCodes).length
const hasTaxLines = !!Object.keys(taxCodes).length
const discountTotal = automaticTaxesOn
? order.discount_total
: order.discount_subtotal
return ( return (
<div className="text-ui-fg-subtle flex flex-col gap-y-2 px-6 py-4"> <div className="text-ui-fg-subtle flex flex-col gap-y-2 px-6 py-4">
<Cost <Cost
label={t( label={t("orders.summary.itemSubtotal")}
automaticTaxesOn value={getLocaleAmount(order.item_subtotal, order.currency_code)}
? "orders.summary.itemTotal"
: "orders.summary.itemSubtotal"
)}
value={getLocaleAmount(order.item_total, order.currency_code)}
/> />
<Cost <Cost
label={ label={
@@ -621,13 +610,7 @@ const CostBreakdown = ({
onClick={() => setIsShippingOpen((o) => !o)} onClick={() => setIsShippingOpen((o) => !o)}
className="flex cursor-pointer items-center gap-1" className="flex cursor-pointer items-center gap-1"
> >
<span> <span>{t("orders.summary.shippingSubtotal")}</span>
{t(
automaticTaxesOn
? "orders.summary.shippingTotal"
: "orders.summary.shippingSubtotal"
)}
</span>
<TriangleDownMini <TriangleDownMini
style={{ style={{
transform: `rotate(${isShippingOpen ? 0 : -90}deg)`, transform: `rotate(${isShippingOpen ? 0 : -90}deg)`,
@@ -635,10 +618,7 @@ const CostBreakdown = ({
/> />
</div> </div>
} }
value={getLocaleAmount( value={getLocaleAmount(order.shipping_subtotal, order.currency_code)}
automaticTaxesOn ? order.shipping_total : order.shipping_subtotal,
order.currency_code
)}
/> />
{isShippingOpen && ( {isShippingOpen && (
@@ -654,7 +634,7 @@ const CostBreakdown = ({
className="flex items-center justify-between gap-x-2" className="flex items-center justify-between gap-x-2"
> >
<div> <div>
<span className="txt-small text-ui-fg-subtle font-medium"> <span className="txt-small">
{sm.name} {sm.name}
{sm.detail.return_id && {sm.detail.return_id &&
` (${t("fields.returnShipping")})`}{" "} ` (${t("fields.returnShipping")})`}{" "}
@@ -665,10 +645,7 @@ const CostBreakdown = ({
<div className="bottom-[calc(50% - 2px)] absolute h-[1px] w-full border-b border-dashed" /> <div className="bottom-[calc(50% - 2px)] absolute h-[1px] w-full border-b border-dashed" />
</div> </div>
<span className="txt-small text-ui-fg-muted"> <span className="txt-small text-ui-fg-muted">
{getLocaleAmount( {getLocaleAmount(sm.subtotal, order.currency_code)}
automaticTaxesOn ? sm.total : sm.subtotal,
order.currency_code
)}
</span> </span>
</div> </div>
) )
@@ -676,36 +653,18 @@ const CostBreakdown = ({
</div> </div>
)} )}
<Cost
label={t(
automaticTaxesOn
? "orders.summary.discountTotal"
: "orders.summary.discountSubtotal"
)}
secondaryValue={discountCodes.join(", ")}
value={
discountTotal > 0
? `- ${getLocaleAmount(discountTotal, order.currency_code)}`
: "-"
}
/>
<> <>
<div className="flex justify-between"> <div className="flex justify-between">
<div <div
onClick={() => hasTaxLines && setIsTaxOpen((o) => !o)} onClick={() => hasTaxes && setIsTaxOpen((o) => !o)}
className={clx("flex items-center gap-1", { className={clx("flex items-center gap-1", {
"cursor-pointer": hasTaxLines, "cursor-pointer": hasTaxes,
})} })}
> >
<span className="txt-small select-none"> <span className="txt-small select-none">
{t( {t("orders.summary.taxTotal")}
automaticTaxesOn
? "orders.summary.taxTotalIncl"
: "orders.summary.taxTotal"
)}
</span> </span>
{hasTaxLines && ( {hasTaxes && (
<TriangleDownMini <TriangleDownMini
style={{ style={{
transform: `rotate(${isTaxOpen ? 0 : -90}deg)`, transform: `rotate(${isTaxOpen ? 0 : -90}deg)`,
@@ -716,21 +675,22 @@ const CostBreakdown = ({
<div className="text-right"> <div className="text-right">
<Text size="small" leading="compact"> <Text size="small" leading="compact">
{getLocaleAmount(order.tax_total, order.currency_code)} {getLocaleAmount(order.original_tax_total, order.currency_code)}
</Text> </Text>
</div> </div>
</div> </div>
{isTaxOpen && ( {isTaxOpen && (
<div className="flex flex-col gap-1 pl-5"> <div className="flex flex-col gap-1 pl-5">
{Object.entries(taxCodes).map(([code, total]) => { {Object.entries(taxCodes).map(([code, { total, rate }]) => {
return ( return (
<div <div
key={code} key={code}
className="flex items-center justify-between gap-x-2" className="flex items-center justify-between gap-x-2"
> >
<div> <div className="flex gap-1">
<span className="txt-small text-ui-fg-subtle font-medium"> <span className="txt-small">{code}</span>
{code} <span className="txt-small">
({formatPercentage(rate)})
</span> </span>
</div> </div>
<div className="relative flex-1"> <div className="relative flex-1">
@@ -745,11 +705,23 @@ const CostBreakdown = ({
</div> </div>
)} )}
</> </>
<div className="text-ui-fg-base flex items-center justify-between">
<Text className="text-ui-fg-subtle" size="small" leading="compact">
{t("fields.total")}
</Text>
<Text
className="text-ui-fg-subtle text-bold"
size="small"
leading="compact"
>
{getLocaleAmount(order.original_total, order.currency_code)}
</Text>
</div>
</div> </div>
) )
} }
const CreditLinesBreakdown = ({ const DiscountAndTotalBreakdown = ({
order, order,
plugins, plugins,
}: { }: {
@@ -757,97 +729,208 @@ const CreditLinesBreakdown = ({
plugins: AdminPlugin[] plugins: AdminPlugin[]
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const [isDiscountOpen, setIsDiscountOpen] = useState(false)
const [isCreditLinesOpen, setIsCreditLinesOpen] = useState(false) const [isCreditLinesOpen, setIsCreditLinesOpen] = useState(false)
const creditLines = order.credit_lines ?? [] const creditLines = order.credit_lines ?? []
const loyaltyPlugin = getLoyaltyPlugin(plugins) const loyaltyPlugin = getLoyaltyPlugin(plugins)
if (creditLines.length === 0) { const discounts = useMemo(() => {
return null const discounts: {
} type: "item" | "shipping"
total: number
codes: string[]
}[] = []
if (order.item_discount_total) {
discounts.push({
type: "item",
total: order.item_discount_total,
codes: Array.from(
new Set(
order.items
.flatMap((item) => item.adjustments || [])
.map((adjustment) => adjustment.code!)
)
).sort(),
})
}
if (order.shipping_discount_total) {
discounts.push({
type: "shipping",
total: order.shipping_discount_total,
codes: Array.from(
new Set(
order.shipping_methods
.flatMap((shippingMethod) => shippingMethod.adjustments || [])
.map((adjustment) => adjustment.code!)
)
).sort(),
})
}
return discounts
}, [order])
const hasDiscount = discounts.length > 0
const hasCreditLines = creditLines.length > 0
return ( return (
<div className="text-ui-fg-subtle flex flex-col"> <div className="text-ui-fg-subtle flex flex-col gap-y-2 px-6 py-4">
<> <Cost
<div label={
onClick={() => setIsCreditLinesOpen((o) => !o)} <div
className="bg-ui-bg-component flex cursor-pointer items-center justify-between border border-dashed px-6 py-4" onClick={() => hasDiscount && setIsDiscountOpen((o) => !o)}
> className={clx("flex items-center gap-1", {
<div className="flex items-center gap-2"> "cursor-pointer": hasDiscount,
<TriangleDownMini })}
style={{ >
transform: `rotate(${isCreditLinesOpen ? 0 : -90}deg)`, <span>{t("orders.summary.discountTotal")}</span>
}} {hasDiscount && (
/> <TriangleDownMini
<span className="text-ui-fg-muted txt-small select-none"> style={{
{loyaltyPlugin transform: `rotate(${isDiscountOpen ? 0 : -90}deg)`,
? t("orders.giftCardsStoreCreditLines") }}
: t("orders.creditLines.title")} />
</span> )}
</div>
<div>
<Text size="small" leading="compact">
{getLocaleAmount(order.credit_line_total, order.currency_code)}
</Text>
</div> </div>
}
value={getLocaleAmount(order.discount_total, order.currency_code)}
/>
{isDiscountOpen && (
<div className="flex flex-col gap-1 pl-5">
{discounts.map(({ type, total, codes }) => {
return (
<div
key={type}
className="flex items-center justify-between gap-x-2"
>
<div className="flex gap-1">
<span className="txt-small">{t(`fields.${type}`)}</span>
<span className="txt-small">({codes.join(", ")})</span>
</div>
<div className="relative flex-1">
<div className="bottom-[calc(50% - 2px)] absolute h-[1px] w-full border-b border-dashed" />
</div>
<span className="txt-small text-ui-fg-muted">
{getLocaleAmount(total, order.currency_code)}
</span>
</div>
)
})}
</div> </div>
)}
{isCreditLinesOpen && ( {hasCreditLines && (
<div className="flex flex-col"> <>
{creditLines.map((creditLine) => { <Cost
const prettyReference = creditLine.reference label={
?.split("_") <div
.join(" ") onClick={() => setIsCreditLinesOpen((o) => !o)}
.split("-") className="flex cursor-pointer items-center gap-1"
.join(" ") >
<span>
{loyaltyPlugin
? t("orders.giftCardsStoreCreditLines")
: t("orders.creditLines.title")}
</span>
<TriangleDownMini
style={{
transform: `rotate(${isCreditLinesOpen ? 0 : -90}deg)`,
}}
/>
</div>
}
value={getLocaleAmount(
order.credit_line_total,
order.currency_code
)}
/>
{isCreditLinesOpen && (
<div className="flex flex-col gap-1 pl-5">
{creditLines.map((creditLine) => {
const prettyReference = creditLine.reference
?.split("_")
.join(" ")
.split("-")
.join(" ")
const prettyReferenceId = creditLine.reference_id ? ( const prettyReferenceId = creditLine.reference_id ? (
<DisplayId id={creditLine.reference_id} /> <DisplayId id={creditLine.reference_id} />
) : null ) : null
return ( return (
<div <div
className="text-ui-fg-subtle grid grid-cols-[1fr_1fr_1fr] items-center px-6 py-4 py-4 sm:grid-cols-[1fr_1fr_1fr]" key={creditLine.id}
key={creditLine.id} className="flex items-center justify-between gap-x-2"
> >
<div className="w-full min-w-[60px] overflow-hidden"> <div className="flex items-center">
<Text <Text
size="small" size="small"
leading="compact" leading="compact"
weight="plus" weight="plus"
className="truncate" className="txt-small text-ui-fg-subtle font-medium"
> >
<DisplayId id={creditLine.id} /> <DisplayId id={creditLine.id} />
</Text> </Text>
<span className="txt-small text-ui-fg-subtle mx-1">
<Text size="small" leading="compact"> -
{format( </span>
new Date(creditLine.created_at), <Tooltip
"dd MMM, yyyy, HH:mm:ss" content={format(
)} new Date(creditLine.created_at),
</Text> "dd MMM, yyyy, HH:mm:ss"
</div> )}
>
<div className="hidden items-center justify-end gap-x-2 sm:flex"> <Text
<Text size="small" leading="compact" className="capitalize"> size="small"
{prettyReference} ({prettyReferenceId}) leading="compact"
</Text> className="txt-small text-ui-fg-subtle"
</div> >
{format(
<div className="flex items-center justify-end"> new Date(creditLine.created_at),
<Text size="small" leading="compact"> "dd MMM, yyyy"
)}
</Text>
</Tooltip>
<span className="txt-small text-ui-fg-subtle mx-1">
-
</span>
<Text
size="small"
leading="compact"
className="txt-small text-ui-fg-subtle capitalize"
>
({prettyReference} {prettyReferenceId})
</Text>
</div>
<div className="relative flex-1">
<div className="bottom-[calc(50% - 2px)] absolute h-[1px] w-full border-b border-dashed" />
</div>
<span className="txt-small text-ui-fg-muted">
{getLocaleAmount( {getLocaleAmount(
creditLine.amount as number, creditLine.amount as number,
order.currency_code order.currency_code
)} )}
</Text> </span>
</div> </div>
</div> )
) })}
})} </div>
</div> )}
)} </>
</> )}
<div className="text-ui-fg-base flex items-center justify-between">
<Text className="text-ui-fg-subtle" size="small" leading="compact">
{t("orders.summary.totalAfterDiscount")}
</Text>
<Text
className="text-ui-fg-subtle text-bold"
size="small"
leading="compact"
>
{getLocaleAmount(order.total, order.currency_code)}
</Text>
</div>
</div> </div>
) )
} }
@@ -1138,15 +1221,6 @@ const Total = ({ order }: { order: AdminOrder }) => {
return ( return (
<div className=" flex flex-col gap-y-2 px-6 py-4"> <div className=" flex flex-col gap-y-2 px-6 py-4">
<div className="text-ui-fg-base flex items-center justify-between">
<Text className="text-ui-fg-subtle" size="small" leading="compact">
{t("fields.total")}
</Text>
<Text className="text-ui-fg-subtle" size="small" leading="compact">
{getStylizedAmount(order.original_total, order.currency_code)}
</Text>
</div>
<div className="text-ui-fg-base flex items-center justify-between"> <div className="text-ui-fg-base flex items-center justify-between">
<Text className="text-ui-fg-subtle" size="small" leading="compact"> <Text className="text-ui-fg-subtle" size="small" leading="compact">
{t("fields.paidTotal")} {t("fields.paidTotal")}
@@ -1159,18 +1233,20 @@ const Total = ({ order }: { order: AdminOrder }) => {
</Text> </Text>
</div> </div>
<div className="text-ui-fg-base flex items-center justify-between"> {getTotalCreditLines(order.credit_lines ?? []) > 0 && (
<Text className="text-ui-fg-subtle" size="small" leading="compact"> <div className="text-ui-fg-base flex items-center justify-between">
{t("fields.creditTotal")} <Text className="text-ui-fg-subtle" size="small" leading="compact">
</Text> {t("fields.creditTotal")}
</Text>
<Text className="text-ui-fg-subtle" size="small" leading="compact"> <Text className="text-ui-fg-subtle" size="small" leading="compact">
{getStylizedAmount( {getStylizedAmount(
getTotalCreditLines(order.credit_lines ?? []), getTotalCreditLines(order.credit_lines ?? []),
order.currency_code order.currency_code
)} )}
</Text> </Text>
</div> </div>
)}
<div className="text-ui-fg-base flex items-center justify-between"> <div className="text-ui-fg-base flex items-center justify-between">
<Text <Text
@@ -1181,7 +1257,7 @@ const Total = ({ order }: { order: AdminOrder }) => {
{t("orders.returns.outstandingAmount")} {t("orders.returns.outstandingAmount")}
</Text> </Text>
<Text <Text
className="text-ui-fg-subtle text-bold" className="text-ui-fg-subtle text-bold" // ici
size="small" size="small"
leading="compact" leading="compact"
> >
@@ -10,14 +10,21 @@ const DEFAULT_PROPERTIES = [
// --- TOTALS --- // --- TOTALS ---
"total", "total",
"credit_line_total", "credit_line_total",
"item_subtotal",
"item_total", "item_total",
"item_tax_total",
"original_item_tax_total",
"item_discount_total",
"shipping_subtotal", "shipping_subtotal",
"original_total", "original_total",
"original_tax_total",
"subtotal", "subtotal",
"discount_total", "discount_total",
"discount_subtotal", "discount_subtotal",
"shipping_total", "shipping_total",
"shipping_tax_total", "shipping_tax_total",
"original_shipping_tax_total",
"shipping_discount_total",
"tax_total", "tax_total",
"refundable_total", "refundable_total",
"order_change", "order_change",
+9 -1
View File
@@ -820,6 +820,10 @@ export interface BaseOrder {
* The tax total applied on the order's items, including promotions. * The tax total applied on the order's items, including promotions.
*/ */
item_tax_total: number item_tax_total: number
/**
* The promotion total applied on the order's items.
*/
item_discount_total: number
/** /**
* The total of the order including taxes, excluding promotions. * The total of the order including taxes, excluding promotions.
*/ */
@@ -837,7 +841,7 @@ export interface BaseOrder {
*/ */
total: number total: number
/** /**
* The total of the order excluding taxes, including promotions. * The total of the order excluding taxes and promotions.
*/ */
subtotal: number subtotal: number
/** /**
@@ -872,6 +876,10 @@ export interface BaseOrder {
* The tax total applied on the order's shipping methods, including promotions. * The tax total applied on the order's shipping methods, including promotions.
*/ */
shipping_tax_total: number shipping_tax_total: number
/**
* The promotion total applied on the order's shipping methods.
*/
shipping_discount_total: number
/** /**
* The total of the order's shipping methods including taxes, excluding promotions. * The total of the order's shipping methods including taxes, excluding promotions.
*/ */
@@ -68,7 +68,7 @@ export type QueryIndexFunction = {
metadata: RemoteQueryFunctionReturnPagination metadata: RemoteQueryFunctionReturnPagination
} }
: Variables extends { skip?: number | undefined } | { skip?: number } : Variables extends { skip?: number | undefined } | { skip?: number }
? // TODO: the real type is the one in parenthsis but we put any for now as the current API is broken and need fixin in a separate iteration (RemoteQueryReturnedData<TEntry>[] | {rows: RemoteQueryReturnedData<TEntry>[] metadata: RemoteQueryFunctionReturnPagination }) ? // TODO: the real type is the one in parenthesis but we put any for now as the current API is broken and need fixing in a separate iteration (RemoteQueryReturnedData<TEntry>[] | {rows: RemoteQueryReturnedData<TEntry>[] metadata: RemoteQueryFunctionReturnPagination })
any any
: RemoteQueryReturnedData<TEntry>[] : RemoteQueryReturnedData<TEntry>[]
: RemoteQueryReturnedData<TEntry>[] : RemoteQueryReturnedData<TEntry>[]
+10
View File
@@ -1182,6 +1182,11 @@ export interface OrderDTO {
*/ */
item_tax_total: BigNumberValue item_tax_total: BigNumberValue
/**
* The item discount total of the order.
*/
item_discount_total: BigNumberValue
/** /**
* The original total of the order. * The original total of the order.
*/ */
@@ -1257,6 +1262,11 @@ export interface OrderDTO {
*/ */
shipping_tax_total: BigNumberValue shipping_tax_total: BigNumberValue
/**
* The shipping discount total of the order.
*/
shipping_discount_total: BigNumberValue
/** /**
* The original shipping total of the order. * The original shipping total of the order.
*/ */
@@ -76,6 +76,7 @@ describe("Total calculation", function () {
item_total: 73.5, item_total: 73.5,
item_subtotal: 65, item_subtotal: 65,
item_tax_total: 8.5, item_tax_total: 8.5,
item_discount_total: 0,
original_total: 73.5, original_total: 73.5,
original_tax_total: 8.5, original_tax_total: 8.5,
original_item_subtotal: 65, original_item_subtotal: 65,
@@ -149,6 +150,7 @@ describe("Total calculation", function () {
item_total: 99, item_total: 99,
item_subtotal: 100, item_subtotal: 100,
item_tax_total: 9, item_tax_total: 9,
item_discount_total: 11,
original_item_total: 110, original_item_total: 110,
original_item_subtotal: 100, original_item_subtotal: 100,
original_item_tax_total: 10, original_item_tax_total: 10,
@@ -350,12 +352,14 @@ describe("Total calculation", function () {
item_total: 95.7, item_total: 95.7,
item_subtotal: 99, item_subtotal: 99,
item_tax_total: 8.7, item_tax_total: 8.7,
item_discount_total: 13.2,
original_item_total: 108.9, original_item_total: 108.9,
original_item_subtotal: 99, original_item_subtotal: 99,
original_item_tax_total: 9.9, original_item_tax_total: 9.9,
shipping_total: 95.7, shipping_total: 95.7,
shipping_subtotal: 99, shipping_subtotal: 99,
shipping_tax_total: 8.7, shipping_tax_total: 8.7,
shipping_discount_total: 13.2,
original_shipping_tax_total: 9.9, original_shipping_tax_total: 9.9,
original_shipping_subtotal: 99, original_shipping_subtotal: 99,
original_shipping_total: 108.9, original_shipping_total: 108.9,
@@ -444,6 +448,7 @@ describe("Total calculation", function () {
item_total: 100, item_total: 100,
item_subtotal: 90.9090909090909, item_subtotal: 90.9090909090909,
item_tax_total: 9.090909090909092, item_tax_total: 9.090909090909092,
item_discount_total: 0,
original_item_total: 100, original_item_total: 100,
original_item_subtotal: 90.9090909090909, original_item_subtotal: 90.9090909090909,
original_item_tax_total: 9.090909090909092, original_item_tax_total: 9.090909090909092,
@@ -486,6 +491,7 @@ describe("Total calculation", function () {
item_total: 110, item_total: 110,
item_subtotal: 100, item_subtotal: 100,
item_tax_total: 10, item_tax_total: 10,
item_discount_total: 0,
original_item_total: 110, original_item_total: 110,
original_item_subtotal: 100, original_item_subtotal: 100,
original_item_tax_total: 10, original_item_tax_total: 10,
@@ -548,6 +554,7 @@ describe("Total calculation", function () {
item_total: 210, item_total: 210,
item_subtotal: 190.9090909090909, item_subtotal: 190.9090909090909,
item_tax_total: 19.09090909090909, item_tax_total: 19.09090909090909,
item_discount_total: 0,
original_item_total: 210, original_item_total: 210,
original_item_subtotal: 190.9090909090909, original_item_subtotal: 190.9090909090909,
original_item_tax_total: 19.09090909090909, original_item_tax_total: 19.09090909090909,
@@ -638,6 +645,7 @@ describe("Total calculation", function () {
item_subtotal: 100, item_subtotal: 100,
item_tax_total: 18.333333333333332, item_tax_total: 18.333333333333332,
item_total: 110, item_total: 110,
item_discount_total: 10,
credit_line_subtotal: 0, credit_line_subtotal: 0,
credit_line_tax_total: 0, credit_line_tax_total: 0,
@@ -749,12 +757,14 @@ describe("Total calculation", function () {
item_total: 88, item_total: 88,
item_subtotal: 100, item_subtotal: 100,
item_tax_total: 8, item_tax_total: 8,
item_discount_total: 22,
original_item_total: 110, original_item_total: 110,
original_item_subtotal: 100, original_item_subtotal: 100,
original_item_tax_total: 10, original_item_tax_total: 10,
shipping_total: 25.3, shipping_total: 25.3,
shipping_subtotal: 25, shipping_subtotal: 25,
shipping_tax_total: 2.3, shipping_tax_total: 2.3,
shipping_discount_total: 2.2,
original_shipping_tax_total: 2.5, original_shipping_tax_total: 2.5,
original_shipping_subtotal: 25, original_shipping_subtotal: 25,
original_shipping_total: 27.5, original_shipping_total: 27.5,
@@ -866,6 +876,7 @@ describe("Total calculation", function () {
item_total: 88, item_total: 88,
item_subtotal: 100, item_subtotal: 100,
item_tax_total: 8, item_tax_total: 8,
item_discount_total: 22,
original_item_total: 110, original_item_total: 110,
original_item_subtotal: 100, original_item_subtotal: 100,
original_item_tax_total: 10, original_item_tax_total: 10,
@@ -942,6 +953,7 @@ describe("Total calculation", function () {
item_total: 0, item_total: 0,
item_subtotal: 119, item_subtotal: 119,
item_tax_total: 0, item_tax_total: 0,
item_discount_total: 141.61,
original_item_total: 141.61, original_item_total: 141.61,
original_item_subtotal: 119, original_item_subtotal: 119,
original_item_tax_total: 22.61, original_item_tax_total: 22.61,
@@ -1005,6 +1017,7 @@ describe("Total calculation", function () {
discount_total: 0, discount_total: 0,
item_subtotal: 100, item_subtotal: 100,
item_tax_total: 19, item_tax_total: 19,
item_discount_total: 0,
item_total: 119, item_total: 119,
items: [ items: [
{ {
@@ -1048,6 +1061,7 @@ describe("Total calculation", function () {
item_subtotal: 119, item_subtotal: 119,
item_tax_total: 22.61, item_tax_total: 22.61,
item_total: 141.61, item_total: 141.61,
item_discount_total: 0,
items: [ items: [
{ {
discount_subtotal: 0, discount_subtotal: 0,
@@ -1090,6 +1104,7 @@ describe("Total calculation", function () {
item_subtotal: 219, item_subtotal: 219,
item_tax_total: 41.61, item_tax_total: 41.61,
item_total: 260.61, item_total: 260.61,
item_discount_total: 0,
items: [ items: [
{ {
discount_subtotal: 0, discount_subtotal: 0,
@@ -1176,6 +1191,7 @@ describe("Total calculation", function () {
item_subtotal: 100, item_subtotal: 100,
item_tax_total: 0, item_tax_total: 0,
item_total: 0, item_total: 0,
item_discount_total: 119,
items: [ items: [
{ {
adjustments: [ adjustments: [
+35 -39
View File
@@ -4,8 +4,8 @@ import { calculateCreditLinesTotal } from "../credit-lines"
import { GetItemTotalInput, getLineItemsTotals } from "../line-item" import { GetItemTotalInput, getLineItemsTotals } from "../line-item"
import { MathBN } from "../math" import { MathBN } from "../math"
import { import {
GetShippingMethodTotalInput,
getShippingMethodsTotals, getShippingMethodsTotals,
GetShippingMethodTotalInput,
} from "../shipping-method" } from "../shipping-method"
import { transformPropertiesToBigNumber } from "../transform-properties-to-bignumber" import { transformPropertiesToBigNumber } from "../transform-properties-to-bignumber"
@@ -86,23 +86,19 @@ export function decorateCartTotals(
let itemsSubtotal = MathBN.convert(0) let itemsSubtotal = MathBN.convert(0)
let itemsTotal = MathBN.convert(0) let itemsTotal = MathBN.convert(0)
let itemsOriginalTotal = MathBN.convert(0) let itemsOriginalTotal = MathBN.convert(0)
let itemsOriginalSubtotal = MathBN.convert(0) let itemsOriginalSubtotal = MathBN.convert(0)
let itemsTaxTotal = MathBN.convert(0) let itemsTaxTotal = MathBN.convert(0)
let itemsOriginalTaxTotal = MathBN.convert(0) let itemsOriginalTaxTotal = MathBN.convert(0)
let itemsDiscountTotal = MathBN.convert(0)
let shippingSubtotal = MathBN.convert(0) let shippingSubtotal = MathBN.convert(0)
let shippingTotal = MathBN.convert(0) let shippingTotal = MathBN.convert(0)
let shippingOriginalTotal = MathBN.convert(0) let shippingOriginalTotal = MathBN.convert(0)
let shippingOriginalSubtotal = MathBN.convert(0) let shippingOriginalSubtotal = MathBN.convert(0)
let shippingTaxTotal = MathBN.convert(0) let shippingTaxTotal = MathBN.convert(0)
let shippingOriginalTaxTotal = MathBN.convert(0) let shippingOriginalTaxTotal = MathBN.convert(0)
let shippingDiscountTotal = MathBN.convert(0)
const cartItems = items.map((item, index) => { const cartItems = items.map((item, index) => {
const itemTotals = Object.assign(item, itemsTotals[item.id ?? index] ?? {}) const itemTotals = Object.assign(item, itemsTotals[item.id ?? index] ?? {})
@@ -128,15 +124,16 @@ export function decorateCartTotals(
itemsTotal = MathBN.add(itemsTotal, itemTotal) itemsTotal = MathBN.add(itemsTotal, itemTotal)
itemsOriginalTotal = MathBN.add(itemsOriginalTotal, itemOriginalTotal) itemsOriginalTotal = MathBN.add(itemsOriginalTotal, itemOriginalTotal)
itemsOriginalSubtotal = MathBN.add(itemsOriginalSubtotal, itemSubtotal) itemsOriginalSubtotal = MathBN.add(itemsOriginalSubtotal, itemSubtotal)
itemsSubtotal = MathBN.add(itemsSubtotal, itemSubtotal) itemsSubtotal = MathBN.add(itemsSubtotal, itemSubtotal)
itemsTaxTotal = MathBN.add(itemsTaxTotal, itemTaxTotal) itemsTaxTotal = MathBN.add(itemsTaxTotal, itemTaxTotal)
itemsOriginalTaxTotal = MathBN.add( itemsOriginalTaxTotal = MathBN.add(
itemsOriginalTaxTotal, itemsOriginalTaxTotal,
itemOriginalTaxTotal itemOriginalTaxTotal
) )
itemsDiscountTotal = MathBN.add(
itemsDiscountTotal,
itemDiscountTotal
)
for (const key of Object.values(optionalFields)) { for (const key of Object.values(optionalFields)) {
if (key in itemTotals) { if (key in itemTotals) {
@@ -156,48 +153,45 @@ export function decorateCartTotals(
subtotal = MathBN.add(subtotal, shippingMethodTotals.subtotal) subtotal = MathBN.add(subtotal, shippingMethodTotals.subtotal)
shippingSubtotal = MathBN.add(
shippingSubtotal,
shippingMethodTotals.subtotal
)
shippingTotal = MathBN.add(shippingTotal, shippingMethodTotals.total)
shippingOriginalTotal = MathBN.add(
shippingOriginalTotal,
shippingMethodTotals.original_total
)
shippingOriginalSubtotal = MathBN.add(
shippingOriginalSubtotal,
shippingMethodTotals.subtotal
)
shippingTaxTotal = MathBN.add(
shippingTaxTotal,
shippingMethodTotals.tax_total
)
shippingOriginalTaxTotal = MathBN.add(
shippingOriginalTaxTotal,
shippingMethodTotals.original_tax_total
)
discountTotal = MathBN.add( discountTotal = MathBN.add(
discountTotal, discountTotal,
shippingMethodTotals.discount_total shippingMethodTotals.discount_total
) )
discountSubtotal = MathBN.add( discountSubtotal = MathBN.add(
discountSubtotal, discountSubtotal,
shippingMethodTotals.discount_subtotal shippingMethodTotals.discount_subtotal
) )
discountTaxTotal = MathBN.add( discountTaxTotal = MathBN.add(
discountTaxTotal, discountTaxTotal,
shippingMethodTotals.discount_tax_total shippingMethodTotals.discount_tax_total
) )
shippingSubtotal = MathBN.add(
shippingSubtotal,
shippingMethodTotals.subtotal
)
shippingTotal = MathBN.add(shippingTotal, shippingMethodTotals.total)
shippingOriginalTotal = MathBN.add(
shippingOriginalTotal,
shippingMethodTotals.original_total
)
shippingOriginalSubtotal = MathBN.add(
shippingOriginalSubtotal,
shippingMethodTotals.subtotal
)
shippingTaxTotal = MathBN.add(
shippingTaxTotal,
shippingMethodTotals.tax_total
)
shippingOriginalTaxTotal = MathBN.add(
shippingOriginalTaxTotal,
shippingMethodTotals.original_tax_total
)
shippingDiscountTotal = MathBN.add(
shippingDiscountTotal,
shippingMethodTotals.discount_total
)
return shippingMethodTotals return shippingMethodTotals
}) })
@@ -250,6 +244,7 @@ export function decorateCartTotals(
cart.item_total = new BigNumber(itemsTotal) cart.item_total = new BigNumber(itemsTotal)
cart.item_subtotal = new BigNumber(itemsSubtotal) cart.item_subtotal = new BigNumber(itemsSubtotal)
cart.item_tax_total = new BigNumber(itemsTaxTotal) cart.item_tax_total = new BigNumber(itemsTaxTotal)
cart.item_discount_total = new BigNumber(itemsDiscountTotal)
cart.original_item_total = new BigNumber(itemsOriginalTotal) cart.original_item_total = new BigNumber(itemsOriginalTotal)
cart.original_item_subtotal = new BigNumber(itemsOriginalSubtotal) cart.original_item_subtotal = new BigNumber(itemsOriginalSubtotal)
@@ -265,6 +260,7 @@ export function decorateCartTotals(
cart.shipping_total = new BigNumber(shippingTotal) cart.shipping_total = new BigNumber(shippingTotal)
cart.shipping_subtotal = new BigNumber(shippingSubtotal) cart.shipping_subtotal = new BigNumber(shippingSubtotal)
cart.shipping_tax_total = new BigNumber(shippingTaxTotal) cart.shipping_tax_total = new BigNumber(shippingTaxTotal)
cart.shipping_discount_total = new BigNumber(shippingDiscountTotal)
cart.original_shipping_tax_total = new BigNumber(shippingOriginalTaxTotal) cart.original_shipping_tax_total = new BigNumber(shippingOriginalTaxTotal)
cart.original_shipping_subtotal = new BigNumber(shippingOriginalSubtotal) cart.original_shipping_subtotal = new BigNumber(shippingOriginalSubtotal)
@@ -18,12 +18,14 @@ export const defaultStoreCartFields = [
"item_total", "item_total",
"item_subtotal", "item_subtotal",
"item_tax_total", "item_tax_total",
"item_discount_total",
"original_item_total", "original_item_total",
"original_item_subtotal", "original_item_subtotal",
"original_item_tax_total", "original_item_tax_total",
"shipping_total", "shipping_total",
"shipping_subtotal", "shipping_subtotal",
"shipping_tax_total", "shipping_tax_total",
"shipping_discount_total",
"original_shipping_tax_total", "original_shipping_tax_total",
"original_shipping_subtotal", "original_shipping_subtotal",
"original_shipping_total", "original_shipping_total",
@@ -3170,12 +3170,14 @@ moduleIntegrationTestRunner<ICartModuleService>({
item_total: 200, item_total: 200,
item_subtotal: 500, item_subtotal: 500,
item_tax_total: 0, item_tax_total: 0,
item_discount_total: 300,
original_item_total: 500, original_item_total: 500,
original_item_subtotal: 500, original_item_subtotal: 500,
original_item_tax_total: 0, original_item_tax_total: 0,
shipping_total: 10, shipping_total: 10,
shipping_subtotal: 10, shipping_subtotal: 10,
shipping_tax_total: 0, shipping_tax_total: 0,
shipping_discount_total: 0,
original_shipping_tax_total: 0, original_shipping_tax_total: 0,
original_shipping_subtotal: 10, original_shipping_subtotal: 10,
original_shipping_total: 10, original_shipping_total: 10,
@@ -3195,6 +3197,14 @@ moduleIntegrationTestRunner<ICartModuleService>({
value: "300", value: "300",
precision: 20, precision: 20,
}, },
raw_item_discount_total: {
value: "300",
precision: 20,
},
raw_shipping_discount_total: {
value: "0",
precision: 20,
},
raw_discount_subtotal: { raw_discount_subtotal: {
value: "300", value: "300",
precision: 20, precision: 20,