feat: H-3 출하 관리 API 구현
- ShipmentController: 출하 CRUD 및 상태 관리 API - ShipmentService: 출하 비즈니스 로직 - Shipment, ShipmentItem 모델 - FormRequest 검증 클래스 - Swagger 문서화 - shipments, shipment_items 테이블 마이그레이션 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('shipments', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('tenant_id')->comment('테넌트 ID');
|
||||
$table->string('shipment_no', 50)->comment('출고번호');
|
||||
$table->string('lot_no', 50)->nullable()->comment('LOT번호');
|
||||
$table->foreignId('order_id')->nullable()->comment('수주 ID');
|
||||
$table->date('scheduled_date')->comment('출고예정일');
|
||||
$table->enum('status', ['scheduled', 'ready', 'shipping', 'completed'])->default('scheduled')->comment('상태: scheduled=출고예정, ready=출하대기, shipping=배송중, completed=배송완료');
|
||||
$table->enum('priority', ['urgent', 'normal', 'low'])->default('normal')->comment('우선순위');
|
||||
$table->enum('delivery_method', ['pickup', 'direct', 'logistics'])->default('pickup')->comment('배송방식: pickup=상차, direct=직접배차, logistics=물류사');
|
||||
|
||||
// 발주처/배송 정보
|
||||
$table->foreignId('client_id')->nullable()->comment('거래처 ID');
|
||||
$table->string('customer_name', 100)->nullable()->comment('발주처명');
|
||||
$table->string('site_name', 100)->nullable()->comment('현장명');
|
||||
$table->string('delivery_address', 255)->nullable()->comment('배송주소');
|
||||
$table->string('receiver', 50)->nullable()->comment('인수자');
|
||||
$table->string('receiver_contact', 50)->nullable()->comment('인수자 연락처');
|
||||
|
||||
// 상태 플래그
|
||||
$table->boolean('can_ship')->default(false)->comment('출하가능 여부');
|
||||
$table->boolean('deposit_confirmed')->default(false)->comment('입금확인 여부');
|
||||
$table->boolean('invoice_issued')->default(false)->comment('세금계산서 발행 여부');
|
||||
$table->string('customer_grade', 20)->nullable()->comment('거래처 등급');
|
||||
|
||||
// 상차 정보
|
||||
$table->string('loading_manager', 50)->nullable()->comment('상차담당자');
|
||||
$table->datetime('loading_completed_at')->nullable()->comment('상차완료 일시');
|
||||
$table->datetime('loading_time')->nullable()->comment('상차시간(입차예정)');
|
||||
|
||||
// 물류/배차 정보
|
||||
$table->string('logistics_company', 50)->nullable()->comment('물류사');
|
||||
$table->string('vehicle_tonnage', 20)->nullable()->comment('차량 톤수');
|
||||
$table->decimal('shipping_cost', 12, 0)->nullable()->comment('운송비');
|
||||
|
||||
// 차량/운전자 정보
|
||||
$table->string('vehicle_no', 20)->nullable()->comment('차량번호');
|
||||
$table->string('driver_name', 50)->nullable()->comment('운전자명');
|
||||
$table->string('driver_contact', 50)->nullable()->comment('운전자 연락처');
|
||||
$table->datetime('expected_arrival')->nullable()->comment('입차예정시간');
|
||||
$table->datetime('confirmed_arrival')->nullable()->comment('입차확정시간');
|
||||
|
||||
// 기타
|
||||
$table->text('remarks')->nullable()->comment('비고');
|
||||
$table->foreignId('created_by')->nullable()->comment('등록자');
|
||||
$table->foreignId('updated_by')->nullable()->comment('수정자');
|
||||
$table->foreignId('deleted_by')->nullable()->comment('삭제자');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// 인덱스
|
||||
$table->unique(['tenant_id', 'shipment_no']);
|
||||
$table->index(['tenant_id', 'status']);
|
||||
$table->index(['tenant_id', 'scheduled_date']);
|
||||
$table->index(['tenant_id', 'lot_no']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('shipments');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('shipment_items', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('tenant_id')->comment('테넌트 ID');
|
||||
$table->foreignId('shipment_id')->comment('출하 ID');
|
||||
$table->integer('seq')->default(1)->comment('순번');
|
||||
$table->string('item_code', 50)->nullable()->comment('품목코드');
|
||||
$table->string('item_name', 100)->comment('품목명');
|
||||
$table->string('floor_unit', 50)->nullable()->comment('층/M호');
|
||||
$table->string('specification', 100)->nullable()->comment('규격');
|
||||
$table->decimal('quantity', 10, 2)->default(0)->comment('수량');
|
||||
$table->string('unit', 20)->nullable()->comment('단위');
|
||||
$table->string('lot_no', 50)->nullable()->comment('LOT번호');
|
||||
$table->foreignId('stock_lot_id')->nullable()->comment('재고 LOT ID');
|
||||
$table->text('remarks')->nullable()->comment('비고');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
// 인덱스
|
||||
$table->index(['shipment_id', 'seq']);
|
||||
$table->index(['tenant_id', 'item_code']);
|
||||
|
||||
// 외래키
|
||||
$table->foreign('shipment_id')->references('id')->on('shipments')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('shipment_items');
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user