471 lines
15 KiB
PHP
471 lines
15 KiB
PHP
<?php
|
||
|
||
namespace App\Endpoint\Api\Http\Controllers\Dealer;
|
||
|
||
use App\Endpoint\Api\Http\Controllers\Controller;
|
||
use App\Endpoint\Api\Http\Resources\Dealer\OrderResource;
|
||
use App\Endpoint\Api\Http\Resources\Dealer\OrderSimpleResource;
|
||
use App\Enums\DealerLvl;
|
||
use App\Enums\PayWay;
|
||
use App\Exceptions\BizException;
|
||
use App\Exceptions\PayPasswordIncorrectException;
|
||
use App\Helpers\Paginator as PaginatorHelper;
|
||
use App\Models\DealerOrder;
|
||
use App\Models\DealerOrderProduct;
|
||
use App\Models\DealerProduct;
|
||
use App\Services\Dealer\OrderService;
|
||
use Illuminate\Database\QueryException;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Facades\DB;
|
||
use Throwable;
|
||
|
||
class OrderController extends Controller
|
||
{
|
||
/**
|
||
* @param \Illuminate\Http\Request $request
|
||
* @return void
|
||
*/
|
||
public function index(Request $request)
|
||
{
|
||
$cate = $request->input('cate', 'purchase');//获取订单类别
|
||
$user = $request->user();
|
||
switch ($cate) {
|
||
case 'consignor'://发货单
|
||
$query = $user->dealerConsignOrders();
|
||
break;
|
||
default://采购单
|
||
$query = $user->dealerOrders();
|
||
break;
|
||
}
|
||
$perPage = PaginatorHelper::resolvePerPage('per_page', 20, 50);
|
||
|
||
$orders = $query->with('products')
|
||
->filter($request->all())
|
||
->latest('id')
|
||
->simplePaginate($perPage);
|
||
|
||
return OrderSimpleResource::collection($orders);
|
||
}
|
||
|
||
public function store(Request $request, OrderService $orderService)
|
||
{
|
||
$input = $request->validate([
|
||
'shipping_address_id' => ['bail', 'required', 'int'],
|
||
'product_id'=>['bail', 'required', 'int', 'min:0'],
|
||
'num'=>['bail', 'required', 'int', 'min:1'],
|
||
], [], [
|
||
'product_id' => '商品',
|
||
'num' => '数量',
|
||
'shipping_address_id' => '收货地址',
|
||
]);
|
||
$product = DealerProduct::online()->findOrFail($input['product_id']);
|
||
try {
|
||
DB::beginTransaction();
|
||
$order = $orderService->quickCreateOrder($request->user(), $product, $input['num'], $input['shipping_address_id']);
|
||
DB::commit();
|
||
} catch (BizException $e) {
|
||
DB::rollBack();
|
||
throw $e;
|
||
} catch (Throwable $th) {
|
||
DB::rollBack();
|
||
report($th);
|
||
throw new BizException('下单失败,请稍后再试');
|
||
}
|
||
|
||
return OrderResource::make($order);
|
||
}
|
||
|
||
/**
|
||
* 确认订单
|
||
*
|
||
* @param Request $request
|
||
* @param OrderService $orderService
|
||
*/
|
||
public function checkOrder(Request $request, OrderService $orderService)
|
||
{
|
||
$input = $request->validate([
|
||
'shopping_cart' => ['bail', 'required', 'array'],
|
||
], [], [
|
||
'shopping_cart'=>'购物车商品',
|
||
]);
|
||
$user = $request->user();
|
||
$shoppingCartItems = $user->dealerShoppingCartItems()->findMany($input['shopping_cart']);
|
||
$shoppingCartItems->load('product');
|
||
$totalQty = $shoppingCartItems->sum('quantity');
|
||
$data = [];
|
||
foreach ($shoppingCartItems as $item) {
|
||
$data[] = [
|
||
'id' => $item->id,
|
||
'name' => $item->name,
|
||
'cover' => $item->cover,
|
||
'sell_price' => $item->sell_price,
|
||
'dealer_price' => $orderService->getSalePrice($user, $item->product, $totalQty),
|
||
'quantity' => $item->quantity,
|
||
];
|
||
}
|
||
return response()->json(['data'=>$data]);
|
||
}
|
||
|
||
/**
|
||
* 新下单接口
|
||
*/
|
||
public function newStore(Request $request, OrderService $orderService)
|
||
{
|
||
$isQuick = $request->filled('product');
|
||
|
||
$rules = $isQuick ? [
|
||
'product.id' => ['bail', 'required', 'int'],
|
||
'product.quantity' => ['bail', 'required', 'int', 'min:1'],
|
||
'shipping_address_id' => ['bail', 'required', 'int'],
|
||
] : [
|
||
'shopping_cart' => ['bail', 'required', 'array'],
|
||
'shipping_address_id' => ['bail', 'required', 'int'],
|
||
];
|
||
|
||
$input = $request->validate($rules, [], [
|
||
'product.id' => '商品',
|
||
'product.quantity' => '数量',
|
||
'shopping_cart' => '购物车商品',
|
||
'shipping_address_id' => '收货地址',
|
||
]);
|
||
|
||
try {
|
||
DB::beginTransaction();
|
||
|
||
if ($isQuick) {
|
||
$product = DealerProduct::online()->findOrFail($input['product']['id']);
|
||
$order = $orderService->quickCreateOrder($request->user(), $product, $input['product']['quantity'], $input['shipping_address_id']);
|
||
} else {
|
||
$order = $orderService->cartCreateOrder($request->user(), $input['shopping_cart'], $input['shipping_address_id']);
|
||
}
|
||
|
||
DB::commit();
|
||
} catch (BizException $e) {
|
||
DB::rollBack();
|
||
throw $e;
|
||
} catch (Throwable $th) {
|
||
DB::rollBack();
|
||
report($th);
|
||
throw new BizException('下单失败,请稍后再试');
|
||
}
|
||
|
||
return OrderResource::make($order);
|
||
}
|
||
|
||
public function show($id, Request $request)
|
||
{
|
||
$order = DealerOrder::findOrFail($id);
|
||
$userId = $request->user()->id;
|
||
//既不是采购人,也不是发货人
|
||
if (!$order->canCurd($userId)) {
|
||
throw new BizException('订单未找到');
|
||
}
|
||
|
||
$refuseLog = $order->isPendinged() ? $order->refuseLogs()->latest('id')->first() : null;
|
||
|
||
$data = OrderResource::make($order)->toArray($request);
|
||
$data['refuse_reason'] = $refuseLog?->reason;
|
||
|
||
return response()->json($data);
|
||
}
|
||
|
||
/**
|
||
* 计算订单价格
|
||
*
|
||
* @return void
|
||
*/
|
||
public function totalAmount(Request $request, OrderService $orderService)
|
||
{
|
||
$input = $request->validate([
|
||
'product_id'=>['bail', 'required', 'int', 'min:0'],
|
||
'num'=>['bail', 'required', 'int', 'min:1'],
|
||
]);
|
||
|
||
$product = DealerProduct::online()->findOrFail($input['product_id']);
|
||
|
||
return response()->json([
|
||
'total_amount'=> $orderService->totalAmount($request->user(), $product, $input['num']),
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 确认接单
|
||
*
|
||
* @param [type] $id
|
||
* @param Request $request
|
||
* @return void
|
||
*/
|
||
public function confirmOrder($id, Request $request, OrderService $orderService)
|
||
{
|
||
$order = DealerOrder::findOrFail($id);
|
||
$userId = $request->user()->id;
|
||
//不是发货人
|
||
if (!$order->isConsignor($userId)) {
|
||
throw new BizException('订单未找到');
|
||
}
|
||
|
||
$orderService->confirmOrder($order);
|
||
return response()->noContent();
|
||
}
|
||
|
||
/**
|
||
* 确认打款
|
||
*
|
||
* @return void
|
||
*/
|
||
public function payOrder($id, Request $request, OrderService $orderService)
|
||
{
|
||
$input = $request->validate([
|
||
'pay_image' => ['bail', 'string'],
|
||
'pay_way' => ['bail', 'string'],
|
||
'pay_password' => ['bail', 'required_if:pay_way,wallet'],
|
||
'products'=> ['array'],
|
||
], [
|
||
'pay_password.required_if' => '支付密码 不能为空。',
|
||
], [
|
||
'pay_image' => '打款凭证',
|
||
'pay_way' => '支付方式',
|
||
'pay_password' => '支付密码',
|
||
]);
|
||
$payWay = PayWay::tryFrom($input['pay_way'] ?? 'offline');
|
||
|
||
if (! in_array($payWay, [PayWay::Offline, PayWay::Wallet, PayWay::WxpayH5, PayWay::WxpayJsApi])) {
|
||
throw new BizException('支付方式 非法');
|
||
}
|
||
|
||
$user = $request->user();
|
||
|
||
$order = $user->dealerOrders()->findOrFail($id);
|
||
|
||
switch ($payWay) {
|
||
case PayWay::Wallet:
|
||
if (! $user->wallet?->verifyPassword($input['pay_password'])) {
|
||
throw new PayPasswordIncorrectException();
|
||
}
|
||
|
||
break;
|
||
|
||
case PayWay::WxpayH5:
|
||
case PayWay::WxpayJsApi:
|
||
if ($order->consignor !== null) {
|
||
throw new BizException('订单不是签约订单');
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
try {
|
||
DB::beginTransaction();
|
||
|
||
|
||
//签约单-处理云库存
|
||
if ($order->consignor === null) {
|
||
//处理云库存设置,如果没有设置则默认云仓库为0。
|
||
$products = $input['products'] ?? [];
|
||
if ($products) {
|
||
$num = 0;
|
||
foreach ($order->products as $product) {
|
||
//更新云库存
|
||
if (isset($products[$product->id]) && ($product->qty + $product->deposit_qty) >= $products[$product->id]) {
|
||
DealerOrderProduct::where('id', $product->id)->update([
|
||
'qty' => $products[$product->id],
|
||
'deposit_qty' =>($product->qty + $product->deposit_qty) - $products[$product->id],
|
||
]);
|
||
$num += $products[$product->id];
|
||
}
|
||
}
|
||
if ($num < 20) {
|
||
throw new BizException('首次发货最少20盒');
|
||
}
|
||
}
|
||
}
|
||
|
||
$data = $orderService->pay($order, $payWay, $input['pay_image'] ?? null);
|
||
|
||
DB::commit();
|
||
} catch (Throwable $e) {
|
||
DB::rollBack();
|
||
|
||
report($e);
|
||
|
||
if (! $e instanceof BizException) {
|
||
$e = new BizException('操作失败,请刷新后再试');
|
||
}
|
||
|
||
throw $e;
|
||
}
|
||
|
||
return response()->json($data);
|
||
}
|
||
|
||
/**
|
||
* 确认收款
|
||
*
|
||
* @return void
|
||
*/
|
||
public function paidOrder($id, Request $request, OrderService $orderService)
|
||
{
|
||
$order = DealerOrder::findOrFail($id);
|
||
$userId = $request->user()->id;
|
||
//不是发货人
|
||
if (!$order->isConsignor($userId)) {
|
||
throw new BizException('订单未找到');
|
||
}
|
||
try {
|
||
DB::beginTransaction();
|
||
$orderService->paidOrder($order);//确认收款
|
||
//3-14号取消确认收款后自动发货
|
||
// $orderService->shippingOrder($order);//确认发货
|
||
DB::commit();
|
||
} catch (QueryException $e) {
|
||
DB::rollBack();
|
||
if (strpos($e->getMessage(), 'Numeric value out of range') !== false) {
|
||
$e = new BizException('当前可发货库存不足');
|
||
}
|
||
throw $e;
|
||
} catch (Throwable $th) {
|
||
DB::rollBack();
|
||
report($th);
|
||
throw new BizException('操作失败,请刷新后再试');
|
||
}
|
||
return response()->noContent();
|
||
}
|
||
|
||
/**
|
||
* 确认发货
|
||
*
|
||
* @param [type] $id
|
||
* @param Request $request
|
||
* @param OrderService $orderService
|
||
* @return void
|
||
*/
|
||
public function shippingOrder($id, Request $request, OrderService $orderService)
|
||
{
|
||
$order = DealerOrder::findOrFail($id);
|
||
$user = $request->user();
|
||
//不是发货人
|
||
if (!$order->isConsignor($user->id)) {
|
||
throw new BizException('订单未找到');
|
||
}
|
||
$deliveryBill = null;
|
||
try {
|
||
DB::beginTransaction();
|
||
//如果发货人是签约经销商, 则可以使用云仓库发货
|
||
if ($user->dealer->lvl?->value >= DealerLvl::Contracted->value) {
|
||
$deliveryBill = $orderService->shippingOrderByDeposit($order);
|
||
if ($deliveryBill) {
|
||
$order->refresh();
|
||
//扣除本地库存
|
||
$orderService->orderOutQty($order);
|
||
} else {
|
||
$orderService->shippingOrder($order);//确认发货
|
||
}
|
||
} else {
|
||
$orderService->shippingOrder($order);//确认发货
|
||
}
|
||
DB::commit();
|
||
} catch (BizException $e) {
|
||
DB::rollBack();
|
||
$e = new BizException($e->getMessage());
|
||
throw $e;
|
||
} catch (QueryException $e) {
|
||
DB::rollBack();
|
||
if (strpos($e->getMessage(), 'Numeric value out of range') !== false) {
|
||
$e = new BizException('当前可发货库存不足');
|
||
}
|
||
throw $e;
|
||
} catch (Throwable $th) {
|
||
DB::rollBack();
|
||
report($th);
|
||
throw new BizException('操作失败,请刷新后再试');
|
||
}
|
||
|
||
return response()->json([
|
||
'delivery_bill_id'=>$deliveryBill?->id,
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* 确认收货
|
||
*
|
||
* @return void
|
||
*/
|
||
public function shippingedOrder($id, Request $request, OrderService $orderService)
|
||
{
|
||
$order = DealerOrder::findOrFail($id);
|
||
$user = $request->user();
|
||
//不是收货人
|
||
if (!$order->isUser($user->id)) {
|
||
throw new BizException('订单未找到');
|
||
}
|
||
try {
|
||
DB::beginTransaction();
|
||
$orderService->shippingedOrder($order);
|
||
DB::commit();
|
||
} catch (Throwable $th) {
|
||
DB::rollBack();
|
||
report($th);
|
||
throw new BizException('操作失败,请刷新后再试');
|
||
}
|
||
return response()->noContent();
|
||
}
|
||
|
||
/**
|
||
* 取消订单
|
||
*
|
||
* @param [type] $id
|
||
* @param Request $request
|
||
* @return void
|
||
*/
|
||
public function cancelOrder($id, Request $request, OrderService $orderService)
|
||
{
|
||
$order = DealerOrder::findOrFail($id);
|
||
$userId = $request->user()->id;
|
||
if (!$order->isUser($userId)) {
|
||
throw new BizException('订单未找到');
|
||
}
|
||
try {
|
||
DB::beginTransaction();
|
||
$orderService->cancelOrder($order);
|
||
DB::commit();
|
||
} catch (Throwable $th) {
|
||
DB::rollBack();
|
||
report($th);
|
||
throw new BizException('操作失败,请刷新后再试');
|
||
}
|
||
return response()->noContent();
|
||
}
|
||
|
||
/**
|
||
* 放弃接单/转让订单
|
||
*
|
||
* @param [type] $id
|
||
* @param Request $request
|
||
* @param OrderService $orderService
|
||
* @return void
|
||
*/
|
||
public function transferOrder($id, Request $request, OrderService $orderService)
|
||
{
|
||
$order = DealerOrder::findOrFail($id);
|
||
$userId = $request->user()->id;
|
||
//不是发货人
|
||
if (!$order->isConsignor($userId)) {
|
||
throw new BizException('订单未找到');
|
||
}
|
||
if (!$order->isPending()) {
|
||
throw new BizException('订单状态异常,请刷新后再试');
|
||
}
|
||
try {
|
||
DB::beginTransaction();
|
||
$orderService->updateOrderConsignor($order);
|
||
DB::commit();
|
||
} catch (Throwable $th) {
|
||
DB::rollBack();
|
||
report($th);
|
||
throw new BizException('操作失败,请刷新后再试');
|
||
}
|
||
|
||
return response()->noContent();
|
||
}
|
||
}
|