| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980 |
- <?php
- /*
- * @Descripttion: 触发推三返一奖励
- * @copyright: Copyright (c) 2021 广东七件事集团
- * @Author: lun
- * @Date: 2022-01-01 20:16:12
- */
- namespace addons\Rebate\common\logic;
- use addons\Coupon\common\enums\AddonsCouponEnum;
- use addons\Coupon\common\models\AddonsCoupon;
- use addons\Coupon\common\models\AddonsCouponUserRelate;
- use addons\Rebate\common\enums\RebateEnum;
- use addons\Rebate\common\models\Rebate;
- use addons\Rebate\common\models\RebateBuy;
- use addons\Rebate\common\models\RebateRecommendNum;
- use addons\Rebate\common\models\RebateRewardLog;
- use addons\Rebate\common\models\RebateStatistics;
- use addons\Rebate\common\models\RebateVirtualOrderLog;
- use addons\Rebate\common\services\SettingService;
- use common\enums\AddonsEnum;
- use common\enums\RabbitMqEnum;
- use common\enums\StatusEnum;
- use common\enums\UserWalletEnum;
- use common\models\common\AddonsSetting;
- use common\models\common\CapitalLog;
- use common\models\goods\Goods;
- use common\models\mall\MallAddons;
- use common\models\order\Order;
- use common\models\order\OrderDetail;
- use common\models\user\User;
- use common\traits\ErrorTrait;
- use services\common\UserWalletService;
- use yii\db\Exception;
- use Yii;
- use yii\helpers\Json;
- class RewardLogic
- {
- use ErrorTrait;
- /**
- * 奖励处理
- * @Author: lun
- * @DateTime: 2022/1/15 0015 9:51
- * @Copyright: copyright (c) 2021 广东七件事集团
- * @param $order_id
- * @param $settlement_type // 结算类型,1=支付完成,2=订单完成
- * @return bool
- */
- public static function execute($order_id, $settlement_type)
- {
- $t = Yii::$app->db->beginTransaction();
- try {
- // 获取订单内容
- $where = ['id' => $order_id];
- $order = Order::find()->select("id,user_id,mall_id,order_no,pay_time")
- ->where($where)
- ->with(['detail' => function($query){
- $query->select("id, order_id,goods_id,num,goods_price,goods_name,price,pic_url");
- }])
- ->asArray()->one();
- if(empty($order)) throw new Exception("订单不存在");
- $mall_id = $order['mall_id'];
- $user_id = $order['user_id'];
- // 获取推三返一基础配置内容
- $settingService = new SettingService(['mall_id' => $mall_id]);
- $config = $settingService->getSetting();
- $settlement_method = $config['settlement_method'];
- $addons_name = $config['addons_name'];
- // 获取推三返一的商品
- $rebate_list = Rebate::getRebateAllGoodsId($mall_id);
- $goods_arr = [];
- foreach ($rebate_list as $item) {
- $goods_arr[$item['item_id']][] = $item;
- }
- $order_settlement_status = 0;// 订单结算状态[0:未达成;1:已达成]
- if($settlement_method == $settlement_type) $order_settlement_status = 1;
- $reward_commission = [];
- $unfozenRebateBuys = [];
- foreach($order['detail'] as $order_detail) {
- // 检查该商品是否参与了推三返一活动
- if(!isset($goods_arr[$order_detail['goods_id']])) continue;
- foreach ($goods_arr[$order_detail['goods_id']] as $rebate) {
- // 获取消费者的直推上级
- $parent_id = User::find()->select('parent_id')->where(['id' => $user_id, 'mall_id' => $mall_id, 'status' => StatusEnum::ENABLED])->asArray()->scalar();
- if(empty($parent_id)) {
- continue;
- }
- if(empty($rebate['join_type'])){
- // 判断上级是否有权限
- if($rebate['initiate_type'] == RebateEnum::INITIATE_TYPE_NEW && Rebate::checkUserHasOrder($mall_id, $parent_id) !== false) {
- continue;
- }
- if($rebate['initiate_type'] == RebateEnum::INITIATE_TYPE_LEVEL && Rebate::checkUserLevel($parent_id, $rebate['initiate_level']) == false) {
- continue;
- }
- // 判断消费者是否符合权限
- if($rebate['consume_type'] == RebateEnum::CONSUME_TYPE_NEW) {
- $order_num = Rebate::checkUserHasOrder($mall_id, $user_id);
- if (!empty($order_num) && $order_num > 1) {
- continue;
- }
- }
- if($rebate['consume_type'] == RebateEnum::CONSUME_TYPE_LEVEL && Rebate::checkUserLevel($user_id, $rebate['consume_level']) == false) {
- continue;
- }
- }else{
- // 判断上级是否有权限
- if($rebate['initiate_type'] == RebateEnum::INITIATE_TYPE_NEW && Rebate::checkNewRegisterUser($mall_id, $parent_id) == false) {
- continue;
- }
- if($rebate['initiate_type'] == RebateEnum::INITIATE_TYPE_LEVEL && Rebate::checkRebateUserLevel($parent_id, $rebate['initiate_level']) == false) {
- continue;
- }
- // 判断消费者是否符合权限
- if($rebate['consume_type'] == RebateEnum::CONSUME_TYPE_NEW && Rebate::checkNewRegisterUser($mall_id, $user_id)==false) {
- continue;
- }
- if($rebate['consume_type'] == RebateEnum::CONSUME_TYPE_LEVEL && Rebate::checkRebateUserLevel($user_id, $rebate['consume_level']) == false) {
- continue;
- }
- }
- // 初始化参与活动
- $res = RebateRecommendNum::initRecommendNum($mall_id, ['r_id' => $rebate['id'], 'user_id' => $parent_id]);
- if ($res === false) throw new \Exception(RebateRecommendNum::getStaticError());
- // 检测购买此商品是否有使用优惠或抵扣(随机减不算)
- if (!empty($rebate['is_grant']) && ($order_detail['price'] * $order_detail['num']) != $order_detail['goods_price']) continue;
- // 保存消费者数据
- $rabate_buy = self::saveRebateBuy($mall_id, $rebate['id'], $user_id, $parent_id, $order, $order_detail, $order_settlement_status);
- if ($rabate_buy && $rabate_buy['is_settlement'] == 1) {// 如果此订单已经结算过则不再触发
- continue;
- }
- if($settlement_method != $settlement_type) {
- continue;
- }
- // 获取未结算的ids
- $rebate_buy_ids = RebateBuy::getNoSettlementList($mall_id, $rebate['id'], $parent_id);
- // 奖励的内容
- $rebate_info = Json::decode($rebate['reward_info'], true);
- // 获取用户上级已有的订单数
- $recommend_num = RebateRecommendNum::setData($mall_id, ['r_id' => $rebate['id'], 'user_id' => $parent_id, 'pay_num' => 1]);
- // 活动统计
- RebateStatistics::setData($mall_id, ['r_id' => $rebate['id'], 'pay_money' => $order_detail['goods_price']]);
- // 判断奖励方式
- $reward_title = $content = '';
- if($rebate['reward_type'] == RebateEnum::REWARD_TYPE_COND) {// 条件奖励
- if($recommend_num['pay_num'] % $rebate_info[0]['num'] == 0) {// 取余=0则代表可的奖励
- $reward_title = "每推荐" . $rebate_info[0]['num']. "人购买";
- $content = self::giveParentReward($mall_id, $rebate_info[0]['data'], $parent_id, $order_id, $order_detail['id'], $addons_name,$reward_commission);
- $reward_key = 0;
- }
- } else {
- // 阶梯奖励
- if (empty($rebate['is_repeat'])) {
- foreach($rebate_info as $k => $item){
- if($item['num'] == $recommend_num['pay_num']) {
- $reward_title = "推荐" . $item['num']. "人购买";
- $is_frozen = $k === 0 && $rebate['is_freeze_first_reward'] ? RebateEnum::FROZEN : RebateEnum::NOT_FROZEN;
- $content = self::giveParentReward($mall_id, $item['data'], $parent_id, $order_id, $order_detail['id'], $addons_name,$reward_commission, $is_frozen, $rebate);
- $reward_key = $k;
- break;
- }
- }
- } else {
- // 重复发奖处理
- $last_value = $rebate_info[count($rebate_info) - 1]['num'];// 获取数组中最后一个的数值
- $multiple = empty($recommend_num['pay_num']) ? 0 : ceil($recommend_num['pay_num'] / $last_value) - 1;// 向上取整再减1,获取倍数
- // 设置循环奖励,从第二轮开始
- if ($recommend_num['pay_num'] > $last_value && !empty($rebate['is_reward_after_n']) && !empty($rebate['reward_threshold'])) {
- if (!is_numeric($offset = array_search($rebate['reward_threshold'], array_column($rebate_info, 'num')))) {
- continue;
- }
- // 得到 $rebate['reward_threshold'] 的奖励
- $rebate_info_by_threshold = array_slice($rebate_info, $offset);
- if (empty($rebate_info_by_threshold)) {
- continue;
- }
- $rebate_info_by_threshold_count = count($rebate_info_by_threshold);
- $rewardIndex = (($recommend_num['pay_num'] - $last_value) % $rebate_info_by_threshold_count) - 1;
- $rewardIndex < 0 && $rewardIndex = $rebate_info_by_threshold_count - 1;
- $item = $rebate_info_by_threshold[$rewardIndex];
- $reward_title = "推荐" . $recommend_num['pay_num']. "人购买";
- $content = self::giveParentReward($mall_id, $item['data'], $parent_id, $order_id, $order_detail['id'], $addons_name,$reward_commission);
- $reward_key = $offset + $rewardIndex; // 在$rebate_info数组的key
- $isRepeat = true; // 标识这是循环奖励
- } else {
- foreach($rebate_info as $k => $item) {
- $item['num'] = $item['num'] + $last_value * $multiple;// 奖励个数计算=阶梯个数 + 最后数值 * 向下取整倍数
- if($item['num'] == $recommend_num['pay_num']) {
- $is_frozen = $k === 0 && $rebate['is_freeze_first_reward'] ? RebateEnum::FROZEN : RebateEnum::NOT_FROZEN;
- $reward_title = "推荐" . $item['num']. "人购买";
- $content = self::giveParentReward($mall_id, $item['data'], $parent_id, $order_id, $order_detail['id'], $addons_name,$reward_commission, $is_frozen, $rebate);
- $item['num'] = $rebate_info[$k]['num'];
- $reward_key = $k;
- break;
- }
- }
- }
- }
-
- // 如果当前获取第二项奖励,并且第一项是冻结的,需要解冻第一项
- if (isset($reward_key) && $reward_key == 1 && !isset($isRepeat)) {
- $unfozenRebateBuys[] = $rabate_buy;
- }
- }
- if($content) {
- // 保存数据时的配置
- $setting = [
- 'title' => $rebate['title'],
- 'item_id' => $rebate['id'],
- 'settlement_method' => $settlement_method,
- 'reward_type' => $rebate['reward_type'],
- 'reward_info' => $rebate_info,
- 'log_ids' => implode(',', $rebate_buy_ids),
- 'reward_key' => $reward_key ?? -1,
- 'order_detail_id' => $order_detail['id'],
- 'freeze_first_reward_type' => $rebate['freeze_first_reward_type'],
- 'freeze_first_reward_percentage' => $rebate['freeze_first_reward_percentage']
- ];
- // 保存奖励数据
- $log = [
- 'r_id' => $rebate['id'],
- 'user_id' => $parent_id,
- 'reward_title' => $reward_title,
- 'content' => $content,
- 'setting' => Json::encode($setting),
- 'is_frozen' => $is_frozen ?? RebateEnum::NOT_FROZEN,
- ];
- $reward = RebateRewardLog::setData($mall_id, $log);
- if($reward == false) throw new Exception(RebateRewardLog::getStaticError());
- // 将购买记录改为已结算
- RebateBuy::updateAll(['is_reward_trigger' => 1, 'updated_at' => time()], ['id' => $rabate_buy['id'], 'order_settlement_status' => 1]);
- RebateBuy::updateAll(['is_settlement' => 1, 'reward_id' => $reward['id'], 'updated_at' => time()], ['id' => $rebate_buy_ids, 'order_settlement_status' => 1]);
- }
- }
- }
- self::unfrozenFirstReward2Queue($unfozenRebateBuys);
- $t->commit();
- LevelUpLogic::execute($order,$settlement_type);
- // 推三返一订单完成-触发的奖励
- if ($settlement_type==2 && MallAddons::isInstall($order['mall_id'], 'BonusPool')) {
- $handle_class = \addons\BonusPool\common\listeners\order\OrderComputeCommissionListener::class;
- $data = [
- 'rebate_commission_reward_arr' => $reward_commission,
- 'order_id' => $order_id,
- ];
- \Yii::$app->services->rabbitMq->push(RabbitMqEnum::EXCHANGE_ORDER, RabbitMqEnum::ORDER_QUEUE, $data, $handle_class, 'handleSync');
- }
- return true;
- } catch (Exception $e) {
- $t->rollBack();
- self::setStaticError($e->getMessage());
- return false;
- }
- }
- /**
- * 保存购买者信息
- * @Author: lun
- * @DateTime: 2022/1/15 0015 9:47
- * @Copyright: copyright (c) 2021 广东七件事集团
- * @param $mall_id
- * @param $r_id
- * @param $user_id
- * @param $parent_id
- * @param $order
- * @param $order_detail
- * @param $order_settlement_status
- * @return array| bool
- */
- private static function saveRebateBuy($mall_id, $r_id, $user_id, $parent_id, $order, $order_detail, $order_settlement_status = 0, $is_virtual = 0, $is_settlement = 0)
- {
- $params = [
- 'mall_id' => $mall_id,
- 'r_id' => $r_id,
- 'pid' => $parent_id,
- 'order_no' => $order['order_no'],
- 'pay_at' => $order['pay_time'],
- 'pay_money' => $order_detail['goods_price'],
- 'goods_info' => Json::encode([
- 'id' => $order_detail['goods_id'],
- 'goods_name' => $order_detail['goods_name'],
- 'cover_pic' => $order_detail['pic_url'],
- 'price' => $order_detail['price'],
- ]),
- 'user_id' => $user_id,
- 'order_settlement_status' => $order_settlement_status,
- 'is_virtual' => $is_virtual,
- 'is_settlement' => $is_settlement,
- 'order_detail_id' => $order_detail['id']
- ];
- // 检测是否已经生成过数据
- $has_buy = RebateBuy::find()->where(['r_id' => $r_id, 'pid' => $parent_id, 'user_id' => $user_id, 'order_no' => $order['order_no']])->one();
- if ($has_buy) {
- if (empty($has_buy->order_settlement_status) && $order_settlement_status == 1) {
- $has_buy->order_settlement_status = 1;
- $has_buy->settlement_at = time();
- $has_buy->position = self::getPosition($mall_id, $r_id, $parent_id);
- if (!$has_buy->save()) throw new Exception($has_buy->getErrorMessage());
- }
- return $has_buy->toArray();
- }
- if ($params['order_settlement_status']) {
- $params['settlement_at'] = time();
- $params['position'] = self::getPosition($mall_id, $r_id, $parent_id);
- }
- return RebateBuy::setData($params);
- }
- /**
- * 得到position
- *
- * @param int $mallId
- * @param int $rId
- * @param int $parentId
- *
- * @return int
- */
- public static function getPosition(int $mallId, int $rId, int $parentId): int
- {
- $position = RebateBuy::find()
- ->where([
- 'mall_id' => $mallId,
- 'r_id' => $rId,
- 'pid' => $parentId,
- 'order_settlement_status' => StatusEnum::ENABLED
- ])
- ->orderBy('position desc')
- ->select('position')
- ->scalar() ?: 0;
- return ++$position;
- }
- /**
- * 赠送活动奖励
- * @Author: lun
- * @DateTime: 2022/1/15 0015 9:47
- * @Copyright: copyright (c) 2021 广东七件事集团
- * @param $mall_id
- * @param $rewards
- * @param $user_id
- * @param $order_id
- * @param string $desc
- * @param string $rebate 推三返一活动数据
- * @return bool|string
- */
- private static function giveParentReward($mall_id, $rewards, $user_id, $order_id, $order_detail_id, $desc = '推三返一',&$reward_commission = [], bool $is_frozen = false, array $rebate = [])
- {
- try {
- $orderInfo = OrderDetail::find()->where(['mall_id' => $mall_id, 'status' => StatusEnum::ENABLED, 'id' => $order_detail_id])
- ->select('id, goods_price as pay_money, original_goods_price, cost_price, num')
- ->asArray()->one();
- $reward_text = "";
- //判断是否安装红包拓客插件
- $has_redpack = MallAddons::isInstall($mall_id, AddonsEnum::ADDONS_NAME_REDPACK);
- $insert_wallet = [];
- foreach ($rewards as $item) {
- // 注意:冻结奖励时,商城资产 积分 佣金 余额 冻结时会转为冻结资产。优惠券奖励则订单完成后再发奖励。积分拓客则发未冻结的,已冻结的订单完成再发送
- switch ($item['type']) {
- case RebateEnum::REWARD_SCORE:// 积分
- if ($item['ratio']) {
- $item['data'] = self::getPercentage($mall_id, $orderInfo, $item);
- }
- // 当赠送金额小于等于0,不赠送
- if ($item['data'] <= 0) break;
- $reward_text.= ",积分:" . $item['data'];
- $walletItem = [
- 'mall_id' => $mall_id,
- 'user_id' => $user_id,
- 'wallet_type' => $item['type'],
- 'desc' => $desc . '赠送',
- 'source_table' => Order::tableName(),
- 'source_table_id' => $order_id,
- 'from_type' => AddonsEnum::ADDONS_NAME_REBATE,
- 'capital_type' => UserWalletEnum::GIVE,
- ];
- self::computeAndInsertWallet($is_frozen, $item['data'], $rebate, $walletItem, $insert_wallet, $reward_text);
- break;
- case RebateEnum::REWARD_BALANCE:// 余额
- if ($item['ratio']) {
- $item['data'] = self::getPercentage($mall_id, $orderInfo, $item);
- }
- if ($item['data'] <= 0) break;
- $reward_text.= ",余额:¥" . $item['data'];
- $walletItem = [
- 'mall_id' => $mall_id,
- 'user_id' => $user_id,
- 'wallet_type' => $item['type'],
- 'desc' => $desc . '赠送',
- 'source_table' => Order::tableName(),
- 'source_table_id' => $order_id,
- 'from_type' => AddonsEnum::ADDONS_NAME_REBATE,
- 'capital_type' => UserWalletEnum::GIVE,
- ];
- self::computeAndInsertWallet($is_frozen, $item['data'], $rebate, $walletItem, $insert_wallet, $reward_text);
- break;
- case RebateEnum::REWARD_COMMISSION:// 佣金
- if ($item['ratio']) {
- $item['data'] = self::getPercentage($mall_id, $orderInfo, $item);
- }
- if ($item['data'] <= 0) break;
- $reward_text.= ",佣金:¥" . $item['data'];
- $walletItem = [
- 'mall_id' => $mall_id,
- 'user_id' => $user_id,
- 'wallet_type' => $item['type'],
- 'desc' => $desc . '赠送',
- 'source_table' => OrderDetail::tableName(),
- 'source_table_id' => $order_detail_id,
- 'from_type' => AddonsEnum::ADDONS_NAME_REBATE,
- 'capital_type' => UserWalletEnum::GIVE,
- ];
- self::computeAndInsertWallet($is_frozen, $item['data'], $rebate, $walletItem, $insert_wallet, $reward_text);
- if(isset($reward_commission[$order_detail_id])){
- $reward_commission[$order_detail_id]['money'] += $item['data'];
- }else{
- $reward_commission[$order_detail_id]['money'] = $item['data'];
- }
- break;
- case RebateEnum::REWARD_COUPON:// 优惠券
- // 赠送优惠券
- foreach ($item['data'] as $coupon) {
- $give_coupon_arr[$coupon['relevant_id']] = $coupon['num'];
- }
- if (empty($give_coupon_arr)) {
- break;
- }
- if ($is_frozen) {
- $coupon_arr = AddonsCoupon::find()
- ->select('name')
- ->where(['mall_id' => $mall_id, 'id' => array_keys($give_coupon_arr), 'status' => StatusEnum::ENABLED, 'coupon_status' => AddonsCouponEnum::STATUS_RECEIVING])
- ->asArray()
- ->all();
- } else {
- $coupon_arr = AddonsCouponUserRelate::giveCoupon($mall_id, $user_id, $give_coupon_arr, AddonsCouponEnum::SEND_FROM14);
- }
- if ($coupon_arr) {
- foreach ($coupon_arr as $info) {
- $coupon_text[] = $info['name'];
- }
- $reward_text.= ",优惠券:[" . implode(',', $coupon_text) .']';
- }
- break;
- case RebateEnum::REWARD_REDPACK://激活红包
- case RebateEnum::REWARD_FROZEN_REDPACK:
- //未安装红包拓客插件,则跳出
- if (!$has_redpack) break;
- if ($item['ratio']) {
- $item['data'] = self::getPercentage($mall_id, $orderInfo, $item);
- }
- // 当赠送金额小于等于0,不赠送
- if ($item['data'] <= 0) break;
- ['frozen_money' => $frozen_money, 'money' => $money] = self::computeRewardMoney(
- $is_frozen,
- $item['data'],
- $rebate['freeze_first_reward_type'] ?? RebateEnum::FREEZE_FIRST_REWARD_TYPE_ALL,
- $rebate['freeze_first_reward_percentage'] ?? 0
- );
- $redpack_data = [
- 'mall_id' => $mall_id,
- 'user_id' => $user_id,
- 'is_frozen' => false,
- 'money' => $money,
- 'desc' => '订单('.$order_id.')推三返一赠送红包',
- 'source_table' => OrderDetail::tableName(),
- 'source_table_id' => $order_detail_id,
- 'from_type' => \addons\Redpack\common\enums\RedpackEnum::FROM_REBATE_REWARD,
- ];
- if ($item['type'] == 'frozen_redpack') {
- $reward_text.= ",冻结红包:" . $item['data'];
- $redpack_data['is_frozen'] = true;
- } else {
- $reward_text.= ",激活红包:" . $item['data'];
- }
- if ($frozen_money > 0) {
- $reward_text .= '(冻结 ' . $frozen_money . ')';
- }
- if ($money > 0) {
- $res = \addons\Redpack\common\models\RedpackWallet::setData($redpack_data);
- if (!$res) throw new Exception(\addons\Redpack\common\models\RedpackWallet::$static_error);
- }
- break;
- default:
- break;
- }
- }
- if (!empty($insert_wallet)) {
- $res = UserWalletService::batchHandleByQueue($insert_wallet);
- if (empty($res)) throw new \Exception(UserWalletService::getStaticError());
- }
- return ltrim($reward_text, ',');
- } catch (\Exception $e) {
- Yii::error("推三返一奖励报错=" . $e->getMessage());
- return false;
- }
- }
- /**
- * 计算冻结奖励和非冻结奖励
- *
- * @return void
- */
- private static function computeRewardMoney(bool $is_frozen, float $rewardMoney, int $freezeFirstRewardType, float $freezeFirstRewardPercentage): array
- {
- if (
- !$is_frozen ||
- (
- $freezeFirstRewardType == RebateEnum::FREEZE_FIRST_REWARD_TYPE_PERCENTAGE &&
- $freezeFirstRewardPercentage <= 0
- )
- ) {
- return [
- 'frozen_money' => 0,
- 'money' => $rewardMoney,
- ];
- }
- // 全部冻结
- if (
- $freezeFirstRewardType == RebateEnum::FREEZE_FIRST_REWARD_TYPE_ALL ||
- (
- $freezeFirstRewardType == RebateEnum::FREEZE_FIRST_REWARD_TYPE_PERCENTAGE &&
- $freezeFirstRewardPercentage >= 100
- )
- ) {
- return [
- 'frozen_money' => $rewardMoney,
- 'money' => 0,
- ];
- }
- // 按百分比冻结
- $frozen_money = bcmul($rewardMoney, $freezeFirstRewardPercentage / 100, 2);
- return [
- 'frozen_money' => $frozen_money,
- 'money' => bcsub($rewardMoney, $frozen_money, 2),
- ];
- }
- /**
- * 计算并插入奖励
- *
- * @param bool $is_frozen
- * @param float $rewardMoney
- * @param array $rebate
- * @param array $walletItem
- * @param array $insert_wallet
- * @param string $reward_text
- *
- * @return void
- */
- private static function computeAndInsertWallet(bool $is_frozen, float $rewardMoney, array $rebate, array $walletItem, array &$insert_wallet, string &$reward_text)
- {
- ['frozen_money' => $frozen_money, 'money' => $money] = self::computeRewardMoney(
- $is_frozen,
- $rewardMoney,
- $rebate['freeze_first_reward_type'] ?? RebateEnum::FREEZE_FIRST_REWARD_TYPE_ALL,
- $rebate['freeze_first_reward_percentage'] ?? 0
- );
- if ($money > 0) {
- $insert_wallet[] = array_merge($walletItem, ['is_frozen' => false, 'money' => $money]);
- }
- $rewardFlag = in_array($walletItem['wallet_type'], [RebateEnum::REWARD_BALANCE, RebateEnum::REWARD_COMMISSION]) ? '¥' : '';
- if ($frozen_money > 0) {
- $insert_wallet[] = array_merge($walletItem, ['is_frozen' => true, 'money' => $frozen_money]);
- $reward_text .= '(冻结 ' . $rewardFlag . $frozen_money . ')';
- }
- }
- /**
- * 奖励(余额-佣金-积分)百分比计算
- * @param $mall_id //商户id
- * @param $order //商品信息
- * @param $item //占比信息
- */
- public static function getPercentage($mall_id, $order, $item)
- {
- $ratio_money = 0; //返回比率计算价格
- // 获取配置字段
- $settingService = new SettingService(['mall_id' => $mall_id]);
- $system = $settingService->getSetting()['computing_method'];
- //计算比率
- $ratio = $item['data'] / 100;
- switch ($system)
- {
- case RebateEnum::COMPUTING_METHOD_PAY_PRICE:// 支付价格计算
- //计算金额
- $ratio_money = bcmul($order['pay_money'], $ratio,2);
- break;
- case RebateEnum::COMPUTING_METHOD_GOODS_PRICE:// 商品售价计算
- $ratio_money = bcmul($order['original_goods_price'], $ratio, 2);
- break;
- case RebateEnum::COMPUTING_METHOD_GOODS_PROFIT:// 商品利润计算
- //商品利润=商品支付价格-成本
- $profit_money = $order['pay_money'] - ($order['cost_price'] * $order['num']);
- $ratio_money = bcmul($profit_money, $ratio, 2);
- break;
- default:
- break;
- }
- return $ratio_money;
- }
- /**
- * 奖励判断
- * @return bool
- */
- public static function checkOrder($order_id,$settlement_type){
- // 获取订单内容
- $where = ['id' => $order_id];
- $order = Order::find()->select("id,user_id,mall_id,order_no,pay_time")
- ->where($where)
- ->with(['detail' => function($query){
- $query->select("order_id,goods_id,num,goods_price,goods_name,price,pic_url");
- }])
- ->asArray()->one();
- if(empty($order)) return true;
- $mall_id = $order['mall_id'];
- $user_id = $order['user_id'];
- // 获取推三返一基础配置内容
- $settingService = new SettingService(['mall_id' => $mall_id]);
- $config = $settingService->getSetting();
- $settlement_method = $config['settlement_method'];
- //结算状态与订单状态不一致时不判断
- if($settlement_method != $settlement_type) {
- return true;
- }
- // 获取消费者的直推上级
- $parent_id = User::find()->select('parent_id')->where(['id' => $user_id, 'mall_id' => $mall_id, 'status' => StatusEnum::ENABLED])->asArray()->scalar();
- if(empty($parent_id)) {
- return true;
- }
- // 获取推三返一的商品
- $rebate_list = Rebate::getRebateAllGoodsId($mall_id);
- if(empty($rebate_list)) return true;
- // 获取所有商品id
- $goods_arr = [];
- foreach ($rebate_list as $item) {
- $goods_arr[$item['item_id']][] = $item;
- }
- $result = true;
- foreach($order['detail'] as $order_detail) {
- // 检查该商品是否参与了推三返一活动
- if(!isset($goods_arr[$order_detail['goods_id']])) continue;
- foreach ($goods_arr[$order_detail['goods_id']] as $rebate) {
- //检查活动是否开启触发奖励设置
- if(empty($rebate['repeat_setting']) || empty($rebate['agent_limit_num'])) continue;
- //条件奖励不判断
- if($rebate['reward_type'] == RebateEnum::REWARD_TYPE_COND) continue;
- if(empty($rebate['join_type'])){
- // 判断上级是否有权限
- if($rebate['initiate_type'] == RebateEnum::INITIATE_TYPE_NEW && Rebate::checkUserHasOrder($mall_id, $parent_id) !== false) {
- continue;
- }
- if($rebate['initiate_type'] == RebateEnum::INITIATE_TYPE_LEVEL && Rebate::checkUserLevel($parent_id, $rebate['initiate_level']) == false) {
- continue;
- }
- // 判断消费者是否符合权限
- if($rebate['consume_type'] == RebateEnum::CONSUME_TYPE_NEW) {
- $order_num = Rebate::checkUserHasOrder($mall_id, $user_id);
- if (!empty($order_num) && $order_num > 1) {
- continue;
- }
- }
- if($rebate['consume_type'] == RebateEnum::CONSUME_TYPE_LEVEL && Rebate::checkUserLevel($user_id, $rebate['consume_level']) == false) {
- continue;
- }
- }else{
- // 判断上级是否有权限
- if($rebate['initiate_type'] == RebateEnum::INITIATE_TYPE_NEW && Rebate::checkNewRegisterUser($mall_id, $parent_id) == false) {
- continue;
- }
- if($rebate['initiate_type'] == RebateEnum::INITIATE_TYPE_LEVEL && Rebate::checkRebateUserLevel($parent_id, $rebate['initiate_level']) == false) {
- continue;
- }
- // 判断消费者是否符合权限
- if($rebate['consume_type'] == RebateEnum::CONSUME_TYPE_NEW && Rebate::checkNewRegisterUser($mall_id, $user_id)==false) {
- continue;
- }
- if($rebate['consume_type'] == RebateEnum::CONSUME_TYPE_LEVEL && Rebate::checkRebateUserLevel($user_id, $rebate['consume_level']) == false) {
- continue;
- }
- }
- // 奖励的内容
- $rebate_info = Json::decode($rebate['reward_info'], true);
- // 获取用户上级已有的订单数
- $recommend_num = RebateRecommendNum::find()
- ->where(['r_id'=>$rebate['id'],'user_id'=>$parent_id])
- ->select('pay_num')
- ->scalar() ?? 0;
- //获取当前订单是否已统计
- $has_buy = RebateBuy::find()->where(['r_id' => $rebate['id'], 'pid' => $parent_id, 'user_id' => $user_id, 'order_no' => $order['order_no'],'is_settlement'=>1])->one();
- if(empty($has_buy)) $recommend_num += 1;
- //触发奖励判断
- if($recommend_num % $rebate['agent_limit_num'] == 0){
- $result = false;
- }
- }
- }
- return $result;
- }
- /**
- * 创建虚拟订单
- *
- * @param $mall_id
- * @param $user_id
- * @param $rebate_id
- *
- * @return bool
- */
- public static function createVirtualOrder($mall_id, $user_id, $rebate_id)
- {
- $parent_id = User::find()->select('parent_id')->where(['id' => $user_id, 'mall_id' => $mall_id, 'status' => StatusEnum::ENABLED])->asArray()->scalar();
- if (empty($parent_id)) {
- self::$static_error = '上级用户不存在';
- return false;
- }
- $t = Yii::$app->db->beginTransaction();
- try {
- // 初始化参与活动
- $res = RebateRecommendNum::initRecommendNum($mall_id, ['r_id' => $rebate_id, 'user_id' => $parent_id]);
- if ($res === false) {
- throw new \Exception(RebateRecommendNum::getStaticError());
- }
- // 找到参与活动的商品
- $goods = Goods::findOne(['id' => Rebate::find()->where(['id' => $rebate_id])->select('item_id')->scalar()]);
- if (empty($goods)) {
- throw new \Exception('商品不存在');
- }
- $order_detail = [
- 'id' => 0,
- 'goods_price' => 0,
- 'goods_id' => $goods->id,
- 'goods_name' => $goods->goods_name,
- 'pic_url' => $goods->cover_pic,
- 'price' => $goods->price,
- ];
- // 保存消费者数据
- $rabate_buy = self::saveRebateBuy(
- $mall_id,
- $rebate_id,
- $user_id,
- $parent_id,
- ['order_no' => Order::generateOrderNo('s'), 'pay_time' => time()],
- $order_detail,
- 1,
- 1,
- 1
- );
- if ($rabate_buy === false) {
- throw new \Exception(RebateRecommendNum::getStaticError());
- }
- // 增加推荐数量
- if (RebateRecommendNum::setData($mall_id, ['r_id' => $rebate_id, 'user_id' => $parent_id, 'pay_num' => 1]) === false) {
- throw new \Exception(RebateRecommendNum::getStaticError());
- }
- // 活动统计
- if (RebateStatistics::setData($mall_id, ['r_id' => $rebate_id, 'pay_money' => 0]) === false) {
- throw new \Exception(RebateStatistics::getStaticError());
- }
- // 记录手动生成订单
- $setRebateVirtualOrderLogRes = RebateVirtualOrderLog::setData($mall_id, [
- 'user_id' => $user_id,
- 'user_parent_id' => $parent_id,
- 'rebate_id' => $rebate_id,
- 'rebate_buy_id' => $rabate_buy['id']
- ]);
- if ($setRebateVirtualOrderLogRes === false) {
- throw new \Exception(RebateVirtualOrderLog::getStaticError());
- }
- $t->commit();
- }catch (\Exception $e) {
- $t->rollBack();
- Yii::error(Json::encode([
- 'msg' => $e->getMessage(),
- 'line' => $e->getLine(),
- 'file' => $e->getFile()
- ]));
- self::$static_error = '系统错误';
- return false;
- }
- return true;
- }
- /**
- * 如果当前获取的奖励是第二项,则检查需要解冻第一项
- *
- * @param array $rebate_buy
- *
- * @return void
- */
- public static function unfrozenFirstReward(array $rebate_buy)
- {
- $rewardLog = RebateRewardLog::find()
- ->where([
- 'mall_id' => $rebate_buy['mall_id'],
- 'r_id' => $rebate_buy['r_id'],
- 'user_id' => $rebate_buy['pid'],
- 'is_frozen' => RebateEnum::FROZEN,
- 'status' => StatusEnum::ENABLED,
- ])
- ->one();
- if (empty($rewardLog)) {
- return;
- }
- $rebateBuy = RebateBuy::find()
- ->where([
- 'reward_id' => $rewardLog->id,
- 'status' => StatusEnum::ENABLED,
- 'mall_id' => $rebate_buy['mall_id'],
- ])
- ->select('reward_id, order_no, order_detail_id')
- ->asArray()
- ->one();
- if (empty($rebateBuy)) {
- return;
- }
-
- // 循环需要解冻的类型
- $setting = json_decode($rewardLog->setting, true);
- if (isset($setting['reward_key'], $setting['reward_info'][$setting['reward_key']])) {
- // 查询订单
- $orderId = Order::find()
- ->where([
- 'order_no' => $rebateBuy['order_no'],
- 'mall_id' => $rewardLog->mall_id,
- 'status' => StatusEnum::ENABLED
- ])
- ->select('id')
- ->scalar();
- $orderInfo = OrderDetail::find()
- ->where(['mall_id' => $rewardLog->mall_id, 'status' => StatusEnum::ENABLED, 'id' => $rebateBuy['order_detail_id']])
- ->select('id, order_id, goods_price as pay_money, original_goods_price, cost_price, num')
- ->asArray()
- ->one();
- //判断是否安装红包拓客插件
- $has_redpack = MallAddons::isInstall($rewardLog->mall_id, AddonsEnum::ADDONS_NAME_REDPACK);
-
- foreach ($setting['reward_info'][$setting['reward_key']]['data'] as $item) {
- switch ($item['type']) {
- case RebateEnum::REWARD_SCORE:
- case RebateEnum::REWARD_BALANCE:
- case RebateEnum::REWARD_COMMISSION:
- $wallet_type = $item['type'];
- CapitalLog::$capitalType = "{$wallet_type}_frozen";
- $commission_list = CapitalLog::lists([
- 'where' => [
- [
- 'or',
- ['source_table' => Order::tableName(), 'source_table_id' => $orderId],
- ['source_table' => OrderDetail::tableName(), 'source_table_id' => $rebateBuy['order_detail_id']],
- ],
- ['from_type' => AddonsEnum::ADDONS_NAME_REBATE],
- ['capital_type' => UserWalletEnum::GIVE],
- ['status' => CapitalLog::STATUS_WAIT_SEND]
- ]
- ]);
- foreach ($commission_list as $commission) {
- UserWalletService::unfrozen($commission['id'], $item['type']);
- }
- break;
- case RebateEnum::REWARD_COUPON:
- foreach ($item['data'] as $coupon) {
- $give_coupon_arr[$coupon['relevant_id']] = $coupon['num'];
- }
- if (empty($give_coupon_arr)) {
- break;
- }
- AddonsCouponUserRelate::giveCoupon($rewardLog->mall_id, $rewardLog->user_id, $give_coupon_arr, AddonsCouponEnum::SEND_FROM14);
- break;
- case RebateEnum::REWARD_REDPACK://激活红包
- case RebateEnum::REWARD_FROZEN_REDPACK:
- //未安装红包拓客插件,则跳出
- if (!$has_redpack) break;
- if ($item['ratio']) {
- $item['data'] = self::getPercentage($rewardLog->mall_id, $orderInfo, $item);
- }
- // 当赠送金额小于等于0,不赠送
- if ($item['data'] <= 0) break;
- ['frozen_money' => $frozen_money] = self::computeRewardMoney(
- true,
- $item['data'],
- $setting['freeze_first_reward_type'] ?? RebateEnum::FREEZE_FIRST_REWARD_TYPE_ALL,
- $setting['freeze_first_reward_percentage'] ?? 0
- );
- if ($frozen_money <= 0) {
- break;
- }
- $redpack_data = [
- 'mall_id' => $rewardLog->mall_id,
- 'user_id' => $rewardLog->user_id,
- 'is_frozen' => false,
- 'money' => $frozen_money,
- 'desc' => '订单('.$orderInfo['order_id'].')推三返一赠送红包',
- 'source_table' => OrderDetail::tableName(),
- 'source_table_id' => $orderInfo['id'],
- 'from_type' => \addons\Redpack\common\enums\RedpackEnum::FROM_REBATE_REWARD,
- ];
- if ($item['type'] == 'frozen_redpack') {
- $redpack_data['is_frozen'] = true;
- }
- $res = \addons\Redpack\common\models\RedpackWallet::setData($redpack_data);
- if (!$res) throw new Exception(\addons\Redpack\common\models\RedpackWallet::$static_error);
- break;
- }
- }
- }
- $rewardLog->is_frozen = RebateEnum::UNFREEZE;
- $rewardLog->save();
- }
- public static function unfrozenFirstReward2Queue(array $unfozenRebateBuys)
- {
- foreach ($unfozenRebateBuys as $unfozenRebateBuy) {
- Yii::$app->services->rabbitMq->push(
- RabbitMqEnum::EXCHANGE_TASK_USER_WALLET,
- RabbitMqEnum::USER_WALLET_QUEUE,
- $unfozenRebateBuy,
- self::class,
- 'unfrozenFirstReward'
- );
- }
- }
- }
|