[4][5] RE 메모 기관관리 RE 탭을 메모장처럼 만들었다. 메모 1개가 RE 1개다.
내용·작성자·일자에 완료 체크 한 칸을 더했고, 대시보드 '미해결 RE'가
이제 실제 숫자를 센다(예전에는 항상 0으로 고정돼 있었다).
완료 체크는 회신에 없던 항목이라 확인 요청해 둔 상태다.
[6] 업무구간 필터를 뺐다. 현재 단계와 겹친다는 지적을 반영했고 순서도 현재 단계를
앞으로 옮겼다. 구간 구분 자체는 칸반 컬럼 색에 계속 쓰이므로 남겨 둔다.
[8] 자료접수를 권리확인·권리처리 통합으로 바꿨다. 어느 쪽이든 한 건이라도 있으면 접수다.
[15] 일괄 등록에 비고를 더했다. 권리확인·권리처리 양쪽 모두.
[25] 보고서 교체 기능을 넣었다. 목록에 새 줄이 생기지 않고 그 자리만 바뀐다.
개정판으로 남기고 싶으면 지금처럼 새로 올리면 된다.
RE 메모의 해결 여부를 뒤집으면 대시보드 숫자가 실제로 따라 움직이는지까지 테스트한다.
백엔드 275건, 프론트 208건 통과.
Co-Authored-By: Claude Opus 5 (1M context)
설계서에서 "업로드와 다운로드가 따로 정의돼 어긋날 수 있다"고 적었던 그 결함이
실제로 나 있었다.
다운로드 기존 증빙자료를 헤더 자리인 T열(19)에 쓴다
업로드 U열(20)을 읽는다
기관 원본 파일은 헤더가 T인데 데이터가 U에 있어서(T에는 엑셀 화면용 '수정' 링크가
들어 있다) 파서가 U를 읽도록 돼 있었는데, 이 시스템이 만들어 주는 다운로드 파일은
T에 쓴다. 그래서 내려받아 고쳐서 다시 올리면 그 칸만 조용히 비워졌다.
파서가 U를 먼저 보고 비어 있으면 T를 보게 했다. 한쪽만 맞추면 다른 쪽이 깨지므로
둘 다 읽는다.
왕복 테스트를 먼저 만들어 결함을 재현한 뒤 고쳤다. 헤더 이름과 파서 컬럼이 같은
자리를 가리키는지도 24개 필드 전부 확인한다 - 앞으로 한쪽만 고치면 여기서 깨진다.
덤: PowerShell로 파일을 손보다 들어간 BOM 14건을 제거했다.
백엔드 270건, 프론트 208건 통과.
Co-Authored-By: Claude Opus 5 (1M context)
SQL 5곳(ProcessItemMapper 4 + DashboardMapper 1)과 자바 화이트리스트 1곳에 '처리완료'가
남아 있었다. 쿼리는 코드표를 참조할 방법이 없어 서비스가 값을 읽어 파라미터로 넘긴다.
처리상태 검증도 코드표를 따른다. 상태를 하나 더 만들어도 자바를 안 고쳐도 된다.
지정이 없을 때는 빈 문자열이 아니라 매칭되지 않는 값을 넘긴다. 빈 문자열을 주면
처리상태가 비어 있는 행이 전부 완료로 잡힌다.
파라미터화가 형식만 바뀐 게 아님을 확인하는 테스트를 넣었다. 코드표에서 done 속성을
'미처리' 쪽으로 옮기면 진행률과 상태 필터가 실제로 뒤집힌다 - 예전 구조에서는 코드표를
바꿔도 아무 일도 일어나지 않았다.
이로써 조사에서 세었던 13곳이 모두 정리됐다.
백엔드 266건 통과.
Co-Authored-By: Claude Opus 5 (1M context)
대시보드는 단계를 안 바꾸고는 코드표에 연결할 수 없는 구조였다. 칸반 컬럼 수가 단계
배열 길이에서 나오고 완료 판정이 11로 박혀 있었는데 코드표는 13을 말하기 때문이다.
프론트만 바꾸면 화면과 서버 숫자가 어긋나므로 백엔드까지 한 번에 옮긴다.
[11] 칸반 컬럼이 단계 미지정 + 13개가 된다. 단계 상한도 코드표 개수를 따른다.
[2] 완료 = ⑬보고서 제출 완료. 보고서가 실제로 올라온 기관만 센다.
[7] 진행상태에 '신청'이 생긴다. 신청은 ①만, 완료는 ⑬만, 나머지가 진행중이다.
채널이 없어 단계가 아예 없는 기관은 '단계 미지정'으로 그대로 둔다.
원문자 배열(①~⑫)과 구간 색 맵을 지웠다. 원문자는 번호에서 계산하고 색은 코드표의
tone에서 온다 - 단계가 늘 때마다 같이 늘려야 했던 자리다.
stages.ts를 지웠다. 남아 있던 소비자(기관상세·타임라인·시스템관리)도 모두 옮겼다.
동작이 바뀐 테스트 3건은 새 기준으로 다시 썼다(11단계 완료 집계, 13단계 거부,
마지막 단계 12). 도움말 문구도 13단계 기준으로 고쳤다.
백엔드 263건, 프론트 208건 전부 통과.
Co-Authored-By: Claude Opus 5 (1M context)
시드를 쓸 때 화면 소스를 안 보고 의미만으로 색을 골랐던 탓에 두 가지가 어긋나 있었다.
Phase 2에서 화면이 코드테이블을 보게 되면 조용히 바뀔 값들이다.
업무구간 색 assign violet->indigo, check sky->emerald, closing emerald->violet
담당자 구분 MJ 표시명 주관기관->문정원 (주관기관은 엑셀 표기라 importAlias로)
뱃지색 5개 전부 화면 기준으로 교정
이미 적용된 V13을 고치면 체크섬이 어긋나 기동이 실패하므로 V15로 앞으로 나아가며 고친다.
어긋남이 다시 생기지 않도록 화면 기준값을 테스트로 잠갔다.
STAGE_GROUP의 cardBody 속성은 뺐다. 칸반 카드 본문은 구간이 아니라 단계 번호로 갈리는
자리가 있어(1단계는 신청일, 2·3단계는 목록 건수) 화면 로직으로 두는 편이 정확하다.
Co-Authored-By: Claude Opus 5 (1M context)
배포 전 정합성 점검을 실제 DB에 돌려보니 코드테이블에 없는 값이 1,926건 있었다.
review_item.kogl_type = 유형 확인 필요 1,858건
review_item.kogl_type = 제4유형 68건
둘 다 기관 조사표에서 온 값이라 prior(기존 부착 유형) 자리에만 넣고, 변호사가 고르는
판정값(review/process)에는 넣지 않는다. surveyOnly 속성으로 구분하고 그 구분이 새는지를
테스트로 막는다.
등록하지 않았다면 Phase 2에서 이 1,926건이 상세 화면에 선택 안 됨으로 보였을 것이다.
Co-Authored-By: Claude Opus 5 (1M context)
운영 DB에는 정책 변경 전 값이나 공백만 다른 값이 남아 있을 수 있다. Phase 2에서
화면이 코드테이블만 보게 되면 그런 값은 선택지에서 조용히 사라지므로, 배포 전에
찾아내 active=false 코드로 보존해야 한다.
Phase 1 회귀 확인: 백엔드 255건(기존 221 + 신규 34), 프론트 191건 전부 통과.
기존 동작은 바뀌지 않았다.
Co-Authored-By: Claude Opus 5 (1M context)
CodeService가 기동 후 첫 조회에 코드를 한 번 읽어 메모리에 들고 있는다. 지연 로딩인
이유는 Flyway 마이그레이션보다 빈 초기화가 먼저 돌 수 있기 때문이다.
활성 목록과 전체 목록을 나눠 들고 있는다. 화면 선택지에는 활성만 나가지만, 이미
저장된 과거 값의 라벨을 그리려면 비활성도 조회돼야 한다.
GET /api/meta/codes는 아직 소비자가 없다. 화면 전환은 Phase 2다.
Co-Authored-By: Claude Opus 5 (1M context)
진행단계는 요구사항 [7][11]대로 13단계로 넣고, 진행상태(신청/진행중/완료)와
KPI 임계값을 attrs로 데이터화했다. 요구사항 [2](보고서가 올라와야 최종완료)는
completed 임계값을 13번에 두는 것으로 해결된다.
공공누리 유형은 scopes로 사용처(review/process/prior)를 구분한다. 세 화면의
목록이 7/5/6개로 달랐던 것이 실수가 아니라 자리 차이였기 때문이고, 이 구분 없이
합치면 권리처리 화면에 보류가 잘못 노출된다.
Co-Authored-By: Claude Opus 5 (1M context)
코드값을 소스가 아니라 데이터로 관리하기 위한 기반. 저장값은 지금 업무 테이블에
들어 있는 한글 문자열을 그대로 쓴다 - 영문 키로 바꾸면 기존 데이터 변환과 엑셀
양식 수정이 딸려와 위험 대비 실익이 없다.
설계서와 Phase 1 구현계획도 함께 넣는다.
Co-Authored-By: Claude Opus 5 (1M context)
요청자 피드백 PPT 2건(기능확인 24쪽, 문정원 검토내용 17쪽)에서 확인된
요구를 다음과 같이 반영한다.
- 대시보드: KPI 7타일 + "단계 미지정" 포함 13컬럼 칸반(카드 드래그로 단계 이동)
+ 최근 진행 기관. 집계는 /api/dashboard 한 번으로 끝낸다 - 기관별로 건수를
반복 조회하면 화면 한 번에 150회 조회가 되기 때문이다.
- 사업관리: 3단계 대상 기관 현황, 신청 확인 연락 이력, 기관별 최종 보고서.
기관 현황 숫자는 대시보드와 같은 집계를 재사용해 두 화면이 어긋나지 않게 한다.
- 시스템관리: 채널 초기화(대상 미리보기 → 확인문구 입력 → 서버 재검사).
삭제가 아니라 보관(아카이브)이며 DB가 아는 채널만 대상으로 한다.
- 권리확인: 제3자 권리처리 정책변경 반영. "권리처리 추진 미희망"과 공공누리
"보류"를 신설하고, 처리결과에 따라 공공누리 유형·비고를 규칙대로 자동 채운다.
- 권리확인/권리처리: 일괄 등록·선택 삭제와 열별 조건 복합검색(AND).
- 업무메모: 작성자를 화면에서 고르지 않고 로그인 사용자를 서버가 기록하며,
수정 기능을 추가한다(작성자·작성시각은 유지).
- 기관관리: 채널에 고정된 최초 안내글을 확인하는 [최초 게시글 보기].
- 도움말: 주요 버튼 옆 (?) 모달 15개 항목. 실제 화면 캡처를 함께 담는다.
마이그레이션 두 건:
- V11 "채널 있음 <=> 단계 있음" 불변식을 맞추는 1회성 백필. 단계 기능(V8)
이전에 채널을 만든 기관이 칸반에서 사라지는 것을 막는다.
- V12 사업관리용 contact_log / org_report.
테스트: 백엔드 221건, 프런트 191건 전부 통과.
Co-Authored-By: Claude Opus 5 (1M context)
권리확인 모듈을 참고해 권리처리 탭 전용 process_item 테이블과 CRUD API를 구성한다.
조사원+권리확인 영역은 재업로드마다 항상 최신 파일값으로 갱신하고, 계약서 유무와
권리처리 판정(공공누리유형/최종의견/판단근거/처리상태)은 웹에서 한 번이라도 수정하면
재업로드가 덮어쓰지 않는다. 처리완료 최초 도달 시각은 processed_at에 남기고 이후
재저장에도 값이 바뀌지 않는다.
기관별 권리확인 엑셀(Sheet0, ~1000행)을 업로드해 review_item 테이블에 반영하고,
조사원 항목은 항상 최신화하되 변호사 판정은 웹에서 한번 수정되면(web_edited_at)
재업로드가 덮어쓰지 않는 병합 정책을 적용한다. 목록/단건조회/판정저장/삭제/원본
서식 그대로의 엑셀 다운로드까지 REST로 제공한다.
기관의 신청기관/문정원/아이티앤/변호사 담당자가 채널 생성(또는 재확인) 시
이메일 기준으로 Mattermost 계정을 찾거나 새로 만들고, 문정원/법률검토 채널에
알맞게 추가하도록 ChannelProvisionService.ensureMembers 훅을 추가했다.
계정 생성 실패(아이디 중복 등)와 채널 추가 실패는 담당자별로 격리되어
provision 결과를 뒤집지 않고 메시지에만 남는다.
Co-Authored-By: ITN Dev
- 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만 변환해
그대로 보존한다.
기관에 박혀 있던 담당자 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()로 교체
신청기관 담당자 1종만 저장하던 기관 테이블에 문정원 담당자(부서/담당자/연락처/이메일)와
담당 변호사(성명/연락처/이메일/배정일) 정보를 추가해, 채널관리 화면에서 세 담당자를
한 번에 저장하고 다른 화면(기관관리·업무메모)에서도 쓸 수 있게 한다.
- V3 마이그레이션으로 organization에 컬럼 8개 추가 (upsertBySeed는 그대로 둬서
엑셀 재시드가 새 컬럼을 건드리지 않는다)
- ContactRequest/OrgResponse/updateContact에 8개 필드를 선택값으로 반영
- 컨트롤러 테스트 2건(신규 필드 왕복, 신규 필드 없는 기존 페이로드) +
매퍼 테스트 2건(영속화 왕복, 재시드 시 보존) 추가
기관관리 상세의 업무메모 탭이 쓸 CRUD 엔드포인트를 추가한다. 통화 등
담당자와의 연락 내용을 기관별로 남기는 단순 기능이라 Mattermost 연동
없이 순수 DB로만 처리한다.
- V2__work_memo.sql: work_memo 테이블, org_id+created_at 인덱스
- WorkMemoMapper/xml: 최신순 조회, 등록, (orgId, id) 동시 조건 삭제
- WorkMemoService/Controller: GET/POST /api/orgs/{id}/memos,
DELETE /api/orgs/{id}/memos/{memoId}
- GlobalExceptionHandler: contactName/body 검증 메시지 한글 라벨 추가
- WorkMemoControllerTest: 등록/조회/최신순/검증/404/삭제/인증 검증
Co-Authored-By: Claude Opus 4.8 (1M context)