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:
committed by
olivermrbl
parent
d80eaa172d
commit
47588e7a8d
@@ -349,7 +349,7 @@ class SendGridService extends NotificationService {
|
||||
}
|
||||
}
|
||||
|
||||
async orderPlacedData({ id }) {
|
||||
async orderCanceledData({ id }) {
|
||||
const order = await this.orderService_.retrieve(id, {
|
||||
select: [
|
||||
"shipping_total",
|
||||
@@ -448,6 +448,131 @@ class SendGridService extends NotificationService {
|
||||
}
|
||||
}
|
||||
|
||||
async orderPlacedData({ id }) {
|
||||
const order = await this.orderService_.retrieve(id, {
|
||||
select: [
|
||||
"shipping_total",
|
||||
"discount_total",
|
||||
"tax_total",
|
||||
"refunded_total",
|
||||
"gift_card_total",
|
||||
"subtotal",
|
||||
"total",
|
||||
],
|
||||
relations: [
|
||||
"customer",
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_methods",
|
||||
"shipping_methods.shipping_option",
|
||||
"payments",
|
||||
"fulfillments",
|
||||
"returns",
|
||||
"gift_cards",
|
||||
"gift_card_transactions",
|
||||
],
|
||||
})
|
||||
|
||||
const { tax_total, shipping_total, gift_card_total, total } = order
|
||||
|
||||
const currencyCode = order.currency_code.toUpperCase()
|
||||
|
||||
const items = await Promise.all(
|
||||
order.items.map(async (i) => {
|
||||
i.totals = await this.totalsService_.getLineItemTotals(i, order, {
|
||||
include_tax: true,
|
||||
use_tax_lines: true,
|
||||
})
|
||||
i.thumbnail = this.normalizeThumbUrl_(i.thumbnail)
|
||||
i.discounted_price = `${this.humanPrice_(
|
||||
i.totals.total / i.quantity,
|
||||
currencyCode
|
||||
)} ${currencyCode}`
|
||||
i.price = `${this.humanPrice_(
|
||||
i.totals.original_total / i.quantity,
|
||||
currencyCode
|
||||
)} ${currencyCode}`
|
||||
return i
|
||||
})
|
||||
)
|
||||
|
||||
let discounts = []
|
||||
if (order.discounts) {
|
||||
discounts = order.discounts.map((discount) => {
|
||||
return {
|
||||
is_giftcard: false,
|
||||
code: discount.code,
|
||||
descriptor: `${discount.rule.value}${
|
||||
discount.rule.type === "percentage" ? "%" : ` ${currencyCode}`
|
||||
}`,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let giftCards = []
|
||||
if (order.gift_cards) {
|
||||
giftCards = order.gift_cards.map((gc) => {
|
||||
return {
|
||||
is_giftcard: true,
|
||||
code: gc.code,
|
||||
descriptor: `${gc.value} ${currencyCode}`,
|
||||
}
|
||||
})
|
||||
|
||||
discounts.concat(giftCards)
|
||||
}
|
||||
|
||||
const locale = await this.extractLocale(order)
|
||||
|
||||
// Includes taxes in discount amount
|
||||
const discountTotal = items.reduce((acc, i) => {
|
||||
return acc + i.totals.original_total - i.totals.total
|
||||
}, 0)
|
||||
|
||||
const discounted_subtotal = items.reduce((acc, i) => {
|
||||
return acc + i.totals.total
|
||||
}, 0)
|
||||
const subtotal = items.reduce((acc, i) => {
|
||||
return acc + i.totals.original_total
|
||||
}, 0)
|
||||
|
||||
const subtotal_ex_tax = items.reduce((total, i) => {
|
||||
return total + i.totals.subtotal
|
||||
}, 0)
|
||||
|
||||
return {
|
||||
...order,
|
||||
locale,
|
||||
has_discounts: order.discounts.length,
|
||||
has_gift_cards: order.gift_cards.length,
|
||||
date: order.created_at.toDateString(),
|
||||
items,
|
||||
discounts,
|
||||
subtotal_ex_tax: `${this.humanPrice_(
|
||||
subtotal_ex_tax,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
subtotal: `${this.humanPrice_(subtotal, currencyCode)} ${currencyCode}`,
|
||||
gift_card_total: `${this.humanPrice_(
|
||||
gift_card_total,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
tax_total: `${this.humanPrice_(tax_total, currencyCode)} ${currencyCode}`,
|
||||
discount_total: `${this.humanPrice_(
|
||||
discountTotal,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
shipping_total: `${this.humanPrice_(
|
||||
shipping_total,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
total: `${this.humanPrice_(total, currencyCode)} ${currencyCode}`,
|
||||
}
|
||||
}
|
||||
|
||||
async gcCreatedData({ id }) {
|
||||
const giftCard = await this.giftCardService_.retrieve(id, {
|
||||
relations: ["region", "order"],
|
||||
@@ -475,68 +600,76 @@ class SendGridService extends NotificationService {
|
||||
relations: [
|
||||
"items",
|
||||
"items.item",
|
||||
"items.item.tax_lines",
|
||||
"items.item.variant",
|
||||
"items.item.variant.product",
|
||||
"shipping_method",
|
||||
"shipping_method.tax_lines",
|
||||
"shipping_method.shipping_option",
|
||||
],
|
||||
})
|
||||
|
||||
const items = await this.lineItemService_.list({
|
||||
id: returnRequest.items.map(({ item_id }) => item_id),
|
||||
})
|
||||
|
||||
returnRequest.items = returnRequest.items.map((item) => {
|
||||
const found = items.find((i) => i.id === item.item_id)
|
||||
return {
|
||||
...item,
|
||||
item: found,
|
||||
}
|
||||
})
|
||||
const items = await this.lineItemService_.list(
|
||||
{
|
||||
id: returnRequest.items.map(({ item_id }) => item_id),
|
||||
},
|
||||
{ relations: ["tax_lines"] }
|
||||
)
|
||||
|
||||
// Fetch the order
|
||||
const order = await this.orderService_.retrieve(id, {
|
||||
select: ["total"],
|
||||
relations: [
|
||||
"items",
|
||||
"items.tax_lines",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_address",
|
||||
"returns",
|
||||
"swaps",
|
||||
"swaps.additional_items",
|
||||
],
|
||||
})
|
||||
|
||||
let merged = [...order.items]
|
||||
|
||||
// merge items from order with items from order swaps
|
||||
if (order.swaps && order.swaps.length) {
|
||||
for (const s of order.swaps) {
|
||||
merged = [...merged, ...s.additional_items]
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate which items are in the return
|
||||
const returnItems = returnRequest.items.map((i) => {
|
||||
const found = merged.find((oi) => oi.id === i.item_id)
|
||||
return {
|
||||
...found,
|
||||
quantity: i.quantity,
|
||||
}
|
||||
})
|
||||
|
||||
const taxRate = order.tax_rate / 100
|
||||
const currencyCode = order.currency_code.toUpperCase()
|
||||
|
||||
// Calculate which items are in the return
|
||||
const returnItems = await Promise.all(
|
||||
returnRequest.items.map(async (i) => {
|
||||
const found = items.find((oi) => oi.id === i.item_id)
|
||||
found.quantity = i.quantity
|
||||
found.thumbnail = this.normalizeThumbUrl_(found.thumbnail)
|
||||
found.totals = await this.totalsService_.getLineItemTotals(
|
||||
found,
|
||||
order,
|
||||
{
|
||||
include_tax: true,
|
||||
use_tax_lines: true,
|
||||
}
|
||||
)
|
||||
found.price = `${this.humanPrice_(
|
||||
found.totals.total,
|
||||
currencyCode
|
||||
)} ${currencyCode}`
|
||||
found.tax_lines = found.totals.tax_lines
|
||||
return found
|
||||
})
|
||||
)
|
||||
|
||||
// Get total of the returned products
|
||||
const item_subtotal = this.totalsService_.getRefundTotal(order, returnItems)
|
||||
const item_subtotal = returnItems.reduce(
|
||||
(acc, next) => acc + next.totals.total,
|
||||
0
|
||||
)
|
||||
|
||||
// If the return has a shipping method get the price and any attachments
|
||||
let shippingTotal = 0
|
||||
if (returnRequest.shipping_method) {
|
||||
shippingTotal = returnRequest.shipping_method.price * (1 + taxRate)
|
||||
const base = returnRequest.shipping_method.price
|
||||
shippingTotal =
|
||||
base +
|
||||
returnRequest.shipping_method.tax_lines.reduce((acc, next) => {
|
||||
return Math.round(acc + base * (next.rate / 100))
|
||||
}, 0)
|
||||
}
|
||||
|
||||
const locale = await this.extractLocale(order)
|
||||
@@ -545,7 +678,7 @@ class SendGridService extends NotificationService {
|
||||
locale,
|
||||
has_shipping: !!returnRequest.shipping_method,
|
||||
email: order.email,
|
||||
items: this.processItems_(returnItems, taxRate, currencyCode),
|
||||
items: returnItems,
|
||||
subtotal: `${this.humanPrice_(
|
||||
item_subtotal,
|
||||
currencyCode
|
||||
@@ -570,11 +703,12 @@ class SendGridService extends NotificationService {
|
||||
}
|
||||
}
|
||||
|
||||
async swapCreatedData({ id }) {
|
||||
async swapReceivedData({ id }) {
|
||||
const store = await this.storeService_.retrieve()
|
||||
const swap = await this.swapService_.retrieve(id, {
|
||||
relations: [
|
||||
"additional_items",
|
||||
"additional_items.tax_lines",
|
||||
"return_order",
|
||||
"return_order.items",
|
||||
"return_order.items.item",
|
||||
@@ -585,9 +719,14 @@ class SendGridService extends NotificationService {
|
||||
|
||||
const returnRequest = swap.return_order
|
||||
|
||||
const items = await this.lineItemService_.list({
|
||||
id: returnRequest.items.map(({ item_id }) => item_id),
|
||||
})
|
||||
const items = await this.lineItemService_.list(
|
||||
{
|
||||
id: returnRequest.items.map(({ item_id }) => item_id),
|
||||
},
|
||||
{
|
||||
relations: ["tax_lines"],
|
||||
}
|
||||
)
|
||||
|
||||
returnRequest.items = returnRequest.items.map((item) => {
|
||||
const found = items.find((i) => i.id === item.item_id)
|
||||
@@ -612,42 +751,51 @@ class SendGridService extends NotificationService {
|
||||
"shipping_address",
|
||||
"swaps",
|
||||
"swaps.additional_items",
|
||||
"swaps.additional_items.tax_lines",
|
||||
],
|
||||
})
|
||||
|
||||
const taxRate = order.tax_rate / 100
|
||||
const cart = await this.cartService_.retrieve(swap.cart_id, {
|
||||
select: [
|
||||
"total",
|
||||
"tax_total",
|
||||
"discount_total",
|
||||
"shipping_total",
|
||||
"subtotal",
|
||||
],
|
||||
})
|
||||
const currencyCode = order.currency_code.toUpperCase()
|
||||
|
||||
let merged = [...order.items]
|
||||
const decoratedItems = await Promise.all(
|
||||
cart.items.map(async (i) => {
|
||||
const totals = await this.totalsService_.getLineItemTotals(i, cart, {
|
||||
include_tax: true,
|
||||
})
|
||||
|
||||
// merge items from order with items from order swaps
|
||||
if (order.swaps && order.swaps.length) {
|
||||
for (const s of order.swaps) {
|
||||
merged = [...merged, ...s.additional_items]
|
||||
}
|
||||
}
|
||||
|
||||
const returnItems = this.processItems_(
|
||||
swap.return_order.items.map((i) => {
|
||||
const found = merged.find((oi) => oi.id === i.item_id)
|
||||
return {
|
||||
...found,
|
||||
quantity: i.quantity,
|
||||
...i,
|
||||
totals,
|
||||
price: this.humanPrice_(
|
||||
totals.subtotal + totals.tax_total,
|
||||
currencyCode
|
||||
),
|
||||
}
|
||||
}),
|
||||
taxRate,
|
||||
currencyCode
|
||||
})
|
||||
)
|
||||
|
||||
const returnTotal = this.totalsService_.getRefundTotal(order, returnItems)
|
||||
const returnTotal = decoratedItems.reduce((acc, next) => {
|
||||
if (next.is_return) {
|
||||
return acc + -1 * (next.totals.subtotal + next.totals.tax_total)
|
||||
}
|
||||
return acc
|
||||
}, 0)
|
||||
|
||||
const constructedOrder = {
|
||||
...order,
|
||||
shipping_methods: [],
|
||||
items: swap.additional_items,
|
||||
}
|
||||
|
||||
const additionalTotal = this.totalsService_.getTotal(constructedOrder)
|
||||
const additionalTotal = decoratedItems.reduce((acc, next) => {
|
||||
if (!next.is_return) {
|
||||
return acc + next.totals.subtotal + next.totals.tax_total
|
||||
}
|
||||
return acc
|
||||
}, 0)
|
||||
|
||||
const refundAmount = swap.return_order.refund_amount
|
||||
|
||||
@@ -661,8 +809,143 @@ class SendGridService extends NotificationService {
|
||||
date: swap.updated_at.toDateString(),
|
||||
swap_link: swapLink,
|
||||
email: order.email,
|
||||
items: this.processItems_(swap.additional_items, taxRate, currencyCode),
|
||||
return_items: returnItems,
|
||||
items: decoratedItems.filter((di) => !di.is_return),
|
||||
return_items: decoratedItems.filter((di) => di.is_return),
|
||||
return_total: `${this.humanPrice_(
|
||||
returnTotal,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
tax_total: `${this.humanPrice_(
|
||||
cart.total,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
refund_amount: `${this.humanPrice_(
|
||||
refundAmount,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
additional_total: `${this.humanPrice_(
|
||||
additionalTotal,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
}
|
||||
}
|
||||
|
||||
async swapCreatedData({ id }) {
|
||||
const store = await this.storeService_.retrieve()
|
||||
const swap = await this.swapService_.retrieve(id, {
|
||||
relations: [
|
||||
"additional_items",
|
||||
"additional_items.tax_lines",
|
||||
"return_order",
|
||||
"return_order.items",
|
||||
"return_order.items.item",
|
||||
"return_order.shipping_method",
|
||||
"return_order.shipping_method.shipping_option",
|
||||
],
|
||||
})
|
||||
|
||||
const returnRequest = swap.return_order
|
||||
|
||||
const items = await this.lineItemService_.list(
|
||||
{
|
||||
id: returnRequest.items.map(({ item_id }) => item_id),
|
||||
},
|
||||
{
|
||||
relations: ["tax_lines"],
|
||||
}
|
||||
)
|
||||
|
||||
returnRequest.items = returnRequest.items.map((item) => {
|
||||
const found = items.find((i) => i.id === item.item_id)
|
||||
return {
|
||||
...item,
|
||||
item: found,
|
||||
}
|
||||
})
|
||||
|
||||
const swapLink = store.swap_link_template.replace(
|
||||
/\{cart_id\}/,
|
||||
swap.cart_id
|
||||
)
|
||||
|
||||
const order = await this.orderService_.retrieve(swap.order_id, {
|
||||
select: ["total"],
|
||||
relations: [
|
||||
"items",
|
||||
"items.tax_lines",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"shipping_address",
|
||||
"swaps",
|
||||
"swaps.additional_items",
|
||||
"swaps.additional_items.tax_lines",
|
||||
],
|
||||
})
|
||||
|
||||
const cart = await this.cartService_.retrieve(swap.cart_id, {
|
||||
select: [
|
||||
"total",
|
||||
"tax_total",
|
||||
"discount_total",
|
||||
"shipping_total",
|
||||
"subtotal",
|
||||
],
|
||||
})
|
||||
const currencyCode = order.currency_code.toUpperCase()
|
||||
|
||||
const decoratedItems = await Promise.all(
|
||||
cart.items.map(async (i) => {
|
||||
const totals = await this.totalsService_.getLineItemTotals(i, cart, {
|
||||
include_tax: true,
|
||||
})
|
||||
|
||||
return {
|
||||
...i,
|
||||
totals,
|
||||
tax_lines: totals.tax_lines,
|
||||
price: `${this.humanPrice_(
|
||||
totals.original_total / i.quantity,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
discounted_price: `${this.humanPrice_(
|
||||
totals.total / i.quantity,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
const returnTotal = decoratedItems.reduce((acc, next) => {
|
||||
const { total } = next.totals
|
||||
if (next.is_return && next.variant_id) {
|
||||
return acc + -1 * total
|
||||
}
|
||||
return acc
|
||||
}, 0)
|
||||
|
||||
const additionalTotal = decoratedItems.reduce((acc, next) => {
|
||||
const { total } = next.totals
|
||||
if (!next.is_return) {
|
||||
return acc + total
|
||||
}
|
||||
return acc
|
||||
}, 0)
|
||||
|
||||
const refundAmount = swap.return_order.refund_amount
|
||||
|
||||
const locale = await this.extractLocale(order)
|
||||
|
||||
return {
|
||||
locale,
|
||||
swap,
|
||||
order,
|
||||
return_request: returnRequest,
|
||||
date: swap.updated_at.toDateString(),
|
||||
swap_link: swapLink,
|
||||
email: order.email,
|
||||
items: decoratedItems.filter((di) => !di.is_return),
|
||||
return_items: decoratedItems.filter((di) => di.is_return),
|
||||
return_total: `${this.humanPrice_(
|
||||
returnTotal,
|
||||
currencyCode
|
||||
@@ -687,7 +970,9 @@ class SendGridService extends NotificationService {
|
||||
relations: [
|
||||
"shipping_address",
|
||||
"shipping_methods",
|
||||
"shipping_methods.tax_lines",
|
||||
"additional_items",
|
||||
"additional_items.tax_lines",
|
||||
"return_order",
|
||||
"return_order.items",
|
||||
],
|
||||
@@ -695,40 +980,68 @@ class SendGridService extends NotificationService {
|
||||
|
||||
const order = await this.orderService_.retrieve(swap.order_id, {
|
||||
relations: [
|
||||
"region",
|
||||
"items",
|
||||
"items.tax_lines",
|
||||
"discounts",
|
||||
"discounts.rule",
|
||||
"discounts.rule.valid_for",
|
||||
"swaps",
|
||||
"swaps.additional_items",
|
||||
"swaps.additional_items.tax_lines",
|
||||
],
|
||||
})
|
||||
|
||||
let merged = [...order.items]
|
||||
const cart = await this.cartService_.retrieve(swap.cart_id, {
|
||||
select: [
|
||||
"total",
|
||||
"tax_total",
|
||||
"discount_total",
|
||||
"shipping_total",
|
||||
"subtotal",
|
||||
],
|
||||
})
|
||||
|
||||
// merge items from order with items from order swaps
|
||||
if (order.swaps && order.swaps.length) {
|
||||
for (const s of order.swaps) {
|
||||
merged = [...merged, ...s.additional_items]
|
||||
const returnRequest = swap.return_order
|
||||
const items = await this.lineItemService_.list(
|
||||
{
|
||||
id: returnRequest.items.map(({ item_id }) => item_id),
|
||||
},
|
||||
{
|
||||
relations: ["tax_lines"],
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const taxRate = order.tax_rate / 100
|
||||
const currencyCode = order.currency_code.toUpperCase()
|
||||
|
||||
const returnItems = this.processItems_(
|
||||
swap.return_order.items.map((i) => {
|
||||
const found = merged.find((oi) => oi.id === i.item_id)
|
||||
const returnItems = await Promise.all(
|
||||
swap.return_order.items.map(async (i) => {
|
||||
const found = items.find((oi) => oi.id === i.item_id)
|
||||
const totals = await this.totalsService_.getLineItemTotals(i, cart, {
|
||||
include_tax: true,
|
||||
})
|
||||
|
||||
return {
|
||||
...found,
|
||||
thumbnail: this.normalizeThumbUrl_(found.thumbnail),
|
||||
price: `${this.humanPrice_(
|
||||
totals.original_total / i.quantity,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
discounted_price: `${this.humanPrice_(
|
||||
totals.total / i.quantity,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
quantity: i.quantity,
|
||||
}
|
||||
}),
|
||||
taxRate,
|
||||
currencyCode
|
||||
})
|
||||
)
|
||||
|
||||
const returnTotal = this.totalsService_.getRefundTotal(order, returnItems)
|
||||
const returnTotal = await this.totalsService_.getRefundTotal(
|
||||
order,
|
||||
returnItems
|
||||
)
|
||||
|
||||
const constructedOrder = {
|
||||
...order,
|
||||
@@ -736,7 +1049,7 @@ class SendGridService extends NotificationService {
|
||||
items: swap.additional_items,
|
||||
}
|
||||
|
||||
const additionalTotal = this.totalsService_.getTotal(constructedOrder)
|
||||
const additionalTotal = await this.totalsService_.getTotal(constructedOrder)
|
||||
|
||||
const refundAmount = swap.return_order.refund_amount
|
||||
|
||||
@@ -750,11 +1063,31 @@ class SendGridService extends NotificationService {
|
||||
locale,
|
||||
swap,
|
||||
order,
|
||||
items: this.processItems_(swap.additional_items, taxRate, currencyCode),
|
||||
items: await Promise.all(
|
||||
swap.additional_items.map(async (i) => {
|
||||
const totals = await this.totalsService_.getLineItemTotals(i, cart, {
|
||||
include_tax: true,
|
||||
})
|
||||
|
||||
return {
|
||||
...i,
|
||||
thumbnail: this.normalizeThumbUrl_(i.thumbnail),
|
||||
price: `${this.humanPrice_(
|
||||
totals.original_total / i.quantity,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
discounted_price: `${this.humanPrice_(
|
||||
totals.total / i.quantity,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
quantity: i.quantity,
|
||||
}
|
||||
})
|
||||
),
|
||||
date: swap.updated_at.toDateString(),
|
||||
email: order.email,
|
||||
tax_amount: `${this.humanPrice_(
|
||||
swap.difference_due * taxRate,
|
||||
cart.tax_total,
|
||||
currencyCode
|
||||
)} ${currencyCode}`,
|
||||
paid_total: `${this.humanPrice_(
|
||||
@@ -871,7 +1204,7 @@ class SendGridService extends NotificationService {
|
||||
if (fromOrder.cart_id) {
|
||||
try {
|
||||
const cart = await this.cartService_.retrieve(fromOrder.cart_id, {
|
||||
select: ["context"],
|
||||
select: ["id", "context"],
|
||||
})
|
||||
|
||||
if (cart.context && cart.context.locale) {
|
||||
|
||||
Reference in New Issue
Block a user