4
0
Fork 0
dcat-admin-order/src/Http/Api/OrderController.php

408 lines
13 KiB
PHP

<?php
namespace Peidikeji\Order\Http\Api;
use Peidikeji\Order\Exceptions\OrderException;
use App\Http\Controllers\Controller;
use App\Http\Resources\UserAddressResource;
use App\Models\UserAddress;
use App\Models\Zone;
use App\Services\Kuaidi100Service;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Enum;
use Peidikeji\Merchant\Models\Merchant;
use Peidikeji\Order\Enums\OrderScene;
use Peidikeji\Order\Enums\OrderStatus;
use Peidikeji\Order\Enums\PayWay;
use Peidikeji\Order\Enums\ShipWay;
use Peidikeji\Order\Http\Resources\OrderResource;
use Peidikeji\Order\Http\Resources\OrderShipResouce;
use Peidikeji\Order\OrderService;
use Peidikeji\Order\OrderStore;
class OrderController extends Controller
{
public function index(Request $request)
{
$user = auth('api')->user();
$query = $user->orders()->with(['goods', 'merchant'])->filter($request->all());
$list = $query->sort()->paginate($request->input('per_page'));
return $this->json(OrderResource::collection($list));
}
public function total()
{
$user = auth('api')->user();
$query = $user->orders();
$maps = [
'unpay' => OrderStatus::None,
'paid' => OrderStatus::Paid,
'send_full' => OrderStatus::SendFull,
'receive' => OrderStatus::Receive
];
$data = [];
foreach($maps as $key => $status) {
$data[$key] = $query->clone()->filter(['status' => $status->value])->count();
}
return $this->json($data);
}
public function sure(Request $request)
{
$request->validate([
'scene' => ['required', new Enum(OrderScene::class)],
'goods' => [Rule::requiredIf(!$request->filled('cart_id')), 'array'],
'cart_id' => ['array'],
'merchant_id' => [Rule::requiredIf($request->input('scene') === OrderScene::Merchant->value)],
]);
$user = auth('api')->user();
$service = OrderStore::init()->user($user)->scene($request->input('scene'));
if ($request->filled('merchant_id')) {
$merchant = Merchant::findOrFail($request->input('merchant_id'));
if (!$merchant->enable()) {
throw new OrderException('店铺不可用');
}
$service->merchant($merchant);
}
$goods = $request->input('goods');
if ($request->filled('cart_id')) {
$goods = $this->formatCartGoods($user->carts()->whereIn('id', $request->input('cart_id'))->get());
}
$service->goods($goods);
// 收货地址
$address = null;
if ($request->filled('address_id')) {
$address = $user->addresses()->find($request->input('address_id'));
if (!$address) {
return $this->error('收货地址不存在');
}
}
if (!$address) {
$address = $user->addresses()->orderBy('is_default', 'desc')->orderBy('created_at', 'desc')->first();
}
$service->ship(ShipWay::Express->value, $this->formatAddress($address));
// 计算最大积分抵扣
$maxScore = floatval($service->orderGoodsList->sum('score_max_amount'));
$score = $request->input('score');
$userScore = floatval($user->profit);
if (!$score) {
$score = $userScore > $maxScore ? $maxScore : $userScore;
}
$service->score($score);
$goodsList = $service->orderGoodsList;
$dataList = collect();
foreach($goodsList->groupBy('merchant_id') as $id => $list) {
$dataList->push([
'merchant' => $id ? Merchant::select('id', 'name')->find($id) : ['id' => null, 'name' => '自营店铺'],
'list' => $list
]);
}
// 付款金额
$payMoney = $service->getPayMoney();
return $this->json([
'address' => $address ? UserAddressResource::make($address) : null,
'list' => $dataList,
'score' => [
'has' => $userScore,
'use' => $score,
'max' => $maxScore,
'bonus' => $service->getUserBonus($payMoney),
],
'price' => [
'goods' => floatval($goodsList->sum('price')),
'ship' => $service->ship['money'],
'coupon' => 0,
'vip' => $service->vip['money'],
'score' => $service->score['money'],
'total' => $payMoney,
]
]);
}
public function store(Request $request)
{
$user = auth('api')->user();
$request->validate([
'scene' => ['required', new Enum(OrderScene::class)]
]);
$scene = $request->input('scene');
$store = OrderStore::init()->scene($scene)->user($user)->remarks($request->input('remarks'));
// 自营商城下单
if ($scene === OrderScene::Online->value) {
$request->validate([
'goods' => [Rule::requiredIf(!$request->filled('cart_id')), 'array'],
'cart_id' => ['array'],
'address' => [Rule::requiredIf(!$request->filled('address_id')), 'array'],
]);
$goods = $request->input('goods');
if ($request->filled('cart_id')) {
$goods = $this->formatCartGoods($user->carts()->whereIn('id', $request->input('cart_id'))->get());
}
$store->goods($goods);
$address = null;
if ($request->filled('address_id')) {
$address = $user->addresses()->find($request->input('address_id'));
if (!$address) {
return $this->error('收货地址不存在');
}
}
if (!$address) {
$address = $request->input('address');
}
$store->ship(ShipWay::Express->value, $this->formatAddress($address));
$store->score($request->input('score', 0));
}
// 店铺下单
else if ($scene === OrderScene::Merchant->value) {
$request->validate([
'goods' => [Rule::requiredIf(!$request->filled('cart_id')), 'array'],
'cart_id' => ['array'],
'merchant_id' => 'required',
]);
$merchant = Merchant::findOrFail($request->input('merchant_id'));
if (!$merchant->enable()) {
throw new OrderException('店铺不可用');
}
$store->merchant($merchant);
$goods = $request->input('goods');
if ($request->filled('cart_id')) {
$goods = $this->formatCartGoods($user->carts()->whereIn('id', $request->input('cart_id'))->get());
}
$store->goods($goods);
$store->ship(ShipWay::Pick->value);
// 验证店铺返现余额是否足够
$payMoney = $store->getPayMoney();
$ratio = $merchant->profit_ratio / 100;
$userProfit = round($payMoney * $ratio, 2, PHP_ROUND_HALF_DOWN);
$merchantUser = $merchant->user;
if ($merchantUser->profit < $userProfit) {
throw new OrderException('店铺返现账户余额不足');
}
}
// 扫码付款
else if ($scene === OrderScene::Scan->value) {
$request->validate([
'money' => 'required',
'merchant_id' => 'required',
]);
$merchant = Merchant::findOrFail($request->input('merchant_id'));
if (!$merchant->enable()) {
throw new OrderException('店铺不可用');
}
$store->merchant($merchant);
$store->money($request->input('money'));
} else {
return $this->error('未知下单场景');
}
try {
DB::beginTransaction();
$order = $store->create();
// 删除购物车商品
if ($request->filled('cart_id')) {
$user->carts()->whereIn('id', $request->input('cart_id'))->delete();
}
$result = OrderResource::make($order);
if ($request->filled('pay_way')) {
$result = [];
$payData = OrderService::make()->pay($order, $request->input('pay_way'));
$result['order'] = OrderResource::make($order);
$result['payment'] = $payData;
}
DB::commit();
return $this->json($result);
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
}
public function show($id)
{
$user = auth('api')->user();
$order = $user->orders()->with(['goods'])->findOrFail($id);
return $this->json(OrderResource::make($order));
}
public function pay($id, Request $request)
{
$request->validate([
'pay_way' => ['required', new Enum(PayWay::class)]
]);
$user = auth('api')->user();
$order = $user->orders()->findOrFail($id);
try {
DB::beginTransaction();
$result = OrderService::make()->pay($order, PayWay::WxMini->value);
DB::commit();
return $this->json($result);
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
}
public function cancel($id, Request $request)
{
$user = auth('api')->user();
$order = $user->orders()->findOrFail($id);
try {
DB::beginTransaction();
OrderService::make()->cancel($order);
$order->options()->create([
'user_type' => get_class($user),
'user_id' => $user->id,
'description' => '用户取消订单',
'attribute' => [
'is_closed' => 1
]
]);
DB::commit();
return $this->success('订单成功取消');
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
}
public function receive($id)
{
$user = auth('api')->user();
$order = $user->orders()->findOrFail($id);
try {
DB::beginTransaction();
OrderService::make()->receive($order);
$order->options()->create([
'user_type' => get_class($user),
'user_id' => $user->id,
'description' => '用户 确认收货',
'attribute' => [
'is_closed' => 1
]
]);
DB::commit();
return $this->success('收货成功');
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
}
public function destroy($id)
{
$user = auth('api')->user();
$order = $user->orders()->findOrFail($id);
try {
DB::beginTransaction();
OrderService::make()->delete($order);
DB::commit();
return $this->success('删除成功');
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
}
public function ships($id)
{
$user = auth('api')->user();
$order = $user->orders()->findOrFail($id);
$list = $order->ships()->with(['goods'])->sort()->get();
return $this->json(OrderShipResouce::collection($list));
}
public function logistics(Request $request)
{
$request->validate([
'order_id' => 'required',
'ship_id' => 'required',
]);
$user = auth('api')->user();
$order = $user->orders()->findOrFail($request->input('order_id'));
$ship = $order->ships()->findOrFail($request->input('ship_id'));
return $this->success();
}
protected function formatCartGoods($carts)
{
$goods = [];
foreach($carts as $item) {
array_push($goods, [
'id' => $item->goods_id,
'amount' => $item->amount,
'spec' => $item->spec,
'part' => $item->part,
]);
}
return $goods;
}
protected function formatAddress($userAddress)
{
$address = [];
if ($userAddress instanceof UserAddress) {
$address = [
'name' => $userAddress->contact_name,
'phone' => $userAddress->phone,
'region' => [$userAddress->province?->name, $userAddress->city?->name, $userAddress->area?->name],
'zone' => [$userAddress->province_id, $userAddress->city_id, $userAddress->area_id],
'address' => $userAddress->address,
'address_id' => $userAddress->id
];
} else if (is_array($userAddress)) {
$address = $userAddress;
$region = data_get($address, 'region');
if (!$region || count($region) === 0) {
throw new OrderException('收货地址格式不正确');
}
$area = Zone::where('name', $region[2])->where('type', 'area')->firstOrFail();
$city = Zone::findOrFail($area->parent_id);
$address['zone'] = [$city->parent_id, $area->parent_id, $area->id];
}
return $address;
}
}