Queue invoice status check

This commit is contained in:
Dawid Tarasiuk 2020-06-26 19:06:48 +02:00
parent 18603cd97a
commit c88572356f
7 changed files with 181 additions and 9 deletions

View file

@ -1,21 +1,21 @@
import { IMessageContext } from "@saleor/components/messages";
import useNotifier from "@saleor/hooks/useNotifier";
import { checkOrderInvoicesStatus } from "@saleor/orders/queries";
import ApolloClient from "apollo-client";
import React from "react";
import { useApolloClient } from "react-apollo";
import { IntlShape, useIntl } from "react-intl";
import BackgroundTasksContext from "./context";
import { handleTask, queueCustom } from "./tasks";
import { handleTask, queueCustom, queueInvoiceGenerate } from "./tasks";
import { QueuedTask, Task, TaskData, TaskStatus } from "./types";
export const backgroundTasksRefreshTime = 15 * 1000;
// TODO: Remove underscores when working on #575 or similar PR
export function useBackgroundTasks(
_apolloClient: ApolloClient<any>,
_notify: IMessageContext,
_intl: IntlShape
apolloClient: ApolloClient<any>,
notify: IMessageContext,
intl: IntlShape
) {
const idCounter = React.useRef(0);
const tasks = React.useRef<QueuedTask[]>([]);
@ -64,6 +64,23 @@ export function useBackgroundTasks(
case Task.CUSTOM:
queueCustom(idCounter.current, tasks, data);
break;
case Task.INVOICE_GENERATE:
queueInvoiceGenerate(
idCounter.current,
data.generateInvoice,
tasks,
() =>
apolloClient.query({
fetchPolicy: "network-only",
query: checkOrderInvoicesStatus,
variables: {
id: data.generateInvoice.orderId
}
}),
notify,
intl
);
break;
}
return idCounter.current;

View file

@ -1,4 +1,31 @@
import { QueuedTask, TaskData, TaskStatus } from "./types";
import { IMessageContext } from "@saleor/components/messages";
import { commonMessages } from "@saleor/intl";
import { CheckOrderInvoicesStatus } from "@saleor/orders/types/CheckOrderInvoicesStatus";
import { JobStatusEnum } from "@saleor/types/globalTypes";
import { ApolloQueryResult } from "apollo-client";
import { defineMessages, IntlShape } from "react-intl";
import {
InvoiceGenerateParams,
QueuedTask,
TaskData,
TaskStatus
} from "./types";
export const messages = defineMessages({
invoiceGenerateFinishedText: {
defaultMessage:
"Requested Invoice was generated. It was added to the top of the invoice list on this view. Enjoy!"
},
invoiceGenerateFinishedTitle: {
defaultMessage: "Invoice Generated",
description: "invoice generating has finished, header"
},
invoiceGenerationFailedTitle: {
defaultMessage: "Invoice Generation",
description: "dialog header, title"
}
});
export async function handleTask(task: QueuedTask): Promise<TaskStatus> {
let status = TaskStatus.PENDING;
@ -41,3 +68,46 @@ export function queueCustom(
}
];
}
export function queueInvoiceGenerate(
id: number,
generateInvoice: InvoiceGenerateParams,
tasks: React.MutableRefObject<QueuedTask[]>,
fetch: () => Promise<ApolloQueryResult<CheckOrderInvoicesStatus>>,
notify: IMessageContext,
intl: IntlShape
) {
if (!generateInvoice) {
throw new Error("generateInvoice is required when creating custom task");
}
tasks.current = [
...tasks.current,
{
handle: async () => {
const result = await fetch();
const status = result.data.order.invoices.find(
invoice => invoice.id === generateInvoice.invoiceId
).status;
return status === JobStatusEnum.SUCCESS
? TaskStatus.SUCCESS
: status === JobStatusEnum.PENDING
? TaskStatus.PENDING
: TaskStatus.FAILURE;
},
id,
onCompleted: data =>
data.status === TaskStatus.SUCCESS
? notify({
text: intl.formatMessage(messages.invoiceGenerateFinishedText),
title: intl.formatMessage(messages.invoiceGenerateFinishedTitle)
})
: notify({
text: intl.formatMessage(commonMessages.somethingWentWrong),
title: intl.formatMessage(messages.invoiceGenerationFailedTitle)
}),
onError: handleError,
status: TaskStatus.PENDING
}
];
}

View file

