erp-backend/app/Http/Controllers/OrderController_new.php
2026-04-01 17:07:04 +08:00

1363 lines
44 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Http\Controllers;
use App\Http\Requests\OrderRequest;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Stock;
use App\Models\StockLog;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class OrderController extends Controller
{
/**
* 订单列表
*/
public function index(Request $request)
{
$query = Order::with(['items', 'warehouse'])
->orderBy('created_at', 'desc');
// 筛选条件
if ($request->filled('platform')) {
$query->where('platform', $request->platform);
}
if ($request->filled('shop_id')) {
$query->where('shop_id', $request->shop_id);
}
if ($request->filled('order_status')) {
$query->where('order_status', $request->order_status);
}
if ($request->filled('audit_status')) {
$query->where('audit_status', $request->audit_status);
}
if ($request->filled('delivery_status')) {
$query->where('delivery_status', $request->delivery_status);
}
if ($request->filled('keyword')) {
$keyword = $request->keyword;
$query->where(function ($q) use ($keyword) {
$q->where('short_id', 'like', "%{$keyword}%")
->orWhere('platform_order_sn', 'like', "%{$keyword}%")
->orWhere('receiver_name', 'like', "%{$keyword}%")
->orWhere('receiver_phone', 'like', "%{$keyword}%");
});
}
if ($request->filled('date_range')) {
$dates = explode(',', $request->date_range);
if (count($dates) === 2) {
$query->whereBetween('order_time', [$dates[0], $dates[1]]);
}
}
$perPage = $request->input('limit', 10);
$orders = $query->paginate($perPage);
return response()->json([
'code' => 200,
'data' => [
'list' => $orders->items(),
'total' => $orders->total(),
'current_page' => $orders->currentPage(),
'last_page' => $orders->lastPage(),
],
'message' => 'success'
]);
}
/**
* 订单详情
*/
public function show(string $id)
{
$order = Order::with(['items', 'warehouse'])->find($id);
if (!$order) {
return response()->json([
'code' => 404,
'message' => '订单不存在'
], 404);
}
return response()->json([
'code' => 200,
'data' => $order,
'message' => 'success'
]);
}
/**
* 手动拉取订单
*/
public function pullOrders(Request $request)
{
$request->validate([
'platform' => 'required|string',
'shop_id' => 'required|integer',
'pull_type' => 'required|in:all,increment,specify',
'order_ids' => 'required_if:pull_type,specify|string',
'start_time' => 'nullable|date',
'end_time' => 'nullable|date',
]);
// TODO: 这里应该调用平台API拉取订单
// 暂时返回模拟数据
$mockOrders = [
[
'platform_order_sn' => 'TEST' . Str::random(10),
'order_time' => now()->toDateTimeString(),
'buyer_nick' => '测试买家',
'receiver_name' => '张三',
'receiver_phone' => '13800138000',
'receiver_address' => '测试地址',
'goods_amount' => 199.00,
'discount_amount' => 0,
'freight' => 10.00,
'total_amount' => 209.00,
'platform_status' => 'WAIT_SELLER_SEND_GOODS',
'items' => [
[
'goods_name' => '测试商品',
'platform_sku' => 'SKU001',
'quantity' => 1,
'price' => 199.00,
'total_amount' => 199.00,
]
]
]
];
$createdCount = 0;
try {
DB::beginTransaction();
foreach ($mockOrders as $orderData) {
// 生成短ID
$shortId = 'O' . date('Ymd') . strtoupper(Str::random(6));
$order = Order::create([
'short_id' => $shortId,
'platform_order_sn' => $orderData['platform_order_sn'],
'platform' => $request->platform,
'shop_id' => $request->shop_id,
'shop_name' => '测试店铺',
'order_time' => $orderData['order_time'],
'buyer_nick' => $orderData['buyer_nick'],
'receiver_name' => $orderData['receiver_name'],
'receiver_phone' => $orderData['receiver_phone'],
'receiver_address' => $orderData['receiver_address'],
'goods_amount' => $orderData['goods_amount'],
'discount_amount' => $orderData['discount_amount'],
'freight' => $orderData['freight'],
'total_amount' => $orderData['total_amount'],
'order_status' => 'pending',
'platform_status' => $orderData['platform_status'],
'audit_status' => 'pending',
'delivery_status' => 'pending',
]);
// 创建订单项
foreach ($orderData['items'] as $itemData) {
OrderItem::create([
'order_id' => $order->id,
'goods_name' => $itemData['goods_name'],
'platform_sku' => $itemData['platform_sku'],
'quantity' => $itemData['quantity'],
'price' => $itemData['price'],
'total_amount' => $itemData['total_amount'],
]);
}
$createdCount++;
}
DB::commit();
return response()->json([
'code' => 200,
'data' => ['count' => $createdCount],
'message' => "成功拉取 {$createdCount} 个订单"
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'code' => 500,
'message' => '拉取失败: ' . $e->getMessage()
], 500);
}
}
/**
* 批量审核订单
*/
public function batchAudit(Request $request)
{
$request->validate([
'order_ids' => 'required|array|min:1',
'order_ids.*' => 'integer|exists:orders,id',
'action' => 'required|in:approve,reject',
'comment' => 'required_if:action,reject|string|max:500',
]);
$successCount = 0;
$failedOrders = [];
try {
DB::beginTransaction();
foreach ($request->order_ids as $orderId) {
$order = Order::find($orderId);
if (!$order) {
$failedOrders[] = ['id' => $orderId, 'reason' => '订单不存在'];
continue;
}
// 只有待审核状态的订单可以审核
if ($order->audit_status !== 'pending') {
$failedOrders[] = ['id' => $orderId, 'reason' => '订单状态不可审核'];
continue;
}
$order->update([
'audit_status' => $request->action === 'approve' ? 'approved' : 'rejected',
'audit_comment' => $request->comment,
'order_status' => $request->action === 'approve' ? 'auditing' : 'pending',
]);
$successCount++;
}
DB::commit();
return response()->json([
'code' => 200,
'data' => [
'success_count' => $successCount,
'failed_orders' => $failedOrders,
],
'message' => "成功审核 {$successCount} 个订单"
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'code' => 500,
'message' => '审核失败: ' . $e->getMessage()
], 500);
}
}
/**
* 单个订单审核
*/
public function auditOrder(Request $request, string $id)
{
$request->validate([
'action' => 'required|in:approve,reject',
'comment' => 'required_if:action,reject|string|max:500',
]);
$order = Order::find($id);
if (!$order) {
return response()->json([
'code' => 404,
'message' => '订单不存在'
], 404);
}
// 只有待审核状态的订单可以审核
if ($order->audit_status !== 'pending') {
return response()->json([
'code' => 400,
'message' => '订单状态不可审核'
], 400);
}
$order->update([
'audit_status' => $request->action === 'approve' ? 'approved' : 'rejected',
'audit_comment' => $request->comment,
'order_status' => $request->action === 'approve' ? 'auditing' : 'pending',
]);
return response()->json([
'code' => 200,
'message' => $request->action === 'approve' ? '订单审核通过' : '订单已驳回'
]);
}
/**
* 设置仓库和快递
*/
public function setWarehouseExpress(Request $request, string $id)
{
$request->validate([
'warehouse_id' => 'nullable|integer|exists:warehouses,id',
'express_company' => 'nullable|string|max:50',
'express_name' => 'nullable|string|max:50',
'express_template_id' => 'nullable|integer|exists:templates,id',
]);
$order = Order::find($id);
if (!$order) {
return response()->json([
'code' => 404,
'message' => '订单不存在'
], 404);
}
// 只有已审核的订单可以设置仓库和快递
if ($order->audit_status !== 'approved') {
return response()->json([
'code' => 400,
'message' => '只有已审核的订单可以设置仓库和快递'
], 400);
}
$order->update([
'warehouse_id' => $request->warehouse_id ?? $order->warehouse_id,
'express_company' => $request->express_company ?? $order->express_company,
'express_name' => $request->express_name ?? $order->express_name,
]);
return response()->json([
'code' => 200,
'message' => '设置成功'
]);
}
/**
* 发货
*/
public function shipOrder(Request $request, string $id)
{
$request->validate([
'express_company' => 'required|string|max:50',
'express_no' => 'required|string|max:50',
'is_print' => 'nullable|boolean',
]);
$order = Order::with('items')->find($id);
if (!$order) {
return response()->json([
'code' => 404,
'message' => '订单不存在'
], 404);
}
// 检查订单状态
if ($order->order_status !== 'auditing') {
return response()->json([
'code' => 400,
'message' => '只有待发货的订单可以发货'
], 400);
}
// 检查是否设置了仓库
if (!$order->warehouse_id) {
return response()->json([
'code' => 400,
'message' => '请先设置发货仓库'
], 400);
}
try {
DB::beginTransaction();
// 更新订单状态
$order->update([
'express_company' => $request->express_company,
'express_no' => $request->express_no,
'delivery_status' => 'delivered',
'delivery_time' => now(),
'order_status' => 'shipped',
]);
// 扣减库存
foreach ($order->items as $item) {
if ($item->erp_sku) {
$this->deductStock(
$order->warehouse_id,
$item->erp_sku,
$item->quantity,
$order->short_id
);
}
}
DB::commit();
return response()->json([
'code' => 200,
'message' => '发货成功'
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'code' => 500,
'message' => '发货失败: ' . $e->getMessage()
], 500);
}
}
/**
* 扣减库存
*/
private function deductStock($warehouseId, $skuCode, $quantity, $relatedNo)
{
$stock = Stock::where('warehouse_id', $warehouseId)
->where('sku_code', $skuCode)
->first();
if (!$stock) {
throw new \Exception("商品 {$skuCode} 在仓库中不存在");
}
if ($stock->available_quantity < $quantity) {
throw new \Exception("商品 {$skuCode} 库存不足,可用库存: {$stock->available_quantity}");
}
$stock->decrement('quantity', $quantity);
// 记录库存流水
StockLog::create([
'sku_code' => $skuCode,
'warehouse_id' => $warehouseId,
'change_quantity' => -$quantity,
'type' => 'order_ship',
'related_no' => $relatedNo,
'remark' => '订单发货出库',
]);
}
/**
* 订单统计
*/
public function statistics(Request $request)
{
$query = Order::query();
// 时间范围筛选
if ($request->filled('start_date')) {
$query->where('order_time', '>=', $request->start_date);
}
if ($request->filled('end_date')) {
$query->where('order_time', '<=', $request->end_date);
}
// 平台筛选
if ($request->filled('platform')) {
$query->where('platform', $request->platform);
}
// 店铺筛选
if ($request->filled('shop_id')) {
$query->where('shop_id', $request->shop_id);
}
// 订单状态统计
$statusStats = [
'pending' => (clone $query)->where('order_status', 'pending')->count(),
'auditing' => (clone $query)->where('order_status', 'auditing')->count(),
'shipped' => (clone $query)->where('order_status', 'shipped')->count(),
'completed' => (clone $query)->where('order_status', 'completed')->count(),
'cancelled' => (clone $query)->where('order_status', 'cancelled')->count(),
];
// 审核状态统计
$auditStats = [
'pending' => (clone $query)->where('audit_status', 'pending')->count(),
'approved' => (clone $query)->where('audit_status', 'approved')->count(),
'rejected' => (clone $query)->where('audit_status', 'rejected')->count(),
];
// 发货状态统计
$deliveryStats = [
'pending' => (clone $query)->where('delivery_status', 'pending')->count(),
'delivered' => (clone $query)->where('delivery_status', 'delivered')->count(),
];
// 金额统计
$amountStats = [
'total_goods_amount' => (clone $query)->sum('goods_amount'),
'total_discount_amount' => (clone $query)->sum('discount_amount'),
'total_freight' => (clone $query)->sum('freight'),
'total_amount' => (clone $query)->sum('total_amount'),
'avg_order_amount' => (clone $query)->avg('total_amount') ?? 0,
];
// 平台分布统计
$platformStats = Order::select('platform', DB::raw('count(*) as count'), DB::raw('sum(total_amount) as amount'))
->when($request->filled('start_date'), function ($q) use ($request) {
$q->where('order_time', '>=', $request->start_date);
})
->when($request->filled('end_date'), function ($q) use ($request) {
$q->where('order_time', '<=', $request->end_date);
})
->groupBy('platform')
->get()
->map(function ($item) {
return [
'platform' => $item->platform,
'count' => $item->count,
'amount' => (float) $item->amount,
];
});
// 时间趋势统计(按天)
$dateFormat = $request->input('date_format', 'day'); // day, week, month
$format = $dateFormat === 'day' ? '%Y-%m-%d' : ($dateFormat === 'week' ? '%Y-%U' : '%Y-%m');
$trendStats = Order::select(
DB::raw("DATE_FORMAT(order_time, '{$format}') as date_group"),
DB::raw('count(*) as order_count'),
DB::raw('sum(total_amount) as total_amount')
)
->when($request->filled('start_date'), function ($q) use ($request) {
$q->where('order_time', '>=', $request->start_date);
})
->when($request->filled('end_date'), function ($q) use ($request) {
$q->where('order_time', '<=', $request->end_date);
})
->groupBy('date_group')
->orderBy('date_group')
->get();
return response()->json([
'code' => 200,
'data' => [
'status_stats' => $statusStats,
'audit_stats' => $auditStats,
'delivery_stats' => $deliveryStats,
'amount_stats' => $amountStats,
'platform_stats' => $platformStats,
'trend_stats' => $trendStats,
'total_orders' => array_sum($statusStats),
'date_range' => [
'start_date' => $request->start_date,
'end_date' => $request->end_date,
],
],
'message' => 'success'
]);
}
/**
* 订单导出
*/
public function export(Request $request)
{
$request->validate([
'export_type' => 'required|in:excel,csv',
'order_ids' => 'nullable|array',
'order_ids.*' => 'integer|exists:orders,id',
'start_date' => 'nullable|date',
'end_date' => 'nullable|date',
'platform' => 'nullable|string',
'order_status' => 'nullable|string',
'audit_status' => 'nullable|string',
'delivery_status' => 'nullable|string',
]);
$query = Order::with(['items', 'warehouse']);
// 筛选条件
if ($request->filled('order_ids')) {
$query->whereIn('id', $request->order_ids);
}
if ($request->filled('start_date')) {
$query->where('order_time', '>=', $request->start_date);
}
if ($request->filled('end_date')) {
$query->where('order_time', '<=', $request->end_date);
}
if ($request->filled('platform')) {
$query->where('platform', $request->platform);
}
if ($request->filled('order_status')) {
$query->where('order_status', $request->order_status);
}
if ($request->filled('audit_status')) {
$query->where('audit_status', $request->audit_status);
}
if ($request->filled('delivery_status')) {
$query->where('delivery_status', $request->delivery_status);
}
$orders = $query->orderBy('order_time', 'desc')->get();
// 准备导出数据
$exportData = $orders->map(function ($order) {
return [
'订单短ID' => $order->short_id,
'平台订单号' => $order->platform_order_sn,
'平台' => $order->platform,
'店铺名称' => $order->shop_name,
'下单时间' => $order->order_time,
'买家昵称' => $order->buyer_nick,
'收货人' => $order->receiver_name,
'收货电话' => $order->receiver_phone,
'收货地址' => $order->receiver_address,
'商品金额' => $order->goods_amount,
'优惠金额' => $order->discount_amount,
'运费' => $order->freight,
'总金额' => $order->total_amount,
'订单状态' => $this->getStatusText($order->order_status),
'平台状态' => $order->platform_status,
'审核状态' => $this->getAuditStatusText($order->audit_status),
'发货状态' => $this->getDeliveryStatusText($order->delivery_status),
'发货时间' => $order->delivery_time,
'快递公司' => $order->express_company,
'快递单号' => $order->express_no,
'仓库名称' => $order->warehouse_name,
'备注' => $order->remark,
'创建时间' => $order->created_at,
'更新时间' => $order->updated_at,
];
});
// 生成文件名
$filename = 'orders_export_' . date('Ymd_His') . '.' . $request->export_type;
// 在实际项目中这里会生成Excel或CSV文件
// 暂时返回数据供前端处理
return response()->json([
'code' => 200,
'data' => [
'filename' => $filename,
'count' => $orders->count(),
'data' => $exportData,
'headers' => array_keys($exportData->first() ?? []),
],
'message' => '导出数据准备完成'
]);
}
/**
* 获取状态文本
*/
private function getStatusText($status): string
{
$statusMap = [
'pending' => '待处理',
'auditing' => '审核中',
'shipped' => '已发货',
'completed' => '已完成',
'cancelled' => '已取消',
];
return $statusMap[$status] ?? $status;
}
/**
* 获取审核状态文本
*/
private function getAuditStatusText($status): string
{
$statusMap = [
'pending' => '待审核',
'approved' => '已通过',
'rejected' => '已驳回',
];
return $statusMap[$status] ?? $status;
}
/**
* 获取发货状态文本
*/
private function getDeliveryStatusText($status): string
{
$statusMap = [
'pending' => '待发货',
'delivered' => '已发货',
];
return $statusMap[$status] ?? $status;
}
/**
* 订单操作日志
*/
public function getOrderLogs(string $id)
{
$order = Order::find($id);
if (!$order) {
return response()->json([
'code' => 404,
'message' => '订单不存在'
], 404);
}
// 在实际项目中,这里应该查询操作日志表
// 暂时返回模拟数据
$logs = $this->generateOrderLogs($order);
return response()->json([
'code' => 200,
'data' => $logs,
'message' => 'success'
]);
}
/**
* 生成订单操作日志
*/
private function generateOrderLogs(Order $order): array
{
$logs = [];
// 订单创建日志
$logs[] = [
'id' => 1,
'operator' => '系统',
'operator_id' => 0,
'action' => 'create',
'action_text' => '创建订单',
'content' => "订单创建成功,订单号:{$order->short_id}",
'ip' => '127.0.0.1',
'user_agent' => '系统自动创建',
'created_at' => $order->created_at,
];
// 如果订单已审核,添加审核日志
if ($order->audit_status === 'approved') {
$logs[] = [
'id' => 2,
'operator' => '管理员',
'operator_id' => 1,
'action' => 'audit_approve',
'action_text' => '审核通过',
'content' => '订单审核通过,进入待发货状态',
'ip' => '192.168.1.100',
'user_agent' => 'Chrome/120.0.0.0',
'created_at' => $order->updated_at,
];
} elseif ($order->audit_status === 'rejected') {
$logs[] = [
'id' => 2,
'operator' => '管理员',
'operator_id' => 1,
'action' => 'audit_reject',
'action_text' => '审核驳回',
'content' => "订单审核驳回,原因:{$order->audit_comment}",
'ip' => '192.168.1.100',
'user_agent' => 'Chrome/120.0.0.0',
'created_at' => $order->updated_at,
];
}
// 如果设置了仓库,添加仓库设置日志
if ($order->warehouse_id) {
$logs[] = [
'id' => 3,
'operator' => '操作员',
'operator_id' => 2,
'action' => 'set_warehouse',
'action_text' => '设置仓库',
'content' => "设置发货仓库:{$order->warehouse_name}",
'ip' => '192.168.1.101',
'user_agent' => 'Firefox/121.0.0.0',
'created_at' => $order->updated_at,
];
}
// 如果已发货,添加发货日志
if ($order->delivery_status === 'delivered') {
$logs[] = [
'id' => 4,
'operator' => '发货员',
'operator_id' => 3,
'action' => 'ship',
'action_text' => '订单发货',
'content' => "订单已发货,快递公司:{$order->express_company},快递单号:{$order->express_no}",
'ip' => '192.168.1.102',
'user_agent' => 'Safari/17.0.0.0',
'created_at' => $order->delivery_time,
];
}
// 如果订单已完成,添加完成日志
if ($order->order_status === 'completed') {
$logs[] = [
'id' => 5,
'operator' => '系统',
'operator_id' => 0,
'action' => 'complete',
'action_text' => '订单完成',
'content' => '订单已完成交易',
'ip' => '127.0.0.1',
'user_agent' => '系统自动完成',
'created_at' => $order->end_time,
];
}
// 如果订单已取消,添加取消日志
if ($order->order_status === 'cancelled') {
$logs[] = [
'id' => 6,
'operator' => '管理员',
'operator_id' => 1,
'action' => 'cancel',
'action_text' => '订单取消',
'content' => "订单已取消,原因:{$order->audit_comment}",
'ip' => '192.168.1.100',
'user_agent' => 'Chrome/120.0.0.0',
'created_at' => $order->updated_at,
];
}
// 按时间倒序排序
usort($logs, function ($a, $b) {
return strtotime($b['created_at']) - strtotime($a['created_at']);
});
return $logs;
}
/**
* 记录订单操作日志
*/
private function logOrderOperation(Order $order, string $action, string $content, array $data = []): void
{
// 在实际项目中,这里应该将日志保存到数据库
// 暂时只记录到文件或控制台
$logData = [
'order_id' => $order->id,
'short_id' => $order->short_id,
'action' => $action,
'content' => $content,
'operator' => auth()->user() ? auth()->user()->name : '系统',
'operator_id' => auth()->id() ?? 0,
'data' => $data,
'created_at' => now()->toDateTimeString(),
];
// 记录到日志文件
$logPath = storage_path('logs/order_operations.log');
file_put_contents($logPath, json_encode($logData, JSON_UNESCAPED_UNICODE) . PHP_EOL, FILE_APPEND);
}
/**
* 批量操作订单
*/
public function batchOperation(Request $request)
{
$request->validate([
'order_ids' => 'required|array|min:1',
'order_ids.*' => 'integer|exists:orders,id',
'operation' => 'required|in:audit_approve,audit_reject,set_warehouse,ship,cancel,delete',
'data' => 'nullable|array',
]);
$successCount = 0;
$failedOrders = [];
try {
DB::beginTransaction();
foreach ($request->order_ids as $orderId) {
$order = Order::find($orderId);
if (!$order) {
$failedOrders[] = ['id' => $orderId, 'reason' => '订单不存在'];
continue;
}
$result = $this->processBatchOperation($order, $request->operation, $request->data ?? []);
if ($result['success']) {
$successCount++;
// 记录操作日志
$this->logOrderOperation(
$order,
$request->operation,
$result['log_content'] ?? '批量操作',
$request->data ?? []
);
} else {
$failedOrders[] = ['id' => $orderId, 'reason' => $result['reason']];
}
}
DB::commit();
return response()->json([
'code' => 200,
'data' => [
'success_count' => $successCount,
'failed_orders' => $failedOrders,
],
'message' => "成功处理 {$successCount} 个订单"
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'code' => 500,
'message' => '批量操作失败: ' . $e->getMessage()
], 500);
}
}
/**
* 处理批量操作
*/
private function processBatchOperation(Order $order, string $operation, array $data): array
{
$logContent = '';
switch ($operation) {
case 'audit_approve':
if ($order->audit_status !== 'pending') {
return ['success' => false, 'reason' => '订单状态不可审核'];
}
$order->update([
'audit_status' => 'approved',
'order_status' => 'auditing',
]);
$logContent = '批量审核通过';
break;
case 'audit_reject':
if ($order->audit_status !== 'pending') {
return ['success' => false, 'reason' => '订单状态不可审核'];
}
$order->update([
'audit_status' => 'rejected',
'audit_comment' => $data['comment'] ?? '',
]);
$logContent = '批量审核驳回,原因:' . ($data['comment'] ?? '无');
break;
case 'set_warehouse':
if ($order->audit_status !== 'approved') {
return ['success' => false, 'reason' => '只有已审核的订单可以设置仓库'];
}
$order->update([
'warehouse_id' => $data['warehouse_id'] ?? $order->warehouse_id,
'warehouse_name' => $data['warehouse_name'] ?? $order->warehouse_name,
]);
$logContent = '批量设置仓库:' . ($data['warehouse_name'] ?? '未知仓库');
break;
case 'ship':
if ($order->order_status !== 'auditing') {
return ['success' => false, 'reason' => '只有待发货的订单可以发货'];
}
if (!$order->warehouse_id) {
return ['success' => false, 'reason' => '请先设置发货仓库'];
}
$order->update([
'express_company' => $data['express_company'] ?? '',
'express_no' => $data['express_no'] ?? '',
'delivery_status' => 'delivered',
'delivery_time' => now(),
'order_status' => 'shipped',
]);
$logContent = '批量发货,快递:' . ($data['express_company'] ?? '未知') . ',单号:' . ($data['express_no'] ?? '无');
break;
case 'cancel':
if (!in_array($order->order_status, ['pending', 'auditing'])) {
return ['success' => false, 'reason' => '订单状态不可取消'];
}
$order->update([
'order_status' => 'cancelled',
'audit_status' => 'rejected',
'audit_comment' => '订单已取消',
]);
$logContent = '批量取消订单';
break;
case 'delete':
if (!in_array($order->order_status, ['cancelled', 'completed'])) {
return ['success' => false, 'reason' => '只有已取消或已完成的订单可以删除'];
}
$order->delete();
$logContent = '批量删除订单';
break;
default:
return ['success' => false, 'reason' => '不支持的操作类型'];
}
return ['success' => true, 'log_content' => $logContent];
}
/**
* 获取订单状态选项
*/
public function getStatusOptions()
{
$options = [
['value' => 'pending', 'label' => '待处理'],
['value' => 'auditing', 'label' => '审核中'],
['value' => 'shipped', 'label' => '已发货'],
['value' => 'completed', 'label' => '已完成'],
['value' => 'cancelled', 'label' => '已取消'],
];
return response()->json([
'code' => 200,
'data' => $options,
'message' => 'success'
]);
}
/**
* 获取审核状态选项
*/
public function getAuditStatusOptions()
{
$options = [
['value' => 'pending', 'label' => '待审核'],
['value' => 'approved', 'label' => '已通过'],
['value' => 'rejected', 'label' => '已驳回'],
];
return response()->json([
'code' => 200,
'data' => $options,
'message' => 'success'
]);
}
/**
* 获取发货状态选项
*/
public function getDeliveryStatusOptions()
{
$options = [
['value' => 'pending', 'label' => '待发货'],
['value' => 'delivered', 'label' => '已发货'],
];
return response()->json([
'code' => 200,
'data' => $options,
'message' => 'success'
]);
}
/**
* 获取平台选项
*/
public function getPlatformOptions()
{
$platforms = Order::select('platform')
->distinct()
->orderBy('platform')
->get()
->map(function ($item) {
return [
'value' => $item->platform,
'label' => $item->platform,
];
});
return response()->json([
'code' => 200,
'data' => $platforms,
'message' => 'success'
]);
}
/**
* 获取店铺选项
*/
public function getShopOptions()
{
$shops = Order::select('shop_id', 'shop_name')
->distinct()
->orderBy('shop_name')
->get()
->map(function ($item) {
return [
'value' => $item->shop_id,
'label' => $item->shop_name,
];
});
return response()->json([
'code' => 200,
'data' => $shops,
'message' => 'success'
]);
}
/**
* 更新订单备注
*/
public function updateRemark(Request $request, string $id)
{
$request->validate([
'remark' => 'required|string|max:1000',
]);
$order = Order::find($id);
if (!$order) {
return response()->json([
'code' => 404,
'message' => '订单不存在'
], 404);
}
$oldRemark = $order->remark;
$order->update(['remark' => $request->remark]);
// 记录操作日志
$this->logOrderOperation(
$order,
'update_remark',
"更新订单备注,原备注:{$oldRemark},新备注:{$request->remark}"
);
return response()->json([
'code' => 200,
'message' => '备注更新成功'
]);
}
/**
* 完成订单
*/
public function completeOrder(string $id)
{
$order = Order::find($id);
if (!$order) {
return response()->json([
'code' => 404,
'message' => '订单不存在'
], 404);
}
// 只有已发货的订单可以完成
if ($order->order_status !== 'shipped') {
return response()->json([
'code' => 400,
'message' => '只有已发货的订单可以完成'
], 400);
}
$order->update([
'order_status' => 'completed',
'end_time' => now(),
]);
// 记录操作日志
$this->logOrderOperation(
$order,
'complete',
'订单已完成交易'
);
return response()->json([
'code' => 200,
'message' => '订单已完成'
]);
}
/**
* 同步订单到平台
*/
public function syncToPlatform(string $id)
{
$order = Order::find($id);
if (!$order) {
return response()->json([
'code' => 404,
'message' => '订单不存在'
], 404);
}
// TODO: 实现同步到平台API
// 这里应该调用对应平台的API更新订单状态
// 记录操作日志
$this->logOrderOperation(
$order,
'sync_to_platform',
"同步订单到平台:{$order->platform},平台订单号:{$order->platform_order_sn}"
);
return response()->json([
'code' => 200,
'message' => '订单已同步到平台(模拟)',
'data' => [
'order_id' => $id,
'platform' => $order->platform,
'platform_order_sn' => $order->platform_order_sn,
]
]);
}
/**
* 获取订单操作历史
*/
public function getOperationHistory(string $id)
{
$order = Order::find($id);
if (!$order) {
return response()->json([
'code' => 404,
'message' => '订单不存在'
], 404);
}
// 在实际项目中,这里应该查询操作日志表
// 暂时返回模拟数据
$history = $this->generateOrderLogs($order);
return response()->json([
'code' => 200,
'data' => $history,
'message' => 'success'
]);
}
/**
* 获取订单数量统计(用于仪表板)
*/
public function getDashboardStats()
{
$today = now()->startOfDay();
$yesterday = now()->subDay()->startOfDay();
$thisMonth = now()->startOfMonth();
$stats = [
'today' => [
'total' => Order::where('order_time', '>=', $today)->count(),
'pending' => Order::where('order_time', '>=', $today)->where('order_status', 'pending')->count(),
'auditing' => Order::where('order_time', '>=', $today)->where('order_status', 'auditing')->count(),
'shipped' => Order::where('order_time', '>=', $today)->where('order_status', 'shipped')->count(),
'amount' => Order::where('order_time', '>=', $today)->sum('total_amount'),
],
'yesterday' => [
'total' => Order::whereBetween('order_time', [$yesterday, $today])->count(),
'amount' => Order::whereBetween('order_time', [$yesterday, $today])->sum('total_amount'),
],
'this_month' => [
'total' => Order::where('order_time', '>=', $thisMonth)->count(),
'amount' => Order::where('order_time', '>=', $thisMonth)->sum('total_amount'),
],
'all' => [
'total' => Order::count(),
'pending' => Order::where('order_status', 'pending')->count(),
'auditing' => Order::where('order_status', 'auditing')->count(),
'shipped' => Order::where('order_status', 'shipped')->count(),
'completed' => Order::where('order_status', 'completed')->count(),
'cancelled' => Order::where('order_status', 'cancelled')->count(),
'amount' => Order::sum('total_amount'),
],
];
return response()->json([
'code' => 200,
'data' => $stats,
'message' => 'success'
]);
}
/**
* 获取订单操作类型选项
*/
public function getOperationTypeOptions()
{
$options = [
['value' => 'create', 'label' => '创建'],
['value' => 'audit_approve', 'label' => '审核通过'],
['value' => 'audit_reject', 'label' => '审核驳回'],
['value' => 'set_warehouse', 'label' => '设置仓库'],
['value' => 'ship', 'label' => '发货'],
['value' => 'complete', 'label' => '完成'],
['value' => 'cancel', 'label' => '取消'],
['value' => 'update_remark', 'label' => '更新备注'],
['value' => 'sync_to_platform', 'label' => '同步到平台'],
['value' => 'delete', 'label' => '删除'],
];
return response()->json([
'code' => 200,
'data' => $options,
'message' => 'success'
]);
}
/**
* 导出订单操作日志
*/
public function exportOperationLogs(Request $request, string $id)
{
$order = Order::find($id);
if (!$order) {
return response()->json([
'code' => 404,
'message' => '订单不存在'
], 404);
}
$request->validate([
'export_type' => 'required|in:excel,csv',
]);
// 获取操作日志
$logs = $this->generateOrderLogs($order);
// 准备导出数据
$exportData = array_map(function ($log) {
return [
'操作时间' => $log['created_at'],
'操作人' => $log['operator'],
'操作类型' => $log['action_text'],
'操作内容' => $log['content'],
'IP地址' => $log['ip'],
'用户代理' => $log['user_agent'],
];
}, $logs);
// 生成文件名
$filename = "order_{$order->short_id}_logs_" . date('Ymd_His') . '.' . $request->export_type;
return response()->json([
'code' => 200,
'data' => [
'filename' => $filename,
'count' => count($logs),
'data' => $exportData,
'headers' => array_keys($exportData[0] ?? []),
'order_info' => [
'short_id' => $order->short_id,
'platform_order_sn' => $order->platform_order_sn,
'platform' => $order->platform,
'shop_name' => $order->shop_name,
],
],
'message' => '操作日志导出数据准备完成'
]);
}
}