- VehicleDispatchService: index(검색/필터/페이지네이션), stats(선불/착불/합계), show, update - VehicleDispatchController + VehicleDispatchUpdateRequest - options JSON 컬럼 추가 (dispatch_no, status, freight_cost_type, supply_amount, vat, total_amount, writer) - ShipmentService.syncDispatches에 options 필드 지원 추가 - inventory.php에 vehicle-dispatches 라우트 4개 등록 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
141 lines
4.1 KiB
PHP
141 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Tenants\ShipmentVehicleDispatch;
|
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
|
|
|
class VehicleDispatchService extends Service
|
|
{
|
|
/**
|
|
* 배차차량 목록 조회
|
|
*/
|
|
public function index(array $params): LengthAwarePaginator
|
|
{
|
|
$tenantId = $this->tenantId();
|
|
|
|
$query = ShipmentVehicleDispatch::query()
|
|
->where('tenant_id', $tenantId)
|
|
->with('shipment');
|
|
|
|
// 검색어 필터
|
|
if (! empty($params['search'])) {
|
|
$search = $params['search'];
|
|
$query->where(function ($q) use ($search) {
|
|
$q->where('vehicle_no', 'like', "%{$search}%")
|
|
->orWhere('options->dispatch_no', 'like', "%{$search}%")
|
|
->orWhereHas('shipment', function ($q3) use ($search) {
|
|
$q3->where('lot_no', 'like', "%{$search}%")
|
|
->orWhere('site_name', 'like', "%{$search}%")
|
|
->orWhere('customer_name', 'like', "%{$search}%");
|
|
});
|
|
});
|
|
}
|
|
|
|
// 상태 필터 (options JSON)
|
|
if (! empty($params['status'])) {
|
|
$query->where('options->status', $params['status']);
|
|
}
|
|
|
|
// 날짜 범위 필터
|
|
if (! empty($params['start_date'])) {
|
|
$query->where('arrival_datetime', '>=', $params['start_date']);
|
|
}
|
|
if (! empty($params['end_date'])) {
|
|
$query->where('arrival_datetime', '<=', $params['end_date'].' 23:59:59');
|
|
}
|
|
|
|
// 정렬
|
|
$query->orderBy('id', 'desc');
|
|
|
|
// 페이지네이션
|
|
$perPage = $params['per_page'] ?? 20;
|
|
|
|
return $query->paginate($perPage);
|
|
}
|
|
|
|
/**
|
|
* 배차차량 통계
|
|
*/
|
|
public function stats(): array
|
|
{
|
|
$tenantId = $this->tenantId();
|
|
|
|
$all = ShipmentVehicleDispatch::query()
|
|
->where('tenant_id', $tenantId)
|
|
->get();
|
|
|
|
$prepaid = 0;
|
|
$collect = 0;
|
|
$total = 0;
|
|
|
|
foreach ($all as $dispatch) {
|
|
$opts = $dispatch->options ?? [];
|
|
$amount = (float) ($opts['total_amount'] ?? 0);
|
|
$total += $amount;
|
|
|
|
if (($opts['freight_cost_type'] ?? '') === 'prepaid') {
|
|
$prepaid += $amount;
|
|
}
|
|
if (($opts['freight_cost_type'] ?? '') === 'collect') {
|
|
$collect += $amount;
|
|
}
|
|
}
|
|
|
|
return [
|
|
'prepaid_amount' => $prepaid,
|
|
'collect_amount' => $collect,
|
|
'total_amount' => $total,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 배차차량 상세 조회
|
|
*/
|
|
public function show(int $id): ShipmentVehicleDispatch
|
|
{
|
|
$tenantId = $this->tenantId();
|
|
|
|
return ShipmentVehicleDispatch::query()
|
|
->where('tenant_id', $tenantId)
|
|
->with('shipment')
|
|
->findOrFail($id);
|
|
}
|
|
|
|
/**
|
|
* 배차차량 수정
|
|
*/
|
|
public function update(int $id, array $data): ShipmentVehicleDispatch
|
|
{
|
|
$tenantId = $this->tenantId();
|
|
|
|
$dispatch = ShipmentVehicleDispatch::query()
|
|
->where('tenant_id', $tenantId)
|
|
->findOrFail($id);
|
|
|
|
// options에 저장할 필드 분리
|
|
$optionFields = ['freight_cost_type', 'supply_amount', 'vat', 'total_amount', 'status'];
|
|
$directFields = ['logistics_company', 'arrival_datetime', 'tonnage', 'vehicle_no', 'driver_contact', 'remarks'];
|
|
|
|
// 기존 options 유지하면서 업데이트
|
|
$options = $dispatch->options ?? [];
|
|
foreach ($optionFields as $field) {
|
|
if (array_key_exists($field, $data)) {
|
|
$options[$field] = $data[$field];
|
|
}
|
|
}
|
|
|
|
// 직접 컬럼 업데이트
|
|
$updateData = ['options' => $options];
|
|
foreach ($directFields as $field) {
|
|
if (array_key_exists($field, $data)) {
|
|
$updateData[$field] = $data[$field];
|
|
}
|
|
}
|
|
|
|
$dispatch->update($updateData);
|
|
|
|
return $dispatch->load('shipment');
|
|
}
|
|
}
|