Chuyển tới nội dung chính

Order (Đơn Hàng)

Class: \Ecommerce\Models\Order
Alias: Order (đã đăng ký toàn cục)
Table: order
Namespace: Ecommerce\Models


Cấu trúc Cột (Columns)​

Bảng order (cột chính)​

Tên CộtKiểuMặc địnhMô tả
codestring—Mã đơn hàng (tự sinh, VD: 1012)
totalint0Tổng tiền thực tế thanh toán (VND)
statusstringwaitTrạng thái đơn hàng (xem OrderStatus)
status_paystringunpaidTrạng thái thanh toán (xem OrderPay)

Metadata (bảng order_metadata / order_history)​

Các trường mở rộng được tải tự động khi truy vấn Order thông qua Order::data():

Tên FieldMô tả
nameHọ tên khách hàng
phoneSố điện thoại
emailEmail
addressĐịa chỉ giao hàng
cityTỉnh/Thành phố (code)
wardPhường/Xã (code)
noteGhi chú đơn hàng
payment_typeKey cổng thanh toán đã chọn (VD: vnpay, cod)
shipping_typeKey đơn vị vận chuyển đã chọn
shippingPhí vận chuyển (int)
shipping_nameTên đơn vị vận chuyển
discountsMảng các khoản giảm giá được áp dụng
currencyĐối tượng tiền tệ tại thời điểm đặt hàng
user_idID khách hàng (nếu đã đăng nhập)
security_codeMã bảo mật để xác thực callback

Lưu ý: Các trường metadata được gắn tự động vào object Order thông qua event retrieved → Order::data().


Truy Vấn Cơ Bản​

// Lấy đơn hàng theo ID (kèm theo metadata và items)
$order = Order::find(100);
echo $order->name; // Họ tên khách (từ metadata)
echo $order->total; // Tổng tiền
echo $order->status; // 'wait', 'confirm', 'completed'...
echo $order->status_pay; // 'unpaid', 'paid', 'refunded'

// Items của đơn hàng (tự động load)
foreach ($order->items as $item) {
echo $item->title; // Tên sản phẩm
echo $item->quantity; // Số lượng
echo $item->price; // Đơn giá
echo $item->subtotal; // Thành tiền
}

// Tìm theo mã đơn hàng
$order = Order::where('code', '1025')->first();

// Đơn hàng đang chờ xác nhận
$orders = Order::where('status', 'wait')->get();

// Đơn hàng của khách hàng cụ thể (qua metadata user_id)
// Cần join với order_metadata
$orders = Order::whereHasMeta('user_id', $userId)->get();

Model OrderItem​

Class: \Ecommerce\Models\OrderItem
Alias: OrderItem
Table: order_detail

// Lấy tất cả items của đơn hàng
$items = OrderItem::where('order_id', $orderId)->get();

foreach ($items as $item) {
echo $item->title; // Tên sản phẩm
echo $item->product_id; // ID sản phẩm
echo $item->price; // Đơn giá
echo $item->quantity; // Số lượng
echo $item->subtotal; // = price * quantity
// $item->option – mảng biến thể (color, size, variation_id...)
// $item->image – ảnh sản phẩm tại thời điểm đặt
}

Hook pre_insert_order_item_data​

Được gọi trước khi insert OrderItem, dùng để chỉnh sửa dữ liệu:

add_filter('pre_insert_order_item_data', function($data) {
// Lưu thêm thông tin vào option
$data['option']['barcode'] = '...';
return $data;
});

Model OrderHistory​

Class: \Ecommerce\Models\OrderHistory
Table: order_history

Dùng để ghi log lịch sử hành động trên đơn hàng:

use Ecommerce\Models\OrderHistory;

OrderHistory::insert([
'order_id' => $orderId,
'action' => 'your-plugin-action',
'message' => 'Đơn hàng đã được đẩy lên GHTK. Mã vận đơn: GHT123456',
]);

// Lấy lịch sử
$history = OrderHistory::where('order_id', $orderId)
->orderByDesc('created')
->get();

Dùng OrderHistoryService để ghi log theo chuẩn hệ thống:

use Ecommerce\Services\OrderHistoryService;

// Ghi log sau khi tạo đơn (frontend)
OrderHistoryService::add($order);

// Ghi log thay đổi trạng thái
OrderHistoryService::status($order, 'confirm');
OrderHistoryService::statusPay($order, 'paid');

// Ghi log huỷ đơn
OrderHistoryService::cancelled($order, 'Khách yêu cầu hủy');

Trạng Thái Đơn Hàng​

OrderStatus (Enum \Ecommerce\Status\OrderStatus)​

