feat: ✨ add order-cancelled avatax adapter
This commit is contained in:
parent
0013af2f6d
commit
d458452573
10 changed files with 82 additions and 15 deletions
|
@ -1,9 +1,6 @@
|
||||||
fragment OrderCancelledSubscription on Order {
|
fragment OrderCancelledSubscription on Order {
|
||||||
id
|
id
|
||||||
privateMetadata {
|
externalId: metafield(key: "externalId")
|
||||||
key
|
|
||||||
value
|
|
||||||
}
|
|
||||||
channel {
|
channel {
|
||||||
id
|
id
|
||||||
slug
|
slug
|
||||||
|
|
|
@ -53,6 +53,11 @@ export type ValidateAddressArgs = {
|
||||||
address: AvataxAddress;
|
address: AvataxAddress;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type VoidTransactionArgs = {
|
||||||
|
transactionCode: string;
|
||||||
|
companyCode: string;
|
||||||
|
};
|
||||||
|
|
||||||
export class AvataxClient {
|
export class AvataxClient {
|
||||||
private client: Avatax;
|
private client: Avatax;
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
|
@ -73,6 +78,16 @@ export class AvataxClient {
|
||||||
return this.client.commitTransaction(args);
|
return this.client.commitTransaction(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async voidTransaction({
|
||||||
|
transactionCode,
|
||||||
|
companyCode,
|
||||||
|
}: {
|
||||||
|
transactionCode: string;
|
||||||
|
companyCode: string;
|
||||||
|
}) {
|
||||||
|
return this.client.voidTransaction({ transactionCode, companyCode });
|
||||||
|
}
|
||||||
|
|
||||||
async validateAddress({ address }: ValidateAddressArgs) {
|
async validateAddress({ address }: ValidateAddressArgs) {
|
||||||
return this.client.resolveAddress(address);
|
return this.client.resolveAddress(address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@ import { AvataxConfig, defaultAvataxConfig } from "./avatax-connection-schema";
|
||||||
import { AvataxCalculateTaxesAdapter } from "./calculate-taxes/avatax-calculate-taxes-adapter";
|
import { AvataxCalculateTaxesAdapter } from "./calculate-taxes/avatax-calculate-taxes-adapter";
|
||||||
import { AvataxOrderCreatedAdapter } from "./order-created/avatax-order-created-adapter";
|
import { AvataxOrderCreatedAdapter } from "./order-created/avatax-order-created-adapter";
|
||||||
import { AvataxOrderFulfilledAdapter } from "./order-fulfilled/avatax-order-fulfilled-adapter";
|
import { AvataxOrderFulfilledAdapter } from "./order-fulfilled/avatax-order-fulfilled-adapter";
|
||||||
|
import { AvataxOrderCancelledAdapter } from "./order-cancelled/avatax-order-cancelled-adapter";
|
||||||
|
import { OrderCancelledPayload } from "../../pages/api/webhooks/order-cancelled";
|
||||||
|
|
||||||
export class AvataxWebhookService implements ProviderWebhookService {
|
export class AvataxWebhookService implements ProviderWebhookService {
|
||||||
config = defaultAvataxConfig;
|
config = defaultAvataxConfig;
|
||||||
|
@ -52,9 +54,10 @@ export class AvataxWebhookService implements ProviderWebhookService {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
async cancelOrder(payload: OrderCancelledEventSubscriptionFragment) {
|
async cancelOrder(payload: OrderCancelledPayload) {
|
||||||
// todo: implement
|
|
||||||
this.logger.debug("cancelOrder", payload);
|
this.logger.debug("cancelOrder", payload);
|
||||||
return { ok: true };
|
const adapter = new AvataxOrderCancelledAdapter(this.config);
|
||||||
|
|
||||||
|
await adapter.send(payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { Logger, createLogger } from "../../../lib/logger";
|
||||||
|
import { OrderCancelledPayload } from "../../../pages/api/webhooks/order-cancelled";
|
||||||
|
import { WebhookAdapter } from "../../taxes/tax-webhook-adapter";
|
||||||
|
import { AvataxClient, VoidTransactionArgs } from "../avatax-client";
|
||||||
|
import { AvataxConfig } from "../avatax-connection-schema";
|
||||||
|
import { AvataxOrderCancelledPayloadTransformer } from "./avatax-order-cancelled-payload-transformer";
|
||||||
|
|
||||||
|
export type AvataxOrderCancelledTarget = VoidTransactionArgs;
|
||||||
|
|
||||||
|
export class AvataxOrderCancelledAdapter implements WebhookAdapter<OrderCancelledPayload, void> {
|
||||||
|
private logger: Logger;
|
||||||
|
|
||||||
|
constructor(private readonly config: AvataxConfig) {
|
||||||
|
this.logger = createLogger({ name: "AvataxOrderCancelledAdapter" });
|
||||||
|
}
|
||||||
|
|
||||||
|
async send(payload: OrderCancelledPayload) {
|
||||||
|
this.logger.debug("Transforming the Saleor payload for cancelling transaction with Avatax...");
|
||||||
|
|
||||||
|
const payloadTransformer = new AvataxOrderCancelledPayloadTransformer(this.config);
|
||||||
|
const target = payloadTransformer.transform({ ...payload });
|
||||||
|
|
||||||
|
this.logger.debug("Calling Avatax commitTransaction with transformed payload...");
|
||||||
|
|
||||||
|
const client = new AvataxClient(this.config);
|
||||||
|
|
||||||
|
await client.voidTransaction(target);
|
||||||
|
|
||||||
|
this.logger.debug("Avatax commitTransaction succesfully responded");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { OrderCancelledPayload } from "../../../pages/api/webhooks/order-cancelled";
|
||||||
|
import { taxProviderUtils } from "../../taxes/tax-provider-utils";
|
||||||
|
import { AvataxConfig } from "../avatax-connection-schema";
|
||||||
|
import { AvataxOrderCancelledTarget } from "./avatax-order-cancelled-adapter";
|
||||||
|
|
||||||
|
export class AvataxOrderCancelledPayloadTransformer {
|
||||||
|
constructor(private readonly config: AvataxConfig) {}
|
||||||
|
|
||||||
|
transform({ order }: OrderCancelledPayload): AvataxOrderCancelledTarget {
|
||||||
|
if (!order) {
|
||||||
|
throw new Error("Order is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
const transactionCode = taxProviderUtils.resolveOptionalOrThrow(order.externalId);
|
||||||
|
|
||||||
|
return {
|
||||||
|
transactionCode,
|
||||||
|
companyCode: this.config.companyCode ?? "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ import { AvataxWebhookService } from "../avatax/avatax-webhook.service";
|
||||||
import { ProviderConnection } from "../provider-connections/provider-connections";
|
import { ProviderConnection } from "../provider-connections/provider-connections";
|
||||||
import { TaxJarWebhookService } from "../taxjar/taxjar-webhook.service";
|
import { TaxJarWebhookService } from "../taxjar/taxjar-webhook.service";
|
||||||
import { ProviderWebhookService } from "./tax-provider-webhook";
|
import { ProviderWebhookService } from "./tax-provider-webhook";
|
||||||
|
import { OrderCancelledPayload } from "../../pages/api/webhooks/order-cancelled";
|
||||||
|
|
||||||
// todo: refactor to a factory
|
// todo: refactor to a factory
|
||||||
class ActiveTaxProviderService implements ProviderWebhookService {
|
class ActiveTaxProviderService implements ProviderWebhookService {
|
||||||
|
@ -57,8 +58,8 @@ class ActiveTaxProviderService implements ProviderWebhookService {
|
||||||
return this.client.fulfillOrder(payload);
|
return this.client.fulfillOrder(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
async cancelOrder(payload: OrderCancelledEventSubscriptionFragment) {
|
async cancelOrder(payload: OrderCancelledPayload) {
|
||||||
return this.client.cancelOrder(payload);
|
this.client.cancelOrder(payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
* If it ever happens, we have nothing to fall back to, so we throw an error.
|
* If it ever happens, we have nothing to fall back to, so we throw an error.
|
||||||
* Should only be used for values that are required for further calculation.
|
* Should only be used for values that are required for further calculation.
|
||||||
*/
|
*/
|
||||||
function resolveOptionalOrThrow<T>(value: T | undefined, error?: Error): T {
|
function resolveOptionalOrThrow<T>(value: T | undefined | null, error?: Error): T {
|
||||||
if (value === undefined) {
|
if (value === undefined || value === null) {
|
||||||
throw error
|
throw error
|
||||||
? error
|
? error
|
||||||
: new Error("Could not resolve data. Value needed for further calculation is undefined.");
|
: new Error("Could not resolve data. Value needed for further calculation is undefined.");
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { SyncWebhookResponsesMap } from "@saleor/app-sdk/handlers/next";
|
import { SyncWebhookResponsesMap } from "@saleor/app-sdk/handlers/next";
|
||||||
import {
|
import {
|
||||||
OrderCancelledEventSubscriptionFragment,
|
|
||||||
OrderCreatedSubscriptionFragment,
|
OrderCreatedSubscriptionFragment,
|
||||||
OrderFulfilledSubscriptionFragment,
|
OrderFulfilledSubscriptionFragment,
|
||||||
TaxBaseFragment,
|
TaxBaseFragment,
|
||||||
} from "../../../generated/graphql";
|
} from "../../../generated/graphql";
|
||||||
|
import { OrderCancelledPayload } from "../../pages/api/webhooks/order-cancelled";
|
||||||
|
|
||||||
export type CalculateTaxesResponse = SyncWebhookResponsesMap["ORDER_CALCULATE_TAXES"];
|
export type CalculateTaxesResponse = SyncWebhookResponsesMap["ORDER_CALCULATE_TAXES"];
|
||||||
|
|
||||||
|
@ -14,5 +14,5 @@ export interface ProviderWebhookService {
|
||||||
calculateTaxes: (payload: TaxBaseFragment) => Promise<CalculateTaxesResponse>;
|
calculateTaxes: (payload: TaxBaseFragment) => Promise<CalculateTaxesResponse>;
|
||||||
createOrder: (payload: OrderCreatedSubscriptionFragment) => Promise<CreateOrderResponse>;
|
createOrder: (payload: OrderCreatedSubscriptionFragment) => Promise<CreateOrderResponse>;
|
||||||
fulfillOrder: (payload: OrderFulfilledSubscriptionFragment) => Promise<{ ok: boolean }>;
|
fulfillOrder: (payload: OrderFulfilledSubscriptionFragment) => Promise<{ ok: boolean }>;
|
||||||
cancelOrder: (payload: OrderCancelledEventSubscriptionFragment) => Promise<any>;
|
cancelOrder: (payload: OrderCancelledPayload) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,5 @@ export class TaxJarWebhookService implements ProviderWebhookService {
|
||||||
async cancelOrder(payload: OrderCancelledEventSubscriptionFragment) {
|
async cancelOrder(payload: OrderCancelledEventSubscriptionFragment) {
|
||||||
// todo: implement
|
// todo: implement
|
||||||
this.logger.debug("cancelOrder", payload);
|
this.logger.debug("cancelOrder", payload);
|
||||||
return { ok: true };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ export const config = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
type OrderCancelledPayload = Extract<
|
export type OrderCancelledPayload = Extract<
|
||||||
OrderCancelledEventSubscriptionFragment,
|
OrderCancelledEventSubscriptionFragment,
|
||||||
{ __typename: "OrderCancelled" }
|
{ __typename: "OrderCancelled" }
|
||||||
>;
|
>;
|
||||||
|
|
Loading…
Reference in a new issue