feat: new tax api (#979)

* feat: add tax calculation strategy (#885)

* feat: add tax calculation strategy

* fix: adds strategy loader

* fix: eslint ignore

* chore: cleanup

* fix: allow plugin overwrites

* fix: allow plugin overwrites

* fix: fake region

* Update packages/medusa/src/loaders/strategies.ts

Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com>

Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com>

* feat: adds tax related db entities + tax provider (#896)

* feat: adds tax related db entities + tax provider

* fix: add tax provider tests

* fix: add tax service unit tests

* fix: tests + migrations

* fix: add inherited tax lines

* chore: rm tax-line repo

* fix: test

* fix: pr comments

* fix: unit test

* feat: totals service to ts (#911)

* feat: adds tax related db entities + tax provider

* fix: add tax provider tests

* fix: add tax service unit tests

* fix: tests + migrations

* feat: totals service to ts

* fix: remove totals.js

* fix: add shipping methods

* fix: add inherited tax lines

* chore: rm tax-line repo

* fix: test

* fix: tests

* fix: tests

* fix: unit test

* fix: adds TotalsServiceProps

* feat: adds integration tests for automatic tax calculation + shipping tax rates (#945)

* feat: adds tax related db entities + tax provider

* fix: add tax provider tests

* fix: add tax service unit tests

* fix: tests + migrations

* feat: totals service to ts

* fix: remove totals.js

* fix: add shipping methods

* fix: add inherited tax lines

* chore: rm tax-line repo

* fix: test

* fix: tests

* fix: tests

* fix: unit test

* fix: integration test helpers

* fix: adds factories + tests automatic tax rates

* fix: remove verbose

* fix: adds TotalsServiceProps

* fix: add shipping tax lines

* fix: add migration for shipping taxes

* fix: integration tests for shipping taxes

* fix: integration tests for shipping taxes

* fix: jsdoc types

* Feat/manual taxes (#950)

* feat: adds tax related db entities + tax provider

* fix: add tax provider tests

* fix: add tax service unit tests

* fix: tests + migrations

* feat: totals service to ts

* fix: remove totals.js

* fix: add shipping methods

* fix: add inherited tax lines

* chore: rm tax-line repo

* fix: test

* fix: tests

* fix: tests

* fix: unit test

* fix: integration test helpers

* fix: adds factories + tests automatic tax rates

* fix: remove verbose

* fix: adds TotalsServiceProps

* fix: add shipping tax lines

* fix: add migration for shipping taxes

* fix: integration tests for shipping taxes

* fix: integration tests for shipping taxes

* fix: add integration tests for manual taxes

* fix: cart service - cleanup jsdoc

* feat: add /carts/id/taxes to manually calculate taxes

* feat: add integration tests for order tax calculations

* fix: unit tests

* fix: merge

* fix: rm verbose

* fix: unit tests

* fix: object -> cartOrOrder

* fix: rounding

* Feat/complete order w tax lines (#951)

* feat: adds tax related db entities + tax provider

* fix: add tax provider tests

* fix: add tax service unit tests

* fix: tests + migrations

* feat: totals service to ts

* fix: remove totals.js

* fix: add shipping methods

* fix: add inherited tax lines

* chore: rm tax-line repo

* fix: test

* fix: tests

* fix: tests

* fix: unit test

* fix: integration test helpers

* fix: adds factories + tests automatic tax rates

* fix: remove verbose

* fix: adds TotalsServiceProps

* fix: add shipping tax lines

* fix: add migration for shipping taxes

* fix: integration tests for shipping taxes

* fix: integration tests for shipping taxes

* fix: add integration tests for manual taxes

* fix: cart service - cleanup jsdoc

* feat: add /carts/id/taxes to manually calculate taxes

* feat: add integration tests for order tax calculations

* feat: adds cart completion strategy + create order w. tax lines

* fix: unit tests

* fix: merge

* fix: rm verbose

* fix: unit tests

* fix: unit tests

* fix: unit tests

* fix: ensure calculation for list orders

* fix: unit tests

* fix: integration tests

* fix: adds cart order type gaurds

* Docs/tax api (#954)

* feat: adds tax related db entities + tax provider

* fix: add tax provider tests

* fix: add tax service unit tests

* fix: tests + migrations

* feat: totals service to ts

* fix: remove totals.js

* fix: add shipping methods

* fix: add inherited tax lines

* chore: rm tax-line repo

* fix: test

* fix: tests

* fix: tests

* fix: unit test

* fix: integration test helpers

* fix: adds factories + tests automatic tax rates

* fix: remove verbose

* fix: adds TotalsServiceProps

* fix: add shipping tax lines

* fix: add migration for shipping taxes

* fix: integration tests for shipping taxes

* fix: integration tests for shipping taxes

* fix: add integration tests for manual taxes

* fix: cart service - cleanup jsdoc

* feat: add /carts/id/taxes to manually calculate taxes

* feat: add integration tests for order tax calculations

* feat: adds cart completion strategy + create order w. tax lines

* fix: unit tests

* fix: merge

* fix: rm verbose

* fix: unit tests

* fix: unit tests

* fix: unit tests

* fix: ensure calculation for list orders

* fix: unit tests

* fix: integration tests

* docs: documents tax related methods and types

* fix: require either item_id or shipping_method_id

* feat: product type tax rate (#969)

* feat: adds tax related db entities + tax provider

* fix: add tax provider tests

* fix: add tax service unit tests

* fix: tests + migrations

* feat: totals service to ts

* fix: remove totals.js

* fix: add shipping methods

* fix: add inherited tax lines

* chore: rm tax-line repo

* fix: test

* fix: tests

* fix: tests

* fix: unit test

* fix: integration test helpers

* fix: adds factories + tests automatic tax rates

* fix: remove verbose

* fix: adds TotalsServiceProps

* fix: add shipping tax lines

* fix: add migration for shipping taxes

* fix: integration tests for shipping taxes

* fix: integration tests for shipping taxes

* fix: add integration tests for manual taxes

* fix: cart service - cleanup jsdoc

* feat: add /carts/id/taxes to manually calculate taxes

* feat: add integration tests for order tax calculations

* feat: adds cart completion strategy + create order w. tax lines

* fix: unit tests

* fix: merge

* fix: rm verbose

* fix: unit tests

* fix: unit tests

* fix: unit tests

* fix: ensure calculation for list orders

* fix: unit tests

* fix: integration tests

* docs: documents tax related methods and types

* fix: require either item_id or shipping_method_id

* feat: adds returns tests for new tax system

* feat: adds return lines + integration tests for swaps

* feat: return integration tests

* feat: adds product type tax rates

* feat: add tax management endpoints

* fix: create single migration

* fix: adds tax rates to js client

* fix: strats

* Fix/plugin tests (#998)

* plugin testing setup

* fix: test sendgrid plugin

* fix: test sendgrid plugin

* chore: clean

* chore: clean

* fix: clean up tests

* fix: remove dirty import

* fix: sendgrid + brightpearl

* fix: plugin integration tests

* fix: klarna

* fix: shipping method tax

* fix: remove taxrates

* fix: unit tests

* fix: integration

* fix: integration

* fix: plugins tests

* fix: ignore plugins

* fix: tests

* fix: taxes (#1017)

* fix: taxes

* fix: taxes

* fix: faulty ref

* fix: create tax-lines with claim items

* fix: snapshot tax-liens

* fix: allows integration test teardown to force deleting tables

* fix: tests

* fix: merge

* fix: adds tax-rates to client

* fix: adds tax-rates to medusa-react

* fix: tests

* fix: tests

* fix: add product types

* fix: adds tax provider endpoint + cascaded deletes on tax rate relations

* fix: move errors to service layer

* fix: cleanup api

* fix: unit tests

* fix: error handler in base-service

* fix: Add order region to swap on createFulfillment (#1110)

Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
Sebastian Rindom
2022-02-24 20:14:09 +01:00
committed by olivermrbl
parent d80eaa172d
commit 47588e7a8d
223 changed files with 28546 additions and 2229 deletions

View File

@@ -156,6 +156,20 @@ const TotalsService = {
getTotal: () => {
return Promise.resolve(123)
},
getShippingMethodTotals: () => {
return {
price: 0,
discount_total: 0,
tax_total: 0,
}
},
getLineItemTotals: () => {
return {
subtotal: 15800,
discount_total: 0,
tax_total: 3950,
}
},
getLineDiscounts: (o) => {
if (o.id === "rounding") {
return [
@@ -242,76 +256,6 @@ describe("BrightpearlService", () => {
})
})
describe("createSalesOrder", () => {
const bpService = new BrightpearlService(
{
orderService: OrderService,
totalsService: TotalsService,
oauthService: OAuthService,
regionService: RegionService,
},
{ account: "test" }
)
it("successfully builds sales order", async () => {
jest.clearAllMocks()
await bpService.createSalesOrder(order)
expect(mockCreateOrder).toHaveBeenCalledWith({
currency: { code: "DKK" },
ref: "1234",
externalRef: "12355",
channelId: "1",
installedIntegrationInstanceId: undefined,
statusId: "3",
customer: {
id: "12345",
address: {
addressFullName: "Test Testson",
addressLine1: "Test",
addressLine2: "TEst",
postalCode: "1234",
countryIsoCode: "DK",
telephone: "12345678",
email: "test@example.com",
},
},
delivery: {
shippingMethodId: 0,
address: {
addressFullName: "Test Testson",
addressLine1: "Test",
addressLine2: "TEst",
postalCode: "1234",
countryIsoCode: "DK",
telephone: "12345678",
email: "test@example.com",
},
},
rows: [
{
name: "Test",
net: 22,
tax: 5.082,
quantity: 2,
taxCode: "1234",
externalRef: undefined,
nominalCode: "4000",
},
{
name: "Shipping: standard",
quantity: 1,
net: 123.99,
tax: 28.6417,
taxCode: "1234",
nominalCode: "4040",
},
],
})
})
})
describe("rounding", () => {
const bpService = new BrightpearlService(
{

View File

@@ -322,15 +322,8 @@ class BrightpearlService extends BaseService {
name: `${fromRefund.reason}: ${fromRefund.note}`,
quantity: 1,
taxCode: region.tax_code,
net: this.bpnum_(
fromRefund.amount,
fromOrder.currency_code,
10000 / (100 + fromOrder.tax_rate)
),
tax: this.bpnum_(
fromRefund.amount * (1 - 100 / (100 + fromOrder.tax_rate)),
fromOrder.currency_code
),
net: this.bpnum_(fromRefund.amount, fromOrder.currency_code),
tax: 0,
nominalCode: accountingCode,
},
],
@@ -410,6 +403,29 @@ class BrightpearlService extends BaseService {
}),
}
if (fromReturn.shipping_method) {
const totals = await this.totalsService_.getShippingMethodTotals(
fromReturn.shipping_method,
fromOrder,
{
include_tax: true,
use_tax_lines: true,
}
)
order.rows.push({
net: this.bpnum_(
-1 * (totals.total - totals.tax_total),
fromOrder.currency_code
),
tax: this.bpnum_(-1 * totals.tax_total, fromOrder.currency_code),
name: "Return shipping",
taxCode: region.tax_code,
nominalCode: this.options.shipping_account_code || "4040",
quantity: 1,
})
}
const total = order.rows.reduce((acc, next) => {
return acc + next.net + next.tax
}, 0)
@@ -421,15 +437,8 @@ class BrightpearlService extends BaseService {
name: "Difference",
quantity: 1,
taxCode: region.tax_code,
net: this.bpnum_(
difference,
fromOrder.currency_code,
10000 / (100 + fromOrder.tax_rate)
),
tax: this.bpnum_(
difference * (1 - 100 / (100 + fromOrder.tax_rate)),
fromOrder.currency_code
),
net: this.bpround_(difference),
tax: 0,
nominalCode: this.options.sales_account_code || "4000",
})
}
@@ -811,14 +820,24 @@ class BrightpearlService extends BaseService {
fromSwap.return_order.shipping_method &&
fromSwap.return_order.shipping_method.price
) {
const shippingTotals =
await this.totalsService_.getShippingMethodTotals(
fromSwap.return_order.shipping_method,
fromOrder,
{
include_tax: true,
use_tax_lines: true,
}
)
order.rows.push({
name: "Return Shipping",
quantity: 1,
taxCode: region.tax_code,
net: (-1 * fromSwap.return_order.shipping_method.price) / 100,
tax:
((-1 * fromSwap.return_order.shipping_method.price) / 100) *
(fromOrder.tax_rate / 100),
net: this.bpnum_(1 * shippingTotals.price, fromOrder.currency_code),
tax: this.bpnum_(
1 * shippingTotals.tax_total,
fromOrder.currency_code
),
nominalCode: this.options.shipping_account_code || "4040",
})
}
@@ -882,21 +901,19 @@ class BrightpearlService extends BaseService {
config = { include_price: true, is_claim: false }
) {
const { region } = fromOrder
const discount = fromOrder.discounts.find(
({ rule }) => rule.type !== "free_shipping"
)
let lineDiscounts = []
if (discount) {
lineDiscounts = this.totalsService_.getLineDiscounts(fromOrder, discount)
}
const lines = await Promise.all(
fromOrder.items.map(async (item) => {
const bpProduct = await this.retrieveProductBySKU(item.variant.sku)
const ld = lineDiscounts.find((l) => item.id === l.item.id) || {
amount: 0,
}
const lineTotals = await this.totalsService_.getLineItemTotals(
item,
fromOrder,
{
include_tax: true,
use_tax_lines: true,
}
)
const row = {}
if (bpProduct) {
@@ -907,23 +924,20 @@ class BrightpearlService extends BaseService {
if (config.include_price) {
row.net = this.bpnum_(
item.unit_price * item.quantity - ld.amount,
lineTotals.subtotal - lineTotals.discount_total,
fromOrder.currency_code
)
row.tax = this.bpnum_(
item.unit_price * item.quantity - ld.amount,
fromOrder.currency_code,
fromOrder.tax_rate
)
row.tax = this.bpnum_(lineTotals.tax_total, fromOrder.currency_code)
} else if (config.is_claim) {
row.net = await this.retrieveProductPrice(
bpProduct.productId,
this.options.cost_price_list || `1`
)
row.tax = this.bpnum_(
row.net * 100,
fromOrder.currency_code,
fromOrder.tax_rate
lineTotals.tax_lines.reduce((acc, next) => acc + next.rate, 0)
)
}
@@ -948,34 +962,48 @@ class BrightpearlService extends BaseService {
// purchased.
const gcTotal = fromOrder.gift_card_total
if (gcTotal) {
let tax = 0
if (fromOrder.region.gift_cards_taxable) {
tax = this.bpnum_(
-1 * gcTotal,
fromOrder.currency_code,
fromOrder.region.tax_rate
)
}
lines.push({
name: `Gift Card`,
net: this.bpnum_(-1 * gcTotal, fromOrder.currency_code),
tax: this.bpnum_(
-1 * gcTotal,
fromOrder.currency_code,
fromOrder.tax_rate
),
tax,
quantity: 1,
taxCode: region.tax_code,
nominalCode: this.options.gift_card_account_code || "4000",
})
}
const shippingTotal =
fromOrder.shipping_total ||
this.totalsService_.getShippingTotal(fromOrder)
const shippingMethods = fromOrder.shipping_methods
if (shippingMethods.length > 0) {
const shippingTotal = await shippingMethods.reduce(async (acc, next) => {
const accum = await acc
const totals = await this.totalsService_.getShippingMethodTotals(
next,
fromOrder,
{
include_tax: true,
use_tax_lines: true,
}
)
return {
price: accum.price + totals.price,
tax: accum.tax + totals.tax_total,
}
}, Promise.resolve({ price: 0, tax: 0 }))
lines.push({
name: `Shipping: ${shippingMethods.map((m) => m.name).join(" + ")}`,
quantity: 1,
net: this.bpnum_(shippingTotal, fromOrder.currency_code),
tax: this.bpnum_(
shippingTotal,
fromOrder.currency_code,
fromOrder.tax_rate
),
net: this.bpnum_(shippingTotal.price, fromOrder.currency_code),
tax: this.bpnum_(shippingTotal.tax, fromOrder.currency_code),
taxCode: region.tax_code,
nominalCode: this.options.shipping_account_code || "4040",
})

View File

@@ -72,21 +72,20 @@ class OrderSubscriber {
const fromSwap = await this.swapService_.retrieve(id, {
relations: [
"order",
"order.payments",
"order.region",
"order.swaps",
"order.discounts",
"order.discounts.rule",
"return_order",
"return_order.items",
"return_order.shipping_method",
"return_order.shipping_method.tax_lines",
"additional_items",
"additional_items.tax_lines",
"shipping_address",
"shipping_methods",
"shipping_methods.tax_lines",
],
})
let fromOrder = fromSwap.order
const fromOrder = await this.orderService_.retrieve(fromSwap.order_id, {
relations: ["payments", "region", "swaps", "discounts", "discounts.rule"],
})
if (
!(
@@ -105,23 +104,27 @@ class OrderSubscriber {
const { id } = data
const fromClaim = await this.claimService_.retrieve(id, {
relations: [
"order",
"order.payments",
"order.region",
"order.claims",
"order.discounts",
"order.discounts.rule",
"claim_items",
"return_order",
"return_order.items",
"return_order.shipping_method",
"return_order.shipping_method.tax_lines",
"additional_items",
"additional_items.tax_lines",
"shipping_address",
"shipping_methods",
],
})
const fromOrder = fromClaim.order
const fromOrder = await this.orderService_.retrieve(fromClaim.order_id, {
relations: [
"payments",
"region",
"claims",
"discounts",
"discounts.rule",
],
})
if (fromClaim.type === "replace") {
await this.brightpearlService_.createClaim(fromOrder, fromClaim)
@@ -147,11 +150,11 @@ class OrderSubscriber {
const { id, return_id } = data
const order = await this.orderService_.retrieve(id, {
relations: ["region", "swaps", "payments"],
relations: ["discounts", "region", "swaps", "payments"],
})
const fromReturn = await this.returnService_.retrieve(return_id, {
relations: ["items"],
relations: ["items", "shipping_method", "shipping_method.tax_lines"],
})
return this.brightpearlService_