Autotask.php 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. <?php
  2. namespace addons\qingdongams\controller;
  3. use addons\qingdongams\model\AttendanceRule;
  4. use addons\qingdongams\model\AttendanceStatisc;
  5. use addons\qingdongams\model\AttendanceTime;
  6. use addons\qingdongams\library\JuheExpress;
  7. use addons\qingdongams\model\Attendance;
  8. use addons\qingdongams\model\Leads;
  9. use addons\qingdongams\library\ReceiveMail;
  10. use addons\qingdongams\model\AdminConfig;
  11. use addons\qingdongams\model\Contract;
  12. use addons\qingdongams\model\Customer;
  13. use addons\qingdongams\model\CustomerType;
  14. use addons\qingdongams\model\Message;
  15. use addons\qingdongams\model\Receivables;
  16. use addons\qingdongams\model\Staff;
  17. use addons\qingdongams\model\StaffSignIn;
  18. use addons\qingdongams\model\StaffTeam;
  19. use addons\qingdongams\model\StaffTeamList;
  20. use addons\qingdongams\model\Quote;
  21. use addons\qingdongams\model\Workorder;
  22. use addons\qingdongams\model\WorkorderLogistics;
  23. use addons\qingdongams\model\WorkReport;
  24. use addons\qingdongams\model\Event;
  25. use addons\qingdongams\model\Record;
  26. use fast\Http;
  27. use think\Db;
  28. use think\Exception;
  29. use think\Log;
  30. @header('Content-type: text/html;charset=UTF-8');
  31. error_reporting(0);
  32. ignore_user_abort(); // run script in background
  33. set_time_limit(0); // run script forever
  34. date_default_timezone_set('Asia/Shanghai');
  35. class Autotask
  36. {
  37. public $mailServer = "pophz.qiye.163.com";
  38. public $serverType = "pop3";
  39. public $port = "110";
  40. protected $now = 0;
  41. protected $savePath;
  42. protected $webPath;
  43. protected $formater = ['gif', 'jpeg', 'png', 'jpg', 'bmp'];
  44. public function __construct()
  45. {
  46. try{
  47. \think\Db::execute("SET @@sql_mode='';");
  48. }catch (Exception $e){
  49. }
  50. $this->prikey = AdminConfig::where(array('type'=>'wechat','field'=>'email_key'))->value('value');
  51. $this->savePath = ROOT_PATH;
  52. $this->webPath = "../emails/";
  53. }
  54. //合同到期提醒
  55. public function contract()
  56. {
  57. $endDate = date('Y-m-d', strtotime('+3 day'));
  58. $contracts = Contract::where(['check_status' => 2, 'contract_status' => 0, 'end_time' => ['lt', $endDate]])->select();
  59. try {
  60. //合同即将到期通知
  61. foreach ($contracts as $v) {
  62. Message::addMessage(Message::CONTRACT_EXPIRE_TYPE, $v['id'], $v['owner_staff_id'], 0,'合同即将到期,请尽快跟进回款');
  63. }
  64. } catch (Exception $e) {
  65. return $e->getMessage();
  66. }
  67. $this->plan();
  68. $this->visitWorkorderMessage();
  69. return 'success';
  70. }
  71. //回款计划通知
  72. public function plan()
  73. {
  74. $endDate = date('Y-m-d', strtotime('+1 day'));
  75. //进行中 -- 待回款
  76. $plans = \addons\qingdongams\model\ReceivablesPlan::where(['status' => 0, 'remind_date' => ['lt', $endDate]])->select();
  77. try {
  78. //合同即将到期通知
  79. foreach ($plans as $v) {
  80. Message::addMessage(Message::PLAN_EXPIRE_TYPE, $v['contract_id'], $v['owner_staff_id'],0, '已到计划回款约定时间,请尽快跟进回款');
  81. }
  82. } catch (Exception $e) {
  83. return $e->getMessage();
  84. }
  85. return 'success';
  86. }
  87. //日程提醒
  88. public function event()
  89. {
  90. $endDate = date('Y-m-d H:i:s');
  91. $events = \addons\qingdongams\model\Event::where(['status' => 0, 'remind_time' => ['lt', $endDate]])->select();
  92. $endIds = \addons\qingdongams\model\Event::where([
  93. 'status' => ['in', [0, 1]],
  94. 'end_time' => ['lt', $endDate]
  95. ])->column('id');
  96. try {
  97. //日程自动结束
  98. Event::where(['id' => ['in', $endIds]])->update(['status' => 2]);
  99. //日程时间提醒
  100. foreach ($events as $v) {
  101. if (Message::where([
  102. 'relation_type' => Message::EVENT_TYPE,
  103. 'relation_id' => $v['id'],
  104. 'to_staff_id' => $v['staff_id']
  105. ])->count()) {
  106. //已经提醒过了
  107. continue;
  108. }
  109. Message::addMessage(Message::EVENT_TYPE, $v['id'], $v['staff_id'],0, $v['title'] . '日程即将开始');
  110. }
  111. } catch (Exception $e) {
  112. return $e->getMessage();
  113. }
  114. return 'success';
  115. }
  116. //公海
  117. public function seas()
  118. {
  119. if (AdminConfig::getConfigValue('auto', AdminConfig::TYPE_SEAS)) {//自动回收客户
  120. if (AdminConfig::getConfigValue('genjing', AdminConfig::TYPE_SEAS) == 1) {//未跟进客户回收
  121. $day = AdminConfig::getConfigValue('genjing_day', AdminConfig::TYPE_SEAS);
  122. $genjing_c_name = AdminConfig::getConfigValue('genjing_c_name', AdminConfig::TYPE_SEAS);
  123. $where = [
  124. 'receivetime' => ['<', strtotime('-' . $day . ' day')],
  125. 'last_time' => ['<', date('Y-m-d H:i:s', strtotime('-' . $day . ' day'))]];
  126. if ($genjing_c_name) {
  127. $where['name'] = ['like', "%{$genjing_c_name}%"];
  128. }
  129. if (AdminConfig::getConfigValue('genjing_success', AdminConfig::TYPE_SEAS) == 1) {
  130. $where['contract_status'] = 0;
  131. }
  132. $customers = Customer::where($where)->field('id,name,owner_staff_id')->select();
  133. try {
  134. foreach ($customers as $c) {
  135. Customer::moveSeas($c['id']);
  136. Message::addMessage(Message::SEAS_TYPE, $c['id'], $c['owner_staff_id'], 0, "您的客户`{$c['name']}`长时间未跟进,已被系统自动回收到公海池内。");
  137. }
  138. } catch (Exception $e) {
  139. Log::error($e->getMessage());
  140. }
  141. }
  142. if (AdminConfig::getConfigValue('chengjiao', AdminConfig::TYPE_SEAS) == 1) {//未成交客户回收
  143. $day = AdminConfig::getConfigValue('chengjiao_day', AdminConfig::TYPE_SEAS);
  144. $chengjiao_c_name = AdminConfig::getConfigValue('chengjiao_c_name', AdminConfig::TYPE_SEAS);
  145. $where = [
  146. 'receivetime' => ['<', strtotime('-' . $day . ' day')],
  147. 'contract_status' => 0
  148. ];
  149. if ($chengjiao_c_name) {
  150. $where['name'] = ['like', "%{$chengjiao_c_name}%"];
  151. }
  152. $customers = Customer::where($where)->field('id,name,owner_staff_id')->select();
  153. try {
  154. foreach ($customers as $c) {
  155. Customer::moveSeas($c['id']);
  156. Message::addMessage(Message::SEAS_TYPE, $c['id'], $c['owner_staff_id'], 0, "您的客户`{$c['name']}`长时间未成交,已被系统自动回收到公海池内。");
  157. }
  158. } catch (Exception $e) {
  159. Log::error($e->getMessage());
  160. }
  161. }
  162. }
  163. return 'success';
  164. }
  165. /**
  166. * 线索池分配
  167. */
  168. public function leadpool(){
  169. if(AdminConfig::getConfigValue('leadauto', AdminConfig::TYPE_LEAD)){
  170. $leadauto = AdminConfig::getConfigValue('leadauto', AdminConfig::TYPE_LEAD);
  171. $lead_day = AdminConfig::getConfigValue('lead_day', AdminConfig::TYPE_LEAD);
  172. $attendance = AdminConfig::getConfigValue('leadcard', AdminConfig::TYPE_LEAD);
  173. $department = AdminConfig::getConfigValue('department', AdminConfig::TYPE_LEAD);
  174. //开启分配
  175. if($leadauto == 1 && $lead_day>0 && $department){
  176. $leadpool = Leads::where('owner_staff_id is null or owner_staff_id = 0')->order('id desc')->limit(100)->column('id');
  177. if($leadpool){
  178. $department = explode(',',$department);
  179. $staffinfo = array();
  180. foreach($department as $k=>$v){
  181. $staffids = Staff::where('', 'exp', Db::raw('FIND_IN_SET(' . $v . ',group_ids)'))->where(['status'=>1])->column('id');
  182. $staffinfo[] = $staffids;
  183. }
  184. if(!$staffinfo){
  185. return '无数据';
  186. }
  187. $staffinfos =[];
  188. foreach($staffinfo as $k=>$v){
  189. foreach($v as $ks=>$vs){
  190. $staffinfos[] = $vs;
  191. }
  192. }
  193. $staff = array_unique($staffinfos);
  194. foreach($leadpool as $ks=>$vs){
  195. $stafflead =[];
  196. foreach($staff as $k=>$v){
  197. if($attendance == 1){ //打卡
  198. $whereC['staff']= $v;
  199. $whereC['createtime'] = array(array('egt',strtotime(date('Y-m-d 00:00:00'))),array('elt',strtotime(date('Y-m-d 23:59:59'))));
  200. $leadcard = Attendance::where($whereC)->find();
  201. if(!$leadcard){//未打卡不分配
  202. continue;
  203. }
  204. }
  205. $wherelead['owner_staff_id'] = $v;
  206. $wherelead['receive_time'] = array(array('egt',strtotime('-'.$lead_day.' days',time())),array('elt',time()));
  207. $lead = Leads::where($wherelead)->count();
  208. $stafflead[] = array(
  209. 'id'=>$v,
  210. 'num'=>$lead
  211. );
  212. }
  213. if($stafflead){
  214. $num_count = array_column($stafflead,'num');//返回数组中指定的一列
  215. array_multisort($num_count,SORT_ASC,$stafflead);
  216. Leads::where(array('id'=>$vs))->update(array('owner_staff_id'=>$stafflead[0]['id'],'receive_time'=>time()));
  217. }
  218. }
  219. }
  220. }
  221. }
  222. return 'success';
  223. }
  224. //工作报告 日志
  225. public function dayWorkorder()
  226. {
  227. $type=input('type');
  228. if ($type == '日') {
  229. $time = date('Y-m-d', strtotime('-1 day'));
  230. $startDate = strtotime($time);
  231. //月底
  232. $endDate = strtotime($time . '+1 day') - 1;
  233. } elseif ($type == '周') {
  234. $time = date('Y-m-d', strtotime('-1 monday', time()));
  235. $startDate = strtotime($time);
  236. //月底
  237. $endDate = strtotime($time . '+1 week') - 1;
  238. } elseif ($type == '月') {
  239. $time = date('Y-m-d', strtotime('-1 month', strtotime(date('Y-m', time()) . '-01 00:00:00')));;
  240. $startDate = strtotime($time);
  241. //月底
  242. $endDate = strtotime($time . '+1 month') - 1;
  243. } elseif ($type == '季') {
  244. $season = ceil((date('n')) / 3) - 1;
  245. $time = date('Y-m-d', mktime(0, 0, 0, $season * 3 - 3 + 1, 1, date('Y')));
  246. $startDate = strtotime($time);
  247. //月底
  248. $endDate = strtotime($time . '+3 month') - 1;
  249. } elseif ($type == '年') {
  250. $time = date('Y-1-1', strtotime('-1 year'));
  251. $startDate = strtotime($time);
  252. //月底
  253. $endDate = strtotime($time . '+1 year') - 1;
  254. } else {
  255. return '链接必须带参数';
  256. }
  257. $workreportModel = new WorkReport();
  258. $find = $workreportModel->where([
  259. 'report_date' => $time,
  260. 'type' => $type
  261. ])->find();
  262. if ($find) {
  263. return '已生成日报';
  264. }
  265. //跟进记录
  266. $followUp = Record::where([
  267. 'relation_type' => 1,
  268. 'createtime' => ['between', [$startDate, $endDate]],
  269. ])->group('staff_id')->field('staff_id,count(*) as count,group_concat(id) as id_list')->select();
  270. $followUp = $this->setStaffList($followUp);
  271. //获客 客户
  272. $customer = Customer::where([
  273. 'createtime' => ['between', [$startDate, $endDate]],
  274. ])->group('create_staff_id')->field('create_staff_id,count(*) as count,group_concat(id) as id_list')->select();
  275. $customer = $this->setStaffList($customer);
  276. //合同
  277. $contract = Contract::where([
  278. 'createtime' => ['between', [$startDate, $endDate]],
  279. 'check_status' => 2
  280. ])->group('create_staff_id')->field('create_staff_id,count(*) as count,group_concat(id) as id_list,sum(money) as money')->select();
  281. $contract = $this->setStaffList($contract);
  282. //报价
  283. $quote = Quote::where([
  284. 'createtime' => ['between', [$startDate, $endDate]],
  285. 'check_status' => 2
  286. ])->group('create_staff_id')->field('create_staff_id,count(*) as count,group_concat(id) as id_list')->select();
  287. $quote = $this->setStaffList($quote);
  288. //
  289. $order = \addons\qingdongams\model\Order::where([
  290. 'createtime' => ['between', [$startDate, $endDate]],
  291. ])->group('create_staff_id')->field('create_staff_id,count(*) as count,group_concat(id) as id_list')->select();
  292. $order = $this->setStaffList($order);
  293. //回款次数
  294. $receivables = Receivables::where([
  295. 'createtime' => ['between', [$startDate, $endDate]],
  296. 'check_status' => 2
  297. ])->group('create_staff_id')->field('create_staff_id,count(*) as count,group_concat(id) as id_list,sum(money) as money')->select();
  298. $receivables = $this->setStaffList($receivables);
  299. //拜访次数
  300. $visit = Event::where([
  301. 'event_type' => ['like',"客户服务%"],
  302. 'actual_end_time' => ['between', [$startDate, $endDate]],
  303. 'status' => 2
  304. ])->group('staff_id')->field('staff_id,count(*) as count,group_concat(id) as id_list,sum(use_time) as time')->select();
  305. $visit = $this->setStaffList($visit);
  306. //新建工单
  307. $workorder = Workorder::where([
  308. 'createtime' => ['between', [$startDate, $endDate]]
  309. ])->group('create_staff_id')->field('create_staff_id,count(*) as count,group_concat(id) as id_list')->select();
  310. $workorder = $this->setStaffList($workorder);
  311. //完成工单数量
  312. $completeWorkorder = Workorder::where([
  313. 'status' => 3,
  314. 'end_time' => ['between', [$startDate, $endDate]]
  315. ])->group('owner_staff_id')->field('owner_staff_id,count(*) as count,group_concat(id) as id_list,sum(money) as money')->select();
  316. $completeWorkorder = $this->setStaffList($completeWorkorder);
  317. //好评工单
  318. $goodWorkorder = Workorder::where([
  319. 'comment_score' => 5,
  320. 'status' => 3,
  321. 'end_time' => ['between', [$startDate, $endDate]]
  322. ])->group('owner_staff_id')->field('owner_staff_id,count(*) as count,group_concat(id) as id_list')->select();
  323. $goodWorkorder = $this->setStaffList($goodWorkorder);
  324. //未完成日程
  325. $notEvent = Event::where([
  326. 'createtime' => ['between', [$startDate, $endDate]],
  327. 'status' => ['in', [0, 1]]
  328. ])->group('staff_id')->field('staff_id,count(*) as count,group_concat(id) as id_list')->select();
  329. $notEvent = $this->setStaffList($notEvent);
  330. //完成日程及任务
  331. $completeEvent = Event::where([
  332. 'actual_end_time' => ['between', [$startDate, $endDate]],
  333. 'status' => 2
  334. ])->group('staff_id')->field('staff_id,count(*) as count,group_concat(id) as id_list,sum(use_time) as time')->select();
  335. $completeEvent = $this->setStaffList($completeEvent);
  336. $staff = Staff::where(['status'=>1])->field('id,name')->select();
  337. $insertAll = [];
  338. foreach ($staff as $v) {
  339. $customerinfo = $customer[$v['id']] ?? '';
  340. $visitinfo = $visit[$v['id']] ?? '';
  341. $quoteinfo = $quote[$v['id']] ?? '';
  342. $contractinfo = $quote[$v['id']] ?? '';
  343. $orderinfo = $order[$v['id']] ?? '';
  344. $receivablesinfo = $receivables[$v['id']] ?? '';
  345. $workorderinfo = $workorder[$v['id']] ?? '';
  346. $complete_workorderinfo = $completeWorkorder[$v['id']] ?? '';
  347. $good_workorderinfo = $goodWorkorder[$v['id']] ?? '';
  348. $not_eventinfo=$notEvent[$v['id']] ?? '';
  349. $complete_eventinfo = $completeEvent[$v['id']] ?? '';
  350. $follow_upinfo = $followUp[$v['id']] ?? '';
  351. if(!$customerinfo && !$visitinfo && !$quoteinfo && !$contractinfo && !$orderinfo && !$receivablesinfo &&
  352. !$workorderinfo && !$complete_workorderinfo && !$good_workorderinfo && !$not_eventinfo && !$complete_eventinfo && !$follow_upinfo){
  353. continue;
  354. }
  355. $insertAll[] = [
  356. 'staff_id' => $v['id'],
  357. 'report_date' => $time,
  358. 'type' => $type,
  359. 'customer' => $customer[$v['id']] ?? '',//获客
  360. 'visit' => $visit[$v['id']] ?? '',//拜访
  361. 'quote' => $quote[$v['id']] ?? '',//拜访
  362. 'contract' => $contract[$v['id']] ?? '',//合同
  363. 'order' => $order[$v['id']] ?? '',//订单
  364. 'receivables' => $receivables[$v['id']] ?? '',//回款
  365. 'workorder' => $workorder[$v['id']] ?? '',//工单
  366. 'complete_workorder' => $completeWorkorder[$v['id']] ?? '',//完成工单数量
  367. 'good_workorder' => $goodWorkorder[$v['id']] ?? '',//好评工单数量
  368. 'not_event' => $notEvent[$v['id']] ?? '',//未完成日程
  369. 'complete_event' => $completeEvent[$v['id']] ?? '',//已完成日程
  370. 'follow_up' => $followUp[$v['id']] ?? '',//跟进
  371. ];
  372. }
  373. if(!$insertAll){
  374. return '数据为空';
  375. }
  376. if ($workreportModel->allowField(true)->isUpdate(false)->saveAll($insertAll) == false) {
  377. return '保存失败';
  378. }
  379. $list = $workreportModel->where([ 'report_date' => $time, 'type' => $type])->select();
  380. foreach ($list as $v) {
  381. if ($type == '日') {
  382. $content = $time . '个人日报已经生成';
  383. } elseif ($type == '周') {
  384. $content = $time . '上周周报已经生成';
  385. } elseif ($type == '月') {
  386. $content = $time . '上月月报已经生成';
  387. } elseif ($type == '季') {
  388. $content = $time . '上季季报已经生成';
  389. } elseif ($type == '年') {
  390. $content = $time . '上年年报已经生成';
  391. }
  392. Message::addMessage(Message::WORKREPORT_TYPE, $v['id'], $v['staff_id'], 0, $content, 7);
  393. }
  394. return '成功';
  395. }
  396. //查询快递
  397. public function getCompanys()
  398. {
  399. $logistics = WorkorderLogistics::where(['status' => 0])->select();
  400. $juheExpress = new JuheExpress();
  401. $workorderLogistics = new WorkorderLogistics();
  402. foreach ($logistics as $v) {
  403. $result = $juheExpress->getResult('sf', $v['number'],'7836');
  404. if(empty($result)){
  405. continue;
  406. }
  407. $list = $result['list'];
  408. $data = [];
  409. foreach ($list as $ves) {
  410. $data[] = ['text' => $ves['datetime'], 'desc' => $ves['remark']];
  411. }
  412. $lastList = $data[count($data) - 1];
  413. $workorderLogistics->where(['id' => $v['id']])->update([
  414. 'content' => json_encode($data),
  415. 'current_status' => json_encode($lastList),
  416. 'status' => $result['status'],
  417. ]);
  418. }
  419. return 'success';
  420. }
  421. //生成列表
  422. private function setStaffList($list)
  423. {
  424. $list = collection($list)->toArray();
  425. $data = [];
  426. foreach ($list as $v) {
  427. $staff_id = $v['create_staff_id'] ?? $v['staff_id'] ?? $v['owner_staff_id'];
  428. $data[$staff_id] = json_encode($v);
  429. }
  430. return $data;
  431. }
  432. // 销售消息提醒
  433. public function staffCusTypeRemain(){
  434. $typeList = CustomerType::where(['cus_status'=>1])->column('days_cus','name');
  435. if(!$typeList){
  436. echo '未开启提醒';exit;
  437. }
  438. foreach($typeList as $k=>$v){
  439. $date = date("Y-m-d",strtotime("-$v days"));
  440. $this->typeStaffMessage($k,$date,$v);
  441. }
  442. $this->leaderCusTypeRemain();
  443. echo "over";
  444. }
  445. // 领导消息提醒
  446. public function leaderCusTypeRemain(){
  447. $typeList = CustomerType::where(['pid_status'=>1])->column('(days_pid+days_cus)','name');
  448. if(!$typeList){
  449. echo '未开启提醒';exit;
  450. }
  451. $staffTeam = StaffTeamList::where([])->column('team_id','staff_id');// 员工团队表
  452. $teamInfo = StaffTeam::where([])->column('staff_id','id');// 团队详情
  453. foreach($typeList as $k=>$v){
  454. $date = date("Y-m-d",strtotime("-$v days"));
  455. $this->typeLeaderMessage($k,$date,$v,$staffTeam,$teamInfo);
  456. }
  457. echo "over";
  458. }
  459. // 消息提醒
  460. public function typeStaffMessage($k,$date,$days){
  461. $customerModel = new Customer();
  462. $list = collection($customerModel->where(['contract_status'=>0,'type'=>$k,'claimdate'=>$date])->select())->toArray();
  463. if(!$list) return true;
  464. foreach ($list as $key=>$v){
  465. $content = $k.'类客户['.$v['name'].']已领用'.$days.'天,但仍未成交';
  466. Message::addMessage(Message::CUSTOMER_NODEAL, $v['id'], $v['owner_staff_id'], 0, $content, 10);
  467. }
  468. }
  469. // 消息提醒给领导
  470. public function typeLeaderMessage($k, $date, $days, $staffTeam, $teamInfo){
  471. $customerModel = new Customer();
  472. $list = collection($customerModel->with('ownerStaff')->where(['contract_status'=>0,'type'=>$k,'claimdate'=>$date])->select())->toArray();
  473. if(!$list) return true;
  474. foreach ($list as $key=>$v){
  475. $hasMessage = Message::where(['relation_type'=>Message::CUSTOMER_TYPE_MESSAGE,'relation_id'=>$v['id'],'from_staff_id'=>$v['owner_staff_id']])->find();
  476. if($hasMessage){
  477. continue;
  478. }
  479. $content = '['.$v['owner_staff']['name'].']下'.$k.'类客户['.$v['name'].']已领用'.$days.'天,但仍未成交';
  480. $toMessageId = $teamInfo[$staffTeam[$v['owner_staff_id']]];
  481. Message::addMessage(Message::CUSTOMER_NODEAL, $v['id'], $toMessageId, 0, $content, 10);
  482. }
  483. }
  484. //回访工单提醒
  485. public function visitWorkorderMessage()
  486. {
  487. $workorders = Workorder::where(['status' => 3,
  488. 'is_visit' => 0,
  489. 'workorder_type' => ['in', Workorder::getVisitType()],
  490. 'end_time' => ['lt', time()-86400*3]])->select();
  491. foreach ($workorders as $v) {
  492. $content = "工单[{$v['title']}]完成3天后未回访客户,请及时跟进!";
  493. Message::addMessage(Message::WORKORDER_TYPE, $v['id'], $v['create_staff_id'], 0, $content, 10);
  494. Message::addMessage(Message::WORKORDER_TYPE, $v['id'], $v['owner_staff_id'], 0, $content, 10);
  495. }
  496. return 'success';
  497. }
  498. //解析客户地址
  499. public function customerAddress(){
  500. $customer=Customer::where('lng','null')->where(['address'=>['neq',''],'address_detail'=>['neq','']])->field('id,address,address_detail')->select();
  501. foreach ($customer as $v){
  502. $address=$v['address'].$v['address_detail'];
  503. if(empty($address)){
  504. continue;
  505. }
  506. $url="https://apis.map.qq.com/ws/geocoder/v1/?address={$address}&key=";
  507. $result=file_get_contents($url);
  508. $result=json_decode($result,true);
  509. if(empty($result)){
  510. continue;
  511. }
  512. if($result['status'] == 0){
  513. $lng=$result['result']['location']['lng'];
  514. $lat=$result['result']['location']['lat'];
  515. }else{
  516. $lng=1;
  517. $lat=1;
  518. }
  519. Customer::where(['id'=>$v['id']])->update(['lng'=>$lng,'lat'=>$lat]);
  520. }
  521. return 'success';
  522. }
  523. // 邮箱定时 pop 服务器直接请求
  524. public function autogetemails()
  525. {
  526. set_time_limit(0);
  527. $where['email'] = [['not null',''],['neq',''],'and'];
  528. $where['email_code'] = [['not null',''],['neq',''],'and'];
  529. $where['status'] = 1;
  530. $list = \addons\qingdongams\model\Staff::where($where)->field('id,email,email_code,name')->select();
  531. if (count($list) < 1) {
  532. return '失败';
  533. }
  534. $list = collection($list)->toArray();
  535. $emailModel = new \addons\qingdongams\model\ReceiveEmail();
  536. $genjinModel = new StaffSignIn();
  537. foreach ($list as $K => $v) {
  538. $addList = $genjinList = [];
  539. $obj = new ReceiveMail($v['email'], $v['email_code'], $v['email'], $this->mailServer, $this->serverType, $this->port, false);
  540. //Connect to the Mail Box
  541. $res = $obj->connect();
  542. if (!$res) {
  543. echo "Error: Connecting to mail server";
  544. continue;
  545. }
  546. // Get Total Number of Unread Email in mail box
  547. $tot = $obj->getTotalMails(); //Total Mails in Inbox Return integer value
  548. echo $tot . '封邮件';
  549. if ($tot < 1) { //如果信件数为0,显示信息
  550. echo "No Message for " . $v['email'];
  551. continue;
  552. } else {
  553. Db::startTrans();
  554. try {
  555. $customerId = '';// 客户id
  556. for ($i = $tot; $i > 0; $i--) {
  557. $head = $obj->getHeaders($i); // Get Header Info Return Array Of Headers **Array Keys are (subject,to,toOth,toNameOth,from,fromName)
  558. Log::write($v['name'] . $i . '头部内容'.json_encode($head));
  559. if(!$head) continue;
  560. if ($emailModel->where(['uuid' => $head['udate']])->find()) {
  561. Log::write($v['name'] . '邮箱:' . $v['email'] . $head['udate'] . '已存储');
  562. continue;
  563. }
  564. $detail = [
  565. 'uuid' => $head['udate'],
  566. 'staff_id' => $v['id'],
  567. 'staff_name' => $v['name'],
  568. 'from_account' => $head['fromBy'],
  569. 'from_name' => $head['fromName'],
  570. 'receivetime' => $head['mailDate'],
  571. 'theme' => $head['subject'],
  572. ];
  573. $customerId = \addons\qingdongams\model\Contacts::where(['email' => $head['fromBy']])->value('customer_id');
  574. //处理邮件附件
  575. $files = $obj->GetAttach($i, $this->savePath); // 获取邮件附件,返回的邮件附件信息数组
  576. Log::write($v['name'] . $i . '附件:----' . json_encode($files));
  577. $imageList = $attachIds = $imgIds = array();
  578. if ($files) {
  579. foreach ($files as $k => $file) {
  580. //type=1为附件,0为邮件内容图片
  581. if ($file['type'] == 0) {
  582. $imageList[$file['title']] = $file['pathname'];
  583. }
  584. //附件列表
  585. $file_path = str_replace('public', '', $file['pathname']);
  586. $attach = [
  587. 'types' => 'file',
  588. 'name' => $file['title'],
  589. 'save_name' => $file['pathname'],
  590. 'size' => is_numeric($file['size']) ? $file['size'] : 0,
  591. 'file_path' => $file_path,
  592. 'file_path_thumb' => '',
  593. 'create_staff_id' => $v['id'],
  594. 'createtime' => time(),
  595. 'updatetime' => time(),
  596. ];
  597. if (in_array($file['extension'], $this->formater)) {
  598. $attach['types'] = 'image';
  599. }
  600. if (!$file = \addons\qingdongams\model\File::create($attach)) {
  601. // Log::write(\addons\qingdongams\model\File::getError().'----'.\addons\qingdongams\model\File::getLastSql());
  602. throw new Exception(\addons\qingdongams\model\File::getError() . '----' . \addons\qingdongams\model\File::getLastSql());
  603. }
  604. if($attach['types'] == 'image'){
  605. $imgIds[] = $file->id;
  606. }else{
  607. $attachIds[] = $file->id;
  608. }
  609. }
  610. }
  611. $detail['imgs'] = implode(',', $imgIds);
  612. $detail['attach'] = implode(',', $attachIds);
  613. $genjin = [
  614. 'staff_id' => $v['id'],
  615. 'location' => '',
  616. 'lng' => '',
  617. 'lat' => '',
  618. 'files' => $detail['attach'],
  619. 'customer_id' => $customerId,//客户id
  620. 'relation_type' => StaffSignIn::CUSTOMER_TYPE,//日程类型 客户
  621. 'relation_id' => $customerId,//签到关联发送邮件id
  622. 'relation_process' => '邮箱回复',//进度
  623. 'content' => $head['subject'],
  624. 'distance' => '',
  625. ];
  626. $body = $obj->getBody($i, $this->webPath, $imageList);
  627. $detail['content'] = $body;
  628. $addList[] = $detail;
  629. $genjinList[] = $genjin;
  630. Log::write($v['name'] . $i . '内容:----' . $body);
  631. }
  632. $res = $emailModel->saveAll($addList);
  633. $res1 = $genjinModel->saveAll($genjinList);
  634. if ($res === false) {
  635. Log::write($v['name'] . $i . '存储失败:----' . $emailModel->getError().'===='. $emailModel->getLastSql());
  636. throw new Exception($emailModel->getError() . '----' . $emailModel->getLastSql());
  637. }
  638. Db::commit();
  639. $content = '您有新邮件,请注意查收!';
  640. Message::addMessage(Message::CUSTOMER_TYPE, $customerId, $v['id'], 0, $content, 8);
  641. } catch (Exception $e) {
  642. Log::write('错误信息:' . $e->getMessage());
  643. Db::rollback();
  644. }
  645. }
  646. $obj->close_mailbox(); //Close Mail Box
  647. }
  648. echo 'over';
  649. }
  650. // 邮箱定时 api接口形式
  651. public function getEmailList()
  652. {
  653. $domain = 'qdsd.vip';
  654. $product = 'qdsd_hzqiye_ntesmail_com';
  655. $accounts = 'admin';
  656. $params = ['fids' => [1], 'order' => 'receivedDate', 'desc' => true, 'start' => 0, 'limit' => 100, 'returnTotal' => true];
  657. $time = date(time()) . '000';
  658. $res = openssl_pkey_get_private($this->prikey);
  659. $src = "account_name=" . $accounts . "&domain=" . $domain . "&params=" . json_encode($params) . "&product=" . $product . "&time=" . $time;
  660. if (openssl_sign($src, $out, $res)) {
  661. $sign = bin2hex($out);
  662. $url = "http://apihz.qiye.163.com/qiyeservice/api/mailbox/listMessages";
  663. $pram = $src . "&sign=" . $sign;
  664. echo $url . "?" . $pram . "<br>";
  665. $ch = curl_init();
  666. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  667. curl_setopt($ch, CURLOPT_URL, $url);
  668. curl_setopt($ch, CURLOPT_POST, 1);
  669. curl_setopt($ch, CURLOPT_POSTFIELDS, $pram);
  670. $data = curl_exec($ch);
  671. curl_close($ch);
  672. $res = json_decode($data, true);
  673. dump($res);
  674. }
  675. }
  676. // 邮箱定时 api接口形式 开始时间到结束时间
  677. public function getEmails()
  678. {
  679. $domain = 'qdsd.vip';
  680. $product = 'qdsd_hzqiye_ntesmail_com';
  681. $accounts = 'admin';
  682. $start = date("Y-m-d", '-30day');
  683. $end = date("Y-m-d H:i:s");
  684. $page_num = "1";
  685. $page_size = "10";
  686. $time = date(time()) . '000';
  687. $res = openssl_pkey_get_private($this->prikey);
  688. // $src = "accounts=" . $accounts . "&domain=" . $domain . "&end=" . $end . "&page_num=" . $page_num . "&page_size=" . $page_size . "&product=" . $product . "&start=" . $start . "&time=" . $time;
  689. $src = "accounts=" . $accounts . "&domain=" . $domain . "&end=" . $end . "&page_num=" . $page_num . "&page_size=" . $page_size . "&product=" . $product . "&start=" . $start . "&time=" . $time;
  690. if (openssl_sign($src, $out, $res)) {
  691. $sign = bin2hex($out);
  692. $url = "http://apihz.qiye.163.com/qiyeservice/api/mail/getReceivedMailLogs";
  693. $pram = $src . "&sign=" . $sign;
  694. echo $url . "?" . $pram . "<br>";
  695. $ch = curl_init();
  696. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  697. curl_setopt($ch, CURLOPT_URL, $url);
  698. curl_setopt($ch, CURLOPT_POST, 1);
  699. curl_setopt($ch, CURLOPT_POSTFIELDS, $pram);
  700. $data = curl_exec($ch);
  701. curl_close($ch);
  702. $res = json_decode($data, true);
  703. dump($res);
  704. }
  705. }
  706. /**
  707. * 打卡定时任务
  708. */
  709. public function attendance()
  710. {
  711. $w = date('w');
  712. $date = [
  713. 1 => 'monday',
  714. 2 => 'tuesday',
  715. 3 => 'wednesday',
  716. 4 => 'thursday',
  717. 5 => 'friday',
  718. 6 => 'saturday',
  719. 0 => 'weekday',
  720. ];
  721. $weekname = $date[$w];
  722. $times = AttendanceTime::where([$weekname => 1])->select();
  723. if (empty($times)) {
  724. return '未设置规则';
  725. }
  726. $row = AttendanceStatisc::where(['time' => date('Y-m-d')])->find();
  727. if (!empty($row)) {
  728. return '规则已生成';
  729. }
  730. $times = collection($times)->toArray();
  731. $rule = AttendanceRule::where([])->find();
  732. $statiscs = AttendanceStatisc::where(['time' => date('Y-m-d', strtotime('-1 day'))])->select();
  733. foreach ($statiscs as $v) {
  734. $update = [];
  735. if (empty($t['clock_in']) && !empty($t['clock_out'])) {//缺卡
  736. $update['clock_in_status'] = 1;
  737. }
  738. if (empty($t['clock_out']) && !empty($t['clock_in'])) {//缺卡
  739. $update['clock_out_status'] = 1;
  740. }
  741. if (empty($t['clock_in']) && empty($t['clock_out'])) {//旷工
  742. $update['clock_in_status'] = 2;
  743. $update['clock_out_status'] = 2;
  744. }
  745. if ($update) {
  746. $statiscModel = new AttendanceStatisc();
  747. $statiscModel->save($update, ['id' => $v['id']]);
  748. }
  749. }
  750. $staff_ids = explode(',', $rule['staff_id']);
  751. $statisc = [];
  752. foreach ($staff_ids as $sid) {
  753. foreach ($times as $t) {
  754. $statisc[] = [
  755. 'staff_id' => $sid,
  756. 'number' => $t['number'],
  757. 'time' => date('Y-m-d'),
  758. 'start_time' => $t['start_time'],
  759. 'end_time' => $t['end_time'],
  760. 'ustart_time' => $t['ustart_time'],
  761. 'uend_time' => $t['uend_time'],
  762. 'dstart_time' => $t['dstart_time'],
  763. 'dend_time' => $t['dend_time'],
  764. 'start_status' => $t['start_status'],
  765. 'end_status' => $t['end_status'],
  766. ];
  767. }
  768. }
  769. $statiscModel = new AttendanceStatisc();
  770. $result = $statiscModel->allowField(true)->saveAll($statisc);
  771. if (empty($result)) {
  772. return '生成规则失败';
  773. }
  774. return '生成规则成功';
  775. }
  776. }