12 Commits

Author SHA1 Message Date
72cf5d86a2 feat: [결재/공통] 결재함 + 레이아웃 + 캘린더 + 모바일 반응형
- 결재함 검사성적서 템플릿 기반 렌더링 + 결재 상신
- Sidebar/HeaderFavoritesBar 개선
- AuthenticatedLayout 모바일 반응형
- SearchableSelectionModal HTML 유효성 수정
- VacationManagement, 사원관리 정렬 옵션
2026-03-07 03:04:01 +09:00
a4f99ae339 feat: [출하/배차/회계] 배차 다중행 + 어음 리팩토링 + 출고관리
- 배차차량관리 목업→API 연동, 배차정보 다중 행
- ShipmentManagement 출고관리 API 매핑
- BillManagement 리팩토링 (섹션 분리, hooks, constants)
- 상품권 actions/types 확장
- 출하관리 캘린더 기본 뷰 week-time
2026-03-07 03:03:27 +09:00
9ad4c8ee9f feat: [CEO 대시보드] API 연동 + 섹션 확장 + SummaryNavBar
- 접대비/복리후생비/매출채권/캘린더 섹션 API 연동
- SummaryNavBar 추가 + mockData/modalConfigs 대규모 리팩토링
- Dashboard transformers 도메인별 분리
- 상세 모달 ScheduleDetailModal 추가
2026-03-07 03:03:07 +09:00
04f2a8a74c feat: [문서스냅샷] Lazy Snapshot + rendered_html 캡처
- capture-rendered-html 유틸 추가
- 검사성적서/작업일지 저장 시 HTML 스냅샷 캡처
- 중간검사/작업일지 조회 시 자동 스냅샷
- DocumentViewer 스냅샷 출력 지원
2026-03-07 03:02:59 +09:00
8b6da749a9 feat: [생산지시] 목록/상세 API 연동 + 작업자 화면 개선
- ProductionOrders 목록/상세 페이지 API 연동
- 절곡 중간검사 입력 모달 (7개 제품 항목 통합)
- 자재투입 다중 BOM 그룹 LOT 독립 관리
- 작업자 화면 제품명 productCode만 표시
- BOM 공정 분류 접이식 카드 UI
- 검사성적서 TemplateInspectionContent API 연동
2026-03-07 03:02:52 +09:00
c150d80725 feat: [품질관리] Mock→API 전환 + 검사 모달/문서 개선
- InspectionManagement 전체 API 연동 (Mock 제거)
- 제품검사 성적서 8컬럼 동적 렌더링 + FQC 모드
- 제품검사 요청서 양식 기반 렌더링 + Lazy Snapshot
- 수주선택 모달 발주처 필터링/비활성화 제약
- 실적신고 snake_case→camelCase 변환
- 공정 단계 검사범위(InspectionScope) 설정 추가
- 빌드 타입 에러 수정 (specification, ProductInspectionData 등)
2026-03-07 03:02:30 +09:00
f9eea0c950 chore: [infra] Slack 알림 채널 분리 — product_infra → deploy_react 2026-03-05 11:33:07 +09:00
유병철
2a2a356f58 feat: [생산] 작업지시/작업자화면/대시보드 개선
- 검사문서 모달 및 템플릿 기능 확장
- WorkOrders actions 추가
- 작업자화면 WorkOrderListPanel 개선
- 생산대시보드 actions/타입 보강

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:20:41 +09:00
유병철
181352d7a9 feat: [전자결재] 결재함 기능 확장 및 연결문서 기능 추가
- ApprovalBox actions/타입 확장
- DocumentDetailModalV2 개선
- LinkedDocumentContent 신규 추가
- 결재 문서 타입 보강

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:20:33 +09:00
유병철
1691337f7d feat: [회계] 매출/매입/부실채권/일일보고 UI 개선
- 부실채권 상세/목록/타입 개선
- 매출관리 SalesDetail 개선
- 매입관리 PurchaseDetail 개선
- 일일보고 UI 리팩토링

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:20:21 +09:00
유병철
4e179d2eca refactor: [CEO대시보드] 컴포넌트 분리 및 모달/섹션 리팩토링
- DashboardSettingsSections, DetailModalSections 분리
- 모달 설정(카드/접대비/복리후생/부가세/월비용) 개선
- 섹션 컴포넌트 최적화 (매출/매입/카드/미출고 등)
- mockData, types 정리

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:20:05 +09:00
유병철
db84d6796b feat: [공통] Sidebar, 대시보드 훅, 유틸 개선
- Sidebar 레이아웃 개선
- useCEODashboard 최적화, useDashboardFetch 훅 신규
- amount, status-config 유틸 개선
- dashboard transformers 개선

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:19:53 +09:00
8 changed files with 6 additions and 1231 deletions

View File

@@ -107,10 +107,3 @@ fixed_tools: []
# override of the corresponding setting in serena_config.yml, see the documentation there.
# If null or missing, the value from the global config is used.
symbol_info_budget:
# The language backend to use for this project.
# If not set, the global setting from serena_config.yml is used.
# Valid values: LSP, JetBrains
# Note: the backend is fixed at startup. If a project with a different backend
# is activated post-init, an error will be returned.
language_backend:

View File

