# 차량관리 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