@startuml meeting-Todo완료처리 !theme mono title Meeting Service - Todo완료처리 내부 시퀀스 participant "TodoController" as Controller participant "TodoService" as Service participant "TodoRepository" as TodoRepo participant "MinutesRepository" as MinutesRepo participant "CollaborationService" as CollabService database "Meeting DB<>" as DB database "Redis Cache<>" as Cache queue "Azure Event Hubs<>" as EventHub participant "WebSocket<>" as WebSocket [-> Controller: PATCH /todos/{todoId}/complete activate Controller note over Controller 경로 변수: todoId 사용자 정보: userId, userName, email end note Controller -> Controller: todoId 유효성 검증 Controller -> Service: completeTodo(todoId, userId) activate Service ' Todo 정보 조회 Service -> TodoRepo: findById(todoId) activate TodoRepo TodoRepo -> DB: SELECT * FROM todos WHERE id = ? activate DB DB --> TodoRepo: Todo 정보 deactivate DB TodoRepo --> Service: Todo deactivate TodoRepo note over Service 비즈니스 규칙 검증: - Todo 존재 확인 - 완료 권한 확인 (담당자만) - 상태 확인 (이미 완료된 경우 처리) end note Service -> Service: Todo 존재 확인 Service -> Service: 완료 권한 검증\n(담당자만 가능) alt 권한 없음 Service --> Controller: 403 Forbidden\n담당자만 완료 가능 return 403 Forbidden else 권한 있음 alt Todo가 이미 완료됨 Service --> Controller: 409 Conflict\n이미 완료된 Todo return 409 Conflict else 완료 처리 가능 ' 완료 확인 다이얼로그 (프론트엔드에서 처리됨) ' Todo 완료 처리 Service -> TodoRepo: markAsCompleted(todoId, userId) activate TodoRepo TodoRepo -> DB: UPDATE todos\nSET status = 'COMPLETED',\n completedAt = NOW(),\n completedBy = ?\nWHERE id = ? activate DB DB --> TodoRepo: 업데이트 완료 deactivate DB TodoRepo --> Service: 업데이트 성공 deactivate TodoRepo note over Service 회의록 실시간 반영: - 관련 회의록 섹션 자동 업데이트 - 완료 표시 추가 - 완료 시간 및 완료자 정보 기록 end note ' 회의록 섹션 업데이트 Service -> MinutesRepo: updateTodoStatus(todoId, "COMPLETED") activate MinutesRepo MinutesRepo -> DB: UPDATE minutes_sections\nSET todoStatuses = JSON_SET(todoStatuses,\n CONCAT('$."', ?, '"'),\n JSON_OBJECT(\n 'status', 'COMPLETED',\n 'completedAt', NOW(),\n 'completedBy', ?\n )\n)\nWHERE JSON_CONTAINS(todoIds, CAST(? AS JSON)) activate DB DB --> MinutesRepo: 업데이트 완료 deactivate DB MinutesRepo --> Service: 업데이트 성공 deactivate MinutesRepo ' 회의록의 모든 Todo 완료 여부 확인 Service -> TodoRepo: countPendingTodos(minutesId) activate TodoRepo TodoRepo -> DB: SELECT COUNT(*) FROM todos\nWHERE minutesId = ?\nAND status != 'COMPLETED' activate DB DB --> TodoRepo: 미완료 Todo 개수 deactivate DB TodoRepo --> Service: int pendingCount deactivate TodoRepo ' 캐시 무효화 Service -> Cache: DELETE dashboard:{assigneeId} activate Cache Cache --> Service: 삭제 완료 deactivate Cache Service -> Cache: DELETE minutes:detail:{minutesId} activate Cache Cache --> Service: 삭제 완료 deactivate Cache note over Service 실시간 협업: - WebSocket으로 회의록 업데이트 전송 - 모든 참석자에게 완료 상태 동기화 end note ' 실시간 동기화 Service -> CollabService: broadcastTodoUpdate(minutesId, todoId, status) activate CollabService note over CollabService WebSocket 메시지 형식: { "type": "TODO_COMPLETED", "todoId": "uuid", "minutesId": "uuid", "completedBy": { "userId": "...", "userName": "..." }, "completedAt": "...", "timestamp": "..." } end note CollabService -> WebSocket: broadcast to room:{minutesId} activate WebSocket WebSocket --> CollabService: 전송 완료 deactivate WebSocket CollabService --> Service: 동기화 완료 deactivate CollabService note over Service 비동기 이벤트 발행: - 완료 알림 발송 - 모든 Todo 완료 시 전체 완료 알림 end note alt 모든 Todo 완료됨 Service -> EventHub: publish(AllTodosCompleted)\n{\n minutesId, meetingId,\n completedAt, totalTodos\n} activate EventHub EventHub --> Service: 발행 완료 deactivate EventHub else 일부 Todo만 완료 Service -> EventHub: publish(TodoCompleted)\n{\n todoId, minutesId,\n completedBy, completedAt\n} activate EventHub EventHub --> Service: 발행 완료 deactivate EventHub end Service --> Controller: TodoCompleteResponse deactivate Service note over Controller 응답 데이터: { "todoId": "uuid", "status": "COMPLETED", "completedAt": "2025-01-24T10:00:00", "completedBy": "userId", "minutesId": "uuid", "allTodosCompleted": true/false } end note return 200 OK\nTodoCompleteResponse end end deactivate Controller @enduml