Skip to content

Commit

Permalink
feat: 태스크 생성, 수정 API에 우선순위 데이터(rankValue)추가
Browse files Browse the repository at this point in the history
- task 엔티티
  - rankValue 프로퍼티 추가
  - task의 rankValue가 project에서 고유하도록 유니크 제약조건 추가
- project 레포지토리, project 서비스의 task 관련 update, create 메서드에 rankValue정보 추가
- task 컨트롤러에 rankValue 정보 추가
- task DTO에 rankValue 정보 추가
- E2E 테스트
  - 태스크, init 백로그 테스트에 태스크의 rankValue정보 추가
  - 태스크 테스트에 같은 스토리 내 rankValue 업데이트 테스트 추가
  - 태스크 테스트에 다른 스토리으로의 rankValue 업데이트 테스트 추가
  • Loading branch information
choyoungwoo9 committed Jul 31, 2024
1 parent 7c19a12 commit 05fcf8a
Show file tree
Hide file tree
Showing 10 changed files with 212 additions and 1 deletion.
3 changes: 3 additions & 0 deletions backend/src/project/dto/task/TaskCreateNotify.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class TaskDto {
status: TaskStatus;
assignedMemberId: number|null;
storyId: number;
rankValue: string;

static of(task: Task) {
const dto = new TaskDto();
dto.id = task.id;
Expand All @@ -18,6 +20,7 @@ class TaskDto {
dto.status = task.status;
dto.assignedMemberId = task.assignedMemberId;
dto.storyId = task.storyId;
dto.rankValue = task.rankValue;
return dto;
}
}
Expand Down
6 changes: 6 additions & 0 deletions backend/src/project/dto/task/TaskCreateRequest.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
ValidationOptions,
ValidationArguments,
} from 'class-validator';
import { IsLexoRankValue } from 'src/common/decorator/IsLexoRankValue';

