Merge branch 'dev' of https://github.com/SyncrowIOT/backend into bugix/delete-subspace

This commit is contained in:
hannathkadher
2025-03-11 01:25:31 +04:00
5 changed files with 186 additions and 179 deletions

View File

@ -481,6 +481,7 @@ export class SpaceModelService {
await this.subspaceRepository.save(subspace);
}
const subspaceAllocations = subspaceModel.productAllocations.map(
(modelAllocation) =>
this.subspaceProductAllocationRepository.create({

View File

@ -45,11 +45,14 @@ export class ValidationService {
await this.communityService.validateProject(projectUuid);
const spaces = await this.spaceRepository.find({
where: { uuid: In(spacesUuids), disabled: false },
relations: ['devices', 'subspaces'],
relations: ['devices', 'subspaces', 'productAllocations'],
});
const hasInvalidSpaces = spaces.some(
(space) => space.devices.length > 0 || space.subspaces.length > 0,
(space) =>
space.devices.length > 0 ||
space.subspaces.length > 0 ||
space.productAllocations.length > 0,
);
if (hasInvalidSpaces) {
@ -122,6 +125,12 @@ export class ValidationService {
'children',
'subspaces',
'tags',
'productAllocations',
'productAllocations.product',
'productAllocations.tags',
'subspaces.productAllocations',
'subspaces.productAllocations.tags',
'subspaces.productAllocations.product',
'subspaces.tags',
'subspaces.devices',
],
@ -172,6 +181,7 @@ export class ValidationService {
'subspaceModels',
'subspaceModels.productAllocations',
'subspaceModels.productAllocations.tags',
'subspaceModels.productAllocations.product',
'productAllocations.product',
'productAllocations.tags',
],

View File

@ -530,7 +530,7 @@ export class SpaceService {
}
throw new HttpException(
'An error occurred while updating the space',
`An error occurred while updating the space: error ${error}`,
HttpStatus.INTERNAL_SERVER_ERROR,
);
} finally {
@ -653,15 +653,9 @@ export class SpaceService {
private buildSpaceHierarchy(spaces: SpaceEntity[]): SpaceEntity[] {
const map = new Map<string, SpaceEntity>();
// Step 1: Create a map of spaces by UUID
// Step 1: Create a map of spaces by UUID, without creating new instances
spaces.forEach((space) => {
map.set(
space.uuid,
this.spaceRepository.create({
...space,
children: [], // Add children if needed
}),
);
map.set(space.uuid, space); // Use the existing space entity
});
// Step 2: Organize the hierarchy
@ -669,9 +663,14 @@ export class SpaceService {
spaces.forEach((space) => {
if (space.parent && space.parent.uuid) {
const parent = map.get(space.parent.uuid);
parent?.children?.push(map.get(space.uuid));
if (parent) {
if (!parent.children) {
parent.children = [];
}
parent.children.push(space);
}
} else {
rootSpaces.push(map.get(space.uuid));
rootSpaces.push(space);
}
});

View File

@ -79,134 +79,62 @@ export class SubspaceProductAllocationService {
spaceTagUpdateDtos?: ModifyTagDto[],
) {
const spaceAllocationToExclude: SpaceProductAllocationEntity[] = [];
for (const subspace of subspaces) {
if (!subspace.tags || subspace.tags.length === 0) continue;
const tagDtos = subspace.tags;
if (tagDtos.length > 0) {
const tagsToAddDto: ProcessTagDto[] = tagDtos
.filter((dto) => dto.action === ModifyAction.ADD)
.map((dto) => ({
name: dto.name,
productUuid: dto.productUuid,
uuid: dto.newTagUuid,
}));
const tagsToAddDto: ProcessTagDto[] = tagDtos
.filter((dto) => dto.action === ModifyAction.ADD)
.map((dto) => ({
name: dto.name,
productUuid: dto.productUuid,
uuid: dto.newTagUuid,
}));
const tagsToDeleteDto = tagDtos.filter(
(dto) => dto.action === ModifyAction.DELETE,
const tagsToDeleteDto = tagDtos.filter(
(dto) => dto.action === ModifyAction.DELETE,
);
if (tagsToAddDto.length > 0) {
let processedTags = await this.tagService.processTags(
tagsToAddDto,
projectUuid,
queryRunner,
);
if (tagsToAddDto.length > 0) {
let processedTags = await this.tagService.processTags(
tagsToAddDto,
projectUuid,
queryRunner,
);
for (const subspaceDto of subspaces) {
if (
subspaceDto !== subspace &&
subspaceDto.action === ModifyAction.UPDATE &&
subspaceDto.tags
) {
const deletedTags = subspaceDto.tags.filter(
(tagDto) =>
tagDto.action === ModifyAction.DELETE &&
processedTags.some((tag) => tag.uuid === tagDto.tagUuid),
);
for (const subspaceDto of subspaces) {
if (
subspaceDto !== subspace &&
subspaceDto.action === ModifyAction.UPDATE &&
subspaceDto.tags
) {
const deletedTags = subspaceDto.tags.filter(
(tagDto) =>
tagDto.action === ModifyAction.DELETE &&
processedTags.some((tag) => tag.uuid === tagDto.tagUuid),
);
for (const deletedTag of deletedTags) {
const allocation = await queryRunner.manager.findOne(
SubspaceProductAllocationEntity,
{
where: {
subspace: { uuid: subspaceDto.subspace.uuid },
},
relations: ['tags', 'product', 'subspace'],
},
);
const isCommonTag = allocation.tags.some(
(tag) => tag.uuid === deletedTag.tagUuid,
);
if (allocation && isCommonTag) {
const tagEntity = allocation.tags.find(
(tag) => tag.uuid === deletedTag.tagUuid,
);
allocation.tags = allocation.tags.filter(
(tag) => tag.uuid !== deletedTag.tagUuid,
);
await queryRunner.manager.save(allocation);
const productAllocationExistInSubspace =
await queryRunner.manager.findOne(
SubspaceProductAllocationEntity,
{
where: {
subspace: {
uuid: subspaceDto.subspace.uuid,
},
product: { uuid: allocation.product.uuid },
},
relations: ['tags'],
},
);
if (productAllocationExistInSubspace) {
productAllocationExistInSubspace.tags.push(tagEntity);
await queryRunner.manager.save(
productAllocationExistInSubspace,
);
} else {
const newProductAllocation = queryRunner.manager.create(
SubspaceProductAllocationEntity,
{
subspace: subspace.subspace,
product: allocation.product,
tags: [tagEntity],
},
);
await queryRunner.manager.save(newProductAllocation);
}
processedTags = processedTags.filter(
(tag) => tag.uuid !== deletedTag.tagUuid,
);
subspaceDto.tags = subspaceDto.tags.filter(
(tagDto) => tagDto.tagUuid !== deletedTag.tagUuid,
);
}
}
}
if (
subspaceDto !== subspace &&
subspaceDto.action === ModifyAction.DELETE
) {
for (const deletedTag of deletedTags) {
const allocation = await queryRunner.manager.findOne(
SubspaceProductAllocationEntity,
{
where: {
subspace: { uuid: subspaceDto.subspace.uuid },
},
relations: ['tags'],
relations: ['tags', 'product', 'subspace'],
},
);
const repeatedTags = allocation?.tags.filter((tag) =>
processedTags.some(
(processedTag) => processedTag.uuid === tag.uuid,
),
const isCommonTag = allocation.tags.some(
(tag) => tag.uuid === deletedTag.tagUuid,
);
if (repeatedTags.length > 0) {
if (allocation && isCommonTag) {
const tagEntity = allocation.tags.find(
(tag) => tag.uuid === deletedTag.tagUuid,
);
allocation.tags = allocation.tags.filter(
(tag) =>
!repeatedTags.some(
(repeatedTag) => repeatedTag.uuid === tag.uuid,
),
(tag) => tag.uuid !== deletedTag.tagUuid,
);
await queryRunner.manager.save(allocation);
@ -216,7 +144,9 @@ export class SubspaceProductAllocationService {
SubspaceProductAllocationEntity,
{
where: {
subspace: { uuid: subspaceDto.subspace.uuid },
subspace: {
uuid: subspaceDto.subspace.uuid,
},
product: { uuid: allocation.product.uuid },
},
relations: ['tags'],
@ -224,7 +154,7 @@ export class SubspaceProductAllocationService {
);
if (productAllocationExistInSubspace) {
productAllocationExistInSubspace.tags.push(...repeatedTags);
productAllocationExistInSubspace.tags.push(tagEntity);
await queryRunner.manager.save(
productAllocationExistInSubspace,
);
@ -234,14 +164,71 @@ export class SubspaceProductAllocationService {
{
subspace: subspace.subspace,
product: allocation.product,
tags: repeatedTags,
tags: [tagEntity],
},
);
await queryRunner.manager.save(newProductAllocation);
}
const newAllocation = queryRunner.manager.create(
processedTags = processedTags.filter(
(tag) => tag.uuid !== deletedTag.tagUuid,
);
subspaceDto.tags = subspaceDto.tags.filter(
(tagDto) => tagDto.tagUuid !== deletedTag.tagUuid,
);
}
}
}
if (
subspaceDto !== subspace &&
subspaceDto.action === ModifyAction.DELETE
) {
const allocation = await queryRunner.manager.findOne(
SubspaceProductAllocationEntity,
{
where: {
subspace: { uuid: subspaceDto.subspace.uuid },
},
relations: ['tags'],
},
);
const repeatedTags = allocation?.tags.filter((tag) =>
processedTags.some(
(processedTag) => processedTag.uuid === tag.uuid,
),
);
if (repeatedTags.length > 0) {
allocation.tags = allocation.tags.filter(
(tag) =>
!repeatedTags.some(
(repeatedTag) => repeatedTag.uuid === tag.uuid,
),
);
await queryRunner.manager.save(allocation);
const productAllocationExistInSubspace =
await queryRunner.manager.findOne(
SubspaceProductAllocationEntity,
{
where: {
subspace: { uuid: subspaceDto.subspace.uuid },
product: { uuid: allocation.product.uuid },
},
relations: ['tags'],
},
);
if (productAllocationExistInSubspace) {
productAllocationExistInSubspace.tags.push(...repeatedTags);
await queryRunner.manager.save(
productAllocationExistInSubspace,
);
} else {
const newProductAllocation = queryRunner.manager.create(
SubspaceProductAllocationEntity,
{
subspace: subspace.subspace,
@ -250,47 +237,58 @@ export class SubspaceProductAllocationService {
},
);
await queryRunner.manager.save(newAllocation);
await queryRunner.manager.save(newProductAllocation);
}
}
}
if (spaceTagUpdateDtos) {
const deletedSpaceTags = spaceTagUpdateDtos.filter(
(tagDto) =>
tagDto.action === ModifyAction.DELETE &&
processedTags.some((tag) => tag.uuid === tagDto.tagUuid),
);
for (const deletedTag of deletedSpaceTags) {
const allocation = await queryRunner.manager.findOne(
SpaceProductAllocationEntity,
const newAllocation = queryRunner.manager.create(
SubspaceProductAllocationEntity,
{
where: {
space: { uuid: space.uuid },
tags: { uuid: deletedTag.tagUuid },
},
relations: ['tags', 'subspace'],
subspace: subspace.subspace,
product: allocation.product,
tags: repeatedTags,
},
);
if (
allocation &&
allocation.tags.some((tag) => tag.uuid === deletedTag.tagUuid)
) {
spaceAllocationToExclude.push(allocation);
}
await queryRunner.manager.save(newAllocation);
}
}
await this.createSubspaceProductAllocations(
subspace.subspace,
processedTags,
queryRunner,
spaceAllocationToExclude,
}
if (spaceTagUpdateDtos) {
const deletedSpaceTags = spaceTagUpdateDtos.filter(
(tagDto) =>
tagDto.action === ModifyAction.DELETE &&
processedTags.some((tag) => tag.uuid === tagDto.tagUuid),
);
for (const deletedTag of deletedSpaceTags) {
const allocation = await queryRunner.manager.findOne(
SpaceProductAllocationEntity,
{
where: {
space: { uuid: space.uuid },
tags: { uuid: deletedTag.tagUuid },
},
relations: ['tags', 'subspace'],
},
);
if (
allocation &&
allocation.tags.some((tag) => tag.uuid === deletedTag.tagUuid)
) {
spaceAllocationToExclude.push(allocation);
}
}
}
if (tagsToDeleteDto.length > 0) {
await this.processDeleteActions(tagsToDeleteDto, queryRunner);
}
await this.createSubspaceProductAllocations(
subspace.subspace,
processedTags,
queryRunner,
spaceAllocationToExclude,
);
}
if (tagsToDeleteDto.length > 0) {
await this.processDeleteActions(tagsToDeleteDto, queryRunner);
}
}
}

View File

@ -324,6 +324,9 @@ export class SubSpaceService {
projectUuid?: string,
spaceTagUpdateDtos?: ModifyTagDto[],
) {
if (!subspaceDtos || subspaceDtos.length === 0) {
return;
}
const addedSubspaces = [];
const updatedSubspaces = [];
@ -335,14 +338,17 @@ export class SubSpaceService {
space,
queryRunner,
);
addedSubspaces.push(addedSubspace);
if (addedSubspace) addedSubspaces.push(addedSubspace);
break;
case ModifyAction.UPDATE:
const updatedSubspace = await this.handleUpdateAction(
subspace,
queryRunner,
);
updatedSubspaces.push(updatedSubspace);
if (updatedSubspace) {
updatedSubspaces.push(updatedSubspace);
}
break;
case ModifyAction.DELETE:
await this.handleDeleteAction(subspace, queryRunner);
@ -355,7 +361,9 @@ export class SubSpaceService {
}
}
const combinedSubspaces = [...addedSubspaces, ...updatedSubspaces];
const combinedSubspaces = [...addedSubspaces, ...updatedSubspaces].filter(
(subspace) => subspace !== undefined,
);
if (combinedSubspaces.length > 0) {
await this.subspaceProductAllocationService.updateSubspaceProductAllocations(
@ -436,32 +444,22 @@ export class SubSpaceService {
private async handleUpdateAction(
modifyDto: ModifySubspaceDto,
queryRunner: QueryRunner,
): Promise<void> {
): Promise<SubspaceEntity> {
const subspace = await this.findOne(modifyDto.uuid);
await this.update(
const updatedSubspace = await this.update(
queryRunner,
subspace,
modifyDto.subspaceName,
modifyDto.tags,
);
return updatedSubspace;
}
async update(
queryRunner: QueryRunner,
subspace: SubspaceEntity,
subspaceName?: string,
modifyTagDto?: ModifyTagDto[],
) {
await this.updateSubspaceName(queryRunner, subspace, subspaceName);
if (modifyTagDto?.length) {
await this.tagService.modifyTags(
modifyTagDto,
queryRunner,
null,
subspace,
);
}
return await this.updateSubspaceName(queryRunner, subspace, subspaceName);
}
async handleDeleteAction(
@ -517,11 +515,12 @@ export class SubSpaceService {
queryRunner: QueryRunner,
subSpace: SubspaceEntity,
subspaceName?: string,
): Promise<void> {
): Promise<SubspaceEntity> {
if (subspaceName) {
subSpace.subspaceName = subspaceName;
await queryRunner.manager.save(subSpace);
return await queryRunner.manager.save(subSpace);
}
return subSpace;
}
private async checkForDuplicateNames(names: string[]): Promise<void> {