services->setting->addons->get($mallId, 'BossWeight', 'basic'); if ($config['is_enable'] == StatusEnum::ENABLED) { $continue = false; // 获取结算周期,0=天,1=周,2=月 $compute_period = $config['compute_period']; switch ($config['compute_period']) { case 1: $start_day = date("Ymd", strtotime("-1 day")); $end_day = $start_day; break; case 2: if (date('w') != 1) $continue = true;// 非周一直接退出 $start_day = date("Ymd", strtotime("last Monday")); $end_day = date('Ymd', strtotime('-1 sunday', time()));; break; case 3: if (date('d') != 1) $continue = true;// 非当月1号直接退出 $start_day = date("Ym01", strtotime("-1 month")); $end_day = date('Ymd', strtotime(date('Y-m', time()) . '-01 00:00:00') - 86400); break; } if ($continue) continue; $date_limit = $start_day . '-' . $end_day; $job = AddonsBossCommissionJob::findOne(['mall_id' => $mallId, 'compute_period' => $compute_period, 'date_limit' => $date_limit, 'status' => StatusEnum::ENABLED]); if ($job) continue; // 生成执行记录 $job = new AddonsBossCommissionJob(); $job->mall_id = $mallId; $job->date_limit = $date_limit; $job->compute_period = $compute_period; if (!$job->save()) throw new Exception($job->getErrorMessage()); $trans = Yii::$app->db->beginTransaction(); try { $res = $this->addCommissionLog($mallId, $config, $start_day, $end_day); if($res === false) throw new Exception($this->getError()); $trans->commit(); } catch (Exception $e) { $trans->rollBack(); } } } return true; } } /** * 增加boss分红佣金 * @Author: lun * @DateTime: 2021/11/5 0005 14:27 * @Copyright: copyright (c) 2021 广东七件事集团 * @param $mallId * @param $config * @param $start_day * @param $end_time * @return bool */ private function addCommissionLog($mallId, $config, $start_day, $end_day) { if ($config['is_enable'] == StatusEnum::DISABLED) { Yii::error('系统没有开启股东提成'); return true; } try { // 初始化数据 $time = time(); $table_name = AddonsBossCommissionLog::tableName(); // 获取所有股东列表 $boss_list = AddonsBoss::find()->where(['mall_id' => $mallId, 'status' => StatusEnum::ENABLED])->asArray()->all(); if (empty($boss_list)) return true; foreach ($boss_list as $k => $boss){ /** @var AddonsBossPrice $bossPrice */ $bossPrice = AddonsBossPrice::find()->where([ 'user_id' => $boss['user_id'], 'level' => $boss['level'] ])->one(); if($bossPrice){ /** @var AddonsBossLevelSetting $levelSetting */ $levelSetting = AddonsBossLevelSetting::find()->where([ 'status' => 1, 'mall_id'=> $boss['mall_id'], 'level' => $boss['level'] ])->one(); //如果boss用户的分红金额达到设置的上限金额。就从数组移除,不再往下处理 //如果开启了权重限制并且boss用户权重状态不为0。就从数组移除,不再往下处理 if($levelSetting->weight_max_price && $bossPrice->price > $levelSetting->weight_max_price){ if($levelSetting->weight_is_limit == 0 || ($levelSetting->weight_is_limit == 1 && $boss['boss_weight_status'])){ unset($boss_list[$k]); } } } } $boss_arr = array_column($boss_list,'user_id'); //修改加权分红获取方式 $rows = $this->weightCommission($boss_list,$config,$start_day,$end_day,$mallId); Yii::error("addCommissionLog rows=".var_export($rows,true)); unset($boss_list); // 获取分红奖励列表 //查询已取消的订单 $cancel_order_ids = AddonsBossRewardLog::find() ->alias('brl') ->innerJoin(Order::tableName() . ' as o', 'o.id = brl.order_id') ->where(['brl.mall_id' => $mallId, 'brl.is_settlement' => StatusEnum::DISABLED, 'brl.status' => StatusEnum::ENABLED,'o.order_status'=>OrderStatusEnum::REPEAL]) ->andFilterWhere(['between', 'brl.date', $start_day, $end_day]) ->select('brl.order_id') ->column(); $reward_list = AddonsBossRewardLog::find() ->select('user_id,sum(amounts) amounts,sum(commission) commission,sum(order_price) order_price,sum(settle_price) settle_price,type') ->where(['mall_id' => $mallId, 'is_settlement' => StatusEnum::DISABLED, 'status' => StatusEnum::ENABLED]) ->andWhere(['not in', 'order_id', $cancel_order_ids]) ->andFilterWhere(['between', 'date', $start_day, $end_day]) ->groupBy('user_id,type') ->asArray() ->all(); if($reward_list){ // 生成计算好的结算数据 foreach ($reward_list as $item) { if (in_array($item['user_id'], $boss_arr)) { $rows[] = [ 'mall_id' => $mallId, 'user_id' => $item['user_id'], 'order_price' => $item['order_price'], 'settle_price' => $item['settle_price'], 'amounts' => $item['amounts'], 'commission' => $item['commission'], 'type' => $item['type'], 'compute_period' => $config['compute_period'], 'start_time' => $start_day, 'end_time' => $end_day, 'created_at' => $time, 'updated_at' => $time, 'settlement_config' => $item['settlement_config'] ? $item['settlement_config'] : '', ]; } } } if($cancel_order_ids){ AddonsBossRewardLog::updateAll( ['status' => StatusEnum::DELETE, 'updated_at' => $time], ['and', ['mall_id' => $mallId, 'status' => StatusEnum::ENABLED],['in', 'order_id', $cancel_order_ids]] ); } if (empty($rows)) return true; unset($reward_list); // 生成数据 $field = ['mall_id','user_id','order_price','settle_price','amounts','commission','type','compute_period','start_time','end_time','created_at','updated_at','settlement_config']; Yii::$app->db->createCommand()->batchInsert($table_name, $field, $rows)->execute(); unset($rows); // 数据生成完成记录表修改结算状态 AddonsBossRewardLog::updateAll( ['is_settlement' => StatusEnum::ENABLED, 'updated_at' => $time], ['and', ['mall_id' => $mallId, 'is_settlement' => StatusEnum::DISABLED],['between', 'date', $start_day, $end_day],['not in', 'order_id', $cancel_order_ids]] ); // 增加对应股东分佣金额 $log_list = AddonsBossCommissionLog::getBossCommissionLog([['mall_id' => $mallId,'start_time' => $start_day,'end_time' => $end_day]]); $boss_commission = []; foreach ($log_list as $item) { switch ($item['type']){ case 1: $capital_type = UserWalletEnum::FOREVER; break; case 4: $class = new \ReflectionClass(UserWalletEnum::class); $var = "BOSS_WIGHT"; if($class->hasConstant($var)){ $capital_type= $class->getConstant($var); }else{ $capital_type = 'boss_weight'; } break; default: $capital_type = UserWalletEnum::BO_EXTRA; break; } $insert_wallet[] = [ 'mall_id' => $mallId, 'user_id' => $item['user_id'], 'is_frozen' => false, 'wallet_type' => 'commission', 'money' => $item['commission'], 'desc' => '加权分红佣金', 'source_table' => $table_name, 'source_table_id' => $item['id'], 'from_type' => BossEnum::ADDONS_NAME, 'capital_type' => $capital_type, ]; if ($item['type'] == 1 || $item['type'] == 4) { $boss_commission[$item['user_id']]['commission'] += $item['commission']; } else { $boss_commission[$item['user_id']]['extra_commission'] += $item['commission']; } } if ($insert_wallet) { $res = UserWalletService::batchHandleByQueue($insert_wallet); if (empty($res)) throw new \Exception(UserWalletService::getStaticError()); } unset($insert_wallet); // 增加用户股东金额 foreach ($boss_commission as $user_id => $commission) { $boss = AddonsBoss::findOne(['mall_id' => $mallId, 'user_id' => $user_id, 'status' => StatusEnum::ENABLED]); if(!$boss) continue; $boss->commission = empty($commission['commission']) ? $boss->commission : $boss->commission + $commission['commission']; $boss->extra_commission = empty($commission['extra_commission']) ? $boss->extra_commission : $boss->extra_commission + $commission['extra_commission']; $boss->total_commission = $boss->commission + $boss->extra_commission; if (!$boss->save()) throw new \Exception($boss->getErrorMessage()); //更新用户股东分红总金额。 /** @var AddonsBossPrice $bossPrice */ //增加金额为0则不执行 $bossPricePrice = $commission['commission'] ? $commission['commission']:0; if($bossPricePrice){ $bossPrice = AddonsBossPrice::find()->where([ 'user_id' => $boss['user_id'], 'level' => $boss['level'] ])->one(); if(!$bossPrice){ $bossPrice = new AddonsBossPrice(); $bossPrice->user_id = $boss->user_id; $bossPrice->level = $boss->level; } $bossPrice->price += $bossPricePrice; if (!$bossPrice->save()) throw new \Exception($bossPrice->getErrorMessage()); } } return true; } catch (Exception $e) { $exception = FormatHelper::exception($e, "mall_id={$mallId} 股东定时分红任务失败"); echo $exception; Yii::error($exception); $this->setError($exception); return false; } } /** * 加权分红 * @param AddonsBoss[] $bossList */ private function weightCommission(array $bossList,array $config, string $start_day, string $end_day,$mall_id){ if($bossList){ $where = [ 'and', ['mall_id' => $mall_id], ['status' => StatusEnum::ENABLED], ['store_id' => 0], ['mch_id' => 0] ]; //查询已结算的订单 $reward_order_ids = AddonsBossRewardOrderLog::find() ->where(['mall_id' => $mall_id]) ->andWhere(['status' => StatusEnum::ENABLED]) ->andWhere([ 'and', ['>=', 'created_at', strtotime($start_day)], ['<=', 'created_at', strtotime("$end_day 23:59:59")] ]) ->select('order_id') ->column(); if (!empty($reward_order_ids)) {//过滤已结算的订单 $where[] = ['not in', 'id', $reward_order_ids]; } // 判断结算方式,0=支付完成,1=订单完成 if ($config['settlement_method'] == 0) { $where[] = ['pay_status' => OrderStatusEnum::PAY]; $where[] = ['not in', 'order_status', [OrderStatusEnum::REPEAL]]; $where[] = [ 'and', ['>=', 'pay_time', strtotime($start_day)], ['<=', 'pay_time', strtotime("$end_day 23:59:59")] ]; } else { $where[] = ['order_status' => OrderStatusEnum::ACCOMPLISH]; $where[] = [ 'and', ['>=', 'finish_time', strtotime($start_day)], ['<=', 'finish_time', strtotime("$end_day 23:59:59")] ]; } $order_list = Order::find()->where($where)->all(); if(!$order_list){ return []; } $time = time(); $reward_log = []; //判断结算方式 if($config['compute_type'] == 1){//计算订单利润 $order_ids = array_column($order_list,'id'); //读取商城营业额 $order_profit = OrderDetail::find() ->select([ 'order_id', 'total_sum' => 'SUM(cost_price*num + adjust_money)' ]) ->where(['order_id' => $order_ids]) ->groupBy('order_id') ->indexBy('order_id') ->asArray() ->all(); } $totalTurnover = 0;//订单计算总金额 $order_price = 0;//订单总金额 //记录订单结算记录 foreach ($order_list as $order){ if($config['compute_type'] == 1){//利润 $amounts = ($order['goods_price'] - $order_profit[$order['id']]['total_sum']); }elseif ($config['compute_type'] == 2){//售价 $amounts = $order['original_goods_price']; }else{ $amounts = $order['goods_price']; } $reward_log[] = [ 'mall_id' => $mall_id, 'order_id' => $order['id'], 'order_no' => $order['order_no'], 'order_price' => $order['goods_price'], 'amounts' => $amounts, 'settlement_method' => $config['settlement_method'], 'date' => $end_day, 'created_at' => $time, 'updated_at' => $time, ]; $totalTurnover += $amounts; $order_price += $order['goods_price']; } $trans = Yii::$app->db->beginTransaction(); try { // 生成订单结算记录 $field = ['mall_id','order_id','order_no','order_price','amounts','settlement_method','date','created_at','updated_at']; Yii::$app->db->createCommand()->batchInsert(AddonsBossRewardOrderLog::tableName(), $field, $reward_log)->execute(); $trans->commit(); } catch (Exception $e) { $trans->rollBack(); $this->setError($e->getMessage()); return false; } $rows = []; $level_list = array_unique(array_column($bossList,'level')); $totalWeight_list = []; foreach($level_list as $level){ $totalWeight_list[$level] = self::getLevelWeight($mall_id,$level); } $levelSetting_list = AddonsBossLevelSetting::find()->where([ 'status' => 1, 'mall_id'=> $mall_id, 'level' => $level_list ])->indexBy('level')->asArray()->all(); foreach ($bossList as $boss){ Yii::error("weightCommission boss=".var_export($boss,true)); /** @var AddonsBossLevelSetting $levelSetting */ $levelSetting = $levelSetting_list[$boss['level']]; if(!$levelSetting || !$levelSetting['weight_turnover_ratio'] || !$levelSetting['weight_level_ratio']){ continue ; } $levelPrice = bcdiv($totalTurnover * intval($levelSetting['weight_turnover_ratio']) * intval($levelSetting['weight_level_ratio']),10000,2); Yii::error("weightCommission levelPrice=".$levelPrice); $userWeight = self::getBossWeight($boss); Yii::error("weightCommission userWeight=".$userWeight); $totalWeight = $totalWeight_list[$boss['level']]; Yii::error("weightCommission totalWeight=".$totalWeight); $commission = 0; if($totalWeight > 0){ $commission = bcdiv($totalTurnover*intval($levelSetting['weight_turnover_ratio'])*intval($levelSetting['weight_level_ratio'])/10000 *$userWeight,$totalWeight,2); } Yii::error("weightCommission commissin=".$commission); if($commission){ $settlement_config = [ 'settlement_method' => $config['settlement_method'], 'compute_type' => $config['compute_type'], 'weight_turnover_ratio' => $levelSetting['weight_turnover_ratio'], 'weight_level_ratio' => $levelSetting['weight_level_ratio'], 'total_weight' => $totalWeight, 'user_weight' => $userWeight, 'level' => $boss['level'], ]; $rows[] = [ 'mall_id' => $boss['mall_id'], 'user_id' => $boss['user_id'], 'order_price' => $order_price,//订单总支付金额 'settle_price' => $levelPrice,//总结算金额 'amounts' => $totalTurnover,//订单总计算金额 'commission' => $commission, 'type' => 4,//加权分红 'compute_period' => $config['compute_period'], 'start_time' => $start_day, 'end_time' => $end_day, 'created_at' => time(), 'updated_at' => $time, 'settlement_config' => Json::encode($settlement_config), ]; } } return $rows; } } //获取boss权重分红的份额数量 public static function getBossWeight(array $boss):int{ /** @var AddonsBossLevelSetting $levelSetting */ $levelSetting = AddonsBossLevelSetting::find()->where([ 'status' => 1, 'mall_id'=> $boss['mall_id'], 'level' => $boss['level'] ])->one(); if(!$levelSetting) return 0; if(!$levelSetting->weight_status) return 0; // if(!$levelSetting->weight_member_num) return 0; // if(!$levelSetting->weight_num) return 0; //开启权重限制且股东权重状态不为0,则该股东权重为0 if($levelSetting->weight_is_limit == 1 && $boss['boss_weight_status']) return 0; //权重数量 $BossWeight = 0; $userChilds =UserPartitionRelationship::getChildIdArr($boss['user_id'],1); $userChildsSecond = $userChilds; if($levelSetting->weight_product_num > 0){ foreach ($userChilds as $k=>&$child){ /** @var OrderDetail[] $orderDetails */ $orderDetails = OrderDetail::find()->with('order')->where([ 'status' => 1, 'user_id' => $child ])->andWhere(['>','order_status',0])->all(); //删除不满足条件的下级 if(!$orderDetails){ unset($userChilds[$k]); continue ; } $total_goods_num = 0;//任意商品总数量 foreach ($orderDetails as $detail){ $total_goods_num += $detail->num; } //删除不满足条件的下级 if($total_goods_num < $levelSetting->weight_product_num){ unset($userChilds[$k]); } } } if(!$levelSetting->weight_member_num || !$levelSetting->weight_num){ $BossWeight = 0; }else{ $BossWeight = floor( count($userChilds) / intval($levelSetting->weight_member_num) ) * intval($levelSetting->weight_num); } if($levelSetting->weight_member_num_second > 0){ $level_num = User::find()->where(['id'=>$userChildsSecond,'level'=>$levelSetting->weight_member_level_second,'status'=>1])->count(); $BossWeight += intval($level_num / $levelSetting->weight_member_num_second) * $levelSetting->weight_num_second; } if($levelSetting->weight_member_num_team > 0){ //获取直推用户id $direct_child_ids = UserPartitionRelationship::getChildIdArr($boss['user_id'], 1); if (!empty($direct_child_ids)) { //获取哪些市场超过指定业绩 $where = [ 'and', ['user_id' => $direct_child_ids], ['>','team_order_pay_achievement',$levelSetting->weight_member_num_team * 10000], ]; $count = UserTeamProfitStatistics::find()->where($where)->count(); if($count>0){ $BossWeight += $count * $levelSetting->weight_num_team; } } } //权重数量 = 固定权重 + 条件权重 $BossWeight += $boss['fixed_weight']; if($BossWeight < 0) $BossWeight = 0; return $BossWeight; } //获取平台权重总份额 public static function getTotalWeight(int $mallId){ /** @var AddonsBoss[] $boss_list */ $boss_list = AddonsBoss::find()->where(['mall_id' => $mallId, 'status' => StatusEnum::ENABLED])->asArray()->all(); if(!$boss_list) return 0; $total_weight_num = 0; foreach ($boss_list as $boss){ $total_weight_num += self::getBossWeight($boss); } return $total_weight_num; } //获取指定等级权重总份额 public static function getLevelWeight(int $mallId,int $level){ /** @var AddonsBoss[] $boss_list */ $boss_list = AddonsBoss::find() ->where(['mall_id' => $mallId,'level'=>$level, 'status' => StatusEnum::ENABLED]) ->asArray()->all(); if(!$boss_list) return 0; $total_weight_num = 0; foreach ($boss_list as $boss){ $total_weight_num += self::getBossWeight($boss); } return $total_weight_num; } //获取boss权重分红的份额数量(不包含股东失效情况) public static function getBossWeightOutStatus(array $boss):int{ /** @var AddonsBossLevelSetting $levelSetting */ $levelSetting = AddonsBossLevelSetting::find()->where([ 'status' => 1, 'mall_id'=> $boss['mall_id'], 'level' => $boss['level'] ])->one(); if(!$levelSetting) return 0; if(!$levelSetting->weight_status) return 0; // if(!$levelSetting->weight_member_num) return 0; // if(!$levelSetting->weight_num) return 0; //权重数量 $BossWeight = 0; $userChilds =UserPartitionRelationship::getChildIdArr($boss['user_id'],1); $userChildsSecond = $userChilds; if($levelSetting->weight_product_num > 0){ foreach ($userChilds as $k=>&$child){ /** @var OrderDetail[] $orderDetails */ $orderDetails = OrderDetail::find()->with('order')->where([ 'status' => 1, 'user_id' => $child ])->andWhere(['>','order_status',0])->all(); //删除不满足条件的下级 if(!$orderDetails){ unset($userChilds[$k]); continue ; } $total_goods_num = 0;//任意商品总数量 foreach ($orderDetails as $detail){ $total_goods_num += $detail->num; } //删除不满足条件的下级 if($total_goods_num < $levelSetting->weight_product_num){ unset($userChilds[$k]); } } } if(!$levelSetting->weight_member_num || !$levelSetting->weight_num){ $BossWeight = 0; }else{ $BossWeight = floor( count($userChilds) / intval($levelSetting->weight_member_num) ) * intval($levelSetting->weight_num); } if($levelSetting->weight_member_num_second > 0){ $level_num = User::find()->where(['id'=>$userChildsSecond,'level'=>$levelSetting->weight_member_level_second,'status'=>1])->count(); $BossWeight += intval($level_num / $levelSetting->weight_member_num_second) * $levelSetting->weight_num_second; } //权重数量 = 固定权重 + 条件权重 $BossWeight += $boss['fixed_weight']; if($BossWeight < 0) $BossWeight = 0; return $BossWeight; } public static function getComputeTime($mallId){ $config = Yii::$app->services->setting->addons->get($mallId, 'BossWeight', 'basic'); $start_day = 0; $end_day = 0; if ($config['is_enable'] == StatusEnum::ENABLED) { // 获取结算周期,0=天,1=周,2=月 $compute_period = $config['compute_period']; switch ($config['compute_period']) { case 1: $start_day = date("Ymd", time()); $end_day = $start_day; break; case 2: if (date('w') != 1){ $start_day = date("Ymd", strtotime("last Monday")); }else{ $start_day = date("Ymd", time()); } $end_day = date('Ymd', strtotime('-6 day', strtotime($start_day))); break; case 3: $start_day = date("Ym01", time()); $end_day = date('Ymt',time()); break; } } return [strtotime($start_day),strtotime($end_day)]; } }