🚐🚢Logistic tracking Project✈️Week1
Tôi làm cho anh “Tuần 1: Tracking core chạy thật” theo đúng kiểu copy → paste → chạy được ngay ⚙️🚀
👉 Scope tuần 1:
DB: shipments + shipment_events + locations
Migration Laravel
Model + relationships
API
/api/tracking/{code}
⚙️ 1. MIGRATIONS (Laravel)
📍 locations
Schema::create('locations', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('type')->nullable(); // port, city
$table->string('country');
$table->string('code')->nullable(); // UN/LOCODE
$table->decimal('latitude', 10, 7)->nullable();
$table->decimal('longitude', 10, 7)->nullable();
$table->timestamps();
});
🚚 shipments
Schema::create('shipments', function (Blueprint $table) {
$table->id();
$table->string('tracking_code')->unique();
$table->enum('type', ['air', 'sea', 'land']);
$table->enum('status', ['pending', 'in_transit', 'delivered'])->default('pending');
$table->foreignId('origin_id')->constrained('locations')->cascadeOnDelete();
$table->foreignId('destination_id')->constrained('locations')->cascadeOnDelete();
$table->timestamp('etd')->nullable();
$table->timestamp('eta')->nullable();
$table->timestamps();
$table->index('tracking_code');
});
📊 shipment_events
Schema::create('shipment_events', function (Blueprint $table) {
$table->id();
$table->foreignId('shipment_id')->constrained()->cascadeOnDelete();
$table->foreignId('location_id')->nullable()->constrained()->nullOnDelete();
$table->string('status');
$table->text('description')->nullable();
$table->timestamp('event_time');
$table->timestamps();
$table->index('shipment_id');
});
🧩 2. MODELS + RELATIONSHIPS
📍 Location.php
class Location extends Model
{
protected $fillable = ['name', 'type', 'country', 'code'];
public function shipmentsOrigin()
{
return $this->hasMany(Shipment::class, 'origin_id');
}
public function shipmentsDestination()
{
return $this->hasMany(Shipment::class, 'destination_id');
}
}
🚚 Shipment.php
class Shipment extends Model
{
protected $fillable = [
'tracking_code',
'type',
'status',
'origin_id',
'destination_id',
'etd',
'eta'
];
public function origin()
{
return $this->belongsTo(Location::class, 'origin_id');
}
public function destination()
{
return $this->belongsTo(Location::class, 'destination_id');
}
public function events()
{
return $this->hasMany(ShipmentEvent::class)->orderBy('event_time', 'desc');
}
}
📊 ShipmentEvent.php
class ShipmentEvent extends Model
{
protected $fillable = [
'shipment_id',
'location_id',
'status',
'description',
'event_time'
];
public function shipment()
{
return $this->belongsTo(Shipment::class);
}
public function location()
{
return $this->belongsTo(Location::class);
}
}
🚀 3. API TRACKING (CHẠY THẬT)
📌 routes/api.php
Route::get('/tracking/{code}', [TrackingController::class, 'show']);
🎯 TrackingController.php
class TrackingController extends Controller
{
public function show($code)
{
$shipment = Shipment::with([
'origin',
'destination',
'events.location'
])->where('tracking_code', $code)->first();
if (!$shipment) {
return response()->json([
'message' => 'Tracking code not found'
], 404);
}
return response()->json([
'tracking_code' => $shipment->tracking_code,
'type' => $shipment->type,
'status' => $shipment->status,
'origin' => $shipment->origin->name,
'destination' => $shipment->destination->name,
'etd' => $shipment->etd,
'eta' => $shipment->eta,
'events' => $shipment->events->map(function ($e) {
return [
'location' => optional($e->location)->name,
'status' => $e->status,
'description' => $e->description,
'time' => $e->event_time
];
})
]);
}
}
🧪 4. SEED DATA TEST (RẤT QUAN TRỌNG)
👉 Tạo nhanh để test API:
$hcm = Location::create(['name' => 'Ho Chi Minh City', 'country' => 'Vietnam']);
$van = Location::create(['name' => 'Vancouver', 'country' => 'Canada']);
$shipment = Shipment::create([
'tracking_code' => 'ABC123456',
'type' => 'sea',
'status' => 'in_transit',
'origin_id' => $van->id,
'destination_id' => $hcm->id,
]);
ShipmentEvent::create([
'shipment_id' => $shipment->id,
'location_id' => $van->id,
'status' => 'Departed',
'description' => 'Left Vancouver Port',
'event_time' => now()->subDays(5)
]);
ShipmentEvent::create([
'shipment_id' => $shipment->id,
'status' => 'In Transit',
'description' => 'On the way to Vietnam',
'event_time' => now()->subDays(2)
]);
🌐 5. TEST API
👉 Gọi:
GET /api/tracking/ABC123456
👉 Response:
{
"tracking_code": "ABC123456",
"type": "sea",
"status": "in_transit",
"origin": "Vancouver",
"destination": "Ho Chi Minh City",
"events": [...]
}
🧨 Kết quả sau Tuần 1
✔️ Có API tracking thật
✔️ Có DB chuẩn
✔️ Có data test
✔️ Frontend gọi là chạy
👉 Tức là:
Anh đã có “xương sống” của hệ thống logistics
🚀 Bước tiếp theo (tuần 2)
RFQ API
Form submit
Email notify
Admin basic
Tôi có thể:
⚡ Viết luôn frontend tracking (Tailwind + AJAX)
🎯 Tạo Postman collection
🧱 Build Filament admin cho shipment
╔══════════════════════════════════╗⚙️ Made by AI – Ship Code, Not Ideas 🚀╚══════════════════════════════════╝
Nhận xét
Đăng nhận xét