feat: align avatax with plugin (#414)
* refactor: 🚚 OrderLineFragmentFragment -> OrderLineFragment * refactor: 🚚 getLine... to getTaxBaseLine... * refactor: ♻️ temporarily remove usage of getTaxBaseLineTaxCode * feat: ✨ add shipping as line to avatax-order-created * feat: ✨ add description to order-created lines * feat: ✨ add itemCode to avatax-order-created line * feat: ✅ add tests for avatax maps * feat: ✨ add basic discounts logic * docs: 🔥 remove comment * build: 👷 add changeset * fix: 🐛 shipping amount
This commit is contained in:
parent
aa27f9d6ef
commit
9eacc88b53
16 changed files with 426 additions and 50 deletions
5
.changeset/healthy-spies-camp.md
Normal file
5
.changeset/healthy-spies-camp.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"saleor-app-taxes": minor
|
||||
---
|
||||
|
||||
Map new fields from Saleor to Avatax (e.g. discounts, itemCode, description).
|
|
@ -1,4 +1,4 @@
|
|||
fragment OrderLineFragment on OrderLine {
|
||||
fragment OrderLine on OrderLine {
|
||||
productSku
|
||||
productName
|
||||
quantity
|
||||
|
@ -42,12 +42,21 @@ fragment OrderCreatedSubscription on Order {
|
|||
}
|
||||
}
|
||||
shippingPrice {
|
||||
gross {
|
||||
amount
|
||||
}
|
||||
net {
|
||||
amount
|
||||
}
|
||||
}
|
||||
lines {
|
||||
...OrderLineFragment
|
||||
...OrderLine
|
||||
}
|
||||
discounts {
|
||||
id
|
||||
amount {
|
||||
amount
|
||||
}
|
||||
}
|
||||
}
|
||||
fragment OrderCreatedEventSubscription on Event {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
fragment OrderLineFragment on OrderLine {
|
||||
fragment OrderLine on OrderLine {
|
||||
productSku
|
||||
productName
|
||||
quantity
|
||||
|
@ -46,7 +46,7 @@ fragment OrderFulfilledSubscription on Order {
|
|||
value
|
||||
}
|
||||
lines {
|
||||
...OrderLineFragment
|
||||
...OrderLine
|
||||
}
|
||||
}
|
||||
fragment OrderFulfilledEventSubscription on Event {
|
||||
|
|
|
@ -45,7 +45,7 @@ export class AvataxWebhookService implements ProviderWebhookService {
|
|||
|
||||
async createOrder(order: OrderCreatedSubscriptionFragment, channel: ChannelConfig) {
|
||||
this.logger.debug({ order, channel }, "createOrder called with:");
|
||||
const model = avataxOrderCreatedMaps.mapPayload(order, channel, this.config);
|
||||
const model = avataxOrderCreatedMaps.mapPayload({ order, channel, config: this.config });
|
||||
|
||||
this.logger.debug({ model }, "will call createTransaction with");
|
||||
const result = await this.client.createTransaction(model);
|
||||
|
@ -56,7 +56,7 @@ export class AvataxWebhookService implements ProviderWebhookService {
|
|||
|
||||
async fulfillOrder(order: OrderFulfilledSubscriptionFragment, channel: ChannelConfig) {
|
||||
this.logger.debug({ order, channel }, "fulfillOrder called with:");
|
||||
const args = avataxOrderFulfilledMaps.mapPayload(order, this.config);
|
||||
const args = avataxOrderFulfilledMaps.mapPayload({ order, config: this.config });
|
||||
|
||||
this.logger.debug({ args }, "will call commitTransaction with");
|
||||
const result = await this.client.commitTransaction(args);
|
||||
|
|
|
@ -4,12 +4,11 @@ import { TaxBaseFragment } from "../../../../generated/graphql";
|
|||
|
||||
import { DocumentType } from "avatax/lib/enums/DocumentType";
|
||||
import { ChannelConfig } from "../../channels-configuration/channels-config";
|
||||
import { taxLineResolver } from "../../taxes/tax-line-resolver";
|
||||
import { numbers } from "../../taxes/numbers";
|
||||
import { CalculateTaxesResponse } from "../../taxes/tax-provider-webhook";
|
||||
import { CreateTransactionArgs } from "../avatax-client";
|
||||
import { AvataxConfig } from "../avatax-config";
|
||||
import { avataxAddressFactory } from "./address-factory";
|
||||
import { numbers } from "../../taxes/numbers";
|
||||
|
||||
/**
|
||||
* * Shipping is a regular line item in Avatax
|
||||
|
@ -22,7 +21,7 @@ function mapLines(taxBase: TaxBaseFragment): LineItemModel[] {
|
|||
amount: line.unitPrice.amount,
|
||||
taxIncluded: line.chargeTaxes,
|
||||
// todo: get from tax code matcher
|
||||
taxCode: taxLineResolver.getLineTaxCode(line),
|
||||
taxCode: "",
|
||||
quantity: line.quantity,
|
||||
}));
|
||||
|
||||
|
|
|
@ -1,14 +1,190 @@
|
|||
import { describe, it } from "vitest";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { OrderStatus } from "../../../../generated/graphql";
|
||||
import {
|
||||
CreateTransactionMapPayloadArgs,
|
||||
avataxOrderCreatedMaps,
|
||||
} from "./avatax-order-created-map";
|
||||
|
||||
describe.skip("avataxOrderCreatedMaps", () => {
|
||||
const MOCKED_ORDER: CreateTransactionMapPayloadArgs = {
|
||||
order: {
|
||||
id: "T3JkZXI6OTU4MDA5YjQtNDUxZC00NmQ1LThhMWUtMTRkMWRmYjFhNzI5",
|
||||
created: "2023-04-11T11:03:09.304109+00:00",
|
||||
status: OrderStatus.Unfulfilled,
|
||||
user: {
|
||||
id: "VXNlcjo5ZjY3ZjY0Zi1iZjY5LTQ5ZjYtYjQ4Zi1iZjY3ZjY0ZjY0ZjY=",
|
||||
email: "tester@saleor.io",
|
||||
},
|
||||
channel: {
|
||||
id: "Q2hhbm5lbDoy",
|
||||
slug: "channel-pln",
|
||||
},
|
||||
shippingAddress: {
|
||||
streetAddress1: "123 Palm Grove Ln",
|
||||
streetAddress2: "",
|
||||
city: "LOS ANGELES",
|
||||
countryArea: "CA",
|
||||
postalCode: "90002",
|
||||
country: {
|
||||
code: "US",
|
||||
},
|
||||
},
|
||||
billingAddress: {
|
||||
streetAddress1: "123 Palm Grove Ln",
|
||||
streetAddress2: "",
|
||||
city: "LOS ANGELES",
|
||||
countryArea: "CA",
|
||||
postalCode: "90002",
|
||||
country: {
|
||||
code: "US",
|
||||
},
|
||||
},
|
||||
total: {
|
||||
net: {
|
||||
amount: 183.33,
|
||||
},
|
||||
tax: {
|
||||
amount: 12.83,
|
||||
},
|
||||
currency: "USD",
|
||||
},
|
||||
shippingPrice: {
|
||||
gross: {
|
||||
amount: 48.33,
|
||||
},
|
||||
net: {
|
||||
amount: 43.74,
|
||||
},
|
||||
},
|
||||
lines: [
|
||||
{
|
||||
productSku: "328223581",
|
||||
productName: "Monospace Tee",
|
||||
quantity: 1,
|
||||
unitPrice: {
|
||||
net: {
|
||||
amount: 90,
|
||||
},
|
||||
},
|
||||
totalPrice: {
|
||||
tax: {
|
||||
amount: 8.55,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
productSku: "328223580",
|
||||
productName: "Polyspace Tee",
|
||||
quantity: 1,
|
||||
unitPrice: {
|
||||
net: {
|
||||
amount: 45,
|
||||
},
|
||||
},
|
||||
totalPrice: {
|
||||
tax: {
|
||||
amount: 4.28,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
discounts: [
|
||||
{
|
||||
amount: {
|
||||
amount: 10,
|
||||
},
|
||||
id: "RGlzY291bnREaXNjb3VudDox",
|
||||
},
|
||||
{
|
||||
amount: {
|
||||
amount: 21.45,
|
||||
},
|
||||
id: "RGlzY291bnREaXNjb3VudDoy",
|
||||
},
|
||||
],
|
||||
},
|
||||
channel: {
|
||||
providerInstanceId: "b8c29f49-7cae-4762-8458-e9a27eb83081",
|
||||
enabled: false,
|
||||
address: {
|
||||
country: "US",
|
||||
zip: "92093",
|
||||
state: "CA",
|
||||
city: "La Jolla",
|
||||
street: "9500 Gilman Drive",
|
||||
},
|
||||
},
|
||||
config: {
|
||||
companyCode: "DEFAULT",
|
||||
isAutocommit: true,
|
||||
isSandbox: true,
|
||||
name: "Avatax-1",
|
||||
password: "user-password",
|
||||
username: "user-name",
|
||||
},
|
||||
};
|
||||
|
||||
describe("avataxOrderCreatedMaps", () => {
|
||||
describe.todo("mapResponse", () => {
|
||||
it.todo("calculation of fields");
|
||||
it.todo("formatting the fields");
|
||||
it.todo("rounding of numbers");
|
||||
});
|
||||
describe.todo("mapPayload", () => {
|
||||
describe("mapPayload", () => {
|
||||
it("returns lines with discounted: true when there are discounts", () => {
|
||||
const payload = avataxOrderCreatedMaps.mapPayload(MOCKED_ORDER);
|
||||
|
||||
const linesWithoutShipping = payload.model.lines.slice(0, -1);
|
||||
const check = linesWithoutShipping.every((line) => line.discounted === true);
|
||||
|
||||
expect(check).toBeTruthy();
|
||||
});
|
||||
it.todo("calculation of fields");
|
||||
it.todo("formatting the fields");
|
||||
it.todo("rounding of numbers");
|
||||
});
|
||||
describe("mapLines", () => {
|
||||
const lines = avataxOrderCreatedMaps.mapLines(MOCKED_ORDER.order);
|
||||
|
||||
it("returns the correct number of lines", () => {
|
||||
expect(lines).toHaveLength(3);
|
||||
});
|
||||
|
||||
it("includes shipping as a line", () => {
|
||||
expect(lines).toContainEqual({
|
||||
itemCode: avataxOrderCreatedMaps.consts.shippingItemCode,
|
||||
quantity: 1,
|
||||
amount: 48.33,
|
||||
});
|
||||
});
|
||||
|
||||
it("includes products as lines", () => {
|
||||
const [first, second] = lines;
|
||||
|
||||
expect(first).toContain({
|
||||
itemCode: "328223581",
|
||||
description: "Monospace Tee",
|
||||
quantity: 1,
|
||||
amount: 90,
|
||||
});
|
||||
expect(second).toContain({
|
||||
itemCode: "328223580",
|
||||
description: "Polyspace Tee",
|
||||
quantity: 1,
|
||||
amount: 45,
|
||||
});
|
||||
});
|
||||
});
|
||||
describe("mapDiscounts", () => {
|
||||
it("sums up all discounts", () => {
|
||||
const discounts = avataxOrderCreatedMaps.mapDiscounts(MOCKED_ORDER.order.discounts);
|
||||
|
||||
expect(discounts).toEqual(31.45);
|
||||
});
|
||||
|
||||
it("returns 0 if there are no discounts", () => {
|
||||
const discounts = avataxOrderCreatedMaps.mapDiscounts([]);
|
||||
|
||||
expect(discounts).toEqual(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,26 +8,64 @@ import { CreateTransactionArgs } from "../avatax-client";
|
|||
import { AvataxConfig } from "../avatax-config";
|
||||
import { avataxAddressFactory } from "./address-factory";
|
||||
|
||||
const mapLines = (order: OrderCreatedSubscriptionFragment): LineItemModel[] => {
|
||||
const productLines = order.lines.map((line) => ({
|
||||
/**
|
||||
* * Shipping is a regular line item in Avatax
|
||||
* https://developer.avalara.com/avatax/dev-guide/shipping-and-handling/taxability-of-shipping-charges/
|
||||
*/
|
||||
const SHIPPING_ITEM_CODE = "Shipping";
|
||||
|
||||
function mapLines(order: OrderCreatedSubscriptionFragment): LineItemModel[] {
|
||||
const productLines: LineItemModel[] = order.lines.map((line) => ({
|
||||
amount: line.unitPrice.net.amount,
|
||||
quantity: line.quantity,
|
||||
// todo: get from tax code matcher
|
||||
taxCode: "",
|
||||
quantity: line.quantity,
|
||||
description: line.productName,
|
||||
itemCode: line.productSku ?? "",
|
||||
discounted: order.discounts.length > 0,
|
||||
}));
|
||||
|
||||
return productLines;
|
||||
if (order.shippingPrice.net.amount !== 0) {
|
||||
// * In Avatax, shipping is a regular line
|
||||
const shippingLine: LineItemModel = {
|
||||
amount: order.shippingPrice.gross.amount,
|
||||
taxIncluded: true,
|
||||
itemCode: SHIPPING_ITEM_CODE,
|
||||
/**
|
||||
* todo: add taxCode
|
||||
* * Different shipping methods can have different tax codes.
|
||||
* https://developer.avalara.com/ecommerce-integration-guide/sales-tax-badge/designing/non-standard-items/\
|
||||
*/
|
||||
quantity: 1,
|
||||
};
|
||||
|
||||
const mapPayload = (
|
||||
order: OrderCreatedSubscriptionFragment,
|
||||
channel: ChannelConfig,
|
||||
config: AvataxConfig
|
||||
): CreateTransactionArgs => {
|
||||
return [...productLines, shippingLine];
|
||||
}
|
||||
|
||||
return productLines;
|
||||
}
|
||||
|
||||
function mapDiscounts(discounts: OrderCreatedSubscriptionFragment["discounts"]): number {
|
||||
return discounts.reduce((total, current) => total + Number(current.amount.amount), 0);
|
||||
}
|
||||
|
||||
export type CreateTransactionMapPayloadArgs = {
|
||||
order: OrderCreatedSubscriptionFragment;
|
||||
channel: ChannelConfig;
|
||||
config: AvataxConfig;
|
||||
};
|
||||
|
||||
const mapPayload = ({
|
||||
order,
|
||||
channel,
|
||||
config,
|
||||
}: CreateTransactionMapPayloadArgs): CreateTransactionArgs => {
|
||||
return {
|
||||
model: {
|
||||
type: DocumentType.SalesInvoice,
|
||||
customerCode: order.user?.id ?? "",
|
||||
customerCode:
|
||||
order.user?.id ??
|
||||
"" /* In Saleor Avatax plugin, the customer code is 0. In Taxes App, we set it to the user id. */,
|
||||
companyCode: config.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: config.isAutocommit,
|
||||
|
@ -40,6 +78,7 @@ const mapPayload = (
|
|||
email: order.user?.email ?? "",
|
||||
lines: mapLines(order),
|
||||
date: new Date(order.created),
|
||||
discount: mapDiscounts(order.discounts),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -53,4 +92,9 @@ const mapResponse = (response: TransactionModel): CreateOrderResponse => {
|
|||
export const avataxOrderCreatedMaps = {
|
||||
mapPayload,
|
||||
mapResponse,
|
||||
mapLines,
|
||||
mapDiscounts,
|
||||
consts: {
|
||||
shippingItemCode: SHIPPING_ITEM_CODE,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,14 +1,127 @@
|
|||
import { describe, it } from "vitest";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
CommitTransactionMapPayloadArgs,
|
||||
avataxOrderFulfilledMaps,
|
||||
} from "./avatax-order-fulfilled-map";
|
||||
import { OrderFulfilledSubscriptionFragment, OrderStatus } from "../../../../generated/graphql";
|
||||
import { DocumentType } from "avatax/lib/enums/DocumentType";
|
||||
|
||||
describe.skip("avataxOrderFulfilledMaps", () => {
|
||||
describe.todo("mapResponse", () => {
|
||||
it.todo("calculation of fields");
|
||||
it.todo("formatting the fields");
|
||||
it.todo("rounding of numbers");
|
||||
const MOCKED_METADATA: OrderFulfilledSubscriptionFragment["privateMetadata"] = [
|
||||
{
|
||||
key: avataxOrderFulfilledMaps.providerOrderIdKey,
|
||||
value: "transaction-code",
|
||||
},
|
||||
];
|
||||
|
||||
const MOCKED_MAP_PAYLOAD_ARGS: CommitTransactionMapPayloadArgs = {
|
||||
order: {
|
||||
id: "T3JkZXI6OTU4MDA5YjQtNDUxZC00NmQ1LThhMWUtMTRkMWRmYjFhNzI5",
|
||||
created: "2023-04-11T11:03:09.304109+00:00",
|
||||
privateMetadata: MOCKED_METADATA,
|
||||
channel: {
|
||||
id: "Q2hhbm5lbDoy",
|
||||
slug: "channel-pln",
|
||||
},
|
||||
shippingAddress: {
|
||||
streetAddress1: "123 Palm Grove Ln",
|
||||
streetAddress2: "",
|
||||
city: "LOS ANGELES",
|
||||
countryArea: "CA",
|
||||
postalCode: "90002",
|
||||
country: {
|
||||
code: "US",
|
||||
},
|
||||
},
|
||||
billingAddress: {
|
||||
streetAddress1: "123 Palm Grove Ln",
|
||||
streetAddress2: "",
|
||||
city: "LOS ANGELES",
|
||||
countryArea: "CA",
|
||||
postalCode: "90002",
|
||||
country: {
|
||||
code: "US",
|
||||
},
|
||||
},
|
||||
total: {
|
||||
net: {
|
||||
amount: 183.33,
|
||||
},
|
||||
tax: {
|
||||
amount: 12.83,
|
||||
},
|
||||
},
|
||||
shippingPrice: {
|
||||
net: {
|
||||
amount: 48.33,
|
||||
},
|
||||
},
|
||||
lines: [
|
||||
{
|
||||
productSku: "328223581",
|
||||
productName: "Monospace Tee",
|
||||
quantity: 1,
|
||||
unitPrice: {
|
||||
net: {
|
||||
amount: 90,
|
||||
},
|
||||
},
|
||||
totalPrice: {
|
||||
tax: {
|
||||
amount: 8.55,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
productSku: "328223580",
|
||||
productName: "Polyspace Tee",
|
||||
quantity: 1,
|
||||
unitPrice: {
|
||||
net: {
|
||||
amount: 45,
|
||||
},
|
||||
},
|
||||
totalPrice: {
|
||||
tax: {
|
||||
amount: 4.28,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
config: {
|
||||
companyCode: "DEFAULT",
|
||||
isAutocommit: true,
|
||||
isSandbox: true,
|
||||
name: "Avatax-1",
|
||||
password: "user-password",
|
||||
username: "user-name",
|
||||
},
|
||||
};
|
||||
|
||||
describe("avataxOrderFulfilledMaps", () => {
|
||||
describe("getTransactionCodeFromMetadata", () => {
|
||||
it("should return transaction code", () => {
|
||||
expect(avataxOrderFulfilledMaps.getTransactionCodeFromMetadata(MOCKED_METADATA)).toBe(
|
||||
"transaction-code"
|
||||
);
|
||||
});
|
||||
|
||||
it("should throw error when transaction code not found", () => {
|
||||
expect(() => avataxOrderFulfilledMaps.getTransactionCodeFromMetadata([])).toThrowError();
|
||||
});
|
||||
});
|
||||
describe("mapPayload", () => {
|
||||
it("should return mapped payload", () => {
|
||||
const mappedPayload = avataxOrderFulfilledMaps.mapPayload(MOCKED_MAP_PAYLOAD_ARGS);
|
||||
|
||||
expect(mappedPayload).toEqual({
|
||||
transactionCode: "transaction-code",
|
||||
companyCode: "DEFAULT",
|
||||
documentType: DocumentType.SalesInvoice,
|
||||
model: {
|
||||
commit: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
describe.todo("mapPayload", () => {
|
||||
it.todo("calculation of fields");
|
||||
it.todo("formatting the fields");
|
||||
it.todo("rounding of numbers");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import { DocumentType } from "avatax/lib/enums/DocumentType";
|
||||
import { OrderFulfilledSubscriptionFragment } from "../../../../generated/graphql";
|
||||
import { PROVIDER_ORDER_ID_KEY } from "../../../pages/api/webhooks/order-created";
|
||||
|
||||
import { CommitTransactionArgs } from "../avatax-client";
|
||||
import { AvataxConfig } from "../avatax-config";
|
||||
|
||||
// * This is the key that we use to store the provider order id in the Saleor order metadata.
|
||||
export const PROVIDER_ORDER_ID_KEY = "externalId";
|
||||
|
||||
function getTransactionCodeFromMetadata(
|
||||
metadata: OrderFulfilledSubscriptionFragment["privateMetadata"]
|
||||
) {
|
||||
|
@ -16,10 +19,12 @@ function getTransactionCodeFromMetadata(
|
|||
return transactionCode.value;
|
||||
}
|
||||
|
||||
const mapPayload = (
|
||||
order: OrderFulfilledSubscriptionFragment,
|
||||
config: AvataxConfig
|
||||
): CommitTransactionArgs => {
|
||||
export type CommitTransactionMapPayloadArgs = {
|
||||
order: OrderFulfilledSubscriptionFragment;
|
||||
config: AvataxConfig;
|
||||
};
|
||||
|
||||
const mapPayload = ({ order, config }: CommitTransactionMapPayloadArgs): CommitTransactionArgs => {
|
||||
const transactionCode = getTransactionCodeFromMetadata(order.privateMetadata);
|
||||
|
||||
return {
|
||||
|
@ -34,4 +39,6 @@ const mapPayload = (
|
|||
|
||||
export const avataxOrderFulfilledMaps = {
|
||||
mapPayload,
|
||||
getTransactionCodeFromMetadata,
|
||||
providerOrderIdKey: PROVIDER_ORDER_ID_KEY,
|
||||
};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { TaxBaseLineFragment } from "../../../generated/graphql";
|
||||
|
||||
const getLineDiscount = (
|
||||
function getTaxBaseLineDiscount(
|
||||
line: TaxBaseLineFragment,
|
||||
totalDiscount: number,
|
||||
allLinesTotal: number
|
||||
) => {
|
||||
) {
|
||||
if (totalDiscount === 0 || allLinesTotal === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -15,9 +15,15 @@ const getLineDiscount = (
|
|||
return lineTotalAmount;
|
||||
}
|
||||
return discountAmount;
|
||||
};
|
||||
}
|
||||
|
||||
const getLineTaxCode = (line: TaxBaseLineFragment): string => {
|
||||
/**
|
||||
* * currently the CalculateTaxes subscription uses only the taxjar code (see: TaxBaseLine in TaxBase.graphql)
|
||||
* todo: add ability to pass providers or get codes for all providers
|
||||
* todo: add `getOrderLineTaxCode`
|
||||
* todo: later, replace with tax code matcher
|
||||
*/
|
||||
function getTaxBaseLineTaxCode(line: TaxBaseLineFragment): string {
|
||||
if (line.sourceLine.__typename === "OrderLine") {
|
||||
return (
|
||||
line.sourceLine.variant?.product.metafield ??
|
||||
|
@ -31,9 +37,9 @@ const getLineTaxCode = (line: TaxBaseLineFragment): string => {
|
|||
line.sourceLine.productVariant.product.productType.metafield) ??
|
||||
""
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export const taxLineResolver = {
|
||||
getLineDiscount,
|
||||
getLineTaxCode,
|
||||
getTaxBaseLineDiscount,
|
||||
getTaxBaseLineTaxCode,
|
||||
};
|
||||
|
|
|
@ -39,13 +39,17 @@ const prepareLinesWithDiscountPayload = (
|
|||
const totalDiscount = discountsSum <= allLinesTotal ? discountsSum : allLinesTotal;
|
||||
|
||||
return lines.map((line) => {
|
||||
const discountAmount = taxLineResolver.getLineDiscount(line, totalDiscount, allLinesTotal);
|
||||
const taxCode = taxLineResolver.getLineTaxCode(line);
|
||||
const discountAmount = taxLineResolver.getTaxBaseLineDiscount(
|
||||
line,
|
||||
totalDiscount,
|
||||
allLinesTotal
|
||||
);
|
||||
|
||||
return {
|
||||
id: line.sourceLine.id,
|
||||
chargeTaxes: line.chargeTaxes,
|
||||
taxCode: taxCode,
|
||||
// todo: get from tax code matcher
|
||||
taxCode: "",
|
||||
quantity: line.quantity,
|
||||
totalAmount: Number(line.totalPrice.amount),
|
||||
unitAmount: Number(line.unitPrice.amount),
|
||||
|
|
|
@ -48,9 +48,12 @@ const MOCKED_ORDER: TaxJarOrderCreatedMapPayloadArgs = {
|
|||
currency: "USD",
|
||||
},
|
||||
shippingPrice: {
|
||||
net: {
|
||||
gross: {
|
||||
amount: 48.33,
|
||||
},
|
||||
net: {
|
||||
amount: 43.74,
|
||||
},
|
||||
},
|
||||
lines: [
|
||||
{
|
||||
|
@ -84,6 +87,14 @@ const MOCKED_ORDER: TaxJarOrderCreatedMapPayloadArgs = {
|
|||
},
|
||||
},
|
||||
],
|
||||
discounts: [
|
||||
{
|
||||
amount: {
|
||||
amount: 10,
|
||||
},
|
||||
id: "RGlzY291bnREaXNjb3VudDox",
|
||||
},
|
||||
],
|
||||
},
|
||||
channel: {
|
||||
providerInstanceId: "b8c29f49-7cae-4762-8458-e9a27eb83081",
|
||||
|
|
|
@ -14,6 +14,7 @@ function mapLines(lines: OrderCreatedSubscriptionFragment["lines"]): LineItem[]
|
|||
// todo: add from tax code matcher
|
||||
product_tax_code: "",
|
||||
sales_tax: line.totalPrice.tax.amount,
|
||||
description: line.productName,
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ export default checkoutCalculateTaxesSyncWebhook.createHandler(async (req, res,
|
|||
logger.info({ calculatedTaxes }, "Taxes calculated");
|
||||
return webhookResponse.success(ctx.buildResponse(calculatedTaxes));
|
||||
} catch (error) {
|
||||
logger.error({ error });
|
||||
return webhookResponse.failureRetry("Error while calculating taxes");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -68,6 +68,7 @@ export default orderCalculateTaxesSyncWebhook.createHandler(async (req, res, ctx
|
|||
logger.info({ calculatedTaxes }, "Taxes calculated");
|
||||
return webhookResponse.success(ctx.buildResponse(calculatedTaxes));
|
||||
} catch (error) {
|
||||
logger.error({ error });
|
||||
return webhookResponse.failureRetry("Error while calculating taxes");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -13,6 +13,7 @@ import { getActiveTaxProvider } from "../../../modules/taxes/active-tax-provider
|
|||
import { createClient } from "../../../lib/graphql";
|
||||
import { Client } from "urql";
|
||||
import { WebhookResponse } from "../../../modules/app/webhook-response";
|
||||
import { PROVIDER_ORDER_ID_KEY } from "../../../modules/avatax/maps/avatax-order-fulfilled-map";
|
||||
|
||||
export const config = {
|
||||
api: {
|
||||
|
@ -33,9 +34,6 @@ export const orderCreatedAsyncWebhook = new SaleorAsyncWebhook<OrderCreatedPaylo
|
|||
webhookPath: "/api/webhooks/order-created",
|
||||
});
|
||||
|
||||
// * This is the key that we use to store the provider order id in the Saleor order metadata.
|
||||
export const PROVIDER_ORDER_ID_KEY = "externalId";
|
||||
|
||||
/**
|
||||
* We need to store the provider order id in the Saleor order metadata so that we can
|
||||
* update the provider order when the Saleor order is fulfilled.
|
||||
|
@ -105,6 +103,7 @@ export default orderCreatedAsyncWebhook.createHandler(async (req, res, ctx) => {
|
|||
|
||||
return webhookResponse.success();
|
||||
} catch (error) {
|
||||
logger.error({ error });
|
||||
return webhookResponse.failureRetry("Error while creating order in tax provider");
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue