Merge branch 'hotfix/fix-dealer-settle' into develop
commit
df124a8dc8
|
|
@ -0,0 +1,722 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Admin\Imports;
|
||||||
|
|
||||||
|
use App\Enums\DealerEarningStatus;
|
||||||
|
use App\Enums\DealerLvl;
|
||||||
|
use App\Enums\DealerOrderSettleState;
|
||||||
|
use App\Exceptions\BizException;
|
||||||
|
use App\Exceptions\ImportException;
|
||||||
|
use App\Models\Dealer;
|
||||||
|
use App\Models\DealerChannelSubsidyLog;
|
||||||
|
use App\Models\DealerManagerSalesLog;
|
||||||
|
use App\Models\DealerManageSubsidyLog;
|
||||||
|
use App\Models\DealerOrder;
|
||||||
|
use App\Models\DealerOrderAllocateLog;
|
||||||
|
use App\Models\DealerProduct;
|
||||||
|
use App\Models\DealerPurchaseLog;
|
||||||
|
use App\Models\DealerUserProduct;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Services\Dealer\OrderService;
|
||||||
|
use Illuminate\Database\QueryException;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class DealerOrderImport extends Import
|
||||||
|
{
|
||||||
|
public function loadRow($row)
|
||||||
|
{
|
||||||
|
/**校验行数据 **/
|
||||||
|
//获取下单用户
|
||||||
|
$phone = $row->getCellAtIndex(0)?->getValue();
|
||||||
|
if (empty($phone)) {
|
||||||
|
throw new ImportException('未输入下单用户手机号');
|
||||||
|
}
|
||||||
|
//获取下单盒数;
|
||||||
|
$qty = $row->getCellAtIndex(1)?->getValue();
|
||||||
|
if (empty($qty)) {
|
||||||
|
throw new ImportException('未输入下单盒数');
|
||||||
|
}
|
||||||
|
//获取下单金额;
|
||||||
|
$totalAmount = $row->getCellAtIndex(2)?->getValue();
|
||||||
|
if (empty($totalAmount)) {
|
||||||
|
throw new ImportException('未输入下单金额');
|
||||||
|
}
|
||||||
|
//获取目标等级
|
||||||
|
$toLv = $row->getCellAtIndex(3)?->getValue();
|
||||||
|
if (empty($toLv)) {
|
||||||
|
throw new ImportException('未输入目标等级');
|
||||||
|
}
|
||||||
|
|
||||||
|
$productId = $row->getCellAtIndex(4)?->getValue();
|
||||||
|
if (empty($productId)) {
|
||||||
|
$productId = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::where('phone', $phone)->first();
|
||||||
|
dump('手机号:'.$phone.'开始执行');
|
||||||
|
if ($user) {
|
||||||
|
$orderService = new OrderService();
|
||||||
|
|
||||||
|
$product = DealerProduct::findOrFail($productId);
|
||||||
|
$shippingAddress = $user->shippingAddresses()->orderBy('is_default', 'desc')->first();
|
||||||
|
try {
|
||||||
|
DB::beginTransaction();
|
||||||
|
//执行自己升级
|
||||||
|
if ($toLv < 4) {
|
||||||
|
$user->dealer->upgrade(DealerLvl::from($toLv), '后台修改等级');
|
||||||
|
//执行上级尝试升级
|
||||||
|
foreach ($user->dealer->getDealers() as $parentDealer) {
|
||||||
|
$parentDealer->attemptUpgrade();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/**下单 -start **/
|
||||||
|
//没有地址
|
||||||
|
if (!$shippingAddress) {
|
||||||
|
$shippingAddress = $user->shippingAddresses()->create([
|
||||||
|
'zone_id'=>3,
|
||||||
|
'zone'=>'北京市 北京市 东城区',
|
||||||
|
'consignee'=>'测试',
|
||||||
|
'telephone'=>'18888888888',
|
||||||
|
'address'=>'1',
|
||||||
|
'is_default'=>true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$order = $orderService->quickCreateOrder($user, $product, $qty, $shippingAddress->id);
|
||||||
|
//重新按新规则给一次发货人
|
||||||
|
if ($order->consignor_id) {
|
||||||
|
$order->update([
|
||||||
|
'consignor_id'=>$this->getConsignor($user, $order->total_amount)?->user_id,
|
||||||
|
]);
|
||||||
|
$order->refresh();
|
||||||
|
if (!($order->consignor_id > 1)) {//如果是null或者1
|
||||||
|
//确认接单
|
||||||
|
$order = $orderService->confirmOrder($order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**下单 -end **/
|
||||||
|
dump('下单:'.$order->sn);
|
||||||
|
/**更新订单状态 -start **/
|
||||||
|
//【金牌】,【特邀】订单需要发货人有对应的库存,否则往上丢
|
||||||
|
if (in_array($toLv, [
|
||||||
|
'2', '3',
|
||||||
|
])) {
|
||||||
|
do {
|
||||||
|
if ($order->consignor_id > 1) {
|
||||||
|
$userProduct = DealerUserProduct::where('user_id', $order->consignor_id)->where('stock', '>', 0)->first();
|
||||||
|
if (!$userProduct) {
|
||||||
|
//没找到库存商品,则继续往上丢
|
||||||
|
$order = $this->updateOrderConsignor($order);
|
||||||
|
$order->refresh();
|
||||||
|
} else {
|
||||||
|
// if ($userProduct->stock < $qty) {
|
||||||
|
// //记录手机号
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (!$userProduct);
|
||||||
|
}
|
||||||
|
if ($order->isPending()) {
|
||||||
|
//确认接单
|
||||||
|
$order = $orderService->confirmOrder($order);
|
||||||
|
}
|
||||||
|
//确认打款
|
||||||
|
$order = $orderService->payOrder($order, 'offline');
|
||||||
|
//确认收款
|
||||||
|
$order = $orderService->paidOrder($order);
|
||||||
|
|
||||||
|
//如果目标等级是【金牌】【特邀】则只到【待发货】。其余订单走到【已完成】
|
||||||
|
if (!in_array($toLv, [
|
||||||
|
'2', '3',
|
||||||
|
])) {
|
||||||
|
//确认发货
|
||||||
|
$order = $orderService->shippingOrder($order);
|
||||||
|
//确认收货
|
||||||
|
$order = $orderService->shippingedOrder($order);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**更新订单状态 -end **/
|
||||||
|
|
||||||
|
//执行升级结算订单
|
||||||
|
$this->handleDealerOrder($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($th->getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new ImportException('未找到用户:'.$phone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新订单发货人
|
||||||
|
*
|
||||||
|
* @return DealerOrder
|
||||||
|
*/
|
||||||
|
public function updateOrderConsignor(DealerOrder $order)
|
||||||
|
{
|
||||||
|
//只处理当前订单有发货人的情况
|
||||||
|
if ($order->consignor) {
|
||||||
|
$consignor = $this->getConsignor($order->user, $order->total_amount, $order->consignor);
|
||||||
|
$oldConsignor = $order->consignor;
|
||||||
|
$order->update([
|
||||||
|
'allocated_at' => now(),
|
||||||
|
'consignor_id' => $consignor?->user_id,
|
||||||
|
]);
|
||||||
|
//记录分配日志
|
||||||
|
DealerOrderAllocateLog::create([
|
||||||
|
'order_id'=>$order->id,
|
||||||
|
'last_consignor_id'=>$oldConsignor->id,
|
||||||
|
'new_consignor_id' =>$order->consignor_id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getConsignor(User $user, $totalAmount, ?User $lastConsignor = null)
|
||||||
|
{
|
||||||
|
$rules = [
|
||||||
|
[
|
||||||
|
'amount' => '2640',
|
||||||
|
'lvl' => DealerLvl::Contracted,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'amount' => '860',
|
||||||
|
'lvl' => DealerLvl::Special,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'amount' => '630',
|
||||||
|
'lvl' => DealerLvl::Gold,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
$lvl = $user->dealer->lvl;
|
||||||
|
//计算通过这个订单可能升级成为的身份
|
||||||
|
foreach ($rules as $rule) {
|
||||||
|
if ($totalAmount >= $rule['amount'] && $lvl->value < $rule['lvl']->value) {
|
||||||
|
$lvl = $rule['lvl'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//如果是签约单,直接抛到公司后台发货
|
||||||
|
if ($lvl->value >= DealerLvl::Contracted->value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
//新逻辑
|
||||||
|
$consignor = null;
|
||||||
|
$_lastConsignor = $lastConsignor;
|
||||||
|
do {
|
||||||
|
$query = User::with(['userInfo', 'dealer']);
|
||||||
|
if ($_lastConsignor) {
|
||||||
|
$query->where('id', $_lastConsignor->userInfo->real_inviter_id);
|
||||||
|
} else {
|
||||||
|
$query->where('id', $user->userInfo->real_inviter_id);
|
||||||
|
}
|
||||||
|
$consignor = $query->first();
|
||||||
|
if ($consignor) {//找到老上级
|
||||||
|
if ($consignor->dealer->is_sale == true && $consignor->dealer->lvl->value > $lvl->value) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
$_lastConsignor = $consignor;
|
||||||
|
$consignor = null;
|
||||||
|
}
|
||||||
|
} else {//如果找不到人了
|
||||||
|
$consignor = $lastConsignor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (empty($consignor));
|
||||||
|
|
||||||
|
return $consignor?->userInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理经销商订单
|
||||||
|
*
|
||||||
|
* @param \App\Models\DealerOrder $dealerOrder
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function handleDealerOrder(DealerOrder $dealerOrder)
|
||||||
|
{
|
||||||
|
$tz = now()->toDateTimeString();
|
||||||
|
|
||||||
|
// 上级经销商
|
||||||
|
$ancestors = $dealerOrder->dealer->getDealers();
|
||||||
|
|
||||||
|
// 签约经销商的进货日志
|
||||||
|
$this->handlePurchaseLogsOfContractedDealer($dealerOrder, $tz);
|
||||||
|
|
||||||
|
// 一级签约经销商和二级经销商的管理津贴
|
||||||
|
$this->handleManageSubsidyLogs($dealerOrder, $ancestors, $tz);
|
||||||
|
|
||||||
|
// 管理者的销售业绩
|
||||||
|
$this->handleManagerSalesLogs($dealerOrder, $ancestors, $tz);
|
||||||
|
|
||||||
|
// 渠道补贴
|
||||||
|
$this->handleChannelSubsidy($dealerOrder);
|
||||||
|
|
||||||
|
if ($dealerOrder->dealer->wasChanged('lvl')) {
|
||||||
|
$dealers = [
|
||||||
|
$dealerOrder->dealer,
|
||||||
|
...$ancestors,
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($dealers as $dealer) {
|
||||||
|
$dealer->attemptUpgrade();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将订单标记为已处理
|
||||||
|
$dealerOrder->forceFill([
|
||||||
|
'settle_state' => DealerOrderSettleState::Processed,
|
||||||
|
])->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算渠道补贴
|
||||||
|
*
|
||||||
|
* @param \App\Models\DealerOrder $dealerOrder
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function handleChannelSubsidy(DealerOrder $dealerOrder)
|
||||||
|
{
|
||||||
|
$lvl = $dealerOrder->dealer->lvl;
|
||||||
|
|
||||||
|
$lvlValue = [
|
||||||
|
DealerLvl::Contracted->value => '2640',
|
||||||
|
DealerLvl::Special->value => '860',
|
||||||
|
DealerLvl::Gold->value => '630',
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($dealerOrder->total_amount >= $lvlValue[DealerLvl::Contracted->value]) {
|
||||||
|
// 升级为签约
|
||||||
|
if ($lvl->value < DealerLvl::Contracted->value) {
|
||||||
|
$lvl = DealerLvl::Contracted;
|
||||||
|
}
|
||||||
|
} elseif ($dealerOrder->total_amount >= $lvlValue[DealerLvl::Special->value]) {
|
||||||
|
// 升级为特约
|
||||||
|
if ($lvl->value < DealerLvl::Special->value) {
|
||||||
|
$lvl = DealerLvl::Special;
|
||||||
|
}
|
||||||
|
} elseif ($dealerOrder->total_amount >= $lvlValue[DealerLvl::Gold->value]) {
|
||||||
|
// 升级为金牌
|
||||||
|
if ($lvl->value < DealerLvl::Gold->value) {
|
||||||
|
$lvl = DealerLvl::Gold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果经销商等级小于金牌,则没有渠道补贴
|
||||||
|
if ($lvl->value < DealerLvl::Gold->value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[$dealers, $rule] = $this->mapDealersAndRuleOfChannel($dealerOrder->dealer, $lvl);
|
||||||
|
|
||||||
|
if ($lvl->value >= DealerLvl::Contracted->value) {
|
||||||
|
$upgradeAmount = $lvlValue[DealerLvl::Contracted->value];
|
||||||
|
} else {
|
||||||
|
$upgradeAmount = $lvlValue[$lvl->value];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 手续费比例
|
||||||
|
$feeRate = app_settings('dealer.fee_rate');
|
||||||
|
|
||||||
|
foreach ($dealers as $key => $dealer) {
|
||||||
|
$ruleKey = $dealer->lvl->value.'_'.$key;
|
||||||
|
|
||||||
|
if ($dealer->lvl->value >= DealerLvl::Contracted->value) {
|
||||||
|
$ruleKey = DealerLvl::Contracted->value.'_'.$key;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 补贴金额
|
||||||
|
$subsidyAmount = $rule[$ruleKey];
|
||||||
|
|
||||||
|
$totalAmount = bcmul($subsidyAmount, $dealerOrder->total_amount, 10);
|
||||||
|
$totalAmount = bcdiv($totalAmount, $upgradeAmount, 3);
|
||||||
|
$totalAmount = round($totalAmount, 2);
|
||||||
|
|
||||||
|
$channelSubsidyLog = DealerChannelSubsidyLog::create([
|
||||||
|
'user_id' => $dealer->user_id,
|
||||||
|
'lvl' => $dealer->lvl,
|
||||||
|
'order_id' => $dealerOrder->id,
|
||||||
|
'total_amount' => $totalAmount,
|
||||||
|
'order_id' => $dealerOrder->id,
|
||||||
|
'remark' => "补贴总额={$dealerOrder->total_amount}/{$upgradeAmount}*{$subsidyAmount}",
|
||||||
|
]);
|
||||||
|
|
||||||
|
$fee = bcmul($channelSubsidyLog->total_amount, bcdiv($feeRate, '100', 5), 3);
|
||||||
|
$fee = round($fee, 2);
|
||||||
|
|
||||||
|
$channelSubsidyLog->earning()->create([
|
||||||
|
'user_id' => $channelSubsidyLog->user_id,
|
||||||
|
'lvl' => $channelSubsidyLog->lvl,
|
||||||
|
'total_amount' => $channelSubsidyLog->total_amount,
|
||||||
|
'total_earnings' => bcsub($channelSubsidyLog->total_amount, $fee, 2),
|
||||||
|
'fee' => $fee,
|
||||||
|
'fee_rate' => $feeRate,
|
||||||
|
'payer_id' => $dealerOrder->consignor_id,
|
||||||
|
'status' => DealerEarningStatus::Pending,
|
||||||
|
'remark' => "订单号: {$dealerOrder->sn}",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dealerOrder->dealer->upgrade($lvl, '进货升级');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取渠道补贴经销商和补贴规则
|
||||||
|
*
|
||||||
|
* @param \App\Models\Dealer $dealer
|
||||||
|
* @param \App\Enums\DealerLvl $lvl
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function mapDealersAndRuleOfChannel(Dealer $dealer, DealerLvl $lvl): array
|
||||||
|
{
|
||||||
|
// 渠道补贴经销商
|
||||||
|
$dealers = [];
|
||||||
|
// 渠道补贴规则
|
||||||
|
$rule = null;
|
||||||
|
// 是否升级
|
||||||
|
$isUp = $lvl->value > $dealer->lvl->value;
|
||||||
|
// 最后参与渠道补贴的经销商
|
||||||
|
$last = null;
|
||||||
|
// 前一个直属邀请人
|
||||||
|
$previous = null;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if ($previous) {
|
||||||
|
$_dealer = $previous->userInfo->realInviterInfo?->dealer;
|
||||||
|
$_dealer?->setRelation('userInfo', $previous->userInfo->realInviterInfo);
|
||||||
|
} else {
|
||||||
|
$_dealer = $dealer->userInfo->realInviterInfo?->dealer;
|
||||||
|
$_dealer?->setRelation('userInfo', $dealer->userInfo->realInviterInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
$previous = $_dealer;
|
||||||
|
|
||||||
|
if ($_dealer === null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果经销商等级小于金牌, 那么跳过
|
||||||
|
if ($_dealer->lvl->value < DealerLvl::Gold->value) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($lvl->value >= DealerLvl::Contracted->value) {
|
||||||
|
if ($last === null) {
|
||||||
|
if ($_dealer->lvl->value >= DealerLvl::Contracted->value) {
|
||||||
|
// 渠道补贴规则: 签约 -> 签约 -> 签约
|
||||||
|
$rule = [
|
||||||
|
DealerLvl::Contracted->value.'_0' => '396',
|
||||||
|
DealerLvl::Contracted->value.'_1' => '79',
|
||||||
|
];
|
||||||
|
|
||||||
|
$dealers[] = $_dealer;
|
||||||
|
|
||||||
|
$last = $_dealer;
|
||||||
|
} elseif ($isUp && $_dealer->isSpecialDealer()) {
|
||||||
|
// 渠道补贴规则: 签约 -> 特邀 -> 签约 -> 签约
|
||||||
|
$rule = [
|
||||||
|
DealerLvl::Special->value.'_0' => '264',
|
||||||
|
DealerLvl::Contracted->value.'_1' => '132',
|
||||||
|
DealerLvl::Contracted->value.'_2' => '79',
|
||||||
|
];
|
||||||
|
|
||||||
|
$dealers[] = $_dealer;
|
||||||
|
|
||||||
|
$last = $_dealer;
|
||||||
|
}
|
||||||
|
} elseif ($_dealer->lvl->value >= DealerLvl::Contracted->value) {
|
||||||
|
$dealers[] = $_dealer;
|
||||||
|
|
||||||
|
// 如果最后参与渠道补贴的经销商是签约, 那么已经找到所有参与渠道补贴的经销商
|
||||||
|
if ($last->lvl->value >= DealerLvl::Contracted->value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$last = $_dealer;
|
||||||
|
}
|
||||||
|
} elseif ($lvl === DealerLvl::Special) {
|
||||||
|
if ($_dealer->lvl->value > DealerLvl::Special->value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($last === null) {
|
||||||
|
if ($_dealer->isSpecialDealer()) {
|
||||||
|
// 渠道补贴规则: 特邀 -> 特邀 -> 特邀
|
||||||
|
$rule = [
|
||||||
|
DealerLvl::Special->value.'_0' => '80',
|
||||||
|
DealerLvl::Special->value.'_1' => '20',
|
||||||
|
];
|
||||||
|
|
||||||
|
$dealers[] = $_dealer;
|
||||||
|
|
||||||
|
$last = $_dealer;
|
||||||
|
} elseif ($isUp && $_dealer->isGoldDealer()) {
|
||||||
|
// 渠道补贴规则: 特邀 -> 金牌 -> 特邀 -> 特邀
|
||||||
|
$rule = [
|
||||||
|
DealerLvl::Gold->value.'_0' => '50',
|
||||||
|
DealerLvl::Special->value.'_1' => '30',
|
||||||
|
DealerLvl::Special->value.'_2' => '20',
|
||||||
|
];
|
||||||
|
|
||||||
|
$dealers[] = $_dealer;
|
||||||
|
|
||||||
|
$last = $_dealer;
|
||||||
|
}
|
||||||
|
} elseif ($_dealer->isSpecialDealer()) {
|
||||||
|
$dealers[] = $_dealer;
|
||||||
|
|
||||||
|
if ($last->isSpecialDealer()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$last = $_dealer;
|
||||||
|
}
|
||||||
|
} elseif ($lvl === DealerLvl::Gold) {
|
||||||
|
if ($_dealer->lvl->value >= DealerLvl::Gold->value) {
|
||||||
|
if ($_dealer->isGoldDealer()) {
|
||||||
|
// 渠道补贴规则: 金牌 -> 金牌
|
||||||
|
$rule = [
|
||||||
|
DealerLvl::Gold->value.'_0' => '75',
|
||||||
|
];
|
||||||
|
|
||||||
|
$dealers[] = $_dealer;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$dealers, $rule];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成签约经销商的进货日志
|
||||||
|
*
|
||||||
|
* @param \App\Models\DealerOrder $dealerOrder
|
||||||
|
* @param array $dealers
|
||||||
|
* @param string $tz
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function handlePurchaseLogsOfContractedDealer(DealerOrder $dealerOrder, string $tz)
|
||||||
|
{
|
||||||
|
if (! $this->isContractedDealerToPurchase($dealerOrder)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dealer = $dealerOrder->userInfo->dealer;
|
||||||
|
|
||||||
|
// 采购业绩是否算自己的业绩
|
||||||
|
$valid = $dealer->lvl->value >= DealerLvl::Contracted->value;
|
||||||
|
|
||||||
|
$log = new DealerPurchaseLog([
|
||||||
|
'user_id' => $dealer->user_id,
|
||||||
|
'lvl' => $dealer->lvl,
|
||||||
|
'order_id' => $dealerOrder->id,
|
||||||
|
'total_amount' => $dealerOrder->total_amount,
|
||||||
|
'path' => $valid ? $dealerOrder->userInfo->full_path : $dealerOrder->userInfo->path,
|
||||||
|
'remark' => $valid ? null : '升级签约',
|
||||||
|
]);
|
||||||
|
$log->setCreatedAt($tz);
|
||||||
|
$log->setUpdatedAt($tz);
|
||||||
|
$log->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分配一级签约经销商和二级经销商的管理津贴
|
||||||
|
*
|
||||||
|
* @param \App\Models\DealerOrder $dealerOrder
|
||||||
|
* @param array $dealers
|
||||||
|
* @param string $tz
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function handleManageSubsidyLogs(DealerOrder $dealerOrder, array $dealers, string $tz)
|
||||||
|
{
|
||||||
|
if (! $this->isContractedDealerToPurchase($dealerOrder)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$logs = [];
|
||||||
|
|
||||||
|
foreach ($dealerOrder->products as $product) {
|
||||||
|
if ($product->productManageSubsidyRules->isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 管理津贴分配规则
|
||||||
|
$rules = $product->productManageSubsidyRules->keyBy('lvl');
|
||||||
|
|
||||||
|
$last = null;
|
||||||
|
$ranking = 0;
|
||||||
|
|
||||||
|
foreach ($dealers as $dealer) {
|
||||||
|
if (! in_array($dealer->lvl, [DealerLvl::Secondary, DealerLvl::Top])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果当前经销商等级没有对应的管理津贴分配规则,则忽略
|
||||||
|
if (is_null($rule = $rules->get($dealer->lvl->value))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同等级管理津贴最多给三次
|
||||||
|
if ($last === null || $dealer->lvl->value > $last->lvl->value) {
|
||||||
|
if ($ranking < 3 && $dealer->lvl === DealerLvl::Top) {
|
||||||
|
if ($secondarySubsidyRule = $rules->get(DealerLvl::Secondary->value)) {
|
||||||
|
$key = 'price_'.(1 + $ranking).'st';
|
||||||
|
|
||||||
|
$secondarySubsidy = $secondarySubsidyRule->{$key};
|
||||||
|
|
||||||
|
if (bccomp($secondarySubsidy, '0') === 1) {
|
||||||
|
$logs[] = [
|
||||||
|
'user_id' => $dealer->user_id,
|
||||||
|
'order_id' => $product->order_id,
|
||||||
|
'product_id' => $product->product_id,
|
||||||
|
'lvl' => $dealer->lvl,
|
||||||
|
'sales_volume' => $product->qty,
|
||||||
|
'total_amount' => bcmul($product->qty, $secondarySubsidy, 2),
|
||||||
|
'created_at' => $tz,
|
||||||
|
'updated_at' => $tz,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ranking = 1;
|
||||||
|
} elseif ($ranking < 3 && $dealer->lvl->value === $last->lvl->value) {
|
||||||
|
$ranking++;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$subsidy = $rule->{"price_{$ranking}st"};
|
||||||
|
|
||||||
|
if (bccomp($subsidy, '0') === 1) {
|
||||||
|
$logs[] = [
|
||||||
|
'user_id' => $dealer->user_id,
|
||||||
|
'order_id' => $product->order_id,
|
||||||
|
'product_id' => $product->product_id,
|
||||||
|
'lvl' => $dealer->lvl,
|
||||||
|
'sales_volume' => $product->qty,
|
||||||
|
'total_amount' => bcmul($product->qty, $subsidy, 2),
|
||||||
|
'created_at' => $tz,
|
||||||
|
'updated_at' => $tz,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$last = $dealer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DealerManageSubsidyLog::insert($logs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤出可能会享受管理津贴的经销商(每个等级最多3人)
|
||||||
|
*
|
||||||
|
* @param array $dealers
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function mapManageSubsidyDealers(array $dealers): array
|
||||||
|
{
|
||||||
|
$map = [];
|
||||||
|
$last = null;
|
||||||
|
$ranking = 1;
|
||||||
|
|
||||||
|
foreach ($dealers as $dealer) {
|
||||||
|
if ($last === null || $dealer->lvl->value > $last->lvl->value) {
|
||||||
|
$last = $dealer;
|
||||||
|
$map[] = $last;
|
||||||
|
$ranking = 1;
|
||||||
|
} elseif ($ranking < 3 && $dealer->lvl->value === $last->lvl->value) {
|
||||||
|
$last = $dealer;
|
||||||
|
$map[] = $last;
|
||||||
|
$ranking++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成管理者的销售业绩
|
||||||
|
*
|
||||||
|
* @param \App\Models\DealerOrder $dealerOrder
|
||||||
|
* @param array $dealers
|
||||||
|
* @param string $tz
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function handleManagerSalesLogs(DealerOrder $dealerOrder, array $dealers, string $tz): void
|
||||||
|
{
|
||||||
|
if (! $this->isContractedDealerToPurchase($dealerOrder)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_null($manager = $this->firstManager($dealers))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$logs = [];
|
||||||
|
|
||||||
|
foreach ($dealerOrder->products as $product) {
|
||||||
|
$logs[] = [
|
||||||
|
'user_id' => $manager->user_id,
|
||||||
|
'lvl' => $manager->lvl,
|
||||||
|
'order_id' => $product->order_id,
|
||||||
|
'product_id' => $product->product_id,
|
||||||
|
'sales_volume' => $product->qty,
|
||||||
|
'created_at' => $tz,
|
||||||
|
'updated_at' => $tz,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
DealerManagerSalesLog::insert($logs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从给定的经销商中获取第一个管理者
|
||||||
|
*
|
||||||
|
* @param array $dealers
|
||||||
|
* @return \App\Models\Dealer|null
|
||||||
|
*/
|
||||||
|
protected function firstManager(array $dealers): ?Dealer
|
||||||
|
{
|
||||||
|
foreach ($dealers as $dealer) {
|
||||||
|
if ($dealer->is_manager) {
|
||||||
|
return $dealer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认是否是签约经销商进货
|
||||||
|
*
|
||||||
|
* @param DealerOrder $dealerOrder
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isContractedDealerToPurchase(DealerOrder $dealerOrder): bool
|
||||||
|
{
|
||||||
|
$dealer = $dealerOrder->userInfo->dealer;
|
||||||
|
|
||||||
|
if ($dealer->lvl->value < DealerLvl::Contracted->value) {
|
||||||
|
if ($dealerOrder->total_amount < '2640') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands\Dealer;
|
||||||
|
|
||||||
|
use App\Admin\Imports\DealerOrderImport;
|
||||||
|
use App\Models\ImportJobLog;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
class ManagerSubsidySettleCommand extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'dealer:import-order {fileUri}';
|
||||||
|
|
||||||
|
protected $fileUri = '';
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = '导入批零订单';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
if ($this->hasArgument('fileUri')) {
|
||||||
|
$this->fileUri = $this->argument('fileUri');
|
||||||
|
}
|
||||||
|
$import = new DealerOrderImport();
|
||||||
|
$res = $import->readFileByUrl($this->fileUri);
|
||||||
|
|
||||||
|
ImportJobLog::insert(array_map(function ($value) {
|
||||||
|
return array_merge($value, [
|
||||||
|
'job_id'=> 0,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
|
]);
|
||||||
|
}, $res['errors']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -208,30 +208,31 @@ class OrderService
|
||||||
* 确认接单
|
* 确认接单
|
||||||
*
|
*
|
||||||
* @param DealerOrder $order
|
* @param DealerOrder $order
|
||||||
* @return void
|
* @return DealerOrder $order
|
||||||
*/
|
*/
|
||||||
public function confirmOrder(DealerOrder $order)
|
public function confirmOrder(DealerOrder $order)
|
||||||
{
|
{
|
||||||
if (!$order->isPending()) {
|
if (!$order->isPending()) {
|
||||||
throw new BizException('订单状态异常,请刷新后再试');
|
throw new BizException('无法接单:订单状态异常,请刷新后再试');
|
||||||
}
|
}
|
||||||
$order->update([
|
$order->update([
|
||||||
'status' => DealerOrderStatus::Paying,
|
'status' => DealerOrderStatus::Paying,
|
||||||
]);
|
]);
|
||||||
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 确认打款
|
* 确认打款
|
||||||
*
|
*
|
||||||
* @return void
|
* @return DealerOrder $order
|
||||||
*/
|
*/
|
||||||
public function payOrder(DealerOrder $order, string $payWay, ?string $payImage)
|
public function payOrder(DealerOrder $order, string $payWay, ?string $payImage = null)
|
||||||
{
|
{
|
||||||
if (empty($payWay)) {
|
if (empty($payWay)) {
|
||||||
throw new BizException('请选择付款方式');
|
throw new BizException('请选择付款方式');
|
||||||
}
|
}
|
||||||
if (!$order->isPendinged()) {
|
if (!$order->isPendinged()) {
|
||||||
throw new BizException('订单状态异常,请刷新后再试');
|
throw new BizException('无法付款:订单状态异常,请刷新后再试');
|
||||||
}
|
}
|
||||||
switch ($payWay) {
|
switch ($payWay) {
|
||||||
case DealerOrder::PAY_WAY_WALLET:
|
case DealerOrder::PAY_WAY_WALLET:
|
||||||
|
|
@ -260,35 +261,37 @@ class OrderService
|
||||||
]);
|
]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 确认收款
|
* 确认收款
|
||||||
*
|
*
|
||||||
* @param DealerOrder $order
|
* @param DealerOrder $order
|
||||||
* @return void
|
* @return DealerOrder $order
|
||||||
*/
|
*/
|
||||||
public function paidOrder(DealerOrder $order)
|
public function paidOrder(DealerOrder $order)
|
||||||
{
|
{
|
||||||
if (!$order->isPay()) {
|
if (!$order->isPay()) {
|
||||||
throw new BizException('订单状态异常,请刷新后再试');
|
throw new BizException('无法收款:订单状态异常,请刷新后再试');
|
||||||
}
|
}
|
||||||
$order->update([
|
$order->update([
|
||||||
'status' => DealerOrderStatus::Paid,
|
'status' => DealerOrderStatus::Paid,
|
||||||
'paied_time' => now(),
|
'paied_time' => now(),
|
||||||
]);
|
]);
|
||||||
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 确认发货
|
* 确认发货
|
||||||
*
|
*
|
||||||
* @param DealerOrder $order
|
* @param DealerOrder $order
|
||||||
* @return void
|
* @return DealerOrder $order
|
||||||
*/
|
*/
|
||||||
public function shippingOrder(DealerOrder $order)
|
public function shippingOrder(DealerOrder $order)
|
||||||
{
|
{
|
||||||
if (!$order->isPaid()) {
|
if (!$order->isPaid()) {
|
||||||
throw new BizException('订单状态异常,请刷新后再试');
|
throw new BizException('无法发货:订单状态异常,请刷新后再试');
|
||||||
}
|
}
|
||||||
//扣减发货人库存
|
//扣减发货人库存
|
||||||
if ($order->consignor) {
|
if ($order->consignor) {
|
||||||
|
|
@ -299,12 +302,13 @@ class OrderService
|
||||||
'status' => DealerOrderStatus::Shipped,
|
'status' => DealerOrderStatus::Shipped,
|
||||||
'shipping_time' => now(),
|
'shipping_time' => now(),
|
||||||
]);
|
]);
|
||||||
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function shippingedOrder(DealerOrder $order)
|
public function shippingedOrder(DealerOrder $order)
|
||||||
{
|
{
|
||||||
if (!$order->isShipping()) {
|
if (!$order->isShipping()) {
|
||||||
throw new BizException('订单状态异常,请刷新后再试');
|
throw new BizException('无法收货:订单状态异常,请刷新后再试');
|
||||||
}
|
}
|
||||||
//增加自己的库存
|
//增加自己的库存
|
||||||
$this->orderInQty($order);
|
$this->orderInQty($order);
|
||||||
|
|
@ -313,16 +317,18 @@ class OrderService
|
||||||
'status' => DealerOrderStatus::Completed,
|
'status' => DealerOrderStatus::Completed,
|
||||||
'shippinged_time' => now(),
|
'shippinged_time' => now(),
|
||||||
]);
|
]);
|
||||||
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function cancelOrder(DealerOrder $order)
|
public function cancelOrder(DealerOrder $order)
|
||||||
{
|
{
|
||||||
if (!($order->isPending() || $order->isPendinged() || $order->isPay())) {
|
if (!($order->isPending() || $order->isPendinged() || $order->isPay())) {
|
||||||
throw new BizException('订单状态异常,请刷新后再试');
|
throw new BizException('无法取消:订单状态异常,请刷新后再试');
|
||||||
}
|
}
|
||||||
$order->update([
|
$order->update([
|
||||||
'status' => DealerOrderStatus::Cancelled,
|
'status' => DealerOrderStatus::Cancelled,
|
||||||
]);
|
]);
|
||||||
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -334,7 +340,7 @@ class OrderService
|
||||||
{
|
{
|
||||||
//只处理当前订单有发货人的情况
|
//只处理当前订单有发货人的情况
|
||||||
if ($order->consignor) {
|
if ($order->consignor) {
|
||||||
$consignor = $this->getConsignor($order->user, $order->totalAmount, $order->consignor);
|
$consignor = $this->getConsignor($order->user, $order->total_amount, $order->consignor);
|
||||||
$oldConsignor = $order->consignor;
|
$oldConsignor = $order->consignor;
|
||||||
$order->update([
|
$order->update([
|
||||||
'allocated_at' => now(),
|
'allocated_at' => now(),
|
||||||
|
|
@ -347,6 +353,7 @@ class OrderService
|
||||||
'new_consignor_id' =>$order->consignor_id,
|
'new_consignor_id' =>$order->consignor_id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
return $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue