
* feat: ✨ add dummy order-created * refactor: 🔥 unused private-providers-configuration-service * feat: ✨ add dummy order-fulfilled * refactor: 🚚 move provider-config * refactor: 🚚 crudSettingsConfigurator -> crudSettingsManager * refactor: ♻️ [tax-provider].ts -> [tax-provider]-webhook.service.ts * feat: ✨ add dummy createOrder * refactor: ♻️ distinguish between salesOrder and salesInvoice in avatax * refactor: 🚚 [provider]-calculate.ts to [provider]-transform.ts * refactor: 🚚 ResponseTaxPayload to tax-provider-webhook.ts * refactor: 🚚 ResponseTaxPayload -> CalculateTaxesResponse * refactor: ♻️ webhooks with active-tax-provider.service.ts * feat: ✨ add skeleton orderCreate functionality * refactor: ♻️ [provider]-transform.ts -> [provider]-[webhook]-transform.ts * feat: ✨ add order-fulfilled with avatax call * refactor: ♻️ move getActiveTaxProvider to active-tax-provider * refactor: 🏷️ export types for [provider]-client function args * refactor: 🚚 UpdateAppMetadata -> UpdateMetadata * feat: ✨ fulfill order with id from metadata * build: ⬆️ upgrade avatax * feat: ✨ commit transaction on fulfill in avatax * fix: 🐛 return of webhooks to ensure valid retry behavior * refactor: 🚚 [provider]-[webhook]-transform -> [provider]-[webhook]-map * refactor: 🏷️ export types of avatax-calculate-taxes mapPayload * refactor: ♻️ extract address-map to separate function * refactor: ♻️ remove schema.ts * refactor: ♻️ move addressSchema to channels-config.ts * feat: ✨ add tests & placeholder tests for avatax & taxjar maps * refactor: ♻️ throw error if no metadata * refactor: ♻️ change EXTERNAL_ID_KEY to PROVIDER_ORDER_ID_KEY add comments * refactor: ♻️ comments -> it.todo in tests * refactor: 💡 add comment about shipping_item_code * refactor: ✅ add todo items for tests * refactor: ♻️ remove export and add sumLines to taxJarOrderCreated * refactor: ♻️ address-map with avatarAddressFactory * docs: 💡 add comment about MOCKED_SALEOR_PAYLOAD * refactor: ♻️ remove export of mapLines and add to avataxCalculateTaxes * style: 🎨 add newline-after-var warn to eslint-config-saleor * style: 🎨 autofix newline-after-var in taxes * test: ✅ restructure tests according to new naming in address-map * refactor: ♻️ add shippingItemCode to avataxCalculateTaxes wrapper object * refactor: 🚚 payloadProps -> payloadArgs * refactor: ♻️ add Maps suffix to map wrapper objects * refactor: ♻️ remove data: null from ActiveTaxProviderResult * refactor: ♻️ maintain the object hierarchy in tests * refactor: ♻️ refactor webhook responses with WebhookResponseFactory * build: ⬆️ vitest * test: ✅ add tests for get-app-config-test * test: ✅ add tests for getActiveTaxProvider * refactor: ♻️ use address fragment for taxBase and order * refactor: ♻️ rename WebhookResponseFactory -> WebhookResponse * style: 👷 add multiline-comment-style * fix: 🐛 dummy test in get-app-config.test.ts * refactor: ♻️ rename AddressFragment -> Address * refactor: ♻️ use debug instead of error in webhook-response noRetry * refactor: ♻️ refactor as variables in mutation * build: 👷 add changeset * refactor: ♻️ split changesets in two * build: ⬆️ vite * build: ⬆️ vite && vitest in all apps
112 lines
3.9 KiB
TypeScript
112 lines
3.9 KiB
TypeScript
import { LineItemModel } from "avatax/lib/models/LineItemModel";
|
|
import { TransactionModel } from "avatax/lib/models/TransactionModel";
|
|
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 { 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
|
|
* https://developer.avalara.com/avatax/dev-guide/shipping-and-handling/taxability-of-shipping-charges/
|
|
*/
|
|
const SHIPPING_ITEM_CODE = "Shipping";
|
|
|
|
function mapLines(taxBase: TaxBaseFragment): LineItemModel[] {
|
|
const productLines = taxBase.lines.map((line) => ({
|
|
amount: line.unitPrice.amount,
|
|
taxIncluded: line.chargeTaxes,
|
|
// todo: get from tax code matcher
|
|
taxCode: taxLineResolver.getLineTaxCode(line),
|
|
quantity: line.quantity,
|
|
}));
|
|
|
|
if (taxBase.shippingPrice.amount !== 0) {
|
|
// * In Avatax, shipping is a regular line
|
|
const shippingLine: LineItemModel = {
|
|
amount: taxBase.shippingPrice.amount,
|
|
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,
|
|
};
|
|
|
|
return [...productLines, shippingLine];
|
|
}
|
|
|
|
return productLines;
|
|
}
|
|
|
|
export type AvataxCalculateTaxesMapPayloadArgs = {
|
|
taxBase: TaxBaseFragment;
|
|
channel: ChannelConfig;
|
|
config: AvataxConfig;
|
|
};
|
|
|
|
const mapPayload = (props: AvataxCalculateTaxesMapPayloadArgs): CreateTransactionArgs => {
|
|
const { taxBase, channel, config } = props;
|
|
|
|
return {
|
|
model: {
|
|
type: DocumentType.SalesOrder,
|
|
customerCode: taxBase.sourceObject.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,
|
|
addresses: {
|
|
shipFrom: avataxAddressFactory.fromChannelAddress(channel.address),
|
|
shipTo: avataxAddressFactory.fromSaleorAddress(taxBase.address!),
|
|
},
|
|
currencyCode: taxBase.currency,
|
|
lines: mapLines(taxBase),
|
|
date: new Date(),
|
|
},
|
|
};
|
|
};
|
|
|
|
const mapResponse = (transaction: TransactionModel): CalculateTaxesResponse => {
|
|
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 = numbers.roundFloatToTwoDecimals(
|
|
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 = numbers.roundFloatToTwoDecimals(
|
|
lineTotalNetAmount + lineTaxCalculated
|
|
);
|
|
|
|
return {
|
|
total_gross_amount: lineTotalGrossAmount,
|
|
total_net_amount: lineTotalNetAmount,
|
|
// todo: add tax rate
|
|
tax_rate: 0,
|
|
};
|
|
}) ?? [],
|
|
};
|
|
};
|
|
|
|
export const avataxCalculateTaxesMaps = {
|
|
mapPayload,
|
|
mapResponse,
|
|
mapLines,
|
|
shippingItemCode: SHIPPING_ITEM_CODE,
|
|
};
|