refactor: [shipment] 배차 정보를 shipment_vehicle_dispatches로 일원화
- shipments 테이블에서 배차 관련 컬럼 8개 삭제 (vehicle_no, driver_name 등) - shipping 전환 시 배차 정보를 vehicle_dispatches에 저장 - delivery_method ENUM → VARCHAR 변경 (common_codes 기반) - VehicleDispatchService에 수주/작성자 관계 로딩 추가 - Swagger delivery_method enum 제약 제거 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,17 +41,6 @@ public function rules(): array
|
||||
'loading_manager' => 'nullable|string|max:50',
|
||||
'loading_time' => 'nullable|date',
|
||||
|
||||
// 물류/배차 정보
|
||||
'logistics_company' => 'nullable|string|max:50',
|
||||
'vehicle_tonnage' => 'nullable|string|max:20',
|
||||
'shipping_cost' => 'nullable|numeric|min:0',
|
||||
|
||||
// 차량/운전자 정보
|
||||
'vehicle_no' => 'nullable|string|max:20',
|
||||
'driver_name' => 'nullable|string|max:50',
|
||||
'driver_contact' => 'nullable|string|max:50',
|
||||
'expected_arrival' => 'nullable|date',
|
||||
|
||||
// 기타
|
||||
'remarks' => 'nullable|string',
|
||||
|
||||
|
||||
@@ -39,17 +39,6 @@ public function rules(): array
|
||||
'loading_manager' => 'nullable|string|max:50',
|
||||
'loading_time' => 'nullable|date',
|
||||
|
||||
// 물류/배차 정보
|
||||
'logistics_company' => 'nullable|string|max:50',
|
||||
'vehicle_tonnage' => 'nullable|string|max:20',
|
||||
'shipping_cost' => 'nullable|numeric|min:0',
|
||||
|
||||
// 차량/운전자 정보
|
||||
'vehicle_no' => 'nullable|string|max:20',
|
||||
'driver_name' => 'nullable|string|max:50',
|
||||
'driver_contact' => 'nullable|string|max:50',
|
||||
'expected_arrival' => 'nullable|date',
|
||||
|
||||
// 기타
|
||||
'remarks' => 'nullable|string',
|
||||
|
||||
|
||||
@@ -42,16 +42,6 @@ class Shipment extends Model
|
||||
'loading_manager',
|
||||
'loading_completed_at',
|
||||
'loading_time',
|
||||
// 물류/배차 정보
|
||||
'logistics_company',
|
||||
'vehicle_tonnage',
|
||||
'shipping_cost',
|
||||
// 차량/운전자 정보
|
||||
'vehicle_no',
|
||||
'driver_name',
|
||||
'driver_contact',
|
||||
'expected_arrival',
|
||||
'confirmed_arrival',
|
||||
// 기타
|
||||
'remarks',
|
||||
'created_by',
|
||||
@@ -66,9 +56,6 @@ class Shipment extends Model
|
||||
'invoice_issued' => 'boolean',
|
||||
'loading_completed_at' => 'datetime',
|
||||
'loading_time' => 'datetime',
|
||||
'expected_arrival' => 'datetime',
|
||||
'confirmed_arrival' => 'datetime',
|
||||
'shipping_cost' => 'decimal:0',
|
||||
'order_id' => 'integer',
|
||||
'work_order_id' => 'integer',
|
||||
'client_id' => 'integer',
|
||||
|
||||
@@ -239,15 +239,6 @@ public function store(array $data): Shipment
|
||||
// 상차 정보
|
||||
'loading_manager' => $data['loading_manager'] ?? null,
|
||||
'loading_time' => $data['loading_time'] ?? null,
|
||||
// 물류/배차 정보
|
||||
'logistics_company' => $data['logistics_company'] ?? null,
|
||||
'vehicle_tonnage' => $data['vehicle_tonnage'] ?? null,
|
||||
'shipping_cost' => $data['shipping_cost'] ?? null,
|
||||
// 차량/운전자 정보
|
||||
'vehicle_no' => $data['vehicle_no'] ?? null,
|
||||
'driver_name' => $data['driver_name'] ?? null,
|
||||
'driver_contact' => $data['driver_contact'] ?? null,
|
||||
'expected_arrival' => $data['expected_arrival'] ?? null,
|
||||
// 기타
|
||||
'remarks' => $data['remarks'] ?? null,
|
||||
'created_by' => $userId,
|
||||
@@ -299,15 +290,6 @@ public function update(int $id, array $data): Shipment
|
||||
// 상차 정보
|
||||
'loading_manager' => $data['loading_manager'] ?? $shipment->loading_manager,
|
||||
'loading_time' => $data['loading_time'] ?? $shipment->loading_time,
|
||||
// 물류/배차 정보
|
||||
'logistics_company' => $data['logistics_company'] ?? $shipment->logistics_company,
|
||||
'vehicle_tonnage' => $data['vehicle_tonnage'] ?? $shipment->vehicle_tonnage,
|
||||
'shipping_cost' => $data['shipping_cost'] ?? $shipment->shipping_cost,
|
||||
// 차량/운전자 정보
|
||||
'vehicle_no' => $data['vehicle_no'] ?? $shipment->vehicle_no,
|
||||
'driver_name' => $data['driver_name'] ?? $shipment->driver_name,
|
||||
'driver_contact' => $data['driver_contact'] ?? $shipment->driver_contact,
|
||||
'expected_arrival' => $data['expected_arrival'] ?? $shipment->expected_arrival,
|
||||
// 기타
|
||||
'remarks' => $data['remarks'] ?? $shipment->remarks,
|
||||
'updated_by' => $userId,
|
||||
@@ -360,25 +342,26 @@ public function updateStatus(int $id, string $status, ?array $additionalData = n
|
||||
} else {
|
||||
$updateData['loading_completed_at'] = now();
|
||||
}
|
||||
|
||||
if (isset($additionalData['vehicle_no'])) {
|
||||
$updateData['vehicle_no'] = $additionalData['vehicle_no'];
|
||||
}
|
||||
if (isset($additionalData['driver_name'])) {
|
||||
$updateData['driver_name'] = $additionalData['driver_name'];
|
||||
}
|
||||
if (isset($additionalData['driver_contact'])) {
|
||||
$updateData['driver_contact'] = $additionalData['driver_contact'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($status === 'completed' && isset($additionalData['confirmed_arrival'])) {
|
||||
$updateData['confirmed_arrival'] = $additionalData['confirmed_arrival'];
|
||||
}
|
||||
|
||||
$previousStatus = $shipment->status;
|
||||
$shipment->update($updateData);
|
||||
|
||||
// shipping 전환 시 배차 정보를 shipment_vehicle_dispatches에 저장
|
||||
if ($status === 'shipping' && $additionalData) {
|
||||
$nextSeq = $shipment->vehicleDispatches()->max('seq') ?? 0;
|
||||
ShipmentVehicleDispatch::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'shipment_id' => $shipment->id,
|
||||
'seq' => $nextSeq + 1,
|
||||
'vehicle_no' => $additionalData['vehicle_no'] ?? null,
|
||||
'driver_contact' => $additionalData['driver_contact'] ?? null,
|
||||
'logistics_company' => $additionalData['logistics_company'] ?? null,
|
||||
'tonnage' => $additionalData['vehicle_tonnage'] ?? null,
|
||||
'arrival_datetime' => $additionalData['confirmed_arrival'] ?? null,
|
||||
]);
|
||||
}
|
||||
|
||||
// 재고 차감 비활성화: 수주생산은 재고 미경유, 선생산 완성품은 자재 투입 시 차감됨
|
||||
// TODO: 선생산 로직 검증 후 재검토 (decreaseStockForShipment)
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ public function index(array $params): LengthAwarePaginator
|
||||
|
||||
$query = ShipmentVehicleDispatch::query()
|
||||
->where('tenant_id', $tenantId)
|
||||
->with('shipment');
|
||||
->with(['shipment.order.client', 'shipment.order.writer', 'shipment.creator']);
|
||||
|
||||
// 검색어 필터
|
||||
if (! empty($params['search'])) {
|
||||
@@ -98,7 +98,7 @@ public function show(int $id): ShipmentVehicleDispatch
|
||||
|
||||
return ShipmentVehicleDispatch::query()
|
||||
->where('tenant_id', $tenantId)
|
||||
->with('shipment')
|
||||
->with(['shipment.order.client', 'shipment.order.writer', 'shipment.creator'])
|
||||
->findOrFail($id);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ public function update(int $id, array $data): ShipmentVehicleDispatch
|
||||
->findOrFail($id);
|
||||
|
||||
// options에 저장할 필드 분리
|
||||
$optionFields = ['freight_cost_type', 'supply_amount', 'vat', 'total_amount', 'status'];
|
||||
$optionFields = ['freight_cost_type', 'supply_amount', 'vat', 'total_amount'];
|
||||
$directFields = ['logistics_company', 'arrival_datetime', 'tonnage', 'vehicle_no', 'driver_contact', 'remarks'];
|
||||
|
||||
// 기존 options 유지하면서 업데이트
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* @OA\Property(property="status_label", type="string", example="출고예정", description="상태 라벨"),
|
||||
* @OA\Property(property="priority", type="string", enum={"urgent","normal","low"}, example="normal", description="우선순위"),
|
||||
* @OA\Property(property="priority_label", type="string", example="보통", description="우선순위 라벨"),
|
||||
* @OA\Property(property="delivery_method", type="string", enum={"pickup","direct","logistics"}, example="pickup", description="배송방식"),
|
||||
* @OA\Property(property="delivery_method", type="string", example="pickup", description="배송방식 (common_codes delivery_method 참조)"),
|
||||
* @OA\Property(property="delivery_method_label", type="string", example="상차", description="배송방식 라벨"),
|
||||
* @OA\Property(property="client_id", type="integer", nullable=true, description="거래처 ID"),
|
||||
* @OA\Property(property="customer_name", type="string", example="(주)고객사", nullable=true, description="발주처명"),
|
||||
@@ -147,7 +147,7 @@
|
||||
* @OA\Property(property="scheduled_date", type="string", format="date", example="2025-12-26", description="출고예정일"),
|
||||
* @OA\Property(property="status", type="string", enum={"scheduled","ready","shipping","completed"}, example="scheduled", description="상태"),
|
||||
* @OA\Property(property="priority", type="string", enum={"urgent","normal","low"}, example="normal", description="우선순위"),
|
||||
* @OA\Property(property="delivery_method", type="string", enum={"pickup","direct","logistics"}, example="pickup", description="배송방식"),
|
||||
* @OA\Property(property="delivery_method", type="string", example="pickup", description="배송방식 (common_codes delivery_method 참조)"),
|
||||
* @OA\Property(property="client_id", type="integer", description="거래처 ID"),
|
||||
* @OA\Property(property="customer_name", type="string", example="(주)고객사", description="발주처명"),
|
||||
* @OA\Property(property="site_name", type="string", example="서울현장", description="현장명"),
|
||||
@@ -232,7 +232,7 @@ class ShipmentApi
|
||||
* @OA\Parameter(name="search", in="query", description="검색어 (출하번호, LOT번호, 발주처명, 현장명)", @OA\Schema(type="string")),
|
||||
* @OA\Parameter(name="status", in="query", description="상태", @OA\Schema(type="string", enum={"scheduled","ready","shipping","completed"})),
|
||||
* @OA\Parameter(name="priority", in="query", description="우선순위", @OA\Schema(type="string", enum={"urgent","normal","low"})),
|
||||
* @OA\Parameter(name="delivery_method", in="query", description="배송방식", @OA\Schema(type="string", enum={"pickup","direct","logistics"})),
|
||||
* @OA\Parameter(name="delivery_method", in="query", description="배송방식 (common_codes delivery_method 참조)", @OA\Schema(type="string")),
|
||||
* @OA\Parameter(name="scheduled_from", in="query", description="예정일 시작", @OA\Schema(type="string", format="date")),
|
||||
* @OA\Parameter(name="scheduled_to", in="query", description="예정일 종료", @OA\Schema(type="string", format="date")),
|
||||
* @OA\Parameter(name="can_ship", in="query", description="출하가능 여부", @OA\Schema(type="boolean")),
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* 배차 정보를 shipment_vehicle_dispatches 테이블로 일원화
|
||||
* shipments 테이블의 배차 관련 컬럼 삭제
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('shipments', function (Blueprint $table) {
|
||||
$table->dropColumn([
|
||||
'logistics_company',
|
||||
'vehicle_tonnage',
|
||||
'shipping_cost',
|
||||
'vehicle_no',
|
||||
'driver_name',
|
||||
'driver_contact',
|
||||
'expected_arrival',
|
||||
'confirmed_arrival',
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('shipments', function (Blueprint $table) {
|
||||
$table->string('logistics_company', 50)->nullable()->after('loading_time');
|
||||
$table->string('vehicle_tonnage', 20)->nullable()->after('logistics_company');
|
||||
$table->decimal('shipping_cost', 10, 0)->nullable()->after('vehicle_tonnage');
|
||||
$table->string('vehicle_no', 20)->nullable()->after('shipping_cost');
|
||||
$table->string('driver_name', 50)->nullable()->after('vehicle_no');
|
||||
$table->string('driver_contact', 50)->nullable()->after('driver_name');
|
||||
$table->datetime('expected_arrival')->nullable()->after('driver_contact');
|
||||
$table->datetime('confirmed_arrival')->nullable()->after('expected_arrival');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* shipments.delivery_method: ENUM → VARCHAR 변경
|
||||
*
|
||||
* ENUM은 값 추가 시마다 마이그레이션이 필요하므로,
|
||||
* common_codes 기반 VARCHAR로 변경하여 유연하게 관리
|
||||
*/
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
DB::statement("ALTER TABLE `shipments` MODIFY `delivery_method` VARCHAR(30) NOT NULL DEFAULT 'pickup' COMMENT '배송방식 (common_codes delivery_method 참조)'");
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
DB::statement("UPDATE `shipments` SET `delivery_method` = 'pickup' WHERE `delivery_method` NOT IN ('pickup', 'direct', 'logistics')");
|
||||
DB::statement("ALTER TABLE `shipments` MODIFY `delivery_method` ENUM('pickup', 'direct', 'logistics') NOT NULL DEFAULT 'pickup' COMMENT '배송방식: pickup=상차, direct=직접배차, logistics=물류사'");
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user