권리확인 탭과 같은 목록↔상세 구조로 권리처리 보드를 만든다. 상태 칩(전체/미처리/
처리완료)과 검색어로 목록을 필터링하고, 상세에서 계약서 유무를 체크박스 조합(+기타
직접입력)으로 관리하며 권리처리상태를 고르기 전에는 저장을 막는다. 기관 상세 헤더의
권리확인/권리처리 통계 카드도 각 탭의 완료·전체 건수를 실데이터로 보여주도록 연결한다.
권리확인 모듈을 참고해 권리처리 탭 전용 process_item 테이블과 CRUD API를 구성한다.
조사원+권리확인 영역은 재업로드마다 항상 최신 파일값으로 갱신하고, 계약서 유무와
권리처리 판정(공공누리유형/최종의견/판단근거/처리상태)은 웹에서 한 번이라도 수정하면
재업로드가 덮어쓰지 않는다. 처리완료 최초 도달 시각은 processed_at에 남기고 이후
재저장에도 값이 바뀌지 않는다.
기관별 권리확인 엑셀(Sheet0, ~1000행)을 업로드해 review_item 테이블에 반영하고,
조사원 항목은 항상 최신화하되 변호사 판정은 웹에서 한번 수정되면(web_edited_at)
재업로드가 덮어쓰지 않는 병합 정책을 적용한다. 목록/단건조회/판정저장/삭제/원본
서식 그대로의 엑셀 다운로드까지 REST로 제공한다.
기관의 신청기관/문정원/아이티앤/변호사 담당자가 채널 생성(또는 재확인) 시
이메일 기준으로 Mattermost 계정을 찾거나 새로 만들고, 문정원/법률검토 채널에
알맞게 추가하도록 ChannelProvisionService.ensureMembers 훅을 추가했다.
계정 생성 실패(아이디 중복 등)와 채널 추가 실패는 담당자별로 격리되어
provision 결과를 뒤집지 않고 메시지에만 남는다.
Co-Authored-By: ITN Dev
- STEPS 배열을 src/stages.ts(STAGE_LABELS)로 분리해 OrgOverview와 Timeline이 공유
- 업무단계 스트립: 완료(체크)/진행중/미래 상태 표시, 현재 단계 클릭 시 확인 후 다음 단계로 진행
- [진행단계 변경] 버튼을 활성화해 12단계 중 하나를 바로 골라 변경하는 모달 추가
- Timeline 컴포넌트: 단계변경/업무메모/자료등록 이벤트를 날짜별로 묶어 시간순으로 표시
- 관련 컴포넌트 테스트 fixture에 stage 필드 추가
- V8 마이그레이션으로 organization.stage와 stage_history 테이블 도입
- PUT /api/orgs/{id}/stage: 1..12 범위 검증 후 단계 변경 + 이력 적재
- 채널 2개가 처음 모두 갖춰지면 진행단계 1(신청)을 자동 시작(재실행 안전)
- GET /api/orgs/{id}/timeline: 단계 이력·업무메모·채널 첨부파일을 최신순으로 합쳐 제공
(Mattermost 조회 실패는 채널별로 흡수하고 200 유지)
POST /api/contacts/import로 회원정보 시트(Sheet1)를 업로드하면 구분(주관기관/
변호사/신청기관/수행기관)에 따라 담당자를 등록·갱신하고, 신청기관 담당자는
기관명이 정확히 일치하는 기관에 자동 배정한다. 이미 등록된 사람은
findMatching으로 재사용하고 소속/부서/직급은 비어 있을 때만 채워 재업로드해도
안전하다. 확장자·빈 파일 검증은 SeedController와 동일한 방식을 따르고
SeedParseException을 재사용해 400으로 처리한다.
시드와 회원명단 업로드가 같은 사람을 여러 기관 행에서 반복해 만나도(예: 경찰청
계열 27곳이 담당자 1명을 공유) 중복 생성하지 않도록 (구분,성명,전화,이메일) 기준
조회(ContactMapper.findMatching)를 추가하고 SeedService가 이를 쓰도록 바꿨다.
담당자 구분에 수행기관(OPERATOR)을 추가하고, 회원명단의 신청기관 자동배정을 위해
기관명 단독 조회(OrganizationMapper.findByOrgName)를 추가했다.
경찰청 계열처럼 연번1(기관번호) 하나로 하위기관을 대표기관에 흡수하던 모델을
폐기하고, 시트의 모든 행(연번1_연번2)이 각자 독립된 기관·채널 쌍을 갖도록 바꿨다.
경찰청_치안정책연구소에 대한 -policy- 특례는 연번 자체가 하위기관까지 구분하므로
더 이상 필요 없어 제거했다. 기존 채널 ID는 V5 마이그레이션이 org_no만 변환해
그대로 보존한다.
담당자 정보를 직접 입력하던 채널관리 화면을 배정 전용(선택/해제)으로 바꾸고,
담당자 등록·수정은 새 담당자관리 화면에서만 하도록 입력 경로를 하나로 모았다.
- 담당자관리(신규): 구분 필터 + 목록 표 + 추가/수정 공용 모달 + 삭제 확인
- ContactPickerModal(신규): 채널관리에서 역할별로 등록된 담당자를 검색해 배정
- OrgDetail: 담당자 입력 표 제거 → 배정 행 3개(미지정/선택/해제) + 변호사 배정일
- client.ts: Org가 flat 필드 대신 applicant/mj/lawyer 중첩 Contact를 갖도록 변경,
updateAssignments/getContacts/createContact/updateContactInfo/deleteContact 추가
- OrgOverview·WorkMemos·OrgList 등 org 픽스처와 조회 로직을 새 중첩 구조에 맞춤
기관에 박혀 있던 담당자 3종(신청기관/문정원/변호사) 컬럼을 contact 테이블로 옮기고,
기관은 담당자 id만 배정으로 참조하게 했다. 신청기관 담당자 배정 여부가 채널 생성
가능(READY) 판정 기준이 되도록 상태 로직도 함께 바꿨다.
- V4 마이그레이션: contact 테이블 생성 + 기존 임베디드 컬럼 백필 후 제거
- kr.itn.itnhub.contact 패키지: 담당자 CRUD API (GET/POST/PUT/DELETE /api/contacts)
- PUT /api/orgs/{id}/assignments가 기존 /contact 엔드포인트를 대체 (구분 불일치 400)
- SeedService: 시트의 담당자명은 신청기관 담당자가 아직 없을 때만 새로 만들어 연결
- ChannelProvisionService 게이트를 hasApplicantAssigned()로 교체