BonusPool.php 139 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\utils\Share;
  8. use app\events\OrderEvent;
  9. use app\models\AgentGoodsInstallLog;
  10. use app\models\BonusPool as ModelsBonusPool;
  11. use app\models\BonusPoolDetail;
  12. use app\models\BonusPoolLevel;
  13. use app\models\Goods;
  14. use app\models\Order;
  15. use app\models\OrderDetail;
  16. use app\models\PtActivityOrder;
  17. use app\models\ReOrder;
  18. use app\models\SaasUser;
  19. use app\models\ShareDetail;
  20. use app\models\ShareHolder;
  21. use app\models\ShareHolderFrostLog;
  22. use app\models\ShareHolderLevelLog;
  23. use app\models\ShareHolderOutLog;
  24. use app\models\ShareHolderLevel;
  25. use app\models\ShareHolderParentOutLog;
  26. use app\models\ShareHolderProfitGoodsLog;
  27. use app\models\ShareHolderSlippedLog;
  28. use app\models\User;
  29. use app\models\UserTreePath;
  30. use app\models\OldUserTreePath;
  31. use app\models\Option;
  32. use app\constants\OptionSetting;
  33. use app\models\AccountLog;
  34. use Exception;
  35. use yii\base\BaseObject;
  36. use yii\helpers\Json;
  37. use app\models\GoodsChainLevel;
  38. use app\utils\FuGou;
  39. use app\models\ShareHolderFugouFrostLog;
  40. /**
  41. * 股东分红
  42. * Class CloudPrint
  43. * @package app\utils\Share
  44. */
  45. class BonusPool
  46. {
  47. // 根据商品id获取订单股东分红基数
  48. // $goodsList = [['id' => 1, 'num' => 2, 'pay_price' => 100], ['id' => 2, 'num' => 3, 'pay_price' => 100]];
  49. public static function getOrderLevelProfit($store_id, array $goodsList)
  50. {
  51. $levels = ShareHolderLevel::find()->where(['store_id' => $store_id, 'is_delete' => 0, 'status' => 1])->select(['id'])->asArray()->all();
  52. $profit = [];
  53. foreach ($levels as $level) {
  54. foreach ($goodsList as $goods) {
  55. $chainLevel = GoodsChainLevel::find()->where(['goods_id' => $goods['id']])->asArray()->one();
  56. if ($chainLevel && (bool)$chainLevel['is_open'] && $chainLevelValue = \json_decode($chainLevel['value'], true)) {
  57. if (isset($chainLevelValue[$level['id']])) {
  58. if ($chainLevel['type'] == 1) { // 固定金额
  59. $profit[$level['id']]['direct'] += $chainLevelValue[$level['id']][0] * $goods['num'];
  60. $profit[$level['id']]['indirect'] += $chainLevelValue[$level['id']][1] * $goods['num'];
  61. } else {
  62. // 百分比
  63. $profit[$level['id']]['direct'] += ($chainLevelValue[$level['id']][0] * $goods['pay_price'] / 100);
  64. $profit[$level['id']]['indirect'] += ($chainLevelValue[$level['id']][1] * $goods['pay_price'] / 100);
  65. }
  66. } else {
  67. $profit[$level['id']]['direct'] += 0;
  68. $profit[$level['id']]['indirect'] += 0;
  69. }
  70. } else {
  71. $profit[$level['id']]['direct'] += 0;
  72. $profit[$level['id']]['indirect'] += 0;
  73. }
  74. }
  75. }
  76. return $profit;
  77. }
  78. public static function checkFrost($user_id)
  79. {
  80. $parent = ShareHolderOutLog::findOne(['parent_user_id' => $user_id]);
  81. if (!$parent) {
  82. return false;
  83. }
  84. $is = ShareHolderOutLog::findOne(['parent_user_id' => $user_id, 'status' => 0]);
  85. return $is ? false : true;
  86. }
  87. /**
  88. * 在发放 链动极差佣金的时候,判断一下购买人的升级产品金额和获得佣金人的升级产品金额,如果获得佣金人的购物金额小于了购买人购物金额,
  89. * 按照获得佣金人购买升级产品的金额进行返佣。
  90. * @param $base_price
  91. * @param $parent_user_id
  92. * @return int|mixed
  93. */
  94. public static function getBasePrice($base_price, $parent_user_id, $store_id, $order_id) {
  95. $shareHolderProfitSwitch = Option::get('shareHolderProfitSwitch', $store_id, 'bonus_pool', 0)['value'];
  96. //当购买低价格产品成为代理后,再推荐高价格代理时,代理可以获取到高价格产品佣金*佣金折扣比例作为分红基数
  97. $shareHolderHighProfit = Option::get('shareHolderHighProfit', $store_id, 'bonus_pool', 0)['value'];
  98. //如果未开启 则系统中的参数比例判定为0
  99. if (!intval($shareHolderProfitSwitch)) {
  100. $shareHolderHighProfit = 0;
  101. }
  102. //获取父级购买的升级最高价产品金额 与当前订单中的最高价商品进行比对 确认是否是小推大
  103. $order_log = ShareHolderProfitGoodsLog::find()->alias('l')->where(['l.user_id' => $parent_user_id, 'l.is_switch' => 1])
  104. ->leftJoin(['o' => Order::tableName()], 'l.order_id = o.id')->andWhere(['o.is_sale' => 1])
  105. ->orderBy('l.goods_price desc')->select('l.order_id, l.goods_id, l.goods_price')->asArray()->one();
  106. if ($order_log) {
  107. //父级购买的升级最高价产品金额
  108. $old_price = $order_log['goods_price'];
  109. } else {
  110. /**
  111. * 如果没有记录就获取父级首次升级成为股东的订单记录
  112. * 获取该订单中最高金额的产品与当前订单中的最高金额商品进行比较
  113. * 如果小于当前订单中的商品金额
  114. * 就表示满足小推大条件
  115. **/
  116. $level_log = ShareHolderLevelLog::find()->where(['AND', ['user_id' => $parent_user_id], ['>', 'order_id', 0]])
  117. ->orderBy('id ASC')->select('order_id')->asArray()->one();
  118. if (!$level_log) {
  119. return $base_price;
  120. }
  121. $old_order_detail_arr = OrderDetail::find()->alias('od')->leftJoin(['g' => Goods::tableName()], 'od.goods_id = g.id')
  122. ->where(['od.order_id' => $level_log['order_id'], 'od.is_delete' => 0])
  123. ->select('od.goods_info, od.attr, g.share_holder_profit_switch, g.share_holder_high_profit, g.id, od.total_price, od.num')->asArray()->all();
  124. $old_price = 0;
  125. /**
  126. * 判断原来的商品是否开启分红 或者 开启独立链动 (防止下单多个大额商品但是非股东分红产品,容易对比失败)
  127. * 因为原来下单时候没有将GoodsChainLevel添加在订单详情表商品信息中的 所以可能会有问题
  128. * 假如一个商品原来没有设置分红也没有开启独立链动 后来才开启独立链动的 从订单详情商品信息中查询不到GoodsChainLevel
  129. * 可能会使用后来添加的独立链动 就判定$open为true了
  130. **/
  131. foreach ($old_order_detail_arr as $order_detail_item) {
  132. $open = false;
  133. $old_goods_info = json_decode($order_detail_item['goods_info'], true);
  134. if (!empty($old_goods_info)) {
  135. //原订单商品开启分红
  136. if ($old_goods_info['rate'] > 0) {
  137. $open = true;
  138. } else {
  139. //未开启分红但是订单信息中存储的有商品独立链动数据
  140. if (!empty($old_goods_info['goods_chain_level'])) {
  141. $goodsChainLevel = $old_goods_info['goods_chain_level'];
  142. if (intval($goodsChainLevel['is_open'])) {
  143. if (!empty($goodsChainLevel['value'])) {
  144. $open = true;
  145. }
  146. }
  147. } else {
  148. //异常情况 假设没有存储商品独立链动数据 就只能使用最新的独立链动数据 来确认是否满足小推大条件
  149. $goodsChainLevel = GoodsChainLevel::findOne(['goods_id' => $order_detail_item['id']]);
  150. if (!empty($goodsChainLevel)) {
  151. if (intval($goodsChainLevel->is_open)) {
  152. $chainLevelValue = json_decode($goodsChainLevel->value, true);
  153. if (!empty($chainLevelValue)) {
  154. $open = true;
  155. }
  156. }
  157. }
  158. }
  159. }
  160. }
  161. //如果满足条件 就选出金额最大的一个商品单价
  162. if ($open) {
  163. $old_price_ = bcdiv($order_detail_item['total_price'], $order_detail_item['num'], 2);
  164. if ($old_price_ > $old_price) {
  165. $old_price = $old_price_;
  166. }
  167. }
  168. }
  169. }
  170. //获取当前订单中的信息
  171. $order_detail_arr = OrderDetail::find()->alias('od')->leftJoin(['g' => Goods::tableName()], 'od.goods_id = g.id')
  172. ->where(['od.order_id' => $order_id, 'od.is_delete' => 0])
  173. ->select('od.goods_info, od.attr, g.share_holder_profit_switch, g.share_holder_high_profit, g.id, od.total_price, od.num')->asArray()->all();
  174. $new_price = 0;
  175. foreach ($order_detail_arr as $order_detail_item) {
  176. //获取当前订单中的商品分红
  177. $goods = Goods::findOne($order_detail_item['id']);
  178. $open = false;
  179. if ($goods->rate > 0) {
  180. $open = true;
  181. } else {
  182. //如果没开启分红就判断是否开启独立链动
  183. $goodsChainLevel = GoodsChainLevel::findOne(['goods_id' => $order_detail_item['id']]);
  184. if (!empty($goodsChainLevel)) {
  185. if (intval($goodsChainLevel->is_open)) {
  186. $chainLevelValue = json_decode($goodsChainLevel->value, true);
  187. if (!empty($chainLevelValue)) {
  188. $open = true;
  189. }
  190. }
  191. }
  192. }
  193. if ($open) {
  194. //如果开启就判断当前订单商品是否开启独立的小推大开关以及设置比例
  195. $goods_info = json_decode($order_detail_item['goods_info'], true);
  196. $is_use_goods_profit = 0;
  197. if (isset($goods_info['share_holder_profit_switch']) &&
  198. intval($goods_info['share_holder_profit_switch']) &&
  199. isset($goods_info['share_holder_high_profit']) &&
  200. floatval($goods_info['share_holder_high_profit']) > 0
  201. ) {
  202. $is_use_goods_profit = 1;
  203. }
  204. $new_price_ = bcdiv($order_detail_item['total_price'], $order_detail_item['num'], 2);
  205. //选出金额最大的 如果开启独立的小推大 就使用独立小推大比例否则就使用系统默认的小推大比例
  206. if ($new_price_ > $new_price) {
  207. $new_price = $new_price_;
  208. if ($is_use_goods_profit) {
  209. $shareHolderHighProfit = floatval($goods_info['share_holder_high_profit']);
  210. } else {
  211. $shareHolderHighProfit = Option::get('shareHolderHighProfit', $store_id, 'bonus_pool', 0)['value'];
  212. $shareHolderProfitSwitch = Option::get('shareHolderProfitSwitch', $store_id, 'bonus_pool', 0)['value'];
  213. if (!intval($shareHolderProfitSwitch)) {
  214. $shareHolderHighProfit = 0;
  215. }
  216. }
  217. }
  218. }
  219. }
  220. //判断小推大是否成立
  221. if ($old_price < $new_price) {
  222. if ($shareHolderHighProfit <= 0) {
  223. return $base_price;
  224. }
  225. $base_price *= ($shareHolderHighProfit / 100);
  226. }
  227. return $base_price;
  228. }
  229. // 获取商品等级佣金
  230. public static function getProfitByOrder($chainLevelValue, $level_id, $back, $is_direct = false, $shareHolderProfit = 0, $isFrost = false, $other_params = [])
  231. {
  232. if ($isFrost && $shareHolderProfit <= 0) {
  233. $back = 0;
  234. }
  235. if (!$chainLevelValue) {
  236. return $back;
  237. }
  238. if (!isset($chainLevelValue[$level_id])) {
  239. return $back;
  240. }
  241. if ($is_direct) {
  242. $basePrice = isset($chainLevelValue[$level_id]['direct']) ? $chainLevelValue[$level_id]['direct'] : 0;
  243. } else {
  244. $basePrice = isset($chainLevelValue[$level_id]['indirect']) ? $chainLevelValue[$level_id]['indirect'] : 0;
  245. }
  246. if ($basePrice > 0) {
  247. if ($other_params) {
  248. $basePrice = self::getBasePrice($basePrice, $other_params['parent_id'], $other_params['store_id'], $other_params['order_id']);
  249. }
  250. if ($isFrost) {
  251. return $shareHolderProfit > 0 ? \round(($shareHolderProfit / 100) * $basePrice, 2) : 0;
  252. }
  253. return $shareHolderProfit > 0 ? \round(((100 - $shareHolderProfit) / 100) * $basePrice, 2) : $basePrice;
  254. }
  255. return $back;
  256. }
  257. /**
  258. * 级差分红
  259. * @param $order_id
  260. * @param $is_send 0 添加未发放 1 发放佣金
  261. * @param $order_type
  262. */
  263. public static function levelShare($order_id, $order_type = 0)
  264. {
  265. if ($order_type == 0) {
  266. $order = Order::findOne($order_id);
  267. }
  268. \Yii::warning('---------------- 级差分红计算开始 -------------------');
  269. // 判断是否开启奖金池
  270. $setting = [
  271. 'cycle' => Option::get('cycle', $order->store_id, 'bonus_pool', 0)['value'],
  272. // 'is_open_share' => Option::get('is_open_share', $order->store_id, 'bonus_pool', 0)['value'],
  273. // 'is_open_range' => Option::get('is_open_range', $order->store_id, 'bonus_pool', 0)['value'],
  274. 'team_num' => Option::get('team_num', $order->store_id, 'bonus_pool', 0)['value']
  275. ];
  276. // if (!$setting['is_open_range']) {
  277. // \Yii::warning('---------------- 未开启级差分红 -------------------');
  278. // return;
  279. // }
  280. self::oldLevelShare($order);
  281. $base_price = $order->profit;
  282. $user_parent = OldUserTreePath::find()->alias('ut')
  283. ->where(['ut.child_id' => $order->user_id])
  284. // ->leftJoin(['h' => ShareHolder::tableName()], 'ut.parent_id=h.user_id')
  285. // ->andWhere('h.id is not null')
  286. ->andWhere('ut.child_id != ut.parent_id')
  287. // ->andWhere(['h.is_delete' => 0, 'h.status' => 1])
  288. ->orderBy(['ut.parent_level' => SORT_DESC])
  289. ->asArray()
  290. ->select(['ut.*'])
  291. ->all();
  292. // 已分销比例
  293. $share_num = 0;
  294. $level_id = 0;
  295. $shareHolderProfit = Option::get('shareHolderProfit', $order->store_id, 'bonus_pool', 0)['value'];
  296. //冻结层级(等级)
  297. $shareHolderLevel = Option::get('shareHolderLevel', $order->store_id, 'bonus_pool', 0)['value'];
  298. //冻结团队佣金(层数)
  299. $shareHolderNumber = Option::get('shareHolderNumber', $order->store_id, 'bonus_pool', [])['value'];
  300. if (is_string($shareHolderNumber)) {
  301. if (strpos($shareHolderNumber, ',') !== false) {
  302. $shareHolderNumber = explode(',', $shareHolderNumber);
  303. } else {
  304. $shareHolderNumber = [];
  305. }
  306. }
  307. if ($shareHolderLevel > 0 && is_array($shareHolderNumber) && count($shareHolderNumber) == 2) {
  308. $shareHolderNumber = range($shareHolderNumber[0], $shareHolderNumber[1]);
  309. } else {
  310. $shareHolderNumber = [];
  311. }
  312. $t = \Yii::$app->db->beginTransaction();
  313. $level_price = $order->pay_price - $order->express_price;
  314. $user = User::findOne($order->user_id);
  315. if ($order->level_price_json) {
  316. $level_price_arr = json_decode($order->level_price_json, true);
  317. if (!empty($level_price_arr)) {
  318. if (isset($level_price_arr['member' . $user->level])) {
  319. $level_price = $level_price_arr['member' . $user->level];
  320. }
  321. }
  322. }
  323. foreach($user_parent as $val) {
  324. $shareHolder = ShareHolder::findOne(['user_id' => $val['parent_id'], 'is_delete' => 0, 'status' => 1]);
  325. if (!$shareHolder) {
  326. continue;
  327. }
  328. $level = ShareHolderLevel::findOne(['id' => $shareHolder->level_id, 'is_delete' => 0]);
  329. if ($level) {
  330. $teamParent = User::findOne($val['parent_id']);
  331. if (!empty($level_price_arr) && intval($level->range_rate_type) === 1) {
  332. if ($level_price_arr['member' . $teamParent->level] > 0 && $level_price > $level_price_arr['member' . $teamParent->level] && $level->is_user_level_range_rate == 1) {
  333. $equal_price = sprintf("%.2f", ($level_price - $level_price_arr['member' . $teamParent->level]));
  334. $level_price = $level_price_arr['member' . $teamParent->level];
  335. $detail = ShareDetail::findOne(['type_id' => $order_id, 'type' => ShareDetail::TYPE_RANGE_PROFIT_OLD_USER_LEVEL, 'user_id' => $val['parent_id']]);
  336. if (!$detail) {
  337. $detail = new ShareDetail();
  338. $detail->store_id = $order->store_id;
  339. $detail->type_id = $order_id;
  340. $detail->type = ShareDetail::TYPE_RANGE_PROFIT_OLD_USER_LEVEL;
  341. $detail->user_id = $val['parent_id'];
  342. $detail->desc = '订单号:' . $order->order_no . '极差分红_会员(原关系)';
  343. }
  344. $detail->money = $equal_price;
  345. $detail->is_send = 0;
  346. if (!$detail->save()) {
  347. $t->rollBack();
  348. \Yii::warning(['---------------- 极差分红_会员分红奖励计算入库失败 -------------------', $detail->errors]);
  349. return;
  350. }
  351. }
  352. continue;
  353. }
  354. if ($level_id == $level->id) {
  355. // 同级别奖励
  356. //计算冻结后金额
  357. $equal_price = round($base_price * $level->equal_rate / 100, 2);
  358. if ($shareHolderProfit > 0 && !static::checkFrost($val['parent_id'])) {
  359. if ($shareHolderLevel > 0 && !empty($shareHolderNumber)) {
  360. if ((int)$shareHolderLevel === (int)$level['id'] && in_array($val['parent_level'], $shareHolderNumber)) {
  361. $equal_price = round(((100 - $shareHolderProfit) / 100) * $base_price * $level->equal_rate / 100, 2);
  362. }
  363. } else {
  364. $equal_price = round(((100 - $shareHolderProfit) / 100) * $base_price * $level->equal_rate / 100, 2);
  365. }
  366. }
  367. if ($equal_price > 0) {
  368. $detail = ShareDetail::findOne(['type_id' => $order_id, 'type' => ShareDetail::TYPE_RANGE_PROFIT_OLD, 'user_id' => $val['parent_id']]);
  369. if (!$detail) {
  370. $detail = new ShareDetail();
  371. $detail->store_id = $order->store_id;
  372. $detail->type_id = $order_id;
  373. $detail->type = ShareDetail::TYPE_RANGE_PROFIT_OLD;
  374. $detail->user_id = $val['parent_id'];
  375. $detail->desc = '订单号:' . $order->order_no . '同等级奖励分红(原关系)';
  376. }
  377. $detail->money = $equal_price;
  378. $detail->is_send = 0;
  379. if (!$detail->save()) {
  380. $t->rollBack();
  381. \Yii::warning(['---------------- 同等级分红奖励计算入库失败 -------------------', $detail->errors]);
  382. return;
  383. }
  384. }
  385. //计算冻结金额
  386. if ($shareHolderProfit > 0 && !static::checkFrost($val['parent_id'])) {
  387. $open = false;
  388. if ($shareHolderLevel > 0 && !empty($shareHolderNumber)) {
  389. if ((int)$shareHolderLevel === (int)$level['id'] && in_array($val['parent_level'], $shareHolderNumber)) {
  390. $open = true;
  391. }
  392. } else {
  393. $open = true;
  394. }
  395. if ($open) {
  396. $frost_price = round(($shareHolderProfit / 100) * $base_price * $level->equal_rate / 100, 2);
  397. if ($frost_price > 0) {
  398. $model = new ShareHolderFrostLog();
  399. $model->parent_user_id = $val['parent_id'];
  400. $model->child_user_id = $order->user_id;
  401. $model->amount = $frost_price;
  402. $model->status = 0;
  403. $model->order_id = $order_id;
  404. if (!$model->save()) {
  405. $t->rollBack();
  406. \Yii::warning(['---------------- 级差分红发放冻结佣金失败 -------------------', $model->errors]);
  407. return;
  408. };
  409. }
  410. }
  411. }
  412. // 链动直推团队收益奖励(同等级)
  413. // $min_team_price = Option::get('shareHolderPriceMin', $order->store_id, 'bonus_pool', 0)['value'];
  414. // $remark = '链动直推团队同等级收益奖励分红';
  415. // $team_price = round($base_price * $level->equal_rate / 100, 2);
  416. // $type = ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT_OLD;
  417. // $setShareDetail = self::setShareDetail(null, $order, $team_price, $teamParent, $min_team_price, $remark, $type);
  418. // if (!$setShareDetail) {
  419. // $t->rollBack();
  420. // \Yii::error([__METHOD__, '递归分红失败,回滚']);
  421. // return;
  422. // }
  423. // if ($teamParent && $teamParent->old_parent_id > 0) {
  424. // $teamShareHolderSelf = ShareHolder::findOne(['user_id' => $teamParent->id, 'is_delete' => 0, 'status' => 1]);
  425. // $teamShareHolder = ShareHolder::findOne(['user_id' => $teamParent->old_parent_id, 'is_delete' => 0, 'status' => 1]);
  426. //
  427. // if ($teamShareHolder && $teamShareHolder->is_out == 1 && $teamShareHolderSelf->is_out == 1) {
  428. // $teamShareHolderLevel = ShareHolderLevel::findOne(['id' => $teamShareHolder->level_id, 'is_delete' => 0]);
  429. // if ($teamShareHolderLevel && $teamShareHolderLevel->team_reward_rate > 0) {
  430. // //计算冻结后金额
  431. // $team_price = round(round($base_price * $level->equal_rate / 100, 2) * $teamShareHolderLevel->team_reward_rate / 100, 2);
  432. //
  433. // if ($team_price > 0) {
  434. // $detail = ShareDetail::findOne(['type_id' => $order_id, 'type' => ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT_OLD, 'user_id' => $teamParent->old_parent_id]);
  435. // if (!$detail) {
  436. // $detail = new ShareDetail();
  437. // $detail->store_id = $order->store_id;
  438. // $detail->type_id = $order_id;
  439. // $detail->type = ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT_OLD;
  440. // $detail->user_id = $teamParent->old_parent_id;
  441. // $detail->desc = '订单号:' . $order->order_no . '链动直推团队同等级收益奖励分红';
  442. // }
  443. // $detail->money = $team_price;
  444. // $detail->is_send = 0;
  445. // if (!$detail->save()) {
  446. // $t->rollBack();
  447. // return;
  448. // }
  449. // }
  450. // }
  451. // }
  452. // }
  453. // }
  454. $level_id = 0;
  455. }
  456. if ($level->range_rate >= $share_num) {
  457. $range_rate = $level->range_rate - $share_num;
  458. $share_num = $level->range_rate;
  459. $price = round($base_price * $range_rate / 100, 2);
  460. if ($shareHolderProfit > 0 && !static::checkFrost($val['parent_id'])) {
  461. if ($shareHolderLevel > 0 && !empty($shareHolderNumber)) {
  462. if ((int)$shareHolderLevel === (int)$level['id'] && in_array($val['parent_level'], $shareHolderNumber)) {
  463. $price = round(((100 - $shareHolderProfit) / 100) * $base_price * $range_rate / 100, 2);
  464. }
  465. } else {
  466. $price = round(((100 - $shareHolderProfit) / 100) * $base_price * $range_rate / 100, 2);
  467. }
  468. }
  469. if ($price > 0) {
  470. $detail = ShareDetail::findOne(['type_id' => $order_id, 'type' => ShareDetail::TYPE_RANGE_PROFIT_OLD, 'user_id' => $val['parent_id']]);
  471. if (!$detail) {
  472. $old_range_name = Option::get('old_range_name', $order->store_id, 'bonus_pool', '')['value'];
  473. $detail = new ShareDetail();
  474. $detail->store_id = $order->store_id;
  475. $detail->type_id = $order_id;
  476. $detail->type = ShareDetail::TYPE_RANGE_PROFIT_OLD;
  477. $detail->user_id = $val['parent_id'];
  478. $detail->desc = '订单号:'.$order->order_no. ($old_range_name ?: '级差分红(原关系)');////////////
  479. }
  480. $level_id = $level->id;
  481. $detail->money = $price;
  482. $detail->is_send = 0;
  483. if (!$detail->save()) {
  484. $t->rollBack();
  485. \Yii::warning(['---------------- 级差分红计算入库失败 -------------------', $detail->errors]);
  486. return;
  487. }
  488. }
  489. if ($shareHolderProfit > 0 && !static::checkFrost($val['parent_id'])) {
  490. $open = false;
  491. if ($shareHolderLevel > 0 && !empty($shareHolderNumber)) {
  492. if ((int)$shareHolderLevel === (int)$level['id'] && in_array($val['parent_level'], $shareHolderNumber)) {
  493. $open = true;
  494. }
  495. } else {
  496. $open = true;
  497. }
  498. if ($open) {
  499. $frost_price = round(round($base_price * $range_rate / 100, 2) * ($shareHolderProfit / 100), 2);
  500. if ($frost_price > 0) {
  501. $model = new ShareHolderFrostLog();
  502. $model->parent_user_id = $val['parent_id'];
  503. $model->child_user_id = $order->user_id;
  504. $model->amount = $frost_price;
  505. $model->status = 0;
  506. $model->order_id = $order->id;
  507. if (!$model->save()) {
  508. $t->rollBack();
  509. \Yii::warning(['---------------- 级差分红发放冻结佣金失败 -------------------', $model->errors]);
  510. return;
  511. };
  512. }
  513. }
  514. }
  515. // 链动直推团队收益奖励
  516. // $min_team_price = Option::get('shareHolderPriceMin', $order->store_id, 'bonus_pool', 0)['value'];
  517. // $direct_range_name = Option::get('old_add_holder_name', $order->store_id, 'bonus_pool', '')['value'];
  518. // $remark = $direct_range_name ? $direct_range_name : '链动直推团队级差收益奖励分红';
  519. // $team_price = round($base_price * $range_rate / 100, 2);
  520. // $type = ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT_OLD;
  521. // $setShareDetail = self::setShareDetail(null, $order, $team_price, $teamParent, $min_team_price, $remark, $type);
  522. // if (!$setShareDetail) {
  523. // $t->rollBack();
  524. // \Yii::error([__METHOD__, '递归分红失败,回滚']);
  525. // return;
  526. // }
  527. // if ($teamParent && $teamParent->old_parent_id > 0) {
  528. // $teamShareHolderSelf = ShareHolder::findOne(['user_id' => $teamParent->id, 'is_delete' => 0, 'status' => 1]);
  529. // $teamShareHolder = ShareHolder::findOne(['user_id' => $teamParent->old_parent_id, 'is_delete' => 0, 'status' => 1]);
  530. // if ($teamShareHolder && $teamShareHolder->is_out == 1 && $teamShareHolderSelf->is_out == 1) {
  531. // $teamShareHolderLevel = ShareHolderLevel::findOne(['id' => $teamShareHolder->level_id, 'is_delete' => 0]);
  532. // if ($teamShareHolderLevel && $teamShareHolderLevel->team_reward_rate > 0) {
  533. // $team_price = round(round($base_price * $range_rate / 100, 2) * $teamShareHolderLevel->team_reward_rate / 100, 2);
  534. //
  535. // if ($team_price > 0) {
  536. // $detail = ShareDetail::findOne(['type_id' => $order_id, 'type' => ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT_OLD, 'user_id' => $teamParent->old_parent_id]);
  537. // if (!$detail) {
  538. // $detail = new ShareDetail();
  539. // $detail->store_id = $order->store_id;
  540. // $detail->type_id = $order_id;
  541. // $detail->type = ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT_OLD;
  542. // $detail->user_id = $teamParent->old_parent_id;
  543. // $detail->desc = '订单号:' . $order->order_no . '链动直推团队级差收益奖励分红';
  544. // }
  545. // $detail->money = $team_price;
  546. // $detail->is_send = 0;
  547. // if (!$detail->save()) {
  548. // $t->rollBack();
  549. // return;
  550. // }
  551. // }
  552. // }
  553. // }
  554. // }
  555. // }
  556. }
  557. }
  558. }
  559. $t->commit();
  560. \Yii::warning('---------------- 级差分红计算结束 -------------------');
  561. }
  562. // 链动关系级差分红
  563. public static function oldLevelShare($order)
  564. {
  565. $base_price = $order->chain_profit;
  566. $user_parent = UserTreePath::find()->alias('ut')
  567. ->where(['ut.child_id' => $order->user_id])
  568. ->leftJoin(['h' => ShareHolder::tableName()], 'ut.parent_id=h.user_id')
  569. ->andWhere('h.id is not null')
  570. ->andWhere('ut.child_id != ut.parent_id')
  571. ->andWhere(['h.is_delete' => 0, 'h.status' => 1])
  572. ->orderBy(['ut.parent_level' => SORT_DESC])
  573. ->asArray()
  574. ->select(['ut.*', 'h.level_id'])
  575. ->all();
  576. $share_num = 0;
  577. $level_id = 0;
  578. $shareHolderTeamRewardPlatformBears = Option::get('shareHolderTeamRewardPlatformBears', $order->store_id, 'bonus_pool', 1)['value'];
  579. $shareHolderProfit = Option::get('shareHolderProfit', $order->store_id, 'bonus_pool', 0)['value'];
  580. //冻结层级(等级)
  581. $shareHolderLevel = Option::get('shareHolderLevel', $order->store_id, 'bonus_pool', 0)['value'];
  582. //冻结团队佣金(层数)//得到层数如 3-8层冻结佣金
  583. $shareHolderNumber = Option::get('shareHolderNumber', $order->store_id, 'bonus_pool', [])['value'];
  584. if (is_string($shareHolderNumber)) {
  585. if (strpos($shareHolderNumber, ',') !== false) {
  586. $shareHolderNumber = explode(',', $shareHolderNumber);
  587. } else {
  588. $shareHolderNumber = [];
  589. }
  590. }
  591. if (is_array($shareHolderNumber) && count($shareHolderNumber) == 2) {
  592. $shareHolderNumber = range($shareHolderNumber[0], $shareHolderNumber[1]);
  593. } else {
  594. $shareHolderNumber = [];
  595. }
  596. $chainLevelValue = \json_decode($order->chain_level_value, true);
  597. $shareHolderJiandian = Option::get('shareHolderJiandian', $order->store_id, 'bonus_pool', 0)['value'];
  598. $t = \Yii::$app->db->beginTransaction();
  599. $ii = 0; // 层级
  600. foreach($user_parent as $index => $val) {
  601. $ii++;
  602. if ($shareHolderJiandian > 0 && $ii > 1) {
  603. if ($ii != $shareHolderJiandian) {
  604. continue;
  605. }
  606. $shareHolder = ShareHolder::findOne(['user_id' => $val['parent_id'], 'is_delete' => 0, 'status' => 1]);
  607. if (!$shareHolder) {
  608. $t->commit();
  609. return;
  610. }
  611. if ($shareHolder->is_out == 0) {
  612. $t->commit();
  613. return;
  614. }
  615. }
  616. $base_price = self::getBasePrice($base_price, $val['parent_id'], $order->store_id, $order->id);
  617. $level = ShareHolderLevel::findOne(['id' => $val['level_id'], 'is_delete' => 0]);
  618. if ($level) {
  619. $teamParent = User::findOne($val['parent_id']);
  620. //检测是否复购
  621. $order_d = OrderDetail::find()->alias('od')->where(['o.store_id' => $order->store_id, 'o.is_pay' => 1, 'o.user_id' => $order->user_id])
  622. ->leftJoin(['o' => Order::tableName()], 'o.id = od.order_id')
  623. ->leftJoin(['g' => Goods::tableName()], 'g.id = od.goods_id')
  624. ->andWhere(['<', 'order_id', $order->id])->select('od.id')
  625. ->orderBy('od.id desc')->asArray()->one();
  626. $old_range_rate = $level->old_range_rate;
  627. if ($order_d && $level->old_repeat_range_rate > 0) {
  628. $old_range_rate = $level->old_repeat_range_rate;
  629. }
  630. if ($old_range_rate >= $share_num) {
  631. $range_rate = $old_range_rate - $share_num;
  632. $share_num = $old_range_rate;
  633. $price = round($base_price * $range_rate / 100, 2);
  634. $params = [
  635. 'parent_id' => $val['parent_id'],
  636. 'store_id' => $order->store_id,
  637. 'order_id' => $order->id
  638. ];
  639. $price = self::getProfitByOrder($chainLevelValue, $val['level_id'], $price, $index == 0, 0, false, $params);
  640. if ($shareHolderProfit > 0 && !static::checkFrost($val['parent_id'])) {
  641. if ($shareHolderLevel > 0 && !empty($shareHolderNumber)) {
  642. if ((int)$shareHolderLevel === (int)$level['id'] && in_array($val['parent_level'], $shareHolderNumber)) {
  643. $price = round(((100 - $shareHolderProfit) / 100) * $base_price * $range_rate / 100, 2);
  644. $price = self::getProfitByOrder($chainLevelValue, $val['level_id'], $price, $index == 0, $shareHolderProfit, false, $params);
  645. }
  646. } else {
  647. $price = round(((100 - $shareHolderProfit) / 100) * $base_price * $range_rate / 100, 2);
  648. $price = self::getProfitByOrder($chainLevelValue, $val['level_id'], $price, $index == 0, $shareHolderProfit, false, $params);
  649. }
  650. }
  651. $detail = null;
  652. if ($price > 0) {
  653. $fuGouSetting = FuGou::getSetting($order->store_id);
  654. $isFugou = $fuGouSetting['fugou_switch'] > 0 && FuGou::isFugou($val['parent_id'], $order->store_id, $fuGouSetting);
  655. $fugou = false;
  656. if ($isFugou) {
  657. $fugouOpen = true;
  658. $fugouRand = \range($fuGouSetting['fugou_freeze_rand'][0], $fuGouSetting['fugou_freeze_rand'][1]);
  659. if ($fuGouSetting['fugou_freeze_level'] > 0) {
  660. if (
  661. (int)$fuGouSetting['fugou_freeze_level'] === (int)$level['id'] &&
  662. false === \in_array($val['parent_level'], $fugouRand)
  663. ) {
  664. // 如果选了指定等级并且没在范围内, 就不冻结
  665. $fugouOpen = false;
  666. }
  667. }
  668. if ($fugouOpen) {
  669. $fugou = true;
  670. $frostLog = new ShareHolderFugouFrostLog();
  671. $frostLog->user_id = $val['parent_id'];
  672. $frostLog->amount = $price;
  673. $frostLog->status = 0;
  674. $frostLog->order_id = $order->id;
  675. $frostLog->save();
  676. }
  677. }
  678. $detail = ShareDetail::findOne(['type_id' => $order->id, 'type' => ShareDetail::TYPE_RANGE_PROFIT, 'user_id' => $val['parent_id']]);
  679. if (!$detail) {
  680. $range_name = Option::get('range_name', $order->store_id, 'bonus_pool', '')['value'];
  681. $detail = new ShareDetail();
  682. $detail->store_id = $order->store_id;
  683. $detail->type_id = $order->id;
  684. $detail->type = ShareDetail::TYPE_RANGE_PROFIT;
  685. $detail->user_id = $val['parent_id'];
  686. $detail->desc = '订单号:'.$order->order_no. ($range_name ?: '级差分红');/////////////////
  687. }
  688. $detail->is_fugou = $fugou ? 1 : 0;
  689. $detail->money = $price;
  690. $detail->is_send = 0;
  691. if (!$detail->save()) {
  692. $t->rollBack();
  693. \Yii::warning(['---------------- (原关系)级差分红计算入库失败 -------------------', $detail->errors]);
  694. return;
  695. }
  696. }
  697. if ($shareHolderProfit > 0 && !static::checkFrost($val['parent_id'])) {
  698. $open = false;
  699. if ($shareHolderLevel > 0 && !empty($shareHolderNumber)) {
  700. if ((int)$shareHolderLevel === (int)$level['id'] && in_array($val['parent_level'], $shareHolderNumber)) {
  701. $open = true;
  702. }
  703. } else {
  704. $open = true;
  705. }
  706. if ($open) {
  707. $frost_price = round(round($base_price * $range_rate / 100, 2) * ($shareHolderProfit / 100), 2);
  708. $frost_price = self::getProfitByOrder($chainLevelValue, $val['level_id'], $frost_price, $index == 0, $shareHolderProfit, true, $params);
  709. if ($frost_price > 0) {
  710. $model = new ShareHolderFrostLog();
  711. $model->parent_user_id = $val['parent_id'];
  712. $model->child_user_id = $order->user_id;
  713. $model->amount = $frost_price;
  714. $model->status = 0;
  715. $model->order_id = $order->id;
  716. if (!$model->save()) {
  717. $t->rollBack();
  718. \Yii::warning(['---------------- 级差分红发放冻结佣金失败 -------------------', $model->errors]);
  719. return;
  720. };
  721. }
  722. }
  723. }
  724. // 链动直推团队收益奖励
  725. $min_team_price = Option::get('shareHolderPriceMin', $order->store_id, 'bonus_pool', 0)['value'];
  726. $shareHolderPriceLevel = Option::get('shareHolderPriceLevel', $order->store_id, 'bonus_pool', 0)['value'];
  727. $direct_range_name = Option::get('direct_range_name', $order->store_id, 'bonus_pool', '')['value'];
  728. $remark = $direct_range_name ? $direct_range_name : '链动直推团队级差收益奖励分红';
  729. $team_price = $price;
  730. $type = ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT;
  731. // 判断当前直推层级是否在后台设置的直推团队收益发放层级之内
  732. // if ($shareHolderPriceLevel == 0 || $ii <= (int)$shareHolderPriceLevel) {
  733. $setShareDetail = self::setShareDetail($shareHolderTeamRewardPlatformBears ? null : $detail, $order, $team_price, $teamParent, $min_team_price, $remark, $type);
  734. if (!$setShareDetail) {
  735. $t->rollBack();
  736. \Yii::error([__METHOD__, '递归分红失败,回滚']);
  737. return;
  738. }
  739. // }
  740. }
  741. }
  742. }
  743. $t->commit();
  744. }
  745. public static function setJiandian($teamParent, $level, $currentLevel = 1)
  746. {
  747. // 递归获取上级信息
  748. if ($level == $currentLevel) {
  749. return $teamParent;
  750. }
  751. if ($teamParent->old_parent_id == 0) {
  752. return null;
  753. }
  754. $teamParent = User::findOne($teamParent->old_parent_id);
  755. return self::setJiandian($teamParent, $level, $currentLevel + 1);
  756. }
  757. // 链动直推团队收益奖励
  758. public static function setShareDetail($shareDetail = null, $order, $team_price, $teamParent, $min_team_price = 10, $remark = '', $type = 0) {
  759. $shareHolderPriceLevel = Option::get('shareHolderPriceLevel', $order->store_id, 'bonus_pool', 0)['value'];
  760. $detailCount = ShareDetail::find()->where(['type_id' => $order->id, 'type' => $type])->count() ?: 0;
  761. if ($shareHolderPriceLevel > 0 && $detailCount >= $shareHolderPriceLevel) {
  762. return true;
  763. }
  764. if ($teamParent && $teamParent->old_parent_id > 0) {
  765. $teamShareHolderSelf = ShareHolder::findOne(['user_id' => $teamParent->id, 'is_delete' => 0, 'status' => 1]);
  766. $teamShareHolder = ShareHolder::findOne(['user_id' => $teamParent->old_parent_id, 'is_delete' => 0, 'status' => 1]);
  767. if ($teamShareHolder && $teamShareHolder->is_out == 1 && $teamShareHolderSelf->is_out == 1) {
  768. $teamShareHolderUser = User::findOne($teamShareHolder->user_id);
  769. if ($teamShareHolderUser->parent_id > 0) {
  770. return true;
  771. }
  772. // \Yii::error(['--setShareDetail--', $teamShareHolder]);
  773. // if ($teamShareHolder) {
  774. $teamShareHolderLevel = ShareHolderLevel::findOne(['id' => $teamShareHolder->level_id, 'is_delete' => 0]);
  775. // \Yii::error(['--setShareDetail--', $teamShareHolderLevel]);
  776. if ($teamShareHolderLevel && $teamShareHolderLevel->team_reward_rate > 0) {
  777. $team_price = round($team_price * $teamShareHolderLevel->team_reward_rate / 100, 2);
  778. //小于最小分红金额,退出
  779. if ($team_price <= $min_team_price) {
  780. return true;
  781. }
  782. if ($team_price > 0) {
  783. $detail = ShareDetail::findOne(['type_id' => $order->id, 'type' => $type, 'user_id' => $teamParent->old_parent_id]);
  784. if (!$detail) {
  785. $detail = new ShareDetail();
  786. $detail->store_id = $order->store_id;
  787. $detail->type_id = $order->id;
  788. $detail->type = $type;
  789. $detail->user_id = $teamParent->old_parent_id;
  790. $detail->desc = '订单号:' . $order->order_no . $remark;
  791. }
  792. $detail->money = $team_price;
  793. $detail->is_send = 0;
  794. if (!$detail->save()) {
  795. \Yii::error([__METHOD__, array_shift($detail->getFirstErrors())]);
  796. return false;
  797. }
  798. if($shareDetail){
  799. $shareDetail->money -= $detail->money;
  800. $shareDetail->desc .= '-[感恩上级:¥' . $detail->money . '('. $detail->id . ')]';
  801. if (!$shareDetail->save()) {
  802. \Yii::error([__METHOD__, array_shift($shareDetail->getFirstErrors())]);
  803. return false;
  804. }
  805. $shareDetail = $detail;
  806. }
  807. }
  808. }
  809. $teamParent = User::findOne($teamParent['old_parent_id']);
  810. return self::setShareDetail($shareDetail, $order, $team_price, $teamParent, $min_team_price, $remark, $type);
  811. }
  812. }
  813. return true;
  814. }
  815. public static function sendRangePoint($user, $share_detail, $shareHolderRewardPointRate, $STORE_INTEGRAL) {
  816. $money = $share_detail->money;
  817. $point = round($money * $shareHolderRewardPointRate / 100, 2);
  818. $money -= $point;
  819. $integral = $point * $STORE_INTEGRAL;
  820. $user->updateCounters(['total_price' => $money, 'price' => $money]);
  821. $share_detail->desc .= '{[积分占比:'. $shareHolderRewardPointRate .'%][发放佣金:¥'. $money .'][发放积分:'. $integral .'('. $point .'*'. $STORE_INTEGRAL .')]}';
  822. AccountLog::saveLog($user->id, $integral, AccountLog::TYPE_INTEGRAL, AccountLog::LOG_TYPE_INCOME, 0, 0, $share_detail->desc);
  823. }
  824. /**
  825. * 发放级差分红
  826. */
  827. public static function sendRange($order_id) {
  828. \Yii::warning(['------------ 发放级差分红开始, 订单id:' . $order_id .'-------------']);
  829. $list = ShareDetail::find()->where(['type_id' => $order_id, 'is_fugou' => 0, 'type' => [ShareDetail::TYPE_RANGE_PROFIT, ShareDetail::TYPE_RANGE_PROFIT_OLD, ShareDetail::TYPE_RANGE_PROFIT_OLD_USER_LEVEL], 'is_send' => 0, 'is_delete' => 0])->all();
  830. if ($list) {
  831. $t = \Yii::$app->db->beginTransaction();
  832. $store_id = $list[0]['store_id'];
  833. $STORE_INTEGRAL = Option::get(OptionSetting::STORE_INTEGRAL, $store_id, 'gift', Option::get(OptionSetting::STORE_INTEGRAL, $store_id, 'store', 100)['value'])['value'];
  834. $shareHolderRewardPointRate = Option::get('shareHolderRewardPointRate', $store_id, 'bonus_pool', 0)['value'];
  835. foreach ($list as $share_detail) {
  836. /**
  837. * @var $share_detail ShareDetail
  838. */
  839. $user = User::findOne($share_detail->user_id);
  840. if($shareHolderRewardPointRate && in_array($share_detail->type, [ShareDetail::TYPE_RANGE_PROFIT, ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT])){
  841. self::sendRangePoint($user, $share_detail, $shareHolderRewardPointRate, $STORE_INTEGRAL);
  842. }else{
  843. $user->updateCounters(['total_price' => $share_detail->money, 'price' => $share_detail->money]);
  844. }
  845. $share_detail->is_send = 1;
  846. $share_detail->send_time = time();
  847. if (!$share_detail->save()) {
  848. $t->rollBack();
  849. \Yii::warning(['------------ 发放级差分红状态更改失败:-------------', $share_detail->errors]);
  850. return;
  851. }
  852. }
  853. $t->commit();
  854. \Yii::warning(['------------ 发放级差分红成功, 订单id:' . $order_id .'-------------']);
  855. }
  856. }
  857. /**
  858. * 发放2+1股东团队分红
  859. */
  860. public static function sendTwoPlusOneTeamLevelShare($order_id) {
  861. \Yii::warning(['------------ 发放2+1团队分红开始, 订单id:' . $order_id .'-------------']);
  862. $list = ShareDetail::find()->where(['type_id' => $order_id, 'type' => [ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT, ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT_OLD, ShareDetail::TYPE_RANGE_PROFIT_OLD_USER_LEVEL], 'is_send' => 0, 'is_delete' => 0])->all();
  863. if ($list) {
  864. $t = \Yii::$app->db->beginTransaction();
  865. $store_id = $list[0]['store_id'];
  866. $STORE_INTEGRAL = Option::get(OptionSetting::STORE_INTEGRAL, $store_id, 'gift', Option::get(OptionSetting::STORE_INTEGRAL, $store_id, 'store', 100)['value'])['value'];
  867. $shareHolderRewardPointRate = Option::get('shareHolderRewardPointRate', $store_id, 'bonus_pool', 0)['value'];
  868. foreach ($list as $share_detail) {
  869. /**
  870. * @var $share_detail ShareDetail
  871. */
  872. $user = User::findOne($share_detail->user_id);
  873. if($shareHolderRewardPointRate && in_array($share_detail->type, [ShareDetail::TYPE_RANGE_PROFIT, ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT])){
  874. self::sendRangePoint($user, $share_detail, $shareHolderRewardPointRate, $STORE_INTEGRAL);
  875. }else{
  876. $user->updateCounters(['total_price' => $share_detail->money, 'price' => $share_detail->money]);
  877. }
  878. $share_detail->is_send = 1;
  879. $share_detail->send_time = time();
  880. if (!$share_detail->save()) {
  881. $t->rollBack();
  882. \Yii::warning(['------------ 发放2+1团队分红状态更改失败:-------------', $share_detail->errors]);
  883. return;
  884. }
  885. }
  886. $t->commit();
  887. \Yii::warning(['------------ 发放2+1团队分红成功, 订单id:' . $order_id .'-------------']);
  888. }
  889. }
  890. /**
  891. * 发放区域分红
  892. */
  893. public static function sendArea($order_id) {
  894. \Yii::warning(['------------ 发放代理分红开始, 订单id:' . $order_id .'-------------']);
  895. $list = ShareDetail::find()->where(['type_id' => $order_id, 'type' => ShareDetail::TYPE_AREA_PROFIT, 'is_send' => 0, 'is_delete' => 0])->all();
  896. if ($list) {
  897. $t = \Yii::$app->db->beginTransaction();
  898. foreach ($list as $share_detail) {
  899. /**
  900. * @var $share_detail ShareDetail
  901. */
  902. $user = User::findOne($share_detail->user_id);
  903. $user->updateCounters(['total_price' => $share_detail->money, 'price' => $share_detail->money]);
  904. $share_detail->is_send = 1;
  905. $share_detail->send_time = time();
  906. if (!$share_detail->save()) {
  907. $t->rollBack();
  908. \Yii::warning(['------------ 发放代理分红状态更改失败:-------------', $share_detail->errors]);
  909. return;
  910. }
  911. }
  912. $t->commit();
  913. \Yii::warning(['------------ 发放代理分红成功, 订单id:' . $order_id .'-------------']);
  914. }
  915. }
  916. public static function poolUserMoney($pool_level, $user_ids) {
  917. $store_id = $pool_level->store_id;
  918. $pool_level_id = $pool_level->id;
  919. $pool_level_money = $pool_level->money;
  920. $dividends_method = Option::get('dividends_method', $store_id, 'bonus_pool', 0)['value']; //分红方式 0平均分红 1团队业绩加权分红
  921. if($dividends_method){
  922. $pay_price_all = BonusPoolDetail::find()->alias('b')->leftJoin(['o' => Order::tableName()], 'b.order_id = o.id AND b.order_type=0')
  923. ->leftJoin(['sco' => \app\plugins\scanCodePay\models\Order::tableName()], 'b.order_id = sco.id AND b.order_type=6')
  924. ->andWhere(['pool_level_id' => $pool_level_id])
  925. ->andWhere(['or', ['in', 'o.user_id', $user_ids], ['in', 'sco.user_id', $user_ids]])
  926. ->select('SUM(o.pay_price) o_pay_price, SUM(sco.pay_price) sco_pay_price')
  927. ->asArray()->one();
  928. $money_all_order = 0;
  929. if($pay_price_all){
  930. $money_all_order = array_sum($pay_price_all);
  931. }
  932. $res = [];
  933. foreach ($user_ids as $uid) {
  934. if($money_all_order == 0){
  935. $res[$uid] = 0;
  936. continue;
  937. }
  938. $pay_price_all_user = BonusPoolDetail::find()->alias('b')->leftJoin(['o' => Order::tableName()], 'b.order_id = o.id AND b.order_type=0')
  939. ->leftJoin(['sco' => \app\plugins\scanCodePay\models\Order::tableName()], 'b.order_id = sco.id AND b.order_type=6')
  940. ->andWhere(['pool_level_id' => $pool_level_id])
  941. ->andWhere(['or', ['o.user_id' => $uid], ['sco.user_id' => $uid]])
  942. ->select('SUM(o.pay_price) o_pay_price, SUM(sco.pay_price) sco_pay_price')
  943. ->asArray()->one();
  944. $money_all_order_user = 0;
  945. if($pay_price_all_user){
  946. $money_all_order_user = array_sum($pay_price_all_user);
  947. }
  948. $res[$uid] = round($pool_level_money * ($money_all_order_user / $money_all_order), 2);
  949. }
  950. return $res;
  951. }
  952. return null;
  953. }
  954. /**
  955. * 股东分红,发放奖金池
  956. * @param $bool_id 奖金池ID
  957. */
  958. public static function poolShare($id)
  959. {
  960. $t = \Yii::$app->db->beginTransaction();
  961. try {
  962. $pool_level = BonusPoolLevel::findOne($id);
  963. $price = $pool_level->money;
  964. $shareHolderLevel = $pool_level->level_id;
  965. $high_level_join_average = Option::get('high_level_join_average', $pool_level->store_id,
  966. 'bonus_pool', 0)['value'];
  967. if (intval($high_level_join_average)) {
  968. $shareHolderLevelOnce = ShareHolderLevel::findOne(['is_delete' => 0, 'id' => $pool_level->level_id]);
  969. $shareHolderLevel = ShareHolderLevel::find()->where(['store_id' => $shareHolderLevelOnce->store_id, 'is_delete' => 0])
  970. ->andWhere(['>=', 'level', $shareHolderLevelOnce->level])->select('id')->column();
  971. }
  972. // 获取所有对应等级的股东
  973. $holder = ShareHolder::find()->where([
  974. 'store_id' => get_store_id(),
  975. 'level_id' => $shareHolderLevel,
  976. 'is_delete' => 0,
  977. 'status' => 1
  978. ])->asArray()->all();
  979. $holder_count = count($holder);
  980. if ($holder_count < 1) {
  981. $t->rollBack();
  982. return [
  983. 'code' => 1,
  984. 'msg' => '没有可发放的股东'
  985. ];
  986. }
  987. $user_ids = [];
  988. foreach ($holder as $item) {
  989. $bonus_pool = \app\models\BonusPool::findOne($pool_level->pool_id);
  990. $pay_price_arr = BonusPoolDetail::find()->alias('b')->leftJoin(['o' => Order::tableName()], 'b.order_id = o.id')
  991. ->where(['o.user_id' => $item['user_id']])
  992. ->andWhere(['and', ['>=', 'b.created_at', $bonus_pool->start_time], ['<', 'b.created_at', $bonus_pool->end_time]])
  993. ->select('o.pay_price')->groupBy('o.id')->column();
  994. $pay_price = array_sum($pay_price_arr);
  995. //
  996. //判断是否达标
  997. $dividends_condition = Option::get('dividends_condition', get_store_id(), 'bonus_pool', 0)['value'];
  998. if ($dividends_condition <= $pay_price) {
  999. $user_ids = array_merge($user_ids, [$item['user_id']]);
  1000. }
  1001. }
  1002. $holder_count = count($user_ids);
  1003. if ($holder_count < 1) {
  1004. $t->rollBack();
  1005. return [
  1006. 'code' => 1,
  1007. 'msg' => '没有可发放的股东'
  1008. ];
  1009. }
  1010. $share_price = round($price / $holder_count, 2);
  1011. // $user_ids = array_column($holder, 'user_id');
  1012. $pool_level->user_id = Json::encode($user_ids);
  1013. if (!$pool_level->save()) {
  1014. $t->rollBack();
  1015. return [
  1016. 'code' => 1,
  1017. 'msg' => '发放失败1'
  1018. ];
  1019. }
  1020. $dividends_method = intval(Option::get('dividends_method', $pool_level->store_id, 'bonus_pool', 0)['value']); //分红方式 0平均分红 1团队业绩加权分红
  1021. $poolUserMoney = self::poolUserMoney($pool_level, $user_ids);
  1022. if ($dividends_method === BonusPoolLevel::SHARE_TYPE_WEIGHT) {
  1023. if (empty($poolUserMoney)) {
  1024. $user_ids = [];
  1025. $pool_level->user_id = Json::encode([]);
  1026. } else {
  1027. $user_ids_ = [];
  1028. foreach ($poolUserMoney as $poolUserIndex => $poolUserItem) {
  1029. if ($poolUserItem > 0) {
  1030. $user_ids_[] = $poolUserIndex;
  1031. }
  1032. }
  1033. $user_ids = $user_ids_;
  1034. $pool_level->user_id = Json::encode($user_ids);
  1035. }
  1036. }
  1037. foreach ($user_ids as $val_2) {
  1038. $user = User::findOne($val_2);
  1039. if ($user) {
  1040. if($poolUserMoney){
  1041. $share_price = $poolUserMoney[$val_2] ?: 0;
  1042. }
  1043. $user->updateCounters(['total_price' => $share_price, 'price' => $share_price]);
  1044. $holder_name = Option::get('holder_name', get_store_id(), 'bonus_pool', '')['value'];
  1045. $detail = new ShareDetail();
  1046. $detail->store_id = get_store_id();
  1047. $detail->type_id = $pool_level->id;
  1048. $detail->type = ShareDetail::TYPE_HOLDER_PROFIT;
  1049. $detail->user_id = $val_2;
  1050. $detail->desc = date('Y-m-d H:i:s', time()) . ($holder_name ?: '股东分红');
  1051. $detail->is_send = 1;
  1052. $detail->send_time = time();
  1053. $detail->money = $share_price;
  1054. if (!$detail->save()) {
  1055. $t->rollBack();
  1056. return [
  1057. 'code' => 1,
  1058. 'msg' => '发放失败2'
  1059. ];
  1060. }
  1061. }
  1062. }
  1063. $pool_level->share_type = $dividends_method;
  1064. $pool_level->is_send = 1;
  1065. $pool_level->send_time = time();
  1066. if (!$pool_level->save()) {
  1067. $t->rollBack();
  1068. return [
  1069. 'code' => 1,
  1070. 'msg' => '发放失败4'
  1071. ];
  1072. }
  1073. } catch (\Exception $e) {
  1074. $t->commit();
  1075. return [
  1076. 'code' => 1,
  1077. 'line' => $e->getLine(),
  1078. 'msg' => $e->getMessage(),
  1079. 'file' => $e->getFile(),
  1080. ];
  1081. }
  1082. $t->commit();
  1083. return [
  1084. 'code' => 0,
  1085. 'msg' => '发放成功'
  1086. ];
  1087. }
  1088. /**
  1089. * 增加奖金池
  1090. * @param $order_id
  1091. * @param $order_type
  1092. */
  1093. public static function poolPush($order_id, $order_type = 0)
  1094. {
  1095. \Yii::warning(['---------------- 奖金池增加开始 -------------------']);
  1096. if(isset($order_id->id)){
  1097. $order = $order_id;
  1098. }else{
  1099. if ($order_type == 6) {
  1100. $order = \app\plugins\scanCodePay\models\Order::findOne($order_id);
  1101. }else{
  1102. $order = Order::findOne($order_id);
  1103. }
  1104. }
  1105. $order_id = $order->id;
  1106. // 判断是否开启奖金池
  1107. $setting = [
  1108. 'cycle' => Option::get('cycle', $order->store_id, 'bonus_pool', 0)['value'],
  1109. // 'is_open_share' => Option::get('is_open_share', $order->store_id, 'bonus_pool', 0)['value'],
  1110. // 'is_open_range' => Option::get('is_open_range', $order->store_id, 'bonus_pool', 0)['value'],
  1111. 'team_num' => Option::get('team_num', $order->store_id, 'bonus_pool', 0)['value']
  1112. ];
  1113. if (!$setting['cycle'] > 0) {// || !$setting['is_open_share']
  1114. \Yii::warning('---------------- 未开启股东分红 -------------------');
  1115. return;
  1116. }
  1117. $t = \Yii::$app->db->beginTransaction();
  1118. $tool = ModelsBonusPool::find()->where([
  1119. 'and',
  1120. [
  1121. '<',
  1122. 'start_time',
  1123. time()
  1124. ],
  1125. [
  1126. '>=',
  1127. 'end_time',
  1128. time()
  1129. ]
  1130. ])->andWhere(['store_id' => $order->store_id])->orderBy(['id' => SORT_DESC])->one();
  1131. // 如果没有奖金池,重新创建奖金池
  1132. if (!$tool) {
  1133. // 获取最后一个奖金池的结束时间
  1134. // $last_tool = ModelsBonusPool::find()->where([
  1135. // 'store_id' => $order->store_id
  1136. // ])->orderBy(['id' => SORT_DESC])
  1137. // ->one();
  1138. if (false && isset($last_tool) && $last_tool) {
  1139. $start_time = $last_tool->end_time;
  1140. } else {
  1141. $start_time = strtotime(date('Y-m-d', time()));
  1142. }
  1143. $tool = new ModelsBonusPool();
  1144. $tool->store_id = $order->store_id;
  1145. $tool->start_time = $start_time;
  1146. $end_time = $start_time + ($setting['cycle'] * 24 * 3600);
  1147. $tool->end_time = $end_time;
  1148. if (!$tool->save()) {
  1149. $t->rollBack();
  1150. \Yii::warning('---------------- 创建奖金池失败 -------------------');
  1151. return;
  1152. }
  1153. }
  1154. // 根据会员等级,添加奖金池佣金
  1155. $bonus_pool_level = ShareHolderLevel::find()
  1156. ->where([
  1157. 'store_id' => $order->store_id,
  1158. 'is_delete' => 0
  1159. ])->all();
  1160. if($order_type == 6){
  1161. $rate = Option::get('face_rate', $order->store_id, 'store')['value'];
  1162. $rate_type = Option::get('face_rate_type', $order->store_id, 'store')['value'];
  1163. $base_price = $rate_type == 0 ? (($order->total_price + $order->take_price) * $rate / 100) : $rate;
  1164. }else{
  1165. $base_price = $order->profit;
  1166. }
  1167. foreach($bonus_pool_level as $level) {
  1168. $level_model = BonusPoolLevel::findOne(['pool_id' => $tool->id, 'level_id' => $level->id]);
  1169. $price = round($base_price * $level->holder_rate / 100, 2);
  1170. if ($price <= 0) {
  1171. continue;
  1172. }
  1173. if (!$level_model) {
  1174. $level_model = new BonusPoolLevel();
  1175. $level_model->store_id = $order->store_id;
  1176. $level_model->pool_id = $tool->id;
  1177. $level_model->level_id = $level->id;
  1178. $level_model->money = $price;
  1179. $level_model->user_id = '[]';
  1180. $level_model->is_send = 0;
  1181. $level_model->send_time = 0;
  1182. } else {
  1183. $BonusPoolDetail = BonusPoolDetail::findOne(['order_id' => $order_id, 'pool_level_id' => $level_model->id, 'order_type' => $order_type]);
  1184. if ($BonusPoolDetail) {
  1185. continue;
  1186. }
  1187. $level_model->money += $price;
  1188. }
  1189. if (!$level_model->save()) {
  1190. $t->rollBack();
  1191. \Yii::warning(['---------------- 创建等级奖金池失败 -------------------', $level_model->errors]);
  1192. return;
  1193. } else {
  1194. $level_log = new BonusPoolDetail();
  1195. $level_log->store_id = $order->store_id;
  1196. $level_log->order_id = $order_id;
  1197. $level_log->order_type = (int)$order_type;
  1198. $level_log->money = $price;
  1199. $level_log->pool_level_id = $level_model->id;
  1200. $level_log->desc = '订单号:'.$order->order_no.'追加';
  1201. if (!$level_log->save()) {
  1202. $t->rollBack();
  1203. \Yii::warning(['---------------- 奖金池订单入库失败 -------------------', $level_log->errors]);
  1204. return;
  1205. }
  1206. }
  1207. }
  1208. $t->commit();
  1209. \Yii::warning(['---------------- 奖金池增加成功 -------------------', $base_price]);
  1210. }
  1211. public static function ShareHolderLevelJob($store_id = 1, $type = 0, $user_id = 0){
  1212. if(!cache_lock(['ShareHolderLevelJob', $store_id, $type, $user_id], 30)){
  1213. \queue_push(new \app\jobs\ShareHolderLevelJob(['store_id' => $store_id, 'type' => $type, 'user_id' => $user_id]), 30);
  1214. }
  1215. }
  1216. /**
  1217. * @return array|void
  1218. */
  1219. public static function checkLevel($store_id = 1, $type = 0, $user_id = 0) {
  1220. \Yii::warning('----------------- HANDLE SHARE HOLDER LEVEL START -----------------' . time());
  1221. $query = ShareHolder::find()->where(['is_delete' => 0, 'status' => 1, 'store_id' => $store_id]);
  1222. if($user_id){
  1223. // $query->andWhere(['!=', 'user_id', $user_id]);
  1224. $queryUserTree = OldUserTreePath::find()->where(['child_id' => $user_id])->select('parent_id');
  1225. $query->andWhere([
  1226. 'user_id' => $queryUserTree,
  1227. ]);
  1228. }
  1229. $share_holder = $query->select('store_id, user_id, level_id')->asArray()->all();
  1230. if (empty($share_holder)) {
  1231. \Yii::warning('可处理数据为空');
  1232. return;
  1233. }
  1234. foreach ($share_holder as $share) {
  1235. $current_level_id = $share['level_id'];
  1236. $level = ShareHolderLevel::findOne($current_level_id)->level;
  1237. $share_holder_level = ShareHolderLevel::find()->where(['store_id' => $share['store_id'], 'is_delete' => 0, 'status' => 1])->andWhere(['>', 'level', $level])->orderBy('level desc')->all();
  1238. // \Yii::warning(['用户' . $share['user_id'] . '可升等级', ShareHolderLevel::find()->where(['store_id' => $share['store_id'], 'is_delete' => 0, 'status' => 1])->andWhere(['>', 'level', $level])->orderBy('level desc')->asArray()->all()]);
  1239. foreach ($share_holder_level as $value) {
  1240. $is_level = true;
  1241. /**
  1242. * @var $value ShareHolderLevel
  1243. */
  1244. //TODO 股东人数以及金额
  1245. $condition = Json::decode($value->condition);
  1246. // 团队人数
  1247. $man = $condition['man'];
  1248. if ((bool)$man['is_open']) {
  1249. $share_user_parent_tree = OldUserTreePath::findOne(['parent_id' => $share['user_id']]);//获取当前购买用户的当前等级
  1250. foreach ($man['value'] as $m) {
  1251. // $man_data = User::find()->childs($share['user_id'], false, $m['level'])->where(['store_id' => $value->store_id])->asArray()->all();
  1252. $man_data = OldUserTreePath::find()->where([
  1253. 'parent_id' => $share['user_id']
  1254. ])->andWhere([
  1255. '!=',
  1256. 'child_id',
  1257. $share['user_id']
  1258. ])->andWhere([
  1259. 'AND', [
  1260. '>', 'child_level', $share_user_parent_tree->parent_level
  1261. ], [
  1262. '<=', 'child_level', ($share_user_parent_tree->parent_level + (int)$m['level'])
  1263. ]
  1264. ])->asArray()->all();
  1265. if (count($man_data) < $m['count']) {
  1266. $msg = '团队人数:' . $m['level'] . '级团队人数未达到' . $m['count'];
  1267. \Yii::warning(['---------- USER ID: ' . $share['user_id'] . '判断用户是否可以晋升 '. $value->name, $msg]);
  1268. $is_level = false;
  1269. continue;
  1270. } else {
  1271. if (isset($m['money'])) {
  1272. //消费达到$m['money']以上允许升级
  1273. $child_id = array_column($man_data, 'child_id');
  1274. $pay_price = Order::find()->where(
  1275. [
  1276. 'store_id' => $value->store_id,
  1277. 'is_delete' => 0,
  1278. 'trade_status' => Order::ORDER_FLOW_CONFIRM,
  1279. 'user_id' => $child_id
  1280. ])
  1281. ->andWhere(['or', ['is_pay' => 1], ['pay_type' => 2]])->sum('pay_price');
  1282. if ($m['money'] > $pay_price) {
  1283. $msg = '团队人数:' . $m['level'] . '级团队人数下单金额未达到' . $m['money'];
  1284. \Yii::warning(['---------- USER ID: ' . $share['user_id'] . '判断用户是否可以晋升 '. $value->name, $msg]);
  1285. $is_level = false;
  1286. continue;
  1287. }
  1288. }
  1289. }
  1290. }
  1291. if (!$is_level) {
  1292. continue;
  1293. }
  1294. }
  1295. // 团队消费金额
  1296. $team_order = $condition['order'];
  1297. if ((bool)$team_order['is_open']) {
  1298. $share_user_parent_tree = OldUserTreePath::findOne(['parent_id' => $share['user_id']]);//获取当前购买用户的当前等级
  1299. foreach ($team_order['value'] as $o) {
  1300. $man_data = OldUserTreePath::find()->where([
  1301. 'parent_id' => $share['user_id']
  1302. ])->andWhere([
  1303. '!=',
  1304. 'child_id',
  1305. $share['user_id']
  1306. ])->andWhere([
  1307. 'AND', [
  1308. '>=', 'child_level', $share_user_parent_tree->parent_level
  1309. ], [
  1310. '<=', 'child_level', ($share_user_parent_tree->parent_level + ($o['level'] ?: 0))
  1311. ]
  1312. ])->asArray()->all();
  1313. // if (count($man_data) < 1) {
  1314. // $msg = '团队金额:' . $o['level'] . '级团队人数为空';
  1315. // \Yii::warning(['---------- USER ID: ' . $share['user_id'] . '判断用户是否可以晋升 '. $value->name, $msg]);
  1316. // $is_level = false;
  1317. // break;
  1318. // }
  1319. // $man_user_id = array_column($man_data, 'id');
  1320. $man_user_id = [];
  1321. $man_user_id[] = $share['user_id'];
  1322. foreach($man_data as $val) {
  1323. $man_user_id[] = $val['child_id'];
  1324. }
  1325. $order_money = Order::find()->where(
  1326. [
  1327. 'store_id' => $store_id,
  1328. 'is_delete' => 0,
  1329. 'trade_status' => Order::ORDER_FLOW_CONFIRM
  1330. ])
  1331. ->andWhere(['or', ['is_pay' => 1], ['pay_type' => 2]])
  1332. ->andWhere(['in', 'user_id', $man_user_id])->sum('pay_price');
  1333. if ($order_money < $o['count']) {
  1334. $msg = '团队金额:' . $o['level'] . '级团队消费金额未达到' . $o['count'].'|'.$order_money;
  1335. \Yii::warning(['---------- USER ID: ' . $share['user_id'] . '判断用户是否可以晋升 '. $value->name, $msg]);
  1336. $is_level = false;
  1337. continue;
  1338. }
  1339. }
  1340. if (!$is_level) {
  1341. continue;
  1342. }
  1343. }
  1344. // 自身消费金额
  1345. $self = $condition['self'];
  1346. if ((bool)$self['is_open']) {
  1347. // 兼容老版本
  1348. if (!isset($self['value']['order_number'])) {
  1349. $self_price = $self['value'];
  1350. $self['value'] = [];
  1351. $self['value']['order_number'] = 0;
  1352. $self['value']['price'] = $self_price;
  1353. }
  1354. if ($self['value']['order_number'] == 1) {
  1355. $order = Order::find()->where(
  1356. [
  1357. 'store_id' => $value->store_id,
  1358. 'is_delete' => 0,
  1359. 'trade_status' => Order::ORDER_FLOW_CONFIRM,
  1360. 'user_id' => $share['user_id']
  1361. ])
  1362. ->andWhere(['or', ['is_pay' => 1], ['pay_type' => 2]])
  1363. ->andWhere(['>=' , 'pay_price', $self['value']['price']])->one();
  1364. if (!$order) {
  1365. $msg = '您在本商城单笔消费未达到' . $self['value']['price'] . '元';
  1366. \Yii::warning(['---------- USER ID: ' . $share['user_id'] . '判断用户是否可以晋升 '. $value->name, $msg]);
  1367. $is_level = false;
  1368. }
  1369. if (!$is_level) {
  1370. continue;
  1371. }
  1372. } else{
  1373. $order_money = Order::find()->where(
  1374. [
  1375. 'store_id' => $value->store_id,
  1376. 'is_delete' => 0,
  1377. 'trade_status' => Order::ORDER_FLOW_CONFIRM,
  1378. 'user_id' => $share['user_id']
  1379. ])->andWhere(['or', ['is_pay' => 1], ['pay_type' => 2]])->sum('pay_price');
  1380. if ($order_money < $self['value']['price']) {
  1381. $msg = '您在本商城消费未达到' . $self['value']['price'] . '元';
  1382. \Yii::warning(['---------- USER ID: ' . $share['user_id'] . '判断用户是否可以晋升 '. $value->name, $msg]);
  1383. $is_level = false;
  1384. }
  1385. if (!$is_level) {
  1386. continue;
  1387. }
  1388. }
  1389. }
  1390. // 自身充值金额
  1391. $recharge = $condition['recharge'];
  1392. if ((bool)$recharge['is_open']) {
  1393. $recharge_money = ReOrder::find()->where(['store_id' => $value->store_id, 'user_id' => $share['user_id'], 'is_pay' => 1])->sum('pay_price');
  1394. if ($recharge_money < $recharge['value']) {
  1395. $msg = '您在本商城充值未达到' . $recharge['value'] . '元';
  1396. \Yii::warning(['---------- USER ID: ' . $share['user_id'] . '判断用户是否可以晋升 '. $value->name, $msg]);
  1397. $is_level = false;
  1398. }
  1399. if (!$is_level) {
  1400. continue;
  1401. }
  1402. }
  1403. // 购买指定商品
  1404. $goods = $condition['goods'];
  1405. $shareholder = $condition['shareholder'];
  1406. if ((bool)$shareholder['is_open'] && (bool)$shareholder['independent_team'] === false) {
  1407. $goods['is_open'] = false;
  1408. //'u.parent_id' => $parent_user->id,
  1409. //// 'h.level_id' => $user_holder_level_id,
  1410. //// 'h.status' => 1,
  1411. //// 'h.is_delete' => 0
  1412. $user_ids = User::find()->alias('u')
  1413. ->leftJoin(['h' => ShareHolder::tableName()], 'h.user_id = u.id')
  1414. ->where([
  1415. 'u.old_parent_id' => $share['user_id'],
  1416. 'h.level_id' => $shareholder['to_level_id'],
  1417. 'h.status' => 1,
  1418. 'h.is_delete' => 0
  1419. ])
  1420. ->limit($shareholder['num'])
  1421. ->select('u.id')
  1422. ->column();
  1423. if (count($user_ids) < $shareholder['num']) {
  1424. $is_level = false;
  1425. }
  1426. }
  1427. if ((bool)$goods['is_open']) {
  1428. // 查找该用户是否买过此商品
  1429. $goods_model = Order::find()->alias('o')
  1430. ->leftJoin(['od' => OrderDetail::tableName()], 'od.order_id=o.id')
  1431. ->where(
  1432. [
  1433. 'o.store_id' => $value->store_id,
  1434. 'o.user_id' => $share['user_id'],
  1435. 'o.is_delete' => 0,
  1436. 'o.trade_status' => Order::ORDER_FLOW_CONFIRM
  1437. ])
  1438. ->andWhere(['or', ['o.is_pay' => 1], ['o.pay_type' => 2]])
  1439. ->andWhere(['od.goods_id' => $goods['value']['id']])->one();
  1440. if (!$goods_model) {
  1441. $msg = '未购买过指定商品, 商品id' . (is_array($goods['value']['id']) ? implode(',', $goods['value']['id']) : $goods['value']['id']);
  1442. \Yii::warning(['---------- USER ID: ' . $share['user_id'] . '判断用户是否可以晋升 '. $value->name, $msg]);
  1443. $is_level = false;
  1444. }
  1445. if (!$is_level) {
  1446. continue;
  1447. }
  1448. // 是否过了售后期
  1449. $pay_time = $goods_model->pay_time;
  1450. if (time() < ($pay_time + $goods['day'] * 24 * 3600)) {
  1451. $msg = '购买过的指定商品未过售后期, 商品id' . (is_array($goods['value']['id']) ? implode(',', $goods['value']['id']) : $goods['value']['id']);
  1452. \Yii::warning(['---------- USER ID: ' . $share['user_id'] . '判断用户是否可以晋升 '. $value->name, $msg]);
  1453. $is_level = false;
  1454. }
  1455. if (!$is_level) {
  1456. continue;
  1457. }
  1458. }
  1459. // 累计佣金金额
  1460. $amount_total = $condition['amount_total'];
  1461. if ((bool)$amount_total['is_open']) {
  1462. $user = User::findOne($share['user_id']);
  1463. if ($user->total_price < $amount_total['value']) {
  1464. $msg = '您在本商城的佣金未达到' . $amount_total['value'] . '元';
  1465. \Yii::warning(['---------- USER ID: ' . $share['user_id'] . '判断用户是否可以晋升 '. $value->name, $msg]);
  1466. $is_level = false;
  1467. }
  1468. if (!$is_level) {
  1469. continue;
  1470. }
  1471. }
  1472. if (($is_level) && (
  1473. (bool)$goods['is_open'] ||
  1474. (bool)$team_order['is_open'] ||
  1475. (bool)$man['is_open'] ||
  1476. (bool)$self['is_open'] ||
  1477. (bool)$recharge['is_open'] ||
  1478. (bool)$amount_total['is_open'] ||
  1479. (
  1480. (bool)$shareholder['is_open']) &&
  1481. (bool)$shareholder['independent_team'] === false
  1482. )
  1483. ) {
  1484. $t = \Yii::$app->db->beginTransaction();
  1485. $holderSave = 0;
  1486. try {
  1487. $holder = ShareHolder::findOne(['status' => 1, 'is_delete' => 0, 'store_id' => $value->store_id, 'user_id' => $share['user_id']]);
  1488. if ($holder) {
  1489. //添加股东升级记录
  1490. //查询等级(旧)
  1491. $before_level = ShareHolderLevel::findOne($holder->level_id);
  1492. //查询等级(新)
  1493. $after_level = ShareHolderLevel::findOne($value->id);
  1494. //添加股东升级记录
  1495. $level_log = new ShareHolderLevelLog();
  1496. $level_log->before_level = $before_level->level;
  1497. $level_log->after_level = $after_level->level;
  1498. $level_log->user_id = $share['user_id'];
  1499. $level_log->store_id = $value->store_id;
  1500. $level_log->desc = $type ? '后台修改数据使其达到升级条件' : "用户达到升级条件";
  1501. if (!$level_log->save()) {
  1502. throw new Exception('等级更新失败');
  1503. }
  1504. $holder->level_id = $value->id;
  1505. if (!$holder->save()) {
  1506. $t->rollBack();
  1507. \Yii::warning(['------------ 等级更新失败 ------------', $holder->errors]);
  1508. } else {
  1509. $user_info = User::findOne($share['user_id']);
  1510. if (!empty($value->member_level) && $value->member_level > $user_info->level){
  1511. $user_info->level = $value->member_level;
  1512. if (!$user_info->save()) {
  1513. $t->rollBack();
  1514. \Yii::warning(['------------ 等级更新成功自动更新等级对应会员等级更新失败 ------------', $user_info->errors]);
  1515. }else{
  1516. \Yii::warning(['------------ 等级更新成功自动更新等级对应会员等级 ------------', [
  1517. '之前等级' . $user_info->level,
  1518. '之后等级' . $value->member_level,
  1519. ]]);
  1520. $holderSave = 1;
  1521. }
  1522. }
  1523. \Yii::warning(['------------ 等级更新成功 ------------', [
  1524. '之前等级' . $current_level_id,
  1525. '之后等级' . $value->id,
  1526. ]]);
  1527. }
  1528. }
  1529. $t->commit();
  1530. } catch (\Throwable $e) {
  1531. $t->rollBack();
  1532. \Yii::warning(['------------ 等级更新失败 ------------', $e->getMessage()]);
  1533. }
  1534. if($user_id && $holder && $holderSave){
  1535. return self::checkLevel($store_id, $type, $holder['user_id']);
  1536. }
  1537. }
  1538. BonusPool::checkChildHolderUpdateLevel($share['user_id'], $value->id, $type);
  1539. }
  1540. }
  1541. \Yii::warning('----------------- HANDLE SHARE HOLDER LEVEL END -----------------' . time());
  1542. }
  1543. // 获取指定等级的上级
  1544. public static function getParentByLevel($user_id, ShareHolderLevel $level)
  1545. {
  1546. if ($user_id == 0) {
  1547. return 0;
  1548. }
  1549. $user = User::findOne($user_id);
  1550. $parentHolder = ShareHolder::find()->alias('sh')
  1551. ->leftJoin(['shl' => ShareHolderLevel::tableName()], 'sh.level_id = shl.id')
  1552. ->where(['sh.user_id' => $user->parent_id])
  1553. ->andWhere(['>=', 'shl.level', $level->level])
  1554. ->select('sh.user_id')
  1555. ->orderBy('shl.level ASC')
  1556. ->one();
  1557. if ($parentHolder) {
  1558. return $parentHolder->user_id;
  1559. }
  1560. return static::getParentByLevel($user->parent_id, $level);
  1561. }
  1562. /**
  1563. * 检查下级股东升级
  1564. * @param int $user_id
  1565. * @return void
  1566. * @author Syan mzsongyan@gmail.com
  1567. * @date 2022-07-28
  1568. */
  1569. public static function checkChildHolderUpdateLevel($user_id, $user_holder_level_id = 0, $type = 0)
  1570. {
  1571. debug_log('检查下级股东升级=' . $user_id, 'team.log');
  1572. $user = User::findOne($user_id);
  1573. if (!$user) {
  1574. return;
  1575. }
  1576. $holder_level_list = ShareHolderLevel::find()->where([
  1577. 'is_delete' => 0,
  1578. 'status' => 1,
  1579. 'store_id' => $user->store_id,
  1580. ])->all();
  1581. // 找出符合条件的等级
  1582. $current_level = null;
  1583. // foreach ($holder_level_list as $holder_level) {
  1584. // $condition = json_decode($holder_level->condition);
  1585. // if ((bool)$condition->shareholder->is_open === false || (bool)$condition->shareholder->num == 0) {
  1586. // continue;
  1587. // }
  1588. // if ($condition->shareholder->to_level_id == $user_holder_level_id) {
  1589. // $current_level = $holder_level;
  1590. // }
  1591. // }
  1592. foreach ($holder_level_list as $holder_level) {
  1593. $condition = json_decode($holder_level->condition);
  1594. if ((bool)$condition->shareholder->is_open &&
  1595. (int)$condition->shareholder->num > 0 &&
  1596. (bool)$condition->shareholder->independent_team
  1597. ) {
  1598. $current_level = $holder_level;
  1599. break;
  1600. }
  1601. }
  1602. if ($current_level == null) {
  1603. return;
  1604. }
  1605. // 升级代理后直接改当前用户parent_id为链动关系往上的老板等级的用户
  1606. // $parent_id = static::getParentByLevel($user_id, $current_level);
  1607. // $user->parent_id = $parent_id;
  1608. // $user->save();
  1609. $parent_user = User::findOne($user->parent_id);
  1610. if (!$parent_user) {
  1611. return;
  1612. }
  1613. $parent_holder = ShareHolder::findOne(['status' => 1, 'is_delete' => 0, 'is_out' => 0, 'store_id' => $user->store_id, 'user_id' => $parent_user->id]);
  1614. if (!$parent_holder) {
  1615. return;
  1616. }
  1617. $parent_holder_level = ShareHolderLevel::findOne($parent_holder->level_id);
  1618. if (!$parent_holder_level) {
  1619. return;
  1620. }
  1621. if ($parent_holder_level->level >= $current_level->level) {
  1622. return;
  1623. }
  1624. $condition = json_decode($current_level->condition);
  1625. // 查找父级的直属下级股东
  1626. $user_ids = User::find()->alias('u')
  1627. ->leftJoin(['h' => ShareHolder::tableName()], 'h.user_id = u.id')
  1628. ->where([
  1629. 'u.old_parent_id' => $parent_user->id,
  1630. // 'h.level_id' => $user_holder_level_id,
  1631. 'h.status' => 1,
  1632. 'h.is_delete' => 0,
  1633. ])
  1634. ->andWhere(['>=', 'h.level_id', $condition->shareholder->to_level_id])
  1635. ->limit($condition->shareholder->num)//感觉不用加这个 下面有数组截取 但是不加怕查询太慢
  1636. ->orderBy('h.created_at ASC')
  1637. ->select('u.id')
  1638. ->column();
  1639. //去重父级的直属下级股东以及滑落记录 两个数组 满足条件人数以及等级条件上级就出局
  1640. //查询滑落记录
  1641. $slippedUserLog = ShareHolderSlippedLog::getSlippedUserLog($parent_user->id);
  1642. //查询滑落记录的达到条件的股东
  1643. $slippedUserLog = User::find()->alias('u')
  1644. ->leftJoin(['h' => ShareHolder::tableName()], 'h.user_id = u.id')
  1645. ->where([
  1646. 'u.id' => $slippedUserLog,
  1647. // 'h.level_id' => $user_holder_level_id,
  1648. 'h.status' => 1,
  1649. 'h.is_delete' => 0,
  1650. ])
  1651. ->andWhere(['>=', 'h.level_id', $condition->shareholder->to_level_id])
  1652. ->orderBy('h.created_at ASC')
  1653. ->limit($condition->shareholder->num)//感觉不用加这个 下面有数组截取 但是不加怕查询太慢
  1654. ->select('u.id')
  1655. ->column();
  1656. debug_log($slippedUserLog, 'slipped.log');
  1657. debug_log($user_ids, 'slipped.log');
  1658. //将滑落记录跟下级记录合并 再去重
  1659. if (!empty($slippedUserLog)) {
  1660. $user_ids = array_values(array_unique(array_merge($user_ids, $slippedUserLog)));
  1661. }
  1662. $old_user_ids = $user_ids;
  1663. //截取数组
  1664. $user_ids = array_slice($user_ids, 0, $condition->shareholder->num); //得截取一下 怕合并后人数太多 得改动下级的上级ID
  1665. $other_user_ids = array_slice($old_user_ids, $condition->shareholder->num);
  1666. //判断是否满足条件
  1667. if (count($user_ids) >= $condition->shareholder->num) {
  1668. $t = \Yii::$app->db->beginTransaction();
  1669. try {
  1670. //添加股东升级记录
  1671. //查询股东等级(旧)
  1672. $before_level = $parent_holder_level;
  1673. //查询股东等级(新)
  1674. $after_level = $current_level;
  1675. //添加股东升级记录
  1676. $level_log = new ShareHolderLevelLog();
  1677. $level_log->before_level = $before_level->level;
  1678. $level_log->after_level = $after_level->level;
  1679. $level_log->user_id = $parent_holder->user_id;
  1680. $level_log->store_id = $user->store_id;
  1681. $level_log->desc = $type ? "后台修改使下级助力出局升级" : "下级助力出局升级";
  1682. if (!$level_log->save()) {
  1683. throw new Exception('股东等级更新失败');
  1684. }
  1685. $parent_holder->level_id = $current_level->id;
  1686. //将出局的标记为出局状态
  1687. $parent_holder->is_out = 1;
  1688. if (!$parent_holder->save()) {
  1689. throw new Exception('等级更新失败');
  1690. }
  1691. // 更改出局状态表
  1692. $out_log = ShareHolderOutLog::findOne(['child_user_id' => $parent_user->id]);
  1693. if ($out_log) {
  1694. ShareHolderOutLog::updateAll(['status' => 1], ['child_user_id' => $parent_user->id]);
  1695. // $out_log->status = 1;
  1696. // $out_log->save();
  1697. }
  1698. static::sendFrostMoney($parent_user->id, $parent_user->store_id);
  1699. // 升级对应等级的会员等级
  1700. if ($current_level->member_level > $parent_user->level) {
  1701. $parent_user->level = $current_level->member_level;
  1702. if (!$parent_user->save()) {
  1703. throw new Exception('股东升级到对应的等级后,升级绑定的会员等级失败');
  1704. }
  1705. }
  1706. // if ($parent_user->parent_id > 0) {
  1707. // 出局独立团队
  1708. // if ((bool)$condition->shareholder->independent_team) {
  1709. $parent_user_old_parent_id = $parent_user->parent_id;
  1710. $parent_user->parent_id = 0;
  1711. if (!$parent_user->save()) {
  1712. throw new Exception('出局独立团队失败');
  1713. }
  1714. self::addShareHolderParentOutLog($parent_user, $parent_user_old_parent_id, '链动出局');
  1715. foreach ($user_ids as $user_item_id) {
  1716. $user_item = User::findOne($user_item_id);
  1717. if ($user_item) {
  1718. $shareHolder = ShareHolder::findOne(['user_id' => $user_item_id, 'is_delete' => 0]);
  1719. if ($shareHolder && intval($shareHolder->is_out)) {
  1720. continue;
  1721. }
  1722. $beforeParentId = $user_item->parent_id;
  1723. $user_item->parent_id = $parent_user_old_parent_id;
  1724. if (!$user_item->save()) {
  1725. throw new Exception('助力出局的股东改变关系失败');
  1726. }
  1727. $desc = $type ? "后台修改数据使股东上级出局" : "股东上级出局";
  1728. self::addShareHolderParentOutLog($user_item, $beforeParentId, $desc);
  1729. //记录出局关系
  1730. $out = new ShareHolderOutLog();
  1731. $out->parent_user_id = $parent_user->id;
  1732. $out->child_user_id = $user_item->id;
  1733. $out->save();
  1734. }
  1735. }
  1736. foreach ($other_user_ids as $other_user_id) {
  1737. $other_user_item = User::findOne($other_user_id);
  1738. if ($other_user_item) {
  1739. //判断滑落
  1740. $share_detail_arr = [
  1741. ShareDetail::TYPE_HOLDER_PROFIT,
  1742. ShareDetail::TYPE_RANGE_PROFIT,
  1743. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_PROFIT,
  1744. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT,
  1745. ShareDetail::TYPE_RANGE_PROFIT_OLD,
  1746. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT_OLD,
  1747. ShareDetail::TYPE_RANGE_PROFIT_OLD_USER_LEVEL
  1748. ];
  1749. $share_detail = ShareDetail::find()->alias('sd')
  1750. ->leftJoin(['o' => Order::tableName()], 'o.id = sd.type_id')
  1751. ->where(['o.user_id' => $other_user_id, 'sd.type' => $share_detail_arr, 'sd.user_id' => $parent_user->id])
  1752. ->asArray()->one();
  1753. if ($share_detail) {
  1754. ShareDetail::handleChildData($share_detail['id']);
  1755. }
  1756. }
  1757. }
  1758. // }
  1759. // }
  1760. $t->commit();
  1761. } catch (\Throwable $e) {
  1762. debug_log($e->getMessage(), 'team.log');
  1763. $t->rollBack();
  1764. }
  1765. }
  1766. }
  1767. //上级关系变化
  1768. public static function addShareHolderParentOutLog($user, $beforeParentId, $desc = '', $type = 0, $change_type = ShareHolderParentOutLog::CHANGE_TYPE_NORMAL) {
  1769. if($type == 0){
  1770. $parent_id = $user->parent_id;
  1771. }
  1772. if($type == 1){
  1773. $parent_id = $user->old_parent_id;
  1774. }
  1775. if($beforeParentId == $parent_id){
  1776. \Yii::error('$beforeParentId == $parent_id');
  1777. return [
  1778. 'code' => 0,
  1779. 'msg' => 'ok,$beforeParentId == $parent_id',
  1780. ];
  1781. }
  1782. // if($type == 0){
  1783. // $shareHolder = ShareHolder::findOne(['user_id' => $user->id, 'is_delete' => 0, 'status' => 1]);
  1784. // if(!$shareHolder){
  1785. // \Yii::error('!$shareHolder');
  1786. // return [
  1787. // 'code' => 0,
  1788. // 'msg' => 'ok,!$shareHolder',
  1789. // ];
  1790. // }
  1791. // }
  1792. $parent_out_log = new ShareHolderParentOutLog();
  1793. $parent_out_log->user_id = $user->id;
  1794. $parent_out_log->old_parent_user_id = $beforeParentId;
  1795. $parent_out_log->parent_user_id = $parent_id;
  1796. $parent_out_log->store_id = $user->store_id;
  1797. $parent_out_log->desc = $desc;
  1798. $parent_out_log->type = $type;
  1799. $parent_out_log->change_type = $change_type;
  1800. if (!$parent_out_log->save()) {
  1801. \Yii::error($parent_out_log->getFirstErrors());
  1802. return [
  1803. 'code' => 1,
  1804. 'msg' => 'ShareHolderParentOutLog保存失败' . array_shift($parent_out_log->getFirstErrors()),
  1805. ];
  1806. }
  1807. return [
  1808. 'code' => 0,
  1809. 'msg' => 'ok',
  1810. ];
  1811. }
  1812. // 检查普通用户充值金额是否达到成为股东的条件
  1813. public static function generalUserRecharge($user_id, $store_id)
  1814. {
  1815. //查找股东是否存在或被拒绝或审核中
  1816. $shareHolder = ShareHolder::findOne(['user_id' => $user_id, 'is_delete' => 0, 'store_id' => $store_id, 'status' => 1]);
  1817. if ($shareHolder) {
  1818. return;
  1819. }
  1820. $user = User::findOne($user_id);
  1821. if (!$user) {
  1822. return;
  1823. }
  1824. // 获取所有等级消费金额条件
  1825. $share_holder_level = ShareHolderLevel::find()->where(['is_delete' => 0, 'status' => 1, 'store_id' => $store_id])->orderBy('level desc')->all();
  1826. $upgrade_level = 0;
  1827. $member_level = 0;
  1828. foreach ($share_holder_level as $holder_level) {
  1829. $condition = Json::decode($holder_level->condition);
  1830. $recharge = $condition['recharge'];
  1831. if ((bool)$recharge['is_open']) {
  1832. $recharge_money = ReOrder::find()->where(['store_id' => $store_id, 'user_id' => $user_id, 'is_pay' => 1])->sum('pay_price');
  1833. if ($recharge_money >= $recharge['value']) {
  1834. $upgrade_level = $holder_level->id;
  1835. $member_level = $holder_level->member_level;
  1836. break;
  1837. }
  1838. }
  1839. }
  1840. if ($upgrade_level > 0) {
  1841. $t = \Yii::$app->db->beginTransaction();
  1842. try {
  1843. $saas_user = SaasUser::findOne(['mobile' => $user->binding]);
  1844. $model = new ShareHolder();
  1845. $model->level_id = $upgrade_level;
  1846. $model->store_id = $store_id;
  1847. $model->user_id = $user_id;
  1848. $model->name = $saas_user->name;
  1849. $model->address = '';
  1850. $model->mobile = $saas_user->mobile;
  1851. $model->province = 0;
  1852. $model->city = 0;
  1853. $model->district = 0;
  1854. $model->province_name = '';
  1855. $model->city_name = '';
  1856. $model->district_name = '';
  1857. $model->status = 1;
  1858. $model->audit_time = time();
  1859. if (!$model->save()) {
  1860. throw new \Exception(json_encode($model->errors));
  1861. }
  1862. self::checkChildHolderUpdateLevel($user_id, $upgrade_level);
  1863. self::checkLevel($store_id, 0, $user_id);
  1864. if ($member_level > (int)$user->level) {
  1865. $user->level = $member_level;
  1866. }
  1867. $user->is_holder = 1;
  1868. if (!$user->save()) {
  1869. throw new \Exception(json_encode($user->errors));
  1870. }
  1871. $level_log = new ShareHolderLevelLog();
  1872. $level_log->before_level = 0;
  1873. $level_log->after_level = $upgrade_level;
  1874. $level_log->user_id = $user_id;
  1875. $level_log->store_id = $store_id;
  1876. $level_log->order_id = 0;
  1877. $level_log->desc = "用户累计充值升级为股东";
  1878. if (!$level_log->save()) {
  1879. throw new Exception('等级更新失败');
  1880. }
  1881. $t->commit();
  1882. } catch (\Throwable $e) {
  1883. $t->rollBack();
  1884. }
  1885. }
  1886. }
  1887. // 检查普通用户消费金额是否达到成为股东的条件
  1888. public static function generalUserConsume($user_id, $store_id)
  1889. {
  1890. \Yii::warning(['----------------- 检查普通用户消费金额是否达到成为股东的条件 --------' . $user_id, $store_id]);
  1891. //查找股东是否存在或被拒绝或审核中
  1892. $shareHolder = ShareHolder::findOne(['user_id' => $user_id, 'is_delete' => 0, 'store_id' => $store_id, 'status' => 1]);
  1893. if ($shareHolder) {
  1894. return;
  1895. }
  1896. $user = User::findOne($user_id);
  1897. if (!$user) {
  1898. return;
  1899. }
  1900. // 获取所有等级消费金额条件
  1901. $share_holder_level = ShareHolderLevel::find()->where(['is_delete' => 0, 'status' => 1, 'store_id' => $store_id])->orderBy('level desc')->all();
  1902. $upgrade_level = 0;
  1903. $member_level = 0;
  1904. $order_id = 0;
  1905. foreach ($share_holder_level as $holder_level) {
  1906. $condition = Json::decode($holder_level->condition);
  1907. $self = $condition['self'];
  1908. if ((bool)$self['is_open']) {
  1909. // 兼容老版本
  1910. if (!isset($self['value']['order_number'])) {
  1911. $self_price = $self['value'];
  1912. $self['value'] = [];
  1913. $self['value']['order_number'] = 0;
  1914. $self['value']['price'] = $self_price;
  1915. }
  1916. if ($self['value']['order_number'] == 1) {
  1917. $order = Order::find()->where(
  1918. [
  1919. 'store_id' => $store_id,
  1920. 'is_delete' => 0,
  1921. 'trade_status' => Order::ORDER_FLOW_CONFIRM,
  1922. 'user_id' => $user_id
  1923. ])
  1924. ->andWhere(['or', ['is_pay' => 1], ['pay_type' => 2]])
  1925. ->andWhere(['>=' , 'pay_price', $self['value']['price']])->one();
  1926. if ($order) {
  1927. $upgrade_level = $holder_level->id;
  1928. $member_level = $holder_level->member_level;
  1929. $order_id = $order->id;
  1930. break;
  1931. }
  1932. } else{
  1933. $order_money = Order::find()->where(
  1934. [
  1935. 'store_id' => $store_id,
  1936. 'is_delete' => 0,
  1937. 'trade_status' => Order::ORDER_FLOW_CONFIRM,
  1938. 'user_id' => $user_id
  1939. ])->andWhere(['or', ['is_pay' => 1], ['pay_type' => 2]])->sum('pay_price');
  1940. if ($order_money >= $self['value']['price']) {
  1941. $upgrade_level = $holder_level->id;
  1942. $member_level = $holder_level->member_level;
  1943. break;
  1944. }
  1945. }
  1946. }
  1947. }
  1948. if ($upgrade_level > 0) {
  1949. $t = \Yii::$app->db->beginTransaction();
  1950. try {
  1951. $saas_user = SaasUser::findOne(['mobile' => $user->binding]);
  1952. $model = new ShareHolder();
  1953. $model->level_id = $upgrade_level;
  1954. $model->store_id = $store_id;
  1955. $model->user_id = $user_id;
  1956. $model->name = $saas_user->name;
  1957. $model->address = '';
  1958. $model->mobile = $saas_user->mobile;
  1959. $model->province = 0;
  1960. $model->city = 0;
  1961. $model->district = 0;
  1962. $model->province_name = '';
  1963. $model->city_name = '';
  1964. $model->district_name = '';
  1965. $model->status = 1;
  1966. $model->audit_time = time();
  1967. if (!$model->save()) {
  1968. throw new \Exception(json_encode($model->errors));
  1969. }
  1970. self::checkChildHolderUpdateLevel($user_id, $upgrade_level);
  1971. self::checkLevel($store_id, 0, $user_id);
  1972. if ($member_level > (int)$user->level) {
  1973. $user->level = $member_level;
  1974. }
  1975. $user->is_holder = 1;
  1976. if (!$user->save()) {
  1977. throw new \Exception(json_encode($user->errors));
  1978. }
  1979. $level_log = new ShareHolderLevelLog();
  1980. $level_log->before_level = 0;
  1981. $level_log->after_level = $upgrade_level;
  1982. $level_log->user_id = $user_id;
  1983. $level_log->store_id = $store_id;
  1984. $level_log->order_id = $order_id;
  1985. $level_log->desc = "用户消费升级为股东";
  1986. if (!$level_log->save()) {
  1987. throw new Exception('等级更新失败');
  1988. }
  1989. $t->commit();
  1990. } catch (\Throwable $e) {
  1991. \Yii::error($e);
  1992. $t->rollBack();
  1993. }
  1994. }
  1995. }
  1996. public static function handleGoods($store_id = 1) {
  1997. // \Yii::warning(['----------------- 股东会员等级 商品订单自动确认机制开始 --------' . microtime(true)]);
  1998. $share_holder_level = ShareHolderLevel::find()->where(['is_delete' => 0, 'status' => 1, 'store_id' => $store_id])->orderBy('level desc')->all();
  1999. foreach ($share_holder_level as $value) {
  2000. /**
  2001. * @var $value ShareHolderLevel
  2002. */
  2003. $condition = Json::decode($value->condition);
  2004. // 购买指定商品
  2005. $goods = $condition['goods'];
  2006. if ((bool)$goods['is_open'] && !empty($goods['value']['id'])) {
  2007. // 查找买过此商品订单
  2008. $order_model = Order::find()->alias('o')->leftJoin(['od' => OrderDetail::tableName()], 'od.order_id=o.id')->where(['o.store_id' => $value->store_id, 'o.is_delete' => 0, 'o.is_pay' => 1])
  2009. ->andWhere(['od.goods_id' => $goods['value']['id']])->select('o.id order_id');
  2010. if ($goods['value']['is_send']) {
  2011. $order_ids = (clone $order_model)->andWhere(['o.trade_status' => 0])->asArray()->all();
  2012. $order_id = array_column($order_ids, 'order_id');
  2013. if (!empty($order_id)) {
  2014. \Yii::warning(['----------------- 股东会员等级 ' . $value->name . ' 商品订单自动发货机制--------' . microtime(true), $goods['value']['is_send'], count($order_id), implode(',', $order_id)]);
  2015. Order::updateAll(['trade_status' => Order::ORDER_FLOW_SEND, 'send_time' => time()], ['AND', ['in', 'id', $order_id], ['trade_status' => 0]]);
  2016. }
  2017. }
  2018. if ($goods['value']['is_confirm']) {
  2019. // //如果是代理配送 且上门安装,用户没有对商品确认收货则不可确认收货
  2020. // $order_detail = OrderDetail::findAll(['order_id' => $order_id]);
  2021. $is_can_confirm = true;
  2022. // foreach ($order_detail as $detail) {
  2023. // $is_can_confirm_sub = (AgentGoodsInstallLog::findOne(['order_detail_id' => $detail->id, 'status' => [0, 1], 'is_need_install' => 1]));
  2024. // if ($is_can_confirm_sub) {
  2025. // $is_can_confirm = false;
  2026. // }
  2027. // }
  2028. $order_ids = (clone $order_model)->andWhere(['o.trade_status' => Order::ORDER_FLOW_SEND])->asArray()->all();
  2029. $order_id = array_column($order_ids, 'order_id');
  2030. if ($is_can_confirm && !empty($order_id)) {
  2031. \Yii::warning(['----------------- 股东会员等级 ' . $value->name . ' 商品订单自动收货机制--------' . microtime(true), $goods['value']['is_confirm'], count($order_id), implode(',', $order_id)]);
  2032. Order::updateAll(['trade_status' => Order::ORDER_FLOW_CONFIRM, 'confirm_time' => time()], ['and', ['in', 'id', $order_id], ['trade_status' => Order::ORDER_FLOW_SEND]]);
  2033. }
  2034. }
  2035. $order_ids = (clone $order_model)->andWhere(['o.trade_status' => Order::ORDER_FLOW_CONFIRM, 'o.is_sale' => 0])->asArray()->all();
  2036. $order_id = array_column($order_ids, 'order_id');
  2037. if (!empty($order_id)) {
  2038. $after_sale_time = (int)$goods['value']['day'];
  2039. $order_event = new OrderEvent();
  2040. \Yii::warning(['----------------- 股东会员等级 ' . $value->name . ' 商品订单自动售后机制--------' . microtime(true), $goods['value']['day'], count($order_id), implode(',', $order_id)]);
  2041. $order_event->orderSend(1, $order_id, $value->store_id, $after_sale_time);
  2042. }
  2043. }
  2044. }
  2045. // \Yii::warning(['----------------- 股东会员等级 商品订单自动确认机制结束 --------' . microtime(true)]);
  2046. }
  2047. //股东会员等级 商品订单自动确认机制
  2048. public static function handleOrderAuto($order) {
  2049. try {
  2050. if(is_numeric($order)){
  2051. $order = PtActivityOrder::findOne($order);
  2052. }
  2053. if(!$order || $order->is_sale || !$order->user_id || !$order->is_pay){
  2054. return;
  2055. }
  2056. $share_holder_level = ShareHolderLevel::find()->where(['is_delete' => 0, 'status' => 1, 'store_id' => $order->store_id])->orderBy('level desc')->all();
  2057. foreach ($share_holder_level as $value) {
  2058. /**
  2059. * @var $value ShareHolderLevel
  2060. */
  2061. $condition = Json::decode($value->condition);
  2062. // 购买指定商品
  2063. $goods = $condition['goods'];
  2064. if ((bool)$goods['is_open'] && !empty($goods['value']['id'])) {
  2065. // 查找买过此商品订单
  2066. $order_model = Order::find()->alias('o')->leftJoin(['od' => OrderDetail::tableName()], 'od.order_id=o.id')->where(['o.id' => $order->id, 'o.is_delete' => 0, 'o.is_pay' => 1])
  2067. ->andWhere(['od.goods_id' => $goods['value']['id']])->select('o.id order_id');
  2068. if ($goods['value']['is_send']) {
  2069. $order_ids = (clone $order_model)->andWhere(['o.trade_status' => 0])->asArray()->all();
  2070. $order_id = array_column($order_ids, 'order_id');
  2071. if (!empty($order_id) && $order->trade_status == 0) {
  2072. \Yii::warning(['----------------- 股东会员等级 ' . $value->name . ' 商品订单自动发货机制--------' . microtime(true), $goods['value']['is_send'], count($order_id), implode(',', $order_id)]);
  2073. // Order::updateAll(['trade_status' => Order::ORDER_FLOW_SEND, 'send_time' => time()], ['AND', ['in', 'id', $order_id], ['trade_status' => 0]]);
  2074. $order->trade_status = Order::ORDER_FLOW_SEND;
  2075. $order->send_time = time();
  2076. $order->save();
  2077. }
  2078. }
  2079. if ($goods['value']['is_confirm']) {
  2080. // //如果是代理配送 且上门安装,用户没有对商品确认收货则不可确认收货
  2081. // $order_detail = OrderDetail::findAll(['order_id' => $order_id]);
  2082. $is_can_confirm = true;
  2083. // foreach ($order_detail as $detail) {
  2084. // $is_can_confirm_sub = (AgentGoodsInstallLog::findOne(['order_detail_id' => $detail->id, 'status' => [0, 1], 'is_need_install' => 1]));
  2085. // if ($is_can_confirm_sub) {
  2086. // $is_can_confirm = false;
  2087. // }
  2088. // }
  2089. $order_ids = (clone $order_model)->andWhere(['o.trade_status' => Order::ORDER_FLOW_SEND])->asArray()->all();
  2090. $order_id = array_column($order_ids, 'order_id');
  2091. if ($is_can_confirm && !empty($order_id) && $order->trade_status == Order::ORDER_FLOW_SEND) {
  2092. \Yii::warning(['----------------- 股东会员等级 ' . $value->name . ' 商品订单自动收货机制--------' . microtime(true), $goods['value']['is_confirm'], count($order_id), implode(',', $order_id)]);
  2093. // Order::updateAll(['trade_status' => Order::ORDER_FLOW_CONFIRM, 'confirm_time' => time()], ['and', ['in', 'id', $order_id], ['trade_status' => Order::ORDER_FLOW_SEND]]);
  2094. $order->trade_status = Order::ORDER_FLOW_CONFIRM;
  2095. $order->confirm_time = time();
  2096. $order->save();
  2097. }
  2098. }
  2099. $order_ids = (clone $order_model)->andWhere(['o.trade_status' => Order::ORDER_FLOW_CONFIRM, 'o.is_sale' => 0])->asArray()->all();
  2100. $order_id = array_column($order_ids, 'order_id');
  2101. if (!empty($order_id)) {
  2102. $after_sale_time = (int)$goods['value']['day'];
  2103. // $order_event = new OrderEvent();
  2104. \Yii::warning(['----------------- 股东会员等级 ' . $value->name . ' 商品订单自动售后机制--------' . microtime(true), $goods['value']['day'], count($order_id), implode(',', $order_id)]);
  2105. // $order_event->orderSend(1, $order_id, $value->store_id, $after_sale_time);
  2106. $delay = $after_sale_time * 86400;
  2107. $order_ = Order::findOne($order->id);
  2108. $order_->future_sales_time = bcadd(time(), $delay);
  2109. $order_->save();
  2110. if ($delay == 0) {
  2111. $delay = 60;
  2112. }
  2113. \queue_push(new \app\jobs\order\NoAfterSalesOrderJob(['store_id' => $order->store_id, 'order_id' => $order->id]), $delay);
  2114. }
  2115. }
  2116. }
  2117. } catch (\Exception $e) {
  2118. \Yii::error($e);
  2119. debug_log($e->getMessage(), __CLASS__ . '.log');
  2120. }
  2121. // \Yii::warning(['----------------- 股东会员等级 商品订单自动确认机制结束 --------' . microtime(true)]);
  2122. }
  2123. /**
  2124. * 检查是否可以申请股东
  2125. * @param $store_id
  2126. * @param $user_id
  2127. * @return array
  2128. */
  2129. public static function checkApply($store_id, $user_id) {
  2130. $share_level = ShareHolderLevel::findOne(['is_default' => 1, 'store_id' => $store_id, 'is_delete' => 0, 'status' => 1]);
  2131. if (!$share_level) {
  2132. return [
  2133. 'code' => 1,
  2134. 'msg' => '未找到相应等级'
  2135. ];
  2136. }
  2137. //TODO 股东人数以及金额
  2138. $condition = Json::decode($share_level->condition);
  2139. // 团队人数
  2140. $man = $condition['man'];
  2141. if ((bool)$man['is_open']) {
  2142. foreach ((array)$man['value'] as $m) {
  2143. $man_data = User::find()->childs($user_id, false, $m['level'])->where(['store_id' => $store_id])->asArray()->all();
  2144. if (count($man_data) < $m['count']) {
  2145. return [
  2146. 'code' => 1,
  2147. 'msg' => '团队人数:' . $m['level'] . '级团队人数未达到' . $m['count']
  2148. ];
  2149. } else {
  2150. if (isset($m['money'])) {
  2151. //消费达到$m['money']以上允许升级
  2152. $man_user_id = array_column($man_data, 'id');
  2153. $pay_price = Order::find()->where(
  2154. [
  2155. 'store_id' => $store_id,
  2156. 'is_delete' => 0,
  2157. 'trade_status' => Order::ORDER_FLOW_CONFIRM,
  2158. 'user_id' => $man_user_id
  2159. ])
  2160. ->andWhere(['or', ['is_pay' => 1], ['pay_type' => 2]])->sum('pay_price');
  2161. if ($m['money'] > $pay_price) {
  2162. return [
  2163. 'code' => 1,
  2164. 'msg' => '团队金额:' . $m['level'] . '级团队消费金额未达到' . $m['money']
  2165. ];
  2166. }
  2167. }
  2168. }
  2169. }
  2170. }
  2171. // 团队消费金额
  2172. $order = $condition['order'];
  2173. if ((bool)$order['is_open']) {
  2174. foreach ($order['value'] as $o) {
  2175. $man_data = User::find()->childs($user_id, false, $o['level'])->where(['store_id' => $store_id])->select('id')->asArray()->all();
  2176. if (count($man_data) < 1) {
  2177. return [
  2178. 'code' => 1,
  2179. 'msg' => '团队金额:' . $o['level'] . '级团队人数为空'
  2180. ];
  2181. }
  2182. $man_user_id = array_column($man_data, 'id');
  2183. $order_money = Order::find()->where(['store_id' => $store_id, 'is_delete' => 0, 'trade_status' => Order::ORDER_FLOW_CONFIRM])->andWhere(['in', 'user_id', $man_user_id])->sum('pay_price');
  2184. if ($order_money < $o['count']) {
  2185. return [
  2186. 'code' => 1,
  2187. 'msg' => '团队金额:' . $o['level'] . '级团队消费金额未达到' . $o['count']
  2188. ];
  2189. }
  2190. }
  2191. }
  2192. // 自身消费金额
  2193. $self = $condition['self'];
  2194. if ((bool)$self['is_open']) {
  2195. // 兼容老版本
  2196. if (!isset($self['value']['order_number'])) {
  2197. $self_price = $self['value'];
  2198. $self['value'] = [];
  2199. $self['value']['order_number'] = 0;
  2200. $self['value']['price'] = $self_price;
  2201. }
  2202. if ($self['value']['order_number'] == 1) {
  2203. //单笔
  2204. $order = Order::find()->where(['store_id' => $store_id, 'is_delete' => 0, 'trade_status' => Order::ORDER_FLOW_CONFIRM, 'user_id' => $user_id])
  2205. ->andWhere(['>=' , 'pay_price', $self['value']['price']])->one();
  2206. if (!$order) {
  2207. return [
  2208. 'code' => 1,
  2209. 'msg' => '您在本商城单笔消费未达到' . $self['value']['price'] . '元'
  2210. ];
  2211. }
  2212. } else{
  2213. //多笔
  2214. $order_money = Order::find()->where(['store_id' => $store_id, 'is_delete' => 0, 'trade_status' => Order::ORDER_FLOW_CONFIRM, 'user_id' => $user_id])->sum('pay_price');
  2215. if ($order_money < $self['value']['price']) {
  2216. return [
  2217. 'code' => 1,
  2218. 'msg' => '您在本商城消费未达到' . $self['value']['price'] . '元'
  2219. ];
  2220. }
  2221. }
  2222. }
  2223. // 自身充值金额
  2224. $recharge = $condition['recharge'];
  2225. if ((bool)$recharge['is_open']) {
  2226. $recharge_money = ReOrder::find()->where(['store_id' => $store_id, 'user_id' => $user_id, 'is_pay' => 1])->sum('pay_price');
  2227. if ($recharge_money < $recharge['value']) {
  2228. return [
  2229. 'code' => 1,
  2230. 'msg' => '您在本商城充值未达到' . $recharge['value'] . '元'
  2231. ];
  2232. }
  2233. }
  2234. // 购买指定商品
  2235. $goods = $condition['goods'];
  2236. if ((bool)$goods['is_open']) {
  2237. // 查找该用户是否买过此商品
  2238. $order_goods = Order::find()->alias('o')->leftJoin(['od' => OrderDetail::tableName()], 'od.order_id=o.id')->where(['o.store_id' => $store_id, 'o.user_id' => $user_id, 'o.is_delete' => 0, 'o.is_pay' => 1, 'o.trade_status' => Order::ORDER_FLOW_CONFIRM])
  2239. ->andWhere(['od.goods_id' => $goods['value']['id']])->one();
  2240. if (!$order_goods) {
  2241. return [
  2242. 'code' => 1,
  2243. 'msg' => '您未购买过指定商品'
  2244. ];
  2245. }
  2246. // 是否过了售后期
  2247. $pay_time = $order_goods->pay_time;
  2248. if (time() < ($pay_time + $goods['day'] * 24 * 3600)) {
  2249. return [
  2250. 'code' => 1,
  2251. 'msg' => '购买过的指定商品未过售后期'
  2252. ];
  2253. }
  2254. }
  2255. return [
  2256. 'code' => 0,
  2257. 'msg' => 'success'
  2258. ];
  2259. }
  2260. // 用户自己购买指定商品成为股东(已经是股东)
  2261. public static function userSelfBuyGoods2ShareHolder($order_id, $pay_up = 0)
  2262. {
  2263. if ($pay_up) {
  2264. debug_log(['pay_up' => $pay_up, 'order_id' => $order_id->id, 'userSelfBuyGoods2ShareHolder'], 'userAuto2ShareHolder.log');
  2265. }
  2266. $t = \Yii::$app->db->beginTransaction();
  2267. try {
  2268. if (!$order_id) {
  2269. throw new \Exception("订单id为空");
  2270. }
  2271. if(isset($order_id->id)){
  2272. $order = $order_id;
  2273. }else{
  2274. $order = Order::findOne($order_id);
  2275. }
  2276. $order_id = $order->id;
  2277. $user_id = $order->user_id;
  2278. $user = User::findOne($user_id);
  2279. $shareHolder = ShareHolder::findOne(['user_id' => $user_id, 'is_delete' => 0, 'store_id' => $order->store_id, 'status' => 1]);
  2280. if ($shareHolder) {
  2281. $level = ShareHolderLevel::findOne($shareHolder->level_id)->level;
  2282. //查找最高等级
  2283. $shareHolderLevelList = ShareHolderLevel::find()
  2284. ->where(['store_id' => $order->store_id, 'status' => 1, 'is_delete' => 0])
  2285. ->andWhere(['>', 'level', $level])
  2286. ->select('condition, id, level, member_level')
  2287. ->orderBy(['level' => SORT_DESC])->asArray()->all();
  2288. if (empty($shareHolderLevelList)) {
  2289. throw new \Exception("等级为空");
  2290. }
  2291. $level_id = 0;
  2292. $member_level = 0;
  2293. if ($pay_up) {
  2294. debug_log(['shareHolderLevelList' => $shareHolderLevelList], 'userAuto2ShareHolder.log');
  2295. }
  2296. foreach ($shareHolderLevelList as $item) {
  2297. $condition = json_decode($item['condition'], true);
  2298. if ((int)$condition['goods']['is_open'] === 1 && !empty($condition['goods']['value']['id'])) {
  2299. if($pay_up && ($condition['goods']['pay_up'] != 1)){
  2300. continue;
  2301. }
  2302. if($order->share_hold_pay_up == 1){
  2303. continue;
  2304. }
  2305. $order_detail = OrderDetail::find()->where(['order_id' => $order_id, 'goods_id' => $condition['goods']['value']['id']])->select('goods_id')->one();
  2306. if (!empty($order_detail)) {
  2307. $level_id = $item['id'];
  2308. $member_level = $item['member_level'];
  2309. break;
  2310. }
  2311. }
  2312. }
  2313. if ($level_id > 0) {
  2314. $old_level_id = $shareHolder->level_id;
  2315. $shareHolder->level_id = $level_id;
  2316. if ((int)$member_level > (int)$user->level) {
  2317. $user->level = $member_level;
  2318. $user->save();
  2319. }
  2320. $shareHolder->save();
  2321. if($pay_up){
  2322. $order->share_hold_pay_up = 1;
  2323. $order->save();
  2324. }
  2325. self::checkChildHolderUpdateLevel($user_id, $level_id);
  2326. self::checkLevel($order->store_id, 0, $user_id);
  2327. $level_log = new ShareHolderLevelLog();
  2328. $level_log->before_level = $old_level_id;
  2329. $level_log->after_level = $level_id;
  2330. $level_log->user_id = $user_id;
  2331. $level_log->store_id = $order->store_id;
  2332. $level_log->order_id = $order->id;
  2333. $level_log->desc = "用户购买指定商品升级更高等级股东";
  2334. if (!$level_log->save()) {
  2335. throw new Exception('等级更新失败');
  2336. }
  2337. }
  2338. }
  2339. $t->commit();
  2340. } catch (\Exception $e) {
  2341. $t->rollBack();
  2342. debug_log($e->getMessage(), 'userSelfBuyGoods2ShareHolder.log');
  2343. return [
  2344. 'code' => 1,
  2345. 'msg' => $e->getMessage()
  2346. ];
  2347. }
  2348. }
  2349. //用户购买指定商品成为股东
  2350. public static function userAuto2ShareHolder($order_id, $pay_up = 0)
  2351. {
  2352. if ($pay_up) {
  2353. debug_log(['pay_up' => $pay_up, 'order_id' => $order_id->id, 'userAuto2ShareHolder'], 'userAuto2ShareHolder.log');
  2354. }
  2355. $t = \Yii::$app->db->beginTransaction();
  2356. try {
  2357. if (!$order_id) {
  2358. throw new \Exception("订单id为空");
  2359. }
  2360. if(isset($order_id->id)){
  2361. $order = $order_id;
  2362. }else{
  2363. $order = Order::findOne($order_id);
  2364. }
  2365. $order_id = $order->id;
  2366. $user_id = $order->user_id;
  2367. $user = User::findOne($user_id);
  2368. $shareHolder = ShareHolder::findOne(['user_id' => $user_id, 'is_delete' => 0, 'store_id' => $order->store_id, 'status' => 1]);
  2369. if (empty($shareHolder)) {
  2370. //查找最高等级
  2371. $shareHolderLevelList = ShareHolderLevel::find()->where(['store_id' => $order->store_id, 'status' => 1, 'is_delete' => 0])->select('condition, id, level, member_level, store_id')->asArray()->all();
  2372. $id = [];
  2373. $num = 0;
  2374. if ($pay_up) {
  2375. debug_log(['shareHolderLevelList' => $shareHolderLevelList, 'store_id' => $order->store_id], 'userAuto2ShareHolder.log');
  2376. }
  2377. foreach ($shareHolderLevelList as $item) {
  2378. $condition = json_decode($item['condition'], true);
  2379. if ((int)$condition['goods']['is_open'] === 1 && !empty($condition['goods']['value']['id'])) {
  2380. if($pay_up && ($condition['goods']['pay_up'] != 1)){
  2381. continue;
  2382. }
  2383. if($order->share_hold_pay_up == 1){
  2384. continue;
  2385. }
  2386. //给首次升级成功股东的产品购买记录修改成标识为升级产品。 会在链动列表展示 升级产品 并在链动小推大逻辑中使用到。
  2387. $ShareHolderProfitGoodsLog = ShareHolderProfitGoodsLog::findOne(['order_id' => $order_id, 'goods_id' => $condition['goods']['value']['id']]);
  2388. if (!empty($ShareHolderProfitGoodsLog)) {
  2389. $ShareHolderProfitGoodsLog->is_switch = 1;
  2390. $ShareHolderProfitGoodsLog->save();
  2391. }
  2392. $order_detail = OrderDetail::find()->where(['order_id' => $order_id, 'goods_id' => $condition['goods']['value']['id']])->select('goods_id')->one();
  2393. if (!empty($order_detail)) {
  2394. $id[$num]['id'] = $item['id'];
  2395. $id[$num]['level'] = $item['level'];
  2396. $id[$num]['id'] = $item['id'];
  2397. $id[$num]['member_level'] = $item['member_level'];
  2398. $num++;
  2399. }
  2400. }
  2401. }
  2402. $last_names = array_column($id, 'level');
  2403. array_multisort($last_names, SORT_DESC, $id);
  2404. //查找用户是否存在或被拒绝或审核中
  2405. $shareHolder = ShareHolder::findOne(['user_id' => $user_id, 'is_delete' => 0, 'store_id' => $order->store_id]);
  2406. //不存在
  2407. if (empty($shareHolder) && empty($user->is_holder)) {
  2408. $last_names = array_column($id, 'level');
  2409. array_multisort($last_names, SORT_DESC, $id);
  2410. if (!empty($id)) {
  2411. $saas_user = SaasUser::findOne(['mobile' => $user->binding]);
  2412. $model = new ShareHolder();
  2413. $model->level_id = $id[0]['id'];
  2414. $model->store_id = $order->store_id;
  2415. $model->user_id = $user_id;
  2416. $model->name = $saas_user->name;
  2417. $model->address = '';
  2418. $model->mobile = $saas_user->mobile;
  2419. $model->province = 0;
  2420. $model->city = 0;
  2421. $model->district = 0;
  2422. $model->province_name = '';
  2423. $model->city_name = '';
  2424. $model->district_name = '';
  2425. $model->status = 1;
  2426. $model->audit_time = time();
  2427. $result = $model->save();
  2428. if (!$result) {
  2429. throw new \Exception(json_encode($model->errors));
  2430. }
  2431. if($pay_up){
  2432. $order->share_hold_pay_up = 1;
  2433. $order->save();
  2434. }
  2435. self::checkChildHolderUpdateLevel($user_id, $id[0]['id']);
  2436. self::checkLevel($order->store_id, 0, $model->user_id);
  2437. if ((int)$id[0]['member_level'] > (int)$user->level) {
  2438. $user->level = $id[0]['member_level'];
  2439. }
  2440. $user->is_holder = 1;
  2441. $result = $user->save();
  2442. if (!$result) {
  2443. throw new \Exception(json_encode($user->errors));
  2444. }
  2445. }
  2446. }
  2447. if (!empty($id) && !empty($shareHolder) && in_array($shareHolder->status, [0, 2])) {
  2448. $shareHolder->level_id = $id[0]['id'];
  2449. $shareHolder->status = 1;
  2450. $result = $shareHolder->save();
  2451. if (!$result) {
  2452. throw new \Exception(json_encode($shareHolder->errors));
  2453. }
  2454. self::checkLevel($order->store_id, 0, $shareHolder->user_id);
  2455. // self::checkChildHolderUpdateLevel($user->id, $shareHolder->level_id);
  2456. $user->level = $id[0]['member_level'];
  2457. $user->is_holder = 1;
  2458. $result = $user->save();
  2459. if (!$result) {
  2460. throw new \Exception(json_encode($user->errors));
  2461. }
  2462. }
  2463. //添加股东升级记录
  2464. if (!empty($id)) {
  2465. //添加股东升级记录
  2466. $level_log = new ShareHolderLevelLog();
  2467. $level_log->before_level = 0;
  2468. $level_log->after_level = $id[0]['level'];
  2469. $level_log->user_id = $user_id;
  2470. $level_log->store_id = $order->store_id;
  2471. $level_log->order_id = $order->id;
  2472. $level_log->desc = "用户购买指定商品升级为股东";
  2473. if (!$level_log->save()) {
  2474. throw new Exception('等级更新失败');
  2475. }
  2476. }
  2477. }
  2478. $t->commit();
  2479. } catch (\Exception $e) {
  2480. \Yii::error($e);
  2481. $t->rollBack();
  2482. return [
  2483. 'code' => 1,
  2484. 'msg' => $e->getMessage(),
  2485. 'line' => $e->getLine(),
  2486. ];
  2487. }
  2488. }
  2489. public static function sendFrostMoney($child_id, $store_id)
  2490. {
  2491. $parent_log = ShareHolderOutLog::findOne(['child_user_id' => $child_id]);
  2492. if (!$parent_log) {
  2493. return;
  2494. }
  2495. $count = ShareHolderOutLog::find()->where([
  2496. 'parent_user_id' => $parent_log->parent_user_id,
  2497. 'status' => 0,
  2498. ])->count();
  2499. if ($count > 0) {
  2500. return;
  2501. }
  2502. $shareHolderFrostSendCond = Option::get('shareHolderFrostSendCond', $store_id, 'bonus_pool', 0)['value'];
  2503. if($shareHolderFrostSendCond){
  2504. $child_data = ShareHolderOutLog::find()->where([
  2505. 'parent_user_id' => $parent_log->parent_user_id,
  2506. 'status' => 1,
  2507. ])->asArray()->all();
  2508. foreach($child_data as $child){
  2509. $child_out = ShareHolderOutLog::findOne(['parent_user_id' => $child_id, 'status' => 1]);
  2510. if (!$child_out) {
  2511. return;
  2512. }
  2513. $count = ShareHolderOutLog::find()->where([
  2514. 'parent_user_id' => $child['child_user_id'],
  2515. 'status' => 0,
  2516. ])->count();
  2517. if ($count > 0) {
  2518. return;
  2519. }
  2520. }
  2521. }
  2522. $t = \Yii::$app->db->beginTransaction();
  2523. try {
  2524. $frost_log_amout = ShareHolderFrostLog::find()->where([
  2525. 'parent_user_id' => $parent_log->parent_user_id,
  2526. 'status' => 0,
  2527. ])->sum('amount');
  2528. ShareHolderFrostLog::updateAll([
  2529. 'status' => 1,
  2530. 'updated_at' => time(),
  2531. ], [
  2532. 'parent_user_id' => $parent_log->parent_user_id,
  2533. 'status' => 0,
  2534. ]);
  2535. $detail = new ShareDetail();
  2536. $detail->store_id = $store_id;
  2537. $detail->type_id = 0;
  2538. $detail->type = ShareDetail::TYPE_FROST_PROFIT;
  2539. $detail->user_id = $parent_log->parent_user_id;
  2540. $detail->desc = '冻结佣金释放';
  2541. $detail->money = $frost_log_amout;
  2542. $detail->is_send = 1;
  2543. $detail->save();
  2544. $user = User::findOne($parent_log->parent_user_id);
  2545. $user->updateCounters(['total_price' => $frost_log_amout, 'price' => $frost_log_amout]);
  2546. $t->commit();
  2547. } catch (\Exception $e) {
  2548. $t->rollBack();
  2549. }
  2550. }
  2551. public static function getShareHolderLevelOption($store_id)
  2552. {
  2553. try {
  2554. $list = ShareHolderLevel::find()->where(['store_id' => $store_id, 'is_delete' => 0])->asArray()->all();
  2555. $new_list = [];
  2556. foreach ($list as $item) {
  2557. if ($item['condition']) {
  2558. $condition = json_decode($item['condition'], true);
  2559. if ($condition['goods']['is_open'] == 1 && count($condition['goods']['value']['id']) > 0) {
  2560. $new_list[] = [
  2561. 'goods_ids' => $condition['goods']['value']['id'],
  2562. 'day' => (int)$condition['goods']['value']['day'],
  2563. ];
  2564. }
  2565. }
  2566. }
  2567. return $new_list;
  2568. } catch (\Throwable $e) {
  2569. return [];
  2570. }
  2571. }
  2572. // 取消订单后删除股东分红记录
  2573. public static function cancelOrderShareDetail($order_id)
  2574. {
  2575. try {
  2576. ShareDetail::updateAll(['is_delete' => 1], ['type_id' => $order_id]);
  2577. } catch (\Throwable $e) {
  2578. // Todo
  2579. }
  2580. }
  2581. public static function userSlide($order) {
  2582. $t = \Yii::$app->db->beginTransaction();
  2583. try {
  2584. $list = ShareDetail::find()->where(['type_id' => $order->id, 'type' => [ShareDetail::TYPE_RANGE_PROFIT, ShareDetail::TYPE_RANGE_PROFIT_OLD, ShareDetail::TYPE_RANGE_PROFIT_OLD_USER_LEVEL], 'is_delete' => 0])->all();
  2585. if ($list) {
  2586. foreach ($list as $share_detail) {
  2587. $handle_child_data_order_id = cache()->get('handle_child_data_order_id' . $order->id);
  2588. if (!$handle_child_data_order_id) {
  2589. ShareDetail::handleChildData($share_detail->id);
  2590. cache()->set('handle_child_data_order_id' . $order->id, 1);
  2591. }
  2592. }
  2593. }
  2594. $t->commit();
  2595. } catch (\Exception $e) {
  2596. $t->rollBack();
  2597. }
  2598. }
  2599. }