---
name: 결산자동화
description: 결산 자동화 스킬을 만들 때 참고하는 예시 스킬. 회사 업무처리에 맞게 고쳐 써야 한다. 한 회계기간의 raw data(기초BS·은행거래내역·카드승인·세금계산서·급여대장·거래처마스터)를 입력하면 월/분기 결산을 자동 처리해 ① 결산확정 워크북(분개장·시산표·재무제표·현금흐름표, 전부 살아있는 수식) ② 더존 일반전표 업로드 ③ 더존 매입매출전표 업로드 ④ 전문가 검토용 확인사항(.docx) 4종을 산출한다. 계산은 결정적 Python 엔진(1원도 안 틀림), 추출은 AI, 판단(공제/불공제·기말재고·계정분류)은 전문가가 확정한다. 부가세 매입세액 불공제 체크리스트를 전수 적용하고, 전기 확정판단을 승계하며, 규칙 밖 거래는 가계정에 두고 미분류 목록으로 내며, 업로드 사전검증과 워크북 검산으로 확인한다. "결산", "월결산/분기결산", "N분기 결산해줘", "전표 처리", "더존 업로드", "재무제표/시산표 만들어줘", "매입세액 공제", "부가세 정리", "결산조정" 등이 언급되면 트리거.
---

> **이 스킬은 결산 스킬을 만들 때 참고하는 예시입니다. 그대로 쓰지 말고 회사 업무처리에 맞게 고쳐 쓰십시오.**
> 계정체계 · 거래처코드 · 전표 기준 · 부가세 판단 · 회계 프로그램 양식(더존 외)은 회사와 사무소마다 다릅니다.
> 프로파일 예시는 `scripts/profile_sample.py`(가상 회사 (주)예시푸드마켓) 입니다.
> 직접 만든 결산 스킬의 결과와 이 스킬의 결과를 같은 자료로 돌려 비교하고, 빠뜨린 처리를 찾는 데 쓰십시오.


# 월/분기 결산 에이전트 — 추출(AI) / 계산(코드) / 판단(전문가)

한 회계기간 raw를 받아 **결정적 엔진 + 살아있는 수식 워크북 + 전문가 확인사항**으로 결산 4종을 자율 산출한다.
분개 한 줄을 고치면 재무제표까지 자동 재계산되고, 두 검증 스크립트가 PASS여야 완성이다.
**규칙에 안 걸린 거래는 분개하지 않는다.** 가계정에 두고 미분류 목록으로 낸다.

