diff --git a/apps/as/public/webhwpctrl/hwpsdkmain.html b/apps/as/public/webhwpctrl/hwpsdkmain.html
index d24c7eee7..3f4bc1526 100644
--- a/apps/as/public/webhwpctrl/hwpsdkmain.html
+++ b/apps/as/public/webhwpctrl/hwpsdkmain.html
@@ -6,36 +6,57 @@
-
-
-
- Hwp SDK Wasm Sample
-
-
-
-
-
-
-
+
+
+
+
Hwp SDK Wasm Sample
+
+
+
+
+
+
+
+
+
-
-
-
-
- 구성 중 ... 0%
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/apps/as/src/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng/api/pwrk-cnsltn-doc-pjtco-ajmt-mng-service.ts b/apps/as/src/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng/api/pwrk-cnsltn-doc-pjtco-ajmt-mng-service.ts
new file mode 100644
index 000000000..c525ac87b
--- /dev/null
+++ b/apps/as/src/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng/api/pwrk-cnsltn-doc-pjtco-ajmt-mng-service.ts
@@ -0,0 +1,24 @@
+import { client } from "@/shared/api";
+import { ENDPOINT } from "@/shared/config";
+import type { PageResponse } from "@/shared/model";
+
+import type {
+ PwrkCnsltnDocPjtcoAjmtMngResponseDto,
+ PwrkCnsltnDocPjtcoAjmtMngSearchDto,
+ PwrkCnsltnDocPjtcoAjmtMngService,
+} from "../model/pwrk-cnsltn-doc-pjtco-ajmt-mng-interface";
+
+const BASE = ENDPOINT.AS_SERVICE.PWRK_CNSLTN_DOC_PJTCO_AJMT_MNG;
+
+async function findPage(
+ searchDto: PwrkCnsltnDocPjtcoAjmtMngSearchDto,
+): Promise
> {
+ const response = await client.get>(BASE, {
+ params: searchDto,
+ });
+ return response.data;
+}
+
+export const pwrkCnsltnDocPjtcoAjmtMngService = {
+ findPage,
+} satisfies PwrkCnsltnDocPjtcoAjmtMngService;
diff --git a/apps/as/src/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng/api/queries.ts b/apps/as/src/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng/api/queries.ts
new file mode 100644
index 000000000..21f357c2b
--- /dev/null
+++ b/apps/as/src/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng/api/queries.ts
@@ -0,0 +1,22 @@
+import { useQuery } from "@tanstack/react-query";
+
+import type { PwrkCnsltnDocPjtcoAjmtMngSearchDto } from "../model/pwrk-cnsltn-doc-pjtco-ajmt-mng-interface";
+
+import { pwrkCnsltnDocPjtcoAjmtMngService } from "./pwrk-cnsltn-doc-pjtco-ajmt-mng-service";
+
+export const pwrkCnsltnDocPjtcoAjmtMngKeys = {
+ all: ["pwrk-cnsltn-doc-pjtco-ajmt-mng"] as const,
+ page: (params: PwrkCnsltnDocPjtcoAjmtMngSearchDto) =>
+ [...pwrkCnsltnDocPjtcoAjmtMngKeys.all, "findPage", params] as const,
+};
+
+export function usePwrkCnsltnDocPjtcoAjmtMngPage(
+ params: PwrkCnsltnDocPjtcoAjmtMngSearchDto,
+ isEnabled = true,
+) {
+ return useQuery({
+ queryKey: pwrkCnsltnDocPjtcoAjmtMngKeys.page(params),
+ queryFn: () => pwrkCnsltnDocPjtcoAjmtMngService.findPage(params),
+ enabled: Boolean(params.pwrkCnsltnDocNo) && isEnabled,
+ });
+}
diff --git a/apps/as/src/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng/index.ts b/apps/as/src/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng/index.ts
new file mode 100644
index 000000000..143bef3ba
--- /dev/null
+++ b/apps/as/src/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng/index.ts
@@ -0,0 +1,10 @@
+export { pwrkCnsltnDocPjtcoAjmtMngService } from "./api/pwrk-cnsltn-doc-pjtco-ajmt-mng-service";
+export {
+ pwrkCnsltnDocPjtcoAjmtMngKeys,
+ usePwrkCnsltnDocPjtcoAjmtMngPage,
+} from "./api/queries";
+export type {
+ PwrkCnsltnDocPjtcoAjmtMngResponseDto,
+ PwrkCnsltnDocPjtcoAjmtMngSearchDto,
+ PwrkCnsltnDocPjtcoAjmtMngService,
+} from "./model/pwrk-cnsltn-doc-pjtco-ajmt-mng-interface";
diff --git a/apps/as/src/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng/model/pwrk-cnsltn-doc-pjtco-ajmt-mng-interface.ts b/apps/as/src/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng/model/pwrk-cnsltn-doc-pjtco-ajmt-mng-interface.ts
new file mode 100644
index 000000000..420b9d44b
--- /dev/null
+++ b/apps/as/src/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng/model/pwrk-cnsltn-doc-pjtco-ajmt-mng-interface.ts
@@ -0,0 +1,44 @@
+import type { PageableParams, PageResponse } from "@/shared/model";
+
+/** 백엔드 PwrkCnsltnDocPjtcoAjmtMngResponseDto */
+export interface PwrkCnsltnDocPjtcoAjmtMngResponseDto {
+ pwrkCnsltnDocNo: string;
+ rvwOpnnSn: number;
+ acntgSeCd: string;
+ acntgSeCdNm?: string;
+ rvwOpnnClsfComCd?: string;
+ rvwOpnnClsfComCdNm?: string;
+ ognTpcoAmt?: number;
+ ognGvexpAmt?: number;
+ ognLcexpAmt?: number;
+ ognOrgprBrdnAmt?: number;
+ chgTpcoAmt?: number;
+ chgGvexpAmt?: number;
+ chgLcexpAmt?: number;
+ chgOrgprBrdnAmt?: number;
+ ajmtRsn?: string;
+ vrfcTpcoAmt?: number;
+ vrfcGvexpAmt?: number;
+ vrfcLcexpAmt?: number;
+ vrfcOrgprBrdnAmt?: number;
+ rsbnYn?: string;
+ vrfcCn?: string;
+ regDt?: string;
+ rgtr?: string;
+ rgtrNm?: string;
+ mdfcnDt?: string;
+ mdfr?: string;
+}
+
+/** 백엔드 PwrkCnsltnDocPjtcoAjmtMngSearchDto + Pageable */
+export interface PwrkCnsltnDocPjtcoAjmtMngSearchDto extends PageableParams {
+ pwrkCnsltnDocNo?: string;
+ rvwOpnnSn?: number;
+ acntgSeCd?: string;
+}
+
+export interface PwrkCnsltnDocPjtcoAjmtMngService {
+ findPage(
+ searchDto: PwrkCnsltnDocPjtcoAjmtMngSearchDto,
+ ): Promise>;
+}
diff --git a/apps/as/src/pages/fnrs-cnsltn/lib/fnrs-cnsltn-regist-schema.ts b/apps/as/src/pages/fnrs-cnsltn/lib/fnrs-cnsltn-regist-schema.ts
index 0faa372e9..21668e8b8 100644
--- a/apps/as/src/pages/fnrs-cnsltn/lib/fnrs-cnsltn-regist-schema.ts
+++ b/apps/as/src/pages/fnrs-cnsltn/lib/fnrs-cnsltn-regist-schema.ts
@@ -72,9 +72,9 @@ export const fnrsCnsltnRegistSchema = z.object({
cklstSn: z.number(),
cklstArtclSn: z.number(),
cklstRvwSn: z.number(),
- rvwStpComCd: z.string(),
+ rvwStpComCd: z.string().nullish(),
selected: z.enum(["Y", "N"]).nullable(),
- picRvwCn: z.string().nullable().optional(),
+ picRvwCn: z.string().nullish(),
}),
),
esntlAtchFileList: z.array(
diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-mng-dialog.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-mng-dialog.tsx
index f87fbed9b..718cea7f5 100644
--- a/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-mng-dialog.tsx
+++ b/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-mng-dialog.tsx
@@ -1,9 +1,10 @@
"use client";
-import { useEffect, useState } from "react";
+import { useEffect, useMemo, useState } from "react";
import dynamic from "next/dynamic";
import { useQuery, useQueryClient } from "@tanstack/react-query";
+import { PanelRightClose, PanelRightOpen } from "lucide-react";
import { getDefaultFileKey, useAlertStore, useTus } from "@/shared/lib";
import { AttachmentFileField } from "@/shared/ui";
@@ -12,6 +13,7 @@ import {
pwrkCnsltnDocCrtRsltSaveRequestSchema,
pwrkCnsltnDocCrtRsltService,
} from "@/entities/pwrk-cnsltn-doc-crt-rslt";
+import { usePwrkCnsltnDocPjtcoAjmtMngPage } from "@/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng";
import {
findCompletedPwrkDraft,
pwrkCnsltnMngKeys,
@@ -27,6 +29,8 @@ import {
Skeleton,
} from "@common/components";
+import { PwrkCnsltnDocPjtcoAjmtTable } from "./pwrk-cnsltn-doc-pjtco-ajmt-table";
+
const HangulGiangi = dynamic(
() => import("@/widgets/hangulgiangi").then((module) => module.HangulGiangi),
{
@@ -69,6 +73,7 @@ function PwrkCnsltnDocMngDialog({
const alert = useAlertStore((state) => state.setMessage);
const [atchFileGroupId, setAtchFileGroupId] = useState("");
const [uploadedFiles, setUploadedFiles] = useState([]);
+ const [isPjtcoAjmtTableOpen, setIsPjtcoAjmtTableOpen] = useState(true);
const {
data: pwrkCnsltnData,
@@ -92,6 +97,20 @@ function PwrkCnsltnDocMngDialog({
const documentFileName = `실무협의서_${pwrkCnsltnData?.pwrkCnsltnDocNo ?? crtDmndUuid}.hwpx`;
const isLoading = isPwrkCnsltnLoading || isDocumentLoading;
const isError = isPwrkCnsltnError || isDocumentError;
+ const pjtcoAjmtSearchParams = useMemo(
+ () => ({
+ pwrkCnsltnDocNo: pwrkCnsltnData?.pwrkCnsltnDocNo,
+ page: 0,
+ size: 1000,
+ sort: "rvwOpnnSn,asc",
+ }),
+ [pwrkCnsltnData?.pwrkCnsltnDocNo],
+ );
+ const {
+ data: pjtcoAjmtPage,
+ isLoading: isPjtcoAjmtLoading,
+ isError: isPjtcoAjmtError,
+ } = usePwrkCnsltnDocPjtcoAjmtMngPage(pjtcoAjmtSearchParams, open);
const { uploadFileAsync, isUploading, uploads } = useTus({
onSuccess: (atflCd, atflId, _file, fileKey) => {
@@ -258,17 +277,52 @@ function PwrkCnsltnDocMngDialog({
생성 완료된 실무협의서 초안이 없습니다.
) : null}
- {completedDraft ? (
- documentBlob ? (
-
- ) : null
+ {completedDraft && documentBlob ? (
+
+
+
+
+ {isPjtcoAjmtTableOpen ? (
+
+
+ 금액검증결과
+
+
+
+
+ ) : (
+
+ )}
+
) : null}
{completedDraft ? (
diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-pjtco-ajmt-table.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-pjtco-ajmt-table.tsx
new file mode 100644
index 000000000..cc0c9ba35
--- /dev/null
+++ b/apps/as/src/pages/fnrs-cnsltn/ui/components/pwrk-cnsltn-doc-pjtco-ajmt-table.tsx
@@ -0,0 +1,97 @@
+"use client";
+
+import type { PwrkCnsltnDocPjtcoAjmtMngResponseDto } from "@/entities/pwrk-cnsltn-doc-pjtco-ajmt-mng";
+import { fmtNumber } from "@/widgets/pbadms-sprt";
+import {
+ Skeleton,
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@common/components";
+
+interface PwrkCnsltnDocPjtcoAjmtTableProps {
+ rows: PwrkCnsltnDocPjtcoAjmtMngResponseDto[];
+ isLoading: boolean;
+ isError: boolean;
+}
+
+function PwrkCnsltnDocPjtcoAjmtTable({
+ rows,
+ isLoading,
+ isError,
+}: PwrkCnsltnDocPjtcoAjmtTableProps) {
+ if (isLoading) {
+ return (
+
+
+
+
+
+ );
+ }
+
+ if (isError) {
+ return (
+
+ 사업비조정 정보를 불러오지 못했습니다.
+
+ );
+ }
+
+ return (
+
+
+
+ 구분
+ 검증결과
+ 검증금액
+
+
+
+ {rows.length === 0 ? (
+
+
+ 조회된 사업비조정 항목이 없습니다.
+
+
+ ) : (
+ rows.map((row) => (
+
+ {formatDivision(row)}
+
+ {formatVrfcCn(row.vrfcCn)}
+
+ {formatVrfcAmt(row.vrfcTpcoAmt)}
+
+ ))
+ )}
+
+
+ );
+}
+
+function getPjtcoAjmtRowKey(row: PwrkCnsltnDocPjtcoAjmtMngResponseDto) {
+ return [row.pwrkCnsltnDocNo, row.rvwOpnnSn, row.acntgSeCd].join("::");
+}
+
+function formatDivision(row: PwrkCnsltnDocPjtcoAjmtMngResponseDto) {
+ const label = row.acntgSeCdNm?.trim() || row.acntgSeCd?.trim();
+ return label || "-";
+}
+
+function formatVrfcCn(value: string | undefined) {
+ const text = value?.trim();
+ return text || "-";
+}
+
+function formatVrfcAmt(value: number | undefined) {
+ if (value === undefined || value === null) return "-";
+ const formatted = fmtNumber(value);
+ return formatted || "-";
+}
+
+export { PwrkCnsltnDocPjtcoAjmtTable };
+export type { PwrkCnsltnDocPjtcoAjmtTableProps };
diff --git a/apps/as/src/shared/config/api.ts b/apps/as/src/shared/config/api.ts
index 3e7d08c08..a575822f2 100644
--- a/apps/as/src/shared/config/api.ts
+++ b/apps/as/src/shared/config/api.ts
@@ -28,6 +28,7 @@ export const ENDPOINT = {
DCRAG_TO: "/as-service/api/v1/dcrag-to",
PWRK_CNSLTN_MNG: "/as-service/api/v1/pwrk-cnsltn-mng",
PWRK_CNSLTN_DOC_CRT_RSLT: "/as-service/api/v1/pwrk-cnsltn-doc-crt-rslt",
+ PWRK_CNSLTN_DOC_PJTCO_AJMT_MNG: "/as-service/api/v1/pwrk-cnsltn-doc-pjtco-ajmt-mng",
},
USER_SERVICE: {
LOGIN: "/user-service/login",
diff --git a/apps/as/src/shared/model/pbadms-sprt.ts b/apps/as/src/shared/model/pbadms-sprt.ts
index 5456578e8..77a346522 100644
--- a/apps/as/src/shared/model/pbadms-sprt.ts
+++ b/apps/as/src/shared/model/pbadms-sprt.ts
@@ -191,7 +191,7 @@ export interface CklstResultSaveBase {
cklstRvwSn?: number;
cklstArtclSn?: number;
cklstSn?: number;
- rvwStpComCd: string;
+ rvwStpComCd?: string | null;
picRvwCn?: string | null;
}
diff --git a/apps/as/src/widgets/hangulgiangi/model/hwp-ctrl.ts b/apps/as/src/widgets/hangulgiangi/model/hwp-ctrl.ts
index 814a8c5a1..bc3ac97cd 100644
--- a/apps/as/src/widgets/hangulgiangi/model/hwp-ctrl.ts
+++ b/apps/as/src/widgets/hangulgiangi/model/hwp-ctrl.ts
@@ -58,6 +58,7 @@ export interface HwpCtrl {
callback?: HwpCtrlSaveAsCallback,
callbackUserData?: unknown,
) => boolean;
+ ShowHorizontalScroll: (show: boolean) => boolean;
}
export interface HwpCtrlFrameWindow {
diff --git a/apps/as/src/widgets/hangulgiangi/ui/hangul-giangi.tsx b/apps/as/src/widgets/hangulgiangi/ui/hangul-giangi.tsx
index 16663faa2..db9db7c32 100644
--- a/apps/as/src/widgets/hangulgiangi/ui/hangul-giangi.tsx
+++ b/apps/as/src/widgets/hangulgiangi/ui/hangul-giangi.tsx
@@ -87,7 +87,10 @@ function HangulGiangi({
"HWPX",
"",
(result) => {
- const callbackDocumentKey = getCallbackDocumentKey(result.CallbackUserData, documentKey);
+ const callbackDocumentKey = getCallbackDocumentKey(
+ result.CallbackUserData,
+ documentKey,
+ );
if (openingDocumentKeyRef.current !== callbackDocumentKey) return;
openingDocumentKeyRef.current = null;
diff --git a/apps/as/src/widgets/pbadms-sprt/lib/checklist-form-utils.ts b/apps/as/src/widgets/pbadms-sprt/lib/checklist-form-utils.ts
index fbf63472d..52ad49f7a 100644
--- a/apps/as/src/widgets/pbadms-sprt/lib/checklist-form-utils.ts
+++ b/apps/as/src/widgets/pbadms-sprt/lib/checklist-form-utils.ts
@@ -21,14 +21,12 @@ interface CklstResultListItem {
cklstSn: number;
cklstArtclSn: number;
cklstRvwSn: number;
- rvwStpComCd: string;
+ rvwStpComCd?: string | null;
selected: "Y" | "N" | null;
picRvwCn?: string | null;
}
-export function normalizeTaskSeComCdArray(
- value: string | string[] | undefined | null,
-): string[] {
+export function normalizeTaskSeComCdArray(value: string | string[] | undefined | null): string[] {
if (!value) return [];
if (Array.isArray(value)) return value.filter(Boolean);
return value