Giá trịTênMàu BadgeMô tả
waitChờ xác nhậngrayĐơn mới tạo
confirmĐã xác nhậncyanAdmin đã xác nhận
wait-pickupChờ lấy hàngyellowĐang chuẩn bị
pickup-failLấy hàng thất bạiwarningCourier không lấy được
pickupĐã lấy hàngpurpleHàng đã được lấy
processingĐang xử lýlimeĐóng gói/xử lý
shipĐang giaoblueĐang trên đường đi
ship-failGiao thất bạipinkGiao không thành công
completedHoàn thànhgreenGiao thành công
cancelledĐã hủyredĐơn bị hủy

OrderPay (Enum \Ecommerce\Status\OrderPay)​

Giá trịTênMô tả
unpaidChưa thanh toánMặc định khi tạo đơn
paidĐã thanh toánĐã nhận tiền
refundedĐã hoàn tiềnĐã trả lại tiền khách
use Ecommerce\Supports\OrderHelper;

// Lấy tất cả trạng thái để dùng cho Select/Radio
$statuses = OrderHelper::status();
// [['wait' => ['label' => 'Chờ xác nhận', 'color' => '#6e7173', 'colorClass' => 'gray']], ...]

// Lấy label của một trạng thái
$label = OrderHelper::status('wait', 'label'); // 'Chờ xác nhận'
$color = OrderHelper::status('confirm', 'color'); // '#186caa'
$badge = OrderHelper::status('completed', 'colorClass'); // 'green'

// Trạng thái thanh toán
$payStatuses = OrderHelper::statusPay();
$payLabel = OrderHelper::statusPay('paid', 'label'); // 'Đã thanh toán'

Hooks Đơn Hàng – Trạng Thái​

admin_order_status_update​

Được gọi sau mỗi lần Admin thay đổi trạng thái đơn.

add_action('admin_order_status_update', function($statusNew, $statusOld) {
$order = Order::find(request()->input('id'));

if($statusNew == 'completed') {
// Bắn API đánh dấu hoàn thành bên kho
Http::post('https://warehouse.api/complete', ['order_id' => $order->id]);
}
}, 10, 2);

admin_order_status_{status}_save​

Hook chính xác cho từng trạng thái cụ thể. Pattern: admin_order_status_{status_value}_save

// Chỉ khi đơn bị HỦY
add_action('admin_order_status_cancelled_save', function($orderId) {
// Hoàn điểm tích lũy
$order = Order::find($orderId);
User::where('id', $order->user_id)->decrement('loyalty_points', 10);
}, 20, 1);

// Chỉ khi đơn hoàn thành
add_action('admin_order_status_completed_save', function($orderId) {
$order = Order::find($orderId);
// Gửi email cảm ơn
}, 10, 1);

admin_order_status_pay_update​

Khi trạng thái thanh toán thay đổi:

add_action('admin_order_status_pay_update', function($statusNew, $statusOld) {
if($statusNew == 'paid') {
// Kích hoạt dịch vụ / tài khoản
}
}, 10, 2);

admin_order_status_pay_{status}_success​

Hook chính xác cho từng trạng thái thanh toán:

add_action('admin_order_status_pay_paid_success', function($orderId) {
// Kích hoạt license key
}, 10, 2);

Helper Tổng Tiền Đơn Hàng​

// Lấy mảng breakdown chi tiết tổng tiền đơn hàng (cho view)
$totals = get_order_item_totals($order);
// [
// ['label' => 'Tạm tính', 'value' => '450.000đ', 'position' => 0],
// ['label' => 'Giao Hàng Nhanh', 'value' => '35.000đ', 'position' => 10],
// ['label' => 'Giảm giá', 'value' => '- 50.000đ', 'position' => 20],
// ['label' => 'Thành tiền', 'value' => '435.000đ', 'position' => 50],
// ]

// Dùng filter để thêm dòng tùy chỉnh vào breakdown
add_filter('get_order_item_totals', function($totals, $order) {
$totals[] = [
'label' => 'Phí xử lý',
'value' => Prd::price(5000),
'position' => 15, // Hiển thị giữa phí ship (10) và discount (20)
];
return $totals;
}, 10, 2);

Tạo Mã Đơn Hàng Tùy Chỉnh​

// Mặc định mã đơn = 1000 + $id → "1012"
// Để tuỳ chỉnh, dùng filter:
add_filter('order_generate_code', function($code) {
$orderId = Order::orderByDesc('id')->value('id');
return 'DH' . str_pad($orderId, 6, '0', STR_PAD_LEFT); // DH000012
});