docs:카드/차량관리 개발문서 추가 (5개 메뉴)
- 법인카드관리: 카드 CRUD, 결제일 휴일조정, 사용금액 집계, 선불결제 - 카드사용내역: 바로빌 SOAP 연동, 분개, 거래숨김, 금액수정 - 차량목록: 법인/렌트/리스 차량 등록, 주행거리 자동계산 - 차량일지: 운행기록, 용도별 통계, 출발↔도착 교환 - 정비이력: 카테고리별 비용 관리, 주행거리 자동갱신 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
117
features/card-vehicle/README.md
Normal file
117
features/card-vehicle/README.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# 카드/차량관리 기능
|
||||
|
||||
## 개요
|
||||
|
||||
SAM 프로젝트의 카드/차량관리 모듈은 법인카드 관리, 카드 사용내역 조회, 차량 관리, 운행일지, 정비이력을 종합적으로 관리하는 시스템입니다.
|
||||
바로빌 API 연동을 통한 카드거래 자동 수집, 카드별 사용금액 집계, 차량 운행/정비 기록 관리 기능을 제공합니다.
|
||||
|
||||
## 메뉴 구성
|
||||
|
||||
| 메뉴 | 경로 | 설명 | UI 기술 |
|
||||
|------|------|------|---------|
|
||||
| [법인카드관리](./corporate-cards.md) | `/finance/corporate-cards` | 법인카드 등록/조회, 요약 대시보드 | React 18 |
|
||||
| [카드사용내역](./card-transactions.md) | `/finance/card-transactions` | 바로빌 연동 카드거래 조회 및 회계 분류 | React 18 |
|
||||
| [차량목록](./corporate-vehicles.md) | `/finance/corporate-vehicles` | 법인/렌트/리스 차량 등록 관리 | React 18 |
|
||||
| [차량일지](./vehicle-logs.md) | `/finance/vehicle-logs` | 차량 운행기록 관리 | React 18 |
|
||||
| [정비이력](./vehicle-maintenance.md) | `/finance/vehicle-maintenance` | 차량 정비/주유/보험 등 비용 관리 | React 18 |
|
||||
|
||||
## 아키텍처
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────────────────────────────┐
|
||||
│ 카드/차량관리 모듈 │
|
||||
├──────────────────────┬────────────────────────────────────────┤
|
||||
│ 카드 관리 영역 │ 차량 관리 영역 │
|
||||
│ │ │
|
||||
│ ┌────────────────┐ │ ┌──────────┐ ┌────────┐ ┌────────┐ │
|
||||
│ │ 법인카드관리 │ │ │ 차량목록 │ │ 차량일지 │ │ 정비이력│ │
|
||||
│ │ (카드 CRUD) │ │ │(차량CRUD)│ │(운행기록)│ │(비용기록)│ │
|
||||
│ └───────┬────────┘ │ └────┬─────┘ └────┬───┘ └───┬────┘ │
|
||||
│ │ │ │ │ │ │
|
||||
│ ┌───────▼────────┐ │ └──────────────┼──────────┘ │
|
||||
│ │ 카드사용내역 │ │ │ │
|
||||
│ │(바로빌 연동) │ │ │ │
|
||||
│ └───────┬────────┘ │ │ │
|
||||
├──────────┼───────────┴──────────────────────┼─────────────────┤
|
||||
│ ▼ ▼ │
|
||||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||||
│ │ 데이터베이스 │ │
|
||||
│ │ corporate_cards, card_transactions, │ │
|
||||
│ │ barobill_card_transactions, corporate_card_prepayments │ │
|
||||
│ │ corporate_vehicles, vehicle_logs, vehicle_maintenances │ │
|
||||
│ └──────────────────────────────────────────────────────────┘ │
|
||||
└───────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 주요 기술 스택
|
||||
|
||||
| 기술 | 용도 |
|
||||
|------|------|
|
||||
| Laravel 11 (PHP 8.3) | 백엔드 프레임워크 |
|
||||
| React 18 + Babel | 클라이언트 렌더링 UI (전 페이지) |
|
||||
| Tailwind CSS + Lucide | 스타일링 및 아이콘 |
|
||||
| Barobill SOAP API | 카드거래 실시간 연동 |
|
||||
| MySQL 8.0 | 데이터 저장 |
|
||||
|
||||
## 데이터 흐름
|
||||
|
||||
```
|
||||
바로빌 SOAP API ──────────────────────────────┐
|
||||
(CARD.asmx: 카드거래 자동 수집) │
|
||||
▼
|
||||
카드 관리: corporate_cards ← 매칭 → barobill_card_transactions
|
||||
(카드번호 하이픈 제거 후 매칭)
|
||||
│
|
||||
├── barobill_card_transaction_splits (분개)
|
||||
├── barobill_card_transaction_hides (숨김)
|
||||
├── barobill_card_transaction_amount_logs (수정이력)
|
||||
└── corporate_card_prepayments (선불결제)
|
||||
|
||||
차량 관리: corporate_vehicles
|
||||
│
|
||||
├── vehicle_logs (운행기록 → distance_km 합산)
|
||||
└── vehicle_maintenances (정비기록 → mileage 갱신)
|
||||
```
|
||||
|
||||
## 공통 모델/패턴
|
||||
|
||||
### 멀티 테넌트
|
||||
|
||||
모든 테이블은 `tenant_id` 기반으로 데이터를 격리합니다.
|
||||
|
||||
### React 18 + Babel
|
||||
|
||||
모든 페이지는 브라우저 트랜스파일링 방식의 React 18을 사용합니다:
|
||||
- `@push('scripts')` 블록에 React/Babel/Lucide 스크립트 포함
|
||||
- `@verbatim` + `<script type="text/babel">` 패턴
|
||||
- HTMX 네비게이션 시 HX-Redirect 필수 (전체 페이지 리로드)
|
||||
|
||||
### 카드번호 매칭 로직
|
||||
|
||||
```
|
||||
corporate_cards.card_number ←매칭→ barobill_card_transactions.card_num
|
||||
(예: "9438-8309-3638-4247") (예: "9438830936384247")
|
||||
→ 하이픈 제거 후 매칭: str_replace('-', '', $cardNumber)
|
||||
```
|
||||
|
||||
## 데이터베이스 테이블 요약
|
||||
|
||||
### 카드 관련
|
||||
|
||||
| 테이블 | 역할 |
|
||||
|--------|------|
|
||||
| `corporate_cards` | 법인카드 정보 (카드명, 카드사, 번호, 한도 등) |
|
||||
| `corporate_card_prepayments` | 월별 선불결제 금액 |
|
||||
| `card_transactions` | 수동 입력 카드거래 |
|
||||
| `barobill_card_transactions` | 바로빌 자동 수집 카드거래 |
|
||||
| `barobill_card_transaction_splits` | 카드거래 분개 (1거래→N계정과목) |
|
||||
| `barobill_card_transaction_hides` | 거래 숨김 처리 |
|
||||
| `barobill_card_transaction_amount_logs` | 거래 금액 수정 이력 |
|
||||
|
||||
### 차량 관련
|
||||
|
||||
| 테이블 | 역할 |
|
||||
|--------|------|
|
||||
| `corporate_vehicles` | 법인/렌트/리스 차량 정보 |
|
||||
| `vehicle_logs` | 차량 운행기록 (출발/도착, 거리, 용도) |
|
||||
| `vehicle_maintenances` | 정비/주유/보험 등 비용 기록 |
|
||||
311
features/card-vehicle/card-transactions.md
Normal file
311
features/card-vehicle/card-transactions.md
Normal file
@@ -0,0 +1,311 @@
|
||||
# 카드사용내역
|
||||
|
||||
## 개요
|
||||
|
||||
카드사용내역은 바로빌 SOAP API를 통해 카드사 거래내역을 실시간 조회하고,
|
||||
회계 분류(계정과목 지정), 분개(1거래→N계정과목), 거래 숨김, 금액 수정, 수동 거래 등록 등을 지원하는 기능입니다.
|
||||
|
||||
- **라우트**: `GET /finance/card-transactions` → 바로빌 EcardController로 리다이렉트
|
||||
- **실제 페이지**: `GET /barobill/ecard`
|
||||
- **UI 기술**: React 18 + Babel (브라우저 트랜스파일링)
|
||||
|
||||
## 파일 구조
|
||||
|
||||
```
|
||||
mng/
|
||||
├── app/Http/Controllers/
|
||||
│ ├── Barobill/
|
||||
│ │ └── EcardController.php # 메인 컨트롤러 (바로빌 연동)
|
||||
│ └── Finance/
|
||||
│ └── CardTransactionController.php # 수동 거래내역 컨트롤러
|
||||
├── app/Models/Barobill/
|
||||
│ ├── CardTransaction.php # 바로빌 카드거래 모델
|
||||
│ ├── CardTransactionSplit.php # 거래 분개 모델
|
||||
│ ├── CardTransactionHide.php # 거래 숨김 모델
|
||||
│ └── CardTransactionAmountLog.php # 금액 수정 이력 모델
|
||||
├── app/Models/Finance/
|
||||
│ └── CardTransaction.php # 수동 입력 거래 모델
|
||||
└── resources/views/
|
||||
├── barobill/ecard/
|
||||
│ └── index.blade.php # 바로빌 카드거래 React 페이지
|
||||
└── finance/
|
||||
└── card-transactions.blade.php # 수동 거래내역 React 페이지
|
||||
|
||||
api/
|
||||
└── database/migrations/
|
||||
├── 2026_01_23_150000_create_barobill_card_transactions_table.php
|
||||
├── 2026_01_23_160000_create_barobill_card_transaction_splits_table.php
|
||||
├── 2026_02_05_100003_create_card_transactions_table.php
|
||||
├── 2026_02_05_200100_create_barobill_card_transaction_amount_logs_table.php
|
||||
└── 2026_02_05_500000_create_barobill_card_transaction_hides_table.php
|
||||
```
|
||||
|
||||
## 라우트
|
||||
|
||||
### 바로빌 카드거래 (메인)
|
||||
|
||||
```php
|
||||
// routes/web.php (barobill/ecard prefix)
|
||||
GET / → index() React 페이지 렌더링
|
||||
GET /cards → cards() 등록된 카드 목록
|
||||
GET /transactions → transactions() 거래내역 조회 (API+DB 병합)
|
||||
GET /account-codes → accountCodes() 계정과목 목록
|
||||
POST /save → save() 거래 저장 (회계 분류)
|
||||
POST /export → exportExcel() Excel 내보내기
|
||||
GET /splits → splits() 분개 내역 조회
|
||||
POST /splits → saveSplits() 분개 저장
|
||||
DELETE /splits → deleteSplits() 분개 삭제
|
||||
POST /manual → storeManual() 수동 거래 등록
|
||||
PUT /manual/{id} → updateManual() 수동 거래 수정
|
||||
DELETE /manual/{id} → destroyManual() 수동 거래 삭제
|
||||
POST /hide → hideTransaction() 거래 숨김
|
||||
POST /restore → restoreTransaction() 거래 숨김 해제
|
||||
GET /hidden → hiddenTransactions() 숨긴 거래 목록
|
||||
```
|
||||
|
||||
### 수동 거래내역 (보조)
|
||||
|
||||
```php
|
||||
// routes/web.php (card-transactions prefix)
|
||||
GET /list → index() 수동 거래 목록
|
||||
POST /store → store() 수동 거래 등록
|
||||
PUT /{id} → update() 수동 거래 수정
|
||||
DELETE /{id} → destroy() 수동 거래 삭제
|
||||
```
|
||||
|
||||
## 컨트롤러
|
||||
|
||||
### EcardController (바로빌 카드거래)
|
||||
|
||||
| 메서드 | HTTP | 설명 |
|
||||
|--------|------|------|
|
||||
| `index()` | GET | React 페이지 렌더링 (HX-Redirect 적용) |
|
||||
| `cards()` | GET | 바로빌 등록 카드 목록 (SOAP API) |
|
||||
| `transactions()` | GET | **거래내역 조회** (API + DB 병합) |
|
||||
| `accountCodes()` | GET | 계정과목 목록 |
|
||||
| `save()` | POST | 거래 저장 (계정과목 지정) |
|
||||
| `exportExcel()` | POST | Excel 내보내기 |
|
||||
| `splits()` | GET | 분개 내역 조회 |
|
||||
| `saveSplits()` | POST | 분개 저장 |
|
||||
| `deleteSplits()` | DELETE | 분개 삭제 |
|
||||
| `storeManual()` | POST | 수동 거래 등록 |
|
||||
| `updateManual()` | PUT | 수동 거래 수정 |
|
||||
| `destroyManual()` | DELETE | 수동 거래 삭제 |
|
||||
| `hideTransaction()` | POST | 거래 숨김 처리 |
|
||||
| `restoreTransaction()` | POST | 거래 숨김 해제 |
|
||||
| `hiddenTransactions()` | GET | 숨긴 거래 목록 |
|
||||
|
||||
### CardTransactionController (수동 거래)
|
||||
|
||||
| 메서드 | HTTP | 설명 |
|
||||
|--------|------|------|
|
||||
| `index()` | GET | 수동 거래 목록 (필터, 통계 포함) |
|
||||
| `store()` | POST | 거래 등록 |
|
||||
| `update()` | PUT | 거래 수정 |
|
||||
| `destroy()` | DELETE | 거래 삭제 (Soft Delete) |
|
||||
|
||||
## 바로빌 SOAP API 연동
|
||||
|
||||
### 사용 SOAP 메서드
|
||||
|
||||
| WSDL | 메서드 | 기능 |
|
||||
|------|--------|------|
|
||||
| CARD.asmx | `GetRegisteredCard` | 등록된 카드 목록 조회 |
|
||||
| CARD.asmx | `GetPeriodCardLog` | 기간별 카드거래 내역 조회 |
|
||||
|
||||
### 테넌트별 서버 모드
|
||||
|
||||
```
|
||||
BarobillMember.server_mode → 'test' 또는 'production'
|
||||
→ BarobillConfig 재로드 → SOAP 클라이언트 재초기화
|
||||
```
|
||||
|
||||
## 핵심 로직
|
||||
|
||||
### 거래내역 조회 흐름 (transactions)
|
||||
|
||||
```
|
||||
React 컴포넌트 (카드/기간 선택)
|
||||
↓
|
||||
GET /barobill/ecard/transactions
|
||||
↓
|
||||
1. BarobillMember 조회 (바로빌 인증 정보)
|
||||
↓
|
||||
2. 테넌트별 서버 모드 적용 (test/production)
|
||||
↓
|
||||
3. SOAP 호출: GetPeriodCardLog (바로빌 API)
|
||||
↓
|
||||
4. DB 저장된 거래와 병합 (barobill_card_transactions)
|
||||
↓
|
||||
5. 숨긴 거래 표시 (barobill_card_transaction_hides)
|
||||
↓
|
||||
6. 분개 데이터 병합 (barobill_card_transaction_splits)
|
||||
↓
|
||||
7. 수동 거래 병합
|
||||
↓
|
||||
8. 정렬 + JSON 응답
|
||||
```
|
||||
|
||||
### 거래 고유 키 (unique_key)
|
||||
|
||||
```php
|
||||
// CardTransaction (Barobill) 모델
|
||||
return implode('|', [
|
||||
$this->card_num,
|
||||
$this->use_dt, // 사용일시
|
||||
$this->approval_num,
|
||||
$this->approval_amount,
|
||||
]);
|
||||
```
|
||||
|
||||
### 거래 금액 처리
|
||||
|
||||
```
|
||||
approval_type = '1' → 승인 (+ 금액)
|
||||
approval_type = '2' → 취소 (- 금액)
|
||||
|
||||
modified_supply_amount, modified_tax → 금액 수정 시 원본 대신 사용
|
||||
```
|
||||
|
||||
### 분개 저장 흐름
|
||||
|
||||
```
|
||||
React (분개 모달)
|
||||
↓
|
||||
POST /barobill/ecard/splits
|
||||
{
|
||||
originalUniqueKey: "카드번호|사용일시|승인번호|금액",
|
||||
originalData: { cardNum, useDt, ... },
|
||||
splits: [
|
||||
{ amount: 50000, accountCode: "1000", accountName: "당좌예금" },
|
||||
{ amount: 50000, accountCode: "2000", accountName: "미수금" }
|
||||
]
|
||||
}
|
||||
↓
|
||||
기존 분개 삭제 → 새 분개 생성 × N
|
||||
```
|
||||
|
||||
## 모델
|
||||
|
||||
### CardTransaction (Barobill)
|
||||
|
||||
**테이블**: `barobill_card_transactions`
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
|------|------|------|
|
||||
| `tenant_id` | bigint | 테넌트 ID |
|
||||
| `card_num` | string | 카드번호 (하이픈 없음) |
|
||||
| `card_company` / `card_company_name` | string | 카드사 코드/명 |
|
||||
| `use_dt` | string | 사용일시 (YYYYMMDDHHMMSS) |
|
||||
| `use_date` / `use_time` | string | 사용일/시간 분리 |
|
||||
| `approval_num` | string | 승인번호 |
|
||||
| `approval_type` | string | 1=승인, 2=취소 |
|
||||
| `approval_amount` | decimal | 승인금액 |
|
||||
| `tax` / `service_charge` | decimal | 세금/봉사료 |
|
||||
| `merchant_name` / `merchant_biz_num` | string | 가맹점명/사업자번호 |
|
||||
| `account_code` / `account_name` | string | 계정과목 코드/명 |
|
||||
| `modified_supply_amount` / `modified_tax` | decimal | 수정 공급가/세액 |
|
||||
| `is_manual` | boolean | 수동 입력 여부 |
|
||||
|
||||
- **Unique Index**: `[tenant_id, card_num, use_dt, approval_num, approval_amount]`
|
||||
|
||||
### CardTransactionSplit
|
||||
|
||||
**테이블**: `barobill_card_transaction_splits`
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
|------|------|------|
|
||||
| `original_unique_key` | string(200) | 원본 거래 고유 키 |
|
||||
| `split_amount` | decimal | 분개 금액 |
|
||||
| `split_supply_amount` / `split_tax` | decimal | 공급가/세액 |
|
||||
| `account_code` / `account_name` | string | 계정과목 |
|
||||
| `deduction_type` / `evidence_name` | string | 공제구분/증빙명 |
|
||||
| `sort_order` | int | 정렬 순서 |
|
||||
|
||||
### CardTransactionHide
|
||||
|
||||
**테이블**: `barobill_card_transaction_hides`
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
|------|------|------|
|
||||
| `original_unique_key` | string | 거래 고유 키 |
|
||||
| `card_num` / `use_date` / `approval_num` | string | 원본 거래 정보 |
|
||||
| `original_amount` / `merchant_name` | string | 원본 금액/가맹점 |
|
||||
| `hidden_by` | bigint | 숨김 처리 사용자 |
|
||||
|
||||
### CardTransactionAmountLog
|
||||
|
||||
**테이블**: `barobill_card_transaction_amount_logs`
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
|------|------|------|
|
||||
| `card_transaction_id` | bigint | 카드거래 FK |
|
||||
| `before_supply_amount` / `before_tax` | decimal | 수정 전 금액 |
|
||||
| `after_supply_amount` / `after_tax` | decimal | 수정 후 금액 |
|
||||
| `modified_by` / `modified_by_name` | string | 수정자 |
|
||||
| `ip_address` | string | 수정 IP |
|
||||
|
||||
### CardTransaction (Finance - 수동)
|
||||
|
||||
**테이블**: `card_transactions`
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
|------|------|------|
|
||||
| `tenant_id` | bigint | 테넌트 ID |
|
||||
| `card_id` | bigint | 법인카드 FK |
|
||||
| `transaction_date` | date | 거래일 |
|
||||
| `time` | string | 거래시간 (HH:MM) |
|
||||
| `merchant` | string(200) | 가맹점명 |
|
||||
| `category` | string | 카테고리 |
|
||||
| `amount` | bigint | 금액 |
|
||||
| `approval_no` | string | 승인번호 |
|
||||
| `status` | enum | approved / cancelled |
|
||||
|
||||
## 뷰 구성 (React)
|
||||
|
||||
### card-transactions.blade.php (수동 거래)
|
||||
|
||||
```
|
||||
┌─ 페이지 헤더 ──────────────────────
|
||||
│ Excel 내보내기 | 거래 추가 버튼
|
||||
│
|
||||
├─ 통계 카드 (4열) ──────────────────
|
||||
│ 조회 건수 | 총 사용금액 | 승인 금액 | 취소 금액
|
||||
│
|
||||
├─ 카테고리 사용현황 (수평 바) ──────
|
||||
│ 식비 | 교통비 | 접대비 | ... (금액 순 정렬)
|
||||
│
|
||||
├─ 필터 영역 ────────────────────────
|
||||
│ 검색 | 카드 선택 | 카테고리 | 기간 | 상태(전체/승인/취소)
|
||||
│
|
||||
├─ 거래 목록 (날짜별 그룹) ──────────
|
||||
│ 날짜 헤더 (건수, 소계)
|
||||
│ ├─ 가맹점명 + 카테고리 아이콘
|
||||
│ ├─ 시간, 카드명, 카테고리라벨
|
||||
│ ├─ 금액 (승인=빨강, 취소=파랑)
|
||||
│ └─ 수정/삭제 버튼
|
||||
│
|
||||
└─ 등록/수정 모달
|
||||
카드, 날짜, 시간, 가맹점명, 카테고리
|
||||
금액, 승인번호, 상태, 메모
|
||||
```
|
||||
|
||||
### 카테고리 목록
|
||||
|
||||
| 카테고리 | 아이콘 | 색상 |
|
||||
|---------|--------|------|
|
||||
| 식비 | Utensils | amber |
|
||||
| 교통비 | Car | blue |
|
||||
| 운영비 | Settings | gray |
|
||||
| 마케팅비 | Megaphone | purple |
|
||||
| 사무용품 | Paperclip | teal |
|
||||
| 도서/교육 | BookOpen | indigo |
|
||||
| 접대비 | Wine | rose |
|
||||
| 장비구매 | Monitor | cyan |
|
||||
| 기타 | MoreHorizontal | gray |
|
||||
|
||||
## HTMX 호환성
|
||||
|
||||
- React 기반 페이지이므로 **HX-Redirect 필요**
|
||||
- `@push('scripts')` 블록에 React/Babel 스크립트 포함
|
||||
- HTMX 네비게이션 시 전체 페이지 리로드 필수
|
||||
222
features/card-vehicle/corporate-cards.md
Normal file
222
features/card-vehicle/corporate-cards.md
Normal file
@@ -0,0 +1,222 @@
|
||||
# 법인카드관리
|
||||
|
||||
## 개요
|
||||
|
||||
법인카드관리는 회사의 법인카드(신용/체크)를 등록하고 관리하는 기능입니다.
|
||||
카드 CRUD, 결제일 휴일 조정, 바로빌 기반 사용금액 집계, 선불결제 관리 등을 지원합니다.
|
||||
|
||||
- **라우트**: `GET /finance/corporate-cards`
|
||||
- **라우트 이름**: `finance.corporate-cards`
|
||||
- **UI 기술**: React 18 + Babel (브라우저 트랜스파일링)
|
||||
|
||||
## 파일 구조
|
||||
|
||||
```
|
||||
mng/
|
||||
├── app/Http/Controllers/Finance/
|
||||
│ └── CorporateCardController.php # 메인 컨트롤러 (7개 메서드)
|
||||
├── app/Models/Finance/
|
||||
│ ├── CorporateCard.php # 법인카드 모델
|
||||
│ └── CorporateCardPrepayment.php # 선불결제 모델
|
||||
├── app/Models/Barobill/
|
||||
│ ├── CardTransaction.php # 바로빌 카드거래 모델
|
||||
│ └── CardTransactionHide.php # 거래 숨김 모델
|
||||
├── app/Models/System/
|
||||
│ └── Holiday.php # 휴일 모델
|
||||
└── resources/views/finance/
|
||||
└── corporate-cards.blade.php # React 기반 단일 페이지
|
||||
|
||||
api/
|
||||
└── database/migrations/
|
||||
├── 2026_01_30_180000_create_corporate_cards_table.php
|
||||
└── 2026_02_11_100000_create_corporate_card_prepayments_table.php
|
||||
```
|
||||
|
||||
## 라우트
|
||||
|
||||
```php
|
||||
// routes/web.php (finance prefix 그룹 내)
|
||||
Route::get('/corporate-cards', fn() => ...)->name('corporate-cards');
|
||||
|
||||
// API 라우트 (corporate-cards prefix)
|
||||
GET /list → index() 카드 목록 조회
|
||||
GET /summary → summary() 요약 데이터 (결제일, 사용금액 등)
|
||||
POST /prepayment → updatePrepayment() 선불결제 수정
|
||||
POST /store → store() 카드 등록
|
||||
PUT /{id} → update() 카드 수정
|
||||
POST /{id}/deactivate → deactivate() 카드 비활성화
|
||||
DELETE /{id} → destroy() 카드 영구삭제
|
||||
```
|
||||
|
||||
## 컨트롤러
|
||||
|
||||
### CorporateCardController
|
||||
|
||||
| 메서드 | HTTP | 설명 |
|
||||
|--------|------|------|
|
||||
| `index()` | GET | 카드 목록 JSON 반환 |
|
||||
| `store()` | POST | 카드 등록 |
|
||||
| `update()` | PUT | 카드 수정 |
|
||||
| `deactivate()` | POST | 비활성화 (status → inactive) |
|
||||
| `destroy()` | DELETE | 영구삭제 (forceDelete) |
|
||||
| `summary()` | GET | **요약 데이터** (결제일, 사용금액, 선불결제) |
|
||||
| `updatePrepayment()` | POST | 선불결제 금액 수정 (upsert) |
|
||||
|
||||
### summary() 응답 구조
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"paymentDate": "2026-02-19",
|
||||
"paymentDay": 15,
|
||||
"originalDate": "2026-02-15",
|
||||
"isAdjusted": true,
|
||||
"billingPeriod": { "start": "2026-01-01", "end": "2026-02-19" },
|
||||
"billingUsage": 3500000,
|
||||
"cardUsages": { "9438830936384247": 1200000, "1234567890123456": 2300000 },
|
||||
"prepaidAmount": 500000,
|
||||
"prepaidMemo": "2월 선결제"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 핵심 로직
|
||||
|
||||
### 휴일 조정 결제일 계산 (getAdjustedPaymentDate)
|
||||
|
||||
```
|
||||
당월 payment_day (예: 15일)
|
||||
↓
|
||||
Carbon 날짜 생성
|
||||
↓
|
||||
holidays 테이블에서 해당 기간 휴일 조회
|
||||
↓
|
||||
토/일/공휴일이면 다음 날로 반복 이동
|
||||
↓
|
||||
영업일 결제일 반환 (예: 15일→토→17일(월))
|
||||
```
|
||||
|
||||
### 사용금액 계산 (calculateBillingUsage)
|
||||
|
||||
```
|
||||
청구기간: 전월 1일 ~ 당월 결제일(휴일조정)
|
||||
↓
|
||||
corporate_cards에서 활성 카드번호 수집
|
||||
↓
|
||||
카드번호 정규화 (하이픈 제거)
|
||||
↓
|
||||
barobill_card_transactions 조회 (use_date 범위)
|
||||
↓
|
||||
숨긴 거래 제외 (barobill_card_transaction_hides)
|
||||
↓
|
||||
approval_type별 합산:
|
||||
- '1' (승인): + approval_amount
|
||||
- '2' (취소): - approval_amount
|
||||
↓
|
||||
총 사용금액 반환
|
||||
```
|
||||
|
||||
### 잔여 한도 계산
|
||||
|
||||
```
|
||||
잔여 한도 = 총 한도 - 사용금액 + 선불결제
|
||||
```
|
||||
|
||||
## 모델
|
||||
|
||||
### CorporateCard
|
||||
|
||||
**테이블**: `corporate_cards`
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
|------|------|------|
|
||||
| `tenant_id` | bigint | 테넌트 ID |
|
||||
| `card_name` | string(100) | 카드명 (예: "업무용 법인카드") |
|
||||
| `card_company` | string(50) | 카드사 (삼성, 현대 등) |
|
||||
| `card_number` | string(30) | 카드번호 (하이픈 포함) |
|
||||
| `card_type` | enum | credit / debit |
|
||||
| `payment_day` | tinyint | 결제일 (기본: 15) |
|
||||
| `credit_limit` | decimal(15,2) | 사용한도 |
|
||||
| `current_usage` | decimal(15,2) | 현재 사용액 |
|
||||
| `card_holder_name` | string(100) | 이용자명 (법인 명의) |
|
||||
| `actual_user` | string(100) | 실사용자 |
|
||||
| `expiry_date` | string(10) | 유효기간 (YY/MM) |
|
||||
| `cvc` | string(10) | CVC |
|
||||
| `status` | enum | active / inactive |
|
||||
| `memo` | text | 메모 |
|
||||
|
||||
#### 주요 Scope
|
||||
|
||||
```php
|
||||
->active() // status = 'active'
|
||||
->forTenant($id) // tenant_id 필터
|
||||
```
|
||||
|
||||
### CorporateCardPrepayment
|
||||
|
||||
**테이블**: `corporate_card_prepayments`
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
|------|------|------|
|
||||
| `tenant_id` | bigint | 테넌트 ID |
|
||||
| `year_month` | string(7) | "2026-02" 형식 |
|
||||
| `amount` | decimal(15,0) | 선불결제 금액 |
|
||||
| `memo` | string(200) | 메모 |
|
||||
|
||||
- Unique: `[tenant_id, year_month]`
|
||||
- `getOrCreate(tenantId, yearMonth)`: 조회 또는 기본값(0) 생성
|
||||
|
||||
## 뷰 구성 (React)
|
||||
|
||||
### corporate-cards.blade.php
|
||||
|
||||
```
|
||||
┌─ 페이지 헤더 ──────────────────────
|
||||
│ 제목: "법인카드 등록/조회"
|
||||
│ 버튼: "카드 등록" (보라색)
|
||||
│
|
||||
├─ 요약 카드 (2열 / lg:6열) ─────────
|
||||
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
|
||||
│ │등록카드│ │총 한도│ │매월 │ │사용 │ │선불 │ │잔여 │
|
||||
│ │ │ │ │ │결제일 │ │금액 │ │결제 │ │한도 │
|
||||
│ │3장 │ │50백만│ │2/19 │ │35백만│ │5백만 │ │20백만│
|
||||
│ │활성2 │ │신용 │ │(수) │ │1/1~ │ │[수정]│ │한도- │
|
||||
│ │ │ │기준 │ │15→조정│ │2/19 │ │ │ │사용+ │
|
||||
│ │ │ │ │ │ │ │기준 │ │ │ │선결제│
|
||||
│ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘
|
||||
│
|
||||
├─ 검색 및 필터 ─────────────────────
|
||||
│ 검색창 | 전체 | 활성 | 비활성
|
||||
│
|
||||
├─ 카드 목록 테이블 ─────────────────
|
||||
│ 카드명(카드사) | 카드번호 | 실사용자 | 사용현황(진행바) | 상태
|
||||
│ └─ 신용: 사용률 % + 프로그레스 바
|
||||
│ └─ 체크: 사용금액 표시
|
||||
│
|
||||
├─ 등록/수정 모달 ───────────────────
|
||||
│ 카드명, 카드사, 카드종류, 카드번호, 이용자명
|
||||
│ 유효기간, CVC, 상태, 실사용자
|
||||
│ 결제일(신용만), 사용한도(신용만), 메모
|
||||
│ [비활성화] [영구삭제] [취소] [등록/저장]
|
||||
│
|
||||
└─ 선불결제 수정 모달 ───────────────
|
||||
금액 입력 (3자리 콤마), 메모 (선택)
|
||||
[취소] [저장]
|
||||
```
|
||||
|
||||
### React 주요 기능
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| 요약 카드 6개 | 등록카드, 총한도, 매월결제일, 사용금액, 선불결제, 잔여한도 |
|
||||
| 카드별 사용률 | billingUsage 기준 프로그레스 바 표시 |
|
||||
| 선불결제 인라인 수정 | 수정 버튼 → 모달 → 금액/메모 입력 → 즉시 반영 |
|
||||
| 상태 필터 | 전체 / 활성 / 비활성 |
|
||||
| 카드 검색 | 카드명, 카드사, 이용자명, 실사용자 검색 |
|
||||
|
||||
## HTMX 호환성
|
||||
|
||||
- React 기반 페이지이므로 **HX-Redirect 필요**
|
||||
- `@push('scripts')` 블록에 React/Babel 스크립트 포함
|
||||
- HTMX 네비게이션 시 전체 페이지 리로드 필수
|
||||
163
features/card-vehicle/corporate-vehicles.md
Normal file
163
features/card-vehicle/corporate-vehicles.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# 차량목록
|
||||
|
||||
## 개요
|
||||
|
||||
차량목록은 회사의 법인차량(법인/렌트/리스)을 등록하고 관리하는 기능입니다.
|
||||
소유형태별 차량 등록, 총 주행거리 자동 계산, 차량 상태 관리 등을 지원합니다.
|
||||
|
||||
- **라우트**: `GET /finance/corporate-vehicles`
|
||||
- **UI 기술**: React 18 + Babel (브라우저 트랜스파일링)
|
||||
|
||||
## 파일 구조
|
||||
|
||||
```
|
||||
mng/
|
||||
├── app/Http/Controllers/Finance/
|
||||
│ └── CorporateVehicleController.php # 메인 컨트롤러 (5개 메서드)
|
||||
├── app/Models/
|
||||
│ └── CorporateVehicle.php # 차량 모델
|
||||
└── resources/views/finance/
|
||||
└── corporate-vehicles.blade.php # React 기반 단일 페이지
|
||||
|
||||
api/
|
||||
└── database/migrations/
|
||||
└── 2026_02_02_220000_create_corporate_vehicles_table.php
|
||||
```
|
||||
|
||||
## 라우트
|
||||
|
||||
```php
|
||||
// routes/web.php (finance prefix 그룹 내)
|
||||
GET /corporate-vehicles → index() 페이지 렌더링
|
||||
GET /corporate-vehicles/list → list() 차량 목록 (JSON)
|
||||
POST /corporate-vehicles → store() 차량 등록
|
||||
PUT /corporate-vehicles/{id} → update() 차량 수정
|
||||
DELETE /corporate-vehicles/{id} → destroy() 차량 삭제
|
||||
```
|
||||
|
||||
## 컨트롤러
|
||||
|
||||
### CorporateVehicleController
|
||||
|
||||
| 메서드 | HTTP | 설명 |
|
||||
|--------|------|------|
|
||||
| `index()` | GET | React 페이지 렌더링 (HX-Redirect 적용) |
|
||||
| `list()` | GET | 차량 목록 (필터 + 총 주행거리 계산) |
|
||||
| `store()` | POST | 차량 등록 |
|
||||
| `update()` | PUT | 차량 수정 |
|
||||
| `destroy()` | DELETE | 차량 삭제 |
|
||||
|
||||
### list() 핵심 로직
|
||||
|
||||
```
|
||||
필터 파라미터: ownership_type, vehicle_type, status, search
|
||||
↓
|
||||
CorporateVehicle::where(tenant_id, ...)
|
||||
↓
|
||||
각 차량별 총 주행거리 계산:
|
||||
total_mileage = initial_mileage + SUM(vehicle_logs.distance_km)
|
||||
↓
|
||||
JSON 응답
|
||||
```
|
||||
|
||||
## 모델
|
||||
|
||||
### CorporateVehicle
|
||||
|
||||
**테이블**: `corporate_vehicles`
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
|------|------|------|
|
||||
| `tenant_id` | bigint | 테넌트 ID |
|
||||
| `plate_number` | string(20) | 차량번호 |
|
||||
| `model` | string(100) | 차량 모델명 |
|
||||
| `vehicle_type` | string(20) | 차종 |
|
||||
| `ownership_type` | enum | **corporate** / rent / lease |
|
||||
| `year` | year | 연식 |
|
||||
| `driver` | string(50) | 주 운전자 |
|
||||
| `status` | enum | **active** / maintenance / disposed |
|
||||
| `mileage` | int | 현재 주행거리 (정비 기준) |
|
||||
| `memo` | text | 메모 |
|
||||
|
||||
#### 법인 전용 필드
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
|------|------|------|
|
||||
| `purchase_date` | date | 취득일자 |
|
||||
| `purchase_price` | int | 취득가액 |
|
||||
|
||||
#### 렌트/리스 전용 필드
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
|------|------|------|
|
||||
| `contract_date` | date | 계약일자 |
|
||||
| `rent_company` | string | 렌트/리스사 |
|
||||
| `rent_company_tel` | string | 연락처 |
|
||||
| `rent_period` | string | 계약기간 |
|
||||
| `agreed_mileage` | int | 약정주행거리 |
|
||||
| `vehicle_price` | int | 차량가액 |
|
||||
| `residual_value` | int | 잔존가치 |
|
||||
| `deposit` | int | 보증금 |
|
||||
| `monthly_rent` | int | 월 렌트료 |
|
||||
| `monthly_rent_tax` | int | 부가세 |
|
||||
| `insurance_company` | string | 보험사 |
|
||||
| `insurance_company_tel` | string | 보험사 연락처 |
|
||||
|
||||
#### Traits / Scope
|
||||
|
||||
- `SoftDeletes` 적용
|
||||
- Casts: year, mileage, purchase_price, vehicle_price, residual_value, deposit, monthly_rent, monthly_rent_tax → integer
|
||||
|
||||
## 뷰 구성 (React)
|
||||
|
||||
### corporate-vehicles.blade.php
|
||||
|
||||
```
|
||||
┌─ 페이지 헤더 ──────────────────────
|
||||
│ 제목: "차량목록"
|
||||
│ 검색 | Excel 다운로드 | 차량 등록 버튼
|
||||
│
|
||||
├─ 요약 카드 (4열) ──────────────────
|
||||
│ 총 차량 | 법인 취득가 | 월 렌트/리스비 | 총 주행거리
|
||||
│
|
||||
├─ 필터 바 ──────────────────────────
|
||||
│ 소유형태: 전체 | 법인 | 렌트 | 리스
|
||||
│ 상태: 전체 | 운행중 | 정비중 | 처분
|
||||
│
|
||||
├─ 차량 목록 테이블 (12열 그리드) ──
|
||||
│ 차량번호 | 차종/모델 | 소유형태 | 운전자 | 주행거리 | 상태
|
||||
│ └─ 소유형태: 법인(보라), 렌트(파랑), 리스(초록) 배지
|
||||
│ └─ 상태: 운행중(초록), 정비중(노랑), 처분(빨강) 배지
|
||||
│
|
||||
├─ 등록/수정 모달 ───────────────────
|
||||
│ 차량번호, 모델명, 차종, 소유형태
|
||||
│ 연식, 주 운전자, 상태, 메모
|
||||
│ ─────────────────────────
|
||||
│ [법인일 때] 취득일자, 취득가액
|
||||
│ [렌트/리스일 때] 계약일, 렌트사, 계약기간,
|
||||
│ 약정주행, 차량가액, 잔존가치, 보증금,
|
||||
│ 월렌트료, 부가세, 보험사
|
||||
│ ─────────────────────────
|
||||
│ [삭제] [취소] [등록/저장]
|
||||
│
|
||||
└─ 비어있을 때: "등록된 차량이 없습니다" 안내
|
||||
```
|
||||
|
||||
## 데이터 흐름
|
||||
|
||||
```
|
||||
CorporateVehicle (1) ← (N) VehicleLog (총 주행거리 합산)
|
||||
← (N) VehicleMaintenance (주행거리 갱신)
|
||||
```
|
||||
|
||||
### 주행거리 계산 방식
|
||||
|
||||
```
|
||||
총 주행거리 = CorporateVehicle.mileage (정비 시 갱신 기준값)
|
||||
+ SUM(vehicle_logs.distance_km) (운행일지 거리 합계)
|
||||
```
|
||||
|
||||
## HTMX 호환성
|
||||
|
||||
- React 기반 페이지이므로 **HX-Redirect 필요**
|
||||
- `@push('scripts')` 블록에 React/Babel 스크립트 포함
|
||||
179
features/card-vehicle/vehicle-logs.md
Normal file
179
features/card-vehicle/vehicle-logs.md
Normal file
@@ -0,0 +1,179 @@
|
||||
# 차량일지
|
||||
|
||||
## 개요
|
||||
|
||||
차량일지는 법인차량의 운행기록을 관리하는 기능입니다.
|
||||
출발/도착지, 운행 거리, 용도(출퇴근/업무/비업무), 월별 통계 등을 지원합니다.
|
||||
|
||||
- **라우트**: `GET /finance/vehicle-logs`
|
||||
- **UI 기술**: React 18 + Babel (브라우저 트랜스파일링)
|
||||
|
||||
## 파일 구조
|
||||
|
||||
```
|
||||
mng/
|
||||
├── app/Http/Controllers/Finance/
|
||||
│ └── VehicleLogController.php # 메인 컨트롤러 (7개 메서드)
|
||||
├── app/Models/
|
||||
│ └── VehicleLog.php # 운행기록 모델
|
||||
└── resources/views/finance/
|
||||
└── vehicle-logs.blade.php # React 기반 단일 페이지
|
||||
|
||||
api/
|
||||
└── database/migrations/
|
||||
├── 2026_02_03_100000_create_vehicle_logs_table.php
|
||||
└── 2026_02_03_133000_modify_vehicle_logs_trip_type_enum.php
|
||||
```
|
||||
|
||||
## 라우트
|
||||
|
||||
```php
|
||||
// routes/web.php (finance prefix 그룹 내)
|
||||
GET /vehicle-logs → index() 페이지 렌더링
|
||||
GET /vehicle-logs/vehicles → vehicles() 차량 목록 (드롭다운용)
|
||||
GET /vehicle-logs/list → list() 운행기록 목록 (JSON)
|
||||
GET /vehicle-logs/summary → summary() 월별 통계
|
||||
POST /vehicle-logs → store() 기록 등록
|
||||
PUT /vehicle-logs/{id} → update() 기록 수정
|
||||
DELETE /vehicle-logs/{id} → destroy() 기록 삭제
|
||||
```
|
||||
|
||||
## 컨트롤러
|
||||
|
||||
### VehicleLogController
|
||||
|
||||
| 메서드 | HTTP | 설명 |
|
||||
|--------|------|------|
|
||||
| `index()` | GET | React 페이지 렌더링 (HX-Redirect 적용) |
|
||||
| `vehicles()` | GET | 전체 차량 목록 (드롭다운 선택용) |
|
||||
| `list()` | GET | 운행기록 목록 (필터, 검색) |
|
||||
| `summary()` | GET | 월별 용도별 통계 (건수, 거리) |
|
||||
| `store()` | POST | 운행기록 등록 |
|
||||
| `update()` | PUT | 운행기록 수정 |
|
||||
| `destroy()` | DELETE | 운행기록 삭제 |
|
||||
|
||||
### list() 필터 파라미터
|
||||
|
||||
| 파라미터 | 설명 |
|
||||
|---------|------|
|
||||
| `vehicle_id` | 차량 ID |
|
||||
| `year` / `month` | 연/월 |
|
||||
| `trip_type` | 운행 용도 |
|
||||
| `search` | 검색 (운전자, 부서, 출발지, 도착지, 비고) |
|
||||
|
||||
### summary() 응답 구조
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": [
|
||||
{ "trip_type": "business", "count": 15, "total_distance": 450 },
|
||||
{ "trip_type": "commute_to", "count": 22, "total_distance": 330 },
|
||||
{ "trip_type": "commute_from", "count": 22, "total_distance": 330 },
|
||||
{ "trip_type": "personal", "count": 3, "total_distance": 45 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 모델
|
||||
|
||||
### VehicleLog
|
||||
|
||||
**테이블**: `vehicle_logs`
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
|------|------|------|
|
||||
| `tenant_id` | bigint | 테넌트 ID |
|
||||
| `vehicle_id` | bigint | 차량 FK (corporate_vehicles) |
|
||||
| `log_date` | date | 운행일 |
|
||||
| `department` | string(50) | 부서 |
|
||||
| `driver_name` | string(50) | 운전자명 |
|
||||
| `trip_type` | enum | 운행 용도 (아래 참조) |
|
||||
| `departure_type` | string | 출발지 유형 |
|
||||
| `departure_name` | string | 출발지명 |
|
||||
| `departure_address` | string | 출발지 주소 |
|
||||
| `arrival_type` | string | 도착지 유형 |
|
||||
| `arrival_name` | string | 도착지명 |
|
||||
| `arrival_address` | string | 도착지 주소 |
|
||||
| `distance_km` | int | 운행거리 (km) |
|
||||
| `note` | string(200) | 비고 |
|
||||
|
||||
#### 운행 용도 (trip_type)
|
||||
|
||||
| 값 | 설명 |
|
||||
|----|------|
|
||||
| `commute_to` | 출근용 |
|
||||
| `commute_from` | 퇴근용 |
|
||||
| `business` | 업무용 |
|
||||
| `personal` | 비업무 |
|
||||
| `commute_round` | 출퇴근 왕복 |
|
||||
| `business_round` | 업무용 왕복 |
|
||||
| `personal_round` | 비업무 왕복 |
|
||||
|
||||
#### 위치 유형 (departure_type / arrival_type)
|
||||
|
||||
| 값 | 설명 |
|
||||
|----|------|
|
||||
| `home` | 자택 |
|
||||
| `office` | 회사 |
|
||||
| `client` | 거래처 |
|
||||
| `other` | 기타 |
|
||||
|
||||
#### Relationships
|
||||
|
||||
```php
|
||||
$log->vehicle // BelongsTo CorporateVehicle
|
||||
$log->tenant // BelongsTo Tenant
|
||||
```
|
||||
|
||||
#### Static 메서드
|
||||
|
||||
```php
|
||||
VehicleLog::getTripTypes() // 용도 라벨 배열
|
||||
VehicleLog::getLocationTypes() // 위치 유형 라벨 배열
|
||||
VehicleLog::getNoteOptions() // 미리 정의된 비고 옵션
|
||||
```
|
||||
|
||||
## 뷰 구성 (React)
|
||||
|
||||
### vehicle-logs.blade.php
|
||||
|
||||
```
|
||||
┌─ 페이지 헤더 ──────────────────────
|
||||
│ 차량 선택 드롭다운 (현재 주행거리 표시)
|
||||
│ 연/월 선택 | Excel 다운로드 | 기록 추가 버튼
|
||||
│
|
||||
├─ 용도별 통계 카드 ─────────────────
|
||||
│ 출근 | 퇴근 | 업무 | 비업무
|
||||
│ 건수 + 총 거리(km)
|
||||
│
|
||||
├─ 운행기록 테이블 ──────────────────
|
||||
│ 날짜 | 차량 | 부서/이름 | 용도 | 출발지 | 도착지 | 거리 | 비고
|
||||
│ └─ 용도: 출근(초록), 퇴근(파랑), 업무(보라), 비업무(회색) 배지
|
||||
│ └─ 복사 버튼 (이전 기록 복제)
|
||||
│ └─ 출발↔도착 교환 버튼 (trip_type도 자동 전환)
|
||||
│
|
||||
├─ 등록/수정 모달 ───────────────────
|
||||
│ 차량 선택, 날짜, 부서, 운전자, 용도
|
||||
│ 출발지: 유형 + 이름 + 주소
|
||||
│ 도착지: 유형 + 이름 + 주소
|
||||
│ 운행거리(km)
|
||||
│ 비고: 미리 정의된 옵션 버튼 + 자유 입력
|
||||
│ [삭제] [취소] [등록/저장]
|
||||
│
|
||||
└─ 비어있을 때: 안내 메시지
|
||||
```
|
||||
|
||||
### 특수 기능
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| 기록 복사 | 이전 운행기록을 새 날짜로 복제 |
|
||||
| 출발↔도착 교환 | 출발지와 도착지를 스왑, trip_type도 자동 전환 (commute_to ↔ commute_from) |
|
||||
| 미리 정의 비고 | 버튼 클릭으로 빠른 비고 입력 + 자유 텍스트 |
|
||||
| 용도별 통계 | 월별 용도별 건수 및 총 거리 집계 |
|
||||
|
||||
## HTMX 호환성
|
||||
|
||||
- React 기반 페이지이므로 **HX-Redirect 필요**
|
||||
- `@push('scripts')` 블록에 React/Babel 스크립트 포함
|
||||
203
features/card-vehicle/vehicle-maintenance.md
Normal file
203
features/card-vehicle/vehicle-maintenance.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# 정비이력
|
||||
|
||||
## 개요
|
||||
|
||||
정비이력은 법인차량의 정비, 주유, 보험, 세차, 주차, 통행료 등 비용을 기록하고 관리하는 기능입니다.
|
||||
카테고리별 비용 집계, 주행거리 자동 갱신, 기간별 필터링 등을 지원합니다.
|
||||
|
||||
- **라우트**: `GET /finance/vehicle-maintenance`
|
||||
- **UI 기술**: React 18 + Babel (브라우저 트랜스파일링)
|
||||
|
||||
## 파일 구조
|
||||
|
||||
```
|
||||
mng/
|
||||
├── app/Http/Controllers/Finance/
|
||||
│ └── VehicleMaintenanceController.php # 메인 컨트롤러 (6개 메서드)
|
||||
├── app/Models/
|
||||
│ └── VehicleMaintenance.php # 정비이력 모델
|
||||
└── resources/views/finance/
|
||||
└── vehicle-maintenance.blade.php # React 기반 단일 페이지
|
||||
|
||||
api/
|
||||
└── database/migrations/
|
||||
└── 2026_02_03_195000_create_vehicle_maintenances_table.php
|
||||
```
|
||||
|
||||
## 라우트
|
||||
|
||||
```php
|
||||
// routes/web.php (finance prefix 그룹 내)
|
||||
GET /vehicle-maintenance → index() 페이지 렌더링
|
||||
GET /vehicle-maintenance/vehicles → vehicles() 차량 목록 (드롭다운용)
|
||||
GET /vehicle-maintenance/list → list() 정비이력 목록 (JSON)
|
||||
POST /vehicle-maintenance → store() 정비 등록
|
||||
PUT /vehicle-maintenance/{id} → update() 정비 수정
|
||||
DELETE /vehicle-maintenance/{id} → destroy() 정비 삭제
|
||||
```
|
||||
|
||||
## 컨트롤러
|
||||
|
||||
### VehicleMaintenanceController
|
||||
|
||||
| 메서드 | HTTP | 설명 |
|
||||
|--------|------|------|
|
||||
| `index()` | GET | React 페이지 렌더링 (HX-Redirect 적용) |
|
||||
| `vehicles()` | GET | 전체 차량 목록 (드롭다운 선택용) |
|
||||
| `list()` | GET | 정비이력 목록 (필터, 검색, 차량 관계 포함) |
|
||||
| `store()` | POST | 정비 등록 + **차량 주행거리 갱신** |
|
||||
| `update()` | PUT | 정비 수정 + **차량 주행거리 갱신** |
|
||||
| `destroy()` | DELETE | 정비 삭제 |
|
||||
|
||||
### list() 필터 파라미터
|
||||
|
||||
| 파라미터 | 설명 |
|
||||
|---------|------|
|
||||
| `vehicle_id` | 차량 ID |
|
||||
| `category` | 카테고리 (주유, 정비, 보험 등) |
|
||||
| `start_date` / `end_date` | 기간 (기본: 최근 3개월) |
|
||||
| `search` | 검색 (설명, 업체명, 메모) |
|
||||
|
||||
### 주행거리 자동 갱신
|
||||
|
||||
```php
|
||||
// store() / update() 에서
|
||||
if ($request->mileage) {
|
||||
$vehicle = CorporateVehicle::find($request->vehicle_id);
|
||||
$vehicle->update(['mileage' => $request->mileage]);
|
||||
}
|
||||
```
|
||||
|
||||
정비 등록/수정 시 입력한 주행거리가 해당 차량의 기준 주행거리(mileage)를 갱신합니다.
|
||||
|
||||
## 모델
|
||||
|
||||
### VehicleMaintenance
|
||||
|
||||
**테이블**: `vehicle_maintenances`
|
||||
|
||||
| 필드 | 타입 | 설명 |
|
||||
|------|------|------|
|
||||
| `tenant_id` | bigint | 테넌트 ID |
|
||||
| `vehicle_id` | bigint | 차량 FK (corporate_vehicles) |
|
||||
| `date` | date | 정비일 |
|
||||
| `category` | string(20) | 카테고리 |
|
||||
| `description` | string(200) | 설명 |
|
||||
| `amount` | bigint | 금액 |
|
||||
| `mileage` | int | 정비 시 주행거리 |
|
||||
| `vendor` | string(100) | 업체명 |
|
||||
| `memo` | text | 메모 |
|
||||
|
||||
#### 카테고리 목록
|
||||
|
||||
| 카테고리 | 설명 | 아이콘/색상 |
|
||||
|---------|------|------------|
|
||||
| `주유` | 연료비 | Fuel / amber |
|
||||
| `정비` | 차량 정비/수리 | Wrench / blue |
|
||||
| `보험` | 자동차 보험료 | Shield / emerald |
|
||||
| `세차` | 세차 비용 | Droplets / cyan |
|
||||
| `주차` | 주차 비용 | ParkingCircle / purple |
|
||||
| `통행료` | 고속도로 등 통행료 | Route / orange |
|
||||
| `검사` | 정기검사/점검 | ClipboardCheck / indigo |
|
||||
| `기타` | 기타 비용 | MoreHorizontal / gray |
|
||||
|
||||
#### Relationships
|
||||
|
||||
```php
|
||||
$maintenance->vehicle // BelongsTo CorporateVehicle
|
||||
$maintenance->tenant // BelongsTo Tenant
|
||||
```
|
||||
|
||||
#### Static 메서드
|
||||
|
||||
```php
|
||||
VehicleMaintenance::getCategories()
|
||||
// ['주유', '정비', '보험', '세차', '주차', '통행료', '검사', '기타']
|
||||
```
|
||||
|
||||
## 뷰 구성 (React)
|
||||
|
||||
### vehicle-maintenance.blade.php
|
||||
|
||||
```
|
||||
┌─ 페이지 헤더 ──────────────────────
|
||||
│ 제목: "정비이력"
|
||||
│ 새로고침 | Excel 다운로드 | 정비 등록 버튼
|
||||
│
|
||||
├─ 요약 카드 (4열) ──────────────────
|
||||
│ 총 정비비용 | 주유비 | 정비비 | 기타비용
|
||||
│ (기간 내 합산)
|
||||
│
|
||||
├─ 필터 영역 ────────────────────────
|
||||
│ 기간: 시작일 ~ 종료일 (기본: 최근 3개월)
|
||||
│ 카테고리: 전체 | 주유 | 정비 | 보험 | 세차 | 주차 | 통행료 | 검사 | 기타
|
||||
│ 차량: 드롭다운 선택
|
||||
│ 검색: 설명, 업체명 검색
|
||||
│
|
||||
├─ 정비이력 테이블 ──────────────────
|
||||
│ 날짜 | 차량 | 카테고리 | 설명 | 금액 | 주행거리 | 작업
|
||||
│ └─ 카테고리: 컬러 배지 (카테고리별 고유 색상)
|
||||
│ └─ 금액: 원 단위 포맷
|
||||
│ └─ 작업: 수정/삭제 버튼
|
||||
│
|
||||
├─ 등록/수정 모달 ───────────────────
|
||||
│ 차량 선택, 날짜, 카테고리
|
||||
│ 설명, 금액, 주행거리, 업체명, 메모
|
||||
│ [삭제] [취소] [등록/저장]
|
||||
│
|
||||
└─ 비어있을 때: 안내 메시지
|
||||
```
|
||||
|
||||
## 핵심 로직
|
||||
|
||||
### 비용 집계
|
||||
|
||||
```
|
||||
요약 카드 계산:
|
||||
총 정비비용 = 조회 기간 내 모든 정비 금액 합계
|
||||
주유비 = category === '주유' 인 금액 합계
|
||||
정비비 = category === '정비' 인 금액 합계
|
||||
기타비용 = 나머지 카테고리 금액 합계
|
||||
```
|
||||
|
||||
### 차량 주행거리 연동
|
||||
|
||||
```
|
||||
정비 등록/수정 시 mileage 입력
|
||||
↓
|
||||
해당 차량(corporate_vehicles)의 mileage 필드 갱신
|
||||
↓
|
||||
차량목록에서 총 주행거리 재계산:
|
||||
total_mileage = mileage + SUM(vehicle_logs.distance_km)
|
||||
```
|
||||
|
||||
## 데이터베이스 스키마
|
||||
|
||||
### vehicle_maintenances
|
||||
|
||||
```sql
|
||||
CREATE TABLE vehicle_maintenances (
|
||||
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
tenant_id BIGINT NOT NULL,
|
||||
vehicle_id BIGINT NOT NULL,
|
||||
date DATE NOT NULL,
|
||||
category VARCHAR(20) NOT NULL,
|
||||
description VARCHAR(200),
|
||||
amount BIGINT UNSIGNED DEFAULT 0,
|
||||
mileage INT UNSIGNED,
|
||||
vendor VARCHAR(100),
|
||||
memo TEXT,
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
INDEX (tenant_id, vehicle_id, date),
|
||||
INDEX (tenant_id, category),
|
||||
FOREIGN KEY (tenant_id) REFERENCES tenants(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (vehicle_id) REFERENCES corporate_vehicles(id) ON DELETE CASCADE
|
||||
);
|
||||
```
|
||||
|
||||
## HTMX 호환성
|
||||
|
||||
- React 기반 페이지이므로 **HX-Redirect 필요**
|
||||
- `@push('scripts')` 블록에 React/Babel 스크립트 포함
|
||||
Reference in New Issue
Block a user