fix/333 taxes not calculated (#345)

* refactor: 🔊 improve logging in taxes

* refactor: 🔥 redundant channels call

* refactor: ♻️ get app config from payload

* build: add changeset

* refactor: 🔊 routers info -> debug

* refactor: 🔊 redact logs
This commit is contained in:
Adrian Pilarczyk 2023-03-30 13:12:52 +02:00 committed by GitHub
parent 741e9104ed
commit d55b2f9b2a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 174 additions and 105 deletions

View file

@ -0,0 +1,5 @@
---
"saleor-app-taxes": minor
---
Improve webhook processing time by adding the app config to subscription payload instead of fetching it separately.

View file

@ -4,5 +4,11 @@ fragment CalculateTaxesEvent on Event {
taxBase {
...TaxBase
}
recipient {
privateMetadata {
key
value
}
}
}
}

View file

@ -11,6 +11,12 @@ export const logger = pino({
},
}
: undefined,
redact: [
"metadata",
"providerInstance.config.username",
"providerInstance.config.password",
"providerInstance.config.apiKey",
],
});
export const createLogger = logger.child.bind(logger);

View file

@ -65,6 +65,14 @@ const taxBaseLineSchema = z.object({
export const calculateTaxesPayloadSchema: z.ZodType<ExpectedWebhookPayload> = z.object({
__typename: z.literal("CalculateTaxes"),
recipient: z.object({
privateMetadata: z.array(
z.object({
key: z.string(),
value: z.string(),
})
),
}),
taxBase: z.object({
currency: z.string(),
channel: z.object({

View file

@ -0,0 +1,39 @@
import { decrypt } from "@saleor/app-sdk/settings-manager";
import { ExpectedWebhookPayload } from "../../lib/saleor/schema";
import { ChannelsConfig, channelsSchema } from "../channels-configuration/channels-config";
import { ProvidersConfig, providersSchema } from "../providers-configuration/providers-config";
export const getAppConfig = (payload: ExpectedWebhookPayload) => {
const metadata = payload.recipient?.privateMetadata;
let providersConfig = [] as ProvidersConfig;
let channelsConfig = {} as ChannelsConfig;
const secretKey = process.env.SECRET_KEY;
if (!secretKey) {
throw new Error("SECRET_KEY env variable is not set");
}
// * The App Config contains two types of data: providers and channels.
// * We must recognize which one we are dealing with and parse it accordingly.
metadata?.forEach((item) => {
const decrypted = decrypt(item.value, secretKey);
const parsed = JSON.parse(decrypted);
const providersValidation = providersSchema.safeParse(parsed);
if (providersValidation.success) {
providersConfig = providersValidation.data;
return;
}
const channelsValidation = channelsSchema.safeParse(parsed);
if (channelsValidation.success) {
channelsConfig = channelsValidation.data;
return;
}
});
return { providers: providersConfig, channels: channelsConfig };
};

View file

@ -5,12 +5,19 @@ import {
FetchAppDetailsQuery,
UpdateAppMetadataDocument,
} from "../../../generated/graphql";
import { logger as pinoLogger } from "../../lib/logger";
export async function fetchAllMetadata(client: Client): Promise<MetadataEntry[]> {
const logger = pinoLogger.child({ service: "fetchAllMetadata" });
logger.debug("Fetching metadata from Saleor");
const { error, data } = await client
.query<FetchAppDetailsQuery>(FetchAppDetailsDocument, {})
.toPromise();
// * `metadata` name is required for secrets censorship
logger.debug({ error, metadata: data }, "Metadata fetched");
if (error) {
return [];
}
@ -19,11 +26,15 @@ export async function fetchAllMetadata(client: Client): Promise<MetadataEntry[]>
}
export async function mutateMetadata(client: Client, metadata: MetadataEntry[]) {
const logger = pinoLogger.child({ service: "mutateMetadata" });
logger.debug({ metadata }, "Mutating metadata");
// to update the metadata, ID is required
const { error: idQueryError, data: idQueryData } = await client
.query(FetchAppDetailsDocument, {})
.toPromise();
logger.debug({ error: idQueryError, data: idQueryData }, "Metadata mutated");
if (idQueryError) {
throw new Error(
"Could not fetch the app id. Please check if auth data for the client are valid."

View file

@ -1,7 +1,8 @@
import Avatax from "avatax";
import { CreateTransactionModel } from "avatax/lib/models/CreateTransactionModel";
import pino from "pino";
import packageJson from "../../../package.json";
import { logger } from "../../lib/logger";
import { createLogger } from "../../lib/logger";
import { AvataxConfig } from "./avatax-config";
type AvataxSettings = {
@ -36,9 +37,11 @@ const createAvataxSettings = (config: AvataxConfig): AvataxSettings => {
export class AvataxClient {
private client: Avatax;
private logger: pino.Logger;
constructor(config: AvataxConfig) {
logger.debug("AvataxClient constructor");
this.logger = createLogger({ service: "AvataxClient" });
this.logger.trace("AvataxClient constructor");
const { username, password } = config;
const credentials = {
username,
@ -46,15 +49,18 @@ export class AvataxClient {
};
const settings = createAvataxSettings(config);
const avataxClient = new Avatax(settings).withSecurity(credentials);
logger.info({ client: avataxClient }, "External Avatax client created");
this.logger.trace({ client: avataxClient }, "External Avatax client created");
this.client = avataxClient;
}
async fetchTaxesForOrder(model: CreateTransactionModel) {
this.logger.debug({ model }, "fetchTaxesForOrder called with:");
return this.client.createTransaction({ model });
}
async ping() {
this.logger.debug("ping called");
try {
const result = await this.client.ping();

View file

@ -37,14 +37,15 @@ export const avataxConfigurationRouter = router({
procedure: "avataxConfigurationRouter.get",
});
logger.debug("avataxConfigurationRouter.get called");
logger.debug({ input }, "avataxConfigurationRouter.get called with:");
const { apiClient, saleorApiUrl } = ctx;
const avataxConfigurationService = new AvataxConfigurationService(apiClient, saleorApiUrl);
const result = await avataxConfigurationService.get(input.id);
logger.debug({ result }, "avataxConfigurationRouter.get finished");
// * `providerInstance` name is required for secrets censorship
logger.debug({ providerInstance: result }, "avataxConfigurationRouter.get finished");
return { ...result, config: obfuscateAvataxConfig(result.config) };
}),
@ -54,7 +55,7 @@ export const avataxConfigurationRouter = router({
procedure: "avataxConfigurationRouter.post",
});
logger.debug("avataxConfigurationRouter.post called");
logger.debug({ input }, "avataxConfigurationRouter.post called with:");
const { apiClient, saleorApiUrl } = ctx;
const avataxConfigurationService = new AvataxConfigurationService(apiClient, saleorApiUrl);
@ -71,7 +72,7 @@ export const avataxConfigurationRouter = router({
procedure: "avataxConfigurationRouter.delete",
});
logger.debug("avataxConfigurationRouter.delete called");
logger.debug({ input }, "avataxConfigurationRouter.delete called with:");
const { apiClient, saleorApiUrl } = ctx;
const avataxConfigurationService = new AvataxConfigurationService(apiClient, saleorApiUrl);
@ -88,7 +89,7 @@ export const avataxConfigurationRouter = router({
procedure: "avataxConfigurationRouter.patch",
});
logger.debug("avataxConfigurationRouter.patch called");
logger.debug({ input }, "avataxConfigurationRouter.patch called with:");
const { apiClient, saleorApiUrl } = ctx;
const avataxConfigurationService = new AvataxConfigurationService(apiClient, saleorApiUrl);

View file

@ -45,7 +45,7 @@ export class AvataxConfigurationService {
async get(id: string): Promise<AvataxInstanceConfig> {
this.logger.debug(`.get called with id: ${id}`);
const { data } = await this.crudSettingsConfigurator.read(id);
this.logger.debug({ setting: data }, `Fetched setting from crudSettingsConfigurator`);
this.logger.debug(`Fetched setting from crudSettingsConfigurator`);
const validation = getSchema.safeParse(data);

View file

@ -1,5 +1,6 @@
import pino from "pino";
import { TaxBaseFragment } from "../../../generated/graphql";
import { logger } from "../../lib/logger";
import { createLogger } from "../../lib/logger";
import { ChannelConfig } from "../channels-configuration/channels-config";
import { TaxProvider } from "../taxes/tax-provider";
import { avataxCalculate } from "./avatax-calculate";
@ -10,21 +11,24 @@ export class AvataxProvider implements TaxProvider {
readonly name = "avatax";
config = defaultAvataxConfig;
client: AvataxClient;
private logger: pino.Logger;
constructor(config: AvataxConfig) {
this.logger = createLogger({
service: "AvataxProvider",
});
const avataxClient = new AvataxClient(config);
logger.info({ client: avataxClient }, "Internal Avatax client created");
this.logger.trace({ client: avataxClient }, "Internal Avatax client created");
this.config = config;
this.client = avataxClient;
}
async calculate(payload: TaxBaseFragment, channel: ChannelConfig) {
logger.info("Avatax calculate");
this.logger.debug({ payload, channel }, "Avatax calculate called with:");
const model = avataxCalculate.preparePayload(payload, channel, this.config);
logger.info(model, "Payload used for Avatax fetchTaxesForOrder");
const result = await this.client.fetchTaxesForOrder(model);
logger.info({ createOrderTransaction: result }, "Avatax createOrderTransaction response");
this.logger.debug({ createOrderTransaction: result }, "Avatax createOrderTransaction response");
return avataxCalculate.prepareResponse(result);
}
}

View file

@ -9,7 +9,7 @@ export const channelSchema = z.object({
});
export type ChannelConfig = z.infer<typeof channelSchema>;
const channelsSchema = z.record(channelSchema);
export const channelsSchema = z.record(channelSchema);
export type ChannelsConfig = z.infer<typeof channelsSchema>;
export const defaultChannelConfig: ChannelConfig = {

View file

@ -7,9 +7,13 @@ import { setAndReplaceChannelsInputSchema } from "./channels-config-input-schema
import { TaxChannelsConfigurator } from "./channels-configurator";
import { GetChannelsConfigurationService } from "./get-channels-configuration.service";
// todo: refactor with crud-settings
export const channelsConfigurationRouter = router({
fetch: protectedClientProcedure.query(async ({ ctx, input }) => {
const logger = pinoLogger.child({ saleorApiUrl: ctx.saleorApiUrl });
const logger = pinoLogger.child({
saleorApiUrl: ctx.saleorApiUrl,
procedure: "channelsConfigurationRouter.fetch",
});
logger.debug("channelsConfigurationRouter.fetch called");
@ -21,14 +25,17 @@ export const channelsConfigurationRouter = router({
upsert: protectedClientProcedure
.input(setAndReplaceChannelsInputSchema)
.mutation(async ({ ctx, input }) => {
const logger = pinoLogger.child({ saleorApiUrl: ctx.saleorApiUrl });
logger.info(input, "channelsConfigurationRouter.upsert called with input");
const logger = pinoLogger.child({
saleorApiUrl: ctx.saleorApiUrl,
procedure: "channelsConfigurationRouter.upsert",
});
logger.debug(input, "channelsConfigurationRouter.upsert called with input");
const config = await new GetChannelsConfigurationService({
apiClient: ctx.apiClient,
saleorApiUrl: ctx.saleorApiUrl,
}).getConfiguration();
logger.info(config, "Fetched current channels config to update it");
logger.debug(config, "Fetched current channels config to update it");
const taxChannelsConfigurator = new TaxChannelsConfigurator(
createSettingsManager(ctx.apiClient),
@ -43,7 +50,7 @@ export const channelsConfigurationRouter = router({
},
};
logger.info(channelsConfig, "Merged configs. Will set it now");
logger.debug(channelsConfig, "Merged configs. Will set it now");
await taxChannelsConfigurator.setConfig(channelsConfig);

View file

@ -1,8 +1,6 @@
import { Client } from "urql";
import { logger as pinoLogger } from "../../lib/logger";
import { createSettingsManager } from "../app-configuration/metadata-manager";
import { ChannelsFetcher } from "../channels/channels-fetcher";
import { createDefaultChannelsConfig } from "./channels-config";
import { TaxChannelsConfigurator } from "./channels-configurator";
export class GetChannelsConfigurationService {
@ -26,17 +24,11 @@ export class GetChannelsConfigurationService {
saleorApiUrl
);
const channelsFetcher = new ChannelsFetcher(apiClient);
const channels = await channelsFetcher.fetchChannels();
logger.info({ channels }, "Fetched Saleor channels that use TAX_APP for tax calculation");
const defaultConfig = createDefaultChannelsConfig(channels ?? []);
logger.info({ defaultConfig }, "Generated config from Saleor channels");
// todo: validate config
const appChannelsConfig = (await taxConfigurator.getConfig()) ?? null;
logger.debug(appChannelsConfig, "Retrieved channels config from Metadata");
return { ...defaultConfig, ...appChannelsConfig };
return { ...appChannelsConfig };
}
}

View file

@ -20,11 +20,11 @@ export class CrudSettingsConfigurator {
}
async readAll() {
this.logger.debug(".readAll called");
this.logger.trace(".readAll called");
const result = await this.metadataManager.get(this.metadataKey, this.saleorApiUrl);
if (!result) {
this.logger.debug("No metadata found");
this.logger.trace("No metadata found");
return { data: [] };
}
@ -42,7 +42,7 @@ export class CrudSettingsConfigurator {
}
async read(id: string) {
this.logger.debug(".read called");
this.logger.trace(".read called");
const result = await this.readAll();
const { data: settings } = result;
@ -58,7 +58,7 @@ export class CrudSettingsConfigurator {
}
async create(data: any) {
this.logger.debug(data, ".create called with:");
this.logger.trace(data, ".create called with:");
const settings = await this.readAll();
const prevData = settings.data;
@ -77,7 +77,7 @@ export class CrudSettingsConfigurator {
}
async delete(id: string) {
this.logger.debug(`.delete called with: ${id}`);
this.logger.trace(`.delete called with: ${id}`);
const settings = await this.readAll();
const prevData = settings.data;
@ -91,7 +91,7 @@ export class CrudSettingsConfigurator {
}
async update(id: string, data: any) {
this.logger.debug(data, `.update called with: ${id}`);
this.logger.trace(data, `.update called with: ${id}`);
const { data: settings } = await this.readAll();
const nextData = settings.map((item) => {
if (item.id === id) {

View file

@ -5,7 +5,10 @@ import { PublicTaxProvidersConfigurationService } from "./public-providers-confi
export const providersConfigurationRouter = router({
getAll: protectedClientProcedure.query(async ({ ctx }) => {
const logger = pinoLogger.child({ saleorApiUrl: ctx.saleorApiUrl });
const logger = pinoLogger.child({
saleorApiUrl: ctx.saleorApiUrl,
procedure: "providersConfigurationRouter.getAll",
});
logger.debug("providersConfigurationRouter.fetch called");

View file

@ -6,15 +6,19 @@ import { AvataxProvider } from "../avatax/avatax-provider";
import { TaxJarProvider } from "../taxjar/taxjar-provider";
import { TaxProvider } from "./tax-provider";
import { TaxProviderError } from "./tax-provider-error";
import pino from "pino";
export class ActiveTaxProvider {
private client: TaxProvider;
private logger: pino.Logger;
constructor(providerInstance: ProviderConfig) {
const logger = createLogger({});
this.logger = createLogger({
service: "ActiveTaxProvider",
});
const taxProviderName = providerInstance.provider;
logger.info({ taxProviderName }, "Constructing tax provider: ");
this.logger.trace({ taxProviderName }, "Constructing tax provider: ");
switch (taxProviderName) {
case "taxjar":
@ -34,6 +38,8 @@ export class ActiveTaxProvider {
}
async calculate(payload: TaxBaseFragment, channel: ChannelConfig) {
this.logger.debug({ payload, channel }, ".calculate called");
return this.client.calculate(payload, channel);
}
}

View file

@ -1,9 +1,7 @@
import { TaxBaseFragment } from "../../../generated/graphql";
import { ResponseTaxPayload } from "./types";
import { ChannelConfig } from "../channels-configuration/channels-config";
import { TaxProviderName } from "./providers/config";
type ExternalValidationResult = { ok: boolean; error?: string };
import { ResponseTaxPayload } from "./types";
export interface TaxProvider {
name: TaxProviderName;

View file

@ -1,6 +1,7 @@
import pino from "pino";
import TaxJar from "taxjar";
import { Config, TaxForOrderRes, TaxParams } from "taxjar/dist/util/types";
import { logger } from "../../lib/logger";
import { createLogger } from "../../lib/logger";
import { TaxJarConfig } from "./taxjar-config";
const createTaxJarSettings = (config: TaxJarConfig): Config => {
@ -14,21 +15,25 @@ const createTaxJarSettings = (config: TaxJarConfig): Config => {
export class TaxJarClient {
private client: TaxJar;
private logger: pino.Logger;
constructor(providerConfig: TaxJarConfig) {
logger.debug("TaxJarClient constructor");
this.logger = createLogger({ service: "TaxJarClient" });
this.logger.trace("TaxJarClient constructor");
const settings = createTaxJarSettings(providerConfig);
const taxJarClient = new TaxJar(settings);
logger.info({ client: taxJarClient }, "External TaxJar client created");
this.logger.trace({ client: taxJarClient }, "External TaxJar client created");
this.client = taxJarClient;
}
async fetchTaxesForOrder(params: TaxParams) {
this.logger.debug({ params }, "fetchTaxesForOrder called with:");
const response: TaxForOrderRes = await this.client.taxForOrder(params);
return response;
}
async ping() {
this.logger.debug("ping called");
try {
await this.client.categories();
return { authenticated: true };

View file

@ -43,8 +43,8 @@ export const taxjarConfigurationRouter = router({
const result = await taxjarConfigurationService.get(input.id);
logger.debug({ result }, "taxjarConfigurationRouter.get finished");
// * `providerInstance` name is required for secrets censorship
logger.debug({ providerInstance: result }, "taxjarConfigurationRouter.get finished");
return { ...result, config: obfuscateTaxJarConfig(result.config) };
}),
post: protectedClientProcedure.input(postInputSchema).mutation(async ({ ctx, input }) => {

View file

@ -29,7 +29,7 @@ export class TaxJarConfigurationService {
async getAll(): Promise<TaxJarInstanceConfig[]> {
this.logger.debug(".getAll called");
const { data } = await this.crudSettingsConfigurator.readAll();
this.logger.debug({ settings: data }, `Fetched settings from crudSettingsConfigurator`);
this.logger.debug(`Fetched settings from crudSettingsConfigurator`);
const validation = providersSchema.safeParse(data);
if (!validation.success) {
@ -47,7 +47,7 @@ export class TaxJarConfigurationService {
async get(id: string): Promise<TaxJarInstanceConfig> {
this.logger.debug(`.get called with id: ${id}`);
const { data } = await this.crudSettingsConfigurator.read(id);
this.logger.debug({ setting: data }, `Fetched setting from crudSettingsConfigurator`);
this.logger.debug(`Fetched setting from crudSettingsConfigurator`);
const validation = getSchema.safeParse(data);

View file

@ -1,35 +1,36 @@
import pino from "pino";
import { TaxBaseFragment } from "../../../generated/graphql";
import { logger } from "../../lib/logger";
import { ChannelConfig, defaultChannelConfig } from "../channels-configuration/channels-config";
import { createLogger } from "../../lib/logger";
import { ChannelConfig } from "../channels-configuration/channels-config";
import { TaxProvider } from "../taxes/tax-provider";
import { taxJarCalculate } from "./taxjar-calculate";
import { TaxJarClient } from "./taxjar-client";
import { defaultTaxJarConfig, TaxJarConfig } from "./taxjar-config";
import { TaxJarConfig } from "./taxjar-config";
export class TaxJarProvider implements TaxProvider {
readonly name = "taxjar";
config = defaultTaxJarConfig;
channel = defaultChannelConfig;
client: TaxJarClient;
readonly name = "taxjar";
private logger: pino.Logger;
constructor(config: TaxJarConfig) {
const avataxClient = new TaxJarClient(config);
this.config = config;
this.client = avataxClient;
this.logger = createLogger({
service: "TaxJarProvider",
});
}
async calculate(payload: TaxBaseFragment, channel: ChannelConfig) {
logger.info("TaxJar calculate");
this.logger.debug({ payload, channel }, "TaxJar calculate called with:");
const linesWithDiscount = taxJarCalculate.prepareLinesWithDiscountPayload(
payload.lines,
payload.discounts
);
const linesWithChargeTaxes = linesWithDiscount.filter((line) => line.chargeTaxes === true);
const taxParams = taxJarCalculate.preparePayload(payload, channel, linesWithDiscount);
logger.info(taxParams, "Payload used for TaxJar fetchTaxesForOrder");
const fetchedTaxes = await this.client.fetchTaxesForOrder(taxParams);
logger.info({ fetchedTaxes }, "TaxJar createOrderTransaction response");
this.logger.debug({ fetchedTaxes }, "TaxJar createOrderTransaction response");
return taxJarCalculate.prepareResponse(
payload,

View file

@ -1,11 +1,9 @@
import { SaleorSyncWebhook } from "@saleor/app-sdk/handlers/next";
import { UntypedCalculateTaxesDocument } from "../../../../generated/graphql";
import { saleorApp } from "../../../../saleor-app";
import { createClient } from "../../../lib/graphql";
import { createLogger } from "../../../lib/logger";
import { calculateTaxesPayloadSchema, ExpectedWebhookPayload } from "../../../lib/saleor/schema";
import { GetChannelsConfigurationService } from "../../../modules/channels-configuration/get-channels-configuration.service";
import { PrivateTaxProvidersConfigurationService } from "../../../modules/providers-configuration/private-providers-configuration-service";
import { getAppConfig } from "../../../modules/app-configuration/get-app-config";
import { ActiveTaxProvider } from "../../../modules/taxes/active-tax-provider";
@ -25,7 +23,7 @@ export const checkoutCalculateTaxesSyncWebhook = new SaleorSyncWebhook<ExpectedW
export default checkoutCalculateTaxesSyncWebhook.createHandler(async (req, res, ctx) => {
const logger = createLogger({ event: ctx.event });
const { authData, payload } = ctx;
const { payload } = ctx;
logger.info({ payload }, "Handler called with payload");
const validation = calculateTaxesPayloadSchema.safeParse(payload);
@ -37,27 +35,14 @@ export default checkoutCalculateTaxesSyncWebhook.createHandler(async (req, res,
}
const { data } = validation;
logger.info({ data }, "Payload is valid.");
logger.info("Payload validated succesfully");
const { providers, channels } = getAppConfig(data);
logger.debug("Successfully parsed providers & channels from payload");
try {
const client = createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
const providersConfig = await new PrivateTaxProvidersConfigurationService(
client,
authData.saleorApiUrl
).getAll();
const channelsConfig = await new GetChannelsConfigurationService({
saleorApiUrl: authData.saleorApiUrl,
apiClient: client,
}).getConfiguration();
logger.info({ providersConfig }, "Providers configuration returned");
const channelSlug = payload.taxBase.channel.slug;
const channelConfig = channelsConfig[channelSlug];
const channelSlug = data.taxBase.channel.slug;
const channelConfig = channels[channelSlug];
if (!channelConfig) {
logger.error(`Channel config not found for channel ${channelSlug}`);
@ -65,7 +50,7 @@ export default checkoutCalculateTaxesSyncWebhook.createHandler(async (req, res,
return res.send({});
}
const providerInstance = providersConfig.find(
const providerInstance = providers.find(
(instance) => instance.id === channelConfig.providerInstanceId
);

View file

@ -1,11 +1,9 @@
import { SaleorSyncWebhook } from "@saleor/app-sdk/handlers/next";
import { UntypedCalculateTaxesDocument } from "../../../../generated/graphql";
import { saleorApp } from "../../../../saleor-app";
import { createClient } from "../../../lib/graphql";
import { createLogger } from "../../../lib/logger";
import { calculateTaxesPayloadSchema, ExpectedWebhookPayload } from "../../../lib/saleor/schema";
import { GetChannelsConfigurationService } from "../../../modules/channels-configuration/get-channels-configuration.service";
import { PrivateTaxProvidersConfigurationService } from "../../../modules/providers-configuration/private-providers-configuration-service";
import { getAppConfig } from "../../../modules/app-configuration/get-app-config";
import { ActiveTaxProvider } from "../../../modules/taxes/active-tax-provider";
export const config = {
@ -24,7 +22,7 @@ export const orderCalculateTaxesSyncWebhook = new SaleorSyncWebhook<ExpectedWebh
export default orderCalculateTaxesSyncWebhook.createHandler(async (req, res, ctx) => {
const logger = createLogger({ event: ctx.event });
const { authData, payload } = ctx;
const { payload } = ctx;
logger.info({ payload }, "Handler called with payload");
const validation = calculateTaxesPayloadSchema.safeParse(payload);
@ -36,26 +34,14 @@ export default orderCalculateTaxesSyncWebhook.createHandler(async (req, res, ctx
}
const { data } = validation;
logger.info({ data }, "Payload is valid.");
logger.info("Payload validated succesfully");
const { providers, channels } = getAppConfig(data);
logger.debug("Parsed providers & channels from payload");
try {
const client = createClient(authData.saleorApiUrl, async () =>
Promise.resolve({ token: authData.token })
);
const providersConfig = await new PrivateTaxProvidersConfigurationService(
client,
authData.saleorApiUrl
).getAll();
const channelsConfig = await new GetChannelsConfigurationService({
saleorApiUrl: authData.saleorApiUrl,
apiClient: client,
}).getConfiguration();
logger.info({ providersConfig }, "Providers configuration returned");
const channelSlug = payload.taxBase.channel.slug;
const channelConfig = channelsConfig[channelSlug];
const channelSlug = data.taxBase.channel.slug;
const channelConfig = channels[channelSlug];
if (!channelConfig) {
logger.error(`Channel config not found for channel ${channelSlug}`);
@ -63,7 +49,7 @@ export default orderCalculateTaxesSyncWebhook.createHandler(async (req, res, ctx
return res.send({});
}
const providerInstance = providersConfig.find(
const providerInstance = providers.find(
(instance) => instance.id === channelConfig.providerInstanceId
);