@@ -1,172 +0,0 @@
# 일일일보 — USD(외국환) 섹션 누락
**유형**: 프론트엔드 UI 누락
**파일**: `src/components/accounting/DailyReport/index.tsx`
**날짜**: 2026-03-03
---
## 현상
일일일보 페이지에 KRW(원화) 계좌만 표시되고, USD(외국환) 계좌 섹션이 없음.
summary에 `usd_totals`(이월/입금/출금/잔액)이 내려오고, daily-accounts에 `currency: 'USD'` 항목도 내려오지만 UI에서 렌더링하지 않음.
---
## 원인
모든 테이블에서 `currency === 'KRW'` 필터만 적용 중:
```tsx
// line 391 — 계좌별 상세
filteredDailyAccounts.filter(item => item.currency === 'KRW')
// line 448 — 입금 테이블
filteredDailyAccounts.filter(item => item.currency === 'KRW' && item.income > 0)
// line 497 — 출금 테이블
filteredDailyAccounts.filter(item => item.currency === 'KRW' && item.expense > 0)
```
---
## 요구사항
기존 KRW 섹션과 동일한 구조로 USD 섹션 추가:
### 1. 일자별 상세 테이블에 USD 행 추가
- 기존 KRW 계좌 목록 아래에 USD 계좌 목록 표시
- 또는 KRW/USD 구분 소계 행으로 분리
- 합계: `accountTotals.usd` 사용 (이미 계산 로직 있음, line 134-144)
### 2. 예금 입출금 내역에 USD 입금/출금 테이블 추가
- 기존 KRW 입금/출금 아래에 USD 입금/출금 테이블 추가
- 필터: `currency === 'USD' && item.income > 0` / `currency === 'USD' && item.expense > 0`
- 금액 표시: USD 포맷 ($ 또는 달러 표기)
---
## 참고: 이미 준비된 데이터
### summary에서 내려오는 USD 데이터 (line 53-58)
```typescript
summary: {
krwTotals: { carryover, income, expense, balance }, // ← 현재 사용 중
usdTotals: { carryover, income, expense, balance }, // ← 미사용 (여기 추가)
}
```
### accountTotals 계산 로직 (line 134-144)
```typescript
// 이미 USD 합계 계산이 있음 — 사용만 하면 됨
const usdAccounts = dailyAccounts.filter(item => item.currency === 'USD');
const usdTotal = usdAccounts.reduce(
(acc, item) => ({
carryover: acc.carryover + item.carryover,
income: acc.income + item.income,
expense: acc.expense + item.expense,
balance: acc.balance + item.balance,
}),
{ carryover: 0, income: 0, expense: 0, balance: 0 }
);
// accountTotals.usd 로 접근 가능
```
---
## 작업 범위
| 작업 | 설명 |
|------|------|
| 일자별 상세 테이블 | USD 계좌 행 추가 + USD 소계 행 |
| 입금 테이블 | USD 입금 내역 추가 |
| 출금 테이블 | USD 출금 내역 추가 |
| 금액 포맷 | USD 표시 (달러 기호 또는 통화 표기) |
**수정 파일**: `src/components/accounting/DailyReport/index.tsx` (이 파일만)
**새 코드 불필요**: API 데이터, 타입, 계산 로직 모두 이미 있음. 렌더링만 추가.
**상태**: ✅ 완료 (프론트엔드 렌더링 추가됨)
---
# CEO 대시보드 — 자금현황 데이터 정합성 이슈
**유형**: 백엔드 데이터 불일치
**관련 API**: `GET /api/proxy/daily-report/summary`
**관련 파일**: `sam-api/app/Services/DailyReportService.php`
**날짜**: 2026-03-03
---
## 현상
CEO 대시보드 자금현황 섹션의 **입금 합계**가 입금 관리 페이지(`/accounting/deposits`)의 실제 데이터와 불일치.
| 항목 | 대시보드 summary API | 입금 관리 페이지 API | 차이 |
|------|---------------------|---------------------|------|
| 3월 입금 합계 | **200,000원** | **50,000원** (1건) | **150,000원 차이** |
| 3월 출금 합계 | 50,000원 | 50,000원 (1건) | 일치 |
---
## 자금현황 각 수치의 의미 (현재 구조)
```
현금성 자산 합계 (cash_asset_total)
= KRW 활성 계좌들의 누적 잔액 합계 (당월만이 아닌 전체 잔고)
├── 전월이월(carryover): 49,872,638원 ← 3월 이전 누적 (입금총액 - 출금총액)
├── 당월입금(income): 200,000원 ← 3월 1일~오늘 입금
├── 당월출금(expense): 50,000원 ← 3월 1일~오늘 출금
└── 잔액(balance): 50,022,638원 = 이월+입금-출금
외국환(USD) 합계 (foreign_currency_total) = USD 계좌 잔액 합계
입금 합계 = krw_totals.income (당월 KRW 입금만)
출금 합계 = krw_totals.expense (당월 KRW 출금만)
```
---
## 원인 분석
### 대시보드 summary API 쿼리 (DailyReportService.php line 77-80)
```php
$income = Deposit::where('tenant_id', $tenantId)
->where('bank_account_id', $account->id)
->whereBetween('deposit_date', [$startOfMonth, $endOfDay])
->sum('amount');
```
### 입금 관리 페이지 API 쿼리
- 별도 컨트롤러/서비스에서 조회
- 동일한 `deposits` 테이블을 읽지만, 조회 조건이 다를 수 있음
### 불일치 가능 원인
1. **soft delete 차이**: summary는 soft-deleted 레코드 포함, 목록 API는 제외
2. **tenant_id 조건 차이**: 두 API의 tenant 필터링이 다를 수 있음
3. **E2E 테스트 데이터**: 테스트가 DB에 직접 삽입한 레코드가 목록 API에서는 필터됨
4. **status 필터**: 입금 관리 목록에 status 조건이 추가되어 일부 제외
---
## 확인 필요 사항 (백엔드)
### 1. deposits 테이블 직접 조회
```sql
SELECT id, deposit_date, amount, bank_account_id, deleted_at, status
FROM deposits
WHERE tenant_id = [현재테넌트]
AND bank_account_id = 1
AND deposit_date BETWEEN '2026-03-01' AND '2026-03-03'
ORDER BY id;
```
→ 실제 레코드 수와 합계 확인 (soft delete, status 포함)
### 2. 두 API의 쿼리 조건 비교
- `DailyReportService::dailyAccounts()` — Deposit 모델 조건
- 입금 관리 컨트롤러/서비스 — Deposit 모델 조건
- 차이점 확인 (withTrashed, status 등)
### 3. 해결 방향
- 두 API가 동일한 데이터 소스를 보도록 통일
- 또는 대시보드에서 기존 입금/출금 관리 API를 재사용하여 데이터 일관성 확보

View File

@@ -1,52 +0,0 @@
# 백엔드 API 수정 요청: 당월 예상 지출 상세 - 날짜 범위 필터링
## 엔드포인트
`GET /api/v1/expected-expenses/dashboard-detail`
## 현재 상태
- `transaction_type` 파라미터만 지원 (purchase, card, bill)
- `start_date`, `end_date` 파라미터를 **무시**함
- `items` 배열이 항상 **당월(현재 월)** 기준으로만 반환됨
- `summary`도 당월 기준 고정 (total_amount, change_rate 등)
- `monthly_trend`만 여러 월 데이터 포함 (최근 7개월)
## 요청 내용
### 1. 날짜 범위 필터 지원 추가
```
GET /api/v1/expected-expenses/dashboard-detail?transaction_type=purchase&start_date=2026-01-01&end_date=2026-01-31
```
| 파라미터 | 타입 | 설명 | 기본값 |
|---------|------|------|--------|
| `start_date` | string (yyyy-MM-dd) | 조회 시작일 | 당월 1일 |
| `end_date` | string (yyyy-MM-dd) | 조회 종료일 | 당월 말일 |
| `search` | string | 거래처/항목 검색 | (없음) |
### 2. 기대 동작
- `items`: `start_date` ~ `end_date` 범위의 거래 내역만 반환
- `summary.total_amount`: 해당 기간의 합계
- `summary.change_rate`: 해당 기간 vs 직전 동일 기간 비교
- `vendor_distribution`: 해당 기간 기준 분포
- `footer_summary`: 해당 기간 기준 합계
- `monthly_trend`: 변경 불필요 (기존처럼 최근 7개월 유지)
### 3. 검색 필터 (선택)
- `search` 파라미터로 거래처명/항목명 부분 검색
## 검증 데이터
현재 `monthly_trend` 기준 데이터가 있는 월:
- 11월: 14,101,865원
- 12월: 35,241,935원
- 1월: 3,000,000원
- 2월: 1,650,000원
`start_date=2026-01-01&end_date=2026-01-31` 조회 시:
- `items`: 1월 거래 내역 (현재 빈 배열)
- `summary.total_amount`: 3,000,000 (현재 0)
## 프론트엔드 준비 상태
- 프록시: 쿼리 파라미터 정상 전달 확인
- 훅: `fetchData(cardId, { startDate, endDate, search })` 지원
- 모달: 조회 버튼 + 날짜 필터 UI 완료
- 백엔드 수정만 되면 즉시 동작

