RewardLogLogic.php 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. <?php
  2. namespace addons\Boss\common\logic;
  3. use addons\Boss\common\enums\BossEnum;
  4. use addons\Boss\common\enums\LevelEnum;
  5. use addons\Boss\common\models\AddonsBoss;
  6. use addons\Boss\common\models\AddonsBossCommissionItemSetting;
  7. use addons\Boss\common\models\AddonsBossCommissionLog;
  8. use addons\Boss\common\models\AddonsBossLevel;
  9. use addons\Boss\common\models\AddonsBossLevelSetting;
  10. use addons\Boss\common\models\AddonsBossRewardLog;
  11. use addons\Boss\common\models\BossGoodsStatistics;
  12. use addons\DoubleCopy\common\models\DoubleCopyUser;
  13. use addons\Mch\common\enums\MchEnum;
  14. use addons\Mch\common\logic\BossLogic;
  15. use addons\Mch\common\models\MchCensus;
  16. use addons\Mch\common\models\MchModel;
  17. use addons\Mch\common\models\MchSettings;
  18. use addons\Store\common\models\StoreGoodsModel;
  19. use common\enums\AddonsEnum;
  20. use common\enums\StatusEnum;
  21. use common\enums\UserWalletEnum;
  22. use common\helpers\FileHelper;
  23. use common\helpers\FormatHelper;
  24. use common\models\mall\MallAddons;
  25. use common\models\order\Order;
  26. use common\models\statistics\UserStatisticsTotal;
  27. use common\models\user\User;
  28. use yii\helpers\Json;
  29. use common\models\order\OrderDetail;
  30. use common\models\user\UserWallet;
  31. use common\traits\ErrorTrait;
  32. use Exception;
  33. use services\common\UserWalletService;
  34. use yii;
  35. /**
  36. * Class RewardLog
  37. * @Author: lun
  38. * @DateTime: 2021/10/25 9:39
  39. * @Copyright: copyright (c) 2021 广东七件事集团
  40. * @package addons\Boss\common\logic
  41. */
  42. class RewardLogLogic
  43. {
  44. use ErrorTrait;
  45. /**
  46. * @Author: hua
  47. * @DateTime: 2021/10/18 9:57
  48. * @Copyright: copyright (c) 2021 广东七件事集团
  49. * @param $order
  50. * @return bool
  51. */
  52. public function execute($order)
  53. {
  54. try {
  55. // 初始化数据
  56. $order_list = $order['detail'];
  57. $mallId = $order['mall_id'];
  58. $calculate = []; // 佣金计算
  59. $amounts = 0; // 结算的总金额
  60. $date = date('Ymd', time());
  61. $time = time();
  62. // 判断用户插件是否安装
  63. if (MallAddons::isInstall($mallId, BossEnum::ADDONS_NAME) == 0) return true;
  64. $isDecMchTaskCounter = true;
  65. $isMch = false;
  66. if (!empty($order['mch_id'])) {
  67. $isMch = MallAddons::isInstall($mallId, AddonsEnum::ADDONS_NAME_MCH);
  68. }
  69. // 获取基础配置
  70. $config = Yii::$app->services->setting->addons->get($mallId, 'Boss', 'basic');
  71. // 判断是否开启插件分润
  72. if ($config['is_enable'] == StatusEnum::DISABLED) return true;
  73. // 判断结算方式,0=支付完成,1=订单完成
  74. $settlement_method = $config['settlement_method'] == 0 ? 1 : 4;
  75. if ($order['order_status'] != $settlement_method) {
  76. $isDecMchTaskCounter = false;
  77. return true;
  78. }
  79. // 获取股东等级列表
  80. $level_arr = AddonsBossLevelSetting::getBossLevelSetting([['mall_id' => $mallId]], [], true);
  81. if (empty($level_arr)) return true;
  82. $level_arr = array_column($level_arr, null, 'level');
  83. if ($isMch) {
  84. BossLogic::resetCommonSetting($level_arr);
  85. $mchConfig = Yii::$app->services->setting->addons->get($mallId, MchEnum::ADDONS_NAME, 'mode');
  86. // 获取是否开启模式
  87. $enableMode = $mchConfig['is_enable_mode'] ?? 1; // 默认开启
  88. // 多商户股东配置
  89. $mchBossSetting = json_decode($mchConfig[AddonsEnum::ADDONS_NAME_BOSS] ?? '', true) ?: [];
  90. BossLogic::setCommonSetting($level_arr, $mchBossSetting);
  91. $settle_type = \Yii::$app->services->setting->addons->get($mallId, MchEnum::ADDONS_NAME, 'basic.settle_type');
  92. $mch_setting_model = MchSettings::findOne(['mch_id'=>$order['mch_id'],'status'=>StatusEnum::ENABLED]);
  93. if(!empty($mch_setting_model) && !empty($mch_setting_model['individual_fee_setting'])) {
  94. $settle_type = $mch_setting_model['store_settle_type'];
  95. }
  96. if($settle_type==4) {
  97. $store_boss_status = \Yii::$app->services->setting->addons->get($mallId, MchEnum::ADDONS_NAME, 'basic.store_boss_status');
  98. if (!empty($store_boss_status)) {
  99. $store_model = MchModel::getOne([['mch_id' => $order['mch_id']]], true);
  100. if (!empty($store_model)) {
  101. $enableMode = !empty($store_model['status']);
  102. $content = json_decode($store_model['content'], true);
  103. $storeMchBossSetting = json_decode($content[AddonsEnum::ADDONS_NAME_BOSS] ?? '', true) ?: [];
  104. if (!empty($storeMchBossSetting)) {
  105. $mchBossSetting = $storeMchBossSetting;
  106. BossLogic::setCommonSetting($level_arr, $mchBossSetting);
  107. }
  108. }
  109. }
  110. }
  111. $isBossEnableCommission = $mchBossSetting['commission']['is_enable'] ?? 1;
  112. $isBossEnableDigital = $mchBossSetting['digital']['is_enable'] ?? 1;
  113. }
  114. // 检查是否有股东用户,没有直接退出
  115. $has_boss = AddonsBoss::find()->select('id')->where(['mall_id' => $mallId, 'status' => StatusEnum::ENABLED])->asArray()->one();
  116. if (empty($has_boss)) return true;
  117. $boss_levels = AddonsBossLevel::lists([
  118. 'where' => [['mall_id' => $mallId, 'status' => StatusEnum::ENABLED]],
  119. 'select'=> 'level',
  120. 'index' => 'level'
  121. ]);
  122. // 开启“高等级拿低等级分红”的等级数组
  123. $insatiable_level_arr = [];
  124. // 获取高等级拿低等额外分红的数组
  125. $insatiable_extra_level_arr = [];
  126. foreach ($level_arr as $level => $v) {
  127. $level_arr[$level]['extra_type'] = json_decode($v['extra_type'], true);
  128. if (!$v['insatiable']) continue;
  129. if(!isset($boss_levels[$level])) continue;
  130. $insatiable_level_arr[$level] = $v;
  131. }
  132. foreach ($level_arr as $level => $v) {
  133. if (!$v['insatiable_extra']) continue;
  134. if(!isset($boss_levels[$level])) continue;
  135. $insatiable_extra_level_arr[$level] = $v;
  136. }
  137. $level_count = AddonsBoss::find()
  138. ->select("count(id) num,level")
  139. ->where(['mall_id' => $mallId, 'status' => StatusEnum::ENABLED])
  140. ->groupBy("level")
  141. ->indexBy("level")
  142. ->asArray()
  143. ->all();
  144. $extra_level_count = AddonsBoss::getBossCountByExtraUpgrade($mallId);
  145. $is_decr_score = $config['is_decr_score'] ?? 0;
  146. if ($is_decr_score) {
  147. // 根据选择决定哪种类型需要扣除积分
  148. $participate_decr_score_type = json_decode($config['participate_decr_score_type'] ?? '', true) ?: [];
  149. $is_decr_score_perpetual = !isset($participate_decr_score_type['perpetual']) || $participate_decr_score_type['perpetual']; // 这里为了兼容旧数据,只要开启默认扣除永久积分
  150. $is_decr_score_extra = !empty($participate_decr_score_type['extra']);
  151. }
  152. $settlement_data = [];
  153. // 循环订单详情,对不同商品进行对应的佣金结算
  154. foreach ($order_list as $index => $detail) {
  155. // 获取结算的金额
  156. // if ($config['compute_type'] == 0) $order_money = $detail['goods_price'];// 支付金额
  157. // if ($config['compute_type'] == 1) $order_money = $detail['goods_price'] - $detail['cost_price'] + $detail['adjust_money'];// 商品利润
  158. // if ($config['compute_type'] == 2) $order_money = $detail['price'];// 商品售价
  159. if ($config['compute_type'] == 0) $order_money = $detail['goods_price']; // 支付金额
  160. if ($config['compute_type'] == 1) $order_money = $detail['goods_price'] - bcmul($detail['cost_price'], $detail['num'], 2) + $detail['adjust_money']; // 商品利润
  161. if ($config['compute_type'] == 2) $order_money = bcmul($detail['price'], $detail['num'], 2); // 商品售价
  162. // 兼容多商户,多商户则读多商户配置
  163. if ($isMch) {
  164. $goods_setting = BossLogic::getBossAloneSetting($mallId, $detail['goods_id'], $order['mch_id']);
  165. } else {
  166. //判断是否为门店商品订单
  167. if($detail['store_id'] > 0){
  168. // 获取门店商品的股东分红独立配置
  169. $goods_setting = StoreGoodsModel::getGoodsModel($detail['goods_id'],'Boss','commission');
  170. }else{
  171. // 获取平台商品的股东分红独立配置
  172. $goods_setting = AddonsBossCommissionItemSetting::getOne([['mall_id' => $mallId], ['item_id' => $detail['goods_id']], ['commission_type' => 'commission']], true, ['detail']);
  173. }
  174. }
  175. if ($goods_setting['is_extra_scale_ratio']) {
  176. //开启了额外计算比例,重新计算
  177. $order_money = bcmul($order_money, $goods_setting['extra_scale_ratio'] / 100, 2); // 商品售价
  178. }
  179. $amounts = $amounts + $order_money;
  180. // 商品没参与股东分红则直接退出
  181. if (!empty($goods_setting) && $goods_setting['is_enable'] == 0) continue;
  182. // 判断是否开启独立设置
  183. if (!empty($goods_setting['is_alone']) && $goods_setting['is_alone'] == 1) {
  184. // 商品独立分佣配置
  185. $level_calculate = $goods_setting['detail'];
  186. // 下面的额外分红读的是$level_arr,独立配置的额外分红开关不生效,重新赋值
  187. foreach ($level_arr as &$item) {
  188. isset($goods_setting['is_extra']) && $item['is_extra'] = $goods_setting['is_extra'];
  189. }
  190. unset($item);
  191. } else {
  192. if ($isMch && (!$enableMode || !$isBossEnableCommission)) {
  193. continue;
  194. }
  195. // 等级分佣配置
  196. $level_calculate = $level_arr;
  197. }
  198. // “高等级瓜分低等级”永久分红的等级数组
  199. $outer_layer = [];
  200. $extra_outer_layer = [];
  201. // 对应的等级的永久/额外佣金计算
  202. foreach ($level_calculate as $level) {
  203. $level_num = $extra_level_num = 0;
  204. $current_level = $level['level'];// 当前等级
  205. if (!empty($level_count[$current_level]) && !empty($level_count[$current_level]['num'])) {
  206. $level_num = $level_count[$current_level]['num']; // 统计的人数
  207. // 统计额外分红被选中的人数
  208. $extra_type_arr = $level_arr[$current_level]['extra_type'] ?? [];
  209. foreach ($extra_type_arr as $selected) {
  210. if (!empty($extra_level_count[$current_level . '_' . $selected])) $extra_level_num += $extra_level_count[$current_level . '_' . $selected];
  211. }
  212. }
  213. // 获取将瓜分该等级“永久分红”的高级别等级数组
  214. $forever_level_arr = [];
  215. foreach ($insatiable_level_arr as $item) {
  216. if ($item['level'] <= $level['level']) continue;
  217. // 比当前等级高
  218. $forever_level_arr[$item['level']] = $level_count[$item['level']]['num'];
  219. }
  220. // 获取将瓜分该等级“额外分红”的高级别等级数组
  221. $extra_level_arr = [];
  222. foreach ($insatiable_extra_level_arr as $item) {
  223. if ($item['level'] <= $level['level']) continue;
  224. // 比当前等级高
  225. // 统计额外分红被选中的人数
  226. $extra_type_arr = $level_arr[$item['level']]['extra_type'] ?? [];
  227. $temp_extra_level_num = 0;
  228. foreach ($extra_type_arr as $selected) {
  229. if (!empty($extra_level_count[$item['level'] . '_' . $selected])) $temp_extra_level_num += $extra_level_count[$item['level'] . '_' . $selected];
  230. }
  231. if ($temp_extra_level_num > 0) $extra_level_arr[$item['level']] = $temp_extra_level_num;
  232. }
  233. $forever_commonisson = $extra_commonisson = 0;
  234. if ($level_num <= 0) {
  235. if (array_sum($forever_level_arr) > 0) {
  236. $forever_commonisson = $level['prize'] ? bcdiv($order_money * $level['prize'] / array_sum($forever_level_arr), 100, 2) : 0;
  237. }
  238. // 额外分红判断是否开启单独分
  239. if (empty($level_arr[$level['level']]['extra_alone'])) {
  240. if (array_sum($extra_level_arr) > 0) {
  241. $extra_commonisson = $level['extra_prize'] ? bcdiv($order_money * $level['extra_prize'] / (array_sum($extra_level_arr)), 100, 2) : 0; // 额外分红佣金,单位:元
  242. }
  243. } else {
  244. // 开启了单独分则不需要进行平均计算
  245. $extra_commonisson = $level['extra_prize'] ? bcdiv($order_money * $level['extra_prize'], 100, 2) : 0; // 额外分红佣金,单位:元
  246. }
  247. } else {
  248. $forever_commonisson = $level['prize'] ? bcdiv($order_money * $level['prize'] / ($level_num + array_sum($forever_level_arr)), 100, 2) : 0; // 永久分红佣金,单位:元
  249. // 判断是否开启单独分
  250. if (empty($level_arr[$level['level']]['extra_alone'])) {
  251. if ($extra_level_num) $extra_commonisson = $level['extra_prize'] ? bcdiv($order_money * $level['extra_prize'] / ($extra_level_num + array_sum($extra_level_arr)), 100, 2) : 0; // 额外分红佣金,单位:元
  252. } else {
  253. // 开启了单独分则不需要进行平均计算
  254. $extra_commonisson = $level['extra_prize'] ? bcdiv($order_money * $level['extra_prize'], 100, 2) : 0; // 额外分红佣金,单位:元
  255. }
  256. }
  257. if (count($forever_level_arr) > 0) {
  258. foreach ($forever_level_arr as $a => $b) {
  259. $outer_layer[$a] = bcadd($outer_layer[$a] ?? 0, $forever_commonisson, 2);
  260. }
  261. }
  262. // 叠加当前高等级的额外分红
  263. if (count($extra_level_arr) > 0) {
  264. foreach ($extra_level_arr as $a => $b) {
  265. $extra_outer_layer[$a] = bcadd($extra_outer_layer[$a] ?? 0, $extra_commonisson, 2);
  266. }
  267. }
  268. // 单个商品的结算明细
  269. $settlement_data[$level['level']][] = [
  270. 'detail_id' => $detail['id'],
  271. 'goods_id' => $detail['goods_id'],
  272. 'goods_name' => $detail['goods_name'],
  273. 'amounts' => $order_money,
  274. 'prize' => $level['prize'],
  275. 'commonisson' => $forever_commonisson,
  276. 'extra_level_num' => $extra_level_num ?? 0,
  277. 'extra_level_arr' => array_sum($extra_level_arr) ?? 0,
  278. 'extra_prize' => $level['extra_prize'],
  279. 'extra_commonisson' => $extra_commonisson,
  280. 'extra_alone' => $level_arr[$level['level']]['extra_alone'] ?? 0,
  281. ];
  282. // 分红佣金计算
  283. $calculate[$level['level']] = [
  284. 'commission' => empty($calculate[$level['level']]['commission']) ? $forever_commonisson : $calculate[$level['level']]['commission'] + $forever_commonisson,
  285. 'extra_commission' => empty($calculate[$level['level']]['extra_commission']) ? $extra_commonisson : $calculate[$level['level']]['extra_commission'] + $extra_commonisson,
  286. 'average_count' => $level_num,
  287. 'extra_average_count' => $extra_level_num + array_sum($extra_level_arr),
  288. 'forever_average_count' => $level_num + array_sum($forever_level_arr),
  289. 'settlement_data' => $settlement_data[$level['level']],
  290. ];
  291. }
  292. // 对“单个商品的结算明细”和“分红佣金数组”中的佣金分红字段进行修改
  293. foreach ($outer_layer as $m => $n) {
  294. $calculate[$m]['commission'] = bcadd($calculate[$m]['commission'], $n, 2);
  295. foreach ($calculate[$m]['settlement_data'] as &$k) {
  296. $k['commonisson'] = bcadd($k['commonisson'], $n, 2);
  297. }
  298. unset($k);
  299. }
  300. // 对“单个商品的结算明细”和“分红佣金数组”中的佣金额外分红字段进行修改
  301. foreach ($extra_outer_layer as $m => $n) {
  302. $calculate[$m]['extra_commission'] = bcadd($calculate[$m]['extra_commission'], $n, 2);
  303. if (empty($calculate[$m])) continue; // 兼容没有结算明细的等级
  304. foreach ($calculate[$m]['settlement_data'] as &$k) {
  305. $k['extra_commonisson'] = bcadd($k['extra_commonisson'], $n, 2);
  306. }
  307. unset($k);
  308. }
  309. }
  310. $digital_amounts = 0;
  311. // 处理数字币相关分佣
  312. foreach ($order_list as $index => $detail) {
  313. if ($config['compute_type'] == 0) $order_money = $detail['goods_price']; // 支付金额
  314. if ($config['compute_type'] == 1) $order_money = $detail['goods_price'] - bcmul($detail['cost_price'], $detail['num'], 2) + $detail['adjust_money']; // 商品利润
  315. if ($config['compute_type'] == 2) $order_money = bcmul($detail['price'], $detail['num'], 2); // 商品售价
  316. // 兼容多商户,多商户则读多商户配置
  317. if ($isMch) {
  318. $goods_setting = BossLogic::getBossAloneSetting($mallId, $detail['goods_id'], $order['mch_id'], 'digital');
  319. } else {
  320. // 获取商品的股东分红独立配置
  321. $goods_setting = AddonsBossCommissionItemSetting::getOne([['mall_id' => $mallId], ['item_id' => $detail['goods_id']], ['commission_type' => 'digital']], true, ['detail']);
  322. }
  323. if ($goods_setting['is_extra_scale_ratio']) {
  324. //开启了额外计算比例,重新计算
  325. $order_money = bcmul($order_money, $goods_setting['extra_scale_ratio'] / 100, 2); // 商品售价
  326. }
  327. $digital_amounts = $digital_amounts + $order_money;
  328. // 商品没参与股东分红则直接退出
  329. if (!empty($goods_setting) && $goods_setting['is_enable'] == 0) continue;
  330. $is_alone = false;
  331. // 判断是否开启独立设置
  332. if (!empty($goods_setting['is_alone']) && $goods_setting['is_alone'] == 1) {
  333. // 商品独立分佣配置
  334. $level_calculate = $goods_setting['detail'];
  335. $is_alone = true;
  336. } else {
  337. if ($isMch && (!$enableMode || !$isBossEnableDigital)) {
  338. continue;
  339. }
  340. // 等级分佣配置
  341. $level_calculate = $level_arr;
  342. }
  343. $extra_digital_outer_layer = [];
  344. // 对应的等级的永久/额外佣金计算
  345. foreach ($level_calculate as $level) {
  346. if($is_alone){
  347. $level['digital_prize'] = $level['prize'];
  348. $level['extra_digital_prize'] = !empty($goods_setting['is_extra']) ? $level['extra_prize'] : 0;
  349. }
  350. $level_num = 0;
  351. if (!empty($level_count[$level['level']]) && !empty($level_count[$level['level']]['num'])) {
  352. $level_num = $level_count[$level['level']]['num']; // 统计的人数
  353. }
  354. // 获取将瓜分该等级“额外分红”的高级别等级数组
  355. $extra_level_arr = [];
  356. foreach ($insatiable_extra_level_arr as $item) {
  357. if ($item['level'] <= $level['level']) continue;
  358. // 比当前等级高
  359. // 统计额外分红被选中的人数
  360. $extra_type_arr = $level_arr[$item['level']]['extra_type'] ?? [];
  361. $temp_extra_level_num = 0;
  362. foreach ($extra_type_arr as $selected) {
  363. if (!empty($extra_level_count[$item['level'] . '_' . $selected])) $temp_extra_level_num += $extra_level_count[$item['level'] . '_' . $selected];
  364. }
  365. if ($temp_extra_level_num > 0) $extra_level_arr[$item['level']] = $temp_extra_level_num;
  366. }
  367. if ($level_num <= 0) {
  368. $digital_commission = $ex_digital_commission = 0;
  369. if (array_sum($extra_level_arr) > 0) {
  370. // 判断是否开启单独分
  371. if (empty($level_arr[$level['level']]['extra_alone'])) {
  372. $ex_digital_commission = $level['extra_digital_prize'] ? bcdiv($order_money * $level['extra_digital_prize'] / array_sum($extra_level_arr), 100, 2) : 0; //额外分红数字币
  373. } else {
  374. $ex_digital_commission = $level['extra_digital_prize'] ? bcdiv($order_money * $level['extra_digital_prize'], 100, 2) : 0; //额外分红数字币
  375. }
  376. }
  377. } else {
  378. $digital_commission = $level['digital_prize'] ? bcdiv($order_money * $level['digital_prize'] / $level_num , 100, 2) : 0;//数字币永久分红
  379. // 判断是否开启单独分
  380. if (empty($level_arr[$level['level']]['extra_alone'])) {
  381. $ex_digital_commission = $level['extra_digital_prize'] ? bcdiv($order_money * $level['extra_digital_prize'] / ($level_num + array_sum($extra_level_arr)), 100, 2) : 0;//额外分红数字币
  382. } else {
  383. $ex_digital_commission = $level['extra_digital_prize'] ? bcdiv($order_money * $level['extra_digital_prize'], 100, 2) : 0; //额外分红数字币
  384. }
  385. }
  386. // 叠加当前高等级的额外分红
  387. if (array_sum($extra_level_arr) > 0) {
  388. foreach ($extra_level_arr as $a => $b) {
  389. $extra_digital_outer_layer[$a] = bcadd($extra_digital_outer_layer[$a] ?? 0, $ex_digital_commission, 2);
  390. }
  391. }
  392. // 单个商品的结算明细
  393. $settlement_data[$level['level']][] = [
  394. 'detail_id' => $detail['id'],
  395. 'goods_id' => $detail['goods_id'],
  396. 'goods_name' => $detail['goods_name'],
  397. 'amounts' => $order_money,
  398. 'prize' => $level['digital_prize'],
  399. 'commonisson' => $digital_commission,
  400. 'extra_prize' => $level['extra_digital_prize'],
  401. 'extra_commonisson' =>$ex_digital_commission,
  402. 'extra_alone' => $level_arr[$level['level']]['extra_alone'] ?? 0,
  403. 'type' => 'digital',
  404. ];
  405. // 分红佣金计算
  406. $calculate[$level['level']] = [
  407. 'digital' => empty($calculate[$level['level']]['digital']) ? $digital_commission : $calculate[$level['level']]['digital'] + $digital_commission,
  408. 'extra_digital' => empty($calculate[$level['level']]['extra_digital']) ? $ex_digital_commission : $calculate[$level['level']]['extra_digital'] + $ex_digital_commission,
  409. 'commission' => empty($calculate[$level['level']]['commission']) ? 0 : $calculate[$level['level']]['commission'],
  410. 'extra_commission' => empty($calculate[$level['level']]['extra_commission']) ? 0 : $calculate[$level['level']]['extra_commission'],
  411. 'settlement_data' => $settlement_data[$level['level']],
  412. 'average_count' => empty($calculate[$level['level']]['average_count']) ? 0 : empty($calculate[$level['level']]['average_count']),
  413. 'forever_average_count' => $calculate[$level['level']]['forever_average_count'] ?? 0,
  414. 'extra_average_count' => $calculate[$level['level']]['extra_average_count'] ?? 0,
  415. 'digital_average_count' => $level_num,
  416. 'digital_forever_average_count' => $level_num
  417. ];
  418. }
  419. // 对“单个商品的结算明细”和“分红佣金数组”中的佣金额外分红字段进行修改
  420. foreach ($extra_digital_outer_layer as $m => $n) {
  421. $calculate[$m]['extra_digital'] = bcadd($calculate[$m]['extra_digital'], $n, 2);
  422. foreach ($calculate[$m]['settlement_data'] as &$k) {
  423. $k['extra_commonisson'] = bcadd($k['extra_commonisson'], $n, 2);
  424. }
  425. unset($k);
  426. }
  427. }
  428. // 结算的配置
  429. $settlement_config = [
  430. 'compute_type' => $config['compute_type'], // 佣金计算方式
  431. 'settlement_method' => $config['settlement_method'], // 结算方式
  432. ];
  433. if ($isMch) {
  434. $settlement_config['order_source'] = \common\enums\AddonsEnum::ADDONS_NAME_MCH;
  435. $settlement_config['mch_id'] = $order['mch_id'];
  436. }
  437. $i = 1;
  438. $page_size = 1000;
  439. $insert_wallet = [];
  440. $commissionArr = [];
  441. $totalCommission = 0;
  442. while ($boss_list = AddonsBoss::find()->where(['mall_id' => $mallId, 'status' => StatusEnum::ENABLED])->offset(($i - 1) * $page_size)->limit($page_size)->all()) {
  443. // 分红计算
  444. foreach ($boss_list as $boss) {
  445. // 判断是否开启股东分红限制
  446. $bonus_restrict_system = BossBonusLogic::getAccordBonus($boss, $level_arr[$boss->level]);
  447. if (!$bonus_restrict_system) continue;
  448. if (empty($calculate[$boss->level])) continue;
  449. $user_commission = $calculate[$boss->level]['commission'];
  450. if ($is_decr_score && !empty($is_decr_score_perpetual)) {
  451. $user_wallet = UserWallet::getOne([['user_id' => $boss->user_id], ['mall_id' => $boss->mall_id]], true, [], false, 'score');
  452. $user_commission = $user_wallet['score'] >= $user_commission ? $user_commission : $user_wallet['score'];
  453. $user_wallet['score'] -= $user_commission;
  454. }
  455. if ($user_commission > 0) {
  456. // 永久分红
  457. $rows[] = [
  458. 'mall_id' => $boss->mall_id,
  459. 'order_id' => $order['id'],
  460. 'order_no' => $order['order_no'],
  461. 'user_id' => $boss->user_id,
  462. 'type' => 1,
  463. 'level' => $boss->level, // 股东等级
  464. 'average_count' => $calculate[$boss->level]['forever_average_count'], // 统计人数
  465. 'amounts' => $amounts,
  466. 'commission' => $user_commission,
  467. 'settlement_config' => Json::encode($settlement_config),
  468. 'settlement_data' => Json::encode($calculate[$boss->level]['settlement_data']),
  469. 'date' => $date,
  470. 'created_at' => $time,
  471. 'updated_at' => $time,
  472. 'total_num' => $level_count[$boss->level]['num'],
  473. ];
  474. if ($is_decr_score && !empty($is_decr_score_perpetual)) {
  475. $desc = '股东分红佣金扣除积分';
  476. $insert_wallet[] = [
  477. 'mall_id' => $boss->mall_id,
  478. 'user_id' => $boss->user_id,
  479. 'is_frozen' => false,
  480. 'wallet_type' => 'score',
  481. 'money' => bcmul($user_commission, -1, 2),
  482. 'desc' => $desc,
  483. 'source_table' => '{{%order_detail}}',
  484. 'source_table_id' => $order_list[0]['id'],
  485. 'from_type' => BossEnum::ADDONS_NAME,
  486. 'capital_type' => UserWalletEnum::FOREVER,
  487. 'order_no' => $order['order_no'],
  488. 'contributor_name' => $order_list[0]['goods_name'],
  489. 'contributor_id' => $order['user_id'],
  490. 'contributor_money' => $order_list[0]['goods_price'],
  491. ];
  492. }
  493. }
  494. // 统计佣金
  495. foreach ($calculate[$boss->level]['settlement_data'] as $settlementItem) {
  496. if (isset($settlementItem['type']) && $settlementItem['type'] == 'digital') {
  497. continue;
  498. }
  499. $totalCommission = bcadd($totalCommission, $settlementItem['commonisson'], 2);
  500. $commissionArr[$settlementItem['detail_id']][BossEnum::ADDONS_NAME]['commission'] = bcadd($commissionArr[$settlementItem['detail_id']][BossEnum::ADDONS_NAME]['commission'] ?? 0, $settlementItem['commonisson'], 2);
  501. }
  502. $user_digital = $calculate[$boss->level]['digital'];
  503. if($user_digital > 0){
  504. // 数字币永久分红
  505. $rows[] = ['mall_id' => $boss->mall_id,'order_id' => $order['id'],'order_no' => $order['order_no'], 'user_id' => $boss->user_id,'type' => LevelEnum::DIGITAL_PRIZE,'level' => $boss->level, // 股东等级
  506. 'average_count' => $calculate[$boss->level]['digital_forever_average_count'], // 统计人数
  507. 'amounts' => $digital_amounts,'commission' => $user_digital,'settlement_config' => Json::encode($settlement_config),
  508. 'settlement_data' => Json::encode($calculate[$boss->level]['settlement_data']), 'date' => $date,'created_at' => $time,'updated_at' => $time, 'total_num' => $level_count[$boss->level]['num'],
  509. ];
  510. }
  511. $extra_digital = $calculate[$boss->level]['extra_digital'];
  512. if ($extra_digital > 0) {
  513. // 额外分红数字币
  514. $rows[] = ['mall_id' => $boss->mall_id,'order_id' => $order['id'],'order_no' => $order['order_no'],'user_id' => $boss->user_id,
  515. 'type' => LevelEnum::EXTRA_DIGITAL_PRIZE, 'level' => $boss->level, 'average_count' => $calculate[$boss->level]['digital_average_count'],
  516. 'amounts' => $digital_amounts,'commission' => $extra_digital, 'settlement_config' => Json::encode($settlement_config),
  517. 'settlement_data' => Json::encode($calculate[$boss->level]['settlement_data']), 'date' => $date, 'created_at' => $time, 'updated_at' => $time, 'total_num' => $level_count[$boss->level]['num'],
  518. ];
  519. }
  520. $extra_commission = $calculate[$boss->level]['extra_commission'];
  521. if ($extra_commission <= 0) continue; // 额外分红小于=0直接退出
  522. // 判断该等级是否开启额外分红
  523. if ($level_arr[$boss->level]['is_extra'] == 0) continue;
  524. // 判断用户是否符合额外分红条件
  525. if (isset($level_arr[$boss->level]) && !in_array($boss->upgrade_status, $level_arr[$boss->level]['extra_type'])) continue;
  526. $extra_settlement_config = $settlement_config;
  527. // 股东独立开启限额
  528. $is_extra_bonus_alone_limit = $boss->is_extra_bonus_alone_limit;
  529. // 判断是否设置额外分红上限并且用户是否达到额外分红上限
  530. $extra_is_limit = $is_extra_bonus_alone_limit ?: $level_arr[$boss->level]['extra_is_limit'];
  531. if ($is_extra_bonus_alone_limit) {
  532. $extra_limit_price = $boss->extra_bonus_limit;
  533. } else {
  534. $extra_limit_price = $level_arr[$boss->level]['extra_limit_price'];
  535. }
  536. //判断是否计算已满上限用户
  537. if ($level_arr[$boss->level]['is_static_extra'] == 2 && $boss->extra_commission >= $extra_limit_price) continue;
  538. if ($extra_is_limit == 1) {
  539. // if ($is_extra_bonus_alone_limit) {
  540. // $extra_limit_price = $boss->extra_bonus_limit;
  541. // } else {
  542. // $extra_limit_price = $level_arr[$boss->level]['extra_limit_price'];
  543. // }
  544. // 已超额则直接退出
  545. if ($boss->temp_extra_commission >= $extra_limit_price) continue;
  546. // 判断是否开启了股东额外分红限制
  547. if (!empty($level_arr[$boss->level]['extra_restrict'])) {
  548. $check = $this->checkRestrict($boss, $level_arr[$boss->level]['extra_restrict_keys'], $level_arr[$boss->level]['extra_restrict_values'], $order);
  549. if ($check === false) continue; // 不符合条件直接跳过不给额外分红
  550. }
  551. // 没超额,但是加上奖励金额则超额,额外分红 = 限制金额 - 已有额外金额;
  552. if ($boss->temp_extra_commission + $calculate[$boss->level]['extra_commission'] >= $extra_limit_price) {
  553. $extra_commission = $extra_limit_price - $boss->temp_extra_commission;
  554. $extra_settlement_config['extra_msg'] = '额外分红金额已达到上限,应得额外分红:¥' . $calculate[$boss->level]['extra_commission'] . ',实得额外分红:¥' . $extra_commission;
  555. }
  556. }
  557. if ($is_decr_score && !empty($is_decr_score_extra)) {
  558. if (empty($user_wallet)) {
  559. $user_wallet = UserWallet::getOne([['user_id' => $boss->user_id], ['mall_id' => $boss->mall_id], ['status' => StatusEnum::ENABLED]], true, [], false, 'score');
  560. }
  561. $extra_commission = min($user_wallet['score'], $extra_commission);
  562. }
  563. if ($extra_commission > 0) {
  564. // 额外分红
  565. $rows[] = [
  566. 'mall_id' => $boss->mall_id,
  567. 'order_id' => $order['id'],
  568. 'order_no' => $order['order_no'],
  569. 'user_id' => $boss->user_id,
  570. 'type' => 2,
  571. 'level' => $boss->level, // 股东等级
  572. 'average_count' => $calculate[$boss->level]['extra_average_count'], // 统计人数
  573. 'amounts' => $amounts,
  574. 'commission' => $extra_commission,
  575. 'settlement_config' => Json::encode($extra_settlement_config),
  576. 'settlement_data' => Json::encode($calculate[$boss->level]['settlement_data']),
  577. 'date' => $date,
  578. 'created_at' => $time,
  579. 'updated_at' => $time,
  580. 'total_num' => $level_count[$boss->level]['num'],
  581. ];
  582. if ($is_decr_score && !empty($is_decr_score_extra)) {
  583. $desc = '股东分红佣金扣除积分';
  584. $insert_wallet[] = [
  585. 'mall_id' => $boss->mall_id,
  586. 'user_id' => $boss->user_id,
  587. 'is_frozen' => false,
  588. 'wallet_type' => 'score',
  589. 'money' => bcmul($extra_commission, -1, 2),
  590. 'desc' => $desc,
  591. 'source_table' => '{{%order_detail}}',
  592. 'source_table_id' => $order_list[0]['id'],
  593. 'from_type' => BossEnum::ADDONS_NAME,
  594. 'capital_type' => UserWalletEnum::BO_EXTRA,
  595. 'order_no' => $order['order_no'],
  596. 'contributor_name' => $order_list[0]['goods_name'],
  597. 'contributor_id' => $order['user_id'],
  598. 'contributor_money' => $order_list[0]['goods_price'],
  599. ];
  600. }
  601. }
  602. // 增加额外分红的临时额度
  603. $boss->temp_extra_commission += $extra_commission;
  604. $boss->save();
  605. // 统计佣金
  606. foreach ($calculate[$boss->level]['settlement_data'] as $settlementItem) {
  607. if (isset($settlementItem['type']) && $settlementItem['type'] == 'digital') {
  608. continue;
  609. }
  610. $totalCommission = bcadd($totalCommission, $settlementItem['extra_commonisson'], 2);
  611. $commissionArr[$settlementItem['detail_id']][BossEnum::ADDONS_NAME]['commission'] = bcadd($commissionArr[$settlementItem['detail_id']][BossEnum::ADDONS_NAME]['commission'] ?? 0, $settlementItem['extra_commonisson'], 2);
  612. }
  613. }
  614. $i++;
  615. }
  616. // 保存数据
  617. if (!empty($rows)) {
  618. $trans = Yii::$app->db->beginTransaction();
  619. try {
  620. // 生成数据
  621. $field = ['mall_id', 'order_id', 'order_no', 'user_id', 'type', 'level', 'average_count', 'amounts', 'commission', 'settlement_config', 'settlement_data', 'date', 'created_at', 'updated_at', 'total_num'];
  622. Yii::$app->db->createCommand()->batchInsert(AddonsBossRewardLog::tableName(), $field, $rows)->execute();
  623. $trans->commit();
  624. } catch (Exception $e) {
  625. $trans->rollBack();
  626. $this->setError($e->getMessage());
  627. return false;
  628. }
  629. }
  630. if ($insert_wallet) {
  631. $res = UserWalletService::batchHandleByQueue($insert_wallet);
  632. if (empty($res)) throw new \Exception(UserWalletService::getStaticError());
  633. }
  634. if ($isMch) {
  635. $data = [
  636. 'mall_id' => $order['mall_id'],
  637. 'mch_id' => $order['mch_id'],
  638. 'date_time' => date('Y-m-d', time()),
  639. 'order_nums' => 0,
  640. 'settlement_commission' => $totalCommission,
  641. ];
  642. MchCensus::setData($data);
  643. }
  644. return true;
  645. } catch (Exception $e) {
  646. $exception = FormatHelper::exception($e, '订单触发股东分红计算错误');
  647. echo $exception;
  648. $this->setError($exception);
  649. return false;
  650. } finally {
  651. if (!empty($isDecMchTaskCounter) && !empty($isMch)) {
  652. \addons\Mch\common\logic\BossLogic::decMchTaskCounter($mallId, $order['id'], $commissionArr ?? []);
  653. }
  654. }
  655. }
  656. /**
  657. * 检查用户是否符合额外分红限制条件
  658. * @Author: lun
  659. * @DateTime: 2022/9/13 0013 11:02
  660. * @Copyright: copyright (c) 2021 广东七件事集团
  661. * @param $user_id
  662. * @param $keys
  663. * @param $values
  664. * @return bool
  665. */
  666. public function checkRestrict($user, $keys, $values, $order)
  667. {
  668. $keys = json_decode($keys, true);
  669. $values = json_decode($values, true);
  670. if (empty($keys)) return false;
  671. $is_bool = true;
  672. foreach ($values as $item) {
  673. if (in_array($item['key'], $keys) && $item['key'] <= 1) {
  674. $fun = "restrictCond" . ($item['key'] + 1);
  675. $is_bool = $this->$fun($user, $item['value']);
  676. if ($is_bool === false) {
  677. // 将不发送额外分红的用户数据存入日志,便于查询
  678. FileHelper::writeLog($this->getLogPath($fun), "订单id={$order['id']},user_id={$user['user_id']} 本次订单无法获得额外分红");
  679. break;
  680. }
  681. }
  682. }
  683. return $is_bool;
  684. }
  685. /**
  686. * desc@股东额外分红限制条件1
  687. * 股东额外分红每累计收益满__元,必须购买__笔,指定商品__才可继续享受股东额外分红
  688. * @Author: lun
  689. * @DateTime: 2022/9/13 0013 10:59
  690. * @Copyright: copyright (c) 2021 广东七件事集团
  691. * @param $user_id
  692. * @param $setting
  693. * @return bool
  694. */
  695. public function restrictCond1($user, $setting)
  696. {
  697. if ($user['extra_commission'] >= $setting['income']) {
  698. $intval = intval($user['extra_commission'] / $setting['income']);
  699. // 查询用户符合条件的购物数量
  700. $buy_num = BossGoodsStatistics::find()->where(['user_id' => $user['user_id'], 'goods_id' => explode(',', $setting['goods_ids']), 'status' => StatusEnum::ENABLED])->sum('buy_num') ?? 0;
  701. if ($buy_num >= $intval && $buy_num >= $setting['buy_num']) return true;
  702. return false;
  703. } else {
  704. return true;
  705. }
  706. }
  707. /**
  708. * desc@股东额外分红限制条件2
  709. * 用户累计收益每满__元,(链动和股东分红产生的收益总和),必须购买__笔,指定商品__才可继续享受股东额外分红
  710. * @Author: lun
  711. * @DateTime: 2022/9/13 0013 11:34
  712. * @Copyright: copyright (c) 2021 广东七件事集团
  713. * @param $user
  714. * @param $setting
  715. * @return bool
  716. */
  717. public function restrictCond2($user, $setting)
  718. {
  719. $copy_commission = 0; // 二二复制累计收益初始化
  720. if (MallAddons::isInstall($user['mall_id'], 'DoubleCopy')) {
  721. // 获取二二复制总收益
  722. $copy_commission = DoubleCopyUser::find()->select('commission')->where(['user_id' => $user['user_id'], 'status' => StatusEnum::ENABLED])->scalar() ?? 0;
  723. }
  724. // 总收益 = 股东收益 + 二二复制收益
  725. $total_commission = $user['total_commission'] + $copy_commission;
  726. if ($total_commission >= $setting['income']) {
  727. $intval = intval($total_commission / $setting['income']);
  728. // 查询用户符合条件的购物数量
  729. $buy_num = BossGoodsStatistics::find()->where(['user_id' => $user['user_id'], 'goods_id' => explode(',', $setting['goods_ids']), 'status' => StatusEnum::ENABLED])->sum('buy_num') ?? 0;
  730. if ($buy_num >= $intval && $buy_num >= $setting['buy_num']) return true;
  731. return false;
  732. } else {
  733. return true;
  734. }
  735. }
  736. /**
  737. * 插入日志记录
  738. * @Author: lun
  739. * @DateTime: 2022/9/13 0013 16:09
  740. * @Copyright: copyright (c) 2021 广东七件事集团
  741. * @param $type
  742. * @return string
  743. */
  744. protected function getLogPath($type)
  745. {
  746. return Yii::getAlias('@runtime') . "/logs/boss/" . $type . '/' . date('Y_m_d') . '.txt';
  747. }
  748. }