Reward.php 82 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583
  1. <?php
  2. namespace addons\DoubleCopy\common\logic;
  3. use addons\DoubleCopy\common\enums\DoubleCopyEnum;
  4. use addons\DoubleCopy\common\models\DoubleCopyCommission;
  5. use addons\DoubleCopy\common\models\DoubleCopyCommissionItemSetting;
  6. use addons\DoubleCopy\common\models\DoubleCopyLevel;
  7. use addons\DoubleCopy\common\models\DoubleCopyLevelSetting;
  8. use addons\DoubleCopy\common\models\DoubleCopyUser;
  9. use addons\PointUpperLimit\common\service\ScoreLogService;
  10. use addons\PointUpperLimit\common\service\UserService;
  11. use common\enums\GoodsTypeEnum;
  12. use common\enums\OrderStatusEnum;
  13. use common\enums\StatusEnum;
  14. use common\models\common\CapitalLog;
  15. use common\models\goods\Goods;
  16. use common\models\user\User;
  17. use common\models\user\UserPartitionRelationship;
  18. use common\models\user\UserWallet;
  19. use common\traits\ErrorTrait;
  20. use services\common\UserWalletService;
  21. use Yii;
  22. use yii\db\Exception;
  23. use yii\db\Expression;
  24. use yii\helpers\Json;
  25. use addons\DoubleCopy\common\models\DoubleCopyPoolUser;
  26. use common\enums\AddonsEnum;
  27. use common\models\mall\MallAddons;
  28. class Reward
  29. {
  30. use ErrorTrait;
  31. public static $reward = [];// 奖励
  32. public static $is_upgrade = false;
  33. public static $is_fracture = false;// 关系是否断层[false=否,true=是]
  34. public static $task_counter_arr = [];
  35. public static $commission_type = 'commission';// 奖励类型
  36. public static $upgrade_num = 2;// 推荐位数
  37. /**
  38. * 是否为额外积分
  39. * @var bool
  40. */
  41. public static $is_additional_score = false;
  42. /**
  43. * 额外积分与积分映射
  44. * @var string[]
  45. */
  46. protected static $commission_name_map = [
  47. 'additional_score' => 'score'
  48. ];
  49. /**
  50. * 计算奖励
  51. * @Author: lun
  52. * @DateTime: 2022/5/17 0017 14:44
  53. * @Copyright: copyright (c) 2021 广东七件事集团
  54. * @param array $basic_order 订单
  55. * @param bool $is_upgrade 是否是升级
  56. * @return bool
  57. */
  58. public static function compute($basic_order, $is_upgrade,$commission_type= 'commission')
  59. {
  60. $trans = Yii::$app->db->beginTransaction();
  61. try {
  62. $mall_id = $basic_order['mall_id'];// 商城
  63. self::$reward = [];// 初始化置空,防止重复发奖励
  64. self::$is_upgrade = $is_upgrade;
  65. self::$is_fracture = false;
  66. self::$task_counter_arr = [];
  67. // 如果是额外积分
  68. self::$is_additional_score = $commission_type == 'additional_score';
  69. self::$commission_type = $commission_type;
  70. self::getUpgradeNum($basic_order['mall_id']);
  71. $doubleCopyUser = DoubleCopyUser::getOne([['user_id' => $basic_order['user_id']], ['mall_id' => $basic_order['mall_id']],['status'=>StatusEnum::ENABLED]], true, [], 'updated_at desc');
  72. if($doubleCopyUser){
  73. $goods_info = json_encode(['goods_id'=>$basic_order['detail'][0]['goods_id'], 'goods_name'=>$basic_order['detail'][0]['goods_name'],'price'=>$basic_order['detail'][0]['price']]);
  74. DoubleCopyUser::setData(['id'=>$doubleCopyUser['id'],'mall_id' => $basic_order['mall_id'],'goods_info'=>$goods_info]);
  75. }
  76. // 检查商品是虚拟商品订单
  77. $is_virtual = false;
  78. $goods = Goods::find()->where(['id' => $basic_order['detail'][0]['goods_id']])->asArray()->one();
  79. if (!empty($goods) && $goods['goods_type'] == GoodsTypeEnum::GoodsTypeVirtual) {
  80. $is_virtual = true;
  81. // 虚拟商品直接退出
  82. // if ($basic_order['order_status'] == OrderStatusEnum::ACCOMPLISH) {
  83. // $trans->commit();
  84. // return true;
  85. // }
  86. }
  87. // 获取配置信息
  88. $config = Yii::$app->services->setting->addons->get($mall_id, DoubleCopyEnum::ADDONS_NAME, 'basic');
  89. unset($config['reward_name']);// 移除名称自定义配置
  90. // 订单已完成,但是结算方式为支付完成,则后续不再进行结算
  91. // if ($config['compute_type'] == 1 && $basic_order['order_status'] == OrderStatusEnum::ACCOMPLISH) {
  92. // $trans->commit();
  93. // return true;
  94. // }
  95. // 获取链动用户信息
  96. $user = DoubleCopyUser::find()->where(['user_id' => $basic_order['user_id'], 'status' => StatusEnum::ENABLED])->one();
  97. if (empty($user)) {
  98. $trans->commit();
  99. return true;
  100. }
  101. // 检查是否已经生成过订单分润数据
  102. $check_commission = DoubleCopyCommission::find()->where(['order_id' => $basic_order['id'], 'status' => StatusEnum::ENABLED,'reward_currency'=>$commission_type])->asArray()->all();
  103. if (empty($check_commission)) {
  104. // 获取代理等级设置的商品
  105. $level_good_ids = DoubleCopyLevel::find()->select('goods_ids')->where(['mall_id' => $basic_order['mall_id'], 'level' => DoubleCopyEnum::LEVEL_AGENT, 'status' => StatusEnum::ENABLED])->scalar();
  106. $level_good_ids = empty($level_good_ids) ? [] : Json::decode($level_good_ids, true);// json字符串
  107. // 获取独立设置商品
  108. $alone_good_ids = DoubleCopyCommissionItemSetting::find()->select('item_id')->where(['mall_id' => $basic_order['mall_id'], 'status' => StatusEnum::ENABLED,'commission_type' => $commission_type])->column();
  109. $good_ids = array_unique(array_merge($level_good_ids, $alone_good_ids));
  110. // 组合订单信息
  111. $order = [
  112. 'id' => $basic_order['id'],
  113. 'order_id' => $basic_order['id'],
  114. 'order_no' => $basic_order['order_no'],
  115. 'mall_id' => $basic_order['mall_id'],
  116. 'user_id' => $basic_order['user_id'],
  117. 'order_status' => $basic_order['order_status'],
  118. 'created_at' => $basic_order['created_at'],
  119. ];
  120. // 获取等级配置
  121. $level = DoubleCopyLevelSetting::find()->where(['mall_id' => $mall_id,'status' => StatusEnum::ENABLED,'commission_type' => $commission_type])
  122. ->with(['levelInfo' => function($query){
  123. $query->select('id,open_ladder,ladder_setting');
  124. }])->indexBy('level')->asArray()->all();
  125. foreach ($level as &$item) {
  126. $item['open_ladder'] = $item['levelInfo']['open_ladder'];
  127. $item['ladder_setting'] = $item['levelInfo']['ladder_setting'];
  128. }
  129. foreach ($basic_order['detail'] as $key => $detail){
  130. // 获取独立设置商品
  131. $good = DoubleCopyCommissionItemSetting::find()
  132. ->where(['mall_id' => $basic_order['mall_id'], 'item_id' => $detail['goods_id'], 'status' => StatusEnum::ENABLED,'commission_type' => $commission_type])
  133. ->with('detail')
  134. ->asArray()->one();
  135. if (empty($good)) {
  136. $level_setting = $level;
  137. // 获取等级设置商品
  138. $good = DoubleCopyLevel::find()->select('goods_ids')->where(['mall_id' => $basic_order['mall_id'], 'level' => DoubleCopyEnum::LEVEL_AGENT, 'status' => StatusEnum::ENABLED])->asArray()->one();
  139. } else {
  140. if ($good['is_partake'] == 0) {
  141. Yii::$app->custom->logs("二二赠送:".json_encode($order['id']).',结果:不参与分红直接退出');
  142. continue;// 不参与分红直接退出
  143. }
  144. if ($good['is_enable'] == 0) {// 参与分红但是不独立设置,则去等级设置
  145. $level_setting = $level;
  146. } else {
  147. $level_setting = $good['detail'];
  148. foreach ($level_setting as &$setting) {// 设置等级
  149. $setting['first_prize_type'] = $setting['indirect_prize_type'] = $setting['second_prize_type'] = $setting['equal_prize_type'] = $setting['equal_level_prize_type'] = $setting['repurchase_prize_type'] = $good['is_percent'];
  150. $setting['freeze_fund_prize'] = $level[$setting['level']]['freeze_fund_prize'];
  151. $setting['open_ladder'] = $level[$setting['level']]['levelInfo']['open_ladder'];
  152. $setting['ladder_setting'] = $level[$setting['level']]['levelInfo']['ladder_setting'];
  153. }
  154. }
  155. }
  156. if (empty($good)){
  157. Yii::$app->custom->logs("二二赠送:".json_encode($order['id']).',结果:没有商品');
  158. continue;
  159. }
  160. // 检测购买此商品是否有使用优惠或抵扣(随机减不算)
  161. if (!empty($config['is_open_no_rewards']) && bcmul($detail['price'], $detail['num'], 2) != bcmul($detail['goods_price'],1,2)){
  162. Yii::$app->custom->logs("二二赠送:".json_encode($order['id']).',结果:检测购买此商品是否有使用优惠或抵扣(随机减不算)');
  163. continue;
  164. }
  165. // 判断商品是否在商品列表中
  166. if (!in_array($detail['goods_id'], $good_ids)) {
  167. Yii::$app->custom->logs("二二赠送:".json_encode($order['id']).',结果:判断商品是否在商品列表中');
  168. continue;
  169. }
  170. $order['order_detail_id'] = $detail['id'];
  171. $order['goods_name'] = $detail['goods_name'];
  172. $order['pic_url'] = $detail['pic_url'];
  173. $order['price'] = $detail['price'];
  174. $order['cost_price'] = $detail['cost_price'];
  175. $order['original_goods_price'] = $detail['original_goods_price'];
  176. $order['goods_price'] = $detail['goods_price'];
  177. $order['adjust_money'] = $detail['adjust_money'];
  178. $order['num'] = $detail['num'];
  179. $order['goods_id'] = $detail['goods_id'];
  180. self::computeHandle($user, $order, $config, $level_setting, $is_upgrade, $is_virtual);
  181. }
  182. }
  183. // 订单完成操作
  184. if ($basic_order['order_status'] == OrderStatusEnum::ACCOMPLISH) {
  185. // 获取未结算的奖励
  186. $list = DoubleCopyCommission::find()->where(['order_id' => $basic_order['id'], 'settlement_type' => StatusEnum::DISABLED, 'reward_currency' => $commission_type, 'status' => StatusEnum::ENABLED])->asArray()->all();
  187. if (empty($list) || (count($list) == 1 && $list[0]['is_frozen'] == 1)) {
  188. $trans->commit();
  189. return true;
  190. }
  191. $res = self::settlement($list, $config, $basic_order['order_status'], true, $basic_order['mall_id'], $is_virtual);
  192. if ($res === false) throw new Exception(self::getStaticError());
  193. }
  194. $trans->commit();
  195. return true;
  196. } catch (\Exception $e) {
  197. $trans->rollBack();
  198. self::setStaticError($e->getMessage());
  199. return false;
  200. }
  201. }
  202. /**
  203. * 计算处理等级商品与独立设置商品分润
  204. * @Author: lun
  205. * @DateTime: 2022/6/21 0021 15:25
  206. * @Copyright: copyright (c) 2021 广东七件事集团
  207. * @param object $user
  208. * @param array $order 订单信息
  209. * @param array $config 基础设置
  210. * @param array $level 等级设置
  211. * @param bool $is_upgrade 是否是升级
  212. * @return bool
  213. * @throws Exception
  214. */
  215. public static function computeHandle(DoubleCopyUser $user, $order, $config, $level, $is_upgrade, $is_virtual)
  216. {
  217. /*因为当订单为多个子订单循环是。之前订单佣金self::$reward 还会保存之前的数据。如果当下一个子订单没有self::$reward 中对应分佣类型数据
  218. 那么之前的订单分佣数据不会被替换。还是会保留。所以此处需要每次都设置self::$reward = [];*/
  219. self::$reward = [];
  220. // 获取计算金额
  221. $computing_config = self::getComputingConfig($config, $order);
  222. if (empty($computing_config)) return true;
  223. // 初始化奖励参数
  224. $basic_params = [
  225. 'mall_id' => $order['mall_id'],
  226. 'buy_uid' => $order['user_id'],
  227. 'order_id' => $order['id'],
  228. 'order_no' => $order['order_no'],
  229. 'pay_money' => $order['goods_price'],
  230. 'goods_name' => $order['goods_name'],
  231. 'pic_url' => $order['pic_url'],
  232. 'price' => $order['price'],
  233. 'source_table' => 'order_detail',
  234. 'source_table_id' => $order['order_detail_id'],
  235. 'setting' => $config,
  236. 'created_at' => $order['created_at'],
  237. 'updated_at' => time(),
  238. ];
  239. Yii::$app->custom->logs(json_encode(['user' => $user, 'computing_config' => $computing_config,'setting' => $config,'is_upgrade' => $is_upgrade, 'goods_id' => $order['goods_id']]));
  240. // 平台补贴(奖励topid)
  241. $second_prize = self::SecondPrize($user, $level, $computing_config, $basic_params, $is_upgrade,$order['goods_id']);
  242. Yii::$app->custom->logs("二二补贴:".json_encode($order['id']).',结果:'.json_encode($second_prize));
  243. if ($second_prize === false) throw new Exception(self::getStaticError());
  244. //计算平台补贴贡献奖
  245. $contribution_price = self::contributionPrice($order, $basic_params, $user);
  246. if ($contribution_price === false) throw new Exception(self::getStaticError());
  247. // 直推奖(奖励pid)
  248. $first_prize = self::FirstPrize($user, $level, $computing_config, $basic_params, $is_upgrade,$order['goods_id']);
  249. Yii::$app->custom->logs("二二直推奖:".json_encode($order['id']).',结果:'.json_encode($first_prize));
  250. if ($first_prize === false) throw new Exception(self::getStaticError());
  251. // 培育奖(平级奖[奖励pid的上级]),获取培育奖的计算依据:0=平台补贴计算,1=平台补贴+直推奖计算
  252. $equal_settle_basis = $config['equal_settle_basis'] ?? 0;
  253. $second_original_money = self::$reward[DoubleCopyEnum::SECOND_PRIZE]['original_money'] ?? 0;// 平台补贴金额
  254. if ($equal_settle_basis == 0) {// 平台补贴计算
  255. $computing_money = $second_original_money;// 平台补贴金额
  256. } else {// 平台补贴+直推奖计算
  257. // 判断当前用户是否平台补贴加直推一起获得
  258. $first_money = 0;
  259. if ($user['pid'] == $user['topid']) {// 如果平台补贴+直推奖获得者为同一个用户则计算培育收益需要按照两个收益和来做结算
  260. $first_money = self::$reward[DoubleCopyEnum::FIRST_PRIZE]['original_money'] ?? 0;
  261. }
  262. $computing_money = $second_original_money + $first_money;
  263. }
  264. // 培育奖计算
  265. if (!empty($computing_money)) {
  266. // 培育奖奖励人数
  267. $equal_prize = self::EqualPrize($user, $level, $computing_money, $basic_params, $computing_config['multiple'],$order['goods_id']);
  268. if ($equal_prize === false) throw new Exception(self::getStaticError());
  269. if ($equal_prize) {
  270. // 拿平台补贴收益支付处理
  271. if ($config['equal_settle_type'] == 1) {
  272. self::$reward[DoubleCopyEnum::SECOND_PRIZE]['money'] = self::$reward[DoubleCopyEnum::SECOND_PRIZE]['money'] - self::$reward[DoubleCopyEnum::EQUAL_PRIZE]['money'];
  273. }
  274. }
  275. }
  276. //平级奖[奖励pid的上级]获取培育奖的计算依据:0=平台补贴计算,1=平台补贴+直推奖计算
  277. $equal_level_settle_basis = $config['equal_level_settle_basis'] ?? 0;
  278. $second_original_money = self::$reward[DoubleCopyEnum::SECOND_PRIZE]['original_money'] ?? 0;// 平台补贴金额
  279. if ($equal_level_settle_basis == 0) {// 平台补贴计算
  280. $computing_money = $second_original_money;// 平台补贴金额
  281. } else {// 平台补贴+直推奖计算
  282. // 判断当前用户是否平台补贴加直推一起获得
  283. $first_money = 0;
  284. if ($user['pid'] == $user['topid']) {// 如果平台补贴+直推奖获得者为同一个用户则计算培育收益需要按照两个收益和来做结算
  285. $first_money = self::$reward[DoubleCopyEnum::FIRST_PRIZE]['original_money'] ?? 0;
  286. }
  287. $computing_money = $second_original_money + $first_money;
  288. }
  289. // 平级奖计算
  290. if (!empty($computing_money)) {
  291. // 平级奖奖励人数
  292. $equal_level_prize = self::EqualLevelPrize($user, $level, $computing_money, $basic_params, $computing_config['multiple'],$order['goods_id']);
  293. if ($equal_level_prize === false) throw new Exception(self::getStaticError());
  294. if ($equal_level_prize) {
  295. // 拿平台补贴收益支付处理
  296. if ($config['equal_level_settle_type'] == 1) {
  297. self::$reward[DoubleCopyEnum::SECOND_PRIZE]['money'] = self::$reward[DoubleCopyEnum::SECOND_PRIZE]['money'] - self::$reward[DoubleCopyEnum::EQUAL_LEVEL_PRIZE]['money'];
  298. }
  299. }
  300. }
  301. // 间推奖(依据主商城关系链,奖励下单用户的上上级)
  302. $indirect_prize = self::IndirectPrize($level, $computing_config, $basic_params,$order['goods_id']);
  303. if ($indirect_prize === false) throw new Exception(self::getStaticError());
  304. //津贴奖
  305. $allowance_prize = self::AllowancePrize($user, $level, $computing_money, $basic_params, $computing_config['multiple'],$order['goods_id']);
  306. if ($allowance_prize === false) throw new Exception(self::getStaticError());
  307. // print_r(self::$reward);
  308. //复购奖
  309. $repurchase_prize = self::repurchasePrizeDiff($user, $level, $computing_config, $basic_params,$order['goods_id']);
  310. if ($repurchase_prize === false) throw new Exception(self::getStaticError());
  311. // 结算
  312. if (self::$reward) {
  313. $res = self::settlement(self::$reward, $config, $order['order_status'], false, $order['mall_id'], $is_virtual);
  314. if ($res === false) throw new Exception(self::getStaticError());
  315. }
  316. }
  317. /**
  318. * 结算
  319. * @Author: lun
  320. * @DateTime: 2022/5/17 0017 16:07
  321. * @Copyright: copyright (c) 2021 广东七件事集团
  322. * @param $rewards
  323. * @param $config
  324. * @param $order_status
  325. * @param $has_commission
  326. * @param $is_virtual
  327. * @return bool
  328. * @throws \yii\db\Exception
  329. */
  330. public static function settlement($rewards, $config, $order_status, $has_commission, $mall_id, $is_virtual = false)
  331. {
  332. try {
  333. //奖励类型:佣金,积分
  334. $reward_currency = self::$commission_name_map[self::$commission_type] ?? self::$commission_type;
  335. $settlement_type = DoubleCopyEnum::NOT_SETTLEMENT;// 未结算
  336. $field = 'frozen_'.$reward_currency;
  337. $handle_unfrozen = false;// 是否执行解冻操作
  338. $has_freeze = false;// 是否已存在冻结佣金数据
  339. if ($config['compute_type'] == 1 && $order_status == OrderStatusEnum::PAY) {// 支付完成后
  340. $settlement_type = DoubleCopyEnum::SETTLED;// 已结算
  341. //$field = 'commission';
  342. $field = $reward_currency;
  343. }
  344. // 订单完成必须结算,即便中途配置改为支付完成结算
  345. if ($order_status == OrderStatusEnum::ACCOMPLISH) {// 订单完成后
  346. $settlement_type = DoubleCopyEnum::SETTLED;// 已结算
  347. //$field = 'commission';
  348. $field = $reward_currency;
  349. $handle_unfrozen = true;
  350. }
  351. // 虚拟商品直接改为已结算
  352. // if ($is_virtual == true) {
  353. // $settlement_type = DoubleCopyEnum::SETTLED;// 已结算
  354. // $field = 'commission';
  355. // }
  356. // 获取资金类型
  357. $capital_map = DoubleCopyEnum::getCapitalMap($mall_id);
  358. $lduser = $source_table_id = $commission_arr = [];
  359. $update_oids = 0;
  360. $user_total_reward = [];
  361. $point_upper_reward_insert = [];
  362. $height_commission_arr = [];
  363. foreach ($rewards as $key => $reward) {
  364. $reward['reward_currency'] = $reward_currency;
  365. if ($reward['money'] <= 0) continue;// 若平级奖由拿平台补贴用户给,有可能会导致平台补贴收益为空
  366. //奖励类型:佣金,积分
  367. $field = 'frozen_'.$reward_currency;
  368. if ($config['compute_type'] == 1 && $order_status == OrderStatusEnum::PAY) {// 支付完成后
  369. $field = $reward_currency;
  370. }
  371. if ($order_status == OrderStatusEnum::ACCOMPLISH) {// 订单完成后
  372. $field = $reward_currency;
  373. }
  374. $update_oids = $reward['order_id'];
  375. $source_table_id[] = $reward['source_table_id'];
  376. $reward['is_frozen'] = $reward['capital_type'] == DoubleCopyEnum::FREEZE_FUND ? 1 : 0;
  377. if ($reward['capital_type'] == DoubleCopyEnum::FREEZE_FUND) {
  378. $reward['settlement_type'] = StatusEnum::DISABLED;
  379. } else {
  380. $reward['settlement_type'] = $settlement_type;
  381. }
  382. if (!empty($reward['original_money'])) unset($reward['original_money']);
  383. //$reward['reward_currency'] = $reward_currency;
  384. // 如果是额外积分,那么就判断上限
  385. if (self::$is_additional_score && !$has_commission) {
  386. if (!empty($user_total_reward[$reward['user_id']])) {
  387. $user_total_reward[$reward['user_id']] = bcadd($user_total_reward[$reward['user_id']], $reward['money'], 2);
  388. } else {
  389. $user_total_reward[$reward['user_id']] = $reward['money'];
  390. }
  391. $quota = (new UserService())->getUserQuota($reward['mall_id'], $reward['user_id']);
  392. if ($user_total_reward[$reward['user_id']] > $quota) {
  393. $reward['money'] = bcsub($quota, bcsub($user_total_reward[$reward['user_id']], $reward['money'], 2), 2);
  394. }
  395. if ($reward['money'] <= 0) continue;
  396. }
  397. // 云库存计数器,云库存代理承担二二复制分佣开发,必须是支付成功并且未结算情况下计算
  398. if ($order_status == OrderStatusEnum::PAY && $reward_currency == 'commission') {
  399. if(isset(self::$task_counter_arr[$reward['source_table_id']][DoubleCopyEnum::ADDONS_NAME]['commission'])){
  400. self::$task_counter_arr[$reward['source_table_id']][DoubleCopyEnum::ADDONS_NAME]['commission'] += $reward['money'];
  401. }else{
  402. self::$task_counter_arr[$reward['source_table_id']][DoubleCopyEnum::ADDONS_NAME]['commission'] = $reward['money'];
  403. }
  404. }
  405. //判断用户佣金奖励是否设置上限,只在订单支付时判断
  406. $reward_amount = $reward['money'];
  407. if($reward_currency == 'commission' && $order_status == OrderStatusEnum::PAY){
  408. $doubleCopyUser = DoubleCopyUser::find()->where(['user_id' => $reward['user_id'], 'status' => StatusEnum::ENABLED])->one();
  409. if($doubleCopyUser && !empty($doubleCopyUser['is_height_commission'])){
  410. CapitalLog::$capitalType = 'commission_frozen';
  411. $frozen_commission = CapitalLog::find()->where(['user_id' => $reward['user_id'], 'from_type' => DoubleCopyEnum::ADDONS_NAME, 'status' => StatusEnum::DISABLED])->sum("change_num") ?? 0;
  412. $frozen_fund = DoubleCopyCommission::find()->where(['user_id' => $reward['user_id'], 'capital_type' => DoubleCopyEnum::FREEZE_FUND, 'settlement_type' => [0,2],'reward_currency'=>'commission'])->sum('money') ?? 0;
  413. $user_total_commission = $doubleCopyUser['commission'] + $frozen_commission + $frozen_fund;
  414. if(isset($height_commission_arr[$reward['user_id']]['amount'])){
  415. $user_total_commission += $height_commission_arr[$reward['user_id']]['amount'];
  416. }
  417. $can_reward_amount = $doubleCopyUser['height_commission'] - $user_total_commission;
  418. if($can_reward_amount <= 0){
  419. $reward_amount = 0;
  420. $reward['money'] = 0;
  421. $rewards[$key]['money'] = 0;
  422. }else{
  423. if($can_reward_amount < $reward_amount){
  424. $reward_amount = $can_reward_amount;
  425. $reward['money'] = $can_reward_amount;
  426. $rewards[$key]['money'] = $can_reward_amount;
  427. }
  428. if(isset($height_commission_arr[$reward['user_id']]['amount'])){
  429. $height_commission_arr[$reward['user_id']]['amount'] += $reward['money'];
  430. }else{
  431. $height_commission_arr[$reward['user_id']]['amount'] = $reward['money'];
  432. }
  433. }
  434. }
  435. }
  436. // 增加用户的资金累计额度 - 只有结算的时候才需要 所以这里会存在一个问题
  437. if ($reward['capital_type'] == DoubleCopyEnum::FREEZE_FUND) {
  438. if($reward_currency == 'commission'){
  439. $lduser[$reward['user_id']]['frozen_fund'] = $reward['money'];
  440. }else{
  441. $lduser[$reward['user_id']]['frozen_fund_score'] = $reward['money'];
  442. }
  443. } else {
  444. $lduser[$reward['user_id']][$field] = empty($lduser[$reward['user_id']][$field]) ? $reward_amount : $lduser[$reward['user_id']][$field] + $reward_amount;
  445. }
  446. $has_commission == false && $rows[] = $reward;// 支付完成生成数据
  447. $is_frozen = $settlement_type == DoubleCopyEnum::SETTLED ? false : true;
  448. // 用于额外积分记录
  449. if (self::$is_additional_score && !$has_commission) {
  450. $point_upper_reward_insert[] = [
  451. 'mall_id' => $reward['mall_id'],
  452. 'user_id' => $reward['user_id'],
  453. 'is_frozen' => $is_frozen,
  454. // 'wallet_type' => 'commission',
  455. 'wallet_type' => $reward_currency,
  456. 'money' => $reward['money'],
  457. 'desc' => $capital_map[$reward['capital_type']],
  458. 'source_table' => $reward['source_table'],
  459. 'source_table_id' => $reward['source_table_id'],
  460. 'from_type' => DoubleCopyEnum::ADDONS_NAME,
  461. 'capital_type' => $reward['capital_type'],
  462. 'order_no' => $reward['order_no']
  463. ];
  464. }
  465. // 已结算插入钱包队列中(冻结基金不算在内)
  466. if ($reward['capital_type'] != DoubleCopyEnum::FREEZE_FUND) {
  467. // 如果订单已经完成,但是又未进行结算则不需要增加数据
  468. if ($order_status == OrderStatusEnum::ACCOMPLISH && $settlement_type != DoubleCopyEnum::SETTLED) continue;
  469. if (self::$is_upgrade == false && $handle_unfrozen == true) continue;// 执行解冻操作则不需要进行插入钱包队列
  470. $insert_wallet[] = [
  471. 'mall_id' => $reward['mall_id'],
  472. 'user_id' => $reward['user_id'],
  473. 'is_frozen' => $is_frozen,
  474. // 'wallet_type' => 'commission',
  475. 'wallet_type' => $reward_currency,
  476. 'money' => $reward['money'],
  477. 'desc' => $capital_map[$reward['capital_type']],
  478. 'source_table' => $reward['source_table'],
  479. 'source_table_id' => $reward['source_table_id'],
  480. 'from_type' => $reward['capital_type'] == DoubleCopyEnum::CONTRIBUTION_PRICE ? AddonsEnum::ADDONS_NAME_DOUBLE_COPY_COMMITMENT_AWARD : DoubleCopyEnum::ADDONS_NAME,
  481. 'capital_type' => $reward['capital_type'],
  482. 'order_no' => $reward['order_no']
  483. ];
  484. }
  485. }
  486. // 生成数据
  487. if (!empty($rows)) {
  488. $field = ['mall_id','buy_uid','order_id','order_no','pay_money','goods_name','pic_url','price','source_table','source_table_id','setting','created_at','updated_at','user_id','money','capital_type','reward_currency','is_frozen','settlement_type'];
  489. $res = Yii::$app->db->createCommand()->batchInsert(DoubleCopyCommission::tableName(), $field, $rows)->execute();
  490. if ($res == false) throw new Exception("批量插入奖励出错");
  491. }
  492. // 保存数据
  493. if (!empty($lduser) && $settlement_type == DoubleCopyEnum::SETTLED) {
  494. echo 'batchAddCommission:order_id='.$update_oids.','.json_encode($lduser).PHP_EOL;
  495. $res = DoubleCopyUser::batchAddCommission($lduser);
  496. if ($res === false) throw new Exception("批量更新用户佣金数据出错:" . DoubleCopyUser::getStaticError());
  497. }
  498. // 修改佣金列表状态
  499. if (!empty($update_oids) && $settlement_type == DoubleCopyEnum::SETTLED) {
  500. $res = DoubleCopyCommission::updateAll(['settlement_type' => StatusEnum::ENABLED, 'updated_at' => time()], "order_id in({$update_oids}) and reward_currency='{$reward_currency}' and capital_type!='".DoubleCopyEnum::FREEZE_FUND."'");
  501. if ($res === false) throw new Exception("批量修改佣金状态失败:" . DoubleCopyUser::getStaticError());
  502. $res = DoubleCopyCommission::updateAll(['frozen_status' => StatusEnum::ENABLED, 'updated_at' => time()], "order_id in({$update_oids}) and reward_currency='{$reward_currency}' and capital_type='".DoubleCopyEnum::FREEZE_FUND."'");
  503. if ($res === false) throw new Exception("修改冻结基金转入状态失败:" . DoubleCopyUser::getStaticError());
  504. // 将未结算金额移除
  505. if ($handle_unfrozen) {
  506. $where = [
  507. ['source_table' => 'order_detail'],
  508. ['source_table_id' => $source_table_id],
  509. [
  510. 'or',
  511. ['from_type' => DoubleCopyEnum::ADDONS_NAME],
  512. ['from_type' => AddonsEnum::ADDONS_NAME_DOUBLE_COPY_COMMITMENT_AWARD],
  513. ],
  514. ['status' => CapitalLog::STATUS_WAIT_SEND]
  515. ];
  516. $params['where'] = $where;
  517. $wallet_type = 'commission';
  518. CapitalLog::$capitalType = "{$wallet_type}_frozen";
  519. $commission_list = CapitalLog::lists($params);
  520. if ($commission_list) {
  521. $has_freeze = true;
  522. foreach ($commission_list as $item) {
  523. $res = UserWalletService::unfrozen($item['id'], $wallet_type);
  524. if ($res === false) throw new \Exception('解冻失败:'.UserWalletService::getStaticError());
  525. }
  526. }
  527. $wallet_type = 'score';
  528. CapitalLog::$capitalType = "{$wallet_type}_frozen";
  529. $score_list = CapitalLog::lists($params);
  530. if ($score_list) {
  531. $has_freeze = true;
  532. foreach ($score_list as $item) {
  533. $res = UserWalletService::unfrozen($item['id'], $wallet_type);
  534. if ($res === false) throw new \Exception('解冻失败:'.UserWalletService::getStaticError());
  535. }
  536. }
  537. }
  538. }
  539. // 如果是额外积分,那么就需要记录一下
  540. if (self::$is_additional_score && (!empty($point_upper_reward_insert) || $order_status == OrderStatusEnum::ACCOMPLISH)) {
  541. self::pointUpperLimit($order_status == OrderStatusEnum::ACCOMPLISH, $point_upper_reward_insert, $source_table_id);
  542. }
  543. // 插入钱包 - 放在最后预防中途报错
  544. if (!empty($insert_wallet) && $has_freeze == false) {
  545. $res = UserWalletService::batchHandleByQueue($insert_wallet);
  546. if (empty($res)) throw new \Exception('插入钱包队列:' . UserWalletService::getStaticError());
  547. }
  548. return true;
  549. } catch (\Exception $e) {
  550. self::setStaticError("奖励结算错误:第" . $e->getLine().'行,原因:'.$e->getMessage() . " 文件: " . $e->getFile());
  551. return false;
  552. }
  553. }
  554. /**
  555. * 额外积分处理
  556. * @param bool $has_freeze
  557. * @param array $insert_wallet
  558. * @param array $source_table_id
  559. * @return array
  560. * @throws Exception
  561. */
  562. public static function pointUpperLimit(bool $has_freeze, array $insert_wallet, array $source_table_id)
  563. {
  564. $upperLimitService = new ScoreLogService();
  565. if ($has_freeze) { // 是否已存在冻结佣金数据 如果存在那么就是解冻否则就是新增
  566. $upperLimitService->batchUnfrozen([ // 统一在渠道那边解冻
  567. ['source_table' => 'order_detail'],
  568. ['source_table_id' => $source_table_id],
  569. ['from_type' => DoubleCopyEnum::ADDONS_NAME],
  570. ['status' => CapitalLog::STATUS_WAIT_SEND]
  571. ]);
  572. } else {
  573. $upperLimitService->batchInsert($insert_wallet);
  574. }
  575. return $insert_wallet;
  576. }
  577. /**
  578. * 直推奖励
  579. * @Author: lun
  580. * @DateTime: 2022/5/17 0017 14:07
  581. * @Copyright: copyright (c) 2021 广东七件事集团
  582. * @param $buy_user
  583. * @param $level
  584. * @param $computing_config
  585. * @param $basic_params
  586. * @return array|bool
  587. */
  588. public static function FirstPrize(&$buy_user, $level, $computing_config, $basic_params, $is_upgrade,$goods_id=0)
  589. {
  590. try {
  591. $computing_money = $computing_config['computing_money'];// 支付金额
  592. $multiple = $computing_config['multiple'];// 商品数量
  593. $config = $basic_params['setting']; // 基础配置
  594. // 检查用户等级
  595. $first_user = DoubleCopyUser::find()->select('level,upgrade_level_at,user_id,mall_id,goods_info')->where(['user_id' => $buy_user['pid'], 'status' => StatusEnum::ENABLED])->asArray()->one();
  596. // 上级无身份的情况下,判断关系链断层是否继续找可获得直推奖的上级
  597. if (empty($first_user) && isset($config['first_fracture_reward']) && !empty($config['first_fracture_reward'])) {
  598. $parent_ids_arr = UserPartitionRelationship::getParentIdArr($buy_user['pid']);
  599. if (!empty($parent_ids_arr)) {
  600. $parent_ids_arr = array_reverse($parent_ids_arr);
  601. $parent_users = DoubleCopyUser::lists(['where' => [['mall_id' => $buy_user['mall_id']], ['user_id' => $parent_ids_arr], ['status' => StatusEnum::ENABLED]], 'select' => 'level,upgrade_level_at,user_id,mall_id,goods_info', 'index' => 'user_id']);
  602. foreach ($parent_ids_arr as $parent_id) {
  603. if (isset($parent_users[$parent_id])) {
  604. $first_user = $parent_users[$parent_id];
  605. break;
  606. }
  607. }
  608. }
  609. }
  610. // 判断用户等级是否存在,不存在代表该上级并非代理或老板级别
  611. if (empty($first_user)) return [];
  612. // 获取等级配置
  613. $level_config = $level[$first_user['level']];
  614. // 计算直推奖励金额
  615. if ($level_config['first_prize_type'] == 0) {
  616. // 按百分比计算
  617. $money = $computing_money * $level_config['first_prize'] / 100;
  618. $money = sprintf("%.2f",substr(sprintf("%.3f", $money), 0, -1));// 保留两位小数并不四舍五入
  619. } else {
  620. // 按固定金额计算
  621. $money = $level_config['first_prize'] * $multiple;
  622. }
  623. if ($money <= 0) return [];
  624. // 冻结基金
  625. $frozen_money = 0;
  626. // 必须要有平台补贴才能出现冻结基金,只有平台补贴用户跟直推用户为同一个人才可生效
  627. if (!empty(self::$reward[DoubleCopyEnum::FREEZE_FUND]) && $buy_user['topid'] == $first_user['user_id']) {
  628. $top_user = DoubleCopyUser::find()->where(['user_id' => $buy_user['topid'], 'status' => StatusEnum::ENABLED])->asArray()->one();
  629. $freeze_fund_prize = $level[$top_user['level']]['freeze_fund_prize'] ?? 0;// 该等级冻结基金比例
  630. if ($top_user['is_thaw'] != 1 && $freeze_fund_prize > 0 && !empty($config['frozen_settle_basis'])) {
  631. // 计算冻结基金
  632. if ($top_user['level'] >= DoubleCopyEnum::LEVEL_BOSS) {
  633. // 判断该等级是否开启了解冻阶梯设置
  634. if (!empty($level[$top_user['level']]['open_ladder'])) {
  635. $freeze_fund_prize = $freeze_fund_prize * (100 - $top_user['thaw_percent']) / 100;
  636. }
  637. $frozen_money = sprintf("%.2f",substr(sprintf("%.3f", ($money * $freeze_fund_prize / 100)), 0, -1));// 保留两位小数并不四舍五入
  638. if ($frozen_money > 0) {
  639. // 生成冻结基金数据
  640. self::$reward[DoubleCopyEnum::FREEZE_FUND]['money'] = empty(self::$reward[DoubleCopyEnum::FREEZE_FUND]['money']) ? $frozen_money : $frozen_money + self::$reward[DoubleCopyEnum::FREEZE_FUND]['money'];
  641. }
  642. }
  643. }
  644. }
  645. // 生成奖励明细数据
  646. $basic_params['setting']['first_prize_type'] = $level_config['first_prize_type'];
  647. $basic_params['setting']['first_prize'] = $level_config['first_prize'];
  648. $basic_params['setting']['computing_money'] = $computing_money;
  649. $basic_params['setting']['frozen_money'] = $frozen_money;
  650. $basic_params['setting'] = Json::encode($basic_params['setting']);
  651. if(self::isLandaHealth($first_user['user_id'],$basic_params['price'],$goods_id,'first_prize')){
  652. self::$reward[DoubleCopyEnum::FIRST_PRIZE] = array_merge($basic_params, [
  653. 'user_id' => $first_user['user_id'],
  654. 'original_money' => $money,
  655. 'money' => $money - $frozen_money,
  656. 'capital_type' => DoubleCopyEnum::FIRST_PRIZE,
  657. ]);
  658. }
  659. return true;
  660. } catch (\Exception $e) {
  661. self::setStaticError("直推奖错误:第" . $e->getLine().'行,原因:'.$e->getMessage());
  662. return false;
  663. }
  664. }
  665. /**
  666. * 间推奖励
  667. * @Author: lun
  668. * @DateTime: 2023/5/30 0030 14:05
  669. * @Copyright: copyright (c) 2021 广东七件事集团
  670. * @param $level
  671. * @param $computing_config
  672. * @param $basic_params
  673. * @return array|bool
  674. */
  675. public static function IndirectPrize($level, $computing_config, $basic_params,$goods_id=0)
  676. {
  677. try {
  678. $multiple = $computing_config['multiple'];// 商品数量
  679. $indirect_arr = [];// 初始化间推奖励用户
  680. // 获取直推+平台补贴用户
  681. foreach (self::$reward as $key => $item) {
  682. // 目前间推奖只包括平台补贴、直推用户上级才可拥有
  683. if (in_array($item['capital_type'], [DoubleCopyEnum::FIRST_PRIZE, DoubleCopyEnum::SECOND_PRIZE, DoubleCopyEnum::FREEZE_FUND])) {
  684. // 计算该用户总共得到的奖励
  685. $indirect_arr[$item['user_id']] = empty($indirect_arr[$item['user_id']]) ? $item['money'] : $indirect_arr[$item['user_id']] + $item['money'];
  686. }
  687. }
  688. if ($indirect_arr) {
  689. foreach ($indirect_arr as $user_id => $computing_money) {
  690. // 获取该用户的上级,因为间推奖励只给得到直推或平台补贴用户的上级,所以需要查询上级
  691. $parent_id = User::find()->select('parent_id')->where(['id' => $user_id])->scalar();
  692. if (empty($parent_id)) continue;
  693. // 获取该上级的二二复制身份等级
  694. $user = DoubleCopyUser::find()->select('level,upgrade_level_at,goods_info,mall_id')->where(['user_id' => $parent_id, 'status' => StatusEnum::ENABLED])->asArray()->one();
  695. if (empty($user)) continue;
  696. // 获取等级配置
  697. $level_config = $level[$user['level']];
  698. if (empty($level_config['indirect_prize'])) continue;// 奖励设置0直接退出
  699. // 计算直推奖励金额
  700. if ($level_config['indirect_prize_type'] == 0) {
  701. $money = $computing_money * $level_config['indirect_prize'] / 100;
  702. $money = sprintf("%.2f",substr(sprintf("%.3f", $money), 0, -1));// 保留两位小数并不四舍五入
  703. } else {
  704. // 按固定金额计算
  705. $money = $level_config['indirect_prize'] * $multiple;
  706. }
  707. if ($money <= 0) continue;
  708. // 生成奖励明细数据
  709. $setting['indirect_prize_type'] = $level_config['indirect_prize_type'];// 奖励类型[百分比或金额]
  710. $setting['indirect_prize'] = $level_config['indirect_prize'];// 奖励比例或金额
  711. $setting['computing_money'] = $computing_money;// 奖励计算金额(只针对百分比奖励有用)
  712. $setting['source_uid'] = $user_id;// 奖励来源于那个用户
  713. $basic_params['setting'] = Json::encode($setting);
  714. if(self::isLandaHealth($parent_id,$basic_params['price'],$goods_id,'indirect_prize')){
  715. self::$reward[DoubleCopyEnum::INDIRECT_PRIZE.'_'.$parent_id] = array_merge($basic_params, [
  716. 'user_id' => $parent_id,
  717. 'original_money' => $money,
  718. 'money' => $money,
  719. 'capital_type' => DoubleCopyEnum::INDIRECT_PRIZE,
  720. ]);
  721. }
  722. }
  723. }
  724. return true;
  725. } catch (\Exception $e) {
  726. self::setStaticError("间推奖错误:第" . $e->getLine().'行,原因:'.$e->getMessage());
  727. return false;
  728. }
  729. }
  730. /**
  731. * 平台补贴
  732. * @Author: lun
  733. * @DateTime: 2022/5/17 0017 14:09
  734. * @Copyright: copyright (c) 2021 广东七件事集团
  735. * @param $buy_user
  736. * @param $level
  737. * @param $computing_config
  738. * @param $basic_params
  739. * @param $is_upgrade
  740. * @return array|bool
  741. */
  742. public static function SecondPrize(DoubleCopyUser &$buy_user, $level, $computing_config, $basic_params, $is_upgrade,$goods_id=0)
  743. {
  744. try {
  745. if (empty($buy_user['pid'])) return [];
  746. $computing_money = $computing_config['computing_money'];// 支付金额
  747. $multiple = $computing_config['multiple'];// 商品数量
  748. $config = $basic_params['setting'];// 基础设置
  749. /** 平台补贴用户临时计算,如果跟原来的平台补贴用户有变化则需要改变平台补贴用户, 开始 **/
  750. if ($buy_user->pos <= self::$upgrade_num) {
  751. // 获取上级用户
  752. $parent_ids = UserPartitionRelationship::getParentIdArr($buy_user['user_id']);
  753. $parent_ids = array_reverse($parent_ids);// 倒序数组
  754. foreach ($parent_ids as $key => $pid) {
  755. // 查询上级是否有身份
  756. $pdc_user = DoubleCopyUser::find()->select('user_id,pos,pid')->where(['user_id' => $pid, 'status' => StatusEnum::ENABLED])->asArray()->one();
  757. if (empty($pdc_user)) {
  758. $has_identity = false;
  759. self::$is_fracture = true;
  760. // 获取当前用户的上级uid
  761. $ppuid = $parent_ids[$key + 1] ?? 0;
  762. if ($ppuid) {
  763. // 统计跟此用户同级人数,并且判断当前用户的平级数量是否大于或等于2号位
  764. $equal_num = DoubleCopyUser::find()->where(['pid' => $ppuid, 'status' => StatusEnum::ENABLED])->count();
  765. if ($equal_num >= self::$upgrade_num) {// 符合位置则表示当前用户的上级必定是拿平台补贴用户(拿平台补贴用户可以没有身份)
  766. $topid = $ppuid;
  767. break;
  768. }
  769. }
  770. } else {
  771. $has_identity = true;
  772. // 如果当前位置是大于或等于3号位则表示此用户上级必定是老板
  773. if ($pdc_user['pos'] > self::$upgrade_num) {
  774. $topid = $pdc_user['pid'];
  775. break;
  776. }
  777. }
  778. $topid = $has_identity ? 0 : $pid;
  779. }
  780. // 临时检测的平台补贴用户id跟之前不同则需要修改平台补贴用户id
  781. if ($buy_user['topid'] != $topid) {
  782. $buy_user->topid = $topid;
  783. $buy_user->save();
  784. }
  785. // 二二复制关系链得平台补贴用户关系被中断后是否可得平台补贴
  786. if (self::$is_fracture == true && empty($config['fracture_reward'])) return [];
  787. } else {
  788. // 若本人位置大于2号位,则平台补贴必定是给到直推上级,但是上级却非二二复制用户,则不再给任何人平台补贴
  789. $puser = DoubleCopyUser::find()->select('user_id')->where(['user_id' => $buy_user['pid'], 'status' => StatusEnum::ENABLED])->asArray()->one();
  790. if (empty($puser)) return [];
  791. }
  792. /** 修改平台补贴用户, 结束 **/
  793. if (empty($buy_user->topid)) return [];
  794. // 获取拿平台补贴用户的等级
  795. $user = DoubleCopyUser::find()->where(['user_id' => $buy_user['topid'], 'status' => StatusEnum::ENABLED])->one();
  796. // 判断用户等级是否存在,不存在代表该上级并非代理或老板级别
  797. if (empty($user)) return [];
  798. if ($user['level'] < DoubleCopyEnum::LEVEL_BOSS) return [];// topid非老板直接退出
  799. // 获取等级配置
  800. $level_config = $level[$user['level']];
  801. // 直推上级跟平台补贴用户为同一人,并且是因为该用户下单导致上级升级的则不发奖励
  802. if ($buy_user['pid'] == $buy_user['topid']) {
  803. if ($buy_user['pos'] == self::$upgrade_num && $is_upgrade == true) return [];
  804. // 如果是1,2号位,并且平台补贴用户上级为平台,则无平台补贴获取
  805. if ($user['pid'] == 0 && $buy_user['pos'] <= self::$upgrade_num) return [];
  806. // 判断是否可以发送平台补贴,1=发送,2=不发送
  807. if (!empty($config['is_send_second']) && $config['is_send_second'] == 2) return [];
  808. } else {
  809. // 如果平台补贴用户的上级为平台则需要判断能否得到平台补贴
  810. if ($user['pos'] == 0) {
  811. // 获取关系链从上往下第二个用户的位置,位置小于或等于2号位则表示用户平台补贴
  812. $parent_arr = UserPartitionRelationship::getParentIdArr($buy_user['user_id']);
  813. // 只需要判断topid的直推用户是否处于1、2号位即可,处于1、2号位则不给平台补贴
  814. $pos_user = DoubleCopyUser::find()->select('user_id')->where(['pid' => $buy_user['topid'], 'status' => StatusEnum::ENABLED])->andWhere(['<=', 'pos', self::$upgrade_num])->column();
  815. if (in_array($parent_arr[1], $pos_user)) return [];
  816. }
  817. }
  818. // 计算直推奖励金额
  819. if ($level_config['second_prize_type'] == 0) {
  820. // 按百分比计算
  821. $money = $computing_money * $level_config['second_prize'] / 100;
  822. $money = sprintf("%.2f",substr(sprintf("%.3f", $money), 0, -1));// 保留两位小数并不四舍五入
  823. } else {
  824. // 按固定金额计算
  825. $money = $level_config['second_prize'] * $multiple;
  826. }
  827. if ($money <= 0) return [];
  828. // 配置插入
  829. $setting = $basic_params['setting'];
  830. $setting['computing_money'] = $computing_money;
  831. // 查询是否开启了冻结基金
  832. $frozen_money = 0;
  833. if ($user['is_thaw'] != 1 && $level_config['freeze_fund_prize'] > 0) {
  834. // 判断该等级是否开启了解冻阶梯设置
  835. if (!empty($level[$user['level']]['open_ladder'])) {
  836. $level_config['freeze_fund_prize'] = $level_config['freeze_fund_prize'] * (100 - $user['thaw_percent']) / 100;
  837. }
  838. // 计算冻结基金
  839. $frozen_money = $money * $level_config['freeze_fund_prize'] / 100;
  840. $frozen_money = sprintf("%.2f",substr(sprintf("%.3f", $frozen_money), 0, -1));// 保留两位小数并不四舍五入
  841. if ($frozen_money > 0) {
  842. // 生成冻结基金数据
  843. $setting['freeze_fund_prize'] = $level_config['freeze_fund_prize'];
  844. $basic_params['setting'] = Json::encode($setting);
  845. if(self::isLandaHealth($buy_user['topid'],$basic_params['price'],$goods_id,'freeze_fund')){
  846. self::$reward[DoubleCopyEnum::FREEZE_FUND] = array_merge($basic_params, [
  847. 'user_id' => $buy_user['topid'],
  848. 'money' => $frozen_money,
  849. 'capital_type' => DoubleCopyEnum::FREEZE_FUND,
  850. ]);
  851. }
  852. }
  853. }
  854. // 生成奖励明细数据
  855. $setting['second_prize_type'] = $level_config['second_prize_type'];
  856. $setting['second_prize'] = $level_config['second_prize'];
  857. $basic_params['setting'] = Json::encode($setting);
  858. if(self::isLandaHealth($buy_user['topid'],$basic_params['price'],$goods_id,'second_prize')){
  859. self::$reward[DoubleCopyEnum::SECOND_PRIZE] = array_merge($basic_params, [
  860. 'user_id' => $buy_user['topid'],
  861. 'original_money' => $money,
  862. 'money' => $money - $frozen_money,// 可得平台补贴 = 总平台补贴 - 冻结基金
  863. 'capital_type' => DoubleCopyEnum::SECOND_PRIZE,
  864. ]);
  865. }
  866. //平台补贴极差
  867. if(!empty($config['second_prize_diff'])) self::secondPrizeDiff($user,$computing_config,$level,$basic_params,$goods_id);
  868. return true;
  869. } catch (\Exception $e) {
  870. self::setStaticError("平台补贴错误:第" . $e->getLine().'行,原因:'.$e->getMessage());
  871. return false;
  872. }
  873. }
  874. /**
  875. * 培育奖
  876. * @Author: lun
  877. * @DateTime: 2022/5/17 0017 14:19
  878. * @Copyright: copyright (c) 2021 广东七件事集团
  879. * @param $buy_user
  880. * @param $level
  881. * @param $computing_money
  882. * @param $basic_params
  883. * @return array|bool
  884. */
  885. public static function EqualPrize($buy_user, $level, $computing_money, $basic_params, $multiple,$goods_id=0)
  886. {
  887. try {
  888. if (empty($computing_money) || empty($buy_user['topid'])) return [];
  889. $config = $basic_params['setting'];
  890. // 如果关系链断层则需要判断配置是否给奖励
  891. if (self::$is_fracture == true && empty($config['fracture_reward'])) return [];
  892. // 获取平台补贴用户等级
  893. $top_user = DoubleCopyUser::find()->select('level,pid')->where(['user_id' => $buy_user['topid'], 'status' => StatusEnum::ENABLED])->asArray()->one();
  894. if (empty($top_user) || empty($top_user['pid'])) return [];
  895. // 注意:2023-03-08需求更改,获取获得平台补贴用户的直推上级,培育奖只能由平台补贴获得者的直推上级所拥有
  896. $top_parent_user = DoubleCopyUser::find()->select('user_id,level,mall_id,goods_info')->where(['user_id' => $top_user['pid'], 'status' => StatusEnum::ENABLED])->asArray()->one();
  897. if (empty($top_parent_user) || $top_parent_user['level'] < DoubleCopyEnum::LEVEL_BOSS) return [];// 当前用户等级必须要大于或等于老板等级
  898. $reward_uid = $top_parent_user['user_id'];// 培育奖获得者
  899. // 获取等级配置
  900. $level_config = $level[$top_parent_user['level']];
  901. // 计算直推奖励金额
  902. if ($level_config['equal_prize_type'] == 0) {
  903. // 按百分比计算
  904. $money = $computing_money * $level_config['equal_prize'] / 100;
  905. $money = sprintf("%.2f",substr(sprintf("%.3f", $money), 0, -1));// 保留两位小数并不四舍五入
  906. } else {
  907. // 按固定金额计算
  908. $money = $level_config['equal_prize'] * $multiple;
  909. }
  910. if ($money <= 0) return [];
  911. // 生成奖励明细数据
  912. $basic_params['setting']['equal_prize_type'] = $level_config['equal_prize_type'];
  913. $basic_params['setting']['equal_prize'] = $level_config['equal_prize'];
  914. $basic_params['setting']['computing_money'] = $computing_money;
  915. $basic_params['setting'] = Json::encode($basic_params['setting']);
  916. if(self::isLandaHealth($reward_uid,$basic_params['price'],$goods_id,'equal_prize')){
  917. self::$reward[DoubleCopyEnum::EQUAL_PRIZE] = array_merge($basic_params, [
  918. 'user_id' => $reward_uid,
  919. 'money' => $money,
  920. 'capital_type' => DoubleCopyEnum::EQUAL_PRIZE,
  921. ]);
  922. }
  923. return true;
  924. } catch (\Exception $e) {
  925. self::setStaticError("平级奖错误:第" . $e->getLine().'行,原因:'.$e->getMessage());
  926. return false;
  927. }
  928. }
  929. /**
  930. * 津贴奖
  931. * @Author: mz
  932. * @DateTime: 2023/06/27 0017 14:19
  933. * @Copyright: copyright (c) 2021 广东七件事集团
  934. * @param $buy_user
  935. * @param $level
  936. * @param $computing_config
  937. * @param $basic_params
  938. * @return array|bool
  939. * allowance_price
  940. */
  941. public static function AllowancePrize($buy_user, $level, $second_computing_money, $basic_params, $multiple,$goods_id=0)
  942. {
  943. try {
  944. $first_prize = self::$reward[DoubleCopyEnum::FIRST_PRIZE] ?? [];
  945. $second_prize = self::$reward[DoubleCopyEnum::SECOND_PRIZE] ?? [];
  946. if(empty($first_prize) && empty($second_prize)){
  947. Yii::error('直推奖与平台补贴都不存在,不发放津贴奖');
  948. return [];
  949. }
  950. // 可以获得津贴奖用户:0=平台补贴上级,1=直推奖上级,2=平台补贴或直推奖上级
  951. $allowance_compute = $basic_params['setting']['allowance_compute'] ?? 0;
  952. $first_prize_uid = $first_prize['user_id'] ?? 0;// 直推奖获得用户
  953. $second_prize_uid = $second_prize['user_id'] ?? 0;// 平台补贴获得用户
  954. $first_computing_money = $first_prize['money'] ?? 0; // 直推奖金额
  955. if ($allowance_compute == 0) $first_prize_uid = 0;// 平台补贴上级可得奖励时,直推用户直接改为无上级
  956. if ($allowance_compute == 1) $second_prize_uid = 0;// 直推奖上级可得奖励时,平台补贴用户直接改为无上级
  957. if ($first_prize_uid == $second_prize_uid && $first_prize_uid == 0) return [];// 无奖励的用户直接退出
  958. $is_same = $first_prize_uid == $second_prize_uid ? true : false;// 直推奖与平台补贴是否同一个人
  959. // 获取平台补贴用户等级
  960. $first_second_users = DoubleCopyUser::find()->select('user_id,level,pid,pos')->where(['user_id' => [$first_prize_uid,$second_prize_uid], 'status' => StatusEnum::ENABLED])->asArray()->all();
  961. if (empty($first_second_users)) return [];
  962. $reward_users = [];// 津贴奖用户
  963. $reward_level = $basic_params['setting']['allowance_level'] ?? 2;// 可获得奖励的等级,没有设置默认等级2
  964. foreach ($first_second_users as $item) {
  965. // 不符合条件的直接跳过
  966. if (empty($item['pid']) || $item['pos'] > self::$upgrade_num) continue;
  967. // 检测奖励津贴奖的上级是否可以得到奖励
  968. $user = DoubleCopyUser::find()->select('user_id,level,goods_info,mall_id')->where(['user_id' => $item['pid'], 'status' => StatusEnum::ENABLED])->asArray()->one();
  969. if ($user) {
  970. if ($user['level'] < $reward_level) continue;// 等级不符合直接跳过
  971. $user['child_uid'] = $item['user_id'];
  972. $reward_users[] = $user;
  973. }
  974. }
  975. if (empty($reward_users)) return [];// 无奖励用户直接跳过
  976. foreach ($reward_users as $item) {
  977. if ($is_same) {
  978. // 直推奖与平台补贴都是同一个人的上级结算金额
  979. $computing_money = $second_computing_money + $first_computing_money;
  980. } else {
  981. // 直推奖的上级结算金额
  982. if (!empty($first_prize_uid) && $item['child_uid'] == $first_prize_uid) $computing_money = $first_computing_money;
  983. // 平台补贴的上级的结算金额
  984. if (!empty($second_prize_uid) && $item['child_uid'] == $second_prize_uid) $computing_money = $second_computing_money;
  985. }
  986. if (empty($computing_money)) continue;
  987. // 获取等级配置
  988. $level_config = $level[$item['level']];
  989. // 计算直推奖励金额
  990. if ($level_config['allowance_price_type'] == 0) {
  991. // 按百分比计算
  992. $money = $computing_money * $level_config['allowance_price'] / 100;
  993. $money = sprintf("%.2f",substr(sprintf("%.3f", $money), 0, -1));// 保留两位小数并不四舍五入
  994. } else {
  995. // 按固定金额计算
  996. $money = $level_config['allowance_price'] * $multiple;
  997. }
  998. if ($money <= 0) return [];
  999. // 生成奖励明细数据
  1000. if (!is_array($basic_params['setting'])) $basic_params['setting'] = json_decode($basic_params['setting'], true);
  1001. $basic_params['setting']['allowance_price_type'] = $level_config['allowance_price_type'];
  1002. $basic_params['setting']['allowance_price'] = $level_config['allowance_price'];
  1003. $basic_params['setting']['computing_money'] = $computing_money;
  1004. $basic_params['setting'] = Json::encode($basic_params['setting']);
  1005. if(self::isLandaHealth($item['user_id'],$basic_params['price'],$goods_id,'allowance_price')){
  1006. self::$reward[DoubleCopyEnum::ALLOWANCE_PRICE . '_' . $item['user_id']] = array_merge($basic_params, [
  1007. 'user_id' => $item['user_id'],
  1008. 'money' => $money,
  1009. 'capital_type' => DoubleCopyEnum::ALLOWANCE_PRICE,
  1010. ]);
  1011. }
  1012. }
  1013. return true;
  1014. } catch (\Exception $e) {
  1015. self::setStaticError("津贴奖错误:第" . $e->getLine().'行,原因:'.$e->getMessage());
  1016. return false;
  1017. }
  1018. }
  1019. /**
  1020. * 平级奖
  1021. * @Author: lun
  1022. * @DateTime: 2022/5/17 0017 14:19
  1023. * @Copyright: copyright (c) 2021 广东七件事集团
  1024. * @param $buy_user
  1025. * @param $level
  1026. * @param $computing_money
  1027. * @param $basic_params
  1028. * @return array|bool
  1029. */
  1030. public static function EqualLevelPrize($buy_user, $level, $computing_money, $basic_params, $multiple,$goods_id=0)
  1031. {
  1032. try {
  1033. if (empty($computing_money) || empty($buy_user['topid'])) return [];
  1034. $config = $basic_params['setting'];
  1035. // 如果关系链断层则需要判断配置是否给奖励
  1036. if (self::$is_fracture == true && empty($config['fracture_reward'])) return [];
  1037. // 获取平台补贴用户等级
  1038. $top_user = DoubleCopyUser::find()->select('level,pid,topid')->where(['user_id' => $buy_user['topid'], 'status' => StatusEnum::ENABLED])->asArray()->one();
  1039. if (empty($top_user) || empty($top_user['pid'])) return [];
  1040. $equal_level_user = 0;
  1041. //助力升级会员 获得平台补贴上级奖励平级奖
  1042. if ($top_user['pos'] <= self::$upgrade_num) {
  1043. $equal_level_user = $top_user['topid'];
  1044. }else{
  1045. $equal_level_user = $top_user['pid'];
  1046. }
  1047. if(empty($equal_level_user)) return [];
  1048. $top_parent_user = DoubleCopyUser::find()->select('user_id,level')->where(['user_id' => $equal_level_user, 'status' => StatusEnum::ENABLED])->asArray()->one();
  1049. if (empty($top_parent_user) || $top_parent_user['level'] < DoubleCopyEnum::LEVEL_BOSS) return [];// 当前用户等级必须要大于或等于老板等级
  1050. $reward_uid = $top_parent_user['user_id'];// 平级奖获得者
  1051. //与培育奖区别处:判断平级奖获得者的1、2号位是否大于或等于老板等级
  1052. $cusers = DoubleCopyUser::find()
  1053. ->where(['pid' => $reward_uid, 'status' => StatusEnum::ENABLED])
  1054. ->andWhere(['<=','pos',self::$upgrade_num])
  1055. ->select('user_id,level,goods_info,mall_id')
  1056. ->asArray()
  1057. ->all();
  1058. foreach($cusers as $cuser){
  1059. //平级奖获得者的1、2号位小于老板等级 不发放平级奖励
  1060. if($cuser['level'] < DoubleCopyEnum::LEVEL_BOSS){
  1061. return [];
  1062. }
  1063. }
  1064. // 获取等级配置
  1065. $level_config = $level[$top_parent_user['level']];
  1066. // 计算直推奖励金额
  1067. if ($level_config['equal_level_prize_type'] == 0) {
  1068. // 按百分比计算
  1069. $money = $computing_money * $level_config['equal_level_prize'] / 100;
  1070. $money = sprintf("%.2f",substr(sprintf("%.3f", $money), 0, -1));// 保留两位小数并不四舍五入
  1071. } else {
  1072. // 按固定金额计算
  1073. $money = $level_config['equal_level_prize'] * $multiple;
  1074. }
  1075. if ($money <= 0) return [];
  1076. if (!is_array($basic_params['setting'])) $basic_params['setting'] = json_decode($basic_params['setting'], true);
  1077. // 生成奖励明细数据
  1078. $basic_params['setting']['equal_level_prize_type'] = $level_config['equal_level_prize_type'];
  1079. $basic_params['setting']['equal_level_prize'] = $level_config['equal_level_prize'];
  1080. $basic_params['setting']['computing_money'] = $computing_money;
  1081. $basic_params['setting'] = Json::encode($basic_params['setting']);
  1082. if(self::isLandaHealth($reward_uid,$basic_params['price'],$goods_id,'equal_level_prize')){
  1083. self::$reward[DoubleCopyEnum::EQUAL_LEVEL_PRIZE] = array_merge($basic_params, [
  1084. 'user_id' => $reward_uid,
  1085. 'money' => $money,
  1086. 'capital_type' => DoubleCopyEnum::EQUAL_LEVEL_PRIZE,
  1087. ]);
  1088. }
  1089. return true;
  1090. } catch (\Exception $e) {
  1091. self::setStaticError("平级奖错误:第" . $e->getLine().'行,原因:'.$e->getMessage());
  1092. return false;
  1093. }
  1094. }
  1095. /**
  1096. * 获取订单计算金额
  1097. * @Author: lun
  1098. * @DateTime: 2022/5/17 0017 11:43
  1099. * @Copyright: copyright (c) 2021 广东七件事集团
  1100. * @param $config
  1101. * @param $order
  1102. * @return mixed
  1103. */
  1104. private static function getComputingConfig($config, $order)
  1105. {
  1106. switch ($config['computing_method']) {
  1107. case DoubleCopyEnum::COMPUTING_METHOD_PAY_PRICE:// 实际支付金额
  1108. $computing_money = $order['goods_price'];
  1109. break;
  1110. case DoubleCopyEnum::COMPUTING_METHOD_GOODS_PRICE:// 商品售价
  1111. $computing_money = $order['original_goods_price'];
  1112. break;
  1113. case DoubleCopyEnum::COMPUTING_METHOD_GOODS_PROFIT:// 商品利润
  1114. $computing_money = $order['goods_price'] - $order['cost_price'] + $order['adjust_money'];;
  1115. break;
  1116. }
  1117. return ['computing_money' => $computing_money, 'multiple' => $order['num']];
  1118. }
  1119. /**
  1120. * 获取推荐的位数
  1121. * @param $mall_id
  1122. * @return void
  1123. */
  1124. public static function getUpgradeNum($mall_id)
  1125. {
  1126. $boss_level = DoubleCopyLevel::find()->select('upgrade_type_condition, checked_condition_values')->where(['mall_id' => $mall_id, 'level' => DoubleCopyEnum::LEVEL_BOSS, 'status' => StatusEnum::ENABLED])->asArray()->one();
  1127. if ($boss_level['upgrade_type_condition'] == 1) {
  1128. // json解析升级条件数量
  1129. $json = Json::decode($boss_level['checked_condition_values'], true);
  1130. self::$upgrade_num = $json[0]['value']['val0'] ?? 0;
  1131. }
  1132. }
  1133. /**
  1134. * 平台补贴极差
  1135. * @param $mall_id
  1136. * @return void
  1137. */
  1138. public static function secondPrizeDiff($user,$computing_config,$level,$basic_params,$goods_id=0){
  1139. $topUser = DoubleCopyUser::find()->where(['user_id' => $user['topid'], 'status' => StatusEnum::ENABLED])->one();
  1140. if(empty($topUser)) return true;
  1141. if($topUser['level'] <= $user['level']){
  1142. self::secondPrizeDiff($topUser,$computing_config,$level,$basic_params,$goods_id);
  1143. }
  1144. // 计算直推奖励金额
  1145. $computing_money = $computing_config['computing_money'];// 支付金额
  1146. $multiple = $computing_config['multiple'];// 商品数量
  1147. $config = $basic_params['setting'];// 基础设置
  1148. $level_config = $level[$topUser['level']];
  1149. if ($level_config['second_prize_type'] == 0) {
  1150. // 按百分比计算
  1151. $money = $computing_money * $level_config['second_prize'] / 100;
  1152. $money = sprintf("%.2f",substr(sprintf("%.3f", $money), 0, -1));// 保留两位小数并不四舍五入
  1153. } else {
  1154. // 按固定金额计算
  1155. $money = $level_config['second_prize'] * $multiple;
  1156. }
  1157. //if ($money <= 0) return [];
  1158. //已发放平级津贴
  1159. $second_original_money = 0;
  1160. foreach (self::$reward as $key => $reward) {
  1161. if(strpos($key, DoubleCopyEnum::SECOND_PRIZE) !== false) {
  1162. $second_original_money += $reward['money'];
  1163. }
  1164. if(strpos($key, DoubleCopyEnum::FREEZE_FUND) !== false) {
  1165. $second_original_money += $reward['money'];
  1166. }
  1167. }
  1168. $money = bcsub($money,$second_original_money,2);
  1169. if ($money > 0){
  1170. // 配置插入
  1171. if (!is_array($basic_params['setting'])) $basic_params['setting'] = json_decode($basic_params['setting'], true);
  1172. $setting = $basic_params['setting'];
  1173. $setting['computing_money'] = $computing_money;
  1174. // 查询是否开启了冻结基金
  1175. $frozen_money = 0;
  1176. if ($topUser['is_thaw'] != 1 && $level_config['freeze_fund_prize'] > 0) {
  1177. // 判断该等级是否开启了解冻阶梯设置
  1178. if (!empty($level[$topUser['level']]['open_ladder'])) {
  1179. $level_config['freeze_fund_prize'] = $level_config['freeze_fund_prize'] * (100 - $topUser['thaw_percent']) / 100;
  1180. }
  1181. // 计算冻结基金
  1182. $frozen_money = $money * $level_config['freeze_fund_prize'] / 100;
  1183. $frozen_money = sprintf("%.2f",substr(sprintf("%.3f", $frozen_money), 0, -1));// 保留两位小数并不四舍五入
  1184. if ($frozen_money > 0) {
  1185. // 生成冻结基金数据
  1186. $setting['freeze_fund_prize'] = $level_config['freeze_fund_prize'];
  1187. $basic_params['setting'] = Json::encode($setting);
  1188. if(self::isLandaHealth($user['topid'],$basic_params['price'],$goods_id,'freeze_fund')){
  1189. self::$reward[DoubleCopyEnum::FREEZE_FUND . '_' . $user['topid']] = array_merge($basic_params, [
  1190. 'user_id' => $user['topid'],
  1191. 'money' => $frozen_money,
  1192. 'capital_type' => DoubleCopyEnum::FREEZE_FUND,
  1193. ]);
  1194. }
  1195. }
  1196. }
  1197. // 生成奖励明细数据
  1198. $setting['second_prize_type'] = $level_config['second_prize_type'];
  1199. $setting['second_prize'] = $level_config['second_prize'];
  1200. $basic_params['setting'] = Json::encode($setting);
  1201. if(self::isLandaHealth($user['topid'],$basic_params['price'],$goods_id,'second_prize')){
  1202. self::$reward[DoubleCopyEnum::SECOND_PRIZE . '_' . $user['topid']] = array_merge($basic_params, [
  1203. 'user_id' => $user['topid'],
  1204. 'original_money' => $money,
  1205. 'money' => $money - $frozen_money,// 可得平台补贴 = 总平台补贴 - 冻结基金
  1206. 'capital_type' => DoubleCopyEnum::SECOND_PRIZE,
  1207. ]);
  1208. }
  1209. }
  1210. self::secondPrizeDiff($topUser,$computing_config,$level,$basic_params,$goods_id);
  1211. }
  1212. /**
  1213. * 复购奖励极差
  1214. * @param $mall_id
  1215. * @return void
  1216. */
  1217. public static function repurchasePrizeDiff($user,$level, $computing_config, $basic_params,$goods_id=0){
  1218. if ($user['pos'] <= self::$upgrade_num) {
  1219. $user_id = $user['topid'];
  1220. }else{
  1221. $user_id = $user['pid'];
  1222. }
  1223. $pUser = DoubleCopyUser::find()->where(['user_id' => $user_id, 'status' => StatusEnum::ENABLED])->one();
  1224. if(empty($pUser)) return true;
  1225. // if($pUser['level'] <= $user['level']){
  1226. // self::repurchasePrizeDiff($pUser,$level, $computing_config, $basic_params);
  1227. // }
  1228. // 计算直推奖励金额
  1229. $computing_money = $computing_config['computing_money'];// 支付金额
  1230. $multiple = $computing_config['multiple'];// 商品数量
  1231. $config = $basic_params['setting'];// 基础设置
  1232. $level_config = $level[$pUser['level']];
  1233. if ($level_config['repurchase_prize_type'] == 0) {
  1234. // 按百分比计算
  1235. $money = $computing_money * $level_config['repurchase_prize'] / 100;
  1236. $money = sprintf("%.2f",substr(sprintf("%.3f", $money), 0, -1));// 保留两位小数并不四舍五入
  1237. } else {
  1238. // 按固定金额计算
  1239. $money = $level_config['repurchase_prize'] * $multiple;
  1240. }
  1241. //if ($money <= 0) return [];
  1242. //已发放复购奖励
  1243. $repurchase_original_money = 0;
  1244. foreach (self::$reward as $key => $reward) {
  1245. if(strpos($key,DoubleCopyEnum::REPURCHASE_PRIZE) !== false) {
  1246. $repurchase_original_money += $reward['money'];
  1247. }
  1248. }
  1249. $money = bcsub($money,$repurchase_original_money,2);
  1250. if ($money > 0){
  1251. // 配置插入
  1252. if (!is_array($basic_params['setting'])) $basic_params['setting'] = json_decode($basic_params['setting'], true);
  1253. $setting = $basic_params['setting'];
  1254. $setting['computing_money'] = $computing_money;
  1255. $setting['repurchase_prize_type'] = $level_config['repurchase_prize_type'];
  1256. $setting['repurchase_prize'] = $level_config['repurchase_prize'];
  1257. $basic_params['setting'] = Json::encode($setting);
  1258. if(self::isLandaHealth($user_id,$basic_params['price'],$goods_id,'repurchase_prize')){
  1259. self::$reward[DoubleCopyEnum::REPURCHASE_PRIZE . '_' . $user_id] = array_merge($basic_params, [
  1260. 'user_id' => $user_id,
  1261. 'original_money' => $money,
  1262. 'money' => $money,
  1263. 'capital_type' => DoubleCopyEnum::REPURCHASE_PRIZE,
  1264. ]);
  1265. }
  1266. }
  1267. self::repurchasePrizeDiff($pUser,$level, $computing_config, $basic_params,$goods_id);
  1268. }
  1269. public static function isLandaHealth($user_id,$price,$goods_id,$type){
  1270. $res = true;
  1271. $user = DoubleCopyUser::find()->where(['user_id' => $user_id, 'status' => StatusEnum::ENABLED])->one();
  1272. $goods_info = Json::decode($user['goods_info'],true);
  1273. $config = Yii::$app->services->setting->addons->get($user['mall_id'], AddonsEnum::ADDONS_LANDA_HEALTH, 'basic');
  1274. $checkedName = [];
  1275. if(isset($config['checkedName'])){
  1276. $checkedName = Json::decode($config['checkedName'],true);
  1277. }
  1278. $goods_ids = [];
  1279. if(isset($config['goods_ids'])){
  1280. $goods_ids = Json::decode($config['goods_ids'],true);
  1281. }
  1282. if (MallAddons::isInstall($user['mall_id'], AddonsEnum::ADDONS_LANDA_HEALTH) == 1 && $goods_id>0 && isset($goods_info['goods_id']) && isset($goods_info['price']) && isset($config['is_enable']) && $config['is_enable']==1 && count($goods_ids)>=2 && in_array($goods_info['goods_id'],$goods_ids) && in_array($goods_id,$goods_ids) && (float)$goods_info['price'] < (float)$price && !in_array($type,$checkedName)) {
  1283. $res = false;
  1284. }
  1285. return $res;
  1286. }
  1287. public static function contributionPrice($order, $basic_params, DoubleCopyUser &$buy_user)
  1288. {
  1289. try {
  1290. if (self::$commission_type !== 'commission') {
  1291. return [];
  1292. }
  1293. //topid 平台补贴计算过程中可能变化,重新获取
  1294. $user = DoubleCopyUser::find()->where(['user_id' => $order['user_id'], 'status' => StatusEnum::ENABLED])->one();
  1295. //需要安装二二复制贡献补贴奖插件
  1296. if (!MallAddons::isInstall($user['mall_id'], AddonsEnum::ADDONS_NAME_DOUBLE_COPY_COMMITMENT_AWARD)) {
  1297. return [];
  1298. }
  1299. $base_setting = Yii::$app->services->setting->addons->get($user['mall_id'], AddonsEnum::ADDONS_NAME_DOUBLE_COPY_COMMITMENT_AWARD, 'basic');
  1300. if (empty($base_setting['is_enable'])) {
  1301. return [];
  1302. }
  1303. $setting_goods_class = \addons\DoubleCopyCommitmentAward\common\models\DoubleCopyCommitmentAwardGoodsSetting::class;
  1304. //获取商品贡献补贴奖设置
  1305. $setting_goods_detail = $setting_goods_class::getOne([
  1306. ['mall_id' => $order['mall_id']],
  1307. ['goods_id' => $order['goods_id']],
  1308. 'status' => StatusEnum::ENABLED
  1309. ], true);
  1310. //商品需要存在于贡献补贴奖商品列表 且 商品需开启贡献补贴奖
  1311. if (empty($setting_goods_detail) || empty($setting_goods_detail['is_reward'])) {
  1312. return [];
  1313. }
  1314. //判断是否存在平台补贴
  1315. if (self::$reward[DoubleCopyEnum::SECOND_PRIZE] && $user['topid']) {
  1316. //商品是否存在独立设置
  1317. if ($setting_goods_detail['is_alone'] == 1) {
  1318. //通过独立设置计算贡献补贴奖
  1319. $setting = $setting_goods_detail;
  1320. $platform_reward_value = $setting_goods_detail['user_reward_value'];
  1321. } else {
  1322. //通过全局设置计算贡献补贴奖
  1323. $setting = $base_setting;
  1324. $platform_reward_value = $base_setting['user_reward_value'];
  1325. }
  1326. //按照获得的平台补贴奖百分比进行计算贡献补贴奖
  1327. $money = bcmul($platform_reward_value / 100, self::$reward[DoubleCopyEnum::SECOND_PRIZE]['money'], 2);
  1328. if ($user['pid'] == $user['topid']) {
  1329. $target_user_id = $order['user_id'];
  1330. } else {
  1331. if ($buy_user->pos <= self::$upgrade_num) {
  1332. $parent_ids = UserPartitionRelationship::getParentIdArr($buy_user['user_id']);
  1333. $parent_ids = array_reverse($parent_ids);// 倒序数组
  1334. foreach ($parent_ids as $key => $pid) {
  1335. // 查询上级是否有身份
  1336. $pdc_user = DoubleCopyUser::find()->select('user_id,pos,pid')->where(['user_id' => $pid, 'status' => StatusEnum::ENABLED])->asArray()->one();
  1337. if (empty($pdc_user)) {
  1338. // 获取当前用户的上级uid
  1339. $ppuid = $parent_ids[$key + 1] ?? 0;
  1340. if ($ppuid) {
  1341. // 统计跟此用户同级人数,并且判断当前用户的平级数量是否大于或等于2号位
  1342. $equal_num = DoubleCopyUser::find()->where(['pid' => $ppuid, 'status' => StatusEnum::ENABLED])->count();
  1343. if ($equal_num >= self::$upgrade_num) {// 符合位置则表示当前用户的上级必定是拿平台补贴用户(拿平台补贴用户可以没有身份)
  1344. $target_user_id = $pid;
  1345. break;
  1346. }
  1347. }
  1348. } else {
  1349. // 如果当前位置是大于或等于3号位则表示此用户上级必定是老板
  1350. if ($pdc_user['pos'] > self::$upgrade_num) {
  1351. $target_user_id = $pdc_user['user_id'];
  1352. break;
  1353. }
  1354. }
  1355. }
  1356. } else {
  1357. $target_user_id = $user['pid'];
  1358. }
  1359. }
  1360. } else {
  1361. if (!empty($user['topid'])) {
  1362. //见点奖用户不为平台,无需处理
  1363. return [];
  1364. }
  1365. if (empty($user['pid'])) {
  1366. $target_user_id = $order['user_id'];
  1367. } else {
  1368. if ($buy_user->pos <= self::$upgrade_num) {
  1369. $parent_ids = UserPartitionRelationship::getParentIdArr($buy_user['user_id']);
  1370. $target_user_id = reset($parent_ids);
  1371. } else {
  1372. $target_user_id = $user['pid'];
  1373. }
  1374. }
  1375. if ($setting_goods_detail['is_alone'] == 1) {
  1376. $setting = $setting_goods_detail;
  1377. //通过独立设置计算贡献补贴奖
  1378. if ($setting_goods_detail['platform_reward_type'] == 1) {
  1379. //商品实付价百分比
  1380. $money = bcmul($setting_goods_detail['platform_reward_value'] / 100, $order['goods_price'], 2);
  1381. } else {
  1382. $money = $setting_goods_detail['platform_reward_value'];
  1383. }
  1384. } else {
  1385. //通过全局设置计算贡献补贴奖
  1386. $setting = $base_setting;
  1387. //商品实付价百分比
  1388. $money = bcmul($base_setting['platform_reward_value'] / 100, $order['goods_price'], 2);
  1389. }
  1390. }
  1391. if ($money <= 0) {
  1392. return [];
  1393. }
  1394. $basic_params['setting'] = Json::encode($setting);
  1395. self::$reward[DoubleCopyEnum::CONTRIBUTION_PRICE] = array_merge($basic_params, [
  1396. 'user_id' => $target_user_id,
  1397. 'original_money' => $money,
  1398. 'money' => $money * 1,// 可得平台补贴贡献奖
  1399. 'capital_type' => DoubleCopyEnum::CONTRIBUTION_PRICE,
  1400. ]);
  1401. return true;
  1402. } catch (\Exception $e) {
  1403. self::setStaticError("平台补贴贡献奖错误:第" . $e->getLine() . '行,原因:' . $e->getMessage());
  1404. return false;
  1405. }
  1406. }
  1407. }