feat(medusa,orchestration): Decouple Product in Cart domain (#4945)

This commit is contained in:
Carlos R. L. Rodrigues authored and GitHub committed 2023-09-08 17:24:46 +02:00
1 parent 1958809fa9
commit 4b0e3fb2a7
22 files changed
+379 -141

No files matched your search

@@ -556,6 +556,7 @@ describe("/store/carts", () => {
{ {
id: "test-li", id: "test-li",
variant_id: "test-variant", variant_id: "test-variant",
product_id: "test-product",
quantity: 1, quantity: 1,
unit_price: 100, unit_price: 100,
adjustments: [ adjustments: [
@@ -644,6 +645,7 @@ describe("/store/carts", () => {
id: "line-item-2", id: "line-item-2",
cart_id: discountCart.id, cart_id: discountCart.id,
variant_id: "test-variant-quantity", variant_id: "test-variant-quantity",
product_id: "test-product",
unit_price: 950, unit_price: 950,
quantity: 1, quantity: 1,
adjustments: [ adjustments: [
@@ -713,6 +715,7 @@ describe("/store/carts", () => {
id: "line-item-2", id: "line-item-2",
cart_id: discountCart.id, cart_id: discountCart.id,
variant_id: "test-variant-quantity", variant_id: "test-variant-quantity",
product_id: "test-product",
unit_price: 1000, unit_price: 1000,
quantity: 1, quantity: 1,
adjustments: [ adjustments: [
@@ -804,6 +807,7 @@ describe("/store/carts", () => {
unit_price: 1000, unit_price: 1000,
quantity: 1, quantity: 1,
variant_id: "test-variant-quantity", variant_id: "test-variant-quantity",
product_id: "test-product",
cart_id: "test-cart-w-total-fixed-discount", cart_id: "test-cart-w-total-fixed-discount",
}) })
@@ -847,6 +851,7 @@ describe("/store/carts", () => {
unit_price: 1000, unit_price: 1000,
quantity: 1, quantity: 1,
variant_id: "test-variant-quantity", variant_id: "test-variant-quantity",
product_id: "test-product",
cart_id: "test-cart-w-total-percentage-discount", cart_id: "test-cart-w-total-percentage-discount",
}) })
@@ -890,6 +895,7 @@ describe("/store/carts", () => {
unit_price: 1000, unit_price: 1000,
quantity: 1, quantity: 1,
variant_id: "test-variant-quantity", variant_id: "test-variant-quantity",
product_id: "test-product",
cart_id: "test-cart-w-item-fixed-discount", cart_id: "test-cart-w-item-fixed-discount",
}) })
@@ -933,6 +939,7 @@ describe("/store/carts", () => {
unit_price: 1000, unit_price: 1000,
quantity: 1, quantity: 1,
variant_id: "test-variant-quantity", variant_id: "test-variant-quantity",
product_id: "test-product",
cart_id: "test-cart-w-item-percentage-discount", cart_id: "test-cart-w-item-percentage-discount",
}) })
@@ -1050,6 +1057,7 @@ describe("/store/carts", () => {
line_items: [ line_items: [
{ {
variant_id: "test-variant", variant_id: "test-variant",
product_id: "test-product",
unit_price: 100, unit_price: 100,
}, },
], ],
@@ -1110,6 +1118,7 @@ describe("/store/carts", () => {
line_items: [ line_items: [
{ {
variant_id: "test-variant", variant_id: "test-variant",
product_id: "test-product",
unit_price: 100, unit_price: 100,
}, },
], ],
@@ -1260,6 +1269,7 @@ describe("/store/carts", () => {
line_items: [ line_items: [
{ {
variant_id: "test-variant", variant_id: "test-variant",
product_id: "test-product",
unit_price: 100, unit_price: 100,
}, },
], ],
@@ -1327,6 +1337,7 @@ describe("/store/carts", () => {
line_items: [ line_items: [
{ {
variant_id: "test-variant", variant_id: "test-variant",
product_id: "test-product",
unit_price: 100, unit_price: 100,
}, },
], ],
@@ -1387,6 +1398,7 @@ describe("/store/carts", () => {
line_items: [ line_items: [
{ {
variant_id: "test-variant", variant_id: "test-variant",
product_id: "test-product",
unit_price: 100, unit_price: 100,
}, },
], ],
@@ -1457,6 +1469,7 @@ describe("/store/carts", () => {
line_items: [ line_items: [
{ {
variant_id: "test-variant", variant_id: "test-variant",
product_id: "test-product",
unit_price: 100, unit_price: 100,
}, },
], ],
@@ -2207,6 +2220,7 @@ describe("/store/carts", () => {
line_items: [ line_items: [
{ {
variant_id: product.variants[0].id, variant_id: product.variants[0].id,
product_id: product.id,
quantity: 1, quantity: 1,
unit_price: 1000, unit_price: 1000,
}, },
@@ -2251,6 +2265,7 @@ describe("/store/carts", () => {
line_items: [ line_items: [
{ {
variant_id: product.variants[0].id, variant_id: product.variants[0].id,
product_id: product.id,
quantity: 1, quantity: 1,
unit_price: 1000, unit_price: 1000,
}, },
@@ -2702,7 +2717,13 @@ describe("/store/carts", () => {
const product = await simpleProductFactory(dbConnection) const product = await simpleProductFactory(dbConnection)
const cart = await simpleCartFactory(dbConnection, { const cart = await simpleCartFactory(dbConnection, {
region: region.id, region: region.id,
line_items: [{ variant_id: product.variants[0].id, quantity: 1 }], line_items: [
{
variant_id: product.variants[0].id,
product_id: product.id,
quantity: 1,
},
],
shipping_address: { shipping_address: {
country_code: "us", country_code: "us",
}, },
@@ -2737,7 +2758,13 @@ describe("/store/carts", () => {
const product = await simpleProductFactory(dbConnection) const product = await simpleProductFactory(dbConnection)
const cart = await simpleCartFactory(dbConnection, { const cart = await simpleCartFactory(dbConnection, {
region: region.id, region: region.id,
line_items: [{ variant_id: product.variants[0].id, quantity: 1 }], line_items: [
{
variant_id: product.variants[0].id,
product_id: product.id,
quantity: 1,
},
],
}) })
await simpleShippingOptionFactory(dbConnection, { await simpleShippingOptionFactory(dbConnection, {
region_id: region.id, region_id: region.id,
@@ -2769,7 +2796,13 @@ describe("/store/carts", () => {
const product = await simpleProductFactory(dbConnection) const product = await simpleProductFactory(dbConnection)
const cart = await simpleCartFactory(dbConnection, { const cart = await simpleCartFactory(dbConnection, {
region: region.id, region: region.id,
line_items: [{ variant_id: product.variants[0].id, quantity: 1 }], line_items: [
{
variant_id: product.variants[0].id,
product_id: product.id,
quantity: 1,
},
],
}) })
await simpleShippingOptionFactory(dbConnection, { await simpleShippingOptionFactory(dbConnection, {
region_id: region.id, region_id: region.id,
@@ -1,6 +1,6 @@
import { DataSource } from "typeorm"
import faker from "faker"
import { LineItem, LineItemAdjustment, LineItemTaxLine } from "@medusajs/medusa" import { LineItem, LineItemAdjustment, LineItemTaxLine } from "@medusajs/medusa"
import faker from "faker"
import { DataSource } from "typeorm"
type TaxLineFactoryData = { type TaxLineFactoryData = {
rate: number rate: number
@@ -18,6 +18,7 @@ export type LineItemFactoryData = {
cart_id?: string cart_id?: string
order_id?: string order_id?: string
variant_id: string | null variant_id: string | null
product_id: string | null
title?: string title?: string
description?: string description?: string
thumbnail?: string thumbnail?: string
@@ -75,7 +76,8 @@ export const simpleLineItemFactory = async (
adjustments: data.adjustments, adjustments: data.adjustments,
includes_tax: data.includes_tax, includes_tax: data.includes_tax,
order_edit_id: data.order_edit_id, order_edit_id: data.order_edit_id,
is_giftcard: data.is_giftcard || false is_giftcard: data.is_giftcard || false,
product_id: data.product_id,
}) })
const line = await manager.save(toSave) const line = await manager.save(toSave)
+3
View File
@@ -834,6 +834,7 @@ module.exports = async (dataSource, data = {}) => {
unit_price: 8000, unit_price: 8000,
quantity: 1, quantity: 1,
variant_id: "test-variant", variant_id: "test-variant",
product_id: "test-product",
cart_id: "test-cart-2", cart_id: "test-cart-2",
}) })
await manager.save(li) await manager.save(li)
@@ -887,6 +888,7 @@ module.exports = async (dataSource, data = {}) => {
unit_price: 8000, unit_price: 8000,
quantity: 1, quantity: 1,
variant_id: "test-variant", variant_id: "test-variant",
product_id: "test-product",
cart_id: "test-cart-3", cart_id: "test-cart-3",
}) })
await manager.save(li2) await manager.save(li2)
@@ -951,6 +953,7 @@ module.exports = async (dataSource, data = {}) => {
quantity: 1, quantity: 1,
variant_id: "test-variant-sale-cg", variant_id: "test-variant-sale-cg",
cart_id: "test-cart-3", cart_id: "test-cart-3",
product_id: "test-product",
metadata: { "some-existing": "prop" }, metadata: { "some-existing": "prop" },
}) })
await manager.save(li3) await manager.save(li3)
@@ -1,19 +1,19 @@
import {
CartService,
DraftOrderService,
LineItemService,
} from "../../../../services"
import { IsInt, IsObject, IsOptional, IsString } from "class-validator" import { IsInt, IsObject, IsOptional, IsString } from "class-validator"
import { import {
defaultAdminDraftOrdersCartFields, defaultAdminDraftOrdersCartFields,
defaultAdminDraftOrdersCartRelations, defaultAdminDraftOrdersCartRelations,
defaultAdminDraftOrdersFields, defaultAdminDraftOrdersFields,
} from "." } from "."
import {
CartService,
DraftOrderService,
LineItemService,
} from "../../../../services"
import { EntityManager } from "typeorm"
import { MedusaError } from "medusa-core-utils" import { MedusaError } from "medusa-core-utils"
import { validator } from "../../../../utils/validator" import { EntityManager } from "typeorm"
import { cleanResponseData } from "../../../../utils/clean-response-data" import { cleanResponseData } from "../../../../utils/clean-response-data"
import { validator } from "../../../../utils/validator"
/** /**
* @oas [post] /admin/draft-orders/{id}/line-items * @oas [post] /admin/draft-orders/{id}/line-items
@@ -119,7 +119,9 @@ export default async (req, res) => {
await cartService await cartService
.withTransaction(manager) .withTransaction(manager)
.addLineItem(draftOrder.cart_id, line, { validateSalesChannels: false }) .addOrUpdateLineItems(draftOrder.cart_id, line, {
validateSalesChannels: false,
})
} else { } else {
// custom line items can be added to a draft order // custom line items can be added to a draft order
await lineItemService.withTransaction(manager).create({ await lineItemService.withTransaction(manager).create({
@@ -39,7 +39,7 @@ export async function handleAddOrUpdateLineItem(
metadata: data.metadata, metadata: data.metadata,
}) })
await txCartService.addLineItem(cart.id, line, { await txCartService.addOrUpdateLineItems(cart.id, line, {
validateSalesChannels: featureFlagRouter.isFeatureEnabled("sales_channels"), validateSalesChannels: featureFlagRouter.isFeatureEnabled("sales_channels"),
}) })
@@ -1,8 +1,14 @@
import { FlagRouter } from "@medusajs/utils"
import { IsBooleanString, IsOptional, IsString } from "class-validator" import { IsBooleanString, IsOptional, IsString } from "class-validator"
import { PricingService, ProductService } from "../../../../services" import { defaultRelations } from "."
import IsolateProductDomainFeatureFlag from "../../../../loaders/feature-flags/isolate-product-domain"
import {
PricingService,
ProductService,
ShippingProfileService,
} from "../../../../services"
import ShippingOptionService from "../../../../services/shipping-option" import ShippingOptionService from "../../../../services/shipping-option"
import { validator } from "../../../../utils/validator" import { validator } from "../../../../utils/validator"
import { defaultRelations } from "."
/** /**
* @oas [get] /store/shipping-options * @oas [get] /store/shipping-options
@@ -61,6 +67,10 @@ export default async (req, res) => {
const shippingOptionService: ShippingOptionService = req.scope.resolve( const shippingOptionService: ShippingOptionService = req.scope.resolve(
"shippingOptionService" "shippingOptionService"
) )
const shippingProfileService: ShippingProfileService = req.scope.resolve(
"shippingProfileService"
)
const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter")
// should be selector // should be selector
const query: Record<string, unknown> = {} const query: Record<string, unknown> = {}
@@ -76,9 +86,18 @@ export default async (req, res) => {
query.admin_only = false query.admin_only = false
if (productIds.length) { if (productIds.length) {
if (
featureFlagRouter.isFeatureEnabled(IsolateProductDomainFeatureFlag.key)
) {
const productShippinProfileMap =
await shippingProfileService.getMapProfileIdsByProductIds(productIds)
query.profile_id = [...productShippinProfileMap.values()]
} else {
const prods = await productService.list({ id: productIds }) const prods = await productService.list({ id: productIds })
query.profile_id = prods.map((p) => p.profile_id) query.profile_id = prods.map((p) => p.profile_id)
} }
}
const options = await shippingOptionService.list(query, { const options = await shippingOptionService.list(query, {
relations: defaultRelations, relations: defaultRelations,
@@ -0,0 +1,24 @@
import { MigrationInterface, QueryRunner } from "typeorm"
import IsolateProductDomain from "../loaders/feature-flags/isolate-product-domain"
export const featureFlag = IsolateProductDomain.key
export class LineItemProductId1692870898424 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE "line_item" DROP CONSTRAINT IF EXISTS "FK_5371cbaa3be5200f373d24e3d5b";
ALTER TABLE "line_item" ADD COLUMN IF NOT EXISTS "product_id" text;
UPDATE "line_item" SET "product_id" = pv."product_id"
FROM "product_variant" pv
WHERE "line_item"."variant_id" = "pv"."id";
`)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE "line_item" DROP COLUMN IF EXISTS "product_id";
ALTER TABLE "line_item" ADD CONSTRAINT "FK_5371cbaa3be5200f373d24e3d5b" FOREIGN KEY ("variant_id") REFERENCES "product_variant" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
`)
}
}
+46 -3
View File
@@ -1,5 +1,8 @@
import { import {
AfterLoad,
AfterUpdate,
BeforeInsert, BeforeInsert,
BeforeUpdate,
Check, Check,
Column, Column,
Entity, Entity,
@@ -11,9 +14,11 @@ import {
import { BaseEntity } from "../interfaces" import { BaseEntity } from "../interfaces"
import TaxInclusivePricingFeatureFlag from "../loaders/feature-flags/tax-inclusive-pricing" import TaxInclusivePricingFeatureFlag from "../loaders/feature-flags/tax-inclusive-pricing"
import { generateEntityId } from "../utils" import { DbAwareColumn, generateEntityId } from "../utils"
import { DbAwareColumn } from "../utils/db-aware-column" import {
import { FeatureFlagColumn } from "../utils/feature-flag-decorators" FeatureFlagColumn,
FeatureFlagDecorators,
} from "../utils/feature-flag-decorators"
import { Cart } from "./cart" import { Cart } from "./cart"
import { ClaimOrder } from "./claim-order" import { ClaimOrder } from "./claim-order"
import { LineItemAdjustment } from "./line-item-adjustment" import { LineItemAdjustment } from "./line-item-adjustment"
@@ -22,6 +27,8 @@ import { Order } from "./order"
import { OrderEdit } from "./order-edit" import { OrderEdit } from "./order-edit"
import { ProductVariant } from "./product-variant" import { ProductVariant } from "./product-variant"
import { Swap } from "./swap" import { Swap } from "./swap"
import IsolateProductDomain from "../loaders/feature-flags/isolate-product-domain"
import { featureFlagRouter } from "../loaders/feature-flags"
@Check(`"fulfilled_quantity" <= "quantity"`) @Check(`"fulfilled_quantity" <= "quantity"`)
@Check(`"shipped_quantity" <= "fulfilled_quantity"`) @Check(`"shipped_quantity" <= "fulfilled_quantity"`)
@@ -124,6 +131,9 @@ export class LineItem extends BaseEntity {
@JoinColumn({ name: "variant_id" }) @JoinColumn({ name: "variant_id" })
variant: ProductVariant variant: ProductVariant
@FeatureFlagColumn(IsolateProductDomain.key, { nullable: true, type: "text" })
product_id: string | null
@Column({ type: "int" }) @Column({ type: "int" })
quantity: number quantity: number
@@ -155,6 +165,39 @@ export class LineItem extends BaseEntity {
@BeforeInsert() @BeforeInsert()
private beforeInsert(): void { private beforeInsert(): void {
this.id = generateEntityId(this.id, "item") this.id = generateEntityId(this.id, "item")
// This is to maintain compatibility while isolating the product domain
if (featureFlagRouter.isFeatureEnabled(IsolateProductDomain.key)) {
if (
this.variant &&
Object.keys(this.variant).length === 1 &&
this.variant.product_id
) {
this.variant = undefined as any
}
}
}
@FeatureFlagDecorators(IsolateProductDomain.key, [BeforeUpdate])
beforeUpdate(): void {
if (
this.variant &&
Object.keys(this.variant).length === 1 &&
this.variant.product_id
) {
this.variant = undefined as any
}
}
@FeatureFlagDecorators(IsolateProductDomain.key, [AfterLoad, AfterUpdate])
afterUpdateOrLoad(): void {
if (this.variant) {
return
}
if (this.product_id) {
this.variant = { product_id: this.product_id } as any
}
} }
} }
@@ -1,4 +1,8 @@
import { MedusaModule, Modules } from "@medusajs/modules-sdk"
import { DeleteResult, EntityTarget, In, Not } from "typeorm" import { DeleteResult, EntityTarget, In, Not } from "typeorm"
import { dataSource } from "../loaders/database"
import { featureFlagRouter } from "../loaders/feature-flags"
import IsolateProductDomainFeatureFlag from "../loaders/feature-flags/isolate-product-domain"
import { import {
Discount, Discount,
DiscountCondition, DiscountCondition,
@@ -11,7 +15,6 @@ import {
DiscountConditionType, DiscountConditionType,
} from "../models" } from "../models"
import { isString } from "../utils" import { isString } from "../utils"
import { dataSource } from "../loaders/database"
export enum DiscountConditionJoinTableForeignKey { export enum DiscountConditionJoinTableForeignKey {
PRODUCT_ID = "product_id", PRODUCT_ID = "product_id",
@@ -53,6 +56,7 @@ export const DiscountConditionRepository = dataSource
joinTableForeignKey: DiscountConditionJoinTableForeignKey joinTableForeignKey: DiscountConditionJoinTableForeignKey
conditionTable: DiscountConditionResourceType conditionTable: DiscountConditionResourceType
joinTableKey: string joinTableKey: string
relatedTable: string
} { } {
let conditionTable: DiscountConditionResourceType = let conditionTable: DiscountConditionResourceType =
DiscountConditionProduct DiscountConditionProduct
@@ -61,6 +65,7 @@ export const DiscountConditionRepository = dataSource
let joinTableForeignKey: DiscountConditionJoinTableForeignKey = let joinTableForeignKey: DiscountConditionJoinTableForeignKey =
DiscountConditionJoinTableForeignKey.PRODUCT_ID DiscountConditionJoinTableForeignKey.PRODUCT_ID
let joinTableKey = "id" let joinTableKey = "id"
let relatedTable = ""
// On the joined table (e.g. `product`), what key should be match on // On the joined table (e.g. `product`), what key should be match on
// (e.g `type_id` for product types and `id` for products) // (e.g `type_id` for product types and `id` for products)
@@ -80,6 +85,7 @@ export const DiscountConditionRepository = dataSource
joinTableForeignKey = joinTableForeignKey =
DiscountConditionJoinTableForeignKey.PRODUCT_TYPE_ID DiscountConditionJoinTableForeignKey.PRODUCT_TYPE_ID
joinTable = "product" joinTable = "product"
relatedTable = "types"
conditionTable = DiscountConditionProductType conditionTable = DiscountConditionProductType
break break
@@ -89,6 +95,7 @@ export const DiscountConditionRepository = dataSource
joinTableForeignKey = joinTableForeignKey =
DiscountConditionJoinTableForeignKey.PRODUCT_COLLECTION_ID DiscountConditionJoinTableForeignKey.PRODUCT_COLLECTION_ID
joinTable = "product" joinTable = "product"
relatedTable = "collections"
conditionTable = DiscountConditionProductCollection conditionTable = DiscountConditionProductCollection
break break
@@ -99,6 +106,7 @@ export const DiscountConditionRepository = dataSource
joinTableForeignKey = joinTableForeignKey =
DiscountConditionJoinTableForeignKey.PRODUCT_TAG_ID DiscountConditionJoinTableForeignKey.PRODUCT_TAG_ID
joinTable = "product_tags" joinTable = "product_tags"
relatedTable = "tags"
conditionTable = DiscountConditionProductTag conditionTable = DiscountConditionProductTag
break break
@@ -123,6 +131,7 @@ export const DiscountConditionRepository = dataSource
resourceKey, resourceKey,
joinTableForeignKey, joinTableForeignKey,
conditionTable, conditionTable,
relatedTable,
} }
}, },
@@ -204,15 +213,56 @@ export const DiscountConditionRepository = dataSource
.getMany() .getMany()
}, },
async queryConditionTable({ type, condId, resourceId }): Promise<number> { async queryConditionTable({
type,
conditionId,
resourceId,
}): Promise<number> {
const { const {
conditionTable, conditionTable,
joinTable, joinTable,
joinTableForeignKey, joinTableForeignKey,
resourceKey, resourceKey,
joinTableKey, joinTableKey,
relatedTable,
} = this.getJoinTableResourceIdentifiers(type) } = this.getJoinTableResourceIdentifiers(type)
if (
type !== DiscountConditionType.CUSTOMER_GROUPS &&
featureFlagRouter.isFeatureEnabled(IsolateProductDomainFeatureFlag.key)
) {
const module = MedusaModule.getModuleInstance(Modules.PRODUCT)[
Modules.PRODUCT
]
const prop = relatedTable
const resource = await module.retrieve(resourceId, {
select: [`${prop ? prop + "." : ""}id`],
relations: prop ? [prop] : [],
})
if (!resource) {
return 0
}
const relatedResourceIds = prop
? resource[prop].map((relatedResource) => relatedResource.id)
: [resource.id]
if (!relatedResourceIds.length) {
return 0
}
return await this.manager
.createQueryBuilder(conditionTable, "dc")
.where(
`dc.condition_id = :conditionId AND dc.${joinTableForeignKey} IN (:...relatedResourceIds)`,
{
conditionId,
relatedResourceIds,
}
)
.getCount()
}
return await this.manager return await this.manager
.createQueryBuilder(conditionTable, "dc") .createQueryBuilder(conditionTable, "dc")
.innerJoin( .innerJoin(
@@ -224,7 +274,7 @@ export const DiscountConditionRepository = dataSource
} }
) )
.where(`dc.condition_id = :conditionId`, { .where(`dc.condition_id = :conditionId`, {
conditionId: condId, conditionId,
}) })
.getCount() .getCount()
}, },
@@ -258,7 +308,7 @@ export const DiscountConditionRepository = dataSource
const numConditions = await this.queryConditionTable({ const numConditions = await this.queryConditionTable({
type: condition.type, type: condition.type,
condId: condition.id, conditionId: condition.id,
resourceId: productId, resourceId: productId,
}) })
@@ -307,7 +357,7 @@ export const DiscountConditionRepository = dataSource
for (const condition of discountConditions) { for (const condition of discountConditions) {
const numConditions = await this.queryConditionTable({ const numConditions = await this.queryConditionTable({
type: "customer_groups", type: "customer_groups",
condId: condition.id, conditionId: condition.id,
resourceId: customerId, resourceId: customerId,
}) })
@@ -143,9 +143,6 @@ export const ShippingProfileServiceMock = {
fetchCartOptions: jest.fn().mockImplementation(() => { fetchCartOptions: jest.fn().mockImplementation(() => {
return Promise.resolve([{ id: IdMap.getId("cartShippingOption") }]) return Promise.resolve([{ id: IdMap.getId("cartShippingOption") }])
}), }),
fetchOptionsByProductIds: jest.fn().mockImplementation(() => {
return Promise.resolve([{ id: IdMap.getId("cartShippingOption") }])
}),
} }
const mock = jest.fn().mockImplementation(() => { const mock = jest.fn().mockImplementation(() => {
+15 -13
View File
@@ -1,27 +1,28 @@
import _ from "lodash" import { FlagRouter } from "@medusajs/utils"
import { asClass, asValue, createContainer } from "awilix" import { asClass, asValue, createContainer } from "awilix"
import _ from "lodash"
import { MedusaError } from "medusa-core-utils" import { MedusaError } from "medusa-core-utils"
import { IdMap, MockManager, MockRepository } from "medusa-test-utils" import { IdMap, MockManager, MockRepository } from "medusa-test-utils"
import { FlagRouter } from "@medusajs/utils" import { IsNull, Not } from "typeorm"
import CartService from "../cart" import { PaymentSessionStatus } from "../../models"
import { ProductVariantInventoryServiceMock } from "../__mocks__/product-variant-inventory" import TaxCalculationStrategy from "../../strategies/tax-calculation"
import { cacheServiceMock } from "../__mocks__/cache"
import { CustomerServiceMock } from "../__mocks__/customer"
import { EventBusServiceMock } from "../__mocks__/event-bus"
import { LineItemServiceMock } from "../__mocks__/line-item"
import { LineItemAdjustmentServiceMock } from "../__mocks__/line-item-adjustment" import { LineItemAdjustmentServiceMock } from "../__mocks__/line-item-adjustment"
import { newTotalsServiceMock } from "../__mocks__/new-totals" import { newTotalsServiceMock } from "../__mocks__/new-totals"
import { taxProviderServiceMock } from "../__mocks__/tax-provider"
import { PaymentSessionStatus } from "../../models"
import { NewTotalsService, TaxProviderService } from "../index"
import { cacheServiceMock } from "../__mocks__/cache"
import { EventBusServiceMock } from "../__mocks__/event-bus"
import { PaymentProviderServiceMock } from "../__mocks__/payment-provider" import { PaymentProviderServiceMock } from "../__mocks__/payment-provider"
import { ProductServiceMock } from "../__mocks__/product" import { ProductServiceMock } from "../__mocks__/product"
import { ProductVariantServiceMock } from "../__mocks__/product-variant" import { ProductVariantServiceMock } from "../__mocks__/product-variant"
import { ProductVariantInventoryServiceMock } from "../__mocks__/product-variant-inventory"
import { RegionServiceMock } from "../__mocks__/region" import { RegionServiceMock } from "../__mocks__/region"
import { LineItemServiceMock } from "../__mocks__/line-item"
import { ShippingOptionServiceMock } from "../__mocks__/shipping-option" import { ShippingOptionServiceMock } from "../__mocks__/shipping-option"
import { CustomerServiceMock } from "../__mocks__/customer" import { ShippingProfileServiceMock } from "../__mocks__/shipping-profile"
import TaxCalculationStrategy from "../../strategies/tax-calculation" import { taxProviderServiceMock } from "../__mocks__/tax-provider"
import CartService from "../cart"
import { NewTotalsService, TaxProviderService } from "../index"
import SystemTaxService from "../system-tax" import SystemTaxService from "../system-tax"
import { IsNull, Not } from "typeorm"
const eventBusService = { const eventBusService = {
emit: jest.fn(), emit: jest.fn(),
@@ -2628,6 +2629,7 @@ describe("CartService", () => {
.register("regionService", asValue(RegionServiceMock)) .register("regionService", asValue(RegionServiceMock))
.register("lineItemService", asValue(LineItemServiceMock)) .register("lineItemService", asValue(LineItemServiceMock))
.register("shippingOptionService", asValue(ShippingOptionServiceMock)) .register("shippingOptionService", asValue(ShippingOptionServiceMock))
.register("shippingProfileService", asValue(ShippingProfileServiceMock))
.register("customerService", asValue(CustomerServiceMock)) .register("customerService", asValue(CustomerServiceMock))
.register("discountService", asValue({})) .register("discountService", asValue({}))
.register("giftCardService", asValue({})) .register("giftCardService", asValue({}))
@@ -1,3 +1,4 @@
import { FlagRouter } from "@medusajs/utils"
import { IdMap, MockManager, MockRepository } from "medusa-test-utils" import { IdMap, MockManager, MockRepository } from "medusa-test-utils"
import ShippingProfileService from "../shipping-profile" import ShippingProfileService from "../shipping-profile"
@@ -15,6 +16,7 @@ describe("ShippingProfileService", () => {
const profileService = new ShippingProfileService({ const profileService = new ShippingProfileService({
manager: MockManager, manager: MockManager,
shippingProfileRepository: profRepo, shippingProfileRepository: profRepo,
featureFlagRouter: new FlagRouter({}),
}) })
await profileService.retrieve(IdMap.getId("validId")) await profileService.retrieve(IdMap.getId("validId"))
@@ -53,6 +55,7 @@ describe("ShippingProfileService", () => {
shippingProfileRepository: profRepo, shippingProfileRepository: profRepo,
productService, productService,
shippingOptionService, shippingOptionService,
featureFlagRouter: new FlagRouter({}),
}) })
beforeEach(() => { beforeEach(() => {
@@ -106,6 +109,7 @@ describe("ShippingProfileService", () => {
const profileService = new ShippingProfileService({ const profileService = new ShippingProfileService({
manager: MockManager, manager: MockManager,
shippingProfileRepository: profRepo, shippingProfileRepository: profRepo,
featureFlagRouter: new FlagRouter({}),
}) })
beforeEach(() => { beforeEach(() => {
@@ -136,6 +140,7 @@ describe("ShippingProfileService", () => {
manager: MockManager, manager: MockManager,
shippingProfileRepository: profRepo, shippingProfileRepository: profRepo,
productService, productService,
featureFlagRouter: new FlagRouter({}),
}) })
beforeEach(() => { beforeEach(() => {
@@ -219,6 +224,7 @@ describe("ShippingProfileService", () => {
shippingProfileRepository: profRepo, shippingProfileRepository: profRepo,
shippingOptionService, shippingOptionService,
customShippingOptionService, customShippingOptionService,
featureFlagRouter: new FlagRouter({}),
}) })
beforeEach(() => { beforeEach(() => {
@@ -311,6 +317,7 @@ describe("ShippingProfileService", () => {
manager: MockManager, manager: MockManager,
shippingProfileRepository: profRepo, shippingProfileRepository: profRepo,
shippingOptionService, shippingOptionService,
featureFlagRouter: new FlagRouter({}),
}) })
beforeEach(() => { beforeEach(() => {
@@ -335,6 +342,7 @@ describe("ShippingProfileService", () => {
const profileService = new ShippingProfileService({ const profileService = new ShippingProfileService({
manager: MockManager, manager: MockManager,
shippingProfileRepository: profRepo, shippingProfileRepository: profRepo,
featureFlagRouter: new FlagRouter({}),
}) })
afterEach(() => { afterEach(() => {
+68 -20
View File
@@ -18,11 +18,13 @@ import {
RegionService, RegionService,
SalesChannelService, SalesChannelService,
ShippingOptionService, ShippingOptionService,
ShippingProfileService,
StoreService, StoreService,
TaxProviderService, TaxProviderService,
TotalsService, TotalsService,
} from "." } from "."
import { IPriceSelectionStrategy, TransactionBaseService } from "../interfaces" import { IPriceSelectionStrategy, TransactionBaseService } from "../interfaces"
import IsolateProductDomainFeatureFlag from "../loaders/feature-flags/isolate-product-domain"
import SalesChannelFeatureFlag from "../loaders/feature-flags/sales-channels" import SalesChannelFeatureFlag from "../loaders/feature-flags/sales-channels"
import { import {
Address, Address,
@@ -79,6 +81,7 @@ type InjectedDependencies = {
regionService: RegionService regionService: RegionService
lineItemService: LineItemService lineItemService: LineItemService
shippingOptionService: ShippingOptionService shippingOptionService: ShippingOptionService
shippingProfileService: ShippingProfileService
customerService: CustomerService customerService: CustomerService
discountService: DiscountService discountService: DiscountService
giftCardService: GiftCardService giftCardService: GiftCardService
@@ -119,6 +122,7 @@ class CartService extends TransactionBaseService {
protected readonly paymentProviderService_: PaymentProviderService protected readonly paymentProviderService_: PaymentProviderService
protected readonly customerService_: CustomerService protected readonly customerService_: CustomerService
protected readonly shippingOptionService_: ShippingOptionService protected readonly shippingOptionService_: ShippingOptionService
protected readonly shippingProfileService_: ShippingProfileService
protected readonly discountService_: DiscountService protected readonly discountService_: DiscountService
protected readonly giftCardService_: GiftCardService protected readonly giftCardService_: GiftCardService
protected readonly taxProviderService_: TaxProviderService protected readonly taxProviderService_: TaxProviderService
@@ -143,6 +147,7 @@ class CartService extends TransactionBaseService {
regionService, regionService,
lineItemService, lineItemService,
shippingOptionService, shippingOptionService,
shippingProfileService,
customerService, customerService,
discountService, discountService,
giftCardService, giftCardService,
@@ -172,6 +177,7 @@ class CartService extends TransactionBaseService {
this.paymentProviderService_ = paymentProviderService this.paymentProviderService_ = paymentProviderService
this.customerService_ = customerService this.customerService_ = customerService
this.shippingOptionService_ = shippingOptionService this.shippingOptionService_ = shippingOptionService
this.shippingProfileService_ = shippingProfileService
this.discountService_ = discountService this.discountService_ = discountService
this.giftCardService_ = giftCardService this.giftCardService_ = giftCardService
this.totalsService_ = totalsService this.totalsService_ = totalsService
@@ -222,6 +228,21 @@ class CartService extends TransactionBaseService {
) )
} }
if (
this.featureFlagRouter_.isFeatureEnabled(
IsolateProductDomainFeatureFlag.key
)
) {
if (Array.isArray(options.relations)) {
for (let i = 0; i < options.relations.length; i++) {
if (options.relations[i].startsWith("items.variant")) {
options.relations[i] = "items"
}
}
}
options.relations = [...new Set(options.relations)]
}
const { totalsToSelect } = this.transformQueryForTotals_(options) const { totalsToSelect } = this.transformQueryForTotals_(options)
if (totalsToSelect.length) { if (totalsToSelect.length) {
@@ -293,10 +314,25 @@ class CartService extends TransactionBaseService {
): Promise<WithRequiredProperty<Cart, "total">> { ): Promise<WithRequiredProperty<Cart, "total">> {
const relations = this.getTotalsRelations(options) const relations = this.getTotalsRelations(options)
const cart = await this.retrieve(cartId, { const opt = { ...options, relations }
...options,
relations, if (
}) this.featureFlagRouter_.isFeatureEnabled(
IsolateProductDomainFeatureFlag.key
)
) {
if (Array.isArray(opt.relations)) {
for (let i = 0; i < opt.relations.length; i++) {
if (opt.relations[i].startsWith("items.variant")) {
opt.relations[i] = "items"
}
}
}
opt.relations = [...new Set(opt.relations)]
}
const cart = await this.retrieve(cartId, opt)
return await this.decorateTotals(cart, totalsConfig) return await this.decorateTotals(cart, totalsConfig)
} }
@@ -547,23 +583,21 @@ class CartService extends TransactionBaseService {
*/ */
protected validateLineItemShipping_( protected validateLineItemShipping_(
shippingMethods: ShippingMethod[], shippingMethods: ShippingMethod[],
lineItem: LineItem lineItemShippingProfiledId: string
): boolean { ): boolean {
if (!lineItem.variant_id) { if (!lineItemShippingProfiledId) {
return true return true
} }
if ( if (
shippingMethods && shippingMethods &&
shippingMethods.length && shippingMethods.length &&
lineItem.variant && lineItemShippingProfiledId
lineItem.variant.product
) { ) {
const productProfile = lineItem.variant.product.profile_id
const selectedProfiles = shippingMethods.map( const selectedProfiles = shippingMethods.map(
({ shipping_option }) => shipping_option.profile_id ({ shipping_option }) => shipping_option.profile_id
) )
return selectedProfiles.includes(productProfile) return selectedProfiles.includes(lineItemShippingProfiledId)
} }
return false return false
@@ -1083,15 +1117,6 @@ class CartService extends TransactionBaseService {
"discounts.rule", "discounts.rule",
] ]
if (
this.featureFlagRouter_.isFeatureEnabled(
SalesChannelFeatureFlag.key
) &&
data.sales_channel_id
) {
relations.push("items.variant.product.profiles")
}
const cart = await this.retrieve(cartId, { const cart = await this.retrieve(cartId, {
relations, relations,
}) })
@@ -2163,10 +2188,33 @@ class CartService extends TransactionBaseService {
const lineItemServiceTx = const lineItemServiceTx =
this.lineItemService_.withTransaction(transactionManager) this.lineItemService_.withTransaction(transactionManager)
let productShippinProfileMap = new Map<string, string>()
if (
this.featureFlagRouter_.isFeatureEnabled(
IsolateProductDomainFeatureFlag.key
)
) {
productShippinProfileMap =
await this.shippingProfileService_.getMapProfileIdsByProductIds(
cart.items.map((item) => item.variant.product_id)
)
} else {
productShippinProfileMap = new Map<string, string>(
cart.items.map((item) => [
item.variant?.product?.id,
item.variant?.product?.profile_id,
])
)
}
await Promise.all( await Promise.all(
cart.items.map(async (item) => { cart.items.map(async (item) => {
return lineItemServiceTx.update(item.id, { return lineItemServiceTx.update(item.id, {
has_shipping: this.validateLineItemShipping_(methods, item), has_shipping: this.validateLineItemShipping_(
methods,
productShippinProfileMap.get(item.variant?.product_id)!
),
}) })
}) })
) )
+2 -8
View File
@@ -576,7 +576,7 @@ class DiscountService extends TransactionBaseService {
async validateDiscountForProduct( async validateDiscountForProduct(
discountRuleId: string, discountRuleId: string,
productId: string | undefined productId?: string
): Promise<boolean> { ): Promise<boolean> {
return await this.atomicPhase_(async (manager) => { return await this.atomicPhase_(async (manager) => {
const discountConditionRepo = manager.withRepository( const discountConditionRepo = manager.withRepository(
@@ -589,15 +589,9 @@ class DiscountService extends TransactionBaseService {
return false return false
} }
const product = await this.productService_
.withTransaction(manager)
.retrieve(productId, {
relations: ["tags"],
})
return await discountConditionRepo.isValidForProduct( return await discountConditionRepo.isValidForProduct(
discountRuleId, discountRuleId,
product.id productId
) )
}) })
} }
@@ -1,14 +1,14 @@
import { isDefined, MedusaError } from "medusa-core-utils" import { isDefined, MedusaError } from "medusa-core-utils"
import { EntityManager, FindOperator, In } from "typeorm" import { EntityManager, FindOperator, In } from "typeorm"
import { TransactionBaseService } from "../interfaces"
import { Cart, DiscountRuleType, LineItem, LineItemAdjustment } from "../models" import { Cart, DiscountRuleType, LineItem, LineItemAdjustment } from "../models"
import { LineItemAdjustmentRepository } from "../repositories/line-item-adjustment" import { LineItemAdjustmentRepository } from "../repositories/line-item-adjustment"
import { FindConfig } from "../types/common" import { FindConfig } from "../types/common"
import { FilterableLineItemAdjustmentProps } from "../types/line-item-adjustment" import { FilterableLineItemAdjustmentProps } from "../types/line-item-adjustment"
import DiscountService from "./discount"
import { TransactionBaseService } from "../interfaces"
import { buildQuery, setMetadata } from "../utils"
import { CalculationContextData } from "../types/totals" import { CalculationContextData } from "../types/totals"
import { buildQuery, setMetadata } from "../utils"
import DiscountService from "./discount"
type LineItemAdjustmentServiceProps = { type LineItemAdjustmentServiceProps = {
manager: EntityManager manager: EntityManager
+12 -1
View File
@@ -4,6 +4,7 @@ import { DeepPartial } from "typeorm/common/DeepPartial"
import { FlagRouter } from "@medusajs/utils" import { FlagRouter } from "@medusajs/utils"
import { TransactionBaseService } from "../interfaces" import { TransactionBaseService } from "../interfaces"
import IsolateProductDomainFeatureFlag from "../loaders/feature-flags/isolate-product-domain"
import TaxInclusivePricingFeatureFlag from "../loaders/feature-flags/tax-inclusive-pricing" import TaxInclusivePricingFeatureFlag from "../loaders/feature-flags/tax-inclusive-pricing"
import { import {
LineItem, LineItem,
@@ -364,6 +365,14 @@ class LineItemService extends TransactionBaseService {
should_merge: shouldMerge, should_merge: shouldMerge,
} }
if (
this.featureFlagRouter_.isFeatureEnabled(
IsolateProductDomainFeatureFlag.key
)
) {
rawLineItem.product_id = variant.product_id
}
if ( if (
this.featureFlagRouter_.isFeatureEnabled( this.featureFlagRouter_.isFeatureEnabled(
TaxInclusivePricingFeatureFlag.key TaxInclusivePricingFeatureFlag.key
@@ -471,7 +480,9 @@ class LineItemService extends TransactionBaseService {
return await lineItemRepository return await lineItemRepository
.findOne({ where: { id } }) .findOne({ where: { id } })
.then((lineItem) => lineItem && lineItemRepository.remove(lineItem)) .then(
async (lineItem) => lineItem && lineItemRepository.remove(lineItem)
)
} }
) )
} }
+1 -1
View File
@@ -675,7 +675,7 @@ export default class NewTotalsService extends TransactionBaseService {
if (!totals.tax_lines) { if (!totals.tax_lines) {
throw new MedusaError( throw new MedusaError(
MedusaError.Types.UNEXPECTED_STATE, MedusaError.Types.UNEXPECTED_STATE,
"Tax Lines must be joined to calculate taxes" "Tax Lines must be joined to calculate shipping taxes"
) )
} }
} }
@@ -1,6 +1,8 @@
import { isDefined, MedusaError } from "medusa-core-utils" import { FlagRouter, isDefined } from "@medusajs/utils"
import { EntityManager } from "typeorm" import { MedusaError } from "medusa-core-utils"
import { EntityManager, In } from "typeorm"
import { TransactionBaseService } from "../interfaces" import { TransactionBaseService } from "../interfaces"
import IsolateProductDomainFeatureFlag from "../loaders/feature-flags/isolate-product-domain"
import { import {
Cart, Cart,
CustomShippingOption, CustomShippingOption,
@@ -27,6 +29,7 @@ type InjectedDependencies = {
customShippingOptionService: CustomShippingOptionService customShippingOptionService: CustomShippingOptionService
shippingProfileRepository: typeof ShippingProfileRepository shippingProfileRepository: typeof ShippingProfileRepository
productRepository: typeof ProductRepository productRepository: typeof ProductRepository
featureFlagRouter: FlagRouter
} }
/** /**
@@ -41,6 +44,7 @@ class ShippingProfileService extends TransactionBaseService {
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
protected readonly shippingProfileRepository_: typeof ShippingProfileRepository protected readonly shippingProfileRepository_: typeof ShippingProfileRepository
protected readonly productRepository_: typeof ProductRepository protected readonly productRepository_: typeof ProductRepository
protected readonly featureFlagRouter_: FlagRouter
constructor({ constructor({
shippingProfileRepository, shippingProfileRepository,
@@ -48,6 +52,7 @@ class ShippingProfileService extends TransactionBaseService {
productRepository, productRepository,
shippingOptionService, shippingOptionService,
customShippingOptionService, customShippingOptionService,
featureFlagRouter,
}: InjectedDependencies) { }: InjectedDependencies) {
// eslint-disable-next-line prefer-rest-params // eslint-disable-next-line prefer-rest-params
super(arguments[0]) super(arguments[0])
@@ -57,6 +62,7 @@ class ShippingProfileService extends TransactionBaseService {
this.productRepository_ = productRepository this.productRepository_ = productRepository
this.shippingOptionService_ = shippingOptionService this.shippingOptionService_ = shippingOptionService
this.customShippingOptionService_ = customShippingOptionService this.customShippingOptionService_ = customShippingOptionService
this.featureFlagRouter_ = featureFlagRouter
} }
/** /**
@@ -79,49 +85,39 @@ class ShippingProfileService extends TransactionBaseService {
return shippingProfileRepo.find(query) return shippingProfileRepo.find(query)
} }
async fetchOptionsByProductIds( async getMapProfileIdsByProductIds(
productIds: string[], productIds: string[]
filter: Selector<ShippingOption> ): Promise<Map<string, string>> {
): Promise<ShippingOption[]> { const mappedProfiles = new Map<string, string>()
const products = await this.productService_.list(
{ if (!productIds?.length) {
id: productIds, return mappedProfiles
}
const shippingProfiles = await this.shippingProfileRepository_.find({
select: {
id: true,
products: {
id: true,
},
},
where: {
products: {
id: In(productIds),
},
},
relations: {
products: true,
}, },
{
relations: [
"profile",
"profile.shipping_options",
"profile.shipping_options.requirements",
],
}
)
const profiles = products.map((p) => p.profile)
const shippingOptions = profiles.reduce(
(acc: ShippingOption[], next: ShippingProfile) =>
acc.concat(next.shipping_options),
[]
)
const options = await Promise.all(
shippingOptions.map(async (option) => {
let canSend = true
if (filter.region_id) {
if (filter.region_id !== option.region_id) {
canSend = false
}
}
if (option.deleted_at !== null) {
canSend = false
}
return canSend ? option : null
}) })
)
return options.filter(Boolean) as ShippingOption[] shippingProfiles.forEach((profile) => {
profile.products.forEach((product) => {
mappedProfiles.set(product.id, profile.id)
})
})
return mappedProfiles
} }
/** /**
@@ -425,7 +421,7 @@ class ShippingProfileService extends TransactionBaseService {
*/ */
async fetchCartOptions(cart): Promise<ShippingOption[]> { async fetchCartOptions(cart): Promise<ShippingOption[]> {
return await this.atomicPhase_(async (manager) => { return await this.atomicPhase_(async (manager) => {
const profileIds = this.getProfilesInCart(cart) const profileIds = await this.getProfilesInCart(cart)
const selector: Selector<ShippingOption> = { const selector: Selector<ShippingOption> = {
profile_id: profileIds, profile_id: profileIds,
@@ -489,14 +485,25 @@ class ShippingProfileService extends TransactionBaseService {
* @param cart - the cart to extract products from * @param cart - the cart to extract products from
* @return a list of product ids * @return a list of product ids
*/ */
protected getProfilesInCart(cart: Cart): string[] { protected async getProfilesInCart(cart: Cart): Promise<string[]> {
const profileIds = new Set<string>() let profileIds = new Set<string>()
if (
this.featureFlagRouter_.isFeatureEnabled(
IsolateProductDomainFeatureFlag.key
)
) {
const productShippinProfileMap = await this.getMapProfileIdsByProductIds(
cart.items.map((item) => item.variant?.product_id)
)
profileIds = new Set([...productShippinProfileMap.values()])
} else {
cart.items.forEach((item) => { cart.items.forEach((item) => {
if (item.variant?.product) { if (item.variant?.product) {
profileIds.add(item.variant.product.profile_id) profileIds.add(item.variant.product.profile_id)
} }
}) })
}
return [...profileIds] return [...profileIds]
} }
+11 -18
View File
@@ -247,32 +247,26 @@ class TaxProviderService extends TransactionBaseService {
lineItems: LineItem[], lineItems: LineItem[],
calculationContext: TaxCalculationContext calculationContext: TaxCalculationContext
): Promise<(ShippingMethodTaxLine | LineItemTaxLine)[]> { ): Promise<(ShippingMethodTaxLine | LineItemTaxLine)[]> {
const productIds = lineItems const productIds = [
.map((l) => l?.variant?.product_id) ...new Set(
.filter((p) => p) lineItems.map((item) => item?.variant?.product_id).filter((p) => p)
),
]
const productRatesMap = await this.getRegionRatesForProduct( const productRatesMap = await this.getRegionRatesForProduct(
productIds, productIds,
calculationContext.region calculationContext.region
) )
const calculationLines = await Promise.all( const calculationLines = lineItems.map((item) => {
lineItems.map(async (l) => { if (item.is_return) {
if (l.is_return) {
return null return null
} }
if (l.variant_id && !l.variant) { if (item.variant?.product_id) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Unable to get the tax lines for the item ${l.id}, it contains a variant_id but the variant is missing.`
)
}
if (l.variant?.product_id) {
return { return {
item: l, item: item,
rates: productRatesMap.get(l.variant.product_id) ?? [], rates: productRatesMap.get(item.variant?.product_id) ?? [],
} }
} }
@@ -282,11 +276,10 @@ class TaxProviderService extends TransactionBaseService {
* to custom lines at some point * to custom lines at some point
*/ */
return { return {
item: l, item: item,
rates: [], rates: [],
} }
}) })
)
const shippingCalculationLines = await Promise.all( const shippingCalculationLines = await Promise.all(
calculationContext.shipping_methods.map(async (sm) => { calculationContext.shipping_methods.map(async (sm) => {
+1
View File
@@ -622,6 +622,7 @@ class TotalsService extends TransactionBaseService {
* @param value - discount value * @param value - discount value
* @param discountType - the type of discount (fixed or percentage) * @param discountType - the type of discount (fixed or percentage)
* @return triples of lineitem, variant and applied discount * @return triples of lineitem, variant and applied discount
* @deprecated - in favour of DiscountService.calculateDiscountForLineItem
*/ */
calculateDiscount_( calculateDiscount_(
lineItem: LineItem, lineItem: LineItem,
@@ -557,14 +557,15 @@ export class RemoteJoiner {
parsedExpands: Map<string, RemoteExpandProperty> parsedExpands: Map<string, RemoteExpandProperty>
): Map<string, RemoteExpandProperty> { ): Map<string, RemoteExpandProperty> {
const mergedExpands = new Map<string, RemoteExpandProperty>(parsedExpands) const mergedExpands = new Map<string, RemoteExpandProperty>(parsedExpands)
const mergedPaths = new Map<string, string>() const mergedPaths = new Map<string, RemoteExpandProperty>()
for (const [path, expand] of mergedExpands.entries()) { for (const [path, expand] of mergedExpands.entries()) {
const currentServiceName = expand.serviceConfig.serviceName const currentServiceName = expand.serviceConfig.serviceName
let parentPath = expand.parent let parentPath = expand.parent
while (parentPath) { while (parentPath) {
const parentExpand = mergedExpands.get(parentPath) const parentExpand =
mergedExpands.get(parentPath) ?? mergedPaths.get(parentPath)
if ( if (
!parentExpand || !parentExpand ||
parentExpand.serviceConfig.serviceName !== currentServiceName parentExpand.serviceConfig.serviceName !== currentServiceName
@@ -588,7 +589,7 @@ export class RemoteJoiner {
targetExpand.args = expand.args targetExpand.args = expand.args
mergedExpands.delete(path) mergedExpands.delete(path)
mergedPaths.set(path, parentPath) mergedPaths.set(path, expand)
parentPath = parentExpand.parent parentPath = parentExpand.parent
} }
+1 -1
View File
@@ -8,7 +8,7 @@
"outputs": [ "outputs": [
"!node_modules/**", "!node_modules/**",
"!src/**", "!src/**",
"/*/**" "*/**"
] ]
}, },
"test": { "test": {