Display error if no invoicing plugin is active (#1709)

* Add error message if no invoice plugin installed

* Fix types

* Update messages
This commit is contained in:
Dominik Żegleń 2021-12-23 13:42:10 +01:00 committed by GitHub
parent c6e6aeff50
commit ff14720e23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 84 additions and 59 deletions

View file

@ -5180,12 +5180,20 @@
"src_dot_orders_dot_views_dot_OrderDetails_dot_4085755992": {
"string": "Invoice email sent"
},
"src_dot_orders_dot_views_dot_OrderDetails_dot_4207717971": {
"context": "snackbar title",
"string": "Could not generate invoice"
},
"src_dot_orders_dot_views_dot_OrderDetails_dot_55607988": {
"string": "Invoice is Generating"
},
"src_dot_orders_dot_views_dot_OrderDetails_dot_617145655": {
"string": "Shipping method successfully updated"
},
"src_dot_orders_dot_views_dot_OrderDetails_dot_811176136": {
"context": "error message",
"string": "No invoice plugin installed"
},
"src_dot_orders_dot_views_dot_OrderDetails_dot_927945225": {
"string": "Fulfillment successfully cancelled"
},

View file

@ -464,8 +464,6 @@ type AssignedVariantAttribute {
type Attribute implements Node & ObjectWithMetadata {
id: ID!
productTypes(before: String, after: String, first: Int, last: Int): ProductTypeCountableConnection!
productVariantTypes(before: String, after: String, first: Int, last: Int): ProductTypeCountableConnection!
privateMetadata: [MetadataItem]!
metadata: [MetadataItem]!
inputType: AttributeInputTypeEnum
@ -483,6 +481,8 @@ type Attribute implements Node & ObjectWithMetadata {
translation(languageCode: LanguageCodeEnum!): AttributeTranslation
storefrontSearchPosition: Int!
withChoices: Boolean!
productTypes(before: String, after: String, first: Int, last: Int): ProductTypeCountableConnection!
productVariantTypes(before: String, after: String, first: Int, last: Int): ProductTypeCountableConnection!
}
type AttributeBulkDelete {
@ -2611,6 +2611,7 @@ enum InvoiceErrorCode {
NUMBER_NOT_SET
NOT_FOUND
INVALID_STATUS
NO_INVOICE_PLUGIN
}
type InvoiceRequest {
@ -4378,6 +4379,7 @@ input OrderFilterInput {
channels: [ID]
isClickAndCollect: Boolean
isPreorder: Boolean
ids: [ID]
}
type OrderFulfill {
@ -5899,7 +5901,7 @@ input PublishableChannelListingInput {
type Query {
webhook(id: ID!): Webhook
webhookEvents: [WebhookEvent]
webhookEvents: [WebhookEvent] @deprecated(reason: "This field will be removed in Saleor 4.0. Use `WebhookEventTypeAsyncEnum` and `WebhookEventTypeSyncEnum` to get available event types.")
webhookSamplePayload(eventType: WebhookSampleEventTypeEnum!): JSONString
warehouse(id: ID!): Warehouse
warehouses(filter: WarehouseFilterInput, sortBy: WarehouseSortingInput, before: String, after: String, first: Int, last: Int): WarehouseCountableConnection
@ -7148,7 +7150,6 @@ type Warehouse implements Node & ObjectWithMetadata {
id: ID!
name: String!
slug: String!
shippingZones(before: String, after: String, first: Int, last: Int): ShippingZoneCountableConnection!
address: Address!
email: String!
isPrivate: Boolean!
@ -7156,6 +7157,7 @@ type Warehouse implements Node & ObjectWithMetadata {
metadata: [MetadataItem]!
companyName: String! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `Address.companyName` instead.")
clickAndCollectOption: WarehouseClickAndCollectOptionEnum!
shippingZones(before: String, after: String, first: Int, last: Int): ShippingZoneCountableConnection!
}
enum WarehouseClickAndCollectOptionEnum {
@ -7275,8 +7277,8 @@ input WebhookCreateInput {
name: String
targetUrl: String
events: [WebhookEventTypeEnum]
asyncEvents: [WebhookEventTypeAsync!]
syncEvents: [WebhookEventTypeSync!]
asyncEvents: [WebhookEventTypeAsyncEnum!]
syncEvents: [WebhookEventTypeSyncEnum!]
app: ID
isActive: Boolean
secretKey: String
@ -7308,16 +7310,16 @@ type WebhookEvent {
}
type WebhookEventAsync {
eventType: WebhookEventTypeAsync!
eventType: WebhookEventTypeAsyncEnum!
name: String!
}
type WebhookEventSync {
eventType: WebhookEventTypeSync!
eventType: WebhookEventTypeSyncEnum!
name: String!
}
enum WebhookEventTypeAsync {
enum WebhookEventTypeAsyncEnum {
ANY_EVENTS
ORDER_CREATED
ORDER_CONFIRMED
@ -7403,7 +7405,7 @@ enum WebhookEventTypeEnum {
TRANSLATION_UPDATED
}
enum WebhookEventTypeSync {
enum WebhookEventTypeSyncEnum {
PAYMENT_AUTHORIZE
PAYMENT_CAPTURE
PAYMENT_CONFIRM
@ -7448,14 +7450,6 @@ enum WebhookSampleEventTypeEnum {
PAGE_CREATED
PAGE_UPDATED
PAGE_DELETED
PAYMENT_AUTHORIZE
PAYMENT_CAPTURE
PAYMENT_CONFIRM
PAYMENT_LIST_GATEWAYS
PAYMENT_PROCESS
PAYMENT_REFUND
PAYMENT_VOID
SHIPPING_LIST_METHODS_FOR_CHECKOUT
TRANSLATION_CREATED
TRANSLATION_UPDATED
}
@ -7470,8 +7464,8 @@ input WebhookUpdateInput {
name: String
targetUrl: String
events: [WebhookEventTypeEnum]
asyncEvents: [WebhookEventTypeAsync!]
syncEvents: [WebhookEventTypeSync!]
asyncEvents: [WebhookEventTypeAsyncEnum!]
syncEvents: [WebhookEventTypeSyncEnum!]
app: ID
isActive: Boolean
secretKey: String

View file

@ -17,7 +17,11 @@ import {
import React from "react";
import { useIntl } from "react-intl";
import { JobStatusEnum, OrderStatus } from "../../../types/globalTypes";
import {
InvoiceErrorCode,
JobStatusEnum,
OrderStatus
} from "../../../types/globalTypes";
import OrderOperations from "../../containers/OrderOperations";
import { TypedOrderDetailsQuery } from "../../queries";
import {
@ -138,6 +142,23 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
onDraftCancel={orderMessages.handleDraftCancel}
onOrderMarkAsPaid={orderMessages.handleOrderMarkAsPaid}
onInvoiceRequest={(data: InvoiceRequest) => {
if (
data.invoiceRequest.errors.some(
err => err.code === InvoiceErrorCode.NO_INVOICE_PLUGIN
)
) {
notify({
title: intl.formatMessage({
defaultMessage: "Could not generate invoice",
description: "snackbar title"
}),
text: intl.formatMessage({
defaultMessage: "No invoice plugin installed",
description: "error message"
}),
status: "error"
});
}
if (
data.invoiceRequest.invoice.status === JobStatusEnum.SUCCESS
) {

View file

@ -525,6 +525,7 @@ export enum InvoiceErrorCode {
INVALID_STATUS = "INVALID_STATUS",
NOT_FOUND = "NOT_FOUND",
NOT_READY = "NOT_READY",
NO_INVOICE_PLUGIN = "NO_INVOICE_PLUGIN",
NUMBER_NOT_SET = "NUMBER_NOT_SET",
REQUIRED = "REQUIRED",
URL_NOT_SET = "URL_NOT_SET",
@ -1817,7 +1818,7 @@ export enum WebhookErrorCode {
UNIQUE = "UNIQUE",
}
export enum WebhookEventTypeAsync {
export enum WebhookEventTypeAsyncEnum {
ANY_EVENTS = "ANY_EVENTS",
CHECKOUT_CREATED = "CHECKOUT_CREATED",
CHECKOUT_UPDATED = "CHECKOUT_UPDATED",
@ -1903,7 +1904,7 @@ export enum WebhookEventTypeEnum {
TRANSLATION_UPDATED = "TRANSLATION_UPDATED",
}
export enum WebhookEventTypeSync {
export enum WebhookEventTypeSyncEnum {
PAYMENT_AUTHORIZE = "PAYMENT_AUTHORIZE",
PAYMENT_CAPTURE = "PAYMENT_CAPTURE",
PAYMENT_CONFIRM = "PAYMENT_CONFIRM",
@ -2375,6 +2376,7 @@ export interface OrderFilterInput {
channels?: (string | null)[] | null;
isClickAndCollect?: boolean | null;
isPreorder?: boolean | null;
ids?: (string | null)[] | null;
}
export interface OrderFulfillInput {
@ -3013,8 +3015,8 @@ export interface WebhookCreateInput {
name?: string | null;
targetUrl?: string | null;
events?: (WebhookEventTypeEnum | null)[] | null;
asyncEvents?: WebhookEventTypeAsync[] | null;
syncEvents?: WebhookEventTypeSync[] | null;
asyncEvents?: WebhookEventTypeAsyncEnum[] | null;
syncEvents?: WebhookEventTypeSyncEnum[] | null;
app?: string | null;
isActive?: boolean | null;
secretKey?: string | null;
@ -3024,8 +3026,8 @@ export interface WebhookUpdateInput {
name?: string | null;
targetUrl?: string | null;
events?: (WebhookEventTypeEnum | null)[] | null;
asyncEvents?: WebhookEventTypeAsync[] | null;
syncEvents?: WebhookEventTypeSync[] | null;
asyncEvents?: WebhookEventTypeAsyncEnum[] | null;
syncEvents?: WebhookEventTypeSyncEnum[] | null;
app?: string | null;
isActive?: boolean | null;
secretKey?: string | null;

View file

@ -8,8 +8,8 @@ import Savebar from "@saleor/components/Savebar";
import { WebhookErrorFragment } from "@saleor/fragments/types/WebhookErrorFragment";
import { Backlink } from "@saleor/macaw-ui";
import {
WebhookEventTypeAsync,
WebhookEventTypeSync
WebhookEventTypeAsyncEnum,
WebhookEventTypeSyncEnum
} from "@saleor/types/globalTypes";
import WebhookEvents from "@saleor/webhooks/components/WebhookEvents";
import WebhookInfo from "@saleor/webhooks/components/WebhookInfo";
@ -29,8 +29,8 @@ import { useIntl } from "react-intl";
import { getHeaderTitle } from "./messages";
export interface FormData {
syncEvents: WebhookEventTypeSync[];
asyncEvents: WebhookEventTypeAsync[];
syncEvents: WebhookEventTypeSyncEnum[];
asyncEvents: WebhookEventTypeAsyncEnum[];
isActive: boolean;
name: string;
secretKey: string | null;
@ -72,11 +72,11 @@ const WebhookDetailsPage: React.FC<WebhookDetailsPageProps> = ({
{({ data, hasChanged, submit, change }) => {
const syncEventsChoices = disabled
? []
: mapSyncEventsToChoices(Object.values(WebhookEventTypeSync));
: mapSyncEventsToChoices(Object.values(WebhookEventTypeSyncEnum));
const asyncEventsChoices = disabled
? []
: mapAsyncEventsToChoices(
Object.values(WebhookEventTypeAsync),
Object.values(WebhookEventTypeAsyncEnum),
data.asyncEvents
);

View file

@ -7,8 +7,8 @@ import MultiAutocompleteSelectField, {
} from "@saleor/components/MultiAutocompleteSelectField";
import { ChangeEvent } from "@saleor/hooks/useForm";
import {
WebhookEventTypeAsync,
WebhookEventTypeSync
WebhookEventTypeAsyncEnum,
WebhookEventTypeSyncEnum
} from "@saleor/types/globalTypes";
import {
mapAsyncEventsToChoices,
@ -22,8 +22,8 @@ import { messages } from "./messages";
interface WebhookEventsProps {
data: {
syncEvents: WebhookEventTypeSync[];
asyncEvents: WebhookEventTypeAsync[];
syncEvents: WebhookEventTypeSyncEnum[];
asyncEvents: WebhookEventTypeAsyncEnum[];
};
syncEventsChoices: MultiAutocompleteChoiceType[];
asyncEventsChoices: MultiAutocompleteChoiceType[];

View file

@ -1,7 +1,7 @@
import { ChangeEvent } from "@saleor/hooks/useForm";
import {
WebhookEventTypeAsync,
WebhookEventTypeSync
WebhookEventTypeAsyncEnum,
WebhookEventTypeSyncEnum
} from "@saleor/types/globalTypes";
import { toggle } from "@saleor/utils/lists";
@ -9,7 +9,7 @@ import { filterSelectedAsyncEvents } from "./utils";
export const createSyncEventsSelectHandler = (
change: (event: ChangeEvent, cb?: () => void) => void,
syncEvents: WebhookEventTypeSync[]
syncEvents: WebhookEventTypeSyncEnum[]
) => (event: ChangeEvent) => {
const events = toggle(event.target.value, syncEvents, (a, b) => a === b);
@ -23,7 +23,7 @@ export const createSyncEventsSelectHandler = (
export const createAsyncEventsSelectHandler = (
change: (event: ChangeEvent, cb?: () => void) => void,
asyncEvents: WebhookEventTypeAsync[]
asyncEvents: WebhookEventTypeAsyncEnum[]
) => (event: ChangeEvent) => {
const events = toggle(event.target.value, asyncEvents, (a, b) => a === b);
const filteredEvents = filterSelectedAsyncEvents(events);

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { WebhookEventTypeSync, WebhookEventTypeAsync } from "./../../types/globalTypes";
import { WebhookEventTypeSyncEnum, WebhookEventTypeAsyncEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL query operation: WebhookDetails
@ -17,12 +17,12 @@ export interface WebhookDetails_webhook_app {
export interface WebhookDetails_webhook_syncEvents {
__typename: "WebhookEventSync";
eventType: WebhookEventTypeSync;
eventType: WebhookEventTypeSyncEnum;
}
export interface WebhookDetails_webhook_asyncEvents {
__typename: "WebhookEventAsync";
eventType: WebhookEventTypeAsync;
eventType: WebhookEventTypeAsyncEnum;
}
export interface WebhookDetails_webhook {

View file

@ -1,8 +1,8 @@
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
import { WebhookFragment } from "@saleor/fragments/types/WebhookFragment";
import {
WebhookEventTypeAsync,
WebhookEventTypeSync
WebhookEventTypeAsyncEnum,
WebhookEventTypeSyncEnum
} from "@saleor/types/globalTypes";
export function isUnnamed(webhook: WebhookFragment): boolean {
@ -10,7 +10,7 @@ export function isUnnamed(webhook: WebhookFragment): boolean {
}
export function mapSyncEventsToChoices(
events: WebhookEventTypeSync[]
events: WebhookEventTypeSyncEnum[]
): MultiAutocompleteChoiceType[] {
return events.map(event => ({
label: event,
@ -19,26 +19,26 @@ export function mapSyncEventsToChoices(
}
export function mapAsyncEventsToChoices(
events: WebhookEventTypeAsync[],
selectedEvents: WebhookEventTypeAsync[]
events: WebhookEventTypeAsyncEnum[],
selectedEvents: WebhookEventTypeAsyncEnum[]
): MultiAutocompleteChoiceType[] {
const isAnyAsyncEventSelected = selectedEvents.includes(
WebhookEventTypeAsync.ANY_EVENTS
WebhookEventTypeAsyncEnum.ANY_EVENTS
);
return events.map(event => ({
label: event,
value: event,
disabled:
event !== WebhookEventTypeAsync.ANY_EVENTS && isAnyAsyncEventSelected
event !== WebhookEventTypeAsyncEnum.ANY_EVENTS && isAnyAsyncEventSelected
}));
}
export const filterSelectedAsyncEvents = (
asyncEvents: WebhookEventTypeAsync[]
asyncEvents: WebhookEventTypeAsyncEnum[]
) => {
const anyEvent = asyncEvents.find(
event => event === WebhookEventTypeAsync.ANY_EVENTS
event => event === WebhookEventTypeAsyncEnum.ANY_EVENTS
);
if (anyEvent) {
return [anyEvent];

View file

@ -4,7 +4,7 @@ import { WindowTitle } from "@saleor/components/WindowTitle";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import { commonMessages } from "@saleor/intl";
import { WebhookEventTypeAsync } from "@saleor/types/globalTypes";
import { WebhookEventTypeAsyncEnum } from "@saleor/types/globalTypes";
import React from "react";
import { useIntl } from "react-intl";
@ -46,9 +46,9 @@ export const WebhooksCreate: React.FC<WebhooksCreateProps> = ({ id }) => {
app: id,
syncEvents: data.syncEvents,
asyncEvents: data.asyncEvents.includes(
WebhookEventTypeAsync.ANY_EVENTS
WebhookEventTypeAsyncEnum.ANY_EVENTS
)
? [WebhookEventTypeAsync.ANY_EVENTS]
? [WebhookEventTypeAsyncEnum.ANY_EVENTS]
: data.asyncEvents,
isActive: data.isActive,
name: data.name,

View file

@ -4,7 +4,7 @@ import { WindowTitle } from "@saleor/components/WindowTitle";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import { commonMessages } from "@saleor/intl";
import { WebhookEventTypeAsync } from "@saleor/types/globalTypes";
import { WebhookEventTypeAsyncEnum } from "@saleor/types/globalTypes";
import { WebhookUpdate } from "@saleor/webhooks/types/WebhookUpdate";
import React from "react";
import { useIntl } from "react-intl";
@ -71,9 +71,9 @@ export const WebhooksDetails: React.FC<WebhooksDetailsProps> = ({ id }) => {
input: {
syncEvents: data.syncEvents,
asyncEvents: data.asyncEvents.includes(
WebhookEventTypeAsync.ANY_EVENTS
WebhookEventTypeAsyncEnum.ANY_EVENTS
)
? [WebhookEventTypeAsync.ANY_EVENTS]
? [WebhookEventTypeAsyncEnum.ANY_EVENTS]
: data.asyncEvents,
isActive: data.isActive,
name: data.name,