import { ModifyAction } from '@app/common/constants/modify-action.enum'; import { SpaceProductAllocationRepository } from '@app/common/modules/space'; import { SubspaceModelProductAllocationRepoitory } from '@app/common/modules/space-model'; import { SpaceEntity } from '@app/common/modules/space/entities/space.entity'; import { SubspaceProductAllocationRepository, SubspaceRepository, } from '@app/common/modules/space/repositories/subspace.repository'; import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { PropogateUpdateSpaceModelCommand } from '../commands'; import { ISingleSubspaceModel } from '../interfaces'; import { IUpdatedAllocations } from '../interfaces/subspace-product-allocation-update-result.interface'; @CommandHandler(PropogateUpdateSpaceModelCommand) export class PropogateUpdateSpaceModelHandler implements ICommandHandler { constructor( private readonly subspaceRepository: SubspaceRepository, private readonly subspaceModelProductRepository: SubspaceModelProductAllocationRepoitory, private readonly subspaceProductRepository: SubspaceProductAllocationRepository, private readonly spaceProductRepository: SpaceProductAllocationRepository, ) {} async execute(command: PropogateUpdateSpaceModelCommand): Promise { const { subspaceUpdates, spaces } = command.param; try { if (!subspaceUpdates?.subspaceModels?.length) return; // Exit if no updates if (!spaces?.length) return; // Exit if no spaces const subspaceModels = subspaceUpdates.subspaceModels; // 🔹 Filter subspace models by action const subspacesToAdd = subspaceModels.filter( (m) => m.action === ModifyAction.ADD, ); const subspacesToUpdate = subspaceModels.filter( (m) => m.action === ModifyAction.UPDATE, ); const subspacesToDelete = subspaceModels.filter( (m) => m.action === ModifyAction.DELETE, ); // 1️⃣ Create Subspace Models First (if any) await Promise.all( subspacesToAdd.map((m) => this.addSubspaceModel(m, spaces)), ); // 2️⃣ Update Allocations await this.updateAllocations(subspaceUpdates.updatedAllocations); // 3️⃣ Update Existing Subspace Models (if any) await Promise.all( subspacesToUpdate.map((m) => this.updateSubspaceModel(m)), ); // 4️⃣ Delete Subspace Models (if any) await Promise.all( subspacesToDelete.map((m) => this.deleteSubspaceModel(m, spaces)), ); console.log('Successfully executed PropogateUpdateSpaceModelCommand'); } catch (error) { console.error('Error processing subspace model updates', error); } } async updateAllocations(allocations: IUpdatedAllocations[]) { try { for (const allocation of allocations) { if (!allocation) continue; // if (allocation.allocation) { // try { // const subspaceAllocations = // await this.subspaceProductRepository.find({ // where: { // inheritedFromModel: { uuid: allocation.allocation.uuid }, // }, // relations: ['tags'], // }); // if (!subspaceAllocations || subspaceAllocations.length === 0) // continue; // if (allocation.tagsAdded?.length) { // for (const subspaceAllocation of subspaceAllocations) { // subspaceAllocation.tags.push(...allocation.tagsAdded); // } // await this.subspaceProductRepository.save(subspaceAllocations); // console.log( // `Added tags to ${subspaceAllocations.length} subspace allocations.`, // ); // } // if (allocation.tagsRemoved?.length) { // const tagsToRemoveUUIDs = allocation.tagsRemoved.map( // (tag) => tag.uuid, // ); // for (const subspaceAllocation of subspaceAllocations) { // subspaceAllocation.tags = subspaceAllocation.tags.filter( // (tag) => !tagsToRemoveUUIDs.includes(tag.uuid), // ); // } // await this.subspaceProductRepository.save(subspaceAllocations); // console.log( // `Removed tags from ${subspaceAllocations.length} subspace allocations.`, // ); // } // } catch (error) { // console.error('Error processing allocation update:', error); // } // } if (allocation.newAllocation) { try { const subspaceModel = allocation.newAllocation.subspaceModel; const subspaces = await this.subspaceRepository.find({ where: { subSpaceModel: { uuid: subspaceModel.uuid } }, }); if (!subspaces || subspaces.length === 0) continue; const newAllocations = subspaces.map((subspace) => this.subspaceProductRepository.create({ product: allocation.newAllocation.product, tag: allocation.newAllocation.tag, subspace, inheritedFromModel: allocation.newAllocation, }), ); await this.subspaceProductRepository.save(newAllocations); console.log( `Created ${newAllocations.length} new subspace allocations.`, ); } catch (error) { console.error('Error creating new subspace allocation:', error); } } if (allocation.deletedAllocation) { try { const subspaceAllocations = await this.subspaceProductRepository.find({ where: { inheritedFromModel: { uuid: allocation.deletedAllocation.uuid, }, }, }); if (!subspaceAllocations || subspaceAllocations.length === 0) continue; await this.subspaceProductRepository.remove(subspaceAllocations); console.log( `Deleted ${subspaceAllocations.length} subspace allocations.`, ); } catch (error) { console.error('Error deleting subspace allocation:', error); } } } } catch (error) { console.error('Error in updateAllocations method:', error); } } async addSubspaceModel( subspaceModel: ISingleSubspaceModel, spaces: SpaceEntity[], ) { const subspaceModelAllocations = await this.subspaceModelProductRepository.find({ where: { subspaceModel: { uuid: subspaceModel.subspaceModel.uuid, }, }, relations: ['tags', 'product'], }); for (const space of spaces) { const subspace = this.subspaceRepository.create({ subspaceName: subspaceModel.subspaceModel.subspaceName, space: space, }); subspace.subSpaceModel = subspaceModel.subspaceModel; await this.subspaceRepository.save(subspace); if (subspaceModelAllocations?.length > 0) { for (const allocation of subspaceModelAllocations) { const subspaceAllocation = this.subspaceProductRepository.create({ subspace: subspace, product: allocation.product, tag: allocation.tag, inheritedFromModel: allocation, }); await this.subspaceProductRepository.save(subspaceAllocation); } } } } async deleteSubspaceModel( subspaceModel: ISingleSubspaceModel, spaces: SpaceEntity[], ) { // const subspaces = await this.subspaceRepository.find({ // where: { // subSpaceModel: { uuid: subspaceModel.subspaceModel.uuid }, // disabled: false, // }, // relations: [ // 'productAllocations', // 'productAllocations.product', // 'productAllocations.tags', // ], // }); // if (!subspaces.length) { // return; // } // const allocationUuidsToRemove = subspaces.flatMap((subspace) => // subspace.productAllocations.map((allocation) => allocation.uuid), // ); // if (allocationUuidsToRemove.length) { // await this.subspaceProductRepository.delete(allocationUuidsToRemove); // } // await this.subspaceRepository.update( // { uuid: In(subspaces.map((s) => s.uuid)) }, // { disabled: true }, // ); // const relocatedAllocations = subspaceModel.relocatedAllocations || []; // if (!relocatedAllocations.length) { // return; // } // for (const space of spaces) { // for (const { allocation, tags = [] } of relocatedAllocations) { // const spaceAllocation = await this.spaceProductRepository.findOne({ // where: { // inheritedFromModel: { uuid: allocation.uuid }, // space: { uuid: space.uuid }, // }, // relations: ['tags'], // }); // if (spaceAllocation) { // if (tags.length) { // spaceAllocation.tags.push(...tags); // await this.spaceProductRepository.save(spaceAllocation); // } // } else { // const newSpaceAllocation = this.spaceProductRepository.create({ // space, // inheritedFromModel: allocation, // tag: allocation.tag, // product: allocation.product, // }); // await this.spaceProductRepository.save(newSpaceAllocation); // } // } // } } async updateSubspaceModel(subspaceModel: ISingleSubspaceModel) { return this.subspaceRepository.update( { subSpaceModel: { uuid: subspaceModel.subspaceModel.uuid }, disabled: false, }, { subspaceName: subspaceModel.subspaceModel.subspaceName }, ); } }