chore: split credentials and settings (#886)
* feat: ✨ grey out disabled links * chore: 🚚 move fields to new avatax settings fragment * build: 👷 add changeset * refactor: 🚚 move companyCode to credentials * refactor: ♻️ make helper texts more accurate * refactor: 🚚 Avatax -> AvaTax
This commit is contained in:
parent
c50797e836
commit
be761b251e
37 changed files with 219 additions and 203 deletions
5
.changeset/brown-tools-dance.md
Normal file
5
.changeset/brown-tools-dance.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"saleor-app-taxes": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Changed the layout in the AvaTax configuration form to consist of three sections: "Credentials", "Settings" (new) and "Address". Now, the "Credentials" section contains only fields that affect authentication.
|
|
@ -13,7 +13,7 @@ const avataxCredentialsSchema = z.object({
|
||||||
password: z.string().min(1, { message: "Password requires at least one character." }),
|
password: z.string().min(1, { message: "Password requires at least one character." }),
|
||||||
});
|
});
|
||||||
|
|
||||||
// All that is needed to create Avatax configuration.
|
// All that is needed to create AvaTax configuration.
|
||||||
export const baseAvataxConfigSchema = z.object({
|
export const baseAvataxConfigSchema = z.object({
|
||||||
isSandbox: z.boolean(),
|
isSandbox: z.boolean(),
|
||||||
credentials: avataxCredentialsSchema,
|
credentials: avataxCredentialsSchema,
|
||||||
|
|
|
@ -49,7 +49,7 @@ export const avataxConnectionRouter = router({
|
||||||
|
|
||||||
await ctx.connectionService.verifyConnections();
|
await ctx.connectionService.verifyConnections();
|
||||||
|
|
||||||
logger.info("Avatax connections were successfully verified");
|
logger.info("AvaTax connections were successfully verified");
|
||||||
|
|
||||||
return { ok: true };
|
return { ok: true };
|
||||||
}),
|
}),
|
||||||
|
@ -62,7 +62,7 @@ export const avataxConnectionRouter = router({
|
||||||
|
|
||||||
const result = await ctx.connectionService.getById(input.id);
|
const result = await ctx.connectionService.getById(input.id);
|
||||||
|
|
||||||
logger.info(`Avatax configuration with an id: ${result.id} was successfully retrieved`);
|
logger.info(`AvaTax configuration with an id: ${result.id} was successfully retrieved`);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}),
|
}),
|
||||||
|
@ -76,7 +76,7 @@ export const avataxConnectionRouter = router({
|
||||||
|
|
||||||
const result = await ctx.connectionService.create(input.value);
|
const result = await ctx.connectionService.create(input.value);
|
||||||
|
|
||||||
logger.info("Avatax configuration was successfully created");
|
logger.info("AvaTax configuration was successfully created");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}),
|
}),
|
||||||
|
@ -92,7 +92,7 @@ export const avataxConnectionRouter = router({
|
||||||
|
|
||||||
const result = await ctx.connectionService.delete(input.id);
|
const result = await ctx.connectionService.delete(input.id);
|
||||||
|
|
||||||
logger.info(`Avatax configuration with an id: ${input.id} was deleted`);
|
logger.info(`AvaTax configuration with an id: ${input.id} was deleted`);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}),
|
}),
|
||||||
|
@ -108,7 +108,7 @@ export const avataxConnectionRouter = router({
|
||||||
|
|
||||||
const result = await ctx.connectionService.update(input.id, input.value);
|
const result = await ctx.connectionService.update(input.id, input.value);
|
||||||
|
|
||||||
logger.info(`Avatax configuration with an id: ${input.id} was successfully updated`);
|
logger.info(`AvaTax configuration with an id: ${input.id} was successfully updated`);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}),
|
}),
|
||||||
|
@ -137,7 +137,7 @@ export const avataxConnectionRouter = router({
|
||||||
|
|
||||||
const result = await addressValidationService.validate(input.id, input.value);
|
const result = await addressValidationService.validate(input.id, input.value);
|
||||||
|
|
||||||
logger.info(`Avatax address was successfully validated`);
|
logger.info(`AvaTax address was successfully validated`);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}),
|
}),
|
||||||
|
@ -157,7 +157,7 @@ export const avataxConnectionRouter = router({
|
||||||
|
|
||||||
const result = await addressValidation.validate(input.value.address);
|
const result = await addressValidation.validate(input.value.address);
|
||||||
|
|
||||||
logger.info(`Avatax address was successfully validated`);
|
logger.info(`AvaTax address was successfully validated`);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}),
|
}),
|
||||||
|
@ -184,7 +184,7 @@ export const avataxConnectionRouter = router({
|
||||||
|
|
||||||
await authValidation.validate(input.id, input.value);
|
await authValidation.validate(input.id, input.value);
|
||||||
|
|
||||||
logger.info(`Avatax client was successfully validated`);
|
logger.info(`AvaTax client was successfully validated`);
|
||||||
}),
|
}),
|
||||||
createValidateCredentials: protectedClientProcedure
|
createValidateCredentials: protectedClientProcedure
|
||||||
.input(z.object({ value: baseAvataxConfigSchema }))
|
.input(z.object({ value: baseAvataxConfigSchema }))
|
||||||
|
@ -200,7 +200,7 @@ export const avataxConnectionRouter = router({
|
||||||
|
|
||||||
const result = await authValidation.validate();
|
const result = await authValidation.validate();
|
||||||
|
|
||||||
logger.info(`Avatax client was successfully validated`);
|
logger.info(`AvaTax client was successfully validated`);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -15,7 +15,7 @@ export class AvataxDocumentCodeResolver {
|
||||||
const code = avataxDocumentCode ?? orderId;
|
const code = avataxDocumentCode ?? orderId;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The requirement from Avatax API is that document code is a string that must be between 1 and 20 characters long.
|
* The requirement from AvaTax API is that document code is a string that must be between 1 and 20 characters long.
|
||||||
* // todo: document that its sliced
|
* // todo: document that its sliced
|
||||||
*/
|
*/
|
||||||
return code.slice(0, 20);
|
return code.slice(0, 20);
|
||||||
|
|
|
@ -27,21 +27,21 @@ export class AvataxCalculateTaxesAdapter
|
||||||
|
|
||||||
// todo: refactor because its getting too big
|
// todo: refactor because its getting too big
|
||||||
async send(payload: AvataxCalculateTaxesPayload): Promise<AvataxCalculateTaxesResponse> {
|
async send(payload: AvataxCalculateTaxesPayload): Promise<AvataxCalculateTaxesResponse> {
|
||||||
this.logger.debug("Transforming the Saleor payload for calculating taxes with Avatax...");
|
this.logger.debug("Transforming the Saleor payload for calculating taxes with AvaTax...");
|
||||||
const payloadService = new AvataxCalculateTaxesPayloadService(this.authData);
|
const payloadService = new AvataxCalculateTaxesPayloadService(this.authData);
|
||||||
const target = await payloadService.getPayload(payload.taxBase, this.config);
|
const target = await payloadService.getPayload(payload.taxBase, this.config);
|
||||||
|
|
||||||
this.logger.debug("Calling Avatax createTransaction with transformed payload...");
|
this.logger.debug("Calling AvaTax createTransaction with transformed payload...");
|
||||||
|
|
||||||
const client = new AvataxClient(this.config);
|
const client = new AvataxClient(this.config);
|
||||||
const response = await client.createTransaction(target);
|
const response = await client.createTransaction(target);
|
||||||
|
|
||||||
this.logger.debug("Avatax createTransaction successfully responded");
|
this.logger.debug("AvaTax createTransaction successfully responded");
|
||||||
|
|
||||||
const responseTransformer = new AvataxCalculateTaxesResponseTransformer();
|
const responseTransformer = new AvataxCalculateTaxesResponseTransformer();
|
||||||
const transformedResponse = responseTransformer.transform(response);
|
const transformedResponse = responseTransformer.transform(response);
|
||||||
|
|
||||||
this.logger.debug("Transformed Avatax createTransaction response");
|
this.logger.debug("Transformed AvaTax createTransaction response");
|
||||||
|
|
||||||
return transformedResponse;
|
return transformedResponse;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ export class AvataxCalculateTaxesPayloadLinesTransformer {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (taxBase.shippingPrice.amount !== 0) {
|
if (taxBase.shippingPrice.amount !== 0) {
|
||||||
// * In Avatax, shipping is a regular line
|
// * In AvaTax, shipping is a regular line
|
||||||
const shippingLine: LineItemModel = {
|
const shippingLine: LineItemModel = {
|
||||||
amount: taxBase.shippingPrice.amount,
|
amount: taxBase.shippingPrice.amount,
|
||||||
itemCode: SHIPPING_ITEM_CODE,
|
itemCode: SHIPPING_ITEM_CODE,
|
||||||
|
|
|
@ -16,7 +16,7 @@ export class AvataxAuthValidationService {
|
||||||
const result = await this.avataxClient.ping();
|
const result = await this.avataxClient.ping();
|
||||||
|
|
||||||
if (!result.authenticated) {
|
if (!result.authenticated) {
|
||||||
throw new Error("Invalid Avatax credentials.");
|
throw new Error("Invalid AvaTax credentials.");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorResolver = new AvataxValidationErrorResolver();
|
const errorResolver = new AvataxValidationErrorResolver();
|
||||||
|
|
|
@ -27,9 +27,9 @@ describe("AvataxValidationErrorResolver", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(Error);
|
expect(result).toBeInstanceOf(Error);
|
||||||
expect(result.message).toBe("Invalid Avatax credentials.");
|
expect(result.message).toBe("Invalid AvaTax credentials.");
|
||||||
});
|
});
|
||||||
it("when other Avatax error, should return error with first message", () => {
|
it("when other AvaTax error, should return error with first message", () => {
|
||||||
const result = errorResolver.resolve({
|
const result = errorResolver.resolve({
|
||||||
code: "error",
|
code: "error",
|
||||||
details: [
|
details: [
|
||||||
|
@ -57,6 +57,6 @@ describe("AvataxValidationErrorResolver", () => {
|
||||||
const result = errorResolver.resolve("error");
|
const result = errorResolver.resolve("error");
|
||||||
|
|
||||||
expect(result).toBeInstanceOf(Error);
|
expect(result).toBeInstanceOf(Error);
|
||||||
expect(result.message).toBe("Unknown error while validating Avatax configuration.");
|
expect(result.message).toBe("Unknown error while validating AvaTax configuration.");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,12 +26,12 @@ export class AvataxValidationErrorResolver {
|
||||||
const parseResult = avataxErrorSchema.safeParse(error);
|
const parseResult = avataxErrorSchema.safeParse(error);
|
||||||
const isErrorParsed = parseResult.success;
|
const isErrorParsed = parseResult.success;
|
||||||
|
|
||||||
// Avatax doesn't return a type for their error format, so we need to parse the error
|
// AvaTax doesn't return a type for their error format, so we need to parse the error
|
||||||
if (isErrorParsed) {
|
if (isErrorParsed) {
|
||||||
const { code, details } = parseResult.data;
|
const { code, details } = parseResult.data;
|
||||||
|
|
||||||
if (code === "AuthenticationException") {
|
if (code === "AuthenticationException") {
|
||||||
return new Error("Invalid Avatax credentials.");
|
return new Error("Invalid AvaTax credentials.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Error(details[0].message);
|
return new Error(details[0].message);
|
||||||
|
@ -41,7 +41,7 @@ export class AvataxValidationErrorResolver {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.error("Unknown error while validating Avatax configuration.");
|
this.logger.error("Unknown error while validating AvaTax configuration.");
|
||||||
return new Error("Unknown error while validating Avatax configuration.");
|
return new Error("Unknown error while validating AvaTax configuration.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ export class PublicAvataxConnectionService {
|
||||||
const connections = await this.connectionService.getAll();
|
const connections = await this.connectionService.getAll();
|
||||||
|
|
||||||
if (connections.length === 0) {
|
if (connections.length === 0) {
|
||||||
throw new Error("No Avatax connections found");
|
throw new Error("No AvaTax connections found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,12 @@ export class AvataxOrderCancelledAdapter implements WebhookAdapter<OrderCancelle
|
||||||
}
|
}
|
||||||
|
|
||||||
async send(payload: OrderCancelledPayload) {
|
async send(payload: OrderCancelledPayload) {
|
||||||
this.logger.debug("Transforming the Saleor payload for cancelling transaction with Avatax...");
|
this.logger.debug("Transforming the Saleor payload for cancelling transaction with AvaTax...");
|
||||||
|
|
||||||
const payloadTransformer = new AvataxOrderCancelledPayloadTransformer(this.config);
|
const payloadTransformer = new AvataxOrderCancelledPayloadTransformer(this.config);
|
||||||
const target = payloadTransformer.transform({ ...payload });
|
const target = payloadTransformer.transform({ ...payload });
|
||||||
|
|
||||||
this.logger.debug("Calling Avatax voidTransaction with transformed payload...");
|
this.logger.debug("Calling AvaTax voidTransaction with transformed payload...");
|
||||||
|
|
||||||
const client = new AvataxClient(this.config);
|
const client = new AvataxClient(this.config);
|
||||||
|
|
||||||
|
|
|
@ -23,22 +23,22 @@ export class AvataxOrderConfirmedAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
async send(payload: AvataxOrderConfirmedPayload): Promise<AvataxOrderConfirmedResponse> {
|
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 AvataxOrderConfirmedPayloadService(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...");
|
||||||
|
|
||||||
const client = new AvataxClient(this.config);
|
const client = new AvataxClient(this.config);
|
||||||
const response = await client.createTransaction(target);
|
const response = await client.createTransaction(target);
|
||||||
|
|
||||||
this.logger.debug("Avatax createTransaction successfully responded");
|
this.logger.debug("AvaTax createTransaction successfully responded");
|
||||||
|
|
||||||
const responseTransformer = new AvataxOrderConfirmedResponseTransformer();
|
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");
|
||||||
|
|
||||||
return transformedResponse;
|
return transformedResponse;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ export class AvataxOrderConfirmedPayloadLinesTransformer {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (order.shippingPrice.net.amount !== 0) {
|
if (order.shippingPrice.net.amount !== 0) {
|
||||||
// * In Avatax, shipping is a regular line
|
// * In AvaTax, shipping is a regular line
|
||||||
const shippingLine: LineItemModel = {
|
const shippingLine: LineItemModel = {
|
||||||
amount: order.shippingPrice.gross.amount,
|
amount: order.shippingPrice.gross.amount,
|
||||||
taxIncluded: true,
|
taxIncluded: true,
|
||||||
|
|
|
@ -48,7 +48,7 @@ export class AvataxOrderConfirmedPayloadTransformer {
|
||||||
entityUseCode,
|
entityUseCode,
|
||||||
customerCode:
|
customerCode:
|
||||||
order.user?.id ??
|
order.user?.id ??
|
||||||
"" /* In Saleor Avatax plugin, the customer code is 0. In Taxes App, we set it to the user id. */,
|
"" /* In Saleor AvaTax plugin, the customer code is 0. In Taxes App, we set it to the user id. */,
|
||||||
companyCode: avataxConfig.companyCode ?? defaultAvataxConfig.companyCode,
|
companyCode: avataxConfig.companyCode ?? defaultAvataxConfig.companyCode,
|
||||||
// * commit: If true, the transaction will be committed immediately after it is created. See: https://developer.avalara.com/communications/dev-guide_rest_v2/commit-uncommit
|
// * commit: If true, the transaction will be committed immediately after it is created. See: https://developer.avalara.com/communications/dev-guide_rest_v2/commit-uncommit
|
||||||
commit: avataxConfig.isAutocommit,
|
commit: avataxConfig.isAutocommit,
|
||||||
|
|
|
@ -8,7 +8,7 @@ export class AvataxOrderConfirmedResponseTransformer {
|
||||||
id: taxProviderUtils.resolveOptionalOrThrow(
|
id: taxProviderUtils.resolveOptionalOrThrow(
|
||||||
response.code,
|
response.code,
|
||||||
new Error(
|
new Error(
|
||||||
"Could not update the order metadata with Avatax transaction code because it was not returned from the createTransaction mutation."
|
"Could not update the order metadata with AvaTax transaction code because it was not returned from the createTransaction mutation."
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,22 +24,22 @@ export class AvataxOrderCreatedAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
async send(payload: AvataxOrderCreatedPayload): Promise<AvataxOrderCreatedResponse> {
|
async send(payload: AvataxOrderCreatedPayload): Promise<AvataxOrderCreatedResponse> {
|
||||||
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 AvataxOrderCreatedPayloadService(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...");
|
||||||
|
|
||||||
const client = new AvataxClient(this.config);
|
const client = new AvataxClient(this.config);
|
||||||
const response = await client.createTransaction(target);
|
const response = await client.createTransaction(target);
|
||||||
|
|
||||||
this.logger.debug("Avatax createTransaction successfully responded");
|
this.logger.debug("AvaTax createTransaction successfully responded");
|
||||||
|
|
||||||
const responseTransformer = new AvataxOrderCreatedResponseTransformer();
|
const responseTransformer = new AvataxOrderCreatedResponseTransformer();
|
||||||
const transformedResponse = responseTransformer.transform(response);
|
const transformedResponse = responseTransformer.transform(response);
|
||||||
|
|
||||||
this.logger.debug("Transformed Avatax createTransaction response");
|
this.logger.debug("Transformed AvaTax createTransaction response");
|
||||||
|
|
||||||
return transformedResponse;
|
return transformedResponse;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ export class AvataxOrderCreatedPayloadLinesTransformer {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (order.shippingPrice.net.amount !== 0) {
|
if (order.shippingPrice.net.amount !== 0) {
|
||||||
// * In Avatax, shipping is a regular line
|
// * In AvaTax, shipping is a regular line
|
||||||
const shippingLine: LineItemModel = {
|
const shippingLine: LineItemModel = {
|
||||||
amount: order.shippingPrice.gross.amount,
|
amount: order.shippingPrice.gross.amount,
|
||||||
taxIncluded: true,
|
taxIncluded: true,
|
||||||
|
|
|
@ -48,7 +48,7 @@ export class AvataxOrderCreatedPayloadTransformer {
|
||||||
code,
|
code,
|
||||||
customerCode:
|
customerCode:
|
||||||
order.user?.id ??
|
order.user?.id ??
|
||||||
"" /* In Saleor Avatax plugin, the customer code is 0. In Taxes App, we set it to the user id. */,
|
"" /* In Saleor AvaTax plugin, the customer code is 0. In Taxes App, we set it to the user id. */,
|
||||||
companyCode: avataxConfig.companyCode,
|
companyCode: avataxConfig.companyCode,
|
||||||
// * commit: If true, the transaction will be committed immediately after it is created. See: https://developer.avalara.com/communications/dev-guide_rest_v2/commit-uncommit
|
// * commit: If true, the transaction will be committed immediately after it is created. See: https://developer.avalara.com/communications/dev-guide_rest_v2/commit-uncommit
|
||||||
commit: avataxConfig.isAutocommit,
|
commit: avataxConfig.isAutocommit,
|
||||||
|
|
|
@ -8,7 +8,7 @@ export class AvataxOrderCreatedResponseTransformer {
|
||||||
id: taxProviderUtils.resolveOptionalOrThrow(
|
id: taxProviderUtils.resolveOptionalOrThrow(
|
||||||
response.code,
|
response.code,
|
||||||
new Error(
|
new Error(
|
||||||
"Could not update the order metadata with Avatax transaction code because it was not returned from the createTransaction mutation."
|
"Could not update the order metadata with AvaTax transaction code because it was not returned from the createTransaction mutation."
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,22 +22,22 @@ export class AvataxOrderFulfilledAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
async send(payload: AvataxOrderFulfilledPayload): Promise<AvataxOrderFulfilledResponse> {
|
async send(payload: AvataxOrderFulfilledPayload): Promise<AvataxOrderFulfilledResponse> {
|
||||||
this.logger.debug("Transforming the Saleor payload for commiting transaction with Avatax...");
|
this.logger.debug("Transforming the Saleor payload for commiting transaction with AvaTax...");
|
||||||
|
|
||||||
const payloadTransformer = new AvataxOrderFulfilledPayloadTransformer(this.config);
|
const payloadTransformer = new AvataxOrderFulfilledPayloadTransformer(this.config);
|
||||||
const target = payloadTransformer.transform({ ...payload });
|
const target = payloadTransformer.transform({ ...payload });
|
||||||
|
|
||||||
this.logger.debug("Calling Avatax commitTransaction with transformed payload...");
|
this.logger.debug("Calling AvaTax commitTransaction with transformed payload...");
|
||||||
|
|
||||||
const client = new AvataxClient(this.config);
|
const client = new AvataxClient(this.config);
|
||||||
const response = await client.commitTransaction(target);
|
const response = await client.commitTransaction(target);
|
||||||
|
|
||||||
this.logger.debug("Avatax commitTransaction succesfully responded");
|
this.logger.debug("AvaTax commitTransaction succesfully responded");
|
||||||
|
|
||||||
const responseTransformer = new AvataxOrderFulfilledResponseTransformer();
|
const responseTransformer = new AvataxOrderFulfilledResponseTransformer();
|
||||||
const transformedResponse = responseTransformer.transform(response);
|
const transformedResponse = responseTransformer.transform(response);
|
||||||
|
|
||||||
this.logger.debug("Transformed Avatax commitTransaction response");
|
this.logger.debug("Transformed AvaTax commitTransaction response");
|
||||||
|
|
||||||
return transformedResponse;
|
return transformedResponse;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ const MOCK_AVATAX_CONFIG: AvataxConfig = {
|
||||||
isDocumentRecordingEnabled: true,
|
isDocumentRecordingEnabled: true,
|
||||||
isAutocommit: false,
|
isAutocommit: false,
|
||||||
isSandbox: true,
|
isSandbox: true,
|
||||||
name: "Avatax-1",
|
name: "AvaTax-1",
|
||||||
shippingTaxCode: "FR000000",
|
shippingTaxCode: "FR000000",
|
||||||
address: {
|
address: {
|
||||||
country: "US",
|
country: "US",
|
||||||
|
|
|
@ -55,7 +55,6 @@ export const AvataxConfigurationCredentialsFragment = (
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FormSection title="Credentials">
|
<FormSection title="Credentials">
|
||||||
<Box paddingY={4} display={"flex"} flexDirection={"column"} gap={10}>
|
|
||||||
<div>
|
<div>
|
||||||
<Input
|
<Input
|
||||||
control={control}
|
control={control}
|
||||||
|
@ -65,8 +64,8 @@ export const AvataxConfigurationCredentialsFragment = (
|
||||||
helperText={formState.errors.credentials?.username?.message}
|
helperText={formState.errors.credentials?.username?.message}
|
||||||
/>
|
/>
|
||||||
<HelperText>
|
<HelperText>
|
||||||
You can obtain it in the <i>API Keys</i> section of <i>Settings</i> → <i>License</i>{" "}
|
You can obtain it in the <i>API Keys</i> section of <i>Settings</i> → <i>License</i> in
|
||||||
in your Avalara Dashboard.
|
your Avalara Dashboard.
|
||||||
</HelperText>
|
</HelperText>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -79,20 +78,19 @@ export const AvataxConfigurationCredentialsFragment = (
|
||||||
helperText={formState.errors.credentials?.password?.message}
|
helperText={formState.errors.credentials?.password?.message}
|
||||||
/>
|
/>
|
||||||
<HelperText>
|
<HelperText>
|
||||||
You can obtain it in the <i>API Keys</i> section of <i>Settings</i> → <i>License</i>{" "}
|
You can obtain it in the <i>API Keys</i> section of <i>Settings</i> → <i>License</i> in
|
||||||
in your Avalara Dashboard.
|
your Avalara Dashboard.
|
||||||
</HelperText>
|
</HelperText>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Input
|
<Input
|
||||||
control={control}
|
control={control}
|
||||||
name="companyCode"
|
name="companyCode"
|
||||||
label="Company name"
|
label="Company code"
|
||||||
helperText={formState.errors.companyCode?.message}
|
helperText={formState.errors.companyCode?.message}
|
||||||
/>
|
/>
|
||||||
<HelperText>
|
<HelperText>
|
||||||
When not provided, the default company will be used.{" "}
|
When not provided, the default company code will be used.{" "}
|
||||||
<TextLink
|
<TextLink
|
||||||
newTab
|
newTab
|
||||||
href="https://developer.avalara.com/erp-integration-guide/sales-tax-badge/transactions/simple-transactions/company-codes/"
|
href="https://developer.avalara.com/erp-integration-guide/sales-tax-badge/transactions/simple-transactions/company-codes/"
|
||||||
|
@ -102,60 +100,23 @@ export const AvataxConfigurationCredentialsFragment = (
|
||||||
about company codes.
|
about company codes.
|
||||||
</HelperText>
|
</HelperText>
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
|
||||||
<Box paddingY={4} display={"flex"} flexDirection={"column"} gap={10}>
|
|
||||||
<AppToggle
|
<AppToggle
|
||||||
control={control}
|
control={control}
|
||||||
label="Use sandbox mode"
|
label="Use sandbox mode"
|
||||||
helperText={
|
helperText={
|
||||||
<HelperText>
|
<HelperText>
|
||||||
Toggling between{" "}
|
Choose between
|
||||||
<TextLink
|
<TextLink
|
||||||
href="https://developer.avalara.com/erp-integration-guide/sales-tax-badge/authentication-in-avatax/sandbox-vs-production/"
|
href="https://developer.avalara.com/erp-integration-guide/sales-tax-badge/authentication-in-avatax/sandbox-vs-production/"
|
||||||
newTab
|
newTab
|
||||||
>
|
>
|
||||||
<q>Production</q> and <q>Sandbox</q>
|
<q>Production</q> and <q>Sandbox</q>
|
||||||
</TextLink>{" "}
|
</TextLink>{" "}
|
||||||
environment.
|
environment according to your credentials.
|
||||||
</HelperText>
|
</HelperText>
|
||||||
}
|
}
|
||||||
name="isSandbox"
|
name="isSandbox"
|
||||||
/>
|
/>
|
||||||
<AppToggle
|
|
||||||
control={control}
|
|
||||||
label="Document recording"
|
|
||||||
helperText={
|
|
||||||
<HelperText>
|
|
||||||
When turned off, the document type will always be set to <i>SalesOrder</i>. This
|
|
||||||
means the transactions will not be recorded in Avatax. Read more{" "}
|
|
||||||
<TextLink
|
|
||||||
href="https://developer.avalara.com/ecommerce-integration-guide/sales-tax-badge/designing/disable-document-recording/"
|
|
||||||
newTab
|
|
||||||
>
|
|
||||||
here
|
|
||||||
</TextLink>
|
|
||||||
.
|
|
||||||
</HelperText>
|
|
||||||
}
|
|
||||||
name="isDocumentRecordingEnabled"
|
|
||||||
/>
|
|
||||||
<AppToggle
|
|
||||||
control={control}
|
|
||||||
label="Autocommit"
|
|
||||||
helperText={
|
|
||||||
<HelperText>
|
|
||||||
If enabled, the order will be automatically{" "}
|
|
||||||
<TextLink
|
|
||||||
href="https://developer.avalara.com/communications/dev-guide_rest_v2/commit-uncommit/"
|
|
||||||
newTab
|
|
||||||
>
|
|
||||||
commited to Avalara.
|
|
||||||
</TextLink>{" "}
|
|
||||||
</HelperText>
|
|
||||||
}
|
|
||||||
name="isAutocommit"
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</FormSection>
|
</FormSection>
|
||||||
<Box display="flex" justifyContent={"flex-end"}>
|
<Box display="flex" justifyContent={"flex-end"}>
|
||||||
<Button variant="secondary" onClick={verifyCredentials}>
|
<Button variant="secondary" onClick={verifyCredentials}>
|
||||||
|
|
|
@ -14,9 +14,9 @@ import {
|
||||||
} from "../avatax-connection-schema";
|
} from "../avatax-connection-schema";
|
||||||
import { AvataxConfigurationAddressFragment } from "./avatax-configuration-address-fragment";
|
import { AvataxConfigurationAddressFragment } from "./avatax-configuration-address-fragment";
|
||||||
import { AvataxConfigurationCredentialsFragment } from "./avatax-configuration-credentials-fragment";
|
import { AvataxConfigurationCredentialsFragment } from "./avatax-configuration-credentials-fragment";
|
||||||
import { AvataxConfigurationTaxesFragment } from "./avatax-configuration-taxes-fragment";
|
import { AvataxConfigurationSettingsFragment } from "./avatax-configuration-settings-fragment";
|
||||||
import { HelperText } from "./form-helper-text";
|
|
||||||
import { useAvataxConfigurationStatus } from "./configuration-status";
|
import { useAvataxConfigurationStatus } from "./configuration-status";
|
||||||
|
import { HelperText } from "./form-helper-text";
|
||||||
|
|
||||||
type AvataxConfigurationFormProps = {
|
type AvataxConfigurationFormProps = {
|
||||||
submit: {
|
submit: {
|
||||||
|
@ -76,13 +76,13 @@ export const AvataxConfigurationForm = (props: AvataxConfigurationFormProps) =>
|
||||||
isLoading={props.validateCredentials.isLoading}
|
isLoading={props.validateCredentials.isLoading}
|
||||||
/>
|
/>
|
||||||
<Divider marginY={8} />
|
<Divider marginY={8} />
|
||||||
|
<AvataxConfigurationSettingsFragment />
|
||||||
|
<Divider marginY={8} />
|
||||||
<AvataxConfigurationAddressFragment
|
<AvataxConfigurationAddressFragment
|
||||||
onValidateAddress={props.validateAddress.handleFn}
|
onValidateAddress={props.validateAddress.handleFn}
|
||||||
isLoading={props.validateAddress.isLoading}
|
isLoading={props.validateAddress.isLoading}
|
||||||
/>
|
/>
|
||||||
<Divider marginY={8} />
|
<Divider marginY={8} />
|
||||||
<AvataxConfigurationTaxesFragment />
|
|
||||||
<Divider marginY={8} />
|
|
||||||
|
|
||||||
<Box display={"flex"} justifyContent={"space-between"} alignItems={"center"}>
|
<Box display={"flex"} justifyContent={"space-between"} alignItems={"center"}>
|
||||||
{props.leftButton}
|
{props.leftButton}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { TextLink } from "@saleor/apps-ui";
|
||||||
|
import { Input } from "@saleor/react-hook-form-macaw";
|
||||||
|
import { useFormContext } from "react-hook-form";
|
||||||
|
import { AppToggle } from "../../ui/app-toggle";
|
||||||
|
import { AvataxConfig } from "../avatax-connection-schema";
|
||||||
|
import { useAvataxConfigurationStatus } from "./configuration-status";
|
||||||
|
import { HelperText } from "./form-helper-text";
|
||||||
|
import { FormSection } from "./form-section";
|
||||||
|
|
||||||
|
export const AvataxConfigurationSettingsFragment = () => {
|
||||||
|
const { control, formState } = useFormContext<AvataxConfig>();
|
||||||
|
const { status } = useAvataxConfigurationStatus();
|
||||||
|
|
||||||
|
const disabled = status === "not_authenticated";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormSection title="Settings" disabled={disabled}>
|
||||||
|
<AppToggle
|
||||||
|
control={control}
|
||||||
|
label="Document recording"
|
||||||
|
disabled={disabled}
|
||||||
|
helperText={
|
||||||
|
<HelperText>
|
||||||
|
When turned off, the document type will always be set to <i>SalesOrder</i>. This means
|
||||||
|
the transactions will not be recorded in AvaTax. Read more{" "}
|
||||||
|
<TextLink
|
||||||
|
href="https://developer.avalara.com/ecommerce-integration-guide/sales-tax-badge/designing/disable-document-recording/"
|
||||||
|
newTab
|
||||||
|
>
|
||||||
|
here
|
||||||
|
</TextLink>
|
||||||
|
.
|
||||||
|
</HelperText>
|
||||||
|
}
|
||||||
|
name="isDocumentRecordingEnabled"
|
||||||
|
/>
|
||||||
|
<AppToggle
|
||||||
|
control={control}
|
||||||
|
label="Autocommit"
|
||||||
|
disabled={disabled}
|
||||||
|
helperText={
|
||||||
|
<HelperText>
|
||||||
|
If enabled, the order will be automatically{" "}
|
||||||
|
<TextLink
|
||||||
|
href="https://developer.avalara.com/communications/dev-guide_rest_v2/commit-uncommit/"
|
||||||
|
newTab
|
||||||
|
>
|
||||||
|
commited to Avalara.
|
||||||
|
</TextLink>{" "}
|
||||||
|
</HelperText>
|
||||||
|
}
|
||||||
|
name="isAutocommit"
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<Input
|
||||||
|
disabled={disabled}
|
||||||
|
control={control}
|
||||||
|
name="shippingTaxCode"
|
||||||
|
label="Shipping tax code"
|
||||||
|
helperText={formState.errors.shippingTaxCode?.message}
|
||||||
|
/>
|
||||||
|
<HelperText disabled={disabled}>
|
||||||
|
Tax code that for the shipping line sent to AvaTax.{" "}
|
||||||
|
<TextLink newTab href="https://taxcode.avatax.avalara.com">
|
||||||
|
Must match AvaTax tax codes format.
|
||||||
|
</TextLink>
|
||||||
|
</HelperText>
|
||||||
|
</div>
|
||||||
|
</FormSection>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,34 +0,0 @@
|
||||||
import { TextLink } from "@saleor/apps-ui";
|
|
||||||
import { Input } from "@saleor/react-hook-form-macaw";
|
|
||||||
import React from "react";
|
|
||||||
import { useFormContext } from "react-hook-form";
|
|
||||||
import { AvataxConfig } from "../avatax-connection-schema";
|
|
||||||
import { HelperText } from "./form-helper-text";
|
|
||||||
import { FormSection } from "./form-section";
|
|
||||||
import { useAvataxConfigurationStatus } from "./configuration-status";
|
|
||||||
|
|
||||||
export const AvataxConfigurationTaxesFragment = () => {
|
|
||||||
const { control, formState } = useFormContext<AvataxConfig>();
|
|
||||||
const { status } = useAvataxConfigurationStatus();
|
|
||||||
const disabled = status === "not_authenticated";
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FormSection title="Tax codes" disabled={disabled}>
|
|
||||||
<div>
|
|
||||||
<Input
|
|
||||||
disabled={disabled}
|
|
||||||
control={control}
|
|
||||||
name="shippingTaxCode"
|
|
||||||
label="Shipping tax code"
|
|
||||||
helperText={formState.errors.shippingTaxCode?.message}
|
|
||||||
/>
|
|
||||||
<HelperText disabled={disabled}>
|
|
||||||
Tax code that for the shipping line sent to Avatax.{" "}
|
|
||||||
<TextLink newTab href="https://taxcode.avatax.avalara.com">
|
|
||||||
Must match Avatax tax codes format.
|
|
||||||
</TextLink>
|
|
||||||
</HelperText>
|
|
||||||
</div>
|
|
||||||
</FormSection>
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -5,7 +5,7 @@ import { Section } from "../../ui/app-section";
|
||||||
export const AvataxInstructions = () => {
|
export const AvataxInstructions = () => {
|
||||||
return (
|
return (
|
||||||
<Section.Description
|
<Section.Description
|
||||||
title="Avatax Configuration"
|
title="AvaTax Configuration"
|
||||||
description={
|
description={
|
||||||
<>
|
<>
|
||||||
<Text as="p" marginBottom={8}>
|
<Text as="p" marginBottom={8}>
|
||||||
|
@ -49,7 +49,7 @@ export const AvataxInstructions = () => {
|
||||||
</Text>
|
</Text>
|
||||||
<Text as="p" marginBottom={4}>
|
<Text as="p" marginBottom={4}>
|
||||||
Verifying the Address will display suggestions that reflect the resolution of the
|
Verifying the Address will display suggestions that reflect the resolution of the
|
||||||
address by Avatax address validation service. Applying the suggestions is not required
|
address by AvaTax address validation service. Applying the suggestions is not required
|
||||||
but recommended. If the address is not valid, the calculation of taxes will fail.
|
but recommended. If the address is not valid, the calculation of taxes will fail.
|
||||||
</Text>
|
</Text>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -31,7 +31,7 @@ const useGetTaxCodes = () => {
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
notifyError("Error", "Unable to fetch Avatax tax codes.");
|
notifyError("Error", "Unable to fetch AvaTax tax codes.");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
router.push("/configuration");
|
router.push("/configuration");
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
@ -61,7 +61,7 @@ const SelectTaxCode = ({ taxClassId }: { taxClassId: string }) => {
|
||||||
|
|
||||||
const { mutate: updateMutation } = trpcClient.avataxMatches.upsert.useMutation({
|
const { mutate: updateMutation } = trpcClient.avataxMatches.upsert.useMutation({
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
notifySuccess("Success", "Updated Avatax tax code matches");
|
notifySuccess("Success", "Updated AvaTax tax code matches");
|
||||||
},
|
},
|
||||||
onError(error) {
|
onError(error) {
|
||||||
notifyError("Error", error.message);
|
notifyError("Error", error.message);
|
||||||
|
@ -113,7 +113,7 @@ export const AvataxTaxCodeMatcherTable = () => {
|
||||||
<Table.THead>
|
<Table.THead>
|
||||||
<Table.TR>
|
<Table.TR>
|
||||||
<Table.TH>Saleor tax class</Table.TH>
|
<Table.TH>Saleor tax class</Table.TH>
|
||||||
<Table.TH>Avatax tax code</Table.TH>
|
<Table.TH>AvaTax tax code</Table.TH>
|
||||||
</Table.TR>
|
</Table.TR>
|
||||||
</Table.THead>
|
</Table.THead>
|
||||||
<Table.TBody>
|
<Table.TBody>
|
||||||
|
|
|
@ -31,7 +31,7 @@ export const EditAvataxConfiguration = () => {
|
||||||
const { mutate: patchMutation, isLoading: isPatchLoading } =
|
const { mutate: patchMutation, isLoading: isPatchLoading } =
|
||||||
trpcClient.avataxConnection.update.useMutation({
|
trpcClient.avataxConnection.update.useMutation({
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
notifySuccess("Success", "Updated Avatax configuration");
|
notifySuccess("Success", "Updated AvaTax configuration");
|
||||||
refetchProvidersConfigurationData();
|
refetchProvidersConfigurationData();
|
||||||
},
|
},
|
||||||
onError(error) {
|
onError(error) {
|
||||||
|
@ -42,7 +42,7 @@ export const EditAvataxConfiguration = () => {
|
||||||
const { mutate: deleteMutation, isLoading: isDeleteLoading } =
|
const { mutate: deleteMutation, isLoading: isDeleteLoading } =
|
||||||
trpcClient.avataxConnection.delete.useMutation({
|
trpcClient.avataxConnection.delete.useMutation({
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
notifySuccess("Success", "Deleted Avatax configuration");
|
notifySuccess("Success", "Deleted AvaTax configuration");
|
||||||
refetchProvidersConfigurationData();
|
refetchProvidersConfigurationData();
|
||||||
router.push("/configuration");
|
router.push("/configuration");
|
||||||
},
|
},
|
||||||
|
|
5
apps/taxes/src/modules/avatax/ui/form-section.module.css
Normal file
5
apps/taxes/src/modules/avatax/ui/form-section.module.css
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/* when formSection is disabled, change the color of the a element: */
|
||||||
|
.formSection[disabled] a,
|
||||||
|
.formSection[disabled] a span {
|
||||||
|
color: inherit;
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
import { Box, Text } from "@saleor/macaw-ui/next";
|
import { Box, Text } from "@saleor/macaw-ui/next";
|
||||||
import React, { PropsWithChildren } from "react";
|
import React, { PropsWithChildren } from "react";
|
||||||
|
import styles from "./form-section.module.css";
|
||||||
|
|
||||||
export const FormSection = ({
|
export const FormSection = ({
|
||||||
title,
|
title,
|
||||||
|
@ -8,7 +9,14 @@ export const FormSection = ({
|
||||||
disabled = false,
|
disabled = false,
|
||||||
}: PropsWithChildren<{ title: string; subtitle?: string; disabled?: boolean }>) => {
|
}: PropsWithChildren<{ title: string; subtitle?: string; disabled?: boolean }>) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<Box
|
||||||
|
as={"fieldset"}
|
||||||
|
className={styles.formSection}
|
||||||
|
disabled={disabled}
|
||||||
|
__borderWidth={0}
|
||||||
|
padding={0}
|
||||||
|
margin={0}
|
||||||
|
>
|
||||||
<Text
|
<Text
|
||||||
marginBottom={4}
|
marginBottom={4}
|
||||||
as="h3"
|
as="h3"
|
||||||
|
@ -25,6 +33,6 @@ export const FormSection = ({
|
||||||
<Box display="grid" gridTemplateColumns={2} gap={12}>
|
<Box display="grid" gridTemplateColumns={2} gap={12}>
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,7 +35,7 @@ class ActiveTaxProviderService implements ProviderWebhookService {
|
||||||
}
|
}
|
||||||
|
|
||||||
case "avatax": {
|
case "avatax": {
|
||||||
this.logger.debug("Selecting Avatax as tax provider");
|
this.logger.debug("Selecting AvaTax as tax provider");
|
||||||
this.client = new AvataxWebhookService(providerConnection.config, this.authData);
|
this.client = new AvataxWebhookService(providerConnection.config, this.authData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,14 +54,14 @@ const breadcrumbsForRoute: Record<string, Breadcrumb[]> = {
|
||||||
"/providers/avatax": [
|
"/providers/avatax": [
|
||||||
...newProviderBreadcrumbs,
|
...newProviderBreadcrumbs,
|
||||||
{
|
{
|
||||||
label: "Avatax",
|
label: "AvaTax",
|
||||||
href: "/providers/avatax",
|
href: "/providers/avatax",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"/providers/avatax/matcher": [
|
"/providers/avatax/matcher": [
|
||||||
...newProviderBreadcrumbs,
|
...newProviderBreadcrumbs,
|
||||||
{
|
{
|
||||||
label: "Avatax",
|
label: "AvaTax",
|
||||||
href: "/providers/avatax",
|
href: "/providers/avatax",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -72,7 +72,7 @@ const breadcrumbsForRoute: Record<string, Breadcrumb[]> = {
|
||||||
"/providers/avatax/[id]": [
|
"/providers/avatax/[id]": [
|
||||||
...newProviderBreadcrumbs,
|
...newProviderBreadcrumbs,
|
||||||
{
|
{
|
||||||
label: "Editing Avatax provider",
|
label: "Editing AvaTax provider",
|
||||||
href: "/providers/avatax",
|
href: "/providers/avatax",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -11,7 +11,7 @@ const providerConfig = {
|
||||||
icon: TaxJarIcon,
|
icon: TaxJarIcon,
|
||||||
},
|
},
|
||||||
avatax: {
|
avatax: {
|
||||||
label: "Avatax",
|
label: "AvaTax",
|
||||||
icon: AvataxIcon,
|
icon: AvataxIcon,
|
||||||
},
|
},
|
||||||
stripeTax: {
|
stripeTax: {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { AppColumns } from "../../../modules/ui/app-columns";
|
||||||
import { Section } from "../../../modules/ui/app-section";
|
import { Section } from "../../../modules/ui/app-section";
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
return <Section.Header>Edit your existing Avatax configuration</Section.Header>;
|
return <Section.Header>Edit your existing AvaTax configuration</Section.Header>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const EditAvataxPage = () => {
|
const EditAvataxPage = () => {
|
||||||
|
|
|
@ -8,7 +8,7 @@ const Header = () => {
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Text as="p" variant="body">
|
<Text as="p" variant="body">
|
||||||
Create new Avatax configuration
|
Create new AvaTax configuration
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
|
@ -9,21 +9,21 @@ import { useRouter } from "next/router";
|
||||||
import { trpcClient } from "../../../modules/trpc/trpc-client";
|
import { trpcClient } from "../../../modules/trpc/trpc-client";
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
return <Section.Header>Match Saleor tax classes to Avatax tax codes</Section.Header>;
|
return <Section.Header>Match Saleor tax classes to AvaTax tax codes</Section.Header>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Description = () => {
|
const Description = () => {
|
||||||
return (
|
return (
|
||||||
<Section.Description
|
<Section.Description
|
||||||
title="Avatax tax code matcher"
|
title="AvaTax tax code matcher"
|
||||||
description={
|
description={
|
||||||
<>
|
<>
|
||||||
<Text display="block" as="span" marginBottom={4}>
|
<Text display="block" as="span" marginBottom={4}>
|
||||||
To extend the base tax rate of your products, you can map Saleor tax classes to Avatax
|
To extend the base tax rate of your products, you can map Saleor tax classes to AvaTax
|
||||||
tax codes.
|
tax codes.
|
||||||
</Text>
|
</Text>
|
||||||
<Text display="block" as="span" marginBottom={4}>
|
<Text display="block" as="span" marginBottom={4}>
|
||||||
This way, the product's Saleor tax class will be used to determine the Avatax tax
|
This way, the product's Saleor tax class will be used to determine the AvaTax tax
|
||||||
code needed to calculate the tax rate.
|
code needed to calculate the tax rate.
|
||||||
</Text>
|
</Text>
|
||||||
<Text as="p" marginBottom={4}>
|
<Text as="p" marginBottom={4}>
|
||||||
|
@ -37,9 +37,9 @@ const Description = () => {
|
||||||
view.
|
view.
|
||||||
</Text>
|
</Text>
|
||||||
<Text as="p" marginBottom={4}>
|
<Text as="p" marginBottom={4}>
|
||||||
To learn more about Avatax tax codes, please visit{" "}
|
To learn more about AvaTax tax codes, please visit{" "}
|
||||||
<TextLink href="https://taxcode.avatax.avalara.com/search?q=OF400000" newTab>
|
<TextLink href="https://taxcode.avatax.avalara.com/search?q=OF400000" newTab>
|
||||||
Avatax documentation
|
AvaTax documentation
|
||||||
</TextLink>
|
</TextLink>
|
||||||
.
|
.
|
||||||
</Text>
|
</Text>
|
||||||
|
@ -55,7 +55,7 @@ const AvataxMatcher = () => {
|
||||||
|
|
||||||
const { isLoading } = trpcClient.avataxConnection.verifyConnections.useQuery(undefined, {
|
const { isLoading } = trpcClient.avataxConnection.verifyConnections.useQuery(undefined, {
|
||||||
onError: () => {
|
onError: () => {
|
||||||
notifyError("Error", "You must configure Avatax first.");
|
notifyError("Error", "You must configure AvaTax first.");
|
||||||
router.push("/configuration");
|
router.push("/configuration");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -38,7 +38,7 @@ const providerConfig = {
|
||||||
avatax: {
|
avatax: {
|
||||||
description: (
|
description: (
|
||||||
<p>
|
<p>
|
||||||
Avatax is a comprehensive tax automation software service that helps businesses calculate
|
AvaTax is a comprehensive tax automation software service that helps businesses calculate
|
||||||
and manage sales tax accurately and efficiently.
|
and manage sales tax accurately and efficiently.
|
||||||
</p>
|
</p>
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue