Files
GA Pro 81877dcb2b fix: 필수 파라미터 누락 시 500→400 정정 + 전체 메뉴 점검/도메인 문서
- GlobalExceptionHandler: MissingServletRequestParameterException 핸들러 추가.
  기존엔 미처리로 generic Exception→E500. 이제 INVALID_PARAMETER(400) 반환.
  (전수 점검 중 /api/settle/summary 가 settleMonth 누락 시 500 반환하던 결함 발견)
- smoke_allmenus.py: 전체 메뉴 화면 1차 GET 엔드포인트 67개 전수 점검 스크립트.
  admin 전권 로그인 후 5xx 만 FAIL 분류. 검증: 66 PASS + 1 정상400, 5xx 0건.
- DOMAIN_KNOWLEDGE.md: 보험 GA 수수료 정산 도메인 입문 문서
  (수수료 종류/규제룰/세무공제/12단계 정산 파이프라인/상태흐름/용어사전).

검증: 5모듈 compileJava + ga-frontend vite build + PWA tsc PASS,
전체 테스트 112건 PASS, 모바일 me/* 5개 200.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 10:23:44 +09:00

101 lines
4.0 KiB
Python

# -*- coding: utf-8 -*-
"""전체 메뉴 화면 1차 데이터 로드(list) 엔드포인트 전수 점검.
admin(전권) 로그인 후 각 화면이 호출하는 GET 엔드포인트를 호출하여
5xx(코드 오류)만 FAIL 로 분류한다. 4xx(파라미터/권한 요구)는 SKIP 으로 본다."""
import json
import urllib.request
import urllib.error
BASE = "http://localhost:8082"
def call(method, path, token=None, body=None):
data = json.dumps(body).encode() if body is not None else None
req = urllib.request.Request(BASE + path, data=data, method=method)
req.add_header("Content-Type", "application/json")
if token:
req.add_header("Authorization", "Bearer " + token)
try:
with urllib.request.urlopen(req, timeout=30) as r:
return r.status, r.read().decode()
except urllib.error.HTTPError as e:
return e.code, e.read().decode() or "{}"
except Exception as e:
return -1, str(e)
# 1) 로그인
st, raw = call("POST", "/api/auth/login", body={"loginId": "admin", "password": "admin1234!"})
bd = json.loads(raw)
token = bd["data"]["accessToken"]
print("[LOGIN] OK roles=%s" % bd["data"].get("roles"))
# 2) 각 메뉴 화면 1차 GET (list/primary). 일부는 필수 파라미터 동봉.
endpoints = [
# 기준정보
"/api/companies", "/api/products", "/api/orgs/tree", "/api/orgs",
"/api/agents", "/api/contracts", "/api/contract-successions",
"/api/agent-contracts", "/api/agent-licenses",
# 수수료 규칙/마스터
"/api/commissions", "/api/rules/commission-rates", "/api/rules/payout",
"/api/rules/override", "/api/regulatory-limits",
"/api/installment-ratios", "/api/installment-plans",
"/api/chargeback-grades",
"/api/collection-commissions/rules", "/api/collection-commissions/ledgers",
"/api/renewal-commissions/rules", "/api/renewal-commissions/ledgers",
"/api/reinstatement-commissions/rules", "/api/reinstatement-commissions/ledgers",
"/api/persistency-bonus/rules", "/api/persistency-bonus/bonuses",
"/api/override-ledgers",
# 정산/원장/명세
"/api/settle", "/api/settle/summary", "/api/settle-corrections",
"/api/ledger/recruit", "/api/ledger/maintain",
"/api/payments", "/api/deductions", "/api/statements",
"/api/period-close",
# 세무/회계
"/api/tax-invoices", "/api/withholding-tax-reports", "/api/vat-reports",
"/api/accounting-closes", "/api/accounting-entries",
"/api/agent-annual-incomes", "/api/year-end-statements",
# 운영/워크플로우
"/api/disputes", "/api/complaints", "/api/contract-endorsements",
"/api/incentive-programs", "/api/incentive-payments",
"/api/termination-settlements",
"/api/approvals/lines", "/api/approvals/requests/mine",
"/api/withdraw-requests",
# KPI/예측
"/api/kpi/monthly-summary", "/api/kpi/org-summary",
"/api/kpi/retention", "/api/kpi/cumulative",
"/api/forecast-kpi", "/api/retention-anomalies",
# 외부연동/수신
"/api/receive/profiles", "/api/carrier-reconciliation",
"/api/external-call-logs",
# 시스템
"/api/system/users", "/api/system/roles",
"/api/data-dictionary", "/api/data-domains",
"/api/upload-templates", "/api/batch/status", "/api/batch/jobs",
]
ok, fails, skips = 0, [], []
for ep in endpoints:
st, raw = call("GET", ep, token)
if st == 200:
ok += 1
tag = "PASS"
elif 500 <= st < 600 or st == -1:
fails.append((ep, st, raw[:300]))
tag = "FAIL"
else:
skips.append((ep, st))
tag = "SKIP(%d)" % st
print(" [%s] GET %s -> %s" % (tag, ep, st))
print("\n[RESULT] total=%d PASS=%d FAIL=%d SKIP=%d" %
(len(endpoints), ok, len(fails), len(skips)))
if fails:
print("\n=== FAIL DETAIL (code error - fix target) ===")
for ep, st, raw in fails:
print(" %s [%s]\n %s" % (ep, st, raw))
if skips:
print("\n=== SKIP (4xx - param/perm required, screen may be OK) ===")
for ep, st in skips:
print(" %s [%s]" % (ep, st))