552 lines
20 KiB
PHP
Executable File
552 lines
20 KiB
PHP
Executable File
<?php
|
||
|
||
namespace App\Service;
|
||
|
||
use App\Enums\BoolEnum;
|
||
use App\Enums\LottState;
|
||
use App\Enums\MaterialScene;
|
||
use App\Enums\OrderType;
|
||
use App\Enums\PayState;
|
||
use App\Events\OrderTicketedEvent;
|
||
use App\Exceptions\JingCaiException;
|
||
use App\Model\Config;
|
||
use App\Model\Customer\Customer;
|
||
use App\Model\Lottery;
|
||
use App\Model\LotteryType;
|
||
use App\Model\Material;
|
||
use App\Model\Order;
|
||
use App\Model\Seller\Seller;
|
||
use App\Model\Seller\ShopCooperateLottery;
|
||
use App\Utils\ThrowException;
|
||
use Illuminate\Support\Arr;
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
class OrderService
|
||
{
|
||
/**
|
||
* 跟单
|
||
* @param $data
|
||
* @param Customer $customer
|
||
* @return Order
|
||
* @throws \Throwable
|
||
*/
|
||
public function copyOrder($data, Customer $customer)
|
||
{
|
||
$orderSn = Arr::get($data, 'order_sn');
|
||
throw_if(!$orderSn, JingCaiException::create('id不能为空!'));
|
||
|
||
/** @var Order $od */
|
||
$od = Order::sn($orderSn)->first();
|
||
|
||
ThrowException::isTrue($od->type != OrderType::FADAN, '请在跟单大厅中跟单');
|
||
ThrowException::isTrue(!$od->canCopy(), '已无法跟单,请选择大厅中的其他跟单');
|
||
|
||
$jingcaiService = LotteryService::getJingcaiServiceByOrder($od);
|
||
return $jingcaiService->copyOrder($customer, $od, $data);
|
||
}
|
||
|
||
/**
|
||
* 创建订单
|
||
* @param $data
|
||
* @param \App\Model\Customer\Customer $customer
|
||
* @return Order
|
||
* @throws \Throwable
|
||
*/
|
||
public function create($data, Customer $customer)
|
||
{
|
||
$lotteryTypeId = Arr::get($data, 'lottery_type_id');
|
||
$lotteryType = LotteryType::find($lotteryTypeId);
|
||
ThrowException::isTrue(!$lotteryType, '暂不支持该彩种');
|
||
$jingcaiService = LotteryService::getJingcaiService($lotteryType->type);
|
||
return $jingcaiService->createOrder($customer, $data);
|
||
}
|
||
|
||
/**
|
||
* 设置订单为支付成功状态
|
||
* @param Order $order
|
||
* @throws \Throwable
|
||
*/
|
||
public function setOrderPaySuccess(Order $order)
|
||
{
|
||
// 参与合买的订单支付
|
||
if ($order->type == OrderType::UNION && $order->pid != $order->id) {
|
||
$this->setUnionOrderPaySuccess($order);
|
||
return;
|
||
}
|
||
try {
|
||
DB::beginTransaction();
|
||
|
||
/** @var Order $order */
|
||
$order = Order::lockForUpdate()->find($order->id);
|
||
if ($order->pay_state != PayState::UNPAID) {
|
||
JingCaiException::throwJingcai('订单错误,请重新下单');
|
||
}
|
||
|
||
CustomerWalletService::buyLottery($order);
|
||
|
||
// 修改订单支付状态
|
||
$order->setSuccess();
|
||
|
||
DB::commit();
|
||
} catch (JingCaiException $exception) {
|
||
DB::rollBack();
|
||
throw $exception;
|
||
} catch (\Exception $exception) {
|
||
DB::rollBack();
|
||
throw $exception;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 参与合买的流程
|
||
* 设置订单为支付成功状态
|
||
* @param Order $order
|
||
* @throws \Throwable
|
||
*/
|
||
public function setUnionOrderPaySuccess(Order $order)
|
||
{
|
||
try {
|
||
DB::beginTransaction();
|
||
|
||
/** @var Order $unionOrder */
|
||
$unionOrder = Order::lockForUpdate()->find($order->pid);
|
||
|
||
if (date('Y-m-d H:i:s') > $unionOrder->odds_early_close_time) {
|
||
ThrowException::run('订单已截止!');
|
||
}
|
||
|
||
/** @var Order $order */
|
||
$order = Order::lockForUpdate()->find($order->id);
|
||
if ($order->pay_state != PayState::UNPAID) {
|
||
JingCaiException::throwJingcai('订单错误,请重新下单');
|
||
}
|
||
// ThrowException::isTrue($order->customer_id == $unionOrder->customer_id, '发起者不能参与合买');
|
||
|
||
$remainPiece = $unionOrder->union_piece_total - $unionOrder->union_piece_buy - $order->union_piece_self;
|
||
|
||
ThrowException::isTrue($remainPiece < 0, '剩余份数不总,无法支付');
|
||
|
||
// 更新订单的购买份数
|
||
$unionOrder->union_piece_buy += $order->union_piece_self;
|
||
|
||
// 如果合买已完成,则更新合买完成状态
|
||
if ($unionOrder->union_piece_total == $unionOrder->union_piece_buy) {
|
||
$unionOrder->union_pay_success = BoolEnum::YES;
|
||
}
|
||
$unionOrder->save();
|
||
|
||
CustomerWalletService::buyLottery($order);
|
||
// 修改订单支付状态
|
||
$order->setSuccess();
|
||
|
||
DB::commit();
|
||
} catch (JingCaiException $exception) {
|
||
DB::rollBack();
|
||
throw $exception;
|
||
} catch (\Exception $exception) {
|
||
DB::rollBack();
|
||
throw $exception;
|
||
}
|
||
}
|
||
|
||
public function sellerThrowCooperate(Seller $seller, $orderSn)
|
||
{
|
||
/** @var Order $order */
|
||
$order = Order::sn($orderSn)->first();
|
||
ThrowException::isTrue(!$order, '订单不存在');
|
||
ThrowException::isTrue($order->shop_id != $seller->shop_id, '无法跨店甩单');
|
||
|
||
ThrowException::isTrue($order->lottery_state != LottState::PENDING, '订单状态不对,无法接单');
|
||
|
||
ThrowException::isTrue($order->type == OrderType::UNION, '合作模式不支持合买');
|
||
|
||
ThrowException::isTrue($order->cooperate_id <= 0 || $order->cooperate_id == $seller->shop_id, '该订单不是合作店铺模式产生的');
|
||
|
||
/** @var Lottery $lottery */
|
||
$lottery = $order->lottery;
|
||
$scl = $lottery->shopCooperateLottery;
|
||
ThrowException::isTrue(!$scl, '该订单对应的彩种没有开启合作店铺');
|
||
|
||
$order->cooperate_throw_seller_id = $seller->id;
|
||
$order->cooperate_show = BoolEnum::YES;
|
||
$order->save();
|
||
}
|
||
|
||
protected function cooperateOrderValid(Seller $seller, Order $order)
|
||
{
|
||
/** @var Lottery $lottery */
|
||
$lottery = $order->lottery;
|
||
// 本店铺操作
|
||
if ($order->shop_id == $seller->shop_id) {
|
||
|
||
ThrowException::isTrue($lottery->owned == BoolEnum::NO, '本店无此彩种,无法操作');
|
||
|
||
} else {
|
||
// 合作店铺操作
|
||
ThrowException::isTrue($lottery->cooperate_id <= 0, '不是合作订单,无法操作');
|
||
$scl = $lottery->shopCooperateLottery;
|
||
ThrowException::isTrue(!$scl || $scl->cooperate_id != $seller->shop_id, '该订单未与本店铺合作,无法操作');
|
||
}
|
||
}
|
||
public function sellerReceive(Seller $seller, $orderSn)
|
||
{
|
||
$order = Order::sn($orderSn)->first();
|
||
ThrowException::isTrue(!$order, '订单不存在');
|
||
ThrowException::isTrue($order->lottery_state != LottState::PENDING, '订单状态不对,无法接单');
|
||
|
||
$this->cooperateOrderValid($seller, $order);
|
||
if ($order->type == OrderType::UNION) {
|
||
ThrowException::isTrue($order->id != $order->pid, '订单有误,无法接单');
|
||
ThrowException::isTrue($order->union_piece_total > $order->union_piece_buy + $order->union_piece_keep, '合买未完成,无法接单');
|
||
}
|
||
|
||
// 刷新彩票信息,更新订单状态
|
||
$jingcaiService = LotteryService::getJingcaiServiceByOrder($order);
|
||
if ($jingcaiService instanceof JclqService) {
|
||
$oddsInfo = $jingcaiService->refreshOdds($order->odds);
|
||
$odds = $oddsInfo['odds'];
|
||
$oddsRaw = $oddsInfo['odds_raw'];
|
||
} else {
|
||
$odds = $jingcaiService->refreshOdds($order->odds);
|
||
$oddsRaw = null;
|
||
}
|
||
|
||
$order->odds = $odds;
|
||
$order->odds_raw = $oddsRaw;
|
||
|
||
$order->receive_user_id = $seller->id;
|
||
$order->receive_at = date('Y-m-d H:i:s');
|
||
$order->receive_date = date('Ymd');
|
||
$order->lottery_state = LottState::DRAFT;
|
||
$order->save();
|
||
$order->updateUnionOrderState(LottState::DRAFT);
|
||
|
||
}
|
||
|
||
public function sellerRevoke(Seller $seller, $orderSn,$revokeMessage = '')
|
||
{
|
||
$order = Order::sn($orderSn)->first();
|
||
ThrowException::isTrue(!$order, '订单不存在');
|
||
ThrowException::isTrue($order->lottery_state != LottState::DRAFT, '订单状态不对,无法撤单');
|
||
// ThrowException::isTrue($order->shop_id != $seller->shop_id, '无法跨店撤单');
|
||
$this->cooperateOrderValid($seller, $order);
|
||
if ($order->type == OrderType::UNION && $order->id != $order->pid) {
|
||
ThrowException::run('订单有误,无法撤单');
|
||
}
|
||
|
||
DB::beginTransaction();
|
||
try {
|
||
|
||
$order->revoke_user_id = $seller->id;
|
||
$order->revoke_at = date('Y-m-d H:i:s');
|
||
$order->revoke_message = $revokeMessage;
|
||
$order->lottery_state = LottState::REVOKE;
|
||
$order->save();
|
||
|
||
$order->updateUnionOrderState(LottState::REVOKE);
|
||
|
||
CustomerWalletService::refundForRevokeOrder($order, $seller);
|
||
|
||
DB::commit();
|
||
} catch (\Exception $exception) {
|
||
DB::rollBack();
|
||
throw $exception;
|
||
}
|
||
}
|
||
|
||
|
||
public function sellerUploadPiao(Seller $seller, $orderSn, $materialIds)
|
||
{
|
||
ThrowException::isTrue(!$materialIds, '请上传图片');
|
||
$order = Order::sn($orderSn)->first();
|
||
ThrowException::isTrue(!$order, '订单不存在');
|
||
$this->cooperateOrderValid($seller, $order);
|
||
|
||
Material::where('order_id', $order->id)->delete();
|
||
|
||
Material::whereIn('id', $materialIds)
|
||
->where('scene', MaterialScene::LOTTERY)
|
||
->where('order_id', 0)
|
||
->update(['order_id' => $order->id]);
|
||
}
|
||
|
||
public function sellerDraw(Seller $seller, $orderSn, $materialIds, $oddses)
|
||
{
|
||
ThrowException::isTrue(!$materialIds, '请上传图片');
|
||
|
||
$order = Order::sn($orderSn)->first();
|
||
ThrowException::isTrue(!$order, '订单不存在');
|
||
ThrowException::isTrue($order->lottery_state != LottState::DRAFT, '订单状态不对,无法出票');
|
||
ThrowException::isTrue(!$order->sameToReceiver($seller->id), '无出票权限');
|
||
$this->cooperateOrderValid($seller, $order);
|
||
DB::beginTransaction();
|
||
try {
|
||
|
||
// 出票相关账单
|
||
SellerWalletService::ticket($order, $seller);
|
||
|
||
// 刷新彩票信息,更新订单状态
|
||
$jingcaiService = LotteryService::getJingcaiServiceByOrder($order);
|
||
$order = Order::lockForUpdate()->find($order->id);
|
||
|
||
$orderOdds = $order->odds;
|
||
if ($oddses) {
|
||
// 更新赔率
|
||
foreach ($oddses as $id => $oddItem) {
|
||
foreach ($oddItem as $oddPlay => $playData) {
|
||
foreach ($playData as $play => $oddval) {
|
||
if (Arr::get($orderOdds, $id. '.'. $oddPlay. '.' . $play) !== null) {
|
||
$orderOdds[$id][$oddPlay][$play] = $oddval;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
$order->odds = $orderOdds;
|
||
}
|
||
|
||
$computeInfo = $jingcaiService->computePrizeInfo($order->odds, $order->bets_num, $order->pass_mode);
|
||
if ($computeInfo && Arr::get($computeInfo, 'prize_min') !== null) {
|
||
$order->prize_min = Arr::get($computeInfo, 'prize_min');
|
||
}
|
||
if ($computeInfo && Arr::get($computeInfo, 'prize_max') !== null) {
|
||
$order->prize_max = Arr::get($computeInfo, 'prize_max');
|
||
}
|
||
$order->lottery_state = LottState::WAIT;
|
||
$order->draft_at = date('Y-m-d H:i:s');
|
||
$order->draft_date = date('Ymd');
|
||
$order->draft_user_id = $seller->id;
|
||
$order->draft_shop_id = $seller->shop_id;
|
||
$order->save();
|
||
|
||
$order->updateUnionOrderState(LottState::WAIT);
|
||
|
||
DB::commit();
|
||
// 发送出票事件
|
||
OrderTicketedEvent::dispatch($order->id);
|
||
|
||
} catch (JingCaiException $exception) {
|
||
DB::rollBack();
|
||
throw $exception;
|
||
} catch (\Exception $exception) {
|
||
DB::rollBack();
|
||
throw $exception;
|
||
}
|
||
Material::whereIn('id', $materialIds)
|
||
->where('scene', MaterialScene::LOTTERY)
|
||
->where('order_id', 0)
|
||
->update(['order_id' => $order->id]);
|
||
}
|
||
|
||
public function sellerSendPrize(Seller $seller, $orderSn, $sendPrize)
|
||
{
|
||
ThrowException::isTrue(!$seller->enable_send_prize, '无派奖权限');
|
||
$order = Order::sn($orderSn)->first();
|
||
ThrowException::isTrue(!$order, '订单不存在');
|
||
ThrowException::isTrue($order->lottery_state != LottState::WIN, '订单状态不对,无法派奖');
|
||
$this->cooperateOrderValid($seller, $order);
|
||
ThrowException::isTrue($sendPrize <= 0, '奖金有误');
|
||
if ($order->type == OrderType::UNION) {
|
||
return $this->sellerSendUnionPrize($seller, $order, $sendPrize);
|
||
}
|
||
|
||
if ($order->type == OrderType::GENDAN) {
|
||
return $this->sellerSendGendanPrize($seller, $order, $sendPrize);;
|
||
}
|
||
return $this->sellerSendNormalPrize($seller, $order, $sendPrize);
|
||
}
|
||
|
||
public function sellerTakeTicket(Seller $seller, $orderSn)
|
||
{
|
||
$order = Order::sn($orderSn)->first();
|
||
ThrowException::isTrue(!$order, '订单不存在');
|
||
ThrowException::isTrue($order->lottery_take_ticket != BoolEnum::NO, '不可重复取票');
|
||
ThrowException::isTrue($order->lottery->shop_id != $seller->shop_id, '无法跨店取票');
|
||
$this->cooperateOrderValid($seller, $order);
|
||
|
||
$order->lottery_take_ticket = BoolEnum::YES;
|
||
$order->save();
|
||
}
|
||
/**
|
||
* 派奖:合买
|
||
* @param $seller
|
||
* @param $order
|
||
* @param $sendPrize
|
||
* @throws \Exception
|
||
*/
|
||
private function sellerSendUnionPrize($seller, $order, $sendPrize)
|
||
{
|
||
if ($order->type == OrderType::UNION && $order->id != $order->pid) {
|
||
ThrowException::run('该合买参与订单不可派奖!');
|
||
}
|
||
DB::beginTransaction();
|
||
try {
|
||
$unionBrokerageLv = 0;
|
||
// 如果设置了合买佣金
|
||
if ($order->union_brokerage) {
|
||
$unionBrokerageLv = $order->union_brokerage / 100;
|
||
}
|
||
$unionBrokerage = $order->lottery_should_send_prize * $unionBrokerageLv;
|
||
|
||
// 合买主单的数据
|
||
$order->lottery_state = LottState::SEND;
|
||
$order->lottery_send_prize = $sendPrize;
|
||
$order->send_user_id = $seller->id;
|
||
$order->send_at = date('Y-m-d H:i:s');
|
||
$order->send_date = date('Ymd');
|
||
$order->union_brokerage_money = $unionBrokerage;
|
||
$order->save();
|
||
if ($order->union_brokerage && $unionBrokerage > 0) {
|
||
// 合买佣金
|
||
CustomerWalletService::unionBrokerage($order, $unionBrokerage);
|
||
}
|
||
|
||
$perShouldPrize = ($order->lottery_should_send_prize - $unionBrokerage) / $order->union_piece_total;
|
||
$perPrize = ($sendPrize - $unionBrokerage) / $order->union_piece_total;
|
||
|
||
// 合买参与人的数据
|
||
$unionOrders = Order::where('type', OrderType::UNION)
|
||
->where('pay_state', PayState::SUCCESS)
|
||
->where('pid', $order->id)->get();
|
||
foreach ($unionOrders as $unionOrder) {
|
||
|
||
$buyPiece = $unionOrder->union_piece_self;
|
||
if ($unionOrder->id == $unionOrder->pid) {
|
||
$buyPiece = $unionOrder->union_piece_self + $unionOrder->union_piece_keep;
|
||
}
|
||
$unionOrder->union_send_prize = $perPrize * $buyPiece;
|
||
$unionOrder->union_should_send_prize = $perShouldPrize * $buyPiece;
|
||
$unionOrder->lottery_state = LottState::SEND;
|
||
$unionOrder->save();
|
||
|
||
// 中奖
|
||
CustomerWalletService::winPrize($unionOrder, $unionOrder->union_send_prize);
|
||
}
|
||
|
||
DB::commit();
|
||
} catch (JingCaiException $exception) {
|
||
DB::rollBack();
|
||
throw $exception;
|
||
} catch (\Exception $exception) {
|
||
DB::rollBack();
|
||
throw $exception;
|
||
}
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* 跟单中奖100元后,各个环节账单流水:
|
||
*
|
||
* 跟单人:
|
||
* +100 奖金
|
||
* -10 跟单佣金
|
||
*
|
||
* 跟单人店铺:
|
||
* -10 平台扣除佣金
|
||
*
|
||
* 跟单人店铺:
|
||
* +2 平台派发佣金
|
||
*
|
||
* 发单人店铺:
|
||
* +6 发单佣金
|
||
*
|
||
* 发单人账户余额:
|
||
* +6
|
||
* 派奖:跟单
|
||
* @param $seller
|
||
* @param $order
|
||
* @param $sendPrize 奖金扣除跟单佣金后的金额
|
||
* @throws \Exception
|
||
*/
|
||
private function sellerSendGendanPrize($seller, $order, $sendPrize)
|
||
{
|
||
DB::beginTransaction();
|
||
try {
|
||
$order = Order::lockForUpdate()->find($order->id);
|
||
|
||
$winPrize = $sendPrize;
|
||
|
||
$allBrokerage = $winPrize * Config::fadanAllFeeLv();
|
||
|
||
$userBroerage = $allBrokerage * Config::fadanUserFeeLv();
|
||
|
||
// 跟单中奖
|
||
$order->send_user_id = $seller->id;
|
||
$order->send_at = date('Y-m-d H:i:s');
|
||
$order->send_date = date('Ymd');
|
||
$order->lottery_state = LottState::SEND;
|
||
$order->lottery_send_prize = $winPrize;
|
||
$order->lottery_gendan_brokerage = $userBroerage;
|
||
$order->lottery_gendan_brokerage_all = $allBrokerage;
|
||
$order->save();
|
||
|
||
// if (!$order->isTakeTicket()) {
|
||
SellerWalletService::cooperateOrderWined($seller, $order);
|
||
|
||
// -------跟单用户 start
|
||
// 跟单中奖
|
||
CustomerWalletService::winPrize($order, $sendPrize);
|
||
// 扣除跟单佣金
|
||
CustomerWalletService::gendanReduceBrokerage($order);
|
||
// -------跟单用户 end
|
||
// }
|
||
|
||
// -------跟单店铺 start
|
||
// 跟单人店铺扣除所有发单佣金
|
||
SellerWalletService::gendanShopReduceAllBrokerage($seller, $order, $sendPrize);
|
||
// 跟单人店铺增加部分佣金
|
||
SellerWalletService::gendanShopIncrBrokerage($seller, $order, $sendPrize);
|
||
// -------跟单店铺 end
|
||
|
||
// 发单人店铺增加佣金
|
||
$pOrder = $order->pOrder;
|
||
SellerWalletService::fadanShopIncrBrokerage($order, $pOrder->shop_id, $sendPrize);
|
||
|
||
// 发单人余额增加佣金
|
||
CustomerWalletService::fadanBrokerage($order, $pOrder->customer_id, $sendPrize);
|
||
|
||
DB::commit();
|
||
} catch (JingCaiException $exception) {
|
||
DB::rollBack();
|
||
throw $exception;
|
||
} catch (\Exception $exception) {
|
||
DB::rollBack();
|
||
throw $exception;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 派奖:下注
|
||
* @param $seller
|
||
* @param $order
|
||
* @param $sendPrize
|
||
* @throws \Exception
|
||
*/
|
||
private function sellerSendNormalPrize($seller, $order, $sendPrize)
|
||
{
|
||
DB::beginTransaction();
|
||
try {
|
||
|
||
$order->send_user_id = $seller->id;
|
||
$order->send_at = date('Y-m-d H:i:s');
|
||
$order->send_date = date('Ymd');
|
||
$order->lottery_state = LottState::SEND;
|
||
$order->lottery_send_prize = $sendPrize;
|
||
$order->save();
|
||
|
||
// if (!$order->isTakeTicket()) {
|
||
SellerWalletService::cooperateOrderWined($seller, $order);
|
||
|
||
CustomerWalletService::winPrize($order, $sendPrize);
|
||
// }
|
||
|
||
DB::commit();
|
||
} catch (JingCaiException $exception) {
|
||
DB::rollBack();
|
||
throw $exception;
|
||
} catch (\Exception $exception) {
|
||
DB::rollBack();
|
||
throw $exception;
|
||
}
|
||
}
|
||
}
|