room apis
This commit is contained in:
parent
db68884824
commit
e79e09065c
@ -17,18 +17,26 @@ import {
|
||||
ApiOkResponse,
|
||||
ApiBody,
|
||||
ApiNotFoundResponse,
|
||||
ApiParam,
|
||||
} from '@nestjs/swagger';
|
||||
import { User } from 'src/objects/user/user.entity';
|
||||
import { LoggedInUser } from 'src/shared/decorators/user.decorator';
|
||||
import { AuthGuard } from 'src/shared/guards/auth.guard';
|
||||
import { AppBuildingService } from './app-building.service';
|
||||
import { BuildingFloorUpdateRequestDto } from './dto/building-floor-request.dto';
|
||||
import { BuildingFloorUpdateRequestDto } from './dto/buildings-floor-request.dto';
|
||||
import { CreateBuildingRequestDto } from './dto/buildings-create-request.dto';
|
||||
import {
|
||||
BuildingFloorResponseDto,
|
||||
BuildingRoomResponseDto,
|
||||
BuildingRoomWithFloorResponseDto,
|
||||
BuildingsListResponseDto,
|
||||
BuildingsResponseDto,
|
||||
} from './dto/buildings-response.dto';
|
||||
import { BuildingsUpdateRequestDto } from './dto/buildings-update-request.dto';
|
||||
import {
|
||||
BuildingsCreateRoomRequestDto,
|
||||
BuildingsUpdateRoomRequestDto,
|
||||
} from './dto/buildings-create-room-request.dto';
|
||||
|
||||
@Controller({
|
||||
path: 'buildings',
|
||||
@ -62,6 +70,7 @@ export class AppBuildingController {
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiParam({ name: 'id', description: 'Building ID' })
|
||||
@ApiOperation({ summary: 'Get building by ID' })
|
||||
@ApiNotFoundResponse({ description: 'Building not found' })
|
||||
@ApiOkResponse({ type: BuildingsResponseDto })
|
||||
@ -72,8 +81,23 @@ export class AppBuildingController {
|
||||
return this.service.getBuildingById(user, id);
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
@ApiParam({ name: 'id', description: 'Building ID' })
|
||||
@ApiOperation({ summary: 'Update building by ID' })
|
||||
@ApiBody({ type: BuildingsUpdateRequestDto })
|
||||
@ApiNotFoundResponse({ description: 'Building not found' })
|
||||
@ApiOkResponse({ type: BuildingsListResponseDto })
|
||||
async updateBuildingById(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Body() body: BuildingsUpdateRequestDto,
|
||||
@LoggedInUser() user: User,
|
||||
): Promise<BuildingsListResponseDto> {
|
||||
return this.service.updateBuilding(user, id, body);
|
||||
}
|
||||
|
||||
@Get(':id/floors')
|
||||
@ApiOperation({ summary: 'Get building floors by ID' })
|
||||
@ApiParam({ name: 'id', description: 'Building ID' })
|
||||
@ApiOperation({ summary: 'Get building floors' })
|
||||
@ApiOkResponse({ type: BuildingFloorResponseDto, isArray: true })
|
||||
async getBuildingFloorsById(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@ -83,7 +107,9 @@ export class AppBuildingController {
|
||||
}
|
||||
|
||||
@Get(':id/floors/:number')
|
||||
@ApiOperation({ summary: 'Get building floors by ID' })
|
||||
@ApiParam({ name: 'id', description: 'Building ID' })
|
||||
@ApiParam({ name: 'number', description: 'Floor number' })
|
||||
@ApiOperation({ summary: 'Get building floor by floor number' })
|
||||
@ApiOkResponse({ type: BuildingFloorResponseDto })
|
||||
async getBuildingFloorByIdByNumber(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@ -94,8 +120,10 @@ export class AppBuildingController {
|
||||
}
|
||||
|
||||
@Patch(':id/floors/:number')
|
||||
@ApiParam({ name: 'id', description: 'Building ID' })
|
||||
@ApiParam({ name: 'number', description: 'Floor number' })
|
||||
@ApiBody({ type: BuildingFloorUpdateRequestDto })
|
||||
@ApiOperation({ summary: 'Update building floor' })
|
||||
@ApiOperation({ summary: 'Update building floor by floor number' })
|
||||
@ApiOkResponse({ type: BuildingFloorResponseDto })
|
||||
async updateBuildingFloorByIdByNumber(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@ -105,4 +133,71 @@ export class AppBuildingController {
|
||||
): Promise<BuildingFloorResponseDto> {
|
||||
return this.service.updateBuildingFloor(user, body, id, floor);
|
||||
}
|
||||
|
||||
@Post(':id/floors/:number/rooms')
|
||||
@ApiParam({ name: 'id', description: 'Building ID' })
|
||||
@ApiParam({ name: 'number', description: 'Floor number' })
|
||||
@ApiBody({ type: BuildingsCreateRoomRequestDto })
|
||||
@ApiOperation({ summary: 'Create new room on floor' })
|
||||
@ApiOkResponse({ type: BuildingRoomResponseDto })
|
||||
async createNewRoom(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Param('number', ParseIntPipe) floor: number,
|
||||
@Body() body: BuildingsCreateRoomRequestDto,
|
||||
@LoggedInUser() user: User,
|
||||
): Promise<BuildingRoomResponseDto> {
|
||||
return this.service.addNewRoom(user, body, id, floor);
|
||||
}
|
||||
|
||||
@Get(':id/floors/:number/rooms')
|
||||
@ApiParam({ name: 'id', description: 'Building ID' })
|
||||
@ApiParam({ name: 'number', description: 'Floor number' })
|
||||
@ApiOperation({ summary: 'Get rooms on floor' })
|
||||
@ApiOkResponse({ type: BuildingRoomResponseDto, isArray: true })
|
||||
async getRoomsOnFloor(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Param('number', ParseIntPipe) floor: number,
|
||||
@LoggedInUser() user: User,
|
||||
): Promise<BuildingRoomResponseDto[]> {
|
||||
return this.service.getRoomsOnFloor(user, id, floor);
|
||||
}
|
||||
|
||||
@Get(':id/rooms')
|
||||
@ApiParam({ name: 'id', description: 'Building ID' })
|
||||
@ApiOperation({ summary: 'Get rooms in building' })
|
||||
@ApiOkResponse({ type: BuildingRoomWithFloorResponseDto, isArray: true })
|
||||
async getRooms(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@LoggedInUser() user: User,
|
||||
): Promise<BuildingRoomWithFloorResponseDto[]> {
|
||||
return this.service.getRoomsInBuilding(user, id);
|
||||
}
|
||||
|
||||
@Get(':id/rooms/:roomId')
|
||||
@ApiParam({ name: 'id', description: 'Building ID' })
|
||||
@ApiParam({ name: 'roomId', description: 'Room ID' })
|
||||
@ApiOperation({ summary: 'Get room by ID' })
|
||||
@ApiOkResponse({ type: BuildingRoomResponseDto })
|
||||
async getRoomById(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Param('roomId', ParseIntPipe) roomId: number,
|
||||
@LoggedInUser() user: User,
|
||||
): Promise<BuildingRoomResponseDto> {
|
||||
return this.service.getRoom(user, id, roomId);
|
||||
}
|
||||
|
||||
@Patch(':id/rooms/:roomId')
|
||||
@ApiParam({ name: 'id', description: 'Building ID' })
|
||||
@ApiParam({ name: 'roomId', description: 'Room ID' })
|
||||
@ApiBody({ type: BuildingsUpdateRoomRequestDto })
|
||||
@ApiOperation({ summary: 'Update room by ID' })
|
||||
@ApiOkResponse({ type: BuildingRoomResponseDto })
|
||||
async updateRoomById(
|
||||
@Param('id', ParseIntPipe) id: number,
|
||||
@Param('roomId', ParseIntPipe) roomId: number,
|
||||
@Body() body: BuildingsUpdateRoomRequestDto,
|
||||
@LoggedInUser() user: User,
|
||||
): Promise<BuildingRoomResponseDto> {
|
||||
return this.service.updateRoom(user, body, id, roomId);
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,13 @@ 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 } from './dto/building-floor-request.dto';
|
||||
import { BuildingFloorUpdateRequestDto } 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';
|
||||
|
||||
@Injectable()
|
||||
export class AppBuildingService {
|
||||
@ -49,6 +54,27 @@ export class AppBuildingService {
|
||||
return omit(newBuilding, ['groups']);
|
||||
}
|
||||
|
||||
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,
|
||||
@ -110,4 +136,88 @@ export class AppBuildingService {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
18
src/app-building/dto/buildings-create-room-request.dto.ts
Normal file
18
src/app-building/dto/buildings-create-room-request.dto.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { PartialType, PickType } from '@nestjs/swagger';
|
||||
import { IsString } from 'class-validator';
|
||||
import { Room } from 'src/objects/building/entities/room.entity';
|
||||
|
||||
export class BuildingsCreateRoomRequestDto extends PickType(Room, [
|
||||
'displayName',
|
||||
'plan',
|
||||
]) {
|
||||
@IsString()
|
||||
displayName: string;
|
||||
|
||||
@IsString()
|
||||
plan: string;
|
||||
}
|
||||
|
||||
export class BuildingsUpdateRoomRequestDto extends PartialType(
|
||||
BuildingsCreateRoomRequestDto,
|
||||
) {}
|
@ -1,9 +1,24 @@
|
||||
import { ApiProperty, OmitType } from '@nestjs/swagger';
|
||||
import { ApiProperty, OmitType, PickType } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import { Building } from 'src/objects/building/entities/building.entity';
|
||||
import { Floor } from 'src/objects/building/entities/floor.entity';
|
||||
import { Room } from 'src/objects/building/entities/room.entity';
|
||||
|
||||
export class BuildingMinimalFloorResponseDto extends PickType(Floor, [
|
||||
'id',
|
||||
'number',
|
||||
'displayName',
|
||||
]) {}
|
||||
|
||||
export class BuildingRoomWithFloorResponseDto extends OmitType(Room, [
|
||||
'floor',
|
||||
'building',
|
||||
]) {
|
||||
@ApiProperty({ type: BuildingMinimalFloorResponseDto })
|
||||
@Type(() => BuildingMinimalFloorResponseDto)
|
||||
floor: BuildingMinimalFloorResponseDto;
|
||||
}
|
||||
|
||||
export class BuildingRoomResponseDto extends OmitType(Room, [
|
||||
'floor',
|
||||
'building',
|
||||
|
6
src/app-building/dto/buildings-update-request.dto.ts
Normal file
6
src/app-building/dto/buildings-update-request.dto.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { PartialType, PickType } from '@nestjs/swagger';
|
||||
import { Building } from 'src/objects/building/entities/building.entity';
|
||||
|
||||
export class BuildingsUpdateRequestDto extends PartialType(
|
||||
PickType(Building, ['address', 'color', 'displayName']),
|
||||
) {}
|
@ -1,4 +1,5 @@
|
||||
import { Controller, Get, Inject } from '@nestjs/common';
|
||||
import { ApiOperation } from '@nestjs/swagger';
|
||||
import { AppService } from './app.service';
|
||||
|
||||
@Controller()
|
||||
@ -15,6 +16,7 @@ export class AppController {
|
||||
}
|
||||
|
||||
@Get('/.well-known/jwks.json')
|
||||
@ApiOperation({ summary: 'JWT public key in JWK format' })
|
||||
getJWKs() {
|
||||
return {
|
||||
keys: [this.jwks],
|
||||
|
@ -67,6 +67,74 @@ export class BuildingService {
|
||||
});
|
||||
}
|
||||
|
||||
async getRoomByBuildingAndUserSub(
|
||||
buildingId: number,
|
||||
roomId: number,
|
||||
sub: string,
|
||||
relations = [],
|
||||
) {
|
||||
return this.roomRepository.findOne({
|
||||
where: {
|
||||
id: roomId,
|
||||
building: {
|
||||
id: buildingId,
|
||||
groups: {
|
||||
members: {
|
||||
sub,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
relations,
|
||||
});
|
||||
}
|
||||
|
||||
async getRoomsOnFloorByBuildingAndUserSub(
|
||||
buildingId: number,
|
||||
floorNumber: number,
|
||||
sub: string,
|
||||
relations = [],
|
||||
) {
|
||||
return this.roomRepository.find({
|
||||
where: {
|
||||
floor: {
|
||||
number: floorNumber,
|
||||
building: {
|
||||
id: buildingId,
|
||||
groups: {
|
||||
members: {
|
||||
sub,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
relations,
|
||||
});
|
||||
}
|
||||
|
||||
async getRoomsByBuildingAndUserSub(
|
||||
buildingId: number,
|
||||
sub: string,
|
||||
relations = [],
|
||||
) {
|
||||
return this.roomRepository.find({
|
||||
where: {
|
||||
floor: {
|
||||
building: {
|
||||
id: buildingId,
|
||||
groups: {
|
||||
members: {
|
||||
sub,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
relations,
|
||||
});
|
||||
}
|
||||
|
||||
async getFloorsByBuildingAndUserSub(
|
||||
buildingId: number,
|
||||
sub: string,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
@ -11,24 +12,31 @@ import { Floor } from './floor.entity';
|
||||
|
||||
@Entity()
|
||||
export class Room {
|
||||
@ApiProperty()
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@ApiProperty({ type: () => Building })
|
||||
@ManyToOne(() => Building)
|
||||
building: Building;
|
||||
|
||||
@ApiProperty({ type: () => Floor })
|
||||
@ManyToOne(() => Floor)
|
||||
floor: Floor;
|
||||
|
||||
@ApiProperty()
|
||||
@Column()
|
||||
displayName: string;
|
||||
|
||||
@ApiProperty()
|
||||
@Column()
|
||||
plan: string;
|
||||
|
||||
@ApiProperty()
|
||||
@CreateDateColumn()
|
||||
createdAt: Date;
|
||||
|
||||
@ApiProperty()
|
||||
@UpdateDateColumn()
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user