diff --git a/packages/core/utils/src/modules-sdk/internal-module-service-factory.ts b/packages/core/utils/src/modules-sdk/internal-module-service-factory.ts index 26edd8a004..302854410a 100644 --- a/packages/core/utils/src/modules-sdk/internal-module-service-factory.ts +++ b/packages/core/utils/src/modules-sdk/internal-module-service-factory.ts @@ -248,7 +248,9 @@ export function internalModuleServiceFactory< if (input_.selector) { const entitiesToUpdate = await this.list( input_.selector, - {}, + { + take: null, + }, sharedContext ) // Create a pair of entity and data to update diff --git a/packages/modules/notification/integration-tests/__tests__/notification-module-service/index.spec.ts b/packages/modules/notification/integration-tests/__tests__/notification-module-service/index.spec.ts index 867581c2d4..8d2fb76c4a 100644 --- a/packages/modules/notification/integration-tests/__tests__/notification-module-service/index.spec.ts +++ b/packages/modules/notification/integration-tests/__tests__/notification-module-service/index.spec.ts @@ -25,6 +25,8 @@ let moduleOptions = { ], } +jest.setTimeout(30000) + moduleIntegrationTestRunner({ moduleName: Modules.NOTIFICATION, moduleOptions, diff --git a/packages/modules/product/integration-tests/__tests__/services/product-module-service/product-collections.spec.ts b/packages/modules/product/integration-tests/__tests__/services/product-module-service/product-collections.spec.ts index 8fba59fbd6..557ace762c 100644 --- a/packages/modules/product/integration-tests/__tests__/services/product-module-service/product-collections.spec.ts +++ b/packages/modules/product/integration-tests/__tests__/services/product-module-service/product-collections.spec.ts @@ -365,6 +365,73 @@ moduleIntegrationTestRunner({ "ProductCollection with id: does-not-exist was not found" ) }) + + it("should dissociate existing products when new products are synced", async () => { + await service.upsertCollections([ + { + id: collectionId, + product_ids: [productOne.id, productTwo.id], + }, + ]) + + /** + * Another upsert should remove the first productOne + */ + await service.upsertCollections([ + { + id: collectionId, + product_ids: [productTwo.id], + }, + ]) + + const productCollection = await service.retrieveCollection( + collectionId, + { + select: ["products.id"], + relations: ["products"], + } + ) + + expect(productCollection.products).toHaveLength(1) + expect(productCollection).toEqual( + expect.objectContaining({ + products: expect.arrayContaining([ + expect.objectContaining({ + id: productTwo.id, + }), + ]), + }) + ) + }) + + it("should dissociate all existing products", async () => { + await service.upsertCollections([ + { + id: collectionId, + product_ids: [productOne.id, productTwo.id], + }, + ]) + + /** + * Another upsert should remove the first productOne + */ + await service.upsertCollections([ + { + id: collectionId, + product_ids: [], + }, + ]) + + const productCollection = await service.retrieveCollection( + collectionId, + { + select: ["products.id"], + relations: ["products"], + } + ) + + expect(productCollection.products).toHaveLength(0) + }) }) describe("createCollections", () => { diff --git a/packages/modules/product/src/services/product-module-service.ts b/packages/modules/product/src/services/product-module-service.ts index 5ce5ba0be4..2747597f91 100644 --- a/packages/modules/product/src/services/product-module-service.ts +++ b/packages/modules/product/src/services/product-module-service.ts @@ -34,6 +34,7 @@ import { removeUndefined, isValidHandle, toHandle, + isPresent, } from "@medusajs/utils" import { ProductCategoryEventData, @@ -925,37 +926,53 @@ export default class ProductModuleService< sharedContext ) - const collectionWithProducts = await promiseAll( - updatedCollections.map(async (collection, i) => { - const input = normalizedInput.find((c) => c.id === collection.id) + const collections: TProductCollection[] = [] + + const updateSelectorAndData = updatedCollections.flatMap( + (collectionData) => { + const input = normalizedInput.find((c) => c.id === collectionData.id) const productsToUpdate = (input as any)?.products - if (!productsToUpdate) { - return { ...collection, products: [] } + + const dissociateSelector = { + collection_id: collectionData.id, + } + const associateSelector = {} + + if (!!productsToUpdate?.length) { + const productIds = productsToUpdate.map((p) => p.id) + dissociateSelector["id"] = { $nin: productIds } + associateSelector["id"] = { $in: productIds } } - await this.productService_.update( + const result: Record[] = [ { - selector: { collection_id: collection.id }, - data: { collection_id: null }, + selector: dissociateSelector, + data: { + collection_id: null, + }, }, - sharedContext - ) + ] - if (productsToUpdate.length > 0) { - await this.productService_.update( - productsToUpdate.map((p) => ({ - id: p.id, - collection_id: collection.id, - })), - sharedContext - ) + if (isPresent(associateSelector)) { + result.push({ + selector: associateSelector, + data: { + collection_id: collectionData.id, + }, + }) } - return { ...collection, products: productsToUpdate } - }) + collections.push({ + ...collectionData, + products: productsToUpdate ?? [], + }) + + return result + } ) - return collectionWithProducts + await this.productService_.update(updateSelectorAndData, sharedContext) + return collections } @InjectManager("baseRepository_")