| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- <?php
- namespace addons\ScoreBonus\common\services;
- use yii\data\Pagination;
- use Yii;
- use common\helpers\DateHelper;
- use common\helpers\FormatHelper;
- use common\enums\StatusEnum;
- use common\enums\UserWalletEnum;
- use common\models\user\UserWallet;
- use services\common\UserWalletService;
- use addons\ScoreBonus\common\models\ScoreBonusModel;
- use addons\ScoreBonus\common\models\ScoreBonusRewardLogModel;
- use addons\ScoreBonus\common\models\ScoreBonusCapitalModel;
- use addons\ScoreBonus\common\models\ScoreBonusErrorLogModel;
- use addons\ScoreBonus\common\enums\ScoreBonusEnums;
- use addons\ScoreBonus\common\models\ScoreBonusCapitalPool;
- use addons\ScoreBonus\common\models\ScoreBonusUserWeight;
- use Exception;
- /**
- *
- * 应用置顶服务
- */
- class ScoreBonusSettleService
- {
- // 积分分红结算
- public function scoreBonusSettle($mall_id = '', $config = [])
- {
-
- try {
- if (empty($mall_id) || empty($config)) throw new \Exception('无商城id或商城配置');
- $where = [
- 'mall_id' => $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());
- }
- }
- }
|