homemanager-be/src/app-building/app-building.service.ts

312 lines
7.5 KiB
TypeScript

import {
BadRequestException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import omit from 'lodash.omit';
import pick from 'lodash.pick';
import { BuildingService } from 'src/objects/building/building.service';
import { GroupService } from 'src/objects/group/group.service';
import { User } from 'src/objects/user/user.entity';
import { UserService } from 'src/objects/user/user.service';
import {
BuildingFloorUpdateRequestDto,
CreateFloorRequestDto,
} from './dto/buildings-floor-request.dto';
import { CreateBuildingRequestDto } from './dto/buildings-create-request.dto';
import { BuildingsUpdateRequestDto } from './dto/buildings-update-request.dto';
import {
BuildingsCreateRoomRequestDto,
BuildingsUpdateRoomRequestDto,
} from './dto/buildings-create-room-request.dto';
import { PlanRendererService } from './plan-renderer/plan-renderer.service';
import { BuildingSearchRequestDto } from './dto/buildings-search-request.dto';
import { BuildingSearchResponseDto } from './dto/building-search-response.dto';
@Injectable()
export class AppBuildingService {
constructor(
private readonly buildingService: BuildingService,
private readonly userService: UserService,
private readonly groupService: GroupService,
private readonly planRenderService: PlanRendererService,
) {}
async getUserBuildings(user: User) {
return this.buildingService.getBuildingsByUserSub(user.sub);
}
async createBuilding(user: User, body: CreateBuildingRequestDto) {
const getGroup = await this.groupService.getByIdAndMemberSub(
body.group,
user.sub,
);
if (!getGroup) {
throw new NotFoundException('Group not found');
}
// TODO: validate color
const newBuilding = await this.buildingService.saveBuilding({
...pick(body, ['displayName', 'color', 'address']),
groups: [getGroup],
});
const newFloor = await this.buildingService.saveFloor({
displayName: 'Ground Floor',
number: 0,
plan: '{}',
building: newBuilding,
});
delete newFloor.building;
newBuilding.floors = [newFloor];
return omit(newBuilding, ['groups']);
}
async createBuildingFloor(
user: User,
id: number,
body: CreateFloorRequestDto,
) {
const building = await this.buildingService.getBuildingByIdAndUserSub(
id,
user.sub,
);
if (!building) {
throw new NotFoundException('Building not found');
}
const newFloor = await this.buildingService.saveFloor({
displayName: body.displayName,
number: body.number,
plan: '{}',
building,
});
return omit(newFloor, ['building']);
}
async updateBuilding(
user: User,
id: number,
body: BuildingsUpdateRequestDto,
) {
const building = await this.buildingService.getBuildingByIdAndUserSub(
id,
user.sub,
);
if (!building) {
throw new NotFoundException('Building not found');
}
Object.assign(building, body);
await this.buildingService.saveBuilding(building);
return building;
}
async getBuildingById(user: User, id: number) {
const building = await this.buildingService.getBuildingByIdAndUserSub(
id,
user.sub,
['floors', 'floors.rooms'],
);
if (!building) {
throw new NotFoundException('Building not found');
}
return omit(building, ['groups']);
}
async getBuildingFloors(user: User, buildingId: number) {
const floors = await this.buildingService.getFloorsByBuildingAndUserSub(
buildingId,
user.sub,
['rooms'],
);
return floors.map((floor) => omit(floor, ['building']));
}
async getBuildingFloor(user: User, buildingId: number, floorNumber: number) {
const floor = await this.buildingService.getFloorByBuildingAndUserSub(
buildingId,
floorNumber,
user.sub,
['rooms'],
);
if (!floor) {
throw new NotFoundException('Floor not found');
}
return omit(floor, ['building']);
}
async deleteBuildingFloor(
user: User,
buildingId: number,
floorNumber: number,
) {
const floor = await this.buildingService.getFloorByBuildingAndUserSub(
buildingId,
floorNumber,
user.sub,
['rooms'],
);
if (!floor) {
throw new NotFoundException('Floor not found');
}
if (floor.rooms.length) {
throw new BadRequestException(
'A floor cannot be deleted if it has defined rooms',
);
}
await this.planRenderService.deletePlanImage(floor);
await this.buildingService.deleteFloor(floor);
return omit(floor, ['building']);
}
async updateBuildingFloor(
user: User,
body: BuildingFloorUpdateRequestDto,
buildingId: number,
floorNumber: number,
) {
const floor = await this.buildingService.getFloorByBuildingAndUserSub(
buildingId,
floorNumber,
user.sub,
['rooms'],
);
if (!floor) {
throw new NotFoundException('Floor not found');
}
Object.assign(floor, body);
this.planRenderService.renderFloor(floor);
await this.buildingService.saveFloor(floor);
return omit(floor, ['building']);
}
async addNewRoom(
user: User,
body: BuildingsCreateRoomRequestDto,
buildingId: number,
floorNumber: number,
) {
const floor = await this.buildingService.getFloorByBuildingAndUserSub(
buildingId,
floorNumber,
user.sub,
['building', 'rooms'],
);
if (!floor) {
throw new NotFoundException('Floor not found');
}
const newRoom = await this.buildingService.saveRoom({
...body,
floor,
building: floor.building,
});
floor.rooms = [...floor.rooms, newRoom];
return omit(newRoom, ['building', 'floor']);
}
async getRoomsOnFloor(user: User, buildingId: number, floorNumber: number) {
return this.buildingService.getRoomsOnFloorByBuildingAndUserSub(
buildingId,
floorNumber,
user.sub,
);
}
async getRoomsInBuilding(user: User, buildingId: number) {
const rooms = await this.buildingService.getRoomsByBuildingAndUserSub(
buildingId,
user.sub,
['floor'],
);
return rooms.map((room) => ({
...room,
floor: pick(room.floor, ['id', 'displayName', 'number']),
}));
}
async getRoom(user: User, buildingId: number, roomId: number) {
const room = await this.buildingService.getRoomByBuildingAndUserSub(
buildingId,
roomId,
user.sub,
);
if (!room) {
throw new NotFoundException('Room not found');
}
return room;
}
async updateRoom(
user: User,
body: BuildingsUpdateRoomRequestDto,
buildingId: number,
roomId: number,
) {
const room = await this.buildingService.getRoomByBuildingAndUserSub(
buildingId,
roomId,
user.sub,
);
if (!room) {
throw new NotFoundException('Room not found');
}
Object.assign(room, body);
await this.buildingService.saveRoom(room);
return room;
}
async deleteRoom(user: User, buildingId: number, roomId: number) {
const room = await this.buildingService.getRoomByBuildingAndUserSub(
buildingId,
roomId,
user.sub,
);
if (!room) {
throw new NotFoundException('Room not found');
}
await this.buildingService.deleteRoom(room);
return room;
}
async searchForBuilding(
{ searchTerm }: BuildingSearchRequestDto,
{ sub }: User,
) {
const list = await this.buildingService.searchBuilding(searchTerm, sub);
return list.map((building) => new BuildingSearchResponseDto(building));
}
}