Ranking.php 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Description: 商业智能-排行榜
  4. // +----------------------------------------------------------------------
  5. // | Author: Michael_xu | gengxiaoxu@5kcrm.com
  6. // +----------------------------------------------------------------------
  7. namespace app\bi\controller;
  8. use app\admin\controller\ApiCommon;
  9. use app\bi\traits\SortTrait;
  10. use think\Hook;
  11. use think\Request;
  12. use think\Db;
  13. use app\bi\model\Customer as CustomerModel;
  14. use app\bi\model\Contract as ContractModel;
  15. use app\bi\logic\ExcelLogic;
  16. class Ranking extends ApiCommon
  17. {
  18. use SortTrait;
  19. /**
  20. * 用于判断权限
  21. * @permission 无限制
  22. * @allow 登录用户可访问
  23. * @other 其他根据系统设置
  24. **/
  25. public function _initialize()
  26. {
  27. $action = [
  28. 'permission' => [''],
  29. 'allow' => [
  30. 'contract',
  31. 'receivables',
  32. 'signing',
  33. 'addcustomer',
  34. 'addcontacts',
  35. 'recordnun',
  36. 'recordcustomer',
  37. 'examine',
  38. 'product',
  39. 'excelexport'
  40. ]
  41. ];
  42. Hook::listen('check_auth', $action);
  43. $request = Request::instance();
  44. $a = strtolower($request->action());
  45. if (!in_array($a, $action['permission'])) {
  46. parent::_initialize();
  47. }
  48. if (!checkPerByAction('bi', 'ranking', 'read')) {
  49. header('Content-Type:application/json; charset=utf-8');
  50. exit(json_encode(['code' => 102, 'error' => '无权操作']));
  51. }
  52. }
  53. /**
  54. * 合同金额排行
  55. * @param
  56. * @return
  57. * @author Michael_xu
  58. */
  59. public function contract($param = '')
  60. {
  61. if($param['excel_type']!=1){
  62. $param = $this->param;
  63. }
  64. if (!empty($param['start_time'])) $param['start_time'] =$param['start_time'] . ' 00:00:00';
  65. if (!empty($param['end_time'])) $param['end_time'] = $param['end_time'] . ' 23:59:59';
  66. $whereArr = $this->com($param, 'contract');
  67. $whereArr['check_status'] = 2;
  68. //导出使用
  69. if (!empty($param['excel_type'])) {
  70. $data=$this->handel(
  71. new \app\bi\model\Contract,
  72. $whereArr,
  73. ['field' => 'SUM(`money`)', 'alias' => 'money', 'default' => '0.00'],
  74. $param['excel_type']
  75. );
  76. return $data;
  77. }
  78. return $this->handel(
  79. new \app\bi\model\Contract,
  80. $whereArr,
  81. ['field' => 'SUM(`money`)', 'alias' => 'money', 'default' => '0.00']
  82. );
  83. }
  84. /**
  85. * 回款金额排序
  86. * @return
  87. */
  88. public function receivables($param = '')
  89. {
  90. if($param['excel_type']!=1){
  91. $param = $this->param;
  92. }
  93. if (!empty($param['start_time'])) $param['start_time'] = $param['start_time'] . ' 00:00:00';
  94. if (!empty($param['end_time'])) $param['end_time'] = $param['end_time'] . ' 23:59:59';
  95. $whereArr = $this->com($param, 'receivables');
  96. $whereArr['check_status'] = 2;
  97. //导出使用
  98. if (!empty($param['excel_type'])) {
  99. $data=$this->handel(
  100. new \app\bi\model\Receivables,
  101. $whereArr,
  102. ['field' => 'SUM(`money`)', 'alias' => 'money', 'default' => '0.00'],
  103. $param['excel_type']
  104. );
  105. return $data;
  106. }
  107. return $this->handel(
  108. new \app\bi\model\Receivables,
  109. $whereArr,
  110. ['field' => 'SUM(`money`)', 'alias' => 'money', 'default' => '0.00']
  111. );
  112. }
  113. /**
  114. * 签约合同排序
  115. * @return
  116. */
  117. public function signing($param = '')
  118. {
  119. if($param['excel_type']!=1){
  120. $param = $this->param;
  121. }
  122. if (!empty($param['start_time'])) $param['start_time'] = $param['start_time'] . ' 00:00:00';
  123. if (!empty($param['end_time'])) $param['end_time'] = $param['end_time'] . ' 23:59:59';
  124. $whereArr = $this->com($param, 'contract');
  125. // $whereArr['check_status'] = 2;
  126. //导出使用
  127. if (!empty($param['excel_type'])) {
  128. $data= $this->handel(
  129. new ContractModel,
  130. $whereArr,
  131. ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0],
  132. $param['excel_type']
  133. );
  134. return $data;
  135. }
  136. return $this->handel(
  137. new ContractModel,
  138. $whereArr,
  139. ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0]
  140. );
  141. }
  142. /**
  143. * 新增客户排序
  144. * @return
  145. */
  146. public function addCustomer($param = '')
  147. {
  148. if($param['excel_type']!=1){
  149. $param = $this->param;
  150. }
  151. if (!empty($param['start_time'])) $param['start_time'] = $param['start_time'] . ' 00:00:00';
  152. if (!empty($param['end_time'])) $param['end_time'] = $param['end_time'] . ' 23:59:59';
  153. $whereArr = $this->com($param, 'customer');
  154. $poolWhere = $this->getWhereByPool();
  155. $poolId = db('crm_customer')->alias('customer')->where($poolWhere)->column('customer_id');
  156. if (!empty($poolId)) $whereArr['customer_id'] = ['notin', $poolId];
  157. //导出使用
  158. if (!empty($param['excel_type'])) return $this->handel(
  159. new \app\bi\model\Customer,
  160. $whereArr,
  161. ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0],
  162. $param['excel_type']
  163. );
  164. return $this->handel(
  165. new \app\bi\model\Customer,
  166. $whereArr,
  167. ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0]
  168. );
  169. }
  170. /**
  171. * 新增联系人排序
  172. * @return
  173. */
  174. public function addContacts()
  175. {
  176. $param = $this->param;
  177. if (!empty($param['start_time'])) $param['start_time'] = $param['start_time'] . ' 00:00:00';
  178. if (!empty($param['end_time'])) $param['end_time'] = $param['end_time'] . ' 23:59:59';
  179. $whereArr = $this->com($param, 'contacts');
  180. //导出使用
  181. if (!empty($param['excel_type'])) return $this->handel(
  182. new \app\bi\model\Contacts,
  183. $whereArr,
  184. ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0],
  185. $param['excel_type']
  186. );
  187. return $this->handel(
  188. new \app\bi\model\Contacts,
  189. $whereArr,
  190. ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0]
  191. );
  192. }
  193. /**
  194. * 跟进次数排行
  195. *
  196. * @param string $param
  197. * @return array|\think\response\Json
  198. * @throws \think\db\exception\DataNotFoundException
  199. * @throws \think\db\exception\ModelNotFoundException
  200. * @throws \think\exception\DbException
  201. */
  202. public function recordNun($param = '')
  203. {
  204. if($param['excel_type']!=1){
  205. $param = $this->param;
  206. }
  207. if (!empty($param['start_time'])) $param['start_time'] = $param['start_time'] . ' 00:00:00';
  208. if (!empty($param['end_time'])) $param['end_time'] = $param['end_time'] . ' 23:59:59';
  209. $whereArr = $this->com($param, 'record');
  210. # 权限内的员工列表
  211. $userData = [];
  212. $userList = db('admin_user')->alias('user')
  213. ->field(['user.id', 'user.realname AS user_name', 'structure.name AS structure_name'])
  214. ->join('__ADMIN_STRUCTURE__ structure', 'structure.id = user.structure_id')
  215. ->whereIn('user.id', $whereArr['create_user_id'][1])->select();
  216. foreach ($userList AS $key => $value) {
  217. $userData[$value['id']]['user_name'] = $value['user_name'];
  218. $userData[$value['id']]['structure_name'] = $value['structure_name'];
  219. }
  220. # 跟进记录列表
  221. $data = [];
  222. $recordWhere['type'] = 1;
  223. $recordWhere['activity_type'] = 2;
  224. $recordWhere['create_user_id'] = ['in', $whereArr['create_user_id'][1]];
  225. $recordWhere['create_time'] = ['between', [$whereArr['create_time'][1][0], $whereArr['create_time'][1][1]]];
  226. $recordList = db('crm_activity')->field(['count(*) as count', 'create_user_id'])->where($recordWhere)
  227. ->group('create_user_id')->order('count', 'desc')->select();
  228. foreach ($recordList AS $key => $value) {
  229. $data[] = [
  230. 'count' => $value['count'],
  231. 'user_name' => $userData[$value['create_user_id']]['user_name'],
  232. 'structure_name' => $userData[$value['create_user_id']]['structure_name']
  233. ];
  234. }
  235. //导出使用
  236. if (!empty($param['excel_type'])) return $data;
  237. return resultArray(['data' => $data]);
  238. }
  239. /**
  240. * 跟进客户数排行
  241. *
  242. * @param string $param
  243. * @return mixed|\think\response\Json
  244. * @throws \think\db\exception\DataNotFoundException
  245. * @throws \think\db\exception\ModelNotFoundException
  246. * @throws \think\exception\DbException
  247. */
  248. public function recordCustomer($param = '')
  249. {
  250. if($param['excel_type']!=1){
  251. $param = $this->param;
  252. }
  253. if (!empty($param['start_time'])) $param['start_time'] = $param['start_time'] . ' 00:00:00';
  254. if (!empty($param['end_time'])) $param['end_time'] =$param['end_time'] . ' 23:59:59';
  255. $whereArr = $this->com($param, 'record');
  256. # 权限内的员工列表
  257. $userData = [];
  258. $userList = db('admin_user')->alias('user')
  259. ->field(['user.id', 'user.realname AS user_name', 'structure.name AS structure_name'])
  260. ->join('__ADMIN_STRUCTURE__ structure', 'structure.id = user.structure_id')
  261. ->whereIn('user.id', $whereArr['create_user_id'][1])->select();
  262. foreach ($userList AS $key => $value) {
  263. $userData[$value['id']]['user_name'] = $value['user_name'];
  264. $userData[$value['id']]['structure_name'] = $value['structure_name'];
  265. }
  266. # 跟进记录列表
  267. $data = [];
  268. $recordWhere['type'] = 1;
  269. $recordWhere['activity_type'] = 2;
  270. $recordWhere['create_user_id'] = ['in', $whereArr['create_user_id'][1]];
  271. $recordWhere['create_time'] = ['between', [$whereArr['create_time'][1][0], $whereArr['create_time'][1][1]]];
  272. $recordList = db('crm_activity')->field(['create_user_id', 'activity_type_id'])->where($recordWhere)
  273. ->group('create_user_id, activity_type_id')->select();
  274. foreach ($recordList AS $key => $value) {
  275. if (empty($data[$value['create_user_id']]['user_name'])) {
  276. $data[$value['create_user_id']]['user_name'] = $userData[$value['create_user_id']]['user_name'];
  277. $data[$value['create_user_id']]['structure_name'] = $userData[$value['create_user_id']]['structure_name'];
  278. $data[$value['create_user_id']]['count'] = 1;
  279. } else {
  280. $data[$value['create_user_id']]['count'] = $data[$value['create_user_id']]['count'] + 1;
  281. }
  282. }
  283. $data = $this->sortCommon($data, 'count', 'desc');
  284. //导出使用
  285. if (!empty($param['excel_type'])) return $data;
  286. return resultArray(['data' => $data]);
  287. }
  288. /**
  289. * 出差次数排行
  290. * @return
  291. */
  292. public function examine($param = '')
  293. {
  294. if($param['excel_type']!=1){
  295. $param = $this->param;
  296. }
  297. if (!empty($param['start_time'])) $param['start_time'] = $param['start_time'] . ' 00:00:00';
  298. if (!empty($param['end_time'])) $param['end_time'] = $param['end_time'] . ' 23:59:59';
  299. $whereArr = $this->com($param, 'record');
  300. $whereArr['category_id'] = 3; // 审批类型,3出差
  301. $whereArr['check_status'] = 2;
  302. //导出使用
  303. if (!empty($param['excel_type'])) return $this->handel(
  304. new \app\bi\model\Examine,
  305. $whereArr,
  306. ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0],
  307. $param['excel_type'],
  308. 'create_user_id'
  309. );
  310. return $this->handel(
  311. new \app\bi\model\Examine,
  312. $whereArr,
  313. ['field' => 'COUNT(*)', 'alias' => 'count', 'default' => 0],
  314. '',
  315. 'create_user_id'
  316. );
  317. }
  318. /**
  319. * 产品销量排行
  320. * @return
  321. */
  322. public function product($param = '')
  323. {
  324. $userModel = new \app\admin\model\User();
  325. $productModel = new \app\bi\model\Product();
  326. if($param['excel_type']!=1){
  327. $param = $this->param;
  328. }
  329. if (!empty($param['start_time'])) $param['start_time'] = $param['start_time'] . ' 00:00:00';
  330. if (!empty($param['end_time'])) $param['end_time'] = $param['end_time'] . ' 23:59:59';
  331. $list = $productModel->getSortByProduct($param);
  332. $list = array_column($list, null, 'owner_user_id');
  333. $whereArr = $this->com($param, 'contract');
  334. $data = [];
  335. foreach ($whereArr['owner_user_id'][1] as $val) {
  336. $user = $userModel->getUserById($val);
  337. $item = [];
  338. $item['num'] = !empty($list[$val]['num']) ? (int)$list[$val]['num'] : 0;
  339. $item['user_name'] = $user['realname'];
  340. $item['structure_name'] = $user['structure_name'];
  341. $data[] = $item;
  342. }
  343. # 排序
  344. if (!empty($data)) $data = $this->sortCommon($data, 'num', 'desc');
  345. //导出使用
  346. if (!empty($param['excel_type'])) return $data;
  347. return resultArray(['data' => $data]);
  348. }
  349. /**
  350. * 查询条件
  351. * @return
  352. */
  353. private function com($param, $type = '')
  354. {
  355. $userModel = new \app\admin\model\User();
  356. $adminModel = new \app\admin\model\Admin();
  357. $perUserIds = $userModel->getUserByPer('bi', 'ranking', 'read'); //权限范围内userIds
  358. $whereData = $adminModel->getWhere($param, '', $perUserIds); //统计条件
  359. $userIds = $whereData['userIds'];
  360. $between_time = $whereData['between_time'];
  361. if ($type == 'contract') {
  362. $where_time = 'order_date';
  363. } elseif (in_array($type, ['record', 'customer', 'contacts'])) {
  364. $where_time = 'create_time';
  365. } elseif ($type == 'receivables') {
  366. $where_time = 'return_time';
  367. } else {
  368. $where_time = 'start_time';
  369. }
  370. //时间戳:新增客户排行
  371. if ($type == 'contract' || $type == 'receivables') {
  372. $whereArr[$where_time] = array('between', array(date('Y-m-d', $between_time[0]), date('Y-m-d', $between_time[1])));
  373. } else {
  374. $whereArr[$where_time] = array('between', array($between_time[0], $between_time[1]));
  375. }
  376. if (in_array($type, ['customer', 'contract', 'receivables', 'contacts'])) {
  377. $whereArr['owner_user_id'] = ['IN', $userIds];
  378. } else {
  379. $whereArr['create_user_id'] = ['IN', $userIds];
  380. }
  381. return $whereArr;
  382. }
  383. /**
  384. * 查询统计数据
  385. *
  386. * @param model $model
  387. * @param array $whereArr
  388. * @return void
  389. * @author Ymob
  390. * @datetime 2019-11-25 11:11:59
  391. */
  392. private function handel($model, $whereArr, $field, $excel_type = '', $user_field = 'owner_user_id')
  393. {
  394. $userModel = new \app\admin\model\User();
  395. $sql = $model->field([
  396. $user_field,
  397. $field['field'] => $field['alias']
  398. ])
  399. ->where($whereArr)
  400. ->group($user_field)
  401. ->fetchSql()
  402. ->select();
  403. $list = queryCache($sql);
  404. $list = array_column($list, null, $user_field);
  405. $data = [];
  406. foreach ($whereArr[$user_field][1] as $val) {
  407. $user = $userModel->getUserById($val);
  408. $item = [];
  409. $item[$field['alias']] = $list[$val][$field['alias']] ?: $field['default'];
  410. $item['user_name'] = $user['realname'];
  411. $item['structure_name'] = $user['structure_name'];
  412. $data[] = $item;
  413. }
  414. array_multisort($data, SORT_DESC, array_column($data, $field['alias']));
  415. if (!empty($excel_type)) return $data;
  416. return resultArray(['data' => $data]);
  417. }
  418. /**
  419. * 导出
  420. * @param $type
  421. * @param $types
  422. */
  423. public function excelExport()
  424. {
  425. $param = $this->param;
  426. $excel_type = $param['excel_type'];
  427. $type = [];
  428. $type['excel_types'] = $param['excel_types'];
  429. switch ($param['excel_types']) {
  430. case 'contract':
  431. $list = $this->contract($param);
  432. $param['type'] = '合同金额排行';
  433. break;
  434. case 'receivablesRanKingExport':
  435. $list = $this->receivables($param);
  436. $param['type'] = '回款金额排行';
  437. break;
  438. case 'signing':
  439. $list = $this->signing($param);
  440. $param['type'] = '签约合同排行';
  441. break;
  442. case 'product':
  443. $list = $this->product($param);
  444. $param['type'] = '产品销量排行';
  445. break;
  446. case 'addCustomer':
  447. $list = $this->addCustomer($param);
  448. $param['type'] = '新增客户数排行';
  449. break;
  450. case 'addContacts':
  451. $list = $this->addContacts($param);
  452. $param['type'] = '新增联系人数排行';
  453. break;
  454. case 'recordNun':
  455. $list = $this->recordNun($param);
  456. $param['type'] = '跟进次数排行';
  457. break;
  458. case 'recordCustomer':
  459. $list = $this->recordCustomer($param);
  460. $param['type'] = '跟进客户数排行';
  461. break;
  462. case 'examine':
  463. $list = $this->examine($param);
  464. $param['type'] = '出差次数排行';
  465. break;
  466. }
  467. if(empty($list)){
  468. return resultArray(['data'=>'数据不存在']);
  469. }
  470. $excelLogic = new ExcelLogic();
  471. foreach ($list as $key => $v) {
  472. $list[$key]['id'] = $key + 1;
  473. }
  474. $data = $excelLogic->rankingExcle($param, $list);
  475. return $data;
  476. }
  477. /**
  478. * [客户公海条件]
  479. * @author Michael_xu
  480. * @param
  481. * @return
  482. */
  483. public function getWhereByPool()
  484. {
  485. $configModel = new \app\crm\model\ConfigData();
  486. $configInfo = $configModel->getData();
  487. $config = $configInfo['config'] ? : 0;
  488. $follow_day = $configInfo['follow_day'] ? : 0;
  489. $deal_day = $configInfo['deal_day'] ? : 0;
  490. $whereData = [];
  491. //启用
  492. if ($config == 1) {
  493. //默认公海条件(没有负责人或已经到期)
  494. $data['follow_time'] = time()-$follow_day*86400;
  495. $data['deal_time'] = time()-$deal_day*86400;
  496. $data['deal_status'] = '未成交';
  497. if ($follow_day < $deal_day) {
  498. $whereData = function($query) use ($data){
  499. $query->where(['customer.owner_user_id'=>0])
  500. ->whereOr(function ($query) use ($data) {
  501. $query->where(function ($query) use ($data) {
  502. $query->where(['customer.update_time' => array('elt',$data['follow_time'])])
  503. ->whereOr(['customer.deal_time' => array('elt',$data['deal_time'])]);
  504. })
  505. ->where(['customer.is_lock' => 0])
  506. ->where(['customer.deal_status' => ['neq','已成交']]);
  507. });
  508. };
  509. } else {
  510. $whereData = function($query) use ($data){
  511. $query->where(['customer.owner_user_id'=>0])
  512. ->whereOr(function ($query) use ($data) {
  513. $query->where(function ($query) use ($data) {
  514. $query->where(['customer.deal_time' => array('elt',$data['deal_time'])]);
  515. })
  516. ->where(['customer.is_lock' => 0])
  517. ->where(['customer.deal_status' => ['neq','已成交']]);
  518. });
  519. };
  520. }
  521. } else {
  522. $whereData['customer.owner_user_id'] = 0;
  523. }
  524. return $whereData ? : '';
  525. }
  526. }