@ -1,11 +1,16 @@
export enum Task {
CUSTOM
CUSTOM,
INVOICE_GENERATE
}
export enum TaskStatus {
FAILURE,
PENDING,
SUCCESS
}
export interface InvoiceGenerateParams {
orderId: string;
invoiceId: string;
}
export interface OnCompletedTaskData {
status: TaskStatus;
@ -21,6 +26,7 @@ export interface QueuedTask {
}
export interface TaskData {
generateInvoice?: InvoiceGenerateParams;
id?: string;
handle?: () => Promise<TaskStatus>;
onCompleted?: OnCompletedTaskFn;

View file

@ -228,3 +228,15 @@ export const useOrderFulfillData = makeQuery<
OrderFulfillData,
OrderFulfillDataVariables
>(orderFulfillData);
export const checkOrderInvoicesStatus = gql`
${fragmentInvoice}
query CheckOrderInvoicesStatus($id: ID!) {
order(id: $id) {
id
invoices {
...InvoiceFragment
}
}
}
`;

View file

@ -0,0 +1,32 @@
/* tslint:disable */
/* eslint-disable */
// This file was automatically generated and should not be edited.
import { JobStatusEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL query operation: CheckOrderInvoicesStatus
// ====================================================
export interface CheckOrderInvoicesStatus_order_invoices {
__typename: "Invoice";
id: string;
number: string | null;
createdAt: any;
url: string | null;
status: JobStatusEnum;
}
export interface CheckOrderInvoicesStatus_order {
__typename: "Order";
id: string;
invoices: (CheckOrderInvoicesStatus_order_invoices | null)[] | null;
}
export interface CheckOrderInvoicesStatus {
order: CheckOrderInvoicesStatus_order | null;
}
export interface CheckOrderInvoicesStatusVariables {
id: string;
}

View file

@ -1,3 +1,4 @@
import { messages } from "@saleor/containers/BackgroundTasks/tasks";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
@ -45,6 +46,7 @@ interface OrderDetailsMessages {
handleShippingMethodUpdate: (data: OrderShippingMethodUpdate) => void;
handleUpdate: (data: OrderUpdate) => void;
handleInvoiceGeneratePending: (data: InvoiceRequest) => void;
handleInvoiceGenerateFinished: (data: InvoiceRequest) => void;
handleInvoiceSend: (data: InvoiceEmailSend) => void;
}) => React.ReactElement;
id: string;
@ -270,6 +272,16 @@ export const OrderDetailsMessages: React.FC<OrderDetailsMessages> = ({
closeModal();
}
};
const handleInvoiceGenerateFinished = (data: InvoiceRequest) => {
const errs = data.invoiceRequest?.errors;
if (errs.length === 0) {
pushMessage({
text: intl.formatMessage(messages.invoiceGenerateFinishedText),
title: intl.formatMessage(messages.invoiceGenerateFinishedTitle)
});
closeModal();
}
};
const handleInvoiceSend = (data: InvoiceEmailSend) => {
const errs = data.invoiceSendEmail?.errors;
if (errs.length === 0) {
@ -286,6 +298,7 @@ export const OrderDetailsMessages: React.FC<OrderDetailsMessages> = ({
handleDraftCancel,
handleDraftFinalize,
handleDraftUpdate,
handleInvoiceGenerateFinished,
handleInvoiceGeneratePending,
handleInvoiceSend,
handleNoteAdd,

View file

@ -1,10 +1,13 @@
import NotFoundPage from "@saleor/components/NotFoundPage";
import { WindowTitle } from "@saleor/components/WindowTitle";
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
import { Task } from "@saleor/containers/BackgroundTasks/types";
import useBackgroundTask from "@saleor/hooks/useBackgroundTask";
import useNavigator from "@saleor/hooks/useNavigator";
import useUser from "@saleor/hooks/useUser";
import OrderCannotCancelOrderDialog from "@saleor/orders/components/OrderCannotCancelOrderDialog";
import OrderInvoiceEmailSendDialog from "@saleor/orders/components/OrderInvoiceEmailSendDialog";
import { InvoiceRequest } from "@saleor/orders/types/InvoiceRequest";
import useCustomerSearch from "@saleor/searches/useCustomerSearch";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import { useWarehouseList } from "@saleor/warehouses/queries";
@ -18,7 +21,11 @@ import {
transformAddressToForm,
} from "../../../misc";
import { productUrl } from "../../../products/urls";
import { FulfillmentStatus, OrderStatus } from "../../../types/globalTypes";
import {
FulfillmentStatus,
JobStatusEnum,
OrderStatus,
} from "../../../types/globalTypes";
import OrderAddressEditDialog from "../../components/OrderAddressEditDialog";
import OrderCancelDialog from "../../components/OrderCancelDialog";
import OrderDetailsPage from "../../components/OrderDetailsPage";
@ -104,6 +111,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
first: 30,
},
});
const { queue } = useBackgroundTask();
const intl = useIntl();
const [openModal, closeModal] = createDialogActionHandlers<
@ -149,7 +157,21 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
onDraftFinalize={orderMessages.handleDraftFinalize}
onDraftCancel={orderMessages.handleDraftCancel}
onOrderMarkAsPaid={orderMessages.handleOrderMarkAsPaid}
onInvoiceRequest={orderMessages.handleInvoiceGeneratePending}
onInvoiceRequest={(data: InvoiceRequest) => {
if (
data.invoiceRequest.invoice.status === JobStatusEnum.SUCCESS
) {
orderMessages.handleInvoiceGenerateFinished(data);
} else {
orderMessages.handleInvoiceGeneratePending(data);
queue(Task.INVOICE_GENERATE, {
params: {
invoiceId: data.invoiceRequest.invoice.id,
orderId: id,
},
});
}
}}
onInvoiceSend={orderMessages.handleInvoiceSend}
>
{({