설계·지식은 `references/` 3종에 있다:
- [처리기준.md](references/처리기준.md) — 표준 처리 관례 · 매입세액 불공제 체크리스트 · **회사 프로파일(누적 학습)**
- [더존업로드양식.md](references/더존업로드양식.md) — 더존 양식 스펙(컬럼·과세유형·계정코드·숫자형) authoritative
- [산출물양식.md](references/산출물양식.md) — 4종 산출물 규격 + 수식 규칙
- [위하고_계정과목.csv](references/위하고_계정과목.csv) — 위하고(더존 SmartA) 매입매출 업로드 양식의 계정과목 시트 423개. `verify_upload.py` 가 일반전표 계정코드를 이 표와 맞춘다
- [scripts/vat_engine.py](scripts/vat_engine.py) — 부가세 전표 판단 결정론 룰셋(라우팅·과세유형·공제/불공제·금액분해·매출 4분기·업종게이팅). 판단성 항목은 hitl=True로 전문가 확인. 불공제 사유는 DenyReason enum(①~⑧), 더존 코드매핑은 로그인 검증 후. 근거: 부가세법 §39·§10·§26·§29·시행령 §88⑤·§81·§63.
- [scripts/vat_return.py](scripts/vat_return.py) — 부가세 신고서 집계(Judgment 집합 → 일반과세 확정신고 본지 (1)~(30), 현행 별지21호 2025.7.4.). 검증식 assert(㉮㉯㉰, (18)=(16)−(17)) 1원 대사. build_return_xlsx로 신고서 엑셀 산출.
- [scripts/vat_douzone.py](scripts/vat_douzone.py) — 더존 SmartA 업로드 산출(Judgment+전표컨텍스트 → 매입매출전표 18컬럼/일반전표). 불공제 사유코드는 라이브 더존 명세서 순번(접대비만 G3 미결). 계정매핑은 회사 프로파일 제공.
- [scripts/vat_attachments.py](scripts/vat_attachments.py) — 붙임서식(별지) 산출. A상시: 매출/매입처별 세계합계표·카드수령/발행·공제받지못할명세서. B: 영세율첨부·고정자산취득·계산서합계표·대손·의제매입. C: 부동산임대 간주임대료(3.1%)·재활용폐자원. Voucher 그루핑 + 특수계산.
- [scripts/segment_pnl.py](scripts/segment_pnl.py) — (선택 확장) **부문손익·CC 분석**. 은행·카드·세금계산서를 규칙 태깅해 수익부문별 매출 × CC별 비용 월별 표를 산출(현금주의·완전분할 1원 tie-out·SUMIFS 살아있는 수식·미분류는 FLAG 시트로 HITL). 회사별 규칙은 프로파일의 부문손익·CC 매핑(RULES dict)으로 교체. 내장 기본값은 가상 예시회사(GF) 규칙. "부문손익", "부문별 손익", "코스트센터", "CC 분석" 언급 시 사용.
- [scripts/vat_simplified.py](scripts/vat_simplified.py) — 간이과세자 세액계산(공급대가×업종별 부가가치율×10%, 매입 세계 0.5% 수취세액공제, 4,800만 미만 납부면제). vat_return.aggregate는 신고구분='예정'으로 예정신고(전자신고공제·대손·예정고지 제외) 지원. ⚠ 간이 별지44호 란번호 미확정.
- [scripts/verify_upload.py](scripts/verify_upload.py) — **더존 업로드 사전검증(체크 11 집행부).** 시트명·18/10컬럼 완전일치·숫자형·앞자리0 텍스트·유효 코드값·차대 균형, 그리고 **채권채무 거래처코드와 매입매출 11열 사업자번호가 채워졌는지**를 올리기 전에 본다. 거래처코드 빈칸과 미해소 거래처는 확인사항으로 적고 반려하지 않는다(2026-10-16). 한 거래처가 아닌 라벨(임직원·다수(매입처))은 프로파일 `집합거래처` 에 선언하면 「의도한 빈칸」으로 따로 적힌다. FAIL 은 거래처마스터에 없는 거래처코드와, 위하고 마스터에서 다른 계정을 가리키는 일반전표 계정코드(예: 이자비용을 951 로 올림)다(§더존업로드양식 §4).
- [scripts/review_items.py](scripts/review_items.py): **AI 1차 판단 입구.** 엔진과 검증이 사람에게 넘기는 항목(미분류 거래 · 잠정 처리 · 해외카드 · 거래처 미해소 · 검증 확인/FAIL)을 `_확인항목_{기간}.json` 으로 내고, AI 가 쓴 `AI의견_{기간}.json` 의 형식(의견 · 근거 · 확신도 · 판단보류)을 `--check` 로 본다. AI 의견은 숫자를 바꾸지 않는다(§7).
- [scripts/vat_reconcile.py](scripts/vat_reconcile.py) — 신고 완결성 Layer 1 결정론 대사(홈택스매출↔신고·입금↔매출·재고롤포워드·순환거래신호·안분재계산·간주임대료·붙임서식↔본지). FLAG/PASS 리포트 + 판례근거. 비결정론 이상탐지·질문생성은 상위 AI 레이어(제품).

**전제: 계산은 코드, 판단은 전문가. 분개는 1원도 틀리면 안 된다. 비식별·이모지 미사용.**

