Customers.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. <?php
  2. namespace app\admin\controller\qingdong\statistic;
  3. use addons\qingdong\model\Form;
  4. use app\admin\model\AuthGroup;
  5. use app\common\controller\Backend;
  6. use addons\qingdong\model\Contract;
  7. use addons\qingdong\model\Customer;
  8. use addons\qingdong\model\Field;
  9. use addons\qingdong\model\Receivables;
  10. use addons\qingdong\model\Record;
  11. use addons\qingdong\model\Staff;
  12. use fast\Tree;
  13. use think\Config;
  14. /**
  15. * 客户分析
  16. */
  17. class Customers extends Backend
  18. {
  19. public function _initialize()
  20. {
  21. parent::_initialize();
  22. $childrenGroupIds = $this->auth->getChildrenGroupIds(true);
  23. $groupList = collection(AuthGroup::where('id', 'in', $childrenGroupIds)->select())->toArray();
  24. Tree::instance()->init($groupList);
  25. $groupList = [];
  26. if ($this->auth->isSuperAdmin()) {
  27. $groupList = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0));
  28. } else {
  29. $groups = $this->auth->getGroups();
  30. $groupIds = [];
  31. foreach ($groups as $m => $n) {
  32. if (in_array($n['id'], $groupIds) || in_array($n['pid'], $groupIds)) {
  33. continue;
  34. }
  35. $groupList = array_merge($groupList, Tree::instance()->getTreeList(Tree::instance()->getTreeArray($n['pid'])));
  36. foreach ($groupList as $index => $item) {
  37. $groupIds[] = $item['id'];
  38. }
  39. }
  40. }
  41. $this->assign('groupdata',$groupList);
  42. }
  43. /**
  44. * 客户总量分析
  45. */
  46. public function index()
  47. {
  48. $row = input('row/a');
  49. if (isset($row['times']) && $row['times']) {
  50. $times = explode(' - ', $row['times']);
  51. } else {
  52. $times = [date('Y-01-01'), date('Y-m-d')];
  53. }
  54. if (isset($row['type']) && $row['type']) {
  55. $type = $row['type'];
  56. } else {
  57. $type = 0;
  58. }
  59. $staff = Staff::info();
  60. $between = [strtotime($times[0]), strtotime($times[1]) + 86400 - 1];
  61. $betweentime = [date('Y-m-d 00:00:00',strtotime($times[0])), date('Y-m-d 23:59:59',strtotime($times[1]) + 86400 - 1)];
  62. if ($type == 1) {//本人
  63. $ids = [$staff->id];
  64. } elseif ($type == 2) {//下属
  65. $ids = Staff::getLowerStaffId();
  66. } else {//全部
  67. $ids = Staff::getMyStaffIds();
  68. }
  69. if (isset($row['staff_id']) && $row['staff_id']) {
  70. $ids = $staff_id = $row['staff_id'];
  71. } else {
  72. $staff_id = '';
  73. }
  74. //新增客户数
  75. $customers = Customer::where([
  76. 'createtime' => [
  77. 'between',
  78. $between
  79. ],
  80. 'owner_staff_id' => ['in', $ids]
  81. ])->field("FROM_UNIXTIME(createtime,'%Y-%m') as ctime,count(*) as c")->group('ctime')->select();
  82. $select = [];
  83. foreach ($customers as $v) {
  84. $select[$v['ctime']] = $v['c'];
  85. }
  86. //已成交客户数
  87. $usecustomers = Customer::where([
  88. 'owner_staff_id' => ['in', $ids],
  89. 'createtime' => [
  90. 'between',
  91. $between
  92. ],
  93. 'contract_status' => 1
  94. ])->field("FROM_UNIXTIME(createtime,'%Y-%m') as ctime,count(*) as c")->group('ctime')->select();
  95. $useselect = [];
  96. foreach ($usecustomers as $v) {
  97. $useselect[$v['ctime']] = $v['c'];
  98. }
  99. $toMonthTime = strtotime($times[1]);
  100. $typedata = [];
  101. $startTime = strtotime($times[0]);
  102. for ($startTime; $startTime <= $toMonthTime; $startTime = strtotime('+1 month', $startTime)) {
  103. $typedata['date'][] = date('Y-m', $startTime);
  104. $typedata['num'][] = $select[date('Y-m', $startTime)] ?? 0;
  105. $typedata['use'][] = $useselect[date('Y-m', $startTime)] ?? 0;
  106. }
  107. $where['status'] = 1;
  108. $where['id'] = ['in', $ids];
  109. $staff = Staff::where($where)->field('id,name')->select();
  110. $customInfo = [];
  111. foreach ($staff as $k => $v) {
  112. $customInfo[$k]['name'] = $v['name'];
  113. //新增客户数
  114. $addcustomer = Customer::where(array('owner_staff_id' => $v['id'], 'createtime' => [
  115. 'between',
  116. $between
  117. ]))->count();
  118. $customInfo[$k]['addcustomer'] = $addcustomer;
  119. //成交客户数
  120. $usecustomer = Customer::where(array('owner_staff_id' => $v['id'], 'contract_status' => 1, 'createtime' => [
  121. 'between',
  122. $between
  123. ]))->count();
  124. $customInfo[$k]['usecustomer'] = $usecustomer;
  125. //客户成交率(%)
  126. $customInfo[$k]['userate'] = $addcustomer ? sprintf("%.2f", $usecustomer / $addcustomer) * 100 : 0;
  127. //合同总金额
  128. $contractMoney = Contract::where(array('owner_staff_id' => $v['id'], 'check_status' => 2, 'order_date' => [
  129. 'between',
  130. $betweentime
  131. ]))->sum('money');
  132. $customInfo[$k]['contractMoney'] = $contractMoney;
  133. //回款金额
  134. $reciveMoney = Receivables::where(array('owner_staff_id' => $v['id'], 'check_status' => 2, 'return_time' => [
  135. 'between',
  136. $betweentime
  137. ]))->sum('money');
  138. $customInfo[$k]['reciveMoney'] = $reciveMoney;
  139. //未回款金额
  140. $customInfo[$k]['noreciveMoney'] = $contractMoney - $reciveMoney;
  141. //回款完成率
  142. $customInfo[$k]['ratereciveMoney'] = $contractMoney ? sprintf("%.2f", $reciveMoney / $contractMoney) * 100 : 0;
  143. }
  144. $this->view->assign([
  145. 'customerdata' => $typedata,
  146. 'customInfo' => $customInfo,
  147. 'times' => implode(' - ', $times),
  148. 'type' => $type,
  149. 'staff_id' => $staff_id,
  150. ]);
  151. return $this->view->fetch();
  152. }
  153. /**
  154. * 客户跟进次数分析
  155. */
  156. public function record()
  157. {
  158. $row = input('row/a');
  159. if (isset($row['times']) && $row['times']) {
  160. $times = explode(' - ', $row['times']);
  161. } else {
  162. $times = [date('Y-01-01'), date('Y-m-d')];
  163. }
  164. if (isset($row['type']) && $row['type']) {
  165. $type = $row['type'];
  166. } else {
  167. $type = 0;
  168. }
  169. $staff = Staff::info();
  170. $between = [strtotime($times[0]), strtotime($times[1]) + 86400 - 1];
  171. if ($type == 1) {//本人
  172. $ids = [$staff->id];
  173. } elseif ($type == 2) {//下属
  174. $ids = Staff::getLowerStaffId();
  175. } else {//全部
  176. $ids = Staff::getMyStaffIds();
  177. }
  178. if (isset($row['staff_id']) && $row['staff_id']) {
  179. $ids = $staff_id = $row['staff_id'];
  180. } else {
  181. $staff_id = '';
  182. }
  183. //跟进客户数
  184. $customers = Record::where([
  185. 'create_staff_id' => ['in', $ids],
  186. 'relation_type' => 1,
  187. 'createtime' => [
  188. 'between',
  189. $between
  190. ]
  191. ])->field("FROM_UNIXTIME(createtime,'%Y-%m') as ctime,relation_id,count('*') as c")->group('relation_id,ctime')->select();
  192. $select = [];
  193. foreach ($customers as $v) {
  194. $select[$v['ctime']] = $v['c'];
  195. }
  196. //跟进次数
  197. $usecustomers = Record::where([
  198. 'create_staff_id' => ['in', $ids],
  199. 'relation_type' => 1,
  200. 'createtime' => [
  201. 'between',
  202. $between
  203. ]
  204. ])->field("FROM_UNIXTIME(createtime,'%Y-%m') as ctime,count(*) as c")->group('ctime')->select();
  205. $useselect = [];
  206. foreach ($usecustomers as $v) {
  207. $useselect[$v['ctime']] = $v['c'];
  208. }
  209. $toMonthTime = strtotime($times[1]);
  210. $typedata = [];
  211. $time = strtotime($times[0]);
  212. for ($time; $time <= $toMonthTime; $time = strtotime('+1 month', $time)) {
  213. $typedata['date'][] = date('Y-m', $time);
  214. $typedata['num'][] = $select[date('Y-m', $time)] ?? 0;
  215. $typedata['use'][] = $useselect[date('Y-m', $time)] ?? 0;
  216. }
  217. $where['status'] = 1;
  218. $where['id'] = ['in', $ids];
  219. $staff = Staff::where($where)->field('id,name')->select();
  220. $customInfo = [];
  221. foreach ($staff as $k => $v) {
  222. $customInfo[$k]['name'] = $v['name'];
  223. //跟进客户数
  224. $addcustomer = Record::where(array('create_staff_id' => $v['id'], 'relation_type' => 1))->group('relation_id')->count();
  225. $customInfo[$k]['addcustomer'] = $addcustomer;
  226. //跟进次数
  227. $usecustomer = Record::where(array('create_staff_id' => $v['id'], 'relation_type' => 1))->count();
  228. $customInfo[$k]['usecustomer'] = $usecustomer;
  229. }
  230. $this->view->assign([
  231. 'customerdata' => $typedata,
  232. 'customInfo' => $customInfo,
  233. 'times' => implode(' - ', $times),
  234. 'type' => $type,
  235. 'staff_id' => $staff_id,
  236. ]);
  237. return $this->view->fetch();
  238. }
  239. /**
  240. * 客户跟进方式分析
  241. */
  242. public function recordtype()
  243. {
  244. $row = input('row/a');
  245. if (isset($row['times']) && $row['times']) {
  246. $times = explode(' - ', $row['times']);
  247. } else {
  248. $times = [date('Y-01-01'), date('Y-m-d')];
  249. }
  250. if (isset($row['type']) && $row['type']) {
  251. $type = $row['type'];
  252. } else {
  253. $type = 0;
  254. }
  255. $staff = Staff::info();
  256. $between = [strtotime($times[0]), strtotime($times[1]) + 86400 - 1];
  257. if ($type == 1) {//本人
  258. $ids = [$staff->id];
  259. } elseif ($type == 2) {//下属
  260. $ids = Staff::getLowerStaffId();
  261. } else {//全部
  262. $ids = Staff::getMyStaffIds();
  263. }
  264. if (isset($row['staff_id']) && $row['staff_id']) {
  265. $ids = $staff_id = $row['staff_id'];
  266. } else {
  267. $staff_id = '';
  268. }
  269. $sources = Field::getField('客户来源');
  270. $customers = Customer::where([
  271. 'owner_staff_id' => ['in', $ids],
  272. 'createtime' => [
  273. 'between',
  274. $between
  275. ]
  276. ])->field("FROM_UNIXTIME(createtime,'%Y-%m') as ctime,source,count(*) as c")->group('source,ctime')->select();
  277. $select = [];
  278. foreach ($customers as $v) {
  279. $select[$v['source']][$v['ctime']] = $v['c'];
  280. }
  281. $sourcedata = ['客户来源' => ['客户来源']];
  282. $toMonthTime = strtotime($times[1]);
  283. $time = strtotime($times[0]);
  284. for ($time; $time <= $toMonthTime; $time = strtotime('+1 month', $time)) {
  285. $sourcedata['客户来源'][] = date('Y-m', $time);
  286. foreach ($sources as $v) {
  287. if (empty($sourcedata[$v])) {
  288. $sourcedata[$v][] = $v;
  289. }
  290. $sourcedata[$v][] = intval($select[$v][date('Y-m', $time)] ?? 0);
  291. }
  292. }
  293. $this->view->assign([
  294. 'customerdata' => array_values($sourcedata),
  295. 'times' => implode(' - ', $times),
  296. 'type' => $type,
  297. 'staff_id' => $staff_id,
  298. ]);
  299. return $this->view->fetch();
  300. }
  301. /**
  302. * 客户跟进方式分析
  303. */
  304. public function ratio()
  305. {
  306. $type=input('type','bar');//bar 柱状图 pie 饼状图
  307. $row = input('row/a');
  308. if (isset($row['times']) && $row['times']) {
  309. $times = explode(' - ', $row['times']);
  310. } else {
  311. $times = [date('Y-01-01'), date('Y-m-d')];
  312. }
  313. $between = [strtotime($times[0]), strtotime($times[1]) + 86400 - 1];
  314. $group_id = $row['group_id']??0;
  315. $ids=[];
  316. if ($group_id) {//角色组
  317. $ids = Staff::getGroupStaffIds($group_id);
  318. }
  319. if (isset($row['staff_id']) && $row['staff_id']) {
  320. $ids = $staff_id = $row['staff_id'];
  321. } else {
  322. $staff_id = '';
  323. }
  324. $this->view->assign([
  325. 'customerdata' =>[],
  326. 'times' => implode(' - ', $times),
  327. 'staff_id' => $staff_id,
  328. 'group_id' => $group_id,
  329. 'list' => [],
  330. 'type' => $type,
  331. ]);
  332. return $this->view->fetch();
  333. }
  334. /**
  335. * 客户自定义分析
  336. */
  337. public function customize()
  338. {
  339. $type=input('type','bar');//bar 柱状图 pie 饼状图
  340. $row = input('row/a');
  341. if (isset($row['times']) && $row['times']) {
  342. $times = explode(' - ', $row['times']);
  343. } else {
  344. $times = [date('Y-01-01'), date('Y-m-d')];
  345. }
  346. $between = [strtotime($times[0]), strtotime($times[1]) + 86400 - 1];
  347. $group_id = $row['group_id']??0;
  348. $ids=[];
  349. if ($group_id) {//角色组
  350. $ids = Staff::getGroupStaffIds($group_id);
  351. }
  352. if (isset($row['staff_id']) && $row['staff_id']) {
  353. $ids = $staff_id = $row['staff_id'];
  354. } else {
  355. $staff_id = '';
  356. }
  357. $customer=Form::getDataValue('customer');
  358. $fields=[];
  359. foreach ($customer as $v) {
  360. if ($v['component'] == 'select' && substr($v['id'], 0, 5) != 'other') {
  361. $content = $v['config']['content'];
  362. $label = [];
  363. foreach ($content as $ves) {
  364. $label[] = $ves['label'];
  365. }
  366. $fields[$v['id']] = ['id' => $v['id'], 'name' => $v['config']['label'],
  367. 'label' => $label, 'multiple' => $v['config']['multiple']];
  368. }
  369. }
  370. if (isset($row['field']) && $row['field']) {
  371. $field = html_entity_decode(trim($row['field']));
  372. if(empty($fields[$field])){
  373. $this->error('没有可用的筛选项');
  374. }
  375. } else {
  376. if(empty($fields)){
  377. $this->error('没有可用的筛选项');
  378. }
  379. $field=current($fields)['id'];
  380. }
  381. $where=[
  382. 'createtime'=>[
  383. 'between',
  384. $between
  385. ]];
  386. if ($ids || !empty($group_id)) {
  387. $where['owner_staff_id'] = ['in', $ids];
  388. }
  389. if($fields[$field]['multiple'] == false){
  390. $customers = Customer::where($where)
  391. ->field("{$field},count(*) as c")
  392. ->group($field)->order('c desc')->select();
  393. $select = [];
  394. $total_count=0;
  395. foreach ($customers as $v) {
  396. $total_count+=$v['c'];
  397. $select[$v[$field]] = $v['c'];
  398. }
  399. }else{
  400. $select = [];
  401. $total_count=0;
  402. //多选情况
  403. foreach ($fields[$field]['label'] as $label) {
  404. $where[$field] = ['like', "%{$label}%"];
  405. $count = Customer::where($where)->count();
  406. $select[$label] = $count;
  407. $total_count += $count;
  408. }
  409. }
  410. $sourcedata = [];
  411. $y=[];
  412. $list=[];
  413. $data=[];
  414. foreach ($fields[$field]['label'] as $label){
  415. if(isset($select[$label])){
  416. $list[]=[
  417. 'name'=>$label,
  418. 'number'=>$select[$label],
  419. 'ratio'=>sprintf("%.2f", $select[$label] / $total_count * 100),
  420. ];
  421. $data[]=['value'=>$select[$label],'name'=>$label];
  422. $y[]=$select[$label];
  423. }else{
  424. $list[] = [
  425. 'name' => $label,
  426. 'number' => 0,
  427. 'ratio' => 0,
  428. ];
  429. $data[]=['value'=>0,'name'=>$label];
  430. $y[]=0;
  431. }
  432. }
  433. $sourcedata['x']=$fields[$field]['label'];
  434. $sourcedata['y']=$y;
  435. $sourcedata['title']=$fields[$field]['name'];
  436. $sourcedata['data']=$data;
  437. $sourcedata['type']=$type;
  438. $this->view->assign([
  439. 'customerdata' =>$sourcedata,
  440. 'times' => implode(' - ', $times),
  441. 'fields' => $fields,
  442. 'field' => $field,
  443. 'field_name' => $fields[$field]['name'],
  444. 'staff_id' => $staff_id,
  445. 'group_id' => $group_id,
  446. 'list' => $list,
  447. 'type' => $type,
  448. 'multiple' => $fields[$field]['multiple'],
  449. ]);
  450. return $this->view->fetch();
  451. }
  452. /**
  453. * 获取员工列表
  454. */
  455. public function getstaff()
  456. {
  457. $pageSize = input('pageSize');
  458. $pageNumber = input('pageNumber');
  459. $where = [];
  460. if ($keyValue = $this->request->request("keyValue")) {
  461. $where['id'] = ['in', $keyValue];
  462. }else{
  463. $where['id'] = ['in', Staff::getMyStaffIds()];
  464. }
  465. $name = input('name');
  466. if (!empty($name)) {
  467. $where['name'] = ['like', '%' . $name . '%'];
  468. }
  469. $staff = Staff::where($where)->field('id,name')->order('id desc')->paginate($pageSize, false, ['page' => $pageNumber]);
  470. return json(['list' => $staff->items(), 'total' => $staff->total()]);
  471. }
  472. }