Browse Source

fix(core): Deleting a Collection also deletes descendants

Relates to #186
Michael Bromley 6 years ago
parent
commit
1ba9e2d6f7

+ 64 - 36
packages/core/e2e/collection.e2e-spec.ts

@@ -447,36 +447,53 @@ describe('Collection resolver', () => {
     });
 
     describe('deleteCollection', () => {
-        let collectionToDelete: CreateCollection.CreateCollection;
+        let collectionToDeleteParent: CreateCollection.CreateCollection;
+        let collectionToDeleteChild: CreateCollection.CreateCollection;
         let laptopProductId: string;
 
         beforeAll(async () => {
-            const { createCollection } = await client.query<
-                CreateCollection.Mutation,
-                CreateCollection.Variables
-            >(CREATE_COLLECTION, {
-                input: {
-                    filters: [
-                        {
-                            code: variantNameCollectionFilter.code,
-                            arguments: [
-                                {
-                                    name: 'operator',
-                                    value: 'contains',
-                                    type: 'string',
-                                },
-                                {
-                                    name: 'term',
-                                    value: 'laptop',
-                                    type: 'string',
-                                },
-                            ],
-                        },
-                    ],
-                    translations: [{ languageCode: LanguageCode.en, name: 'Delete Me', description: '' }],
+            const result1 = await client.query<CreateCollection.Mutation, CreateCollection.Variables>(
+                CREATE_COLLECTION,
+                {
+                    input: {
+                        filters: [
+                            {
+                                code: variantNameCollectionFilter.code,
+                                arguments: [
+                                    {
+                                        name: 'operator',
+                                        value: 'contains',
+                                        type: 'string',
+                                    },
+                                    {
+                                        name: 'term',
+                                        value: 'laptop',
+                                        type: 'string',
+                                    },
+                                ],
+                            },
+                        ],
+                        translations: [
+                            { languageCode: LanguageCode.en, name: 'Delete Me Parent', description: '' },
+                        ],
+                    },
                 },
-            });
-            collectionToDelete = createCollection;
+            );
+            collectionToDeleteParent = result1.createCollection;
+
+            const result2 = await client.query<CreateCollection.Mutation, CreateCollection.Variables>(
+                CREATE_COLLECTION,
+                {
+                    input: {
+                        filters: [],
+                        translations: [
+                            { languageCode: LanguageCode.en, name: 'Delete Me Child', description: '' },
+                        ],
+                        parentId: collectionToDeleteParent.id,
+                    },
+                },
+            );
+            collectionToDeleteChild = result2.createCollection;
         });
 
         it(
@@ -493,7 +510,7 @@ describe('Collection resolver', () => {
                 GetCollectionProducts.Query,
                 GetCollectionProducts.Variables
             >(GET_COLLECTION_PRODUCT_VARIANTS, {
-                id: collectionToDelete.id,
+                id: collectionToDeleteParent.id,
             });
             expect(collection!.productVariants.items.map(pick(['name']))).toEqual([
                 { name: 'Laptop 13 inch 8GB' },
@@ -515,7 +532,8 @@ describe('Collection resolver', () => {
                 { id: 'T_3', name: 'Electronics' },
                 { id: 'T_4', name: 'Computers' },
                 { id: 'T_5', name: 'Pear' },
-                { id: 'T_6', name: 'Delete Me' },
+                { id: 'T_6', name: 'Delete Me Parent' },
+                { id: 'T_7', name: 'Delete Me Child' },
             ]);
         });
 
@@ -524,17 +542,27 @@ describe('Collection resolver', () => {
                 DeleteCollection.Mutation,
                 DeleteCollection.Variables
             >(DELETE_COLLECTION, {
-                id: collectionToDelete.id,
+                id: collectionToDeleteParent.id,
             });
 
             expect(deleteCollection.result).toBe(DeletionResult.DELETED);
         });
 
-        it('deleted collection is null', async () => {
+        it('deleted parent collection is null', async () => {
+            const { collection } = await client.query<GetCollection.Query, GetCollection.Variables>(
+                GET_COLLECTION,
+                {
+                    id: collectionToDeleteParent.id,
+                },
+            );
+            expect(collection).toBeNull();
+        });
+
+        it('deleted child collection is null', async () => {
             const { collection } = await client.query<GetCollection.Query, GetCollection.Variables>(
                 GET_COLLECTION,
                 {
-                    id: collectionToDelete.id,
+                    id: collectionToDeleteChild.id,
                 },
             );
             expect(collection).toBeNull();
@@ -1059,11 +1087,11 @@ describe('Collection resolver', () => {
             expect(result.products.items[0].collections).toEqual([
                 { id: 'T_3', name: 'Electronics' },
                 { id: 'T_5', name: 'Pear' },
-                { id: 'T_8', name: 'Photo AND Pear' },
-                { id: 'T_9', name: 'Photo OR Pear' },
-                { id: 'T_11', name: 'contains camera' },
-                { id: 'T_13', name: 'endsWith camera' },
-                { id: 'T_15', name: 'pear electronics' },
+                { id: 'T_9', name: 'Photo AND Pear' },
+                { id: 'T_10', name: 'Photo OR Pear' },
+                { id: 'T_12', name: 'contains camera' },
+                { id: 'T_14', name: 'endsWith camera' },
+                { id: 'T_16', name: 'pear electronics' },
             ]);
         });
     });

+ 1 - 1
packages/core/src/api/schema/admin-api/collection.api.graphql

@@ -11,7 +11,7 @@ type Mutation {
     "Update an existing Collection"
     updateCollection(input: UpdateCollectionInput!): Collection!
 
-    "Delete a Collection"
+    "Delete a Collection and all of its descendants"
     deleteCollection(id: ID!): DeletionResponse!
 
     "Move a Collection to a different parent or index"

+ 11 - 8
packages/core/src/service/services/collection.service.ts

@@ -48,7 +48,7 @@ import { FacetValueService } from './facet-value.service';
 import { JobService } from './job.service';
 
 export class CollectionService implements OnModuleInit {
-    private rootCategories: { [channelCode: string]: Collection } = {};
+    private rootCollections: { [channelCode: string]: Collection } = {};
     private availableFilters: Array<CollectionFilter<any>> = [
         facetValueCollectionFilter,
         variantNameCollectionFilter,
@@ -279,9 +279,12 @@ export class CollectionService implements OnModuleInit {
 
     async delete(ctx: RequestContext, id: ID): Promise<DeletionResponse> {
         const collection = await getEntityOrThrow(this.connection, Collection, id);
-        const affectedVariantIds = await this.getCollectionProductVariantIds(collection);
-        await this.connection.getRepository(Collection).remove(collection);
-        this.eventBus.publish(new CollectionModificationEvent(ctx, collection, affectedVariantIds));
+        const descendants = await this.getDescendants(ctx, collection.id);
+        for (const coll of [...descendants.reverse(), collection]) {
+            const affectedVariantIds = await this.getCollectionProductVariantIds(coll);
+            await this.connection.getRepository(Collection).remove(coll);
+            this.eventBus.publish(new CollectionModificationEvent(ctx, coll, affectedVariantIds));
+        }
         return {
             result: DeletionResult.DELETED,
         };
@@ -428,7 +431,7 @@ export class CollectionService implements OnModuleInit {
     }
 
     private async getRootCollection(ctx: RequestContext): Promise<Collection> {
-        const cachedRoot = this.rootCategories[ctx.channel.code];
+        const cachedRoot = this.rootCollections[ctx.channel.code];
 
         if (cachedRoot) {
             return cachedRoot;
@@ -444,8 +447,8 @@ export class CollectionService implements OnModuleInit {
             .getOne();
 
         if (existingRoot) {
-            this.rootCategories[ctx.channel.code] = translateDeep(existingRoot, ctx.languageCode);
-            return this.rootCategories[ctx.channel.code];
+            this.rootCollections[ctx.channel.code] = translateDeep(existingRoot, ctx.languageCode);
+            return this.rootCollections[ctx.channel.code];
         }
 
         const rootTranslation = await this.connection.getRepository(CollectionTranslation).save(
@@ -465,7 +468,7 @@ export class CollectionService implements OnModuleInit {
         });
 
         await this.connection.getRepository(Collection).save(newRoot);
-        this.rootCategories[ctx.channel.code] = newRoot;
+        this.rootCollections[ctx.channel.code] = newRoot;
         return newRoot;
     }