diff --git a/apps/as/docs/pwrk-cnsltn/development-guide.md b/apps/as/docs/pwrk-cnsltn/development-guide.md index 99e38c569..bf3b72af6 100644 --- a/apps/as/docs/pwrk-cnsltn/development-guide.md +++ b/apps/as/docs/pwrk-cnsltn/development-guide.md @@ -116,7 +116,7 @@ SV → ST → LE → FV → ER → AC → TE → TP → RM → RB → RC → RA | `TE` | 기술검토 | 웹기안기·검토완료·보완. 결재선 1차 | | `TP` | 기술검토 회신 | 환경청 → 광역 `RM` | | `RM` | 재원협의결과회신 | 광역 → 기초 `RB` | -| `RB` | 지자체회신 | 기초 조치결과 저장/협의회신 | +| `RB` | 지자체회신 | 기초 실무협의서 관리 / 조치완료 | | `RC` | 조치결과서 제출 | 광역 → 환경청 `RA` | | `RA` | 조치결과서제출(환경청) | 환경청 2차 의뢰 `AV` | | `AV` | 금액검증 | AI 진행 표시. **30분** 후 `RK` Fallback | @@ -167,8 +167,8 @@ BEGIN ON [삭제] (SV) → remove ON [파일보완완료] (SL←ER) → submitsupplement ON [보완완료] (SL←TE|RK) → submitsupplement - ON [저장] (RB) → submit-actn-result { isSubmit: false } - ON [협의회신] (RB) → submit-actn-result { isSubmit: true } + ON [실무협의서 관리] (RB) → GET webhwp/open (blob) → HwpCtrl.Open(File) + ON [조치완료] (RB) → submit-actn-result { isSubmit: true } ON [결과회신] (TA) → API 없음 (조회) // ----- 광역 ROLE_USER04 ----- @@ -230,7 +230,8 @@ END | 기초 | 파일보완완료 / 보완완료 | `SL→ER | TE | RK` | `POST /fnrs-cnsltn-mng/{docNo}/submitsupplement` | | 환경청 | 재원협의 결과 회신 | `TP→RM` | `POST /fnrs-cnsltn-mng/{docNo}/tech-review` | | 광역 | 지자체회신 | `RM→RB` | `updatePrgrsStts` | -| 기초 | 저장(조치) / 협의회신 | `RB` / `RB→RC` | **신규** `POST /pwrk-cnsltn-mng/{pwrkDocNo}/submit-actn-result` | +| 기초 | 실무협의서 관리 | `RB` 유지 | `GET .../pwrk-cnsltn-doc-crt-rslt/{uuid}/webhwp/open` | +| 기초 | 조치완료 | `RB→RA` | **신규** `POST /pwrk-cnsltn-mng/{pwrkDocNo}/submit-actn-result` (`isSubmit: true`) | | 광역 | 조치결과서제출 | `RC→RA` | `updatePrgrsStts` | | 환경청 | 조치결과서 검토요청 | `RA→AV` | **신규** `POST /fnrs-cnsltn-mng/{docNo}/request-actn-review` | | 공단 검토 | 금액검증 재실행 | `RK` 유지 | `POST /dcrag-to/documents/cost/verify` | diff --git a/apps/as/docs/pwrk-cnsltn/ref-endpoint.md b/apps/as/docs/pwrk-cnsltn/ref-endpoint.md index b14a429ce..f34eb0e52 100644 --- a/apps/as/docs/pwrk-cnsltn/ref-endpoint.md +++ b/apps/as/docs/pwrk-cnsltn/ref-endpoint.md @@ -39,8 +39,8 @@ | 23 | 보완완료(조치) | `SL→RK` | as | 동일 | 기존 | | 24 | 재원협의 결과 회신 | `TP→RM` | as | `POST .../{docNo}/tech-review` | 기존 | | 25 | 지자체회신 | `RM→RB` | as | `POST .../doc/updatePrgrsStts` | 기존 | -| 26 | 저장(조치결과) | `RB` | as | `POST /api/v1/pwrk-cnsltn-mng/{pwrkDocNo}/submit-actn-result` | **신규** | -| 27 | 협의회신 | `RB→RC` | as | 동일 (`isSubmit=true`) | **신규** | +| 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→RK` | as | `POST /api/v1/dcrag/cost/verify-result` | 서버 | @@ -186,16 +186,16 @@ v1.0 가이드의 “이 API를 프론트가 치면 안 된다”는 **폐기**. 반려: `ATRZ_PRGRS_004`. 기존 `elaprPrgrsSttsService.process`. 최종 시 서버가 `TP`/`RR` 전이. -### 3-5. `TP → RM → RB → RC` +### 3-5. `TP → RM → RB → RA` **환경청 1차 회신** — `tech-review` (`TP→RM`). **광역 지자체회신** — `updatePrgrsStts` `RB`. -**조치결과 저장/제출 (신규)** — `POST /pwrk-cnsltn-mng/{pwrkDocNo}/submit-actn-result` +**조치완료 (신규)** — `POST /pwrk-cnsltn-mng/{pwrkDocNo}/submit-actn-result` ```json { - "isSubmit": false, + "isSubmit": true, "actnList": [ { "rvwOpnnSn": 1, @@ -203,19 +203,16 @@ v1.0 가이드의 “이 API를 프론트가 치면 안 된다”는 **폐기**. "atchFileGroupId": "optional" } ], - "totActnSummary": "제출 시 필수", - "muniDocNo": "제출 시 필수" + "totActnSummary": "제출 시 권장", + "muniDocNo": "제출 시 권장" } ``` -- `isSubmit: false` → `RB` 유지 -- `isSubmit: true` → `RB→RC` +- `isSubmit: false` → `RB` 유지 (API만 존재, **화면 버튼 없음**. HWP·첨부는 실무협의서 관리 다이얼로그에서 저장) +- `isSubmit: true` → `RB→RA` (조치완료) 응답: `string` (pwrkDocNo). DTO명 `PwrkActnResultSubmitDto`. -### 3-6. `RC → RA → AV → RK` - -**광역 제출** — `updatePrgrsStts` `RA`. - +### 3-6. `RA → AV → RK` **2차 의뢰 (신규)** — `POST /fnrs-cnsltn-mng/{docNo}/request-actn-review` ```json diff --git a/apps/as/docs/pwrk-cnsltn/ref-frontend-entities.md b/apps/as/docs/pwrk-cnsltn/ref-frontend-entities.md index f74b63571..4544a8ec7 100644 --- a/apps/as/docs/pwrk-cnsltn/ref-frontend-entities.md +++ b/apps/as/docs/pwrk-cnsltn/ref-frontend-entities.md @@ -168,13 +168,14 @@ requestCostVerification(body: DcRagCostVerifyRequestDto): Promise>광역: [재원협의 결과 회신] TP → RM 광역->>기초: [지자체회신] RM → RB - 기초->>광역: [협의회신] RB → RC + 기초->>환경청: [조치완료] RB → RA end rect rgb(240, 255, 255) @@ -123,8 +123,8 @@ sequenceDiagram | 7 | 1차 기술검토 | 공단 결재선 | `TE` / `SL` | 웹기안기, HWP 파싱은 서버 | | 8 | 기술검토 회신 | 공단 최종 | `TE→TP` | `process` 최종 | | 9 | 검토결과 회신 | 환경청·광역 | `TP→RM→RB` | 1차 회신. `EP`와 혼동 금지 | -| 10 | 조치결과 작성 | 기초 | `RB→RC` | `submit-actn-result` | -| 11 | 조치 제출·의뢰 | 광역·환경청 | `RC→RA→AV` | `request-actn-review` | +| 10 | 조치결과 작성 | 기초 | `RB→RA` | `submit-actn-result` `isSubmit:true` (조치완료) | +| 11 | 조치 의뢰 | 환경청 | `RA→AV` | `request-actn-review` | | 12 | AI 금액검증 | AI·공단 | `AV→RK` | 결재선 복사(서버) | | 13 | 2차 검토·결재 | 공단 | `RK→RR` / `SL` | 2차 결재선 | | 14 | 최종 회신 | 환경청·광역·기초 | `RR→EP→TA` | 종결 | @@ -149,7 +149,7 @@ sequenceDiagram | `RM` | 재원협의결과회신 | Result Message to Province | 환경청→광역 | `TP→RM` | | `RB` | 재원협의결과회신(지자체) | Result Back to Municipality | 광역→기초 | `RM→RB` | | `RC` | 조치결과서 제출 | Result Complete | 기초→광역 | `RB→RC` | -| `RA` | 조치결과서 제출(환경청) | Result Ask to Basin | 광역→환경청 | `RC→RA` | +| `RA` | 조치결과서 제출(환경청) | Result Ask to Basin | 기초→환경청 | `RB→RA` | | `AV` | 금액검증 | Amount Verification | AI | `RA→AV` | | `RK` | 조치결과서검토 | Result Check | 공단 2차 결재 | `AV→RK`, `SL→RK` | | `RR` | 조치결과서검토 회신 | Result Return to Basin | 공단→환경청 | `RK→RR` | diff --git a/apps/as/docs/pwrk-cnsltn/ref-screen-buttons.md b/apps/as/docs/pwrk-cnsltn/ref-screen-buttons.md index 556aab39b..adfbbf3aa 100644 --- a/apps/as/docs/pwrk-cnsltn/ref-screen-buttons.md +++ b/apps/as/docs/pwrk-cnsltn/ref-screen-buttons.md @@ -11,9 +11,9 @@ | 화면 | 소유 | 라우트 (현행) | 비고 | | --- | --- | --- | --- | -| 작성화면 | 기초 `ROLE_USER05` | `/fnrs-cnsltn/new`, `/fnrs-cnsltn/{id}/edit` | `SV`, `RB` | +| 작성화면 | 기초 `ROLE_USER05` | `/fnrs-cnsltn/new`, `/fnrs-cnsltn/{id}/edit` | `SV` | | 수정화면 | 기초 | `/fnrs-cnsltn/{id}/edit` | `SL` 보완 | -| 상세화면 | 광역·환경청·공단·기초(TA) | `/fnrs-cnsltn/{id}` | 조회 + 액션 버튼 | +| 상세화면 | 광역·환경청·공단·기초(`RB`/`TA`) | `/fnrs-cnsltn/{id}` | 조회 + 액션 버튼 | | 자동화 | AI | 버튼 없음 | `FV`/`AC`/`AV` 진행 패널 | 공단 상세는 결재선 구분으로 같은 상태라도 버튼이 다르다. @@ -57,8 +57,8 @@ API 컬럼은 [ref-endpoint.md](./ref-endpoint.md)와 동일. | 22 | 수정 | USER05 | - | `SL` | 보완완료 | `RK` | 공단 검토 | `submitsupplement` (직전=`RK`) | | 23 | 상세 | USER03 | - | `TP` | 재원협의 결과 회신 | `RM` | 광역 | `tech-review` | | 24 | 상세 | USER04 | - | `RM` | 지자체회신 | `RB` | 기초 | `updatePrgrsStts` | -| 25 | 작성 | USER05 | - | `RB` | 저장 | `RB` | 본인 | **`submit-actn-result` `isSubmit:false`** | -| 26 | 작성 | USER05 | - | `RB` | 협의회신 | `RC` | 광역 | **`submit-actn-result` `isSubmit:true`** | +| 25 | 상세 | USER05 | - | `RB` | 실무협의서 관리 | 유지 | — | 웹기안기 Open | +| 26 | 상세 | USER05 | - | `RB` | 조치완료 | `RA` | 환경청 | **`submit-actn-result` `isSubmit:true`** | | 27 | 상세 | USER04 | - | `RC` | 조치결과서제출 | `RA` | 환경청 | `updatePrgrsStts` | | 28 | 상세 | USER03 | - | `RA` | 조치결과서 검토요청 | `AV` | 공단 검토 | **`request-actn-review`** | | 29 | 자동화 | AI | - | `AV` | (금액검증) | `RK` | 공단 검토 | FE 호출 없음. 진행 패널 | @@ -85,11 +85,10 @@ API 컬럼은 [ref-endpoint.md](./ref-endpoint.md)와 동일. | `fileSplmnt` | 파일보완 | `ER` 접수자. 현행에 없음 | | `fileVrfc` | 파일검증 | 유지. `ER` 재실행 | | `dsgntRvwr` | 검토자지정 | 유지. 전이를 `AC`로 | -| `pwrkCnsltnDocMng` | 실무협의서관리 | 유지. `TE`·`RK` | +| `pwrkCnsltnDocMng` | 실무협의서관리 | 유지. `TE`·`RK`·`RB` | | `pwrkCnsltnDocCrt` | 실무협의서생성 | 유지. 실패/타임아웃만 | | `rvwRsltInq` | 검토결과조회 | 신규 | -| `actnStrg` | 저장(조치결과) | `RB` | -| `cnsltnRply` | 협의회신 | `RB→RC` | +| `actnCmptn` | 조치완료 | `RB→RA`. `isSubmit:true` | | `actnSbmsn` | 조치결과서제출 | 광역 `RC→RA` | | `rqstActnRvw` | 조치결과서 검토요청 | 환경청 `RA→AV` | | `costVrfc` | 금액검증 | `RK` | @@ -107,7 +106,7 @@ API 컬럼은 [ref-endpoint.md](./ref-endpoint.md)와 동일. ROLE_USER05 "" | SV → 저장, 신청완료, 삭제 SL → (직전 ER) 파일보완완료 | (직전 TE|RK) 보완완료 - RB → 저장(조치), 협의회신 + RB → 실무협의서 관리, 조치완료 TA → 결과회신 (조회) ROLE_USER04 diff --git a/apps/as/src/entities/pwrk-cnsltn-mng/api/pwrk-cnsltn-mng-service.ts b/apps/as/src/entities/pwrk-cnsltn-mng/api/pwrk-cnsltn-mng-service.ts index 2654f544f..2faf8acef 100644 --- a/apps/as/src/entities/pwrk-cnsltn-mng/api/pwrk-cnsltn-mng-service.ts +++ b/apps/as/src/entities/pwrk-cnsltn-mng/api/pwrk-cnsltn-mng-service.ts @@ -5,6 +5,10 @@ import type { PwrkCnsltnMngDetResponseDto, PwrkCnsltnMngService, } from "../model/pwrk-cnsltn-mng-interface"; +import { + type PwrkActnResultSubmitDto, + pwrkActnResultSubmitSchema, +} from "../model/pwrk-cnsltn-mng-payload-schema"; const BASE = ENDPOINT.AS_SERVICE.PWRK_CNSLTN_MNG; @@ -18,7 +22,20 @@ async function findByUpDocNo(upDocNo: string): Promise { + const payload = pwrkActnResultSubmitSchema.parse(body); + const response = await client.post( + `${BASE}/${pwrkCnsltnDocNo}/submit-actn-result`, + payload, + ); + return response.data; +} + export const pwrkCnsltnMngService = { findById, findByUpDocNo, + submitActnResult, } satisfies PwrkCnsltnMngService; diff --git a/apps/as/src/entities/pwrk-cnsltn-mng/index.ts b/apps/as/src/entities/pwrk-cnsltn-mng/index.ts index 1083b207b..e2191546f 100644 --- a/apps/as/src/entities/pwrk-cnsltn-mng/index.ts +++ b/apps/as/src/entities/pwrk-cnsltn-mng/index.ts @@ -1,9 +1,5 @@ export { pwrkCnsltnMngService } from "./api/pwrk-cnsltn-mng-service"; -export { - pwrkCnsltnMngKeys, - usePwrkCnsltnMng, - usePwrkCnsltnMngByUpDocNo, -} from "./api/queries"; +export { pwrkCnsltnMngKeys, usePwrkCnsltnMng, usePwrkCnsltnMngByUpDocNo } from "./api/queries"; export { findCompletedPwrkDraft } from "./lib/find-completed-draft"; export type { PwrkCnsltnCnsltnResponseDto, @@ -13,3 +9,7 @@ export type { PwrkCnsltnMngService, PwrkCnsltnPjtcoAjmtResponseDto, } from "./model/pwrk-cnsltn-mng-interface"; +export { + type PwrkActnResultSubmitDto, + pwrkActnResultSubmitSchema, +} from "./model/pwrk-cnsltn-mng-payload-schema"; diff --git a/apps/as/src/entities/pwrk-cnsltn-mng/model/pwrk-cnsltn-mng-interface.ts b/apps/as/src/entities/pwrk-cnsltn-mng/model/pwrk-cnsltn-mng-interface.ts index 67065215a..b89f06d2d 100644 --- a/apps/as/src/entities/pwrk-cnsltn-mng/model/pwrk-cnsltn-mng-interface.ts +++ b/apps/as/src/entities/pwrk-cnsltn-mng/model/pwrk-cnsltn-mng-interface.ts @@ -1,5 +1,7 @@ import type { AtflMngClientResponseDto } from "@/shared/model"; +import type { PwrkActnResultSubmitDto } from "./pwrk-cnsltn-mng-payload-schema"; + export interface PwrkCnsltnDocCrtRsltResponseDto { crtDmndUuid: string; verSn: number; @@ -88,4 +90,8 @@ export interface PwrkCnsltnMngDetResponseDto { export interface PwrkCnsltnMngService { findById(pwrkCnsltnDocNo: string): Promise; findByUpDocNo(upDocNo: string): Promise; + submitActnResult( + pwrkCnsltnDocNo: string, + body: PwrkActnResultSubmitDto, + ): Promise; } diff --git a/apps/as/src/entities/pwrk-cnsltn-mng/model/pwrk-cnsltn-mng-payload-schema.ts b/apps/as/src/entities/pwrk-cnsltn-mng/model/pwrk-cnsltn-mng-payload-schema.ts new file mode 100644 index 000000000..d12926429 --- /dev/null +++ b/apps/as/src/entities/pwrk-cnsltn-mng/model/pwrk-cnsltn-mng-payload-schema.ts @@ -0,0 +1,20 @@ +import { z } from "zod"; + +/** 백엔드 PwrkActnResultSubmitDto.ActnItemDto */ +export const pwrkActnResultActnItemSchema = z.object({ + rvwOpnnSn: z.number(), + actnRsltCn: z.string().optional(), + rfltYn: z.string().optional(), + atchFileGroupId: z.string().optional(), +}); + +/** 백엔드 PwrkActnResultSubmitDto */ +export const pwrkActnResultSubmitSchema = z.object({ + isSubmit: z.boolean(), + actnList: z.array(pwrkActnResultActnItemSchema).optional(), + totActnSummary: z.string().optional(), + muniDocNo: z.string().optional(), + pwrkAtchFileGroupId: z.string().optional(), +}); + +export type PwrkActnResultSubmitDto = z.infer; diff --git a/apps/as/src/pages/fnrs-cnsltn/lib/button-config.ts b/apps/as/src/pages/fnrs-cnsltn/lib/button-config.ts index bf2d11767..d393dc425 100644 --- a/apps/as/src/pages/fnrs-cnsltn/lib/button-config.ts +++ b/apps/as/src/pages/fnrs-cnsltn/lib/button-config.ts @@ -19,6 +19,7 @@ export const FNRS_CNSLTN_VIEW_BUTTON_ACTION = { dmndSplmnt: "dmndSplmnt", atrzAprv: "atrzAprv", atrzRply: "atrzRply", + actnCmptn: "actnCmptn", } as const; export type FnrsCnsltnViewButtonAction = @@ -36,6 +37,10 @@ const ROLE_STATUS_BUTTON_ACTIONS: Record
@@ -553,6 +576,11 @@ function FloatingActionButtons({ 실무협의서 관리 )} + {shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.actnCmptn) && ( + + )} {shouldShowButton(FNRS_CNSLTN_VIEW_BUTTON_ACTION.rvwRsltInq) && (