Add orders filter by payment status (#1619)

* Add orders filter by payment status

* Move messages to root intl file
This commit is contained in:
Dawid Tarasiuk 2021-11-24 11:13:53 +01:00 committed by GitHub
parent 8cb665e091
commit 7ac687d082
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 235 additions and 86 deletions

View file

@ -1293,7 +1293,7 @@
"string": "Cancel"
},
"src_dot_cancelled": {
"context": "order status",
"context": "payment status",
"string": "Cancelled"
},
"src_dot_cannotFullfillUnpaidOrder": {
@ -5456,6 +5456,13 @@
"context": "order status",
"string": "Partially returned"
},
"src_dot_paymentStatus": {
"string": "Payment status"
},
"src_dot_pending": {
"context": "payment status",
"string": "Pending"
},
"src_dot_permissionGroups": {
"context": "permission groups section name",
"string": "Permission Groups"
@ -6699,6 +6706,10 @@
"context": "payment status",
"string": "Fully refunded"
},
"src_dot_refused": {
"context": "payment status",
"string": "Refused"
},
"src_dot_remove": {
"context": "button",
"string": "Remove"

View file

@ -99,6 +99,9 @@ export const commonMessages = defineMessages({
status: {
defaultMessage: "Status"
},
paymentStatus: {
defaultMessage: "Payment status"
},
summary: {
defaultMessage: "Summary"
},
@ -347,6 +350,83 @@ export const sectionNames = defineMessages({
}
});
export const commonStatusMessages = defineMessages({
cancelled: {
defaultMessage: "Cancelled",
description: "payment status"
}
});
export const orderStatusMessages = defineMessages({
draft: {
defaultMessage: "Draft",
description: "order status"
},
fulfilled: {
defaultMessage: "Fulfilled",
description: "order status"
},
partiallyFulfilled: {
defaultMessage: "Partially fulfilled",
description: "order status"
},
partiallyReturned: {
defaultMessage: "Partially returned",
description: "order status"
},
readyToCapture: {
defaultMessage: "Ready to capture",
description: "order status"
},
readyToFulfill: {
defaultMessage: "Ready to fulfill",
description: "order status"
},
returned: {
defaultMessage: "Returned",
description: "order status"
},
unconfirmed: {
defaultMessage: "Unconfirmed",
description: "order status"
},
unfulfilled: {
defaultMessage: "Unfulfilled",
description: "order status"
}
});
export const paymentStatusMessages = defineMessages({
paid: {
defaultMessage: "Fully paid",
description: "payment status"
},
partiallyPaid: {
defaultMessage: "Partially paid",
description: "payment status"
},
partiallyRefunded: {
defaultMessage: "Partially refunded",
description: "payment status"
},
refunded: {
defaultMessage: "Fully refunded",
description: "payment status"
},
unpaid: {
defaultMessage: "Unpaid",
description: "payment status"
},
pending: {
defaultMessage: "Pending",
description: "payment status"
},
refused: {
defaultMessage: "Refused",
description: "payment status"
}
});
export function translateBoolean(value: boolean, intl: IntlShape): string {
return value
? intl.formatMessage(commonMessages.yes)

View file

@ -1,7 +1,7 @@
import { ThemeType } from "@saleor/macaw-ui";
import moment from "moment-timezone";
import { MutationFunction, MutationResult } from "react-apollo";
import { defineMessages, IntlShape } from "react-intl";
import { IntlShape } from "react-intl";
import urlJoin from "url-join";
import { ConfirmButtonTransitionState } from "./components/ConfirmButton";
@ -9,6 +9,11 @@ import { StatusType } from "./components/StatusChip/types";
import { StatusLabelProps } from "./components/StatusLabel";
import { APP_MOUNT_URI } from "./config";
import { AddressType, AddressTypeInput } from "./customers/types";
import {
commonStatusMessages,
orderStatusMessages,
paymentStatusMessages
} from "./intl";
import {
MutationResultAdditionalProps,
PartialMutationProviderOutput,
@ -69,29 +74,6 @@ export function weight(value: string) {
export const removeDoubleSlashes = (url: string) =>
url.replace(/([^:]\/)\/+/g, "$1");
const paymentStatusMessages = defineMessages({
paid: {
defaultMessage: "Fully paid",
description: "payment status"
},
partiallyPaid: {
defaultMessage: "Partially paid",
description: "payment status"
},
partiallyRefunded: {
defaultMessage: "Partially refunded",
description: "payment status"
},
refunded: {
defaultMessage: "Fully refunded",
description: "payment status"
},
unpaid: {
defaultMessage: "Unpaid",
description: "payment status"
}
});
export const transformPaymentStatus = (
status: string,
intl: IntlShape
@ -100,74 +82,50 @@ export const transformPaymentStatus = (
case PaymentChargeStatusEnum.PARTIALLY_CHARGED:
return {
localized: intl.formatMessage(paymentStatusMessages.partiallyPaid),
status: "error"
status: StatusType.ERROR
};
case PaymentChargeStatusEnum.FULLY_CHARGED:
return {
localized: intl.formatMessage(paymentStatusMessages.paid),
status: "success"
status: StatusType.SUCCESS
};
case PaymentChargeStatusEnum.PARTIALLY_REFUNDED:
return {
localized: intl.formatMessage(paymentStatusMessages.partiallyRefunded),
status: "error"
status: StatusType.ERROR
};
case PaymentChargeStatusEnum.FULLY_REFUNDED:
return {
localized: intl.formatMessage(paymentStatusMessages.refunded),
status: "success"
status: StatusType.SUCCESS
};
default:
case PaymentChargeStatusEnum.PENDING:
return {
localized: intl.formatMessage(paymentStatusMessages.pending),
status: StatusType.NEUTRAL
};
case PaymentChargeStatusEnum.REFUSED:
return {
localized: intl.formatMessage(paymentStatusMessages.refused),
status: StatusType.ERROR
};
case PaymentChargeStatusEnum.CANCELLED:
return {
localized: intl.formatMessage(commonStatusMessages.cancelled),
status: StatusType.ERROR
};
case PaymentChargeStatusEnum.NOT_CHARGED:
return {
localized: intl.formatMessage(paymentStatusMessages.unpaid),
status: "error"
status: StatusType.ERROR
};
}
return {
localized: status,
status: StatusType.ERROR
};
};
export const orderStatusMessages = defineMessages({
cancelled: {
defaultMessage: "Cancelled",
description: "order status"
},
draft: {
defaultMessage: "Draft",
description: "order status"
},
fulfilled: {
defaultMessage: "Fulfilled",
description: "order status"
},
partiallyFulfilled: {
defaultMessage: "Partially fulfilled",
description: "order status"
},
partiallyReturned: {
defaultMessage: "Partially returned",
description: "order status"
},
readyToCapture: {
defaultMessage: "Ready to capture",
description: "order status"
},
readyToFulfill: {
defaultMessage: "Ready to fulfill",
description: "order status"
},
returned: {
defaultMessage: "Returned",
description: "order status"
},
unconfirmed: {
defaultMessage: "Unconfirmed",
description: "order status"
},
unfulfilled: {
defaultMessage: "Unfulfilled",
description: "order status"
}
});
export const transformOrderStatus = (
status: string,
intl: IntlShape
@ -190,7 +148,7 @@ export const transformOrderStatus = (
};
case OrderStatus.CANCELED:
return {
localized: intl.formatMessage(orderStatusMessages.cancelled),
localized: intl.formatMessage(commonStatusMessages.cancelled),
status: StatusType.ERROR
};
case OrderStatus.DRAFT:

View file

@ -1,9 +1,16 @@
import { IFilter } from "@saleor/components/Filter";
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
import { commonMessages } from "@saleor/intl";
import { orderStatusMessages } from "@saleor/misc";
import {
commonStatusMessages,
orderStatusMessages,
paymentStatusMessages
} from "@saleor/intl";
import { FilterOpts, MinMax } from "@saleor/types";
import { OrderStatusFilter } from "@saleor/types/globalTypes";
import {
OrderStatusFilter,
PaymentChargeStatusEnum
} from "@saleor/types/globalTypes";
import {
createDateField,
createOptionsField,
@ -15,6 +22,7 @@ export enum OrderFilterKeys {
created = "created",
customer = "customer",
status = "status",
paymentStatus = "paymentStatus",
channel = "channel"
}
@ -22,6 +30,7 @@ export interface OrderListFilterOpts {
created: FilterOpts<MinMax>;
customer: FilterOpts<string>;
status: FilterOpts<OrderStatusFilter[]>;
paymentStatus: FilterOpts<PaymentChargeStatusEnum[]>;
channel?: FilterOpts<MultiAutocompleteChoiceType[]>;
}
@ -69,7 +78,7 @@ export function createFilterStructure(
true,
[
{
label: intl.formatMessage(orderStatusMessages.cancelled),
label: intl.formatMessage(commonStatusMessages.cancelled),
value: OrderStatusFilter.CANCELED
},
{
@ -91,11 +100,58 @@ export function createFilterStructure(
{
label: intl.formatMessage(orderStatusMessages.readyToFulfill),
value: OrderStatusFilter.READY_TO_FULFILL
},
{
label: intl.formatMessage(orderStatusMessages.unconfirmed),
value: OrderStatusFilter.UNCONFIRMED
}
]
),
active: opts.status.active
},
{
...createOptionsField(
OrderFilterKeys.paymentStatus,
intl.formatMessage(commonMessages.paymentStatus),
opts.paymentStatus.value,
true,
[
{
label: intl.formatMessage(paymentStatusMessages.paid),
value: PaymentChargeStatusEnum.FULLY_CHARGED
},
{
label: intl.formatMessage(paymentStatusMessages.partiallyPaid),
value: PaymentChargeStatusEnum.PARTIALLY_CHARGED
},
{
label: intl.formatMessage(paymentStatusMessages.unpaid),
value: PaymentChargeStatusEnum.NOT_CHARGED
},
{
label: intl.formatMessage(paymentStatusMessages.refunded),
value: PaymentChargeStatusEnum.FULLY_REFUNDED
},
{
label: intl.formatMessage(paymentStatusMessages.partiallyRefunded),
value: PaymentChargeStatusEnum.PARTIALLY_REFUNDED
},
{
label: intl.formatMessage(commonStatusMessages.cancelled),
value: PaymentChargeStatusEnum.CANCELLED
},
{
label: intl.formatMessage(paymentStatusMessages.pending),
value: PaymentChargeStatusEnum.PENDING
},
{
label: intl.formatMessage(paymentStatusMessages.refused),
value: PaymentChargeStatusEnum.REFUSED
}
]
),
active: opts.paymentStatus.active
},
...(opts?.channel?.value.length
? [
{

View file

@ -27,6 +27,7 @@ export enum OrderListUrlFiltersEnum {
}
export enum OrderListUrlFiltersWithMultipleValues {
status = "status",
paymentStatus = "paymentStatus",
channel = "channel"
}

View file

@ -6,6 +6,10 @@ Object {
"createdFrom": "2019-12-09",
"createdTo": "2019-12-38",
"customer": "email@example.com",
"paymentStatus": Array [
"FULLY_CHARGED",
"PARTIALLY_CHARGED",
],
"status": Array [
"FULFILLED",
"PARTIALLY_FULFILLED",
@ -13,4 +17,4 @@ Object {
}
`;
exports[`Filtering URL params should not be empty if active filters are present 2`] = `"customer=email%40example.com&createdFrom=2019-12-09&createdTo=2019-12-38&status%5B%5D=FULFILLED&status%5B%5D=PARTIALLY_FULFILLED"`;
exports[`Filtering URL params should not be empty if active filters are present 2`] = `"customer=email%40example.com&createdFrom=2019-12-09&createdTo=2019-12-38&status%5B%5D=FULFILLED&status%5B%5D=PARTIALLY_FULFILLED&paymentStatus%5B%5D=FULLY_CHARGED&paymentStatus%5B%5D=PARTIALLY_CHARGED"`;

View file

@ -1,7 +1,10 @@
import { date } from "@saleor/fixtures";
import { createFilterStructure } from "@saleor/orders/components/OrderListPage";
import { OrderListUrlFilters } from "@saleor/orders/urls";
import { OrderStatusFilter } from "@saleor/types/globalTypes";
import {
OrderStatusFilter,
PaymentChargeStatusEnum
} from "@saleor/types/globalTypes";
import { getFilterQueryParams } from "@saleor/utils/filters";
import { stringifyQs } from "@saleor/utils/urls";
import { getExistingKeys, setFilterOptsStatus } from "@test/filters";
@ -64,6 +67,13 @@ describe("Filtering URL params", () => {
OrderStatusFilter.FULFILLED,
OrderStatusFilter.PARTIALLY_FULFILLED
]
},
paymentStatus: {
active: false,
value: [
PaymentChargeStatusEnum.FULLY_CHARGED,
PaymentChargeStatusEnum.PARTIALLY_CHARGED
]
}
});

View file

@ -8,7 +8,8 @@ import {
import { IFilterElement } from "../../../components/Filter";
import {
OrderFilterInput,
OrderStatusFilter
OrderStatusFilter,
PaymentChargeStatusEnum
} from "../../../types/globalTypes";
import {
createFilterTabUtils,
@ -60,6 +61,14 @@ export function getFilterOpts(
findValueInEnum(status, OrderStatusFilter)
) || []
)
},
paymentStatus: {
active: params?.paymentStatus !== undefined,
value: dedupeFilter(
params.paymentStatus?.map(paymentStatus =>
findValueInEnum(paymentStatus, PaymentChargeStatusEnum)
) || []
)
}
};
}
@ -75,7 +84,12 @@ export function getFilterVariables(
}),
customer: params.customer,
search: params.query,
status: params?.status?.map(status => findInEnum(status, OrderStatusFilter))
status: params?.status?.map(status =>
findInEnum(status, OrderStatusFilter)
),
paymentStatus: params?.paymentStatus?.map(paymentStatus =>
findInEnum(paymentStatus, PaymentChargeStatusEnum)
)
};
}
@ -99,6 +113,13 @@ export function getFilterQueryParam(
OrderStatusFilter
);
case OrderFilterKeys.paymentStatus:
return getMultipleEnumValueQueryParam(
filter,
OrderListUrlFiltersWithMultipleValues.paymentStatus,
PaymentChargeStatusEnum
);
case OrderFilterKeys.channel:
return getMultipleValueQueryParam(
filter,

View file

@ -130599,9 +130599,7 @@ exports[`Storyshots Views / Orders / Order details no payment 1`] = `
>
<div
class="MuiTypography-root-id MuiTypography-body1-id"
>
Unpaid
</div>
/>
</div>
</div>
</span>

View file

@ -2,7 +2,10 @@ import OrderListPage, {
OrderListPageProps
} from "@saleor/orders/components/OrderListPage";
import { OrderListUrlSortField } from "@saleor/orders/urls";
import { OrderStatusFilter } from "@saleor/types/globalTypes";
import {
OrderStatusFilter,
PaymentChargeStatusEnum
} from "@saleor/types/globalTypes";
import { storiesOf } from "@storybook/react";
import React from "react";
@ -46,6 +49,13 @@ const props: OrderListPageProps = {
status: {
active: false,
value: [OrderStatusFilter.CANCELED, OrderStatusFilter.FULFILLED]
},
paymentStatus: {
active: false,
value: [
PaymentChargeStatusEnum.CANCELLED,
PaymentChargeStatusEnum.FULLY_CHARGED
]
}
},
limits,