View File

@@ -1,821 +0,0 @@
# CEO Dashboard 백엔드 API 명세서
**작성일**: 2026-03-03
**기획서**: SAM_ERP_Storyboard_D1.7_260227.pdf p33~60
**프론트엔드 타입**: `src/lib/api/dashboard/types.ts`
**대상**: 백엔드 팀 (Laravel sam-api)
---
## 공통 규칙
### 응답 형식
```json
{
"success": true,
"message": "조회 성공",
"data": { ... }
}
```
### 인증
- 모든 API는 `Authorization: Bearer {access_token}` 필수
- Next.js API route 프록시(`/api/proxy/...`) 경유
### 캐싱
- `sam_stat` 테이블 5분 캐시 (기존 구현 유지)
- 대시보드 API는 실시간성보다 성능 우선
### 날짜/기간 파라미터 규칙
- 날짜: `YYYY-MM-DD` (예: `2026-03-03`)
- 월: `YYYY-MM` (예: `2026-03`)
- 분기: `year=2026&quarter=1`
- 기본값: 파라미터 미지정 시 **당월/당분기** 기준
---
## 검수 중 발견된 누락 API
### N1. 오늘의 이슈 — 과거 이력 저장 및 조회
**우선순위**: 상
**페이지**: p34
**현상**: `GET /api/v1/today-issues/summary?date=2026-02-17` 호출 시 항상 `{"items":[], "total_count":0}` 반환. 과거 이슈를 저장하는 구조가 없어서 이전 이슈 탭이 항상 빈 목록.
**요구사항**:
1. **이슈 이력 테이블** 필요 (예: `dashboard_issue_history`)
- 매일 자정(또는 배치) 시점에 당일 이슈 스냅샷 저장
- 또는 이슈 발생 시점에 이력 테이블에 INSERT
2. **기존 API 수정**: `GET /api/v1/today-issues/summary`
- `date` 파라미터가 있을 때 해당 날짜의 이력 데이터 반환
- `date` 파라미터가 없으면 기존대로 실시간 집계
**Response** (기존 `TodayIssueApiResponse`와 동일):
```json
{
"items": [
{
"id": "issue-20260302-001",
"badge": "수주",
"notification_type": "sales_order",
"content": "대한건설 수주 3건 접수",
"time": "14:30",
"date": "2026-03-02",
"path": "/ko/sales/order-management",
"needs_approval": false
}
],
"total_count": 5
}
```
**Laravel 힌트**:
- 배치 저장 방식: `App\Console\Commands\SnapshotDailyIssues` (Schedule::daily)
- 또는 이벤트 기반: 수주/채권/재고 변동 시 `dashboard_issue_history` INSERT
### N2. 자금현황 — 전일 대비 변동률 (daily_change)
**우선순위**: 중
**페이지**: p33
**현상**: `GET /api/v1/daily-report/summary` 응답에 `daily_change` 필드가 없음. 프론트엔드에서 하드코딩 fallback 값(+5.2%, +2.1%, +12.0%, -8.0%)을 사용 중.
**요구사항**:
1. **기존 API 수정**: `GET /api/v1/daily-report/summary`
2. 응답에 `daily_change` 객체 추가
3. 각 항목의 전일 대비 변동률(%) 계산 로직:
- `cash_asset_change_rate`: (오늘 현금성자산 - 어제 현금성자산) / 어제 현금성자산 × 100
- `foreign_currency_change_rate`: (오늘 외국환 - 어제 외국환) / 어제 외국환 × 100
- `income_change_rate`: (오늘 입금 - 어제 입금) / 어제 입금 × 100
- `expense_change_rate`: (오늘 지출 - 어제 지출) / 어제 지출 × 100
4. 어제 데이터 없을 시 해당 필드 `null` (프론트에서 fallback 처리)
**Response** (기존 응답에 `daily_change` 추가):
```json
{
"date": "2026-03-03",
"day_of_week": "화",
"cash_asset_total": 1250000000,
"foreign_currency_total": 85000,
"krw_totals": { "income": 45000000, "expense": 32000000, "balance": 1250000000 },
"daily_change": {
"cash_asset_change_rate": 5.2,
"foreign_currency_change_rate": 2.1,
"income_change_rate": 12.0,
"expense_change_rate": -8.0
}
}
```
**Laravel 힌트**:
- `DailyReportService`에서 전일 데이터 조회 추가
- `sam_stat` 캐시 테이블에 전일 스냅샷 있으면 활용
- 프론트 타입: `DailyChangeRate` (`src/lib/api/dashboard/types.ts:23`)
### N3. 일일일보 — daily-accounts에 입출금관리 데이터 미반영
**우선순위**: 상
**페이지**: 일일일보 페이지 (`/ko/accounting/daily-report`)
**현상**: 입금관리/출금관리에서 당일 거래를 등록하면 대시보드 자금현황(`daily-report/summary`)의 합계에는 즉시 반영되지만, 일일일보 페이지의 계좌별 상세 테이블(`daily-report/daily-accounts`)에는 표시되지 않음. (출금 테스트로 확인됨, 입금도 동일 구조로 미반영 추정)
**영향 범위**:
| 데이터 | 관리 테이블 | summary (합계) | daily-accounts (상세) |
|--------|-----------|:-:|:-:|
| 입금 | `deposits` (`/api/v1/deposits`) | ✅ 반영 추정 | ❌ 미반영 추정 |
| 출금 | `withdrawals` (`/api/v1/withdrawals`) | ✅ 반영 확인 | ❌ 미반영 확인 |
| 외국환 (USD) | 별도 관리 페이지 미확인 | ✅ 반영 | ❓ 확인 필요 |
**원인 분석**:
- `GET /api/v1/daily-report/summary``krw_totals``deposits`/`withdrawals` 테이블 데이터 포함 ✅
- `GET /api/v1/daily-report/daily-accounts``bank_accounts` 단위 집계만 반환, `deposits`/`withdrawals` 테이블 미포함 ❌
**데이터 흐름**:
```
입금관리 등록 → deposits 테이블 INSERT (bank_account_id 포함)
출금관리 등록 → withdrawals 테이블 INSERT (bank_account_id 포함)
├─ summary API → krw_totals.income/expense에 합산 → 대시보드 ✅
└─ daily-accounts API → bank_accounts 기준만 조회 → 일일일보 상세 ❌
```
**요구사항**:
1. `GET /api/v1/daily-report/daily-accounts` 수정
2. 각 계좌별로 `deposits` 테이블의 당일 income과 `withdrawals` 테이블의 당일 expense를 합산
3. 또는 입금/출금 등록 시 해당 계좌의 거래 내역(`bank_account_transactions`)에도 자동 반영
**해결 방안 (택 1)**:
- **방안 A** (daily-accounts 쿼리 수정): `bank_accounts` LEFT JOIN `deposits`/`withdrawals` WHERE date = 당일 → 계좌별 income/expense에 합산
- **방안 B** (트랜잭션 연동): 입금/출금 등록 시 `bank_account_transactions`에도 INSERT → daily-accounts가 자연스럽게 포함
**Response** (기존 `DailyAccountItemApi[]`와 동일, 데이터만 보완):
```json
[
{
"id": "acc_1",
"category": "우리은행 123-456",
"match_status": "matched",
"carryover": 50000000,
"income": 1000000,
"expense": 50000,
"balance": 50950000,
"currency": "KRW"
}
]
```
**Laravel 힌트**:
- `DailyReportService``getDailyAccounts()` 메서드 확인
- `deposits` 테이블: `deposit.bank_account_id`로 해당 계좌 income 합산
- `withdrawals` 테이블: `withdrawal.bank_account_id`로 해당 계좌 expense 합산
- USD 계좌도 동일 패턴 적용 필요
### N4. 현황판 `purchases`(발주) — path 오류 + 데이터 정합성 이슈
**우선순위**: 중
**페이지**: p34 (현황판)
#### 이슈 A: path 하드코딩 오류
**현상**: `purchases` 항목의 실제 데이터는 `purchases` 테이블(매입, 공통)에서 조회하면서, path는 건설 모듈 경로로 하드코딩되어 있음.
**문제 코드** (`StatusBoardService.php``getPurchaseStatus()`):
```php
$count = Purchase::query()
->where('tenant_id', $tenantId)
->where('status', 'draft')
->count();
return [
'id' => 'purchases',
'label' => '발주',
'path' => '/construction/order/order-management', // ← 매입 데이터인데 건설 경로
];
```
- 데이터 출처: `purchases` 테이블 (모든 테넌트 공통 매입 테이블)
- path: `/construction/order/order-management` (건설 전용 페이지)
- **데이터와 path가 불일치** — 매입 draft 건수를 보여주면서 건설 발주 페이지로 링크
**현재 프론트 임시 대응**: `status-issue.ts`에서 `/accounting/purchase`(매입관리)로 오버라이드 중
**요구사항**:
1. path를 `/accounting/purchase`로 변경 (데이터 출처와 일치시키기)
2. 또는 테넌트 업종에 따라 path 동적 분기 (건설: `/construction/order/order-management`, 기타: `/accounting/purchase`)
3. 라벨도 재검토: "발주"가 맞는지, "매입(임시저장)"이 더 정확한지
#### 이슈 B: 데이터 정합성 의심
**현상**: StatusBoard API에서 `purchases` count=**9건** 반환, 하지만 매입관리 페이지(`/accounting/purchase`)에서 전체 조회 시 **1건**만 표시.
**확인 사항** (DB 직접 확인 필요):
```sql
-- 현재 테넌트의 purchases 테이블 전체 건수
SELECT COUNT(*), status FROM purchases WHERE tenant_id = {현재 테넌트 ID} GROUP BY status;
-- draft 상태 건수 (StatusBoard가 조회하는 조건)
SELECT COUNT(*) FROM purchases WHERE tenant_id = {현재 테넌트 ID} AND status = 'draft';
```
**가능한 원인**:
1. StatusBoard와 매입관리 페이지가 다른 tenant_id 스코프로 조회
2. DummyDataSeeder가 다른 tenant_id로 데이터 생성
3. 매입관리 API에 추가 필터 조건이 있어서 draft 건이 제외됨
4. StatusBoard가 실제와 다른 데이터를 집계
**기대 결과**: StatusBoard 9건 클릭 → 매입관리 페이지에서 9건 확인 가능해야 함
---
## 신규 API (10개)
### 1. 매출 현황 Summary
**우선순위**: 중
**페이지**: p39
```
GET /api/v1/dashboard/sales/summary
```
**Query Params**:
| 파라미터 | 타입 | 필수 | 설명 |
|---------|------|------|------|
| year | int | N | 조회 연도 (기본: 당해) |
| month | int | N | 조회 월 (기본: 당월) |
**Response** (`SalesStatusApiResponse`):
```json
{
"cumulative_sales": 312300000,
"achievement_rate": 94.5,
"yoy_change": 12.5,
"monthly_sales": 312300000,
"monthly_trend": [
{ "month": "2026-08", "label": "8월", "amount": 250000000 },
{ "month": "2026-09", "label": "9월", "amount": 280000000 }
],
"client_sales": [
{ "name": "대한건설", "amount": 95000000 },
{ "name": "삼성테크", "amount": 78000000 }
],
"daily_items": [
{
"date": "2026-02-01",
"client": "대한건설",
"item": "스크린 외",
"amount": 25000000,
"status": "deposited"
}
],
"daily_total": 312300000
}
```
**Laravel 힌트**:
- 매출: `sales_orders` 합계 (confirmed 상태)
- 달성률: 매출 목표 대비 (`sales_targets` 테이블)
- YoY: 전년 동월 대비 변화율
- 거래처별: GROUP BY vendor_id → TOP 5
- status 코드: `deposited` (입금완료), `unpaid` (미입금), `partial` (부분입금)
---
### 2. 매입 현황 Summary
**우선순위**: 중
**페이지**: p40
```
GET /api/v1/dashboard/purchases/summary
```
**Query Params**:
| 파라미터 | 타입 | 필수 | 설명 |
|---------|------|------|------|
| year | int | N | 조회 연도 (기본: 당해) |
| month | int | N | 조회 월 (기본: 당월) |
**Response** (`PurchaseStatusApiResponse`):
```json
{
"cumulative_purchase": 312300000,
"unpaid_amount": 312300000,
"yoy_change": -12.5,
"monthly_trend": [
{ "month": "2026-08", "label": "8월", "amount": 180000000 }
],
"material_ratio": [
{ "name": "원자재", "value": 55, "percentage": 55, "color": "#3b82f6" },
{ "name": "부자재", "value": 35, "percentage": 35, "color": "#10b981" },
{ "name": "소모품", "value": 10, "percentage": 10, "color": "#f59e0b" }
],
"daily_items": [
{
"date": "2026-02-01",
"supplier": "한국철강",
"item": "철판 외",
"amount": 45000000,
"status": "paid"
}
],
"daily_total": 312300000
}
```
**Laravel 힌트**:
- 매입: `purchase_orders` 합계
- 미결제: 결제 미완료 건 합계
- 원자재/부자재/소모품: `item_categories` 기준 분류
- status 코드: `paid` (결제완료), `unpaid` (미결제), `partial` (부분결제)
---
### 3. 생산 현황 Summary
**우선순위**: 상
**페이지**: p41
```
GET /api/v1/dashboard/production/summary
```
**Query Params**:
| 파라미터 | 타입 | 필수 | 설명 |
|---------|------|------|------|
| date | string | N | 조회 일자 (기본: 오늘, YYYY-MM-DD) |
**Response** (`DailyProductionApiResponse`):
```json
{
"date": "2026-02-23",
"day_of_week": "월요일",
"processes": [
{
"process_name": "스크린",
"total_work": 10,
"todo": 3,
"in_progress": 4,
"completed": 3,
"urgent": 2,
"sub_line": 1,
"regular": 5,
"worker_count": 8,
"work_items": [
{
"id": "wo_1",
"order_no": "SO-2026-001",
"client": "대한건설",
"product": "스크린 A형",
"quantity": 50,
"status": "in_progress"
}
],
"workers": [
{
"name": "김철수",
"assigned": 5,
"completed": 3,
"rate": 60
}
]
}
],
"shipment": {
"expected_amount": 150000000,
"expected_count": 12,
"actual_amount": 120000000,
"actual_count": 9
}
}
```
**Laravel 힌트**:
- 공정: `work_processes` 테이블 (스크린, 슬랫, 절곡 등)
- 작업: `work_orders` JOIN `work_process_id`
- status: `pending` → todo, `in_progress`, `completed`
- urgent: 납기 3일 이내
- 출고: `shipments` 테이블 (당일 예상 vs 실적)
---
### 4. 출고 현황 (생산 현황에 포함)
**우선순위**: 하
**페이지**: p41
생산 현황 API의 `shipment` 필드로 포함됨. 별도 API 불필요.
---
### 5. 미출고 내역
**우선순위**: 하
**페이지**: p42
```
GET /api/v1/dashboard/unshipped/summary
```
**Query Params**:
| 파라미터 | 타입 | 필수 | 설명 |
|---------|------|------|------|
| days | int | N | 납기 N일 이내 (기본: 30) |
**Response** (`UnshippedApiResponse`):
```json
{
"items": [
{
"id": "us_1",
"port_no": "P-2026-001",
"site_name": "강남 현장",
"order_client": "대한건설",
"due_date": "2026-02-25",
"days_left": 2
}
],
"total_count": 7
}
```
**Laravel 힌트**:
- `shipment_items` WHERE shipped_at IS NULL AND due_date >= NOW()
- days_left: DATEDIFF(due_date, NOW())
- ORDER BY due_date ASC (납기 임박 순)
---
### 6. 시공 현황
**우선순위**: 중
**페이지**: p42
```
GET /api/v1/dashboard/construction/summary
```
**Query Params**:
| 파라미터 | 타입 | 필수 | 설명 |
|---------|------|------|------|
| month | int | N | 조회 월 (기본: 당월) |
**Response** (`ConstructionApiResponse`):
```json
{
"this_month": 15,
"completed": 5,
"items": [
{
"id": "cs_1",
"site_name": "강남 현장",
"client": "대한건설",
"start_date": "2026-02-01",
"end_date": "2026-02-28",
"progress": 85,
"status": "in_progress"
}
]
}
```
**Laravel 힌트**:
- `constructions` 테이블
- status: `in_progress`, `scheduled`, `completed`
- completed: 최근 7일 이내 완료 건
---
### 7. 근태 현황
**우선순위**: 중
**페이지**: p43
```
GET /api/v1/dashboard/attendance/summary
```
**Query Params**:
| 파라미터 | 타입 | 필수 | 설명 |
|---------|------|------|------|
| date | string | N | 조회 일자 (기본: 오늘, YYYY-MM-DD) |
**Response** (`DailyAttendanceApiResponse`):
```json
{
"present": 42,
"on_leave": 3,
"late": 1,
"absent": 0,
"employees": [
{
"id": "emp_1",
"department": "생산부",
"position": "과장",
"name": "김철수",
"status": "present"
}
]
}
```
**Laravel 힌트**:
- `attendances` WHERE date = :date
- status: `present`, `on_leave`, `late`, `absent`
- employees: 이상 상태(late, absent, on_leave) 위주 표시
---
### 8. 일별 매출 내역
**우선순위**: 하
**페이지**: p47 (설정 팝업에서 별도 ON/OFF)
매출 현황 API의 `daily_items`로 이미 포함. 별도 API 필요 시:
```
GET /api/v1/dashboard/sales/daily
```
**Query Params**:
| 파라미터 | 타입 | 필수 | 설명 |
|---------|------|------|------|
| start_date | string | N | 시작일 (기본: 당월 1일) |
| end_date | string | N | 종료일 (기본: 오늘) |
| page | int | N | 페이지 (기본: 1) |
| per_page | int | N | 건수 (기본: 20) |
---
### 9. 일별 매입 내역
**우선순위**: 하
매입 현황 API의 `daily_items`로 이미 포함. 별도 API 필요 시:
```
GET /api/v1/dashboard/purchases/daily
```
(매출 일별과 동일 구조)
---
### 10. 접대비 상세
**우선순위**: 상
**페이지**: p53-54
```
GET /api/v1/dashboard/entertainment/detail
```
**Query Params**:
| 파라미터 | 타입 | 필수 | 설명 |
|---------|------|------|------|
| year | int | N | 연도 |
| quarter | int | N | 분기 (1-4) |
| limit_type | string | N | annual/quarterly |
| company_type | string | N | large/medium/small |
**Response**:
```json
{
"summary": {
"total_used": 10000000,
"annual_limit": 40120000,
"remaining": 30120000,
"usage_rate": 24.9
},
"limit_calculation": {
"base_limit": 36000000,
"revenue_additional": 4120000,
"total_limit": 40120000,
"revenue": 2060000000,
"company_type": "medium"
},
"quarterly_status": [
{
"quarter": 1,
"label": "1분기",
"limit": 10030000,
"used": 3500000,
"remaining": 6530000,
"exceeded": 0
}
],
"transactions": [
{
"id": 1,
"date": "2026-01-15",
"user_name": "홍길동",
"merchant_name": "강남식당",
"amount": 350000,
"counterpart": "대한건설",
"receipt_type": "법인카드",
"risk_flags": ["high_amount"]
}
]
}
```
---
## 수정 API (6개)
### 1. 가지급금 Summary (수정)
**현재**: 카드/가지급금/법인세/종합세
**변경**: 카드/경조사/상품권/접대비/총합계 (5카드)
```
GET /api/proxy/card-transactions/summary
```
**Response 변경**:
```json
{
"cards": [
{ "id": "cm1", "label": "카드", "amount": 3123000, "sub_label": "미정리 5건", "count": 5 },
{ "id": "cm2", "label": "경조사", "amount": 3123000, "sub_label": "미증빙 5건", "count": 5 },
{ "id": "cm3", "label": "상품권", "amount": 3123000, "sub_label": "미증빙 5건", "count": 5 },
{ "id": "cm4", "label": "접대비", "amount": 3123000, "sub_label": "미증빙 5건", "count": 5 },
{ "id": "cm_total", "label": "총 가지급금 합계", "amount": 350000000 }
],
"check_points": [
{
"id": "cm-cp1",
"type": "warning",
"message": "법인카드 사용 총 850만원이 가지급금으로 전환되었습니다.",
"highlights": [{ "text": "850만원", "color": "red" }]
}
],
"warning_banner": "가지급금 인정이자 4.6%, 법인세 및 연말정산 시 대표자 종합세 가중 주의"
}
```
**Laravel 힌트**:
- 분류: `card_transactions.category` 기준 (card/congratulation/gift_card/entertainment)
- 미정리/미증빙: `evidence_status = 'pending'` COUNT
---
### 2. 접대비 Summary (수정)
**현재**: 매출/한도/잔여한도/사용금액
**변경**: 주말심야/기피업종/고액결제/증빙미비 (리스크 4종)
```
GET /api/proxy/entertainment/summary
```
**Response 변경**:
```json
{
"cards": [
{ "id": "et1", "label": "주말/심야", "amount": 3123000, "sub_label": "5건", "count": 5 },
{ "id": "et2", "label": "기피업종 (유흥, 귀금속 등)", "amount": 3123000, "sub_label": "불인정 5건", "count": 5 },
{ "id": "et3", "label": "고액 결제", "amount": 3123000, "sub_label": "5건", "count": 5 },
{ "id": "et4", "label": "증빙 미비", "amount": 3123000, "sub_label": "5건", "count": 5 }
],
"check_points": [...]
}
```
**리스크 감지 로직** (p60 참조):
- 주말/심야: 토~일, 22:00~06:00 거래
- 기피업종: MCC 코드 기반 (유흥업소 7273, 귀금속 5944, 골프장 7941 등)
- 고액 결제: 설정 금액(기본 50만원) 초과
- 증빙 미비: 적격증빙(세금계산서/카드매출전표) 없는 건
---
### 3. 복리후생비 Summary (수정)
**현재**: 한도/잔여한도/사용금액
**변경**: 비과세한도초과/사적사용의심/특정인편중/항목별한도초과 (리스크 4종)
```
GET /api/proxy/welfare/summary
```
**Response 변경**:
```json
{
"cards": [
{ "id": "wf1", "label": "비과세 한도 초과", "amount": 3123000, "sub_label": "5건", "count": 5 },
{ "id": "wf2", "label": "사적 사용 의심", "amount": 3123000, "sub_label": "5건", "count": 5 },
{ "id": "wf3", "label": "특정인 편중", "amount": 3123000, "sub_label": "5건", "count": 5 },
{ "id": "wf4", "label": "항목별 한도 초과", "amount": 3123000, "sub_label": "5건", "count": 5 }
],
"check_points": [...]
}
```
**리스크 감지 로직**:
- 비과세 한도 초과: 항목별 비과세 기준 초과 (식대 20만원, 교통비 10만원 등)
- 사적 사용 의심: 주말/야간 + 비업무 업종 조합
- 특정인 편중: 직원별 사용액 편차 > 평균의 200%
- 항목별 한도 초과: 설정 금액 초과
---
### 4. 가지급금 Detail (수정)
기존 `LoanDashboardApiResponse`에 AI분류 컬럼 추가.
```
GET /api/v1/loans/dashboard
```
**Response 추가 필드**:
```json
{
"items": [
{
"...기존 필드...",
"ai_category": "카드",
"evidence_status": "미증빙"
}
]
}
```
---
### 5. 복리후생비 Detail (수정)
기존 `WelfareDetailApiResponse`에 계산방식 파라미터 추가.
```
GET /api/proxy/welfare/detail?calculation_type=fixed&fixed_amount_per_month=200000
```
(기존 구현 유지, 계산 파라미터만 반영 확인)
---
### 6. 부가세 Detail (수정)
기존 `VatApiResponse`에 신고기간 파라미터 반영.
```
GET /api/proxy/vat/summary?period_type=quarter&year=2026&period=1
```
(기존 구현 유지, 기간별 필터링 확인)
---
## 리스크 감지 로직 참고 (p58-60)
### MCC 코드 기피업종
| MCC | 업종 | 분류 |
|-----|------|------|
| 7273 | 유흥업소 | 기피업종 |
| 5944 | 귀금속 | 기피업종 |
| 7941 | 골프장 | 기피업종 |
| 5813 | 주점 | 기피업종 |
| 7011 | 호텔/리조트 | 주의업종 |
### 리스크 판별 규칙
```
규칙1: 시간대 이상 → 22:00~06:00 또는 토~일
규칙2: 업종 이상 → MCC 기피업종 해당
규칙3: 금액 이상 → 설정 금액 초과 (기본 50만원)
규칙4: 빈도 이상 → 월 10회 이상 동일 업종
규칙5: 증빙 미비 → 적격증빙 없음
리스크 등급:
- 2개 이상 해당 → 🔴 고위험
- 1개 해당 → 🟡 주의
- 0개 → 🟢 정상
```
---
## 계산 공식 참고
### 가지급금 인정이자 (p58)
```
인정이자 = 가지급금잔액 × (4.6% / 365) × 경과일수
법인세 추가 = 인정이자 × 19%
대표자 소득세 = 인정이자 × 35%
```
### 접대비 손금한도 (p59)
```
기본한도:
일반법인: 1,200만원/년
중소기업: 3,600만원/년
수입금액별 추가:
100억 이하: 수입금액 × 0.2%
100~500억: 2,000만원 + (수입금액-100억) × 0.1%
500억 초과: 6,000만원 + (수입금액-500억) × 0.03%
```
### 복리후생비 (p60)
```
방식1 (정액): 직원수 × 월정액 × 12
방식2 (비율): 연봉총액 × 비율%
비과세 한도:
식대: 20만원/월
교통비: 10만원/월
경조사: 5만원/건
건강검진: 연간 총액/12 환산
교육훈련: 8만원/월
복지포인트: 10만원/월
```
---
## 우선순위 정리
| 우선순위 | API | 이유 |
|---------|-----|------|
| 🔴 상 | 접대비 summary 수정, 복리후생비 summary 수정 | D1.7 카드 구조 변경 |
| 🔴 상 | 가지급금 summary 수정 | D1.7 카드 구조 변경 |
| 🔴 상 | 접대비 detail 신규 | 모달 확장 |
| 🟡 중 | 매출 현황, 매입 현황, 시공 현황, 근태 현황 | 신규 섹션 |
| 🟡 중 | 생산 현황 | 복잡한 공정 집계 |
| 🟢 하 | 미출고 내역, 일별 매출/매입 | 단순 조회 |

