ShareDetail.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. <?php
  2. /**
  3. * 厦门云联储网络科技有限公司
  4. * https://www.baokuaiyun.com
  5. * Copyright (c) 2023 爆块云 All rights reserved.
  6. */
  7. namespace app\models;
  8. use app\utils\Share\BonusPool;
  9. use yii\db\ActiveRecord;
  10. use yii\behaviors\TimestampBehavior;
  11. use Yii;
  12. /**
  13. * This is the model class for table "{{%share_detail}}".
  14. *
  15. * @property integer $id
  16. * @property integer $store_id
  17. * @property integer $user_id
  18. * @property integer $money
  19. * @property integer $is_send
  20. * @property integer $type
  21. * @property integer $type_id
  22. * @property string $desc
  23. * @property string $remark
  24. * @property integer $is_delete
  25. * @property integer $created_at
  26. * @property integer $send_time
  27. * @property integer $updated_at
  28. */
  29. class ShareDetail extends \yii\db\ActiveRecord
  30. {
  31. /**
  32. * 股东分红
  33. */
  34. const TYPE_HOLDER_PROFIT = 1;
  35. /**
  36. * 极差分红
  37. */
  38. const TYPE_RANGE_PROFIT = 2;
  39. /**
  40. * 区域分红
  41. */
  42. const TYPE_AREA_PROFIT = 3;
  43. /**
  44. * 基础分销
  45. */
  46. const TYPE_SHARE_PROFIT = 4;
  47. /**
  48. * 2+1股东分销
  49. */
  50. const TYPE_TWO_PLUS_ONE_SHARE_PROFIT = 5;
  51. /**
  52. * 2+1直推团队收益比例
  53. */
  54. const TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT = 6;
  55. /**
  56. * 极差分红(原关系)
  57. */
  58. const TYPE_RANGE_PROFIT_OLD = 7;
  59. /**
  60. * 2+1直推团队收益比例(原关系)
  61. */
  62. const TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT_OLD = 8;
  63. /**
  64. * 冻结金额
  65. */
  66. const TYPE_FROST_PROFIT = 9;
  67. /**
  68. * 极差分红_会员方式(原关系)
  69. */
  70. const TYPE_RANGE_PROFIT_OLD_USER_LEVEL = 10;
  71. /**
  72. * @inheritdoc
  73. */
  74. public static function tableName()
  75. {
  76. return '{{%share_detail}}';
  77. }
  78. public function behaviors()
  79. {
  80. return [
  81. [
  82. 'class' => TimestampBehavior::class,
  83. 'attributes' => [
  84. ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
  85. ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at']
  86. ]
  87. ]
  88. ];
  89. }
  90. /**
  91. * @inheritdoc
  92. */
  93. public function rules()
  94. {
  95. return [
  96. [['store_id', 'user_id', 'is_send', 'type', 'type_id', 'created_at', 'updated_at', 'is_delete', 'send_time'], 'integer'],
  97. [['money'], 'number'],
  98. [['desc', 'remark'], 'string'],
  99. [['created_at', 'updated_at'], 'safe']
  100. ];
  101. }
  102. public function afterSave($insert, $changedAttributes)
  103. {
  104. parent::afterSave($insert, $changedAttributes); // TODO: Change the autogenerated stub
  105. $share_detail_arr = [
  106. ShareDetail::TYPE_HOLDER_PROFIT,
  107. ShareDetail::TYPE_RANGE_PROFIT,
  108. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_PROFIT,
  109. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT,
  110. ShareDetail::TYPE_RANGE_PROFIT_OLD,
  111. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT_OLD,
  112. ShareDetail::TYPE_RANGE_PROFIT_OLD_USER_LEVEL
  113. ];
  114. // if (in_array($this->type, $share_detail_arr) && intval($this->is_send)) {
  115. //// $this->handleChildData($this->user_id);
  116. // }
  117. }
  118. public static function handleChildData($id, $parent_id = 0)
  119. {
  120. //$t = \Yii::$app->db->beginTransaction();
  121. // $user = User::findOne($user_id);
  122. // $parent_id = $user->old_parent_id;
  123. if (!$parent_id) {
  124. $share_detail = self::findOne($id);
  125. $parent_id = $share_detail->user_id;
  126. $store_id = $share_detail->store_id;
  127. } else {
  128. $user = User::findOne($parent_id);
  129. $store_id = $user->store_id;
  130. }
  131. $holder_level_list = ShareHolderLevel::find()->where([
  132. 'is_delete' => 0,
  133. 'status' => 1,
  134. 'store_id' => $store_id,
  135. ])->all();
  136. // 找出符合条件的等级
  137. $current_level = null;
  138. foreach ($holder_level_list as $holder_level) {
  139. $condition = json_decode($holder_level->condition);
  140. if ((bool)$condition->shareholder->is_open &&
  141. (int)$condition->shareholder->num > 0 &&
  142. (bool)$condition->shareholder->independent_team
  143. ) {
  144. $current_level = $holder_level;
  145. break;
  146. }
  147. }
  148. if ($current_level == null) {
  149. return;
  150. }
  151. $share_detail_arr = [
  152. ShareDetail::TYPE_HOLDER_PROFIT,
  153. ShareDetail::TYPE_RANGE_PROFIT,
  154. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_PROFIT,
  155. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT,
  156. ShareDetail::TYPE_RANGE_PROFIT_OLD,
  157. ShareDetail::TYPE_TWO_PLUS_ONE_SHARE_TEAM_PROFIT_OLD,
  158. ShareDetail::TYPE_RANGE_PROFIT_OLD_USER_LEVEL
  159. ];
  160. //比如滑落设置为2 ,那么就是满2个人第三个人贡献了直推佣金后,放到第一个下级下面
  161. //设置滑落数量时需要判断是否大于 可助力出局人数
  162. $shareHolderChangeOldParentSwitch = Option::get('shareHolderChangeOldParentSwitch', $store_id, 'bonus_pool', 0)['value'];
  163. $shareHolderChangeOldParentNumber = Option::get('shareHolderChangeOldParentNumber', $store_id, 'bonus_pool', 0)['value'];
  164. $shareHolderChangeChildMinNumber = Option::get('shareHolderChangeChildMinNumber', $store_id, 'bonus_pool', 0)['value'];
  165. /*debug_log([
  166. 'shareHolderChangeOldParentSwitch' => $shareHolderChangeOldParentSwitch,
  167. 'shareHolderChangeOldParentNumber' => $shareHolderChangeOldParentNumber,
  168. 'shareHolderChangeChildMinNumber' => $shareHolderChangeChildMinNumber
  169. ], 'user_new.log');*/
  170. //设置滑落数量时需要判断是否大于 可助力出局人数
  171. $condition = json_decode($current_level->condition, true);
  172. //设置滑落数量时需要判断是否大于 可助力出局人数
  173. // if ($condition['shareholder']['num'] > $shareHolderChangeOldParentNumber) {
  174. // return;
  175. // }
  176. if (!intval($shareHolderChangeOldParentSwitch) || $shareHolderChangeOldParentNumber <= 1 || $shareHolderChangeOldParentNumber <= $shareHolderChangeChildMinNumber) {
  177. return;
  178. }
  179. $i = 0;
  180. reset:
  181. if ($i > $shareHolderChangeOldParentNumber) {
  182. return;
  183. }
  184. //查询真实id
  185. $real_child_id = User::find()->alias('u')
  186. ->leftJoin(['h' => ShareHolder::tableName()], 'u.id=h.user_id')
  187. ->where(['u.parent_id' => $parent_id, 'u.is_delete' => 0, 'h.is_delete' => 0, 'h.status' => 1])->andWhere('h.id is not null')->select('u.id')->column();
  188. //查询自己下的所有历史下级
  189. $query = UserTreePath::find()->alias('ut')
  190. ->leftJoin(['h' => ShareHolder::tableName()], 'ut.parent_id=h.user_id')
  191. ->where(['ut.parent_id' => $parent_id])
  192. ->andWhere('h.id is not null')
  193. ->andWhere('ut.child_id != ut.parent_id')
  194. ->andWhere(['IN', 'ut.child_id', $real_child_id])
  195. ->orderBy(['ut.created_at' => SORT_ASC]);
  196. /*debug_log([
  197. 'sql' => $query->createCommand()->getRawSql()
  198. ], 'user_new.log');*/
  199. $user_child = $query->asArray()->all();
  200. $user_child = array_values($user_child);
  201. debug_log([
  202. 'old_parent_id' => $parent_id,
  203. 'user_child' => $user_child,
  204. 'real_child' => $real_child_id
  205. ], 'user_new.log');
  206. $old_child_id = array_column($user_child, 'child_id');
  207. //判断自己下级是否超过三项
  208. if (count($user_child) > $shareHolderChangeOldParentNumber) {
  209. //重新组合数据 便于遍历除前三项剩余的下级
  210. $data = $user_child;
  211. foreach ($data as $old_index => $old_item) {
  212. if ($old_index < $shareHolderChangeOldParentNumber) {
  213. unset($data[$old_index]);
  214. continue;
  215. }
  216. }
  217. $data = array_values($data);//剩余的下级开始遍历分配上级
  218. debug_log([
  219. 'data' => $data
  220. ], 'user_new.log');
  221. //判断第三项是否已经出局
  222. $share_holder_3 = ShareHolder::findOne(['user_id' => $user_child[$i]['child_id'], 'is_delete' => 0]);
  223. debug_log([
  224. 'share_holder_3_id' => $share_holder_3->id
  225. ], 'user_new.log');
  226. if (!$share_holder_3) {
  227. ++$i;
  228. goto reset;
  229. }
  230. //未出局
  231. //获取是自己发展的下级人数
  232. $user_child_id_arr = User::find()->where(['old_parent_id' => $user_child[$i]['child_id'], 'is_delete' => 0])
  233. ->select('id')->column();
  234. /*debug_log([
  235. 'user_child_id_arr' => $user_child_id_arr
  236. ], 'user_new.log');*/
  237. $shareHolderParentOutQuery= ShareHolderParentOutLog::find()
  238. ->where([
  239. 'change_type' => ShareHolderParentOutLog::CHANGE_TYPE_NORMAL,
  240. 'parent_user_id' => $user_child[$i]['child_id'],
  241. 'type' => 1,
  242. 'user_id' => $user_child_id_arr
  243. ]);
  244. /*debug_log([
  245. 'shareHolderParentOutLogSql' => $shareHolderParentOutQuery->createCommand()->getRawSql()
  246. ], 'user_new.log');*/
  247. $shareHolderParentOutLog = $shareHolderParentOutQuery->asArray()->count() ?? 0;
  248. /*debug_log([
  249. 'shareHolderParentOutLog' => $shareHolderParentOutLog
  250. ], 'user_new.log');*/
  251. foreach ($data as $d_item) {
  252. $user_ = User::findOne($d_item['child_id']);
  253. $beforeParentId = $user_->parent_id;
  254. $beforeOldParentId = $user_->old_parent_id;
  255. if ($user_) {
  256. //贡献了直推佣金后,放到第一个下级下面
  257. $share_detail = ShareDetail::find()->alias('sd')
  258. ->leftJoin(['o' => Order::tableName()], 'o.id = sd.type_id')
  259. ->where(['o.user_id' => $d_item['child_id'], 'sd.type' => $share_detail_arr, 'sd.user_id' => $user_->old_parent_id])
  260. ->asArray()->one();
  261. if (!$share_detail) {
  262. continue;
  263. }
  264. //获取下级人数
  265. $user_child_count = User::find()->where(['old_parent_id' => $user_child[$i]['child_id'], 'is_delete' => 0])
  266. ->select('id')->count();
  267. /*debug_log([
  268. 'new_user_count' => $user_child_count
  269. ], 'user_new.log');*/
  270. if ($user_child_count >= $shareHolderChangeOldParentNumber) {
  271. self::handleChildData(0, $user_child[$i]['child_id']);
  272. ++$i;
  273. goto reset;
  274. }
  275. //判断下级人数是否符合滑落需求
  276. if (($shareHolderParentOutLog < $shareHolderChangeChildMinNumber && ($shareHolderChangeChildMinNumber + $user_child_count) >= $shareHolderChangeOldParentNumber)) {
  277. self::handleChildData(0, $user_child[$i]['child_id']);
  278. ++$i;
  279. goto reset;
  280. }
  281. // 2
  282. if ($shareHolderChangeChildMinNumber <= $shareHolderParentOutLog) {//0 < 1
  283. $count = $condition['shareholder']['num'] - $user_child_count;
  284. if ($count > 0) {
  285. $user_->old_parent_id = $user_child[$i]['child_id'];
  286. $user_->parent_id = $user_child[$i]['child_id'];
  287. $user_->save();
  288. $result = \app\utils\Share\BonusPool::addShareHolderParentOutLog($user_, $beforeOldParentId, ShareHolderParentOutLog::getConditionName(101), 1, ShareHolderParentOutLog::CHANGE_TYPE_CHANGE_OLD_PARENT);
  289. $result = \app\utils\Share\BonusPool::addShareHolderParentOutLog($user_, $beforeParentId, ShareHolderParentOutLog::getConditionName(101), 0, ShareHolderParentOutLog::CHANGE_TYPE_CHANGE_OLD_PARENT);
  290. }
  291. //检测是否可以出局
  292. BonusPool::checkChildHolderUpdateLevel($d_item['child_id']);
  293. } else {
  294. if ($user_child_count - $condition['shareholder']['num'] >= 0) {//2 3
  295. //检测是否可以出局
  296. BonusPool::checkChildHolderUpdateLevel($d_item['child_id']);
  297. } else {//3 2 1
  298. $count = $condition['shareholder']['num'] - $shareHolderChangeChildMinNumber;
  299. if ($count > 0) {//2 > 2
  300. $user_->old_parent_id = $user_child[$i]['child_id'];
  301. $user_->parent_id = $user_child[$i]['child_id'];
  302. $user_->save();
  303. $result = \app\utils\Share\BonusPool::addShareHolderParentOutLog($user_, $beforeOldParentId, ShareHolderParentOutLog::getConditionName(101), 1, ShareHolderParentOutLog::CHANGE_TYPE_CHANGE_OLD_PARENT);
  304. $result = \app\utils\Share\BonusPool::addShareHolderParentOutLog($user_, $beforeParentId, ShareHolderParentOutLog::getConditionName(101), 0, ShareHolderParentOutLog::CHANGE_TYPE_CHANGE_OLD_PARENT);
  305. //检测是否可以出局
  306. BonusPool::checkChildHolderUpdateLevel($d_item['child_id']);
  307. }
  308. }
  309. }
  310. $user_share_holder_ = ShareHolder::findOne(['user_id' => $user_->id, 'status' => 1, 'is_delete' => 0]);
  311. if (intval($user_share_holder_->is_out)) {
  312. ++$i;
  313. goto reset;
  314. }
  315. }
  316. }
  317. }
  318. //$t->rollBack();
  319. }
  320. }