# 레퍼런스 — 상태별 Endpoint > 상위: [개발가이드.md](./개발가이드.md) > SoT: `05.재원협의_상태별_endpoint_설계.md` (v1.0, 2026-09-03) > Gateway: `/as-service`, `/as-elapr-service` > Auth: `Authorization`, `X-Site-Id`, `token-id` (기존 `client` 인터셉터) > 날짜: `yyyy-MM-dd HH:mm:ss` 프론트가 치는 API만 상세히 적는다. AI 콜백·스케줄러·Feign은 [§6 호출 금지](#6-프론트-호출-금지). --- ## 1. 총괄 매트릭스 (38 + WebHWP) | 순번 | 버튼 | From → To | 서비스 | Method & URI | 구분 | | :---: | --- | --- | --- | --- | --- | | 1 | 저장 | →`SV` | as | `POST /api/v1/fnrs-cnsltn-mng/save-apply` | 기존 | | 2 | 신청완료 | `SV→ST` | as | 동일 (`prgrsSttsComCd=ST`) | 기존 | | 3 | 삭제 | `SV` | as | `DELETE /api/v1/fnrs-cnsltn-mng/{docNo}` | 기존 | | 4 | 환경청제출 | `ST→LE` | as | `POST /api/v1/fnrs-cnsltn-mng/doc/updatePrgrsStts` | 기존 | | 5 | 결과회신(자체종결) | `LE→EP` | as | `POST /api/v1/fnrs-cnsltn-mng/{docNo}/tech-review` | 기존 | | 6 | 기술검토 의뢰 | `LE→FV` | as | `POST /api/v1/fnrs-cnsltn-mng/{docNo}/request-examine` | **신규** | | 7 | 파일검증 콜백 | `FV→ER` | as | `POST /api/v1/dcrag/documents/verify-result` | 서버 | | 8 | 파일보완 팝업 | `ER` | as | `GET /api/v1/fnrs-cnsltn-mng/{docNo}/file-vrfc-results` | 기존 | | 9 | 파일보완요청 | `ER→SL` | as | `POST /api/v1/fnrs-cnsltn-mng/{docNo}/reqsupplement` | 기존 | | 10 | 파일검증 재실행 | `ER` | as | `POST /api/v1/dcrag-to/documents/transfer` | 기존 | | 11 | 검토자지정 | `ER→AC` | elapr | `POST /api/v1/elapr-dmnd` | 기존 | | 12 | 초안 콜백 | `AC→TE` | as | `POST /api/v1/dcrag/draft/complete` | 서버 | | 13 | 실무협의서관리 | `TE` | as | `GET /api/v1/pwrk-cnsltn-mng/updocno/{upDocNo}` | 기존 | | 14 | 검토결과조회 | `TE` | as | `GET /api/v1/pwrk-cnsltn-mng/{pwrkDocNo}` | 기존 | | 15 | 실무협의서생성 | `TE` | as | `POST /api/v1/dcrag-to/documents/draft/generate` | 기존 | | 16 | 저장(실무) | `TE` | as | `POST /api/v1/pwrk-cnsltn-mng/save-apply` | 기존 | | 17 | 검토완료 | `TE` | elapr | `PUT /api/v1/elapr-prgrs-stts/{id}/process` | 기존 | | 18 | 보완요청 | `TE→SL` | as | `POST .../reqsupplement` | 기존 | | 19 | 결재(승인) | `TE` | elapr | `PUT .../process` | 기존 | | 20 | 결재(회신) | `TE→TP` | elapr | `PUT .../process` | 기존 | | 21 | 파일보완완료 | `SL→ER` | as | `POST .../submitsupplement` | 기존 | | 22 | 보완완료(기술) | `SL→TE` | as | 동일 | 기존 | | 23 | 보완완료(조치) | `SL→RK` | as | 동일 | 기존 | | 24 | 재원협의 결과 회신 | `TP→RM` | as | `POST .../{docNo}/tech-review` | 기존 | | 25 | 지자체회신 | `RM→RB` | as | `POST .../doc/updatePrgrsStts` | 기존 | | 26 | 실무협의서 관리 | `RB` | as | `GET .../pwrk-cnsltn-doc-crt-rslt/{uuid}/webhwp/open` | 기존 | | 27 | 조치완료 | `RB→RA` | as | `POST /api/v1/pwrk-cnsltn-mng/{pwrkDocNo}/submit-actn-result` (`isSubmit=true`) | **신규** | | 28 | 조치결과서제출 | `RC→RA` | as | `updatePrgrsStts` | 기존 | | 29 | 조치결과 검토의뢰 | `RA→AV` | as | `POST /api/v1/fnrs-cnsltn-mng/{docNo}/request-actn-review` | **신규** | | 30 | 금액검증 콜백 | `AV→EV` | as | `POST /api/v1/dcrag/cost/verify-result` | 서버 | | 30a | 검토자지정(2차) | `EV→RK` | elapr | `POST /api/v1/elapr-dmnd` (`elaprCycl=2`) | 기존 | | 31 | 실무협의서관리 | `RK` | as | `GET /pwrk-cnsltn-mng/{pwrkDocNo}` | 기존 | | 32 | 금액검증 재실행 | `RK` | as | `POST /api/v1/dcrag-to/documents/cost/verify` | 기존 | | 33 | 보완요청(금액) | `RK→SL` | as | `reqsupplement` | 기존 | | 34 | 결재(승인) | `RK` | elapr | `process` | 기존 | | 35 | 결재(회신) | `RK→RR` | elapr | `process` | 기존 | | 36 | 결과회신 | `RR→EP` | as | `updatePrgrsStts` | 기존 | | 37 | 결과회신 | `EP→TA` | as | `updatePrgrsStts` | 기존 | | 38 | 결과회신(확인) | `TA` | — | 없음 | — | | W1 | 웹기안기 Open | — | as | `GET /api/v1/pwrk-cnsltn-doc-crt-rslt/{uuid}/webhwp/open` | 기존 | | W2 | HWPX 저장 | — | as | `POST /api/v1/pwrk-cnsltn-doc-crt-rslt` multipart | 기존 | | W3 | 다운로드 | — | as | `GET /api/v1/pwrk-cnsltn-doc-crt-rslt/{uuid}/download` | 기존 | | E-N | 결재선 복사 | `AV→RK` 부수 | elapr | `POST /api/v1/elapr-apln/copy-line` | **신규·서버** | 조회 공통: `GET /fnrs-cnsltn-mng`, `GET /fnrs-cnsltn-mng/{docNo}`, `GET /pwrk-cnsltn-mng`, `GET /dcrag-to/documents/draft/status/{crtDmndUuid}`. --- ## 2. 공통 요청 ### `DocPrgrsUpdateRequestDto` `POST /fnrs-cnsltn-mng/doc/updatePrgrsStts` — `ST→LE`, `RM→RB`, `RC→RA`, `RR→EP`, `EP→TA`. ```json { "docNo": "F-20260824-0001", "docSeComCd": "FNRS", "prgrsSttsComCd": "LE", "rgtrUuid": "optional-uuid", "rmrk": "optional" } ``` 응답: `204/200` void. 프론트 엔티티: 기존 `changePrgrsSttsComCd`. ### `FnrsCnsltnApplySaveRequestDto` `save-apply`, `tech-review`, `reqsupplement`, `submitsupplement`가 공유. 핵심은 `fnrsCnsltnMng.prgrsSttsComCd`와 중첩 리스트(`bzScaleList`, `bizCstList`, `cklstResultList`, `esntlAtchFileList`, `splmntDmndList`). --- ## 3. 단계별 FE API ### 3-1. `SV → ST → LE` **저장 / 신청완료** — `POST /fnrs-cnsltn-mng/save-apply` 권한: `ROLE_USER05`. 임시저장은 `prgrsSttsComCd=SV`, 신청은 `ST`. 응답: `string` (문서번호). 기존 `fnrsCnsltnMngService.saveApply`. **삭제** — `DELETE /fnrs-cnsltn-mng/{docNo}` (`SV`만). **환경청제출** — `updatePrgrsStts` `LE`. 권한: `ROLE_USER04`. ### 3-2. `LE → FV | EP` **자체종결** — `POST /fnrs-cnsltn-mng/{docNo}/tech-review` Body: `FnrsCnsltnApplySaveRequestDto` (환경청 의견·체크리스트). `LE→EP`. 기존 `techReview`. 현재 화면은 `TP`에서도 이 API를 쓰며 목표 상태를 `EP`로 넣고 있다 → **`TP`는 `RM`으로 바꿔야 함**. **기술검토 의뢰 (신규)** — `POST /fnrs-cnsltn-mng/{docNo}/request-examine` ```json { "prgrsSttsComCd": "FV" } ``` 응답: `string` (docNo). `LE→FV` + AI 파일검증 + 30분 타이머(서버). 프론트: `fnrsCnsltnMngService.requestExamine(docNo, body)` 추가. **`updatePrgrsStts("ER")` 금지.** ### 3-3. `FV → ER → SL → ER` 파일검증 콜백은 서버. FE는 `FV`에서 상세 refetch. **검증결과 목록** — `GET /fnrs-cnsltn-mng/{fnrsCnsltnDocNo}/file-vrfc-results` 응답: `FnrsCnsltnFileVrfcRsltResponseDto[]` | 필드 | 설명 | | --- | --- | | `fileSeComCd` | `ESSENTIAL` / `ADDITIONAL` | | `fileSeNm` | 구분명 | | `esntlAtchFileId` | 필수첨부 ID | | `atchFileNm` | 파일명 | | `vrfcRsltComCd` | `PASS` / `FAIL` / `WARN` | | `vrfcOpnn` | 검증의견 | 엔티티에 `findFileVrfcResults` 추가. 첨부 행 배지는 상세 `esntlFileList`/`etcFileList`의 `vrfcSttsComCd`, `vrfcRsltCn`, `vrfcDt`도 사용 (타입 확장 필요). **파일보완요청** — `POST .../{docNo}/reqsupplement` (`ER→SL`). **파일보완완료** — `POST .../{docNo}/submitsupplement` (`SL→ER`). 복귀는 서버. **파일검증 재실행** — `POST /dcrag-to/documents/transfer` ```json { "fnrsCnsltnDocNo": "F-20260824-0001", "taskSeComCd": "SF", "taskSeCdNm": "하수처리시설" } ``` 응답: `{ resultCode, message, requestId }`. 상태 유지. 기존 `dcRagApiToService.requestDocumentTransfer`. ### 3-4. `ER → AC → TE → TP` **검토자지정** — `POST /elapr-dmnd` 기존 `elaprDmndService.save`. | 필드 | 값 | | --- | --- | | `elaprDocNo` | 재원협의 번호 | | `elaprCycl` | `1` | | `docPrgrsSttsComCd` | **`AC`** (현행은 현재 상태 `ER`를 넣고 있음 → 수정) | | `elaprPrgrsSttsList[].atrzOrdr` | 1 검토자, 2 승인자, 3 최종 | 서버가 실무협의 문서 생성 + RAG 초안 트리거 + 30분 타이머. 응답의 문서번호/`crtDmndUuid`가 있으면 폴링 키로 쓴다. 없으면 `findByUpDocNo`로 복원. **초안 상태 폴링** — `GET /dcrag-to/documents/draft/status/{crtDmndUuid}` 기존 `getDraftGenerationStatus`. 주기 5~10초. 종료 `COMPLETED`/`FAILED`. **수동 초안생성** — `POST /dcrag-to/documents/draft/generate` (`TE` 유지) ```json { "fnrsCnsltnDocNo": "F-...", "pwrkCnsltnDocNo": "P-...", "crtDmndUuid": "optional" } ``` 202 + `DcRagDraftGenerateResponseDto` (`crtDmndUuid`, `crtSttsComCd`, `estimatedMinutes`). v1.0 가이드의 “이 API를 프론트가 치면 안 된다”는 **폐기**. 1차 트리거는 검토자지정이고, 이 API는 Fallback 전용. **실무 저장** — `POST /pwrk-cnsltn-mng/save-apply` → `string`. **보완요청/완료** — fnrs `reqsupplement` / `submitsupplement`. **결재** — `PUT /elapr-prgrs-stts/{elaprPrgrsId}/process` ```json { "atrzPrgrsSttsComCd": "ATRZ_PRGRS_003", "atrzOpnnCn": "의견", "finalApprovalYn": false } ``` 반려: `ATRZ_PRGRS_004`. 기존 `elaprPrgrsSttsService.process`. 최종 시 서버가 `TP`/`RR` 전이. ### 3-5. `TP → RM → RB → RA` **환경청 1차 회신** — `tech-review` (`TP→RM`). **광역 지자체회신** — `updatePrgrsStts` `RB`. **조치완료 (신규)** — `POST /pwrk-cnsltn-mng/{pwrkDocNo}/submit-actn-result` ```json { "isSubmit": true, "actnList": [ { "rvwOpnnSn": 1, "actnRsltCn": "수용 — 관로 연장 재산정", "atchFileGroupId": "optional" } ], "totActnSummary": "제출 시 권장", "muniDocNo": "제출 시 권장" } ``` - `isSubmit: false` → `RB` 유지 (API만 존재, **화면 버튼 없음**. HWP·첨부는 실무협의서 관리 다이얼로그에서 저장) - `isSubmit: true` → `RB→RA` (조치완료) 응답: `string` (pwrkDocNo). DTO명 `PwrkActnResultSubmitDto`. ### 3-6. `RA → AV → EV → RK` **2차 의뢰 (신규)** — `POST /fnrs-cnsltn-mng/{docNo}/request-actn-review` ```json { "specialRqstCn": "중점 검증 요청 (선택)" } ``` `RA→AV`. 응답: `string` (docNo). DTO명 `EnvoActnReviewReqDto`. `specialRqstCn`만 선택. 금액검증 콜백은 서버 → `AV→EV`. **2차 검토자지정** — `POST /elapr-dmnd` (`elaprCycl: 2`, `docPrgrsSttsComCd: RK`). 1차 결재선(`findDocPrgrsByDocNo`, cycl=1)을 시드로 편집. **금액검증 재실행** — `POST /dcrag-to/documents/cost/verify` ```json { "fnrsCnsltnDocNo": "F-...", "pwrkCnsltnDocNo": "P-..." } ``` 202. 기존 `requestCostVerification`. `RK` 유지. ### 3-7. `RK → RR | SL` 보완은 3-4와 동일 API. 팝업만 금액 체크. 결재 `process` 2차 최종 → 서버가 `RR`. ### 3-8. `RR → EP → TA` 둘 다 `updatePrgrsStts`. `TA` 확인은 API 없음. --- ## 4. 웹기안기 설계서 기준 **기존**. 구현 시 컨트롤러 존재 여부를 확인한다. | ID | 용도 | URI | 응답 | | --- | --- | --- | --- | | W1 | 웹기안기 Open | `GET .../pwrk-cnsltn-doc-crt-rslt/{crtDmndUuid}/webhwp/open` | `inline` HWPX blob → `HwpCtrl.Open(File)` | | W2 | 편집 저장 | `POST .../pwrk-cnsltn-doc-crt-rslt` multipart `file` + `crtDmndUuid` | 201, `verSn+1` | | W3 | PC 저장 | `GET .../{crtDmndUuid}/download` | `attachment` blob | 버전 지정: `GET .../{crtDmndUuid}/{verSn}/webhwp/open`, `.../{verSn}/download`. `/{uuid}/latest`, `/{uuid}/download`가 `/{uuid}/{verSn}`보다 우선. path를 섞지 말 것. 다운로드: - axios `responseType: "blob"` - 파일명: `Content-Disposition` `filename*=UTF-8''...` (`parseFilenameFromResponse`) - 서버 파일명: `재원협의 실무협의서({bizNm})_v{verSn}.hwp` - Content-Type은 `application/x-hwp` 또는 `application/haansofthwpx`일 수 있음. 타입에 의존하지 말 것 Open은 axios `responseType: "blob"`으로 인증된 API를 호출하고, 응답 Blob을 HWPX `File`로 감싸 `HwpCtrl.Open`에 전달한다. `blob:` Object URL은 사용하지 않는다. multipart `Content-Type` 헤더를 수동 지정하지 않는다 (boundary). JSON `saveJson`은 UI에서 쓰지 않는다. --- ## 5. 전자결재 (`as-elapr-service`) | API | URI | FE | | --- | --- | --- | | 검토자지정·1차 결재요청 | `POST /elapr-dmnd` | O | | 결재 처리 | `PUT /elapr-prgrs-stts/{id}/process` | O | | 결재선 복사 | `POST /elapr-apln/copy-line` | **X (서버)** | `copy-line` body (참고만): ```json { "docNo": "P-20260827-0001", "sourceElaprCycl": 1, "targetElaprCycl": 2, "rgtrUuid": "system-uuid" } ``` `RK`에서 결재현황은 `findDocPrgrsByDocNo`(전체) 조회 후 `elaprCycl`로 1차/2차 탭 표시. --- ## 6. 프론트 호출 금지 | URI | 이유 | | --- | --- | | `POST /dcrag/documents/verify-result` | AI→AS 콜백 | | `POST /dcrag/draft/complete` | AI→AS 콜백 | | `POST /dcrag/cost/verify-result` | AI→AS 콜백. 여기서 copy-line도 호출 | | `POST /elapr-apln/copy-line` | 콜백 Feign | | `POST /pwrk-cnsltn-mng` (`save` 초안 트리거) | v3.0 1차 트리거는 `elapr-dmnd`. 컨트롤러가 남아 있어도 화면에서 쓰지 않음 | `POST /dcrag-to/documents/draft/generate`는 **Fallback에서만** 허용. --- ## 7. Gap Analysis (프론트 엔티티) ### 이미 있는 것 `fnrsCnsltnMngService`: `findPage`, `findById`, `save`, `saveApply`, `update`, `techReview`, `submitSupplement`, `submitReqSupplement`, `remove`, `changePrgrsSttsComCd` `dcRagApiToService`: `requestDocumentTransfer`, `requestDraftGeneration`, `getDraftGenerationStatus`, `requestCostVerification` `elaprDmndService.save`, `elaprPrgrsSttsService.process` ### 추가할 것 | 메서드 | URI | | --- | --- | | `requestExamine` | `POST /fnrs-cnsltn-mng/{id}/request-examine` | | `findFileVrfcResults` | `GET /fnrs-cnsltn-mng/{id}/file-vrfc-results` | | `requestActnReview` | `POST /fnrs-cnsltn-mng/{id}/request-actn-review` | | `pwrkCnsltnMngService.*` | 슬라이스 신규 | | `submitActnResult` | `POST /pwrk-cnsltn-mng/{id}/submit-actn-result` | | `pwrkCnsltnDocCrtRsltService.*` | 슬라이스 신규 | `copyLine`은 프론트 서비스에 넣지 않는다.