jingcai-php/app/Service/OrderService.php

552 lines
20 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?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;
}
}
}