Skip to content

엔티티 리팩터링 갈무리 #25

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 5, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 5 additions & 19 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,23 @@
## 업데이트 유형

- [ ] Hot Fix
- [ ] Release
- [ ] Develop
- [ ] Others

## 업데이트 개요

* Fix # (issue)
* Feature # (issue)
[여기에 PR 한줄 요약 작성, 대상 이슈번호 작성.]

[여기에 PR 한줄 요약 작성, 대상 이슈번호 작성.]

## 업데이트 요약
업데이트 내역 작성

## 새로운 정책
세부 변경 사항 작성

## 해결한 문제
해결한 문제 등 이슈

## 미해결 문제
미해결 이슈, 발견한 이슈

## 테스트
- [ ] 유닛 테스트
- [ ] 빌드 테스트 (통합 테스트)
- [ ] 기타 유효성 테스트
업데이트 내역 작성

## 수정 사항 진단

- [ ] 코드가 이 프로젝트의 스타일 지침을 따릅니다.
- [ ] 코드에 대한 자체 리뷰를 수행했습니다.
- [ ] 변경 내역에 대해 주석을 작성했습니다.
- [ ] 해당 PR에 대한 문서를 변경했습니다.
- [ ] 기능, 정책, 수정 사항, 이슈에 대한 테스트 코드를 추가했습니다.
- [ ] 변경 내용이 로컬 개발환경에서의 테스트를 통과했습니다.
- [ ] 모든 종속 변경 사항이 병합되어 다운스트림 모듈에 게시되었습니다.
2 changes: 0 additions & 2 deletions src/entities/contest.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ export class Contest {
this.endTime = endTime;
this.badge = badge;
this.background = background;

return this;
}
}

Expand Down
23 changes: 16 additions & 7 deletions src/entities/group.entity.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
import { Prop, SchemaFactory } from '@nestjs/mongoose';
import { IsMongoId, IsString } from 'class-validator';
import { ObjectId } from 'mongodb';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';

export type GroupDocument = HydratedDocument<Group>;

@Schema()
export class Group {
@Prop({ type: ObjectId })
@IsMongoId()
id: string;

@Prop({ required: true })
@IsString()
name: string;

@Prop()
@IsString()
description: string;

@Prop({ type: [String], ref: 'Poker' })
pokers: string[];

constructor(id: string, name: string, description: string, pokers: string[]) {
this.id = id;
this.name = name;
this.description = description;
this.pokers = pokers;
}

static fromDocument(groupDocument: GroupDocument): Group {
return new Group(groupDocument._id.toString(), groupDocument.name, groupDocument.description, groupDocument.pokers);
}
}

export const GroupSchema = SchemaFactory.createForClass(Group);
44 changes: 43 additions & 1 deletion src/entities/participant.entity.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,56 @@
import { SchemaFactory } from '@nestjs/mongoose';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';

import { Problem } from './problem.entity';

export type ParticipantDocument = HydratedDocument<Participant>;

@Schema()
export class Participant {
@Prop({ required: true })
handle: string;

@Prop({ required: true })
profileImage: string;

@Prop({ required: true })
snapshot: number[];

@Prop({ required: true })
point: number;

@Prop({ required: true })
goal: number;

@Prop({ required: true })
result: Problem[];

constructor(
handle: string,
profileImage: string,
snapshot: number[],
point: number,
goal: number,
result: Problem[],
) {
this.handle = handle;
this.profileImage = profileImage;
this.snapshot = snapshot;
this.point = point;
this.goal = goal;
this.result = result;
}

static fromDocument(participantDocument: ParticipantDocument): Participant {
return new Participant(
participantDocument.handle,
participantDocument.profileImage,
participantDocument.snapshot,
participantDocument.point,
participantDocument.goal,
participantDocument.result,
);
}
}

export const ParticipantSchema = SchemaFactory.createForClass(Participant);
29 changes: 25 additions & 4 deletions src/entities/poker.entity.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { Prop, SchemaFactory } from '@nestjs/mongoose';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';

import { Participant } from './participant.entity';

export type PokerDocument = HydratedDocument<Poker>;

