From c7edebaba64e43a37616929728feceaaddb56b65 Mon Sep 17 00:00:00 2001 From: olivermrbl Date: Wed, 17 Jan 2024 21:46:30 +0100 Subject: [PATCH 1/8] item tax lines --- packages/cart/src/services/cart-module.ts | 186 +++++++++++++++++++++- packages/types/src/cart/service.ts | 40 +++++ 2 files changed, 225 insertions(+), 1 deletion(-) diff --git a/packages/cart/src/services/cart-module.ts b/packages/cart/src/services/cart-module.ts index 5a20a5e9eaafa..75be9f4690cd1 100644 --- a/packages/cart/src/services/cart-module.ts +++ b/packages/cart/src/services/cart-module.ts @@ -1,11 +1,14 @@ import { Context, + CreateLineItemTaxLineDTO, DAL, FilterableCartProps, FindConfig, ICartModuleService, InternalModuleDeclaration, + LineItemTaxLineDTO, ModuleJoinerConfig, + UpdateLineItemTaxLineDTO, } from "@medusajs/types" import { CartTypes } from "@medusajs/types" @@ -14,10 +17,11 @@ import { InjectManager, InjectTransactionManager, MedusaContext, + MedusaError, isObject, isString, } from "@medusajs/utils" -import { LineItem } from "@models" +import { LineItem, LineItemTaxLine } from "@models" import { UpdateLineItemDTO } from "@types" import { joinerConfig } from "../joiner-config" import * as services from "../services" @@ -527,4 +531,184 @@ export default class CartModuleService implements ICartModuleService { const addressIds = Array.isArray(ids) ? ids : [ids] await this.addressService_.delete(addressIds, sharedContext) } + + @InjectManager("baseRepository_") + async listLineItemTaxLines( + filters = {}, + config: FindConfig = {}, + @MedusaContext() sharedContext: Context = {} + ) { + const adjustments = await this.lineItemAdjustmentService_.list( + filters, + config, + sharedContext + ) + + return await this.baseRepository_.serialize( + adjustments, + { + populate: true, + } + ) + } + + addLineItemTaxLines( + taxLines: CreateLineItemTaxLineDTO[] + ): Promise + addLineItemTaxLines( + taxLine: CreateLineItemTaxLineDTO + ): Promise + addLineItemTaxLines( + cartId: string, + taxLines: CreateLineItemTaxLineDTO[], + sharedContext?: Context + ): Promise + + @InjectTransactionManager("baseRepository_") + async addLineItemTaxLines( + cartIdOrData: + | string + | CartTypes.CreateLineItemTaxLineDTO[] + | CartTypes.CreateLineItemTaxLineDTO, + taxLines?: CartTypes.CreateLineItemTaxLineDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + let addedTaxLines: LineItemTaxLine[] = [] + if (isString(cartIdOrData)) { + const cart = await this.retrieve( + cartIdOrData, + { select: ["id"], relations: ["items"] }, + sharedContext + ) + + const lineIds = cart.items?.map((item) => item.id) + + for (const taxLine of taxLines || []) { + if (!lineIds?.includes(taxLine.item_id)) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Line item with id ${taxLine.item_id} does not exist on cart with id ${cartIdOrData}` + ) + } + } + + addedTaxLines = await this.lineItemTaxLineService_.create( + taxLines as CartTypes.CreateLineItemTaxLineDTO[], + sharedContext + ) + } else { + const data = Array.isArray(cartIdOrData) ? cartIdOrData : [cartIdOrData] + + addedTaxLines = await this.lineItemTaxLineService_.create( + data as CartTypes.CreateLineItemTaxLineDTO[], + sharedContext + ) + } + + return await this.baseRepository_.serialize( + addedTaxLines, + { + populate: true, + } + ) + } + + @InjectTransactionManager("baseRepository_") + async setLineItemTaxLines( + cartId: string, + taxLines: (CreateLineItemTaxLineDTO | UpdateLineItemTaxLineDTO)[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + const cart = await this.retrieve( + cartId, + { select: ["id"], relations: ["items.tax_lines"] }, + sharedContext + ) + + const lineIds = cart.items?.map((item) => item.id) + + const existingTaxLines = await this.listLineItemTaxLines( + { item_id: lineIds }, + { select: ["id"] }, + sharedContext + ) + + let toUpdate: UpdateLineItemTaxLineDTO[] = [] + let toCreate: CreateLineItemTaxLineDTO[] = [] + for (const taxLine of taxLines) { + if ("id" in taxLine) { + toUpdate.push(taxLine as UpdateLineItemTaxLineDTO) + } else { + toCreate.push(taxLine as CreateLineItemTaxLineDTO) + } + } + + const taxLinesSet = new Set(toUpdate.map((a) => a.id)) + + const toDelete: LineItemTaxLineDTO[] = [] + + // From the existing tax lines, find the ones that are not passed in taxLines + existingTaxLines.forEach((taxLine: LineItemTaxLineDTO) => { + if (!taxLinesSet.has(taxLine.id)) { + toDelete.push(taxLine) + } + }) + + await this.lineItemTaxLineService.delete( + toDelete.map((adj) => adj!.id), + sharedContext + ) + + const [result] = await promiseAll([ + this.lineItemTaxLineService.create(toCreate, sharedContext), + this.lineItemTaxLineService.update(toUpdate, sharedContext), + ]) + + return await this.baseRepository_.serialize( + result, + { + populate: true, + } + ) + } + + removeLineItemTaxLines( + taxLineIds: string[], + sharedContext?: Context + ): Promise + removeLineItemTaxLines( + taxLineIds: string, + sharedContext?: Context + ): Promise + removeLineItemTaxLines( + selector: Partial, + sharedContext?: Context + ): Promise + + async removeLineItemTaxLines( + taxLineIdsOrSelector: + | string + | string[] + | Partial, + @MedusaContext() sharedContext: Context = {} + ): Promise { + let ids: string[] = [] + if (isObject(taxLineIdsOrSelector)) { + const taxLines = await this.listLineItemTaxLines( + { + ...taxLineIdsOrSelector, + } as Partial, + { select: ["id"] }, + sharedContext + ) + + ids = taxLines.map((adj) => adj.id) + } else { + ids = Array.isArray(taxLineIdsOrSelector) + ? taxLineIdsOrSelector + : [taxLineIdsOrSelector] + } + + await this.lineItemTaxLinesService_.delete(ids, sharedContext) + } } diff --git a/packages/types/src/cart/service.ts b/packages/types/src/cart/service.ts index 9f7f413acc3ff..e2899acf8bf4c 100644 --- a/packages/types/src/cart/service.ts +++ b/packages/types/src/cart/service.ts @@ -7,15 +7,18 @@ import { CartLineItemDTO, FilterableAddressProps, FilterableCartProps, + LineItemTaxLineDTO, } from "./common" import { CreateAddressDTO, CreateCartDTO, CreateLineItemDTO, CreateLineItemForCartDTO, + CreateLineItemTaxLineDTO, UpdateAddressDTO, UpdateCartDTO, UpdateLineItemDTO, + UpdateLineItemTaxLineDTO, UpdateLineItemWithSelectorDTO, } from "./mutations" @@ -102,4 +105,41 @@ export interface ICartModuleService extends IModuleService { selector: Partial, sharedContext?: Context ): Promise + + listLineItemTaxLines( + filters: any, + config?: FindConfig, + sharedContext?: Context + ): Promise + + addLineItemTaxLines( + taxLines: CreateLineItemTaxLineDTO[] + ): Promise + addLineItemTaxLines( + taxLine: CreateLineItemTaxLineDTO + ): Promise + addLineItemTaxLines( + cartId: string, + taxLines: CreateLineItemTaxLineDTO[], + sharedContext?: Context + ): Promise + + setLineItemTaxLines( + cartId: string, + taxLines: (CreateLineItemTaxLineDTO | UpdateLineItemTaxLineDTO)[], + sharedContext?: Context + ): Promise + + removeLineItemTaxLines( + taxLineIds: string[], + sharedContext?: Context + ): Promise + removeLineItemTaxLines( + taxLineIds: string, + sharedContext?: Context + ): Promise + removeLineItemTaxLines( + selector: Partial, + sharedContext?: Context + ): Promise } From a3ea1baec0dccddf1e4fafbc44ceba9456d56548 Mon Sep 17 00:00:00 2001 From: olivermrbl Date: Thu, 18 Jan 2024 09:39:08 +0100 Subject: [PATCH 2/8] shipping method tax lines --- packages/cart/src/services/cart-module.ts | 226 +++++++++++++++++++--- packages/types/src/cart/mutations.ts | 17 ++ packages/types/src/cart/service.ts | 40 ++++ 3 files changed, 260 insertions(+), 23 deletions(-) diff --git a/packages/cart/src/services/cart-module.ts b/packages/cart/src/services/cart-module.ts index 75be9f4690cd1..b8c2dc7c3d2ad 100644 --- a/packages/cart/src/services/cart-module.ts +++ b/packages/cart/src/services/cart-module.ts @@ -1,14 +1,11 @@ import { Context, - CreateLineItemTaxLineDTO, DAL, FilterableCartProps, FindConfig, ICartModuleService, InternalModuleDeclaration, - LineItemTaxLineDTO, ModuleJoinerConfig, - UpdateLineItemTaxLineDTO, } from "@medusajs/types" import { CartTypes } from "@medusajs/types" @@ -21,7 +18,7 @@ import { isObject, isString, } from "@medusajs/utils" -import { LineItem, LineItemTaxLine } from "@models" +import { LineItem, LineItemTaxLine, ShippingMethodTaxLine } from "@models" import { UpdateLineItemDTO } from "@types" import { joinerConfig } from "../joiner-config" import * as services from "../services" @@ -538,14 +535,14 @@ export default class CartModuleService implements ICartModuleService { config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ) { - const adjustments = await this.lineItemAdjustmentService_.list( + const taxLines = await this.lineItemTaxLineService_.list( filters, config, sharedContext ) return await this.baseRepository_.serialize( - adjustments, + taxLines, { populate: true, } @@ -553,16 +550,16 @@ export default class CartModuleService implements ICartModuleService { } addLineItemTaxLines( - taxLines: CreateLineItemTaxLineDTO[] - ): Promise + taxLines: CartTypes.CreateLineItemTaxLineDTO[] + ): Promise addLineItemTaxLines( - taxLine: CreateLineItemTaxLineDTO - ): Promise + taxLine: CartTypes.CreateLineItemTaxLineDTO + ): Promise addLineItemTaxLines( cartId: string, - taxLines: CreateLineItemTaxLineDTO[], + taxLines: CartTypes.CreateLineItemTaxLineDTO[], sharedContext?: Context - ): Promise + ): Promise @InjectTransactionManager("baseRepository_") async addLineItemTaxLines( @@ -616,7 +613,10 @@ export default class CartModuleService implements ICartModuleService { @InjectTransactionManager("baseRepository_") async setLineItemTaxLines( cartId: string, - taxLines: (CreateLineItemTaxLineDTO | UpdateLineItemTaxLineDTO)[], + taxLines: ( + | CartTypes.CreateLineItemTaxLineDTO + | CartTypes.UpdateLineItemTaxLineDTO + )[], @MedusaContext() sharedContext: Context = {} ): Promise { const cart = await this.retrieve( @@ -633,29 +633,29 @@ export default class CartModuleService implements ICartModuleService { sharedContext ) - let toUpdate: UpdateLineItemTaxLineDTO[] = [] - let toCreate: CreateLineItemTaxLineDTO[] = [] + let toUpdate: CartTypes.pdateLineItemTaxLineDTO[] = [] + let toCreate: CartTypes.CreateLineItemTaxLineDTO[] = [] for (const taxLine of taxLines) { if ("id" in taxLine) { - toUpdate.push(taxLine as UpdateLineItemTaxLineDTO) + toUpdate.push(taxLine as CartTypes.UpdateLineItemTaxLineDTO) } else { - toCreate.push(taxLine as CreateLineItemTaxLineDTO) + toCreate.push(taxLine as CartTypes.CreateLineItemTaxLineDTO) } } - const taxLinesSet = new Set(toUpdate.map((a) => a.id)) + const taxLinesSet = new Set(toUpdate.map((taxLine) => taxLine.id)) - const toDelete: LineItemTaxLineDTO[] = [] + const toDelete: CartTypes.LineItemTaxLineDTO[] = [] // From the existing tax lines, find the ones that are not passed in taxLines - existingTaxLines.forEach((taxLine: LineItemTaxLineDTO) => { + existingTaxLines.forEach((taxLine: CartTypes.LineItemTaxLineDTO) => { if (!taxLinesSet.has(taxLine.id)) { toDelete.push(taxLine) } }) await this.lineItemTaxLineService.delete( - toDelete.map((adj) => adj!.id), + toDelete.map((taxLine) => taxLine!.id), sharedContext ) @@ -681,7 +681,7 @@ export default class CartModuleService implements ICartModuleService { sharedContext?: Context ): Promise removeLineItemTaxLines( - selector: Partial, + selector: Partial, sharedContext?: Context ): Promise @@ -702,7 +702,7 @@ export default class CartModuleService implements ICartModuleService { sharedContext ) - ids = taxLines.map((adj) => adj.id) + ids = taxLines.map((taxLine) => taxLine.id) } else { ids = Array.isArray(taxLineIdsOrSelector) ? taxLineIdsOrSelector @@ -711,4 +711,184 @@ export default class CartModuleService implements ICartModuleService { await this.lineItemTaxLinesService_.delete(ids, sharedContext) } + + @InjectManager("baseRepository_") + async listShippingMethodTaxLines( + filters = {}, + config: FindConfig = {}, + @MedusaContext() sharedContext: Context = {} + ) { + const taxLines = await this.shippingMethodTaxLineService_.list( + filters, + config, + sharedContext + ) + + return await this.baseRepository_.serialize< + CartTypes.ShippingMethodTaxLineDTO[] + >(taxLines, { + populate: true, + }) + } + + addShippingMethodTaxLines( + taxLines: CartTypes.CreateShippingMethodTaxLineDTO[] + ): Promise + addShippingMethodTaxLines( + taxLine: CartTypes.CreateShippingMethodTaxLineDTO + ): Promise + addShippingMethodTaxLines( + cartId: string, + taxLines: CartTypes.CreateShippingMethodTaxLineDTO[], + sharedContext?: Context + ): Promise + + @InjectTransactionManager("baseRepository_") + async addShippingMethodTaxLines( + cartIdOrData: + | string + | CartTypes.CreateShippingMethodTaxLineDTO[] + | CartTypes.CreateShippingMethodTaxLineDTO, + taxLines?: CartTypes.CreateShippingMethodTaxLineDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + let addedTaxLines: ShippingMethodTaxLine[] = [] + if (isString(cartIdOrData)) { + const cart = await this.retrieve( + cartIdOrData, + { select: ["id"], relations: ["shipping_methods"] }, + sharedContext + ) + + const methodIds = cart.shipping_methods?.map((method) => method.id) + + for (const taxLine of taxLines || []) { + if (!methodIds?.includes(taxLine.shipping_method_id)) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Shipping method with id ${taxLine.shipping_method_id} does not exist on cart with id ${cartIdOrData}` + ) + } + } + + addedTaxLines = await this.shippingMethodTaxLineService_.create( + taxLines as CartTypes.CreateShippingMethodTaxLineDTO[], + sharedContext + ) + } else { + const data = Array.isArray(cartIdOrData) ? cartIdOrData : [cartIdOrData] + + addedTaxLines = await this.shippingMethodTaxLineService_.create( + data as CartTypes.CreateShippingMethodTaxLineDTO[], + sharedContext + ) + } + + return await this.baseRepository_.serialize< + CartTypes.ShippingMethodTaxLineDTO[] + >(addedTaxLines, { + populate: true, + }) + } + + @InjectTransactionManager("baseRepository_") + async setShippingMethodTaxLines( + cartId: string, + taxLines: ( + | CartTypes.CreateShippingMethodTaxLineDTO + | CartTypes.UpdateShippingMethodTaxLineDTO + )[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + const cart = await this.retrieve( + cartId, + { select: ["id"], relations: ["shipping_methods.tax_lines"] }, + sharedContext + ) + + const methodIds = cart.shipping_methods?.map((method) => method.id) + + const existingTaxLines = await this.listShippingMethodTaxLines( + { shipping_method_id: methodIds }, + { select: ["id"] }, + sharedContext + ) + + let toUpdate: CartTypes.UpdateShippingMethodTaxLineDTO[] = [] + let toCreate: CartTypes.CreateShippingMethodTaxLineDTO[] = [] + for (const taxLine of taxLines) { + if ("id" in taxLine) { + toUpdate.push(taxLine as CartTypes.UpdateShippingMethodTaxLineDTO) + } else { + toCreate.push(taxLine as CartTypes.CreateShippingMethodTaxLineDTO) + } + } + + const taxLinesSet = new Set(toUpdate.map((taxLine) => taxLine.id)) + + const toDelete: CartTypes.ShippingMethodTaxLineDTO[] = [] + + // From the existing tax lines, find the ones that are not passed in taxLines + existingTaxLines.forEach((taxLine: CartTypes.ShippingMethodTaxLineDTO) => { + if (!taxLinesSet.has(taxLine.id)) { + toDelete.push(taxLine) + } + }) + + await this.shippingMethodTaxLineService.delete( + toDelete.map((taxLine) => taxLine!.id), + sharedContext + ) + + const [result] = await promiseAll([ + this.shippingMethodTaxLineService.create(toCreate, sharedContext), + this.shippingMethodTaxLineService.update(toUpdate, sharedContext), + ]) + + return await this.baseRepository_.serialize< + CartTypes.ShippingMethodTaxLineDTO[] + >(result, { + populate: true, + }) + } + + removeShippingMethodTaxLines( + taxLineIds: string[], + sharedContext?: Context + ): Promise + removeShippingMethodTaxLines( + taxLineIds: string, + sharedContext?: Context + ): Promise + removeShippingMethodTaxLines( + selector: Partial, + sharedContext?: Context + ): Promise + + async removeShippingMethodTaxLines( + taxLineIdsOrSelector: + | string + | string[] + | Partial, + @MedusaContext() sharedContext: Context = {} + ): Promise { + let ids: string[] = [] + if (isObject(taxLineIdsOrSelector)) { + const taxLines = await this.listShippingMethodTaxLines( + { + ...taxLineIdsOrSelector, + } as Partial, + { select: ["id"] }, + sharedContext + ) + + ids = taxLines.map((taxLine) => taxLine.id) + } else { + ids = Array.isArray(taxLineIdsOrSelector) + ? taxLineIdsOrSelector + : [taxLineIdsOrSelector] + } + + await this.shippingMethodTaxLinesService_.delete(ids, sharedContext) + } } diff --git a/packages/types/src/cart/mutations.ts b/packages/types/src/cart/mutations.ts index f128d819c911c..717165694ba99 100644 --- a/packages/types/src/cart/mutations.ts +++ b/packages/types/src/cart/mutations.ts @@ -56,6 +56,23 @@ export interface UpdateCartDTO { metadata?: Record } +export interface CreateShippingMethodTaxLineDTO { + description?: string + tax_rate_id?: string + code: string + rate: number + provider_id?: string +} + +export interface UpdateShippingMethodTaxLineDTO { + id: string + description?: string + tax_rate_id?: string + code?: string + rate?: number + provider_id?: string +} + export interface CreateLineItemTaxLineDTO { description?: string tax_rate_id?: string diff --git a/packages/types/src/cart/service.ts b/packages/types/src/cart/service.ts index e2899acf8bf4c..18c0b95b27098 100644 --- a/packages/types/src/cart/service.ts +++ b/packages/types/src/cart/service.ts @@ -8,6 +8,7 @@ import { FilterableAddressProps, FilterableCartProps, LineItemTaxLineDTO, + ShippingMethodTaxLineDTO, } from "./common" import { CreateAddressDTO, @@ -15,11 +16,13 @@ import { CreateLineItemDTO, CreateLineItemForCartDTO, CreateLineItemTaxLineDTO, + CreateShippingMethodTaxLineDTO, UpdateAddressDTO, UpdateCartDTO, UpdateLineItemDTO, UpdateLineItemTaxLineDTO, UpdateLineItemWithSelectorDTO, + UpdateShippingMethodTaxLineDTO, } from "./mutations" export interface ICartModuleService extends IModuleService { @@ -142,4 +145,41 @@ export interface ICartModuleService extends IModuleService { selector: Partial, sharedContext?: Context ): Promise + + listShippingMethodTaxLines( + filters: any, + config?: FindConfig, + sharedContext?: Context + ): Promise + + addShippingMethodTaxLines( + taxLines: CreateShippingMethodTaxLineDTO[] + ): Promise + addShippingMethodTaxLines( + taxLine: CreateShippingMethodTaxLineDTO + ): Promise + addShippingMethodTaxLines( + cartId: string, + taxLines: CreateShippingMethodTaxLineDTO[], + sharedContext?: Context + ): Promise + + setShippingMethodTaxLines( + cartId: string, + taxLines: (CreateShippingMethodTaxLineDTO | UpdateShippingMethodTaxLineDTO)[], + sharedContext?: Context + ): Promise + + removeShippingMethodTaxLines( + taxLineIds: string[], + sharedContext?: Context + ): Promise + removeShippingMethodTaxLines( + taxLineIds: string, + sharedContext?: Context + ): Promise + removeShippingMethodTaxLines( + selector: Partial, + sharedContext?: Context + ): Promise } From 2113fa24c19daf6456cb49b02790b07e66d6b4e5 Mon Sep 17 00:00:00 2001 From: olivermrbl Date: Thu, 18 Jan 2024 10:22:48 +0100 Subject: [PATCH 3/8] add item tax lines tests --- .../services/cart-module/index.spec.ts | 520 +++++++++++++++++- 1 file changed, 512 insertions(+), 8 deletions(-) diff --git a/packages/cart/integration-tests/__tests__/services/cart-module/index.spec.ts b/packages/cart/integration-tests/__tests__/services/cart-module/index.spec.ts index acbdd99435945..4d319bc97e3b0 100644 --- a/packages/cart/integration-tests/__tests__/services/cart-module/index.spec.ts +++ b/packages/cart/integration-tests/__tests__/services/cart-module/index.spec.ts @@ -466,12 +466,9 @@ describe("Cart Module Service", () => { expect(item.title).toBe("test") - const updatedItem = await service.updateLineItems( - item.id, - { - title: "test2", - } - ) + const updatedItem = await service.updateLineItems(item.id, { + title: "test2", + }) expect(updatedItem.title).toBe("test2") }) @@ -519,13 +516,13 @@ describe("Cart Module Service", () => { selector: { cart_id: createdCart.id }, data: { title: "changed-test", - } + }, }, { selector: { id: itemTwo!.id }, data: { title: "changed-other-test", - } + }, }, ]) @@ -603,4 +600,511 @@ describe("Cart Module Service", () => { expect(cart.items?.length).toBe(0) }) }) + + describe("setLineItemTaxLines", () => { + it("should set line item tax lines for a cart", async () => { + const [createdCart] = await service.create([ + { + currency_code: "eur", + }, + ]) + + const [itemOne] = await service.addLineItems(createdCart.id, [ + { + quantity: 1, + unit_price: 100, + title: "test", + }, + ]) + + const [itemTwo] = await service.addLineItems(createdCart.id, [ + { + quantity: 2, + unit_price: 200, + title: "test-2", + }, + ]) + + const adjustments = await service.setLineItemTaxLines(createdCart.id, [ + { + item_id: itemOne.id, + rate: 20, + code: "TX", + }, + { + item_id: itemTwo.id, + rate: 20, + code: "TX", + }, + ]) + + expect(adjustments).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + item_id: itemOne.id, + rate: 20, + code: "TX", + }), + expect.objectContaining({ + item_id: itemTwo.id, + rate: 20, + code: "TX", + }), + ]) + ) + }) + + it("should replace line item tax lines for a cart", async () => { + const [createdCart] = await service.create([ + { + currency_code: "eur", + }, + ]) + + const [itemOne] = await service.addLineItems(createdCart.id, [ + { + quantity: 1, + unit_price: 100, + title: "test", + }, + ]) + + const adjustments = await service.setLineItemTaxLines(createdCart.id, [ + { + item_id: itemOne.id, + rate: 20, + code: "TX", + }, + ]) + + expect(adjustments).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + item_id: itemOne.id, + rate: 20, + code: "TX", + }), + ]) + ) + + await service.setLineItemTaxLines(createdCart.id, [ + { + item_id: itemOne.id, + rate: 25, + code: "TX-2", + }, + ]) + + const cart = await service.retrieve(createdCart.id, { + relations: ["items.tax_lines"], + }) + + expect(cart.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: itemOne.id, + tax_lines: expect.arrayContaining([ + expect.objectContaining({ + item_id: itemOne.id, + rate: 20, + code: "TX", + }), + ]), + }), + ]) + ) + + expect(cart.items?.length).toBe(1) + expect(cart.items?.[0].tax_lines?.length).toBe(1) + }) + + it("should remove all line item tax lines for a cart", async () => { + const [createdCart] = await service.create([ + { + currency_code: "eur", + }, + ]) + + const [itemOne] = await service.addLineItems(createdCart.id, [ + { + quantity: 1, + unit_price: 100, + title: "test", + }, + ]) + + const adjustments = await service.setLineItemTaxLines(createdCart.id, [ + { + item_id: itemOne.id, + rate: 20, + code: "TX", + }, + ]) + + expect(adjustments).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + item_id: itemOne.id, + rate: 20, + code: "TX", + }), + ]) + ) + + await service.setLineItemTaxLines(createdCart.id, []) + + const cart = await service.retrieve(createdCart.id, { + relations: ["items.tax_lines"], + }) + + expect(cart.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: itemOne.id, + tax_lines: [], + }), + ]) + ) + + expect(cart.items?.length).toBe(1) + expect(cart.items?.[0].tax_lines?.length).toBe(0) + }) + + it("should update line item tax lines for a cart", async () => { + const [createdCart] = await service.create([ + { + currency_code: "eur", + }, + ]) + + const [itemOne] = await service.addLineItems(createdCart.id, [ + { + quantity: 1, + unit_price: 100, + title: "test", + }, + ]) + + const adjustments = await service.setLineItemTaxLines(createdCart.id, [ + { + item_id: itemOne.id, + rate: 20, + code: "TX", + }, + ]) + + expect(adjustments).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + item_id: itemOne.id, + rate: 20, + code: "TX", + }), + ]) + ) + + await service.setLineItemAdjustments(createdCart.id, [ + { + id: adjustments[0].id, + rate: 25, + code: "TX", + }, + ]) + + const cart = await service.retrieve(createdCart.id, { + relations: ["items.tax_lines"], + }) + + expect(cart.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: itemOne.id, + tax_lines: [ + expect.objectContaining({ + id: adjustments[0].id, + item_id: itemOne.id, + rate: 25, + code: "TX", + }), + ], + }), + ]) + ) + + expect(cart.items?.length).toBe(1) + expect(cart.items?.[0].tax_lines?.length).toBe(1) + }) + }) + + describe("addLineItemAdjustments", () => { + it("should add line item tax lines for items in a cart", async () => { + const [createdCart] = await service.create([ + { + currency_code: "eur", + }, + ]) + + const [itemOne] = await service.addLineItems(createdCart.id, [ + { + quantity: 1, + unit_price: 100, + title: "test", + }, + ]) + + const adjustments = await service.addLineItemTaxLines(createdCart.id, [ + { + item_id: itemOne.id, + rate: 20, + code: "TX", + }, + ]) + + expect(adjustments).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + item_id: itemOne.id, + rate: 20, + code: "TX", + }), + ]) + ) + }) + + it("should add multiple line item tax lines for multiple line items", async () => { + const [createdCart] = await service.create([ + { + currency_code: "eur", + }, + ]) + + const [itemOne] = await service.addLineItems(createdCart.id, [ + { + quantity: 1, + unit_price: 100, + title: "test", + }, + ]) + const [itemTwo] = await service.addLineItems(createdCart.id, [ + { + quantity: 2, + unit_price: 200, + title: "test-2", + }, + ]) + + const adjustments = await service.addLineItemTaxLines(createdCart.id, [ + { + item_id: itemOne.id, + rate: 20, + code: "TX", + }, + { + item_id: itemTwo.id, + rate: 20, + code: "TX", + }, + ]) + + expect(adjustments).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + item_id: itemOne.id, + rate: 20, + code: "TX", + }), + expect.objectContaining({ + item_id: itemTwo.id, + rate: 20, + code: "TX", + }), + ]) + ) + }) + + it("should add line item tax lines for line items on multiple carts", async () => { + const [cartOne] = await service.create([ + { + currency_code: "eur", + }, + ]) + const [cartTwo] = await service.create([ + { + currency_code: "usd", + }, + ]) + + const [itemOne] = await service.addLineItems(cartOne.id, [ + { + quantity: 1, + unit_price: 100, + title: "test", + }, + ]) + const [itemTwo] = await service.addLineItems(cartTwo.id, [ + { + quantity: 2, + unit_price: 200, + title: "test-2", + }, + ]) + + await service.addLineItemTaxLines([ + // item from cart one + { + item_id: itemOne.id, + rate: 20, + code: "TX", + }, + // item from cart two + { + item_id: itemTwo.id, + rate: 25, + code: "TX-2", + }, + ]) + + const cartOneItems = await service.listLineItems( + { cart_id: cartOne.id }, + { relations: ["tax_lines"] } + ) + const cartTwoItems = await service.listLineItems( + { cart_id: cartTwo.id }, + { relations: ["tax_lines"] } + ) + + expect(cartOneItems).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + adjustments: expect.arrayContaining([ + expect.objectContaining({ + item_id: itemOne.id, + rate: 20, + code: "TX", + }), + ]), + }), + ]) + ) + expect(cartTwoItems).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + adjustments: expect.arrayContaining([ + expect.objectContaining({ + item_id: itemTwo.id, + rate: 25, + code: "TX-2", + }), + ]), + }), + ]) + ) + }) + + it("should throw if line item is not associated with cart", async () => { + const [cartOne] = await service.create([ + { + currency_code: "eur", + }, + ]) + + const [cartTwo] = await service.create([ + { + currency_code: "eur", + }, + ]) + + const [itemOne] = await service.addLineItems(cartOne.id, [ + { + quantity: 1, + unit_price: 100, + title: "test", + }, + ]) + + const error = await service + .addLineItemTaxLines(cartTwo.id, [ + { + item_id: itemOne.id, + rate: 20, + code: "TX", + }, + ]) + .catch((e) => e) + + expect(error.message).toBe( + `Line item with id ${itemOne.id} does not exist on cart with id ${cartTwo.id}` + ) + }) + }) + + describe("removeLineItemAdjustments", () => { + it("should remove line item tax line succesfully", async () => { + const [createdCart] = await service.create([ + { + currency_code: "eur", + }, + ]) + + const [item] = await service.addLineItems(createdCart.id, [ + { + quantity: 1, + unit_price: 100, + title: "test", + }, + ]) + + const [adjustment] = await service.addLineItemTaxLines(createdCart.id, [ + { + item_id: item.id, + rate: 20, + code: "TX", + }, + ]) + + expect(adjustment.item_id).toBe(item.id) + + await service.removeLineItemTaxLines(adjustment.id) + + const taxLines = await service.listLineItemTaxLines({ + item_id: item.id, + }) + + expect(taxLines?.length).toBe(0) + }) + + it("should remove line item tax lines succesfully with selector", async () => { + const [createdCart] = await service.create([ + { + currency_code: "eur", + }, + ]) + + const [item] = await service.addLineItems(createdCart.id, [ + { + quantity: 1, + unit_price: 100, + title: "test", + }, + ]) + + const [taxLine] = await service.addLineItemTaxLines(createdCart.id, [ + { + item_id: item.id, + rate: 20, + code: "TX", + }, + ]) + + expect(taxLine.item_id).toBe(item.id) + + await service.removeLineItemTaxLines({ item_id: item.id }) + + const taxLines = await service.listLineItemTaxLines({ + item_id: item.id, + }) + + expect(taxLines?.length).toBe(0) + }) + }) }) From e8da707dfbce23b96a807fa6b1d2bcbd4689ac4d Mon Sep 17 00:00:00 2001 From: olivermrbl Date: Mon, 22 Jan 2024 12:03:18 +0100 Subject: [PATCH 4/8] fix types --- packages/types/src/cart/mutations.ts | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/types/src/cart/mutations.ts b/packages/types/src/cart/mutations.ts index cb4b79224c124..25d0dc71728d1 100644 --- a/packages/types/src/cart/mutations.ts +++ b/packages/types/src/cart/mutations.ts @@ -117,21 +117,13 @@ export interface UpdateTaxLineDTO { provider_id?: string } -export interface CreateShippingMethodTaxLineDTO extends CreateTaxLineDTO { - shipping_method_id: string -} +export interface CreateShippingMethodTaxLineDTO extends CreateTaxLineDTO {} -export interface UpdateShippingMethodTaxLineDTO extends UpdateTaxLineDTO { - shipping_method_id: string -} +export interface UpdateShippingMethodTaxLineDTO extends UpdateTaxLineDTO {} -export interface CreateLineItemTaxLineDTO extends CreateTaxLineDTO { - item_id: string -} +export interface CreateLineItemTaxLineDTO extends CreateTaxLineDTO {} -export interface UpdateLineItemTaxLineDTO extends UpdateTaxLineDTO { - item_id: string -} +export interface UpdateLineItemTaxLineDTO extends UpdateTaxLineDTO {} /** TAX LINES END */ From ed3ac0d8fb08549003135ba0df5f8691597373b1 Mon Sep 17 00:00:00 2001 From: olivermrbl Date: Mon, 22 Jan 2024 12:50:53 +0100 Subject: [PATCH 5/8] fix last things --- .../services/cart-module/index.spec.ts | 72 ------------------- packages/cart/src/services/cart-module.ts | 69 +++++++++--------- .../cart/src/services/line-item-tax-line.ts | 7 +- .../src/services/shipping-method-tax-line.ts | 6 +- packages/types/src/cart/common.ts | 20 ++++++ packages/types/src/cart/service.ts | 10 +-- 6 files changed, 65 insertions(+), 119 deletions(-) diff --git a/packages/cart/integration-tests/__tests__/services/cart-module/index.spec.ts b/packages/cart/integration-tests/__tests__/services/cart-module/index.spec.ts index d56949f9a1619..2465ec2efe646 100644 --- a/packages/cart/integration-tests/__tests__/services/cart-module/index.spec.ts +++ b/packages/cart/integration-tests/__tests__/services/cart-module/index.spec.ts @@ -1200,42 +1200,6 @@ describe("Cart Module Service", () => { ]) ) }) - - it("should throw if line item is not associated with cart", async () => { - const [cartOne] = await service.create([ - { - currency_code: "eur", - }, - ]) - - const [cartTwo] = await service.create([ - { - currency_code: "eur", - }, - ]) - - const [itemOne] = await service.addLineItems(cartOne.id, [ - { - quantity: 1, - unit_price: 100, - title: "test", - }, - ]) - - const error = await service - .addLineItemAdjustments(cartTwo.id, [ - { - item_id: itemOne.id, - amount: 100, - code: "FREE", - }, - ]) - .catch((e) => e) - - expect(error.message).toBe( - `Line item with id ${itemOne.id} does not exist on cart with id ${cartTwo.id}` - ) - }) }) describe("removeLineItemAdjustments", () => { @@ -2261,42 +2225,6 @@ describe("Cart Module Service", () => { ]) ) }) - - it("should throw if line item is not associated with cart", async () => { - const [cartOne] = await service.create([ - { - currency_code: "eur", - }, - ]) - - const [cartTwo] = await service.create([ - { - currency_code: "eur", - }, - ]) - - const [itemOne] = await service.addLineItems(cartOne.id, [ - { - quantity: 1, - unit_price: 100, - title: "test", - }, - ]) - - const error = await service - .addLineItemTaxLines(cartTwo.id, [ - { - item_id: itemOne.id, - rate: 20, - code: "TX", - }, - ]) - .catch((e) => e) - - expect(error.message).toBe( - `Line item with id ${itemOne.id} does not exist on cart with id ${cartTwo.id}` - ) - }) }) describe("removeLineItemAdjustments", () => { diff --git a/packages/cart/src/services/cart-module.ts b/packages/cart/src/services/cart-module.ts index 0d63c33369368..0aba88a1c1fe4 100644 --- a/packages/cart/src/services/cart-module.ts +++ b/packages/cart/src/services/cart-module.ts @@ -1114,7 +1114,7 @@ export default class CartModuleService implements ICartModuleService { @InjectManager("baseRepository_") async listLineItemTaxLines( - filters = {}, + filters: CartTypes.FilterableLineItemTaxLineProps = {}, config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ) { @@ -1137,7 +1137,7 @@ export default class CartModuleService implements ICartModuleService { ): Promise addLineItemTaxLines( taxLine: CartTypes.CreateLineItemTaxLineDTO - ): Promise + ): Promise addLineItemTaxLines( cartId: string, taxLines: CartTypes.CreateLineItemTaxLineDTO[], @@ -1152,25 +1152,11 @@ export default class CartModuleService implements ICartModuleService { | CartTypes.CreateLineItemTaxLineDTO, taxLines?: CartTypes.CreateLineItemTaxLineDTO[], @MedusaContext() sharedContext: Context = {} - ): Promise { + ): Promise { let addedTaxLines: LineItemTaxLine[] = [] if (isString(cartIdOrData)) { - const cart = await this.retrieve( - cartIdOrData, - { select: ["id"], relations: ["items"] }, - sharedContext - ) - - const lineIds = cart.items?.map((item) => item.id) - - for (const taxLine of taxLines || []) { - if (!lineIds?.includes(taxLine.item_id)) { - throw new MedusaError( - MedusaError.Types.INVALID_DATA, - `Line item with id ${taxLine.item_id} does not exist on cart with id ${cartIdOrData}` - ) - } - } + // existence check + await this.retrieve(cartIdOrData, { select: ["id"] }, sharedContext) addedTaxLines = await this.lineItemTaxLineService_.create( taxLines as CartTypes.CreateLineItemTaxLineDTO[], @@ -1185,6 +1171,15 @@ export default class CartModuleService implements ICartModuleService { ) } + if (isObject(cartIdOrData)) { + return await this.baseRepository_.serialize( + addedTaxLines[0], + { + populate: true, + } + ) + } + return await this.baseRepository_.serialize( addedTaxLines, { @@ -1297,7 +1292,7 @@ export default class CartModuleService implements ICartModuleService { @InjectManager("baseRepository_") async listShippingMethodTaxLines( - filters = {}, + filters: CartTypes.FilterableShippingMethodTaxLineProps = {}, config: FindConfig = {}, @MedusaContext() sharedContext: Context = {} ) { @@ -1319,7 +1314,7 @@ export default class CartModuleService implements ICartModuleService { ): Promise addShippingMethodTaxLines( taxLine: CartTypes.CreateShippingMethodTaxLineDTO - ): Promise + ): Promise addShippingMethodTaxLines( cartId: string, taxLines: CartTypes.CreateShippingMethodTaxLineDTO[], @@ -1334,25 +1329,18 @@ export default class CartModuleService implements ICartModuleService { | CartTypes.CreateShippingMethodTaxLineDTO, taxLines?: CartTypes.CreateShippingMethodTaxLineDTO[], @MedusaContext() sharedContext: Context = {} - ): Promise { + ): Promise< + CartTypes.ShippingMethodTaxLineDTO[] | CartTypes.ShippingMethodTaxLineDTO + > { let addedTaxLines: ShippingMethodTaxLine[] = [] if (isString(cartIdOrData)) { - const cart = await this.retrieve( - cartIdOrData, - { select: ["id"], relations: ["shipping_methods"] }, + // existence check + await this.retrieve(cartIdOrData, { select: ["id"] }, sharedContext) + + addedTaxLines = await this.shippingMethodTaxLineService_.create( + taxLines as CartTypes.CreateShippingMethodTaxLineDTO[], sharedContext ) - - const methodIds = cart.shipping_methods?.map((method) => method.id) - - for (const taxLine of taxLines || []) { - if (!methodIds?.includes(taxLine.shipping_method_id)) { - throw new MedusaError( - MedusaError.Types.INVALID_DATA, - `Shipping method with id ${taxLine.shipping_method_id} does not exist on cart with id ${cartIdOrData}` - ) - } - } } else { addedTaxLines = await this.shippingMethodTaxLineService_.create( taxLines as CartTypes.CreateShippingMethodTaxLineDTO[], @@ -1360,6 +1348,15 @@ export default class CartModuleService implements ICartModuleService { ) } + if (isObject(cartIdOrData)) { + return await this.baseRepository_.serialize( + addedTaxLines[0], + { + populate: true, + } + ) + } + return await this.baseRepository_.serialize< CartTypes.ShippingMethodTaxLineDTO[] >(addedTaxLines, {}) diff --git a/packages/cart/src/services/line-item-tax-line.ts b/packages/cart/src/services/line-item-tax-line.ts index 4df12924379a4..a740fae4366d1 100644 --- a/packages/cart/src/services/line-item-tax-line.ts +++ b/packages/cart/src/services/line-item-tax-line.ts @@ -1,7 +1,10 @@ -import { DAL } from "@medusajs/types" +import { + CreateLineItemTaxLineDTO, + DAL, + UpdateLineItemTaxLineDTO, +} from "@medusajs/types" import { ModulesSdkUtils } from "@medusajs/utils" import { LineItemTaxLine } from "@models" -import { CreateLineItemTaxLineDTO, UpdateLineItemTaxLineDTO } from "@types" type InjectedDependencies = { lineItemTaxLineRepository: DAL.RepositoryService diff --git a/packages/cart/src/services/shipping-method-tax-line.ts b/packages/cart/src/services/shipping-method-tax-line.ts index 5ac2d141ad4ac..9229d6556717b 100644 --- a/packages/cart/src/services/shipping-method-tax-line.ts +++ b/packages/cart/src/services/shipping-method-tax-line.ts @@ -1,10 +1,6 @@ -import { DAL } from "@medusajs/types" +import { CreateShippingMethodTaxLineDTO, DAL, UpdateShippingMethodTaxLineDTO } from "@medusajs/types" import { ModulesSdkUtils } from "@medusajs/utils" import { ShippingMethodTaxLine } from "@models" -import { - CreateShippingMethodTaxLineDTO, - UpdateShippingMethodTaxLineDTO, -} from "@types" type InjectedDependencies = { shippingMethodTaxLineRepository: DAL.RepositoryService diff --git a/packages/types/src/cart/common.ts b/packages/types/src/cart/common.ts index 61cdd40d896fd..729b0d4da63a2 100644 --- a/packages/types/src/cart/common.ts +++ b/packages/types/src/cart/common.ts @@ -538,6 +538,26 @@ export interface FilterableShippingMethodAdjustmentProps provider_id?: string | string[] } +export interface FilterableLineItemTaxLineProps + extends BaseFilterable { + id?: string | string[] + description?: string + code?: string | string[] + tax_rate_id?: string | string[] + provider_id?: string | string[] + item_id?: string | string[] +} + +export interface FilterableShippingMethodTaxLineProps + extends BaseFilterable { + id?: string | string[] + description?: string + code?: string | string[] + tax_rate_id?: string | string[] + provider_id?: string | string[] + shipping_method_id?: string | string[] +} + /** * TODO: Remove this in favor of CartDTO, when module is released * @deprecated Use CartDTO instead diff --git a/packages/types/src/cart/service.ts b/packages/types/src/cart/service.ts index 470415b89f214..c79c8250ed49b 100644 --- a/packages/types/src/cart/service.ts +++ b/packages/types/src/cart/service.ts @@ -10,8 +10,10 @@ import { FilterableCartProps, FilterableLineItemAdjustmentProps, FilterableLineItemProps, + FilterableLineItemTaxLineProps, FilterableShippingMethodAdjustmentProps, FilterableShippingMethodProps, + FilterableShippingMethodTaxLineProps, LineItemAdjustmentDTO, LineItemTaxLineDTO, ShippingMethodAdjustmentDTO, @@ -242,7 +244,7 @@ export interface ICartModuleService extends IModuleService { ): Promise listLineItemTaxLines( - filters: any, + filters: FilterableLineItemTaxLineProps, config?: FindConfig, sharedContext?: Context ): Promise @@ -252,7 +254,7 @@ export interface ICartModuleService extends IModuleService { ): Promise addLineItemTaxLines( taxLine: CreateLineItemTaxLineDTO - ): Promise + ): Promise addLineItemTaxLines( cartId: string, taxLines: CreateLineItemTaxLineDTO[], @@ -279,7 +281,7 @@ export interface ICartModuleService extends IModuleService { ): Promise listShippingMethodTaxLines( - filters: any, + filters: FilterableShippingMethodTaxLineProps, config?: FindConfig, sharedContext?: Context ): Promise @@ -289,7 +291,7 @@ export interface ICartModuleService extends IModuleService { ): Promise addShippingMethodTaxLines( taxLine: CreateShippingMethodTaxLineDTO - ): Promise + ): Promise addShippingMethodTaxLines( cartId: string, taxLines: CreateShippingMethodTaxLineDTO[], From b323a121dfa3ef432dbb6c9d53fef394f3f85524 Mon Sep 17 00:00:00 2001 From: olivermrbl Date: Tue, 23 Jan 2024 20:55:34 +0100 Subject: [PATCH 6/8] address PR comments --- .../services/cart-module/index.spec.ts | 90 ++++++++++++++ .../cart/src/models/line-item-tax-line.ts | 2 +- .../src/models/shipping-method-tax-line.ts | 2 +- packages/cart/src/services/cart-module.ts | 116 ++++++++---------- packages/types/src/cart/common.ts | 2 +- packages/types/src/cart/service.ts | 4 +- 6 files changed, 146 insertions(+), 70 deletions(-) diff --git a/packages/cart/integration-tests/__tests__/services/cart-module/index.spec.ts b/packages/cart/integration-tests/__tests__/services/cart-module/index.spec.ts index 2465ec2efe646..fc6a2033a134e 100644 --- a/packages/cart/integration-tests/__tests__/services/cart-module/index.spec.ts +++ b/packages/cart/integration-tests/__tests__/services/cart-module/index.spec.ts @@ -2059,6 +2059,96 @@ describe("Cart Module Service", () => { expect(cart.items?.length).toBe(1) expect(cart.items?.[0].tax_lines?.length).toBe(1) }) + + it("should remove, update, and create line item tax lines for a cart", async () => { + const [createdCart] = await service.create([ + { + currency_code: "eur", + }, + ]) + + const [itemOne] = await service.addLineItems(createdCart.id, [ + { + quantity: 1, + unit_price: 100, + title: "test", + }, + ]) + + const taxLines = await service.setLineItemTaxLines(createdCart.id, [ + { + item_id: itemOne.id, + rate: 20, + code: "TX", + }, + { + item_id: itemOne.id, + rate: 25, + code: "TX", + }, + ]) + + expect(taxLines).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + item_id: itemOne.id, + rate: 20, + code: "TX", + }), + expect.objectContaining({ + item_id: itemOne.id, + rate: 25, + code: "TX", + }), + ]) + ) + + const taxLine = taxLines.find((tx) => tx.item_id === itemOne.id) + + await service.setLineItemTaxLines(createdCart.id, [ + // update + { + id: taxLine.id, + rate: 40, + code: "TX", + }, + // create + { + item_id: itemOne.id, + rate: 25, + code: "TX-2", + }, + // remove: should remove the initial tax line for itemOne + ]) + + const cart = await service.retrieve(createdCart.id, { + relations: ["items.tax_lines"], + }) + + expect(cart.items).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: itemOne.id, + tax_lines: [ + expect.objectContaining({ + id: taxLine!.id, + item_id: itemOne.id, + rate: 40, + code: "TX", + }), + expect.objectContaining({ + item_id: itemOne.id, + rate: 25, + code: "TX-2", + }), + ], + }), + ]) + ) + + expect(cart.items?.length).toBe(1) + expect(cart.items?.[0].tax_lines?.length).toBe(2) + }) }) describe("addLineItemAdjustments", () => { diff --git a/packages/cart/src/models/line-item-tax-line.ts b/packages/cart/src/models/line-item-tax-line.ts index 2d9a3f8c771bb..149d767fec51a 100644 --- a/packages/cart/src/models/line-item-tax-line.ts +++ b/packages/cart/src/models/line-item-tax-line.ts @@ -16,7 +16,7 @@ export default class LineItemTaxLine extends TaxLine { nullable: true, index: "IDX_tax_line_item_id", }) - item?: LineItem | null + item: LineItem | null @Property({ columnType: "text" }) item_id: string diff --git a/packages/cart/src/models/shipping-method-tax-line.ts b/packages/cart/src/models/shipping-method-tax-line.ts index a506f3d707440..e5a022ab78daf 100644 --- a/packages/cart/src/models/shipping-method-tax-line.ts +++ b/packages/cart/src/models/shipping-method-tax-line.ts @@ -16,7 +16,7 @@ export default class ShippingMethodTaxLine extends TaxLine { nullable: true, index: "IDX_tax_line_shipping_method_id", }) - shipping_method?: ShippingMethod | null + shipping_method: ShippingMethod | null @Property({ columnType: "text" }) shipping_method_id: string diff --git a/packages/cart/src/services/cart-module.ts b/packages/cart/src/services/cart-module.ts index 0aba88a1c1fe4..4d067356b7f9a 100644 --- a/packages/cart/src/services/cart-module.ts +++ b/packages/cart/src/services/cart-module.ts @@ -2,6 +2,7 @@ import { CartTypes, Context, DAL, + FilterableLineItemTaxLineProps, FindConfig, ICartModuleService, InternalModuleDeclaration, @@ -14,7 +15,6 @@ import { MedusaError, isObject, isString, - promiseAll, } from "@medusajs/utils" import { Cart, @@ -1140,7 +1140,9 @@ export default class CartModuleService implements ICartModuleService { ): Promise addLineItemTaxLines( cartId: string, - taxLines: CartTypes.CreateLineItemTaxLineDTO[], + taxLines: + | CartTypes.CreateLineItemTaxLineDTO[] + | CartTypes.CreateShippingMethodTaxLineDTO, sharedContext?: Context ): Promise @@ -1150,7 +1152,9 @@ export default class CartModuleService implements ICartModuleService { | string | CartTypes.CreateLineItemTaxLineDTO[] | CartTypes.CreateLineItemTaxLineDTO, - taxLines?: CartTypes.CreateLineItemTaxLineDTO[], + taxLines?: + | CartTypes.CreateLineItemTaxLineDTO[] + | CartTypes.CreateLineItemTaxLineDTO, @MedusaContext() sharedContext: Context = {} ): Promise { let addedTaxLines: LineItemTaxLine[] = [] @@ -1158,8 +1162,10 @@ export default class CartModuleService implements ICartModuleService { // existence check await this.retrieve(cartIdOrData, { select: ["id"] }, sharedContext) + const lines = Array.isArray(taxLines) ? taxLines : [taxLines] + addedTaxLines = await this.lineItemTaxLineService_.create( - taxLines as CartTypes.CreateLineItemTaxLineDTO[], + lines, sharedContext ) } else { @@ -1171,21 +1177,17 @@ export default class CartModuleService implements ICartModuleService { ) } + const serialized = await this.baseRepository_.serialize< + CartTypes.LineItemTaxLineDTO[] + >(addedTaxLines, { + populate: true, + }) + if (isObject(cartIdOrData)) { - return await this.baseRepository_.serialize( - addedTaxLines[0], - { - populate: true, - } - ) + return serialized[0] } - return await this.baseRepository_.serialize( - addedTaxLines, - { - populate: true, - } - ) + return serialized } @InjectTransactionManager("baseRepository_") @@ -1203,25 +1205,15 @@ export default class CartModuleService implements ICartModuleService { sharedContext ) - const lineIds = cart.items?.map((item) => item.id) - const existingTaxLines = await this.listLineItemTaxLines( - { item_id: lineIds }, + { item: { cart_id: cart.id } }, { select: ["id"] }, sharedContext ) - let toUpdate: CartTypes.UpdateLineItemTaxLineDTO[] = [] - let toCreate: CartTypes.CreateLineItemTaxLineDTO[] = [] - for (const taxLine of taxLines) { - if ("id" in taxLine) { - toUpdate.push(taxLine as CartTypes.UpdateLineItemTaxLineDTO) - } else { - toCreate.push(taxLine as CartTypes.CreateLineItemTaxLineDTO) - } - } - - const taxLinesSet = new Set(toUpdate.map((taxLine) => taxLine.id)) + const taxLinesSet = new Set( + taxLines.map((taxLine) => taxLine.id).filter(Boolean) + ) const toDelete: CartTypes.LineItemTaxLineDTO[] = [] @@ -1237,10 +1229,10 @@ export default class CartModuleService implements ICartModuleService { sharedContext ) - const [result] = await promiseAll([ - this.lineItemTaxLineService_.create(toCreate, sharedContext), - this.lineItemTaxLineService_.update(toUpdate, sharedContext), - ]) + const result = await this.lineItemTaxLineService_.upsert( + taxLines, + sharedContext + ) return await this.baseRepository_.serialize( result, @@ -1259,7 +1251,7 @@ export default class CartModuleService implements ICartModuleService { sharedContext?: Context ): Promise removeLineItemTaxLines( - selector: Partial, + selector: FilterableLineItemTaxLineProps, sharedContext?: Context ): Promise @@ -1267,7 +1259,7 @@ export default class CartModuleService implements ICartModuleService { taxLineIdsOrSelector: | string | string[] - | Partial, + | CartTypes.FilterableShippingMethodTaxLineProps, @MedusaContext() sharedContext: Context = {} ): Promise { let ids: string[] = [] @@ -1275,7 +1267,7 @@ export default class CartModuleService implements ICartModuleService { const taxLines = await this.listLineItemTaxLines( { ...taxLineIdsOrSelector, - } as Partial, + }, { select: ["id"] }, sharedContext ) @@ -1317,7 +1309,9 @@ export default class CartModuleService implements ICartModuleService { ): Promise addShippingMethodTaxLines( cartId: string, - taxLines: CartTypes.CreateShippingMethodTaxLineDTO[], + taxLines: + | CartTypes.CreateShippingMethodTaxLineDTO[] + | CartTypes.CreateShippingMethodTaxLineDTO, sharedContext?: Context ): Promise @@ -1327,7 +1321,9 @@ export default class CartModuleService implements ICartModuleService { | string | CartTypes.CreateShippingMethodTaxLineDTO[] | CartTypes.CreateShippingMethodTaxLineDTO, - taxLines?: CartTypes.CreateShippingMethodTaxLineDTO[], + taxLines?: + | CartTypes.CreateShippingMethodTaxLineDTO[] + | CartTypes.CreateShippingMethodTaxLineDTO, @MedusaContext() sharedContext: Context = {} ): Promise< CartTypes.ShippingMethodTaxLineDTO[] | CartTypes.ShippingMethodTaxLineDTO @@ -1337,8 +1333,10 @@ export default class CartModuleService implements ICartModuleService { // existence check await this.retrieve(cartIdOrData, { select: ["id"] }, sharedContext) + const lines = Array.isArray(taxLines) ? taxLines : [taxLines] + addedTaxLines = await this.shippingMethodTaxLineService_.create( - taxLines as CartTypes.CreateShippingMethodTaxLineDTO[], + lines, sharedContext ) } else { @@ -1348,18 +1346,19 @@ export default class CartModuleService implements ICartModuleService { ) } - if (isObject(cartIdOrData)) { - return await this.baseRepository_.serialize( + const serialized = + await this.baseRepository_.serialize( addedTaxLines[0], { populate: true, } ) + + if (isObject(cartIdOrData)) { + return serialized[0] } - return await this.baseRepository_.serialize< - CartTypes.ShippingMethodTaxLineDTO[] - >(addedTaxLines, {}) + return serialized } @InjectTransactionManager("baseRepository_") @@ -1377,25 +1376,15 @@ export default class CartModuleService implements ICartModuleService { sharedContext ) - const methodIds = cart.shipping_methods?.map((method) => method.id) - const existingTaxLines = await this.listShippingMethodTaxLines( - { shipping_method_id: methodIds }, + { shipping_method: { cart_id: cart.id } }, { select: ["id"] }, sharedContext ) - let toUpdate: CartTypes.UpdateShippingMethodTaxLineDTO[] = [] - let toCreate: CartTypes.CreateShippingMethodTaxLineDTO[] = [] - for (const taxLine of taxLines) { - if ("id" in taxLine) { - toUpdate.push(taxLine as CartTypes.UpdateShippingMethodTaxLineDTO) - } else { - toCreate.push(taxLine as CartTypes.CreateShippingMethodTaxLineDTO) - } - } - - const taxLinesSet = new Set(toUpdate.map((taxLine) => taxLine.id)) + const taxLinesSet = new Set( + taxLines.map((taxLine) => taxLine.id).filter(Boolean) + ) const toDelete: CartTypes.ShippingMethodTaxLineDTO[] = [] @@ -1411,10 +1400,7 @@ export default class CartModuleService implements ICartModuleService { sharedContext ) - const [result] = await promiseAll([ - this.shippingMethodTaxLineService_.create(toCreate, sharedContext), - this.shippingMethodTaxLineService_.update(toUpdate, sharedContext), - ]) + const result = await this.lineItemTaxLineService_.upsert(taxLines) return await this.baseRepository_.serialize< CartTypes.ShippingMethodTaxLineDTO[] @@ -1440,7 +1426,7 @@ export default class CartModuleService implements ICartModuleService { taxLineIdsOrSelector: | string | string[] - | Partial, + | CartTypes.FilterableShippingMethodTaxLineProps, @MedusaContext() sharedContext: Context = {} ): Promise { let ids: string[] = [] @@ -1448,7 +1434,7 @@ export default class CartModuleService implements ICartModuleService { const taxLines = await this.listShippingMethodTaxLines( { ...taxLineIdsOrSelector, - } as Partial, + }, { select: ["id"] }, sharedContext ) diff --git a/packages/types/src/cart/common.ts b/packages/types/src/cart/common.ts index 729b0d4da63a2..2602e28bef13d 100644 --- a/packages/types/src/cart/common.ts +++ b/packages/types/src/cart/common.ts @@ -106,7 +106,7 @@ export interface ShippingMethodTaxLineDTO extends TaxLineDTO { /** * The ID of the associated shipping method */ - shipping_item_id: string + shipping_method_id: string } export interface LineItemTaxLineDTO extends TaxLineDTO { diff --git a/packages/types/src/cart/service.ts b/packages/types/src/cart/service.ts index c79c8250ed49b..955ce48b2d717 100644 --- a/packages/types/src/cart/service.ts +++ b/packages/types/src/cart/service.ts @@ -276,7 +276,7 @@ export interface ICartModuleService extends IModuleService { sharedContext?: Context ): Promise removeLineItemTaxLines( - selector: Partial, + selector: FilterableLineItemTaxLineProps, sharedContext?: Context ): Promise @@ -316,7 +316,7 @@ export interface ICartModuleService extends IModuleService { sharedContext?: Context ): Promise removeShippingMethodTaxLines( - selector: Partial, + selector: FilterableShippingMethodTaxLineProps, sharedContext?: Context ): Promise } From affd30d828b5386eafadc76e7f7bb858b6a7eadf Mon Sep 17 00:00:00 2001 From: olivermrbl Date: Wed, 24 Jan 2024 08:37:08 +0100 Subject: [PATCH 7/8] add missing file --- packages/types/src/cart/service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/types/src/cart/service.ts b/packages/types/src/cart/service.ts index 955ce48b2d717..2af985f422c9c 100644 --- a/packages/types/src/cart/service.ts +++ b/packages/types/src/cart/service.ts @@ -257,7 +257,7 @@ export interface ICartModuleService extends IModuleService { ): Promise addLineItemTaxLines( cartId: string, - taxLines: CreateLineItemTaxLineDTO[], + taxLines: CreateLineItemTaxLineDTO[] | CreateLineItemTaxLineDTO, sharedContext?: Context ): Promise @@ -294,7 +294,7 @@ export interface ICartModuleService extends IModuleService { ): Promise addShippingMethodTaxLines( cartId: string, - taxLines: CreateShippingMethodTaxLineDTO[], + taxLines: CreateShippingMethodTaxLineDTO[] | CreateShippingMethodTaxLineDTO, sharedContext?: Context ): Promise From ccf311d7b64e6d6589408bb32ffaedf8a026d09f Mon Sep 17 00:00:00 2001 From: olivermrbl Date: Wed, 24 Jan 2024 08:50:20 +0100 Subject: [PATCH 8/8] clean up --- packages/cart/src/services/cart-module.ts | 119 ++++++++-------------- packages/types/src/cart/common.ts | 4 + 2 files changed, 48 insertions(+), 75 deletions(-) diff --git a/packages/cart/src/services/cart-module.ts b/packages/cart/src/services/cart-module.ts index 4d067356b7f9a..e3eaff368aa6f 100644 --- a/packages/cart/src/services/cart-module.ts +++ b/packages/cart/src/services/cart-module.ts @@ -802,25 +802,17 @@ export default class CartModuleService implements ICartModuleService { sharedContext ) - const lineIds = cart.items?.map((item) => item.id) - const existingAdjustments = await this.listLineItemAdjustments( - { item_id: lineIds }, + { item: { cart_id: cart.id } }, { select: ["id"] }, sharedContext ) - let toUpdate: CartTypes.UpdateLineItemAdjustmentDTO[] = [] - let toCreate: CartTypes.CreateLineItemAdjustmentDTO[] = [] - for (const adj of adjustments) { - if ("id" in adj) { - toUpdate.push(adj as CartTypes.UpdateLineItemAdjustmentDTO) - } else { - toCreate.push(adj as CartTypes.CreateLineItemAdjustmentDTO) - } - } - - const adjustmentsSet = new Set(toUpdate.map((a) => a.id)) + const adjustmentsSet = new Set( + adjustments + .map((a) => (a as CartTypes.UpdateLineItemAdjustmentDTO).id) + .filter(Boolean) + ) const toDelete: CartTypes.LineItemAdjustmentDTO[] = [] @@ -831,29 +823,17 @@ export default class CartModuleService implements ICartModuleService { } }) - await this.lineItemAdjustmentService_.delete( - toDelete.map((adj) => adj!.id), - sharedContext - ) - - let result: LineItemAdjustment[] = [] - - // TODO: Replace the following two calls with a single bulk upsert call - if (toUpdate?.length) { - const updated = await this.lineItemAdjustmentService_.update( - toUpdate, + if (toDelete.length) { + await this.lineItemAdjustmentService_.delete( + toDelete.map((adj) => adj!.id), sharedContext ) - result.push(...updated) } - if (toCreate?.length) { - const created = await this.lineItemAdjustmentService_.create( - toCreate, - sharedContext - ) - result.push(...created) - } + let result = await this.lineItemAdjustmentService_.upsert( + adjustments, + sharedContext + ) return await this.baseRepository_.serialize< CartTypes.LineItemAdjustmentDTO[] @@ -936,25 +916,17 @@ export default class CartModuleService implements ICartModuleService { sharedContext ) - const methodIds = cart.shipping_methods?.map((method) => method.id) - const existingAdjustments = await this.listShippingMethodAdjustments( - { shipping_method_id: methodIds ?? [] }, + { shipping_method: { cart_id: cart.id } }, { select: ["id"] }, sharedContext ) - let toUpdate: CartTypes.UpdateShippingMethodAdjustmentDTO[] = [] - let toCreate: CartTypes.CreateShippingMethodAdjustmentDTO[] = [] - for (const adj of adjustments) { - if ("id" in adj) { - toUpdate.push(adj as CartTypes.UpdateShippingMethodAdjustmentDTO) - } else { - toCreate.push(adj as CartTypes.CreateShippingMethodAdjustmentDTO) - } - } - - const adjustmentsSet = new Set(toUpdate.map((a) => a.id)) + const adjustmentsSet = new Set( + adjustments + .map((a) => (a as CartTypes.UpdateShippingMethodAdjustmentDTO)?.id) + .filter(Boolean) + ) const toDelete: CartTypes.ShippingMethodAdjustmentDTO[] = [] @@ -974,24 +946,10 @@ export default class CartModuleService implements ICartModuleService { ) } - let result: ShippingMethodAdjustment[] = [] - - if (toCreate.length) { - const created = await this.shippingMethodAdjustmentService_.create( - toCreate, - sharedContext - ) - - result.push(...created) - } - - if (toUpdate.length) { - const updated = await this.shippingMethodAdjustmentService_.update( - toUpdate, - sharedContext - ) - result.push(...updated) - } + const result = await this.shippingMethodAdjustmentService_.upsert( + adjustments, + sharedContext + ) return await this.baseRepository_.serialize< CartTypes.ShippingMethodAdjustmentDTO[] @@ -1165,7 +1123,7 @@ export default class CartModuleService implements ICartModuleService { const lines = Array.isArray(taxLines) ? taxLines : [taxLines] addedTaxLines = await this.lineItemTaxLineService_.create( - lines, + lines as CartTypes.CreateLineItemTaxLineDTO[], sharedContext ) } else { @@ -1212,7 +1170,9 @@ export default class CartModuleService implements ICartModuleService { ) const taxLinesSet = new Set( - taxLines.map((taxLine) => taxLine.id).filter(Boolean) + taxLines + .map((taxLine) => (taxLine as CartTypes.UpdateLineItemTaxLineDTO)?.id) + .filter(Boolean) ) const toDelete: CartTypes.LineItemTaxLineDTO[] = [] @@ -1266,7 +1226,7 @@ export default class CartModuleService implements ICartModuleService { if (isObject(taxLineIdsOrSelector)) { const taxLines = await this.listLineItemTaxLines( { - ...taxLineIdsOrSelector, + ...(taxLineIdsOrSelector as CartTypes.FilterableLineItemTaxLineProps), }, { select: ["id"] }, sharedContext @@ -1336,7 +1296,7 @@ export default class CartModuleService implements ICartModuleService { const lines = Array.isArray(taxLines) ? taxLines : [taxLines] addedTaxLines = await this.shippingMethodTaxLineService_.create( - lines, + lines as CartTypes.CreateShippingMethodTaxLineDTO[], sharedContext ) } else { @@ -1383,7 +1343,11 @@ export default class CartModuleService implements ICartModuleService { ) const taxLinesSet = new Set( - taxLines.map((taxLine) => taxLine.id).filter(Boolean) + taxLines + .map( + (taxLine) => (taxLine as CartTypes.UpdateShippingMethodTaxLineDTO)?.id + ) + .filter(Boolean) ) const toDelete: CartTypes.ShippingMethodTaxLineDTO[] = [] @@ -1395,13 +1359,18 @@ export default class CartModuleService implements ICartModuleService { } }) - await this.shippingMethodTaxLineService_.delete( - toDelete.map((taxLine) => taxLine!.id), + if (toDelete.length) { + await this.shippingMethodTaxLineService_.delete( + toDelete.map((taxLine) => taxLine!.id), + sharedContext + ) + } + + const result = await this.shippingMethodTaxLineService_.upsert( + taxLines, sharedContext ) - const result = await this.lineItemTaxLineService_.upsert(taxLines) - return await this.baseRepository_.serialize< CartTypes.ShippingMethodTaxLineDTO[] >(result, { @@ -1433,7 +1402,7 @@ export default class CartModuleService implements ICartModuleService { if (isObject(taxLineIdsOrSelector)) { const taxLines = await this.listShippingMethodTaxLines( { - ...taxLineIdsOrSelector, + ...(taxLineIdsOrSelector as CartTypes.FilterableShippingMethodTaxLineProps), }, { select: ["id"] }, sharedContext diff --git a/packages/types/src/cart/common.ts b/packages/types/src/cart/common.ts index 2602e28bef13d..b83c2b7d6d514 100644 --- a/packages/types/src/cart/common.ts +++ b/packages/types/src/cart/common.ts @@ -521,6 +521,7 @@ export interface FilterableLineItemAdjustmentProps item_id?: string | string[] promotion_id?: string | string[] provider_id?: string | string[] + item?: FilterableLineItemProps } export interface FilterableShippingMethodProps extends BaseFilterable { @@ -536,6 +537,7 @@ export interface FilterableShippingMethodAdjustmentProps shipping_method_id?: string | string[] promotion_id?: string | string[] provider_id?: string | string[] + shipping_method?: FilterableShippingMethodProps } export interface FilterableLineItemTaxLineProps @@ -546,6 +548,7 @@ export interface FilterableLineItemTaxLineProps tax_rate_id?: string | string[] provider_id?: string | string[] item_id?: string | string[] + item?: FilterableLineItemProps } export interface FilterableShippingMethodTaxLineProps @@ -556,6 +559,7 @@ export interface FilterableShippingMethodTaxLineProps tax_rate_id?: string | string[] provider_id?: string | string[] shipping_method_id?: string | string[] + shipping_method?: FilterableShippingMethodProps } /**