diff --git a/integration-tests/api/__tests__/store/cart.js b/integration-tests/api/__tests__/store/cart.js index 4edc9a8baa..3503bf5d7a 100644 --- a/integration-tests/api/__tests__/store/cart.js +++ b/integration-tests/api/__tests__/store/cart.js @@ -486,7 +486,8 @@ describe("/store/carts", () => { regions: ["test-region"], } - let discountCart, discount + let discountCart + let discount beforeEach(async () => { try { discount = await simpleDiscountFactory( @@ -718,15 +719,17 @@ describe("/store/carts", () => { ) .catch((err) => console.log(err)) - expect(response.data.cart.items).toEqual([ - expect.objectContaining({ - cart_id: "test-cart-3", - unit_price: 8000, - variant_id: "test-variant-sale-cg", - quantity: 3, - adjustments: [], - }), - ]) + expect(response.data.cart.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + cart_id: "test-cart-3", + unit_price: 8000, + variant_id: "test-variant-sale-cg", + quantity: 3, + adjustments: [], + }), + ]) + ) }) it("updates line item of a cart containing a total fixed discount", async () => { @@ -1363,7 +1366,14 @@ describe("/store/carts", () => { .catch((error) => console.log(error)) expect(response.status).toEqual(200) - expect(response.data.cart.items[0].unit_price).toEqual(500) + expect(response.data.cart.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + variant_id: "test-variant-sale-cg", + unit_price: 500, + }), + ]) + ) }) it("updates prices when cart region id is updated", async () => { @@ -1479,11 +1489,38 @@ describe("/store/carts", () => { const getRes = await api.post(`/store/carts/test-cart-2/complete-cart`) expect(getRes.status).toEqual(200) + expect(getRes.data.type).toEqual("order") const variantRes = await api.get("/store/variants/test-variant") expect(variantRes.data.variant.inventory_quantity).toEqual(0) }) + it("calculates correct payment totals on cart completion taking into account line item adjustments", async () => { + const api = useApi() + + await api.post("/store/carts/test-cart-3", { + discounts: [{ code: "CREATED" }], + }) + + const createdOrder = await api.post( + `/store/carts/test-cart-3/complete-cart` + ) + + expect(createdOrder.data.type).toEqual("order") + expect(createdOrder.data.data.discount_total).toEqual(10000) + expect(createdOrder.data.data.subtotal).toEqual(16000) + expect(createdOrder.data.data.total).toEqual(6000) + expect(createdOrder.data.data.payments).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + amount: 6000, + }), + ]) + ) + + expect(createdOrder.status).toEqual(200) + }) + it("returns early, if cart is already completed", async () => { const manager = dbConnection.manager const api = useApi() @@ -1739,7 +1776,9 @@ describe("/store/carts", () => { .catch((err) => console.log(err)) // Ensure that the discount is only applied to the standard item - const itemId = cartWithGiftcard.data.cart.items.find(item => !item.is_giftcard).id + const itemId = cartWithGiftcard.data.cart.items.find( + (item) => !item.is_giftcard + ).id expect(cartWithGiftcard.data.cart.items).toEqual( expect.arrayContaining([ expect.objectContaining({ diff --git a/integration-tests/api/helpers/cart-seeder.js b/integration-tests/api/helpers/cart-seeder.js index b3dee44d51..4514956f2c 100644 --- a/integration-tests/api/helpers/cart-seeder.js +++ b/integration-tests/api/helpers/cart-seeder.js @@ -50,6 +50,7 @@ module.exports = async (connection, data = {}) => { const r = manager.create(Region, { id: "test-region", name: "Test Region", + payment_providers: [{ id: "test-pay" }], currency_code: "usd", tax_rate: 0, }) @@ -819,6 +820,23 @@ module.exports = async (connection, data = {}) => { completed_at: null, items: [], }) + + await manager.save(cart3) + + const ps = manager.create(PaymentSession, { + id: "test-cart-session", + cart_id: "test-cart-3", + provider_id: "test-pay", + is_selected: true, + data: {}, + status: "authorized", + }) + + await manager.save(ps) + + cart3.payment_sessions = [ps] + cart3.payment_session = ps + await manager.save(cart3) await manager.insert(ShippingMethod, { @@ -842,7 +860,7 @@ module.exports = async (connection, data = {}) => { await manager.save(li2) const cart4 = manager.create(Cart, { - id: "test-cart-3", + id: "test-cart-4", email: "some-customer@email.com", shipping_address: { id: "test-shipping-address", diff --git a/packages/medusa/src/api/routes/store/carts/update-cart.ts b/packages/medusa/src/api/routes/store/carts/update-cart.ts index 6fc264f1a8..1874c6b398 100644 --- a/packages/medusa/src/api/routes/store/carts/update-cart.ts +++ b/packages/medusa/src/api/routes/store/carts/update-cart.ts @@ -8,10 +8,10 @@ import { } from "class-validator" import { defaultStoreCartFields, defaultStoreCartRelations } from "." import { CartService } from "../../../../services" -import { AddressPayload } from "../../../../types/common" import { CartUpdateProps } from "../../../../types/cart" -import { IsType } from "../../../../utils/validators/is-type" +import { AddressPayload } from "../../../../types/common" import { validator } from "../../../../utils/validator" +import { IsType } from "../../../../utils/validators/is-type" /** * @oas [post] /store/carts/{id} @@ -90,7 +90,7 @@ export default async (req, res) => { // Update the cart const { shipping_address, billing_address, ...rest } = validated - const cartDataToUpdate: CartUpdateProps = { ...rest }; + const cartDataToUpdate: CartUpdateProps = { ...rest } if (typeof shipping_address === "string") { cartDataToUpdate.shipping_address_id = shipping_address } else { diff --git a/packages/medusa/src/services/__tests__/line-item-adjustment.js b/packages/medusa/src/services/__tests__/line-item-adjustment.js index a57dd6b7b1..279643c28d 100644 --- a/packages/medusa/src/services/__tests__/line-item-adjustment.js +++ b/packages/medusa/src/services/__tests__/line-item-adjustment.js @@ -1,8 +1,8 @@ -import LineItemAdjustmentService from "../line-item-adjustment" -import { MockManager, MockRepository, IdMap } from "medusa-test-utils" -import { EventBusServiceMock } from "../__mocks__/event-bus" -import { DiscountServiceMock } from "../__mocks__/discount" +import { MockManager, MockRepository } from "medusa-test-utils" import { In } from "typeorm" +import LineItemAdjustmentService from "../line-item-adjustment" +import { DiscountServiceMock } from "../__mocks__/discount" +import { EventBusServiceMock } from "../__mocks__/event-bus" describe("LineItemAdjustmentService", () => { describe("list", () => { @@ -101,7 +101,7 @@ describe("LineItemAdjustmentService", () => { } const lineItemAdjustmentRepo = MockRepository({ - create: (f) => Promise.resolve(lineItemAdjustment), + create: (f) => lineItemAdjustment, save: (f) => Promise.resolve(lineItemAdjustment), }) @@ -270,11 +270,11 @@ describe("LineItemAdjustmentService", () => { it("calls createAdjustmentForLineItem once when given a line item", () => { const cart = { - id: "cart1", - discounts: ["disc-1"], - items: [{ id: "li-1" }], - }, - lineItem = { id: "li-1" } + id: "cart1", + discounts: ["disc-1"], + items: [{ id: "li-1" }], + } + const lineItem = { id: "li-1" } lineItemAdjustmentService.createAdjustments(cart, lineItem) expect( diff --git a/packages/medusa/src/services/cart.ts b/packages/medusa/src/services/cart.ts index e05e2b6310..55b9fd9261 100644 --- a/packages/medusa/src/services/cart.ts +++ b/packages/medusa/src/services/cart.ts @@ -3,6 +3,7 @@ import { MedusaError, Validator } from "medusa-core-utils" import { DeepPartial, EntityManager, In } from "typeorm" import { TransactionBaseService } from "../interfaces" import { IPriceSelectionStrategy } from "../interfaces/price-selection-strategy" +import { DiscountRuleType } from "../models" import { Address } from "../models/address" import { Cart } from "../models/cart" import { CustomShippingOption } from "../models/custom-shipping-option" @@ -1221,7 +1222,7 @@ class CartService extends TransactionBaseService { const freshCart = await this.retrieve(cart.id, { select: ["total"], - relations: ["payment_sessions"], + relations: ["payment_sessions", "items", "items.adjustments"], }) if (session.status === "authorized") { diff --git a/packages/medusa/src/services/line-item-adjustment.ts b/packages/medusa/src/services/line-item-adjustment.ts index 8ce03c7229..4331a1835b 100644 --- a/packages/medusa/src/services/line-item-adjustment.ts +++ b/packages/medusa/src/services/line-item-adjustment.ts @@ -1,14 +1,14 @@ -import { EntityManager } from "typeorm" -import { BaseService } from "medusa-interfaces" import { MedusaError } from "medusa-core-utils" +import { BaseService } from "medusa-interfaces" +import { EntityManager } from "typeorm" +import { Cart } from "../models/cart" +import { LineItem } from "../models/line-item" +import { LineItemAdjustment } from "../models/line-item-adjustment" +import { ProductVariant } from "../models/product-variant" import { LineItemAdjustmentRepository } from "../repositories/line-item-adjustment" import { FindConfig } from "../types/common" -import { LineItemAdjustment } from "../models/line-item-adjustment" import { FilterableLineItemAdjustmentProps } from "../types/line-item-adjustment" -import { LineItem } from "../models/line-item" -import { Cart } from "../models/cart" import DiscountService from "./discount" -import { ProductVariant } from "../models/product-variant" type LineItemAdjustmentServiceProps = { manager: EntityManager @@ -96,7 +96,7 @@ class LineItemAdjustmentService extends BaseService { const lineItemAdjustmentRepo: LineItemAdjustmentRepository = manager.getCustomRepository(this.lineItemAdjustmentRepo_) - const lineItemAdjustment = await lineItemAdjustmentRepo.create(data) + const lineItemAdjustment = lineItemAdjustmentRepo.create(data) return await lineItemAdjustmentRepo.save(lineItemAdjustment) })