export function IsOneDecimalPlace(validationOptions?: ValidationOptions) {
return function (object: Object, propertyName: string) {
Expand Down Expand Up @@ -61,6 +62,11 @@ class Task {

@IsInt()
storyId: number;

@IsString()
@IsLexoRankValue()
@Length(2, 255)
rankValue: string;
}

export class TaskCreateRequestDto {
Expand Down
5 changes: 5 additions & 0 deletions backend/src/project/dto/task/TaskUpdateNotify.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class Task {
actualTime?: number;
status?: TaskStatus;
assignedMemberId?: number;
rankValue?: string;

static of(
id: number,
Expand All @@ -17,6 +18,7 @@ class Task {
actualTime: number | undefined,
status: TaskStatus | undefined,
assignedMemberId: number | undefined,
rankValue: string | undefined,
) {
const dto = new Task();
dto.id = id;
Expand All @@ -26,6 +28,7 @@ class Task {
if (actualTime !== undefined) dto.actualTime = actualTime;
if (status !== undefined) dto.status = status;
if (assignedMemberId !== undefined) dto.assignedMemberId = assignedMemberId;
if (rankValue !== undefined) dto.rankValue = rankValue;
return dto;
}
}
Expand All @@ -43,6 +46,7 @@ export class TaskUpdateNotifyDto {
actualTime: number | undefined,
status: TaskStatus | undefined,
assignedMemberId: number | undefined,
rankValue: string | undefined,
) {
const dto = new TaskUpdateNotifyDto();
dto.domain = 'task';
Expand All @@ -55,6 +59,7 @@ export class TaskUpdateNotifyDto {
actualTime,
status,
assignedMemberId,
rankValue,
);
return dto;
}
Expand Down
8 changes: 8 additions & 0 deletions backend/src/project/dto/task/TaskUpdateRequest.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Matches,
ValidateNested,
} from 'class-validator';
import { IsLexoRankValue } from 'src/common/decorator/IsLexoRankValue';
import { TaskStatus } from 'src/project/entity/task.entity';
import { AtLeastOneProperty } from 'src/project/util/validation.util';
import { IsOneDecimalPlace } from './TaskCreateRequest.dto';
Expand All @@ -22,6 +23,7 @@ class Task {
'actualTime',
'assignedMemberId',
'status',
'rankValue',
])
id: number;

Expand Down Expand Up @@ -49,6 +51,12 @@ class Task {
@IsOptional()
@IsEnum(TaskStatus)
status?: TaskStatus;

@IsOptional()
@IsString()
@IsLexoRankValue()
@Length(2, 255)
rankValue?: string;
}

export class TaskUpdateRequestDto {
Expand Down
8 changes: 7 additions & 1 deletion backend/src/project/entity/task.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
JoinColumn,
ManyToOne,
PrimaryGeneratedColumn,
Unique,
} from 'typeorm';
import { Project } from './project.entity';
import { Story } from './story.entity';
Expand All @@ -16,6 +17,7 @@ export enum TaskStatus {
}

@Entity()
@Unique(['rankValue', 'projectId'])
export class Task {
@PrimaryGeneratedColumn('increment', { type: 'int' })
id: number;
Expand Down Expand Up @@ -62,6 +64,9 @@ export class Task {
@JoinColumn({ name: 'member_id' })
member: Member;

@Column({ type: 'varchar', length: 255, nullable: false, name: 'rank_value' })
rankValue: string;

static of(
project: Project,
storyId: number,
Expand All @@ -71,17 +76,18 @@ export class Task {
actualTime: number,
memberId: number,
status: TaskStatus,
rankValue: string,
) {
const newTask = new Task();
newTask.project = project;
newTask.storyId = storyId;
newTask.title = title;
newTask.displayId = displayId;

newTask.expectedTime = expectedTime;
newTask.actualTime = actualTime;
newTask.assignedMemberId = memberId;
newTask.status = status;
newTask.rankValue = rankValue;
return newTask;
}
}
4 changes: 4 additions & 0 deletions backend/src/project/project.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ export class ProjectRepository {
actualTime: number | undefined,
status: TaskStatus | undefined,
assignedMemberId: number | undefined,
rankValue: string | undefined,
): Promise<boolean> {
const updateData: any = {};

Expand All @@ -266,6 +267,9 @@ export class ProjectRepository {
if (assignedMemberId !== undefined) {
updateData.assignedMemberId = assignedMemberId;
}
if (rankValue !== undefined) {
updateData.rankValue = rankValue;
}

const result = await this.taskRepository.update(
{ id, project: { id: project.id } },
Expand Down
4 changes: 4 additions & 0 deletions backend/src/project/service/project.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ export class ProjectService {
status: TaskStatus,
assignedMemberId: number,
storyId: number,
rankValue: string,
) {
const story = await this.projectRepository.getStoryById(project, storyId);
if (!story) throw new Error('Story id not found');
Expand All @@ -192,6 +193,7 @@ export class ProjectService {
actualTime,
assignedMemberId,
status,
rankValue,
);
return this.projectRepository.createTask(newTask);
}
Expand All @@ -210,6 +212,7 @@ export class ProjectService {
actualTime: number | undefined,
status: TaskStatus | undefined,
assignedMemberId: number | undefined,
rankValue: string | undefined,
): Promise<boolean> {
if (storyId !== undefined) {
const story = await this.projectRepository.getStoryById(project, storyId);
Expand All @@ -224,6 +227,7 @@ export class ProjectService {
actualTime,
status,
assignedMemberId,
rankValue,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class WsProjectTaskController {
content.status,
content.assignedMemberId,
content.storyId,
content.rankValue,
);
client.nsp
.to('backlog')
Expand Down Expand Up @@ -73,6 +74,7 @@ export class WsProjectTaskController {
content.actualTime,
content.status,
content.assignedMemberId,
content.rankValue,
);

if (isUpdated) {
Expand All @@ -88,6 +90,7 @@ export class WsProjectTaskController {
content.actualTime,
content.status,
content.assignedMemberId,
content.rankValue,
),
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ describe('WS epic', () => {
status: taskStatus,
assignedMemberId: taskAssignedMemberId,
storyId,
rankValue: middleRankValue,
},
});

Expand Down
Loading

0 comments on commit 05fcf8a

Please sign in to comment.