knowledge(마스터): 만들기 화면이 쓸 새 API 계약 — 절 목록·절 거르기·표 조건 값·소유 거름·자체 로직·끝수

- `GET /sections` · `GET /table/options` · `/tables` 의 `section` · `/logics` 의 `owner`
- 자체 로직 `POST /logic/new|copy|edit|delete`(키 GX 서버 발급 · 파일 로직_자체_NN장_….json · 소유 현장/공용 · 정본은 403)
- 저장 안 한 초안 시험 계산(`key` "" · `file` 없이) · 끝수 묶음 {대상, 자리, 방법}

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JgUhN55Z3BCYhUJTjwTNfj
This commit is contained in:
2026-09-21 09:18:39 +09:00
co-authored by Claude Opus 5
parent 2d24cd358e
commit 964552c2ba
+50 -12
View File
@@ -14,18 +14,20 @@
## 2. 읽기
| 길 | 받음 | 줌 |
| --------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /groups` | | `{groups: [{group, files, rows}]}` — 그룹 차례는 `_틀.md` 2장 |
| `GET /groups/{group}/files` | | `{files: [{file, book, chapter, edition, rows, version, order}]}` — 머리 `차례` 순 |
| `GET /subs` | `file` 또는 `group` | `{file, version, slot, subs: [{name, book, details}]}` — 인력 `구분` · 기계 `세부분류`(머리에 등록된 것) · `group`(소요량 · 계수 · 로직)은 장 파일에서 모음(구분 = 원문 + 부문 · 상세구분 = 장 · 차례대로) |
| `GET /rows` | `file` · `page`(1) · `size`(50) · `q` · `sub` · `detail` | `{file, version, total, page, size, rows: [줄…]}` |
| `GET /tables` | `file` 또는 `group` · `sub` · `detail` · `q` · `page`(1) · `size`(30) | `{file, version, total, page, size, tables: [{file, 키, 원문번호, 구분, 상세구분, 이름, 기준, 출처, 조건, 값칸, count}]}` — 파일을 가로지른 한 목록 |
| `GET /table` | `file` · `key` | `{file, version, table: {표 하나 통째}}` |
| `GET /logics` | `sub` · `detail` · `q` · `blocked`(0/1) | `{logics: [{file, 키, 원문번호, 구분, 상세구분, 이름, 결과단위, 출처, blocked, reasons}]}` — 장 차례대로 |
| `GET /logic` | `key` | `{file, version, logic: {로직 한 줄 통째}, blocked, reasons, prices: {요소: 요약 \| null}}` |
| `GET /elements` | `group` · `q` · `limit`(50 · 200까지) | `{total, items: [{ref, file, 원문번호, 구분, 상세구분, 이름, 규격, 단위, 값, 값칸}]}` |
| `GET /materials` | `sub`(구분) · `detail` · `spec` · `region`(자재지역) · `limit`(50 · 200까지) | `{total, 기본, items: [{ref, 구분, 상세구분, 이름, 규격, 단위, 값, 관급}]}` — 재료 고르기 조건 안 후보 · `기본` = 시험 계산이 쓸 줄 |
| 길 | 받음 | 줌 |
| --------------------------- | --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /groups` | | `{groups: [{group, files, rows}]}` — 그룹 차례는 `_틀.md` 2장 |
| `GET /groups/{group}/files` | | `{files: [{file, book, chapter, edition, rows, version, order}]}` — 머리 `차례` 순 |
| `GET /subs` | `file` 또는 `group` | `{file, version, slot, subs: [{name, book, details}]}` — 인력 `구분` · 기계 `세부분류`(머리에 등록된 것) · `group`(소요량 · 계수 · 로직)은 장 파일에서 모음(구분 = 원문 + 부문 · 상세구분 = 장 · 차례대로) |
| `GET /rows` | `file` · `page`(1) · `size`(50) · `q` · `sub` · `detail` | `{file, version, total, page, size, rows: [줄…]}` |
| `GET /tables` | `file` 또는 `group` · `sub` · `detail` · `section` · `q` · `page`(1) · `size`(30) | `{file, version, total, page, size, tables: [{file, 키, 원문번호, 구분, 상세구분, 이름, 기준, 출처, 조건, 값칸, count}]}` — 파일을 가로지른 한 목록 |
| `GET /table` | `file` · `key` | `{file, version, table: {표 하나 통째}}` |
| `GET /table/options` | `file` · `key` | `{file, key, 이름, 조건, 범위규칙, 값칸, count, 값: {조건 이름: [값…]}}` — 표 줄을 통째로 안 받고 조건 칸의 값만 |
| `GET /sections` | `book`(필수) · `division` · `chapter` · `q` · `limit`(200 · 1000까지) | `{total, sections: [{book, division, chapter, section, title, tables, logics}]}` — 원문 절 목록 |
| `GET /logics` | `sub` · `detail` · `q` · `blocked`(0/1) · `owner` | `{logics: [{file, 키, 원문번호, 구분, 상세구분, 이름, 결과단위, 출처, 소유, blocked, reasons}]}` — 장 차례대로 |
| `GET /logic` | `key` | `{file, version, logic: {로직 한 줄 통째}, blocked, reasons, prices: {요소: 요약 \| null}}` |
| `GET /elements` | `group` · `q` · `limit`(50 · 200까지) | `{total, items: [{ref, file, 원문번호, 구분, 상세구분, 이름, 규격, 단위, 값, 값칸}]}` |
| `GET /materials` | `sub`(구분) · `detail` · `spec` · `region`(자재지역) · `limit`(50 · 200까지) | `{total, 기본, items: [{ref, 구분, 상세구분, 이름, 규격, 단위, 값, 관급}]}` — 재료 고르기 조건 안 후보 · `기본` = 시험 계산이 쓸 줄 |
- `rows` 는 요소·로직 파일은 `줄`, 표형 파일(소요량·계수)은 `표` 를 줄로 봄.
- `q` = 찾기 — `키`·`원문번호`·`이름`·`옛이름` 에 든 글(대소문자 무시).
@@ -36,6 +38,10 @@
- `elements` = 요소 찾기 창 — 그룹 전체에서 `q` 찾기 · `ref` = 식에 넣는 키 · 표형 그룹은 `값칸` 이 옴.
- `materials` = 재료 고르기 단계 — 로직 재료 줄 `요소` 가 조건 `{구분, 상세구분, 규격}` 이면 이 API 로 후보(방식 A·B·C 가 부품 `M01_MasterData_UI_Test_Pick.ts` 하나를 같이 씀 · 구분 → 상세구분 → 후보 순으로 좁힘). `값` 이 비어 있어도 후보로 둠. 옛 재료 줄(품셈재료 키)은 품셈재료 이름(없으면 이름 첫 낱말)으로 `pick?kind=price` 후보. 후보 글 = 이름 규격 · 값 있는 열 전부(물가자료 · 유통물가 …). 멈춤 까닭 `입력 「X」 없음` · `맞는 줄 0개` 는 방식 A·B·C 가 쉬운 말로 바꿔 보임(`plainReason`) · 빈 수 칸은 「값을 넣어 주세요」 안내 글.
- 소요량·계수 표의 `용도`({공종, 대상, 로직키}) = 방식 B 원문 표 미리보기 머리에 안내 · 칸이 없으면 안 보임 · `/tables``usage``용도.대상` 거름(기계 `sub`·`detail` 은 인력과 같이 구분 → 상세구분).
- `section` = 절 번호 거름 — 그 절과 그 아래 절만(`13-4``13-4` · `13-4-1` 만 · `13-40` 은 안 걸림). 「만들기」가 절을 고르면 그 절의 표만 보임.
- `/sections` = 만들기 첫 걸음 — 원문 본문의 절 제목 줄에서 모음(`book` = 산림품셈 · 건설품셈 · `division` = 건설품셈 부문(공통 · 토목 · 건축 · 기계설비 · 유지관리) · `chapter` = 장 번호 두 자리 「13」 · `q` = 절 번호·제목 찾기). `tables` · `logics` = 그 절(아래 절 포함)의 마스터 표·로직 수 — 0 이면 아직 안 올린 절.
- `/table/options` = 조건 값 고르기 — `고르기` 조건은 줄에 나온 값 차례대로(중복 없음) · `범위` 조건은 `[[아래, 위]…]` · `count` = 줄 수. 표 몸을 통째로 받지 않으려는 자리에만 씀(통째는 `/table`).
- `owner` = 로직 `소유` 거름(`공용` 정본 · `현장` 자체) · 빈 글 = 전체.
- `pick` = 고르기 창 — `price` = `재료_자재품목.json`(값 = 값 열 다섯 가운데 낮은 값 · `관급` = 관급 값 있음) ref 키 · `job` = `인력.json` 값 있는 공표 직종(구분 「미확보」 빼고) ref 키.
## 3. 시험 계산
@@ -46,6 +52,8 @@
- 돈 아닌 로직 — `{ok: true, result, middle}`
- 멈춤 — `{ok: false, reason}` (200). 까닭 = 엔진 글 그대로(「입력 「돌」 없음」 · 「값 없음 — 관리자가 채울 값」 …).
- `row` 없음 = 저장된 파일로 계산 · `row` 있음 = 그 로직만 고친 줄로 바꿔(없던 로직이면 `file` 에 더해) 메모리에서 계산 — 파일에 안 씀. 요소 값은 늘 저장된 파일.
- 저장 안 한 새 초안 = `key` "" · `row` 에 로직 한 줄 통째 · `file` 은 안 보내도 됨(서버가 메모리에만 얹음). 「만들기」 모달의 [시험 계산] 이 이 길을 씀 — 키를 미리 받지 않음.
- `끝수` 가 묶음이면 계산 끝에 붙음(6장) · 글자면 설명일 뿐 계산에 안 붙음.
## 4. 저장
@@ -67,3 +75,33 @@
- 검사 = `check_master.py` 의 틀(고친 파일) + 로직 변수(모든 로직 파일, 고친 뒤 마스터 기준). **고친 뒤 새로 생긴 걸림**만 막음 — 원래 있던 걸림은 막지 않음. 인력·재료의 원문번호 겹침도 걸림(표·로직 원문번호는 절 번호라 겹쳐도 됨 · 자재품목은 줄에 원문번호가 없음).
- 요소를 지워 어떤 로직이 가리키던 것이 사라지면 로직 변수 검사에 걸림(422).
- 쓰기는 UTF-8 · LF · 들여쓰기 2칸.
## 5. 자체 로직 (만들기 · 본뜨기 · 고치기 · 지우기)
정본 로직(`소유` 「공용」 · `로직_산림품셈…` · `로직_건설품셈…`)은 이 길로 못 고침 — 403. 고치려면 먼저 복제.
- 자리 = `로직_자체_NN장_<장 제목>.json`(`NN` = 원문 절 번호의 장 · 원문 절이 없으면 `로직_자체_00장_자체.json`) · 없으면 서버가 머리(`{"그룹": "로직", "원문": "자체", "차례": 90, "판": <올해>, "줄": []}`)와 함께 만듦.
- 키 = 서버가 `_키대장.json` 에서 `GX` 다음 번호로 줌 — 화면은 키를 만들지 않음.
- `소유` = `현장`(기본) · `공용`. 줄의 `구분` = 「자체」 · `상세구분` = 「NN장 장 제목」 은 서버가 넣음.
| 길 | 받음 | 줌 |
| -------------------- | ----------------------- | ------------------------------------------------------------ |
| `POST /logic/new` | `{logic, owner?}` | `{file, version, key, logic}` |
| `POST /logic/copy` | `{key, 이름?, owner?}` | `{file, version, key, logic}` — 정본·자체 둘 다 본뜰 수 있음 |
| `POST /logic/edit` | `{key, version, logic}` | `{file, version, logic}` |
| `POST /logic/delete` | `{key, version}` | `{file, version}` |
- `logic` = 로직 한 줄 통째(`_틀.md` 7장) · `키`·`구분`·`상세구분` 은 보내도 서버 것이 이김.
- `version` = `GET /logic` 이 준 그 파일 판본 — 다르면 409 `{detail: {stale: [file]}}`.
- `copy` 는 비고 끝에 「`<본뜬 키>` 를 본뜸」 을 붙이고 `시험입력` 은 그대로 가져옴 · `이름` 을 주면 그 이름으로.
- 답 — 200 · 400(틀린 몸) · 403(정본 로직) · 404(없는 키·파일) · 409(낡은 판본) · 422 `{detail: {errors: […]}}`(검사 걸림 — `/save` 와 같은 검사).
- 지움은 그 로직을 부르는 다른 로직이 있으면 422.
## 6. 끝수
로직 줄의 `끝수` 는 묶음 `{대상, 자리, 방법, 출처?, 비고?}` — 계산 맨 끝에 붙음.
- `대상``계`(돈 로직 · 비목 합 셋을 각각 끊고 계 = 그 셋의 합) · `결과`(돈 아닌 로직의 결과 수).
- `자리` = 소수 자리(0 = 원 미만 · 3 = 소수 넷째 자리에서).
- `방법``버림` · `올림` · `반올림`.
- 옛 줄의 글자 `끝수`(「손료 원 미만 버림(…)」)는 원문 근거를 적어 둔 설명 — 계산에 안 붙음(그 끊기는 이미 식 안에 있음).