refactor: 🚚 order_created -> order_confirmed
This commit is contained in:
parent
7cb991abaf
commit
32a7a91294
35 changed files with 177 additions and 176 deletions
|
@ -20,7 +20,7 @@ fragment OrderLine on OrderLine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment OrderCreatedSubscription on Order {
|
fragment OrderConfirmedSubscription on Order {
|
||||||
id
|
id
|
||||||
user {
|
user {
|
||||||
id
|
id
|
||||||
|
@ -66,11 +66,11 @@ fragment OrderCreatedSubscription on Order {
|
||||||
}
|
}
|
||||||
avataxEntityCode: metafield(key: "avataxEntityCode")
|
avataxEntityCode: metafield(key: "avataxEntityCode")
|
||||||
}
|
}
|
||||||
fragment OrderCreatedEventSubscription on Event {
|
fragment OrderConfirmedEventSubscription on Event {
|
||||||
__typename
|
__typename
|
||||||
... on OrderCreated {
|
... on OrderConfirmed {
|
||||||
order {
|
order {
|
||||||
...OrderCreatedSubscription
|
...OrderConfirmedSubscription
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
recipient {
|
recipient {
|
||||||
|
@ -80,8 +80,8 @@ fragment OrderCreatedEventSubscription on Event {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
subscription OrderCreatedSubscription {
|
subscription OrderConfirmedSubscription {
|
||||||
event {
|
event {
|
||||||
...OrderCreatedEventSubscription
|
...OrderConfirmedEventSubscription
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { OrderCreatedSubscriptionFragment, OrderStatus } from "../generated/graphql";
|
import { OrderConfirmedSubscriptionFragment, OrderStatus } from "../generated/graphql";
|
||||||
|
|
||||||
export const defaultOrder: OrderCreatedSubscriptionFragment = {
|
export const defaultOrder: OrderConfirmedSubscriptionFragment = {
|
||||||
id: "T3JkZXI6ZTUzZTBlM2MtMjk5Yi00OWYxLWIyZDItY2Q4NWExYTgxYjY2",
|
id: "T3JkZXI6ZTUzZTBlM2MtMjk5Yi00OWYxLWIyZDItY2Q4NWExYTgxYjY2",
|
||||||
user: {
|
user: {
|
||||||
id: "VXNlcjoyMDg0NTEwNDEw",
|
id: "VXNlcjoyMDg0NTEwNDEw",
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
import { AuthData } from "@saleor/app-sdk/APL";
|
import { AuthData } from "@saleor/app-sdk/APL";
|
||||||
import {
|
import {
|
||||||
OrderCancelledEventSubscriptionFragment,
|
OrderConfirmedSubscriptionFragment,
|
||||||
OrderCreatedSubscriptionFragment,
|
|
||||||
OrderFulfilledSubscriptionFragment,
|
OrderFulfilledSubscriptionFragment,
|
||||||
TaxBaseFragment,
|
TaxBaseFragment,
|
||||||
} from "../../../generated/graphql";
|
} from "../../../generated/graphql";
|
||||||
import { Logger, createLogger } from "../../lib/logger";
|
import { Logger, createLogger } from "../../lib/logger";
|
||||||
import { ProviderWebhookService } from "../taxes/tax-provider-webhook";
|
import { OrderCancelledPayload } from "../../pages/api/webhooks/order-cancelled";
|
||||||
|
import { CreateOrderResponse, ProviderWebhookService } from "../taxes/tax-provider-webhook";
|
||||||
import { AvataxClient } from "./avatax-client";
|
import { AvataxClient } from "./avatax-client";
|
||||||
import { AvataxConfig, defaultAvataxConfig } from "./avatax-connection-schema";
|
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 { AvataxOrderFulfilledAdapter } from "./order-fulfilled/avatax-order-fulfilled-adapter";
|
|
||||||
import { AvataxOrderCancelledAdapter } from "./order-cancelled/avatax-order-cancelled-adapter";
|
import { AvataxOrderCancelledAdapter } from "./order-cancelled/avatax-order-cancelled-adapter";
|
||||||
import { OrderCancelledPayload } from "../../pages/api/webhooks/order-cancelled";
|
import { AvataxOrderConfirmedAdapter } from "./order-confirmed/avatax-order-confirmed-adapter";
|
||||||
|
import { AvataxOrderFulfilledAdapter } from "./order-fulfilled/avatax-order-fulfilled-adapter";
|
||||||
|
|
||||||
export class AvataxWebhookService implements ProviderWebhookService {
|
export class AvataxWebhookService implements ProviderWebhookService {
|
||||||
config = defaultAvataxConfig;
|
config = defaultAvataxConfig;
|
||||||
|
@ -38,8 +37,8 @@ export class AvataxWebhookService implements ProviderWebhookService {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
async createOrder(order: OrderCreatedSubscriptionFragment) {
|
async confirmOrder(order: OrderConfirmedSubscriptionFragment) {
|
||||||
const adapter = new AvataxOrderCreatedAdapter(this.config, this.authData);
|
const adapter = new AvataxOrderConfirmedAdapter(this.config, this.authData);
|
||||||
|
|
||||||
const response = await adapter.send({ order });
|
const response = await adapter.send({ order });
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, it } from "vitest";
|
import { describe, it } from "vitest";
|
||||||
|
|
||||||
describe("AvataxOrderCreatedAdapter", () => {
|
describe("AvataxOrderConfirmedAdapter", () => {
|
||||||
// ? how to mock internal call to avatax?
|
// ? how to mock internal call to avatax?
|
||||||
it.todo("calls avatax client", () => {});
|
it.todo("calls avatax client", () => {});
|
||||||
});
|
});
|
|
@ -1,32 +1,31 @@
|
||||||
import { AuthData } from "@saleor/app-sdk/APL";
|
import { AuthData } from "@saleor/app-sdk/APL";
|
||||||
import { OrderCreatedSubscriptionFragment } from "../../../../generated/graphql";
|
import { OrderConfirmedSubscriptionFragment } from "../../../../generated/graphql";
|
||||||
import { Logger, createLogger } from "../../../lib/logger";
|
import { Logger, createLogger } from "../../../lib/logger";
|
||||||
import { CreateOrderResponse } from "../../taxes/tax-provider-webhook";
|
import { CreateOrderResponse } from "../../taxes/tax-provider-webhook";
|
||||||
import { WebhookAdapter } from "../../taxes/tax-webhook-adapter";
|
import { WebhookAdapter } from "../../taxes/tax-webhook-adapter";
|
||||||
import { AvataxClient } from "../avatax-client";
|
import { AvataxClient } from "../avatax-client";
|
||||||
import { AvataxConfig } from "../avatax-connection-schema";
|
import { AvataxConfig } from "../avatax-connection-schema";
|
||||||
import { AvataxOrderCreatedPayloadTransformer } from "./avatax-order-created-payload-transformer";
|
import { AvataxOrderConfirmedPayloadService } from "./avatax-order-confirmed-payload.service";
|
||||||
import { AvataxOrderCreatedPayloadService } from "./avatax-order-created-payload.service";
|
import { AvataxOrderConfirmedResponseTransformer } from "./avatax-order-confirmed-response-transformer";
|
||||||
import { AvataxOrderCreatedResponseTransformer } from "./avatax-order-created-response-transformer";
|
|
||||||
|
|
||||||
type AvataxOrderCreatedPayload = {
|
type AvataxOrderConfirmedPayload = {
|
||||||
order: OrderCreatedSubscriptionFragment;
|
order: OrderConfirmedSubscriptionFragment;
|
||||||
};
|
};
|
||||||
type AvataxOrderCreatedResponse = CreateOrderResponse;
|
type AvataxOrderConfirmedResponse = CreateOrderResponse;
|
||||||
|
|
||||||
export class AvataxOrderCreatedAdapter
|
export class AvataxOrderConfirmedAdapter
|
||||||
implements WebhookAdapter<AvataxOrderCreatedPayload, AvataxOrderCreatedResponse>
|
implements WebhookAdapter<AvataxOrderConfirmedPayload, AvataxOrderConfirmedResponse>
|
||||||
{
|
{
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
|
|
||||||
constructor(private readonly config: AvataxConfig, private authData: AuthData) {
|
constructor(private readonly config: AvataxConfig, private authData: AuthData) {
|
||||||
this.logger = createLogger({ name: "AvataxOrderCreatedAdapter" });
|
this.logger = createLogger({ name: "AvataxOrderConfirmedAdapter" });
|
||||||
}
|
}
|
||||||
|
|
||||||
async send(payload: AvataxOrderCreatedPayload): Promise<AvataxOrderCreatedResponse> {
|
async send(payload: AvataxOrderConfirmedPayload): Promise<AvataxOrderConfirmedResponse> {
|
||||||
this.logger.debug("Transforming the Saleor payload for creating order with Avatax...");
|
this.logger.debug("Transforming the Saleor payload for creating order with Avatax...");
|
||||||
|
|
||||||
const payloadService = new AvataxOrderCreatedPayloadService(this.authData);
|
const payloadService = new AvataxOrderConfirmedPayloadService(this.authData);
|
||||||
const target = await payloadService.getPayload(payload.order, this.config);
|
const target = await payloadService.getPayload(payload.order, this.config);
|
||||||
|
|
||||||
this.logger.debug("Calling Avatax createTransaction with transformed payload...");
|
this.logger.debug("Calling Avatax createTransaction with transformed payload...");
|
||||||
|
@ -36,7 +35,7 @@ export class AvataxOrderCreatedAdapter
|
||||||
|
|
||||||
this.logger.debug("Avatax createTransaction successfully responded");
|
this.logger.debug("Avatax createTransaction successfully responded");
|
||||||
|
|
||||||
const responseTransformer = new AvataxOrderCreatedResponseTransformer();
|
const responseTransformer = new AvataxOrderConfirmedResponseTransformer();
|
||||||
const transformedResponse = responseTransformer.transform(response);
|
const transformedResponse = responseTransformer.transform(response);
|
||||||
|
|
||||||
this.logger.debug("Transformed Avatax createTransaction response");
|
this.logger.debug("Transformed Avatax createTransaction response");
|
|
@ -1,7 +1,7 @@
|
||||||
import { TransactionModel } from "avatax/lib/models/TransactionModel";
|
import { TransactionModel } from "avatax/lib/models/TransactionModel";
|
||||||
import { OrderCreatedSubscriptionFragment } from "../../../../generated/graphql";
|
import { OrderConfirmedSubscriptionFragment } from "../../../../generated/graphql";
|
||||||
import { ChannelConfig } from "../../channel-configuration/channel-config";
|
import { ChannelConfig } from "../../channel-configuration/channel-config";
|
||||||
import { orderCreatedTransactionMock } from "./avatax-order-created-response-transaction-mock";
|
import { orderConfirmedTransactionMock } from "./avatax-order-confirmed-response-transaction-mock";
|
||||||
import { AvataxConfig } from "../avatax-connection-schema";
|
import { AvataxConfig } from "../avatax-connection-schema";
|
||||||
import { defaultOrder } from "../../../mocks";
|
import { defaultOrder } from "../../../mocks";
|
||||||
import { AvataxConfigMockGenerator } from "../avatax-config-mock-generator";
|
import { AvataxConfigMockGenerator } from "../avatax-config-mock-generator";
|
||||||
|
@ -14,23 +14,23 @@ const defaultChannelConfig: ChannelConfig = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultOrderCreatedResponse: TransactionModel = orderCreatedTransactionMock;
|
const defaultOrderConfirmedResponse: TransactionModel = orderConfirmedTransactionMock;
|
||||||
|
|
||||||
const testingScenariosMap = {
|
const testingScenariosMap = {
|
||||||
default: {
|
default: {
|
||||||
order: defaultOrder,
|
order: defaultOrder,
|
||||||
channelConfig: defaultChannelConfig,
|
channelConfig: defaultChannelConfig,
|
||||||
response: defaultOrderCreatedResponse,
|
response: defaultOrderConfirmedResponse,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
type TestingScenario = keyof typeof testingScenariosMap;
|
type TestingScenario = keyof typeof testingScenariosMap;
|
||||||
|
|
||||||
export class AvataxOrderCreatedMockGenerator {
|
export class AvataxOrderConfirmedMockGenerator {
|
||||||
constructor(private scenario: TestingScenario = "default") {}
|
constructor(private scenario: TestingScenario = "default") {}
|
||||||
generateOrder = (
|
generateOrder = (
|
||||||
overrides: Partial<OrderCreatedSubscriptionFragment> = {}
|
overrides: Partial<OrderConfirmedSubscriptionFragment> = {}
|
||||||
): OrderCreatedSubscriptionFragment =>
|
): OrderConfirmedSubscriptionFragment =>
|
||||||
structuredClone({
|
structuredClone({
|
||||||
...testingScenariosMap[this.scenario].order,
|
...testingScenariosMap[this.scenario].order,
|
||||||
...overrides,
|
...overrides,
|
|
@ -1,16 +1,16 @@
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { AvataxOrderCreatedPayloadLinesTransformer } from "./avatax-order-created-payload-lines-transformer";
|
import { AvataxOrderConfirmedPayloadLinesTransformer } from "./avatax-order-confirmed-payload-lines-transformer";
|
||||||
import { avataxConfigMock } from "./avatax-order-created-payload-transformer.test";
|
import { avataxConfigMock } from "./avatax-order-confirmed-payload-transformer.test";
|
||||||
import { AvataxTaxCodeMatches } from "../tax-code/avatax-tax-code-match-repository";
|
import { AvataxTaxCodeMatches } from "../tax-code/avatax-tax-code-match-repository";
|
||||||
import { AvataxOrderCreatedMockGenerator } from "./avatax-order-created-mock-generator";
|
import { AvataxOrderConfirmedMockGenerator } from "./avatax-order-confirmed-mock-generator";
|
||||||
|
|
||||||
const linesTransformer = new AvataxOrderCreatedPayloadLinesTransformer();
|
const linesTransformer = new AvataxOrderConfirmedPayloadLinesTransformer();
|
||||||
const mockGenerator = new AvataxOrderCreatedMockGenerator();
|
const mockGenerator = new AvataxOrderConfirmedMockGenerator();
|
||||||
const orderMock = mockGenerator.generateOrder();
|
const orderMock = mockGenerator.generateOrder();
|
||||||
|
|
||||||
const matches: AvataxTaxCodeMatches = [];
|
const matches: AvataxTaxCodeMatches = [];
|
||||||
|
|
||||||
describe("AvataxOrderCreatedPayloadLinesTransformer", () => {
|
describe("AvataxOrderConfirmedPayloadLinesTransformer", () => {
|
||||||
const lines = linesTransformer.transform(orderMock, avataxConfigMock, matches);
|
const lines = linesTransformer.transform(orderMock, avataxConfigMock, matches);
|
||||||
|
|
||||||
it("returns the correct number of lines", () => {
|
it("returns the correct number of lines", () => {
|
|
@ -1,19 +1,19 @@
|
||||||
import { LineItemModel } from "avatax/lib/models/LineItemModel";
|
import { LineItemModel } from "avatax/lib/models/LineItemModel";
|
||||||
import { OrderCreatedSubscriptionFragment } from "../../../../generated/graphql";
|
import { OrderConfirmedSubscriptionFragment } from "../../../../generated/graphql";
|
||||||
import { numbers } from "../../taxes/numbers";
|
import { numbers } from "../../taxes/numbers";
|
||||||
import { AvataxConfig } from "../avatax-connection-schema";
|
import { AvataxConfig } from "../avatax-connection-schema";
|
||||||
import { AvataxTaxCodeMatches } from "../tax-code/avatax-tax-code-match-repository";
|
import { AvataxTaxCodeMatches } from "../tax-code/avatax-tax-code-match-repository";
|
||||||
import { SHIPPING_ITEM_CODE } from "./avatax-order-created-payload-transformer";
|
import { SHIPPING_ITEM_CODE } from "./avatax-order-confirmed-payload-transformer";
|
||||||
import { AvataxOrderCreatedTaxCodeMatcher } from "./avatax-order-created-tax-code-matcher";
|
import { AvataxOrderConfirmedTaxCodeMatcher } from "./avatax-order-confirmed-tax-code-matcher";
|
||||||
|
|
||||||
export class AvataxOrderCreatedPayloadLinesTransformer {
|
export class AvataxOrderConfirmedPayloadLinesTransformer {
|
||||||
transform(
|
transform(
|
||||||
order: OrderCreatedSubscriptionFragment,
|
order: OrderConfirmedSubscriptionFragment,
|
||||||
config: AvataxConfig,
|
config: AvataxConfig,
|
||||||
matches: AvataxTaxCodeMatches
|
matches: AvataxTaxCodeMatches
|
||||||
): LineItemModel[] {
|
): LineItemModel[] {
|
||||||
const productLines: LineItemModel[] = order.lines.map((line) => {
|
const productLines: LineItemModel[] = order.lines.map((line) => {
|
||||||
const matcher = new AvataxOrderCreatedTaxCodeMatcher();
|
const matcher = new AvataxOrderConfirmedTaxCodeMatcher();
|
||||||
const taxCode = matcher.match(line, matches);
|
const taxCode = matcher.match(line, matches);
|
||||||
|
|
||||||
return {
|
return {
|
|
@ -1,9 +1,9 @@
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { AvataxOrderCreatedMockGenerator } from "./avatax-order-created-mock-generator";
|
import { AvataxOrderConfirmedMockGenerator } from "./avatax-order-confirmed-mock-generator";
|
||||||
import { AvataxOrderCreatedPayloadTransformer } from "./avatax-order-created-payload-transformer";
|
import { AvataxOrderConfirmedPayloadTransformer } from "./avatax-order-confirmed-payload-transformer";
|
||||||
import { DocumentType } from "avatax/lib/enums/DocumentType";
|
import { DocumentType } from "avatax/lib/enums/DocumentType";
|
||||||
|
|
||||||
const mockGenerator = new AvataxOrderCreatedMockGenerator();
|
const mockGenerator = new AvataxOrderConfirmedMockGenerator();
|
||||||
|
|
||||||
const orderMock = mockGenerator.generateOrder();
|
const orderMock = mockGenerator.generateOrder();
|
||||||
const discountedOrderMock = mockGenerator.generateOrder({
|
const discountedOrderMock = mockGenerator.generateOrder({
|
||||||
|
@ -17,11 +17,11 @@ const discountedOrderMock = mockGenerator.generateOrder({
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const transformer = new AvataxOrderCreatedPayloadTransformer();
|
const transformer = new AvataxOrderConfirmedPayloadTransformer();
|
||||||
|
|
||||||
export const avataxConfigMock = mockGenerator.generateAvataxConfig();
|
export const avataxConfigMock = mockGenerator.generateAvataxConfig();
|
||||||
|
|
||||||
describe("AvataxOrderCreatedPayloadTransformer", () => {
|
describe("AvataxOrderConfirmedPayloadTransformer", () => {
|
||||||
it("returns document type of SalesInvoice when isDocumentRecordingEnabled is true", async () => {
|
it("returns document type of SalesInvoice when isDocumentRecordingEnabled is true", async () => {
|
||||||
const payload = await transformer.transform(orderMock, avataxConfigMock, []);
|
const payload = await transformer.transform(orderMock, avataxConfigMock, []);
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ describe("AvataxOrderCreatedPayloadTransformer", () => {
|
||||||
expect(check).toBe(true);
|
expect(check).toBe(true);
|
||||||
});
|
});
|
||||||
it("returns lines with discounted: false when there are no discounts", async () => {
|
it("returns lines with discounted: false when there are no discounts", async () => {
|
||||||
const transformer = new AvataxOrderCreatedPayloadTransformer();
|
const transformer = new AvataxOrderConfirmedPayloadTransformer();
|
||||||
const payload = await transformer.transform(orderMock, avataxConfigMock, []);
|
const payload = await transformer.transform(orderMock, avataxConfigMock, []);
|
||||||
|
|
||||||
const linesWithoutShipping = payload.model.lines.slice(0, -1);
|
const linesWithoutShipping = payload.model.lines.slice(0, -1);
|
|
@ -1,16 +1,16 @@
|
||||||
import { DocumentType } from "avatax/lib/enums/DocumentType";
|
import { DocumentType } from "avatax/lib/enums/DocumentType";
|
||||||
import { OrderCreatedSubscriptionFragment } from "../../../../generated/graphql";
|
import { OrderConfirmedSubscriptionFragment } from "../../../../generated/graphql";
|
||||||
import { discountUtils } from "../../taxes/discount-utils";
|
import { discountUtils } from "../../taxes/discount-utils";
|
||||||
import { avataxAddressFactory } from "../address-factory";
|
import { avataxAddressFactory } from "../address-factory";
|
||||||
import { AvataxClient, CreateTransactionArgs } from "../avatax-client";
|
import { AvataxClient, CreateTransactionArgs } from "../avatax-client";
|
||||||
import { AvataxConfig } from "../avatax-connection-schema";
|
import { AvataxConfig } from "../avatax-connection-schema";
|
||||||
import { AvataxTaxCodeMatches } from "../tax-code/avatax-tax-code-match-repository";
|
import { AvataxTaxCodeMatches } from "../tax-code/avatax-tax-code-match-repository";
|
||||||
import { AvataxOrderCreatedPayloadLinesTransformer } from "./avatax-order-created-payload-lines-transformer";
|
import { AvataxOrderConfirmedPayloadLinesTransformer } from "./avatax-order-confirmed-payload-lines-transformer";
|
||||||
import { AvataxEntityTypeMatcher } from "../avatax-entity-type-matcher";
|
import { AvataxEntityTypeMatcher } from "../avatax-entity-type-matcher";
|
||||||
|
|
||||||
export const SHIPPING_ITEM_CODE = "Shipping";
|
export const SHIPPING_ITEM_CODE = "Shipping";
|
||||||
|
|
||||||
export class AvataxOrderCreatedPayloadTransformer {
|
export class AvataxOrderConfirmedPayloadTransformer {
|
||||||
private matchDocumentType(config: AvataxConfig): DocumentType {
|
private matchDocumentType(config: AvataxConfig): DocumentType {
|
||||||
if (!config.isDocumentRecordingEnabled) {
|
if (!config.isDocumentRecordingEnabled) {
|
||||||
// isDocumentRecordingEnabled = false changes all the DocTypes within your AvaTax requests to SalesOrder. This will stop any transaction from being recorded within AvaTax.
|
// isDocumentRecordingEnabled = false changes all the DocTypes within your AvaTax requests to SalesOrder. This will stop any transaction from being recorded within AvaTax.
|
||||||
|
@ -20,11 +20,11 @@ export class AvataxOrderCreatedPayloadTransformer {
|
||||||
return DocumentType.SalesInvoice;
|
return DocumentType.SalesInvoice;
|
||||||
}
|
}
|
||||||
async transform(
|
async transform(
|
||||||
order: OrderCreatedSubscriptionFragment,
|
order: OrderConfirmedSubscriptionFragment,
|
||||||
avataxConfig: AvataxConfig,
|
avataxConfig: AvataxConfig,
|
||||||
matches: AvataxTaxCodeMatches
|
matches: AvataxTaxCodeMatches
|
||||||
): Promise<CreateTransactionArgs> {
|
): Promise<CreateTransactionArgs> {
|
||||||
const linesTransformer = new AvataxOrderCreatedPayloadLinesTransformer();
|
const linesTransformer = new AvataxOrderConfirmedPayloadLinesTransformer();
|
||||||
const avataxClient = new AvataxClient(avataxConfig);
|
const avataxClient = new AvataxClient(avataxConfig);
|
||||||
const entityTypeMatcher = new AvataxEntityTypeMatcher({ client: avataxClient });
|
const entityTypeMatcher = new AvataxEntityTypeMatcher({ client: avataxClient });
|
||||||
const entityUseCode = await entityTypeMatcher.match(order.avataxEntityCode);
|
const entityUseCode = await entityTypeMatcher.match(order.avataxEntityCode);
|
|
@ -1,11 +1,11 @@
|
||||||
import { AuthData } from "@saleor/app-sdk/APL";
|
import { AuthData } from "@saleor/app-sdk/APL";
|
||||||
import { OrderCreatedSubscriptionFragment } from "../../../../generated/graphql";
|
import { OrderConfirmedSubscriptionFragment } from "../../../../generated/graphql";
|
||||||
import { CreateTransactionArgs } from "../avatax-client";
|
import { CreateTransactionArgs } from "../avatax-client";
|
||||||
import { AvataxConfig } from "../avatax-connection-schema";
|
import { AvataxConfig } from "../avatax-connection-schema";
|
||||||
import { AvataxTaxCodeMatchesService } from "../tax-code/avatax-tax-code-matches.service";
|
import { AvataxTaxCodeMatchesService } from "../tax-code/avatax-tax-code-matches.service";
|
||||||
import { AvataxOrderCreatedPayloadTransformer } from "./avatax-order-created-payload-transformer";
|
import { AvataxOrderConfirmedPayloadTransformer } from "./avatax-order-confirmed-payload-transformer";
|
||||||
|
|
||||||
export class AvataxOrderCreatedPayloadService {
|
export class AvataxOrderConfirmedPayloadService {
|
||||||
constructor(private authData: AuthData) {}
|
constructor(private authData: AuthData) {}
|
||||||
|
|
||||||
private getMatches() {
|
private getMatches() {
|
||||||
|
@ -15,11 +15,11 @@ export class AvataxOrderCreatedPayloadService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPayload(
|
async getPayload(
|
||||||
order: OrderCreatedSubscriptionFragment,
|
order: OrderConfirmedSubscriptionFragment,
|
||||||
avataxConfig: AvataxConfig
|
avataxConfig: AvataxConfig
|
||||||
): Promise<CreateTransactionArgs> {
|
): Promise<CreateTransactionArgs> {
|
||||||
const matches = await this.getMatches();
|
const matches = await this.getMatches();
|
||||||
const payloadTransformer = new AvataxOrderCreatedPayloadTransformer();
|
const payloadTransformer = new AvataxOrderConfirmedPayloadTransformer();
|
||||||
|
|
||||||
return payloadTransformer.transform(order, avataxConfig, matches);
|
return payloadTransformer.transform(order, avataxConfig, matches);
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { TransactionModel } from "avatax/lib/models/TransactionModel";
|
import { TransactionModel } from "avatax/lib/models/TransactionModel";
|
||||||
|
|
||||||
export const orderCreatedTransactionMock = {
|
export const orderConfirmedTransactionMock = {
|
||||||
id: 85026453274669,
|
id: 85026453274669,
|
||||||
code: "31fa9e94-e8df-429b-b303-549e7bc10f1e",
|
code: "31fa9e94-e8df-429b-b303-549e7bc10f1e",
|
||||||
companyId: 7799660,
|
companyId: 7799660,
|
|
@ -9,7 +9,7 @@ import { LiabilityType } from "avatax/lib/enums/LiabilityType";
|
||||||
import { RateType } from "avatax/lib/enums/RateType";
|
import { RateType } from "avatax/lib/enums/RateType";
|
||||||
import { TransactionModel } from "avatax/lib/models/TransactionModel";
|
import { TransactionModel } from "avatax/lib/models/TransactionModel";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { AvataxOrderCreatedResponseTransformer } from "./avatax-order-created-response-transformer";
|
import { AvataxOrderConfirmedResponseTransformer } from "./avatax-order-confirmed-response-transformer";
|
||||||
|
|
||||||
const MOCKED_TRANSACTION: TransactionModel = {
|
const MOCKED_TRANSACTION: TransactionModel = {
|
||||||
id: 0,
|
id: 0,
|
||||||
|
@ -497,9 +497,9 @@ const MOCKED_TRANSACTION: TransactionModel = {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
describe("AvataxOrderCreatedResponseTransformer", () => {
|
describe("AvataxOrderConfirmedResponseTransformer", () => {
|
||||||
it("returns orded id in response", () => {
|
it("returns orded id in response", () => {
|
||||||
const transformer = new AvataxOrderCreatedResponseTransformer();
|
const transformer = new AvataxOrderConfirmedResponseTransformer();
|
||||||
const result = transformer.transform(MOCKED_TRANSACTION);
|
const result = transformer.transform(MOCKED_TRANSACTION);
|
||||||
|
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
|
@ -507,7 +507,7 @@ describe("AvataxOrderCreatedResponseTransformer", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("throws an error when no transaction id is present", () => {
|
it("throws an error when no transaction id is present", () => {
|
||||||
const transformer = new AvataxOrderCreatedResponseTransformer();
|
const transformer = new AvataxOrderConfirmedResponseTransformer();
|
||||||
|
|
||||||
expect(() => transformer.transform({} as any)).toThrowError();
|
expect(() => transformer.transform({} as any)).toThrowError();
|
||||||
});
|
});
|
|
@ -2,7 +2,7 @@ import { CreateOrderResponse } from "../../taxes/tax-provider-webhook";
|
||||||
import { TransactionModel } from "avatax/lib/models/TransactionModel";
|
import { TransactionModel } from "avatax/lib/models/TransactionModel";
|
||||||
import { taxProviderUtils } from "../../taxes/tax-provider-utils";
|
import { taxProviderUtils } from "../../taxes/tax-provider-utils";
|
||||||
|
|
||||||
export class AvataxOrderCreatedResponseTransformer {
|
export class AvataxOrderConfirmedResponseTransformer {
|
||||||
transform(response: TransactionModel): CreateOrderResponse {
|
transform(response: TransactionModel): CreateOrderResponse {
|
||||||
return {
|
return {
|
||||||
id: taxProviderUtils.resolveOptionalOrThrow(
|
id: taxProviderUtils.resolveOptionalOrThrow(
|
|
@ -1,7 +1,7 @@
|
||||||
import { OrderLineFragment } from "../../../../generated/graphql";
|
import { OrderLineFragment } from "../../../../generated/graphql";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { AvataxTaxCodeMatches } from "../tax-code/avatax-tax-code-match-repository";
|
import { AvataxTaxCodeMatches } from "../tax-code/avatax-tax-code-match-repository";
|
||||||
import { AvataxOrderCreatedTaxCodeMatcher } from "./avatax-order-created-tax-code-matcher";
|
import { AvataxOrderConfirmedTaxCodeMatcher } from "./avatax-order-confirmed-tax-code-matcher";
|
||||||
|
|
||||||
const mockedLine: OrderLineFragment = {
|
const mockedLine: OrderLineFragment = {
|
||||||
productSku: "sku",
|
productSku: "sku",
|
||||||
|
@ -42,15 +42,15 @@ const matches: AvataxTaxCodeMatches = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
describe("AvataxOrderCreatedTaxCodeMatcher", () => {
|
describe("AvataxOrderConfirmedTaxCodeMatcher", () => {
|
||||||
it("should return empty string if tax class is not found", () => {
|
it("should return empty string if tax class is not found", () => {
|
||||||
const matcher = new AvataxOrderCreatedTaxCodeMatcher();
|
const matcher = new AvataxOrderConfirmedTaxCodeMatcher();
|
||||||
|
|
||||||
expect(matcher.match(mockedLine, matches)).toEqual("");
|
expect(matcher.match(mockedLine, matches)).toEqual("");
|
||||||
});
|
});
|
||||||
it("should return tax code if tax class is found", () => {
|
it("should return tax code if tax class is found", () => {
|
||||||
const line = structuredClone({ ...mockedLine, taxClass: { id: "tax-class-id" } });
|
const line = structuredClone({ ...mockedLine, taxClass: { id: "tax-class-id" } });
|
||||||
const matcher = new AvataxOrderCreatedTaxCodeMatcher();
|
const matcher = new AvataxOrderConfirmedTaxCodeMatcher();
|
||||||
|
|
||||||
expect(matcher.match(line, matches)).toEqual("P0000000");
|
expect(matcher.match(line, matches)).toEqual("P0000000");
|
||||||
});
|
});
|
|
@ -1,7 +1,7 @@
|
||||||
import { OrderLineFragment } from "../../../../generated/graphql";
|
import { OrderLineFragment } from "../../../../generated/graphql";
|
||||||
import { AvataxTaxCodeMatches } from "../tax-code/avatax-tax-code-match-repository";
|
import { AvataxTaxCodeMatches } from "../tax-code/avatax-tax-code-match-repository";
|
||||||
|
|
||||||
export class AvataxOrderCreatedTaxCodeMatcher {
|
export class AvataxOrderConfirmedTaxCodeMatcher {
|
||||||
private mapTaxClassWithTaxMatch(taxClassId: string, matches: AvataxTaxCodeMatches) {
|
private mapTaxClassWithTaxMatch(taxClassId: string, matches: AvataxTaxCodeMatches) {
|
||||||
return matches.find((m) => m.data.saleorTaxClassId === taxClassId);
|
return matches.find((m) => m.data.saleorTaxClassId === taxClassId);
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@ import { AuthData } from "@saleor/app-sdk/APL";
|
||||||
import {
|
import {
|
||||||
MetadataItem,
|
MetadataItem,
|
||||||
OrderCancelledEventSubscriptionFragment,
|
OrderCancelledEventSubscriptionFragment,
|
||||||
OrderCreatedSubscriptionFragment,
|
OrderConfirmedSubscriptionFragment,
|
||||||
OrderFulfilledSubscriptionFragment,
|
OrderFulfilledSubscriptionFragment,
|
||||||
TaxBaseFragment,
|
TaxBaseFragment,
|
||||||
} from "../../../generated/graphql";
|
} from "../../../generated/graphql";
|
||||||
|
@ -12,7 +12,7 @@ import { getAppConfig } from "../app/get-app-config";
|
||||||
import { AvataxWebhookService } from "../avatax/avatax-webhook.service";
|
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 { CreateOrderResponse, ProviderWebhookService } from "./tax-provider-webhook";
|
||||||
import { OrderCancelledPayload } from "../../pages/api/webhooks/order-cancelled";
|
import { OrderCancelledPayload } from "../../pages/api/webhooks/order-cancelled";
|
||||||
|
|
||||||
// todo: refactor to a factory
|
// todo: refactor to a factory
|
||||||
|
@ -50,8 +50,8 @@ class ActiveTaxProviderService implements ProviderWebhookService {
|
||||||
return this.client.calculateTaxes(payload);
|
return this.client.calculateTaxes(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createOrder(order: OrderCreatedSubscriptionFragment) {
|
async confirmOrder(order: OrderConfirmedSubscriptionFragment) {
|
||||||
return this.client.createOrder(order);
|
return this.client.confirmOrder(order);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fulfillOrder(payload: OrderFulfilledSubscriptionFragment) {
|
async fulfillOrder(payload: OrderFulfilledSubscriptionFragment) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { SyncWebhookResponsesMap } from "@saleor/app-sdk/handlers/next";
|
import { SyncWebhookResponsesMap } from "@saleor/app-sdk/handlers/next";
|
||||||
import {
|
import {
|
||||||
OrderCreatedSubscriptionFragment,
|
OrderConfirmedSubscriptionFragment,
|
||||||
OrderFulfilledSubscriptionFragment,
|
OrderFulfilledSubscriptionFragment,
|
||||||
TaxBaseFragment,
|
TaxBaseFragment,
|
||||||
} from "../../../generated/graphql";
|
} from "../../../generated/graphql";
|
||||||
|
@ -12,7 +12,7 @@ export type CreateOrderResponse = { id: string };
|
||||||
|
|
||||||
export interface ProviderWebhookService {
|
export interface ProviderWebhookService {
|
||||||
calculateTaxes: (payload: TaxBaseFragment) => Promise<CalculateTaxesResponse>;
|
calculateTaxes: (payload: TaxBaseFragment) => Promise<CalculateTaxesResponse>;
|
||||||
createOrder: (payload: OrderCreatedSubscriptionFragment) => Promise<CreateOrderResponse>;
|
confirmOrder: (payload: OrderConfirmedSubscriptionFragment) => Promise<CreateOrderResponse>;
|
||||||
fulfillOrder: (payload: OrderFulfilledSubscriptionFragment) => Promise<{ ok: boolean }>;
|
fulfillOrder: (payload: OrderFulfilledSubscriptionFragment) => Promise<{ ok: boolean }>;
|
||||||
cancelOrder: (payload: OrderCancelledPayload) => Promise<void>;
|
cancelOrder: (payload: OrderCancelledPayload) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
import { describe } from "vitest";
|
||||||
|
|
||||||
|
describe.todo("TaxJarOrderConfirmedAdapter", () => {});
|
|
@ -1,30 +1,30 @@
|
||||||
import { AuthData } from "@saleor/app-sdk/APL";
|
import { AuthData } from "@saleor/app-sdk/APL";
|
||||||
import { OrderCreatedSubscriptionFragment } from "../../../../generated/graphql";
|
import { OrderConfirmedSubscriptionFragment } from "../../../../generated/graphql";
|
||||||
import { Logger, createLogger } from "../../../lib/logger";
|
import { Logger, createLogger } from "../../../lib/logger";
|
||||||
import { CreateOrderResponse } from "../../taxes/tax-provider-webhook";
|
import { CreateOrderResponse } from "../../taxes/tax-provider-webhook";
|
||||||
import { WebhookAdapter } from "../../taxes/tax-webhook-adapter";
|
import { WebhookAdapter } from "../../taxes/tax-webhook-adapter";
|
||||||
import { CreateOrderArgs, TaxJarClient } from "../taxjar-client";
|
import { CreateOrderArgs, TaxJarClient } from "../taxjar-client";
|
||||||
import { TaxJarConfig } from "../taxjar-connection-schema";
|
import { TaxJarConfig } from "../taxjar-connection-schema";
|
||||||
import { TaxJarOrderCreatedPayloadService } from "./taxjar-order-created-payload.service";
|
import { TaxJarOrderConfirmedPayloadService } from "./taxjar-order-confirmed-payload.service";
|
||||||
import { TaxJarOrderCreatedResponseTransformer } from "./taxjar-order-created-response-transformer";
|
import { TaxJarOrderConfirmedResponseTransformer } from "./taxjar-order-confirmed-response-transformer";
|
||||||
|
|
||||||
export type TaxJarOrderCreatedPayload = {
|
export type TaxJarOrderConfirmedPayload = {
|
||||||
order: OrderCreatedSubscriptionFragment;
|
order: OrderConfirmedSubscriptionFragment;
|
||||||
};
|
};
|
||||||
export type TaxJarOrderCreatedTarget = CreateOrderArgs;
|
export type TaxJarOrderConfirmedTarget = CreateOrderArgs;
|
||||||
export type TaxJarOrderCreatedResponse = CreateOrderResponse;
|
export type TaxJarOrderConfirmedResponse = CreateOrderResponse;
|
||||||
|
|
||||||
export class TaxJarOrderCreatedAdapter
|
export class TaxJarOrderConfirmedAdapter
|
||||||
implements WebhookAdapter<TaxJarOrderCreatedPayload, TaxJarOrderCreatedResponse>
|
implements WebhookAdapter<TaxJarOrderConfirmedPayload, TaxJarOrderConfirmedResponse>
|
||||||
{
|
{
|
||||||
private logger: Logger;
|
private logger: Logger;
|
||||||
constructor(private readonly config: TaxJarConfig, private authData: AuthData) {
|
constructor(private readonly config: TaxJarConfig, private authData: AuthData) {
|
||||||
this.logger = createLogger({ name: "TaxJarOrderCreatedAdapter" });
|
this.logger = createLogger({ name: "TaxJarOrderConfirmedAdapter" });
|
||||||
}
|
}
|
||||||
|
|
||||||
async send(payload: TaxJarOrderCreatedPayload): Promise<TaxJarOrderCreatedResponse> {
|
async send(payload: TaxJarOrderConfirmedPayload): Promise<TaxJarOrderConfirmedResponse> {
|
||||||
this.logger.debug("Transforming the Saleor payload for creating order with TaxJar...");
|
this.logger.debug("Transforming the Saleor payload for creating order with TaxJar...");
|
||||||
const payloadService = new TaxJarOrderCreatedPayloadService(this.authData);
|
const payloadService = new TaxJarOrderConfirmedPayloadService(this.authData);
|
||||||
const target = await payloadService.getPayload(payload.order, this.config);
|
const target = await payloadService.getPayload(payload.order, this.config);
|
||||||
|
|
||||||
this.logger.debug("Calling TaxJar fetchTaxForOrder with transformed payload...");
|
this.logger.debug("Calling TaxJar fetchTaxForOrder with transformed payload...");
|
||||||
|
@ -33,7 +33,7 @@ export class TaxJarOrderCreatedAdapter
|
||||||
const response = await client.createOrder(target);
|
const response = await client.createOrder(target);
|
||||||
|
|
||||||
this.logger.debug("TaxJar createOrder successfully responded");
|
this.logger.debug("TaxJar createOrder successfully responded");
|
||||||
const responseTransformer = new TaxJarOrderCreatedResponseTransformer();
|
const responseTransformer = new TaxJarOrderConfirmedResponseTransformer();
|
||||||
const transformedResponse = responseTransformer.transform(response);
|
const transformedResponse = responseTransformer.transform(response);
|
||||||
|
|
||||||
this.logger.debug("Transformed TaxJar createOrder response");
|
this.logger.debug("Transformed TaxJar createOrder response");
|
|
@ -1,11 +1,11 @@
|
||||||
import { CreateOrderRes } from "taxjar/dist/types/returnTypes";
|
import { CreateOrderRes } from "taxjar/dist/types/returnTypes";
|
||||||
import { OrderCreatedSubscriptionFragment, OrderStatus } from "../../../../generated/graphql";
|
import { OrderConfirmedSubscriptionFragment } from "../../../../generated/graphql";
|
||||||
import { ChannelConfig } from "../../channel-configuration/channel-config";
|
|
||||||
import { defaultOrder } from "../../../mocks";
|
import { defaultOrder } from "../../../mocks";
|
||||||
import { TaxJarConfig } from "../taxjar-connection-schema";
|
import { ChannelConfig } from "../../channel-configuration/channel-config";
|
||||||
import { ChannelConfigMockGenerator } from "../../channel-configuration/channel-config-mock-generator";
|
import { ChannelConfigMockGenerator } from "../../channel-configuration/channel-config-mock-generator";
|
||||||
|
import { TaxJarConfig } from "../taxjar-connection-schema";
|
||||||
|
|
||||||
type Order = OrderCreatedSubscriptionFragment;
|
type Order = OrderConfirmedSubscriptionFragment;
|
||||||
|
|
||||||
// providerConfigMockGenerator class that other classes extend?
|
// providerConfigMockGenerator class that other classes extend?
|
||||||
const defaultProviderConfig: TaxJarConfig = {
|
const defaultProviderConfig: TaxJarConfig = {
|
||||||
|
@ -23,7 +23,7 @@ const defaultProviderConfig: TaxJarConfig = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultOrderCreatedResponse: CreateOrderRes = {
|
const defaultOrderConfirmedResponse: CreateOrderRes = {
|
||||||
order: {
|
order: {
|
||||||
user_id: 314973,
|
user_id: 314973,
|
||||||
transaction_reference_id: null,
|
transaction_reference_id: null,
|
||||||
|
@ -82,14 +82,14 @@ const defaultOrderCreatedResponse: CreateOrderRes = {
|
||||||
const testingScenariosMap = {
|
const testingScenariosMap = {
|
||||||
default: {
|
default: {
|
||||||
order: defaultOrder,
|
order: defaultOrder,
|
||||||
response: defaultOrderCreatedResponse,
|
response: defaultOrderConfirmedResponse,
|
||||||
providerConfig: defaultProviderConfig,
|
providerConfig: defaultProviderConfig,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
type TestingScenario = keyof typeof testingScenariosMap;
|
type TestingScenario = keyof typeof testingScenariosMap;
|
||||||
|
|
||||||
export class TaxJarOrderCreatedMockGenerator {
|
export class TaxJarOrderConfirmedMockGenerator {
|
||||||
constructor(private scenario: TestingScenario = "default") {}
|
constructor(private scenario: TestingScenario = "default") {}
|
||||||
generateOrder = (overrides: Partial<Order> = {}): Order =>
|
generateOrder = (overrides: Partial<Order> = {}): Order =>
|
||||||
structuredClone({
|
structuredClone({
|
|
@ -1,12 +1,12 @@
|
||||||
import { OrderCreatedSubscriptionFragment, OrderLineFragment } from "../../../../generated/graphql";
|
import { OrderConfirmedSubscriptionFragment } from "../../../../generated/graphql";
|
||||||
import { TaxJarTaxCodeMatches } from "../tax-code/taxjar-tax-code-match-repository";
|
import { TaxJarTaxCodeMatches } from "../tax-code/taxjar-tax-code-match-repository";
|
||||||
|
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { TaxJarOrderCreatedPayloadLinesTransformer } from "./taxjar-order-created-payload-lines-transformer";
|
import { TaxJarOrderConfirmedPayloadLinesTransformer } from "./taxjar-order-confirmed-payload-lines-transformer";
|
||||||
|
|
||||||
const transformer = new TaxJarOrderCreatedPayloadLinesTransformer();
|
const transformer = new TaxJarOrderConfirmedPayloadLinesTransformer();
|
||||||
|
|
||||||
const mockedLines: OrderCreatedSubscriptionFragment["lines"] = [
|
const mockedLines: OrderConfirmedSubscriptionFragment["lines"] = [
|
||||||
{
|
{
|
||||||
productSku: "sku",
|
productSku: "sku",
|
||||||
productName: "Test product",
|
productName: "Test product",
|
||||||
|
@ -67,7 +67,7 @@ const matches: TaxJarTaxCodeMatches = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
describe("TaxJarOrderCreatedPayloadLinesTransformer", () => {
|
describe("TaxJarOrderConfirmedPayloadLinesTransformer", () => {
|
||||||
it("should map payload lines correctly", () => {
|
it("should map payload lines correctly", () => {
|
||||||
expect(transformer.transform(mockedLines, matches)).toEqual([
|
expect(transformer.transform(mockedLines, matches)).toEqual([
|
||||||
{
|
{
|
|
@ -1,15 +1,15 @@
|
||||||
import { LineItem } from "taxjar/dist/util/types";
|
import { LineItem } from "taxjar/dist/util/types";
|
||||||
import { OrderCreatedSubscriptionFragment } from "../../../../generated/graphql";
|
import { OrderConfirmedSubscriptionFragment } from "../../../../generated/graphql";
|
||||||
import { TaxJarTaxCodeMatches } from "../tax-code/taxjar-tax-code-match-repository";
|
import { TaxJarTaxCodeMatches } from "../tax-code/taxjar-tax-code-match-repository";
|
||||||
import { TaxJarOrderCreatedTaxCodeMatcher } from "./taxjar-order-created-tax-code-matcher";
|
import { TaxJarOrderConfirmedTaxCodeMatcher } from "./taxjar-order-confirmed-tax-code-matcher";
|
||||||
|
|
||||||
export class TaxJarOrderCreatedPayloadLinesTransformer {
|
export class TaxJarOrderConfirmedPayloadLinesTransformer {
|
||||||
transform(
|
transform(
|
||||||
lines: OrderCreatedSubscriptionFragment["lines"],
|
lines: OrderConfirmedSubscriptionFragment["lines"],
|
||||||
matches: TaxJarTaxCodeMatches
|
matches: TaxJarTaxCodeMatches
|
||||||
): LineItem[] {
|
): LineItem[] {
|
||||||
return lines.map((line) => {
|
return lines.map((line) => {
|
||||||
const matcher = new TaxJarOrderCreatedTaxCodeMatcher();
|
const matcher = new TaxJarOrderConfirmedTaxCodeMatcher();
|
||||||
const taxCode = matcher.match(line, matches);
|
const taxCode = matcher.match(line, matches);
|
||||||
|
|
||||||
return {
|
return {
|
|
@ -1,17 +1,17 @@
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
import { TaxJarOrderCreatedMockGenerator } from "./taxjar-order-created-mock-generator";
|
import { TaxJarOrderConfirmedMockGenerator } from "./taxjar-order-confirmed-mock-generator";
|
||||||
import {
|
import {
|
||||||
TaxJarOrderCreatedPayloadTransformer,
|
TaxJarOrderConfirmedPayloadTransformer,
|
||||||
sumPayloadLines,
|
sumPayloadLines,
|
||||||
} from "./taxjar-order-created-payload-transformer";
|
} from "./taxjar-order-confirmed-payload-transformer";
|
||||||
|
|
||||||
const mockGenerator = new TaxJarOrderCreatedMockGenerator();
|
const mockGenerator = new TaxJarOrderConfirmedMockGenerator();
|
||||||
|
|
||||||
describe("TaxJarOrderCreatedPayloadTransformer", () => {
|
describe("TaxJarOrderConfirmedPayloadTransformer", () => {
|
||||||
it("returns the correct order amount", () => {
|
it("returns the correct order amount", () => {
|
||||||
const orderMock = mockGenerator.generateOrder();
|
const orderMock = mockGenerator.generateOrder();
|
||||||
const providerConfig = mockGenerator.generateProviderConfig();
|
const providerConfig = mockGenerator.generateProviderConfig();
|
||||||
const transformer = new TaxJarOrderCreatedPayloadTransformer();
|
const transformer = new TaxJarOrderConfirmedPayloadTransformer();
|
||||||
const transformedPayload = transformer.transform(orderMock, providerConfig, []);
|
const transformedPayload = transformer.transform(orderMock, providerConfig, []);
|
||||||
|
|
||||||
expect(transformedPayload.params.amount).toBe(239.17);
|
expect(transformedPayload.params.amount).toBe(239.17);
|
|
@ -1,11 +1,11 @@
|
||||||
import { LineItem } from "taxjar/dist/util/types";
|
import { LineItem } from "taxjar/dist/util/types";
|
||||||
import { OrderCreatedSubscriptionFragment } from "../../../../generated/graphql";
|
import { OrderConfirmedSubscriptionFragment } from "../../../../generated/graphql";
|
||||||
import { numbers } from "../../taxes/numbers";
|
import { numbers } from "../../taxes/numbers";
|
||||||
import { taxProviderUtils } from "../../taxes/tax-provider-utils";
|
import { taxProviderUtils } from "../../taxes/tax-provider-utils";
|
||||||
import { TaxJarTaxCodeMatches } from "../tax-code/taxjar-tax-code-match-repository";
|
import { TaxJarTaxCodeMatches } from "../tax-code/taxjar-tax-code-match-repository";
|
||||||
import { TaxJarConfig } from "../taxjar-connection-schema";
|
import { TaxJarConfig } from "../taxjar-connection-schema";
|
||||||
import { TaxJarOrderCreatedTarget } from "./taxjar-order-created-adapter";
|
import { TaxJarOrderConfirmedTarget } from "./taxjar-order-confirmed-adapter";
|
||||||
import { TaxJarOrderCreatedPayloadLinesTransformer } from "./taxjar-order-created-payload-lines-transformer";
|
import { TaxJarOrderConfirmedPayloadLinesTransformer } from "./taxjar-order-confirmed-payload-lines-transformer";
|
||||||
|
|
||||||
export function sumPayloadLines(lines: LineItem[]): number {
|
export function sumPayloadLines(lines: LineItem[]): number {
|
||||||
return numbers.roundFloatToTwoDecimals(
|
return numbers.roundFloatToTwoDecimals(
|
||||||
|
@ -25,13 +25,13 @@ export function sumPayloadLines(lines: LineItem[]): number {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TaxJarOrderCreatedPayloadTransformer {
|
export class TaxJarOrderConfirmedPayloadTransformer {
|
||||||
transform(
|
transform(
|
||||||
order: OrderCreatedSubscriptionFragment,
|
order: OrderConfirmedSubscriptionFragment,
|
||||||
taxJarConfig: TaxJarConfig,
|
taxJarConfig: TaxJarConfig,
|
||||||
matches: TaxJarTaxCodeMatches
|
matches: TaxJarTaxCodeMatches
|
||||||
): TaxJarOrderCreatedTarget {
|
): TaxJarOrderConfirmedTarget {
|
||||||
const linesTransformer = new TaxJarOrderCreatedPayloadLinesTransformer();
|
const linesTransformer = new TaxJarOrderConfirmedPayloadLinesTransformer();
|
||||||
const lineItems = linesTransformer.transform(order.lines, matches);
|
const lineItems = linesTransformer.transform(order.lines, matches);
|
||||||
const lineSum = sumPayloadLines(lineItems);
|
const lineSum = sumPayloadLines(lineItems);
|
||||||
const shippingAmount = order.shippingPrice.gross.amount;
|
const shippingAmount = order.shippingPrice.gross.amount;
|
|
@ -1,11 +1,11 @@
|
||||||
import { AuthData } from "@saleor/app-sdk/APL";
|
import { AuthData } from "@saleor/app-sdk/APL";
|
||||||
import { OrderCreatedSubscriptionFragment } from "../../../../generated/graphql";
|
import { OrderConfirmedSubscriptionFragment } from "../../../../generated/graphql";
|
||||||
import { TaxJarTaxCodeMatchesService } from "../tax-code/taxjar-tax-code-matches.service";
|
import { TaxJarTaxCodeMatchesService } from "../tax-code/taxjar-tax-code-matches.service";
|
||||||
import { TaxJarConfig } from "../taxjar-connection-schema";
|
import { TaxJarConfig } from "../taxjar-connection-schema";
|
||||||
import { TaxJarOrderCreatedPayloadTransformer } from "./taxjar-order-created-payload-transformer";
|
import { TaxJarOrderConfirmedPayloadTransformer } from "./taxjar-order-confirmed-payload-transformer";
|
||||||
import { CreateOrderArgs } from "../taxjar-client";
|
import { CreateOrderArgs } from "../taxjar-client";
|
||||||
|
|
||||||
export class TaxJarOrderCreatedPayloadService {
|
export class TaxJarOrderConfirmedPayloadService {
|
||||||
constructor(private authData: AuthData) {}
|
constructor(private authData: AuthData) {}
|
||||||
|
|
||||||
private getMatches() {
|
private getMatches() {
|
||||||
|
@ -15,11 +15,11 @@ export class TaxJarOrderCreatedPayloadService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPayload(
|
async getPayload(
|
||||||
order: OrderCreatedSubscriptionFragment,
|
order: OrderConfirmedSubscriptionFragment,
|
||||||
taxJarConfig: TaxJarConfig
|
taxJarConfig: TaxJarConfig
|
||||||
): Promise<CreateOrderArgs> {
|
): Promise<CreateOrderArgs> {
|
||||||
const matches = await this.getMatches();
|
const matches = await this.getMatches();
|
||||||
const payloadTransformer = new TaxJarOrderCreatedPayloadTransformer();
|
const payloadTransformer = new TaxJarOrderConfirmedPayloadTransformer();
|
||||||
|
|
||||||
return payloadTransformer.transform(order, taxJarConfig, matches);
|
return payloadTransformer.transform(order, taxJarConfig, matches);
|
||||||
}
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { TaxJarOrderConfirmedMockGenerator } from "./taxjar-order-confirmed-mock-generator";
|
||||||
|
import { TaxJarOrderConfirmedResponseTransformer } from "./taxjar-order-confirmed-response-transformer";
|
||||||
|
|
||||||
|
describe("TaxJarOrderConfirmedResponseTransformer", () => {
|
||||||
|
it("returns orded id in response", () => {
|
||||||
|
const mockGenerator = new TaxJarOrderConfirmedMockGenerator();
|
||||||
|
const responseMock = mockGenerator.generateResponse();
|
||||||
|
const transformer = new TaxJarOrderConfirmedResponseTransformer();
|
||||||
|
const result = transformer.transform(responseMock);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
id: "T3JkZXI6ZTUzZTBlM2MtMjk5Yi00OWYxLWIyZDItY2Q4NWExYTgxYjY2",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,7 +1,7 @@
|
||||||
import { CreateOrderRes } from "taxjar/dist/types/returnTypes";
|
import { CreateOrderRes } from "taxjar/dist/types/returnTypes";
|
||||||
import { CreateOrderResponse } from "../../taxes/tax-provider-webhook";
|
import { CreateOrderResponse } from "../../taxes/tax-provider-webhook";
|
||||||
|
|
||||||
export class TaxJarOrderCreatedResponseTransformer {
|
export class TaxJarOrderConfirmedResponseTransformer {
|
||||||
transform(response: CreateOrderRes): CreateOrderResponse {
|
transform(response: CreateOrderRes): CreateOrderResponse {
|
||||||
return {
|
return {
|
||||||
id: response.order.transaction_id,
|
id: response.order.transaction_id,
|
|
@ -1,6 +1,6 @@
|
||||||
import { OrderLineFragment } from "../../../../generated/graphql";
|
import { OrderLineFragment } from "../../../../generated/graphql";
|
||||||
import { TaxJarTaxCodeMatches } from "../tax-code/taxjar-tax-code-match-repository";
|
import { TaxJarTaxCodeMatches } from "../tax-code/taxjar-tax-code-match-repository";
|
||||||
import { TaxJarOrderCreatedTaxCodeMatcher } from "./taxjar-order-created-tax-code-matcher";
|
import { TaxJarOrderConfirmedTaxCodeMatcher } from "./taxjar-order-confirmed-tax-code-matcher";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
const mockedLine: OrderLineFragment = {
|
const mockedLine: OrderLineFragment = {
|
||||||
|
@ -42,15 +42,15 @@ const matches: TaxJarTaxCodeMatches = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
describe("TaxJarOrderCreatedTaxCodeMatcher", () => {
|
describe("TaxJarOrderConfirmedTaxCodeMatcher", () => {
|
||||||
it("should return empty string if tax class is not found", () => {
|
it("should return empty string if tax class is not found", () => {
|
||||||
const matcher = new TaxJarOrderCreatedTaxCodeMatcher();
|
const matcher = new TaxJarOrderConfirmedTaxCodeMatcher();
|
||||||
|
|
||||||
expect(matcher.match(mockedLine, matches)).toEqual("");
|
expect(matcher.match(mockedLine, matches)).toEqual("");
|
||||||
});
|
});
|
||||||
it("should return tax code if tax class is found", () => {
|
it("should return tax code if tax class is found", () => {
|
||||||
const line = structuredClone({ ...mockedLine, taxClass: { id: "tax-class-id" } });
|
const line = structuredClone({ ...mockedLine, taxClass: { id: "tax-class-id" } });
|
||||||
const matcher = new TaxJarOrderCreatedTaxCodeMatcher();
|
const matcher = new TaxJarOrderConfirmedTaxCodeMatcher();
|
||||||
|
|
||||||
expect(matcher.match(line, matches)).toEqual("P0000000");
|
expect(matcher.match(line, matches)).toEqual("P0000000");
|
||||||
});
|
});
|
|
@ -1,7 +1,7 @@
|
||||||
import { OrderLineFragment } from "../../../../generated/graphql";
|
import { OrderLineFragment } from "../../../../generated/graphql";
|
||||||
import { TaxJarTaxCodeMatches } from "../tax-code/taxjar-tax-code-match-repository";
|
import { TaxJarTaxCodeMatches } from "../tax-code/taxjar-tax-code-match-repository";
|
||||||
|
|
||||||
export class TaxJarOrderCreatedTaxCodeMatcher {
|
export class TaxJarOrderConfirmedTaxCodeMatcher {
|
||||||
private mapTaxClassWithTaxMatch(taxClassId: string, matches: TaxJarTaxCodeMatches) {
|
private mapTaxClassWithTaxMatch(taxClassId: string, matches: TaxJarTaxCodeMatches) {
|
||||||
return matches.find((m) => m.data.saleorTaxClassId === taxClassId);
|
return matches.find((m) => m.data.saleorTaxClassId === taxClassId);
|
||||||
}
|
}
|
|
@ -1,3 +0,0 @@
|
||||||
import { describe } from "vitest";
|
|
||||||
|
|
||||||
describe.todo("TaxJarOrderCreatedAdapter", () => {});
|
|
|
@ -1,16 +0,0 @@
|
||||||
import { describe, expect, it } from "vitest";
|
|
||||||
import { TaxJarOrderCreatedMockGenerator } from "./taxjar-order-created-mock-generator";
|
|
||||||
import { TaxJarOrderCreatedResponseTransformer } from "./taxjar-order-created-response-transformer";
|
|
||||||
|
|
||||||
describe("TaxJarOrderCreatedResponseTransformer", () => {
|
|
||||||
it("returns orded id in response", () => {
|
|
||||||
const mockGenerator = new TaxJarOrderCreatedMockGenerator();
|
|
||||||
const responseMock = mockGenerator.generateResponse();
|
|
||||||
const transformer = new TaxJarOrderCreatedResponseTransformer();
|
|
||||||
const result = transformer.transform(responseMock);
|
|
||||||
|
|
||||||
expect(result).toEqual({
|
|
||||||
id: "T3JkZXI6ZTUzZTBlM2MtMjk5Yi00OWYxLWIyZDItY2Q4NWExYTgxYjY2",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,14 +1,14 @@
|
||||||
import {
|
import {
|
||||||
OrderCancelledEventSubscriptionFragment,
|
OrderCancelledEventSubscriptionFragment,
|
||||||
OrderCreatedSubscriptionFragment,
|
OrderConfirmedSubscriptionFragment,
|
||||||
TaxBaseFragment,
|
TaxBaseFragment,
|
||||||
} from "../../../generated/graphql";
|
} from "../../../generated/graphql";
|
||||||
import { Logger, createLogger } from "../../lib/logger";
|
import { Logger, createLogger } from "../../lib/logger";
|
||||||
import { TaxJarCalculateTaxesAdapter } from "./calculate-taxes/taxjar-calculate-taxes-adapter";
|
import { TaxJarCalculateTaxesAdapter } from "./calculate-taxes/taxjar-calculate-taxes-adapter";
|
||||||
import { TaxJarClient } from "./taxjar-client";
|
import { TaxJarClient } from "./taxjar-client";
|
||||||
import { TaxJarConfig } from "./taxjar-connection-schema";
|
import { TaxJarConfig } from "./taxjar-connection-schema";
|
||||||
import { TaxJarOrderCreatedAdapter } from "./order-created/taxjar-order-created-adapter";
|
import { TaxJarOrderConfirmedAdapter } from "./order-confirmed/taxjar-order-confirmed-adapter";
|
||||||
import { ProviderWebhookService } from "../taxes/tax-provider-webhook";
|
import { CreateOrderResponse, ProviderWebhookService } from "../taxes/tax-provider-webhook";
|
||||||
import { AuthData } from "@saleor/app-sdk/APL";
|
import { AuthData } from "@saleor/app-sdk/APL";
|
||||||
|
|
||||||
export class TaxJarWebhookService implements ProviderWebhookService {
|
export class TaxJarWebhookService implements ProviderWebhookService {
|
||||||
|
@ -34,8 +34,8 @@ export class TaxJarWebhookService implements ProviderWebhookService {
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
async createOrder(order: OrderCreatedSubscriptionFragment) {
|
async confirmOrder(order: OrderConfirmedSubscriptionFragment) {
|
||||||
const adapter = new TaxJarOrderCreatedAdapter(this.config, this.authData);
|
const adapter = new TaxJarOrderConfirmedAdapter(this.config, this.authData);
|
||||||
|
|
||||||
const response = await adapter.send({ order });
|
const response = await adapter.send({ order });
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { AppManifest } from "@saleor/app-sdk/types";
|
||||||
import packageJson from "../../../package.json";
|
import packageJson from "../../../package.json";
|
||||||
import { checkoutCalculateTaxesSyncWebhook } from "./webhooks/checkout-calculate-taxes";
|
import { checkoutCalculateTaxesSyncWebhook } from "./webhooks/checkout-calculate-taxes";
|
||||||
import { orderCalculateTaxesSyncWebhook } from "./webhooks/order-calculate-taxes";
|
import { orderCalculateTaxesSyncWebhook } from "./webhooks/order-calculate-taxes";
|
||||||
import { orderCreatedAsyncWebhook } from "./webhooks/order-created";
|
import { orderConfirmedAsyncWebhook } from "./webhooks/order-confirmed";
|
||||||
import { orderFulfilledAsyncWebhook } from "./webhooks/order-fulfilled";
|
import { orderFulfilledAsyncWebhook } from "./webhooks/order-fulfilled";
|
||||||
import { REQUIRED_SALEOR_VERSION } from "../../../saleor-app";
|
import { REQUIRED_SALEOR_VERSION } from "../../../saleor-app";
|
||||||
import { orderCancelledAsyncWebhook } from "./webhooks/order-cancelled";
|
import { orderCancelledAsyncWebhook } from "./webhooks/order-cancelled";
|
||||||
|
@ -36,7 +36,7 @@ export default createManifestHandler({
|
||||||
webhooks: [
|
webhooks: [
|
||||||
orderCalculateTaxesSyncWebhook.getWebhookManifest(apiBaseURL),
|
orderCalculateTaxesSyncWebhook.getWebhookManifest(apiBaseURL),
|
||||||
checkoutCalculateTaxesSyncWebhook.getWebhookManifest(apiBaseURL),
|
checkoutCalculateTaxesSyncWebhook.getWebhookManifest(apiBaseURL),
|
||||||
orderCreatedAsyncWebhook.getWebhookManifest(apiBaseURL),
|
orderConfirmedAsyncWebhook.getWebhookManifest(apiBaseURL),
|
||||||
orderFulfilledAsyncWebhook.getWebhookManifest(apiBaseURL),
|
orderFulfilledAsyncWebhook.getWebhookManifest(apiBaseURL),
|
||||||
orderCancelledAsyncWebhook.getWebhookManifest(apiBaseURL),
|
orderCancelledAsyncWebhook.getWebhookManifest(apiBaseURL),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next";
|
import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next";
|
||||||
import {
|
import {
|
||||||
OrderCreatedEventSubscriptionFragment,
|
OrderConfirmedEventSubscriptionFragment,
|
||||||
OrderStatus,
|
OrderStatus,
|
||||||
UntypedOrderCreatedSubscriptionDocument,
|
UntypedOrderConfirmedSubscriptionDocument,
|
||||||
} from "../../../../generated/graphql";
|
} from "../../../../generated/graphql";
|
||||||
import { saleorApp } from "../../../../saleor-app";
|
import { saleorApp } from "../../../../saleor-app";
|
||||||
import { createLogger } from "../../../lib/logger";
|
import { createLogger } from "../../../lib/logger";
|
||||||
|
@ -17,20 +17,20 @@ export const config = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
type OrderCreatedPayload = Extract<
|
type OrderConfirmedPayload = Extract<
|
||||||
OrderCreatedEventSubscriptionFragment,
|
OrderConfirmedEventSubscriptionFragment,
|
||||||
{ __typename: "OrderCreated" }
|
{ __typename: "OrderConfirmed" }
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export const orderCreatedAsyncWebhook = new SaleorAsyncWebhook<OrderCreatedPayload>({
|
export const orderConfirmedAsyncWebhook = new SaleorAsyncWebhook<OrderConfirmedPayload>({
|
||||||
name: "OrderCreated",
|
name: "OrderConfirmed",
|
||||||
apl: saleorApp.apl,
|
apl: saleorApp.apl,
|
||||||
event: "ORDER_CREATED",
|
event: "ORDER_CONFIRMED",
|
||||||
query: UntypedOrderCreatedSubscriptionDocument,
|
query: UntypedOrderConfirmedSubscriptionDocument,
|
||||||
webhookPath: "/api/webhooks/order-created",
|
webhookPath: "/api/webhooks/order-confirmed",
|
||||||
});
|
});
|
||||||
|
|
||||||
export default orderCreatedAsyncWebhook.createHandler(async (req, res, ctx) => {
|
export default orderConfirmedAsyncWebhook.createHandler(async (req, res, ctx) => {
|
||||||
const logger = createLogger({ event: ctx.event });
|
const logger = createLogger({ event: ctx.event });
|
||||||
const { payload, authData } = ctx;
|
const { payload, authData } = ctx;
|
||||||
const { saleorApiUrl, token } = authData;
|
const { saleorApiUrl, token } = authData;
|
||||||
|
@ -54,9 +54,9 @@ export default orderCreatedAsyncWebhook.createHandler(async (req, res, ctx) => {
|
||||||
|
|
||||||
logger.info("Creating order...");
|
logger.info("Creating order...");
|
||||||
|
|
||||||
const createdOrder = await taxProvider.createOrder(payload.order);
|
const confirmedOrder = await taxProvider.confirmOrder(payload.order);
|
||||||
|
|
||||||
logger.info({ createdOrder }, "Order created");
|
logger.info({ confirmedOrder }, "Order confirmed");
|
||||||
const client = createGraphQLClient({
|
const client = createGraphQLClient({
|
||||||
saleorApiUrl,
|
saleorApiUrl,
|
||||||
token,
|
token,
|
||||||
|
@ -64,7 +64,10 @@ export default orderCreatedAsyncWebhook.createHandler(async (req, res, ctx) => {
|
||||||
|
|
||||||
const orderMetadataManager = new OrderMetadataManager(client);
|
const orderMetadataManager = new OrderMetadataManager(client);
|
||||||
|
|
||||||
await orderMetadataManager.updateOrderMetadataWithExternalId(payload.order.id, createdOrder.id);
|
await orderMetadataManager.updateOrderMetadataWithExternalId(
|
||||||
|
payload.order.id,
|
||||||
|
confirmedOrder.id
|
||||||
|
);
|
||||||
logger.info("Updated order metadata with externalId");
|
logger.info("Updated order metadata with externalId");
|
||||||
|
|
||||||
return webhookResponse.success();
|
return webhookResponse.success();
|
Loading…
Reference in a new issue