fix(medusa): Reduce joins in cart retrieval (#3909)

* fix(medusa): Remove discounts.regions relation from cart retrieval

* Create violet-poets-rule.md

* fix service test

* update snapshot

---------

Co-authored-by: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com>
This commit is contained in:
Oliver Windall Juhl
2023-04-25 12:51:33 +02:00
committed by GitHub
co-authored by Philip Korsholm
parent 935abeae68
commit 3b3236cc01
8 changed files with 69 additions and 77 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/medusa": patch
---
fix(medusa): Remove discounts.regions relation from cart retrieval
@@ -547,17 +547,10 @@ Object {
"created_at": Any<Date>, "created_at": Any<Date>,
"currency_code": "usd", "currency_code": "usd",
"deleted_at": null, "deleted_at": null,
"fulfillment_providers": Array [],
"gift_cards_taxable": true, "gift_cards_taxable": true,
"id": Any<String>, "id": Any<String>,
"metadata": null, "metadata": null,
"name": "Test region", "name": "Test region",
"payment_providers": Array [
PaymentProvider {
"id": "test-pay",
"is_installed": true,
},
],
"tax_code": null, "tax_code": null,
"tax_provider_id": null, "tax_provider_id": null,
"tax_rate": 12.5, "tax_rate": 12.5,
@@ -903,17 +896,10 @@ Object {
"created_at": Any<Date>, "created_at": Any<Date>,
"currency_code": "usd", "currency_code": "usd",
"deleted_at": null, "deleted_at": null,
"fulfillment_providers": Array [],
"gift_cards_taxable": true, "gift_cards_taxable": true,
"id": "test-region", "id": "test-region",
"metadata": null, "metadata": null,
"name": "Test region", "name": "Test region",
"payment_providers": Array [
PaymentProvider {
"id": "test-pay",
"is_installed": true,
},
],
"tax_code": null, "tax_code": null,
"tax_provider_id": null, "tax_provider_id": null,
"tax_rate": 12.5, "tax_rate": 12.5,
@@ -1161,17 +1147,10 @@ Object {
"created_at": Any<Date>, "created_at": Any<Date>,
"currency_code": "usd", "currency_code": "usd",
"deleted_at": null, "deleted_at": null,
"fulfillment_providers": Array [],
"gift_cards_taxable": true, "gift_cards_taxable": true,
"id": "test-region", "id": "test-region",
"metadata": null, "metadata": null,
"name": "Test region", "name": "Test region",
"payment_providers": Array [
PaymentProvider {
"id": "test-pay",
"is_installed": true,
},
],
"tax_code": null, "tax_code": null,
"tax_provider_id": null, "tax_provider_id": null,
"tax_rate": 12.5, "tax_rate": 12.5,
@@ -1417,17 +1396,10 @@ Object {
"created_at": Any<Date>, "created_at": Any<Date>,
"currency_code": "usd", "currency_code": "usd",
"deleted_at": null, "deleted_at": null,
"fulfillment_providers": Array [],
"gift_cards_taxable": true, "gift_cards_taxable": true,
"id": "test-region", "id": "test-region",
"metadata": null, "metadata": null,
"name": "Test region", "name": "Test region",
"payment_providers": Array [
PaymentProvider {
"id": "test-pay",
"is_installed": true,
},
],
"tax_code": null, "tax_code": null,
"tax_provider_id": null, "tax_provider_id": null,
"tax_rate": 12.5, "tax_rate": 12.5,
@@ -1750,17 +1722,10 @@ Object {
"created_at": Any<Date>, "created_at": Any<Date>,
"currency_code": "usd", "currency_code": "usd",
"deleted_at": null, "deleted_at": null,
"fulfillment_providers": Array [],
"gift_cards_taxable": true, "gift_cards_taxable": true,
"id": Any<String>, "id": Any<String>,
"metadata": null, "metadata": null,
"name": "Test region", "name": "Test region",
"payment_providers": Array [
PaymentProvider {
"id": "test-pay",
"is_installed": true,
},
],
"tax_code": null, "tax_code": null,
"tax_provider_id": null, "tax_provider_id": null,
"tax_rate": 12.5, "tax_rate": 12.5,
@@ -2205,17 +2170,10 @@ Object {
"created_at": Any<Date>, "created_at": Any<Date>,
"currency_code": "usd", "currency_code": "usd",
"deleted_at": null, "deleted_at": null,
"fulfillment_providers": Array [],
"gift_cards_taxable": true, "gift_cards_taxable": true,
"id": Any<String>, "id": Any<String>,
"metadata": null, "metadata": null,
"name": "Test region", "name": "Test region",
"payment_providers": Array [
PaymentProvider {
"id": "test-pay",
"is_installed": true,
},
],
"tax_code": null, "tax_code": null,
"tax_provider_id": null, "tax_provider_id": null,
"tax_rate": 12.5, "tax_rate": 12.5,
+5 -7
View File
@@ -10,17 +10,17 @@ import {
OneToMany, OneToMany,
} from "typeorm" } from "typeorm"
import { SoftDeletableEntity } from "../interfaces/models/soft-deletable-entity"
import TaxInclusivePricingFeatureFlag from "../loaders/feature-flags/tax-inclusive-pricing"
import { DbAwareColumn } from "../utils/db-aware-column"
import { FeatureFlagColumn } from "../utils/feature-flag-decorators"
import { generateEntityId } from "../utils/generate-entity-id"
import { Country } from "./country" import { Country } from "./country"
import { Currency } from "./currency" import { Currency } from "./currency"
import { DbAwareColumn } from "../utils/db-aware-column"
import { FulfillmentProvider } from "./fulfillment-provider" import { FulfillmentProvider } from "./fulfillment-provider"
import { PaymentProvider } from "./payment-provider" import { PaymentProvider } from "./payment-provider"
import { SoftDeletableEntity } from "../interfaces/models/soft-deletable-entity"
import { TaxProvider } from "./tax-provider" import { TaxProvider } from "./tax-provider"
import { TaxRate } from "./tax-rate" import { TaxRate } from "./tax-rate"
import { generateEntityId } from "../utils/generate-entity-id"
import { FeatureFlagColumn } from "../utils/feature-flag-decorators"
import TaxInclusivePricingFeatureFlag from "../loaders/feature-flags/tax-inclusive-pricing"
@Entity() @Entity()
export class Region extends SoftDeletableEntity { export class Region extends SoftDeletableEntity {
@@ -61,7 +61,6 @@ export class Region extends SoftDeletableEntity {
tax_provider: TaxProvider tax_provider: TaxProvider
@ManyToMany(() => PaymentProvider, { @ManyToMany(() => PaymentProvider, {
eager: true,
cascade: ["insert", "update"], cascade: ["insert", "update"],
}) })
@JoinTable({ @JoinTable({
@@ -78,7 +77,6 @@ export class Region extends SoftDeletableEntity {
payment_providers: PaymentProvider[] payment_providers: PaymentProvider[]
@ManyToMany(() => FulfillmentProvider, { @ManyToMany(() => FulfillmentProvider, {
eager: true,
cascade: ["insert", "update"], cascade: ["insert", "update"],
}) })
@JoinTable({ @JoinTable({
+1 -1
View File
@@ -1,5 +1,5 @@
import { Discount } from "../models"
import { dataSource } from "../loaders/database" import { dataSource } from "../loaders/database"
import { Discount } from "../models"
export const DiscountRepository = dataSource.getRepository(Discount) export const DiscountRepository = dataSource.getRepository(Discount)
export default DiscountRepository export default DiscountRepository
+38 -20
View File
@@ -65,8 +65,7 @@ describe("CartService", () => {
describe("retrieve", () => { describe("retrieve", () => {
let result let result
const cartRepository = MockRepository({ const cartRepository = MockRepository({
findOne: () => findOne: () => Promise.resolve({ id: IdMap.getId("emptyCart") }),
Promise.resolve({ id: IdMap.getId("emptyCart") }),
}) })
beforeAll(async () => { beforeAll(async () => {
jest.clearAllMocks() jest.clearAllMocks()
@@ -83,13 +82,11 @@ describe("CartService", () => {
it("calls cart model functions", () => { it("calls cart model functions", () => {
expect(cartRepository.findOne).toHaveBeenCalledTimes(1) expect(cartRepository.findOne).toHaveBeenCalledTimes(1)
expect(cartRepository.findOne).toHaveBeenCalledWith( expect(cartRepository.findOne).toHaveBeenCalledWith({
{ where: { id: IdMap.getId("emptyCart") },
where: { id: IdMap.getId("emptyCart") }, select: undefined,
select: undefined, relations: undefined,
relations: undefined, })
}
)
}) })
}) })
@@ -852,25 +849,24 @@ describe("CartService", () => {
billing_address: true, billing_address: true,
customer: true, customer: true,
discounts: { discounts: {
regions: true, rule: true,
rule: true
}, },
gift_cards: true, gift_cards: true,
items: { items: {
variant: { variant: {
product: true product: true,
} },
}, },
payment_sessions: true, payment_sessions: true,
region: { countries: true }, region: { countries: true },
shipping_address: true, shipping_address: true,
shipping_methods: true shipping_methods: true,
}, },
select: undefined, select: undefined,
where: { where: {
id: "withpays" id: "withpays",
} },
}), })
) )
}) })
}) })
@@ -1271,6 +1267,25 @@ describe("CartService", () => {
return this return this
}, },
} }
const discountService = {
list: jest.fn().mockReturnValue(
Promise.resolve([
{
id: IdMap.getId("stays"),
regions: [{ id: IdMap.getId("region-us") }],
},
{
id: IdMap.getId("removes"),
regions: [],
},
])
),
withTransaction: function () {
return this
},
}
const cartRepository = MockRepository({ const cartRepository = MockRepository({
findOne: () => findOne: () =>
Promise.resolve({ Promise.resolve({
@@ -1325,6 +1340,7 @@ describe("CartService", () => {
manager: MockManager, manager: MockManager,
paymentProviderService, paymentProviderService,
addressRepository, addressRepository,
discountService,
totalsService, totalsService,
cartRepository, cartRepository,
newTotalsService: newTotalsServiceMock, newTotalsService: newTotalsServiceMock,
@@ -1377,9 +1393,11 @@ describe("CartService", () => {
shipping_address: { shipping_address: {
country_code: "us", country_code: "us",
}, },
items: [{ items: [
id: IdMap.getId("testitem") {
}], id: IdMap.getId("testitem"),
},
],
payment_session: null, payment_session: null,
payment_sessions: [], payment_sessions: [],
gift_cards: [], gift_cards: [],
+14 -6
View File
@@ -1,9 +1,9 @@
import { isEmpty, isEqual } from "lodash" import { isEmpty, isEqual } from "lodash"
import { isDefined, MedusaError } from "medusa-core-utils" import { MedusaError, isDefined } from "medusa-core-utils"
import { DeepPartial, EntityManager, In, IsNull, Not } from "typeorm" import { DeepPartial, EntityManager, In, IsNull, Not } from "typeorm"
import { import {
CustomerService,
CustomShippingOptionService, CustomShippingOptionService,
CustomerService,
DiscountService, DiscountService,
EventBusService, EventBusService,
GiftCardService, GiftCardService,
@@ -26,8 +26,8 @@ import SalesChannelFeatureFlag from "../loaders/feature-flags/sales-channels"
import { import {
Address, Address,
Cart, Cart,
Customer,
CustomShippingOption, CustomShippingOption,
Customer,
Discount, Discount,
DiscountRule, DiscountRule,
DiscountRuleType, DiscountRuleType,
@@ -46,9 +46,9 @@ import {
CartCreateProps, CartCreateProps,
CartUpdateProps, CartUpdateProps,
FilterableCartProps, FilterableCartProps,
isCart,
LineItemUpdate, LineItemUpdate,
LineItemValidateData, LineItemValidateData,
isCart,
} from "../types/cart" } from "../types/cart"
import { import {
AddressPayload, AddressPayload,
@@ -1064,7 +1064,6 @@ class CartService extends TransactionBaseService {
"region.countries", "region.countries",
"discounts", "discounts",
"discounts.rule", "discounts.rule",
"discounts.regions",
] ]
if ( if (
@@ -2382,7 +2381,16 @@ class CartService extends TransactionBaseService {
} }
if (cart.discounts && cart.discounts.length) { if (cart.discounts && cart.discounts.length) {
cart.discounts = cart.discounts.filter((discount) => { const discounts = await this.discountService_
.withTransaction(this.activeManager_)
.list(
{
id: [...cart.discounts.map(({ id }) => id)],
},
{ relations: ["rule", "regions"] }
)
cart.discounts = discounts.filter((discount) => {
return discount.regions.find(({ id }) => id === regionId) return discount.regions.find(({ id }) => id === regionId)
}) })
} }
+1 -1
View File
@@ -1,6 +1,6 @@
import { parse, toSeconds } from "iso8601-duration" import { parse, toSeconds } from "iso8601-duration"
import { isEmpty, omit } from "lodash" import { isEmpty, omit } from "lodash"
import { isDefined, MedusaError } from "medusa-core-utils" import { MedusaError, isDefined } from "medusa-core-utils"
import { import {
DeepPartial, DeepPartial,
EntityManager, EntityManager,
+5
View File
@@ -16,6 +16,7 @@ import {
Region, Region,
} from "../models" } from "../models"
import { optionalBooleanMapper } from "../utils/validators/is-boolean" import { optionalBooleanMapper } from "../utils/validators/is-boolean"
import { IsType } from "../utils/validators/is-type"
import { ExactlyOne } from "./validators/exactly-one" import { ExactlyOne } from "./validators/exactly-one"
export type QuerySelector = { export type QuerySelector = {
@@ -27,6 +28,10 @@ export class FilterableDiscountProps {
@IsOptional() @IsOptional()
q?: string q?: string
@IsOptional()
@IsType([String, [String]])
id?: string | string[]
@IsBoolean() @IsBoolean()
@IsOptional() @IsOptional()
@Transform(({ value }) => optionalBooleanMapper.get(value)) @Transform(({ value }) => optionalBooleanMapper.get(value))