You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
425 lines
20 KiB
425 lines
20 KiB
<?php
|
|
|
|
namespace App\Service\v3\Implementations;
|
|
|
|
use App\Commons\Log;
|
|
use App\Constants\v3\LogLabel;
|
|
use App\Constants\v3\OrderState;
|
|
use App\Constants\v3\OrderType;
|
|
use App\Model\v3\FinancialRecord;
|
|
use App\Model\v3\Market;
|
|
use App\Model\v3\MmInfo;
|
|
use App\Model\v3\MpInfo;
|
|
use App\Model\v3\Order;
|
|
use App\Model\v3\OrderMain;
|
|
use App\Model\v3\ServiceReward;
|
|
use App\Model\v3\Store;
|
|
use App\Model\v3\UserRelationBind;
|
|
use App\Model\v3\User;
|
|
use App\Service\v3\Interfaces\FinancialRecordServiceInterface;
|
|
use App\Service\v3\Interfaces\MiniprogramServiceInterface;
|
|
use App\Service\v3\Interfaces\OrderOnlineServiceInterface;
|
|
use App\Service\v3\Interfaces\SeparateAccountsServiceInterface;
|
|
use App\Service\v3\Interfaces\SmsSendServiceInterface;
|
|
use App\Service\v3\Interfaces\UserServiceInterface;
|
|
use App\TaskWorker\SSDBTask;
|
|
use Hyperf\DbConnection\Db;
|
|
use Hyperf\Di\Annotation\Inject;
|
|
use Hyperf\Utils\ApplicationContext;
|
|
|
|
class SeparateAccountsService implements SeparateAccountsServiceInterface
|
|
{
|
|
/**
|
|
* @Inject
|
|
* @var Log
|
|
*/
|
|
protected $log;
|
|
|
|
/**
|
|
* @Inject
|
|
* @var UserServiceInterface
|
|
*/
|
|
protected $userService;
|
|
|
|
/**
|
|
* @Inject
|
|
* @var FinancialRecordServiceInterface
|
|
*/
|
|
protected $financialRecordService;
|
|
|
|
/**
|
|
* @Inject
|
|
* @var MiniprogramServiceInterface
|
|
*/
|
|
protected $miniprogramService;
|
|
|
|
/**
|
|
* @Inject
|
|
* @var OrderOnlineServiceInterface
|
|
*/
|
|
protected $orderOnlineService;
|
|
|
|
/**
|
|
* @Inject
|
|
* @var SmsSendServiceInterface
|
|
*/
|
|
protected $smsAliSendService;
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function orderOnlinePaid($globalOrderId)
|
|
{
|
|
try {
|
|
// 线上订单支付完成
|
|
// 订单
|
|
$orderMain = OrderMain::query()->where(['global_order_id' => $globalOrderId])->first();
|
|
|
|
if (empty($orderMain)) {
|
|
return false;
|
|
}
|
|
|
|
// =======用户支付流水 / Start=======
|
|
$this->financialRecordService->userByOLOrderPaid($orderMain->user_id, $orderMain->global_order_id, $orderMain->money);
|
|
// =======用户支付流水 / End=======
|
|
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
$this->log->event(LogLabel::SEPARATE_ACCOUNTS_LOG, ['exception' => $e->getMessage()]);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function orderOnlineCompleted($globalOrderId, $userId)
|
|
{
|
|
// 线上订单完成(用户点击确认收货完成/管理后台点击完成/配送员点击完成/自动收货等),进行相关分账
|
|
// 订单
|
|
$orderMain = $this->orderOnlineService->check($globalOrderId, $userId,OrderState::FINISH);
|
|
|
|
$currentTime = time();
|
|
Db::beginTransaction();
|
|
try {
|
|
|
|
$ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
|
|
|
|
// =======商户订单收入流水 / Start=======
|
|
// 查询子订单
|
|
$orders = Order::query()
|
|
->where(['order_main_id' => $orderMain->global_order_id])
|
|
->get()->toArray();
|
|
|
|
// 新商户流水
|
|
foreach ($orders as $key => &$order) {
|
|
$store = Store::query()->find($order['store_id']);
|
|
$this->financialRecordService->storeByOLOrderComp($store->user_id, $orderMain->global_order_id ,$order['money']);
|
|
}
|
|
// =======商户订单收入流水 / End=======
|
|
|
|
// =======社区服务点分账 / Start=======
|
|
// 前提:用户线上下单并且订单完成
|
|
// 奖励规则A:用户是平台新用户,奖励社区服务点平台新用户奖励x元+平台新用户首单奖励y元+订单商品金额z%的分成
|
|
// 奖励规则B:用户是非新用户,奖励社区服务点订单实际支付金额z%的分成
|
|
// =======社区服务点分账 / Start=======
|
|
|
|
// 当前用户的社区服务点绑定关系
|
|
$communityBind = UserRelationBind::query()
|
|
->where(['bind_type' => UserRelationBind::BIND_TYPE_COMMUNITY, 'user_id' => $orderMain->user_id])
|
|
->first();
|
|
|
|
if ($communityBind) {
|
|
// 奖励/分账金额
|
|
$award = ServiceReward::query()->where(['type' => ServiceReward::TYPE_COMMUNITY])->first();
|
|
if (empty($award)) {
|
|
Db::rollBack();
|
|
return false;
|
|
}
|
|
$award = $award->set_reward;
|
|
// 平台新用户
|
|
if ($this->userService->isPlatformNewUser($orderMain->user_id, $orderMain->global_order_id)) {
|
|
$this->financialRecordService->communityAwardByPlatNewUser(
|
|
$communityBind->source_id,
|
|
$orderMain->global_order_id,
|
|
$award['new_user_reward']
|
|
);
|
|
// 发送短信
|
|
co(function () use ($orderMain, $award) {
|
|
$this->smsAliSendService->doCommunityFinancial($orderMain->user_id, $award['new_user_reward']);
|
|
});
|
|
$this->financialRecordService->communityAwardByPlatNewUserFirstOLOrder(
|
|
$communityBind->source_id,
|
|
$orderMain->global_order_id,
|
|
$award['first_reward']
|
|
);
|
|
// 发送短信
|
|
co(function () use ($orderMain, $award) {
|
|
$this->smsAliSendService->doCommunityFinancial($orderMain->user_id, $award['first_reward']);
|
|
});
|
|
}
|
|
// 账单分成
|
|
$money = bcmul($orderMain->money, bcdiv($award['flow_reward'], 100, 6), 2);
|
|
$this->financialRecordService->communitySeparateAccountsByOrderComp($communityBind->source_id, $orderMain->global_order_id, $money);
|
|
// 发送短信
|
|
co(function () use ($orderMain, $money) {
|
|
$this->smsAliSendService->doCommunityFinancial($orderMain->user_id, $money);
|
|
});
|
|
}
|
|
|
|
// =======社区服务点分账 / End=======
|
|
|
|
// =======服务商、市场经理奖励分账 / Start=======
|
|
// 前提A:新用户下单并且订单完成(线上、线下都行)
|
|
// 奖励规则A:用户是平台新用户,奖励市场经理 1 元,服务商 0.5 元,如果是线上订单,服务商有6%的订单分成
|
|
// 前提B:新商户旗下产生 10 个新用户
|
|
// 奖励规则B:奖励市场经理 25 元,服务商 10 元(仅仅奖励一次)
|
|
// 前提C:用户线上下单并且订单完成
|
|
// 奖励规则C:奖励服务商账单 6% 分成
|
|
// 判断是新商户:入驻绑定的时候把关系存在SSDB
|
|
// =======服务商、市场经理奖励分账 / Start=======
|
|
|
|
$MmMpAwardConfig = [
|
|
'mm_new_user' => 1,
|
|
'mm_new_store' => 25,
|
|
'mp_new_user' => 0.5,
|
|
'mp_new_store' => 10,
|
|
'separate_rate' => 6,
|
|
'limit_new_user_number' => 10,
|
|
];
|
|
foreach ($orders as $key => &$order) {
|
|
|
|
// 当前订单(子)对应商户是否有市场经理绑定关系
|
|
$store = Store::query()->find($order['store_id']); // 商户
|
|
// $mmInfo = MmInfo::query()->where(['user_id' => $store->mm_user_id])->first(); // 市场经理
|
|
// if (empty($mmInfo)) continue;
|
|
// $market = Market::query()->find($mmInfo->market_id); // 市场
|
|
$market = Market::query()->find($orderMain->market_id); // 市场
|
|
if (empty($market)) continue;
|
|
$mpInfo = MpInfo::query()->find($market->mp_id); // 服务商
|
|
if (empty($mpInfo)) continue;
|
|
|
|
// $ssdbName = 'mm_'.$mmInfo->id.'_award_'.$store->id;
|
|
$ssdbName = 'mm_'.$mpInfo->id.'_award_'.$store->id;
|
|
|
|
// TODO 暂时在这里初始化
|
|
if (!$ssdb->exec('hexists', $ssdbName, 'is_awarded')) {
|
|
$ssdb->exec('hset', $ssdbName, 'is_awarded', 0);
|
|
}
|
|
|
|
if (!$ssdb->exec('hexists', $ssdbName, 'new_user_number')) {
|
|
$ssdb->exec('hset', $ssdbName, 'new_user_number', 0);
|
|
}
|
|
|
|
// 平台新用户
|
|
if ($this->userService->isPlatformNewUser($orderMain->user_id, $orderMain->id)) {
|
|
$ssdb->exec('hincr', $ssdbName, 'new_user_number', 1);
|
|
// $this->financialRecordService->mmAwardByPlatNewUser($mmInfo->admin_user_id, $globalOrderId, $MmMpAwardConfig['mm_new_user'], '发展新用户'); // 市场经理新用户奖励
|
|
// $this->financialRecordService->mpAwardByPlatNewUser($mpInfo->admin_user_id, $globalOrderId, $MmMpAwardConfig['mp_new_user'], '市场经理「'.$mmInfo->name.'」发展新用户'); // 服务商新用户奖励
|
|
$this->financialRecordService->mpAwardByPlatNewUser($mpInfo->admin_user_id, $globalOrderId, $MmMpAwardConfig['mp_new_user'], '发展新用户'); // 服务商新用户奖励
|
|
}
|
|
|
|
$record = $ssdb->exec('hgetall', $ssdbName);
|
|
|
|
// 判断是否已经奖励过新拓展商户的奖励,没有的话判断新用户个数是否达到要求,进行奖励
|
|
if (
|
|
!empty($record)
|
|
&&$record['is_awarded']==0
|
|
&&$record['new_user_number']>=$MmMpAwardConfig['limit_new_user_number']
|
|
) { // 存在记录且未发放奖励,同时新用户数已经超过10
|
|
$ssdb->exec('hset', $ssdbName, 'is_awarded', 1);
|
|
// $this->financialRecordService->mmAwardByNewStore($mmInfo->admin_user_id, $globalOrderId, $MmMpAwardConfig['mm_new_store'], '发展新商户【'.$store->name.'】'); // 市场经理新商户奖励
|
|
// $this->financialRecordService->mpAwardByNewStore($mpInfo->admin_user_id, $globalOrderId, $MmMpAwardConfig['mp_new_store'], '市场经理「'.$mmInfo->name.'」发展新商户【'.$store->name.'】'); // 服务商新商户奖励
|
|
$this->financialRecordService->mpAwardByNewStore($mpInfo->admin_user_id, $globalOrderId, $MmMpAwardConfig['mp_new_store'], '发展新商户【'.$store->name.'】'); // 服务商新商户奖励
|
|
}
|
|
|
|
// 线上订单服务商分账
|
|
if ($orderMain->type == OrderType::ONLINE) {
|
|
$rate = bcdiv($order['money'], $orderMain->total_money, 6);
|
|
$preMoney = bcmul($orderMain->money, $rate, 6);
|
|
$money = bcmul($preMoney, bcdiv($MmMpAwardConfig['separate_rate'], 100, 6), 2);
|
|
$this->financialRecordService->mpSeparateAccountByOLOrderComp($mpInfo->admin_user_id, $globalOrderId, $money);
|
|
}
|
|
}
|
|
|
|
// =======服务商、市场经理奖励分账 / End=======
|
|
|
|
Db::commit();
|
|
return true;
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
$this->log->event(LogLabel::SEPARATE_ACCOUNTS_LOG, ['exception' => $e->getMessage(), 'order_main' => json_encode($orderMain)]);
|
|
Db::rollBack();
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
public function orderOfflinePaid($globalOrderId)
|
|
{
|
|
// 线下订单支付完成
|
|
// 订单
|
|
$orderMain = OrderMain::query()->where(['global_order_id' => $globalOrderId])->first();
|
|
|
|
if (empty($orderMain)) {
|
|
return false;
|
|
}
|
|
|
|
// 查询子订单,当面付目前实际上只有一个子订单
|
|
$order = Order::query()
|
|
->where(['order_main_id' => $orderMain->global_order_id])
|
|
->first();
|
|
|
|
if (empty($order)) {
|
|
return false;
|
|
}
|
|
|
|
$currentTime = time();
|
|
Db::beginTransaction();
|
|
try {
|
|
|
|
// =======用户支付流水 / Start=======
|
|
$this->financialRecordService->userByOFLOrderPaid($orderMain->user_id, $orderMain->global_order_id, $orderMain->money);
|
|
// =======用户支付流水 / End=======
|
|
|
|
// =======线下订单支付完成商户分账 / Start=======
|
|
// 前提:用户线上下单并且支付完成
|
|
// 奖励规则A:用户是平台新用户,奖励商户2元
|
|
// 奖励规则B:用户是非新用户,但是是商户当日首单,奖励商户0.05元
|
|
// =======线下订单支付完成商户分账 / Start=======
|
|
|
|
$message = [];
|
|
|
|
// 商户
|
|
$store = Store::find($order->store_id);
|
|
|
|
// 新商户订单流水
|
|
$this->financialRecordService->storeByOFLOrderComp($store->user_id, $orderMain->global_order_id, $order->money);
|
|
|
|
$needAward = false;
|
|
$awardAmount = 0;
|
|
// 新用户商户奖励
|
|
if ($this->userService->isPlatformNewUser($orderMain->user_id, $orderMain->global_order_id)) {
|
|
|
|
$awardAmount = 2;
|
|
// 旧商户流水 TODO 直接移除或后续考虑移除
|
|
$message = [
|
|
'money' => $awardAmount,
|
|
'note' => '新用户下单成功,平台奖励',
|
|
];
|
|
// 新商户流水
|
|
$this->financialRecordService->storeAwardByPlatNewUserOFLOrder($store->user_id, $orderMain->global_order_id, $awardAmount);
|
|
$needAward = true;
|
|
|
|
} else {
|
|
// 商户当日首单奖励
|
|
if (
|
|
$this->userService->isStoreFirstOrderToday(
|
|
$order->user_id,
|
|
$order->store_id,
|
|
$order->id,
|
|
FinancialRecord::OFL_FIRST_AWARD_LIMIT_AMOUNT
|
|
)
|
|
&& $order->money >= FinancialRecord::OFL_FIRST_AWARD_LIMIT_AMOUNT
|
|
) {
|
|
|
|
$awardAmount = 0.05;
|
|
// 旧商户流水 TODO 直接移除或后续考虑移除
|
|
$message = [
|
|
'money' => $awardAmount,
|
|
'note' => '用户下单成功,平台奖励',
|
|
];
|
|
// 新商户流水
|
|
$this->financialRecordService->storeAwardByTodayFirstOFLOrder($store->user_id, $orderMain->global_order_id, $awardAmount);
|
|
$needAward = true;
|
|
|
|
}
|
|
}
|
|
|
|
if ($needAward && $awardAmount) {
|
|
// 发模板消息
|
|
$openid = User::query()->where(['id' => $store['user_id']])->value('openid');
|
|
$res = $this->miniprogramService->sendTemMsgForAward($message['money'], $message['note'], $openid, date('Y-m-d H:i:s', $currentTime));
|
|
}
|
|
|
|
// =======线下订单支付完成商户分账 / End=======
|
|
|
|
// =======线下订单支付完成商户分账 / End=======
|
|
|
|
// =======服务商、市场经理奖励分账 / Start=======
|
|
// 前提A:新用户下单并且订单完成(线上、线下都行)
|
|
// 奖励规则A:用户是平台新用户,奖励市场经理 1 元,服务商 0.5 元,如果是线上订单,服务商有6%的订单分成
|
|
// 前提B:新商户旗下产生 10 个新用户
|
|
// 奖励规则B:奖励市场经理 25 元,服务商 10 元(仅仅奖励一次)
|
|
// 前提C:用户线上下单并且订单完成
|
|
// 奖励规则C:奖励服务商账单 6% 分成
|
|
// 判断是新商户:入驻绑定的时候把关系存在SSDB
|
|
// =======服务商、市场经理奖励分账 / Start=======
|
|
|
|
$MmMpAwardConfig = [
|
|
'mm_new_user' => 1,
|
|
'mm_new_store' => 25,
|
|
'mp_new_user' => 0.5,
|
|
'mp_new_store' => 10,
|
|
'separate_rate' => 6,
|
|
'limit_new_user_number' => 10,
|
|
];
|
|
|
|
// 当前订单(子)对应商户是否有市场经理绑定关系
|
|
$store = Store::query()->find($order['store_id']); // 商户
|
|
// $mmInfo = MmInfo::query()->where(['user_id' => $store->mm_user_id])->first(); // 市场经理
|
|
$market = Market::query()->find($orderMain->market_id); // 市场
|
|
$mpInfo = MpInfo::query()->find($market->mp_id); // 服务商
|
|
|
|
if (!empty($mpInfo)) {
|
|
$ssdb = ApplicationContext::getContainer()->get(SSDBTask::class);
|
|
// $ssdbName = 'mm_'.$mmInfo->id.'_award_'.$store->id;
|
|
$ssdbName = 'mm_'.$mpInfo->id.'_award_'.$store->id;
|
|
|
|
// TODO 暂时在这里初始化
|
|
if (!$ssdb->exec('hexists', $ssdbName, 'is_awarded')) {
|
|
$ssdb->exec('hset', $ssdbName, 'is_awarded', 0);
|
|
}
|
|
|
|
if (!$ssdb->exec('hexists', $ssdbName, 'new_user_number')) {
|
|
$ssdb->exec('hset', $ssdbName, 'new_user_number', 0);
|
|
}
|
|
|
|
// 平台新用户
|
|
if ($this->userService->isPlatformNewUser($orderMain->user_id, $orderMain->id)) {
|
|
$ssdb->exec('hincr', $ssdbName, 'new_user_number', 1);
|
|
// $this->financialRecordService->mmAwardByPlatNewUser($mmInfo->admin_user_id, $global_order_id, $MmMpAwardConfig['mm_new_user'], '发展新用户'); // 市场经理新用户奖励
|
|
// $this->financialRecordService->mpAwardByPlatNewUser($mpInfo->admin_user_id, $global_order_id, $MmMpAwardConfig['mp_new_user'], '市场经理「'.$mmInfo->name.'」发展新用户'); // 服务商新用户奖励
|
|
$this->financialRecordService->mpAwardByPlatNewUser($mpInfo->admin_user_id, $globalOrderId, $MmMpAwardConfig['mp_new_user'], '发展新用户'); // 服务商新用户奖励
|
|
}
|
|
|
|
$record = $ssdb->exec('hgetall', $ssdbName);
|
|
// 判断是否已经奖励过新拓展商户的奖励,没有的话判断新用户个数是否达到要求,进行奖励
|
|
if (
|
|
!empty($record)
|
|
&&$record['is_awarded']==0
|
|
&&$record['new_user_number']>=$MmMpAwardConfig['limit_new_user_number']
|
|
) { // 存在记录且未发放奖励,同时新用户数已经超过10
|
|
$ssdb->exec('hset', $ssdbName, 'is_awarded', 1);
|
|
// $this->financialRecordService->mmAwardByNewStore($mmInfo->admin_user_id, $global_order_id, $MmMpAwardConfig['mm_new_store'], '发展新商户【'.$store->name.'】'); // 市场经理新商户奖励
|
|
// $this->financialRecordService->mpAwardByNewStore($mpInfo->admin_user_id, $global_order_id, $MmMpAwardConfig['mp_new_store'], '市场经理「'.$mmInfo->name.'」发展新新商户【'.$store->name.'】'); // 服务商新商户奖励
|
|
$this->financialRecordService->mpAwardByNewStore($mpInfo->admin_user_id, $globalOrderId, $MmMpAwardConfig['mp_new_store'], '发展新商户【'.$store->name.'】'); // 服务商新商户奖励
|
|
}
|
|
}
|
|
|
|
// =======服务商、市场经理奖励分账 / End=======
|
|
|
|
Db::commit();
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
|
|
$this->log->event(LogLabel::SEPARATE_ACCOUNTS_LOG, ['exception' => $e->getMessage(), 'order_main' => json_encode($orderMain)]);
|
|
Db::rollBack();
|
|
return false;
|
|
}
|
|
}
|
|
}
|