Workorder.php 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798
  1. <?php
  2. namespace addons\qingdongams\model;
  3. use app\admin\model\Admin;
  4. use think\Db;
  5. use think\Exception;
  6. use think\Model;
  7. use traits\model\SoftDelete;
  8. /**
  9. *工单表
  10. */
  11. class Workorder extends Model
  12. {
  13. use SoftDelete;
  14. protected $name = 'qingdongams_workorder';
  15. // 开启自动写入时间戳字段
  16. protected $autoWriteTimestamp = 'int';
  17. // 定义时间戳字段名
  18. protected $createTime = 'createtime';
  19. protected $updateTime = 'updatetime';
  20. protected $deleteTime = 'deletetime';
  21. // 追加属性
  22. protected $append = [
  23. 'show_staff_data',
  24. ];
  25. public function getCreatetimeAttr($value)
  26. {
  27. return date('Y-m-d H:i', $value);
  28. }
  29. public function getPayTimeAttr($value)
  30. {
  31. return $value ? date('Y-m-d H:i', $value) : '';
  32. }
  33. public function getAccepttimeAttr($value)
  34. {
  35. if (empty($value)) {
  36. return $value;
  37. }
  38. return date('Y-m-d H:i', $value);
  39. }
  40. public function getTrainContentAttr($value)
  41. {
  42. if (empty($value)) {
  43. return [];
  44. }
  45. $value = json_decode($value, true);
  46. if (empty($value)) {
  47. return [];
  48. }
  49. foreach ($value as $k => $v) {
  50. if (empty($v['content'])) {
  51. // continue;
  52. }
  53. foreach ($v['content'] as $kc => $vc) {
  54. if (empty($vc['autograph_url'])) {
  55. continue;
  56. }
  57. $autograph_url = explode(',', $vc['autograph_url']);
  58. $autograph = [];
  59. foreach ($autograph_url as $url) {
  60. $autograph[] = ['id' => $vc['autograph_url'], 'url' => cdnurl(File::getUrl($url), true)];
  61. }
  62. $vc['autograph'] = $autograph;
  63. $v['content'][$kc] = $vc;
  64. }
  65. $value[$k] = $v;
  66. }
  67. return $value;
  68. }
  69. //
  70. public function getPayServiceAttr($value)
  71. {
  72. if (empty($value)) {
  73. return [];
  74. }
  75. return json_decode($value, true);
  76. }
  77. //预计完成时间 expected_end_time
  78. public function getExpectedEndTimeAttr($value)
  79. {
  80. if (empty($value)) {
  81. return $value;
  82. }
  83. return date('Y-m-d H:i', $value);
  84. }
  85. public function getStarttimeAttr($value)
  86. {
  87. if (empty($value)) {
  88. return $value;
  89. }
  90. return date('Y-m-d H:i', $value);
  91. }
  92. public function getEndtimeAttr($value)
  93. {
  94. if (empty($value)) {
  95. return $value;
  96. }
  97. return date('Y-m-d H:i', $value);
  98. }
  99. public function getProductPartAttr($value)
  100. {
  101. $value = json_decode($value, true);
  102. if (empty($value)) {
  103. return [];
  104. }
  105. $data = [];
  106. foreach ($value as $v) {
  107. $cp = CustomerProduct::where(['id' => ['in', $v['customer_product_id']]])->with(['product'])->find();
  108. if (empty($cp)) {
  109. continue;
  110. }
  111. $parts_id = explode(',', $v['parts_id'] ?? '');
  112. if ($cp['product_id']) {
  113. $parts = Parts::where('', 'exp', Db::raw('FIND_IN_SET(' . $cp['product_id'] . ',product_id)'))->select();
  114. $parts = collection($parts)->toArray();
  115. } else {
  116. $parts = [];
  117. }
  118. foreach ($parts as $k => $p) {
  119. $p['is_select'] = in_array($p['id'], $parts_id) ? 1 : 0;
  120. $parts[$k] = $p;
  121. }
  122. $cp['parts'] = $parts;
  123. $data[] = $cp;
  124. }
  125. return $data;
  126. }
  127. public function getShowStaffDataAttr($value, $data)
  128. {
  129. if (!isset($data['show_staff_id'])) {
  130. return '';
  131. }
  132. $ids = explode(',', $data['show_staff_id']);
  133. return Staff::where(['id' => ['in', $ids]])->field('id,name,img,post,mobile')->select();
  134. }
  135. public function getPartsAttr($value)
  136. {
  137. if (empty($value)) {
  138. return [];
  139. }
  140. $value = json_decode($value, true);
  141. $data = [];
  142. foreach ($value as $v) {
  143. $p = Parts::where(['id' => $v['id']])->field('id,name,num,img,unit,price')->find();
  144. $p['number'] = isset($v['number']) ? $v['number'] : $v['num'];
  145. $data[] = $p;
  146. }
  147. return $data;
  148. }
  149. //已使用零件
  150. public function getUsePartsAttr($value)
  151. {
  152. if (empty($value)) {
  153. return [];
  154. }
  155. $value = json_decode($value, true);
  156. $data = [];
  157. foreach ($value as $v) {
  158. $p = Parts::where(['id' => $v['id']])->field('id,name,num,img,unit,price')->find();
  159. $p['number'] = isset($v['number']) ? $v['number'] : $v['num'];
  160. $p['is_charge'] = $v['is_charge'] ?? 1;
  161. $data[] = $p;
  162. }
  163. return $data;
  164. }
  165. //剩余零件
  166. public function getSurplusPartsAttr($value)
  167. {
  168. if (empty($value)) {
  169. return $value;
  170. }
  171. $value = json_decode($value, true);
  172. $data = [];
  173. foreach ($value as $v) {
  174. $p = Parts::where(['id' => $v['id']])->field('id,name,num,img,unit,price')->find();
  175. $p['number'] = isset($v['number']) ? $v['number'] : $v['num'];
  176. $data[] = $p;
  177. }
  178. return $data;
  179. }
  180. //获取评价附件
  181. public function getCommentFilesAttr($value)
  182. {
  183. $files = explode(',', $value);
  184. $result = [];
  185. foreach ($files as $fid) {
  186. if ($fid) {
  187. $result[] = cdnurl(File::getUrl($fid), true);
  188. }
  189. }
  190. return $result;
  191. }
  192. //回执附件 receipt_file_ids
  193. public function getReceiptFileIdsAttr($value)
  194. {
  195. if (empty($value)) {
  196. return $value;
  197. }
  198. $files = explode(',', $value);
  199. $result = [];
  200. foreach ($files as $fid) {
  201. if ($fid) {
  202. $result[] = cdnurl(File::getUrl($fid), true);
  203. }
  204. }
  205. return $result;
  206. }
  207. public function getProductAttr($value)
  208. {
  209. if (empty($value)) {
  210. return '';
  211. }
  212. $value = json_decode($value, true);
  213. if (empty($value)) {
  214. return '';
  215. }
  216. $data = [];
  217. foreach ($value as $v) {
  218. if (!isset($v['product_id'])) {
  219. continue;
  220. }
  221. $p = Product::where(['id' => $v['product_id']])->field('id,name,num,img,type_id')->find();
  222. $p['product_id'] = $p['id'] ?? 0;
  223. $p['number'] = $v['number'] ?? 0;
  224. $p['end_date'] = $v['end_date'] ?? '';
  225. $p['desc'] = $v['desc'] ?? '';
  226. $data[] = $p;
  227. }
  228. return $data;
  229. }
  230. //获取回款图片
  231. public function getCollectionImgAttr($value)
  232. {
  233. $files = explode(',', $value);
  234. $result = [];
  235. foreach ($files as $fid) {
  236. if ($fid) {
  237. $result[] = ['id' => $fid, 'url' => cdnurl(File::getUrl($fid), true)];
  238. }
  239. }
  240. return $result;
  241. }
  242. //获取评价附件
  243. public function getAutographUrlAttr($value)
  244. {
  245. if (empty($value)) {
  246. return '';
  247. }
  248. return cdnurl(File::getUrl($value), true);
  249. }
  250. //获取支付附件
  251. public function getPayFilesAttr($value)
  252. {
  253. $files = explode(',', $value);
  254. $result = [];
  255. foreach ($files as $fid) {
  256. if ($fid) {
  257. $result[] = cdnurl(File::getUrl($fid), true);
  258. }
  259. }
  260. return $result;
  261. }
  262. //创建人 员工
  263. public function createStaff()
  264. {
  265. return $this->hasOne(Staff::class, 'id', 'create_staff_id')->field('id,name,img,post');
  266. }
  267. //创建人 联系人
  268. public function createPerson()
  269. {
  270. return $this->hasOne(Person::class, 'id', 'person_id')->field('id,account');
  271. }
  272. //获取联系人
  273. public function contacts()
  274. {
  275. return $this->hasOne(Contacts::class, 'id', 'contacts_id')
  276. ->order('is_major desc')->field('id,customer_id,name,mobile,mobilecode,region');
  277. }
  278. //获取售后服务用户端
  279. public function person()
  280. {
  281. return $this->hasOne(Person::class, 'id', 'person_id')->field('id,nickname,account');
  282. }
  283. //获取售后服务用户端
  284. public function comments()
  285. {
  286. return $this->hasOne(Comment::class, 'relation_id', 'id')->where(['relation_type' => 'workorder'])->field('id,relation_id,content,praise');
  287. }
  288. //获取客户
  289. public function customer()
  290. {
  291. return $this->hasOne(Customer::class, 'id', 'customer_id')->field('id,name,industry,level,source,main_twesya');
  292. }
  293. //获取评分情况
  294. public function visit()
  295. {
  296. return $this->hasOne(WorkorderVisit::class, 'workorder_id', 'id');
  297. }
  298. //获取日程
  299. public function getevent()
  300. {
  301. return $this->hasOne(Event::class, 'relation_id', 'id')->where(['relation_type' => 'workorder']);
  302. }
  303. //负责人
  304. public function ownerStaff()
  305. {
  306. return $this->hasOne(Staff::class, 'id', 'owner_staff_id')->field('id,name,img,mobile,email');
  307. }
  308. //获取附件记录
  309. public function file()
  310. {
  311. return $this->hasMany(WorkorderFile::class, 'workorder_id', 'id')->with('file')->field('workorder_id,file_id');
  312. }
  313. //创建工单
  314. public static function createWorkorder($params)
  315. {
  316. if (isset($params['file_ids'])) {
  317. $files = $params['file_ids'];
  318. unset($params['file_ids']);
  319. } else {
  320. $files = '';
  321. }
  322. //自定义字段
  323. $other = [];
  324. foreach ($params as $name => $val) {
  325. if (strstr($name, 'other_') !== false) {
  326. $other[$name] = $val;
  327. unset($params[$name]);
  328. continue;
  329. }
  330. if (empty($params[$name])) {
  331. unset($params[$name]);
  332. continue;
  333. }
  334. }
  335. $staff = Staff::info();
  336. $params['dep_id'] = $params['owner_dep_id'];
  337. if (!empty($staff)) {
  338. $params['create_staff_id'] = $staff->id;
  339. }
  340. if (isset($params['start_time'])) {
  341. $params['start_time'] = strtotime($params['start_time']);
  342. }
  343. if (isset($params['end_time'])) {
  344. $params['end_time'] = strtotime($params['end_time']);
  345. }
  346. if (!isset($params['owner_staff_id']) || empty($params['owner_staff_id'])) {
  347. $params['owner_staff_id'] = $staff->id;
  348. }
  349. $parts = $params['parts'] ?? [];
  350. foreach ($parts as $pk => $pv) {
  351. $parts[$pk] = ['id' => $pv['id'], 'number' => $pv['number']];
  352. }
  353. $params['parts'] = json_encode($parts);
  354. $params['status'] = 1;
  355. if ($params['workorder_type'] == '返厂维修') {
  356. $params['process'] = 1;
  357. }
  358. if (isset($params['product']) && $params['product']) {
  359. //添加产品
  360. $product = $params['product'];
  361. if (is_array($product)) {
  362. $params['product'] = json_encode($product);
  363. }
  364. if ($params['workorder_type'] == '产品发货') {
  365. $addAll = [];
  366. foreach ($product as $v) {
  367. for ($i = 0; $i < $v['number']; $i++) {
  368. $addAll[] = [
  369. 'customer_id' => $params['customer_id'],
  370. 'product_id' => $v['product_id'],
  371. 'pay_date' => date('Y-m-d'),
  372. 'create_staff_id' => $staff->id,
  373. 'createtime' => time(),
  374. ];
  375. }
  376. }
  377. $CustomerProductModel = new CustomerProduct();
  378. $customerProductIds = [];
  379. foreach ($addAll as $ins) {
  380. $CustomerProductModel->insert($ins);
  381. $customerProductIds[] = $CustomerProductModel->getLastInsID();
  382. }
  383. $params['customer_product_id'] = implode(',', $customerProductIds);
  384. }
  385. }
  386. $params['product_part'] = $params['product_part'] ?? [];
  387. if (is_array($params['product_part'])) {
  388. $params['product_part'] = json_encode($params['product_part'] ?? []);
  389. }
  390. // 添加可查看员工id
  391. $params['show_staff_id'] = $params['owner_staff_id'] ?? '';
  392. $workorderM = new self;
  393. // 调用当前模型对应的User验证器类进行数据验证
  394. $result = $workorderM->allowField(true)->save($params);
  395. $lastId = $workorderM->getLastInsID();
  396. if (false === $result) {
  397. // 验证失败 输出错误信息
  398. throw new Exception($workorderM->getError());
  399. }
  400. $otherModel = new WorkorderOther();
  401. if ($otherModel->save(['id' => $lastId, 'other' => json_encode($other, JSON_UNESCAPED_UNICODE)]) === false) {
  402. // 验证失败 输出错误信息
  403. throw new Exception($otherModel->getError());
  404. }
  405. if ($files) {
  406. WorkorderFile::addFiles($files, $lastId);
  407. }
  408. //创建下次执行的巡检时间
  409. if (isset($params['check_up']) && $params['check_up'] == 1) {
  410. $time_data['check_up'] = $params['check_up'];
  411. $time_data['time_up'] = $params['time_up'];
  412. // $time_data['m']=$params['m'];
  413. // $time_data['d']=$params['d'];
  414. // $time_data['h']=$params['h'];
  415. // $time_data['i']=$params['i'];
  416. // $time_data['week']=$params['week'];
  417. // $w_time=WorkorderInspection::getTime($time_data);
  418. $w_time = strtotime($params['jh_start_time']);
  419. $n_time = WorkorderInspection::getNextTime($w_time, $time_data);
  420. $WorkorderInspection = new WorkorderInspection();
  421. if ($WorkorderInspection->save([
  422. 'type' => $params['time_up'],
  423. 'work_id' => $lastId,
  424. 'executetime' => $w_time,
  425. 'next_executetime' => $n_time,
  426. 'createtime' => time(),
  427. 'updatetime' => time()
  428. ]) === false) {
  429. throw new Exception($WorkorderInspection->getError());
  430. }
  431. }
  432. //操作记录
  433. OperationLog::createLog(OperationLog::WORKORDER_TYPE, $lastId, '创建工单');
  434. $content = '创建工单';
  435. $paramsSign['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  436. $paramsSign['relation_id'] = $lastId;
  437. $paramsSign['files'] = $files ?? '';
  438. $paramsSign['relation_process'] = '创建工单';
  439. //创建跟进记录
  440. if (isset($params['customer_id']) && $params['customer_id']) {
  441. StaffSignIn::quickSignIn($params['customer_id'], $content, $paramsSign);
  442. }
  443. // 发送通知-工单派单提醒
  444. $noticeParams = [
  445. 'event' => 'dispatch_order',
  446. 'params' => array (
  447. 'receiver_admin_ids' => $staff->admin_id,
  448. 'receiver_admin_group_ids' => '',
  449. 'orderno' => $params['workorder_number'],
  450. 'title' => $params['title'],
  451. 'type' => $params['workorder_type'],
  452. 'order_id' => $lastId,
  453. )];
  454. \Think\Hook::listen('send_notice', $noticeParams);
  455. return $lastId;
  456. }
  457. public static function inspection()
  458. {
  459. // //查询所以的巡检计划
  460. $workorderM = new self;
  461. $WorkorderInspection = new WorkorderInspection();
  462. $w_time = time() + 3600 * 24 * config('site.order_tq_time');
  463. $list = WorkorderInspection::where(array('status' => 0))->field("id,type,work_id,executetime,next_executetime,status")->select();
  464. foreach ($list as $key => $val) {
  465. //判断当前时间是否可以创建巡检订单
  466. if ($w_time > $val['executetime']) {
  467. //执行创建新的巡检工单
  468. $info = $workorderM->where(array('id' => $val['work_id']))->find()->toArray();
  469. unset($info['id']);
  470. unset($info['show_staff_data']);
  471. $info['title'] = $info['title'] . "[巡检计划]";
  472. $info['createtime'] = time();
  473. $info['start_time'] = $w_time;
  474. $info['end_time'] = config('site.xjjh_time') * 3600 + time();
  475. $status = $workorderM->save($info);
  476. if ($status) {
  477. //更新执行状态创建下一次执行
  478. if ($WorkorderInspection->where(array('id' => $val['id']))->update(['status' => 1]) && $val['next_executetime']) {
  479. $time_data['check_up'] = $info['check_up'];
  480. $time_data['time_up'] = $info['time_up'];
  481. // $time_data['m']=$info['m'];
  482. // $time_data['d']=$info['d'];
  483. // $time_data['h']=$info['h'];
  484. // $time_data['i']=$info['i'];
  485. // $time_data['week']=$info['week'];
  486. $n_time = WorkorderInspection::getNextTime($val['next_executetime'], $time_data);
  487. $WorkorderInspection->save([
  488. 'type' => $info['time_up'],
  489. 'work_id' => $val['work_id'],
  490. 'executetime' => $val['next_executetime'],
  491. 'next_executetime' => $n_time,
  492. 'createtime' => time(),
  493. 'updatetime' => time()
  494. ]);
  495. }
  496. }
  497. }
  498. }
  499. }
  500. public static function wanderorder()
  501. {
  502. //指定员工
  503. $where['status'] = 1; //没有处理
  504. $workorderM = new self;
  505. $infoList = $workorderM->where($where)->order("id desc")->field("id,owner_staff_id,is_notice,create_staff_id,workorder_number,title,createtime,workorder_type,dep_id,updatetime")->select();
  506. $time = time();
  507. $allout_time = 0;
  508. $all_num = 0;
  509. foreach ($infoList as $info) {
  510. $yglist = Staff::getYkList($info['dep_id']);
  511. $all_num = count($yglist);
  512. $cs_time = $info['updatetime'] + config('site.csorder') * 60;
  513. $allout_time = strtotime($info['createtime']) + config('site.csorder') * 60 * $all_num;
  514. if ($time > $allout_time && $info['is_notice'] == 0) {
  515. //查询部门总人数 ,人数乘以每单的超时时间得出总的超时时间,如果总的超时时间过点,仍然没有进行派单处理。则通知管理员
  516. $noticeParams = [
  517. 'event' => 'timeout_order',
  518. 'params' => array(
  519. 'receiver_admin_ids' => '',
  520. 'receiver_admin_group_ids' => '6',
  521. 'order_id' => $info['id'],
  522. 'orderno' => $info['workorder_number'],
  523. 'title' => $info['title'],
  524. 'type' => $info['workorder_type'],
  525. )];
  526. \Think\Hook::listen('send_notice', $noticeParams);
  527. self::where(['id' => $info['id']])->update(['is_notice' => 1]);
  528. }
  529. if ($time > $cs_time) {
  530. //更换员工
  531. foreach ($yglist as $key => $val) {
  532. if ($val['id'] == $info['owner_staff_id']) {
  533. //分配下一个员工
  534. if (isset($yglist[$key + 1]['id'])) {
  535. $owner_staff_id = $yglist[$key + 1]['id'];
  536. } else {
  537. $owner_staff_id = $yglist[0]['id'];
  538. }
  539. }
  540. }
  541. // 查找对应员工的admin账号id,发送对应消息
  542. $staff = Staff::where(['id' => $owner_staff_id])->find();
  543. // 发送通知-工单派单提醒
  544. $noticeParams = [
  545. 'event' => 'dispatch_order',
  546. 'params' => array (
  547. 'receiver_admin_ids' => $staff->admin_id,
  548. 'receiver_admin_group_ids' => '',
  549. 'orderno' => $info['workorder_number'],
  550. 'title' => $info['title'],
  551. 'type' => $info['workorder_type'],
  552. 'order_id' => $info['id'],
  553. )];
  554. \Think\Hook::listen('send_notice', $noticeParams);
  555. $update['owner_staff_id'] = $owner_staff_id;
  556. $update['updatetime'] = time();
  557. self::where(['id' => $info['id']])->update($update);
  558. echo "ok";
  559. } else {
  560. echo "no time order";
  561. }
  562. }
  563. }
  564. //创建工单
  565. public static function createCustomerWorkorder($params)
  566. {
  567. if (isset($params['file_ids'])) {
  568. $files = $params['file_ids'];
  569. unset($params['file_ids']);
  570. } else {
  571. $files = '';
  572. }
  573. //自定义字段
  574. $other = [];
  575. foreach ($params as $name => $val) {
  576. if (strstr($name, 'other_') !== false) {
  577. $other[$name] = $val;
  578. unset($params[$name]);
  579. }
  580. }
  581. if (isset($params['start_time'])) {
  582. $params['start_time'] = strtotime($params['start_time']);
  583. }
  584. if (isset($params['end_time'])) {
  585. $params['end_time'] = strtotime($params['end_time']);
  586. }
  587. $parts = $params['parts'] ?? [];
  588. foreach ($parts as $pk => $pv) {
  589. $parts[$pk] = ['id' => $pv['id'], 'number' => $pv['number']];
  590. }
  591. $params['parts'] = json_encode($parts);
  592. $params['status'] = 1;
  593. if ($params['customer_product_id']) {
  594. $customer_product_ids = explode(',', $params['customer_product_id']);
  595. $product_part = [];
  596. foreach ($customer_product_ids as $ids) {
  597. $product_part[] = ['customer_product_id' => $ids, 'parts_id' => ''];
  598. }
  599. $params['product_part'] = $product_part;
  600. }
  601. $params['product_part'] = json_encode($params['product_part'] ?? []);
  602. // //指定员工
  603. // $yglist =Staff::getYkList();
  604. $workorderM = new self;
  605. // //查询最后一条分配的员工
  606. // $worker_yg_id = $workorderM->order("id desc")->value("owner_staff_id");
  607. // // dump($worker_yg_id);
  608. // //如果指定了管理员
  609. // if($worker_yg_id==1){
  610. // $owner_staff_id=$yglist[0]['id'];
  611. // }else{
  612. // $owner_staff_id=0;
  613. // }
  614. // foreach($yglist as $key=>$val){
  615. // if($val['id']==$worker_yg_id){
  616. // //分配下一个员工
  617. // if(isset($yglist[$key+1]['id'])){
  618. // $owner_staff_id=$yglist[$key+1]['id'];
  619. // }else{
  620. // $owner_staff_id=$yglist[0]['id'];
  621. // }
  622. // }
  623. // }
  624. // dump($owner_staff_id);die;
  625. // 根据上传的用户id查询所属员工
  626. $customer = Customer::where(['id' => $params['customer_id']])->find();
  627. if ($customer) {
  628. $params['create_staff_id'] = $customer['create_staff_id'];
  629. $params['owner_staff_id'] = $customer['owner_staff_id'];
  630. }
  631. // $params['create_staff_id'] = 1;
  632. // $params['owner_staff_id'] = $owner_staff_id;
  633. // 调用当前模型对应的User验证器类进行数据验证
  634. $result = $workorderM->allowField(true)->save($params);
  635. $lastId = $workorderM->getLastInsID();
  636. if (false === $result) {
  637. // 验证失败 输出错误信息
  638. throw new Exception($workorderM->getError());
  639. }
  640. $otherModel = new WorkorderOther();
  641. if ($otherModel->save(['id' => $lastId, 'other' => json_encode($other, JSON_UNESCAPED_UNICODE)]) === false) {
  642. // 验证失败 输出错误信息
  643. throw new Exception($otherModel->getError());
  644. }
  645. if ($files) {
  646. WorkorderFile::addFiles($files, $lastId);
  647. }
  648. //TODO
  649. $content = '客户提交了维修工单《' . $params['title'] . '》,请尽快处理!';
  650. // Message::batchMessage(Message::WORKORDER_TYPE, $lastId, $params['show_staff_id'],0, $content, 12);
  651. return $lastId;
  652. }
  653. //接受工单
  654. public static function acceptWorkorder($params)
  655. {
  656. $update = [
  657. 'status' => 2,
  658. 'process' => 0,
  659. 'accept_time' => time()
  660. ];
  661. if (isset($params['expected_end_time']) && $params['expected_end_time']) {
  662. $update['expected_end_time'] = strtotime($params['expected_end_time']);
  663. }
  664. if (self::where(['id' => $params['id'], 'status' => 1])->update($update) == false) {
  665. // 验证失败 输出错误信息
  666. throw new Exception('更新工单状态失败');
  667. }
  668. $staff = Staff::info();
  669. $row = self::get($params['id']);
  670. $content = '接受了工单';
  671. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  672. $params['relation_id'] = $row['id'];
  673. $params['relation_process'] = '接受工单';
  674. //创建跟进记录
  675. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  676. return true;
  677. }
  678. //开始工单
  679. public static function startWorkorder($params)
  680. {
  681. $update = [
  682. 'process' => 1,
  683. 'start_time' => time(),
  684. ];
  685. if (isset($params['car_type']) && $params['car_type']) {
  686. $update['car_type'] = $params['car_type'];
  687. $update['car_number'] = $params['car_number'] ?? '';
  688. }
  689. if (isset($params['start_mileage']) && $params['start_mileage']) {
  690. $update['start_mileage'] = intval($params['start_mileage']);
  691. }
  692. if (self::where(['id' => $params['id'], 'status' => 2])->update($update) == false) {
  693. // 验证失败 输出错误信息
  694. throw new Exception('更新工单状态失败');
  695. }
  696. //日程开始
  697. Event::where(['relation_type' => 'workorder', 'relation_id' => $params['id']])
  698. ->update(['status' => 1]);
  699. $row = self::get($params['id']);
  700. $content = '开始了工单<br>备注:' . $params['desc'] ?? '';
  701. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  702. $params['relation_id'] = $row['id'];
  703. $params['relation_process'] = '开始工单';
  704. //创建跟进记录
  705. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  706. return true;
  707. }
  708. //录入零件
  709. public static function inputParts($params)
  710. {
  711. $parts = $params['parts'] ?? [];
  712. $update = [];
  713. if ($parts) {
  714. $data = [];
  715. foreach ($parts as $v) {
  716. $data[] = [
  717. 'id' => $v['id'],
  718. 'number' => $v['number']
  719. ];
  720. }
  721. $update['parts'] = json_encode($data);
  722. }
  723. if (self::where(['id' => $params['id']])->update($update) == false) {
  724. // 验证失败 输出错误信息
  725. throw new Exception('更新工单状态失败');
  726. }
  727. $row = self::get($params['id']);
  728. $content = '录入携带配件信息';
  729. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  730. $params['relation_id'] = $row['id'];
  731. $params['relation_process'] = '录入配件';
  732. //创建跟进记录
  733. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  734. return true;
  735. }
  736. /**
  737. *修改工单信息
  738. */
  739. public static function updateWorkorder($params)
  740. {
  741. $row = self::get($params['id']);
  742. if (isset($params['file_ids'])) {
  743. $files = $params['file_ids'];
  744. unset($params['file_ids']);
  745. } else {
  746. $files = '';
  747. }
  748. if (isset($params['files'])) {
  749. $files = $params['files'];
  750. unset($params['files']);
  751. }
  752. //自定义字段
  753. $other = [];
  754. foreach ($params as $name => $val) {
  755. if (strstr($name, 'other_') !== false) {
  756. $other[$name] = $val;
  757. unset($params[$name]);
  758. }
  759. if (empty($val)) {
  760. unset($params[$name]);
  761. }
  762. }
  763. if (isset($params['start_time'])) {
  764. $params['start_time'] = strtotime($params['start_time']);
  765. }
  766. if (isset($params['workorder_type'])) {
  767. unset($params['workorder_type']);
  768. }
  769. if (isset($params['end_time'])) {
  770. $params['end_time'] = strtotime($params['end_time']);
  771. }
  772. if (isset($params['product']) && $params['product']) {
  773. $product = $params['product'];
  774. if (is_array($product)) {
  775. $params['product'] = json_encode($product);
  776. }
  777. if ($row->workorder_type == '产品发货') {
  778. $addAll = [];
  779. $staff = Staff::info();
  780. foreach ($product as $v) {
  781. for ($i = 0; $i < $v['number']; $i++) {
  782. $addAll[] = [
  783. 'customer_id' => $params['customer_id'],
  784. 'product_id' => $v['product_id'],
  785. 'pay_date' => date('Y-m-d'),
  786. 'create_staff_id' => $staff->id,
  787. 'createtime' => time(),
  788. ];
  789. }
  790. }
  791. $CustomerProductModel = new CustomerProduct();
  792. $customerProductIds = [];
  793. foreach ($addAll as $ins) {
  794. $CustomerProductModel->insert($ins);
  795. $customerProductIds[] = $CustomerProductModel->getLastInsID();
  796. }
  797. $CustomerProductModel
  798. ->where(['id' => ['in', explode(',', $row['customer_product_id'])]])->delete();
  799. $params['customer_product_id'] = implode(',', $customerProductIds);
  800. }
  801. }
  802. if (isset($params['appointment_time'])) {
  803. $params['appointment_time'] = $params['appointment_time'] ?: NULL;
  804. }
  805. $params['product_part'] = json_encode($params['product_part'] ?? []);
  806. if ($row->workorder_type == '返厂维修') {
  807. $params['process'] = 1;
  808. }
  809. $parts = $params['parts'] ?? [];
  810. foreach ($parts as $pk => $pv) {
  811. $parts[$pk] = ['id' => $pv['id'], 'number' => $pv['number']];
  812. }
  813. $params['parts'] = json_encode($parts);
  814. $customer = new self;
  815. // 调用当前模型对应的User验证器类进行数据验证
  816. $result = $customer->allowField(true)->isUpdate(true)->save($params, ['id' => $params['id']]);
  817. if (false === $result) {
  818. // 验证失败 输出错误信息
  819. throw new Exception($customer->getError());
  820. }
  821. //日程 修改信息
  822. if (isset($params['owner_staff_id'])) {
  823. $updateEvent = [
  824. 'title' => $params['title'],
  825. 'staff_id' => $params['owner_staff_id'],
  826. ];
  827. $eventModel = new Event();
  828. $eventModel->allowField(true)->save($updateEvent, ['relation_type' => 'workorder', 'relation_id' => $params['id']]);
  829. }
  830. $otherModel = new WorkorderOther();
  831. if ($otherModel->isUpdate(true)->save([
  832. 'id' => $params['id'],
  833. 'other' => json_encode($other, JSON_UNESCAPED_UNICODE)
  834. ]) === false) {
  835. // 验证失败 输出错误信息
  836. throw new Exception($otherModel->getError());
  837. }
  838. if ($files) {
  839. WorkorderFile::editFiles($files, $params['id']);
  840. }
  841. return true;
  842. }
  843. /**
  844. * 指派工单
  845. * @desc 备注
  846. * @update_date 2021/7/9 更新时间
  847. * @author zhangwei
  848. */
  849. public static function assignWorkorder($id, $staff_id, $desc)
  850. {
  851. $row = self::get($id);
  852. $update = [
  853. 'owner_staff_id' => $staff_id,
  854. 'status' => 1];
  855. if ($row['workorder_type'] == '返厂维修') {
  856. $update['process'] = 1;
  857. }
  858. $result = self::where(['id' => $id])->update($update);
  859. if (false === $result) {
  860. // 验证失败 输出错误信息
  861. throw new Exception('修改信息错误');
  862. }
  863. //日程 修改指派人
  864. Event::where(['relation_type' => 'workorder', 'relation_id' => $id])->update(['staff_id' => $staff_id]);
  865. $staff = Staff::info();
  866. $transferStaff = Staff::get($staff_id);
  867. $content = '将工单指派给[' . $transferStaff['name'] . ']' . '备注:' . $desc;
  868. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  869. $params['relation_id'] = $id;
  870. $params['relation_process'] = '指派工单';
  871. //创建跟进记录
  872. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  873. //发送通知
  874. Message::addMessage(Message::WORKORDER_TYPE, $id, $row->owner_staff_id, $staff->id,
  875. "任务《{$row['title']}》已被指派给其他员工,请您及时审阅!");
  876. Message::addMessage(Message::WORKORDER_TYPE, $id, $staff_id, $staff->id,
  877. $staff->name . '指派给您一项任务,请您及时审阅');
  878. return true;
  879. }
  880. /**
  881. * 转派工单
  882. * @desc 备注
  883. * @update_date 2021/7/9 更新时间
  884. * @author zhangwei
  885. */
  886. public static function transferWorkorder($id, $dep_id, $staff_id, $desc = '')
  887. {
  888. $workorder = self::get($id);
  889. $result = self::where(['id' => $id])
  890. ->update(['dep_id' => $dep_id, 'owner_staff_id' => $staff_id, 'status' => 1]);
  891. if (false === $result) {
  892. // 验证失败 输出错误信息
  893. throw new Exception('修改信息错误');
  894. }
  895. $staff = Staff::info();
  896. $transferStaff = Staff::get($staff_id);
  897. $depinfo = StaffRole::get($dep_id);
  898. //日程 修改指派人
  899. Event::where(['relation_type' => 'workorder', 'relation_id' => $id])->update(['staff_id' => $staff_id]);
  900. $row = self::get($id);
  901. $content = '将工单转派给[部门:' . $depinfo['name'] . '][' . $transferStaff['name'] . ']' . '原因:' . $desc;
  902. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  903. $params['relation_id'] = $id;
  904. $params['relation_process'] = '转派工单';
  905. //创建跟进记录
  906. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  907. //发送通知
  908. Message::addMessage(Message::WORKORDER_TYPE, $id, $workorder->owner_staff_id, $staff->id,
  909. "任务《{$row['title']}》已被指派给其他员工,请您及时审阅!");
  910. Message::addMessage(Message::WORKORDER_TYPE, $id, $staff_id, $staff->id,
  911. $staff->name . '转派给您一项任务,请您及时审阅');
  912. return true;
  913. }
  914. /**
  915. * 工单签到
  916. * @desc
  917. * @update_date 2021/7/10 更新时间
  918. * @author zhangwei
  919. */
  920. public static function workorderSign($id, $desc, $params)
  921. {
  922. $workorder = self::get($id);
  923. $update = [
  924. 'process' => 2,//到达目标位置
  925. 'stock_up_time' => time(),
  926. ];
  927. if (isset($params['end_mileage']) && $params['end_mileage']) {
  928. $params['end_mileage'] = intval($params['end_mileage']);
  929. if ($params['end_mileage'] <= $workorder['start_mileage']) {
  930. throw new Exception('结束公里数不能小于起始公里数');
  931. }
  932. //根据 起始公里数 ,录入行程费用
  933. $mileage = $params['end_mileage'] - $workorder['start_mileage'];
  934. $mileage_consume = [
  935. 'title' => $workorder['title'] . '-路程费用',
  936. 'number' => Consume::getNumber(),
  937. 'customer_id' => $workorder['customer_id'],
  938. 'relation_id' => $id,
  939. 'relation_type' => Consume::WORKORDER_TYPE,
  940. 'submit_date' => date('Y-m-d'),
  941. 'remark' => '',
  942. 'money' => Consume::getMileageMoney($mileage)
  943. ];
  944. $files = StaffSignIn::where(['relation_type' => StaffSignIn::WORKORDER_TYPE, 'relation_id' => $id])
  945. ->column('file_ids');
  946. $files[] = $params['file_ids'];
  947. $mileage_consume['detail'][] = [
  948. 'consume_date' => date('Y-m-d'),
  949. 'consume_type' => '交通费',
  950. 'consume_money' => Consume::getMileageMoney($mileage),
  951. 'mileage' => $mileage,
  952. 'car_type' => $workorder['car_type'],
  953. 'car_number' => $workorder['car_number'],
  954. 'start_mileage' => $workorder['start_mileage'],
  955. 'end_mileage' => $params['end_mileage'],
  956. 'file_ids' => implode(',', $files)
  957. ];
  958. Consume::createConsume($mileage_consume);
  959. $update['end_mileage'] = $params['end_mileage'];
  960. }
  961. $result = self::where(['id' => $id])->update($update);
  962. if (false === $result) {
  963. // 验证失败 输出错误信息
  964. throw new Exception('修改信息错误');
  965. }
  966. $row = self::get($id);
  967. $content = '已到达客户位置<br/>备注:' . $desc;
  968. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  969. $params['relation_id'] = $row['id'];
  970. $params['file_ids'] = $params['file_ids'] ?? '';
  971. $params['relation_process'] = '到达客户位置';
  972. //创建跟进记录
  973. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  974. return true;
  975. }
  976. /**
  977. * 终止流程
  978. * @desc
  979. * @update_date 2021/7/10 更新时间
  980. * @author zhangwei
  981. */
  982. public static function cancelWorkorder($id, $desc)
  983. {
  984. $result = self::where(['id' => $id])->update([
  985. 'status' => 9,//取消工单
  986. ]);
  987. if (false === $result) {
  988. // 验证失败 输出错误信息
  989. throw new Exception('修改信息错误');
  990. }
  991. $staff = Staff::info();
  992. //日程 取消
  993. Event::where(['relation_type' => 'workorder', 'relation_id' => $id])->update(['status' => 3]);
  994. $row = self::get($id);
  995. $content = '终止流程,备注:' . $desc;
  996. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  997. $params['relation_id'] = $row['id'];
  998. $params['relation_process'] = '终止流程';
  999. //创建跟进记录
  1000. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  1001. //发送通知
  1002. Message::addMessage(Message::WORKORDER_TYPE, $id, $row->owner_staff_id, $staff->id,
  1003. $staff->name . '终止任务《' . $row->title . '》,请您及时审阅');
  1004. return true;
  1005. }
  1006. /**
  1007. * 终止流程
  1008. * @desc
  1009. * @update_date 2021/7/10 更新时间
  1010. * @author zhangwei
  1011. */
  1012. public static function failWorkorder($id, $desc)
  1013. {
  1014. $result = self::where(['id' => $id])->update([
  1015. 'status' => 9,//取消工单
  1016. ]);
  1017. if (false === $result) {
  1018. // 验证失败 输出错误信息
  1019. throw new Exception('修改信息错误');
  1020. }
  1021. $staff = Staff::info();
  1022. $workorder = self::get($id);
  1023. //日程 取消
  1024. Event::where(['relation_type' => 'workorder', 'relation_id' => $id])->update(['status' => 3]);
  1025. $row = self::get($id);
  1026. $content = $workorder['workorder_type'] . '任务终止,备注:' . $desc;
  1027. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1028. $params['relation_id'] = $row['id'];
  1029. $params['relation_process'] = '任务终止';
  1030. //创建跟进记录
  1031. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  1032. //发送通知
  1033. Message::addMessage(Message::WORKORDER_TYPE, $id, $row->owner_staff_id, $staff->id,
  1034. $staff->name . '任务终止《' . $row->title . '》,请您及时审阅');
  1035. return true;
  1036. }
  1037. //回访工单
  1038. public static function visitWorkorder($params)
  1039. {
  1040. $result = self::where(['id' => $params['id']])->update([
  1041. 'is_visit' => 1,//回访
  1042. ]);
  1043. if (false === $result) {
  1044. // 验证失败 输出错误信息
  1045. throw new Exception('修改信息错误');
  1046. }
  1047. $data = [
  1048. 'workorder_id' => $params['id'],//
  1049. 'satisfaction' => $params['satisfaction'],//
  1050. 'visit_time' => $params['visit_time'],//回访时间
  1051. 'visit_desc' => $params['visit_desc'],//回访意见
  1052. 'visit_opinion' => $params['visit_opinion'],//
  1053. 'visit_service' => $params['visit_service'],//
  1054. 'visit_skill' => $params['visit_skill'],//
  1055. 'skill_score' => $params['skill_score'],//
  1056. 'service_score' => $params['service_score'],//
  1057. 'opinion_score' => $params['opinion_score'],//
  1058. ];
  1059. $visit = new WorkorderVisit();
  1060. $visit->save($data);
  1061. $row = self::get($params['id']);
  1062. $content = '回访工单';
  1063. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1064. $params['relation_id'] = $row['id'];
  1065. $params['relation_process'] = '回访工单';
  1066. //创建跟进记录
  1067. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  1068. return true;
  1069. }
  1070. //回执工单
  1071. public static function receiptWorkorder($params)
  1072. {
  1073. $result = self::where(['id' => $params['id']])->update([
  1074. 'receipt_file_ids' => $params['receipt_file_ids'],//回访
  1075. 'receipt_date' => $params['receipt_date'],//回访
  1076. ]);
  1077. if (false === $result) {
  1078. // 验证失败 输出错误信息
  1079. throw new Exception('修改信息错误');
  1080. }
  1081. $row = self::get($params['id']);
  1082. $content = '回执工单';
  1083. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1084. $params['relation_id'] = $row['id'];
  1085. $params['relation_process'] = '回执工单';
  1086. $params['file_ids'] = $params['receipt_file_ids'];
  1087. //创建跟进记录
  1088. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  1089. return true;
  1090. }
  1091. /**
  1092. * 撤销工单
  1093. * @desc
  1094. * @update_date 2021/7/10 更新时间
  1095. * @author zhangwei
  1096. */
  1097. public static function revokeWorkorder($id, $desc)
  1098. {
  1099. $result = self::where(['id' => $id])->update([
  1100. 'status' => 1,//取消工单
  1101. 'process' => 0,
  1102. ]);
  1103. if (false === $result) {
  1104. // 验证失败 输出错误信息
  1105. throw new Exception('修改信息错误');
  1106. }
  1107. $staff = Staff::info();
  1108. $row = self::get($id);
  1109. $content = '撤销工单,备注:' . $desc;
  1110. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1111. $params['relation_id'] = $row['id'];
  1112. $params['relation_process'] = '撤销工单';
  1113. //创建跟进记录
  1114. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  1115. //发送通知
  1116. Message::addMessage(Message::WORKORDER_TYPE, $id, $row->owner_staff_id, $staff->id,
  1117. $staff->name . '撤销任务《' . $row->title . '》,请您及时审阅');
  1118. return true;
  1119. }
  1120. /**
  1121. * 签名去人
  1122. * @desc
  1123. * @update_date 2021/7/10 更新时间
  1124. * @author zhangwei
  1125. */
  1126. public static function autograph($id, $url)
  1127. {
  1128. $result = self::where(['id' => $id])->update([
  1129. 'is_autograph' => 1,//签名
  1130. 'autograph_url' => $url,
  1131. ]);
  1132. if (false === $result) {
  1133. // 验证失败 输出错误信息
  1134. throw new Exception('修改信息错误');
  1135. }
  1136. $staff = Staff::info();
  1137. $row = self::get($id);
  1138. $content = '客户签字确认';
  1139. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1140. $params['relation_id'] = $row['id'];
  1141. $params['relation_process'] = '签字';
  1142. $params['file_ids'] = $url;
  1143. //创建跟进记录
  1144. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  1145. return true;
  1146. }
  1147. /**
  1148. * 完结工单
  1149. * @desc 备注
  1150. * @update_date 2021/7/10 更新时间
  1151. * @author zhangwei
  1152. */
  1153. public static function completeWorkorder($id, $desc, $params)
  1154. {
  1155. $row = self::where(['id' => $id])->find();
  1156. $update = [
  1157. 'status' => 2,//进行中
  1158. 'process' => 3,//录入零件 待录入费用
  1159. 'train_content' => json_encode($params['train_content'] ?? [], JSON_UNESCAPED_UNICODE),
  1160. 'end_time' => time()
  1161. ];
  1162. if ($desc) {
  1163. $update['results'] = $desc;
  1164. }
  1165. $use_parts = $params['use_parts'] ?? [];
  1166. $pay_service = $params['pay_service'] ?? [];
  1167. $new_use_parts = [];
  1168. foreach ($use_parts as $v) {
  1169. $new_use_parts[] = ['id' => $v['id'], 'number' => $v['number']];
  1170. }
  1171. $use_parts = $new_use_parts;
  1172. if ($row['parts'] && $use_parts) {//计算剩余零件
  1173. $parts = $row['parts'];
  1174. $parts_key = [];
  1175. foreach ($parts as $v) {
  1176. $parts_key[$v['id']] = $v['number'];
  1177. }
  1178. $use_parts_key = [];
  1179. foreach ($use_parts as $v) {
  1180. $use_parts_key[$v['id']] = $v['number'];
  1181. }
  1182. $surplus_parts = [];
  1183. foreach ($parts_key as $k => $number) {
  1184. if (isset($use_parts_key[$k])) {
  1185. $number = $number - $use_parts_key[$k];
  1186. $number = $number > 0 ? $number : 0;
  1187. }
  1188. $surplus_parts[] = ['id' => $k, 'number' => $number];
  1189. }
  1190. $update['surplus_parts'] = json_encode($surplus_parts);
  1191. }
  1192. !empty($use_parts) && $update['use_parts'] = json_encode($use_parts);
  1193. !empty($pay_service) && $update['pay_service'] = json_encode($pay_service);
  1194. $update['aftermarket_ids'] = $params['aftermarket_ids'] ?? '';//方案id
  1195. $update['aftermarket_text'] = $params['aftermarket_text'] ?? '';//其他方案
  1196. isset($params['resolved_results']) && $update['resolved_results'] = $params['resolved_results'];//
  1197. isset($params['complete_contact']) && $update['complete_contact'] = $params['complete_contact'];//
  1198. $update['complete_name'] = $params['complete_name'] ?? '';//
  1199. isset($params['mobile_result']) && $update['mobile_result'] = $params['mobile_result'];//电话结果 , 1 已解决 11 上门服务 12 返厂维修
  1200. isset($params['remarks']) && $update['remarks'] = $params['remarks'];//
  1201. isset($params['desc']) && $update['desc'] = $params['desc'];//
  1202. isset($params['is_mobile']) && $update['is_mobile'] = $params['is_mobile'];//
  1203. if (in_array($row['workorder_type'], ['维修工单', '巡检工单'])) {//
  1204. $update['process'] = 9;
  1205. $update['status'] = 3;//已完成
  1206. } elseif (in_array($row['workorder_type'], ['设计工单', '生产工单', '配件配送', '产品发货'])) {
  1207. $update['process'] = 9;
  1208. $update['status'] = 3;//已完成
  1209. } elseif ($row['workorder_type'] == '电话售后') {
  1210. if (empty($use_parts)) {//不需要发送配件 直接完成
  1211. $update['process'] = 9;
  1212. $update['status'] = 3;//已完成
  1213. }
  1214. }
  1215. $result = self::where(['id' => $id])->update($update);
  1216. if (false === $result) {
  1217. // 验证失败 输出错误信息
  1218. throw new Exception('修改信息错误');
  1219. }
  1220. if ($row['workorder_type'] == '电话售后' && $use_parts) {
  1221. //自动发货审批人
  1222. $customerInfo = Customer::where(['id' => $row['customer_id']])->find();
  1223. $addWorkorder = [
  1224. 'workorder_number' => self::getWorkorderNumber(),
  1225. 'workorder_type' => '配件配送',
  1226. 'title' => '配件配送',
  1227. 'customer_id' => $customerInfo['id'],
  1228. 'contacts_id' => $row['contacts_id'],
  1229. 'address' => $customerInfo['address'],
  1230. 'address_detail' => $customerInfo['address_detail'],
  1231. 'lng' => $customerInfo['lng'],
  1232. 'lat' => $customerInfo['lat'],
  1233. 'priority' => '一般',
  1234. 'create_staff_id' => $row['owner_staff_id'],
  1235. 'owner_staff_id' => $row['owner_staff_id'],
  1236. 'parts' => $use_parts
  1237. ];
  1238. self::createWorkorder($addWorkorder);
  1239. }
  1240. $staff = Staff::info();
  1241. $row = self::get($id);
  1242. if ($row['workorder_type'] == '上门维修') {
  1243. $res = $row['resolved_results'];
  1244. $res = ($res == 1) ? '已解决' : (($res == 9) ? '未解决' : '返厂维修');
  1245. $content = '完成了工单;' . '<br>处理结果:' . $res;
  1246. } elseif ($row['workorder_type'] == '上门安装') {
  1247. $res = $row['resolved_results'];
  1248. if ($res == 1) {//安装成功
  1249. CustomerProduct::where(['id' => ['in', $row['customer_product_id']]])->update([
  1250. 'status' => 3
  1251. ]);
  1252. }
  1253. $res = ($res == 1) ? '安装成功' : (($res == 9) ? '安装失败' : '返厂维修');
  1254. $content = '完成了工单;' . '<br>处理结果:' . $res;
  1255. } else {
  1256. $content = '完成了工单;' . '<br>处理结果:' . $desc;
  1257. }
  1258. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1259. $params['relation_id'] = $row['id'];
  1260. $params['file_ids'] = $params['file_ids'] ?? '';
  1261. $params['relation_process'] = '完成工单';
  1262. //创建跟进记录
  1263. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  1264. //发送通知
  1265. Message::addMessage(Message::WORKORDER_TYPE, $id, $row->owner_staff_id, $staff->id, $staff->name . '《' . $row->title . '》任务已完成,请您继续操作');
  1266. //发送通知
  1267. if ($update['status'] == 3) {
  1268. self::setComplete($row['id']);
  1269. }
  1270. return true;
  1271. }
  1272. /**
  1273. * 填写维修结果
  1274. * @desc 备注
  1275. * @update_date 2021/7/10 更新时间
  1276. * @author zhangwei
  1277. */
  1278. public static function repairResult($id, $params)
  1279. {
  1280. $row = self::where(['id' => $id])->find();
  1281. $staff = Staff::info();
  1282. if ($params['resolved_results'] == 1) {//维修成功
  1283. $update = [
  1284. 'status' => 2,//处理中
  1285. 'process' => 3,//维修成功 待提交费用
  1286. 'resolved_results' => $params['resolved_results'] ?? 0,
  1287. 'is_replace' => $params['is_replace'] ?? 0,
  1288. 'is_recovery' => $params['is_recovery'] ?? 0,
  1289. 'maintain' => $params['maintain'] ?? '',
  1290. 'results' => $params['results'] ?? '',
  1291. 'start_time' => strtotime($params['start_time']),
  1292. 'end_time' => time()
  1293. ];
  1294. if ($row['is_over'] == 2) {//未过保
  1295. // $update['process']=5;
  1296. }
  1297. $use_parts = $params['use_parts'] ?? [];
  1298. $update['use_parts'] = [];
  1299. foreach ($use_parts as $k => $n) {
  1300. $update['use_parts'][] = ['id' => $n['id'], 'number' => $n['number'] ?? 0];
  1301. }
  1302. $update['use_parts'] = json_encode($update['use_parts']);
  1303. } else {//维修失败
  1304. $update = [
  1305. 'status' => 2,//处理中
  1306. 'process' => 2,
  1307. 'resolved_results' => $params['resolved_results'] ?? 0,
  1308. 'is_replace' => $params['is_replace'] ?? 0,
  1309. 'is_recovery' => $params['is_recovery'] ?? 0,
  1310. 'maintain' => $params['maintain'] ?? '',
  1311. 'results' => $params['results'] ?? '',
  1312. 'start_time' => strtotime($params['start_time']),
  1313. // 'owner_staff_id' => $row->create_staff_id
  1314. ];
  1315. $use_parts = $params['use_parts'] ?? [];
  1316. $update['use_parts'] = [];
  1317. foreach ($use_parts as $k => $n) {
  1318. $update['use_parts'][] = ['id' => $n['id'], 'number' => $n['number'] ?? 0];
  1319. }
  1320. $update['use_parts'] = json_encode($update['use_parts']);
  1321. }
  1322. $result = self::where(['id' => $id])->update($update);
  1323. if (false === $result) {
  1324. // 验证失败 输出错误信息
  1325. throw new Exception('修改信息错误');
  1326. }
  1327. //日程开始
  1328. Event::where(['relation_type' => 'workorder', 'relation_id' => $params['id']])
  1329. ->update(['status' => 1]);
  1330. $row = self::get($id);
  1331. if ($update['process'] == 2) {
  1332. $content = '填写维修结果<br>' . '处理结果:维修失败';
  1333. Message::addMessage(Message::WORKORDER_TYPE, $id, $row->owner_staff_id, $staff->id,
  1334. $staff->name . '的工单《' . $row->title . '》维修失败,请您及时处理');
  1335. } else {
  1336. $content = '填写维修结果<br>' . '处理结果:维修成功';
  1337. Message::addMessage(Message::WORKORDER_TYPE, $id, $row->owner_staff_id, $staff->id,
  1338. $staff->name . '的工单《' . $row->title . '》维修成功,请您录入相关费用!');
  1339. }
  1340. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1341. $params['relation_id'] = $row['id'];
  1342. $params['file_ids'] = $params['file_ids'] ?? '';
  1343. $params['relation_process'] = '填写维修结果';
  1344. //创建跟进记录
  1345. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  1346. return true;
  1347. }
  1348. /**
  1349. * 录入工单费用
  1350. */
  1351. public static function enterWorkorderMoney($id, $params)
  1352. {
  1353. $update = [
  1354. 'status' => 2,//处理中
  1355. 'process' => 7,//费用待审核
  1356. ];
  1357. $pay_service = $params['pay_service'] ?? [];
  1358. $update['pay_service'] = json_encode($pay_service);
  1359. $update['total_money'] = $params['total_money'] ?? 0;//总费用
  1360. $update['discount_money'] = $params['discount_money'] ?? 0;//优惠费用
  1361. $update['money'] = $params['total_money'] - $update['discount_money'];//当前价格
  1362. $update['tax'] = $params['tax'] ?? '';//当前价格
  1363. $update['collection_img'] = $params['collection_img'] ?? '';//
  1364. $update['collection_deposit'] = $params['collection_deposit'] ?? '';//
  1365. $update['collection_account'] = $params['collection_account'] ?? '';
  1366. $update['collection_name'] = $params['collection_name'] ?? '';//
  1367. $update['is_charge'] = $params['is_charge'] ?? 1;//是否收费 1收费 2不收费
  1368. $update['use_parts'] = [];
  1369. $use_parts = $params['use_parts'] ?? [];
  1370. foreach ($use_parts as $k => $n) {
  1371. $update['use_parts'][] = [
  1372. 'id' => $n['id'],
  1373. 'number' => $n['number'] ?? 0,
  1374. 'is_charge' => $n['is_charge'] ?? 1,
  1375. ];
  1376. }
  1377. $update['use_parts'] = json_encode($update['use_parts']);
  1378. $flow = Flow::getsteplist(Flow::WORKORDER_STATUS);
  1379. $update['flow_id'] = $flow['flow_id'];
  1380. $update['order_id'] = $flow['order_id'];
  1381. if ($flow['status'] == 0) {//发起人自选
  1382. if (empty($params['flow_staff_ids'])) {
  1383. throw new Exception('审批人必须选择');
  1384. }
  1385. $update['flow_staff_ids'] = trim($params['flow_staff_ids']);
  1386. } else {
  1387. $update['flow_staff_ids'] = trim($flow['flow_staff_ids']);
  1388. }
  1389. $update['check_status'] = 1;
  1390. if ($flow['status'] == 1) {//固定审批
  1391. //发送审批通知
  1392. Flow::sendStepRecord($flow, Flow::WORKORDER_STATUS, $id);
  1393. } else {//发起人自选 依次审批
  1394. $staff_id = explode(',', $params['flow_staff_ids'])[0];
  1395. if ($staff_id) {
  1396. ExamineRecord::addExaminse(ExamineRecord::WORKORDER_TYPE, $id, $staff_id);
  1397. }
  1398. }
  1399. $result = self::where(['id' => $id])->update($update);
  1400. if (false === $result) {
  1401. // 验证失败 输出错误信息
  1402. throw new Exception('修改信息错误');
  1403. }
  1404. $row = self::get($id);
  1405. $content = '录入维修费用<br> 金额:' . $update['money'];
  1406. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1407. $params['relation_id'] = $row['id'];
  1408. $params['file_ids'] = $params['file_ids'] ?? '';
  1409. $params['relation_process'] = '录入维修费用';
  1410. //创建跟进记录
  1411. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  1412. return true;
  1413. }
  1414. //财务确认回款
  1415. public static function financialAudit($workorder_id)
  1416. {
  1417. $row = self::where(['id' => $workorder_id])->find();
  1418. //设置产品编号
  1419. self::where(['id' => $workorder_id])->update(['is_financial_audit' => 1]);
  1420. $content = '财务确认收款';
  1421. $data['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1422. $data['relation_id'] = $row['id'];
  1423. $data['relation_process'] = '确认收款';
  1424. //创建跟进记录
  1425. StaffSignIn::quickSignIn($row['customer_id'], $content, $data);
  1426. $staff = Staff::info();
  1427. Message::setRead(Message::WORKORDER_RECEIVABLES, $workorder_id, $staff->id);
  1428. return true;
  1429. }
  1430. //设置产品编号
  1431. public static function setProductNumber($workorder_id, $params)
  1432. {
  1433. $row = self::where(['id' => $workorder_id])->find();
  1434. $staff = Staff::info();
  1435. //设置产品编号
  1436. self::where(['id' => $workorder_id])->update(['process' => 2, 'stock_up_time' => time()]);
  1437. $content = '录入了产品编号';
  1438. $self = new self();
  1439. $self->allowField(true)->save($params, ['id' => $params['workorder_id']]);
  1440. $data['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1441. $data['relation_id'] = $row['id'];
  1442. $data['relation_process'] = '设置产品编号';
  1443. //创建跟进记录
  1444. StaffSignIn::quickSignIn($row['customer_id'], $content, $data);
  1445. return true;
  1446. }
  1447. //设置产品编号
  1448. public static function setPartsNumber($workorder_id, $params)
  1449. {
  1450. $row = self::where(['id' => $workorder_id])->find();
  1451. $staff = Staff::info();
  1452. //设置产品编号
  1453. self::where(['id' => $workorder_id])->update(['process' => 2, 'stock_up_time' => time()]);
  1454. $content = '提交配送信息成功';
  1455. $self = new self();
  1456. $self->allowField(true)->save($params, ['id' => $params['workorder_id']]);
  1457. $data['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1458. $data['relation_id'] = $row['id'];
  1459. $data['relation_process'] = '提交配送信息';
  1460. //创建跟进记录
  1461. StaffSignIn::quickSignIn($row['customer_id'], $content, $data);
  1462. return true;
  1463. }
  1464. //添加物流信息 发货
  1465. public static function setLogistics($workorder_id, $product_ids)
  1466. {
  1467. $row = self::where(['id' => $workorder_id])->find();
  1468. $update = ['process' => 3];
  1469. if ($row['workorder_type'] == '产品发货') {//运输中
  1470. // $customer_product_id=$row['customer_product_id']??'';
  1471. // $customer_product_id=explode(',',$customer_product_id);
  1472. CustomerProduct::where(['id' => ['in', $product_ids]])->update([
  1473. 'status' => 1
  1474. ]);
  1475. } else if ($row['workorder_type'] == '返厂维修') {
  1476. $update['process'] = 8;//等待物流到货
  1477. }
  1478. self::where(['id' => $workorder_id])->update($update);
  1479. $content = '提交了物流信息';
  1480. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1481. $params['relation_id'] = $workorder_id;
  1482. $params['relation_process'] = '添加物流信息';
  1483. //创建跟进记录
  1484. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  1485. return true;
  1486. }
  1487. //添加品质异常单
  1488. public static function addProgress($params)
  1489. {
  1490. $staff = Staff::info();
  1491. //填写进度
  1492. $model = new WorkorderProgress();
  1493. $params['create_staff_id'] = $staff->id;
  1494. $model->save($params);
  1495. $workorderModel = new self();
  1496. $row = $workorderModel->get($params['workorder_id']);
  1497. $flow_staff_ids = explode(',', trim($row['flow_staff_ids'], ','));
  1498. $check_staff_ids = explode(',', trim($row['check_staff_ids'], ','));
  1499. $check_staff_ids[] = $staff->id;
  1500. $diff = array_diff($flow_staff_ids, $check_staff_ids);
  1501. $diff = array_values($diff);
  1502. if (empty($diff)) {
  1503. $workorderModel->save([
  1504. 'status' => 3,
  1505. 'check_status' => 2,
  1506. 'check_staff_ids' => implode(',', $check_staff_ids)
  1507. ], ['id' => $row->id]);
  1508. Message::addMessage(Message::WORKORDER_TYPE, $row->id, $row['create_staff_id'], $staff->id, $staff->name . '已经完成了品质异常单,请及时查看!');
  1509. } else {
  1510. //处理中
  1511. $workorderModel->save([
  1512. 'check_staff_ids' => implode(',', $check_staff_ids),
  1513. 'status' => 2,
  1514. 'owner_staff_id' => $diff[0],
  1515. ], ['id' => $row->id]);
  1516. Message::addMessage(Message::WORKORDER_TYPE, $row->id, $diff[0], $row['create_staff_id'], $staff->name . '提交了一个品质异常单需要您处理!');
  1517. }
  1518. $content = '提交异常分析结果';
  1519. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1520. $params['relation_id'] = $params['workorder_id'];
  1521. $params['relation_process'] = '提交异常分析结果';
  1522. //创建跟进记录
  1523. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  1524. return true;
  1525. }
  1526. //取消测试/继续测试
  1527. public static function continueTest($id, $is_continue)
  1528. {
  1529. $workorder = self::where(['id' => $id])->find();
  1530. if (empty($workorder)) {
  1531. return false;
  1532. }
  1533. if ($is_continue == 1) {//继续维修
  1534. $data['process'] = 6;
  1535. $result = self::where(['id' => $id])->update($data);
  1536. if (false === $result) {
  1537. // 验证失败 输出错误信息
  1538. throw new Exception('修改信息错误');
  1539. }
  1540. Event::where(['relation_type' => 'workorder', 'relation_id' => $id, 'type' => 1])
  1541. ->update(['status' => 1]);
  1542. $content = '根据评估结果,继续维修';
  1543. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1544. $params['relation_id'] = $id;
  1545. //创建跟进记录
  1546. StaffSignIn::quickSignIn($workorder['customer_id'], $content, $params);
  1547. $staff = Staff::info();
  1548. //发送通知
  1549. $messageContent = $staff->name . '《' . $workorder['title'] . '》评估继续维修,请您及时审阅';
  1550. $toStaff = [$workorder['create_staff_id'], $workorder['owner_staff_id']];
  1551. $toStaff = implode(',', $toStaff);
  1552. Message::addMessage(Message::WORKORDER_TYPE, $id, $workorder['owner_staff_id'], $staff->id, $messageContent);
  1553. } elseif ($is_continue == 9) {//取消维修
  1554. $data['process'] = 9;
  1555. $data['status'] = 3;
  1556. $result = self::where(['id' => $id])->update($data);
  1557. if (false === $result) {
  1558. // 验证失败 输出错误信息
  1559. throw new Exception('修改信息错误');
  1560. }
  1561. //取消任务
  1562. Event::where(['relation_type' => 'workorder', 'relation_id' => $id])->update([
  1563. 'status' => 3]);
  1564. $content = '销售根据评估结果,取消维修';
  1565. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1566. $params['relation_id'] = $id;
  1567. //创建跟进记录
  1568. StaffSignIn::quickSignIn($workorder['customer_id'], $content, $params);
  1569. $staff = Staff::info();
  1570. $messageContent = $staff->name . '《' . $workorder['title'] . '》评估取消维修,请您及时审阅';
  1571. Message::addMessage(Message::WORKORDER_TYPE, $id, $workorder['owner_staff_id'], $staff->id, $messageContent);
  1572. }
  1573. return true;
  1574. }
  1575. public static function getWorkorderNumber()
  1576. {
  1577. return 'S' . date('ymd') . rand(100, 999);
  1578. }
  1579. //工单完成
  1580. public static function setComplete($workorder_id)
  1581. {
  1582. $staff = Staff::info();
  1583. $row = self::get($workorder_id);
  1584. //日程完成
  1585. Event::where(['relation_type' => 'workorder', 'relation_id' => $workorder_id])
  1586. ->update(['status' => 2]);
  1587. if (in_array($row['workorder_type'], self::getVisitType())) {
  1588. //回访客户通知
  1589. Message::addMessage(Message::WORKORDER_TYPE, $row['id'], $row['create_staff_id'], $staff->id, '《' . $row->title . '》工单已完成,请您尽快回访客户!');
  1590. }
  1591. if ($row['is_pay'] == 1) {
  1592. //发送通知
  1593. Message::addMessage(Message::WORKORDER_RECEIVABLES, $workorder_id, $row['create_staff_id'], $staff->id, '《' . $row->title . '》任务已完成,请您及时确认回款情况!');
  1594. }
  1595. return true;
  1596. }
  1597. //获取回访工单类型
  1598. public static function getVisitType()
  1599. {
  1600. return ['上门安装', '上门维修', '配件安装'];
  1601. }
  1602. }