## 핵심 원리 (이게 품질을 만든다)
- **보통예금 출금은 손익계정과 직접 상대하지 않는다.** 급여·4대보험·경비·카드 모두 미지급금(상품은 외상매입금)으로 먼저 인식하고 지급 때 보통예금과 상계한다. 발생 전표와 지급 전표가 나뉘어야 전표 틀(와꾸)을 검토할 수 있다. 상세는 처리기준.md §A, 검산은 verify_close.py.
- **초안작성자 vs 확정자**: 판단 항목(계정 분류 애매·증빙 부족·공제/불공제·실사 미도착)은 임의 확정하지 않는다. 가장 합리적인 안을 **추천안으로 잠정 기표**(`분류=잠정`)하고 **확인사항 5필드**(항목/상황/선택지/추천안·근거/재무제표 영향)로 등재한 뒤 결산은 끝까지 완성한다. 멈추고 되묻지 않는다(예외: 회사·기간 식별 불가).
- **계산은 결정적 엔진, 추출은 AI, 가정은 사람**: 숫자는 LLM 암산 금지. Python 엔진이 분개·부가세분리·상각·집계를 짜고 `assert`로 대차·앵커를 강제.
- **산출물은 살아있는 수식**: 시산표는 분개장을 SUMIFS로, 재무제표는 시산표 셀을 참조. 하드코딩 금지. (더존 업로드는 반대로 값·숫자형만.)
- **독립 이중검증**: ① `formulas`로 워크북을 실제 재계산해 자체검산과 대조. ② 별도 서브에이전트가 raw부터 다시 집계해 대사.
- **오류는 실질 신호**: 더존 반려·린트·에러를 꼼수로 통과시키지 않는다. "왜 막혔나"를 요건 미충족으로 먼저 해석.

## 절차 STEP 0~9

### 0. 자료 인벤토리
raw 폴더를 스캔해 회사·기간을 식별한다. 필요한 raw: 기초BS(또는 전기이월분개장)·은행거래내역·카드승인내역·세금계산서·급여대장·거래처마스터, (선택) 기말재고 실사표. **식별 불가 시에만** 사용자에게 묻는다(이때만 멈춤).

### 1. 처리 방식 로드 + 전기 참고(필수)
[처리기준.md](references/처리기준.md)의 **회사 프로파일**을 baseline으로 로드한다. 프로파일이 없으면 §C 템플릿으로 `scripts/profile_<회사>.py`를 만든다(예시: `profile_sample.py`). **전기 output이 있으면 `전기 확인사항`(확정 판단·플래그)과 `전기 결산확정`을 반드시 읽어** 확정 판단을 승계하고, 전기 플래그(예: 택시 재분류)를 당기에 확정한다. **전기와 달라지면 「전기 방식 승계·편차」에 편차로 등재**.

### 2. raw 적재·정합성 대사
기초BS↔전기말, 은행 입출금↔세금계산서/급여/카드 상호대사, 카드승인 합↔카드대금 결제를 대사한다. 불일치(예: 기초BS 이월이익잉여금 부호 오류)는 대차 맞는 쪽을 채택하고 **확인사항 등재**. 엔진이 `find`로 파일을 자동 매칭한다.

#### Gridie(MCP) 표에서 받을 때
DB 표에는 여러 분기가 한 표에 있다. 표를 raw 엑셀로 내릴 때 이 순서를 지킨다(2026-10-16 마루키 2분기를 MCP 로 받아 돌려, Drive 원본으로 돌린 산출물과 셀 단위로 같음을 확인).
- **기간으로 거른다.** 통장 · 카드 · 세금계산서는 날짜, 급여대장은 귀속월, 기초재무상태표는 기준일(직전 분기말), 전기이월분개장은 일자(직전 분기말)로 거른다. 엔진도 결산 기간에 들지 않는 행을 빼고 `[주의]` 줄과 확인 항목으로 남기지만, 원천에서 거르는 것이 먼저다. 거르지 않으면 매출이 두 배로 잡혀도 `verify_close` 는 ALL PASS 를 낸다.
- **파일 이름 · 머리글 · 열 순서는 예시 폴더(`2분기_당기`)와 같게** 둔다. 엔진은 열을 위치로 읽는다. 금액 · 계정코드 · 사업자번호는 숫자형, 거래처코드는 텍스트('00101').
- **`run_sql` 은 UNION 을 쓰면 행을 돌려주지 않는다**(`affectedRows` 만 온다). 표마다 따로 읽거나 스칼라 하위 질의로 묶는다.
- **한 행을 문자열로 묶을 때 `concat_ws` 를 쓰지 않는다.** NULL 값이 사라져 입금 · 출금 열이 밀린다. `concat(a, '|', b, …)` 는 NULL 을 빈 문자열로 둔다.
- **내린 뒤 원천과 맞춘다.** 표마다 행 수와 금액 합계(또는 정렬한 행 문자열의 md5)를 `run_sql` 로 다시 세어 엑셀과 대조한다. 행을 옮겨 적다 생긴 오타는 대차가 맞아도 남는다.

