# 차량관리 API 명세

> **작성일**: 2026-03-12
> **상태**: API 이관 예정 (MNG에서 운영중, API 엔드포인트 미구현)
> **Base URL**: `api.codebridge-x.com` (운영) / `api.dev.codebridge-x.com` (개발)

---

## 1. 개요

법인/렌트/리스 차량을 등록하고, 운행일지와 정비이력을 관리하는 API이다.
멀티테넌트 구조로 테넌트별 데이터 격리가 적용된다.

### 1.1 인증

모든 요청에 다음 헤더가 필요하다:

```
X-API-KEY: {api_key}
Authorization: Bearer {token}
```

### 1.2 공통 응답 형식

```json
{
  "success": true,
  "message": "조회 성공",
  "data": { ... }
}
```

에러 시:

```json
{
  "success": false,
  "message": "에러 메시지"
}
```

### 1.3 메뉴 구성

| 메뉴 | 설명 | 섹션 |
|------|------|------|
| 차량목록 | 법인/렌트/리스 차량 등록 관리 | [3. 차량목록 API](#3-차량목록-api) |
| 차량일지 | 운행기록 관리 및 월별 통계 | [4. 차량일지 API](#4-차량일지-api) |
| 정비이력 | 정비/주유/보험 등 비용 관리 | [5. 정비이력 API](#5-정비이력-api) |

### 1.4 엔드포인트 요약

| # | Method | Path | 설명 |
|---|--------|------|------|
| 1 | GET | `/api/v1/corporate-vehicles` | 차량 목록 |
| 2 | POST | `/api/v1/corporate-vehicles` | 차량 등록 |
| 3 | GET | `/api/v1/corporate-vehicles/{id}` | 차량 상세 |
| 4 | PUT | `/api/v1/corporate-vehicles/{id}` | 차량 수정 |
| 5 | DELETE | `/api/v1/corporate-vehicles/{id}` | 차량 삭제 |
| 6 | GET | `/api/v1/corporate-vehicles/dropdown` | 차량 드롭다운 목록 |
| 7 | GET | `/api/v1/vehicle-logs` | 운행기록 목록 |
| 8 | POST | `/api/v1/vehicle-logs` | 운행기록 등록 |
| 9 | GET | `/api/v1/vehicle-logs/{id}` | 운행기록 상세 |
| 10 | PUT | `/api/v1/vehicle-logs/{id}` | 운행기록 수정 |
| 11 | DELETE | `/api/v1/vehicle-logs/{id}` | 운행기록 삭제 |
| 12 | GET | `/api/v1/vehicle-logs/summary` | 월별 용도별 통계 |
| 13 | GET | `/api/v1/vehicle-maintenances` | 정비이력 목록 |
| 14 | POST | `/api/v1/vehicle-maintenances` | 정비이력 등록 |
| 15 | GET | `/api/v1/vehicle-maintenances/{id}` | 정비이력 상세 |
| 16 | PUT | `/api/v1/vehicle-maintenances/{id}` | 정비이력 수정 |
| 17 | DELETE | `/api/v1/vehicle-maintenances/{id}` | 정비이력 삭제 |
| 18 | GET | `/api/v1/corporate-vehicles/{id}/photos` | 차량 사진 목록 |
| 19 | POST | `/api/v1/corporate-vehicles/{id}/photos` | 차량 사진 업로드 (최대 10장) |
| 20 | DELETE | `/api/v1/corporate-vehicles/{id}/photos/{fileId}` | 차량 사진 삭제 |

---

## 2. 데이터 모델

### 2.1 CorporateVehicle (차량)

```json
{
  "id": 1,
  "plate_number": "12가 3456",
  "model": "에쿠스",
  "vehicle_type": "승용차",
  "ownership_type": "corporate",
  "year": 2024,
  "driver": "홍길동",
  "status": "active",
  "mileage": 15000,
  "memo": "대표이사 전용",
  "purchase_date": "2024-01-15",
  "purchase_price": 85000000,
  "contract_date": null,
  "rent_company": null,
  "rent_company_tel": null,
  "rent_period": null,
  "agreed_mileage": null,
  "vehicle_price": 0,
  "residual_value": 0,
  "deposit": 0,
  "monthly_rent": 0,
  "monthly_rent_tax": 0,
  "insurance_company": null,
  "insurance_company_tel": null,
  "log_distance": 2350,
  "total_mileage": 17350,
  "created_at": "2026-01-15T09:00:00.000000Z",
  "updated_at": "2026-03-10T14:30:00.000000Z"
}
```

#### 필드 설명 — 공통

| 필드 | 타입 | 필수 | 설명 |
|------|------|:----:|------|
| `plate_number` | string(20) | ✅ | 차량번호 |
| `model` | string(100) | ✅ | 차량 모델명 |
| `vehicle_type` | string(20) | ✅ | 차종 |
| `ownership_type` | enum | ✅ | 소유형태 |
| `year` | int | | 연식 |
| `driver` | string(50) | | 주 운전자 |
| `status` | enum | | 상태 (기본: `active`) |
| `mileage` | int | | 기준 주행거리 (정비 시 갱신, 기본: 0) |
| `memo` | text | | 메모 |

#### 필드 설명 — 법인 전용 (`ownership_type = "corporate"`)

| 필드 | 타입 | 설명 |
|------|------|------|
| `purchase_date` | date | 취득일자 |
| `purchase_price` | int | 취득가액 (원) |

#### 필드 설명 — 렌트/리스 전용 (`ownership_type = "rent" or "lease"`)

| 필드 | 타입 | 설명 |
|------|------|------|
| `contract_date` | date | 계약일자 |
| `rent_company` | string(100) | 렌트/리스 회사명 |
| `rent_company_tel` | string(20) | 회사 연락처 |
| `rent_period` | string(20) | 계약기간 |
| `agreed_mileage` | string(20) | 약정주행거리 |
| `vehicle_price` | int | 차량가액 (원) |
| `residual_value` | int | 잔존가치 (원) |
| `deposit` | int | 보증금 (원) |
| `monthly_rent` | int | 월 렌트료 공급가 (원) |
| `monthly_rent_tax` | int | 월 렌트료 부가세 (원) |
| `insurance_company` | string(100) | 보험사명 |
| `insurance_company_tel` | string(20) | 보험사 연락처 |

#### 계산 필드 (API 응답에만 포함, 저장 안 함)

| 필드 | 계산식 | 설명 |
|------|--------|------|
| `log_distance` | `SUM(vehicle_logs.distance_km)` | 운행일지 거리 합계 |
| `total_mileage` | `mileage + log_distance` | 총 주행거리 |

#### Enum 값

**ownership_type (소유형태)**:

| 값 | 라벨 | UI 배지 색상 |
|----|------|:----------:|
| `corporate` | 법인 | 보라 (purple) |
| `rent` | 렌트 | 파랑 (blue) |
| `lease` | 리스 | 초록 (green) |

**vehicle_type (차종)**:

| 값 | 설명 |
|----|------|
| `승용차` | 일반 승용차 |
| `승합차` | 승합차 |
| `화물차` | 화물차 |
| `SUV` | SUV |

**status (상태)**:

| 값 | 라벨 | UI 배지 색상 |
|----|------|:----------:|
| `active` | 운행중 | 초록 (green) |
| `maintenance` | 정비중 | 노랑 (yellow) |
| `disposed` | 처분 | 빨강 (red) |

---

### 2.2 VehicleLog (운행기록)

```json
{
  "id": 1,
  "logDate": "2026-03-12",
  "vehicleId": 1,
  "plateNumber": "12가 3456",
  "model": "에쿠스",
  "department": "영업부",
  "driverName": "홍길동",
  "tripType": "business",
  "departureType": "office",
  "departureName": "본사",
  "departureAddress": "서울시 강남구 테헤란로 123",
  "arrivalType": "client",
  "arrivalName": "거래처A",
  "arrivalAddress": "경기도 성남시 분당구 판교로 456",
  "distanceKm": 45,
  "note": "거래처방문"
}
```

#### 필드 설명

| 필드 | 타입 | 필수 | 설명 |
|------|------|:----:|------|
| `vehicleId` | int | ✅ | 차량 ID (FK → corporate_vehicles) |
| `logDate` | date | ✅ | 운행일 |
| `driverName` | string(50) | ✅ | 운전자명 |
| `tripType` | enum | ✅ | 운행 용도 |
| `distanceKm` | int | ✅ | 운행거리 (km, 0 이상) |
| `department` | string(50) | | 부서 |
| `departureType` | enum | | 출발지 유형 |
| `departureName` | string(100) | | 출발지명 |
| `departureAddress` | string(200) | | 출발지 주소 |
| `arrivalType` | enum | | 도착지 유형 |
| `arrivalName` | string(100) | | 도착지명 |
| `arrivalAddress` | string(200) | | 도착지 주소 |
| `note` | string(200) | | 비고 |

> **참고**: `plateNumber`, `model`은 차량 관계에서 자동 포함된 읽기 전용 필드이다.

#### Enum 값

**tripType (운행 용도)**:

| 값 | 라벨 | UI 배지 색상 |
|----|------|:----------:|
| `commute_to` | 출근용 | 초록 (green) |
| `commute_from` | 퇴근용 | 파랑 (blue) |
| `business` | 업무용 | 보라 (purple) |
| `personal` | 비업무 | 회색 (gray) |
| `commute_round` | 출퇴근 왕복 | 초록 (green) |
| `business_round` | 업무용 왕복 | 보라 (purple) |
| `personal_round` | 비업무 왕복 | 회색 (gray) |

**departureType / arrivalType (위치 유형)**:

| 값 | 라벨 |
|----|------|
| `home` | 자택 |
| `office` | 회사 |
| `client` | 거래처 |
| `other` | 기타 |

**비고 프리셋 옵션** (버튼으로 빠른 입력):

```json
["거래처방문", "제조시설등", "회의참석", "판촉활동", "교육등"]
```

---

### 2.3 VehicleMaintenance (정비이력)

```json
{
  "id": 1,
  "date": "2026-03-10",
  "vehicleId": 1,
  "plateNumber": "12가 3456",
  "model": "에쿠스",
  "category": "주유",
  "description": "LPG 충전",
  "amount": 85000,
  "mileage": 17350,
  "vendor": "SK에너지 강남점",
  "memo": null
}
```

#### 필드 설명

| 필드 | 타입 | 필수 | 설명 |
|------|------|:----:|------|
| `vehicleId` | int | ✅ | 차량 ID (FK → corporate_vehicles) |
| `date` | date | ✅ | 정비일 |
| `category` | string(20) | ✅ | 카테고리 |
| `amount` | int | ✅ | 금액 (원, 0 이상) |
| `description` | string(200) | | 설명 |
| `mileage` | int | | 정비 시 주행거리 (입력 시 차량 mileage 자동 갱신) |
| `vendor` | string(100) | | 업체명 |
| `memo` | text | | 메모 |

#### 카테고리 목록

| 카테고리 | 아이콘 | UI 배지 색상 |
|---------|--------|:----------:|
| `주유` | Fuel | amber |
| `정비` | Wrench | blue |
| `보험` | Shield | emerald |
| `세차` | Droplets | cyan |
| `주차` | ParkingCircle | purple |
| `통행료` | Route | orange |
| `검사` | ClipboardCheck | indigo |
| `기타` | MoreHorizontal | gray |

---

## 3. 차량목록 API

### 3.1 차량 목록 조회

```
GET /api/v1/corporate-vehicles
```

**쿼리 파라미터**:

| 파라미터 | 타입 | 기본값 | 설명 |
|---------|------|-------|------|
| `ownership_type` | string | `all` | `corporate` / `rent` / `lease` / `all` |
| `vehicle_type` | string | `all` | 승용차 / 승합차 / 화물차 / SUV / `all` |
| `status` | string | `all` | `active` / `maintenance` / `disposed` / `all` |
| `search` | string | | 차량번호, 모델, 운전자 검색 |

**응답**:

```json
{
  "success": true,
  "data": [
    {
      "id": 1,
      "plate_number": "12가 3456",
      "model": "에쿠스",
      "vehicle_type": "승용차",
      "ownership_type": "corporate",
      "year": 2024,
      "driver": "홍길동",
      "status": "active",
      "mileage": 15000,
      "memo": null,
      "purchase_date": "2024-01-15",
      "purchase_price": 85000000,
      "log_distance": 2350,
      "total_mileage": 17350
    }
  ]
}
```

### 3.2 차량 등록

```
POST /api/v1/corporate-vehicles
```

**요청 Body**:

```json
{
  "plate_number": "12가 3456",
  "model": "에쿠스",
  "vehicle_type": "승용차",
  "ownership_type": "corporate",
  "year": 2024,
  "driver": "홍길동",
  "status": "active",
  "mileage": 15000,
  "memo": "대표이사 전용",
  "purchase_date": "2024-01-15",
  "purchase_price": 85000000
}
```

**유효성 검증**:

| 필드 | 규칙 |
|------|------|
| `plate_number` | required, string, max:20 |
| `model` | required, string, max:100 |
| `vehicle_type` | required, string, max:20 |
| `ownership_type` | required, in:corporate,rent,lease |

**응답** (201):

```json
{
  "success": true,
  "message": "차량이 등록되었습니다.",
  "data": { ... }
}
```

### 3.3 차량 상세

```
GET /api/v1/corporate-vehicles/{id}
```

### 3.4 차량 수정

```
PUT /api/v1/corporate-vehicles/{id}
```

요청 Body는 등록과 동일. 유효성 검증도 동일.

### 3.5 차량 삭제

```
DELETE /api/v1/corporate-vehicles/{id}
```

SoftDelete 적용 (복구 가능).

**응답**:

```json
{
  "success": true,
  "message": "차량이 삭제되었습니다."
}
```

### 3.6 차량 드롭다운 목록

```
GET /api/v1/corporate-vehicles/dropdown
```

차량일지, 정비이력에서 차량 선택 드롭다운에 사용. 간소화된 필드만 반환.

**응답**:

```json
{
  "success": true,
  "data": [
    { "id": 1, "plate_number": "12가 3456", "model": "에쿠스" },
    { "id": 2, "plate_number": "56나 7890", "model": "스타리아" }
  ]
}
```

---

## 4. 차량일지 API

### 4.1 운행기록 목록

```
GET /api/v1/vehicle-logs
```

**쿼리 파라미터**:

| 파라미터 | 타입 | 기본값 | 설명 |
|---------|------|-------|------|
| `vehicle_id` | int | `all` | 차량 ID |
| `year` | int | 현재년 | 연도 |
| `month` | int | 현재월 | 월 |
| `trip_type` | string | `all` | 운행 용도 |
| `search` | string | | 운전자, 부서, 출발지, 도착지, 비고 검색 |

**응답**:

```json
{
  "success": true,
  "data": [
    {
      "id": 1,
      "logDate": "2026-03-12",
      "vehicleId": 1,
      "plateNumber": "12가 3456",
      "model": "에쿠스",
      "department": "영업부",
      "driverName": "홍길동",
      "tripType": "business",
      "departureType": "office",
      "departureName": "본사",
      "departureAddress": "서울시 강남구 테헤란로 123",
      "arrivalType": "client",
      "arrivalName": "거래처A",
      "arrivalAddress": "경기도 성남시 분당구 판교로 456",
      "distanceKm": 45,
      "note": "거래처방문"
    }
  ]
}
```

> **참고**: 응답 필드명은 camelCase를 사용한다 (MNG 기존 패턴 유지).

### 4.2 운행기록 등록

```
POST /api/v1/vehicle-logs
```

**요청 Body**:

```json
{
  "vehicle_id": 1,
  "log_date": "2026-03-12",
  "department": "영업부",
  "driver_name": "홍길동",
  "trip_type": "business",
  "departure_type": "office",
  "departure_name": "본사",
  "departure_address": "서울시 강남구 테헤란로 123",
  "arrival_type": "client",
  "arrival_name": "거래처A",
  "arrival_address": "경기도 성남시 분당구 판교로 456",
  "distance_km": 45,
  "note": "거래처방문"
}
```

**유효성 검증**:

| 필드 | 규칙 |
|------|------|
| `vehicle_id` | required, exists:corporate_vehicles,id |
| `log_date` | required, date |
| `driver_name` | required, string, max:50 |
| `trip_type` | required, in:commute_to,commute_from,business,personal,commute_round,business_round,personal_round |
| `distance_km` | required, integer, min:0 |

**응답** (201):

```json
{
  "success": true,
  "message": "운행기록이 등록되었습니다.",
  "data": { ... }
}
```

### 4.3 운행기록 상세

```
GET /api/v1/vehicle-logs/{id}
```

### 4.4 운행기록 수정

```
PUT /api/v1/vehicle-logs/{id}
```

요청 Body/유효성 검증은 등록과 동일.

### 4.5 운행기록 삭제

```
DELETE /api/v1/vehicle-logs/{id}
```

### 4.6 월별 용도별 통계

```
GET /api/v1/vehicle-logs/summary
```

**쿼리 파라미터**:

| 파라미터 | 타입 | 설명 |
|---------|------|------|
| `vehicle_id` | int | 차량 ID (생략 시 전체) |
| `year` | int | 연도 |
| `month` | int | 월 |

**응답**:

```json
{
  "success": true,
  "data": {
    "byType": {
      "commute_to": { "label": "출근용", "count": 5, "distance": 125 },
      "commute_from": { "label": "퇴근용", "count": 5, "distance": 130 },
      "business": { "label": "업무용", "count": 10, "distance": 280 },
      "personal": { "label": "비업무", "count": 2, "distance": 45 }
    },
    "total": {
      "count": 22,
      "distance": 580
    }
  }
}
```

---

## 5. 정비이력 API

### 5.1 정비이력 목록

```
GET /api/v1/vehicle-maintenances
```

**쿼리 파라미터**:

| 파라미터 | 타입 | 기본값 | 설명 |
|---------|------|-------|------|
| `vehicle_id` | int | `all` | 차량 ID |
| `category` | string | `all` | 카테고리 (주유, 정비, 보험 등) |
| `start_date` | date | 3개월 전 | 시작일 |
| `end_date` | date | 오늘 | 종료일 |
| `search` | string | | 설명, 업체명, 메모 검색 |

**응답**:

```json
{
  "success": true,
  "data": [
    {
      "id": 1,
      "date": "2026-03-10",
      "vehicleId": 1,
      "plateNumber": "12가 3456",
      "model": "에쿠스",
      "category": "주유",
      "description": "LPG 충전",
      "amount": 85000,
      "mileage": 17350,
      "vendor": "SK에너지 강남점",
      "memo": null
    }
  ]
}
```

### 5.2 정비이력 등록

```
POST /api/v1/vehicle-maintenances
```

**요청 Body**:

```json
{
  "vehicle_id": 1,
  "date": "2026-03-10",
  "category": "주유",
  "description": "LPG 충전",
  "amount": 85000,
  "mileage": 17350,
  "vendor": "SK에너지 강남점",
  "memo": null
}
```

**유효성 검증**:

| 필드 | 규칙 |
|------|------|
| `vehicle_id` | required, exists:corporate_vehicles,id |
| `date` | required, date |
| `category` | required, string, max:20 |
| `amount` | required, numeric, min:0 |

**부수 효과**: `mileage` 값이 있으면 해당 차량의 `corporate_vehicles.mileage`를 자동 갱신한다.

**응답** (201):

```json
{
  "success": true,
  "message": "정비 이력이 등록되었습니다.",
  "data": { ... }
}
```

### 5.3 정비이력 상세

```
GET /api/v1/vehicle-maintenances/{id}
```

### 5.4 정비이력 수정

```
PUT /api/v1/vehicle-maintenances/{id}
```

요청 Body/유효성 검증은 등록과 동일. `mileage` 갱신 부수 효과도 동일.

### 5.5 정비이력 삭제

```
DELETE /api/v1/vehicle-maintenances/{id}
```

---

## 6. UI 구현 가이드

### 6.1 차량목록 화면

```
┌─ 페이지 헤더 ──────────────────────
│  제목: "차량목록"
│  검색 | Excel 다운로드 | 차량 등록 버튼
│
├─ 요약 카드 (4열) ──────────────────
│  총 차량 | 법인 취득가 | 월 렌트/리스비 | 총 주행거리
│
├─ 필터 바 ──────────────────────────
│  소유형태: 전체 | 법인 | 렌트 | 리스
│  상태: 전체 | 운행중 | 정비중 | 처분
│
├─ 차량 목록 테이블 ─────────────────
│  차량번호 | 차종/모델 | 소유형태 | 운전자 | 주행거리 | 상태
│
├─ 등록/수정 모달 ───────────────────
│  차량번호, 모델명, 차종, 소유형태
│  연식, 주 운전자, 상태, 메모
│  ─────────────────────────
│  [법인] 취득일자, 취득가액
│  [렌트/리스] 계약일, 렌트사, 계약기간,
│    약정주행, 차량가액, 잔존가치, 보증금,
│    월렌트료, 부가세, 보험사
│  ─────────────────────────
│  [삭제] [취소] [등록/저장]
└────────────────────────────────────
```

**요약 카드 계산**:

| 카드 | 계산식 |
|------|--------|
| 총 차량 | 전체 차량 수 |
| 법인 취득가 | `ownership_type = 'corporate'`인 차량의 `purchase_price` 합계 |
| 월 렌트/리스비 | `ownership_type in ('rent','lease')`인 차량의 `monthly_rent + monthly_rent_tax` 합계 |
| 총 주행거리 | 전체 차량의 `total_mileage` 합계 |

**조건부 폼 필드**:
- `ownership_type = "corporate"` → 법인 전용 필드 표시
- `ownership_type = "rent" or "lease"` → 렌트/리스 전용 필드 표시

---

### 6.2 차량일지 화면

```
┌─ 페이지 헤더 ──────────────────────
│  차량 선택 드롭다운 (현재 주행거리 표시)
│  연/월 선택 | CSV 다운로드 | 기록 추가 버튼
│
├─ 용도별 통계 카드 ─────────────────
│  출근 | 퇴근 | 업무 | 비업무
│  건수 + 총 거리(km)
│
├─ 운행기록 테이블 ──────────────────
│  날짜 | 차량 | 부서/이름 | 용도 | 출발지 | 도착지 | 거리 | 비고
│
├─ 등록/수정 모달 ───────────────────
│  차량 선택, 날짜, 부서, 운전자, 용도
│  출발지: 유형 + 이름 + 주소
│  도착지: 유형 + 이름 + 주소
│  운행거리(km)
│  비고: 프리셋 버튼 + 자유 입력
│  [삭제] [취소] [등록/저장]
└────────────────────────────────────
```

**특수 기능 (프론트엔드에서 처리)**:

| 기능 | 설명 |
|------|------|
| 기록 복사 | 기존 기록을 복제하여 새 날짜로 등록 (API는 일반 POST) |
| 출발↔도착 교환 | 출발지/도착지 swap + tripType 자동 전환 (`commute_to` ↔ `commute_from`) |
| 비고 프리셋 | 5개 버튼 클릭 시 비고 필드에 텍스트 입력 |

---

### 6.3 정비이력 화면

```
┌─ 페이지 헤더 ──────────────────────
│  제목: "정비이력"
│  새로고침 | CSV 다운로드 | 정비 등록 버튼
│
├─ 요약 카드 (4열) ──────────────────
│  총 정비비용 | 주유비 | 정비비 | 기타비용
│
├─ 필터 영역 ────────────────────────
│  기간: 시작일 ~ 종료일 (기본: 최근 3개월)
│  카테고리: 전체 | 주유 | 정비 | 보험 | 세차 | 주차 | 통행료 | 검사 | 기타
│  차량: 드롭다운 선택
│  검색: 설명, 업체명 검색
│
├─ 정비이력 테이블 ──────────────────
│  날짜 | 차량 | 카테고리 | 설명 | 금액 | 주행거리 | 작업
│
├─ 등록/수정 모달 ───────────────────
│  차량 선택, 날짜, 카테고리
│  설명, 금액, 주행거리, 업체명, 메모
│  [삭제] [취소] [등록/저장]
└────────────────────────────────────
```

**요약 카드 계산** (조회된 목록 데이터 기준):

| 카드 | 계산식 |
|------|--------|
| 총 정비비용 | 전체 `amount` 합계 |
| 주유비 | `category = '주유'`인 `amount` 합계 |
| 정비비 | `category = '정비'`인 `amount` 합계 |
| 기타비용 | 총 정비비용 - 주유비 - 정비비 |

---

## 7. 차량 사진 API

### 7.1 사진 목록 조회

```
GET /api/v1/corporate-vehicles/{id}/photos
```

**응답 예시**:

```json
{
  "success": true,
  "message": "조회 성공",
  "data": [
    {
      "id": 42,
      "file_name": "차량_전면.jpg",
      "file_path": "1/corporate-vehicles/2026/03/a1b2c3d4e5f6.jpg",
      "file_url": "/api/v1/files/42/download",
      "file_size": 2048576,
      "mime_type": "image/jpeg",
      "created_at": "2026-03-12 15:30:00"
    }
  ]
}
```

### 7.2 사진 업로드

```
POST /api/v1/corporate-vehicles/{id}/photos
Content-Type: multipart/form-data
```

| 파라미터 | 타입 | 필수 | 설명 |
|---------|------|:----:|------|
| `files[]` | file[] | ✅ | 이미지 파일 (다중 업로드) |

**제약조건**:

| 항목 | 값 |
|------|------|
| 최대 보유 수량 | 10장 / 차량 |
| 허용 확장자 | jpg, jpeg, png, gif, bmp, webp |
| 파일 크기 제한 | 10MB / 파일 |
| 동적 max 계산 | `max = 10 - 현재 사진 수` |

**응답 예시** (업로드된 파일 목록 반환):

```json
{
  "success": true,
  "message": "등록 성공",
  "data": [
    {
      "id": 43,
      "file_name": "차량_후면.jpg",
      "file_path": "1/corporate-vehicles/2026/03/f6e5d4c3b2a1.jpg",
      "file_url": "/api/v1/files/43/download",
      "file_size": 1536000,
      "mime_type": "image/jpeg",
      "created_at": "2026-03-12 16:00:00"
    }
  ]
}
```

**에러 응답** (10장 초과 시):

```json
{
  "success": false,
  "message": "사진은 최대 10장까지 등록할 수 있습니다."
}
```

### 7.3 사진 삭제

```
DELETE /api/v1/corporate-vehicles/{id}/photos/{fileId}
```

**응답 예시**:

```json
{
  "success": true,
  "message": "삭제 성공",
  "data": {
    "file_id": 42,
    "deleted": true
  }
}
```

### 7.4 UI 구현 가이드 — 사진

```
┌─ 차량 상세/수정 페이지 ───────────────
│
├─ 사진 영역 ──────────────────────────
│  ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│  │ 📷   │ │ 📷   │ │ 📷   │ │  +   │
│  │ 사진1 │ │ 사진2 │ │ 사진3 │ │ 추가 │
│  └──────┘ └──────┘ └──────┘ └──────┘
│  * 최대 10장 (n/10 표시)
│  * 사진 클릭 → 확대 보기
│  * 삭제 버튼 (X) 각 사진에 표시
│  * 드래그앤드롭 또는 파일 선택으로 업로드
│
```

**특수 기능**:
- 다중 파일 선택 지원 (`multiple` attribute)
- 업로드 전 미리보기 (FileReader API)
- 남은 업로드 가능 수량 = 10 - 현재 사진 수
- 업로드 가능 수량 초과 시 파일 선택 차단

---

## 8. 데이터 관계도

```
corporate_vehicles (차량 마스터)
    │
    ├── vehicle_logs (1:N)
    │   운행기록 → distance_km 합산하여 차량 total_mileage 계산
    │
    ├── vehicle_maintenances (1:N)
    │   정비기록 → mileage 입력 시 차량 mileage 기준값 갱신
    │
    └── files (1:N, polymorphic)
        사진 → document_type='corporate_vehicle', document_id=vehicle.id
        최대 10장, R2 스토리지 저장, Soft Delete
```

```
총 주행거리 계산:
  total_mileage = corporate_vehicles.mileage (정비 시 갱신되는 기준값)
                + SUM(vehicle_logs.distance_km) (운행일지 거리 합계)
```

---

## 관련 문서

- [차량목록 기능 상세](../../features/card-vehicle/corporate-vehicles.md)
- [차량일지 기능 상세](../../features/card-vehicle/vehicle-logs.md)
- [정비이력 기능 상세](../../features/card-vehicle/vehicle-maintenance.md)
- [카드/차량관리 모듈 README](../../features/card-vehicle/README.md)

---

**최종 업데이트**: 2026-03-12
