- 구분 유형 추가: 출퇴근용(왕복), 업무용(왕복), 비업무용(왕복) - 비업무 라벨을 '비업무용(개인)'으로 변경 - 출발지/도착지 장소명 라벨 수정 (장소명 → 출발지명/도착지명) - 새 유형별 색상 추가 Co-Authored-By: Claude <noreply@anthropic.com>
266 lines
9.7 KiB
PHP
266 lines
9.7 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Finance;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\CorporateVehicle;
|
|
use App\Models\VehicleLog;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Http\Response;
|
|
use Illuminate\View\View;
|
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
|
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
|
|
|
class VehicleLogController extends Controller
|
|
{
|
|
public function index(Request $request): View|Response
|
|
{
|
|
if ($request->header('HX-Request')) {
|
|
return response('', 200)->header('HX-Redirect', route('finance.vehicle-logs'));
|
|
}
|
|
|
|
$tenantId = session('tenant_id', 1);
|
|
$vehicles = CorporateVehicle::where('tenant_id', $tenantId)
|
|
->where('status', 'active')
|
|
->orderBy('plate_number')
|
|
->get();
|
|
|
|
return view('finance.vehicle-logs', [
|
|
'vehicles' => $vehicles,
|
|
'tripTypes' => VehicleLog::tripTypeLabels(),
|
|
'locationTypes' => VehicleLog::locationTypeLabels(),
|
|
]);
|
|
}
|
|
|
|
public function list(Request $request): JsonResponse
|
|
{
|
|
$tenantId = session('tenant_id', 1);
|
|
|
|
$request->validate([
|
|
'vehicle_id' => 'required|integer',
|
|
'start_date' => 'required|date',
|
|
'end_date' => 'required|date|after_or_equal:start_date',
|
|
]);
|
|
|
|
$vehicleId = $request->vehicle_id;
|
|
$startDate = $request->start_date;
|
|
$endDate = $request->end_date;
|
|
|
|
// 차량 정보
|
|
$vehicle = CorporateVehicle::where('tenant_id', $tenantId)
|
|
->findOrFail($vehicleId);
|
|
|
|
// 전체 운행기록 수 (해당 차량)
|
|
$totalCount = VehicleLog::where('tenant_id', $tenantId)
|
|
->where('vehicle_id', $vehicleId)
|
|
->count();
|
|
|
|
$logs = VehicleLog::where('tenant_id', $tenantId)
|
|
->where('vehicle_id', $vehicleId)
|
|
->whereBetween('log_date', [$startDate, $endDate])
|
|
->orderBy('log_date')
|
|
->orderBy('id')
|
|
->get();
|
|
|
|
// 월별 합계
|
|
$totals = [
|
|
'business_km' => $logs->whereIn('trip_type', ['commute_to', 'commute_from', 'business', 'commute_round', 'business_round'])->sum('distance_km'),
|
|
'personal_km' => $logs->whereIn('trip_type', ['personal', 'personal_round'])->sum('distance_km'),
|
|
'total_km' => $logs->sum('distance_km'),
|
|
];
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => [
|
|
'vehicle' => $vehicle,
|
|
'logs' => $logs,
|
|
'totals' => $totals,
|
|
'totalCount' => $totalCount,
|
|
],
|
|
]);
|
|
}
|
|
|
|
public function store(Request $request): JsonResponse
|
|
{
|
|
$tenantId = session('tenant_id', 1);
|
|
|
|
$request->validate([
|
|
'vehicle_id' => 'required|integer|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',
|
|
]);
|
|
|
|
// 해당 차량이 현재 테넌트의 것인지 확인
|
|
CorporateVehicle::where('tenant_id', $tenantId)
|
|
->findOrFail($request->vehicle_id);
|
|
|
|
$log = VehicleLog::create([
|
|
'tenant_id' => $tenantId,
|
|
'vehicle_id' => $request->vehicle_id,
|
|
'log_date' => $request->log_date,
|
|
'department' => $request->department,
|
|
'driver_name' => $request->driver_name,
|
|
'trip_type' => $request->trip_type,
|
|
'departure_type' => $request->departure_type,
|
|
'departure_name' => $request->departure_name,
|
|
'departure_address' => $request->departure_address,
|
|
'arrival_type' => $request->arrival_type,
|
|
'arrival_name' => $request->arrival_name,
|
|
'arrival_address' => $request->arrival_address,
|
|
'distance_km' => $request->distance_km,
|
|
'note' => $request->note,
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => '운행기록이 등록되었습니다.',
|
|
'data' => $log,
|
|
]);
|
|
}
|
|
|
|
public function update(Request $request, int $id): JsonResponse
|
|
{
|
|
$tenantId = session('tenant_id', 1);
|
|
|
|
$log = VehicleLog::where('tenant_id', $tenantId)->findOrFail($id);
|
|
|
|
$request->validate([
|
|
'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',
|
|
]);
|
|
|
|
$log->update([
|
|
'log_date' => $request->log_date,
|
|
'department' => $request->department,
|
|
'driver_name' => $request->driver_name,
|
|
'trip_type' => $request->trip_type,
|
|
'departure_type' => $request->departure_type,
|
|
'departure_name' => $request->departure_name,
|
|
'departure_address' => $request->departure_address,
|
|
'arrival_type' => $request->arrival_type,
|
|
'arrival_name' => $request->arrival_name,
|
|
'arrival_address' => $request->arrival_address,
|
|
'distance_km' => $request->distance_km,
|
|
'note' => $request->note,
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => '운행기록이 수정되었습니다.',
|
|
'data' => $log,
|
|
]);
|
|
}
|
|
|
|
public function destroy(int $id): JsonResponse
|
|
{
|
|
$tenantId = session('tenant_id', 1);
|
|
|
|
$log = VehicleLog::where('tenant_id', $tenantId)->findOrFail($id);
|
|
$log->delete();
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => '운행기록이 삭제되었습니다.',
|
|
]);
|
|
}
|
|
|
|
public function export(Request $request): StreamedResponse
|
|
{
|
|
$tenantId = session('tenant_id', 1);
|
|
|
|
$request->validate([
|
|
'vehicle_id' => 'required|integer',
|
|
'start_date' => 'required|date',
|
|
'end_date' => 'required|date|after_or_equal:start_date',
|
|
]);
|
|
|
|
$vehicleId = $request->vehicle_id;
|
|
$startDate = $request->start_date;
|
|
$endDate = $request->end_date;
|
|
|
|
$vehicle = CorporateVehicle::where('tenant_id', $tenantId)
|
|
->findOrFail($vehicleId);
|
|
|
|
$logs = VehicleLog::where('tenant_id', $tenantId)
|
|
->where('vehicle_id', $vehicleId)
|
|
->whereBetween('log_date', [$startDate, $endDate])
|
|
->orderBy('log_date')
|
|
->orderBy('id')
|
|
->get();
|
|
|
|
$spreadsheet = new Spreadsheet();
|
|
$sheet = $spreadsheet->getActiveSheet();
|
|
$sheet->setTitle('운행기록부');
|
|
|
|
// 기본 정보
|
|
$sheet->setCellValue('A1', '업무용승용차 운행기록부');
|
|
$sheet->setCellValue('A3', '차량번호');
|
|
$sheet->setCellValue('B3', $vehicle->plate_number);
|
|
$sheet->setCellValue('C3', '차종');
|
|
$sheet->setCellValue('D3', $vehicle->model);
|
|
$sheet->setCellValue('E3', '구분');
|
|
$sheet->setCellValue('F3', $this->getOwnershipTypeLabel($vehicle->ownership_type));
|
|
$sheet->setCellValue('A4', '조회기간');
|
|
$sheet->setCellValue('B4', sprintf('%s ~ %s', $startDate, $endDate));
|
|
|
|
// 헤더
|
|
$headers = ['일자', '부서', '성명', '구분', '출발지', '도착지', '주행km', '비고'];
|
|
$col = 'A';
|
|
foreach ($headers as $header) {
|
|
$sheet->setCellValue($col . '6', $header);
|
|
$col++;
|
|
}
|
|
|
|
// 데이터
|
|
$row = 7;
|
|
$tripTypeLabels = VehicleLog::tripTypeLabels();
|
|
|
|
foreach ($logs as $log) {
|
|
$sheet->setCellValue('A' . $row, $log->log_date->format('Y-m-d'));
|
|
$sheet->setCellValue('B' . $row, $log->department ?? '');
|
|
$sheet->setCellValue('C' . $row, $log->driver_name);
|
|
$sheet->setCellValue('D' . $row, $tripTypeLabels[$log->trip_type] ?? $log->trip_type);
|
|
$sheet->setCellValue('E' . $row, $log->departure_name ?? '');
|
|
$sheet->setCellValue('F' . $row, $log->arrival_name ?? '');
|
|
$sheet->setCellValue('G' . $row, $log->distance_km);
|
|
$sheet->setCellValue('H' . $row, $log->note ?? '');
|
|
$row++;
|
|
}
|
|
|
|
// 합계
|
|
$businessKm = $logs->whereIn('trip_type', ['commute_to', 'commute_from', 'business', 'commute_round', 'business_round'])->sum('distance_km');
|
|
$personalKm = $logs->whereIn('trip_type', ['personal', 'personal_round'])->sum('distance_km');
|
|
$totalKm = $logs->sum('distance_km');
|
|
|
|
$sheet->setCellValue('A' . $row, '합계');
|
|
$sheet->setCellValue('F' . $row, '업무용: ' . number_format($businessKm) . 'km');
|
|
$sheet->setCellValue('G' . $row, number_format($totalKm));
|
|
$sheet->setCellValue('H' . $row, '비업무: ' . number_format($personalKm) . 'km');
|
|
|
|
$filename = sprintf('운행기록부_%s_%s_%s.xlsx', $vehicle->plate_number, $startDate, $endDate);
|
|
|
|
return response()->streamDownload(function () use ($spreadsheet) {
|
|
$writer = new Xlsx($spreadsheet);
|
|
$writer->save('php://output');
|
|
}, $filename, [
|
|
'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
]);
|
|
}
|
|
|
|
private function getOwnershipTypeLabel(string $type): string
|
|
{
|
|
return match ($type) {
|
|
'corporate' => '회사',
|
|
'rent' => '렌트',
|
|
'lease' => '리스',
|
|
default => $type,
|
|
};
|
|
}
|
|
}
|