@Schema()
export class Poker {
@Prop()
id: string;

@Prop()
@Prop({ required: true })
name: string;

@Prop()
Expand All @@ -15,8 +18,26 @@ export class Poker {
@Prop()
startTime: Date;

@Prop()
@Prop({ required: true })
endTime: Date;

constructor(id: string, name: string, participants: Participant[], startTime: Date, endTime: Date) {
this.id = id;
this.name = name;
this.participants = participants;
this.startTime = startTime;
this.endTime = endTime;
}

static fromDocument(pokerDocument: PokerDocument): Poker {
return new Poker(
pokerDocument._id.toString(),
pokerDocument.name,
pokerDocument.participants,
pokerDocument.startTime,
pokerDocument.endTime,
);
}
}

export const PokerSchema = SchemaFactory.createForClass(Poker);
18 changes: 13 additions & 5 deletions src/entities/problem.entity.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import { SchemaFactory } from '@nestjs/mongoose';
import { Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';

export type ProblemDocument = HydratedDocument<Problem>;

@Schema()
export class Problem {
problemId: number;
titleKo: string;
level: number;

constructor(problem: { problemId: number; titleKo: string; level: number }) {
this.problemId = problem.problemId;
this.titleKo = problem.titleKo;
this.level = problem.level;
constructor(problemId: number, titleKo: string, level: number) {
this.problemId = problemId;
this.titleKo = titleKo;
this.level = level;
}

static fromDocument(problemDocument: ProblemDocument): Problem {
return new Problem(problemDocument.problemId, problemDocument.titleKo, problemDocument.level);
}
}

Expand Down
26 changes: 13 additions & 13 deletions src/modules/group/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,26 @@ export class GroupRepository {
private readonly groupModel: Model<Group>,
) {}

create(createGroupDto: CreateGroupDto): Promise<Group> {
return this.groupModel.create(createGroupDto);
async create(createGroupDto: CreateGroupDto): Promise<Group> {
return Group.fromDocument(await this.groupModel.create(createGroupDto));
}

getAll(): Promise<Group[]> {
return this.groupModel.find().exec();
async getAll(): Promise<Group[]> {
const groupDocs = await this.groupModel.find().exec();
if (!groupDocs) {
throw new NotFoundException('No groups found');
}

return groupDocs.map((document) => Group.fromDocument(document));
}

async get(groupId: string): Promise<Group> {
const group = await this.groupModel.findById(groupId);
if (!group) {
const groupDoc = await this.groupModel.findById(groupId);
if (!groupDoc) {
throw new NotFoundException(`Group not found: ${groupId}`);
}
return group;
}

validate(groupId: string, group: Group): void {
if (!group) {
throw new NotFoundException(`Group not found: ${groupId}`);
}
return Group.fromDocument(groupDoc);
}

deleteAll() {
Expand All @@ -43,6 +43,6 @@ export class GroupRepository {
throw new NotFoundException(`Group not found: ${groupId}`);
}

return updatedGroup;
return Group.fromDocument(updatedGroup);
}
}
12 changes: 4 additions & 8 deletions src/modules/poker/controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Body, Controller, Delete, Get, Param, Post, Query } from '@nestjs/common';
import { ApiOperation, ApiParam, ApiQuery, ApiTags } from '@nestjs/swagger';
import { Body, Controller, Delete, Get, Param, Post } from '@nestjs/common';
import { ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger';

import { CreatePokerDto } from './dto/create-poker.dto';
import { PokerService } from './service';
Expand All @@ -11,12 +11,8 @@ export class PokerController {

@Post()
@ApiOperation({ summary: '포커 생성' })
@ApiQuery({
name: 'name',
description: '포커 이름',
})
async create(@Query('name') name: string, @Body() createPokerDto: CreatePokerDto) {
return this.pokerService.create(name, createPokerDto);
async create(@Body() createPokerDto: CreatePokerDto) {
return this.pokerService.create(createPokerDto);
}

@Get()
Expand Down
6 changes: 6 additions & 0 deletions src/modules/poker/dto/create-poker.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ export class CreatePokerDto {
})
groupId: string;

@ApiProperty({
description: '포커 이름',
default: 'SCCC 포커',
})
name: string;

@ApiProperty({
description: '게임에 참여하는 사람들의 목록',
default: [
Expand Down
52 changes: 27 additions & 25 deletions src/modules/poker/repository.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,49 @@
import { Participant } from '@entities/participant.entity';
import { Poker } from '@entities/poker.entity';
import { CreatePokerDto } from '@modules/poker/dto/create-poker.dto';
import { Inject, Injectable } from '@nestjs/common';
import { Model } from 'mongoose';

import { GroupRepository } from '../group/repository';

@Injectable()
export class PokerRepository {
constructor(
@Inject('POKER_MODEL') private readonly pokerModel: Model<Poker>,
private readonly groupRepository: GroupRepository,
) {}

create(poker: Poker): Promise<Poker> {
const createdPoker = new this.pokerModel(poker);
return createdPoker.save();
constructor(@Inject('POKER_MODEL') private readonly pokerModel: Model<Poker>) {}

async create(createPokerDto: CreatePokerDto, participants: Participant[]): Promise<Poker> {
const pokerDoc = new this.pokerModel({
name: createPokerDto.name,
participants: participants,
startTime: new Date(),
endTime: createPokerDto.endDate,
});

return Poker.fromDocument(await pokerDoc.save());
}

getAll(): Promise<Poker[]> {
return this.pokerModel.find();
async getAll(): Promise<Poker[]> {
const pokerDocs = await this.pokerModel.find().exec();
if (!pokerDocs) {
throw new Error('No pokers found');
}

return pokerDocs.map((document) => Poker.fromDocument(document));
}

async get(id: string): Promise<Poker> {
const poker = (await this.pokerModel.findById(id)) as Poker;
if (!poker) {
const pokerDoc = await this.pokerModel.findById(id);
if (!pokerDoc) {
throw new Error(`Poker not found: ${id.toString()}`);
}

return poker;
return Poker.fromDocument(pokerDoc);
}

validate(id: string, poker: Poker): void {
if (!poker) {
async update(id: string, poker: Poker): Promise<Poker> {
const pokerDoc = await this.pokerModel.findByIdAndUpdate(id, poker);
Copy link
Preview

Copilot AI Apr 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findByIdAndUpdate by default returns the pre-update document. Consider adding the option { new: true } to return the updated document, ensuring that Poker.fromDocument reflects the latest changes.

Suggested change
const pokerDoc = await this.pokerModel.findByIdAndUpdate(id, poker);
const pokerDoc = await this.pokerModel.findByIdAndUpdate(id, poker, { new: true });

Copilot uses AI. Check for mistakes.

if (!pokerDoc) {
throw new Error(`Poker not found: ${id}`);
}
}

update(id: string, poker: Poker): void {
this.pokerModel.updateOne(
{
_id: id,
},
poker,
);
return Poker.fromDocument(pokerDoc);
}

async deleteAll(): Promise<void> {
Expand Down
Loading