fix(medusa-payment-klarna, medusa-payment-stripe, medusa-payment-paypal): Totals calculation (#2381)

This commit is contained in:
Sebastian Rindom
2022-10-08 10:53:19 +02:00
committed by GitHub
parent 5f2bc975cb
commit a908a7716c
8 changed files with 157 additions and 198 deletions
@@ -16,6 +16,7 @@ export const carts = {
title: "merge line",
description: "This is a new line",
thumbnail: "test-img-yeah.com/thumb",
tax_lines: [],
content: [
{
unit_price: 8,
@@ -45,6 +46,7 @@ export const carts = {
title: "merge line",
description: "This is a new line",
thumbnail: "test-img-yeah.com/thumb",
tax_lines: [],
content: {
unit_price: 10,
variant: {
@@ -62,6 +64,7 @@ export const carts = {
{
id: IdMap.getId("freeShipping"),
name: "Free shipping",
tax_lines: [],
data: {
name: "test",
},
@@ -2,107 +2,78 @@ export default async (req, res) => {
// In Medusa, we store the cart id in merchant_data
const { shipping_address, merchant_data } = req.body
try {
const manager = req.scope.resolve("manager")
const cartService = req.scope.resolve("cartService")
const klarnaProviderService = req.scope.resolve("pp_klarna")
const shippingProfileService = req.scope.resolve("shippingProfileService")
const cartService = req.scope.resolve("cartService")
const klarnaProviderService = req.scope.resolve("pp_klarna")
const shippingProfileService = req.scope.resolve("shippingProfileService")
const result = await manager.transaction("SERIALIZABLE", async (m) => {
const cart = await cartService.retrieve(merchant_data, {
select: ["subtotal"],
relations: [
"shipping_address",
"billing_address",
"region",
"items",
"shipping_methods",
"shipping_methods.shipping_option",
"items.variant",
"items.variant.product",
],
})
if (shipping_address) {
const shippingAddress = {
first_name: shipping_address.given_name,
last_name: shipping_address.family_name,
address_1: shipping_address.street_address,
address_2: shipping_address.street_address2,
city: shipping_address.city,
country_code: shipping_address.country,
postal_code: shipping_address.postal_code,
phone: shipping_address.phone,
}
if (shipping_address) {
const shippingAddress = {
first_name: shipping_address.given_name,
last_name: shipping_address.family_name,
address_1: shipping_address.street_address,
address_2: shipping_address.street_address2,
city: shipping_address.city,
country_code: shipping_address.country,
postal_code: shipping_address.postal_code,
phone: shipping_address.phone,
}
let billingAddress = {
first_name: shipping_address.given_name,
last_name: shipping_address.family_name,
address_1: shipping_address.street_address,
address_2: shipping_address.street_address2,
city: shipping_address.city,
country_code: shipping_address.country,
postal_code: shipping_address.postal_code,
phone: shipping_address.phone,
}
let billingAddress = {
first_name: shipping_address.given_name,
last_name: shipping_address.family_name,
address_1: shipping_address.street_address,
address_2: shipping_address.street_address2,
city: shipping_address.city,
country_code: shipping_address.country,
postal_code: shipping_address.postal_code,
phone: shipping_address.phone,
}
await cartService.update(cart.id, {
shipping_address: shippingAddress,
billing_address: billingAddress,
email: shipping_address.email,
})
const shippingOptions = await shippingProfileService.fetchCartOptions(
cart
)
if (shippingOptions?.length) {
const option = shippingOptions.find(
(o) => o.data && !o.data.require_drop_point
)
await cartService
.withTransaction(m)
.addShippingMethod(cart.id, option.id, option.data)
}
// Fetch and return updated Klarna order
const updatedCart = await cartService
.withTransaction(m)
.retrieve(cart.id, {
select: [
"gift_card_total",
"subtotal",
"total",
"shipping_total",
"tax_total",
"discount_total",
"subtotal",
],
relations: [
"shipping_address",
"billing_address",
"region",
"shipping_methods",
"shipping_methods.shipping_option",
"items",
"items.variant",
"items.variant.product",
],
})
return klarnaProviderService.cartToKlarnaOrder(updatedCart)
} else {
return null
}
await cartService.update(merchant_data, {
shipping_address: shippingAddress,
billing_address: billingAddress,
email: shipping_address.email,
})
if (result) {
res.json(result)
return
} else {
res.sendStatus(400)
return
let cart = await cartService.retrieveWithTotals(merchant_data, {
relations: [
"shipping_address",
"billing_address",
"region",
"shipping_methods",
"shipping_methods.shipping_option",
"items",
"items.variant",
"items.variant.product",
],
})
const shippingOptions = await shippingProfileService.fetchCartOptions(cart)
if (shippingOptions?.length) {
const option = shippingOptions.find(
(o) => o.data && !o.data.require_drop_point
)
if (option) {
await cartService.addShippingMethod(cart.id, option.id, option.data)
cart = await cartService.retrieveWithTotals(cart.id, {
relations: [
"shipping_address",
"billing_address",
"region",
"shipping_methods",
"shipping_methods.shipping_option",
"items",
"items.variant",
"items.variant.product",
],
})
}
}
} catch (error) {
throw error
const order = await klarnaProviderService.cartToKlarnaOrder(cart)
res.json(order)
} else {
res.sendStatus(400)
return
}
}
@@ -7,20 +7,23 @@ export default async (req, res) => {
const klarnaProviderService = req.scope.resolve("pp_klarna")
const shippingProfileService = req.scope.resolve("shippingProfileService")
const cart = await cartService.retrieve(merchant_data, {
select: ["subtotal"],
relations: [
"shipping_address",
"billing_address",
"region",
"shipping_methods",
"shipping_methods.shipping_option",
"items",
"items.adjustments",
"items.variant",
"items.variant.product",
],
})
const cart = await cartService.retrieveWithTotals(
merchant_data,
{
relations: [
"shipping_address",
"billing_address",
"region",
"shipping_methods",
"shipping_methods.shipping_option",
"items",
"items.adjustments",
"items.variant",
"items.variant.product",
],
},
{ force_taxes: true }
)
let shippingOptions = await shippingProfileService.fetchCartOptions(cart)
shippingOptions = shippingOptions.filter(
@@ -35,28 +38,23 @@ export default async (req, res) => {
}
}
const newCart = await cartService.retrieve(cart.id, {
select: [
"gift_card_total",
"subtotal",
"total",
"shipping_total",
"tax_total",
"discount_total",
"subtotal",
],
relations: [
"shipping_address",
"billing_address",
"shipping_methods",
"shipping_methods.shipping_option",
"region",
"items",
"items.adjustments",
"items.variant",
"items.variant.product",
],
})
const newCart = await cartService.retrieveWithTotals(
cart.id,
{
relations: [
"shipping_address",
"billing_address",
"shipping_methods",
"shipping_methods.shipping_option",
"region",
"items",
"items.adjustments",
"items.variant",
"items.variant.product",
],
},
{ force_taxes: true }
)
const order = await klarnaProviderService.cartToKlarnaOrder(newCart)
@@ -5,7 +5,7 @@ import { PaymentService } from "medusa-interfaces"
class KlarnaProviderService extends PaymentService {
static identifier = "klarna"
constructor({ shippingProfileService, totalsService }, options) {
constructor({ logger, shippingProfileService, totalsService }, options) {
super()
/**
@@ -23,6 +23,7 @@ class KlarnaProviderService extends PaymentService {
* }
*/
this.options_ = options
this.logger_ = logger
/** @private @const {Klarna} */
this.klarna_ = axios.create({
@@ -53,22 +54,16 @@ class KlarnaProviderService extends PaymentService {
// Withdraw discount from the total item amount
const quantity = item.quantity
const totals = await this.totalsService_.getLineItemTotals(item, cart, {
include_tax: true,
})
const tax =
totals.tax_lines.reduce((acc, next) => acc + next.rate, 0) / 100
const tax = item.tax_lines.reduce((acc, next) => acc + next.rate, 0) / 100
order_lines.push({
name: item.title,
tax_rate: tax * 10000,
quantity,
unit_price: Math.round(totals.original_total / item.quantity),
total_amount: totals.total - totals.gift_card_total,
total_tax_amount: totals.tax_total,
total_discount_amount:
totals.original_total - totals.total + totals.gift_card_total,
unit_price: Math.round(item.original_total / item.quantity),
total_amount: item.total,
total_tax_amount: item.tax_total,
total_discount_amount: item.original_total - item.total,
})
}
@@ -79,23 +74,15 @@ class KlarnaProviderService extends PaymentService {
let taxRate = 0
if (cart.shipping_total > 0) {
for (const next of cart.shipping_methods) {
const totals = await this.totalsService_.getShippingMethodTotals(
next,
cart,
{
include_tax: true,
}
)
for (const method of cart.shipping_methods) {
const methodTaxRate =
totals.tax_lines.reduce((acc, next) => acc + next.rate, 0) / 100
method.tax_lines.reduce((acc, next) => acc + next.rate, 0) / 100
name.push(next?.shipping_option.name)
name.push(method.shipping_option.name)
total += totals.total
taxRate += (totals.price / cart.shipping_total) * methodTaxRate
tax += totals.tax_total
total += method.total
taxRate += (method.price / cart.shipping_total) * methodTaxRate
tax += method.tax_total
}
}
@@ -124,16 +111,17 @@ class KlarnaProviderService extends PaymentService {
order.order_lines = await this.lineItemsToOrderLines_(cart)
if (gift_card_total && !region.gift_cards_taxable) {
if (gift_card_total) {
const taxRate = cart.gift_card_tax_total / cart.gift_card_total
order.order_lines.push({
name: `Gift Card`,
name: "Gift Card",
quantity: 1,
type: "gift_card",
unit_price: 0,
total_discount_amount: gift_card_total,
tax_rate: 0,
total_amount: -gift_card_total,
total_tax_amount: 0,
unit_price: -1 * (cart.gift_card_total + cart.gift_card_tax_total),
tax_rate: Math.round(taxRate * 10000),
total_amount: -1 * (cart.gift_card_total + cart.gift_card_tax_total),
total_tax_amount: -1 * cart.gift_card_tax_total,
})
}
@@ -159,7 +147,7 @@ class KlarnaProviderService extends PaymentService {
}
order.order_amount = total
order.order_tax_amount = tax_total
order.order_tax_amount = tax_total - cart.gift_card_tax_total
order.purchase_currency = region.currency_code.toUpperCase()
order.merchant_urls = {
@@ -183,21 +171,13 @@ class KlarnaProviderService extends PaymentService {
// If the cart does not have shipping methods yet, preselect one from
// shipping_options and set the selected shipping method
if (cart.shipping_methods.length) {
const shipping_method = cart.shipping_methods[0]
const totals = await this.totalsService_.getShippingMethodTotals(
shipping_method,
cart,
{
include_tax: true,
}
)
const taxRate = totals.tax_total / (totals.total - totals.tax_total)
const method = cart.shipping_methods[0]
const taxRate = method.tax_total / (method.total - method.tax_total)
order.selected_shipping_option = {
id: shipping_method.shipping_option.id,
name: shipping_method.shipping_option.name,
price: totals.total,
tax_amount: total.tax_total,
id: method.shipping_option.id,
name: method.shipping_option.name,
price: method.total,
tax_amount: method.tax_total,
tax_rate: taxRate * 10000,
}
}
@@ -286,6 +266,7 @@ class KlarnaProviderService extends PaymentService {
return klarnaPayment
} catch (error) {
this.logger_.error(error)
throw error
}
}