한 줄 목표
Case 상세 화면에서 같은 사업장의 활성 HR·관리자를 Task 담당자로 지정·변경하고, 새로고침 후에도 담당자가 유지되도록 합니다.
왜 필요한가요?
현재 Client의 Case 상세에는 담당자 변경 버튼이 있지만 Server에는 담당자를 저장할 assignee_id와 변경 API가 없습니다.
created_by와 updated_by는 각각 생성자와 마지막 수정자를 뜻하므로 현재 업무 담당자로 사용할 수 없습니다.
API 계약
담당자 변경
PATCH /api/v1/tasks/{taskId}/assignee
Authorization: Bearer <access-token>
Content-Type: application/json
{
"assignee_id" : " 7e2722bb-3c72-4aa0-b37c-28931c4f8e53" ,
"expected_version" : 3
}
성공 시 변경된 Task 상세를 반환합니다.
담당자 후보 조회
기존 API를 그대로 사용합니다.
GET /api/v1/company-members?active_only=true
구현 범위
오류 규칙
400: 요청 형식 또는 필수값 오류
403: VIEWER 등 변경 권한 없음
404: Task가 없거나 다른 사업장 Task·사용자를 요청
409: 오래된 expected_version
422: 비활성 사용자 또는 담당자로 지정할 수 없는 사용자
보안·데이터 규칙
company_id는 요청에서 받지 않고 JWT의 ActorContext로 결정
다른 사업장의 사용자 존재 여부가 노출되지 않도록 404 처리
이메일 등 인증정보는 Task 응답에 포함하지 않음
감사로그에는 담당자 ID 변경만 기록하고 개인정보 원문은 남기지 않음
DB·충돌 주의
이번 담당자 변경 PR #143이 공통 Migration V42 를 사용합니다.
새 테이블은 만들지 않고 기존 task에 assignee_id와 tenant-aware FK를 추가합니다.
PR #135의 PostgreSQL 전용 RLS Migration은 V43 으로 조정합니다.
feat: 업무카드 담당자 지정·변경 API 구현 #143 병합 후 #135에 최신 main을 반영하고 전체 Flyway 검증을 다시 실행합니다.
완료 기준
담당자 변경 후 Task·Case 재조회에서 동일 담당자가 반환됨
같은 사업장의 활성 HR·ADMIN만 선택 가능
타 사업장·비활성 사용자·권한 없음·동시 수정 충돌 테스트 통과
담당자 변경 감사로그 1건 생성
Client #315가 후보 조회 → 변경 → 새로고침 복구 흐름을 연결할 수 있음
한 줄 목표
Case 상세 화면에서 같은 사업장의 활성 HR·관리자를 Task 담당자로 지정·변경하고, 새로고침 후에도 담당자가 유지되도록 합니다.
GET /api/v1/company-members왜 필요한가요?
현재 Client의 Case 상세에는 담당자 변경 버튼이 있지만 Server에는 담당자를 저장할
assignee_id와 변경 API가 없습니다.created_by와updated_by는 각각 생성자와 마지막 수정자를 뜻하므로 현재 업무 담당자로 사용할 수 없습니다.API 계약
담당자 변경
{ "assignee_id": "7e2722bb-3c72-4aa0-b37c-28931c4f8e53", "expected_version": 3 }성공 시 변경된 Task 상세를 반환합니다.
담당자 후보 조회
기존 API를 그대로 사용합니다.
구현 범위
assignee_id추가PATCH /api/v1/tasks/{taskId}/assignee구현expected_version기반 동시 수정 충돌 처리오류 규칙
400: 요청 형식 또는 필수값 오류403: VIEWER 등 변경 권한 없음404: Task가 없거나 다른 사업장 Task·사용자를 요청409: 오래된expected_version422: 비활성 사용자 또는 담당자로 지정할 수 없는 사용자보안·데이터 규칙
company_id는 요청에서 받지 않고 JWT의 ActorContext로 결정DB·충돌 주의
task에assignee_id와 tenant-aware FK를 추가합니다.완료 기준