|
|
@@ -0,0 +1,271 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace Webkul\Shop\Http\Controllers\API;
|
|
|
+
|
|
|
+use Carbon\Carbon;
|
|
|
+use Illuminate\Http\JsonResponse;
|
|
|
+use Illuminate\Http\Request;
|
|
|
+use Longyi\RewardPoints\Helpers\ApiResponse;
|
|
|
+use Webkul\Sales\Models\Order;
|
|
|
+use Webkul\Sales\Repositories\OrderRepository;
|
|
|
+
|
|
|
+class OrderController extends APIController
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * Create a new controller instance.
|
|
|
+ */
|
|
|
+ public function __construct(protected OrderRepository $orderRepository) {}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前客户订单列表(分页)
|
|
|
+ *
|
|
|
+ * @param Request $request
|
|
|
+ * @return JsonResponse
|
|
|
+ */
|
|
|
+ public function index(Request $request): JsonResponse
|
|
|
+ {
|
|
|
+ $customer = auth()->guard('customer')->user();
|
|
|
+ if (! $customer) {
|
|
|
+ return ApiResponse::unauthorized();
|
|
|
+ }
|
|
|
+
|
|
|
+ $page = (int) $request->input('page', 1);
|
|
|
+ $limit = (int) $request->input('limit', 10);
|
|
|
+ $limit = min(max($limit, 1), 100);
|
|
|
+
|
|
|
+ $status = $request->input('status');
|
|
|
+
|
|
|
+ $query = Order::query()
|
|
|
+ ->where('customer_id', $customer->id)
|
|
|
+ ->orderBy('created_at', 'desc');
|
|
|
+
|
|
|
+ if ($status) {
|
|
|
+ $query->where('status', $status);
|
|
|
+ }
|
|
|
+
|
|
|
+ $paginator = $query->paginate($limit, ['*'], 'page', $page);
|
|
|
+
|
|
|
+ $orders = $paginator->through(function ($order) {
|
|
|
+ return $this->formatOrderListItem($order);
|
|
|
+ });
|
|
|
+
|
|
|
+ return ApiResponse::paginated($orders->values(), $paginator);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取订单详情
|
|
|
+ *
|
|
|
+ * @param int $id
|
|
|
+ * @return JsonResponse
|
|
|
+ */
|
|
|
+ public function show(int $id): JsonResponse
|
|
|
+ {
|
|
|
+ $customer = auth()->guard('customer')->user();
|
|
|
+ if (! $customer) {
|
|
|
+ return ApiResponse::unauthorized();
|
|
|
+ }
|
|
|
+
|
|
|
+ $order = Order::query()
|
|
|
+ ->with([
|
|
|
+ 'items' => function ($q) {
|
|
|
+ $q->whereNull('parent_id');
|
|
|
+ },
|
|
|
+ 'items.child',
|
|
|
+ 'items.additional',
|
|
|
+ 'billing_address',
|
|
|
+ 'shipping_address',
|
|
|
+ 'payment',
|
|
|
+ 'invoices',
|
|
|
+ 'invoices.items',
|
|
|
+ 'shipments',
|
|
|
+ 'shipments.items',
|
|
|
+ 'refunds',
|
|
|
+ 'comments',
|
|
|
+ ])
|
|
|
+ ->where('customer_id', $customer->id)
|
|
|
+ ->where('id', $id)
|
|
|
+ ->first();
|
|
|
+
|
|
|
+ if (! $order) {
|
|
|
+ return ApiResponse::notFound('Order not found');
|
|
|
+ }
|
|
|
+
|
|
|
+ return ApiResponse::success($this->formatOrderDetail($order));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 格式化订单列表项
|
|
|
+ */
|
|
|
+ protected function formatOrderListItem(Order $order): array
|
|
|
+ {
|
|
|
+ return [
|
|
|
+ 'id' => $order->id,
|
|
|
+ 'increment_id' => $order->increment_id,
|
|
|
+ 'status' => $order->status,
|
|
|
+ 'status_label' => $this->getStatusLabel($order->status),
|
|
|
+ 'grand_total' => (float) $order->grand_total,
|
|
|
+ 'order_currency_code' => $order->order_currency_code,
|
|
|
+ 'item_count' => $order->items->sum('qty_ordered'),
|
|
|
+ 'items' => $order->items->map(fn ($item) => [
|
|
|
+ 'id' => $item->id,
|
|
|
+ 'name' => $item->name,
|
|
|
+ 'sku' => $item->sku,
|
|
|
+ 'qty_ordered' => $item->qty_ordered,
|
|
|
+ 'price' => (float) $item->price,
|
|
|
+ 'total' => (float) $item->total,
|
|
|
+ 'product_id' => $item->product_id,
|
|
|
+ ])->values(),
|
|
|
+ 'created_at' => $order->created_at ? Carbon::parse($order->created_at)->toDateTimeString() : null,
|
|
|
+ 'can_cancel' => $order->canCancel(),
|
|
|
+ 'can_reorder' => $order->canReorder(),
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 格式化订单详情
|
|
|
+ */
|
|
|
+ protected function formatOrderDetail(Order $order): array
|
|
|
+ {
|
|
|
+ return [
|
|
|
+ 'id' => $order->id,
|
|
|
+ 'increment_id' => $order->increment_id,
|
|
|
+ 'status' => $order->status,
|
|
|
+ 'status_label' => $this->getStatusLabel($order->status),
|
|
|
+ 'customer_email' => $order->customer_email,
|
|
|
+ 'customer_first_name' => $order->customer_first_name,
|
|
|
+ 'customer_last_name' => $order->customer_last_name,
|
|
|
+ 'channel_name' => $order->channel_name,
|
|
|
+ 'order_currency_code' => $order->order_currency_code,
|
|
|
+
|
|
|
+ 'sub_total' => (float) $order->sub_total,
|
|
|
+ 'shipping_amount' => (float) $order->shipping_amount,
|
|
|
+ 'tax_amount' => (float) ($order->tax_amount ?? 0),
|
|
|
+ 'discount_amount' => (float) ($order->discount_amount ?? 0),
|
|
|
+ 'grand_total' => (float) $order->grand_total,
|
|
|
+ 'total_qty_ordered'=> $order->total_qty_ordered,
|
|
|
+
|
|
|
+ 'shipping_method' => $order->shipping_method,
|
|
|
+ 'shipping_title' => $order->shipping_title,
|
|
|
+
|
|
|
+ 'billing_address' => $this->formatAddress($order->billing_address),
|
|
|
+ 'shipping_address' => $this->formatAddress($order->shipping_address),
|
|
|
+
|
|
|
+ 'payment' => $order->payment ? [
|
|
|
+ 'method' => $order->payment->method,
|
|
|
+ 'method_title' => $order->payment->method_title,
|
|
|
+ ] : null,
|
|
|
+
|
|
|
+ 'items' => $order->items->map(fn ($item) => [
|
|
|
+ 'id' => $item->id,
|
|
|
+ 'name' => $item->name,
|
|
|
+ 'sku' => $item->sku,
|
|
|
+ 'type' => $item->type,
|
|
|
+ 'qty_ordered' => $item->qty_ordered,
|
|
|
+ 'qty_shipped' => (int) ($item->qty_shipped ?? 0),
|
|
|
+ 'qty_invoiced' => (int) ($item->qty_invoiced ?? 0),
|
|
|
+ 'qty_canceled' => (int) ($item->qty_canceled ?? 0),
|
|
|
+ 'qty_refunded' => (int) ($item->qty_refunded ?? 0),
|
|
|
+ 'price' => (float) $item->price,
|
|
|
+ 'total' => (float) $item->total,
|
|
|
+ 'weight' => (float) ($item->weight ?? 0),
|
|
|
+ 'product_id' => $item->product_id,
|
|
|
+ 'additional' => $item->additional ? $item->additional->toArray() : null,
|
|
|
+ ])->values(),
|
|
|
+
|
|
|
+ 'invoices' => $order->invoices->map(fn ($invoice) => [
|
|
|
+ 'id' => $invoice->id,
|
|
|
+ 'increment_id' => $invoice->increment_id ?? ('#' . $invoice->id),
|
|
|
+ 'state' => $invoice->state,
|
|
|
+ 'email_sent' => $invoice->email_sent,
|
|
|
+ 'total_qty' => $invoice->total_qty,
|
|
|
+ 'sub_total' => (float) $invoice->sub_total,
|
|
|
+ 'grand_total' => (float) $invoice->grand_total,
|
|
|
+ 'created_at' => $invoice->created_at ? Carbon::parse($invoice->created_at)->toDateTimeString() : null,
|
|
|
+ 'items' => $invoice->items->map(fn ($invItem) => [
|
|
|
+ 'name' => $invItem->name,
|
|
|
+ 'qty' => $invItem->qty,
|
|
|
+ 'price' => (float) $invItem->price,
|
|
|
+ 'total' => (float) $invItem->total,
|
|
|
+ ])->values(),
|
|
|
+ ])->values(),
|
|
|
+
|
|
|
+ 'shipments' => $order->shipments->map(fn ($shipment) => [
|
|
|
+ 'id' => $shipment->id,
|
|
|
+ 'increment_id' => $shipment->increment_id ?? ('#' . $shipment->id),
|
|
|
+ 'status' => $shipment->status,
|
|
|
+ 'total_qty' => $shipment->total_qty,
|
|
|
+ 'total_weight' => (float) $shipment->total_weight,
|
|
|
+ 'carrier_code' => $shipment->carrier_code,
|
|
|
+ 'carrier_title'=> $shipment->carrier_title,
|
|
|
+ 'track_number' => $shipment->track_number,
|
|
|
+ 'created_at' => $shipment->created_at ? Carbon::parse($shipment->created_at)->toDateTimeString() : null,
|
|
|
+ 'items' => $shipment->items->map(fn ($shipItem) => [
|
|
|
+ 'name' => $shipItem->name,
|
|
|
+ 'qty' => $shipItem->qty,
|
|
|
+ ])->values(),
|
|
|
+ ])->values(),
|
|
|
+
|
|
|
+ 'refunds' => $order->refunds->map(fn ($refund) => [
|
|
|
+ 'id' => $refund->id,
|
|
|
+ 'increment_id' => $refund->increment_id ?? ('#' . $refund->id),
|
|
|
+ 'state' => $refund->state,
|
|
|
+ 'total_qty' => $refund->total_qty,
|
|
|
+ 'grand_total' => (float) $refund->grand_total,
|
|
|
+ 'created_at' => $refund->created_at ? Carbon::parse($refund->created_at)->toDateTimeString() : null,
|
|
|
+ ])->values(),
|
|
|
+
|
|
|
+ 'comments' => $order->comments->map(fn ($comment) => [
|
|
|
+ 'comment' => $comment->comment,
|
|
|
+ 'customer_notified' => $comment->customer_notified,
|
|
|
+ 'created_at' => $comment->created_at ? Carbon::parse($comment->created_at)->toDateTimeString() : null,
|
|
|
+ ])->values(),
|
|
|
+
|
|
|
+ 'can_cancel' => $order->canCancel(),
|
|
|
+ 'can_reorder' => $order->canReorder(),
|
|
|
+
|
|
|
+ 'created_at' => $order->created_at ? Carbon::parse($order->created_at)->toDateTimeString() : null,
|
|
|
+ 'updated_at' => $order->updated_at ? Carbon::parse($order->updated_at)->toDateTimeString() : null,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 格式化地址
|
|
|
+ */
|
|
|
+ protected function formatAddress($address): ?array
|
|
|
+ {
|
|
|
+ if (! $address) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'first_name' => $address->first_name,
|
|
|
+ 'last_name' => $address->last_name,
|
|
|
+ 'email' => $address->email,
|
|
|
+ 'phone' => $address->phone,
|
|
|
+ 'address1' => $address->address1,
|
|
|
+ 'address2' => $address->address2,
|
|
|
+ 'city' => $address->city,
|
|
|
+ 'state' => $address->state,
|
|
|
+ 'country' => $address->country,
|
|
|
+ 'postcode' => $address->postcode,
|
|
|
+ 'company' => $address->company_name,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取状态中文标签
|
|
|
+ */
|
|
|
+ protected function getStatusLabel(string $status): string
|
|
|
+ {
|
|
|
+ return match ($status) {
|
|
|
+ Order::STATUS_PENDING => '待处理',
|
|
|
+ Order::STATUS_PENDING_PAYMENT => '待付款',
|
|
|
+ Order::STATUS_PROCESSING => '处理中',
|
|
|
+ Order::STATUS_COMPLETED => '已完成',
|
|
|
+ Order::STATUS_CANCELED => '已取消',
|
|
|
+ Order::STATUS_CLOSED => '已关闭',
|
|
|
+ Order::STATUS_FRAUD => '欺诈',
|
|
|
+ default => $status,
|
|
|
+ };
|
|
|
+ }
|
|
|
+}
|