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

View file

@ -99,6 +99,9 @@ export const commonMessages = defineMessages({
status: { status: {
defaultMessage: "Status" defaultMessage: "Status"
}, },
paymentStatus: {
defaultMessage: "Payment status"
},
summary: { summary: {
defaultMessage: "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 { export function translateBoolean(value: boolean, intl: IntlShape): string {
return value return value
? intl.formatMessage(commonMessages.yes) ? intl.formatMessage(commonMessages.yes)

View file

@ -1,7 +1,7 @@
import { ThemeType } from "@saleor/macaw-ui"; import { ThemeType } from "@saleor/macaw-ui";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { MutationFunction, MutationResult } from "react-apollo"; import { MutationFunction, MutationResult } from "react-apollo";
import { defineMessages, IntlShape } from "react-intl"; import { IntlShape } from "react-intl";
import urlJoin from "url-join"; import urlJoin from "url-join";
import { ConfirmButtonTransitionState } from "./components/ConfirmButton"; import { ConfirmButtonTransitionState } from "./components/ConfirmButton";
@ -9,6 +9,11 @@ import { StatusType } from "./components/StatusChip/types";
import { StatusLabelProps } from "./components/StatusLabel"; import { StatusLabelProps } from "./components/StatusLabel";
import { APP_MOUNT_URI } from "./config"; import { APP_MOUNT_URI } from "./config";
import { AddressType, AddressTypeInput } from "./customers/types"; import { AddressType, AddressTypeInput } from "./customers/types";
import {
commonStatusMessages,
orderStatusMessages,
paymentStatusMessages
} from "./intl";
import { import {
MutationResultAdditionalProps, MutationResultAdditionalProps,
PartialMutationProviderOutput, PartialMutationProviderOutput,
@ -69,29 +74,6 @@ export function weight(value: string) {
export const removeDoubleSlashes = (url: string) => export const removeDoubleSlashes = (url: string) =>
url.replace(/([^:]\/)\/+/g, "$1"); 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 = ( export const transformPaymentStatus = (
status: string, status: string,
intl: IntlShape intl: IntlShape
@ -100,74 +82,50 @@ export const transformPaymentStatus = (
case PaymentChargeStatusEnum.PARTIALLY_CHARGED: case PaymentChargeStatusEnum.PARTIALLY_CHARGED:
return { return {
localized: intl.formatMessage(paymentStatusMessages.partiallyPaid), localized: intl.formatMessage(paymentStatusMessages.partiallyPaid),
status: "error" status: StatusType.ERROR
}; };
case PaymentChargeStatusEnum.FULLY_CHARGED: case PaymentChargeStatusEnum.FULLY_CHARGED:
return { return {
localized: intl.formatMessage(paymentStatusMessages.paid), localized: intl.formatMessage(paymentStatusMessages.paid),
status: "success" status: StatusType.SUCCESS
}; };
case PaymentChargeStatusEnum.PARTIALLY_REFUNDED: case PaymentChargeStatusEnum.PARTIALLY_REFUNDED:
return { return {
localized: intl.formatMessage(paymentStatusMessages.partiallyRefunded), localized: intl.formatMessage(paymentStatusMessages.partiallyRefunded),
status: "error" status: StatusType.ERROR
}; };
case PaymentChargeStatusEnum.FULLY_REFUNDED: case PaymentChargeStatusEnum.FULLY_REFUNDED:
return { return {
localized: intl.formatMessage(paymentStatusMessages.refunded), 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 { return {
localized: intl.formatMessage(paymentStatusMessages.unpaid), 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 = ( export const transformOrderStatus = (
status: string, status: string,
intl: IntlShape intl: IntlShape
@ -190,7 +148,7 @@ export const transformOrderStatus = (
}; };
case OrderStatus.CANCELED: case OrderStatus.CANCELED:
return { return {
localized: intl.formatMessage(orderStatusMessages.cancelled), localized: intl.formatMessage(commonStatusMessages.cancelled),
status: StatusType.ERROR status: StatusType.ERROR
}; };
case OrderStatus.DRAFT: case OrderStatus.DRAFT:

View file

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

View file

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

View file

@ -6,6 +6,10 @@ Object {
"createdFrom": "2019-12-09", "createdFrom": "2019-12-09",
"createdTo": "2019-12-38", "createdTo": "2019-12-38",
"customer": "email@example.com", "customer": "email@example.com",
"paymentStatus": Array [
"FULLY_CHARGED",
"PARTIALLY_CHARGED",
],
"status": Array [ "status": Array [
"FULFILLED", "FULFILLED",
"PARTIALLY_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 { date } from "@saleor/fixtures";
import { createFilterStructure } from "@saleor/orders/components/OrderListPage"; import { createFilterStructure } from "@saleor/orders/components/OrderListPage";
import { OrderListUrlFilters } from "@saleor/orders/urls"; 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 { getFilterQueryParams } from "@saleor/utils/filters";
import { stringifyQs } from "@saleor/utils/urls"; import { stringifyQs } from "@saleor/utils/urls";
import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; import { getExistingKeys, setFilterOptsStatus } from "@test/filters";
@ -64,6 +67,13 @@ describe("Filtering URL params", () => {
OrderStatusFilter.FULFILLED, OrderStatusFilter.FULFILLED,
OrderStatusFilter.PARTIALLY_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 { IFilterElement } from "../../../components/Filter";
import { import {
OrderFilterInput, OrderFilterInput,
OrderStatusFilter OrderStatusFilter,
PaymentChargeStatusEnum
} from "../../../types/globalTypes"; } from "../../../types/globalTypes";
import { import {
createFilterTabUtils, createFilterTabUtils,
@ -60,6 +61,14 @@ export function getFilterOpts(
findValueInEnum(status, OrderStatusFilter) 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, customer: params.customer,
search: params.query, 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 OrderStatusFilter
); );
case OrderFilterKeys.paymentStatus:
return getMultipleEnumValueQueryParam(
filter,
OrderListUrlFiltersWithMultipleValues.paymentStatus,
PaymentChargeStatusEnum
);
case OrderFilterKeys.channel: case OrderFilterKeys.channel:
return getMultipleValueQueryParam( return getMultipleValueQueryParam(
filter, filter,

View file

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

View file

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