User.php 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
  8. // +----------------------------------------------------------------------
  9. // | Author: 萤火科技 <admin@yiovo.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types=1);
  12. namespace app\store\model;
  13. use app\common\enum\order\PayStatus as PayStatusEnum;
  14. use app\common\model\User as UserModel;
  15. use app\common\model\user\CommissionsDetail;
  16. use app\store\model\UserOauth as UserOauthModel;
  17. use app\store\model\user\GradeLog as GradeLogModel;
  18. use app\store\model\user\PointsLog as PointsLogModel;
  19. use app\store\model\user\BalanceLog as BalanceLogModel;
  20. use app\store\service\store\User as StoreUserService;
  21. use app\common\enum\user\balanceLog\Scene as SceneEnum;
  22. use app\common\enum\user\grade\log\ChangeType as ChangeTypeEnum;
  23. use app\common\library\helper;
  24. use app\common\model\Shops;
  25. use app\api\model\User as UserApiModel;
  26. use app\store\model\user\BonusHistory;
  27. use think\model\relation\HasMany;
  28. /**
  29. * 用户模型
  30. * Class User
  31. * @package app\store\model
  32. */
  33. class User extends UserModel
  34. {
  35. // 充值类型枚举: 余额
  36. const RECHARGE_TYPE_BALANCE = 'balance';
  37. // 充值类型枚举: 积分
  38. const RECHARGE_TYPE_POINTS = 'points';
  39. // 追加字段
  40. protected $append = ['role_text'];
  41. /**
  42. * 获取当前用户总数
  43. * @param array $param 查询参数
  44. * @return int|string
  45. */
  46. public function getUserTotal(array $param = [])
  47. {
  48. // 检索查询条件
  49. $filter = $this->getUserTotalFilter($param);
  50. // 查询结果
  51. return $this->where($filter)
  52. ->where('is_delete', '=', '0')
  53. ->count();
  54. }
  55. /**
  56. * 获取当前用户总数的查询条件
  57. * @param array $param
  58. * @return array
  59. */
  60. private function getUserTotalFilter(array $param = [])
  61. {
  62. // 默认查询参数
  63. $params = $this->setQueryDefaultValue($param, [
  64. 'date' => null, // 注册日期 如: 2020-08-01
  65. 'isConsume' => null, // 是否已消费
  66. ]);
  67. // 检索查询条件
  68. $filter = [];
  69. if (!is_null($params['date'])) {
  70. $startTime = strtotime($params['date']);
  71. $filter[] = ['create_time', '>=', $startTime];
  72. $filter[] = ['create_time', '<', $startTime + 86400];
  73. }
  74. if (is_bool($params['isConsume'])) {
  75. $filter[] = ['pay_money', $params['isConsume'] ? '>' : '=', 0];
  76. }
  77. return $filter;
  78. }
  79. /**
  80. * 获取用户列表
  81. * @param array $param
  82. * @return \think\Paginator
  83. * @throws \think\db\exception\DbException
  84. */
  85. public function getList(array $param = [])
  86. {
  87. // 检索查询条件
  88. $filter = $this->getFilter($param);
  89. $shop_users = [];
  90. // 获取用户列表
  91. $query = $this->with(['avatar', 'grade', 'shops', 'bindShops', 'upperUser'])
  92. ->alias('users')
  93. ->field('users.*')
  94. // ->leftJoin('shops', 'shops.shop_id = users.shop_id')
  95. ->leftJoin('user', 'user.user_id = users.upper_user_id')
  96. ->where($filter)
  97. ->where('users.is_delete', '=', '0');
  98. if (!empty($param['shop_name'])) {
  99. $shop_users = Shops::where('shop_name', 'like', "%{$param['shop_name']}%")->column('shop_id');
  100. if (!empty($shop_users)) {
  101. $query->where(function($query) use($shop_users) {
  102. $query->whereOr('users.shop_id', 'in', $shop_users)->whereOr('users.bind_shop_id', 'in', $shop_users);
  103. });
  104. }
  105. }
  106. return $query->order(['users.create_time' => 'desc'])
  107. ->paginate(15)
  108. ->each(function ($item) {
  109. $item->order_paid_count = Order::where('user_id',$item->user_id)
  110. ->where('pay_status',PayStatusEnum::SUCCESS)->count(); // 消费订单数
  111. $item->order_paid_amount = Order::where('user_id',$item->user_id)
  112. ->where('pay_status',PayStatusEnum::SUCCESS)->sum('pay_price'); // 消费金额
  113. $item->promote_user_count = UserApiModel::countSubordinates($item->user_id, $item->shop_id, $item->role); // 直推人数
  114. /* $item->promoter_order_count = OrderGoods::alias('order_goods')
  115. ->leftJoin('order','order_goods.order_id=order.order_id')
  116. ->where('order_goods.staff_user_id',$item->user_id)
  117. ->where('order.pay_status',PayStatusEnum::SUCCESS)->count(); // 推广订单*/
  118. $item->promoter_order_count = Order::alias('order')
  119. ->where('order.staff_user_id',$item->user_id)
  120. ->where('order.pay_status',PayStatusEnum::SUCCESS)
  121. ->count(); // 推广订单
  122. //todo 销售额 = 实付+米卡抵扣
  123. /* $item->promote_sale_sum = (OrderGoods::alias('order_goods')
  124. ->leftJoin('order','order_goods.order_id=order.order_id')
  125. ->where('order_goods.staff_user_id',$item->user_id)->where('order.pay_status',PayStatusEnum::SUCCESS)
  126. ->field('sum(order_goods.total_pay_price+order_goods.rice_card_money) as tm')->find())->tm??0;*/
  127. $tempSaleSum = Order::alias('order')
  128. ->where('order.staff_user_id',$item->user_id)
  129. ->where('order.pay_status',PayStatusEnum::SUCCESS)
  130. ->field('sum(order.pay_price+order.rice_card_money) as tm')
  131. ->find();
  132. $item->promote_sale_sum = $tempSaleSum->tm??0;
  133. $item->fc_yj_amount = $item->can_withdraw_money; // 总佣金
  134. $item->shop_name = $item->shops->shop_name ?? ($item->bindShops->shop_name ?? '');
  135. $promoter_mobile = '';
  136. if (in_array($item->role, [2,3])) {
  137. $promoter_name = '总店';
  138. } elseif ($item->role == 4) { // 店员
  139. $promoter_name = $item->shops->shop_name ?? '';
  140. $promoter_mobile = $item->shops->contact_mobile??'';
  141. } else {
  142. $promoter_name = $item->upperUser->nick_name ?? '';
  143. $promoter_mobile = $item->upperUser->mobile??'';
  144. }
  145. $item->promoter_name = $promoter_name;
  146. $item->promoter_mobile = $promoter_mobile;
  147. unset($item['shops'],$item['bindShops'],$item['upperUser']);
  148. });
  149. }
  150. /**
  151. * 获取查询条件
  152. * @param array $param
  153. * @return array
  154. */
  155. private function getFilter(array $param = [])
  156. {
  157. // 默认查询条件
  158. $params = $this->setQueryDefaultValue($param, [
  159. 'search' => '', // 微信昵称
  160. 'mobile' => '', // 手机号
  161. 'gender' => -1, // 用户性别
  162. 'grade' => 0, // 用户等级
  163. 'shop_name' => '', // 门店名称
  164. 'upper_user' => '',// 推荐人手机号
  165. ]);
  166. // 检索查询条件
  167. $filter = [];
  168. // 微信昵称
  169. !empty($params['search']) && $filter[] = ['users.nick_name', 'like', "%{$params['search']}%"];
  170. // 手机号
  171. !empty($params['mobile']) && $filter[] = ['users.mobile', 'like', "%{$params['mobile']}%"];
  172. // 门店名称
  173. // !empty($params['shop_name']) && $filter[] = ['shops.shop_name', 'like', "%{$params['shop_name']}%"];
  174. // 推荐人手机号
  175. !empty($params['upper_user']) && $filter[] = ['user.mobile', 'like', "%{$params['upper_user']}%"];
  176. // 用户性别
  177. $params['gender'] > -1 && $filter[] = ['users.gender', '=', (int)$params['gender']];
  178. // 用户等级
  179. $params['grade'] > 0 && $filter[] = ['users.grade_id', '=', (int)$params['grade']];
  180. // 起止时间
  181. if (!empty($params['betweenTime'])) {
  182. $times = between_time($params['betweenTime']);
  183. $filter[] = ['users.create_time', '>=', $times['start_time']];
  184. $filter[] = ['users.create_time', '<', $times['end_time'] + 86400];
  185. }
  186. return $filter;
  187. }
  188. /**
  189. * 获取用户信息
  190. * @param $where
  191. * @param array $with
  192. * @return array|null|static
  193. */
  194. public static function detail($where, $with = [])
  195. {
  196. $filter = ['is_delete' => 0];
  197. if (is_array($where)) {
  198. $filter = array_merge($filter, $where);
  199. } else {
  200. $filter['user_id'] = (int)$where;
  201. }
  202. return static::get($filter, $with);
  203. }
  204. /**
  205. * 删除用户
  206. * @return bool|mixed
  207. */
  208. public function setDelete()
  209. {
  210. return $this->transaction(function () {
  211. // 将第三方用户信息记录标记删除
  212. UserOauthModel::updateBase(['is_delete' => 1], [
  213. ['user_id', '=', $this['user_id']]
  214. ]);
  215. // 标记为已删除
  216. return $this->save(['is_delete' => 1]);
  217. });
  218. }
  219. /**
  220. * 用户充值
  221. * @param string $target 充值类型
  222. * @param array $data 表单数据
  223. * @return bool
  224. */
  225. public function recharge(string $target, array $data)
  226. {
  227. // 当前操作人用户名
  228. $storeUserName = StoreUserService::getLoginInfo()['user']['user_name'];
  229. if ($target === self::RECHARGE_TYPE_BALANCE) {
  230. return $this->rechargeToBalance($storeUserName, $data['balance']);
  231. } elseif ($target === self::RECHARGE_TYPE_POINTS) {
  232. return $this->rechargeToPoints($storeUserName, $data['points']);
  233. }
  234. return false;
  235. }
  236. /**
  237. * 用户充值:余额
  238. * @param string $storeUserName
  239. * @param array $data
  240. * @return bool
  241. */
  242. private function rechargeToBalance(string $storeUserName, array $data)
  243. {
  244. if (!isset($data['money']) || $data['money'] === '' || $data['money'] < 0) {
  245. $this->error = '请输入正确的金额';
  246. return false;
  247. }
  248. // 判断充值方式,计算最终金额
  249. if ($data['mode'] === 'inc') {
  250. $diffMoney = $data['money'];
  251. } elseif ($data['mode'] === 'dec') {
  252. $diffMoney = -$data['money'];
  253. } else {
  254. $diffMoney = helper::bcsub($data['money'], $this['balance']);
  255. }
  256. // 更新记录
  257. $this->transaction(function () use ($storeUserName, $data, $diffMoney) {
  258. // 更新账户余额
  259. static::setIncBalance((int)$this['user_id'], (float)$diffMoney);
  260. // 新增余额变动记录
  261. BalanceLogModel::add(SceneEnum::ADMIN, [
  262. 'user_id' => $this['user_id'],
  263. 'money' => (float)$diffMoney,
  264. 'remark' => $data['remark'],
  265. ], [$storeUserName]);
  266. });
  267. return true;
  268. }
  269. /**
  270. * 用户充值:积分
  271. * @param string $storeUserName
  272. * @param array $data
  273. * @return bool
  274. */
  275. private function rechargeToPoints(string $storeUserName, array $data)
  276. {
  277. if (!isset($data['value']) || $data['value'] === '' || $data['value'] < 0) {
  278. $this->error = '请输入正确的积分数量';
  279. return false;
  280. }
  281. // 判断充值方式,计算最终积分
  282. if ($data['mode'] === 'inc') {
  283. $diffMoney = $data['value'];
  284. } elseif ($data['mode'] === 'dec') {
  285. $diffMoney = -$data['value'];
  286. } else {
  287. $diffMoney = $data['value'] - $this['points'];
  288. }
  289. // 更新记录
  290. $this->transaction(function () use ($storeUserName, $data, $diffMoney) {
  291. // 更新账户积分
  292. $this->setInc($this['user_id'], 'points', $diffMoney);
  293. // 新增积分变动记录
  294. PointsLogModel::add([
  295. 'user_id' => $this['user_id'],
  296. 'value' => $diffMoney,
  297. 'describe' => "后台管理员 [{$storeUserName}] 操作",
  298. 'remark' => $data['remark'],
  299. ]);
  300. });
  301. return true;
  302. }
  303. /**
  304. * 修改用户等级
  305. * @param array $data
  306. * @return mixed
  307. */
  308. public function updateGrade(array $data)
  309. {
  310. // 变更前的等级id
  311. $oldGradeId = $this['grade_id'];
  312. return $this->transaction(function () use ($oldGradeId, $data) {
  313. // 更新用户的等级
  314. $status = $this->save(['grade_id' => $data['grade_id']]);
  315. // 新增用户等级修改记录
  316. if ($status) {
  317. (new GradeLogModel)->record([
  318. 'user_id' => $this['user_id'],
  319. 'old_grade_id' => $oldGradeId,
  320. 'new_grade_id' => $data['grade_id'],
  321. 'change_type' => ChangeTypeEnum::ADMIN_USER,
  322. 'remark' => $data['remark']
  323. ]);
  324. }
  325. return $status !== false;
  326. });
  327. }
  328. /**
  329. * 消减用户的实际消费金额
  330. * @param int $userId
  331. * @param float $expendMoney
  332. * @return mixed
  333. */
  334. public function setDecUserExpend(int $userId, float $expendMoney)
  335. {
  336. return $this->setDec(['user_id' => $userId], 'expend_money', $expendMoney);
  337. }
  338. /**
  339. * 员工业绩统计
  340. * @param $shopId
  341. * @param $from
  342. * @param $to
  343. * @return array
  344. * @throws \think\db\exception\DbException
  345. */
  346. public function staffPerformanceList($shopId,$from,$to): array
  347. {
  348. $res = self::field('user_id,role,nick_name,mobile,avatar_id,bind_shop_status,create_time')
  349. ->with('avatar')
  350. ->withCount(['straightUsersCnt'=>function($query) use ($from,$to){
  351. $query->whereBetweenTime('create_time',$from,$to);
  352. }])
  353. ->withSum(['commissionTotal'=>function($query) use ($from,$to){
  354. $query->where('clearing_status',1)->whereBetweenTime('order_create_time',$from,$to);
  355. }],'clearing_money')
  356. ->where('role', '>', User::SHOP_BOSS)//11-27除去店老板
  357. ->where('role', '<', User::COMMISSION_USER)
  358. ->where('shop_id',$shopId)->paginate(10)->toArray();
  359. foreach ($res['data'] as $key=>&$item){
  360. $item['rec_orders_cnt_sum'] = "0.00";
  361. $item['rec_orders_cnt_count'] = CommissionsDetail::where('user_id',$item['user_id'])
  362. ->where('shop_id',$shopId)
  363. ->whereBetweenTime('order_create_time',$from,$to)
  364. ->count();
  365. $item['rec_orders_cnt_sum'] = OrderGoods::sumShopGiveOutOrder($shopId,$from,$to,$item['user_id']);
  366. //todo 后面奖励金需要细化到门店 达量奖励金
  367. $bonusAmount = BonusHistory::where('clearing_status', 1)
  368. ->where('shop_id', $shopId)
  369. ->where('user_id', $item['user_id'])
  370. ->sum('bonus_money');
  371. $item['bonus_amount'] = helper::bcsub($bonusAmount, 0, 2);
  372. $is_virtual = Shops::where('shop_id', $shopId)->value('is_virtual');
  373. $qrcode = '';
  374. if ($is_virtual == Shops::SHOP_TYPE_VIRTUAL && $item['role'] == User::SHOP_SELLER) {
  375. // 虚拟门店小程序码
  376. if ($item['user_id']) {
  377. $path = "/pages/tabBar/index/index?apple_s_id={$item['user_id']}&shaer=xcx&scan=1";
  378. $qrcode = request()->domain()."/api/mp_wx/qrcode?path=".urlencode($path);
  379. }
  380. }
  381. $item['qrcode'] = $qrcode;
  382. }
  383. return $res;
  384. }
  385. /**
  386. * Notes:获取用户佣金明细列表
  387. * Author: zhangs
  388. * DateTime: 2021/10/11 11:49
  389. * @param $userId
  390. * @return mixed
  391. */
  392. public function userCommissionDetailList($userId)
  393. {
  394. return CommissionsDetail::alias('cd')
  395. ->field('cd.*,order.order_no')
  396. ->leftJoin('order', 'order.order_id=cd.order_id')
  397. ->where('cd.user_id', $userId)
  398. ->where('cd.clearing_status', 1) // 已结算
  399. ->order('cd.update_time', 'desc')
  400. ->paginate();
  401. }
  402. public function straightUsersCnt(){
  403. return $this->hasMany(User::class,'upper_user_id','user_id');
  404. }
  405. public function recOrdersCnt(){
  406. return $this->hasMany(OrderGoods::class,'staff_user_id','user_id');
  407. }
  408. public function commissionTotal(){
  409. return $this->hasMany(CommissionsDetail::class,'user_id','user_id');
  410. }
  411. public static function getUserByMobile($mobile){
  412. $m = User::field('role')->where('mobile',$mobile)->find();
  413. return $m?$m->getAttr('role'):0;
  414. }
  415. /**
  416. * 员工列表
  417. * @param $shopId
  418. * @return array
  419. * @throws \think\db\exception\DbException
  420. */
  421. public static function staffList($shopId){
  422. return User::field('user_id,nick_name,mobile,role')->where('shop_id',$shopId)
  423. ->where('role',User::SHOP_SELLER)->paginate(15)->toArray();
  424. }
  425. /**
  426. * 获取店老板
  427. * @param $shopId
  428. * @return array|null
  429. * @throws \think\db\exception\DataNotFoundException
  430. * @throws \think\db\exception\DbException
  431. * @throws \think\db\exception\ModelNotFoundException
  432. */
  433. public static function getBoss($shopId){
  434. $bossUserId = \app\store\model\Shops::where('shop_id',$shopId)->find();
  435. $bossUserId = $bossUserId->boss_user_id??0;
  436. $boss = User::field('user_id,nick_name,mobile,role')->where('user_id',$bossUserId)->find();
  437. return $boss?$boss->toArray():null;
  438. }
  439. public static function getBossCommission($shopId){
  440. $bossUserId = \app\store\model\Shops::where('shop_id',$shopId)->find();
  441. $bossUserId = $bossUserId->boss_user_id??0;
  442. $boss = User::field('user_id,nick_name,mobile,role,can_withdraw_money')->where('user_id',$bossUserId)->find();
  443. return $boss?$boss->can_withdraw_money:null;
  444. }
  445. /**
  446. * 分销员佣金统计
  447. * @return \think\Paginator
  448. * @throws \think\db\exception\DataNotFoundException
  449. * @throws \think\db\exception\DbException
  450. * @throws \think\db\exception\ModelNotFoundException
  451. */
  452. public function financeCommerStat($params){
  453. if (!empty($params['betweenTime'])){
  454. $times = between_time($params['betweenTime']);
  455. }else{
  456. /* $times['end_time'] = strtotime(date('Y-m-01 00:00:00')) - 1 ;//上月的最后一秒
  457. $times['start_time'] =strtotime(date('Y-m-01 00:00:00',strtotime('-1 month')));*/
  458. $times['end_time'] = time();
  459. $times['start_time'] = 1590385853;
  460. }
  461. $where[] = ['role','=',User::COMMISSION_USER];
  462. if (!empty($params['userId']) && $params['userId']>0)$where[] = ['user_id','=', $params['userId']];
  463. if (!empty($params['sellerGrade']) && $params['sellerGrade']>0)$where[] = ['seller_grade','=', $params['sellerGrade']];
  464. if (!empty($params['nickName']))$where[] = ['nick_name', 'like','%'.$params['nickName'].'%'];
  465. if (!empty($params['mobile']))$where[] = ['mobile', 'like','%'.$params['mobile'].'%'];
  466. return User::where($where)->field('user_id,nick_name,mobile,role,seller_grade')
  467. ->paginate(15)
  468. ->each(function(&$item) use ($times){
  469. $details = CommissionsDetail::where('user_id',$item['user_id'])
  470. ->whereBetweenTime('order_create_time',$times['start_time'],$times['end_time'])
  471. ->where('clearing_status','<',2)
  472. ->select();
  473. $clearingMoneySum = $clearingMoneyFirstSum = $clearingMoneySecondSum//佣金
  474. = $clearedMoney = $unclearedMoney //已结未结佣金
  475. = $orderCount = $orderFirstCount = $orderSecondCount //订单数
  476. = $orderSaleVolume = $orderSaleVolumeFirst = $orderSaleVolumeSecond//销售额
  477. = 0;
  478. if (!$details->isEmpty()){
  479. $orderCount = count($details);
  480. foreach ($details as $d){
  481. $clearingMoneySum += $d->clearing_money;
  482. $orderSaleVolume += $d->order_sale_volume;
  483. if ($d->commission_level == 1){
  484. $clearingMoneyFirstSum += $d->clearing_money;
  485. $orderFirstCount += 1;
  486. $orderSaleVolumeFirst += $d->order_sale_volume;
  487. }
  488. if ($d->commission_level == 2){
  489. $clearingMoneySecondSum += $d->clearing_money;
  490. $orderSecondCount += 1;
  491. $orderSaleVolumeSecond += $d->order_sale_volume;
  492. }
  493. if ($d->clearing_status == 0){
  494. $unclearedMoney += $d->clearing_money;
  495. }
  496. if ($d->clearing_status == 1){
  497. $clearedMoney += $d->clearing_money;
  498. }
  499. }
  500. }
  501. $item['clearingMoneySum'] = helper::bcadd($clearingMoneySum,0,2);
  502. $item['clearingMoneyFirstSum'] = helper::bcadd($clearingMoneyFirstSum,0,2);
  503. $item['clearingMoneySecondSum'] = helper::bcadd($clearingMoneySecondSum,0,2);
  504. $item['clearedMoney'] = helper::bcadd($clearedMoney,0,2);
  505. $item['unclearedMoney'] = helper::bcadd($unclearedMoney,0,2);
  506. $item['orderCount'] = $orderCount;
  507. $item['orderFirstCount'] = $orderFirstCount;
  508. $item['orderSecondCount'] = $orderSecondCount;
  509. $item['orderSaleVolume'] = helper::bcadd($orderSaleVolume,0,2);
  510. $item['orderSaleVolumeFirst'] = helper::bcadd($orderSaleVolumeFirst,0,2);
  511. $item['orderSaleVolumeSecond'] = helper::bcadd($orderSaleVolumeSecond,0,2);
  512. });
  513. }
  514. /**
  515. * 分销员佣金统计
  516. * @return \think\Paginator
  517. * @throws \think\db\exception\DataNotFoundException
  518. * @throws \think\db\exception\DbException
  519. * @throws \think\db\exception\ModelNotFoundException
  520. */
  521. public function commerStat($params){
  522. if (!empty($params['betweenTime'])){
  523. $times = between_time($params['betweenTime']);
  524. }else{
  525. $times['end_time'] = strtotime(date('Y-m-01 00:00:00',time())) - 1;
  526. $times['start_time'] = strtotime(date('Y-m-01 00:00:00',strtotime('-1 month')));
  527. }
  528. $where[] = ['role','=',User::COMMISSION_USER];
  529. //if (!empty($params['userId']) && $params['userId']>0)$where[] = ['user_id','=', $params['userId']];
  530. if (!empty($params['nickName'])){
  531. $where[] = ['nick_name|user_id', 'like','%'.$params['nickName'].'%'];
  532. }
  533. if (!empty($params['sellerGrade']) && $params['sellerGrade']>0)$where[] = ['seller_grade','=', $params['sellerGrade']];
  534. if (!empty($params['mobile']))$where[] = ['mobile', 'like','%'.$params['mobile'].'%'];
  535. return User::where($where)->field('user_id,nick_name,mobile,role,seller_grade')
  536. ->paginate(15)
  537. ->each(function(&$item) use ($times){
  538. $details = CommissionsDetail::where('user_id',$item['user_id'])
  539. ->whereBetweenTime('order_create_time',$times['start_time'],$times['end_time'])
  540. ->where('clearing_status','<',2)
  541. ->select();
  542. $clearedMoneySum//总基本佣金
  543. = $clearedMoneyFirstSum//一级佣金
  544. = $clearedMoneySecondSum//二级佣金
  545. = $orderCount//总订单数
  546. = $orderFirstCount //一级订单数
  547. = $orderSecondCount //二级订单数
  548. = $orderTotalPrices//订单总金额
  549. = $orderGoodsPrices//订单商品总金额
  550. = $expressPrices//运费
  551. = $couponPrices//平台优惠券
  552. = $actDiscountPrices//活动优惠金额
  553. = $payPrices//实付金额
  554. = 0;
  555. if (!$details->isEmpty()){
  556. $details = $details->toArray();
  557. $orderCount = count($details);
  558. $orderIds = array_column($details,'order_id');
  559. $orders = Order::whereIn('order_id',$orderIds)
  560. ->field('order_price,total_price,express_price,coupon_money,pay_price,rice_card_money,update_price')
  561. ->select()->toArray();
  562. //$orderPriceArr = array_column($orders,'order_price');
  563. //$orderTotalPrices = array_sum($orderPriceArr);
  564. $orderGoodsPricesArr = array_column($orders,'total_price');
  565. $orderGoodsPrices = array_sum($orderGoodsPricesArr);
  566. $expressPricesArr = array_column($orders,'express_price');
  567. $expressPrices = array_sum($expressPricesArr);
  568. $couponPricesArr = array_column($orders,'coupon_money');
  569. $couponPrices = array_sum($couponPricesArr);
  570. $payPricesArr = array_column($orders,'pay_price');
  571. $payPrices = array_sum($payPricesArr);
  572. $riceCardPricesArr = array_column($orders,'rice_card_money');
  573. $riceCardPrices = array_sum($riceCardPricesArr);
  574. $actDiscountPrices = $orderGoodsPrices - $payPrices - $riceCardPrices;
  575. //$orderTotalPrices = $payPrices + $riceCardPrices;
  576. $orderTotalPrices = $orderGoodsPrices + $expressPrices;
  577. foreach ($details as $d){
  578. $clearedMoneySum += $d['clearing_money'];
  579. if ($d['commission_level'] == 1){
  580. $clearedMoneyFirstSum += $d['clearing_money'];
  581. $orderFirstCount += 1;
  582. }
  583. if ($d['commission_level'] == 2){
  584. $clearedMoneySecondSum += $d['clearing_money'];
  585. $orderSecondCount += 1;
  586. }
  587. }
  588. }
  589. $item['orderCount'] = $orderCount;
  590. $item['orderFirstCount'] = $orderFirstCount;
  591. $item['orderSecondCount'] = $orderSecondCount;
  592. $item['orderTotalPrices'] = $orderTotalPrices;
  593. $item['orderGoodsPrices'] = $orderGoodsPrices;
  594. $item['expressPrices'] = $expressPrices;
  595. $item['couponPrices'] = $couponPrices;
  596. $item['payPrices'] = $payPrices;
  597. $item['actDiscountPrices'] = helper::bcadd($actDiscountPrices,0,2);
  598. $item['clearedMoneySum'] = helper::bcadd($clearedMoneySum,0,2);
  599. $item['clearedMoneySecondSum'] = helper::bcadd($clearedMoneySecondSum,0,2);
  600. $item['clearedMoneyFirstSum'] = helper::bcadd($clearedMoneyFirstSum,0,2);
  601. });
  602. }
  603. /**
  604. * 分销员佣金统计
  605. * @throws \think\db\exception\DataNotFoundException
  606. * @throws \think\db\exception\DbException
  607. * @throws \think\db\exception\ModelNotFoundException
  608. */
  609. public function exportCommerStat($params){
  610. if (!empty($params['betweenTime'])){
  611. $times = between_time($params['betweenTime']);
  612. }else{
  613. $times['end_time'] = strtotime(date('Y-m-01 00:00:00',time())) - 1;
  614. $times['start_time'] = strtotime(date('Y-m-01 00:00:00',strtotime('-1 month')));
  615. }
  616. $where[] = ['role','=',User::COMMISSION_USER];
  617. //if (!empty($params['userId']) && $params['userId']>0)$where[] = ['user_id','=', $params['userId']];
  618. if (!empty($params['nickName'])){
  619. $where[] = ['nick_name|user_id', 'like','%'.$params['nickName'].'%'];
  620. }
  621. if (!empty($params['sellerGrade']) && $params['sellerGrade']>0)$where[] = ['seller_grade','=', $params['sellerGrade']];
  622. if (!empty($params['mobile']))$where[] = ['mobile', 'like','%'.$params['mobile'].'%'];
  623. $lists = User::where($where)->field('user_id,nick_name,mobile,role,seller_grade')
  624. ->paginate(15)
  625. ->each(function(&$item) use ($times){
  626. $details = CommissionsDetail::where('user_id',$item['user_id'])
  627. ->whereBetweenTime('order_create_time',$times['start_time'],$times['end_time'])
  628. ->where('clearing_status','=',1)
  629. ->select();
  630. $clearedMoneySum//总基本佣金
  631. = $clearedMoneyFirstSum//一级佣金
  632. = $clearedMoneySecondSum//二级佣金
  633. = $orderCount//总订单数
  634. = $orderFirstCount //一级订单数
  635. = $orderSecondCount //二级订单数
  636. = $orderTotalPrices//订单总金额
  637. = $orderGoodsPrices//订单商品总金额
  638. = $expressPrices//运费
  639. = $couponPrices//平台优惠券
  640. = $actDiscountPrices//活动优惠金额
  641. = $payPrices//实付金额
  642. = 0;
  643. if (!$details->isEmpty()){
  644. $details = $details->toArray();
  645. $orderCount = count($details);
  646. $orderIds = array_column($details,'order_id');
  647. $orders = Order::whereIn('order_id',$orderIds)
  648. ->field('order_price,total_price,express_price,coupon_money,pay_price,rice_card_money,update_price')
  649. ->select()->toArray();
  650. //$orderPriceArr = array_column($orders,'order_price');
  651. //$orderTotalPrices = array_sum($orderPriceArr);
  652. $orderGoodsPricesArr = array_column($orders,'total_price');
  653. $orderGoodsPrices = array_sum($orderGoodsPricesArr);
  654. $expressPricesArr = array_column($orders,'express_price');
  655. $expressPrices = array_sum($expressPricesArr);
  656. $couponPricesArr = array_column($orders,'coupon_money');
  657. $couponPrices = array_sum($couponPricesArr);
  658. $payPricesArr = array_column($orders,'pay_price');
  659. $payPrices = array_sum($payPricesArr);
  660. $riceCardPricesArr = array_column($orders,'rice_card_money');
  661. $riceCardPrices = array_sum($riceCardPricesArr);
  662. $actDiscountPrices = $orderGoodsPrices - $payPrices - $riceCardPrices;
  663. //$orderTotalPrices = $payPrices + $riceCardPrices;
  664. $orderTotalPrices = $orderGoodsPrices + $expressPrices;
  665. foreach ($details as $d){
  666. $clearedMoneySum += $d['clearing_money'];
  667. if ($d['commission_level'] == 1){
  668. $clearedMoneyFirstSum += $d['clearing_money'];
  669. $orderFirstCount += 1;
  670. }
  671. if ($d['commission_level'] == 2){
  672. $clearedMoneySecondSum += $d['clearing_money'];
  673. $orderSecondCount += 1;
  674. }
  675. }
  676. }
  677. $item['orderCount'] = $orderCount;
  678. $item['orderFirstCount'] = $orderFirstCount;
  679. $item['orderSecondCount'] = $orderSecondCount;
  680. $item['orderTotalPrices'] = $orderTotalPrices;
  681. $item['orderGoodsPrices'] = $orderGoodsPrices;
  682. $item['expressPrices'] = $expressPrices;
  683. $item['couponPrices'] = $couponPrices;
  684. $item['payPrices'] = $payPrices;
  685. $item['actDiscountPrices'] = helper::bcadd($actDiscountPrices,0,2);
  686. $item['clearedMoneySum'] = helper::bcadd($clearedMoneySum,0,2);
  687. $item['clearedMoneySecondSum'] = helper::bcadd($clearedMoneySecondSum,0,2);
  688. $item['clearedMoneyFirstSum'] = helper::bcadd($clearedMoneyFirstSum,0,2);
  689. });
  690. $data['header'] = ['用户ID', '推荐官昵称', '推荐官手机号','总订单数','一级订单数','二级订单数','订单总金额(含运费)',
  691. '订单商品总金额','运费','平台优惠券','活动优惠','实付金额(商品+运费)','一级佣金','二级佣金','总基本佣金'];
  692. $data['filename'] = '推荐官基础数据';
  693. $data['data'] = [];
  694. foreach ($lists as $k=>$arr){
  695. $new_list['user_id'] = $arr['user_id'];
  696. $new_list['nick_name'] = $arr['nick_name'];
  697. $new_list['mobile'] = $arr['mobile'];
  698. $new_list['orderCount'] = $arr['orderCount'];
  699. $new_list['orderFirstCount'] = $arr['orderFirstCount'];
  700. $new_list['orderSecondCount'] = $arr['orderSecondCount'];
  701. $new_list['orderTotalPrices'] = $arr['orderTotalPrices'];
  702. $new_list['orderGoodsPrices'] = $arr['orderGoodsPrices'];
  703. $new_list['expressPrices'] = $arr['expressPrices'];
  704. $new_list['couponPrices'] = $arr['couponPrices'];
  705. $new_list['actDiscountPrices'] = $arr['actDiscountPrices'];
  706. $new_list['payPrices'] = $arr['payPrices'];
  707. $new_list['clearedMoneySum'] = $arr['clearedMoneySum'];
  708. $new_list['clearedMoneySecondSum'] = $arr['clearedMoneySecondSum'];
  709. $new_list['clearedMoneyFirstSum'] = $arr['clearedMoneyFirstSum'];
  710. $data['data'][] = $new_list;
  711. }
  712. return $data;
  713. }
  714. /**
  715. * 分销员佣金统计
  716. * @param $params
  717. * @param bool $dataCenter
  718. * @return \think\Paginator
  719. * @throws \think\db\exception\DataNotFoundException
  720. * @throws \think\db\exception\DbException
  721. * @throws \think\db\exception\ModelNotFoundException
  722. */
  723. public function financeCommerBonusStat($params,$dataCenter = false){
  724. list($where,$times) =$this->getBonusFilter($params,$dataCenter);
  725. return User::where($where)->field('user_id,nick_name,mobile,role,seller_grade')
  726. ->paginate(15)
  727. ->each(function(&$item) use ($times){
  728. $details = BonusHistory::where('user_id',$item['user_id'])
  729. ->where('clearing_status',1)
  730. ->whereBetweenTime('year_month',$times['start_time'],$times['end_time'])
  731. ->field('sum(sales_volume) as sales_volumes,sum(order_count) as order_cnt,sum(bonus_money) as bonus_money')
  732. ->find();
  733. $item['sales_volumes'] = $details->sales_volumes??0;
  734. $item['order_cnt'] = $details->order_cnt??0;
  735. $item['bonus_money'] = $details->bonus_money??0;
  736. });
  737. }
  738. private function getBonusFilter($params,$dataCenter = false){
  739. if (!empty($params['betweenTime'])){
  740. $times = between_time($params['betweenTime']);
  741. $times['start_time'] = intval(date('Ym',$times['start_time']));
  742. $times['end_time'] = intval(date('Ym',$times['end_time']));
  743. }else{
  744. $times['end_time'] = intval(date('Ym')) ;//上月的最后一秒
  745. $times['start_time'] =intval(date('Ym',strtotime('-1 month')));
  746. }
  747. $where[] = ['role','=',User::COMMISSION_USER];
  748. if ($dataCenter === true && !empty($params['nickName'])){
  749. $where[] = ['nick_name|user_id', 'like','%'.$params['nickName'].'%'];
  750. }else{
  751. if (!empty($params['userId']) && $params['userId']>0)$where[] = ['user_id','=', $params['userId']];
  752. if (!empty($params['nickName']))$where[] = ['nick_name', 'like','%'.$params['nickName'].'%'];
  753. }
  754. if (!empty($params['sellerGrade']) && $params['sellerGrade']>0)$where[] = ['seller_grade','=', $params['sellerGrade']];
  755. if (!empty($params['mobile']))$where[] = ['mobile', 'like','%'.$params['mobile'].'%'];
  756. return [$where,$times];
  757. }
  758. /**
  759. * 奖励金统计导出
  760. * @param $params
  761. * @param false $dataCenter
  762. * @return array
  763. * @throws \think\db\exception\DataNotFoundException
  764. * @throws \think\db\exception\DbException
  765. * @throws \think\db\exception\ModelNotFoundException
  766. */
  767. public function exportCommerBonusStat($params,$dataCenter = false){
  768. list($where,$times) =$this->getBonusFilter($params,$dataCenter);
  769. $lists = User::where($where)->field('user_id,nick_name,mobile,role,seller_grade')
  770. ->select()
  771. ->each(function(&$item) use ($times){
  772. $details = BonusHistory::where('user_id',$item['user_id'])
  773. ->where('clearing_status',1)
  774. ->whereBetweenTime('year_month',$times['start_time'],$times['end_time'])
  775. ->field('sum(sales_volume) as sales_volumes,sum(order_count) as order_cnt,sum(bonus_money) as bonus_money')
  776. ->find();
  777. $item['sales_volumes'] = $details->sales_volumes??0;
  778. $item['order_cnt'] = $details->order_cnt??0;
  779. $item['bonus_money'] = $details->bonus_money??0;
  780. });
  781. $data['header'] = ['用户ID', '推荐官昵称', '推荐官手机号','推广订单数','商品销售额','奖励金'];
  782. $data['filename'] = '推荐官基础数据';
  783. $data['data'] = [];
  784. foreach ($lists as $k=>$arr){
  785. $new_list['user_id'] = $arr['user_id'];
  786. $new_list['nick_name'] = $arr['nick_name'];
  787. $new_list['mobile'] = $arr['mobile'];
  788. $new_list['order_cnt'] = $arr['order_cnt'];
  789. $new_list['sales_volumes'] = $arr['sales_volumes'];
  790. $new_list['bonus_money'] = $arr['bonus_money'];
  791. $data['data'][] = $new_list;
  792. }
  793. return $data;
  794. }
  795. public function commDetails()
  796. {
  797. return $this->hasMany(CommissionsDetail::class,'user_id','user_id');
  798. }
  799. public function commDetailsCnt()
  800. {
  801. return $this->hasMany(CommissionsDetail::class,'user_id','user_id');
  802. }
  803. public function commerVolumeRank($params){
  804. if (!empty($params['betweenTime'])){
  805. $times = between_time($params['betweenTime']);
  806. }else{
  807. $times['end_time'] = strtotime(date('Y-m-01 00:00:00',time())) - 1;
  808. $times['start_time'] = strtotime(date('Y-m-01 00:00:00',strtotime('-1 month')));
  809. }
  810. $where[] = ['role','=',User::COMMISSION_USER];
  811. if (!empty($params['nickName'])){
  812. $where[] = ['nick_name|user_id', 'like','%'.$params['nickName'].'%'];
  813. }
  814. if (!empty($params['mobile']))$where[] = ['mobile', 'like','%'.$params['mobile'].'%'];
  815. $from = $times['start_time'];
  816. $to = $times['end_time'];
  817. return User::where($where)->field('user_id,nick_name,mobile,role,seller_grade')
  818. ->withSum(['commDetails'=>function($query) use ($from,$to){//订单总金额(含运费)
  819. $query->where('commission_level',1)->where('clearing_status','<',2)
  820. ->whereBetweenTime('order_create_time',$from,$to);
  821. }],'order_sale_volume')
  822. ->withCount(['commDetailsCnt'=>function($query) use ($from,$to){//订单总金额(含运费)
  823. $query->where('commission_level',1)->where('clearing_status','<',2)
  824. ->whereBetweenTime('order_create_time',$from,$to);
  825. }])
  826. ->order('comm_details_sum desc')
  827. ->paginate(15);
  828. }
  829. /**
  830. * 推荐官业绩排行
  831. * @param $params
  832. * @return array
  833. * @throws \think\db\exception\DataNotFoundException
  834. * @throws \think\db\exception\DbException
  835. * @throws \think\db\exception\ModelNotFoundException
  836. */
  837. public function exportCommerRank($params){
  838. if (!empty($params['betweenTime'])){
  839. $times = between_time($params['betweenTime']);
  840. }else{
  841. $times['end_time'] = strtotime(date('Y-m-01 00:00:00',time())) - 1;
  842. $times['start_time'] = strtotime(date('Y-m-01 00:00:00',strtotime('-1 month')));
  843. }
  844. $where[] = ['role','=',User::COMMISSION_USER];
  845. if (!empty($params['nickName'])){
  846. $where[] = ['nick_name|user_id', 'like','%'.$params['nickName'].'%'];
  847. }
  848. if (!empty($params['mobile']))$where[] = ['mobile', 'like','%'.$params['mobile'].'%'];
  849. $from = $times['start_time'];
  850. $to = $times['end_time'];
  851. $lists = User::where($where)->field('user_id,nick_name,mobile,role,seller_grade')
  852. ->withSum(['commDetails'=>function($query) use ($from,$to){//订单总金额(含运费)
  853. $query->where('commission_level',1)->where('clearing_status','<',2)
  854. ->whereBetweenTime('order_create_time',$from,$to);
  855. }],'order_sale_volume')
  856. ->withCount(['commDetailsCnt'=>function($query) use ($from,$to){//订单总金额(含运费)
  857. $query->where('commission_level',1)->where('clearing_status','<',2)
  858. ->whereBetweenTime('order_create_time',$from,$to);
  859. }])
  860. ->order('comm_details_sum desc')
  861. ->select();
  862. $data['header'] = ['排名','用户ID', '推荐官昵称', '推荐官手机号','推广订单数','销售额'];
  863. $data['filename'] = '推荐官业绩排行';
  864. $data['data'] = [];
  865. foreach ($lists as $k=>$arr){
  866. $new_list['rank'] = $k+1;
  867. $new_list['user_id'] = $arr['user_id'];
  868. $new_list['nick_name'] = $arr['nick_name'];
  869. $new_list['mobile'] = $arr['mobile'];
  870. $new_list['comm_details_cnt_count'] = $arr['comm_details_cnt_count'];
  871. $new_list['comm_details_sum'] = $arr['comm_details_sum']?:0;
  872. $data['data'][] = $new_list;
  873. }
  874. return $data;
  875. }
  876. public function getMemberLists($params){
  877. $time = time();
  878. $filter[] = ['is_delete','=',0];
  879. // 微信昵称
  880. //!empty($params['nickName']) && $filter[] = ['nick_name', 'like', "%{$params['nickName']}%"];
  881. // 手机号
  882. if (!empty($params['memStatus']) && $params['memStatus'] >= 1){
  883. if ($params['memStatus'] == 1){
  884. $filter[] = ['member_expire_time', '<', $time];
  885. }else{
  886. $filter[] = ['member_expire_time', '>', $time];
  887. }
  888. }
  889. if (isset($params['memberStartTime']) && is_array($params['memberStartTime'])){
  890. $btes = between_time_format($params['memberStartTime']);
  891. $bt['start_time'] = strtotime(date('Y-m-d 00:00:00',$btes['start_time']));
  892. $bt['end_time'] = strtotime(date('Y-m-d 23:59:59',$btes['end_time']));
  893. $filter[] = ['member_start_time','>=',$bt['start_time']] ;
  894. $filter[] = ['member_start_time','<=',$bt['end_time']] ;
  895. }
  896. $list = self::where('member_expire_time','>',0)
  897. ->where($filter);
  898. if (!empty($params['nickName'])){
  899. $list = $list->where('nick_name|user_id','like',"%{$params['nickName']}%");
  900. }
  901. return $list->field('user_id,nick_name,member_start_time,member_expire_time,gold_rice,growth_value')
  902. ->paginate(15)->each(function (&$item) use ($time){
  903. $item['mem_status'] = $item['member_expire_time']>$time?2:1;//1已过期,2:生效中
  904. $item['mem_status_text'] = ($item['mem_status'] ==1)?'已过期':'生效中';
  905. $item['member_start_time'] = date('Y-m-d H:i',$item['member_start_time']);//1已过期,2:生效中
  906. $item['member_expire_time'] = date('Y-m-d H:i',$item['member_expire_time']);//1已过期,2:生效中
  907. });
  908. }
  909. }