### 3~6. 결정적 엔진 실행 (분개→조정→재무제표→더존 업로드)
```
python "{skill}/scripts/run_close.py" "<raw_dir>" "<out_dir>" <기간라벨> [profile_모듈]
```
- 산출: `결산확정_{기간}.xlsx`(8시트 전부 수식) · `일반전표_업로드_더존_{기간}.xlsx` · `매입매출전표_업로드_더존_{기간}.xlsx`.
- 엔진(`close_engine.py`)이 원천별 분개(부가세 분리) → **매입공제 전 불공제 체크리스트 적용**(references §B) → 결산조정(감가·무형·원가대체·부가세정리) → 시산표/손익/재무상태표/현금흐름표를 **셀 참조 수식**으로 연결한다.
- 출력된 앵커(매출액·매출원가·미지급세금·카드공제세액·일반전표 차대·매입매출 공급·세액)를 프로파일 §D 기대값과 대조한다.

### 7. AI 1차 판단 → 확인사항 리포트 (.docx, 가장 중요)
§8 검증을 먼저 돌린 뒤 이 순서로 한다.
```
python "{skill}/scripts/review_items.py" "<raw_dir>" "<out_dir>" <기간라벨> [profile_모듈]
#   → <out_dir>/_확인항목_{기간}.json  (미분류 거래 · 잠정 처리 · 해외카드 · 거래처 미해소 · 검증 확인/FAIL)
#   AI 가 <out_dir>/AI의견_{기간}.json 을 쓴다(아래 규칙)
python "{skill}/scripts/review_items.py" --check "<out_dir>" <기간라벨>
python "{skill}/scripts/build_docx.py" "<raw_dir>" "<out_dir>" <기간라벨> [profile_모듈]
```
- `AI의견_{기간}.json` 형식: `{"작성": "AI 1차 의견 · 회계사 확정 전", "의견": {"<항목 id>": {"의견": "...", "근거": ["..."], "확신도": "높음|중간|낮음", "판단보류": false}}}`. 항목마다 하나씩 쓴다.
- **AI 1차 판단 규칙**
  - 항목 JSON 의 `참고`(전기_확정판단 · 처리기준 · 계정과목 마스터)와 raw 원천 자료(은행 · 카드 · 세금계산서 · 급여대장 · 거래처마스터)를 읽고 판단한다.
  - 근거는 하나 이상 적는다. 처리기준 항목, 전기 확정판단 문장, 원천 자료에서 찾은 사실(무엇이 어디에 있고 없는지), 세법이면 korean-law 로 확인한 조문 원문과 시행일을 적는다.
  - 근거를 못 찾으면 `판단보류: true` 로 두고 무엇을 받아야 판단할 수 있는지 적는다. 그럴듯한 추측으로 채우지 않는다.
  - 확신도: 높음은 규칙 · 조문과 데이터가 모두 맞을 때, 중간은 정황 근거만 있을 때, 낮음은 적요로 추정할 때.
  - **숫자를 바꾸지 않는다.** 프로파일 · 엔진 · 산출물을 고치지 않는다. 회계사가 받아들인 의견만 §9 에서 프로파일 규칙에 넣고 엔진을 다시 돌린다.
  - 확신도가 높아도 확인 항목에서 빼지 않는다. AI 의견은 회계사가 볼 순서와 근거를 정리하는 용도다.