Binary file not shown.

View File

@@ -1,176 +0,0 @@
# CEO Dashboard 분석 (기획서 D1.7 기준)
**기획서**: `SAM_ERP_Storyboard_D1.7_260227.pdf` p33~60
**분석일**: 2026-02-27
**상태**: 기획서 분석 완료, 구현 대기
---
## 1. 전체 구성
| 구분 | 페이지 | 수량 |
|------|--------|------|
| 메인 대시보드 섹션 | p33~43 | 20개 |
| 상세 모달 | p44~57 | 10개 |
| 참고 자료 (계산공식) | p58~60 | 3페이지 |
---
## 2. 섹션별 현황 (20개)
### API 연동 완료 (11개)
| # | 섹션 | 페이지 | hook | API endpoint |
|---|------|--------|------|-------------|
| 1 | 오늘의 이슈 | p33 | useTodayIssue | today-issues/summary |
| 2 | 자금 현황 | p33-34 | useCEODashboard | daily-report/summary |
| 3 | 현황판 | p34 | useStatusBoard | status-board/summary |
| 4 | 당월 예상 지출 | p34-35 | useMonthlyExpense | expected-expenses/summary |
| 5 | 가지급금 현황 | p35 | useCardManagement | card-transactions/summary + 2개 |
| 6 | 접대비 현황 | p35-36 | useEntertainment | entertainment/summary |
| 7 | 복리후생비 현황 | p36 | useWelfare | welfare/summary |
| 8 | 미수금 현황 | p36 | useReceivable | receivables/summary |
| 9 | 채권추심 현황 | p37 | useDebtCollection | bad-debts/summary |
| 10 | 부가세 현황 | p37-38 | useVat | vat/summary |
| 11 | 캘린더 | p38 | useCalendar | calendar/schedules |
### Mock 데이터만 (9개) - API 신규 필요
| # | 섹션 | 페이지 | 필요 데이터 |
|---|------|--------|-----------|
| 12 | 매출 현황 | p39 | 누적매출, 달성률, YoY, 당월매출 + 차트2 + 테이블 |
| 13 | 일별 매출 내역 | p47(설정) | 매출일, 거래처, 매출금액 (🆕 신규 섹션) |
| 14 | 매입 현황 | p40 | 누적매입, 미결제, YoY + 차트2 + 테이블 |
| 15 | 일별 매입 내역 | p47(설정) | 매입일, 거래처, 매입금액 (🆕 신규 섹션) |
| 16 | 생산 현황 | p41 | 공정별(스크린/슬랫/절곡) 집계 + 작업자현황 |
| 17 | 출고 현황 | p41 | 예상출고 7일/30일 금액+건수 |
| 18 | 미출고 내역 | p42 | 로트번호, 현장명, 수주처, 잔량, 납기일 |
| 19 | 시공 현황 | p42 | 진행/완료(7일이내) + 현장카드 |
| 20 | 근태 현황 | p43 | 출근/휴가/지각/결근 + 직원테이블 |
---
## 3. 🔴 D1.7 핵심 변경사항
### 카드 구조 변경 (한도관리형 → 리스크감지형)
| 섹션 | 기존 구현 | D1.7 기획서 |
|------|---------|-----------|
| **가지급금** | 카드, 가지급금, 법인세예상, 종합세예상 | 카드, 경조사, 상품권, 접대비, 총합계 (5카드) |
| **접대비** | 매출, 분기한도, 잔여한도, 사용금액 | **주말/심야, 기피업종, 고액결제, 증빙미비** |
| **복리후생비** | 당해한도, 분기한도, 잔여한도, 사용금액 | **비과세한도초과, 사적사용의심, 특정인편중, 항목별한도초과** |
### 신규 섹션 (2개)
- 일별 매출 내역: 항목 설정(p47)에서 별도 ON/OFF
- 일별 매입 내역: 항목 설정(p47)에서 별도 ON/OFF
### 설정 팝업 확장 (p45-47)
- 접대비: 한도관리(연간/반기/분기/월), 기업구분(일반법인/중소기업), 고액결제기준금액
- 복리후생비: 한도관리, 계산방식(직원당정액 or 연봉총액×비율), 조건부입력필드, 1회결제기준금액
---
## 4. 상세 모달 (10개)
| # | 모달 | 페이지 | 프론트 config | API 상태 |
|---|------|--------|-------------|---------|
| 1 | 일정 상세 | p44 | ✅ ScheduleDetailModal | ✅ 연동 |
| 2 | 항목 설정 | p45-47 | ✅ DashboardSettingsDialog | localStorage |
| 3 | 당월 매입 상세 | p48 | ✅ me1 config | ⚠️ 부분연동 |
| 4 | 당월 카드 상세 | p49 | ✅ me2 config | ⚠️ 부분연동 |
| 5 | 당월 발행어음 상세 | p50 | ✅ me3 config | ⚠️ 부분연동 |
| 6 | 당월 지출 예상 상세 | p51 | ✅ me4 config | ⚠️ 부분연동 |
| 7 | 가지급금 상세 | p52 | ✅ cm2 config | ⚠️ 구조변경 필요 |
| 8 | 접대비 상세 | p53-54 | ✅ et config | ⚠️ 대폭확장 |
| 9 | 복리후생비 상세 | p55-56 | ✅ wf config | ⚠️ 대폭확장 |
| 10 | 예상 납부세액 상세 | p57 | ✅ vat config | ⚠️ 확장필요 |
---
## 5. 필요 API 작업 (16개)
### 백엔드 API 수정 (6개)
| # | API | 변경 내용 |
|---|-----|---------|
| 1 | 가지급금 summary | 카드/경조사/상품권/접대비 분류 집계 |
| 2 | 접대비 summary | 리스크 4종 (주말심야/기피업종/고액/증빙미비) - MCC코드 판별 |
| 3 | 복리후생비 summary | 리스크 4종 (비과세초과/사적사용/편중/한도초과) |
| 4 | 가지급금 detail | 분류별 상세 + AI분류 컬럼 |
| 5 | 복리후생비 detail | 계산방식별 + 분기별현황 |
| 6 | 부가세 detail | 신고기간별 + 부가세요약 + 미발행/미수취 |
### 백엔드 API 신규 (10개)
| # | API | 용도 | 난이도 |
|---|-----|------|--------|
| 1 | 접대비 detail | 한도계산 + 분기별현황 + 내역테이블 | 상 |
| 2 | 매출 현황 summary | 누적/달성률/YoY/당월 + 차트 | 중 |
| 3 | 일별 매출 내역 | 매출일, 거래처, 매출금액 | 하 |
| 4 | 매입 현황 summary | 누적/미결제/YoY + 차트 | 중 |
| 5 | 일별 매입 내역 | 매입일, 거래처, 매입금액 | 하 |
| 6 | 생산 현황 | 공정별 집계 + 작업자실적 | 상 |
| 7 | 출고 현황 | 7일/30일 예상출고 | 하 |
| 8 | 미출고 내역 | 납기기준 미출고 조회 | 하 |
| 9 | 시공 현황 | 진행/완료(7일이내) + 카드 | 중 |
| 10 | 근태 현황 | 출근/휴가/지각/결근 집계 | 중 |
---
## 6. 프론트엔드 작업 (8개)
| # | 작업 | 대상 |
|---|------|------|
| 1 | 가지급금 카드 구조 변경 | CardManagementSection |
| 2 | 접대비 카드 → 리스크형 | EntertainmentSection |
| 3 | 복리후생비 카드 → 리스크형 | WelfareSection |
| 4 | 일별 매출 내역 섹션 신규 | 새 컴포넌트 |
| 5 | 일별 매입 내역 섹션 신규 | 새 컴포넌트 |
| 6 | 항목 설정 팝업 업데이트 | DashboardSettingsDialog |
| 7 | 모달 config API 연동 | 각 modalConfigs |
| 8 | Mock 섹션 API 연동 | 매출~근태 hook 생성 |
---
## 7. 데이터 아키텍처
대시보드 전용 테이블 없음. 모든 데이터는 각 도메인 페이지 입력 데이터의 실시간 집계.
### 자금 현황 데이터 조합
| 카드 | 출처 |
|------|------|
| 일일일보 | bank_accounts 잔액 합계 |
| 미수금 잔액 | sales 합계 - deposits 합계 |
| 미지급금 잔액 | purchases 합계 - payments 합계 |
| 당월 예상 지출 | 매입예정 + 카드결제 + 어음만기 합산 |
### 리스크 감지 로직 (접대비/복리후생비)
- MCC 코드 기반 업종 판별 (p60: 유흥업소, 귀금속, 골프장 등)
- 체크 규칙: 시간대이상(22~06시), 업종이상, 금액이상(50만원), 빈도이상(월10회)
- 사적사용 의심: 토요일 23시 + 유흥주점 + 25만원 → 2개 규칙 해당
### 캐싱
- sam_stat 테이블 5분 캐시 (백엔드 기존 구현)
---
## 8. 참고 계산 공식 (p58-60)
### 가지급금 인정이자
- 인정이자율: 4.6% (당좌대출이자율 기준, 매년 고시)
- 인정이자 = 가지급금 × 일이자율(연이자율/365) × 경과일수
- 법인세 추가: 인정이자 × 0.19
- 대표자 소득세 추가: 인정이자 × 0.35
### 접대비 손금한도
- 기본한도: 일반법인 1,200만원/년, 중소기업 3,600만원/년
- 수입금액별 추가한도:
- 100억 이하: 수입금액 × 0.2%
- 100억~500억: 2,000만원 + (수입금액-100억) × 0.1%
- 500억 초과: 6,000만원 + (수입금액-500억) × 0.03%
### 복리후생비 계산
- 방식1 (직원당 정액): 직원수 × 월정액 × 12
- 방식2 (연봉총액 비율): 연봉총액 × 비율%
- 법정 복리후생비: 4대보험 회사부담분
- 비과세 항목별 기준: 식대 20만원, 교통비 10만원, 경조사 5만원, 건강검진 월환산, 교육훈련 8만원, 복지포인트 10만원

