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

369 lines
13 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\PurchaseOrder;
use App\Models\PurchaseOrderItem;
use App\Models\ReceivingOrder;
use App\Models\ReceivingOrderItem;
use App\Services\PurchaseService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
class PurchaseOrderController extends Controller
{
protected $purchaseService;
public function __construct(PurchaseService $purchaseService)
{
$this->purchaseService = $purchaseService;
}
/**
* 采购单列表
*/
public function index(Request $request)
{
$query = PurchaseOrder::with(['supplier', 'warehouse', 'items']);
// 筛选条件
if ($request->has('po_no')) {
$query->where('po_no', 'like', '%' . $request->po_no . '%');
}
if ($request->has('supplier_id')) {
$query->where('supplier_id', $request->supplier_id);
}
if ($request->has('warehouse_id')) {
$query->where('warehouse_id', $request->warehouse_id);
}
if ($request->has('status')) {
$query->where('status', $request->status);
}
if ($request->has('date_from')) {
$query->whereDate('created_at', '>=', $request->date_from);
}
if ($request->has('date_to')) {
$query->whereDate('created_at', '<=', $request->date_to);
}
$perPage = $request->get('per_page', 15);
$orders = $query->orderBy('id', 'desc')->paginate($perPage);
return response()->json([
'code' => 200,
'data' => $orders,
'message' => 'success'
]);
}
/**
* 创建采购单
*/
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'warehouse_id' => 'required|exists:warehouses,id',
'supplier_id' => 'required|exists:suppliers,id',
'expected_arrival' => 'nullable|date',
'shipping_method' => 'nullable|string|max:50',
'freight' => 'nullable|numeric|min:0',
'category' => 'nullable|string|max:100',
'remark' => 'nullable|string',
'items' => 'required|array|min:1',
'items.*.sku_code' => 'required|string',
'items.*.sku_name' => 'required|string',
'items.*.quantity' => 'required|integer|min:1',
'items.*.price' => 'required|numeric|min:0',
]);
if ($validator->fails()) {
return response()->json([
'code' => 422,
'message' => '验证失败',
'errors' => $validator->errors()
], 422);
}
try {
DB::beginTransaction();
// 生成采购单号
$poNo = 'PO' . date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
$purchaseOrder = PurchaseOrder::create([
'po_no' => $poNo,
'warehouse_id' => $request->warehouse_id,
'supplier_id' => $request->supplier_id,
'expected_arrival' => $request->expected_arrival,
'shipping_method' => $request->shipping_method,
'freight' => $request->freight ?? 0,
'category' => $request->category,
'remark' => $request->remark,
'status' => 'draft',
]);
foreach ($request->items as $item) {
PurchaseOrderItem::create([
'purchase_order_id' => $purchaseOrder->id,
'sku_code' => $item['sku_code'],
'sku_name' => $item['sku_name'],
'quantity' => $item['quantity'],
'received_quantity' => 0,
'price' => $item['price'],
]);
}
DB::commit();
return response()->json([
'code' => 201,
'data' => $purchaseOrder->load('items'),
'message' => '采购单创建成功'
], 201);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'code' => 500,
'message' => '创建失败:' . $e->getMessage()
], 500);
}
}
/**
* 采购单详情
*/
public function show($id)
{
$order = PurchaseOrder::with(['supplier', 'warehouse', 'items'])->find($id);
if (!$order) {
return response()->json([
'code' => 404,
'message' => '采购单不存在'
], 404);
}
return response()->json([
'code' => 200,
'data' => $order,
'message' => 'success'
]);
}
/**
* 更新采购单(仅草稿状态可更新)
*/
public function update(Request $request, $id)
{
$purchaseOrder = PurchaseOrder::find($id);
if (!$purchaseOrder) {
return response()->json(['code' => 404, 'message' => '采购单不存在'], 404);
}
if ($purchaseOrder->status !== 'draft') {
return response()->json(['code' => 403, 'message' => '仅草稿状态可修改'], 403);
}
$validator = Validator::make($request->all(), [
'warehouse_id' => 'sometimes|exists:warehouses,id',
'supplier_id' => 'sometimes|exists:suppliers,id',
'expected_arrival' => 'nullable|date',
'shipping_method' => 'nullable|string|max:50',
'freight' => 'nullable|numeric|min:0',
'category' => 'nullable|string|max:100',
'remark' => 'nullable|string',
'items' => 'sometimes|array|min:1',
'items.*.sku_code' => 'required_with:items|string',
'items.*.sku_name' => 'required_with:items|string',
'items.*.quantity' => 'required_with:items|integer|min:1',
'items.*.price' => 'required_with:items|numeric|min:0',
]);
if ($validator->fails()) {
return response()->json(['code' => 422, 'message' => '验证失败', 'errors' => $validator->errors()], 422);
}
DB::beginTransaction();
try {
$purchaseOrder->update($request->only([
'warehouse_id', 'supplier_id', 'expected_arrival',
'shipping_method', 'freight', 'category', 'remark'
]));
if ($request->has('items')) {
$purchaseOrder->items()->delete();
foreach ($request->items as $item) {
$purchaseOrder->items()->create([
'sku_code' => $item['sku_code'],
'sku_name' => $item['sku_name'],
'quantity' => $item['quantity'],
'received_quantity' => 0,
'price' => $item['price'],
]);
}
}
DB::commit();
return response()->json([
'code' => 200,
'data' => $purchaseOrder->load('items'),
'message' => '更新成功'
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json(['code' => 500, 'message' => '更新失败:' . $e->getMessage()], 500);
}
}
/**
* 提交审核
*/
public function submitReview($id)
{
$purchaseOrder = PurchaseOrder::find($id);
if (!$purchaseOrder) {
return response()->json(['code' => 404, 'message' => '采购单不存在'], 404);
}
if ($purchaseOrder->status !== 'draft') {
return response()->json(['code' => 403, 'message' => '仅草稿状态可提交审核'], 403);
}
$purchaseOrder->status = 'under_review';
$purchaseOrder->save();
return response()->json(['code' => 200, 'message' => '提交审核成功']);
}
/**
* 审核通过
*/
public function approve($id)
{
\Log::info('approve method entered', ['id' => $id, 'time' => now()]);
$purchaseOrder = PurchaseOrder::with('items')->find($id);
if (!$purchaseOrder) {
return response()->json(['code' => 404, 'message' => '采购单不存在'], 404);
}
if ($purchaseOrder->status !== 'under_review') {
return response()->json(['code' => 403, 'message' => '仅待审核状态可审核通过'], 403);
}
DB::beginTransaction();
try {
$purchaseOrder->status = 'approved';
// 临时注释掉以下两行,避免字段缺失错误
// $purchaseOrder->approved_at = now();
// $purchaseOrder->approved_by = auth()->id() ?? 1;
$purchaseOrder->save();
// 计算总数量
$totalQuantity = $purchaseOrder->items->sum('quantity');
// 自动生成收货单
$receivingOrder = ReceivingOrder::create([
'receiving_no' => 'RO' . date('Ymd') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT),
'po_id' => $purchaseOrder->id,
'warehouse_id' => $purchaseOrder->warehouse_id,
'total_quantity' => $totalQuantity,
'received_quantity' => 0,
'status' => 'pending',
'is_cloud_warehouse' => false, // 默认为false
// 其他可选字段:'receiver', 'remark' 暂不设置
]);
foreach ($purchaseOrder->items as $item) {
ReceivingOrderItem::create([
'receiving_order_id' => $receivingOrder->id,
'sku_code' => $item->sku_code,
'sku_name' => $item->sku_name,
'order_quantity' => $item->quantity,
'received_quantity' => 0,
]);
}
DB::commit();
return response()->json(['code' => 200, 'message' => '审核通过,已生成收货单']);
} catch (\Exception $e) {
DB::rollBack();
\Log::error('Approve failed', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
return response()->json(['code' => 500, 'message' => '审核失败:' . $e->getMessage()], 500);
}
}
/**
* 驳回审核
*/
public function reject(Request $request, $id)
{
$purchaseOrder = PurchaseOrder::find($id);
if (!$purchaseOrder) {
return response()->json(['code' => 404, 'message' => '采购单不存在'], 404);
}
if ($purchaseOrder->status !== 'under_review') {
return response()->json(['code' => 403, 'message' => '仅待审核状态可驳回'], 403);
}
$validator = Validator::make($request->all(), [
'reason' => 'required|string'
]);
if ($validator->fails()) {
return response()->json(['code' => 422, 'message' => '请填写驳回原因', 'errors' => $validator->errors()], 422);
}
$purchaseOrder->status = 'rejected';
$purchaseOrder->reject_reason = $request->reason;
$purchaseOrder->save();
return response()->json(['code' => 200, 'message' => '已驳回']);
}
/**
* 推送云仓(模拟)
*/
public function pushCloud($id)
{
$purchaseOrder = PurchaseOrder::find($id);
if (!$purchaseOrder) {
return response()->json(['code' => 404, 'message' => '采购单不存在'], 404);
}
if ($purchaseOrder->status !== 'approved') {
return response()->json(['code' => 403, 'message' => '仅审核通过的采购单可推送云仓'], 403);
}
$result = $this->purchaseService->pushToCloud($purchaseOrder);
if ($result['success']) {
$purchaseOrder->cloud_push_status = 'pushed';
$purchaseOrder->cloud_push_time = now();
$purchaseOrder->save();
return response()->json(['code' => 200, 'message' => '推送成功', 'data' => $result]);
} else {
return response()->json(['code' => 500, 'message' => '推送失败', 'error' => $result['error']], 500);
}
}
/**
* 删除采购单(仅草稿)
*/
public function destroy($id)
{
$purchaseOrder = PurchaseOrder::find($id);
if (!$purchaseOrder) {
return response()->json(['code' => 404, 'message' => '采购单不存在'], 404);
}
if ($purchaseOrder->status !== 'draft') {
return response()->json(['code' => 403, 'message' => '仅草稿状态可删除'], 403);
}
DB::transaction(function () use ($purchaseOrder) {
$purchaseOrder->items()->delete();
$purchaseOrder->delete();
});
return response()->json(['code' => 200, 'message' => '删除成功']);
}
}