- `확인사항_{기간}.docx` 생성: 「확정·회신 필요 항목」 요약 + **①-2 확인 항목 · AI 의견 · 근거 · 확신도** + 판단 5필드 표 + 전기 승계·편차 + 채권채무 + 손익 + 검증 요약(부록 B). AI 의견 파일이 없으면 「AI 1차 의견 없음」으로 적고, 형식이 틀리면 오류 건수를 적는다.
- 회사별 판단 항목은 프로파일의 `확인사항_요약` · `확인사항_5필드` · `전기승계_표` 로 준다(예: `profile_sample.py`). 없으면 ①-2 항목과 `전기_확정판단` 으로 채운다. `pip install python-docx` 필요.

### 8. 검증 (필수 — 독립 이중검증)
```
python "{skill}/scripts/verify_upload.py" "<out_dir>" <기간라벨> [profile_모듈]
python "{skill}/scripts/verify_close.py" "<out>/결산확정_{기간}.xlsx" [expected.json]
```
- `verify_upload.py` 가 **먼저다.** 대차가 맞아도 더존에서 막히는 것은 양식과 거래처코드·사업자번호다.
  FAIL 이면 올리지 않는다. 임의값으로 통과시키지 않는다.
- `formulas`로 워크북을 재계산해 **엔진값 = 수식값**, 대차 균형, 현금흐름=BS 현금, 순이익 연결을 확인.
- **그리고 별도 서브에이전트를 디스패치**해 raw부터 재집계 → §9 대조. FAIL이면 원인 수정 후 재검증(임의 확정 금지).
- **검증을 확인사항 문서보다 먼저 돌린다.** 문서는 검증 결과 JSON(`_검증_업로드_*.json`·`_검증_워크북_*.json`)을 읽어 적는다. 결과가 없으면 문서에 「검증 미실행」이라고 쓴다. **검사하지 않은 것을 PASS로 적지 않는다.**

### 9. 회사 프로파일 갱신
새 확정판단·매핑·손익을 [처리기준.md](references/처리기준.md) 회사 프로파일과 `profile_<회사>.py`에 승계 기록한다(다음 기간 대비).

## 무엇을 자동으로 검증하고 무엇을 안 하는가

**PASS는 실행한 검사에만 붙인다.** 아래 표의 「어디서」가 빈 항목은 자동 판정이 없다.

| 검사 | 어디서 |
|---|---|
| 시산표 차대, 재무상태표 대차, 현금흐름=BS 현금 | `verify_close.py` · 워크북 검증리포트 수식 |
| 수식 개수(하드코딩 아님), 손익 항등식, 순이익=시산표 손익계정 합 | `verify_close.py` |
| 매출=원천 합계, 부가세 정합, 계정 부호 | 워크북 검증리포트 수식 |
| 보통예금 출금 전표에 손익계정이 직접 걸리지 않음 | `verify_close.py` |
| 시트·컬럼·숫자형·앞자리0, 날짜 범위, 구분과 차대 방향, 전표 유무 | `verify_upload.py` |
| 채권채무 거래처코드, 매입매출 사업자번호, 미등록 거래처 | `verify_upload.py` |
| 분개 건수 + 미분류 건수 = 통장 전체 | `run_close.py` |
| 원천 자료 자체의 정확성 | **자동 판정 없음.** 전문가가 본다 |
| 공제·불공제, 계정 분류, 기말재고 같은 판단 | **자동 판정 없음.** 확인사항으로 등재 |

## 미분류 가드레일 (100% 자동화 금지)

규칙이 모든 거래를 덮으면 어느 것이 규칙이고 어느 것이 추측인지 구분이 없어져 전문가가 검토할 수 없다.
- 전기에 같은 적요 모양이 있으면 그 방식을 승계한다.
- 전기에 없는 신규 거래는 적요가 성격을 설명할 때만 규칙으로 처리한다.
- 둘 다 아니면 **가계정**(가지급금·가수금)에 두고 `미분류목록_<기간>.xlsx` 로 낸다. 분개에서 빼지 않는다.
  빼면 현금 대사와 대차가 깨지고, 임의 계정을 주면 추측이 규칙으로 둔갑한다.
