$mall_id, 'status' => [StatusEnum::ENABLED,StatusEnum::DISABLED], ]; $today = DateHelper::today(); switch ($config['settle_circle']) { case 1: //结算周期为周 $this_week = DateHelper::thisWeek(); if (date("Ymd", $this_week['start']) != date("Ymd", $today['start'])) throw new \Exception('非每周第一天,终止结算'); //正式代码 $last_week = DateHelper::lastWeek(); $date_time = date('Ymd', $last_week['end']); break; case 2://结算周期为月 $this_month = DateHelper::thisMonth(); if (date("Ymd", $this_month['start']) != date("Ymd", $today['start'])) throw new \Exception('非每月第一天,终止结算'); $last_month = DateHelper::lastMonth(); $date_time = date('Ymd', $last_month['end']); break; case 3://结算周期为天 $last_day = DateHelper::yesterDay(); $date_time = date('Ymd', $last_day['start']); break; default: throw new \Exception('非有效结算周期'); break; } //测试代码 // $date_time = date('Ymd', time()); // $where['date_time'] = $date_time; //获取最新结算的一期 $check_score_bonus_data = ScoreBonusModel::getDataOne($where, 'id desc'); //检查本次结算是否已结算 if (!empty($check_score_bonus_data) && $check_score_bonus_data['date_time'] == $date_time) throw new \Exception("该周期已结算"); // print_r($check_score_bonus_data);exit; //开始结算分红 //获取未结算资金池 //获取分红池数据 $capital = ScoreBonusCapitalPool::getOne([ ['mall_id' => $mall_id] ]); // $where['status'] = StatusEnum::DISABLED; // $capital_pool = ScoreBonusCapitalModel::getFieldSum($where, 'bonus_price'); $capital_pool = $capital->bonus_price; if ($config['settle_method']) { //新模式 权重占比分配 //平台符合条件用户的总权重 $all_user_weight = ScoreBonusUserWeight::find() ->alias('w') ->joinWith(['userWallet uw' => function($query) { $query->andWhere(['>', 'uw.score', 0]); }]) ->where(['w.status' => 1, 'w.mall_id' => $mall_id]) ->andWhere(['>', 'weight', 0]) ->sum('weight'); //平台符合条件用户的总积分 $all_user_score = ScoreBonusUserWeight::find() ->alias('w') ->joinWith(['userWallet uw' => function($query) { $query->andWhere(['>', 'uw.score', 0]); }]) ->where(['w.status' => 1, 'w.mall_id' => $mall_id]) ->andWhere(['>', 'weight', 0]) ->sum('uw.score'); //平台符合条件的用户 $all_user_score_arr = ScoreBonusUserWeight::find() ->alias('w') ->joinWith(['userWallet uw' => function($query) { $query->andWhere(['>', 'uw.score', 0]); }]) ->where(['w.status' => 1, 'w.mall_id' => $mall_id]) ->andWhere(['>', 'weight', 0]) ->asArray() ->all(); } else { //原模式 积分占比分配 // 因为之前查询条件放在下面导致用户查询没有 到达积分条件限制。所以移动到此处 $where = ['and', ['mall_id' => $mall_id], ['status' => StatusEnum::ENABLED], ['>=', 'score', $config['user_score']]]; //平台符合条件的用户数据 $all_user_score_arr = UserWallet::find()->where($where)->andWhere(['>','score',0])->asArray()->all(); //平台符合条件用户的总积分 $all_user_score = UserWallet::find()->where($where)->sum('score'); } $all_user_score_num = count($all_user_score_arr); $i = 0; //插入钱包数据 $insert_wallet = []; $settle_circle = ScoreBonusEnums::getSettleCircleMap(); //写入当期结算数据写入结算周期表 $settle_circle_data = [ //当期结算的数据 'mall_id' => $mall_id, 'bonus_circle' => $config['settle_circle'], 'status' => StatusEnum::DISABLED, 'num' => $check_score_bonus_data['num'] ? $check_score_bonus_data['num'] +1 : 1, 'bonus_price' => $capital_pool, //资金分红池总额 'bonus_num' => $all_user_score_num, //参与分红人数 'settle_price' => round($capital_pool, 2),//当期结算总金额 'total_score' => $all_user_score, //周期总积分 'date_time' => $date_time, 'settle_method' => $config['settle_method'] ?? 0, // 设置没有保存是配置默认为积分占比 'total_weight' => $all_user_weight ?? 0, ]; if ($settle_circle_data['num'] < 10) { $settle_circle_data['num_text'] = $settle_circle_data['date_time'].'0'.$settle_circle_data['num'].'期'; } else { $settle_circle_data['num_text'] = $settle_circle_data['date_time'].$settle_circle_data['num'].'期'; } $res = ScoreBonusModel::setData($settle_circle_data); if (!$res) throw new \Exception($settle_circle_data['num_text'] . '写入结算周期数据失败' . ScoreBonusModel::$static_error); if ($capital_pool <= 0) throw new \Exception($settle_circle_data['num_text'] . '资金池为空'); $bid = $res->id; $error_log = [ 'mall_id' => $mall_id, 'bid' => $bid, 'date_time' => $date_time, ]; // $trans = Yii::$app->db->beginTransaction(); if (count($all_user_score_arr) == 0) throw new \Exception($settle_circle_data['num_text'] . '参与活动总人数为0,终止结算'); $bonus_price = 0; //获取资产积分自定义名称 $mall_config = Yii::$app->services->setting->mall->get($mall_id, 'score'); $custom_score_name = !empty($mall_config['score_name']) ? $mall_config['score_name'] . '分红' : '积分分红'; //处理用户数据 while (!empty($all_user_score_arr[$i])) { if ($config['settle_method']) { //新模式 权重占比分配 $commission = $capital_pool / $all_user_weight * $all_user_score_arr[$i]['weight']; $reward_log_data_score = $all_user_score_arr[$i]['userWallet']['score']; $all_user_score_arr[$i]['score'] = $all_user_score_arr[$i]['userWallet']['score']; $desc_text = '权重分红('; } else { //原模式 积分占比分配 $commission = ($all_user_score_arr[$i]['score'] / $all_user_score) * $capital_pool; $reward_log_data_score = $all_user_score_arr[$i]['score']; $desc_text = $custom_score_name.'('; } if (empty($config['is_all_reward']) || $config['is_all_reward'] == 1) { if ($commission < 0.01) $commission = 0.01; } else { if ($commission < 0.01) { $settle_circle_data['bonus_num'] -= 1; continue; } if ($commission >= $all_user_score_arr[$i]['score']) $commission = $all_user_score_arr[$i]['score']; } $commission = round($commission, 2); $bonus_price += $commission; $reward_log_data = [ 'mall_id' => $mall_id, 'user_id' => $all_user_score_arr[$i]['user_id'], 'bid' => $bid, 'amounts' => $capital_pool, 'total_score' => $all_user_score, //周期总积分 'score' => $reward_log_data_score, 'weight' => $all_user_score_arr[$i]['weight'] ?? 0, 'commission' => $commission , 'status' => StatusEnum::ENABLED, 'bonus_circle' => $config['settle_circle'], 'date_time' => $date_time, ]; if ($reward_log_data['commission'] >= 0) { $reward_log_data['change_type'] = 'add'; } else { $reward_log_data['change_type'] = 'sub'; } $result = ScoreBonusRewardLogModel::setData($reward_log_data); if (!$result) { $error_log['json_data'] = json_encode($reward_log_data); $error_log['error_log'] = "写入用户结算数据失败"; ScoreBonusErrorLogModel::setData($error_log); continue; }; //处理写入用户钱包数据 $insert_wallet[] = [ 'mall_id' => $mall_id, 'user_id' => $all_user_score_arr[$i]['user_id'], 'is_frozen' => false, 'wallet_type' => 'commission', 'money' => $commission, //分红金额 'desc' => $custom_score_name . '('.$settle_circle[$config['settle_circle']].')', 'source_table' => ScoreBonusModel::tableName(), 'source_table_id' => $bid,//结算周期id 'from_type' => UserWalletEnum::FROM_SCORE_BONUS, 'capital_type' => UserWalletEnum::BOUNS, ]; $score = $commission; if($all_user_score_arr[$i]['score'] < $commission){ $score = $all_user_score_arr[$i]['score']; } $insert_wallet[] = [ 'mall_id' => $mall_id, 'user_id' => $all_user_score_arr[$i]['user_id'], 'is_frozen' => false, 'wallet_type' => 'score', 'money' => -$score, //分红金额 'desc' => $desc_text.$settle_circle[$config['settle_circle']].')', 'source_table' => ScoreBonusModel::tableName(), 'source_table_id' => $bid,//结算周期id 'from_type' => UserWalletEnum::FROM_SCORE_BONUS, 'capital_type' => UserWalletEnum::BOUNS, 'not_add_total' => true, ]; //钱包数据不为空,请求异步修改用户钱包数据 if ($i % 100 == 0 && $i > 0) { //每100条用户数据推送一次 if (!empty($insert_wallet)) { $res = UserWalletService::batchHandleByQueue($insert_wallet); if (empty($res)) { $error_log['json_data'] = json_encode($insert_wallet); $error_log['error_log'] = '推送mq队列:' . UserWalletService::getStaticError(); ScoreBonusErrorLogModel::setData($error_log); } $insert_wallet = []; } } //更新用户的累计收入 $user_weight_info = ScoreBonusUserWeight::setCreateData([ 'mall_id' => $mall_id, 'user_id' => $all_user_score_arr[$i]['user_id'] ]); $user_weight_info->total_income += $commission; if (!$user_weight_info->save()) { $error_log['json_data'] = json_encode(['score_bonus_user_weight' => $user_weight_info]); $error_log['error_log'] = "修改积分分红用户权重数据失败"; ScoreBonusErrorLogModel::setData($error_log); } $i++; } //检测是否还有用户数据未推送至钱包 if (!empty($insert_wallet)) { $res = UserWalletService::batchHandleByQueue($insert_wallet); if (empty($res)) { $error_log['json_data'] = json_encode($insert_wallet); $error_log['error_log'] = '推送mq队列:' . UserWalletService::getStaticError(); ScoreBonusErrorLogModel::setData($error_log); } $insert_wallet = []; } //处理资金池内数据 // $capital_res = ScoreBonusCapitalModel::updateAll(['status' => StatusEnum::ENABLED], ['and', ['mall_id' => $mall_id], ['status' => StatusEnum::DISABLED], ['<=' ,'date_time', $date_time]]); if ($capital->bonus_price < $bonus_price) { $capital->total_price += $capital->bonus_price; $capital->bonus_price = 0; } else { $capital->total_price += $bonus_price; $capital->bonus_price = bcsub($capital->bonus_price, $bonus_price, 2); } if (!$capital->save()) { $error_log['json_data'] = json_encode(['bonus_price' => $bonus_price]); $error_log['error_log'] = "修改资金池数据失败"; ScoreBonusErrorLogModel::setData($error_log); } //更新结算周期数据为已结算 并更新结算金额 $res = ScoreBonusModel::updateAll(['status' => StatusEnum::ENABLED, 'settle_price' => $bonus_price], ['mall_id' => $mall_id, 'id' => $bid]); if (!$res) { $error_log['json_data'] = json_encode(['update_data' => ['status' => StatusEnum::ENABLED], 'where' => ['mall_id' => $mall_id, 'id' => $bid]]); $error_log['error_log'] = "更新结算周期数据失败"; ScoreBonusErrorLogModel::setData($error_log); }; // $trans->commit(); return true; } catch (\Exception $e) { $error_log = [ 'mall_id' => $mall_id, 'bid' => 0, 'date_time' => $date_time, 'error_log' => '商城:'.$mall_id.', scoreBonusSettle err:'.$e->getMessage(), 'json_data' => '', ]; ScoreBonusErrorLogModel::setData($error_log); // $trans->rollBack(); $exception = FormatHelper::exception($e,'商城:'.$mall_id.', scoreBonusSettle err:'.$e->getMessage()); Yii::error($exception); return false; } } //迁移文件-累计分红池金额 public function total_capital_pool($mall_id) { try { $config = Yii::$app->services->setting->addons->get($mall_id, ScoreBonusEnums::ADDONS_NAME, 'basic',true); $is_enable = $config['is_enable'] ?? StatusEnum::DISABLED; if(!$is_enable) return true; $capital_pool = ScoreBonusCapitalPool::getOne([ ['mall_id' => $mall_id], ]); //初始化分红池 if (empty($capital_pool)) { $capital_pool = new ScoreBonusCapitalPool(); $capital_pool->loadDefaultValues(); $capital_pool->mall_id = $mall_id; } //获取已结算订单 $total_price = ScoreBonusCapitalModel::find()->where(['mall_id' => $mall_id, 'status' => StatusEnum::ENABLED])->sum('bonus_price'); $total_price = round($total_price, 2); $capital_pool->total_price = $total_price; //获取未结算订单 $bonus_price = ScoreBonusCapitalModel::find()->where(['mall_id' => $mall_id, 'status' => StatusEnum::DISABLED])->sum('bonus_price'); $bonus_price = round($bonus_price, 2); $capital_pool->bonus_price = $bonus_price; if (!$capital_pool->save()) throw new Exception('修改分红池数据失败'); ScoreBonusCapitalModel::updateAll(['status' => StatusEnum::ENABLED], ['mall_id' => $mall_id, 'status' => StatusEnum::DISABLED]); return true; } catch (\Exception $e) { throw new Exception($e->getMessage()); } } }