feat(medusa): Add line item totals to cart totals decoration (#1740)
This commit is contained in:
@@ -0,0 +1,237 @@
|
|||||||
|
const path = require("path")
|
||||||
|
|
||||||
|
const setupServer = require("../../../helpers/setup-server")
|
||||||
|
const { useApi } = require("../../../helpers/use-api")
|
||||||
|
const { useDb, initDb } = require("../../../helpers/use-db")
|
||||||
|
const {
|
||||||
|
simpleDiscountFactory,
|
||||||
|
simpleRegionFactory,
|
||||||
|
simpleProductFactory,
|
||||||
|
simpleProductTaxRateFactory,
|
||||||
|
} = require("../../factories")
|
||||||
|
|
||||||
|
const adminSeeder = require("../../helpers/admin-seeder")
|
||||||
|
|
||||||
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
|
describe("Cart Totals Calculations", () => {
|
||||||
|
let medusaProcess
|
||||||
|
let dbConnection
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const cwd = path.resolve(path.join(__dirname, "..", ".."))
|
||||||
|
dbConnection = await initDb({ cwd })
|
||||||
|
medusaProcess = await setupServer({ cwd })
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.shutdown()
|
||||||
|
|
||||||
|
medusaProcess.kill()
|
||||||
|
})
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
try {
|
||||||
|
await adminSeeder(dbConnection)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
await db.teardown()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets correct line item totals for a cart with item of price 100 and tax rate 10", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const region = await simpleRegionFactory(dbConnection)
|
||||||
|
const product = await simpleProductFactory(dbConnection)
|
||||||
|
await simpleProductTaxRateFactory(dbConnection, {
|
||||||
|
product_id: product.id,
|
||||||
|
rate: {
|
||||||
|
region_id: region.id,
|
||||||
|
rate: 10,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// create cart
|
||||||
|
const { cart } = await api
|
||||||
|
.post("/store/carts", {
|
||||||
|
region_id: region.id,
|
||||||
|
})
|
||||||
|
.then((res) => res.data)
|
||||||
|
|
||||||
|
// add product to cart
|
||||||
|
const res = await api.post(`/store/carts/${cart.id}/line-items`, {
|
||||||
|
variant_id: product.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(res.data.cart.items[0].unit_price).toEqual(100)
|
||||||
|
expect(res.data.cart.items[0].quantity).toEqual(1)
|
||||||
|
expect(res.data.cart.items[0].subtotal).toEqual(100)
|
||||||
|
expect(res.data.cart.items[0].tax_total).toEqual(10)
|
||||||
|
expect(res.data.cart.items[0].total).toEqual(110)
|
||||||
|
expect(res.data.cart.items[0].original_total).toEqual(110)
|
||||||
|
expect(res.data.cart.items[0].original_tax_total).toEqual(10)
|
||||||
|
expect(res.data.cart.items[0].discount_total).toEqual(0)
|
||||||
|
expect(res.data.cart.items[0].gift_card_total).toEqual(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets correct line item totals for a cart with item of price 100; tax rate 10; discount 10", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const region = await simpleRegionFactory(dbConnection)
|
||||||
|
const product = await simpleProductFactory(dbConnection)
|
||||||
|
const discount = await simpleDiscountFactory(dbConnection, {
|
||||||
|
regions: [region.id],
|
||||||
|
type: "percentage",
|
||||||
|
value: 10,
|
||||||
|
})
|
||||||
|
|
||||||
|
await simpleProductTaxRateFactory(dbConnection, {
|
||||||
|
product_id: product.id,
|
||||||
|
rate: {
|
||||||
|
region_id: region.id,
|
||||||
|
rate: 10,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const { cart } = await api
|
||||||
|
.post("/store/carts", {
|
||||||
|
region_id: region.id,
|
||||||
|
})
|
||||||
|
.then((res) => res.data)
|
||||||
|
|
||||||
|
await api.post(`/store/carts/${cart.id}/line-items`, {
|
||||||
|
variant_id: product.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
const res = await api.post(`/store/carts/${cart.id}`, {
|
||||||
|
discounts: [
|
||||||
|
{
|
||||||
|
code: discount.code,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(res.data.cart.items[0].unit_price).toEqual(100)
|
||||||
|
expect(res.data.cart.items[0].quantity).toEqual(1)
|
||||||
|
expect(res.data.cart.items[0].subtotal).toEqual(100)
|
||||||
|
expect(res.data.cart.items[0].tax_total).toEqual(9)
|
||||||
|
expect(res.data.cart.items[0].total).toEqual(99)
|
||||||
|
expect(res.data.cart.items[0].original_total).toEqual(110)
|
||||||
|
expect(res.data.cart.items[0].original_tax_total).toEqual(10)
|
||||||
|
expect(res.data.cart.items[0].discount_total).toEqual(10)
|
||||||
|
expect(res.data.cart.items[0].gift_card_total).toEqual(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("doesn't include taxes in !automatic_taxes regions", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const region = await simpleRegionFactory(dbConnection, {
|
||||||
|
automatic_taxes: false,
|
||||||
|
})
|
||||||
|
const product = await simpleProductFactory(dbConnection)
|
||||||
|
const discount = await simpleDiscountFactory(dbConnection, {
|
||||||
|
regions: [region.id],
|
||||||
|
type: "percentage",
|
||||||
|
value: 10,
|
||||||
|
})
|
||||||
|
|
||||||
|
await simpleProductTaxRateFactory(dbConnection, {
|
||||||
|
product_id: product.id,
|
||||||
|
rate: {
|
||||||
|
region_id: region.id,
|
||||||
|
rate: 10,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const { cart } = await api
|
||||||
|
.post("/store/carts", {
|
||||||
|
region_id: region.id,
|
||||||
|
})
|
||||||
|
.then((res) => res.data)
|
||||||
|
|
||||||
|
await api.post(`/store/carts/${cart.id}/line-items`, {
|
||||||
|
variant_id: product.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
const res = await api.post(`/store/carts/${cart.id}`, {
|
||||||
|
discounts: [
|
||||||
|
{
|
||||||
|
code: discount.code,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(res.data.cart.items[0].unit_price).toEqual(100)
|
||||||
|
expect(res.data.cart.items[0].quantity).toEqual(1)
|
||||||
|
expect(res.data.cart.items[0].subtotal).toEqual(100)
|
||||||
|
expect(res.data.cart.items[0].tax_total).toEqual(0)
|
||||||
|
expect(res.data.cart.items[0].total).toEqual(90)
|
||||||
|
expect(res.data.cart.items[0].original_total).toEqual(100)
|
||||||
|
expect(res.data.cart.items[0].original_tax_total).toEqual(0)
|
||||||
|
expect(res.data.cart.items[0].discount_total).toEqual(10)
|
||||||
|
expect(res.data.cart.items[0].gift_card_total).toEqual(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("includes taxes in !automatic_taxes regions when forced", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const region = await simpleRegionFactory(dbConnection, {
|
||||||
|
automatic_taxes: false,
|
||||||
|
})
|
||||||
|
const product = await simpleProductFactory(dbConnection)
|
||||||
|
const discount = await simpleDiscountFactory(dbConnection, {
|
||||||
|
regions: [region.id],
|
||||||
|
type: "percentage",
|
||||||
|
value: 10,
|
||||||
|
})
|
||||||
|
|
||||||
|
await simpleProductTaxRateFactory(dbConnection, {
|
||||||
|
product_id: product.id,
|
||||||
|
rate: {
|
||||||
|
region_id: region.id,
|
||||||
|
rate: 10,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const { cart } = await api
|
||||||
|
.post("/store/carts", {
|
||||||
|
region_id: region.id,
|
||||||
|
})
|
||||||
|
.then((res) => res.data)
|
||||||
|
|
||||||
|
await api.post(`/store/carts/${cart.id}/line-items`, {
|
||||||
|
variant_id: product.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
await api.post(`/store/carts/${cart.id}`, {
|
||||||
|
discounts: [
|
||||||
|
{
|
||||||
|
code: discount.code,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const res = await api.post(`/store/carts/${cart.id}/taxes`)
|
||||||
|
|
||||||
|
expect(res.data.cart.items[0].unit_price).toEqual(100)
|
||||||
|
expect(res.data.cart.items[0].quantity).toEqual(1)
|
||||||
|
expect(res.data.cart.items[0].subtotal).toEqual(100)
|
||||||
|
expect(res.data.cart.items[0].tax_total).toEqual(9)
|
||||||
|
expect(res.data.cart.items[0].total).toEqual(99)
|
||||||
|
expect(res.data.cart.items[0].original_total).toEqual(110)
|
||||||
|
expect(res.data.cart.items[0].original_tax_total).toEqual(10)
|
||||||
|
expect(res.data.cart.items[0].discount_total).toEqual(10)
|
||||||
|
expect(res.data.cart.items[0].gift_card_total).toEqual(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
export * from "./simple-payment-factory"
|
export * from "./simple-payment-factory"
|
||||||
export * from "./simple-batch-job-factory"
|
export * from "./simple-batch-job-factory"
|
||||||
|
export * from "./simple-discount-factory"
|
||||||
export * from "./simple-order-factory"
|
export * from "./simple-order-factory"
|
||||||
export * from "./simple-cart-factory"
|
export * from "./simple-cart-factory"
|
||||||
export * from "./simple-region-factory"
|
export * from "./simple-region-factory"
|
||||||
@@ -14,4 +15,3 @@ export * from "./simple-shipping-method-factory"
|
|||||||
export * from "./simple-product-type-tax-rate-factory"
|
export * from "./simple-product-type-tax-rate-factory"
|
||||||
export * from "./simple-price-list-factory"
|
export * from "./simple-price-list-factory"
|
||||||
export * from "./simple-batch-job-factory"
|
export * from "./simple-batch-job-factory"
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { EntityManager } from "typeorm"
|
|||||||
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
||||||
import { CartService } from "../../../../services"
|
import { CartService } from "../../../../services"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [post] /carts/{id}/shipping-methods
|
* @oas [post] /carts/{id}/shipping-methods
|
||||||
@@ -59,7 +60,9 @@ export default async (req, res) => {
|
|||||||
relations: defaultStoreCartRelations,
|
relations: defaultStoreCartRelations,
|
||||||
})
|
})
|
||||||
|
|
||||||
res.status(200).json({ cart: updatedCart })
|
const data = await decorateLineItemsWithTotals(updatedCart, req)
|
||||||
|
|
||||||
|
res.status(200).json({ cart: data })
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StorePostCartsCartShippingMethodReq {
|
export class StorePostCartsCartShippingMethodReq {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { EntityManager } from "typeorm"
|
import { EntityManager } from "typeorm"
|
||||||
import { IdempotencyKey } from "../../../../models/idempotency-key"
|
import { IdempotencyKey } from "../../../../models/idempotency-key"
|
||||||
import { CartService, IdempotencyKeyService } from "../../../../services"
|
import { CartService, IdempotencyKeyService } from "../../../../services"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [post] /carts/{id}/taxes
|
* @oas [post] /carts/{id}/taxes
|
||||||
@@ -64,6 +65,7 @@ export default async (req, res) => {
|
|||||||
const cart = await cartService.withTransaction(manager).retrieve(
|
const cart = await cartService.withTransaction(manager).retrieve(
|
||||||
id,
|
id,
|
||||||
{
|
{
|
||||||
|
relations: ["items", "items.adjustments"],
|
||||||
select: [
|
select: [
|
||||||
"total",
|
"total",
|
||||||
"subtotal",
|
"subtotal",
|
||||||
@@ -76,9 +78,13 @@ export default async (req, res) => {
|
|||||||
{ force_taxes: true }
|
{ force_taxes: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const data = await decorateLineItemsWithTotals(cart, req, {
|
||||||
|
force_taxes: true,
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
response_code: 200,
|
response_code: 200,
|
||||||
response_body: { cart },
|
response_body: { cart: data },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
|||||||
import { CartService, LineItemService } from "../../../../services"
|
import { CartService, LineItemService } from "../../../../services"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
import { AddressPayload } from "../../../../types/common"
|
import { AddressPayload } from "../../../../types/common"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [post] /carts
|
* @oas [post] /carts
|
||||||
@@ -144,7 +145,9 @@ export default async (req, res) => {
|
|||||||
relations: defaultStoreCartRelations,
|
relations: defaultStoreCartRelations,
|
||||||
})
|
})
|
||||||
|
|
||||||
res.status(200).json({ cart })
|
const data = await decorateLineItemsWithTotals(cart, req)
|
||||||
|
|
||||||
|
res.status(200).json({ cart: data })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { EntityManager } from "typeorm"
|
|||||||
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
||||||
import { CartService, LineItemService } from "../../../../services"
|
import { CartService, LineItemService } from "../../../../services"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [post] /carts/{id}/line-items
|
* @oas [post] /carts/{id}/line-items
|
||||||
@@ -63,7 +64,9 @@ export default async (req, res) => {
|
|||||||
relations: defaultStoreCartRelations,
|
relations: defaultStoreCartRelations,
|
||||||
})
|
})
|
||||||
|
|
||||||
res.status(200).json({ cart })
|
const data = await decorateLineItemsWithTotals(cart, req)
|
||||||
|
|
||||||
|
res.status(200).json({ cart: data })
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StorePostCartsCartLineItemsReq {
|
export class StorePostCartsCartLineItemsReq {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
||||||
import { CartService } from "../../../../services"
|
import { CartService } from "../../../../services"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [post] /carts/{id}/payment-sessions
|
* @oas [post] /carts/{id}/payment-sessions
|
||||||
@@ -32,5 +33,6 @@ export default async (req, res) => {
|
|||||||
relations: defaultStoreCartRelations,
|
relations: defaultStoreCartRelations,
|
||||||
})
|
})
|
||||||
|
|
||||||
res.status(200).json({ cart })
|
const data = await decorateLineItemsWithTotals(cart, req)
|
||||||
|
res.status(200).json({ cart: data })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { Request } from "express"
|
||||||
|
import { TotalsService } from "../../../../services"
|
||||||
|
import { Cart, LineItem } from "../../../../models"
|
||||||
|
|
||||||
|
export const decorateLineItemsWithTotals = async (
|
||||||
|
cart: Cart,
|
||||||
|
req: Request,
|
||||||
|
options: { force_taxes: boolean } = { force_taxes: false }
|
||||||
|
): Promise<Cart> => {
|
||||||
|
const totalsService: TotalsService = req.scope.resolve("totalsService")
|
||||||
|
|
||||||
|
if (cart.items && cart.region) {
|
||||||
|
const items = await Promise.all(
|
||||||
|
cart.items.map(async (item: LineItem) => {
|
||||||
|
const itemTotals = await totalsService.getLineItemTotals(item, cart, {
|
||||||
|
include_tax: options.force_taxes || cart.region.automatic_taxes,
|
||||||
|
})
|
||||||
|
|
||||||
|
return Object.assign(item, itemTotals)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
return Object.assign(cart, { items })
|
||||||
|
}
|
||||||
|
|
||||||
|
return cart
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { EntityManager } from "typeorm"
|
import { EntityManager } from "typeorm"
|
||||||
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
||||||
import { CartService } from "../../../../services"
|
import { CartService } from "../../../../services"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [delete] /carts/{id}/discounts/{code}
|
* @oas [delete] /carts/{id}/discounts/{code}
|
||||||
@@ -46,6 +47,7 @@ export default async (req, res) => {
|
|||||||
select: defaultStoreCartFields,
|
select: defaultStoreCartFields,
|
||||||
relations: defaultStoreCartRelations,
|
relations: defaultStoreCartRelations,
|
||||||
})
|
})
|
||||||
|
const data = await decorateLineItemsWithTotals(cart, req)
|
||||||
|
|
||||||
res.status(200).json({ cart })
|
res.status(200).json({ cart: data })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { EntityManager } from "typeorm"
|
import { EntityManager } from "typeorm"
|
||||||
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
||||||
import { CartService } from "../../../../services"
|
import { CartService } from "../../../../services"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [delete] /carts/{id}/line-items/{line_id}
|
* @oas [delete] /carts/{id}/line-items/{line_id}
|
||||||
@@ -46,6 +47,7 @@ export default async (req, res) => {
|
|||||||
select: defaultStoreCartFields,
|
select: defaultStoreCartFields,
|
||||||
relations: defaultStoreCartRelations,
|
relations: defaultStoreCartRelations,
|
||||||
})
|
})
|
||||||
|
const data = await decorateLineItemsWithTotals(cart, req)
|
||||||
|
|
||||||
res.status(200).json({ cart })
|
res.status(200).json({ cart: data })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
||||||
import { CartService } from "../../../../services"
|
import { CartService } from "../../../../services"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [delete] /carts/{id}/payment-sessions/{provider_id}
|
* @oas [delete] /carts/{id}/payment-sessions/{provider_id}
|
||||||
@@ -32,5 +33,6 @@ export default async (req, res) => {
|
|||||||
relations: defaultStoreCartRelations,
|
relations: defaultStoreCartRelations,
|
||||||
})
|
})
|
||||||
|
|
||||||
res.status(200).json({ cart })
|
const data = await decorateLineItemsWithTotals(cart, req)
|
||||||
|
res.status(200).json({ cart: data })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
||||||
import { CartService } from "../../../../services"
|
import { CartService } from "../../../../services"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [get] /carts/{id}
|
* @oas [get] /carts/{id}
|
||||||
@@ -47,5 +48,6 @@ export default async (req, res) => {
|
|||||||
relations: defaultStoreCartRelations,
|
relations: defaultStoreCartRelations,
|
||||||
})
|
})
|
||||||
|
|
||||||
res.json({ cart })
|
const data = await decorateLineItemsWithTotals(cart, req)
|
||||||
|
res.json({ cart: data })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { CartService } from "../../../../services"
|
import { CartService } from "../../../../services"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [post] /carts/{id}/payment-sessions/{provider_id}/refresh
|
* @oas [post] /carts/{id}/payment-sessions/{provider_id}/refresh
|
||||||
@@ -44,5 +45,6 @@ export default async (req, res) => {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
res.status(200).json({ cart })
|
const data = await decorateLineItemsWithTotals(cart, req)
|
||||||
|
res.status(200).json({ cart: data })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { IsString } from "class-validator"
|
|||||||
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
||||||
import { CartService } from "../../../../services"
|
import { CartService } from "../../../../services"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [post] /carts/{id}/payment-session
|
* @oas [post] /carts/{id}/payment-session
|
||||||
@@ -39,7 +40,8 @@ export default async (req, res) => {
|
|||||||
relations: defaultStoreCartRelations,
|
relations: defaultStoreCartRelations,
|
||||||
})
|
})
|
||||||
|
|
||||||
res.status(200).json({ cart })
|
const data = await decorateLineItemsWithTotals(cart, req)
|
||||||
|
res.status(200).json({ cart: data })
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StorePostCartsCartPaymentSessionReq {
|
export class StorePostCartsCartPaymentSessionReq {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { CartUpdateProps } from "../../../../types/cart"
|
|||||||
import { AddressPayload } from "../../../../types/common"
|
import { AddressPayload } from "../../../../types/common"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
import { IsType } from "../../../../utils/validators/is-type"
|
import { IsType } from "../../../../utils/validators/is-type"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [post] /store/carts/{id}
|
* @oas [post] /store/carts/{id}
|
||||||
@@ -118,8 +119,9 @@ export default async (req, res) => {
|
|||||||
select: defaultStoreCartFields,
|
select: defaultStoreCartFields,
|
||||||
relations: defaultStoreCartRelations,
|
relations: defaultStoreCartRelations,
|
||||||
})
|
})
|
||||||
|
const data = await decorateLineItemsWithTotals(cart, req)
|
||||||
|
|
||||||
res.json({ cart })
|
res.json({ cart: data })
|
||||||
}
|
}
|
||||||
|
|
||||||
class GiftCard {
|
class GiftCard {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { EntityManager } from "typeorm"
|
|||||||
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
||||||
import { CartService } from "../../../../services"
|
import { CartService } from "../../../../services"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [post] /carts/{id}/line-items/{line_id}
|
* @oas [post] /carts/{id}/line-items/{line_id}
|
||||||
@@ -78,8 +79,9 @@ export default async (req, res) => {
|
|||||||
select: defaultStoreCartFields,
|
select: defaultStoreCartFields,
|
||||||
relations: defaultStoreCartRelations,
|
relations: defaultStoreCartRelations,
|
||||||
})
|
})
|
||||||
|
const data = await decorateLineItemsWithTotals(cart, req)
|
||||||
|
|
||||||
res.status(200).json({ cart })
|
res.status(200).json({ cart: data })
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StorePostCartsCartLineItemsItemReq {
|
export class StorePostCartsCartLineItemsItemReq {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { IsObject } from "class-validator"
|
|||||||
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
import { defaultStoreCartFields, defaultStoreCartRelations } from "."
|
||||||
import { CartService } from "../../../../services"
|
import { CartService } from "../../../../services"
|
||||||
import { validator } from "../../../../utils/validator"
|
import { validator } from "../../../../utils/validator"
|
||||||
|
import { decorateLineItemsWithTotals } from "./decorate-line-items-with-totals"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @oas [post] /carts/{id}/payment-sessions/{provider_id}
|
* @oas [post] /carts/{id}/payment-sessions/{provider_id}
|
||||||
@@ -41,8 +42,9 @@ export default async (req, res) => {
|
|||||||
select: defaultStoreCartFields,
|
select: defaultStoreCartFields,
|
||||||
relations: defaultStoreCartRelations,
|
relations: defaultStoreCartRelations,
|
||||||
})
|
})
|
||||||
|
const data = await decorateLineItemsWithTotals(cart, req)
|
||||||
|
|
||||||
res.status(200).json({ cart })
|
res.status(200).json({ cart: data })
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StorePostCartsCartPaymentSessionUpdateReq {
|
export class StorePostCartsCartPaymentSessionUpdateReq {
|
||||||
|
|||||||
@@ -30,10 +30,7 @@ export class LineItem extends BaseEntity {
|
|||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
cart_id: string
|
cart_id: string
|
||||||
|
|
||||||
@ManyToOne(
|
@ManyToOne(() => Cart, (cart) => cart.items)
|
||||||
() => Cart,
|
|
||||||
(cart) => cart.items
|
|
||||||
)
|
|
||||||
@JoinColumn({ name: "cart_id" })
|
@JoinColumn({ name: "cart_id" })
|
||||||
cart: Cart
|
cart: Cart
|
||||||
|
|
||||||
@@ -41,10 +38,7 @@ export class LineItem extends BaseEntity {
|
|||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
order_id: string
|
order_id: string
|
||||||
|
|
||||||
@ManyToOne(
|
@ManyToOne(() => Order, (order) => order.items)
|
||||||
() => Order,
|
|
||||||
(order) => order.items
|
|
||||||
)
|
|
||||||
@JoinColumn({ name: "order_id" })
|
@JoinColumn({ name: "order_id" })
|
||||||
order: Order
|
order: Order
|
||||||
|
|
||||||
@@ -52,10 +46,7 @@ export class LineItem extends BaseEntity {
|
|||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
swap_id: string
|
swap_id: string
|
||||||
|
|
||||||
@ManyToOne(
|
@ManyToOne(() => Swap, (swap) => swap.additional_items)
|
||||||
() => Swap,
|
|
||||||
(swap) => swap.additional_items
|
|
||||||
)
|
|
||||||
@JoinColumn({ name: "swap_id" })
|
@JoinColumn({ name: "swap_id" })
|
||||||
swap: Swap
|
swap: Swap
|
||||||
|
|
||||||
@@ -63,27 +54,16 @@ export class LineItem extends BaseEntity {
|
|||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
claim_order_id: string
|
claim_order_id: string
|
||||||
|
|
||||||
@ManyToOne(
|
@ManyToOne(() => ClaimOrder, (co) => co.additional_items)
|
||||||
() => ClaimOrder,
|
|
||||||
(co) => co.additional_items
|
|
||||||
)
|
|
||||||
@JoinColumn({ name: "claim_order_id" })
|
@JoinColumn({ name: "claim_order_id" })
|
||||||
claim_order: ClaimOrder
|
claim_order: ClaimOrder
|
||||||
|
|
||||||
@OneToMany(
|
@OneToMany(() => LineItemTaxLine, (tl) => tl.item, { cascade: ["insert"] })
|
||||||
() => LineItemTaxLine,
|
|
||||||
(tl) => tl.item,
|
|
||||||
{ cascade: ["insert"] }
|
|
||||||
)
|
|
||||||
tax_lines: LineItemTaxLine[]
|
tax_lines: LineItemTaxLine[]
|
||||||
|
|
||||||
@OneToMany(
|
@OneToMany(() => LineItemAdjustment, (lia) => lia.item, {
|
||||||
() => LineItemAdjustment,
|
cascade: ["insert"],
|
||||||
(lia) => lia.item,
|
})
|
||||||
{
|
|
||||||
cascade: ["insert"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
adjustments: LineItemAdjustment[]
|
adjustments: LineItemAdjustment[]
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
@@ -136,7 +116,14 @@ export class LineItem extends BaseEntity {
|
|||||||
@DbAwareColumn({ type: "jsonb", nullable: true })
|
@DbAwareColumn({ type: "jsonb", nullable: true })
|
||||||
metadata: Record<string, unknown>
|
metadata: Record<string, unknown>
|
||||||
|
|
||||||
refundable: number | null
|
refundable?: number | null
|
||||||
|
subtotal?: number | null
|
||||||
|
tax_total?: number | null
|
||||||
|
total?: number | null
|
||||||
|
original_total?: number | null
|
||||||
|
original_tax_total?: number | null
|
||||||
|
discount_total?: number | null
|
||||||
|
gift_card_total?: number | null
|
||||||
|
|
||||||
@BeforeInsert()
|
@BeforeInsert()
|
||||||
private beforeInsert(): void {
|
private beforeInsert(): void {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import _ from "lodash"
|
import { isEmpty, isEqual } from "lodash"
|
||||||
import { MedusaError, Validator } from "medusa-core-utils"
|
import { MedusaError, Validator } from "medusa-core-utils"
|
||||||
import { DeepPartial, EntityManager, In } from "typeorm"
|
import { DeepPartial, EntityManager, In } from "typeorm"
|
||||||
import { TransactionBaseService } from "../interfaces"
|
import { TransactionBaseService } from "../interfaces"
|
||||||
@@ -546,7 +546,7 @@ class CartService extends TransactionBaseService<CartService> {
|
|||||||
if (lineItem.should_merge) {
|
if (lineItem.should_merge) {
|
||||||
currentItem = cart.items.find((item) => {
|
currentItem = cart.items.find((item) => {
|
||||||
if (item.should_merge && item.variant_id === lineItem.variant_id) {
|
if (item.should_merge && item.variant_id === lineItem.variant_id) {
|
||||||
return _.isEqual(item.metadata, lineItem.metadata)
|
return isEqual(item.metadata, lineItem.metadata)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
@@ -1786,7 +1786,7 @@ class CartService extends TransactionBaseService<CartService> {
|
|||||||
let updated = { ...shippingAddress }
|
let updated = { ...shippingAddress }
|
||||||
|
|
||||||
// If the country code of a shipping address is set we need to clear it
|
// If the country code of a shipping address is set we need to clear it
|
||||||
if (!_.isEmpty(shippingAddress) && shippingAddress.country_code) {
|
if (!isEmpty(shippingAddress) && shippingAddress.country_code) {
|
||||||
updated = {
|
updated = {
|
||||||
...updated,
|
...updated,
|
||||||
country_code: null,
|
country_code: null,
|
||||||
@@ -1938,6 +1938,7 @@ class CartService extends TransactionBaseService<CartService> {
|
|||||||
"region.tax_rates",
|
"region.tax_rates",
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
const calculationContext = this.totalsService_
|
const calculationContext = this.totalsService_
|
||||||
.withTransaction(transactionManager)
|
.withTransaction(transactionManager)
|
||||||
.getCalculationContext(cart)
|
.getCalculationContext(cart)
|
||||||
|
|||||||
@@ -689,7 +689,6 @@ class TotalsService extends BaseService {
|
|||||||
const calculationContext = this.getCalculationContext(cartOrOrder, {
|
const calculationContext = this.getCalculationContext(cartOrOrder, {
|
||||||
exclude_shipping: true,
|
exclude_shipping: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const lineItemAllocation =
|
const lineItemAllocation =
|
||||||
calculationContext.allocation_map[lineItem.id] || {}
|
calculationContext.allocation_map[lineItem.id] || {}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user