|
1 | 1 | package clap.server.application.service.task; |
2 | 2 |
|
3 | 3 | import clap.server.adapter.inbound.web.dto.task.request.UpdateTaskOrderRequest; |
| 4 | +import clap.server.adapter.outbound.persistense.entity.notification.constant.NotificationType; |
4 | 5 | import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus; |
5 | 6 | import clap.server.application.port.inbound.domain.MemberService; |
6 | 7 | import clap.server.application.port.inbound.domain.TaskService; |
7 | 8 | import clap.server.application.port.inbound.task.UpdateTaskBoardUsecase; |
8 | 9 | import clap.server.application.port.inbound.task.UpdateTaskOrderAndStatusUsecase; |
9 | 10 | import clap.server.application.port.outbound.task.LoadTaskPort; |
| 11 | +import clap.server.application.service.webhook.SendNotificationService; |
10 | 12 | import clap.server.common.annotation.architecture.ApplicationService; |
11 | 13 | import clap.server.domain.model.member.Member; |
12 | 14 | import clap.server.domain.model.task.Task; |
|
19 | 21 | import lombok.extern.slf4j.Slf4j; |
20 | 22 | import org.springframework.transaction.annotation.Transactional; |
21 | 23 |
|
| 24 | +import java.util.List; |
| 25 | + |
22 | 26 | @Slf4j |
23 | 27 | @ApplicationService |
24 | 28 | @RequiredArgsConstructor |
25 | 29 | class UpdateTaskBoardService implements UpdateTaskBoardUsecase, UpdateTaskOrderAndStatusUsecase { |
26 | 30 | private final MemberService memberService; |
27 | 31 | private final TaskService taskService; |
28 | 32 | private final LoadTaskPort loadTaskPort; |
| 33 | + private final SendNotificationService sendNotificationService; |
29 | 34 |
|
30 | 35 | private final TaskOrderCalculationPolicy taskOrderCalculationPolicy; |
31 | 36 | private final ProcessorValidationPolicy processorValidationPolicy; |
@@ -53,15 +58,15 @@ public void updateTaskOrder(Long processorId, UpdateTaskOrderRequest request) { |
53 | 58 | if (request.prevTaskId() == 0) { |
54 | 59 | Task nextTask = findByIdAndStatus(request.nextTaskId(), targetTask.getTaskStatus()); |
55 | 60 | // 해당 상태에서 바로 앞에 있는 작업 찾기 |
56 | | - Task prevTask = loadTaskPort.findPrevOrderTaskByProcessorIdAndStatus(processorId, targetTask.getTaskStatus(), nextTask.getProcessorOrder()).orElse(null); |
| 61 | + Task prevTask = loadTaskPort.findPrevOrderTaskByProcessorOrderAndStatus(processorId, targetTask.getTaskStatus(), nextTask.getProcessorOrder()).orElse(null); |
57 | 62 | long newOrder = taskOrderCalculationPolicy.calculateOrderForTop(prevTask, nextTask); |
58 | 63 | updateNewTaskOrder(targetTask, newOrder); |
59 | 64 | } |
60 | 65 | // 가장 하위로 이동 |
61 | 66 | else if (request.nextTaskId() == 0) { |
62 | 67 | Task prevTask = findByIdAndStatus(request.prevTaskId(), targetTask.getTaskStatus()); |
63 | 68 | // 해당 상태에서 바로 뒤에 있는 작업 찾기 |
64 | | - Task nextTask = loadTaskPort.findNextOrderTaskByProcessorIdAndStatus(processorId, targetTask.getTaskStatus(), prevTask.getProcessorOrder()).orElse(null); |
| 69 | + Task nextTask = loadTaskPort.findNextOrderTaskByProcessorOrderAndStatus(processorId, targetTask.getTaskStatus(), prevTask.getProcessorOrder()).orElse(null); |
65 | 70 | long newOrder = taskOrderCalculationPolicy.calculateOrderForBottom(prevTask, nextTask); |
66 | 71 | updateNewTaskOrder(targetTask, newOrder); |
67 | 72 | } else { |
@@ -98,49 +103,87 @@ public void updateTaskOrderAndStatus(Long processorId, UpdateTaskOrderRequest re |
98 | 103 | Task targetTask = taskService.findById(request.targetTaskId()); |
99 | 104 | processorValidationPolicy.validateProcessor(processorId, targetTask); |
100 | 105 |
|
101 | | - if (request.prevTaskId() == 0) { |
102 | | - Task nextTask = findByIdAndStatus(request.nextTaskId(), targetStatus); |
| 106 | + Task updatedTask; |
| 107 | + Task prevTask; |
| 108 | + Task nextTask; |
| 109 | + |
| 110 | + // 조회된 작업 보드에서 하나의 작업만 존재하고, 이 작업을 이동할 때 |
| 111 | + if (request.prevTaskId() == 0 && request.nextTaskId() == 0) { |
| 112 | + |
| 113 | + // 요청 시간 기준으로 가장 가장 근접한 이전의 Task를 조회 |
| 114 | + prevTask = loadTaskPort.findPrevOrderTaskByTaskIdAndStatus(processorId, targetStatus, targetTask.getTaskId()).orElse(null); |
| 115 | + if (prevTask != null) { |
| 116 | + // 이전 Task가 있다면 바로 다음의 Task 조회 |
| 117 | + nextTask = loadTaskPort.findNextOrderTaskByProcessorOrderAndStatus(processorId, targetStatus, prevTask.getProcessorOrder()).orElse(null); |
| 118 | + } // 요청 시간 기준으로 가장 가장 근접한 이후의 Task를 조회 |
| 119 | + else |
| 120 | + nextTask = loadTaskPort.findNextOrderTaskByTaskIdAndStatus(processorId, targetStatus, targetTask.getTaskId()).orElse(null); |
| 121 | + |
| 122 | + // 하나의 task만 존재할 경우 상태만 update |
| 123 | + if (prevTask == null && nextTask == null) { |
| 124 | + targetTask.updateTaskStatus(targetStatus); |
| 125 | + updatedTask = taskService.upsert(targetTask); |
| 126 | + } else if (prevTask == null) { |
| 127 | + long newOrder = taskOrderCalculationPolicy.calculateOrderForBottom(null, nextTask); |
| 128 | + updatedTask = updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder); |
| 129 | + } else if (nextTask == null) { |
| 130 | + long newOrder = taskOrderCalculationPolicy.calculateOrderForBottom(prevTask, null); |
| 131 | + updatedTask = updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder); |
| 132 | + } else { |
| 133 | + long newOrder = taskOrderCalculationPolicy.calculateNewProcessorOrder(prevTask.getProcessorOrder(), nextTask.getProcessorOrder()); |
| 134 | + updatedTask = updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder); |
| 135 | + } |
| 136 | + } else if (request.prevTaskId() == 0) { |
| 137 | + nextTask = findByIdAndStatus(request.nextTaskId(), targetStatus); |
103 | 138 | // 해당 상태에서 바로 앞 있는 작업 찾기 |
104 | | - Task prevTask = loadTaskPort.findPrevOrderTaskByProcessorIdAndStatus(processorId, targetStatus, nextTask.getProcessorOrder()).orElse(null); |
| 139 | + prevTask = loadTaskPort.findPrevOrderTaskByProcessorOrderAndStatus(processorId, targetStatus, nextTask.getProcessorOrder()).orElse(null); |
105 | 140 | long newOrder = taskOrderCalculationPolicy.calculateOrderForTop(prevTask, nextTask); |
106 | | - updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder); |
| 141 | + updatedTask = updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder); |
107 | 142 | } else if (request.nextTaskId() == 0) { |
108 | | - Task prevTask = findByIdAndStatus(request.prevTaskId(), targetStatus); |
| 143 | + prevTask = findByIdAndStatus(request.prevTaskId(), targetStatus); |
109 | 144 | // 해당 상태에서 바로 뒤에 있는 작업 찾기 |
110 | | - Task nextTask = loadTaskPort.findNextOrderTaskByProcessorIdAndStatus(processorId, targetStatus, prevTask.getProcessorOrder()).orElse(null); |
| 145 | + nextTask = loadTaskPort.findNextOrderTaskByProcessorOrderAndStatus(processorId, targetStatus, prevTask.getProcessorOrder()).orElse(null); |
111 | 146 | long newOrder = taskOrderCalculationPolicy.calculateOrderForBottom(prevTask, nextTask); |
112 | | - updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder); |
| 147 | + updatedTask = updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder); |
113 | 148 | } else { |
114 | | - Task prevTask = findByIdAndStatus(request.prevTaskId(), targetStatus); |
115 | | - Task nextTask = findByIdAndStatus(request.nextTaskId(), targetStatus); |
| 149 | + prevTask = findByIdAndStatus(request.prevTaskId(), targetStatus); |
| 150 | + nextTask = findByIdAndStatus(request.nextTaskId(), targetStatus); |
116 | 151 | long newOrder = taskOrderCalculationPolicy.calculateNewProcessorOrder(prevTask.getProcessorOrder(), nextTask.getProcessorOrder()); |
117 | | - updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder); |
| 152 | + updatedTask = updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder); |
118 | 153 | } |
| 154 | + |
| 155 | + //TODO: 최종 단계에서 주석 처리 해제 |
| 156 | + //publishNotification(targetTask, NotificationType.STATUS_SWITCHED, String.valueOf(updatedTask.getTaskStatus())); |
119 | 157 | } |
120 | 158 |
|
121 | 159 | /** |
122 | 160 | * 작업의 상태와 순서를 업데이트하는 메서드 |
123 | 161 | */ |
124 | | - private void updateNewTaskOrderAndStatus(TaskStatus targetStatus, Task targetTask, long newOrder) { |
| 162 | + private Task updateNewTaskOrderAndStatus(TaskStatus targetStatus, Task targetTask, long newOrder) { |
125 | 163 | targetTask.updateProcessorOrder(newOrder); |
126 | 164 | targetTask.updateTaskStatus(targetStatus); |
127 | | - taskService.upsert(targetTask); |
| 165 | + return taskService.upsert(targetTask); |
128 | 166 | } |
129 | 167 |
|
130 | 168 | /** |
131 | 169 | * 순서 변경 요청의 유효성을 검증하는 메서드 |
132 | 170 | */ |
133 | 171 | public void validateRequest(UpdateTaskOrderRequest request, TaskStatus targetStatus) { |
134 | | - // 이전 및 다음 작업 ID가 모두 0인 경우 예외 발생 |
135 | | - if (request.prevTaskId() == 0 && request.nextTaskId() == 0) { |
136 | | - throw new ApplicationException(TaskErrorCode.INVALID_TASK_STATUS_TRANSITION); |
137 | | - } |
138 | | - |
139 | 172 | // 타겟 상태가 유효한지 검증 |
140 | 173 | if (targetStatus != null && !TaskPolicyConstants.TASK_BOARD_STATUS_FILTER.contains(targetStatus)) { |
141 | 174 | throw new ApplicationException(TaskErrorCode.INVALID_TASK_STATUS_TRANSITION); |
142 | 175 | } |
143 | 176 | } |
144 | 177 |
|
| 178 | + private void publishNotification(Task task, NotificationType notificationType, String message) { |
| 179 | + List<Member> receivers = List.of(task.getRequester(), task.getProcessor()); |
| 180 | + receivers.forEach(receiver -> { |
| 181 | + sendNotificationService.sendPushNotification(receiver, notificationType, |
| 182 | + task, message, null); |
| 183 | + }); |
| 184 | + sendNotificationService.sendAgitNotification(notificationType, |
| 185 | + task, message, null); |
| 186 | + } |
| 187 | + |
145 | 188 | } |
146 | 189 |
|
0 commit comments