Queue invoice status check
This commit is contained in:
parent
18603cd97a
commit
c88572356f
7 changed files with 181 additions and 9 deletions
|
@ -1,21 +1,21 @@
|
||||||
import { IMessageContext } from "@saleor/components/messages";
|
import { IMessageContext } from "@saleor/components/messages";
|
||||||
import useNotifier from "@saleor/hooks/useNotifier";
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
|
import { checkOrderInvoicesStatus } from "@saleor/orders/queries";
|
||||||
import ApolloClient from "apollo-client";
|
import ApolloClient from "apollo-client";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useApolloClient } from "react-apollo";
|
import { useApolloClient } from "react-apollo";
|
||||||
import { IntlShape, useIntl } from "react-intl";
|
import { IntlShape, useIntl } from "react-intl";
|
||||||
|
|
||||||
import BackgroundTasksContext from "./context";
|
import BackgroundTasksContext from "./context";
|
||||||
import { handleTask, queueCustom } from "./tasks";
|
import { handleTask, queueCustom, queueInvoiceGenerate } from "./tasks";
|
||||||
import { QueuedTask, Task, TaskData, TaskStatus } from "./types";
|
import { QueuedTask, Task, TaskData, TaskStatus } from "./types";
|
||||||
|
|
||||||
export const backgroundTasksRefreshTime = 15 * 1000;
|
export const backgroundTasksRefreshTime = 15 * 1000;
|
||||||
|
|
||||||
// TODO: Remove underscores when working on #575 or similar PR
|
|
||||||
export function useBackgroundTasks(
|
export function useBackgroundTasks(
|
||||||
_apolloClient: ApolloClient<any>,
|
apolloClient: ApolloClient<any>,
|
||||||
_notify: IMessageContext,
|
notify: IMessageContext,
|
||||||
_intl: IntlShape
|
intl: IntlShape
|
||||||
) {
|
) {
|
||||||
const idCounter = React.useRef(0);
|
const idCounter = React.useRef(0);
|
||||||
const tasks = React.useRef<QueuedTask[]>([]);
|
const tasks = React.useRef<QueuedTask[]>([]);
|
||||||
|
@ -64,6 +64,23 @@ export function useBackgroundTasks(
|
||||||
case Task.CUSTOM:
|
case Task.CUSTOM:
|
||||||
queueCustom(idCounter.current, tasks, data);
|
queueCustom(idCounter.current, tasks, data);
|
||||||
break;
|
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;
|
return idCounter.current;
|
||||||
|
|
|
@ -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> {
|
export async function handleTask(task: QueuedTask): Promise<TaskStatus> {
|
||||||
let status = TaskStatus.PENDING;
|
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
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
export enum Task {
|
export enum Task {
|
||||||
CUSTOM
|
CUSTOM,
|
||||||
|
INVOICE_GENERATE
|
||||||
}
|
}
|
||||||
export enum TaskStatus {
|
export enum TaskStatus {
|
||||||
FAILURE,
|
FAILURE,
|
||||||
PENDING,
|
PENDING,
|
||||||
SUCCESS
|
SUCCESS
|
||||||
}
|
}
|
||||||
|
export interface InvoiceGenerateParams {
|
||||||
|
orderId: string;
|
||||||
|
invoiceId: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface OnCompletedTaskData {
|
export interface OnCompletedTaskData {
|
||||||
status: TaskStatus;
|
status: TaskStatus;
|
||||||
|
@ -21,6 +26,7 @@ export interface QueuedTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TaskData {
|
export interface TaskData {
|
||||||
|
generateInvoice?: InvoiceGenerateParams;
|
||||||
id?: string;
|
id?: string;
|
||||||
handle?: () => Promise<TaskStatus>;
|
handle?: () => Promise<TaskStatus>;
|
||||||
onCompleted?: OnCompletedTaskFn;
|
onCompleted?: OnCompletedTaskFn;
|
||||||
|
|
|
@ -228,3 +228,15 @@ export const useOrderFulfillData = makeQuery<
|
||||||
OrderFulfillData,
|
OrderFulfillData,
|
||||||
OrderFulfillDataVariables
|
OrderFulfillDataVariables
|
||||||
>(orderFulfillData);
|
>(orderFulfillData);
|
||||||
|
|
||||||
|
export const checkOrderInvoicesStatus = gql`
|
||||||
|
${fragmentInvoice}
|
||||||
|
query CheckOrderInvoicesStatus($id: ID!) {
|
||||||
|
order(id: $id) {
|
||||||
|
id
|
||||||
|
invoices {
|
||||||
|
...InvoiceFragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
32
src/orders/types/CheckOrderInvoicesStatus.ts
Normal file
32
src/orders/types/CheckOrderInvoicesStatus.ts
Normal 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;
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { messages } from "@saleor/containers/BackgroundTasks/tasks";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useNotifier from "@saleor/hooks/useNotifier";
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
|
@ -45,6 +46,7 @@ interface OrderDetailsMessages {
|
||||||
handleShippingMethodUpdate: (data: OrderShippingMethodUpdate) => void;
|
handleShippingMethodUpdate: (data: OrderShippingMethodUpdate) => void;
|
||||||
handleUpdate: (data: OrderUpdate) => void;
|
handleUpdate: (data: OrderUpdate) => void;
|
||||||
handleInvoiceGeneratePending: (data: InvoiceRequest) => void;
|
handleInvoiceGeneratePending: (data: InvoiceRequest) => void;
|
||||||
|
handleInvoiceGenerateFinished: (data: InvoiceRequest) => void;
|
||||||
handleInvoiceSend: (data: InvoiceEmailSend) => void;
|
handleInvoiceSend: (data: InvoiceEmailSend) => void;
|
||||||
}) => React.ReactElement;
|
}) => React.ReactElement;
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -270,6 +272,16 @@ export const OrderDetailsMessages: React.FC<OrderDetailsMessages> = ({
|
||||||
closeModal();
|
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 handleInvoiceSend = (data: InvoiceEmailSend) => {
|
||||||
const errs = data.invoiceSendEmail?.errors;
|
const errs = data.invoiceSendEmail?.errors;
|
||||||
if (errs.length === 0) {
|
if (errs.length === 0) {
|
||||||
|
@ -286,6 +298,7 @@ export const OrderDetailsMessages: React.FC<OrderDetailsMessages> = ({
|
||||||
handleDraftCancel,
|
handleDraftCancel,
|
||||||
handleDraftFinalize,
|
handleDraftFinalize,
|
||||||
handleDraftUpdate,
|
handleDraftUpdate,
|
||||||
|
handleInvoiceGenerateFinished,
|
||||||
handleInvoiceGeneratePending,
|
handleInvoiceGeneratePending,
|
||||||
handleInvoiceSend,
|
handleInvoiceSend,
|
||||||
handleNoteAdd,
|
handleNoteAdd,
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import NotFoundPage from "@saleor/components/NotFoundPage";
|
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||||
import { WindowTitle } from "@saleor/components/WindowTitle";
|
import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||||
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
|
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 useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useUser from "@saleor/hooks/useUser";
|
import useUser from "@saleor/hooks/useUser";
|
||||||
import OrderCannotCancelOrderDialog from "@saleor/orders/components/OrderCannotCancelOrderDialog";
|
import OrderCannotCancelOrderDialog from "@saleor/orders/components/OrderCannotCancelOrderDialog";
|
||||||
import OrderInvoiceEmailSendDialog from "@saleor/orders/components/OrderInvoiceEmailSendDialog";
|
import OrderInvoiceEmailSendDialog from "@saleor/orders/components/OrderInvoiceEmailSendDialog";
|
||||||
|
import { InvoiceRequest } from "@saleor/orders/types/InvoiceRequest";
|
||||||
import useCustomerSearch from "@saleor/searches/useCustomerSearch";
|
import useCustomerSearch from "@saleor/searches/useCustomerSearch";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
import { useWarehouseList } from "@saleor/warehouses/queries";
|
import { useWarehouseList } from "@saleor/warehouses/queries";
|
||||||
|
@ -18,7 +21,11 @@ import {
|
||||||
transformAddressToForm,
|
transformAddressToForm,
|
||||||
} from "../../../misc";
|
} from "../../../misc";
|
||||||
import { productUrl } from "../../../products/urls";
|
import { productUrl } from "../../../products/urls";
|
||||||
import { FulfillmentStatus, OrderStatus } from "../../../types/globalTypes";
|
import {
|
||||||
|
FulfillmentStatus,
|
||||||
|
JobStatusEnum,
|
||||||
|
OrderStatus,
|
||||||
|
} from "../../../types/globalTypes";
|
||||||
import OrderAddressEditDialog from "../../components/OrderAddressEditDialog";
|
import OrderAddressEditDialog from "../../components/OrderAddressEditDialog";
|
||||||
import OrderCancelDialog from "../../components/OrderCancelDialog";
|
import OrderCancelDialog from "../../components/OrderCancelDialog";
|
||||||
import OrderDetailsPage from "../../components/OrderDetailsPage";
|
import OrderDetailsPage from "../../components/OrderDetailsPage";
|
||||||
|
@ -104,6 +111,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
|
||||||
first: 30,
|
first: 30,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const { queue } = useBackgroundTask();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const [openModal, closeModal] = createDialogActionHandlers<
|
const [openModal, closeModal] = createDialogActionHandlers<
|
||||||
|
@ -149,7 +157,21 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
|
||||||
onDraftFinalize={orderMessages.handleDraftFinalize}
|
onDraftFinalize={orderMessages.handleDraftFinalize}
|
||||||
onDraftCancel={orderMessages.handleDraftCancel}
|
onDraftCancel={orderMessages.handleDraftCancel}
|
||||||
onOrderMarkAsPaid={orderMessages.handleOrderMarkAsPaid}
|
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}
|
onInvoiceSend={orderMessages.handleInvoiceSend}
|
||||||
>
|
>
|
||||||
{({
|
{({
|
||||||
|
|
Loading…
Reference in a new issue