diff --git a/INDEX.md b/INDEX.md index 8fece73..79426a2 100644 --- a/INDEX.md +++ b/INDEX.md @@ -45,6 +45,7 @@ | 계정별원장·손익계산서 | `dev/dev_plans/account-ledger-income-statement-plan.md` | 계정별원장 + 손익계산서 신규 메뉴 기획 (더존 참고) | | 경조사비 서비스 이관 | `dev/dev_plans/condolence-expense-service-plan.md` | MNG 경조사비 → API+React 서비스 이관 기획 | | 계정별원장 서비스 이관 | `dev/dev_plans/account-ledger-service-migration-plan.md` | MNG 계정별원장 → API+React 서비스 이관 기획 (API 완료) | +| 손익계산서 서비스 이관 | `dev/dev_plans/income-statement-service-migration-plan.md` | MNG 손익계산서 → API+React 서비스 이관 기획 (API 완료) | | 서버 운영 | `dev/deploys/ops-manual/README.md` | 서버 운영 매뉴얼 | | 서버 접근/백업 | `system/server-access-management.md` | 계정, 권한, 백업, 리플리케이션 | | 이관 작업 | `system/migration-status.md` | MNG→API+React 이관 현황, 우선순위, 로드맵 | @@ -335,6 +336,7 @@ DB 도메인별: | [nonconforming-api.md](frontend/api-specs/nonconforming-api.md) | 부적합관리 API 명세 (7개 엔드포인트 + 화면 가이드 + Server Actions 예시) | | [account-ledger-income-statement-api.md](frontend/api-specs/account-ledger-income-statement-api.md) | 계정별원장·손익계산서 API 명세 (초기 버전) | | [account-ledger-service-api.md](frontend/api-specs/account-ledger-service-api.md) | 계정별원장 서비스 이관 API 명세 (카드거래+분리전표 보강, 최신) | +| [income-statement-service-api.md](frontend/api-specs/income-statement-service-api.md) | 손익계산서 서비스 이관 API 명세 (기간별+월별 조회, TypeScript 타입, 화면 가이드) | | [condolence-expense-api.md](frontend/api-specs/condolence-expense-api.md) | 경조사비 관리 API 명세 (6개 엔드포인트 + TypeScript 타입 + 화면 가이드) | | [condolence-dashboard-fe-request.md](frontend/api-specs/condolence-dashboard-fe-request.md) | 경조사비 대시보드 연동 FE 구현 요청 (condolence_summary 카드 추가) | | [vehicle-react-implementation.md](plans/vehicle-react-implementation.md) | 차량관리 React 구현 요청서 (3개 메뉴, 컴포넌트 구조, 타입 정의) | diff --git a/dev/dev_plans/income-statement-service-migration-plan.md b/dev/dev_plans/income-statement-service-migration-plan.md new file mode 100644 index 0000000..dc67798 --- /dev/null +++ b/dev/dev_plans/income-statement-service-migration-plan.md @@ -0,0 +1,157 @@ +# 손익계산서 서비스 이관 기획서 + +> **작성일**: 2026-03-20 +> **상태**: 기획 확정, API 완료 +> **대상**: MNG → API + React (서비스 이관) +> **위치**: 서비스 > 회계관리 > 손익계산서 + +--- + +## 1. 개요 + +### 1.1 목적 + +MNG 백오피스의 손익계산서 조회 기능을 서비스(API + React)로 이관한다. +API에는 이미 동일 로직의 `IncomeStatementService`가 구현되어 있으므로, **API 코드 변경 없이** React 프론트엔드 구현만 필요하다. + +### 1.2 배경 + +- MNG `회계/세무관리 > 손익계산서` 메뉴로 기존 구현 완료 (2026-03-19) +- API에 `IncomeStatementService` + `IncomeStatementController`가 MNG와 동일 로직으로 이미 구현됨 +- 기간별 조회 (`GET /api/v1/income-statement`) + 월별 조회 (`GET /api/v1/income-statement/monthly`) 2개 엔드포인트 제공 + +### 1.3 이관 범위 + +| 구분 | MNG (현재) | API + React (이관 후) | +|------|-----------|---------------------| +| **백엔드** | Controller 직접 로직 | `IncomeStatementService` (이미 완료) | +| **프론트** | Blade + React (@verbatim) | React (Next.js) | +| **인증** | 세션 기반 | Bearer 토큰 + `BelongsToTenant` | +| **API 코드 변경** | — | **불필요** (이미 완료) | + +--- + +## 2. 현재 MNG 기능 분석 + +### 2.1 MNG 기능 목록 + +| 기능 | MNG 메서드 | API 대응 | +|------|-----------|---------| +| 페이지 렌더링 | `index()` | React 라우트 | +| 기간별 조회 | `data()` | `GET /api/v1/income-statement` | +| 월별 조회 | `monthly()` | `GET /api/v1/income-statement/monthly` | + +### 2.2 손익계산서 구조 (PL_STRUCTURE) + +한국 일반기업회계기준에 따른 10개 항목: + +``` +I. 매출액 = revenue(sales_revenue) 합계 +II. 매출원가 = expense(cogs + construction_cost) 합계 +III. 매출총이익 = I - II (계산) +IV. 판매비와관리비 = expense(selling_admin) 합계 +V. 영업이익 = III - IV (계산) +VI. 영업외수익 = revenue(other_revenue) 합계 +VII. 영업외비용 = expense(other_expense) - [99800, 99900] 합계 +VIII.법인세비용차감전순이익 = V + VI - VII (계산) +IX. 법인세비용 = expense[99800, 99900] 특정 코드만 +X. 당기순이익 = VIII - IX (계산) +``` + +### 2.3 데이터 소스 + +일반전표(`journal_entry_lines`) + 홈택스 세금계산서(`hometax_invoice_journals`)를 합산하여 계정코드별 차변/대변 합계를 구한다. + +### 2.4 MNG ↔ API 비교 + +| 항목 | MNG | API | +|------|-----|-----| +| PL_STRUCTURE | 동일 | 동일 | +| getAccountSums (journal + hometax) | 동일 | 동일 | +| buildSections | 동일 | 동일 | +| evaluateFormula | 동일 | 동일 | +| 단위 변환 (won/thousand/million) | 동일 | 동일 | +| 기수 계산 (getFiscalYear) | 동일 | 동일 | +| `_debug` 필드 | 포함 | 미포함 (정상) | + +**결론**: API 코드 변경 불필요. + +--- + +## 3. API 엔드포인트 + +### 3.1 기간별 손익계산서 + +| Method | Path | 설명 | +|--------|------|------| +| `GET` | `/api/v1/income-statement` | 기간별 손익계산서 (당기+전기) | + +**요청 파라미터**: + +| 파라미터 | 타입 | 필수 | 설명 | +|---------|------|:----:|------| +| `start_date` | `string(date)` | Y | 당기 시작일 | +| `end_date` | `string(date)` | Y | 당기 종료일 | +| `unit` | `string` | N | `won`(기본) / `thousand` / `million` | + +### 3.2 월별 손익계산서 + +| Method | Path | 설명 | +|--------|------|------| +| `GET` | `/api/v1/income-statement/monthly` | 월별 손익계산서 | + +**요청 파라미터**: + +| 파라미터 | 타입 | 필수 | 설명 | +|---------|------|:----:|------| +| `year` | `integer` | Y | 조회 연도 (2020~2100) | +| `unit` | `string` | N | `won`(기본) / `thousand` / `million` | + +--- + +## 4. React 구현 요구사항 + +### 4.1 보기 모드 + +| 모드 | API | 설명 | +|------|-----|------| +| **기간 보기** | `GET /income-statement` | 당기+전기 비교 (토글로 전기 숨김 가능) | +| **월별 보기** | `GET /income-statement/monthly` | 연도별 1~12월 비교 | + +### 4.2 UI 컨트롤 + +- 보기 모드 전환 (`[기간 보기]` / `[월별 보기]`) +- 당기/전기 토글 (`[당기만]` / `[당기+전기]`) — 기간 보기에서만 +- 월 선택 (`[전체]` `[1월]` `[2월]` ... `[12월]`) — 월별 보기에서만 +- 기간 필터 (시작일~종료일) / 연도 선택 +- 단위 선택 (원 / 천원 / 백만원) +- 인쇄 버튼 + +### 4.3 테이블 레이아웃 + +**기간 보기**: 과목 | 당기(세부+소계) | 전기(세부+소계, 토글) +**월별 단일 월**: 과목 | 금액(세부+소계) +**월별 전체**: 과목(sticky) | 1월 | 2월 | ... | 12월 (가로 스크롤) + +--- + +## 5. MNG 참고 화면 + +> MNG 개발서버: `https://admin.codebridge-x.com` → 회계/세무관리 > 손익계산서 + +| 파일 | 설명 | +|------|------| +| `mng/app/Http/Controllers/Finance/IncomeStatementController.php` | 전체 로직 | +| `mng/resources/views/finance/income-statement.blade.php` | React 컴포넌트 (UI 참고) | + +--- + +## 관련 문서 + +- [dev/dev_plans/account-ledger-income-statement-plan.md](account-ledger-income-statement-plan.md) — 원래 MNG 구현 기획서 +- [frontend/api-specs/income-statement-service-api.md](../../frontend/api-specs/income-statement-service-api.md) — FE API 명세 (서비스 이관 버전) +- [frontend/api-specs/account-ledger-service-api.md](../../frontend/api-specs/account-ledger-service-api.md) — 계정별원장 FE API 명세 + +--- + +**최종 업데이트**: 2026-03-20 diff --git a/frontend/api-specs/income-statement-service-api.md b/frontend/api-specs/income-statement-service-api.md new file mode 100644 index 0000000..8cd9372 --- /dev/null +++ b/frontend/api-specs/income-statement-service-api.md @@ -0,0 +1,382 @@ +# 손익계산서 API 명세 (서비스 이관) + +> **작성일**: 2026-03-20 +> **상태**: API 완료, React 구현 대기 +> **대상**: React 프론트엔드 개발자 + +--- + +## 1. 개요 + +회계관리 메뉴에 **손익계산서** 화면을 구현한다. +기간별 당기/전기 비교와 월별 비교 두 가지 보기 모드를 제공한다. +한국 일반기업회계기준에 따른 10개 항목(I~X) 구조로 매출액, 매출원가, 영업이익, 당기순이익 등을 표시한다. + +### 메뉴 위치 + +``` +회계관리 +├── 일반전표입력 ← 기존 +├── 계정별원장 ← 기존 +├── 손익계산서 ← 이 화면 +├── ... +``` + +--- + +## 2. API 엔드포인트 + +### 2.1 기간별 손익계산서 + +``` +GET /api/v1/income-statement +``` + +**요청 파라미터** (Query String): + +| 파라미터 | 타입 | 필수 | 설명 | 예시 | +|---------|------|:----:|------|------| +| `start_date` | `string(date)` | Y | 당기 시작일 | `2026-01-01` | +| `end_date` | `string(date)` | Y | 당기 종료일 | `2026-12-31` | +| `unit` | `string` | N | `won`(기본) / `thousand` / `million` | `won` | + +> **전기**: API가 자동으로 전년 동기를 계산 (예: 2026 → 2025) + +**응답 예시**: + +```json +{ + "success": true, + "message": "조회되었습니다.", + "data": { + "period": { + "current": { + "start": "2026-01-01", + "end": "2026-12-31", + "label": "제 2 (당)기" + }, + "previous": { + "start": "2025-01-01", + "end": "2025-12-31", + "label": "제 1 (전)기" + } + }, + "unit": "won", + "sections": [ + { + "code": "I", + "name": "매출액", + "current_amount": 50000000, + "previous_amount": 30000000, + "items": [ + { "code": "40400", "name": "용역매출", "current": 50000000, "previous": 30000000 } + ], + "is_calculated": false + }, + { + "code": "II", + "name": "매출원가", + "current_amount": 20000000, + "previous_amount": 15000000, + "items": [ + { "code": "50100", "name": "서비스매출원가", "current": 12000000, "previous": 8000000 }, + { "code": "50200", "name": "외주용역비", "current": 8000000, "previous": 7000000 } + ], + "is_calculated": false + }, + { + "code": "III", + "name": "매출총이익", + "current_amount": 30000000, + "previous_amount": 15000000, + "items": [], + "is_calculated": true + } + ] + } +} +``` + +--- + +### 2.2 월별 손익계산서 + +``` +GET /api/v1/income-statement/monthly +``` + +**요청 파라미터** (Query String): + +| 파라미터 | 타입 | 필수 | 설명 | 예시 | +|---------|------|:----:|------|------| +| `year` | `integer` | Y | 조회 연도 | `2026` | +| `unit` | `string` | N | `won`(기본) / `thousand` / `million` | `won` | + +**응답 예시**: + +```json +{ + "success": true, + "message": "조회되었습니다.", + "data": { + "year": 2026, + "fiscal_year": 2, + "fiscal_label": "제 2 기", + "unit": "won", + "months": [ + { + "month": "01", + "label": "1월", + "sections": [ + { + "code": "I", + "name": "매출액", + "current_amount": 5000000, + "previous_amount": 5000000, + "items": [ + { "code": "40400", "name": "용역매출", "current": 5000000, "previous": 5000000 } + ], + "is_calculated": false + } + ] + }, + { + "month": "02", + "label": "2월", + "sections": [] + } + ] + } +} +``` + +> **참고**: 미래 월은 응답에 포함되지 않는다. +> 월별 데이터에서 `previous_amount`와 `item.previous`는 `current`와 동일한 값 (월별 비교에서는 의미 없음). + +--- + +## 3. TypeScript 인터페이스 + +```typescript +// 기간별 손익계산서 응답 +interface IncomeStatementResponse { + success: boolean; + message: string; + data: { + period: { + current: { start: string; end: string; label: string }; // "제 2 (당)기" + previous: { start: string; end: string; label: string }; // "제 1 (전)기" + }; + unit: 'won' | 'thousand' | 'million'; + sections: PLSection[]; + }; +} + +// 월별 손익계산서 응답 +interface MonthlyIncomeStatementResponse { + success: boolean; + message: string; + data: { + year: number; + fiscal_year: number; + fiscal_label: string; // "제 2 기" + unit: 'won' | 'thousand' | 'million'; + months: MonthPL[]; + }; +} + +interface MonthPL { + month: string; // "01", "02", ... + label: string; // "1월", "2월", ... + sections: PLSection[]; +} + +interface PLSection { + code: string; // "I", "II", "III", ... "X" + name: string; // "매출액", "매출원가", "매출총이익", ... + current_amount: number; // 당기 금액 + previous_amount: number; // 전기 금액 + items: PLItem[]; // 세부 계정과목 (계산 항목은 빈 배열) + is_calculated: boolean; // true = 계산 항목 (III, V, VIII, X) +} + +interface PLItem { + code: string; // 계정코드 "40400" + name: string; // 계정명 "용역매출" + current: number; // 당기 금액 + previous: number; // 전기 금액 +} +``` + +--- + +## 4. 화면 구현 가이드 + +### 4.1 화면 구조 + +``` +┌───────────────────────────────────────────────────┐ +│ 📊 손익계산서 [인쇄] │ +├───────────────────────────────────────────────────┤ +│ [기간 보기] [월별 보기] [당기만] [당기+전기] │ +│ 기간: [시작일]~[종료일] 단위: [원▾] [조회] │ +├───────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────────────────────────────────┐ │ +│ │ 과 목 │ 제 2 (당)기 │ 제 1 (전)기│ │ +│ │ │ 금 액 │ 금 액 │ │ +│ ├─────────────────┼──────────────┼─────────────┤ │ +│ │ I. 매출액 │ │ │ │ +│ │ 용역매출 │ 50,000,000 │ │ │ +│ │ │ │ 50,000,000 │ │ +│ ├─────────────────┼──────────────┼─────────────┤ │ +│ │ II. 매출원가 │ │ │ │ +│ │ 서비스매출원가│ 12,000,000 │ │ │ +│ │ 외주용역비 │ 8,000,000 │ │ │ +│ │ │ │ 20,000,000 │ │ +│ ├─────────────────┼──────────────┼─────────────┤ │ +│ │ III. 매출총이익 │ │ 30,000,000 │ │ ← 강조 (연두) +│ │ ... │ │ │ │ +│ │ X. 당기순이익 │ │ 25,000,000 │ │ ← 강조 (연두) +│ └─────────────────┴──────────────┴─────────────┘ │ +│ (단위: 원) │ +└───────────────────────────────────────────────────┘ +``` + +### 4.2 보기 모드 전환 + +| 모드 | 필터 | API | 설명 | +|------|------|-----|------| +| **기간 보기** | 시작일~종료일 + 단위 | `GET /income-statement` | 당기+전기 2열 비교 | +| **월별 보기** | 연도 + 단위 | `GET /income-statement/monthly` | 월별 비교 | + +- 모드 전환 시 기존 데이터 초기화 후 새로 조회 +- 기본: 기간 보기, 당해 1/1 ~ 12/31 + +### 4.3 기간 보기 테이블 (PeriodTable) + +**컬럼 구성**: + +| 상태 | 컬럼 | +|------|------| +| `당기만` | 과목 \| 금액(세부) \| 금액(소계) | +| `당기+전기` | 과목 \| 당기(세부) \| 당기(소계) \| 전기(세부) \| 전기(소계) | + +**행 유형**: + +| 행 유형 | 조건 | 스타일 | 금액 표시 | +|---------|------|--------|----------| +| **섹션 헤더** | `is_calculated === false` | 굵은 글씨 | items 없으면 소계열에 금액, 있으면 빈칸 | +| **세부 항목** | `items[]` | 들여쓰기(pl-12), 일반 | 세부열에 금액, 마지막 항목의 소계열에 섹션 합계 | +| **계산 항목** | `is_calculated === true` | 강조 배경 | 소계열에만 금액 | + +**강조 표시 (emerald-50 배경)**: +- III (매출총이익), V (영업이익), VIII (법인세비용차감전순이익), X (당기순이익) + +### 4.4 월별 보기 테이블 (MonthlyTable) + +**단일 월 선택**: 기간 보기와 유사한 1열 테이블 +**전체 월 선택**: 가로 스크롤 비교 테이블 + +``` +┌──────────────┬──────┬──────┬──────┬─────┐ +│ 과목 (sticky)│ 1월 │ 2월 │ 3월 │ ... │ +├──────────────┼──────┼──────┼──────┼─────┤ +│ I. 매출액 │ 5M │ 4M │ 6M │ ... │ +│ 용역매출 │ 5M │ 4M │ 6M │ ... │ +│ II. 매출원가 │ 2M │ 1M │ 3M │ ... │ +│ III. 매출총이│ 3M │ 3M │ 3M │ ... │ ← 강조 +│ ... │ │ │ │ │ +└──────────────┴──────┴──────┴──────┴─────┘ +``` + +- 과목 열: `sticky left-0` (가로 스크롤 시 고정) +- 최소 너비: `months.length * 110 + 200` px + +### 4.5 월 선택 버튼 (월별 보기) + +``` +[전체] [1월] [2월] [3월] ... [12월] +``` + +- 데이터가 있는 월만 버튼 표시 (미래 월은 API 응답에 없음) +- `전체` 선택 시 가로 스크롤 비교 테이블 +- 개별 월 선택 시 단일 열 테이블 + +### 4.6 숫자 포맷 + +```typescript +const fmt = (n: number): string => { + if (n === 0 || n === null || n === undefined) return ''; + if (n < 0) return '(' + Math.abs(n).toLocaleString() + ')'; + return n.toLocaleString(); +}; + +const UNIT_LABELS: Record = { + won: '원', + thousand: '천원', + million: '백만원' +}; +``` + +### 4.7 인쇄 + +- `window.print()` 사용 +- 조회 조건, 인쇄 버튼에 `no-print` 클래스 +- CSS: `@media print { .no-print { display: none !important; } }` + +### 4.8 기본값 + +| 항목 | 기본값 | +|------|--------| +| 보기 모드 | 기간 보기 | +| 시작일 | 당해 1/1 | +| 종료일 | 당해 12/31 | +| 단위 | 원 (`won`) | +| 당기/전기 | 당기만 | +| 월 선택 | 전체 | + +- 페이지 진입 시 기본값으로 자동 조회 + +--- + +## 5. 손익계산서 항목 구조 + +``` +I. 매출액 ← 합계 항목 (세부 계정과목 표시) +II. 매출원가 ← 합계 항목 +III. 매출총이익 = I - II ← 계산 항목 (is_calculated: true, 강조) +IV. 판매비와관리비 ← 합계 항목 +V. 영업이익 = III - IV ← 계산 항목 (강조) +VI. 영업외수익 ← 합계 항목 +VII. 영업외비용 ← 합계 항목 +VIII.법인세비용차감전순이익 ← 계산 항목 +IX. 법인세비용 ← 합계 항목 +X. 당기순이익 = VIII - IX ← 계산 항목 (강조) +``` + +- **합계 항목**: `items[]`에 세부 계정과목 포함, `current_amount`/`previous_amount`는 합계 +- **계산 항목**: `items[]`는 빈 배열, `is_calculated: true`, 금액은 공식으로 계산된 결과 + +--- + +## 6. MNG 참고 화면 + +> MNG 개발서버: `https://admin.codebridge-x.com` → 회계/세무관리 > 손익계산서 + +| 파일 | 설명 | +|------|------| +| `mng/app/Http/Controllers/Finance/IncomeStatementController.php` | 전체 로직 (PL_STRUCTURE, buildSections) | +| `mng/resources/views/finance/income-statement.blade.php` | React 컴포넌트 (PeriodTable, MonthlyTable) | + +--- + +## 관련 문서 + +- [dev/dev_plans/income-statement-service-migration-plan.md](../../dev/dev_plans/income-statement-service-migration-plan.md) — 이관 기획서 +- [frontend/api-specs/account-ledger-service-api.md](account-ledger-service-api.md) — 계정별원장 API 명세 +- [features/finance/README.md](../../features/finance/README.md) — 재무관리 기능 개요 + +--- + +**최종 업데이트**: 2026-03-20