@opendata-kr/narajangteo-opening-mcp 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +13 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ function createGateway() {
|
|
|
14
14
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15
15
|
|
|
16
16
|
// src/version.ts
|
|
17
|
-
var VERSION = "0.
|
|
17
|
+
var VERSION = "0.2.0";
|
|
18
18
|
|
|
19
19
|
// src/tools/searchAwards.ts
|
|
20
20
|
import { z } from "zod";
|
|
@@ -46,6 +46,9 @@ function openingInqryDiv(dateType, ppsSrch) {
|
|
|
46
46
|
if (ppsSrch) return dateType === "notice" ? "3" : dateType === "opened" ? "2" : "1";
|
|
47
47
|
return dateType === "notice" ? "4" : dateType === "opened" ? "3" : "2";
|
|
48
48
|
}
|
|
49
|
+
function preparInqryDiv(byNotice) {
|
|
50
|
+
return byNotice ? "2" : "1";
|
|
51
|
+
}
|
|
49
52
|
|
|
50
53
|
// src/api/dateWindow.ts
|
|
51
54
|
var MAX_WINDOW_DAYS = 31;
|
|
@@ -89,8 +92,7 @@ async function fetchAllPages(call, op, params, opts) {
|
|
|
89
92
|
// src/format.ts
|
|
90
93
|
var pick = (raw, k) => raw[k] ?? "";
|
|
91
94
|
function compositeKeyOf(raw) {
|
|
92
|
-
|
|
93
|
-
return `${g("bidNtceNo")}|${g("bidNtceOrd")}|${g("bidClsfcNo")}|${g("rbidNo")}`;
|
|
95
|
+
return `${pick(raw, "bidNtceNo")}|${pick(raw, "bidNtceOrd")}|${pick(raw, "bidClsfcNo")}|${pick(raw, "rbidNo")}`;
|
|
94
96
|
}
|
|
95
97
|
function parseOpengCorpInfo(s) {
|
|
96
98
|
if (!s) return null;
|
|
@@ -158,12 +160,13 @@ function aggregatePreparPrice(items) {
|
|
|
158
160
|
}
|
|
159
161
|
function failReasonHint(participants) {
|
|
160
162
|
const n = Number(participants);
|
|
163
|
+
if (!Number.isFinite(n)) return "\uCC38\uAC00\uC5C5\uCCB4\uC218 \uBBF8\uC0C1. \uC720\uCC30 \uC0AC\uC720 \uCD94\uC815 \uBD88\uAC00";
|
|
161
164
|
if (n === 0) return "\uBB34\uC751\uCC30 \uCD94\uC815(\uCC38\uAC00 0). \uC7AC\uB3C4\uC804 \uAE30\uD68C\uC77C \uC218 \uC788\uC74C";
|
|
162
165
|
if (n === 1) return "\uB2E8\uB3C5\uC751\uCC30 \uCD94\uC815(\uCC38\uAC00 1). \uC218\uC758\uACC4\uC57D \uC9C1\uD589 \uAC00\uB2A5, \uAE30\uD68C \uB0AE\uC74C";
|
|
163
166
|
return "\uC801\uACA9\uC790 \uC5C6\uC74C \uB4F1 \uCD94\uC815(\uCC38\uAC00 2+). \uC7AC\uB3C4\uC804 \uAE30\uD68C\uC77C \uC218 \uC788\uC74C";
|
|
164
167
|
}
|
|
165
168
|
function estimateAwardMethod(bidders) {
|
|
166
|
-
const scored = bidders.some((b) => b.totalScore
|
|
169
|
+
const scored = bidders.some((b) => b.totalScore !== "" || b.techScore !== "");
|
|
167
170
|
return { method: scored ? "negotiated" : "qualification_or_other", uncertain: true };
|
|
168
171
|
}
|
|
169
172
|
|
|
@@ -330,20 +333,20 @@ async function runGetBidResult(client, args) {
|
|
|
330
333
|
const errors = [];
|
|
331
334
|
const kinds = args.bidKind ? [args.bidKind] : [...ALL_BID_KINDS];
|
|
332
335
|
const statuses = !args.status || args.status === "all" ? [...ALL_OPENING_STATUS] : [args.status];
|
|
333
|
-
const
|
|
336
|
+
const notice = args.bidNtceNo;
|
|
334
337
|
const aRaw = [], bRaw = [], cRaw = [], dRaw = [];
|
|
335
338
|
await Promise.all([
|
|
336
339
|
...kinds.map(async (k) => {
|
|
337
|
-
aRaw.push(...await safeItems(client, awardListOp(k), { inqryDiv: awardInqryDiv("notice", false), bidNtceNo:
|
|
340
|
+
aRaw.push(...await safeItems(client, awardListOp(k), { inqryDiv: awardInqryDiv("notice", false), bidNtceNo: notice }, errors));
|
|
338
341
|
}),
|
|
339
342
|
...kinds.map(async (k) => {
|
|
340
|
-
bRaw.push(...await safeItems(client, openingListOp(k), { inqryDiv: openingInqryDiv("notice", false), bidNtceNo:
|
|
343
|
+
bRaw.push(...await safeItems(client, openingListOp(k), { inqryDiv: openingInqryDiv("notice", false), bidNtceNo: notice }, errors));
|
|
341
344
|
}),
|
|
342
345
|
...kinds.map(async (k) => {
|
|
343
|
-
cRaw.push(...await safeItems(client, preparPriceOp(k), { inqryDiv:
|
|
346
|
+
cRaw.push(...await safeItems(client, preparPriceOp(k), { inqryDiv: preparInqryDiv(true), bidNtceNo: notice }, errors));
|
|
344
347
|
}),
|
|
345
348
|
...statuses.map(async (s) => {
|
|
346
|
-
dRaw.push(...await safeItems(client, D_OPERATION[s], { bidNtceNo:
|
|
349
|
+
dRaw.push(...await safeItems(client, D_OPERATION[s], { bidNtceNo: notice }, errors));
|
|
347
350
|
})
|
|
348
351
|
]);
|
|
349
352
|
const keys = /* @__PURE__ */ new Set();
|
|
@@ -370,7 +373,7 @@ async function runGetBidResult(client, args) {
|
|
|
370
373
|
filtered = executions.filter((e) => (args.bidNtceOrd === void 0 || e.bidNtceOrd === args.bidNtceOrd) && (args.bidClsfcNo === void 0 || e.bidClsfcNo === args.bidClsfcNo) && (args.rbidNo === void 0 || e.rbidNo === args.rbidNo));
|
|
371
374
|
}
|
|
372
375
|
return {
|
|
373
|
-
bidNtceNo:
|
|
376
|
+
bidNtceNo: notice,
|
|
374
377
|
executions: filtered,
|
|
375
378
|
errors,
|
|
376
379
|
notes: [
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/api/gateway.ts","../src/server.ts","../src/version.ts","../src/tools/searchAwards.ts","../src/api/endpoints.ts","../src/api/dateWindow.ts","../src/format.ts","../src/tools/searchOpenings.ts","../src/tools/getBidResult.ts"],"sourcesContent":["import { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { createGateway } from \"./api/gateway.js\";\nimport { createServer } from \"./server.js\";\n\nasync function main(): Promise<void> {\n const client = createGateway();\n if (client.serviceKeyLooksPreEncoded) {\n console.error(\n \"[narajangteo-opening-mcp] 경고: DATA_GO_KR_SERVICE_KEY가 이미 URL 인코딩된 키로 보입니다. Decoding(원본) 키를 사용하세요.\",\n );\n }\n const server = createServer(client);\n await server.connect(new StdioServerTransport());\n}\n\nmain().catch((err: unknown) => {\n console.error(\"[narajangteo-opening-mcp] fatal:\", err);\n process.exit(1);\n});\n","import { createClient, type DataGoKrClient } from \"@opendata-kr/core\";\n\n// 나라장터 낙찰정보서비스(ScsbidInfoService). 입찰공고(/ad/)와 달리 /as/ 경로다.\nconst SERVICE_PATH = \"/1230000/as/ScsbidInfoService\";\n\nexport function createGateway(): DataGoKrClient {\n // 개찰결과(계열 B)는 응답이 무겁고 느려 기본 타임아웃(~10초)을 넘는 페이지가 있다\n // (라이브: 30~50행에서 8~9초, 100행 타임아웃). 낙찰(계열 A)은 빨라 영향 없다.\n return createClient({ path: SERVICE_PATH, params: { type: \"json\" }, timeout: 30000 });\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { DataGoKrClient } from \"@opendata-kr/core\";\nimport { VERSION } from \"./version.js\";\nimport { searchAwardsInputShape, runSearchAwards, type SearchAwardsArgs } from \"./tools/searchAwards.js\";\nimport { searchOpeningsInputShape, runSearchOpenings, type SearchOpeningsArgs } from \"./tools/searchOpenings.js\";\nimport { getBidResultInputShape, runGetBidResult, type GetBidResultArgs } from \"./tools/getBidResult.js\";\n\nfunction textResult(payload: unknown, isError = false) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify(payload, null, 2) }], ...(isError ? { isError: true } : {}) };\n}\n\nexport function createServer(client: DataGoKrClient): McpServer {\n const server = new McpServer({ name: \"narajangteo-opening-mcp\", version: VERSION });\n\n server.registerTool(\"search_awards\", {\n title: \"낙찰 결과 검색\",\n description:\n \"나라장터 낙찰 결과(최종낙찰자)를 공고명·기관·수요기관(코드)·지역·업종·추정가·사업자번호·기간으로 검색한다. '누가 얼마에 낙찰받았나', 경쟁사(bizno) 낙찰 이력, 되풀이 사업의 종단 조회에 쓴다. 특정 공고의 개찰·투찰업체·예비가 상세는 get_bid_result, 개찰 진행·유찰 발굴은 search_openings를 쓴다. 업무구분 미지정 시 물품/공사/용역/외자를 병렬 조회한다. 낙찰자만 반환하며 그 업체가 참여했으나 진 입찰은 미포함.\",\n inputSchema: searchAwardsInputShape,\n annotations: { readOnlyHint: true, openWorldHint: true },\n }, async (args) => {\n try { return textResult(await runSearchAwards(client, args as SearchAwardsArgs)); }\n catch (e) { return textResult({ error: e instanceof Error ? e.message : String(e) }, true); }\n });\n\n server.registerTool(\"search_openings\", {\n title: \"개찰결과 검색\",\n description:\n \"나라장터 개찰결과 목록을 검색하고 진행상태(개찰완료/유찰/재입찰)로 필터한다. 유찰·재입찰 공고 발굴에 쓴다. 최종낙찰자 검색은 search_awards, 단일 공고 상세는 get_bid_result를 쓴다. status는 API가 아니라 응답 기준 클라이언트 필터라 응답이 느리니 기관·업종·기간으로 좁혀 쓴다(truncated=true면 미완 스캔). 재입찰은 동일 공고 내 재입찰이며 재공고가 아니다(재공고는 입찰공고 서비스 소관).\",\n inputSchema: searchOpeningsInputShape,\n annotations: { readOnlyHint: true, openWorldHint: true },\n }, async (args) => {\n try { return textResult(await runSearchOpenings(client, args as SearchOpeningsArgs)); }\n catch (e) { return textResult({ error: e instanceof Error ? e.message : String(e) }, true); }\n });\n\n server.registerTool(\"get_bid_result\", {\n title: \"공고 개찰 상세\",\n description:\n \"입찰공고번호로 그 공고의 낙찰자·개찰진행·예비가격상세(사정률)·투찰업체별 순위/금액/점수를 복합키 정합으로 단건 조회한다. 딜 사후분석·투찰가 참고에 쓴다. 여러 공고를 조건으로 찾으려면 search_awards 또는 search_openings를 쓴다. 다분류·다차수 공고는 집행 단위 배열로 분리한다. 낙찰방식은 추정이며(협상계약만 기술·가격 점수 제공, 적격심사는 금액·순위만), myBizno를 주면 자사 투찰행에 isOurs를 표시한다.\",\n inputSchema: getBidResultInputShape,\n annotations: { readOnlyHint: true, openWorldHint: true },\n }, async (args) => {\n try { return textResult(await runGetBidResult(client, args as GetBidResultArgs)); }\n catch (e) { return textResult({ error: e instanceof Error ? e.message : String(e) }, true); }\n });\n\n return server;\n}\n","// 버전은 release-please가 릴리스마다 이 마커 사이 값을 교체한다.\n// release-please-config.json의 extra-files에 { type: \"generic\", path: \"src/version.ts\" }로 등록돼 있다.\n// 초기값 0.0.0은 첫 릴리스에서 실제 버전으로 대체된다.\n// x-release-please-start-version\nexport const VERSION = \"0.1.0\";\n// x-release-please-end\n","import { z } from \"zod\";\nimport type { DataGoKrClient } from \"@opendata-kr/core\";\nimport { ALL_BID_KINDS, awardSearchOp, awardInqryDiv, type BidKind, type DateType } from \"../api/endpoints.js\";\nimport { splitDateWindows, fetchAllPages, MAX_WINDOW_DAYS } from \"../api/dateWindow.js\";\nimport { formatAward } from \"../format.js\";\nimport type { AwardResult } from \"../api/types.js\";\n\nexport const searchAwardsInputShape = {\n bidKind: z.array(z.enum([\"cnstwk\", \"servc\", \"thng\", \"frgcpt\"])).optional().describe(\"업무구분 배열. 미지정 시 전 구분 병렬\"),\n keyword: z.string().optional().describe(\"공고명 부분검색(bidNtceNm)\"),\n institution: z.string().optional().describe(\"공고기관명(ntceInsttNm)\"),\n demandInstitution: z.string().optional().describe(\"수요기관명(dminsttNm)\"),\n demandInstitutionCode: z.string().optional().describe(\"수요기관코드(dminsttCd). 종단 식별에 안정적\"),\n detailProductCode: z.string().optional().describe(\"세부품명번호(dtilPrdctClsfcNo)\"),\n region: z.string().optional().describe(\"참가제한지역명(prtcptLmtRgnNm)\"),\n industry: z.string().optional().describe(\"업종명(indstrytyNm)\"),\n minPrice: z.number().optional().describe(\"추정가격 하한(presmptPrceBgn)\"),\n maxPrice: z.number().optional().describe(\"추정가격 상한(presmptPrceEnd)\"),\n bizno: z.string().optional().describe(\"업체 사업자번호. 그 업체의 낙찰건만 조회(진 입찰은 미포함)\"),\n startDate: z.string().optional().describe(\"조회 시작일 YYYYMMDD\"),\n endDate: z.string().optional().describe(\"조회 종료일 YYYYMMDD\"),\n dateType: z.enum([\"posted\", \"opened\"]).optional().describe(\"날짜 기준. posted=공고게시(기본), opened=개찰\"),\n pageSize: z.number().int().min(1).max(100).optional().describe(\"창당 페이지 크기(기본 100)\"),\n maxPages: z.number().int().min(1).max(50).optional().describe(\"창당 최대 페이지(기본 10)\"),\n};\n\nexport type SearchAwardsArgs = {\n bidKind?: BidKind[]; keyword?: string; institution?: string; demandInstitution?: string;\n demandInstitutionCode?: string; detailProductCode?: string; region?: string; industry?: string;\n minPrice?: number; maxPrice?: number; bizno?: string; startDate?: string; endDate?: string;\n dateType?: \"posted\" | \"opened\"; pageSize?: number; maxPages?: number;\n};\n\ntype KindResult = { totalCount: number; items: AwardResult[]; truncated: boolean } | { error: string };\nexport interface SearchAwardsResult { query: SearchAwardsArgs; results: Partial<Record<BidKind, KindResult>>; notes: string[]; }\n\nexport async function runSearchAwards(client: DataGoKrClient, args: SearchAwardsArgs): Promise<SearchAwardsResult> {\n const kinds = args.bidKind ?? [...ALL_BID_KINDS];\n const dateType: DateType = args.dateType ?? \"posted\";\n const inqryDiv = awardInqryDiv(dateType, true);\n const base: Record<string, string | number | undefined> = {\n inqryDiv,\n bidNtceNm: args.keyword, ntceInsttNm: args.institution, dminsttNm: args.demandInstitution,\n dminsttCd: args.demandInstitutionCode, dtilPrdctClsfcNo: args.detailProductCode,\n prtcptLmtRgnNm: args.region, indstrytyNm: args.industry,\n presmptPrceBgn: args.minPrice, presmptPrceEnd: args.maxPrice, bizno: args.bizno,\n };\n\n if ((args.startDate && !args.endDate) || (!args.startDate && args.endDate)) {\n throw new Error(\"startDate와 endDate는 함께 지정해야 합니다.\");\n }\n if (args.startDate && args.endDate && args.startDate > args.endDate) {\n throw new Error(\"startDate가 endDate보다 늦습니다.\");\n }\n\n const windows = args.startDate && args.endDate\n ? splitDateWindows(args.startDate, args.endDate, MAX_WINDOW_DAYS)\n : [{ bgn: undefined as string | undefined, end: undefined as string | undefined }];\n const pageSize = args.pageSize ?? 100;\n const maxPages = args.maxPages ?? 10;\n\n const settled = await Promise.allSettled(kinds.map(async (kind) => {\n const items: AwardResult[] = [];\n let totalCount = 0, truncated = false;\n for (const w of windows) {\n const params = { ...base, inqryBgnDt: w.bgn, inqryEndDt: w.end };\n const r = await fetchAllPages((op, p) => client.call(op, p), awardSearchOp(kind), params, { pageSize, maxPages });\n items.push(...r.items.map(formatAward));\n totalCount += r.totalCount;\n truncated = truncated || r.truncated;\n }\n return { totalCount, items, truncated };\n }));\n\n const results: Partial<Record<BidKind, KindResult>> = {};\n kinds.forEach((kind, i) => {\n const s = settled[i]!;\n results[kind] = s.status === \"fulfilled\" ? s.value : { error: s.reason instanceof Error ? s.reason.message : String(s.reason) };\n });\n return {\n query: args, results,\n notes: [\n \"낙찰자만 조회한다(그 업체가 참여했으나 진 입찰은 이 API로 도달 불가).\",\n \"여러 창(주 단위 분할)의 totalCount 합은 창별 합계다.\",\n ],\n };\n}\n","export type BidKind = \"cnstwk\" | \"servc\" | \"thng\" | \"frgcpt\";\nexport const ALL_BID_KINDS: readonly BidKind[] = [\"cnstwk\", \"servc\", \"thng\", \"frgcpt\"];\nconst SUFFIX: Record<BidKind, string> = {\n cnstwk: \"Cnstwk\", servc: \"Servc\", thng: \"Thng\", frgcpt: \"Frgcpt\",\n};\n\n// 계열 A: 낙찰된 목록 현황\nexport const awardListOp = (k: BidKind): string => `getScsbidListSttus${SUFFIX[k]}`;\nexport const awardSearchOp = (k: BidKind): string => `getScsbidListSttus${SUFFIX[k]}PPSSrch`;\n// 계열 B: 개찰결과 목록\nexport const openingListOp = (k: BidKind): string => `getOpengResultListInfo${SUFFIX[k]}`;\nexport const openingSearchOp = (k: BidKind): string => `getOpengResultListInfo${SUFFIX[k]}PPSSrch`;\n// 계열 C: 예비가격상세\nexport const preparPriceOp = (k: BidKind): string => `getOpengResultListInfo${SUFFIX[k]}PreparPcDetail`;\n\n// 계열 D: 상태별 (업무구분 무관 단일 오퍼레이션)\nexport type OpeningStatus = \"completed\" | \"failing\" | \"rebid\";\nexport const ALL_OPENING_STATUS: readonly OpeningStatus[] = [\"completed\", \"failing\", \"rebid\"];\nexport const D_OPERATION: Record<OpeningStatus, string> = {\n completed: \"getOpengResultListInfoOpengCompt\",\n failing: \"getOpengResultListInfoFailing\",\n rebid: \"getOpengResultListInfoRebid\",\n};\n\n// 날짜 기준. posted=공고(게시), opened=개찰, notice=공고번호 단건.\nexport type DateType = \"posted\" | \"opened\" | \"notice\";\n\n// A 기본판: 1등록 2공고 3개찰 4공고번호 / A PPSSrch: 1공고게시 2개찰 3공고번호\nexport function awardInqryDiv(dateType: DateType, ppsSrch: boolean): string {\n if (ppsSrch) return dateType === \"notice\" ? \"3\" : dateType === \"opened\" ? \"2\" : \"1\";\n return dateType === \"notice\" ? \"4\" : dateType === \"opened\" ? \"3\" : \"2\";\n}\n// B 기본판: 1입력 2공고 3개찰 4공고번호 / B PPSSrch: A PPSSrch와 동일\nexport function openingInqryDiv(dateType: DateType, ppsSrch: boolean): string {\n if (ppsSrch) return dateType === \"notice\" ? \"3\" : dateType === \"opened\" ? \"2\" : \"1\";\n return dateType === \"notice\" ? \"4\" : dateType === \"opened\" ? \"3\" : \"2\";\n}\n","import type { OperationResult, RawItem } from \"@opendata-kr/core\";\n\n// 라이브 검증(2026-07-07): 낙찰 서비스는 1개월 창도 통과(1주 1189·1개월 6096건 정상).\n// 형제 bid 서비스(1주 축소)와 달라 31일로 둔다.\nexport const MAX_WINDOW_DAYS = 31;\n\nfunction toDate(yyyymmdd: string): Date {\n const y = Number(yyyymmdd.slice(0, 4)), m = Number(yyyymmdd.slice(4, 6)), d = Number(yyyymmdd.slice(6, 8));\n return new Date(Date.UTC(y, m - 1, d));\n}\nfunction fmt(dt: Date): string {\n const y = dt.getUTCFullYear(), m = String(dt.getUTCMonth() + 1).padStart(2, \"0\"), d = String(dt.getUTCDate()).padStart(2, \"0\");\n return `${y}${m}${d}`;\n}\n\nexport function splitDateWindows(start: string, end: string, maxDays: number): Array<{ bgn: string; end: string }> {\n const windows: Array<{ bgn: string; end: string }> = [];\n let cur = toDate(start);\n const last = toDate(end);\n while (cur <= last) {\n const winEnd = new Date(cur);\n winEnd.setUTCDate(winEnd.getUTCDate() + maxDays - 1);\n const eff = winEnd > last ? last : winEnd;\n windows.push({ bgn: `${fmt(cur)}0000`, end: `${fmt(eff)}2359` });\n cur = new Date(eff);\n cur.setUTCDate(cur.getUTCDate() + 1);\n }\n return windows;\n}\n\ntype CallFn = (op: string, params: Record<string, string | number | undefined>) => Promise<OperationResult>;\n\nexport async function fetchAllPages(\n call: CallFn, op: string, params: Record<string, string | number | undefined>,\n opts: { pageSize: number; maxPages: number },\n): Promise<{ totalCount: number; items: RawItem[]; truncated: boolean }> {\n const items: RawItem[] = [];\n let totalCount = 0;\n let page = 1;\n for (; page <= opts.maxPages; page++) {\n const r = await call(op, { ...params, pageNo: page, numOfRows: opts.pageSize });\n totalCount = r.totalCount;\n items.push(...r.items);\n if (items.length >= totalCount || r.items.length === 0) {\n return { totalCount, items, truncated: false };\n }\n }\n return { totalCount, items, truncated: true };\n}\n","import type { RawItem } from \"@opendata-kr/core\";\nimport type { AwardResult, OpeningSummary, BidderDetail, CompositeKey, PreparPriceDetail } from \"./api/types.js\";\n\nconst pick = (raw: RawItem, k: string): string => raw[k] ?? \"\";\n\nexport function compositeKeyOf(raw: RawItem | CompositeKey): string {\n const g = (k: string) => (raw as RawItem)[k] ?? \"\";\n return `${g(\"bidNtceNo\")}|${g(\"bidNtceOrd\")}|${g(\"bidClsfcNo\")}|${g(\"rbidNo\")}`;\n}\n\nexport function parseOpengCorpInfo(s: string): { name: string; bizno: string; ceo: string; amount: string; rate: string } | null {\n if (!s) return null;\n const [name = \"\", bizno = \"\", ceo = \"\", amount = \"\", rate = \"\"] = s.split(\"^\");\n return { name, bizno, ceo, amount, rate };\n}\n\nexport function formatAward(raw: RawItem): AwardResult {\n return {\n bidNtceNo: pick(raw, \"bidNtceNo\"), bidNtceNm: pick(raw, \"bidNtceNm\"), participants: pick(raw, \"prtcptCnum\"),\n winner: pick(raw, \"bidwinnrNm\"), winnerBizno: pick(raw, \"bidwinnrBizno\"), winnerCeo: pick(raw, \"bidwinnrCeoNm\"),\n awardAmount: pick(raw, \"sucsfbidAmt\"), awardRate: pick(raw, \"sucsfbidRate\"), realOpeningDt: pick(raw, \"rlOpengDt\"),\n demandInstitution: pick(raw, \"dminsttNm\"), finalAwardDate: pick(raw, \"fnlSucsfDate\"),\n };\n}\n\nexport function formatOpening(raw: RawItem): OpeningSummary {\n return {\n bidNtceNo: pick(raw, \"bidNtceNo\"), bidNtceNm: pick(raw, \"bidNtceNm\"), openingDt: pick(raw, \"opengDt\"),\n participants: pick(raw, \"prtcptCnum\"), progress: pick(raw, \"progrsDivCdNm\"),\n topBidder: parseOpengCorpInfo(pick(raw, \"opengCorpInfo\")),\n reservePriceFileExists: pick(raw, \"rsrvtnPrceFileExistnceYn\"),\n noticeInstitution: pick(raw, \"ntceInsttNm\"), demandInstitution: pick(raw, \"dminsttNm\"),\n };\n}\n\nexport function formatBidder(raw: RawItem): BidderDetail {\n return {\n rank: pick(raw, \"opengRank\"), name: pick(raw, \"prcbdrNm\"), bizno: pick(raw, \"prcbdrBizno\"), ceo: pick(raw, \"prcbdrCeoNm\"),\n amount: pick(raw, \"bidprcAmt\"), rate: pick(raw, \"bidprcrt\"), remark: pick(raw, \"rmrk\"),\n priceScore: pick(raw, \"bidPrceEvlVal\"), techScore: pick(raw, \"techEvlVal\"), techRawScore: pick(raw, \"techEvlNaturVal\"),\n totalScore: pick(raw, \"totalEvlAmtVal\"), bidDt: pick(raw, \"bidprcDt\"),\n };\n}\n\nexport function aggregatePreparPrice(items: RawItem[]): PreparPriceDetail {\n const first = items[0];\n const planPrice = first ? pick(first, \"plnprc\") : \"\";\n const baseAmount = first ? pick(first, \"bssamt\") : \"\";\n const p = Number(planPrice), b = Number(baseAmount);\n const saJeongRate = first && b > 0 && Number.isFinite(p) && Number.isFinite(b) ? p / b : null;\n return {\n planPrice, baseAmount, saJeongRate,\n totalReserveCount: first ? pick(first, \"totRsrvtnPrceNum\") : \"\",\n drawn: first ? pick(first, \"drwtYn\") : \"\",\n reserves: items.map((r) => ({ seq: pick(r, \"compnoRsrvtnPrceSno\"), basePlanPrice: pick(r, \"bsisPlnprc\") })),\n };\n}\n\n// 유찰 사유는 API에 없다. 참가업체수(prtcptCnum)로 추론 힌트만 제공(spec §6, S4).\nexport function failReasonHint(participants: string): string {\n const n = Number(participants);\n if (n === 0) return \"무응찰 추정(참가 0). 재도전 기회일 수 있음\";\n if (n === 1) return \"단독응찰 추정(참가 1). 수의계약 직행 가능, 기회 낮음\";\n return \"적격자 없음 등 추정(참가 2+). 재도전 기회일 수 있음\";\n}\n\n// 낙찰방식 구분 필드가 API에 없다. D 점수 채움 패턴으로 추정(spec §6, S5).\nexport function estimateAwardMethod(bidders: BidderDetail[]): { method: \"negotiated\" | \"qualification_or_other\"; uncertain: true } {\n const scored = bidders.some((b) => (b.totalScore && b.totalScore !== \"\") || (b.techScore && b.techScore !== \"\"));\n return { method: scored ? \"negotiated\" : \"qualification_or_other\", uncertain: true };\n}\n","import { z } from \"zod\";\nimport type { DataGoKrClient } from \"@opendata-kr/core\";\nimport { ALL_BID_KINDS, openingSearchOp, openingInqryDiv, type BidKind, type DateType } from \"../api/endpoints.js\";\nimport { splitDateWindows, fetchAllPages, MAX_WINDOW_DAYS } from \"../api/dateWindow.js\";\nimport { formatOpening, failReasonHint } from \"../format.js\";\nimport type { OpeningSummary } from \"../api/types.js\";\n\nexport const searchOpeningsInputShape = {\n bidKind: z.array(z.enum([\"cnstwk\", \"servc\", \"thng\", \"frgcpt\"])).optional().describe(\"업무구분 배열(cnstwk=공사·servc=용역·thng=물품·frgcpt=외자). 미지정 시 전 구분 병렬\"),\n keyword: z.string().optional().describe(\"공고명(bidNtceNm)\"),\n institution: z.string().optional().describe(\"공고기관명\"),\n demandInstitution: z.string().optional().describe(\"수요기관명(dminsttNm)\"),\n region: z.string().optional().describe(\"참가제한지역명(prtcptLmtRgnNm, 예: 인천광역시)\"),\n industry: z.string().optional().describe(\"업종명(indstrytyNm)\"),\n status: z.enum([\"개찰완료\", \"유찰\", \"재입찰\"]).optional().describe(\"진행상태 필터(응답 progrsDivCdNm 기준 클라이언트 필터)\"),\n startDate: z.string().optional().describe(\"조회 시작일 YYYYMMDD (endDate와 함께 지정)\"),\n endDate: z.string().optional().describe(\"조회 종료일 YYYYMMDD (startDate와 함께 지정)\"),\n dateType: z.enum([\"posted\", \"opened\"]).optional().describe(\"날짜 기준: posted=공고게시(기본), opened=개찰\"),\n pageSize: z.number().int().min(1).max(100).optional().describe(\"창당 페이지 크기(기본 20, 개찰결과는 느려 작게 권장)\"),\n maxPages: z.number().int().min(1).max(50).optional().describe(\"창당 최대 페이지(기본 5)\"),\n};\n\nexport type SearchOpeningsArgs = {\n bidKind?: BidKind[]; keyword?: string; institution?: string; demandInstitution?: string;\n region?: string; industry?: string; status?: \"개찰완료\" | \"유찰\" | \"재입찰\";\n startDate?: string; endDate?: string; dateType?: \"posted\" | \"opened\"; pageSize?: number; maxPages?: number;\n};\n\ntype KindResult = { totalCountBeforeFilter: number; filteredCount: number; items: OpeningSummary[]; truncated: boolean } | { error: string };\nexport interface SearchOpeningsResult { query: SearchOpeningsArgs; results: Partial<Record<BidKind, KindResult>>; notes: string[]; }\n\nexport async function runSearchOpenings(client: DataGoKrClient, args: SearchOpeningsArgs): Promise<SearchOpeningsResult> {\n if ((args.startDate && !args.endDate) || (!args.startDate && args.endDate)) {\n throw new Error(\"startDate와 endDate는 함께 지정해야 합니다.\");\n }\n if (args.startDate && args.endDate && args.startDate > args.endDate) {\n throw new Error(\"startDate가 endDate보다 늦습니다.\");\n }\n\n const kinds = args.bidKind ?? [...ALL_BID_KINDS];\n const dateType: DateType = args.dateType ?? \"posted\";\n const inqryDiv = openingInqryDiv(dateType, true);\n const base: Record<string, string | number | undefined> = {\n inqryDiv, bidNtceNm: args.keyword, ntceInsttNm: args.institution, dminsttNm: args.demandInstitution,\n prtcptLmtRgnNm: args.region, indstrytyNm: args.industry,\n };\n const windows = args.startDate && args.endDate\n ? splitDateWindows(args.startDate, args.endDate, MAX_WINDOW_DAYS)\n : [{ bgn: undefined as string | undefined, end: undefined as string | undefined }];\n // 개찰결과(계열 B)는 응답이 무겁고 느려 큰 페이지는 타임아웃한다(라이브: 20행 0.6초, 50행 9초, 100행 타임아웃).\n // 기본 페이지를 작게 둔다.\n const pageSize = args.pageSize ?? 20, maxPages = args.maxPages ?? 5;\n\n const settled = await Promise.allSettled(kinds.map(async (kind) => {\n const all: OpeningSummary[] = [];\n let before = 0, truncated = false;\n for (const w of windows) {\n const r = await fetchAllPages((op, p) => client.call(op, p), openingSearchOp(kind), { ...base, inqryBgnDt: w.bgn, inqryEndDt: w.end }, { pageSize, maxPages });\n before += r.totalCount; truncated = truncated || r.truncated;\n for (const raw of r.items) {\n const o = formatOpening(raw);\n if (o.progress === \"유찰\") o.failReasonHint = failReasonHint(o.participants);\n all.push(o);\n }\n }\n const items = args.status ? all.filter((o) => o.progress === args.status) : all;\n return { totalCountBeforeFilter: before, filteredCount: items.length, items, truncated };\n }));\n\n const results: Partial<Record<BidKind, KindResult>> = {};\n kinds.forEach((kind, i) => {\n const s = settled[i]!;\n results[kind] = s.status === \"fulfilled\" ? s.value : { error: s.reason instanceof Error ? s.reason.message : String(s.reason) };\n });\n return {\n query: args, results,\n notes: [\n \"status는 응답 progrsDivCdNm 기준 클라이언트 필터다(API 요청 파라미터 아님). totalCountBeforeFilter는 필터 전 값.\",\n \"재입찰은 동일 공고 내 재입찰이며 재공고가 아니다(재공고는 입찰공고 서비스 소관).\",\n \"개찰결과 조회는 응답이 느리다. 페이지 크기를 작게(기본 20) 유지하고 검색조건(기관·업종·기간)을 좁혀 쓴다.\",\n ],\n };\n}\n","import { z } from \"zod\";\nimport type { DataGoKrClient, RawItem } from \"@opendata-kr/core\";\nimport {\n ALL_BID_KINDS, ALL_OPENING_STATUS, awardListOp, openingListOp, preparPriceOp,\n D_OPERATION, awardInqryDiv, openingInqryDiv, type BidKind, type OpeningStatus,\n} from \"../api/endpoints.js\";\nimport {\n formatAward, formatOpening, formatBidder, aggregatePreparPrice, estimateAwardMethod, compositeKeyOf,\n} from \"../format.js\";\nimport type { AwardResult, OpeningSummary, PreparPriceDetail, BidderDetail } from \"../api/types.js\";\n\nexport const getBidResultInputShape = {\n bidNtceNo: z.string().describe(\"입찰공고번호\"),\n bidKind: z.enum([\"cnstwk\", \"servc\", \"thng\", \"frgcpt\"]).optional().describe(\"업무구분. 미지정 시 A/B/C를 전 구분에서 조회\"),\n status: z.enum([\"completed\", \"failing\", \"rebid\", \"all\"]).optional().describe(\"D 상태(기본 all: 완료·유찰·재입찰 병렬)\"),\n bidNtceOrd: z.string().optional().describe(\"입찰공고차수. 특정 집행으로 좁힘\"),\n bidClsfcNo: z.string().optional().describe(\"입찰분류번호. 특정 집행으로 좁힘\"),\n rbidNo: z.string().optional().describe(\"재입찰번호. 특정 집행으로 좁힘\"),\n myBizno: z.string().optional().describe(\"자사 사업자번호. 일치하는 투찰행에 isOurs 플래그\"),\n};\nexport type GetBidResultArgs = {\n bidNtceNo: string; bidKind?: BidKind; status?: \"completed\" | \"failing\" | \"rebid\" | \"all\";\n bidNtceOrd?: string; bidClsfcNo?: string; rbidNo?: string; myBizno?: string;\n};\n\nexport interface Execution {\n bidNtceOrd: string; bidClsfcNo: string; rbidNo: string;\n awardMethod: { method: \"negotiated\" | \"qualification_or_other\"; uncertain: true };\n award: AwardResult | null; opening: OpeningSummary | null;\n preparPrice: PreparPriceDetail | null; bidders: BidderDetail[];\n}\nexport interface GetBidResultResult { bidNtceNo: string; executions: Execution[]; errors: string[]; notes: string[]; }\n\nasync function safeItems(client: DataGoKrClient, op: string, params: Record<string, string | number | undefined>, errors: string[]): Promise<RawItem[]> {\n try { return (await client.call(op, { ...params, pageNo: 1, numOfRows: 100 })).items; }\n catch (e) { errors.push(`${op}: ${e instanceof Error ? e.message : String(e)}`); return []; }\n}\n\nexport async function runGetBidResult(client: DataGoKrClient, args: GetBidResultArgs): Promise<GetBidResultResult> {\n const errors: string[] = [];\n const kinds: BidKind[] = args.bidKind ? [args.bidKind] : [...ALL_BID_KINDS];\n const statuses: OpeningStatus[] = !args.status || args.status === \"all\" ? [...ALL_OPENING_STATUS] : [args.status];\n const no = args.bidNtceNo;\n\n // A/B/C: 업무구분 병렬 시도(inqryDiv=공고번호). D: 상태 오퍼레이션 병렬.\n const aRaw: RawItem[] = [], bRaw: RawItem[] = [], cRaw: RawItem[] = [], dRaw: RawItem[] = [];\n await Promise.all([\n ...kinds.map(async (k) => { aRaw.push(...await safeItems(client, awardListOp(k), { inqryDiv: awardInqryDiv(\"notice\", false), bidNtceNo: no }, errors)); }),\n ...kinds.map(async (k) => { bRaw.push(...await safeItems(client, openingListOp(k), { inqryDiv: openingInqryDiv(\"notice\", false), bidNtceNo: no }, errors)); }),\n ...kinds.map(async (k) => { cRaw.push(...await safeItems(client, preparPriceOp(k), { inqryDiv: \"2\", bidNtceNo: no }, errors)); }),\n ...statuses.map(async (s) => { dRaw.push(...await safeItems(client, D_OPERATION[s], { bidNtceNo: no }, errors)); }),\n ]);\n\n // 복합키로 집행 그룹핑\n const keys = new Set<string>();\n for (const r of [...aRaw, ...bRaw, ...cRaw, ...dRaw]) keys.add(compositeKeyOf(r));\n\n const executions: Execution[] = [...keys].map((key) => {\n const match = (r: RawItem) => compositeKeyOf(r) === key;\n const [, ord = \"\", clsfc = \"\", rbid = \"\"] = key.split(\"|\");\n const a = aRaw.find(match), b = bRaw.find(match);\n const cItems = cRaw.filter(match), dItems = dRaw.filter(match);\n const bidders = dItems.map(formatBidder).map((b) =>\n args.myBizno && b.bizno === args.myBizno ? { ...b, isOurs: true } : b);\n return {\n bidNtceOrd: ord, bidClsfcNo: clsfc, rbidNo: rbid,\n awardMethod: estimateAwardMethod(bidders),\n award: a ? formatAward(a) : null,\n opening: b ? formatOpening(b) : null,\n preparPrice: cItems.length ? aggregatePreparPrice(cItems) : null,\n bidders,\n };\n });\n\n let filtered = executions;\n if (args.bidNtceOrd !== undefined || args.bidClsfcNo !== undefined || args.rbidNo !== undefined) {\n filtered = executions.filter((e) =>\n (args.bidNtceOrd === undefined || e.bidNtceOrd === args.bidNtceOrd) &&\n (args.bidClsfcNo === undefined || e.bidClsfcNo === args.bidClsfcNo) &&\n (args.rbidNo === undefined || e.rbidNo === args.rbidNo));\n }\n\n return {\n bidNtceNo: no, executions: filtered, errors,\n notes: [\n \"A/B/C/D를 복합키(공고번호+차수+분류+재입찰번호)로 조인한다. 다분류·다차수는 집행 단위로 분리된다.\",\n \"낙찰방식 구분 필드가 API에 없어 점수 채움으로 추정한다(uncertain). 협상계약이 아니면 세부심사점수는 제공되지 않는다.\",\n ],\n };\n}\n"],"mappings":"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","names":["z","z","z","z","b"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/api/gateway.ts","../src/server.ts","../src/version.ts","../src/tools/searchAwards.ts","../src/api/endpoints.ts","../src/api/dateWindow.ts","../src/format.ts","../src/tools/searchOpenings.ts","../src/tools/getBidResult.ts"],"sourcesContent":["import { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { createGateway } from \"./api/gateway.js\";\nimport { createServer } from \"./server.js\";\n\nasync function main(): Promise<void> {\n const client = createGateway();\n if (client.serviceKeyLooksPreEncoded) {\n console.error(\n \"[narajangteo-opening-mcp] 경고: DATA_GO_KR_SERVICE_KEY가 이미 URL 인코딩된 키로 보입니다. Decoding(원본) 키를 사용하세요.\",\n );\n }\n const server = createServer(client);\n await server.connect(new StdioServerTransport());\n}\n\nmain().catch((err: unknown) => {\n console.error(\"[narajangteo-opening-mcp] fatal:\", err);\n process.exit(1);\n});\n","import { createClient, type DataGoKrClient } from \"@opendata-kr/core\";\n\n// 나라장터 낙찰정보서비스(ScsbidInfoService). 입찰공고(/ad/)와 달리 /as/ 경로다.\nconst SERVICE_PATH = \"/1230000/as/ScsbidInfoService\";\n\nexport function createGateway(): DataGoKrClient {\n // 개찰결과(계열 B)는 응답이 무겁고 느려 기본 타임아웃(~10초)을 넘는 페이지가 있다\n // (라이브: 30~50행에서 8~9초, 100행 타임아웃). 낙찰(계열 A)은 빨라 영향 없다.\n return createClient({ path: SERVICE_PATH, params: { type: \"json\" }, timeout: 30000 });\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { DataGoKrClient } from \"@opendata-kr/core\";\nimport { VERSION } from \"./version.js\";\nimport { searchAwardsInputShape, runSearchAwards, type SearchAwardsArgs } from \"./tools/searchAwards.js\";\nimport { searchOpeningsInputShape, runSearchOpenings, type SearchOpeningsArgs } from \"./tools/searchOpenings.js\";\nimport { getBidResultInputShape, runGetBidResult, type GetBidResultArgs } from \"./tools/getBidResult.js\";\n\nfunction textResult(payload: unknown, isError = false) {\n return { content: [{ type: \"text\" as const, text: JSON.stringify(payload, null, 2) }], ...(isError ? { isError: true } : {}) };\n}\n\nexport function createServer(client: DataGoKrClient): McpServer {\n const server = new McpServer({ name: \"narajangteo-opening-mcp\", version: VERSION });\n\n server.registerTool(\"search_awards\", {\n title: \"낙찰 결과 검색\",\n description:\n \"나라장터 낙찰 결과(최종낙찰자)를 공고명·기관·수요기관(코드)·지역·업종·추정가·사업자번호·기간으로 검색한다. '누가 얼마에 낙찰받았나', 경쟁사(bizno) 낙찰 이력, 되풀이 사업의 종단 조회에 쓴다. 특정 공고의 개찰·투찰업체·예비가 상세는 get_bid_result, 개찰 진행·유찰 발굴은 search_openings를 쓴다. 업무구분 미지정 시 물품/공사/용역/외자를 병렬 조회한다. 낙찰자만 반환하며 그 업체가 참여했으나 진 입찰은 미포함.\",\n inputSchema: searchAwardsInputShape,\n annotations: { readOnlyHint: true, openWorldHint: true },\n }, async (args) => {\n try { return textResult(await runSearchAwards(client, args as SearchAwardsArgs)); }\n catch (e) { return textResult({ error: e instanceof Error ? e.message : String(e) }, true); }\n });\n\n server.registerTool(\"search_openings\", {\n title: \"개찰결과 검색\",\n description:\n \"나라장터 개찰결과 목록을 검색하고 진행상태(개찰완료/유찰/재입찰)로 필터한다. 유찰·재입찰 공고 발굴에 쓴다. 최종낙찰자 검색은 search_awards, 단일 공고 상세는 get_bid_result를 쓴다. status는 API가 아니라 응답 기준 클라이언트 필터라 응답이 느리니 기관·업종·기간으로 좁혀 쓴다(truncated=true면 미완 스캔). 재입찰은 동일 공고 내 재입찰이며 재공고가 아니다(재공고는 입찰공고 서비스 소관).\",\n inputSchema: searchOpeningsInputShape,\n annotations: { readOnlyHint: true, openWorldHint: true },\n }, async (args) => {\n try { return textResult(await runSearchOpenings(client, args as SearchOpeningsArgs)); }\n catch (e) { return textResult({ error: e instanceof Error ? e.message : String(e) }, true); }\n });\n\n server.registerTool(\"get_bid_result\", {\n title: \"공고 개찰 상세\",\n description:\n \"입찰공고번호로 그 공고의 낙찰자·개찰진행·예비가격상세(사정률)·투찰업체별 순위/금액/점수를 복합키 정합으로 단건 조회한다. 딜 사후분석·투찰가 참고에 쓴다. 여러 공고를 조건으로 찾으려면 search_awards 또는 search_openings를 쓴다. 다분류·다차수 공고는 집행 단위 배열로 분리한다. 낙찰방식은 추정이며(협상계약만 기술·가격 점수 제공, 적격심사는 금액·순위만), myBizno를 주면 자사 투찰행에 isOurs를 표시한다.\",\n inputSchema: getBidResultInputShape,\n annotations: { readOnlyHint: true, openWorldHint: true },\n }, async (args) => {\n try { return textResult(await runGetBidResult(client, args as GetBidResultArgs)); }\n catch (e) { return textResult({ error: e instanceof Error ? e.message : String(e) }, true); }\n });\n\n return server;\n}\n","// 버전은 release-please가 릴리스마다 이 마커 사이 값을 교체한다.\n// release-please-config.json의 extra-files에 { type: \"generic\", path: \"src/version.ts\" }로 등록돼 있다.\n// 초기값 0.0.0은 첫 릴리스에서 실제 버전으로 대체된다.\n// x-release-please-start-version\nexport const VERSION = \"0.2.0\";\n// x-release-please-end\n","import { z } from \"zod\";\nimport type { DataGoKrClient } from \"@opendata-kr/core\";\nimport { ALL_BID_KINDS, awardSearchOp, awardInqryDiv, type BidKind, type DateType } from \"../api/endpoints.js\";\nimport { splitDateWindows, fetchAllPages, MAX_WINDOW_DAYS } from \"../api/dateWindow.js\";\nimport { formatAward } from \"../format.js\";\nimport type { AwardResult } from \"../api/types.js\";\n\nexport const searchAwardsInputShape = {\n bidKind: z.array(z.enum([\"cnstwk\", \"servc\", \"thng\", \"frgcpt\"])).optional().describe(\"업무구분 배열. 미지정 시 전 구분 병렬\"),\n keyword: z.string().optional().describe(\"공고명 부분검색(bidNtceNm)\"),\n institution: z.string().optional().describe(\"공고기관명(ntceInsttNm)\"),\n demandInstitution: z.string().optional().describe(\"수요기관명(dminsttNm)\"),\n demandInstitutionCode: z.string().optional().describe(\"수요기관코드(dminsttCd). 종단 식별에 안정적\"),\n detailProductCode: z.string().optional().describe(\"세부품명번호(dtilPrdctClsfcNo)\"),\n region: z.string().optional().describe(\"참가제한지역명(prtcptLmtRgnNm)\"),\n industry: z.string().optional().describe(\"업종명(indstrytyNm)\"),\n minPrice: z.number().optional().describe(\"추정가격 하한(presmptPrceBgn)\"),\n maxPrice: z.number().optional().describe(\"추정가격 상한(presmptPrceEnd)\"),\n bizno: z.string().optional().describe(\"업체 사업자번호. 그 업체의 낙찰건만 조회(진 입찰은 미포함)\"),\n startDate: z.string().optional().describe(\"조회 시작일 YYYYMMDD\"),\n endDate: z.string().optional().describe(\"조회 종료일 YYYYMMDD\"),\n dateType: z.enum([\"posted\", \"opened\"]).optional().describe(\"날짜 기준. posted=공고게시(기본), opened=개찰\"),\n pageSize: z.number().int().min(1).max(100).optional().describe(\"창당 페이지 크기(기본 100)\"),\n maxPages: z.number().int().min(1).max(50).optional().describe(\"창당 최대 페이지(기본 10)\"),\n};\n\nexport type SearchAwardsArgs = {\n bidKind?: BidKind[]; keyword?: string; institution?: string; demandInstitution?: string;\n demandInstitutionCode?: string; detailProductCode?: string; region?: string; industry?: string;\n minPrice?: number; maxPrice?: number; bizno?: string; startDate?: string; endDate?: string;\n dateType?: \"posted\" | \"opened\"; pageSize?: number; maxPages?: number;\n};\n\ntype KindResult = { totalCount: number; items: AwardResult[]; truncated: boolean } | { error: string };\nexport interface SearchAwardsResult { query: SearchAwardsArgs; results: Partial<Record<BidKind, KindResult>>; notes: string[]; }\n\nexport async function runSearchAwards(client: DataGoKrClient, args: SearchAwardsArgs): Promise<SearchAwardsResult> {\n const kinds = args.bidKind ?? [...ALL_BID_KINDS];\n const dateType: DateType = args.dateType ?? \"posted\";\n const inqryDiv = awardInqryDiv(dateType, true);\n const base: Record<string, string | number | undefined> = {\n inqryDiv,\n bidNtceNm: args.keyword, ntceInsttNm: args.institution, dminsttNm: args.demandInstitution,\n dminsttCd: args.demandInstitutionCode, dtilPrdctClsfcNo: args.detailProductCode,\n prtcptLmtRgnNm: args.region, indstrytyNm: args.industry,\n presmptPrceBgn: args.minPrice, presmptPrceEnd: args.maxPrice, bizno: args.bizno,\n };\n\n if ((args.startDate && !args.endDate) || (!args.startDate && args.endDate)) {\n throw new Error(\"startDate와 endDate는 함께 지정해야 합니다.\");\n }\n if (args.startDate && args.endDate && args.startDate > args.endDate) {\n throw new Error(\"startDate가 endDate보다 늦습니다.\");\n }\n\n const windows = args.startDate && args.endDate\n ? splitDateWindows(args.startDate, args.endDate, MAX_WINDOW_DAYS)\n : [{ bgn: undefined as string | undefined, end: undefined as string | undefined }];\n const pageSize = args.pageSize ?? 100;\n const maxPages = args.maxPages ?? 10;\n\n const settled = await Promise.allSettled(kinds.map(async (kind) => {\n const items: AwardResult[] = [];\n let totalCount = 0, truncated = false;\n for (const w of windows) {\n const params = { ...base, inqryBgnDt: w.bgn, inqryEndDt: w.end };\n const r = await fetchAllPages((op, p) => client.call(op, p), awardSearchOp(kind), params, { pageSize, maxPages });\n items.push(...r.items.map(formatAward));\n totalCount += r.totalCount;\n truncated = truncated || r.truncated;\n }\n return { totalCount, items, truncated };\n }));\n\n const results: Partial<Record<BidKind, KindResult>> = {};\n kinds.forEach((kind, i) => {\n const s = settled[i]!;\n results[kind] = s.status === \"fulfilled\" ? s.value : { error: s.reason instanceof Error ? s.reason.message : String(s.reason) };\n });\n return {\n query: args, results,\n notes: [\n \"낙찰자만 조회한다(그 업체가 참여했으나 진 입찰은 이 API로 도달 불가).\",\n \"여러 창(주 단위 분할)의 totalCount 합은 창별 합계다.\",\n ],\n };\n}\n","export type BidKind = \"cnstwk\" | \"servc\" | \"thng\" | \"frgcpt\";\nexport const ALL_BID_KINDS: readonly BidKind[] = [\"cnstwk\", \"servc\", \"thng\", \"frgcpt\"];\nconst SUFFIX: Record<BidKind, string> = {\n cnstwk: \"Cnstwk\", servc: \"Servc\", thng: \"Thng\", frgcpt: \"Frgcpt\",\n};\n\n// 계열 A: 낙찰된 목록 현황\nexport const awardListOp = (k: BidKind): string => `getScsbidListSttus${SUFFIX[k]}`;\nexport const awardSearchOp = (k: BidKind): string => `getScsbidListSttus${SUFFIX[k]}PPSSrch`;\n// 계열 B: 개찰결과 목록\nexport const openingListOp = (k: BidKind): string => `getOpengResultListInfo${SUFFIX[k]}`;\nexport const openingSearchOp = (k: BidKind): string => `getOpengResultListInfo${SUFFIX[k]}PPSSrch`;\n// 계열 C: 예비가격상세\nexport const preparPriceOp = (k: BidKind): string => `getOpengResultListInfo${SUFFIX[k]}PreparPcDetail`;\n\n// 계열 D: 상태별 (업무구분 무관 단일 오퍼레이션)\nexport type OpeningStatus = \"completed\" | \"failing\" | \"rebid\";\nexport const ALL_OPENING_STATUS: readonly OpeningStatus[] = [\"completed\", \"failing\", \"rebid\"];\nexport const D_OPERATION: Record<OpeningStatus, string> = {\n completed: \"getOpengResultListInfoOpengCompt\",\n failing: \"getOpengResultListInfoFailing\",\n rebid: \"getOpengResultListInfoRebid\",\n};\n\n// 날짜 기준. posted=공고(게시), opened=개찰, notice=공고번호 단건.\nexport type DateType = \"posted\" | \"opened\" | \"notice\";\n\n// A 기본판: 1등록 2공고 3개찰 4공고번호 / A PPSSrch: 1공고게시 2개찰 3공고번호\nexport function awardInqryDiv(dateType: DateType, ppsSrch: boolean): string {\n if (ppsSrch) return dateType === \"notice\" ? \"3\" : dateType === \"opened\" ? \"2\" : \"1\";\n return dateType === \"notice\" ? \"4\" : dateType === \"opened\" ? \"3\" : \"2\";\n}\n// B 기본판: 1입력 2공고 3개찰 4공고번호 / B PPSSrch: A PPSSrch와 동일\nexport function openingInqryDiv(dateType: DateType, ppsSrch: boolean): string {\n if (ppsSrch) return dateType === \"notice\" ? \"3\" : dateType === \"opened\" ? \"2\" : \"1\";\n return dateType === \"notice\" ? \"4\" : dateType === \"opened\" ? \"3\" : \"2\";\n}\n// 계열 C 예비가격상세: 1입력일시 2입찰공고번호 (PPSSrch 없음)\nexport function preparInqryDiv(byNotice: boolean): string {\n return byNotice ? \"2\" : \"1\";\n}\n","import type { OperationResult, RawItem } from \"@opendata-kr/core\";\n\n// 라이브 검증(2026-07-07): 낙찰 서비스는 1개월 창도 통과(1주 1189·1개월 6096건 정상).\n// 형제 bid 서비스(1주 축소)와 달라 31일로 둔다.\nexport const MAX_WINDOW_DAYS = 31;\n\nfunction toDate(yyyymmdd: string): Date {\n const y = Number(yyyymmdd.slice(0, 4)), m = Number(yyyymmdd.slice(4, 6)), d = Number(yyyymmdd.slice(6, 8));\n return new Date(Date.UTC(y, m - 1, d));\n}\nfunction fmt(dt: Date): string {\n const y = dt.getUTCFullYear(), m = String(dt.getUTCMonth() + 1).padStart(2, \"0\"), d = String(dt.getUTCDate()).padStart(2, \"0\");\n return `${y}${m}${d}`;\n}\n\nexport function splitDateWindows(start: string, end: string, maxDays: number): Array<{ bgn: string; end: string }> {\n const windows: Array<{ bgn: string; end: string }> = [];\n let cur = toDate(start);\n const last = toDate(end);\n while (cur <= last) {\n const winEnd = new Date(cur);\n winEnd.setUTCDate(winEnd.getUTCDate() + maxDays - 1);\n const eff = winEnd > last ? last : winEnd;\n windows.push({ bgn: `${fmt(cur)}0000`, end: `${fmt(eff)}2359` });\n cur = new Date(eff);\n cur.setUTCDate(cur.getUTCDate() + 1);\n }\n return windows;\n}\n\ntype CallFn = (op: string, params: Record<string, string | number | undefined>) => Promise<OperationResult>;\n\nexport async function fetchAllPages(\n call: CallFn, op: string, params: Record<string, string | number | undefined>,\n opts: { pageSize: number; maxPages: number },\n): Promise<{ totalCount: number; items: RawItem[]; truncated: boolean }> {\n const items: RawItem[] = [];\n let totalCount = 0;\n let page = 1;\n for (; page <= opts.maxPages; page++) {\n const r = await call(op, { ...params, pageNo: page, numOfRows: opts.pageSize });\n totalCount = r.totalCount;\n items.push(...r.items);\n if (items.length >= totalCount || r.items.length === 0) {\n return { totalCount, items, truncated: false };\n }\n }\n return { totalCount, items, truncated: true };\n}\n","import type { RawItem } from \"@opendata-kr/core\";\nimport type { AwardResult, OpeningSummary, BidderDetail, TopBidder, PreparPriceDetail } from \"./api/types.js\";\n\nconst pick = (raw: RawItem, k: string): string => raw[k] ?? \"\";\n\nexport function compositeKeyOf(raw: RawItem): string {\n return `${pick(raw, \"bidNtceNo\")}|${pick(raw, \"bidNtceOrd\")}|${pick(raw, \"bidClsfcNo\")}|${pick(raw, \"rbidNo\")}`;\n}\n\nexport function parseOpengCorpInfo(s: string): TopBidder | null {\n if (!s) return null;\n const [name = \"\", bizno = \"\", ceo = \"\", amount = \"\", rate = \"\"] = s.split(\"^\");\n return { name, bizno, ceo, amount, rate };\n}\n\nexport function formatAward(raw: RawItem): AwardResult {\n return {\n bidNtceNo: pick(raw, \"bidNtceNo\"), bidNtceNm: pick(raw, \"bidNtceNm\"), participants: pick(raw, \"prtcptCnum\"),\n winner: pick(raw, \"bidwinnrNm\"), winnerBizno: pick(raw, \"bidwinnrBizno\"), winnerCeo: pick(raw, \"bidwinnrCeoNm\"),\n awardAmount: pick(raw, \"sucsfbidAmt\"), awardRate: pick(raw, \"sucsfbidRate\"), realOpeningDt: pick(raw, \"rlOpengDt\"),\n demandInstitution: pick(raw, \"dminsttNm\"), finalAwardDate: pick(raw, \"fnlSucsfDate\"),\n };\n}\n\nexport function formatOpening(raw: RawItem): OpeningSummary {\n return {\n bidNtceNo: pick(raw, \"bidNtceNo\"), bidNtceNm: pick(raw, \"bidNtceNm\"), openingDt: pick(raw, \"opengDt\"),\n participants: pick(raw, \"prtcptCnum\"), progress: pick(raw, \"progrsDivCdNm\"),\n topBidder: parseOpengCorpInfo(pick(raw, \"opengCorpInfo\")),\n reservePriceFileExists: pick(raw, \"rsrvtnPrceFileExistnceYn\"),\n noticeInstitution: pick(raw, \"ntceInsttNm\"), demandInstitution: pick(raw, \"dminsttNm\"),\n };\n}\n\nexport function formatBidder(raw: RawItem): BidderDetail {\n return {\n rank: pick(raw, \"opengRank\"), name: pick(raw, \"prcbdrNm\"), bizno: pick(raw, \"prcbdrBizno\"), ceo: pick(raw, \"prcbdrCeoNm\"),\n amount: pick(raw, \"bidprcAmt\"), rate: pick(raw, \"bidprcrt\"), remark: pick(raw, \"rmrk\"),\n priceScore: pick(raw, \"bidPrceEvlVal\"), techScore: pick(raw, \"techEvlVal\"), techRawScore: pick(raw, \"techEvlNaturVal\"),\n totalScore: pick(raw, \"totalEvlAmtVal\"), bidDt: pick(raw, \"bidprcDt\"),\n };\n}\n\nexport function aggregatePreparPrice(items: RawItem[]): PreparPriceDetail {\n const first = items[0];\n const planPrice = first ? pick(first, \"plnprc\") : \"\";\n const baseAmount = first ? pick(first, \"bssamt\") : \"\";\n const p = Number(planPrice), b = Number(baseAmount);\n const saJeongRate = first && b > 0 && Number.isFinite(p) && Number.isFinite(b) ? p / b : null;\n return {\n planPrice, baseAmount, saJeongRate,\n totalReserveCount: first ? pick(first, \"totRsrvtnPrceNum\") : \"\",\n drawn: first ? pick(first, \"drwtYn\") : \"\",\n reserves: items.map((r) => ({ seq: pick(r, \"compnoRsrvtnPrceSno\"), basePlanPrice: pick(r, \"bsisPlnprc\") })),\n };\n}\n\n// 유찰 사유는 API에 없다. 참가업체수(prtcptCnum)로 추론 힌트만 제공(spec §6, S4).\nexport function failReasonHint(participants: string): string {\n const n = Number(participants);\n if (!Number.isFinite(n)) return \"참가업체수 미상. 유찰 사유 추정 불가\";\n if (n === 0) return \"무응찰 추정(참가 0). 재도전 기회일 수 있음\";\n if (n === 1) return \"단독응찰 추정(참가 1). 수의계약 직행 가능, 기회 낮음\";\n return \"적격자 없음 등 추정(참가 2+). 재도전 기회일 수 있음\";\n}\n\n// 낙찰방식 구분 필드가 API에 없다. D 점수 채움 패턴으로 추정(spec §6, S5).\nexport function estimateAwardMethod(bidders: BidderDetail[]): { method: \"negotiated\" | \"qualification_or_other\"; uncertain: true } {\n const scored = bidders.some((b) => b.totalScore !== \"\" || b.techScore !== \"\");\n return { method: scored ? \"negotiated\" : \"qualification_or_other\", uncertain: true };\n}\n","import { z } from \"zod\";\nimport type { DataGoKrClient } from \"@opendata-kr/core\";\nimport { ALL_BID_KINDS, openingSearchOp, openingInqryDiv, type BidKind, type DateType } from \"../api/endpoints.js\";\nimport { splitDateWindows, fetchAllPages, MAX_WINDOW_DAYS } from \"../api/dateWindow.js\";\nimport { formatOpening, failReasonHint } from \"../format.js\";\nimport type { OpeningSummary } from \"../api/types.js\";\n\nexport const searchOpeningsInputShape = {\n bidKind: z.array(z.enum([\"cnstwk\", \"servc\", \"thng\", \"frgcpt\"])).optional().describe(\"업무구분 배열(cnstwk=공사·servc=용역·thng=물품·frgcpt=외자). 미지정 시 전 구분 병렬\"),\n keyword: z.string().optional().describe(\"공고명(bidNtceNm)\"),\n institution: z.string().optional().describe(\"공고기관명\"),\n demandInstitution: z.string().optional().describe(\"수요기관명(dminsttNm)\"),\n region: z.string().optional().describe(\"참가제한지역명(prtcptLmtRgnNm, 예: 인천광역시)\"),\n industry: z.string().optional().describe(\"업종명(indstrytyNm)\"),\n status: z.enum([\"개찰완료\", \"유찰\", \"재입찰\"]).optional().describe(\"진행상태 필터(응답 progrsDivCdNm 기준 클라이언트 필터)\"),\n startDate: z.string().optional().describe(\"조회 시작일 YYYYMMDD (endDate와 함께 지정)\"),\n endDate: z.string().optional().describe(\"조회 종료일 YYYYMMDD (startDate와 함께 지정)\"),\n dateType: z.enum([\"posted\", \"opened\"]).optional().describe(\"날짜 기준: posted=공고게시(기본), opened=개찰\"),\n pageSize: z.number().int().min(1).max(100).optional().describe(\"창당 페이지 크기(기본 20, 개찰결과는 느려 작게 권장)\"),\n maxPages: z.number().int().min(1).max(50).optional().describe(\"창당 최대 페이지(기본 5)\"),\n};\n\nexport type SearchOpeningsArgs = {\n bidKind?: BidKind[]; keyword?: string; institution?: string; demandInstitution?: string;\n region?: string; industry?: string; status?: \"개찰완료\" | \"유찰\" | \"재입찰\";\n startDate?: string; endDate?: string; dateType?: \"posted\" | \"opened\"; pageSize?: number; maxPages?: number;\n};\n\ntype KindResult = { totalCountBeforeFilter: number; filteredCount: number; items: OpeningSummary[]; truncated: boolean } | { error: string };\nexport interface SearchOpeningsResult { query: SearchOpeningsArgs; results: Partial<Record<BidKind, KindResult>>; notes: string[]; }\n\nexport async function runSearchOpenings(client: DataGoKrClient, args: SearchOpeningsArgs): Promise<SearchOpeningsResult> {\n if ((args.startDate && !args.endDate) || (!args.startDate && args.endDate)) {\n throw new Error(\"startDate와 endDate는 함께 지정해야 합니다.\");\n }\n if (args.startDate && args.endDate && args.startDate > args.endDate) {\n throw new Error(\"startDate가 endDate보다 늦습니다.\");\n }\n\n const kinds = args.bidKind ?? [...ALL_BID_KINDS];\n const dateType: DateType = args.dateType ?? \"posted\";\n const inqryDiv = openingInqryDiv(dateType, true);\n const base: Record<string, string | number | undefined> = {\n inqryDiv, bidNtceNm: args.keyword, ntceInsttNm: args.institution, dminsttNm: args.demandInstitution,\n prtcptLmtRgnNm: args.region, indstrytyNm: args.industry,\n };\n const windows = args.startDate && args.endDate\n ? splitDateWindows(args.startDate, args.endDate, MAX_WINDOW_DAYS)\n : [{ bgn: undefined as string | undefined, end: undefined as string | undefined }];\n // 개찰결과(계열 B)는 응답이 무겁고 느려 큰 페이지는 타임아웃한다(라이브: 20행 0.6초, 50행 9초, 100행 타임아웃).\n // 기본 페이지를 작게 둔다.\n const pageSize = args.pageSize ?? 20, maxPages = args.maxPages ?? 5;\n\n const settled = await Promise.allSettled(kinds.map(async (kind) => {\n const all: OpeningSummary[] = [];\n let before = 0, truncated = false;\n for (const w of windows) {\n const r = await fetchAllPages((op, p) => client.call(op, p), openingSearchOp(kind), { ...base, inqryBgnDt: w.bgn, inqryEndDt: w.end }, { pageSize, maxPages });\n before += r.totalCount; truncated = truncated || r.truncated;\n for (const raw of r.items) {\n const o = formatOpening(raw);\n if (o.progress === \"유찰\") o.failReasonHint = failReasonHint(o.participants);\n all.push(o);\n }\n }\n const items = args.status ? all.filter((o) => o.progress === args.status) : all;\n return { totalCountBeforeFilter: before, filteredCount: items.length, items, truncated };\n }));\n\n const results: Partial<Record<BidKind, KindResult>> = {};\n kinds.forEach((kind, i) => {\n const s = settled[i]!;\n results[kind] = s.status === \"fulfilled\" ? s.value : { error: s.reason instanceof Error ? s.reason.message : String(s.reason) };\n });\n return {\n query: args, results,\n notes: [\n \"status는 응답 progrsDivCdNm 기준 클라이언트 필터다(API 요청 파라미터 아님). totalCountBeforeFilter는 필터 전 값.\",\n \"재입찰은 동일 공고 내 재입찰이며 재공고가 아니다(재공고는 입찰공고 서비스 소관).\",\n \"개찰결과 조회는 응답이 느리다. 페이지 크기를 작게(기본 20) 유지하고 검색조건(기관·업종·기간)을 좁혀 쓴다.\",\n ],\n };\n}\n","import { z } from \"zod\";\nimport type { DataGoKrClient, RawItem } from \"@opendata-kr/core\";\nimport {\n ALL_BID_KINDS, ALL_OPENING_STATUS, awardListOp, openingListOp, preparPriceOp,\n D_OPERATION, awardInqryDiv, openingInqryDiv, preparInqryDiv, type BidKind, type OpeningStatus,\n} from \"../api/endpoints.js\";\nimport {\n formatAward, formatOpening, formatBidder, aggregatePreparPrice, estimateAwardMethod, compositeKeyOf,\n} from \"../format.js\";\nimport type { AwardResult, OpeningSummary, PreparPriceDetail, BidderDetail } from \"../api/types.js\";\n\nexport const getBidResultInputShape = {\n bidNtceNo: z.string().describe(\"입찰공고번호\"),\n bidKind: z.enum([\"cnstwk\", \"servc\", \"thng\", \"frgcpt\"]).optional().describe(\"업무구분. 미지정 시 A/B/C를 전 구분에서 조회\"),\n status: z.enum([\"completed\", \"failing\", \"rebid\", \"all\"]).optional().describe(\"D 상태(기본 all: 완료·유찰·재입찰 병렬)\"),\n bidNtceOrd: z.string().optional().describe(\"입찰공고차수. 특정 집행으로 좁힘\"),\n bidClsfcNo: z.string().optional().describe(\"입찰분류번호. 특정 집행으로 좁힘\"),\n rbidNo: z.string().optional().describe(\"재입찰번호. 특정 집행으로 좁힘\"),\n myBizno: z.string().optional().describe(\"자사 사업자번호. 일치하는 투찰행에 isOurs 플래그\"),\n};\nexport type GetBidResultArgs = {\n bidNtceNo: string; bidKind?: BidKind; status?: \"completed\" | \"failing\" | \"rebid\" | \"all\";\n bidNtceOrd?: string; bidClsfcNo?: string; rbidNo?: string; myBizno?: string;\n};\n\nexport interface Execution {\n bidNtceOrd: string; bidClsfcNo: string; rbidNo: string;\n awardMethod: { method: \"negotiated\" | \"qualification_or_other\"; uncertain: true };\n award: AwardResult | null; opening: OpeningSummary | null;\n preparPrice: PreparPriceDetail | null; bidders: BidderDetail[];\n}\nexport interface GetBidResultResult { bidNtceNo: string; executions: Execution[]; errors: string[]; notes: string[]; }\n\nasync function safeItems(client: DataGoKrClient, op: string, params: Record<string, string | number | undefined>, errors: string[]): Promise<RawItem[]> {\n try { return (await client.call(op, { ...params, pageNo: 1, numOfRows: 100 })).items; }\n catch (e) { errors.push(`${op}: ${e instanceof Error ? e.message : String(e)}`); return []; }\n}\n\nexport async function runGetBidResult(client: DataGoKrClient, args: GetBidResultArgs): Promise<GetBidResultResult> {\n const errors: string[] = [];\n const kinds: BidKind[] = args.bidKind ? [args.bidKind] : [...ALL_BID_KINDS];\n const statuses: OpeningStatus[] = !args.status || args.status === \"all\" ? [...ALL_OPENING_STATUS] : [args.status];\n const notice = args.bidNtceNo;\n\n // A/B/C: 업무구분 병렬 시도(inqryDiv=공고번호). D: 상태 오퍼레이션 병렬.\n const aRaw: RawItem[] = [], bRaw: RawItem[] = [], cRaw: RawItem[] = [], dRaw: RawItem[] = [];\n await Promise.all([\n ...kinds.map(async (k) => { aRaw.push(...await safeItems(client, awardListOp(k), { inqryDiv: awardInqryDiv(\"notice\", false), bidNtceNo: notice }, errors)); }),\n ...kinds.map(async (k) => { bRaw.push(...await safeItems(client, openingListOp(k), { inqryDiv: openingInqryDiv(\"notice\", false), bidNtceNo: notice }, errors)); }),\n ...kinds.map(async (k) => { cRaw.push(...await safeItems(client, preparPriceOp(k), { inqryDiv: preparInqryDiv(true), bidNtceNo: notice }, errors)); }),\n ...statuses.map(async (s) => { dRaw.push(...await safeItems(client, D_OPERATION[s], { bidNtceNo: notice }, errors)); }),\n ]);\n\n // 복합키로 집행 그룹핑\n const keys = new Set<string>();\n for (const r of [...aRaw, ...bRaw, ...cRaw, ...dRaw]) keys.add(compositeKeyOf(r));\n\n const executions: Execution[] = [...keys].map((key) => {\n const match = (r: RawItem) => compositeKeyOf(r) === key;\n const [, ord = \"\", clsfc = \"\", rbid = \"\"] = key.split(\"|\");\n const a = aRaw.find(match), b = bRaw.find(match);\n const cItems = cRaw.filter(match), dItems = dRaw.filter(match);\n const bidders = dItems.map(formatBidder).map((b) =>\n args.myBizno && b.bizno === args.myBizno ? { ...b, isOurs: true } : b);\n return {\n bidNtceOrd: ord, bidClsfcNo: clsfc, rbidNo: rbid,\n awardMethod: estimateAwardMethod(bidders),\n award: a ? formatAward(a) : null,\n opening: b ? formatOpening(b) : null,\n preparPrice: cItems.length ? aggregatePreparPrice(cItems) : null,\n bidders,\n };\n });\n\n let filtered = executions;\n if (args.bidNtceOrd !== undefined || args.bidClsfcNo !== undefined || args.rbidNo !== undefined) {\n filtered = executions.filter((e) =>\n (args.bidNtceOrd === undefined || e.bidNtceOrd === args.bidNtceOrd) &&\n (args.bidClsfcNo === undefined || e.bidClsfcNo === args.bidClsfcNo) &&\n (args.rbidNo === undefined || e.rbidNo === args.rbidNo));\n }\n\n return {\n bidNtceNo: notice, executions: filtered, errors,\n notes: [\n \"A/B/C/D를 복합키(공고번호+차수+분류+재입찰번호)로 조인한다. 다분류·다차수는 집행 단위로 분리된다.\",\n \"낙찰방식 구분 필드가 API에 없어 점수 채움으로 추정한다(uncertain). 협상계약이 아니면 세부심사점수는 제공되지 않는다.\",\n ],\n };\n}\n"],"mappings":"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","names":["z","z","z","z","b"]}
|