Skip to content

Commit

Permalink
Merge pull request #365 from Kimsoo0119/feature-chat
Browse files Browse the repository at this point in the history
Feature(hyunsoo/chat): 채팅방 초대 거절 기능 구현 #92
  • Loading branch information
khabh authored Feb 22, 2023
2 parents abbba7e + d89c210 commit b2041b2
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 40 deletions.
87 changes: 70 additions & 17 deletions main-project/src/chats/chats-controller.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { BoardsRepository } from 'src/boards/repository/board.repository';
import { NoticeType } from 'src/common/configs/notice-type.config';
import { UserType } from 'src/common/configs/user-type.config';
import { NoticeChats } from 'src/notices/entity/notice-chat.entity';
import { Notices } from 'src/notices/entity/notices.entity';
import { NoticeChatsRepository } from 'src/notices/repository/notices-chats.repository';
import { NoticesRepository } from 'src/notices/repository/notices.repository';
import { EntityManager, Timestamp } from 'typeorm';
Expand Down Expand Up @@ -295,13 +296,12 @@ export class ChatsControllerService {
? NoticeType.INVITE_HOST
: NoticeType.INVITE_GUEST;

const noticeChat: NoticeChats =
await this.noticeChatsRepository.getNoticeChat({
userNo,
targetUserNo,
type: noticeType,
chatRoomNo,
});
const noticeChat: Notices = await this.noticeChatsRepository.getNotice({
userNo,
targetUserNo,
type: noticeType,
chatRoomNo,
});
if (noticeChat) {
throw new BadRequestException('이미 초대를 보낸 상태입니다.');
}
Expand Down Expand Up @@ -332,15 +332,17 @@ export class ChatsControllerService {

async acceptInvitation(
userNo: number,
manager: EntityManager,
chatRoomNo: number,
{ senderNo, receiverNo, type }: AcceptInvitationDto,
{ senderNo, type }: AcceptInvitationDto,
): Promise<void> {
if (userNo !== receiverNo) {
throw new BadRequestException(`초대받은 유저만 수락할 수 있습니다.`);
}
if (type !== NoticeType.INVITE_HOST && type !== NoticeType.INVITE_GUEST) {
throw new BadRequestException(`잘못된 Notice 타입입니다.`);
}
const noticeNo: number = await this.checkChatNotice(
userNo,
senderNo,
chatRoomNo,
type,
);

const userType =
type === NoticeType.INVITE_HOST ? UserType.HOST : UserType.GUEST;

Expand All @@ -356,15 +358,66 @@ export class ChatsControllerService {
isNeededUser: false,
});

await this.joinChatRoom({ userNo, chatRoomNo, userType });
await this.joinChatRoom(manager, { userNo, chatRoomNo, userType });
await this.deleteNotice(manager, noticeNo);
}

private async checkChatNotice(
userNo: number,
senderNo: number,
chatRoomNo: number,
type: number,
): Promise<number> {
const notice: Notices = await this.noticeChatsRepository.getNotice({
userNo,
targetUserNo: senderNo,
type,
chatRoomNo,
});
if (!notice) {
throw new NotFoundException(`초대 정보가 존재하지 않습니다.`);
}
return notice.no;
}

private async joinChatRoom(chatUserInfo: ChatUser): Promise<void> {
private async joinChatRoom(
manager: EntityManager,
chatUserInfo: ChatUser,
): Promise<void> {
const user = [chatUserInfo];

const affectedRow = await this.chatUsersRepository.createChatUsers(user);
const affectedRow: number = await manager
.getCustomRepository(ChatUsersRepository)
.createChatUsers(user);
if (!affectedRow) {
throw new InternalServerErrorException(`채팅방 유저 추가 오류입니다.`);
}
}

private async deleteNotice(manager: EntityManager, noticeNo: number) {
const deleteResult: number = await manager
.getCustomRepository(NoticesRepository)
.deleteNotice(noticeNo);
if (!deleteResult) {
throw new InternalServerErrorException(`알림 삭제에 실패했습니다.`);
}
}

async rejecteInvitation(
manager: EntityManager,
userNo: number,
chatRoomNo: number,
{ senderNo, type }: AcceptInvitationDto,
): Promise<void> {
const noticeNo: number = await this.checkChatNotice(
userNo,
senderNo,
chatRoomNo,
type,
);
if (!noticeNo) {
throw new NotFoundException(`초대 정보가 존재하지 않습니다.`);
}
await this.deleteNotice(manager, noticeNo);
}
}
26 changes: 25 additions & 1 deletion main-project/src/chats/chats.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { APIResponse } from 'src/common/interface/interface';
import { TransactionInterceptor } from 'src/common/interceptor/transaction-interceptor';
import { TransactionDecorator } from 'src/common/decorator/transaction-manager.decorator';
import { EntityManager } from 'typeorm';
import { UseGuards } from '@nestjs/common/decorators';
import { Delete, UseGuards } from '@nestjs/common/decorators';
import { JwtAuthGuard } from 'src/common/guards/jwt-auth.guard';
import { GetUser } from 'src/common/decorator/get-user.decorator';
import { ApiGetPreviousChatLog } from './swagger/get-previous-chat-log.decorator';
Expand All @@ -28,6 +28,8 @@ import { ApiInviteUser } from './swagger/invite-user.decorator';
import { ApiAcceptInvitation } from './swagger/accept-invitation.decorator';
import { APiUploadFile } from './swagger/upload-file.decorator';
import { ApiCreateChatRoom } from './swagger/create-chat-room.decorator';
import { ApiRejecteInvitation } from './swagger/rejected-invitation.decorator';


@Controller('chats')
@ApiTags('채팅 APi')
Expand Down Expand Up @@ -111,13 +113,16 @@ export class ChatsController {
@Patch('/:chatRoomNo/invitation')
@ApiAcceptInvitation()
@UseGuards(JwtAuthGuard)
@UseInterceptors(TransactionInterceptor)
async acceptInvitation(
@GetUser() userNo: number,
@TransactionDecorator() manager: EntityManager,
@Param('chatRoomNo', ParseIntPipe) chatRoomNo: number,
@Body() invitation: AcceptInvitationDto,
): Promise<APIResponse> {
await this.chatControllerService.acceptInvitation(
userNo,
manager,
chatRoomNo,
invitation,
);
Expand All @@ -127,6 +132,25 @@ export class ChatsController {
};
}

@Delete('/:chatRoomNo/invitation')
@ApiRejecteInvitation()
@UseGuards(JwtAuthGuard)
@UseInterceptors(TransactionInterceptor)
async rejecteInvitation(
@GetUser() userNo: number,
@TransactionDecorator() manager: EntityManager,
@Param('chatRoomNo', ParseIntPipe) chatRoomNo: number,
@Body() invitation: AcceptInvitationDto,
): Promise<APIResponse> {
await this.chatControllerService.rejecteInvitation(
manager,
userNo,
chatRoomNo,
invitation,
);
return { msg: '채팅방 초대 거절 성공' };
}

@Post('/:chatRoomNo/files')
@APiUploadFile()
@UseInterceptors(FilesInterceptor('files', 10)) // 10은 최대파일개수
Expand Down
4 changes: 0 additions & 4 deletions main-project/src/chats/dto/accept-invitation.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ export class AcceptInvitationDto {
@IsNotEmpty()
senderNo: number;

@IsNumber()
@IsNotEmpty()
receiverNo: number;

@IsNumber()
@IsNotEmpty()
type: number;
Expand Down
14 changes: 5 additions & 9 deletions main-project/src/chats/swagger/accept-invitation.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ import {
ApiOkResponse,
ApiOperation,
} from '@nestjs/swagger';
import { number } from 'joi';
import { SwaggerApiResponse } from 'src/common/swagger/api-response.swagger';

export function ApiAcceptInvitation() {
return applyDecorators(
ApiOperation({
summary: '채팅방 초대 수락 ',
description: '유저 번호, 타입, 채팅방 번호를 통해 초대 수락',
description: '유저 번호, notice타입, 채팅방 번호를 통해 초대 수락',
}),
ApiBearerAuth(),
ApiBody({
Expand All @@ -28,13 +27,6 @@ export function ApiAcceptInvitation() {
nullable: false,
description: '초대한 유저의 userNo',
},
receiverNo: {
type: 'number',
minLength: 1,
example: 9,
nullable: false,
description: '초대받은 유저의 userNo',
},
type: {
type: 'number',
maxLength: 1,
Expand All @@ -49,6 +41,10 @@ export function ApiAcceptInvitation() {
),
ApiNotFoundResponse(
SwaggerApiResponse.exception([
{
name: 'noticeNotFound',
example: { msg: '초대 정보가 존재하지 않습니다.' },
},
{
name: 'chatRoomNotFound',
example: { msg: '존재하지 않는 채팅방입니다.' },
Expand Down
50 changes: 50 additions & 0 deletions main-project/src/chats/swagger/rejected-invitation.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { applyDecorators } from '@nestjs/common';
import {
ApiBearerAuth,
ApiBody,
ApiNotFoundResponse,
ApiOkResponse,
ApiOperation,
} from '@nestjs/swagger';
import { SwaggerApiResponse } from 'src/common/swagger/api-response.swagger';

export function ApiRejecteInvitation() {
return applyDecorators(
ApiOperation({
summary: '채팅방 초대 거절',
description: '유저 번호, notice타입, 채팅방 번호를 통해 초대 거절',
}),
ApiBearerAuth(),
ApiBody({
schema: {
type: 'object',
properties: {
senderNo: {
type: 'number',
minLength: 1,
example: 9,
nullable: false,
description: '초대한 유저의 userNo',
},
type: {
type: 'number',
maxLength: 1,
nullable: false,
description: '알람 typeNo',
},
},
},
}),
ApiOkResponse(
SwaggerApiResponse.success('채팅방 초대 거절', '채팅방 초대 거절 성공'),
),
ApiNotFoundResponse(
SwaggerApiResponse.exception([
{
name: 'noticeNotFound',
example: { msg: '초대 정보가 존재하지 않습니다.' },
},
]),
),
);
}
17 changes: 8 additions & 9 deletions main-project/src/notices/repository/notices-chats.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from 'src/chats/interface/chat.interface';
import { EntityRepository, InsertResult, Repository } from 'typeorm';
import { NoticeChats } from '../entity/notice-chat.entity';
import { Notices } from '../entity/notices.entity';
import { NoticeChatsInfo } from '../interface/notice.interface';
``;
@EntityRepository(NoticeChats)
Expand All @@ -28,22 +29,20 @@ export class NoticeChatsRepository extends Repository<NoticeChats> {
}
}

async getNoticeChat(
ChatRoomInvitation: ChatRoomInvitation,
): Promise<NoticeChats> {
async getNotice(ChatRoomInvitation: ChatRoomInvitation): Promise<Notices> {
try {
const noticeChat: NoticeChats = await this.createQueryBuilder(
'notice_chats',
)
const notice: Notices = await this.createQueryBuilder('notice_chats')
.leftJoin('notice_chats.noticeNo', 'notices')
.select(['notices.* '])
.select(['notices.no as no '])
.where(
'notice_chats.chatRoomNo = :chatRoomNo AND notices.userNo = :userNo AND notices.type = :type AND notices.targetUserNo = :targetUserNo',
`notice_chats.chatRoomNo = :chatRoomNo
AND notices.userNo = :userNo AND notices.type = :type
AND notices.targetUserNo = :targetUserNo`,
ChatRoomInvitation,
)
.getRawOne();

return noticeChat;
return notice;
} catch (error) {
throw new InternalServerErrorException(
`${error} 채팅 알람 확인 에러(checkNoticeChat): 알 수 없는 서버 오류입니다.`,
Expand Down

0 comments on commit b2041b2

Please sign in to comment.