Skip to content

Commit

Permalink
feat(dashboard) taxes + discount breakdown (#9586)
Browse files Browse the repository at this point in the history
**What**
- add tax breakdown to order details
- display discount total and codes

---

CLOSES CC-553
  • Loading branch information
fPolic authored Oct 18, 2024
1 parent aa6a28a commit 5b91d71
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 33 deletions.
11 changes: 10 additions & 1 deletion packages/admin/dashboard/src/i18n/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -901,7 +901,16 @@
"allocateItems": "Allocate items",
"editOrder": "Edit order",
"editOrderContinue": "Continue order edit",
"inventoryKit": "Consists of {{count}}x inventory items"
"inventoryKit": "Consists of {{count}}x inventory items",
"itemTotal": "Item Total",
"shippingTotal": "Shipping Total",
"discountTotal": "Discount Total",
"taxTotalIncl": "Tax Total (included)",
"itemSubtotal": "Item Subtotal",
"shippingSubtotal": "Shipping Subtotal",
"discountSubtotal": "Discount Subtotal",
"taxTotal": "Tax Total"

},
"payment": {
"title": "Payments",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
AdminOrder,
AdminOrderLineItem,
AdminOrderPreview,
AdminRegion,
AdminReturn,
} from "@medusajs/types"
import {
Expand All @@ -31,6 +32,7 @@ import {
toast,
Tooltip,
usePrompt,
clx,
} from "@medusajs/ui"

import { AdminPaymentCollection } from "../../../../../../../../core/types/dist/http/payment/admin/entities"
Expand Down Expand Up @@ -528,9 +530,9 @@ const Cost = ({
secondaryValue,
tooltip,
}: {
label: string
label: ReactNode
value: string | number
secondaryValue: string
secondaryValue?: string
tooltip?: ReactNode
}) => (
<div className="grid grid-cols-3 items-center">
Expand All @@ -550,45 +552,191 @@ const Cost = ({
</div>
)

const CostBreakdown = ({ order }: { order: AdminOrder }) => {
const CostBreakdown = ({
order,
}: {
order: AdminOrder & { region: AdminRegion }
}) => {
const { t } = useTranslation()
const [isTaxOpen, setIsTaxOpen] = 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 taxCodeMap = {}

order.items.forEach((item) => {
item.tax_lines?.forEach((line) => {
taxCodeMap[line.code] = (taxCodeMap[line.code] || 0) + line.total
})
})

order.shipping_methods.forEach((sm) => {
sm.tax_lines?.forEach((line) => {
taxCodeMap[line.code] = (taxCodeMap[line.code] || 0) + line.total
})
})

return taxCodeMap
}, [order])

const automaticTaxesOn = !!order.region!.automatic_taxes
const hasTaxLines = !!Object.keys(taxCodes).length

const discountTotal = automaticTaxesOn
? order.discount_total
: order.discount_subtotal

return (
<div className="text-ui-fg-subtle flex flex-col gap-y-2 px-6 py-4">
<Cost
label={t("fields.discount")}
// TODO: DISCOUNTS -> moved to line items now
// secondaryValue={
// order.discounts.length > 0
// ? order.discounts.map((d) => d.code).join(", ")
// : "-"
// }
label={t(
automaticTaxesOn
? "orders.summary.itemTotal"
: "orders.summary.itemSubtotal"
)}
value={getLocaleAmount(order.item_total, order.currency_code)}
/>
<Cost
label={
<div
onClick={() => setIsShippingOpen((o) => !o)}
className="flex cursor-pointer items-center gap-1"
>
<span>
{t(
automaticTaxesOn
? "orders.summary.shippingTotal"
: "orders.summary.shippingSubtotal"
)}
</span>
<TriangleDownMini
style={{
transform: `rotate(${isShippingOpen ? 0 : -90}deg)`,
}}
/>
</div>
}
value={getLocaleAmount(
automaticTaxesOn ? order.shipping_total : order.shipping_subtotal,
order.currency_code
)}
/>

{isShippingOpen && (
<div className="flex flex-col gap-1 pl-5">
{(order.shipping_methods || [])
.sort((m1, m2) =>
(m1.created_at as string).localeCompare(m2.created_at as string)
)
.map((sm, i) => {
return (
<div
key={sm.id}
className="flex items-center justify-between gap-x-2"
>
<div>
<span className="txt-small text-ui-fg-subtle font-medium">
{sm.name}
{sm.detail.return_id &&
` (${t("fields.returnShipping")})`}{" "}
<ShippingInfoPopover key={i} shippingMethod={sm} />
</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(
automaticTaxesOn ? sm.total : sm.subtotal,
order.currency_code
)}
</span>
</div>
)
})}
</div>
)}

<Cost
label={t(
automaticTaxesOn
? "orders.summary.discountTotal"
: "orders.summary.discountSubtotal"
)}
secondaryValue={discountCodes.join(", ")}
value={
order.discount_total > 0
? `- ${getLocaleAmount(order.discount_total, order.currency_code)}`
discountTotal > 0
? `- ${getLocaleAmount(discountTotal, order.currency_code)}`
: "-"
}
/>
{(order.shipping_methods || [])
.sort((m1, m2) =>
(m1.created_at as string).localeCompare(m2.created_at as string)
)
.map((sm, i) => {
return (
<div key={sm.id}>
<Cost
label={
sm.detail.return_id
? t("fields.returnShipping")
: t("fields.outboundShipping")
}
secondaryValue={sm.name}
value={getLocaleAmount(sm.total, order.currency_code)}
tooltip={<ShippingInfoPopover key={i} shippingMethod={sm} />}

<>
<div className="flex justify-between">
<div
onClick={() => hasTaxLines && setIsTaxOpen((o) => !o)}
className={clx("flex items-center gap-1", {
"cursor-pointer": hasTaxLines,
})}
>
<span className="txt-small select-none">
{t(
automaticTaxesOn
? "orders.summary.taxTotalIncl"
: "orders.summary.taxTotal"
)}
</span>
{hasTaxLines && (
<TriangleDownMini
style={{
transform: `rotate(${isTaxOpen ? 0 : -90}deg)`,
}}
/>
</div>
)
})}
)}
</div>

<div className="text-right">
<Text size="small" leading="compact">
{getLocaleAmount(order.tax_total, order.currency_code)}
</Text>
</div>
</div>
{isTaxOpen && (
<div className="flex flex-col gap-1 pl-5">
{Object.entries(taxCodes).map(([code, total]) => {
return (
<div
key={code}
className="flex items-center justify-between gap-x-2"
>
<div>
<span className="txt-small text-ui-fg-subtle font-medium">
{code}
</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>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ const DEFAULT_PROPERTIES = [
"currency_code",
// --- TOTALS ---
"total",
"item_total",
"shipping_subtotal",
"subtotal",
"discounts_total",
"discount_total",
"discount_subtotal",
"shipping_total",
"shipping_tax_total",
"tax_total",
Expand Down Expand Up @@ -40,6 +43,7 @@ const DEFAULT_RELATIONS = [
"*payment_collections.payments",
"*payment_collections.payments.refunds",
"*payment_collections.payments.refunds.refund_reason",
"region.automatic_taxes",
]

export const DEFAULT_FIELDS = `${DEFAULT_PROPERTIES.join(
Expand Down

0 comments on commit 5b91d71

Please sign in to comment.