mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-16 02:36:19 +00:00
287 lines
9.5 KiB
TypeScript
287 lines
9.5 KiB
TypeScript
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
|
||
import { PropogateUpdateSpaceModelCommand } from '../commands';
|
||
import { SpaceProductAllocationRepository } from '@app/common/modules/space';
|
||
import {
|
||
SubspaceProductAllocationRepository,
|
||
SubspaceRepository,
|
||
} from '@app/common/modules/space/repositories/subspace.repository';
|
||
import { SubspaceModelProductAllocationRepoitory } from '@app/common/modules/space-model';
|
||
import { In } from 'typeorm';
|
||
import { ISingleSubspaceModel } from '../interfaces';
|
||
import { SpaceEntity } from '@app/common/modules/space/entities/space.entity';
|
||
import { ModifyAction } from '@app/common/constants/modify-action.enum';
|
||
import { IUpdatedAllocations } from '../interfaces/subspace-product-allocation-update-result.interface';
|
||
|
||
@CommandHandler(PropogateUpdateSpaceModelCommand)
|
||
export class PropogateUpdateSpaceModelHandler
|
||
implements ICommandHandler<PropogateUpdateSpaceModelCommand>
|
||
{
|
||
constructor(
|
||
private readonly subspaceRepository: SubspaceRepository,
|
||
private readonly subspaceModelProductRepository: SubspaceModelProductAllocationRepoitory,
|
||
private readonly subspaceProductRepository: SubspaceProductAllocationRepository,
|
||
private readonly spaceProductRepository: SpaceProductAllocationRepository,
|
||
) {}
|
||
|
||
async execute(command: PropogateUpdateSpaceModelCommand): Promise<void> {
|
||
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,
|
||
tags: allocation.newAllocation.tags,
|
||
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,
|
||
tags: allocation.tags,
|
||
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,
|
||
tags: allocation.tags,
|
||
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 },
|
||
);
|
||
}
|
||
}
|