From ed5b1592a42e91f392110f8fa15ce4ae5b813afd Mon Sep 17 00:00:00 2001 From: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> Date: Sat, 27 Feb 2021 10:24:46 +0100 Subject: [PATCH 1/3] hotfix(medusa): wrap update-product in transaction (#182) --- .../medusa/src/api/routes/admin/products/update-product.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/medusa/src/api/routes/admin/products/update-product.js b/packages/medusa/src/api/routes/admin/products/update-product.js index a90d759868..ecb614cc12 100644 --- a/packages/medusa/src/api/routes/admin/products/update-product.js +++ b/packages/medusa/src/api/routes/admin/products/update-product.js @@ -90,8 +90,11 @@ export default async (req, res) => { try { const productService = req.scope.resolve("productService") + const entityManager = req.scope.resolve("manager") - await productService.update(id, value) + await entityManager.transaction(async manager => { + await productService.withTransaction(manager).update(id, value) + }) const product = await productService.retrieve(id, { select: defaultFields, From 7f5ee6bdcc1343f40fced74f43ca58e8a553d845 Mon Sep 17 00:00:00 2001 From: Sebastian Rindom Date: Sat, 27 Feb 2021 11:14:39 +0100 Subject: [PATCH 2/3] hotfix: round totals (#188) * fix: round totals * fix: test --- packages/medusa/src/services/__tests__/totals.js | 2 +- packages/medusa/src/services/totals.js | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/medusa/src/services/__tests__/totals.js b/packages/medusa/src/services/__tests__/totals.js index 9b5cb1060c..b07b2c887f 100644 --- a/packages/medusa/src/services/__tests__/totals.js +++ b/packages/medusa/src/services/__tests__/totals.js @@ -377,7 +377,7 @@ describe("TotalsService", () => { }, ]) - expect(res).toEqual(1243.75) + expect(res).toEqual(1244) }) it("calculates refund with item fixed discount", async () => { diff --git a/packages/medusa/src/services/totals.js b/packages/medusa/src/services/totals.js index c426e58d89..d9d769e20d 100644 --- a/packages/medusa/src/services/totals.js +++ b/packages/medusa/src/services/totals.js @@ -328,10 +328,7 @@ class TotalsService extends BaseService { } rounded(value) { - const decimalPlaces = 4 - return Number( - Math.round(parseFloat(value + "e" + decimalPlaces)) + "e-" + decimalPlaces - ) + return Math.round(value) } } From 92e70cc35b7f406393e23ebd3655df65cced5077 Mon Sep 17 00:00:00 2001 From: olivermrbl Date: Sun, 28 Feb 2021 09:53:41 +0100 Subject: [PATCH 3/3] hotfix(medusa): Optimize cart retrieval --- packages/medusa/src/repositories/cart.ts | 52 ++++++++++++++++++- .../medusa/src/services/__tests__/cart.js | 50 ++++++++++-------- packages/medusa/src/services/cart.js | 4 +- 3 files changed, 81 insertions(+), 25 deletions(-) diff --git a/packages/medusa/src/repositories/cart.ts b/packages/medusa/src/repositories/cart.ts index 6955ad4895..89adbf87cf 100644 --- a/packages/medusa/src/repositories/cart.ts +++ b/packages/medusa/src/repositories/cart.ts @@ -1,5 +1,53 @@ -import { EntityRepository, Repository } from "typeorm" +import { EntityRepository, FindManyOptions, Repository } from "typeorm" +import { flatten, groupBy, map, merge } from "lodash" import { Cart } from "../models/cart" @EntityRepository(Cart) -export class CartRepository extends Repository {} +export class CartRepository extends Repository { + public async findWithRelations( + relations: Array = [], + optionsWithoutRelations: Omit, "relations"> = {} + ): Promise { + const entities = await this.find(optionsWithoutRelations) + const entitiesIds = entities.map(({ id }) => id) + + const groupedRelations = {} + for (const rel of relations) { + const [topLevel] = rel.split(".") + if (groupedRelations[topLevel]) { + groupedRelations[topLevel].push(rel) + } else { + groupedRelations[topLevel] = [rel] + } + } + + const entitiesIdsWithRelations = await Promise.all( + Object.entries(groupedRelations).map(([_, rels]) => { + return this.findByIds(entitiesIds, { + select: ["id"], + relations: rels as string[], + }) + }) + ).then(flatten) + const entitiesAndRelations = entitiesIdsWithRelations.concat(entities) + + const entitiesAndRelationsById = groupBy(entitiesAndRelations, "id") + return map(entitiesAndRelationsById, entityAndRelations => + merge({}, ...entityAndRelations) + ) + } + + public async findOneWithRelations( + relations: Array = [], + optionsWithoutRelations: Omit, "relations"> = {} + ): Promise { + // Limit 1 + optionsWithoutRelations.take = 1 + + const result = await this.findWithRelations( + relations, + optionsWithoutRelations + ) + return result[0] + } +} diff --git a/packages/medusa/src/services/__tests__/cart.js b/packages/medusa/src/services/__tests__/cart.js index b268ff4740..ded354f5ee 100644 --- a/packages/medusa/src/services/__tests__/cart.js +++ b/packages/medusa/src/services/__tests__/cart.js @@ -34,7 +34,8 @@ describe("CartService", () => { describe("retrieve", () => { let result const cartRepository = MockRepository({ - findOne: () => Promise.resolve({ id: IdMap.getId("emptyCart") }), + findOneWithRelations: () => + Promise.resolve({ id: IdMap.getId("emptyCart") }), }) beforeAll(async () => { jest.clearAllMocks() @@ -47,10 +48,13 @@ describe("CartService", () => { }) it("calls cart model functions", () => { - expect(cartRepository.findOne).toHaveBeenCalledTimes(1) - expect(cartRepository.findOne).toHaveBeenCalledWith({ - where: { id: IdMap.getId("emptyCart") }, - }) + expect(cartRepository.findOneWithRelations).toHaveBeenCalledTimes(1) + expect(cartRepository.findOneWithRelations).toHaveBeenCalledWith( + undefined, + { + where: { id: IdMap.getId("emptyCart") }, + } + ) }) }) @@ -314,7 +318,7 @@ describe("CartService", () => { } const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { if (q.where.id === IdMap.getId("cartWithLine")) { return Promise.resolve({ items: [ @@ -472,7 +476,7 @@ describe("CartService", () => { }, } const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { if (q.where.id === IdMap.getId("withShipping")) { return Promise.resolve({ shipping_methods: [ @@ -574,7 +578,7 @@ describe("CartService", () => { describe("update", () => { const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { if (q.where.id === "withpays") { return Promise.resolve({ payment_sessions: [ @@ -602,8 +606,8 @@ describe("CartService", () => { cartService.setPaymentSessions = jest.fn() await cartService.update("withpays", {}) - expect(cartRepository.findOne).toHaveBeenCalledWith({ - relations: [ + expect(cartRepository.findOneWithRelations).toHaveBeenCalledWith( + [ "items", "shipping_methods", "shipping_address", @@ -617,8 +621,10 @@ describe("CartService", () => { "discounts.rule", "discounts.regions", ], - where: { id: "withpays" }, - }) + { + where: { id: "withpays" }, + } + ) }) }) @@ -636,7 +642,7 @@ describe("CartService", () => { } const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { if (q.where.id === IdMap.getId("cannot")) { return Promise.resolve({ items: [ @@ -719,7 +725,7 @@ describe("CartService", () => { }, } const cartRepository = MockRepository({ - findOne: () => Promise.resolve({}), + findOneWithRelations: () => Promise.resolve({}), }) const cartService = new CartService({ manager: MockManager, @@ -792,7 +798,7 @@ describe("CartService", () => { describe("updateBillingAddress", () => { const cartRepository = MockRepository({ - findOne: () => + findOneWithRelations: () => Promise.resolve({ region: { countries: [{ iso_2: "us" }] }, }), @@ -854,7 +860,7 @@ describe("CartService", () => { describe("updateShippingAddress", () => { const cartRepository = MockRepository({ - findOne: () => + findOneWithRelations: () => Promise.resolve({ region: { countries: [{ iso_2: "us" }] }, }), @@ -957,7 +963,7 @@ describe("CartService", () => { ), } const cartRepository = MockRepository({ - findOne: () => + findOneWithRelations: () => Promise.resolve({ items: [ { @@ -1056,7 +1062,7 @@ describe("CartService", () => { describe("setPaymentSession", () => { const cartRepository = MockRepository({ - findOne: () => { + findOneWithRelations: () => { return Promise.resolve({ region: { payment_providers: [ @@ -1165,7 +1171,7 @@ describe("CartService", () => { } const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { if (q.where.id === IdMap.getId("cart-to-filter")) { return Promise.resolve(cart3) } @@ -1287,7 +1293,7 @@ describe("CartService", () => { }) const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { switch (q.where.id) { case IdMap.getId("lines"): return Promise.resolve(cart3) @@ -1420,7 +1426,7 @@ describe("CartService", () => { describe("applyDiscount", () => { const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { if (q.where.id === IdMap.getId("with-d")) { return Promise.resolve({ id: IdMap.getId("cart"), @@ -1599,7 +1605,7 @@ describe("CartService", () => { describe("removeDiscount", () => { const cartRepository = MockRepository({ - findOne: q => { + findOneWithRelations: (rels, q) => { return Promise.resolve({ id: IdMap.getId("cart"), discounts: [ diff --git a/packages/medusa/src/services/cart.js b/packages/medusa/src/services/cart.js index cd9bf09ced..6d1a2f1b1a 100644 --- a/packages/medusa/src/services/cart.js +++ b/packages/medusa/src/services/cart.js @@ -269,7 +269,9 @@ class CartService extends BaseService { query.select = select } - const raw = await cartRepo.findOne(query) + const rels = query.relations + delete query.relations + const raw = await cartRepo.findOneWithRelations(rels, query) if (!raw) { throw new MedusaError(