- 프로파일 `미분류_계정` 이 가계정을 정한다. 없으면 이 단계는 돌지 않는다.

## 참고: 설계서 §9 검산 항목
1 시산표 차변합=대변합(기말합=0) · 2 재무상태표 자산=부채+자본, 기초=전기이월 기말 · 3 현금흐름 기말현금=BS 보통예금=기초+은행 순증감 · 4 순이익=자본(이익잉여) 변동 · 5 매출액=세금계산서 매출 공급가 합 · 6 부가세 정합(매출세액−공제가능 매입세액=미지급세금, 정리 후 예수/대급=0) · 7 업로드 합=분개장 해당분(일반전표 차=대, 매입매출 공급·세액), 더존 컬럼·숫자형 · 8 비정상 부호 없음 · 9 `분류=잠정` 전부 확인사항 5필드 등재 + 전기 편차 등재 · 10 수식 연결(하드코딩 아님) · 11 더존 사전검증(`verify_upload.py`: 시트명·컬럼 완전일치, 사업자번호 숫자형, **채권채무 거래처코드 채움**, **매입매출 11열 사업자번호 채움**(예외는 영세12 국외뿐), 카드57=사업자번호 有 행만, 여객운송 등 불공제 혼입 없음) · 12 매입세액 불공제 사유 전수검토(해당 없으면 '검토 완료' 명시).

## 판단 규율 & Red Flags
- 전기 동일 사례 있으면 그 방식 확정 + 「전기 승계」 표에 행. 없으면 추천안 잠정 + 5필드 등재. 금액 작아도 등재. **프로즈 속 "추정됩니다"는 등재가 아니다 — 표로 등재해야 등재.**
- **Red Flags**: 적요에 추정/가정인데 확인사항에 없음 / 확인사항 0건 / 선택지 없이 추천안만 / 재무영향 빈칸 / 더존 컬럼 임의변경 / 재무제표 하드코딩 / STEP8 없이 완료선언 / **사업자번호 없이 매입공제·여객운송 공제** / **반려를 임의값으로 통과** / **채권채무 계정 거래처코드·매입매출 11열 사업자번호를 선언 없이 빈칸으로 내보냄**(원천에 있는데 안 쓴 것인지, 한 거래처가 아니어서 빈 것인지 구분 안 됨) / **업로드 파일 컬럼·시트명을 손댐**(회사가 쓰던 양식 그대로여야 한다).

## 프로파일 메모

- **월 단위로 여러 번 돌리는 회사는 재고를 기간별로 줍니다.** `상품_기초재고`·`상품_기말재고_잠정` 에
  `{"2026-05": …, "2026-06": …}` 처럼 dict 를 두면 엔진이 그 기간 값을 씁니다(`Engine._by_period`).
- **카드 불공제 사유는 프로파일이 정합니다.** `카드불공제_사유 = {가맹점: 사유}` 를 두면 엔진이 적요에
  「매입세액 불공제 · 사유」로 적습니다. 안 두면 사유 없이 「매입세액 불공제」만 남습니다.

## 커맨드 (슬래시 호출)
- `/결산자동화 <raw_dir> <기간> [profile_모듈]`: run_close → verify_upload · verify_close → review_items(AI 1차 의견) → build_docx 순으로 4종 산출 후 앵커·검증·AI 의견 요약 보고.
- `/결산자동화 <raw_dir>` — 폴더를 스캔해 회사·기간을 식별(파일명·자료에서 추론)한 뒤 위 절차 실행.
- `/결산자동화` (인자 없음) — 처리할 raw 폴더 경로를 되묻고(STEP 0), 확인되면 실행.
- 산출물은 `<raw_dir>/output` (미지정 시)에 저장하고, 기간라벨은 `2026Q2`·`2026-05` 형식으로 정규화한다.

## 거버넌스
계산은 코드·판단은 전문가 · 불공제 체크리스트 전수 · 전기 승계/편차 등재 · 수식 기반(재계산 가능) · 비식별 · 이모지 미사용 · 모든 산출물은 전문가 검토 후 확정.
