LalaPinkJoin.php 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977
  1. <?php
  2. namespace app\models\lala;
  3. use app\models\point_plan\PointPlan;
  4. use app\models\point_plan\UserPointPlan;
  5. use app\models\system\Message;
  6. use app\models\system\SystemMoney;
  7. use app\models\user\User;
  8. use app\models\user\UserBill;
  9. use app\models\user\UserLevel;
  10. use app\models\user\UserMoney;
  11. use crmeb\traits\ModelTrait;
  12. use crmeb\basic\BaseModel;
  13. use Exception;
  14. use think\db\exception\DataNotFoundException;
  15. use think\db\exception\DbException;
  16. use think\db\exception\ModelNotFoundException;
  17. use think\facade\Log;
  18. use think\model\relation\HasOne;
  19. /**
  20. * TODO 文章Model
  21. * Class Article
  22. * @package app\models\article
  23. */
  24. class LalaPinkJoin extends BaseModel
  25. {
  26. /**
  27. * 数据表主键
  28. * @var string
  29. */
  30. protected $pk = 'id';
  31. /**
  32. * 模型名称
  33. * @var string
  34. */
  35. protected $name = 'lala_pink_join';
  36. use ModelTrait;
  37. /**
  38. * @return HasOne
  39. */
  40. public function activity(): HasOne
  41. {
  42. return $this->hasOne(LalaPink::class, 'id', 'lala_id')->field('id,name,background_image,join_number,bingo_number,sp_exchange_bingo_time');
  43. }
  44. /**
  45. * @return HasOne
  46. */
  47. public function user(): HasOne
  48. {
  49. return $this->hasOne(User::class, 'uid', 'uid')->field('uid,nickname,avatar,account,real_name');
  50. }
  51. /**
  52. * @param $uid
  53. * @param $id
  54. * @return bool
  55. * @throws DataNotFoundException
  56. * @throws DbException
  57. * @throws ModelNotFoundException
  58. */
  59. public static function join($uid, $id, $cost_type = ''): bool
  60. {
  61. $open = sys_config('lala_pink_open');
  62. $close = sys_config('lala_pink_close');
  63. if (time() < strtotime(date('Y-m-d') . $open) || time() >= strtotime(date('Y-m-d') . $close)) {
  64. return self::setErrorInfo('当前时间不在拼购时间段内');
  65. }
  66. $open_times = open_times();
  67. //上次开奖
  68. $last_log = LalaPinkLog::order('add_time', 'desc')->find();
  69. //本次开奖
  70. $this_time = [];
  71. if (!$last_log)
  72. foreach ($open_times as $v) {
  73. if ($v['value'] < time()) {
  74. $this_time = $v;
  75. }
  76. }
  77. else {
  78. foreach ($open_times as $v) {
  79. if ($v['value'] > $last_log['add_time'] && $v['value'] < time()) {
  80. $this_time = $v;
  81. break;
  82. }
  83. }
  84. }
  85. if ($this_time) {
  86. return self::setErrorInfo('预约已结束,等待上一场开奖');
  87. }
  88. //下次开奖
  89. $next_time = [];
  90. $next_group = 0;
  91. foreach ($open_times as $k => $v) {
  92. if ($v['value'] > time() && $v['value'] > $last_log['add_time']) {
  93. $next_time = $v;
  94. $next_group = $k + 1;
  95. break;
  96. }
  97. }
  98. if (time() + sys_config('lala_pink_close_join_before_open') * 60 > $next_time['value']) {
  99. return self::setErrorInfo('开奖前' . sys_config('lala_pink_close_join_before_open') . '分钟关闭参与通道!');
  100. }
  101. $activity = LalaPink::validWhere()->where('id', $id)->find();
  102. if (!$activity) return self::setErrorInfo('未找到有效活动');
  103. if ($cost_type == '') $cost_type = $activity['cost_money_type'];
  104. if ($cost_type != $activity['cost_money_type'] && $cost_type != $activity['cost_2_money_type']) return self::setErrorInfo('不支持该币种支付');
  105. if ($cost_type == $activity['cost_2_money_type'] && $cost_type != $activity['cost_money_type']) {
  106. $activity['cost_money_type'] = $activity['cost_2_money_type'];
  107. $activity['cost'] = $activity['cost_2'];
  108. }
  109. if ($activity['ticket_money_type'] != 'LALA') {
  110. $money_types = sys_data('money_type');
  111. $origin_ratio = 0;
  112. $target_ratio = get_lala_ratio();
  113. foreach ($money_types as $v) {
  114. if ($v['code'] == $activity['ticket_money_type']) {
  115. $origin_ratio = $v['usdt_price'];
  116. if ($origin_ratio == 0) {
  117. $origin_ratio = get_huobi_price($v['code']);
  118. }
  119. }
  120. }
  121. $ratio = bcdiv($origin_ratio, $target_ratio, 14);
  122. $activity['ticket'] = bcmul($activity['ticket'], $ratio, 8);
  123. $activity['ticket_money_type'] = 'LALA';
  124. }
  125. $user = User::getUserInfo($uid);
  126. if (!$user) return self::setErrorInfo('用户异常');
  127. if (self::where('paid', 1)->where('status', 0)->where('lala_id', $id)->where('uid', $uid)->find()) return self::setErrorInfo('已有参与中的拼购,请等待下一场!');
  128. if (self::where('paid', 1)->where('uid', $uid)->where('lala_id', $id)->whereTime('pay_time', 'today')->count() >= $activity['join_limit']) return self::setErrorInfo('今日参与次数已达上限,明天再来吧!');
  129. $user_cost_money = UserMoney::initialUserMoney($uid, $activity['cost_money_type']);
  130. $user_ticket_money = UserMoney::initialUserMoney($uid, $activity['ticket_money_type']);
  131. if ($user_cost_money['money'] < $activity['cost']) return self::setErrorInfo('参与拼购的' . $activity['cost_money_type'] . '不足' . $activity['cost']);
  132. if ($user_ticket_money['money'] < $activity['ticket']) return self::setErrorInfo('参与拼购的门票' . $activity['ticket_money_type'] . '不足' . $activity['ticket']);
  133. BaseModel::beginTrans();
  134. try {
  135. $bingo_count = LalaPinkJoin::where('uid', $uid)->where('lala_id', $id)->where('status', 1)->where('paid', 1)->count();
  136. $fail_count = LalaPinkJoin::where('uid', $uid)->where('lala_id', $id)->where('status', 'in', [2, 3])->where('paid', 1)->count();
  137. // var_dump($item['activity']);
  138. $flag = true;
  139. if (($bingo_count + 1) % 11 == 0) {
  140. $times = floor($bingo_count / 11) + 1;
  141. if ($fail_count + $bingo_count < $times * $activity['bingo_limit']) {
  142. $flag = false;
  143. }
  144. }
  145. if (in_array($uid, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 20, 21, 30])) {
  146. if (rand(1, 100) < 80) {
  147. $flag = false;
  148. }
  149. }
  150. //生成订单
  151. $res0 = self::create([
  152. 'uid' => $uid,
  153. 'lala_id' => $id,
  154. 'cost' => $activity['cost'],
  155. 'cost_money_type' => $activity['cost_money_type'],
  156. 'ticket' => $activity['ticket'],
  157. 'ticket_money_type' => $activity['ticket_money_type'],
  158. 'bingo' => $activity['bingo'],
  159. 'bingo_money_type' => $activity['bingo_money_type'],
  160. 'join_award' => bcmul(bcdiv($activity['join_award_ratio'], 100, 8), $activity['cost'], 8),
  161. 'system_money' => bcmul(bcdiv($activity['system_money_ratio'], 100, 8), $activity['cost'], 8),
  162. 'add_time' => time(),
  163. 'site_id' => $user['site_id'],
  164. 'order_id' => self::getNewOrderId($uid),
  165. 'group_num' => $next_group,
  166. 'set_status' => $flag ? 0 : 2
  167. ]);
  168. if (!$res0) {
  169. return BaseModel::setErrorInfo('生成订单失败', true);
  170. }
  171. //支付门票
  172. $res1 = UserMoney::expendMoney($uid, $activity['ticket_money_type'], $activity['ticket'], 'lala_ticket', '拼购门票', '参与拼购支付门票费用', $res0->id, false);
  173. if (!$res1) {
  174. return BaseModel::setErrorInfo(UserMoney::getErrorInfo(), true);
  175. }
  176. //支付
  177. $res2 = UserMoney::expendMoney($uid, $activity['cost_money_type'], $activity['cost'], 'lala_cost', '参与拼购', '参与拼购支付', $res0->id, false);
  178. if (!$res2) {
  179. return BaseModel::setErrorInfo(UserMoney::getErrorInfo(), true);
  180. }
  181. $res3 = self::where('id', $res0->id)->update(['paid' => 1, 'pay_time' => time()]);
  182. if (!$res3) {
  183. return BaseModel::setErrorInfo('支付失败,请重试', true);
  184. }
  185. // $res4 = true;
  186. $res4 = self::sendPointAward($res0);
  187. BaseModel::checkTrans($res4);
  188. if ($res4)
  189. return true;
  190. else
  191. return self::setErrorInfo(self::getErrorInfo());
  192. } catch (Exception $e) {
  193. return BaseModel::setErrorInfo($e->getMessage(), true);
  194. }
  195. }
  196. /**
  197. * @param $order
  198. * @return bool
  199. * @throws DataNotFoundException
  200. * @throws DbException
  201. * @throws ModelNotFoundException
  202. */
  203. public static function sendJoinAward($order): bool
  204. {
  205. $lala = LalaPink::where('id', $order['lala_id'])->find();
  206. $order['cost_money_type'] = $lala['cost_money_type'];
  207. $res = UserMoney::incomeMoney($order['uid'], $order['cost_money_type'], $order['join_award'], 'join_award', '参与奖', '参与拼购获得参与奖', $order['id'], 0);
  208. return $res ?: self::setErrorInfo('发放参与奖失败');
  209. }
  210. /**
  211. * @param $order
  212. * @return bool
  213. * @throws DataNotFoundException
  214. * @throws DbException
  215. * @throws ModelNotFoundException
  216. */
  217. public static function addSystemAward($order): bool
  218. {
  219. $lala = LalaPink::where('id', $order['lala_id'])->find();
  220. $order['cost_money_type'] = $lala['cost_money_type'];
  221. $res = SystemMoney::incomeMoney($order['site_id'], $order['cost_money_type'], $order['system_money'], 'lala_join', '用户参与拼购', '用户参与拼购,奖池累加', $order['id']);
  222. return $res ?: self::setErrorInfo('奖池累加失败');
  223. }
  224. /**
  225. * @param $order
  226. * @return bool
  227. * @throws DataNotFoundException
  228. * @throws DbException
  229. * @throws ModelNotFoundException
  230. */
  231. public static function sendRecommendAward($order): bool
  232. {
  233. $lala = LalaPink::where('id', $order['lala_id'])->find();
  234. $order['cost_money_type'] = $lala['cost_money_type'];
  235. // return true;
  236. $userInfo = User::getUserInfo($order['uid']);
  237. if (!$userInfo || !$userInfo['spread_uid'] || $userInfo['spread_uid'] == $order['uid']) return true;
  238. if (!User::be(['uid' => $userInfo['spread_uid'], 'is_promoter' => 1])) return self::sendRecommendAwardTwo($order);
  239. if (!self::where('paid', 1)->whereTime('add_time', 'today')->where('uid', $userInfo['spread_uid'])->find()) return self::sendRecommendAwardTwo($order);
  240. $ratio = sys_config('store_brokerage_ratio');
  241. if ($ratio <= 0) {
  242. return true;
  243. }
  244. $brokerageRatio = bcdiv($ratio, 100, 4);
  245. $brokeragePrice = bcmul($order['cost'], $brokerageRatio, 8);
  246. if ($brokeragePrice <= 0) return true;
  247. $mark = '下级用户' . $userInfo['nickname'] . '(' . $order['uid'] . ')' . '参与拼购,获得分享奖励' . $brokeragePrice;
  248. $res = UserMoney::incomeMoney($userInfo['spread_uid'], $order['cost_money_type'], $brokeragePrice, 'lala_recommend_award', '分享奖励', $mark, $order['id'], 0);
  249. return $res && self::sendRecommendAwardTwo($order);
  250. }
  251. /**
  252. * @param $order
  253. * @return bool
  254. * @throws DataNotFoundException
  255. * @throws DbException
  256. * @throws ModelNotFoundException
  257. */
  258. public static function sendRecommendAwardTwo($order): bool
  259. {
  260. $lala = LalaPink::where('id', $order['lala_id'])->find();
  261. $order['cost_money_type'] = $lala['cost_money_type'];
  262. $userInfo = User::getUserInfo($order['uid']);
  263. $userInfoTwo = User::getUserInfo($userInfo['spread_uid']);
  264. if (!$userInfoTwo || !$userInfoTwo['spread_uid'] || $userInfoTwo['spread_uid'] == $order['uid']) return true;
  265. if (!User::be(['uid' => $userInfoTwo['spread_uid'], 'is_promoter' => 1])) return true;
  266. if (!self::where('paid', 1)->whereTime('add_time', 'today')->where('uid', $userInfoTwo['spread_uid'])->find()) return true;
  267. $ratio = sys_config('store_brokerage_two');
  268. if ($ratio <= 0) {
  269. return true;
  270. }
  271. $brokerageRatio = bcdiv($ratio, 100, 4);
  272. $brokeragePrice = bcmul($order['cost'], $brokerageRatio, 8);
  273. if ($brokeragePrice <= 0) return true;
  274. $mark = '下下级用户' . $userInfo['nickname'] . '(' . $order['uid'] . ')' . '参与拼购,获得分享奖励' . $brokeragePrice;
  275. return UserMoney::incomeMoney($userInfoTwo['spread_uid'], $order['cost_money_type'], $brokeragePrice, 'lala_recommend_award', '分享奖励', $mark, $order['id'], 0);
  276. }
  277. /**
  278. * @param $order
  279. * @return bool
  280. * @throws DataNotFoundException
  281. * @throws DbException
  282. * @throws ModelNotFoundException
  283. */
  284. public static function sendGroupAward($order): bool
  285. {
  286. $lala = LalaPink::where('id', $order['lala_id'])->find();
  287. $order['cost_money_type'] = $lala['cost_money_type'];
  288. $userInfo = User::getUserInfo($order['uid']);
  289. $spread = User::getUserInfo($userInfo['spread_uid']);
  290. $send = 0;
  291. $last_send = 0;
  292. $last_level = 0;
  293. $same = 0;
  294. $res = true;
  295. while ($spread) {
  296. if (!self::where('paid', 1)->whereTime('add_time', 'today')->where('uid', $spread['uid'])->find()) {
  297. $spread = User::getUserInfo($spread['spread_uid']);
  298. continue;
  299. }
  300. $level = UserLevel::getUserLevelInfo(UserLevel::getUserLevel($spread['uid']));
  301. if ($level['group_award_ratio'] <= 0) {
  302. $spread = User::getUserInfo($spread['spread_uid']);
  303. continue;
  304. }
  305. $brokerageRatio = bcdiv($level['group_award_ratio'], 100, 4);
  306. $brokeragePrice = bcmul($order['cost'], $brokerageRatio, 8);
  307. if ($brokeragePrice < $send) {
  308. $spread = User::getUserInfo($spread['spread_uid']);
  309. continue;
  310. }
  311. if ($brokeragePrice == $send) {
  312. if ($level['level_id'] == $last_level && $same == 0) {
  313. $brokeragePrice = bcmul($last_send, bcdiv($level['same_level_award_ratio'], 100, 4), 8);
  314. if ($brokeragePrice <= 0) {
  315. $spread = User::getUserInfo($spread['spread_uid']);
  316. continue;
  317. }
  318. $mark = '用户' . $userInfo['nickname'] . '(' . $order['uid'] . ')' . '参与拼购,获得团队平级奖励' . $brokeragePrice;
  319. $res = $res && UserMoney::incomeMoney($spread['uid'], $order['cost_money_type'], $brokeragePrice, 'lala_same_level_award', '平级奖励', $mark, $order['id'], 0);
  320. $same++;
  321. }
  322. $spread = User::getUserInfo($spread['spread_uid']);
  323. continue;
  324. }
  325. $realBrokeragePrice = bcsub($brokeragePrice, $send, 8);
  326. $mark = '用户' . $userInfo['nickname'] . '(' . $order['uid'] . ')' . '参与拼购,获得团队极差奖励' . $realBrokeragePrice;
  327. $res = $res && UserMoney::incomeMoney($spread['uid'], $order['cost_money_type'], $realBrokeragePrice, 'lala_group_award', '团队奖励', $mark, $order['id'], 0);
  328. $same = 0;
  329. $send = $brokeragePrice;
  330. $last_level = $level['level_id'];
  331. $last_send = $realBrokeragePrice;
  332. $spread = User::getUserInfo($spread['spread_uid']);
  333. }
  334. return $res;
  335. }
  336. /**
  337. * @param $order
  338. * @return bool
  339. * @throws DataNotFoundException
  340. * @throws DbException
  341. * @throws ModelNotFoundException
  342. */
  343. public static function sendPointAward($order): bool
  344. {
  345. return true;
  346. $userInfo = User::getUserInfo($order['uid']);
  347. // $spread = User::getUserInfo($userInfo['spread_uid']);
  348. $res = true;
  349. $points = UserPointPlan::sum('buy_num');
  350. if ($points <= 0) return true;
  351. $plan = PointPlan::get(1);
  352. if (!$plan) return true;
  353. $list = UserPointPlan::group('uid')->field('SUM(buy_num) as buys,uid')->select();
  354. // = UserPointPlan::select();
  355. $brokerageRatio = bcdiv($plan['ticket_ratio'], 100, 4);
  356. $brokeragePrice = bcmul($order['ticket'], $brokerageRatio, 8);
  357. $every_price = bcdiv($brokeragePrice, $points, 8);
  358. foreach ($list as $v) {
  359. $brokeragePrice = bcmul($v['buys'], $every_price, 8);
  360. if ($brokeragePrice > 0) {
  361. $mark = '用户' . $userInfo['nickname'] . '(' . $order['uid'] . ')' . '参与拼购,获得节点门票分红' . $brokeragePrice . $order['ticket_money_type'];
  362. $res = $res && UserMoney::incomeMoney($v['uid'], $order['ticket_money_type'], $brokeragePrice, 'lala_point_award', '节点分红', $mark, $order['id']);
  363. // break;
  364. }
  365. }
  366. return $res;
  367. }
  368. /**
  369. * @param $where
  370. * @param $page
  371. * @param $limit
  372. * @return array
  373. * @throws DataNotFoundException
  374. * @throws DbException
  375. * @throws ModelNotFoundException
  376. */
  377. public static function getList($where, $page, $limit): array
  378. {
  379. $model = self::with(['user', 'activity'])->where('paid', 1)->order('add_time desc,id desc');
  380. if (isset($where['id']) && $where['id'] != '') {
  381. $model = $model->where('lala_id', $where['id']);
  382. }
  383. if (isset($where['uid']) && $where['uid'] != '') {
  384. $model = $model->where('uid', $where['uid']);
  385. }
  386. $list = $model->page((int)$page, (int)$limit)->select()->each(function ($item) {
  387. $item['cost_money_type'] = get_money_name($item['cost_money_type']);
  388. if ($item['status'] > 0) {
  389. $item['bingos'] = self::where('table_id', $item['table_id'])->where('group_id', $item['group_id'])->where('status', 1)->count();
  390. $item['fails'] = self::where('table_id', $item['table_id'])->where('group_id', $item['group_id'])->where('status', 'in', [2, 3])->count();
  391. $item['joins'] = self::with('user')->where('table_id', $item['table_id'])->where('group_id', $item['group_id'])->select();
  392. }
  393. });
  394. $count = $model->count();
  395. $yesterday = [];
  396. $month = [];
  397. $history = [];
  398. if (isset($where['uid']) && $where['uid'] != '') {
  399. $yesterday = [
  400. 'join' => self::where('uid', $where['uid'])->whereTime('add_time', 'yesterday')->where('paid', 1)->count(),
  401. 'bingo' => self::where('uid', $where['uid'])->whereTime('add_time', 'yesterday')->where('paid', 1)->where('status', 1)->count(),
  402. ];
  403. $month = [
  404. 'join' => self::where('uid', $where['uid'])->whereTime('add_time', 'month')->where('paid', 1)->count(),
  405. 'bingo' => self::where('uid', $where['uid'])->whereTime('add_time', 'month')->where('paid', 1)->where('status', 1)->count(),
  406. ];
  407. $history = [
  408. 'join' => self::where('uid', $where['uid'])->where('paid', 1)->count(),
  409. 'bingo' => self::where('uid', $where['uid'])->where('paid', 1)->where('status', 1)->count(),
  410. ];
  411. }
  412. return compact('list', 'count', 'yesterday', 'month', 'history');
  413. }
  414. /**
  415. * @param $where
  416. * @return array
  417. * @throws DataNotFoundException
  418. * @throws DbException
  419. * @throws ModelNotFoundException
  420. */
  421. public static function getDetail($where): array
  422. {
  423. $model = self::with(['user', 'activity']);
  424. $model = $model->where('id', $where['id']);
  425. if (isset($where['uid']) && $where['uid'] != '') {
  426. $model = $model->where('uid', $where['uid']);
  427. }
  428. $item = $model->find()->toArray();
  429. if ($item['status'] > 0) {
  430. $item['bingos'] = self::where('table_id', $item['table_id'])->where('group_id', $item['group_id'])->where('status', 1)->count();
  431. $item['fails'] = self::where('table_id', $item['table_id'])->where('group_id', $item['group_id'])->where('status', 'in', [2, 3])->count();
  432. $item['joins'] = self::with('user')->where('table_id', $item['table_id'])->where('group_id', $item['group_id'])->select();
  433. }
  434. $item['cost_money_type'] = get_money_name($item['cost_money_type']);
  435. return $item;
  436. }
  437. /**
  438. * @param $where
  439. * @param $page
  440. * @param $limit
  441. * @return array
  442. * @throws DataNotFoundException
  443. * @throws DbException
  444. * @throws ModelNotFoundException
  445. */
  446. public static function getListAdmin($where, $page, $limit): array
  447. {
  448. $model = self::with(['user', 'activity'])->where('paid', 1)->order('status asc,pay_time desc,id desc');
  449. if (isset($where['id']) && $where['id'] != '') {
  450. $model = $model->where('lala_id', $where['id']);
  451. }
  452. if (isset($where['uid']) && $where['uid'] != '') {
  453. $model = $model->where('uid', $where['uid']);
  454. }
  455. $count = $model->count();
  456. $data = $model->page((int)$page, (int)$limit)->select()->each(function ($item) {
  457. if ($item['status'] == 0) {
  458. $item['bingo_count'] = LalaPinkJoin::where('uid', $item['uid'])->where('lala_id', $item['lala_id'])->where('status', 1)->where('paid', 1)->count();
  459. // var_dump($item['activity']);
  460. if (($item['bingo_count'] + 1) % ($item['activity']['sp_exchange_bingo_time'] > 0 ? $item['activity']['sp_exchange_bingo_time'] : 1) == 0) {
  461. $item['bingo_count'] = "<font style='color: red'>" . $item['bingo_count'] . "</font>";
  462. }
  463. } else
  464. $item['bingo_count'] = '--';
  465. $item['_status'] = $item['status'] == 1 ? "拼中" : ($item['status'] == 2 ? "未拼中" : ($item['status'] == 3 ? "未成团" : "等待开团"));
  466. $item['_set_status'] = $item['set_status'] == 1 ? "必拼中" : ($item['set_status'] == 2 ? "必不中" : "未设置");
  467. $item['_open_time'] = time_format($item['open_time']);
  468. });
  469. return compact('data', 'count');
  470. }
  471. /**
  472. * @param $uid
  473. * @return string
  474. */
  475. public static function getNewOrderId($uid): string
  476. {
  477. do {
  478. $str = 'LA' . str_pad($uid, 8, 0, STR_PAD_LEFT) . time() . rand(1000, 9999);
  479. } while (self::be(['order_id' => $str]));
  480. return $str;
  481. }
  482. /**
  483. * @return bool
  484. * @throws DataNotFoundException
  485. * @throws DbException
  486. * @throws ModelNotFoundException
  487. */
  488. public static function openAward(): bool
  489. {
  490. $open_times = open_times();
  491. //上次开奖
  492. $last_log = LalaPinkLog::order('add_time', 'desc')->find();
  493. $this_time = [];
  494. $this_group = 0;
  495. if (!$last_log)
  496. foreach ($open_times as $k => $v) {
  497. if ($v['value'] < time()) {
  498. $this_time = $v;
  499. $this_group = $k + 1;
  500. }
  501. }
  502. else {
  503. foreach ($open_times as $k => $v) {
  504. if ($v['value'] > $last_log['add_time'] && $v['value'] < time()) {
  505. $this_time = $v;
  506. $this_group = $k + 1;
  507. break;
  508. }
  509. }
  510. }
  511. if (!$this_time) {
  512. return true;
  513. }
  514. $auto_success = sys_config('auto_success');
  515. // $auto_success = 1;
  516. $dec = 1;
  517. LalaPinkLog::create(['add_time' => time(), 'time' => $this_time['name']]);
  518. $activity = LalaPink::validWhere()->column('id');
  519. $sites = (new \app\models\system\Site)->where('status', 1)->column('id');
  520. foreach ($activity as $v) {
  521. foreach ($sites as $vv) {
  522. $res1 = true;
  523. $res2 = true;
  524. $res3 = true;
  525. BaseModel::beginTrans();
  526. try {
  527. $activity_info = LalaPink::get($v);
  528. $round = 1;
  529. $group_id = self::getNewGroupId($vv, $v);
  530. $list_success = self::order('pay_time asc,id asc')->where('status', 0)->where('paid', 1)->where('lala_id', $v)->where('site_id', $vv)->where('set_status', 1)->column('id', 'id');
  531. $list_fail = self::order('pay_time asc,id asc')->where('status', 0)->where('paid', 1)->where('lala_id', $v)->where('site_id', $vv)->where('set_status', 2)->column('id', 'id');
  532. $list = self::order('pay_time asc,id asc')->where('status', 0)->where('paid', 1)->where('lala_id', $v)->where('site_id', $vv)->where('set_status', 0)->column('id', 'id');
  533. // var_dump($list);
  534. // var_dump($list_fail);
  535. // var_dump($list_success);
  536. // exit();
  537. while ($list_success || $list_fail || $list) {
  538. //必中用户
  539. $bingo = [];
  540. foreach ($list_success as $k => $vvv) {
  541. if (count($bingo) >= $activity_info['bingo_number']) break;
  542. $bingo[] = $vvv;
  543. unset($list_success[$k]);
  544. }
  545. // var_dump($bingo);
  546. if (count($list) < $activity_info['bingo_number'] - count($bingo)) {
  547. //中奖人数不足,不做操作等待下一轮
  548. if (!$auto_success)
  549. break;
  550. else {
  551. $count = $activity_info['bingo_number'] - count($bingo) - count($list);
  552. for ($i = 0; $i < $count; $i++) {
  553. $list[-($dec + $i)] = -($dec + $i);
  554. }
  555. $dec += $i;
  556. }
  557. }
  558. // var_dump($list);
  559. // var_dump(count($list_fail) + count($list));
  560. // var_dump($activity_info['join_number'] - count($bingo));
  561. // var_dump($dec);
  562. if (count($list_fail) + count($list) < $activity_info['join_number'] - count($bingo)) {
  563. //人数不足,不做操作等待下一轮
  564. if (!$auto_success)
  565. break;
  566. else {
  567. $count = $activity_info['join_number'] - count($bingo) - count($list_fail) - count($list);
  568. for ($i = 0; $i < $count; $i++) {
  569. $list[-($dec + $i)] = -($dec + $i);
  570. }
  571. $dec += $i;
  572. }
  573. }
  574. if (count($bingo) < $activity_info['bingo_number']) {
  575. $count = $activity_info['bingo_number'] - count($bingo);
  576. $random = array_rand($list, $count);
  577. if (is_array($random))
  578. foreach ($random as $vvv) {
  579. $bingo[] = $list[$vvv];
  580. unset($list[$vvv]);
  581. }
  582. else {
  583. $bingo[] = $list[$random];
  584. unset($list[$random]);
  585. }
  586. }
  587. // var_dump($bingo);
  588. // var_dump($list);
  589. // var_dump($list_fail);
  590. // var_dump($list_success);
  591. //开奖
  592. $fail = [];
  593. foreach ($list_fail as $k => $vvv) {
  594. if (count($fail) >= $activity_info['join_number'] - count($bingo)) break;
  595. $fail[] = $vvv;
  596. unset($list_fail[$k]);
  597. }
  598. if (count($list) < $activity_info['join_number'] - count($bingo) - count($fail)) {
  599. //不中人数不足,不做操作等待下一轮
  600. break;
  601. }
  602. if (count($fail) < $activity_info['join_number'] - count($bingo)) {
  603. $count = $activity_info['join_number'] - count($bingo) - count($fail);
  604. $random = array_rand($list, $count);
  605. if (is_array($random))
  606. foreach ($random as $vvv) {
  607. $fail[] = $list[$vvv];
  608. unset($list[$vvv]);
  609. }
  610. else {
  611. $fail[] = $list[$random];
  612. unset($list[$random]);
  613. }
  614. }
  615. //发奖逻辑
  616. foreach ($bingo as $vvv) {
  617. $info = self::get($vvv);
  618. if (!$info) {
  619. $res1 = $res1 && self::create([
  620. 'uid' => 0,
  621. 'lala_id' => $v,
  622. 'cost' => $activity_info['cost'],
  623. 'cost_money_type' => $activity_info['cost_money_type'],
  624. 'ticket' => $activity_info['ticket'],
  625. 'ticket_money_type' => $activity_info['ticket_money_type'],
  626. 'bingo' => $activity_info['bingo'],
  627. 'bingo_money_type' => $activity_info['bingo_money_type'],
  628. 'join_award' => bcmul(bcdiv($activity_info['join_award_ratio'], 100, 8), $activity_info['cost'], 8),
  629. 'system_money' => bcmul(bcdiv($activity_info['system_money_ratio'], 100, 8), $activity_info['cost'], 8),
  630. 'add_time' => time(),
  631. 'pay_time' => time(),
  632. 'paid' => 1,
  633. 'site_id' => $vv,
  634. 'order_id' => self::getNewOrderId(0),
  635. 'group_num' => $this_group,
  636. 'status' => 1,
  637. 'open_time' => time(),
  638. 'group_id' => $group_id,
  639. 'table_id' => $round
  640. ]);
  641. } else {
  642. //设置状态
  643. $res1 = $res1 && self::where('id', $vvv)->update(['status' => 1, 'open_time' => time(), 'group_id' => $group_id, 'table_id' => $round]);
  644. //发奖
  645. $res1 = $res1 && UserMoney::incomeMoney($info['uid'], $info['bingo_money_type'], $info['bingo'], 'lala_bingo', '拼购中奖', '参与' . $activity_info['name'] . '第' . $group_id . '期第' . $round . '桌拼购中奖', $vvv, 0);
  646. $res1 = $res1 && self::addSystemAward($info);
  647. $res1 = $res1 && Message::addMessage($vvv, '您参与的' . $activity_info['name'] . '第' . $group_id . '期第' . $round . '桌拼购已拼中', 202);
  648. //$res1 = $res1 && self::sendJoinAward($info) && self::addSystemAward($info) && self::sendRecommendAward($info) && self::sendGroupAward($info);
  649. $uper = User::getUserInfo($info['uid']);
  650. while ($uper) {
  651. UserLevel::setLevelComplete($uper['uid']);
  652. $uper = User::getUserInfo($uper['spread_uid']);
  653. }
  654. }
  655. }
  656. foreach ($fail as $vvv) {
  657. $info = self::get($vvv);
  658. //设置状态
  659. if (!$info) {
  660. $res1 = $res1 && self::create([
  661. 'uid' => 0,
  662. 'lala_id' => $v,
  663. 'cost' => $activity_info['cost'],
  664. 'cost_money_type' => $activity_info['cost_money_type'],
  665. 'ticket' => $activity_info['ticket'],
  666. 'ticket_money_type' => $activity_info['ticket_money_type'],
  667. 'bingo' => $activity_info['bingo'],
  668. 'bingo_money_type' => $activity_info['bingo_money_type'],
  669. 'join_award' => bcmul(bcdiv($activity_info['join_award_ratio'], 100, 8), $activity_info['cost'], 8),
  670. 'system_money' => bcmul(bcdiv($activity_info['system_money_ratio'], 100, 8), $activity_info['cost'], 8),
  671. 'add_time' => time(),
  672. 'pay_time' => time(),
  673. 'paid' => 1,
  674. 'site_id' => $vv,
  675. 'order_id' => self::getNewOrderId(0),
  676. 'group_num' => $this_group,
  677. 'status' => 2,
  678. 'open_time' => time(),
  679. 'group_id' => $group_id,
  680. 'table_id' => $round
  681. ]);
  682. } else {
  683. $res2 = $res2 && self::where('id', $vvv)->update(['status' => 2, 'open_time' => time(), 'group_id' => $group_id, 'table_id' => $round]);
  684. //发奖
  685. $res2 = $res2 && UserMoney::incomeMoney($info['uid'], $info['cost_money_type'], $info['cost'], 'lala_bingo_fail', '拼购未中奖退回', '参与' . $activity_info['name'] . '第' . $group_id . '期第' . $round . '桌拼购未中奖', $vvv);
  686. $res2 = $res2 && self::sendJoinAward($info) && self::addSystemAward($info) && self::sendRecommendAward($info) && self::sendGroupAward($info);
  687. $res2 = $res2 && Message::addMessage($vvv, '您参与的' . $activity_info['name'] . '第' . $group_id . '期第' . $round . '桌拼购未拼中', 202);
  688. $uper = User::getUserInfo($info['uid']);
  689. while ($uper) {
  690. UserLevel::setLevelComplete($uper['uid']);
  691. $uper = User::getUserInfo($uper['spread_uid']);
  692. }
  693. }
  694. }
  695. $round++;
  696. }
  697. //剩余list用户设置为超时失败
  698. foreach ($list as $vvv) {
  699. $info = self::get($vvv);
  700. $res3 = $res3 && self::where('id', $vvv)->update(['status' => 3, 'open_time' => time(), 'group_id' => $group_id, 'table_id' => $round]);
  701. //发奖
  702. $res3 = $res3 && UserMoney::incomeMoney($info['uid'], $info['cost_money_type'], $info['cost'], 'lala_fail', '拼购人数不足退回', '参与' . $activity_info['name'] . '第' . $group_id . '期第' . $round . '桌拼购人数不足', $vvv, 0);
  703. $res3 = $res3 && Message::addMessage($vvv, '您参与的' . $activity_info['name'] . '第' . $group_id . '期第' . $round . '桌拼购人数不足未成团', 202);
  704. }
  705. //剩余list_fail用户设置为超时失败
  706. foreach ($list_fail as $vvv) {
  707. $info = self::get($vvv);
  708. $res3 = $res3 && self::where('id', $vvv)->update(['status' => 3, 'open_time' => time(), 'group_id' => $group_id, 'table_id' => $round]);
  709. //发奖
  710. $res3 = $res3 && UserMoney::incomeMoney($info['uid'], $info['cost_money_type'], $info['cost'], 'lala_fail', '拼购人数不足退回', '参与' . $activity_info['name'] . '第' . $group_id . '期第' . $round . '桌拼购人数不足', $vvv, 0);
  711. $res3 = $res3 && Message::addMessage($vvv, '您参与的' . $activity_info['name'] . '第' . $group_id . '期第' . $round . '桌拼购人数不足未成团', 202);
  712. }
  713. // BaseModel::rollbackTrans();
  714. BaseModel::checkTrans($res1 && $res2 && $res3);
  715. if (!($res1 && $res2 && $res3)) {
  716. return BaseModel::setErrorInfo($activity_info['name'] . '开奖失败');
  717. }
  718. } catch (Exception $e) {
  719. // dump($e->getTrace());
  720. Log::error($e->getMessage());
  721. return BaseModel::setErrorInfo($e->getMessage(), true);
  722. }
  723. }
  724. }
  725. return true;
  726. }
  727. /**
  728. * @param $site_id
  729. * @param $lala_id
  730. * @return string
  731. */
  732. public static function getNewGroupId($site_id, $lala_id): string
  733. {
  734. do {
  735. $str = date('Ymd') . str_pad($site_id, 3, 0, STR_PAD_LEFT) . str_pad($lala_id, 3, 0, STR_PAD_LEFT) . rand(1000, 9999);
  736. } while (self::be(['group_id' => $str]));
  737. return $str;
  738. }
  739. /**
  740. * @return bool
  741. * @throws DataNotFoundException
  742. * @throws DbException
  743. * @throws ModelNotFoundException
  744. */
  745. public static function sendMoney(): bool
  746. {
  747. $list = UserBill::where(['pm' => 1, 'status' => 0])
  748. ->whereTime('add_time', 'yesterday')
  749. ->where('type', 'in', ['lala_bingo', 'lala_bingo_fail', 'lala_fail', 'join_award', 'lala_recommend_award', 'lala_group_award', 'lala_same_level_award'])
  750. ->select();
  751. if ($list) {
  752. self::beginTrans();
  753. try {
  754. foreach ($list as $v) {
  755. UserMoney::sendMoney($v['id']);
  756. }
  757. self::commitTrans();
  758. return true;
  759. } catch (Exception $e) {
  760. self::rollbackTrans();
  761. return false;
  762. }
  763. }
  764. return true;
  765. }
  766. public static function autoPink()
  767. {
  768. $open_times = open_times();
  769. //上次开奖
  770. $last_log = LalaPinkLog::order('add_time', 'desc')->find();
  771. //本次开奖
  772. $this_time = [];
  773. if (!$last_log)
  774. foreach ($open_times as $v) {
  775. if ($v['value'] < time()) {
  776. $this_time = $v;
  777. }
  778. }
  779. else {
  780. foreach ($open_times as $v) {
  781. if ($v['value'] > $last_log['add_time'] && $v['value'] < time()) {
  782. $this_time = $v;
  783. break;
  784. }
  785. }
  786. }
  787. if ($this_time) {
  788. return true;
  789. }
  790. //下次开奖
  791. $next_time = [];
  792. $next_group = 0;
  793. foreach ($open_times as $k => $v) {
  794. if ($v['value'] > time() && $v['value'] > $last_log['add_time']) {
  795. $next_time = $v;
  796. $next_group = $k + 1;
  797. break;
  798. }
  799. }
  800. if (time() + sys_config('lala_pink_close_join_before_open', 15, true) * 60 > $next_time['value']) {
  801. return true;
  802. }
  803. $open = sys_config('lala_pink_open');
  804. $close = sys_config('lala_pink_close');
  805. if (time() < strtotime(date('Y-m-d') . $open) || time() >= strtotime(date('Y-m-d') . $close)) {
  806. return true;
  807. }
  808. $lala = LalaPink::validWhere()->order('cost', 'desc')->select();
  809. foreach ($lala as $v) {
  810. $cost = $v['cost'];
  811. $cost_money_type = $v['cost_money_type'];
  812. $uids = UserAutoPink::where("FIND_IN_SET('" . $v['id'] . "',lala_id)")->group('uid')->field('COUNT(uid) as cot,uid')->where('status', 1)->select();
  813. foreach ($uids as $vv) {
  814. $v['cost'] = $v['cost_2'];
  815. $v['cost_money_type'] = $v['cost_2_money_type'];
  816. $old = UserAutoPink::where('uid', $vv['uid'])->where("FIND_IN_SET('" . $v['id'] . "',lala_id)")->where('status', 1)->select();
  817. if (!$old) continue;
  818. $valid_time = 0;
  819. $is_forever = 0;
  820. foreach ($old as $vvv) {
  821. if ($vvv['valid_time'] > $valid_time) $valid_time = $vvv['valid_time'];
  822. if ($vvv['is_forever']) $is_forever = $vvv['is_forever'];
  823. }
  824. if (!$is_forever && $valid_time < time()) continue;
  825. $user = User::get($vv['uid']);
  826. if (!$user || $user['status'] == 0) continue;
  827. if (UserLevel::getUserLevelInfo(UserLevel::getUserLevel($vv['uid']), 'grade') < 4 && $next_group <= 1) continue;
  828. if (self::where('paid', 1)->where('status', 0)->where('lala_id', $v['id'])->where('uid', $vv['uid'])->find()) continue;
  829. if (self::where('paid', 1)->where('uid', $vv['uid'])->where('lala_id', $v['id'])->whereTime('pay_time', 'today')->count() >= $v['join_limit']) continue;
  830. if ($v['ticket_money_type'] != 'LALA') {
  831. $money_types = sys_data('money_type');
  832. $origin_ratio = 0;
  833. $target_ratio = get_lala_ratio();
  834. foreach ($money_types as $vvv) {
  835. if ($vvv['code'] == $v['ticket_money_type']) {
  836. $origin_ratio = $vvv['usdt_price'];
  837. if ($origin_ratio == 0) {
  838. $origin_ratio = get_huobi_price($vvv['code']);
  839. }
  840. }
  841. }
  842. $ratio = bcdiv($origin_ratio, $target_ratio, 14);
  843. $v['ticket'] = bcmul($v['ticket'], $ratio, 8);
  844. $v['ticket_money_type'] = 'LALA';
  845. }
  846. $user_cost_money = UserMoney::initialUserMoney($vv['uid'], $v['cost_money_type']);
  847. $user_ticket_money = UserMoney::initialUserMoney($vv['uid'], $v['ticket_money_type']);
  848. if ($user_cost_money['money'] < $v['cost']) {
  849. $v['cost'] = $cost;
  850. $v['cost_money_type'] = $cost_money_type;
  851. $user_cost_money = UserMoney::initialUserMoney($vv['uid'], $v['cost_money_type']);
  852. if ($user_cost_money['money'] < $v['cost']) {
  853. continue;
  854. }
  855. }
  856. // var_dump($user_cost_money);
  857. // var_dump($user_ticket_money);
  858. //var_dump(3);
  859. if ($user_ticket_money['money'] < $v['ticket']) continue;
  860. //var_dump(4);
  861. $bingo_count = LalaPinkJoin::where('uid', $vv['uid'])->where('lala_id', $v['id'])->where('status', 1)->where('paid', 1)->count();
  862. $fail_count = LalaPinkJoin::where('uid', $vv['uid'])->where('lala_id', $v['id'])->where('status', 'in', [2, 3])->where('paid', 1)->count();
  863. // var_dump($item['activity']);
  864. $flag = true;
  865. if (($bingo_count + 1) % 11 == 0) {
  866. $times = floor($bingo_count / 11) + 1;
  867. if ($fail_count + $bingo_count < $times * $v['bingo_limit']) {
  868. $flag = false;
  869. }
  870. }
  871. if (in_array($vv['uid'], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 18, 20, 21, 30])) {
  872. if (rand(1, 100) < 80) {
  873. $flag = false;
  874. }
  875. }
  876. BaseModel::beginTrans();
  877. try {
  878. //生成订单
  879. //var_dump(111);
  880. $res0 = self::create([
  881. 'uid' => $vv['uid'],
  882. 'lala_id' => $v['id'],
  883. 'cost' => $v['cost'],
  884. 'cost_money_type' => $v['cost_money_type'],
  885. 'ticket' => $v['ticket'],
  886. 'ticket_money_type' => $v['ticket_money_type'],
  887. 'bingo' => $v['bingo'],
  888. 'bingo_money_type' => $v['bingo_money_type'],
  889. 'join_award' => bcmul(bcdiv($v['join_award_ratio'], 100, 8), $v['cost'], 8),
  890. 'system_money' => bcmul(bcdiv($v['system_money_ratio'], 100, 8), $v['cost'], 8),
  891. 'add_time' => time(),
  892. 'site_id' => $user['site_id'],
  893. 'order_id' => self::getNewOrderId($vv['uid']),
  894. 'group_num' => $next_group,
  895. 'set_status' => $flag ? 0 : 2,
  896. ]);
  897. if (!$res0) {
  898. Log::error('生成订单失败1');
  899. BaseModel::rollbackTrans();
  900. continue;
  901. }
  902. //支付门票
  903. $res1 = UserMoney::expendMoney($vv['uid'], $v['ticket_money_type'], $v['ticket'], 'lala_ticket', '拼购门票', '参与拼购支付门票费用', $res0->id, false);
  904. if (!$res1) {
  905. Log::error('生成订单失败2');
  906. BaseModel::rollbackTrans();
  907. continue;
  908. }
  909. //支付
  910. $res2 = UserMoney::expendMoney($vv['uid'], $v['cost_money_type'], $v['cost'], 'lala_cost', '参与拼购', '参与拼购支付', $res0->id, false);
  911. if (!$res2) {
  912. Log::error('生成订单失败3');
  913. BaseModel::rollbackTrans();
  914. continue;
  915. }
  916. $res3 = self::where('id', $res0->id)->update(['paid' => 1, 'pay_time' => time()]);
  917. if (!$res3) {
  918. Log::error('生成订单失败4');
  919. BaseModel::rollbackTrans();
  920. continue;
  921. }
  922. $res4 = self::sendPointAward($res0);
  923. if (!$res4) {
  924. Log::error('生成订单失败5');
  925. BaseModel::rollbackTrans();
  926. continue;
  927. }
  928. //BaseModel::rollbackTrans();
  929. BaseModel::commitTrans();
  930. } catch (Exception $e) {
  931. Log::error($e->getMessage());
  932. BaseModel::rollbackTrans();
  933. continue;
  934. }
  935. }
  936. }
  937. return true;
  938. }
  939. }