| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094 |
- <?php
- namespace addons\Agent\backend\services;
- use addons\Agent\common\enums\AgentEnum;
- use addons\Agent\common\enums\ComputingEnum;
- use addons\Agent\common\logic\reward\AgentReward;
- use addons\Agent\common\models\Agent;
- use addons\Agent\common\models\AgentCommissionDetails;
- use addons\Agent\common\models\AgentCommissionItemSetting;
- use addons\Agent\common\models\AgentDelayLog;
- use addons\Agent\common\models\AgentGoodsRepurchase;
- use addons\Agent\common\models\AgentLevel;
- use addons\Agent\common\models\AgentSupplierCommission;
- use addons\Agent\common\models\AgentSupplierCommissionSyncLog;
- use addons\Agent\common\models\AgentSupplierOrder;
- use addons\Course\common\models\AddonsCourseOrders;
- use addons\PointUpperLimit\common\service\SettingService;
- use addons\Store\common\models\StoreCashierOrder;
- use addons\Store\common\models\StoreOrder;
- use addons\Store\common\models\StoreOrderDetail;
- use common\components\export\CsvTool;
- use common\enums\AddonsEnum;
- use common\enums\DownloadEnum;
- use common\enums\OrderStatusEnum;
- use common\enums\RabbitMqEnum;
- use common\enums\RefundStatusEnum;
- use common\enums\RefundTypeEnum;
- use common\enums\StatusEnum;
- use common\helpers\FormatHelper;
- use common\models\common\CapitalLog;
- use common\models\common\Download;
- use common\models\mall\MallAddons;
- use common\models\order\Order;
- use common\models\order\OrderDetail;
- use common\models\order\OrderRefund;
- use common\models\user\DigitalLog;
- use common\models\user\User;
- use common\models\user\UserPartitionRelationship;
- use Exception;
- use RuntimeException;
- use services\common\UserWalletService;
- use Yii;
- class AgentSupplierCommissionService extends BaseService
- {
- /**
- * 供应商收入列表
- *
- * @param array $params
- * @param bool $getAll
- *
- * @return void
- */
- public function getList(array $params, bool $getAll = false)
- {
- $order_no = $params['order_no'] ?? '';
- $buy_keyword = $params['buy_keyword'] ?? '';
- $seller_keyword = $params['seller_keyword'] ?? '';
- $where = [['=', 'mall_id', $this->mall_id], ['status' => StatusEnum::ENABLED]];
- if ($order_no) {
- $where[] = ['like', 'order_no', $order_no];
- }
- if (is_numeric($buy_keyword)) {
- $userIds = User::find()
- ->where(['mall_id' => $this->mall_id])
- ->andWhere(['like', 'mobile', $buy_keyword])
- ->select('id')
- ->column();
- $where[] = ['or', ['=', 'buy_user_id', $buy_keyword], ['in', 'buy_user_id', $userIds]];
- }
- if (is_numeric($seller_keyword)) {
- $userIds = User::find()
- ->where(['mall_id' => $this->mall_id])
- ->andWhere(['like', 'mobile', $seller_keyword])
- ->select('id')
- ->column();
- $where[] = ['or', ['=', 'seller_user_id', $seller_keyword], ['in', 'seller_user_id', $userIds]];
- }
- $getListParams = [
- 'with' => [
- 'order' => function ($query) {
- $query->select('order_no, order_status');
- },
- 'buyUser' => function ($query) {
- $query->select('id, mobile, nickname, avatar_url');
- },
- 'sellerUser' => function ($query) {
- $query->select('id, mobile, nickname, avatar_url');
- },
- ],
- 'where' => $where,
- 'order' => 'pay_time desc, order_no desc, id desc'
- ];
- $levelMap = AgentLevel::getLevelByColumn($this->mall_id);
- if ($getAll) {
- $list = AgentSupplierCommission::lists($getListParams);
- $this->formatList($list, $levelMap);
- } else {
- $list = AgentSupplierCommission::listPage($getListParams);
- $this->formatList($list['list'], $levelMap);
- }
- return $list;
- }
- /**
- * 字段修改
- *
- * @param array $list
- * @param array $levelMap
- *
- * @return void
- */
- protected function formatList(array &$list, array $levelMap)
- {
- array_walk($list, function (&$item) use ($levelMap) {
- $item['order']['order_status_text'] = OrderStatusEnum::getMap()[$item['order']['order_status']] ?? '-';
- $item['pay_time_text'] = date('Y-m-d H:i:s', $item['pay_time']);
- $item['buy_level_text'] = $levelMap[$item['buy_level']] ?? '-';
- $item['seller_level_text'] = $levelMap[$item['seller_level']] ?? '-';
- $item['capital_type_text'] = ComputingEnum::getTypeMap()[$item['capital_type']] ?? '-';
- });
- }
- public function export(array $data): bool
- {
- $download_id = $data['download_id'] ?? 0;
- $download = Download::findOne(['id' => $download_id]);
- if (!$download) {
- return false;
- }
- $this->mall_id = $download->mall_id;
- try {
- $params = json_decode($download->params, true);
- $filename = $download->name;
- $type = $download->type;
- $list = $this->getList($params, true);
- $exportList = [];
- foreach ($list as $item) {
- $exportList[] = [
- 'buy_user' => $item['buyUser']['mobile'] ?? '-',
- 'buy_level_text' => $item['buy_level_text'],
- 'seller_user' => $item['sellerUser']['mobile'] ?? '-',
- 'seller_level_text' => $item['seller_level_text'],
- 'profit' => $item['profit'],
- 'order_no' => $item['order_no'],
- 'payment_amount' => $item['payment_amount'],
- 'order_status_text' => $item['order']['order_status_text'],
- 'pay_time_text' => $item['pay_time_text'],
- 'capital_type_text' => $item['capital_type_text'],
- ];
- }
- unset($list);
- if (!empty($exportList)) {
- $csv = new CsvTool();
- $csv->filename = $filename;
- $csv->file_dirname = DownloadEnum::getTypeStorageDirMap($type);
- $csv->export_mode = CsvTool::EXPORT_MODE_ASYNC;
- $csv->header = ['买家', '身份', '卖家', '身份', '利润', '订单号', '货款金额', '订单状态', '收入时间', '奖项'];
- $csv->data = $exportList;
- $csv->export();
- $csv->updateDown($download, $params['mall_id']);
- }
- } catch (Exception $e) {
- $download->status = 3;
- $download->save();
- $this->setError($e->getMessage());
- return false;
- }
- return true;
- }
- /**
- * 返回是否允许投递任务
- *
- * @return bool
- */
- public function allowDeliveryTask()
- {
- $status = AgentSupplierCommissionSyncLog::find()
- ->where(['mall_id' => $this->mall_id])
- ->select('status')
- ->scalar();
- // 未处理 或者 处理成功不允许投递
- return !(is_numeric($status) && in_array($status, [StatusEnum::DISABLED, StatusEnum::ENABLED]));
- }
- /**
- * 同步旧数据
- *
- * @return void
- */
- public function syncOldData($data)
- {
- if (empty($data['mall_id'])) {
- Yii::$app->custom->logs('同步供应商收入数据:data为空', $data);
- return;
- }
- $this->mall_id = $data['mall_id'];
- $pendingData = AgentSupplierCommissionSyncLog::find()
- ->where(['mall_id' => $this->mall_id, 'status' => StatusEnum::DISABLED])
- ->one();
- if (!$pendingData) {
- Yii::$app->custom->logs('同步供应商收入数据:不存在待处理的数据', $data);
- return;
- }
- try {
- $this->insertCommission('commission', ['mall_id' => $this->mall_id, 'from_type' => 'Agent'], $this->mall_id);
- $this->insertCommission('commission_frozen', ['mall_id' => $this->mall_id, 'from_type' => 'Agent', 'status' => StatusEnum::DISABLED], $this->mall_id);
- $pendingData->status = StatusEnum::ENABLED;
- } catch (\Exception $e) {
- $pendingData->status = StatusEnum::DELETE;
- Yii::$app->custom->logs(FormatHelper::exception($e, '同步供应商收入数据:处理失败'), $data);
- }
- $pendingData->save();
- }
- /**
- * 查询并写入
- *
- * @param string $wallet_type
- * @param array $where
- * @param int $mallId
- *
- * @return void
- */
- protected function insertCommission(string $wallet_type, array $where, int $mallId)
- {
- CapitalLog::$capitalType = $wallet_type;
- foreach (CapitalLog::find()->where($where)->batch(500) as $batch) {
- $batchInsertData = [];
- foreach ($batch as $commissionItem) {
- [
- $payment_amount,
- $goods_nums,
- $buy_user_id,
- $buy_user_level,
- $seller_level,
- $order_no,
- $pay_time
- ] = self::formatData($commissionItem);
- $batchInsertData[] = [
- 'mall_id' => $mallId,
- 'buy_user_id' => $buy_user_id,
- 'buy_level' => $buy_user_level,
- 'seller_user_id' => $commissionItem['user_id'],
- 'seller_level' => $seller_level,
- 'order_no' => $order_no,
- 'supplier_order_no' => Order::generateOrderNo('G'),
- 'goods_nums' => $goods_nums,
- 'stock_nums' => $goods_nums,
- 'payment_amount' => $payment_amount,
- 'profit' => $commissionItem['change_num'],
- 'pay_time' => !is_numeric($pay_time) ? 0 : $pay_time,
- 'capital_type' => $commissionItem['capital_type'],
- 'source_table' => $commissionItem['source_table'],
- 'source_table_id' => $commissionItem['source_table_id'],
- ];
- }
- AgentSupplierCommission::insertData($batchInsertData);
- }
- }
- /**
- * 格式化数据
- * @Author:hua
- * @Date:2024-02-23 15:07
- * @Copyright:copyright(c)2024 广东七件事集团
- * @param $item
- * @return array
- */
- public static function formatData($item)
- {
- $payment_amount = 0;
- $goods_nums = 0;
- $buy_user_id = 0;
- $buy_user_level = 0;
- $seller_level = 0;
- $order_no = '';
- $pay_time = '';
- switch ($item['source_table']) {
- case 'order_detail':
- $order_detail = OrderDetail::findOne(['id' => $item['source_table_id']]);
- if ($order_detail) {
- $order = Order::findOne(['id' => $order_detail['order_id']]);
- if ($order) {
- $order_no = $order['order_no'];
- $pay_time = $order['pay_time'];
- $buy_user_id = $order['user_id'];
- }
- $goods_nums = $order_detail['num'];
- $payment_amount = $order_detail['goods_price'];
- }
- break;
- case 'store_cashier_order':
- $store_cashier_order = StoreCashierOrder::findOne(['id' => $item['source_table_id']]);
- if ($store_cashier_order) {
- $order_no = $store_cashier_order['order_no'];
- $pay_time = $store_cashier_order['pay_time'];
- $buy_user_id = $store_cashier_order['user_id'];
- $payment_amount = $store_cashier_order['pay_money'];
- }
- $goods_nums = 1;
- break;
- case 'store_order_detail':
- $store_order_detail = StoreOrderDetail::findOne(['id' => $item['source_table_id']]);
- if ($store_order_detail) {
- $store_order = StoreOrder::findOne(['id' => $store_order_detail['order_id']]);
- if ($store_order) {
- $order_no = $store_order['order_no'];
- $pay_time = $store_order['pay_time'];
- $buy_user_id = $store_order['user_id'];
- }
- $payment_amount = $store_order_detail['goods_price'];
- }
- $goods_nums = $store_order_detail['num'];
- break;
- case '{{%addons_agent_team_achievement}}':
- break;
- case '{{%addons_course_orders}}':
- $course_order = AddonsCourseOrders::findOne(['id' => $item['source_table_id']]);
- if ($course_order) {
- $order_no = $course_order['order_no'];
- $pay_time = $course_order['pay_time'];
- $buy_user_id = $course_order['user_id'];
- $goods_nums = 1;
- $payment_amount = $course_order['pay_money'];
- }
- break;
- case '{{%order}}':
- $order = Order::findOne(['id' => $item['source_table_id']]);
- if ($order) {
- $num = OrderDetail::find()->where(['order_id' => $order['id']])->sum('num');
- $goods_price = OrderDetail::find()->where(['order_id' => $order['id']])->sum('goods_price');
- if (!empty($num)) $goods_nums = $num;
- if (!empty($goods_price)) $payment_amount = $goods_price;
- $order_no = $order['order_no'];
- $pay_time = $order['pay_time'];
- $buy_user_id = $order['user_id'];
- }
- break;
- }
- // 从供应商订单找之前的等级
- if (!empty($order_no)) {
- $levelArr = AgentSupplierOrder::find()
- ->where(['order_no' => $order_no])
- ->asArray()
- ->all();
- $buyUserLevelArr = array_column($levelArr, 'buy_level', 'buy_user_id');
- $sellerUserLevelArr = array_column($levelArr, 'seller_level', 'seller_user_id');
- }
- $agent_arr = Agent::find()->where(['mall_id' => $item['mall_id'], 'user_id' => [$buy_user_id, $item['user_id']], 'status' => StatusEnum::ENABLED])
- ->indexBy('user_id')->all();
- if (isset($buyUserLevelArr[$buy_user_id])) {
- $buy_user_level = $buyUserLevelArr[$buy_user_id];
- }else if (isset($agent_arr[$buy_user_id])) {
- $buy_user_level = $agent_arr[$buy_user_id]['level'];
- }
- if (isset($sellerUserLevelArr[$item['user_id']])) {
- $seller_level = $sellerUserLevelArr[$item['user_id']];
- }else if (isset($agent_arr[$item['user_id']])) {
- $seller_level = $agent_arr[$item['user_id']]['level'];
- }
- return [$payment_amount, $goods_nums, $buy_user_id, $buy_user_level, $seller_level, $order_no, $pay_time];
- }
- /**
- * 重新分配佣金(数字币只验证是否已结算,不处理其他情况)
- *
- * @param array $post
- *
- * @return bool
- */
- public function redistributeCommissions(array $post): bool
- {
- $orderDetailsIds = $post['order_details_ids'];
- $mallId = $this->mall_id;
- try {
- $this->redistributeCommissionsValidate($orderDetailsIds, $mallId);
- // 验证通过则丢队列处理
- Yii::$app->services->rabbitMq->push(
- RabbitMqEnum::EXCHANGE_ORDER,
- RabbitMqEnum::ORDER_QUEUE,
- ['mall_id' => $this->mall_id, 'order_details_ids' => $orderDetailsIds],
- self::class,
- 'asyncRedistributeCommissions'
- );
-
- return true;
- }catch (Exception $e) {
- $this->error = $e->getMessage();
- return false;
- }
- }
- /**
- * 执行重新分配前数据验证
- *
- * @param array $orderDetailsIds
- * @param int $mallId
- *
- * @return array
- */
- protected function redistributeCommissionsValidate(array &$orderDetailsIds, int $mallId): array
- {
- $orderDetailList = OrderDetail::find()
- ->where([
- 'status' => StatusEnum::ENABLED,
- 'id' => $orderDetailsIds,
- 'mall_id' => $mallId
- ])
- ->andWhere(['not in', 'order_status', [OrderStatusEnum::REPEAL,OrderStatusEnum::ACCOMPLISH]])//已完成的订单无法重新分配
- ->select('id, order_id, is_feedback')
- ->asArray()
- ->all();
- if (empty($orderDetailList)) {
- throw new RuntimeException('订单明细不存在或已退款、已完成');
- }
- $orderIds = array_column($orderDetailList, 'order_id');
- // 验证 details_id正确 并且是 同一个订单
- if (count(array_unique($orderIds)) > 1) {
- throw new RuntimeException('订单参数错误,存在多张订单');
- }
- $orderDetailsIds = array_column($orderDetailList, 'id');
- // 排除售后完成并且不是换货的order details id
- $refundOrderDetailIds = OrderRefund::find()
- ->where([
- 'order_detail_id' => $orderDetailsIds,
- 'status' => StatusEnum::ENABLED,
- 'refund_status' => RefundStatusEnum::FINISH,
- 'type' => [RefundTypeEnum::MONEY, RefundTypeEnum::MONEY_AND_PRODUCT]
- ])
- ->select('order_detail_id')
- ->column();
- $orderDetailsIds = array_diff($orderDetailsIds, $refundOrderDetailIds);
- if (empty($orderDetailsIds)) {
- throw new RuntimeException('订单已退款');
- }
- $order = Order::find()
- ->where([
- 'id' => reset($orderIds),
- 'mall_id' => $this->mall_id,
- 'status' => StatusEnum::ENABLED,
- 'pay_status' => OrderStatusEnum::PAY,
- ])
- ->andWhere(['not in', 'order_status', [OrderStatusEnum::REPEAL,OrderStatusEnum::ACCOMPLISH]])
- ->one();
- if (empty($order)) {
- throw new RuntimeException('订单不存在或已退款、已完成');
- }
- $orderNo = $order['order_no'];
- // 验证是否可以重新分配
- try {
- $frozenCommissionList = $this->checkCommissionOrScore($orderDetailsIds, 'commission');
- $frozenScoreList = $this->checkCommissionOrScore($orderDetailsIds, 'score');
- $this->checkDigital($orderDetailsIds);
- $orderNo && $this->checkDelayLog($orderNo);
- }catch (Exception $e) {
- throw new RuntimeException($e->getMessage());
- }
- // 将冻结列表组装成$insert_wallet
- return [
- 'insert_wallet' => $this->frozenDataToInsertWallet($frozenCommissionList, $frozenScoreList),
- 'order' => $order
- ];
- }
- /**
- * 重新分配,异步执行
- *
- * @param array $data
- *
- * @return false|void
- */
- public function asyncRedistributeCommissions(array $data)
- {
- if (empty($data['mall_id']) || empty($data['order_details_ids'])) {
- return;
- }
-
- $this->mall_id = $data['mall_id'];
- $orderDetailsIds = $data['order_details_ids'];
- $validateRes = $this->redistributeCommissionsValidate($orderDetailsIds, $this->mall_id);
- $order = $validateRes['order'];
- $insertWallet = $validateRes['insert_wallet'];
- $t = Yii::$app->db->beginTransaction();
- try {
- // 将供应商收入的旧数据置为失效
- $this->disableAgentSupplierCommission($orderDetailsIds);
- // 将供应商订单的旧数据置为失效
- $this->disableAgentSupplierOrder($orderDetailsIds);
- // $this->disableFrozenDigital($orderDetailsIds); // 不处理数字币
- // 将佣金和积分的旧数据置为失效
- $this->disableFrozenCommissionOrScore($orderDetailsIds, 'commission');
- $this->disableFrozenCommissionOrScore($orderDetailsIds, 'score');
- // 将延时任务的任务明细置为失效
- $this->disableAgentDelayLog($orderDetailsIds);
- // 减少agent total_commission total_score字段
- foreach ($insertWallet as $walletItem) {
- // 不处理数字币
- if($walletItem['wallet_type'] === 'digital'){
- continue;
- }
- if($walletItem['from_type'] === AddonsEnum::ADDONS_NAME_REGULAR_BONUS. '_'. AgentEnum::ADDONS_NAME) {
- continue;
- }
- $agent = Agent::findOne(['user_id' => $walletItem['user_id'],'status'=>[StatusEnum::DISABLED,StatusEnum::ENABLED], 'mall_id' => $this->mall_id]);
- if(empty($agent)) {
- continue;
- }
- $field = 'total_' . ($this->getCommissionNameMap()[$walletItem['wallet_type']] ?? $walletItem['wallet_type']);
- $agent->$field -= $walletItem['money'];
- $res = $agent->save();
- if (empty($res)) {
- throw new RuntimeException(Agent::getStaticError());
- }
- }
- $t->commit();
- // 重新分配
- $this->reward($order, $orderDetailsIds);
- }catch (Exception $e) {
- $t->rollBack();
- Yii::$app->custom->logs(FormatHelper::exception($e, '重新分配佣金失败'), compact('data'));
- return false;
- }
- }
- /**
- * 检查佣金或积分是否已结算(返回待结算的数据)
- *
- * @param array $orderDetailsIds
- * @param string $wallet_type
- *
- * @return array
- */
- protected function checkCommissionOrScore(array $orderDetailsIds, string $wallet_type): array
- {
- // 实际已结算的表
- CapitalLog::$capitalType = $wallet_type;
- $where = [
- 'source_table' => $this->getOrderDetailsTable(),
- 'source_table_id' => $orderDetailsIds,
- 'from_type' => AgentEnum::ADDONS_NAME
- ];
- $sendCount = CapitalLog::find()
- ->where($where)
- ->count();
- if ($sendCount) {
- throw new RuntimeException('当前订单已存在已结算数据,不允许重新分配');
- }
- // 冻结表
- CapitalLog::$capitalType = "{$wallet_type}_frozen";
- $where['status'] = [CapitalLog::STATUS_SEND, CapitalLog::STATUS_WAIT_SEND];
- $frozenList = [];
- $commissionFrozenList = CapitalLog::find()
- ->where($where)
- ->asArray()
- ->all();
- foreach ($commissionFrozenList as $item) {
- if ($item['status'] == CapitalLog::STATUS_SEND) {
- throw new RuntimeException('当前订单已存在已结算数据,不允许重新分配');
- }
- if ($item['status'] == CapitalLog::STATUS_WAIT_SEND) {
- $frozenList[] = $item;
- }
- }
- return $frozenList;
- }
- /**
- * 检查数字币是否已结算
- *
- * @param array $orderDetailsIds
- */
- protected function checkDigital(array $orderDetailsIds)
- {
- $digitalCount = DigitalLog::find()
- ->where([
- 'source_table' => $this->getOrderDetailsTable(),
- 'source_table_id' => $orderDetailsIds,
- 'from_type' => AgentEnum::ADDONS_NAME,
- 'send_status' => DigitalLog::SEND_STATUS_NORMAL
- ])
- ->count();
- if ($digitalCount) {
- throw new RuntimeException('当前订单已存在已结算数据,不允许重新分配');
- }
- }
- /**
- * 查看延迟结算表是否已结算,或者已经到了结算的时间
- *
- * @param string $orderNo
- *
- * @return void
- */
- protected function checkDelayLog(string $orderNo)
- {
- $sendCount = AgentDelayLog::find()
- ->where([
- 'wallet_type' => ['commission', 'score', 'digital'],
- 'order_no' => $orderNo,
- 'mall_id' => $this->mall_id,
- 'status' => CapitalLog::STATUS_SEND
- ])
- ->count();
- if ($sendCount) {
- throw new RuntimeException('当前订单已存在已结算数据,不允许重新分配');
- }
- $delayLog = AgentDelayLog::find()
- ->where([
- 'wallet_type' => ['commission', 'score', 'digital'],
- 'order_no' => $orderNo,
- 'mall_id' => $this->mall_id
- ])
- ->groupBy('wallet_type')
- ->select('min(day_num) day_num, min(created_at) created_at')
- ->all();
- if (empty($delayLog)) {
- return;
- }
-
- foreach ($delayLog as $item) {
- if ($item['day_num'] * 24 * 3600 + $item['created_at'] <= time() - 60) {
- throw new RuntimeException('当前订单正在结算或已结算,不允许重新分配');
- }
- }
- }
- /**
- * 将冻结数据置为失效(积分,佣金)
- *
- * @return void
- */
- protected function disableFrozenCommissionOrScore(array $orderDetailsIds, string $wallet_type)
- {
- $params = [
- 'where' => [
- [
- 'source_table' => $this->getOrderDetailsTable(),
- 'source_table_id' => $orderDetailsIds,
- 'from_type' => AgentEnum::ADDONS_NAME,
- 'status' => CapitalLog::STATUS_WAIT_SEND
- ]
- ]
- ];
- CapitalLog::$capitalType = "{$wallet_type}_frozen";
- $list = CapitalLog::lists($params);
- if ($list) {
- foreach ($list as $item) {
- UserWalletService::unfrozen($item['id'], $wallet_type, false);
- }
- }
- }
- /**
- * 将冻结数据置为失效(数字币)
- *
- * @return void
- */
- protected function disableFrozenDigital(array $orderDetailsIds)
- {
- DigitalLog::updateAll(
- [
- 'send_status' => DigitalLog::SEND_STATUS_NORMAL,
- 'status' => StatusEnum::DELETE,
- 'updated_at' => time()
- ],
- [
- 'source_table' => $this->getOrderDetailsTable(),
- 'source_table_id' => $orderDetailsIds,
- 'from_type' => AgentEnum::ADDONS_NAME,
- 'send_status' => DigitalLog::SEND_STATUS_FROZEN
- ]
- );
- }
- /**
- * 将佣金和积分禁用(不处理数字币)
- *
- * @return void
- */
- protected function disableAgentDelayLog(array $orderDetailsIds)
- {
- AgentDelayLog::updateAll(
- [
- 'status' => StatusEnum::DELETE,
- 'updated_at' => time()
- ],
- [
- 'wallet_type' => ['commission', 'score'],
- 'mall_id' => $this->mall_id,
- 'status' => CapitalLog::STATUS_WAIT_SEND,
- 'source_table' => $this->getOrderDetailsTable(),
- 'source_table_id' => $orderDetailsIds,
- ]
- );
- }
- /**
- * 禁用供应商收入的数据
- *
- * @return void
- */
- protected function disableAgentSupplierCommission(array $orderDetailsIds)
- {
- AgentSupplierCommission::updateAll(
- [
- 'status' => StatusEnum::DELETE,
- 'updated_at' => time()
- ],
- [
- 'mall_id' => $this->mall_id,
- 'status' => StatusEnum::ENABLED,
- 'source_table' => $this->getOrderDetailsTable(),
- 'source_table_id' => $orderDetailsIds,
- ]
- );
- }
- /**
- * @return array
- */
- protected function getOrderDetailsTable(): array
- {
- return ['order_detail', OrderDetail::tableName()];
- }
- public function reward($order, $orderDetailsIds){
- $mall_id = $order['mall_id'];
- $order_id = $order['id'];
- $user_id = $order['user_id'];
- $setting = \Yii::$app->services->setting->addons->get($mall_id, AgentEnum::ADDONS_NAME, 'basic');
- if (empty($setting['is_enable'])) throw new \yii\db\Exception('没开启经销商');
- $params = [];
- $params['where'] = [['order_id' => $order_id], ['user_id' => $user_id], ['mall_id' => $mall_id], ['id' => $orderDetailsIds]];
- $order_detail_list = OrderDetail::lists($params);
- if (empty($order_detail_list)) throw new \yii\db\Exception('订单详情不存在');
- $is_self_buy = $setting['is_self_buy'];// 经销商内购
- $enable_repurchase_reward = $setting['enable_repurchase_reward'] ?? StatusEnum::DISABLED;// 复购等于报单 - 需要判断当前用户是否有支付过的订单
- if ($enable_repurchase_reward) {
- $enable_repurchase_reward = Order::find()
- ->where(['user_id' => $user_id])
- ->andWhere(['mall_id' => $mall_id])
- ->andWhere(['<>', 'id', $order_id])
- ->andWhere(['pay_status' => StatusEnum::ENABLED])
- ->count() > 0 ? StatusEnum::ENABLED : StatusEnum::DISABLED;
- }
- $parent_id_arr = UserPartitionRelationship::getParentIdArr($user_id);
- $parent_id_arr = array_reverse($parent_id_arr);
- $where = ['user_id' => $parent_id_arr, 'mall_id' => $mall_id, 'status' => StatusEnum::ENABLED];
- $addons_agent_list = Agent::find()->where($where)->indexBy('user_id')->all();//查询经销商列表
- $agent_list = [];
- foreach ($parent_id_arr as $parent_id) {
- if (!empty($addons_agent_list[$parent_id])) $agent_list[] = $addons_agent_list[$parent_id];//按照关系排序
- }
- $agent = Agent::findOne(['user_id' => $user_id, 'mall_id' => $mall_id, 'status' => StatusEnum::ENABLED]);// 查询购买者身份
- $reward_detail = $this->unshiftAgentList($is_self_buy, $enable_repurchase_reward, $agent_list, $order_detail_list, $agent);
- $commission_arr = [];
- $is_settle_additional_score = StatusEnum::DISABLED;
- if (MallAddons::isInstall($mall_id, AddonsEnum::ADDONS_NAME_POINT_UPPER_LIMIT)) {
- $is_settle_additional_score = (new SettingService())->isEnable($mall_id);
- }
- $insert_wallet_data = [];
- foreach ($order_detail_list as $order_detail) {
- // 如果是针对商品的,那么就判断
- // 检测商品是否参与了渠道分红
- [$agent_list, $self_buy_user_id, $enable_repurchase_reward] = $reward_detail[$order_detail['id']];
- $item_setting = AgentCommissionItemSetting::find()->select('item_id,is_participate')->where(['item_id' => $order_detail['goods_id'], 'status' => StatusEnum::ENABLED])->asArray()->one();
- if (!empty($item_setting) && empty($item_setting['is_participate'])) continue;
- $agent_reward_obj = new AgentReward($mall_id, $user_id, $setting, $agent_list, $self_buy_user_id, $enable_repurchase_reward);
- $order_detail['order_no'] = $order['order_no'];
- $agent_reward_obj->order_detail = $order_detail;
- $commission_arr[$order_detail['id']][AgentEnum::ADDONS_NAME]['commission'] = $agent_reward_obj->addFrozenCommission();
- $insert_wallet_data = array_merge($insert_wallet_data, $agent_reward_obj->insert_wallet);
- $agent_reward_obj = new AgentReward($mall_id, $user_id, $setting, $agent_list, $self_buy_user_id, $enable_repurchase_reward, 'score');
- $agent_reward_obj->order_detail = $order_detail;
- $agent_reward_obj->addFrozenCommission();
- $insert_wallet_data = array_merge($insert_wallet_data, $agent_reward_obj->insert_wallet);
- //数字币赠送 (数字币不处理)
- /*$agent_reward_obj = new AgentReward($mall_id, $user_id, $setting, $agent_list, $self_buy_user_id, $enable_repurchase_reward, 'digital');
- $agent_reward_obj->order_detail = $order_detail;
- $agent_reward_obj->addFrozenCommission();
- $insert_wallet_data = array_merge($insert_wallet_data, $agent_reward_obj->insert_wallet);*/
- // 额外积分 - 需要判断是否开启
- if (!empty($is_settle_additional_score)) {
- // 判断当前用户是否已经超出上限, 只有有额度的情况下才需要进行处理
- // if ((new UserService())->getUserQuota($mall_id, $user_id) > 0) {
- $agent_reward_obj = new AgentReward($mall_id, $user_id, $setting, $agent_list, $self_buy_user_id, $enable_repurchase_reward, 'additional_score');
- $agent_reward_obj->order_detail = $order_detail;
- $agent_reward_obj->addFrozenCommission();
- // }
- }
- }
- /*
- * TODO: 渠道分红延时结算/解冻资产
- * 结算方式为“订单完成后”并且“延时结算天数”不为0时执行延时结算
- */
- if (isset($setting['compute_type']) && isset($setting['compute_delay_day']) && !empty($setting['compute_type']) && !empty($setting['compute_delay_day'])) {
- $delay_logs_data = []; // TODO: 渠道分红延时结算 - 需要延时解冻数据
- foreach ($insert_wallet_data as $item) {
- $delay_logs_data[] = [
- 'mall_id' => $mall_id,
- 'user_id' => $item['user_id'],
- 'wallet_type' => $item['wallet_type'],
- 'wallet_num' => $item['money'],
- 'compute_type' => $setting['compute_type'],
- 'day_num' => $setting['compute_delay_day'],
- 'wallet_desc' => $item['desc'],
- 'order_no' => $item['order_no'],
- 'capital_type' => $item['capital_type'],
- 'contributor_name' => $item['contributor_name'],
- 'contributor_money' => $item['contributor_money'],
- 'contributor_id' => $item['contributor_id'],
- 'source_table' => $item['source_table'],
- 'source_table_id' => $item['source_table_id'],
- ];
- }
- // 写入延时结算日志
- AgentDelayLog::batchSave($delay_logs_data);
- }
- $this->addOrderLog($order,$commission_arr);
- return true;
- }
- /**
- * 添加订单
- *
- * @param $order
- * @param $commission_arr
- *
- * @throws Exception
- */
- public function addOrderLog($order,$commission_arr)
- {
- $total_commission = 0;
- foreach ($commission_arr as $order_detail_id => $commission) {
- $total_commission += $commission['commission'] ?? ($commission['Agent']['commission'] ?? 0);
- }
- $agent = Agent::findOne(['mall_id' => $order->mall_id,'user_id' => $order->user_id]);
- // 将旧的禁用
- AgentCommissionDetails::updateAll(
- [
- 'status' => StatusEnum::DELETE,
- 'updated_at' => time()
- ],
- [
- 'mall_id' => $order->mall_id,
- 'order_id' => $order->id,
- 'user_id' => $order->user_id,
- 'agent_id' => $agent->id ?? 0,
- ]
- );
- $data = [
- 'mall_id' => $order->mall_id,
- 'order_id' => $order->id,
- 'user_id' => $order->user_id,
- 'agent_id' => $agent->id ?? 0,
- 'level' => $agent->level ?? 0,
- 'order_price' => $order->pay_money,
- 'commission' => $total_commission,
- 'order_source' => 'order',
- ];
- $res = AgentCommissionDetails::setData($data);
- if(!$res) throw new Exception(AgentCommissionDetails::getStaticError());
- }
- /**
- * 针对每一款商品的设置
- * @param int $is_self_buy
- * @param int $enable_repurchase_reward
- * @param array $agent_list
- * @param array $orders
- * @param Agent|null $agent
- * @return array
- */
- protected function unshiftAgentList(int $is_self_buy, int $enable_repurchase_reward, array $agent_list, array $orders, Agent $agent = null): array
- {
- $data = [];
- foreach ($orders as $order_detail) {
- // 独立设置了
- $data[$order_detail['id']][0] = $agent_list; // agent_list
- $data[$order_detail['id']][1] = StatusEnum::DISABLED; // self_buy_user_id
- $data[$order_detail['id']][2] = StatusEnum::DISABLED; // enable_repurchase_reward
- if (!empty($agent)) {
- $order_detail_enable_repurchase_reward = $enable_repurchase_reward;
- $is_alone_setting = AgentGoodsRepurchase::isAloneSetting($order_detail['mall_id'], $order_detail['goods_id']);
- if ($is_alone_setting) {
- // 单独设置 那么就需要判断之前是否有购买过当前商品
- $order_detail_enable_repurchase_reward = AgentGoodsRepurchase::isBuyCurrentGoods($order_detail['mall_id'], $order_detail['user_id'],
- $order_detail['order_id'], $order_detail['goods_id']) ? StatusEnum::ENABLED : StatusEnum::DISABLED;
- }
- //独立设置内购
- $item_setting = AgentCommissionItemSetting::find()->select('item_id,is_participate,is_self_buy_alone,is_self_buy,enable_goods_deduct')->where(['item_id' => $order_detail['goods_id'], 'status' => StatusEnum::ENABLED])->asArray()->one();
- if (!empty($item_setting) && !empty($item_setting['is_participate']) && !empty($item_setting['is_self_buy_alone'])){
- $is_self_buy_detail = $item_setting['is_self_buy'];
- }else{
- $is_self_buy_detail = $is_self_buy;
- }
- if ($is_self_buy_detail || $order_detail_enable_repurchase_reward) {
- array_unshift($data[$order_detail['id']][0], $agent);
- $data[$order_detail['id']][1] = $agent->user_id;
- $data[$order_detail['id']][2] = StatusEnum::ENABLED;
- }
- }
- }
- return $data;
- }
- /**
- * 将冻结的数据组装成$insert_wallet
- *
- * @return array
- */
- protected function frozenDataToInsertWallet(array $frozenCommissionList, array $frozenScoreList)
- {
- foreach ($frozenCommissionList as &$item) {
- $item['wallet_type'] = 'commission';
- $item['is_frozen'] = true;
- $item['money'] = $item['change_num'];
- }
- foreach ($frozenScoreList as &$item) {
- $item['wallet_type'] = 'score';
- $item['is_frozen'] = true;
- $item['money'] = $item['change_num'];
- }
- return array_merge($frozenCommissionList, $frozenScoreList);
- }
- protected function getCommissionNameMap(): array
- {
- return [
- 'additional_score' => 'score'
- ];
- }
- /**
- * 将供应商订单数据扣回,因为原来写入时同一个订单是累加的,所以为了兼容纠错只选择单个order_detail的情况下只能扣回,不能将原数据删除
- *
- * @param $orderDetailsIds
- *
- * @return void
- */
- private function disableAgentSupplierOrder($orderDetailsIds)
- {
- $wallet_type = 'commission';
- CapitalLog::$capitalType = "{$wallet_type}_frozen";
- $where = [
- [
- 'source_table' => $this->getOrderDetailsTable(),
- 'source_table_id' => $orderDetailsIds,
- 'from_type' => AgentEnum::ADDONS_NAME,
- 'status' => StatusEnum::DISABLED,
- 'change_type' => 'add',
- 'mall_id' => $this->mall_id
- ]
- ];
- $commissionList = CapitalLog::lists([
- 'where' => $where,
- 'select' => 'change_num, user_id, source_table_id, order_no'
- ]);
- // 得到购买数量
- $orderDetails = OrderDetail::find()
- ->where([
- 'id' => $orderDetailsIds,
- 'status' => StatusEnum::ENABLED,
- 'mall_id' => $this->mall_id
- ])
- ->indexBy('id')
- ->all();
- $setting = \Yii::$app->services->setting->addons->get($this->mall_id, AgentEnum::ADDONS_NAME, 'basic');
- $agent_reward_obj = new AgentReward($this->mall_id, 0, $setting, [], 0, 0, '');
- foreach ($commissionList as $commissionItem) {
- $model = AgentSupplierOrder::find()
- ->where([
- 'seller_user_id' => $commissionItem['user_id'],
- 'order_no' => $commissionItem['order_no'],
- 'status' => StatusEnum::ENABLED
- ])
- ->one();
- if (!$model) {
- continue;
- }
- if (empty($orderDetails[$commissionItem['source_table_id']])) {
- continue;
- }
- $agent_reward_obj->order_detail = $orderDetails[$commissionItem['source_table_id']];
- ['money' => $money] = $agent_reward_obj->getRules();
- $model->payment_amount -= $money; // getRule得到
- $model->profit -= $commissionItem['change_num']; // 佣金
- $model->goods_nums -= $orderDetails[$commissionItem['source_table_id']]->num;
- $model->stock_nums -= $orderDetails[$commissionItem['source_table_id']]->num;
- $model->payment_amount = $model->payment_amount < 0 ? 0 : $model->payment_amount;
- $model->profit = $model->profit < 0 ? 0 : $model->profit;
- $model->goods_nums = $model->goods_nums < 0 ? 0 : $model->goods_nums;
- $model->stock_nums = $model->stock_nums < 0 ? 0 : $model->stock_nums;
- if (
- $model->payment_amount == 0 &&
- $model->profit == 0 &&
- $model->goods_nums == 0 &&
- $model->stock_nums == 0
- ) {
- $model->status = StatusEnum::DELETE;
- }
- $model->save();
- }
- }
- }
|