View File

@@ -68,7 +68,7 @@ function transformDetailApiToFrontend(data: ApiProductionOrderDetail): Productio
id: item.id,
itemCode: item.item_code,
itemName: item.item_name,
spec: item.spec || item.specification || '',
spec: item.spec || '',
unit: item.unit || '',
quantity: item.quantity ?? 0,
unitPrice: item.unit_price ?? 0,

View File

@@ -19,6 +19,7 @@ import { executeServerAction } from '@/lib/api/execute-server-action';
import { buildApiUrl } from '@/lib/api/query-params';
import type {
ProductInspection,
ProductInspectionData,
InspectionStats,
InspectionStatus,
InspectionCalendarItem,
@@ -100,6 +101,8 @@ interface ProductInspectionApi {
construction_width: number;
construction_height: number;
change_reason: string;
document_id?: number | null;
inspection_data?: Record<string, unknown>;
}>;
request_document_id: number | null;
created_at: string;
@@ -252,7 +255,7 @@ function transformApiToFrontend(api: ProductInspectionApi): ProductInspection {
constructionHeight: item.construction_height,
changeReason: item.change_reason,
documentId: item.document_id ?? null,
inspectionData: item.inspection_data || undefined,
inspectionData: item.inspection_data ? item.inspection_data as unknown as ProductInspectionData : undefined,
})),
requestDocumentId: api.request_document_id ?? null,
};
@@ -616,7 +619,7 @@ export async function updateInspection(
export async function saveLocationInspection(
docId: string,
locationId: string,
inspectionData: Record<string, unknown>,
inspectionData: ProductInspectionData,
constructionInfo?: {
width: number | null;
height: number | null;