Skip to content

Commit 02a3a34

Browse files
authored
Merge pull request #478 from TaskFlow-CLAP/CLAP-369
CLAP-369 작업보드 순서 변경 단위 테스트 코드 작성 및 usecase 분리
2 parents d5e9b08 + a311299 commit 02a3a34

File tree

9 files changed

+397
-145
lines changed

9 files changed

+397
-145
lines changed

src/main/java/clap/server/adapter/outbound/api/kakaoWork/KakaoWorkBlockBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ private String makeTerminatedStatusBlock(PushNotificationTemplate request, Strin
405405
"inlines", new Object[]{
406406
Map.of(
407407
"type", "styled",
408-
"text", " - 거절 사유 : " + request.reason(),
408+
"text", " - 반려 사유 : " + request.reason(),
409409
"bold", false
410410
)
411411
}

src/main/java/clap/server/adapter/outbound/persistense/mapper/TaskPersistenceMapper.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package clap.server.adapter.outbound.persistense.mapper;
22

3-
import clap.server.adapter.outbound.persistense.entity.task.CommentEntity;
43
import clap.server.adapter.outbound.persistense.entity.task.TaskEntity;
54
import clap.server.adapter.outbound.persistense.mapper.common.PersistenceMapper;
6-
import clap.server.domain.model.task.Comment;
75
import clap.server.domain.model.task.Task;
86
import org.mapstruct.Mapper;
97
import org.mapstruct.Mapping;

src/main/java/clap/server/adapter/outbound/persistense/repository/task/TaskRepository.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,6 @@ List<TaskEntity> findYesterdayTaskByUpdatedAtIsBetween(
2828

2929
List<TaskEntity> findByProcessor_MemberIdAndTaskStatusIn(Long memberId, Collection<TaskStatus> taskStatuses);
3030

31-
32-
@Query("SELECT t FROM TaskEntity t " +
33-
"WHERE t.processor.memberId = :processorId " +
34-
"AND t.taskStatus IN :taskStatus " +
35-
"AND (:fromDateTime IS NULL OR t.taskStatus != 'COMPLETED' OR " +
36-
" (t.taskStatus = 'COMPLETED' AND t.finishedAt >= :fromDateTime)) " +
37-
"ORDER BY t.processorOrder ASC ")
38-
List<TaskEntity> findTasksWithTaskStatusAndCompletedAt(
39-
@Param("processorId") Long processorId,
40-
@Param("taskStatus") List<TaskStatus> taskStatus,
41-
@Param("fromDateTime") LocalDateTime fromDateTime
42-
);
43-
44-
4531
Optional<TaskEntity> findByTaskIdAndTaskStatus(Long id, TaskStatus status);
4632

4733
Optional<TaskEntity> findTopByProcessor_MemberIdAndTaskStatusAndProcessorOrderLessThanOrderByProcessorOrderAsc(Long processorId, TaskStatus taskStatus, Long processorOrder);

src/main/java/clap/server/application/port/inbound/domain/TaskService.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package clap.server.application.port.inbound.domain;
22

3+
import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus;
34
import clap.server.application.port.outbound.task.CommandTaskPort;
45
import clap.server.application.port.outbound.task.LoadTaskPort;
56
import clap.server.domain.model.task.Task;
@@ -23,4 +24,8 @@ public Task findById(Long taskId) {
2324
public Task upsert(Task task) {
2425
return commandTaskPort.save(task);
2526
}
27+
28+
public Task findByIdAndStatus(Long taskId, TaskStatus status) {
29+
return loadTaskPort.findByIdAndStatus(taskId, status).orElseThrow(() -> new ApplicationException(TaskErrorCode.TASK_NOT_FOUND));
30+
}
2631
}
Lines changed: 5 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,29 @@
11
package clap.server.application.service.task;
22

33
import clap.server.adapter.inbound.web.dto.task.request.UpdateTaskOrderRequest;
4-
import clap.server.adapter.outbound.persistense.entity.member.constant.MemberRole;
5-
import clap.server.adapter.outbound.persistense.entity.notification.constant.NotificationType;
6-
import clap.server.adapter.outbound.persistense.entity.task.constant.TaskHistoryType;
7-
import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus;
84
import clap.server.application.port.inbound.domain.MemberService;
95
import clap.server.application.port.inbound.domain.TaskService;
106
import clap.server.application.port.inbound.task.UpdateTaskBoardUsecase;
11-
import clap.server.application.port.inbound.task.UpdateTaskOrderAndStatusUsecase;
127
import clap.server.application.port.outbound.task.LoadTaskPort;
13-
import clap.server.application.port.outbound.taskhistory.CommandTaskHistoryPort;
14-
import clap.server.application.service.webhook.SendNotificationService;
158
import clap.server.common.annotation.architecture.ApplicationService;
169
import clap.server.domain.model.member.Member;
1710
import clap.server.domain.model.task.Task;
18-
import clap.server.domain.model.task.TaskHistory;
1911
import clap.server.domain.policy.task.ProcessorValidationPolicy;
2012
import clap.server.domain.policy.task.TaskOrderCalculationPolicy;
21-
import clap.server.domain.policy.task.TaskPolicyConstants;
22-
import clap.server.exception.ApplicationException;
23-
import clap.server.exception.code.TaskErrorCode;
2413
import lombok.RequiredArgsConstructor;
2514
import lombok.extern.slf4j.Slf4j;
2615
import org.springframework.transaction.annotation.Transactional;
2716

28-
import java.util.List;
29-
3017
@Slf4j
3118
@ApplicationService
3219
@RequiredArgsConstructor
33-
class UpdateTaskBoardService implements UpdateTaskBoardUsecase, UpdateTaskOrderAndStatusUsecase {
20+
public class UpdateTaskBoardService implements UpdateTaskBoardUsecase {
3421
private final MemberService memberService;
3522
private final TaskService taskService;
3623
private final LoadTaskPort loadTaskPort;
37-
private final SendNotificationService sendNotificationService;
38-
private final CommandTaskHistoryPort commandTaskHistoryPort;
3924

4025
private final TaskOrderCalculationPolicy taskOrderCalculationPolicy;
4126
private final ProcessorValidationPolicy processorValidationPolicy;
42-
43-
private Task findByIdAndStatus(Long taskId, TaskStatus status) {
44-
return loadTaskPort.findByIdAndStatus(taskId, status).orElseThrow(() -> new ApplicationException(TaskErrorCode.TASK_NOT_FOUND));
45-
}
46-
4727
/**
4828
* 작업(Task)의 순서를 업데이트하는 메서드
4929
*
@@ -53,30 +33,28 @@ private Task findByIdAndStatus(Long taskId, TaskStatus status) {
5333
@Override
5434
@Transactional
5535
public void updateTaskOrder(Long processorId, UpdateTaskOrderRequest request) {
56-
// 요청 유효성 검증
57-
validateRequest(request, null);
5836
Member processor = memberService.findActiveMember(processorId);
5937
Task targetTask = taskService.findById(request.targetTaskId());
6038
processorValidationPolicy.validateProcessor(processorId, targetTask);
6139

6240
// 가장 상위로 이동
6341
if (request.prevTaskId() == 0) {
64-
Task nextTask = findByIdAndStatus(request.nextTaskId(), targetTask.getTaskStatus());
42+
Task nextTask = taskService.findByIdAndStatus(request.nextTaskId(), targetTask.getTaskStatus());
6543
// 해당 상태에서 바로 앞에 있는 작업 찾기
6644
Task prevTask = loadTaskPort.findPrevOrderTaskByProcessorOrderAndStatus(processorId, targetTask.getTaskStatus(), nextTask.getProcessorOrder()).orElse(null);
6745
long newOrder = taskOrderCalculationPolicy.calculateOrderForTop(prevTask, nextTask);
6846
updateNewTaskOrder(targetTask, newOrder);
6947
}
7048
// 가장 하위로 이동
7149
else if (request.nextTaskId() == 0) {
72-
Task prevTask = findByIdAndStatus(request.prevTaskId(), targetTask.getTaskStatus());
50+
Task prevTask = taskService.findByIdAndStatus(request.prevTaskId(), targetTask.getTaskStatus());
7351
// 해당 상태에서 바로 뒤에 있는 작업 찾기
7452
Task nextTask = loadTaskPort.findNextOrderTaskByProcessorOrderAndStatus(processorId, targetTask.getTaskStatus(), prevTask.getProcessorOrder()).orElse(null);
7553
long newOrder = taskOrderCalculationPolicy.calculateOrderForBottom(prevTask, nextTask);
7654
updateNewTaskOrder(targetTask, newOrder);
7755
} else {
78-
Task prevTask = findByIdAndStatus(request.prevTaskId(), targetTask.getTaskStatus());
79-
Task nextTask = findByIdAndStatus(request.nextTaskId(), targetTask.getTaskStatus());
56+
Task prevTask = taskService.findByIdAndStatus(request.prevTaskId(), targetTask.getTaskStatus());
57+
Task nextTask = taskService.findByIdAndStatus(request.nextTaskId(), targetTask.getTaskStatus());
8058
long newOrder = taskOrderCalculationPolicy.calculateNewProcessorOrder(prevTask.getProcessorOrder(), nextTask.getProcessorOrder());
8159
updateNewTaskOrder(targetTask, newOrder);
8260
}
@@ -93,103 +71,5 @@ private void updateNewTaskOrder(Task targetTask, Long newOrder) {
9371
taskService.upsert(targetTask);
9472
}
9573

96-
/**
97-
* 작업의 상태와 순서를 동시에 변경하는 메서드
98-
*
99-
* @param processorId 작업을 수행하는 멤버 ID
100-
* @param request 순서 변경 요청 객체
101-
* @param targetStatus 변경할 작업 상태
102-
*/
103-
@Override
104-
@Transactional
105-
public void updateTaskOrderAndStatus(Long processorId, UpdateTaskOrderRequest request, TaskStatus targetStatus) {
106-
validateRequest(request, targetStatus);
107-
Member processor = memberService.findActiveMember(processorId);
108-
Task targetTask = taskService.findById(request.targetTaskId());
109-
processorValidationPolicy.validateProcessor(processorId, targetTask);
110-
111-
Task updatedTask;
112-
Task prevTask;
113-
Task nextTask;
114-
115-
// 조회된 작업 보드에서 하나의 작업만 존재하고, 이 작업을 이동할 때
116-
if (request.prevTaskId() == 0 && request.nextTaskId() == 0) {
117-
118-
// 요청 시간 기준으로 가장 가장 근접한 이전의 Task를 조회
119-
prevTask = loadTaskPort.findPrevOrderTaskByTaskIdAndStatus(processorId, targetStatus, targetTask.getTaskId()).orElse(null);
120-
if (prevTask != null) {
121-
// 이전 Task가 있다면 바로 다음의 Task 조회
122-
nextTask = loadTaskPort.findNextOrderTaskByProcessorOrderAndStatus(processorId, targetStatus, prevTask.getProcessorOrder()).orElse(null);
123-
} // 요청 시간 기준으로 가장 가장 근접한 이후의 Task를 조회
124-
else
125-
nextTask = loadTaskPort.findNextOrderTaskByTaskIdAndStatus(processorId, targetStatus, targetTask.getTaskId()).orElse(null);
126-
127-
// 하나의 task만 존재할 경우 상태만 update
128-
if (prevTask == null && nextTask == null) {
129-
targetTask.updateTaskStatus(targetStatus);
130-
updatedTask = taskService.upsert(targetTask);
131-
} else if (prevTask == null) {
132-
long newOrder = taskOrderCalculationPolicy.calculateOrderForBottom(null, nextTask);
133-
updatedTask = updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder);
134-
} else if (nextTask == null) {
135-
long newOrder = taskOrderCalculationPolicy.calculateOrderForBottom(prevTask, null);
136-
updatedTask = updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder);
137-
} else {
138-
long newOrder = taskOrderCalculationPolicy.calculateNewProcessorOrder(prevTask.getProcessorOrder(), nextTask.getProcessorOrder());
139-
updatedTask = updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder);
140-
}
141-
} else if (request.prevTaskId() == 0) {
142-
nextTask = findByIdAndStatus(request.nextTaskId(), targetStatus);
143-
// 해당 상태에서 바로 앞 있는 작업 찾기
144-
prevTask = loadTaskPort.findPrevOrderTaskByProcessorOrderAndStatus(processorId, targetStatus, nextTask.getProcessorOrder()).orElse(null);
145-
long newOrder = taskOrderCalculationPolicy.calculateOrderForTop(prevTask, nextTask);
146-
updatedTask = updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder);
147-
} else if (request.nextTaskId() == 0) {
148-
prevTask = findByIdAndStatus(request.prevTaskId(), targetStatus);
149-
// 해당 상태에서 바로 뒤에 있는 작업 찾기
150-
nextTask = loadTaskPort.findNextOrderTaskByProcessorOrderAndStatus(processorId, targetStatus, prevTask.getProcessorOrder()).orElse(null);
151-
long newOrder = taskOrderCalculationPolicy.calculateOrderForBottom(prevTask, nextTask);
152-
updatedTask = updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder);
153-
} else {
154-
prevTask = findByIdAndStatus(request.prevTaskId(), targetStatus);
155-
nextTask = findByIdAndStatus(request.nextTaskId(), targetStatus);
156-
long newOrder = taskOrderCalculationPolicy.calculateNewProcessorOrder(prevTask.getProcessorOrder(), nextTask.getProcessorOrder());
157-
updatedTask = updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder);
158-
}
159-
160-
TaskHistory taskHistory = TaskHistory.createTaskHistory(TaskHistoryType.STATUS_SWITCHED, updatedTask, targetStatus.getDescription(), null,null);
161-
commandTaskHistoryPort.save(taskHistory);
162-
publishNotification(targetTask);
163-
}
164-
165-
/**
166-
* 작업의 상태와 순서를 업데이트하는 메서드
167-
*/
168-
private Task updateNewTaskOrderAndStatus(TaskStatus targetStatus, Task targetTask, long newOrder) {
169-
targetTask.updateProcessorOrder(newOrder);
170-
targetTask.updateTaskStatus(targetStatus);
171-
return taskService.upsert(targetTask);
172-
}
173-
174-
/**
175-
* 순서 변경 요청의 유효성을 검증하는 메서드
176-
*/
177-
public void validateRequest(UpdateTaskOrderRequest request, TaskStatus targetStatus) {
178-
// 타겟 상태가 유효한지 검증
179-
if (targetStatus != null && !TaskPolicyConstants.TASK_BOARD_STATUS_FILTER.contains(targetStatus)) {
180-
throw new ApplicationException(TaskErrorCode.INVALID_TASK_STATUS_TRANSITION);
181-
}
182-
}
183-
184-
private void publishNotification(Task task) {
185-
List<Member> receivers = List.of(task.getRequester(), task.getProcessor());
186-
receivers.forEach(receiver -> {
187-
boolean isManager = receiver.getMemberInfo().getRole() == MemberRole.ROLE_MANAGER;
188-
sendNotificationService.sendPushNotification(receiver, NotificationType.STATUS_SWITCHED, task, String.valueOf(task.getTaskStatus()), null, null, isManager);
189-
});
190-
sendNotificationService.sendAgitNotification(NotificationType.STATUS_SWITCHED,
191-
task, String.valueOf(task.getTaskStatus()), null);
192-
}
193-
19474
}
19575

0 commit comments

Comments
 (0)