Skip to content

Commit

Permalink
Merge pull request #75 from se-gam/feat/admin-studyroom
Browse files Browse the repository at this point in the history
feat: ์Šคํ„ฐ๋””๋ฃธ ์ •๋ณด ์—…๋ฐ์ดํŠธ api
  • Loading branch information
therealjamesjung authored Feb 11, 2025
2 parents 7a632c2 + c3d0120 commit 1b494d0
Show file tree
Hide file tree
Showing 8 changed files with 290 additions and 8 deletions.
12 changes: 6 additions & 6 deletions src/notice/notice.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import {
ApiOperation,
ApiTags,
} from '@nestjs/swagger';
import { AdminApiGuard } from 'src/auth/guard/admin.guard';
import { NoticePreviewDto } from './dto/notice-preview.dto';
import { NoticeDto } from './dto/notice.dto';
import { NoticeService } from './notice.service';
import { CreateUpdateNoticePayload } from './payload/create-update-notice.payload';
import { NoticePreviewDto } from './dto/notice-preview.dto';
import { AdminApiGuard } from 'src/auth/guard/admin.guard';

@ApiTags('๊ณต์ง€์‚ฌํ•ญ API')
@Controller('notice')
Expand All @@ -39,7 +39,7 @@ export class NoticeController {

@Version('1')
@ApiOperation({
summary: 'ํŒ์—… ๊ณต์ง€์‚ฌํ•ญ ๋“ฑ๋ก API',
summary: '[์–ด๋“œ๋ฏผ] ํŒ์—… ๊ณต์ง€์‚ฌํ•ญ ๋“ฑ๋ก API',
description: 'ํŒ์—… ๊ณต์ง€์‚ฌํ•ญ์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.',
})
@UseGuards(AdminApiGuard)
Expand All @@ -55,7 +55,7 @@ export class NoticeController {

@Version('1')
@ApiOperation({
summary: '๊ณต์ง€์‚ฌํ•ญ ์ƒ์„ฑ API',
summary: '[์–ด๋“œ๋ฏผ] ๊ณต์ง€์‚ฌํ•ญ ์ƒ์„ฑ API',
description: '๊ณต์ง€์‚ฌํ•ญ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.',
})
@UseGuards(AdminApiGuard)
Expand All @@ -73,7 +73,7 @@ export class NoticeController {

@Version('1')
@ApiOperation({
summary: '๊ณต์ง€์‚ฌํ•ญ ์ˆ˜์ • API',
summary: '[์–ด๋“œ๋ฏผ] ๊ณต์ง€์‚ฌํ•ญ ์ˆ˜์ • API',
description: '๊ณต์ง€์‚ฌํ•ญ์„ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.',
})
@UseGuards(AdminApiGuard)
Expand All @@ -92,7 +92,7 @@ export class NoticeController {

@Version('1')
@ApiOperation({
summary: '๊ณต์ง€์‚ฌํ•ญ ์‚ญ์ œ API',
summary: '[์–ด๋“œ๋ฏผ] ๊ณต์ง€์‚ฌํ•ญ ์‚ญ์ œ API',
description: '๊ณต์ง€์‚ฌํ•ญ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.',
})
@UseGuards(AdminApiGuard)
Expand Down
94 changes: 94 additions & 0 deletions src/studyroom/dto/studyroom-infp.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { ApiProperty } from '@nestjs/swagger';
import { StudyroomInfo } from '../types/studyroomInfo.type';

export class StudyroomInfoDto {
@ApiProperty({
description: '์Šคํ„ฐ๋””๋ฃธ id',
type: Number,
})
id!: number;

@ApiProperty({
description: '์Šคํ„ฐ๋””๋ฃธ ์ด๋ฆ„',
type: String,
})
name!: string;

@ApiProperty({
description: '์œ„์น˜',
type: String,
})
location!: string;
@ApiProperty({
description: '์ตœ์†Œ ์ธ์›',
type: Number,
})
minUsers!: number;

@ApiProperty({
description: '์ตœ๋Œ€ ์ธ์›',
type: Number,
})
maxUsers!: number;

@ApiProperty({
description: '์Šคํ„ฐ๋””๋ฃธ ์œ ํ˜•',
type: Boolean,
})
isCinema!: boolean;

@ApiProperty({
description: '์šด์˜ ์‹œ๊ฐ„',
type: String,
})
operatingHours!: string;

@ApiProperty({
description: '์Šคํ„ฐ๋””๋ฃธ ํƒœ๊ทธ',
type: [String],
})
tags!: string[];

@ApiProperty({
description: '์Šคํ„ฐ๋””๋ฃธ ํ™œ์„ฑํ™” ์—ฌ๋ถ€',
type: Boolean,
})
isActive!: boolean;

@ApiProperty({
description: '์Šคํ„ฐ๋””๋ฃธ ๋งˆ์ง€๋ง‰ ์—…๋ฐ์ดํŠธ ์‹œ๊ฐ„',
type: Date,
})
lastUpdatedAt!: Date;

static from(studyroom: StudyroomInfo): StudyroomInfoDto {
return {
id: studyroom.id,
name: studyroom.name,
location: studyroom.location,
minUsers: studyroom.minUsers,
maxUsers: studyroom.maxUsers,
isCinema: studyroom.isCinema,
operatingHours: studyroom.operatingHours,
tags: studyroom.tags,
isActive: studyroom.isActive,
lastUpdatedAt: studyroom.lastUpdatedAt,
};
}
}

export class StudyroomInfoListDto {
@ApiProperty({
description: '์Šคํ„ฐ๋””๋ฃธ ๋ชฉ๋ก',
type: [StudyroomInfoDto],
})
studyrooms: StudyroomInfoDto[];

static from(studyrooms: StudyroomInfo[]): StudyroomInfoListDto {
return {
studyrooms: studyrooms.map((studyroom) => {
return StudyroomInfoDto.from(studyroom);
}),
};
}
}
11 changes: 11 additions & 0 deletions src/studyroom/payload/studyroomUpdate.payload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsBoolean } from 'class-validator';

export class StudyroomUpdatePayload {
@ApiProperty({
description: 'ํ™œ์„ฑํ™” ์—ฌ๋ถ€',
example: 'true',
})
@IsBoolean()
isActive!: boolean;
}
50 changes: 50 additions & 0 deletions src/studyroom/studyroom.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
Controller,
Get,
Param,
ParseIntPipe,
Patch,
Post,
Query,
UseGuards,
Expand All @@ -12,22 +14,26 @@ import {
ApiBadRequestResponse,
ApiBearerAuth,
ApiCreatedResponse,
ApiHeader,
ApiNotFoundResponse,
ApiOkResponse,
ApiOperation,
ApiTags,
ApiUnauthorizedResponse,
} from '@nestjs/swagger';
import { CurrentUser } from 'src/auth/decorator/user.decorator';
import { AdminApiGuard } from 'src/auth/guard/admin.guard';
import { JwtAuthGuard } from 'src/auth/guard/jwt-auth.guard';
import { PasswordPayload } from 'src/auth/payload/password.payload';
import { PasswordValidationPipe } from 'src/auth/pipes/signup-validation.pipe';
import { UserInfo } from 'src/auth/types/user-info.type';
import { StudyroomInfoListDto } from './dto/studyroom-infp.dto';
import { StudyroomReservationListDto } from './dto/studyroom-reservation.dto';
import { StudyroomDto, StudyroomListDto } from './dto/studyroom.dto';
import { UserPidDto } from './dto/userPid.dto';
import { StudyroomCancelPayload } from './payload/studyroomCancel.payload';
import { StudyroomReservePayload } from './payload/studyroomReserve.payload';
import { StudyroomUpdatePayload } from './payload/studyroomUpdate.payload';
import { StudyroomUserPayload } from './payload/studyroomUserPayload.payload';
import { StudyroomQuery } from './query/studyroom.query';
import { StudyroomDateQuery } from './query/studyroomDateQuery.query';
Expand Down Expand Up @@ -170,4 +176,48 @@ export class StudyroomController {
): Promise<UserPidDto> {
return this.studyroomService.checkUserAvailablity(user.studentId, payload);
}

@Version('1')
@ApiOperation({
summary: '[์–ด๋“œ๋ฏผ] ์Šคํ„ฐ๋””๋ฃธ ์ •๋ณด ์—…๋ฐ์ดํŠธ API',
description: '์Šคํ„ฐ๋””๋ฃธ ์ •๋ณด๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ฉ๋‹ˆ๋‹ค.',
})
@ApiOkResponse({
description: '์Šคํ„ฐ๋””๋ฃธ ์ •๋ณด ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต',
})
@ApiNotFoundResponse({
description: 'ํ•ด๋‹น id์˜ ์Šคํ„ฐ๋””๋ฃธ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.',
})
@UseGuards(AdminApiGuard)
@ApiHeader({
name: 'admin-api-key',
description: 'API key for admin access',
required: true,
})
@Patch('info/:id')
async updateStudyroom(
@Param('id', ParseIntPipe) id: number,
@Body() payload: StudyroomUpdatePayload,
): Promise<void> {
return this.studyroomService.updateStudyroom(id, payload);
}

@Version('1')
@ApiOperation({
summary: '[์–ด๋“œ๋ฏผ] ์Šคํ„ฐ๋””๋ฃธ ์ •๋ณด ๋ชฉ๋ก ์กฐํšŒ API',
description: '์Šคํ„ฐ๋””๋ฃธ ์ •๋ณด ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.',
})
@ApiOkResponse({
description: '์Šคํ„ฐ๋””๋ฃธ ์ •๋ณด ๋ชฉ๋ก ์กฐํšŒ ์„ฑ๊ณต',
})
@UseGuards(AdminApiGuard)
@ApiHeader({
name: 'admin-api-key',
description: 'API key for admin access',
required: true,
})
@Get('info/all')
async getAllStudyroomInfo(): Promise<StudyroomInfoListDto> {
return this.studyroomService.getAllStudyroomInfo();
}
}
3 changes: 2 additions & 1 deletion src/studyroom/studyroom.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { StudyroomController } from './studyroom.controller';
import { StudyroomRepository } from './studyroom.repository';
import { StudyroomService } from './studyroom.service';
import { UserService } from 'src/user/user.service';
import { AuthModule } from 'src/auth/auth.module';

@Module({
imports: [ScheduleModule.forRoot()],
imports: [ScheduleModule.forRoot(), AuthModule],
controllers: [StudyroomController],
providers: [
StudyroomService,
Expand Down
99 changes: 98 additions & 1 deletion src/studyroom/studyroom.repository.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Injectable } from '@nestjs/common';
import { Injectable, NotFoundException } from '@nestjs/common';
import { StudyroomReservation as PrismaStudyroomReservation } from '@prisma/client';
import * as _ from 'lodash';
import { PrismaService } from 'src/common/services/prisma.service';
import { StudyroomUpdatePayload } from './payload/studyroomUpdate.payload';
import { StudyroomQuery } from './query/studyroom.query';
import { StudyroomDateQuery } from './query/studyroomDateQuery.query';
import { ReservationResponse } from './types/reservationResponse.type';
import { Studyroom } from './types/studyroom.type';
import { StudyroomInfo } from './types/studyroomInfo.type';
import { StudyroomReservationInfo } from './types/studyroomReservationInfo.type';

@Injectable()
Expand All @@ -17,6 +19,87 @@ export class StudyroomRepository {
return hour + ':00';
}

async getAllStudyroomInfo(): Promise<StudyroomInfo[]> {
const studyrooms = await this.prismaService.studyroom.findMany({
where: {
deletedAt: null,
},
select: {
id: true,
name: true,
location: true,
minUsers: true,
maxUsers: true,
isCinema: true,
operatingHours: true,
tags: true,
isActive: true,
},
});

const lastUpdatedSlots = await this.prismaService.studyroomSlot.groupBy({
by: ['studyroomId'],
_max: {
updatedAt: true,
},
where: {
studyroomId: {
in: studyrooms.map((studyroom) => studyroom.id),
},
},
});

return studyrooms.map((studyroom) => {
return {
...studyroom,
lastUpdatedAt: lastUpdatedSlots.find(
(slot) => slot.studyroomId === studyroom.id,
)?._max.updatedAt,
};
});
}

async getStudyroomInfoById(id: number): Promise<StudyroomInfo> {
const studyroomInfo = await this.prismaService.studyroom.findUnique({
where: {
id: id,
deletedAt: null,
},
select: {
id: true,
name: true,
location: true,
minUsers: true,
maxUsers: true,
isCinema: true,
operatingHours: true,
tags: true,
isActive: true,
},
});

if (!studyroomInfo) {
throw new NotFoundException('์Šคํ„ฐ๋””๋ฃธ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.');
}

const lastUpdatedSlot = await this.prismaService.studyroomSlot.findFirst({
where: {
studyroomId: id,
},
orderBy: {
updatedAt: 'desc',
},
select: {
updatedAt: true,
},
});

return {
...studyroomInfo,
lastUpdatedAt: lastUpdatedSlot.updatedAt,
};
}

async getAllStudyroomIds(): Promise<number[]> {
const studyrooms = await this.prismaService.studyroom.findMany({
where: {
Expand Down Expand Up @@ -377,4 +460,18 @@ export class StudyroomRepository {
}
}
}

async updateStudyroom(
id: number,
payload: StudyroomUpdatePayload,
): Promise<void> {
await this.prismaService.studyroom.update({
where: {
id,
},
data: {
isActive: payload.isActive,
},
});
}
}
Loading

0 comments on commit 1b494d0

Please sign in to comment.