
* refactor: ♻️ split into services * docs: 💡 add comment about joining providers * fix: 🐛 change name from avalara to avatax * build: 👷 add changeset * fix: 🐛 move return into catch
112 lines
3.6 KiB
TypeScript
112 lines
3.6 KiB
TypeScript
import { CreateTransactionModel } from "avatax/lib/models/CreateTransactionModel";
|
|
import { LineItemModel } from "avatax/lib/models/LineItemModel";
|
|
import { TransactionModel } from "avatax/lib/models/TransactionModel";
|
|
import { TaxBaseFragment } from "../../../generated/graphql";
|
|
|
|
import { ChannelConfig } from "../channels-configuration/channels-config";
|
|
import { taxLineResolver } from "../taxes/tax-line-resolver";
|
|
import { ResponseTaxPayload } from "../taxes/types";
|
|
import { AvataxConfig } from "./avatax-config";
|
|
|
|
const SHIPPING_ITEM_CODE = "Shipping";
|
|
|
|
const formatCalculatedAmount = (amount: number) => {
|
|
return Number(amount.toFixed(2));
|
|
};
|
|
|
|
const prepareLines = (taxBase: TaxBaseFragment): LineItemModel[] => {
|
|
const productLines = taxBase.lines.map((line) => ({
|
|
amount: line.unitPrice.amount,
|
|
taxIncluded: line.chargeTaxes,
|
|
taxCode: taxLineResolver.getLineTaxCode(line),
|
|
quantity: line.quantity,
|
|
itemCode: "Product",
|
|
}));
|
|
|
|
if (taxBase.shippingPrice.amount !== 0) {
|
|
// * In Avatax, shipping is a regular line
|
|
const shippingLine: LineItemModel = {
|
|
amount: taxBase.shippingPrice.amount,
|
|
itemCode: SHIPPING_ITEM_CODE,
|
|
quantity: 1,
|
|
};
|
|
|
|
return [...productLines, shippingLine];
|
|
}
|
|
|
|
return productLines;
|
|
};
|
|
|
|
const defaultAvataxTransactionModel = {
|
|
// todo: what is customerCode
|
|
customerCode: "0",
|
|
type: 0,
|
|
};
|
|
|
|
const preparePayload = (
|
|
taxBase: TaxBaseFragment,
|
|
channel: ChannelConfig,
|
|
config: AvataxConfig
|
|
): CreateTransactionModel => {
|
|
return {
|
|
...defaultAvataxTransactionModel,
|
|
companyCode: config.companyName,
|
|
// * 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,
|
|
addresses: {
|
|
shipFrom: {
|
|
line1: channel.address.street,
|
|
city: channel.address.city,
|
|
region: channel.address.state,
|
|
postalCode: channel.address.zip,
|
|
country: channel.address.country,
|
|
},
|
|
shipTo: {
|
|
line1: taxBase.address?.streetAddress1,
|
|
line2: taxBase.address?.streetAddress2,
|
|
city: taxBase.address?.city,
|
|
country: taxBase.address?.country.code,
|
|
postalCode: taxBase.address?.postalCode,
|
|
region: taxBase.address?.countryArea,
|
|
},
|
|
},
|
|
lines: prepareLines(taxBase),
|
|
// todo: replace date with order/checkout date
|
|
date: new Date(),
|
|
};
|
|
};
|
|
|
|
const prepareResponse = (transaction: TransactionModel): ResponseTaxPayload => {
|
|
const shippingLine = transaction.lines?.find((line) => line.itemCode === SHIPPING_ITEM_CODE);
|
|
|
|
const productLines = transaction.lines?.filter((line) => line.itemCode !== SHIPPING_ITEM_CODE);
|
|
|
|
const shippingGrossAmount = shippingLine?.taxableAmount ?? 0;
|
|
const shippingTaxCalculated = shippingLine?.taxCalculated ?? 0;
|
|
const shippingNetAmount = formatCalculatedAmount(shippingGrossAmount - shippingTaxCalculated);
|
|
|
|
return {
|
|
shipping_price_gross_amount: shippingGrossAmount,
|
|
shipping_price_net_amount: shippingNetAmount,
|
|
// todo: add shipping tax rate
|
|
shipping_tax_rate: 0,
|
|
lines:
|
|
productLines?.map((line) => {
|
|
const lineTaxCalculated = line.taxCalculated ?? 0;
|
|
const lineTotalNetAmount = line.taxableAmount ?? 0;
|
|
const lineTotalGrossAmount = formatCalculatedAmount(lineTotalNetAmount + lineTaxCalculated);
|
|
return {
|
|
total_gross_amount: lineTotalGrossAmount,
|
|
total_net_amount: lineTotalNetAmount,
|
|
// todo: add tax rate
|
|
tax_rate: 0,
|
|
};
|
|
}) ?? [],
|
|
};
|
|
};
|
|
|
|
export const avataxCalculate = {
|
|
preparePayload,
|
|
prepareResponse,
|
|
prepareLines,
|
|
};
|