Workorder.php 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763
  1. <?php
  2. namespace addons\qingdongams\controller;
  3. use addons\qingdongams\library\QRCode;
  4. use addons\qingdongams\model\Companys;
  5. use addons\qingdongams\model\ConsumeDetail;
  6. use addons\qingdongams\model\Equipment;
  7. use addons\qingdongams\model\Event;
  8. use addons\qingdongams\model\ExamineRecord;
  9. use addons\qingdongams\model\Flow;
  10. use addons\qingdongams\model\Message;
  11. use addons\qingdongams\model\Staff;
  12. use addons\qingdongams\model\StaffSignIn;
  13. use addons\qingdongams\model\Workorder as WorkorderModel;
  14. use addons\qingdongams\model\WorkorderLogistics;
  15. use addons\qingdongams\model\CustomerProduct;
  16. use addons\qingdongams\model\Customer;
  17. use addons\qingdongams\model\WorkorderProgress;
  18. use PhpOffice\PhpWord\TemplateProcessor;
  19. use think\Db;
  20. use think\Exception;
  21. use think\Log;
  22. use think\Response;
  23. /**
  24. * @desc 操作文档:https://doc.fastadmin.net/qingdongams
  25. * @desc 软件介绍:https://www.fastadmin.net/store/qingdongams.html
  26. * @desc 售后微信:qingdong_crm
  27. */
  28. /**
  29. * 工单
  30. */
  31. class Workorder extends StaffApi
  32. {
  33. protected $noNeedLogin = ['qrcode', 'notifyorder', 'returnorder'];
  34. protected $noNeedRight = [];
  35. //提交 0待指派
  36. //已指派 1
  37. //维修失败,已提交售后领导和销售创建人 2
  38. //维修成功,等待录入费用 3
  39. //费用审核通过,待支付工单 4
  40. //工单支付成功,待录入物流信息 5
  41. //销售根据评估结果,继续生产,即继续维修 6
  42. //费用待审核 7
  43. //维修结束,打样申请结束 9
  44. //获取工单列表
  45. public function getList()
  46. {
  47. $limit = input("limit/d", 10);
  48. $params = $this->request->post();
  49. //
  50. $where = [];
  51. if (isset($params['name']) && $params['name']) {//查询名称
  52. $where['title|workorder_number'] = ['like', "%{$params['name']}%"];
  53. }
  54. if (isset($params['customer_id']) && $params['customer_id']) {//所属客户
  55. $where['customer_id'] = $params['customer_id'];
  56. }
  57. if (isset($params['status']) && $params['status']) {//状态
  58. $where['status'] = $params['status'];
  59. if ($params['status'] == 3) {
  60. $where['status'] = ['in', [3, 9]];
  61. }
  62. }
  63. if (isset($params['complete_status'])) {//完成状态
  64. if ($params['complete_status'] == 1) {//未完成
  65. $where['status'] = ['in', [0, 1, 2]];
  66. } elseif ($params['complete_status'] == 2) {//待指派
  67. $where['status'] = 0;
  68. } elseif ($params['complete_status'] == 3) {//进行中
  69. $where['status'] = ['in', [1, 2]];
  70. } elseif ($params['complete_status'] == 4) {//异常工单
  71. $where['status'] = ['in', [0, 1, 2]];
  72. $where['is_pause|is_timeout'] = 1;
  73. }
  74. }
  75. $whereStaff = [];
  76. if (isset($params['staff_id']) && $params['staff_id']) {//下级员工筛选
  77. $whereStaff['create_staff_id|owner_staff_id'] = $params['staff_id'];
  78. } else {
  79. if (isset($params['type']) && $params['type']) {//客户分类
  80. if ($params['type'] == 1) {//我工单
  81. $whereStaff['create_staff_id|owner_staff_id'] = $this->auth->id;
  82. } elseif ($params['type'] == 2) {//下属负责的工单
  83. $whereStaff['owner_staff_id'] = ['in', Staff::getLowerStaffId()];
  84. }
  85. } else {
  86. $whereStaff = function ($query) {
  87. $query->where('create_staff_id|owner_staff_id', 'in', Staff::getMyStaffIds());
  88. };
  89. }
  90. }
  91. //异常工单
  92. if (isset($params['is_yichang']) && $params['is_yichang']) {
  93. $where['is_pause|is_timeout'] = 1;
  94. }
  95. if (isset($params['workorder_type']) && $params['workorder_type']) {
  96. $where['workorder_type'] = $params['workorder_type'];
  97. }
  98. if (isset($params['createtime']) && $params['createtime']) {
  99. $times = setTimes($params['createtime'], 'time');
  100. $where['createtime'] = ['between', $times];
  101. }
  102. if (isset($params['end_time']) && $params['end_time']) {
  103. $times = setTimes($params['end_time'], 'time');
  104. $where['end_time'] = ['between', $times];
  105. }
  106. if (isset($params['comment_score']) && $params['comment_score']) {
  107. $where['comment_score'] = 5;
  108. }
  109. if (isset($params['prov']) && !empty(trim($params['prov']))) {//省市区筛选
  110. $prov = trim($params['prov']);
  111. $city = trim($params['city']);
  112. $area = trim($params['area']);
  113. if (empty($city)) {
  114. $where['address|address_detail'] = ['like', "%{$prov}%"];
  115. } elseif (empty($area)) {
  116. $where['address|address_detail'] = ['like', "%{$city}%"];
  117. } else {
  118. $where['address|address_detail'] = ['like', "%{$area}%"];
  119. }
  120. }
  121. if (isset($params['id_list'])) {//日志 查询id列表
  122. $where = [];
  123. $whereStaff = [];
  124. $where['id'] = ['in', explode(',', $params['id_list'])];
  125. }
  126. $list = WorkorderModel::where($where)->where($whereStaff)->with([
  127. 'customer',
  128. 'ownerStaff',
  129. 'contacts', 'file'
  130. ])->field('deletetime,updatetime', true)->order('createtime desc')->paginate($limit);
  131. $this->success('请求成功', $list);
  132. }
  133. //获取回访工单列表
  134. public function getVisitList()
  135. {
  136. $limit = input("limit/d", 10);
  137. $is_visit = input('is_visit', 0);
  138. $params = $this->request->post();
  139. //
  140. $where = [];
  141. if (isset($params['name']) && $params['name']) {//查询名称
  142. $where['title|workorder_number'] = ['like', "%{$params['name']}%"];
  143. }
  144. if (isset($params['customer_id']) && $params['customer_id']) {//所属客户
  145. $where['customer_id'] = $params['customer_id'];
  146. }
  147. if (isset($params['prov']) && !empty(trim($params['prov']))) {//省市区筛选
  148. $prov = trim($params['prov']);
  149. $city = trim($params['city']);
  150. $area = trim($params['area']);
  151. if (empty($city)) {
  152. $where['address|address_detail'] = ['like', "%{$prov}%"];
  153. } elseif (empty($area)) {
  154. $where['address|address_detail'] = ['like', "%{$city}%"];
  155. } else {
  156. $where['address|address_detail'] = ['like', "%{$area}%"];
  157. }
  158. }
  159. $where['status'] = 3;
  160. $where['is_visit'] = $is_visit;
  161. $where['workorder_type'] = ['in', WorkorderModel::getVisitType()];
  162. $list = WorkorderModel::where($where)->with([
  163. 'customer',
  164. 'ownerStaff',
  165. 'contacts'
  166. ])->field('deletetime,updatetime', true)->order('createtime desc')->paginate($limit);
  167. $this->success('请求成功', $list);
  168. }
  169. //获取收款工单列表
  170. public function getFinancialList()
  171. {
  172. $limit = input("limit/d", 10);
  173. $is_financial_audit = input('is_financial_audit', 0);
  174. $params = $this->request->post();
  175. //
  176. $where = [];
  177. if (isset($params['name']) && $params['name']) {//查询名称
  178. $where['title|workorder_number'] = ['like', "%{$params['name']}%"];
  179. }
  180. if (isset($params['customer_id']) && $params['customer_id']) {//所属客户
  181. $where['customer_id'] = $params['customer_id'];
  182. }
  183. if (isset($params['prov']) && !empty(trim($params['prov']))) {//省市区筛选
  184. $prov = trim($params['prov']);
  185. $city = trim($params['city']);
  186. $area = trim($params['area']);
  187. if (empty($city)) {
  188. $where['address|address_detail'] = ['like', "%{$prov}%"];
  189. } elseif (empty($area)) {
  190. $where['address|address_detail'] = ['like', "%{$city}%"];
  191. } else {
  192. $where['address|address_detail'] = ['like', "%{$area}%"];
  193. }
  194. }
  195. $where['status'] = 3;
  196. $where['is_pay'] = 1;//收款工单
  197. $where['is_financial_audit'] = $is_financial_audit;
  198. $list = WorkorderModel::where($where)->with([
  199. 'customer',
  200. 'ownerStaff',
  201. 'contacts'
  202. ])->field('deletetime,updatetime', true)->order('createtime desc')->paginate($limit);
  203. $this->success('请求成功', $list);
  204. }
  205. //添加工单
  206. public function addWorkorder()
  207. {
  208. $params = $this->request->post();
  209. // 表单验证
  210. if (($result = $this->qingdongamsValidate($params,get_class(), 'create')) !== true) {
  211. $this->error($result);
  212. }
  213. if (WorkorderModel::where([
  214. 'workorder_number' => $params['workorder_number'],
  215. ])->find()) {
  216. $this->error('工单编号已存在');
  217. }
  218. try {
  219. $result = WorkorderModel::createWorkorder($params);
  220. Db::commit();
  221. } catch (Exception $e) {
  222. Db::rollback();
  223. $this->error($e->getMessage());
  224. }
  225. if ($result) {
  226. $this->success('添加工单成功');
  227. }
  228. }
  229. //获取工单编号
  230. public function getWorkorderNumber()
  231. {
  232. $this->success('请求成功', ['number' => WorkorderModel::getWorkorderNumber()]);
  233. }
  234. //获取品质异常工单编号
  235. public function getBadWorkorderNumber()
  236. {
  237. $this->success('请求成功', ['number' => 'Y' . date('ymd') . rand(100, 999)]);
  238. }
  239. //编辑工单
  240. public function editWorkorder()
  241. {
  242. $id = input('id');
  243. $params = $this->request->post();
  244. $row = WorkorderModel::where(['id' => $id])->find();
  245. if (empty($row)) {
  246. $this->error('修改工单信息不存在');
  247. }
  248. Db::startTrans();
  249. try {
  250. $result = WorkorderModel::updateWorkorder($params);
  251. Db::commit();
  252. } catch (Exception $e) {
  253. Db::rollback();
  254. $this->error($e->getMessage());
  255. }
  256. $this->success('修改工单信息成功');
  257. }
  258. //获取工单详情
  259. public function getWorkorderDetail()
  260. {
  261. $id = input('id');
  262. $workorder = WorkorderModel::where(['id' => $id])->with(['createStaff',
  263. 'contacts', 'customer', 'ownerStaff', 'file', 'getevent', 'visit'])->find();
  264. if (empty($workorder)) {
  265. $this->error('参数不存在');
  266. }
  267. $workorder = $workorder->toArray();
  268. if ($workorder['check_status'] == 1) {//审核中
  269. $workorder['is_examine'] = ExamineRecord::isExaminse(ExamineRecord::WORKORDER_TYPE, $id);
  270. } else {
  271. $workorder['is_examine'] = 0;
  272. }
  273. if (empty($workorder['contacts'])) {
  274. $workorder['contacts'] = \addons\qingdongams\model\Contacts::where(['customer_id' => $workorder['customer_id']])->order('is_major desc')->field('id,customer_id,name,mobile,mobilecode,region')->find();
  275. }
  276. $workorder['is_revoke'] = 0;
  277. $workorder['is_operation'] = 0;
  278. $workorder['is_operation_visit'] = 0;
  279. $workorder['is_financial'] = 0;
  280. $workorder['is_leader'] = 0;
  281. if ($workorder['create_staff_id'] == $this->auth->id || in_array($workorder['create_staff_id'], Staff::getLowerStaffId())) {
  282. //是否可以撤销
  283. $workorder['is_revoke'] = 1;
  284. }
  285. //是否可以录入费用-是否可以回款
  286. $workorder['is_leader'] = 1;
  287. $workorder['is_leader'] = 1;
  288. if ($workorder['workorder_type'] == '产品发货' ) {
  289. //TODO 是否可以操作 售后部不能操作发货工单
  290. $workorder['is_operation'] = 0;
  291. $workorder['is_revoke'] = 0;
  292. }
  293. if (in_array($workorder['workorder_type'], ['产品发货', '设计工单'])) {
  294. //业务部领导可以操作发货工单 和 发货工单
  295. $workorder['is_leader'] = 1;
  296. }
  297. if ($workorder['owner_staff_id'] == $this->auth->id) {
  298. //是否可以操作
  299. $workorder['is_operation'] = 1;
  300. }
  301. if (in_array($workorder['workorder_type'],WorkorderModel::getVisitType()) && $workorder['status'] == 3) { //操作回访
  302. $workorder['is_operation_visit'] = 1;
  303. }
  304. if ($workorder['status'] == 3 && $workorder['is_pay'] == 1 && $workorder['is_financial_audit'] == 0) { //是否财务审核
  305. $workorder['is_financial'] = 1;
  306. }
  307. if ($workorder['customer_product_id']) {
  308. $customer_product_ids = explode(',', $workorder['customer_product_id']);
  309. $workorder['customer_product'] = CustomerProduct::where(['id' => ['in', $customer_product_ids]])->with(['product'])->select();
  310. //是否可以操作物流
  311. $workorder['is_operation_logistics'] = 0;
  312. foreach ($workorder['customer_product'] as $k => $v) {
  313. if (!empty($v['number'])) {
  314. $workorder['is_operation_logistics'] = 1;
  315. }
  316. }
  317. }
  318. if ($workorder['workorder_type'] == '上门维修' || $workorder['workorder_type'] == '返厂维修') {
  319. $workorder['peisong'] = WorkorderModel::where(['relation_workorder_id' => $id, 'workorder_type' => '配件配送'])->select();
  320. $workorder['anzhuang'] = WorkorderModel::where(['relation_workorder_id' => $id, 'workorder_type' => '配件安装'])->select();
  321. }
  322. if ($workorder['flow_staff_ids']) {
  323. $workorder['flow_staff'] = Staff::where(['id' => ['in', $workorder['flow_staff_ids']],'status'=>1])->field('id,name,img')->select();
  324. }
  325. //是否可以操作完成
  326. $workorder['is_operation_end'] = 0;
  327. if (in_array($workorder['status'], [0, 1])) {
  328. $workorder['is_operation_end'] = 1;
  329. }
  330. Message::setRead(Message::WORKORDER_TYPE, $id, $this->auth->id);
  331. Message::setRead(Message::WORKORDER_RECEIVABLES, $id, $this->auth->id);
  332. $this->success('请求成功', $workorder);
  333. }
  334. //指派负责人
  335. public function assign_order()
  336. {
  337. $id = input('id');
  338. $staff_id = input('staff_id');
  339. $desc = input('desc');
  340. $row = WorkorderModel::where(['id' => $id])->find();
  341. if (empty($row)) {
  342. $this->error('工单信息不存在');
  343. }
  344. Db::startTrans();
  345. try {
  346. WorkorderModel::assignWorkorder($id, $staff_id, $desc);
  347. Db::commit();
  348. } catch (Exception $e) {
  349. Db::rollback();
  350. $this->error($e->getMessage());
  351. }
  352. $this->success('指派成功');
  353. }
  354. //转派工单
  355. public function transfer()
  356. {
  357. $id = input('id');
  358. $staff_id = input('staff_id');
  359. $desc = input('desc');
  360. $row = WorkorderModel::where(['id' => $id])->find();
  361. if (empty($row)) {
  362. $this->error('工单信息不存在');
  363. }
  364. if ($row['owner_staff_id'] == $staff_id) {
  365. $this->error('不能将工单转派给原负责人');
  366. }
  367. Db::startTrans();
  368. try {
  369. WorkorderModel::transferWorkorder($id, $staff_id, $desc);
  370. Db::commit();
  371. } catch (Exception $e) {
  372. Db::rollback();
  373. $this->error($e->getMessage());
  374. }
  375. $this->success('转派成功');
  376. }
  377. //接受工单
  378. public function accept_order()
  379. {
  380. $params = $this->request->post();
  381. if (empty($params['id'])) {
  382. $this->error('参数不能为空');
  383. }
  384. $row = WorkorderModel::where(['id' => $params['id']])->find();
  385. if (empty($row)) {
  386. $this->error('工单不存在');
  387. }
  388. Db::startTrans();
  389. try {
  390. $params['workorder_type'] = $row['workorder_type'];
  391. WorkorderModel::acceptWorkorder($params);
  392. Db::commit();
  393. } catch (Exception $e) {
  394. Db::rollback();
  395. $this->error($e->getMessage());
  396. }
  397. $this->success('接受工单成功');
  398. }
  399. //开始工单
  400. public function start_order()
  401. {
  402. $params = $this->request->post();
  403. if (empty($params['id'])) {
  404. $this->error('参数不能为空');
  405. }
  406. if (empty($params['lng']) || empty($params['lat']) || empty($params['location'])) {
  407. $this->error('定位地理位置错误');
  408. }
  409. $row = WorkorderModel::where(['id' => $params['id'], 'status' => 2])->find();
  410. if (empty($row)) {
  411. $this->error('工单不存在');
  412. }
  413. Db::startTrans();
  414. try {
  415. WorkorderModel::startWorkorder($params);
  416. Db::commit();
  417. } catch (Exception $e) {
  418. Db::rollback();
  419. $this->error($e->getMessage());
  420. }
  421. $this->success('开始工单成功');
  422. }
  423. //录入零件
  424. public function input_parts()
  425. {
  426. $params = $this->request->post();
  427. if (empty($params['id'])) {
  428. $this->error('参数不能为空');
  429. }
  430. $row = WorkorderModel::where(['id' => $params['id']])->find();
  431. if (empty($row)) {
  432. $this->error('工单不存在');
  433. }
  434. Db::startTrans();
  435. try {
  436. WorkorderModel::inputParts($params);
  437. Db::commit();
  438. } catch (Exception $e) {
  439. Db::rollback();
  440. $this->error($e->getMessage());
  441. }
  442. $this->success('录入成功');
  443. }
  444. //到达签到
  445. public function addSign()
  446. {
  447. $params = $this->request->post();
  448. $id = input('id');
  449. $desc = input('desc', '');
  450. $where = ['id' => $id];
  451. $workorder = WorkorderModel::where($where)->find();
  452. if (empty($workorder)) {
  453. $this->error('工单不存在');
  454. }
  455. Db::startTrans();
  456. try {
  457. WorkorderModel::workorderSign($id, $desc, $params);
  458. Db::commit();
  459. } catch (Exception $e) {
  460. Db::rollback();
  461. $this->error($e->getMessage());
  462. }
  463. $this->success('操作成功');
  464. }
  465. //完成工单
  466. public function complete()
  467. {
  468. $params = $this->request->post();
  469. $id = input('id');
  470. $desc = input('desc');
  471. $row = WorkorderModel::where(['id' => $id])->find();
  472. if (empty($row)) {
  473. $this->error('工单信息不存在');
  474. }
  475. if ($row['is_pause'] == 1) {
  476. $this->error('工单暂停中');
  477. }
  478. if ($params['discount_money'] ?? 0 > 0) {
  479. if (empty($params['flow_staff_ids'])) {
  480. $this->error('工单审批人不能为空');
  481. }
  482. }
  483. Db::startTrans();
  484. try {
  485. WorkorderModel::completeWorkorder($id, $desc, $params);
  486. if ($row['workorder_type'] == '产品发货') {//送达待安装
  487. CustomerProduct::where(['id' => ['in', $row['customer_product_id']]])->update([
  488. 'status' => 2
  489. ]);
  490. }
  491. //协助任务完成
  492. Event::where(['relation_type' => 'workorder', 'relation_id' => $row['id'], 'type' => 4])->update(['status' => 2]);
  493. Db::commit();
  494. } catch (Exception $e) {
  495. Db::rollback();
  496. $this->error($e->getMessage());
  497. }
  498. $this->success('工单完结成功');
  499. }
  500. //填写维修结果
  501. public function repair_result()
  502. {
  503. $params = $this->request->post();
  504. $id = input('id');
  505. $row = WorkorderModel::where(['id' => $id])->find();
  506. if (empty($row)) {
  507. $this->error('工单信息不存在');
  508. }
  509. Db::startTrans();
  510. try {
  511. WorkorderModel::repairResult($id, $params);
  512. Db::commit();
  513. } catch (Exception $e) {
  514. Db::rollback();
  515. $this->error($e->getMessage());
  516. }
  517. $this->success('提交成功');
  518. }
  519. //录入工单费用
  520. public function enterWorkorderMoney()
  521. {
  522. $params = $this->request->post();
  523. $id = input('id');
  524. $row = WorkorderModel::where(['id' => $id])->find();
  525. if (empty($row)) {
  526. $this->error('工单信息不存在');
  527. }
  528. Db::startTrans();
  529. try {
  530. WorkorderModel::enterWorkorderMoney($id, $params);
  531. Db::commit();
  532. } catch (Exception $e) {
  533. Db::rollback();
  534. $this->error($e->getMessage());
  535. }
  536. $this->success('提交成功');
  537. }
  538. //编辑优惠金额
  539. public function editDiscountMoney()
  540. {
  541. $id = input('id');
  542. $is_charge = input('is_charge', 0);//1 收费 2不收费
  543. $discount_money = input('discount_money', 0);
  544. $discount_desc = input('discount_desc', 0);
  545. if (empty($id)) {
  546. $this->error('参数错误');
  547. }
  548. $row = WorkorderModel::where(['id' => $id])->find();
  549. Db::startTrans();
  550. try {
  551. $money = sprintf('%.2f', $row['total_money'] - $discount_money);
  552. $update = [
  553. 'is_charge' => $is_charge,
  554. 'discount_money' => $discount_money,
  555. 'money' => $money,
  556. 'discount_desc' => $discount_desc
  557. ];
  558. //设置产品编号
  559. WorkorderModel::where(['id' => $id])->update($update);
  560. if ($is_charge == 2) {
  561. $content = '设置工单费用为[不收费]';
  562. } else {
  563. $content = '编辑优惠金额为[' . $discount_money . ']';
  564. }
  565. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  566. $params['relation_id'] = $id;
  567. $params['relation_process'] = '编辑优惠金额';
  568. //创建跟进记录
  569. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  570. Db::commit();
  571. } catch (Exception $e) {
  572. Db::rollback();
  573. $this->error($e->getMessage());
  574. }
  575. $this->success('修改工单信息成功');
  576. }
  577. //取消测试/继续测试
  578. public function isContinueTest()
  579. {
  580. $is_continue = input('is_continue');
  581. $id = input('id');
  582. Db::startTrans();
  583. try {
  584. WorkorderModel::continueTest($id, $is_continue);
  585. Db::commit();
  586. } catch (Exception $e) {
  587. Db::rollback();
  588. $this->error($e->getMessage());
  589. }
  590. $this->success('请求成功');
  591. }
  592. //获取支付类型
  593. public function getPayType()
  594. {
  595. $data = ['现金', '公户', '微信', '其他'];
  596. $this->success('请求成功', $data);
  597. }
  598. //获取微信支付二维码
  599. public function getPayOrder()
  600. {
  601. $id = input('id');
  602. $workorder = WorkorderModel::where(['id' => $id])->find();
  603. if (empty($workorder)) {
  604. $this->error('工单信息不存在');
  605. }
  606. $params = [
  607. 'amount' => $workorder['money'],
  608. 'orderid' => $workorder['workorder_number'],
  609. 'type' => "wechat",
  610. 'method' => "scan",//支付二维码
  611. 'title' => $workorder['title'],
  612. ];
  613. //回调链接
  614. $params['notifyurl'] = $this->request->root(true) . '/addons/qingdongams/workorder/notifyorder';
  615. $params['returnurl'] = $this->request->root(true) . '/addons/qingdongams/workorder/returnorder';
  616. //如果有安装支付插件,则调用插件的生成方法
  617. if (class_exists("\addons\epay\library\Service")) {
  618. $result =\addons\epay\library\Service::submitOrder($params);
  619. $this->success('请求成功', $result);
  620. }else{
  621. $this->error('未安装支付相关插件');
  622. }
  623. }
  624. /**
  625. * 支付成功,仅供开发测试
  626. */
  627. public function notifyorder()
  628. {
  629. $paytype = $this->request->param('paytype');
  630. Log::error('支付回调:' . json_encode($_REQUEST));
  631. if (class_exists("\addons\epay\library\Service")) {
  632. $pay =\addons\epay\library\Service::checkNotify($paytype);
  633. }else{
  634. $this->error('未安装支付相关插件');
  635. }
  636. if (!$pay) {
  637. Log::error('签名验证失败:' . json_encode($pay));
  638. return '签名错误';
  639. }
  640. $data = $pay->verify();
  641. try {
  642. $payamount = $paytype == 'alipay' ? $data['total_amount'] : $data['total_fee'] / 100;
  643. $out_trade_no = $data['out_trade_no'];
  644. $transaction_id = $data['transaction_id'];
  645. $find = WorkorderModel::where(['workorder_number' => $out_trade_no, 'pay_order' => $transaction_id])->find();
  646. if (empty($find)) {
  647. Log::error('未查询到订单:' . json_encode($out_trade_no));
  648. return $pay->success();
  649. }
  650. $result = WorkorderModel::where(['id' => $find['id']])->update([
  651. 'status' => 3,
  652. 'pay_type' => '微信',
  653. 'pay_order' => $transaction_id,
  654. 'pay_time' => time()]);
  655. if ($result == false) {
  656. throw new Exception('错误');
  657. }
  658. //你可以在此编写订单逻辑
  659. } catch (Exception $e) {
  660. return 'error';
  661. }
  662. return $pay->success();
  663. }
  664. //支付订单 去结算
  665. public function pay_order()
  666. {
  667. $id = input('id');
  668. $pay_type = input('pay_type', '');
  669. $pay_files = input('pay_files', '');
  670. if (empty($pay_type)) {
  671. $this->error('支付类型不能为空');
  672. }
  673. if (empty($pay_files)) {
  674. $this->error('支付凭证不能为空');
  675. }
  676. $row = WorkorderModel::where(['id' => $id])->find();
  677. if (empty($row)) {
  678. $this->error('订单不存在');
  679. }
  680. if ($row['is_pay'] == 1) {
  681. $this->error('订单已支付');
  682. }
  683. $update = ['is_pay' => 1, 'pay_time' => time(), 'pay_type' => $pay_type, 'pay_files' => $pay_files];
  684. //TODO 工单费用审核那里也有相同判断
  685. if ($row['workorder_type'] == '返厂维修') {
  686. $update['process'] = 5;
  687. } else if (in_array($row['workorder_type'], ['上门维修', '电话售后', '配件安装'])) {
  688. $update['status'] = 3;
  689. }
  690. if ($row['is_pay'] == 1) {
  691. //发送通知
  692. Message::addMessage(Message::WORKORDER_TYPE, $id, 1, $this->auth->id, '《' . $row->title . '》任务已完成,请您及时确认回款情况!');
  693. }
  694. $result = WorkorderModel::where(['id' => $id])->update($update);
  695. if (empty($result)) {
  696. $this->error('修改信息失败');
  697. }
  698. if (isset($update['status']) && $update['status'] == 3) {
  699. //工单完成
  700. WorkorderModel::setComplete($id);
  701. }
  702. $content = '支付维修费用成功';
  703. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  704. $params['relation_id'] = $row['id'];
  705. $params['files'] = $params['files'] ?? '';
  706. $params['relation_process'] = '支付费用';
  707. //创建跟进记录
  708. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  709. $this->success('支付订单成功');
  710. }
  711. //财务确认收款
  712. public function financial_audit()
  713. {
  714. $workorder_id = input('workorder_id', 0, 'intval');
  715. if (empty($workorder_id)) {
  716. $this->error('参数不能为空');
  717. }
  718. WorkorderModel::financialAudit($workorder_id);
  719. $this->success('确认收款成功');
  720. }
  721. //获取工单进度
  722. public function getLogs()
  723. {
  724. $workorder_id = input('workorder_id', 0, 'intval');
  725. $limit = input('limit', 10);
  726. $where = [
  727. 'relation_type' => StaffSignIn::WORKORDER_TYPE,
  728. ];
  729. if ($workorder_id) {
  730. $where['relation_id'] = $workorder_id;
  731. }
  732. $staffSign = StaffSignIn::where($where)->with(['staff', 'customer'])->order('id desc')->paginate($limit);
  733. //标记 日程已读
  734. Message::where([
  735. 'relation_type' => Message::RECORD_TYPE,
  736. 'to_staff_id' => $this->auth->id,
  737. 'status' => 0
  738. ])->update(['read_time' => time(), 'status' => 1]);
  739. $this->success('请求成功', $staffSign);
  740. }
  741. //添加工单备注
  742. public function addLog()
  743. {
  744. $params = $this->request->post();
  745. if (empty($params['id']) || empty($params['desc'])) {
  746. $this->error('参数不能为空');
  747. }
  748. if (empty($params['lng']) || empty($params['lat']) || empty($params['location'])) {
  749. $this->error('定位地理位置错误');
  750. }
  751. $row = WorkorderModel::get($params['id']);
  752. if (empty($row)) {
  753. $this->error('工单不存在');
  754. }
  755. try {
  756. $content = $params['desc'];
  757. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  758. $params['relation_id'] = $row['id'];
  759. //创建跟进记录
  760. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  761. } catch (Exception $e) {
  762. $this->error($e->getMessage());
  763. }
  764. $this->success('添加工单备注成功');
  765. }
  766. //设置产品编号
  767. public function setCustomerProductNumber()
  768. {
  769. $workorder_id = input('workorder_id');
  770. $product = input('product/a');
  771. $params = $this->request->post();
  772. try {
  773. Db::startTrans();
  774. if (!empty($product)) {
  775. foreach ($product as $v) {
  776. if (empty($v['id']) || empty($v['number'])) {
  777. throw new Exception('产品编号不能为空');
  778. }
  779. $hasBing = CustomerProduct::where(['id' => $v['id']])->find();
  780. if (!empty($hasBing['number'])) {
  781. $logicStatus = CustomerProduct::alias('c')->where(['number' => $hasBing['number']])->join('qingdongams_workorder w', 'w.customer_product_id=c.id', 'left')->field('w.id,w.process')->find();
  782. if ($logicStatus['process'] >= 3) {
  783. throw new Exception('产品编号[' . $hasBing['number'] . ']已配送,编号[' . $v['number'] . ']不能配送');
  784. }
  785. // 如果已经绑定,则原先设备 解绑
  786. Equipment::where(['number' => $hasBing['number']])->update(['binding_status' => 1, 'cus_pro_id' => 0]);
  787. }
  788. CustomerProduct::where(['id' => $v['id']])->update(['number' => $v['number'], 'file_ids' => $v['file_ids'] ?? '']);
  789. }
  790. }
  791. unset($params['product']);
  792. WorkorderModel::setProductNumber($workorder_id, $params);
  793. Db::commit();
  794. } catch (Exception $e) {
  795. Db::rollback();
  796. $this->error($e->getMessage());
  797. }
  798. $this->success('设置产品编号成功');
  799. }
  800. //设置配件配送信息
  801. public function setCustomerPartsNumber()
  802. {
  803. $workorder_id = input('workorder_id');
  804. $params = $this->request->post();
  805. try {
  806. Db::startTrans();
  807. WorkorderModel::setPartsNumber($workorder_id, $params);
  808. Db::commit();
  809. } catch (Exception $e) {
  810. Db::rollback();
  811. $this->error($e->getMessage());
  812. }
  813. $this->success('提交配送信息成功');
  814. }
  815. //获取客户地址
  816. public function getCustomerAddress()
  817. {
  818. $customer_id = input('customer_id');
  819. $address = \addons\qingdongams\model\Customer::where(['id' => $customer_id])->field('id,address,address_detail,lng,lat')->find();
  820. $this->success('请求成功', $address);
  821. }
  822. //添加物流信息
  823. public function addLogistics()
  824. {
  825. $title = input('title');//
  826. $workorder_id = input('workorder_id');//工单id
  827. $number = input('number');//物流编号
  828. $company = input('company');//物流方式
  829. $senderPhone = input('sender_phone');//发货人手机号 后四位
  830. $receiverPhone = input('receiver_phone');//发货人手机号 后四位
  831. $product_ids = input('product_ids');//产品id
  832. $type = input('type');//
  833. $money = input('money');//
  834. $file_ids = input('file_ids');
  835. if ($type == '物流配送') {
  836. if (empty($number)) {
  837. $this->error('物流编号不能为空');
  838. }
  839. }
  840. $workorder = WorkorderModel::where(['id' => $workorder_id])->find();
  841. if (empty($workorder)) {
  842. $this->error('工单不能为空');
  843. }
  844. $params = [
  845. 'title' => $title,
  846. 'customer_id' => $workorder['customer_id'],
  847. 'workorder_id' => $workorder_id,
  848. 'number' => $number,
  849. 'file_ids' => $file_ids,
  850. 'company' => $company,
  851. 'type' => $type,
  852. 'money' => $money,
  853. 'receiver_phone' => $senderPhone,
  854. 'sender_phone' => $receiverPhone,
  855. 'product_ids' => $product_ids,
  856. 'current_status' => json_encode(['text' => date('m-d H:i'), 'desc' => '提交物流信息'], JSON_UNESCAPED_UNICODE),
  857. 'content' => json_encode([['text' => date('m-d H:i'), 'desc' => '提交物流信息']], JSON_UNESCAPED_UNICODE),
  858. ];
  859. $customerInfo = Customer::where(['id' => $workorder['customer_id']])->find();
  860. try {
  861. Db::startTrans();
  862. WorkorderLogistics::createLogistics($params);
  863. $product_ids = explode(',', $product_ids);
  864. foreach ($product_ids as $id) {
  865. if ($workorder['is_install'] == 1) {
  866. if ($workorder['workorder_type'] == '配件配送') {
  867. //获取售后助理
  868. $addWorkorder = [
  869. 'workorder_number' => WorkorderModel::getWorkorderNumber(),
  870. 'workorder_type' => '配件安装',
  871. 'title' => '配件安装',
  872. 'customer_id' => $customerInfo['id'],
  873. 'contacts_id' => $workorder['contacts_id'],
  874. 'address' => $customerInfo['address'],
  875. 'address_detail' => $customerInfo['address_detail'],
  876. 'lng' => $customerInfo['lng'],
  877. 'lat' => $customerInfo['lat'],
  878. 'parts' => $workorder['parts'],
  879. 'priority' => '一般',
  880. 'owner_staff_id' => $workorder['owner_staff_id'],
  881. 'desc' => '自动生成安装工单'
  882. ];
  883. WorkorderModel::createWorkorder($addWorkorder);
  884. } else {
  885. $addWorkorder = [
  886. 'workorder_number' => WorkorderModel::getWorkorderNumber(),
  887. 'workorder_type' => '上门安装',
  888. 'title' => '上门安装',
  889. 'customer_id' => $customerInfo['id'],
  890. 'contacts_id' => $workorder['contacts_id'],
  891. 'address' => $customerInfo['address'],
  892. 'address_detail' => $customerInfo['address_detail'],
  893. 'lng' => $customerInfo['lng'],
  894. 'lat' => $customerInfo['lat'],
  895. 'customer_product_id' => $id,
  896. 'priority' => '一般',
  897. 'owner_staff_id' => $workorder['owner_staff_id'],
  898. 'desc' => '自动生成安装工单'
  899. ];
  900. WorkorderModel::createWorkorder($addWorkorder);
  901. }
  902. }
  903. }
  904. WorkorderModel::setLogistics($workorder_id, $product_ids);
  905. Db::commit();
  906. } catch (Exception $e) {
  907. Db::rollback();
  908. $this->error($e->getMessage());
  909. }
  910. $this->success('添加物流信息成功');
  911. }
  912. //修改物流信息
  913. public function editLogistics()
  914. {
  915. $id = input('id');//
  916. $title = input('title');//
  917. $number = input('number');//物流编号
  918. $company = input('company');//物流方式
  919. $senderPhone = input('sender_phone');//发货人手机号 后四位
  920. $receiverPhone = input('receiver_phone');//发货人手机号 后四位
  921. $product_ids = input('product_ids');//产品id
  922. $type = input('type');//
  923. $money = input('money');//
  924. $file_ids = input('file_ids');
  925. $logistics = WorkorderLogistics::where(['id' => $id])->find();
  926. if (empty($logistics)) {
  927. $this->error('物流信息不存在');
  928. }
  929. $params = [
  930. 'id' => $id,
  931. 'type' => $type,
  932. 'title' => $title,
  933. 'number' => $number,
  934. 'file_ids' => $file_ids,
  935. 'company' => $company,
  936. 'product_ids' => $product_ids,
  937. 'sender_phone' => $senderPhone,
  938. 'receiver_phone' => $receiverPhone,
  939. 'money' => $money,
  940. ];
  941. try {
  942. Db::startTrans();
  943. WorkorderLogistics::updateLogistics($params);
  944. Db::commit();
  945. } catch (Exception $e) {
  946. Db::rollback();
  947. $this->error($e->getMessage());
  948. }
  949. $this->success('修改物流信息成功');
  950. }
  951. //获取列表
  952. public function getWorkorderProduct()
  953. {
  954. $workorder_id = input("workorder_id", 0);
  955. $where = ['id' => $workorder_id];
  956. $workorder = WorkorderModel::where($where)->find();
  957. if (empty($workorder)) {
  958. $this->error('工单不存在');
  959. }
  960. $customer_product_ids = explode(',', $workorder['customer_product_id']);
  961. $customer_product = CustomerProduct::where(['id' => ['in', $customer_product_ids], 'status' => 0])->with(['product'])->select();
  962. $this->success('请求成功', $customer_product);
  963. }
  964. //获取物流信息
  965. public function getLogisticsList()
  966. {
  967. $workorder_id = input('workorder_id', '');
  968. $where = [];
  969. if (empty($workorder_id)) {
  970. $this->error('工单id不能为空');
  971. }
  972. $where['workorder_id'] = $workorder_id;
  973. $workorders = WorkorderLogistics::where($where)->select();
  974. $this->success('请求成功', $workorders);
  975. }
  976. //邀请其他部门协助
  977. public function addEvent()
  978. {
  979. $id = input('id');
  980. $staff_id = input('staff_id');
  981. $title = input('title');//
  982. $remark = input('remark');
  983. try {
  984. $params['staff_id'] = $staff_id;
  985. $params['title'] = $title;
  986. $params['remark'] = $remark;
  987. $params['type'] = 4;//协助任务
  988. $params['status'] = 1;//
  989. $params['relation_type'] = 'workorder';
  990. $params['relation_id'] = $id;
  991. $result = Event::createEvent($params);
  992. } catch (Exception $e) {
  993. $this->error($e->getMessage());
  994. }
  995. if ($result) {
  996. $this->success('添加日程成功');
  997. }
  998. }
  999. //协助任务 多条
  1000. public function addEvents()
  1001. {
  1002. $data = input('data/a');
  1003. if (empty($data)) {
  1004. $this->error('请添加协助人');
  1005. }
  1006. try {
  1007. $staffIds = [];
  1008. foreach ($data as $item) {
  1009. $staffIds[] = $item['staff_id'];
  1010. $params = [
  1011. 'staff_id' => $item['staff_id'] ?? 0,
  1012. 'title' => $item['title'] ?? '协助任务',
  1013. 'remark' => $item['remark'] ?? '',
  1014. 'type' => 4,//协助任务
  1015. 'status' => 1,//
  1016. 'relation_type' => 'workorder',
  1017. 'relation_id' => $item['id'],
  1018. ];
  1019. $result = Event::createEvent($params);
  1020. }
  1021. $row = WorkorderModel::get($item['id']);
  1022. if ($row['status'] == 1) {
  1023. $update = ['status' => 2];
  1024. if ($row['workorder_type'] == '设计工单') {
  1025. $update['process'] = 1;
  1026. }
  1027. $row->save($update);
  1028. Event::where(['relation_type' => 'workorder', 'relation_id' => $item['id'], 'type' => 1])
  1029. ->update(['status' => 1]);
  1030. }
  1031. $names = Staff::where(['id' => ['in', $staffIds],'status'=>1])->column('name');
  1032. $content = "邀请" . implode(',', $names) . "协作";
  1033. $data['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1034. $data['relation_id'] = $row['id'];
  1035. $data['relation_process'] = '邀请协作';
  1036. //创建跟进记录
  1037. StaffSignIn::quickSignIn($row['customer_id'], $content, $params);
  1038. } catch (Exception $e) {
  1039. $this->error($e->getMessage());
  1040. }
  1041. if ($result) {
  1042. $this->success('添加协助任务成功');
  1043. }
  1044. }
  1045. //添加电话沟通记录
  1046. public function addMobileLog()
  1047. {
  1048. $params = $this->request->post();
  1049. $is_complete = input('is_complete', 0);//是否解决 1 已解决 0 未解决
  1050. $id = input('id');
  1051. $desc = input('desc');
  1052. if ($is_complete == 1) {
  1053. $row = WorkorderModel::where(['id' => $id])->find();
  1054. if (empty($row)) {
  1055. $this->error('工单信息不存在');
  1056. }
  1057. Db::startTrans();
  1058. try {
  1059. $params['is_mobile'] = 1;
  1060. WorkorderModel::completeWorkorder($id, $desc, $params);
  1061. Db::commit();
  1062. } catch (Exception $e) {
  1063. Db::rollback();
  1064. $this->error($e->getMessage());
  1065. }
  1066. $this->success('工单完结成功');
  1067. } else {
  1068. $row = WorkorderModel::where(['id' => $id])->find();
  1069. if (empty($row)) {
  1070. $this->error('工单信息不存在');
  1071. }
  1072. if (empty($params['mobile_result'])) {
  1073. $this->error('电话结果不能为空');
  1074. }
  1075. $update = [];
  1076. $update['mobile_result'] = $params['mobile_result'] ?? '';//电话结果 1 已解决 11 上门服务 12 返厂维修
  1077. $update['logistics_type'] = $params['logistics_type'] ?? '';
  1078. $update['is_mobile'] = 1;
  1079. $update['status'] = 2;
  1080. $result = WorkorderModel::where(['id' => $id])->update($update);
  1081. $this->success('提交成功');
  1082. }
  1083. }
  1084. //获取快递公司
  1085. public function getCompanys()
  1086. {
  1087. $companys = Companys::where([])->column('com', 'no');
  1088. $this->success('请求成功', $companys);
  1089. }
  1090. //暂停工单
  1091. public function suspendWorkorder()
  1092. {
  1093. $id = input('id');
  1094. $params = $this->request->post();
  1095. if (empty($params['id']) || empty($params['desc'])) {
  1096. $this->error('参数不能为空');
  1097. }
  1098. if (empty($params['lng']) || empty($params['lat']) || empty($params['location'])) {
  1099. $this->error('定位地理位置错误');
  1100. }
  1101. $workorder = WorkorderModel::where(['id' => $id])->find();
  1102. if (empty($workorder)) {
  1103. $this->error('工单不存在');
  1104. }
  1105. if ($workorder['status'] != 2) {
  1106. $this->error('工单状态错误');
  1107. }
  1108. if (WorkorderModel::save(['is_pause' => 1], ['id' => $id]) != true) {
  1109. $this->error('操作失败');
  1110. }
  1111. $content = $params['desc'];
  1112. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1113. $params['relation_id'] = $workorder['id'];
  1114. $params['relation_process'] = '暂停工单';
  1115. //创建跟进记录
  1116. StaffSignIn::quickSignIn($workorder['customer_id'], $content, $params);
  1117. $this->success('暂停工单成功');
  1118. }
  1119. //继续工单
  1120. public function continueWorkorder()
  1121. {
  1122. $id = input('id');
  1123. $params = $this->request->post();
  1124. if (empty($params['id']) || empty($params['desc'])) {
  1125. $this->error('参数不能为空');
  1126. }
  1127. if (empty($params['lng']) || empty($params['lat']) || empty($params['location'])) {
  1128. $this->error('定位地理位置错误');
  1129. }
  1130. $workorder = WorkorderModel::where(['id' => $id])->find();
  1131. if (empty($workorder)) {
  1132. $this->error('工单不存在');
  1133. }
  1134. if ($workorder['is_pause'] != 1) {
  1135. $this->error('工单状态错误');
  1136. }
  1137. if (WorkorderModel::save(['is_pause' => 0], ['id' => $id]) != true) {
  1138. $this->error('操作失败');
  1139. }
  1140. $content = $params['desc'];
  1141. $params['relation_type'] = StaffSignIn::WORKORDER_TYPE;
  1142. $params['relation_id'] = $workorder['id'];
  1143. $params['relation_process'] = '继续工单';
  1144. //创建跟进记录
  1145. StaffSignIn::quickSignIn($workorder['customer_id'], $content, $params);
  1146. $this->success('继续工单成功');
  1147. }
  1148. //关闭工单
  1149. public function cancelWorkorder()
  1150. {
  1151. $id = input('id');
  1152. $desc = input('desc', '');
  1153. if (empty($id)) {
  1154. $this->error('id不能为空');
  1155. }
  1156. if (empty($desc)) {
  1157. $this->error('备注不能为空');
  1158. }
  1159. Db::startTrans();
  1160. try {
  1161. $result = WorkorderModel::cancelWorkorder($id, $desc);
  1162. Db::commit();
  1163. } catch (Exception $e) {
  1164. Db::rollback();
  1165. $this->error($e->getMessage());
  1166. }
  1167. $this->success('终止成功');
  1168. }
  1169. //撤销工单
  1170. public function revokeWorkorder()
  1171. {
  1172. $id = input('id');
  1173. $desc = input('desc', '');
  1174. if (empty($id)) {
  1175. $this->error('id不能为空');
  1176. }
  1177. if (empty($desc)) {
  1178. $this->error('备注不能为空');
  1179. }
  1180. $workorder=WorkorderModel::get($id);
  1181. if($workorder['owner_staff_id'] != $this->auth->id){
  1182. $this->error('只有负责人才能撤销工单');
  1183. }
  1184. Db::startTrans();
  1185. try {
  1186. $result = WorkorderModel::revokeWorkorder($id, $desc);
  1187. Db::commit();
  1188. } catch (Exception $e) {
  1189. Db::rollback();
  1190. $this->error($e->getMessage());
  1191. }
  1192. $this->success('撤销成功');
  1193. }
  1194. //回访工单工单
  1195. public function visitWorkorder()
  1196. {
  1197. $params = $this->request->post();
  1198. if (empty($params['id'])) {
  1199. $this->error('id不能为空');
  1200. }
  1201. Db::startTrans();
  1202. try {
  1203. $result = WorkorderModel::visitWorkorder($params);
  1204. Db::commit();
  1205. } catch (Exception $e) {
  1206. Db::rollback();
  1207. $this->error($e->getMessage());
  1208. }
  1209. $this->success('回访成功');
  1210. }
  1211. //回执工单
  1212. public function receiptWorkorder()
  1213. {
  1214. $params = $this->request->post();
  1215. if (empty($params['id'])) {
  1216. $this->error('id不能为空');
  1217. }
  1218. if (empty($params['receipt_file_ids'])) {
  1219. $this->error('回执单不能为空');
  1220. }
  1221. if (empty($params['receipt_date'])) {
  1222. $this->error('回执时间不能为空');
  1223. }
  1224. Db::startTrans();
  1225. try {
  1226. $result = WorkorderModel::receiptWorkorder($params);
  1227. Db::commit();
  1228. } catch (Exception $e) {
  1229. Db::rollback();
  1230. $this->error($e->getMessage());
  1231. }
  1232. $this->success('回执成功');
  1233. }
  1234. //签名
  1235. public function autograph()
  1236. {
  1237. $id = input('id');
  1238. $autograph_url = input('autograph_url', '');
  1239. if (empty($id)) {
  1240. $this->error('id不能为空');
  1241. }
  1242. Db::startTrans();
  1243. try {
  1244. $result = WorkorderModel::autograph($id, $autograph_url);
  1245. Db::commit();
  1246. } catch (Exception $e) {
  1247. Db::rollback();
  1248. $this->error($e->getMessage());
  1249. }
  1250. $this->success('签字成功');
  1251. }
  1252. //添加品质异常单进度
  1253. public function addProgress()
  1254. {
  1255. $params = $this->request->post();
  1256. $result=WorkorderModel::addProgress($params);
  1257. $this->success('操作成功');
  1258. }
  1259. //获取品质异常单进度列表
  1260. public function getProgressList()
  1261. {
  1262. $workorder_id = input('workorder_id');
  1263. $model = new WorkorderProgress();
  1264. $list = $model->where(['workorder_id' => $workorder_id])->column('*', 'create_staff_id');
  1265. $workorder = WorkorderModel::get($workorder_id);
  1266. $flow_staff_ids = explode(',', trim($workorder['flow_staff_ids'], ','));
  1267. $check_staff_ids = explode(',', trim($workorder['check_staff_ids'], ','));
  1268. $staffs = Staff::where(['id' => ['in', $flow_staff_ids],'status'=>1])->field('id,name,img,mobile')->select();
  1269. $staffs = collection($staffs)->toArray();
  1270. foreach ($staffs as $k => $v) {
  1271. if (in_array($v['id'], $check_staff_ids)) {
  1272. $v['is_check'] = 1;
  1273. $progress = $list[$v['id']] ?? [];
  1274. if($progress){
  1275. $progress['createtime'] = date('Y-m-d H:i:s',$progress['createtime']);
  1276. }
  1277. $v['progress'] = $progress;
  1278. } else {
  1279. $v['is_check'] = 0;
  1280. }
  1281. $staffs[$k] = $v;
  1282. }
  1283. $this->success('请求成功', $staffs);
  1284. }
  1285. //下载配件报价单
  1286. public function downloadWorkorder()
  1287. {
  1288. $id = input('id');
  1289. $type = input('type', 'word');
  1290. $workorder = WorkorderModel::where(['id' => $id])
  1291. ->with(['customer', 'contacts','ownerStaff'])->find();
  1292. if (empty($workorder)) {
  1293. $this->error('不能为空');
  1294. }
  1295. $workorder = $workorder->toArray();
  1296. $tmp = new TemplateProcessor('assets/addons/qingdongams/phpword/peijian.docx');
  1297. \PhpOffice\PhpWord\Settings::setCompatibility(true);
  1298. \PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true);
  1299. $tmp->setValue('number', $workorder['workorder_number']);//合同编号
  1300. $tmp->setValue('customer', $workorder['customer']['name']);//乙方
  1301. $tmp->setValue('name', $workorder['contacts']['name']);//乙方
  1302. $tmp->setValue('mobile', $workorder['contacts']['mobile']);//乙方
  1303. $tmp->setValue('date', $workorder['createtime']);//签订时间
  1304. $use_parts = $workorder['use_parts'];
  1305. $rda = [];
  1306. foreach ($use_parts as $v) {
  1307. if ($v['is_charge'] == 1) {
  1308. $rda[] = $v;
  1309. }
  1310. }
  1311. $rows = count($rda);//总行数
  1312. $pay_service = $workorder['pay_service'];
  1313. $tmp->cloneRow('one', $rows + count($pay_service));//复制行
  1314. for ($i = 0; $i < $rows; $i++) {
  1315. $tmp->setValue("one#" . ($i + 1), $i + 1);//名称
  1316. $tmp->setValue("two#" . ($i + 1), ($rda[$i]['name'] ?? '') . ($rda[$i]['num'] ?? ''));//
  1317. $tmp->setValue("three#" . ($i + 1), $rda[$i]['number'] ?? '');//
  1318. $tmp->setValue("four#" . ($i + 1), $rda[$i]['price'] ?? '');//
  1319. $tmp->setValue("five#" . ($i + 1), $rda[$i]['number'] * $rda[$i]['price']);//总价格
  1320. }
  1321. foreach ($pay_service as $item) {
  1322. $tmp->setValue("one#" . ($i + 1), $i + 1);//
  1323. $tmp->setValue("two#" . ($i + 1), $item['name']);//
  1324. $tmp->setValue("three#" . ($i + 1), '');//
  1325. $tmp->setValue("four#" . ($i + 1), '');//
  1326. $tmp->setValue("five#" . ($i + 1), $item['money']);//
  1327. $i++;
  1328. }
  1329. $tmp->setValue("price", $workorder['money']);//总价格
  1330. $tmp->setValue("tax", $workorder['tax']);//
  1331. if (empty($workorder['collection_img'])) {
  1332. $tmp->cloneBlock('img', 0);
  1333. } else {
  1334. $tmp->cloneBlock('img');
  1335. foreach ($workorder['collection_img'] as $v) {
  1336. //判断文件是否存在
  1337. if(@file_get_contents($v['url']) == false){
  1338. $tmp->setImageValue("collection_img",'./assets/addons/qingdongams/mini/close.png');
  1339. continue;
  1340. }
  1341. $tmp->setImageValue("collection_img", ['path' => $v['url'], 'width' => 200, 'height' => 200]);
  1342. }
  1343. }
  1344. if (empty($workorder['autograph_url'])) {
  1345. $tmp->cloneBlock('autograph', 0);
  1346. } else {
  1347. $tmp->cloneBlock('autograph');
  1348. $tmp->setImageValue("autograph_url", ['path' => $workorder['autograph_url'], 'width' => 200, 'height' => 200]);
  1349. }
  1350. if($workorder['owner_staff']){
  1351. $tmp->setValue('staff_name', $workorder['owner_staff']['name']);
  1352. $tmp->setValue('staff_mobile', $workorder['owner_staff']['mobile']);
  1353. $tmp->setValue('staff_email', $workorder['owner_staff']['email']);
  1354. }else{
  1355. $tmp->setValue('staff_name','');
  1356. $tmp->setValue('staff_mobile','');
  1357. $tmp->setValue('staff_email','');
  1358. }
  1359. if (empty($workorder['collection_deposit'])) {
  1360. $tmp->cloneBlock('account', 0);
  1361. } else {
  1362. $tmp->cloneBlock('account');
  1363. $tmp->setValue('collection_deposit', $workorder['collection_deposit']);
  1364. $tmp->setValue('collection_account', $workorder['collection_account']);
  1365. $tmp->setValue('collection_name', $workorder['collection_name']);
  1366. }
  1367. //end 配置
  1368. $filename = date('YmdHis') . '.docx';
  1369. $fileurl = './docx/' . date('Ymd') . '/';
  1370. if (!file_exists($fileurl)) {
  1371. mkdir($fileurl);
  1372. }
  1373. $tmp->saveAs($fileurl . $filename);//另存为
  1374. $model = new \addons\qingdongams\model\File();
  1375. $data = [
  1376. 'types' => 'file',
  1377. 'name' => $filename,
  1378. 'save_name' => $fileurl . $filename,
  1379. 'size' => filesize($fileurl . $filename),
  1380. 'file_path' => trim($fileurl, '.') . $filename,
  1381. ];
  1382. $model->save($data);
  1383. $lastid = $model->getLastInsID();
  1384. $file = cdnurl($model::getUrl($lastid), true);
  1385. $this->success('请求成功', ['file' => $file, 'id' => $lastid, 'filename' => $filename]);
  1386. }
  1387. //下载返厂维修
  1388. public function downloadFanchang()
  1389. {
  1390. $id = input('id');
  1391. $type = input('type', 'word');
  1392. $workorder = WorkorderModel::where(['id' => $id])
  1393. ->with(['customer', 'contacts', 'ownerStaff'])->find();
  1394. if (empty($workorder)) {
  1395. $this->error('不能为空');
  1396. }
  1397. if (empty($workorder['contacts'])) {
  1398. $workorder['contacts'] = \addons\qingdongams\model\Contacts::where(['customer_id' => $workorder['customer_id']])->order('is_major desc')->field('id,customer_id,name,mobile,mobilecode,region')->find();
  1399. }
  1400. $workorder = $workorder->toArray();
  1401. $tmp = new TemplateProcessor('assets/addons/qingdongams/phpword/fanchang.docx');
  1402. \PhpOffice\PhpWord\Settings::setCompatibility(true);
  1403. \PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true);
  1404. $tmp->setValue('number', $workorder['workorder_number']);//合同编号
  1405. $tmp->setValue('name', $workorder['customer']['name']);//乙方
  1406. $tmp->setValue('mobile', $workorder['contacts']['mobile']);//乙方
  1407. $tmp->setValue('date', $workorder['createtime']);//签订时间
  1408. $tmp->setValue('desc', $workorder['desc']);//
  1409. $tmp->setValue('matters', $workorder['matters']);//
  1410. $tmp->setValue('appointment_time', $workorder['appointment_time']);//
  1411. $product_name = '';
  1412. foreach ($workorder['product_part'] as $v) {
  1413. $product_name .= $v['product']['name'];
  1414. }
  1415. $tmp->setValue('product_name', $product_name);//
  1416. //end 配置
  1417. $filename = $workorder['customer']['name'] . '返厂维修单' . date('Ymdhis') . '.docx';
  1418. $fileurl = './docx/' . date('Ymd') . '/';
  1419. if (!file_exists($fileurl)) {
  1420. mkdir($fileurl);
  1421. }
  1422. $tmp->setValue('owner_staff', $workorder['owner_staff']['name']);//
  1423. $tmp->setValue('results', $workorder['results']);//
  1424. $use_parts = '';
  1425. foreach ($workorder['use_parts'] as $v) {
  1426. $use_parts .= $v['name'] . '(' . $v['number'] . ');';
  1427. };
  1428. $tmp->setValue('use_parts', $use_parts);//
  1429. $tmp->setValue('maintain', $workorder['maintain']);//
  1430. $tmp->setValue('end_time', $workorder['end_time']);//
  1431. $tmp->setValue('is_replace_0', $workorder['is_replace'] == 0 ? '✔️' : '');//
  1432. $tmp->setValue('is_replace_1', $workorder['is_replace'] == 1 ? '✔️' : '');//
  1433. $tmp->setValue('is_recovery_0', $workorder['is_recovery'] == 0 ? '✔️' : '');//
  1434. $tmp->setValue('is_recovery_1', $workorder['is_recovery'] == 1 ? '✔️' : '');//
  1435. $tmp->saveAs($fileurl . $filename);//另存为
  1436. $model = new \addons\qingdongams\model\File();
  1437. $data = [
  1438. 'types' => 'file',
  1439. 'name' => $filename,
  1440. 'save_name' => $fileurl . $filename,
  1441. 'size' => filesize($fileurl . $filename),
  1442. 'file_path' => trim($fileurl, '.') . $filename,
  1443. ];
  1444. $model->save($data);
  1445. $lastid = $model->getLastInsID();
  1446. $file = cdnurl($model::getUrl($lastid), true);
  1447. if ($type == 'pdf') {
  1448. $docfile = $_SERVER['DOCUMENT_ROOT'] . trim($data['save_name'], '.'); // word文件
  1449. $pdfdir = $_SERVER['DOCUMENT_ROOT'] . trim($fileurl, '.'); // pdf文件
  1450. $cmd = "export HOME=/tmp && libreoffice --headless -convert-to pdf {$docfile} -outdir {$pdfdir}";
  1451. @exec($cmd);
  1452. $pathinfo = pathinfo($file);
  1453. $file = $pathinfo['dirname'] . '/' . $pathinfo['filename'] . '.pdf';
  1454. $filename = $pathinfo['filename'] . '.pdf';
  1455. }
  1456. $this->success('请求成功', ['file' => $file, 'id' => $lastid, 'filename' => $filename]);
  1457. }
  1458. /**
  1459. * 生成二维码
  1460. */
  1461. public function qrcode()
  1462. {
  1463. $text = $this->request->get('text', 'hello world');
  1464. //如果有安装二维码插件,则调用插件的生成方法
  1465. if (class_exists("\addons\qrcode\library\Service") && get_addon_info('qrcode')['state']) {
  1466. $qrCode = \addons\qrcode\library\Service::qrcode(['text' => $text]);
  1467. $response = Response::create()->header("Content-Type", "image/png");
  1468. header('Content-Type: ' . $qrCode->getContentType());
  1469. $response->content($qrCode->writeString());
  1470. return $response;
  1471. } else {
  1472. header("Content-type: image/png");
  1473. $qr = QRCode::getMinimumQRCode($text);
  1474. $im = $qr->createImage(8, 5);
  1475. imagepng($im);
  1476. imagedestroy($im);
  1477. return;
  1478. }
  1479. }
  1480. //获取车牌号
  1481. public function getCarNumber()
  1482. {
  1483. $car_numbers = ConsumeDetail::where(['car_number' => ['neq', '']])->column('car_number');
  1484. $car_numbers = array_unique($car_numbers);
  1485. $this->success('请求成功', $car_numbers);
  1486. }
  1487. //获取结束公里数
  1488. public function getEndMileage()
  1489. {
  1490. $car_number = input('car_number');
  1491. $end_mileage = ConsumeDetail::where(['car_number' => $car_number,
  1492. 'end_mileage' => ['neq', '']])->order('id desc')->value('end_mileage');
  1493. $this->success('请求成功', ['end_mileage' => $end_mileage ?? 0]);
  1494. }
  1495. //
  1496. public function training_content()
  1497. {
  1498. $id = input('id');
  1499. $data = [
  1500. [
  1501. 'id' => 1,
  1502. 'name' => '培训内容',
  1503. 'data' => [
  1504. '使用、保养',
  1505. ],
  1506. ],
  1507. ];
  1508. $this->success('请求成功', $data);
  1509. }
  1510. //工单失败
  1511. public function failWorkorder()
  1512. {
  1513. $id = input('id');
  1514. $desc = input('desc');
  1515. //
  1516. $params = $this->request->post();
  1517. if (empty($id)) {
  1518. $this->error('参数错误');
  1519. }
  1520. $workorder = WorkorderModel::get($id);
  1521. if (empty($workorder)) {
  1522. $this->error('信息不存在');
  1523. }
  1524. Db::startTrans();
  1525. try {
  1526. WorkorderModel::failWorkorder($id,$desc);
  1527. Db::commit();
  1528. } catch (Exception $e) {
  1529. Db::rollback();
  1530. $this->error($e->getMessage());
  1531. }
  1532. $this->success('提交成功');
  1533. }
  1534. //获取协助任务列表
  1535. public function getAssistTaskList()
  1536. {
  1537. $relation_id = input('relation_id', '', 'intval');
  1538. $relation_type = input('relation_type', 'proofing');
  1539. $customer_id = input('customer_id');
  1540. // 0未开始 1执行中2 已结束 3 已取消'
  1541. $status = input('status', '');
  1542. $event_type = input('event_type', '');
  1543. $name = input('name', '');
  1544. $limit = input("limit/d", 10);
  1545. $where = [];
  1546. if ($relation_id) {
  1547. $where['relation_type'] = $relation_type;
  1548. $where['relation_id'] = $relation_id;
  1549. } else {
  1550. $where['create_staff_id|staff_id'] = ['in', Staff::getMyStaffIds()];
  1551. }
  1552. if ($customer_id) {
  1553. $where['customer_id'] = $customer_id;
  1554. }
  1555. if ($event_type) {
  1556. $where['event_type'] = ['like', "%{$event_type}%"];
  1557. }
  1558. if ($status) {
  1559. $where['status'] = ['in', explode(',', $status)];
  1560. }
  1561. $where['type'] = 4;
  1562. if ($name) {
  1563. $where['title'] = ['like', '%' . $name . '%'];
  1564. }
  1565. $records = Event::where($where)->with([
  1566. 'staff',
  1567. 'customer',
  1568. 'comments',
  1569. ])->order('id desc')->select();
  1570. $records = collection($records)->toArray();
  1571. $department = [];
  1572. foreach ($records as $v) {
  1573. Message::setRead(Message::ASSIST_EVENT_TYPE, $v['id'], $this->auth->id);
  1574. $v['status'] = Event::getStatus($v['status']);
  1575. $department[$v['staff']['department_id']][] = $v;
  1576. }
  1577. $data = [];
  1578. foreach ($department as $id => $v) {
  1579. $data[] = [
  1580. 'department_id' => $id,
  1581. 'department_name' => '',
  1582. 'data' => $v
  1583. ];
  1584. }
  1585. $this->success('请求成功', $data);
  1586. }
  1587. public function getWorkorderDepartment()
  1588. {
  1589. $data = [];
  1590. $this->success('请求成功', $data);
  1591. }
  1592. }