Skip to content

Commit

Permalink
Allow shipping cost refund (#5150)
Browse files Browse the repository at this point in the history
* allow shipping cost refund

* add tests

* extract hook to separate file

* fixes
  • Loading branch information
Cloud11PL committed Sep 6, 2024
1 parent 6c3d350 commit 8134b89
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 40 deletions.
5 changes: 5 additions & 0 deletions .changeset/seven-timers-doubt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

You can now make a refund with shipping costs or custom shipping amount. This means you can make a refund without selecting line items.
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const OrderFulfilledProductsCard: React.FC<OrderFulfilledProductsCardProps> = pr
</Box>
}
/>
<DashboardCard.Content>
<DashboardCard.Content paddingX={0}>
<OrderDetailsDatagrid lines={getLines()} loading={false} onShowMetadata={onShowMetadata} />
<ExtraInfoLines fulfillment={fulfillment} />
</DashboardCard.Content>
Expand Down
49 changes: 10 additions & 39 deletions src/orders/components/OrderReturnPage/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { getById } from "@dashboard/misc";
import React, { useEffect } from "react";

import { OrderRefundAmountCalculationMode } from "../OrderRefundPage/form";
import { useFulfillmentFormset } from "./useFulfillmentFormset";
import {
getLineItem,
getOrderUnfulfilledLines,
Expand Down Expand Up @@ -93,41 +94,17 @@ function useOrderReturnForm(
const { setExitDialogSubmitRef } = useExitFormDialog({
formId,
});
const unfulfiledItemsQuantites = useFormset<LineItemData, number>(
getOrderUnfulfilledLines(order).map(getParsedLineData({ initialValue: 0 })),
);
const getItemsFulfilled = () => {
const commonOptions = {
initialValue: 0,
isFulfillment: true,
};
const refundedFulfilmentsItems = getParsedLineDataForFulfillmentStatus(
order,
FulfillmentStatus.REFUNDED,
{ ...commonOptions, isRefunded: true },
);
const fulfilledFulfillmentsItems = getParsedLineDataForFulfillmentStatus(
order,
FulfillmentStatus.FULFILLED,
commonOptions,
);

return refundedFulfilmentsItems.concat(fulfilledFulfillmentsItems);
};
const getItemsWaiting = () => {
const commonOptions = {
initialValue: 0,
isFulfillment: true,
};
const {
fulfiledItemsQuatities,
waitingItemsQuantities,
unfulfiledItemsQuantites,
disabled: isSaveDisabled,
} = useFulfillmentFormset({
order,
formData,
});

return getParsedLineDataForFulfillmentStatus(
order,
FulfillmentStatus.WAITING_FOR_APPROVAL,
commonOptions,
);
};
const fulfiledItemsQuatities = useFormset<LineItemData, number>(getItemsFulfilled());
const waitingItemsQuantities = useFormset<LineItemData, number>(getItemsWaiting());
const getItemsToBeReplaced = () => {
if (!order) {
return [];
Expand Down Expand Up @@ -225,12 +202,6 @@ function useOrderReturnForm(
};
}

const hasAnyItemsSelected =
fulfiledItemsQuatities.data.some(({ value }) => !!value) ||
waitingItemsQuantities.data.some(({ value }) => !!value) ||
unfulfiledItemsQuantites.data.some(({ value }) => !!value);
const isSaveDisabled = !hasAnyItemsSelected;

setIsSubmitDisabled(isSaveDisabled);

return {
Expand Down
102 changes: 102 additions & 0 deletions src/orders/components/OrderReturnPage/useFulfillmentFormset.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { renderHook } from "@testing-library/react-hooks";

import { useFulfillmentFormset } from "./useFulfillmentFormset";

describe("useFulfillmentFormset", () => {
it("should be disabled when no items are returned, no shipping and no amount", () => {
// Arrange & Act
const { result } = renderHook(() =>
useFulfillmentFormset({
order: {
fulfillments: [],
lines: [],
} as any,
formData: {
amount: 0,
refundShipmentCosts: false,
},
}),
);

// Assert
expect(result.current.disabled).toBe(true);
});

it("should not disabled when no items are returned, but with shipping and no amount", () => {
// Arrange & Act
const { result } = renderHook(() =>
useFulfillmentFormset({
order: {
fulfillments: [],
lines: [],
} as any,
formData: {
amount: 0,
refundShipmentCosts: true,
},
}),
);

// Assert
expect(result.current.disabled).toBe(false);
});

it("should not disabled when no items are returned, but with shipping and amount", () => {
// Arrange & Act
const { result } = renderHook(() =>
useFulfillmentFormset({
order: {
fulfillments: [],
lines: [],
} as any,
formData: {
amount: 21.37,
refundShipmentCosts: true,
},
}),
);

// Assert
expect(result.current.disabled).toBe(false);
});

it("should not disabled when there are items selected with value, but with no shipping and no amount", () => {
// Arrange & Act
const { result } = renderHook(() =>
useFulfillmentFormset({
order: {
fulfillments: [
{
status: "FULFILLED",
lines: [
{
id: "id",
quantity: 1,
orderLine: {
id: "id",
},
},
],
} as any,
],
lines: [
{
id: "id",
quantity: 1,
} as any,
],
} as any,
formData: {
amount: 0,
refundShipmentCosts: false,
},
}),
);

result.current.fulfiledItemsQuatities.change("id", 21.37);

// Assert
expect(result.current.fulfiledItemsQuatities.data.length).toBe(1);
expect(result.current.disabled).toBe(false);
});
});
46 changes: 46 additions & 0 deletions src/orders/components/OrderReturnPage/useFulfillmentFormset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { OrderDetailsFragment } from "@dashboard/graphql";
import useFormset from "@dashboard/hooks/useFormset";

import { LineItemData } from "./form";
import {
getItemsFulfilled,
getItemsWaiting,
getOrderUnfulfilledLines,
getParsedLineData,
LineItem,
} from "./utils";

const mapWithLabel = (line: LineItem<number>) => ({ ...line, label: line.label ?? "" });

export const useFulfillmentFormset = ({
order,
formData,
}: {
order: OrderDetailsFragment;
formData: { refundShipmentCosts: boolean; amount: number };
}) => {
const fulfiledItemsQuatities = useFormset<LineItemData, number>(
getItemsFulfilled(order).map(mapWithLabel),
);
const waitingItemsQuantities = useFormset<LineItemData, number>(
getItemsWaiting(order).map(mapWithLabel),
);
const unfulfiledItemsQuantites = useFormset<LineItemData, number>(
getOrderUnfulfilledLines(order)
.map(getParsedLineData({ initialValue: 0 }))
.map(mapWithLabel),
);

const hasAnyItemsSelected =
fulfiledItemsQuatities.data.some(({ value }) => !!value) ||
waitingItemsQuantities.data.some(({ value }) => !!value) ||
unfulfiledItemsQuantites.data.some(({ value }) => !!value);
const disabled = !hasAnyItemsSelected && !formData.refundShipmentCosts && !formData.amount;

return {
fulfiledItemsQuatities,
waitingItemsQuantities,
unfulfiledItemsQuantites,
disabled,
};
};
35 changes: 35 additions & 0 deletions src/orders/components/OrderReturnPage/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ export const getAllOrderWaitingLines = (order?: OrderDetailsFragment) =>
[],
);

// TODO: Migrate this utils file to strict mode
export type LineItem<T> = ReturnType<typeof getLineItem<T>>;

export function getLineItem<T>(
line: FulfillmentLine | ParsedFulfillmentLine | OrderLine,
{ initialValue, isFulfillment = false, isRefunded = false }: LineItemOptions<T>,
Expand Down Expand Up @@ -218,3 +221,35 @@ export const getReturnRefundValue = ({
.toString() ?? ""
);
};

export const getItemsFulfilled = (order: OrderDetailsFragment) => {
const commonOptions = {
initialValue: 0,
isFulfillment: true,
};
const refundedFulfilmentsItems = getParsedLineDataForFulfillmentStatus(
order,
FulfillmentStatus.REFUNDED,
{ ...commonOptions, isRefunded: true },
);
const fulfilledFulfillmentsItems = getParsedLineDataForFulfillmentStatus(
order,
FulfillmentStatus.FULFILLED,
commonOptions,
);

return refundedFulfilmentsItems.concat(fulfilledFulfillmentsItems);
};

export const getItemsWaiting = (order: OrderDetailsFragment) => {
const commonOptions = {
initialValue: 0,
isFulfillment: true,
};

return getParsedLineDataForFulfillmentStatus(
order,
FulfillmentStatus.WAITING_FOR_APPROVAL,
commonOptions,
);
};

0 comments on commit 8134b89

Please sign in to comment.