Customer.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. <?php
  2. namespace addons\qingdong\controller;
  3. use addons\qingdong\model\Contacts;
  4. use addons\qingdong\model\Customer as CustomerModel;
  5. use addons\qingdong\model\CustomerFile;
  6. use addons\qingdong\model\CustomerOther;
  7. use addons\qingdong\model\Business;
  8. use addons\qingdong\model\Contract;
  9. use addons\qingdong\model\FormField;
  10. use addons\qingdong\model\StaffSignIn;
  11. use addons\qingdong\model\Consume;
  12. use addons\qingdong\model\Receivables;
  13. use addons\qingdong\model\OperationLog;
  14. use addons\qingdong\model\Form;
  15. use addons\qingdong\model\Record;
  16. use addons\qingdong\model\Record as RecordModel;
  17. use addons\qingdong\model\Staff;
  18. use addons\qingdong\model\StaffCollect;
  19. use addons\qingdong\model\Message;
  20. use think\Db;
  21. use think\Exception;
  22. use function EasyWeChat\Kernel\Support\get_client_ip;
  23. /**
  24. * 操作文档:https://doc.fastadmin.net/qingdong
  25. * 软件介绍:https://www.fastadmin.net/store/qingdong.html
  26. * 售后微信:qingdong_crm
  27. * 客户接口
  28. */
  29. class Customer extends StaffApi
  30. {
  31. protected $noNeedLogin = [];
  32. protected $noNeedRight = [];
  33. //获取select客户列表
  34. public function getSelectList()
  35. {
  36. $name = input('name');
  37. $where = [];
  38. if ($name) {
  39. $where['name'] = ['like', "%{$name}%"];
  40. }
  41. $staff_id=$this->auth->id;
  42. $list = CustomerModel::where($where)->where(function ($query) use ($staff_id) {
  43. $query->where('ro_staff_id', 'like', "%,{$staff_id},%")
  44. ->whereOr('rw_staff_id', 'like', "%,{$staff_id},%")
  45. ->whereOr('owner_staff_id', 'in', Staff::getMyStaffIds());
  46. })->with(['ownerStaff'])->field('id,name,owner_staff_id,follow')->select();
  47. $this->success('请求成功', $list);
  48. }
  49. //获取客户列表
  50. public function getList()
  51. {
  52. $limit = input("limit/d", 10);
  53. $params = $this->request->post();
  54. $where= FormField::updateWhereField(FormField::CUSTOMER_TYPE,$params);
  55. $whereStaff = [];
  56. if (isset($params['name']) && $params['name']) {//客户名称
  57. if(is_numeric($params['name'])){
  58. $whereContact['mobile'] = ['like', "%".$params['name']."%"];
  59. $customer_id= Contacts::where($whereContact)->column('customer_id');
  60. $where['id'] = array('in',$customer_id);
  61. }else{
  62. $where['name|subname'] = ['like', "%{$params['name']}%"];
  63. }
  64. }
  65. if (isset($params['level']) && $params['level']) {//客户星级
  66. $where['level'] = $params['level'];
  67. }
  68. if (isset($params['source']) && $params['source']) {//客户来源
  69. $where['source'] = $params['source'];
  70. }
  71. if (isset($params['follow']) && $params['follow']) {//跟进状态
  72. $where['follow'] = $params['follow'];
  73. }
  74. if (isset($params['group_id']) && $params['group_id']) {//角色组
  75. $ids = Staff::getGroupStaffIds($params['group_id']);
  76. $where['id'] = ['in', $ids];
  77. }
  78. if (isset($params['createtime']) && $params['createtime']) {//
  79. $createtime = $params['createtime'];
  80. $createtime = explode(',', $createtime);
  81. $where['createtime'] = ['between', [strtotime($createtime[0]), strtotime($createtime[1]) + 86400 - 1]];
  82. }
  83. $order = 'id desc';
  84. if (isset($params['sort']) && $params['sort']) {
  85. switch ($params['sort']) {
  86. case 1://名称正序
  87. $order = 'name asc';
  88. break;
  89. case 2://名称倒序
  90. $order = 'name desc';
  91. break;
  92. case 3://创建时间正序
  93. $order = 'createtime asc';
  94. break;
  95. case 4://创建时间倒序
  96. $order = 'createtime desc';
  97. break;
  98. case 5://下次跟进时间正序
  99. $order = 'next_time asc';
  100. break;
  101. case 6://下次跟进时间倒序
  102. $order = 'next_time desc';
  103. break;
  104. }
  105. }
  106. if (isset($params['next_time']) && $params['next_time']) {//下次联系时间
  107. $next_time = $params['next_time'];
  108. $next_time = explode(',', $next_time);
  109. $where['next_time'] = ['between', [$next_time[0], $next_time[1]]];
  110. }
  111. if (isset($params['staff_id']) && $params['staff_id']) {//下级员工筛选
  112. $where['owner_staff_id'] = $params['staff_id'];
  113. } else {
  114. $staff_id = $this->auth->id;
  115. $type = $params['type'] ?? 0;
  116. if ($type == 1) {//我的客户
  117. $whereStaff['owner_staff_id'] = $this->auth->id;
  118. } elseif ($type == 2) {//下属负责的客户
  119. $whereStaff['owner_staff_id'] = ['in', Staff::getLowerStaffId()];
  120. } elseif ($type == 3) {//我参与的客户
  121. $whereStaff = function ($query) use ($staff_id) {
  122. $query->where('ro_staff_id', 'like', "%,{$staff_id},%")
  123. ->whereOr('rw_staff_id', 'like', "%,{$staff_id},%");
  124. };
  125. }else{
  126. $whereStaff = function ($query) use ($staff_id) {
  127. $query->where(['ro_staff_id' => ['like', "%,{$staff_id},%"]])
  128. ->whereOr('rw_staff_id', 'like', "%,{$staff_id},%")
  129. ->whereOr(['owner_staff_id' => ['in', Staff::getMyStaffIds()]]);
  130. };
  131. }
  132. }
  133. $whereSeas = ['owner_staff_id' => ['neq', 0]];
  134. if (isset($params['is_seas']) && $params['is_seas'] == 1) {//公海
  135. //公海权限
  136. $whereSeas=[];
  137. $where['owner_staff_id'] = 0;
  138. //公海权限
  139. $rules=Staff::getStaffRule('seas');
  140. $whereStaff = function ($query) use ($rules) {
  141. foreach ($rules as $rule) {
  142. $query->whereOr(['seas_id' => ['like', "%,{$rule},%"]]);
  143. }
  144. };
  145. $order = 'sea_time desc';
  146. }
  147. if(is_array($whereStaff)){
  148. //查询会冲突
  149. $whereSeas=[];
  150. }
  151. if (isset($params['contract_status']) && $params['contract_status'] !== "") {
  152. $where['contract_status'] = $params['contract_status'];
  153. }
  154. $list = CustomerModel::where($where)->where($whereStaff)->where($whereSeas)->with([
  155. 'ownerStaff',
  156. 'contacts'
  157. ])->field('id,name,next_time,owner_staff_id,level,follow')->order($order)->paginate($limit);
  158. $this->success('请求成功', $list);
  159. }
  160. //查重客户名称
  161. public function selectName()
  162. {
  163. $name = input('name');
  164. if (CustomerModel::where(['name' => $name])->find()) {
  165. $this->error('客户名称已存在');
  166. }
  167. $this->success('当前客户名称可使用');
  168. }
  169. //新增客户
  170. public function addCustomer()
  171. {
  172. $params = $this->request->post();
  173. if (empty($params['customer'])) {
  174. $this->error('客户信息不能为空');
  175. }
  176. // 表单验证
  177. if (($result = $this->qingdongValidate($params['customer'], get_class(), 'create')) !== true) {
  178. $this->error($result);
  179. }
  180. $result = FormField::checkFields(FormField::CUSTOMER_TYPE,$params['customer']);
  181. if ($result !== true) {
  182. $this->error($result);
  183. }
  184. if (CustomerModel::where(['name' => $params['customer']['name']])->find()) {
  185. $this->error('客户名称已存在');
  186. }
  187. if (isset($params['is_event']) && $params['is_event'] == 1) {//是否创建跟进任务
  188. if (empty($params['event'])) {
  189. $this->error('跟进任务信息不能为空');
  190. }
  191. // 表单验证
  192. if (($result = $this->qingdongValidate($params['event'], str_replace(ucwords($this->request->controller()), 'Event', get_class()), 'create_task')) !== true) {
  193. $this->error($result);
  194. }
  195. }
  196. Db::startTrans();
  197. try {
  198. //线索转化
  199. $leads_id = '';
  200. if(isset($params['leads_id'])){
  201. $leads_id=$params['leads_id'];
  202. }
  203. $customerId = CustomerModel::createCustomer($params['customer'],$leads_id,$params['record']);
  204. if(isset($params['customer']['mobile']) && $params['customer']['mobile']){
  205. $retC = array(
  206. 'customer_id'=>$customerId,
  207. 'is_major'=>1,
  208. 'name'=>$params['customer']['name'],
  209. 'mobile'=>$params['customer']['mobile'],
  210. 'next_time'=>date('Y-m-d H:i:s'),
  211. );
  212. Contacts::createContacts($retC);
  213. }
  214. Db::commit();
  215. } catch (Exception $e) {
  216. Db::rollback();
  217. $this->error($e->getMessage());
  218. }
  219. if ($result) {
  220. $this->success('新增客户成功',array('id'=>$customerId));
  221. }
  222. }
  223. //编辑客户
  224. public function editCustomer()
  225. {
  226. $id = input('id');
  227. $params = $this->request->post();
  228. $row = CustomerModel::where(['id' => $id])->find();
  229. if (empty($row)) {
  230. $this->error('客户信息不存在');
  231. }
  232. // 表单验证
  233. if (($result = $this->qingdongValidate($params, get_class(), 'edit')) !== true) {
  234. $this->error($result);
  235. }
  236. $result = FormField::checkFields(FormField::CUSTOMER_TYPE,$params,$id);
  237. if ($result !== true) {
  238. $this->error($result);
  239. }
  240. Db::startTrans();
  241. try {
  242. $result = CustomerModel::updateCustomer($params);
  243. if(isset($params['mobile']) && $params['mobile']){
  244. Contacts::where(array('customer_id'=>$id,'is_major'=>1))->update(array('mobile'=>$params['mobile'],'updatetime'=>time()));
  245. }
  246. Db::commit();
  247. } catch (Exception $e) {
  248. Db::rollback();
  249. $this->error($e->getMessage());
  250. }
  251. $this->success('修改客户成功');
  252. }
  253. //获取子公司
  254. public function getLowerCustomer()
  255. {
  256. $id = input('id');
  257. $customers = CustomerModel::where(['parent_id' => $id])->with([
  258. 'ownerStaff',
  259. 'contacts'
  260. ])->field('id,name,next_time,owner_staff_id,level,follow')->select();
  261. $this->success('请求成功', $customers);
  262. }
  263. //客户详情
  264. public function customerDetail()
  265. {
  266. $id = input('id');
  267. $customer = CustomerModel::where(['id' => $id])->with([
  268. 'createStaff',
  269. 'ownerStaff',
  270. 'contacts'
  271. ])->find();
  272. if (empty($customer)) {
  273. $this->error('信息不存在');
  274. }
  275. $customer = $customer->toArray();
  276. $customer['is_collect'] = StaffCollect::isCollect(StaffCollect::CUSTOMER_TYPE, $customer['id']) ? 1 : 0;
  277. if ($customer['owner_staff_id'] == $this->auth->id ||
  278. in_array($customer['owner_staff_id'],Staff::getLowerStaffId()) ||
  279. in_array($this->auth->id, explode(',', $customer['rw_staff_id'])) ) {
  280. $customer['operation'] = 'update';//修改权限
  281. } else {
  282. $customer['operation'] = 'read';//只读权限
  283. }
  284. $customer = CustomerOther::getOther($customer);
  285. $form = Form::getDataValue('customer',$customer);
  286. foreach($form as $ks=>$vs){
  287. //备注显示
  288. if($vs['component'] == 'textarea' && ($vs['config']['label'] == '备注信息' || $vs['config']['label'] == '备注')){
  289. $customer[$vs['id']] = isset($customer[$vs['id']]) ? $customer[$vs['id']] :$customer['remarks'];
  290. }
  291. }
  292. //商机数量
  293. $customer['bussinessCount'] = Business::where(['customer_id'=>$id])->count();
  294. //联系人数量
  295. $customer['contactsCount'] = Contacts::where(['customer_id'=>$id])->count();
  296. //签到数量
  297. $customer['signCount'] = StaffSignIn::where(['customer_id'=>$id])->count();
  298. //合同数量
  299. $customer['contractCount'] = Contract::where(['customer_id'=>$id])->count();
  300. //费用数量
  301. $customer['consumeCount'] = Consume::where(['customer_id'=>$id])->count();
  302. //回款数量
  303. $customer['receivalbleCount'] = Receivables::where(['customer_id'=>$id])->count();
  304. //子公司
  305. $customer['companyCount'] = CustomerModel::where(['parent_id'=>$id])->count();
  306. //团队
  307. $ro_staff_id = [];
  308. if($customer['ro_staff_id']){
  309. $ro_staff_id = array_unique(array_filter(explode(',',$customer['ro_staff_id'])));
  310. }
  311. $rw_staff_id = [];
  312. if($customer['rw_staff_id']){
  313. $rw_staff_id = array_unique(array_filter(explode(',',$customer['rw_staff_id'])));
  314. }
  315. $customer['teamCount'] = count($ro_staff_id)+count($rw_staff_id);
  316. //附件
  317. $customer['fileCount'] = CustomerFile::where(['customer_id'=>$id])->count();
  318. //操作记录
  319. $customer['operateCount'] = OperationLog::where(['relation_id'=>$id,'relation_type'=>1,'operation_type' => 1])->count();
  320. //标记通知已读
  321. Message::setRead(Message::CUSTOMER_TYPE, $id, $this->auth->id);
  322. $this->success('请求成功', $customer);
  323. }
  324. //移入公海
  325. public function moveSeas()
  326. {
  327. $id = input('id');
  328. $row = CustomerModel::where(['id' => $id, 'owner_staff_id' => $this->auth->id])->find();
  329. if (empty($row)) {
  330. $this->error('您不是负责人暂无权限移除');
  331. }
  332. Db::startTrans();
  333. try {
  334. CustomerModel::moveSeas($id);
  335. Db::commit();
  336. } catch (Exception $e) {
  337. Db::rollback();
  338. $this->error($e->getMessage());
  339. }
  340. $this->success('放入成功');
  341. }
  342. //转移客户
  343. public function transfer()
  344. {
  345. $id = input('id');
  346. $staff_id = input('staff_id');
  347. if (empty($staff_id)) {
  348. $this->error('参数错误');
  349. }
  350. $staff = Staff::get($staff_id);
  351. if (empty($staff)) {
  352. $this->error('接收对象不存在');
  353. }
  354. $row = CustomerModel::where(['id' => $id])->find();
  355. if (empty($row)) {
  356. $this->error('客户不存在');
  357. }
  358. try {
  359. CustomerModel::transfer($id, $staff_id);
  360. } catch (Exception $e) {
  361. $this->error($e->getMessage());
  362. }
  363. $this->success('转移客户成功');
  364. }
  365. //领取公海客户
  366. public function receive()
  367. {
  368. $customer_id = input('customer_id');
  369. $where = ['owner_staff_id' => 0];
  370. if ($customer_id) {
  371. $where['id'] = $customer_id;
  372. }
  373. $customers = CustomerModel::where($where)->count();
  374. if ($customers == 0) {
  375. $this->error('公海内暂无客户');
  376. }
  377. try {
  378. $id = CustomerModel::receive($customer_id);
  379. } catch (Exception $e) {
  380. $this->error($e->getMessage());
  381. }
  382. $this->success('领取成功', ['id' => $id]);
  383. }
  384. //重点关注客户
  385. public function collect()
  386. {
  387. $customer_id = input('customer_id');
  388. try {
  389. StaffCollect::addCollect(StaffCollect::CUSTOMER_TYPE, $customer_id);
  390. } catch (Exception $e) {
  391. $this->error($e->getMessage());
  392. }
  393. $this->success('重点关注成功');
  394. }
  395. //取消重点关注
  396. public function cancelCollect()
  397. {
  398. $customer_id = input('customer_id');
  399. try {
  400. StaffCollect::cancel(StaffCollect::CUSTOMER_TYPE, $customer_id);
  401. } catch (Exception $e) {
  402. $this->error($e->getMessage());
  403. }
  404. $this->success('取消重点关注成功');
  405. }
  406. //重点关注客户列表
  407. public function collectList()
  408. {
  409. $limit = input("limit/d", 10);
  410. $ids = StaffCollect::where(['staff_id' => $this->auth->id, 'relation_type' => 1])->column('relation_id');
  411. $list = CustomerModel::where(['id' => ['in', $ids]])->with([
  412. 'ownerStaff',
  413. 'contacts'
  414. ])->field('id,name,next_time,owner_staff_id,level,follow')->order('id desc')->paginate($limit);
  415. $this->success('请求成功', $list);
  416. }
  417. //获取附件列表
  418. public function getFilesList()
  419. {
  420. $id = input('customer_id');
  421. $files = CustomerFile::where(['customer_id' => $id])->field('file_id')->with(['file'])->select();
  422. $this->success('请求成功', $files);
  423. }
  424. //周围客户
  425. public function nearby()
  426. {
  427. $lng = input('lng');
  428. $lat = input('lat');
  429. //我的客户
  430. $type = input('type',0);
  431. //距离
  432. $distance = input('distance', 5, 'intval');
  433. $name = input('name', '', 'trim');
  434. if (empty($lng) && empty($lat)) {
  435. $this->error('参数错误');
  436. }
  437. $range = 180 / pi() * $distance / 6372.797; //里面的 1 就代表搜索 1km 之内,单位km
  438. $lngR = $range / cos($lat * pi() / 180);
  439. $maxLat = $lat + $range; //最大纬度
  440. $minLat = $lat - $range; //最小纬度
  441. $maxLng = $lng + $lngR; //最大经度
  442. $minLng = $lng - $lngR; //最小经度
  443. $where = ['lng' => ['between', [$minLng, $maxLng]], 'lat' => ['between', [$minLat, $maxLat]]];
  444. //客户分类
  445. $whereStaff=[];
  446. $staff_id=$this->auth->id;
  447. if ($type == 1) {//我的客户
  448. $whereStaff['owner_staff_id'] = $this->auth->id;
  449. } elseif ($type == 2) {//下属负责的客户
  450. $whereStaff['owner_staff_id'] = ['in', Staff::getLowerStaffId()];
  451. } elseif ($type == 3) {//我参与的客户
  452. $whereStaff = function ($query) use ($staff_id) {
  453. $query->where('ro_staff_id', 'like', "%,{$staff_id},%")
  454. ->whereOr('rw_staff_id', 'like', ",{$staff_id},");
  455. };
  456. }else{
  457. $whereStaff = function ($query) use ($staff_id) {
  458. $query->where('ro_staff_id', 'like', "%,{$staff_id},%")
  459. ->whereOr('rw_staff_id', 'like', "%,{$staff_id},%")
  460. ->whereOr('owner_staff_id', 'in', Staff::getMyStaffIds());
  461. };
  462. }
  463. if ($name) {
  464. $where['name'] = ['like', "%{$name}%"];
  465. }
  466. $customers = CustomerModel::where($where)->where($whereStaff)->field('id,owner_staff_id,name,location,next_time,lng,lat,address_detail,follow')->with('ownerStaff')->select();
  467. $data = [];
  468. //所属员工列表
  469. $myStaffIds = Staff::getMyStaffIds();
  470. foreach ($customers as $k => $v) {
  471. if ($v['owner_staff_id'] == 0) {
  472. $v['type'] = 0;//公海
  473. } elseif ($v['owner_staff_id'] == $this->auth->id) {
  474. $v['type'] = 1;//自己的
  475. } elseif (in_array($v['owner_staff_id'], $myStaffIds)) {
  476. $v['type'] = 2;//团队的
  477. } else {
  478. $v['type'] = 3;//其他人
  479. }
  480. $v['juli_num'] = getdistance($lng, $lat, $v['lng'], $v['lat']);
  481. $v['juli'] = float_number($v['juli_num']);
  482. $data[$v['juli']][] = $v;
  483. }
  484. ksort($data);
  485. $result = [];
  486. foreach ($data as $v) {
  487. $result = array_merge($result, array_values($v));
  488. }
  489. $this->success('请求成功', $result);
  490. }
  491. //获取搜索员工列表
  492. public function getSearchStaffList()
  493. {
  494. $name = input('name','');
  495. $where = [];
  496. if($name){
  497. $where['name'] = ['like',"%$name%"];
  498. }
  499. $ids = Staff::getMyStaffIds();
  500. $staff = Staff::where([
  501. 'id' => ['in', $ids],
  502. 'status' => 1
  503. ])->where($where)->field('id,name,img,post')->select();
  504. $this->success('请求成功', $staff);
  505. }
  506. }