Statistics.php 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. <?php
  2. namespace app\admin\controller\workorder;
  3. use app\common\controller\Backend;
  4. use think\Db;
  5. /**
  6. * 工单管理
  7. *
  8. * @icon fa fa-circle-o
  9. */
  10. class Statistics extends Backend
  11. {
  12. /**
  13. * 模型对象
  14. * @var \app\admin\model\workorder\Statistics
  15. */
  16. public function _initialize()
  17. {
  18. parent::_initialize();
  19. }
  20. public function index()
  21. {
  22. if ($this->request->isAjax()) {
  23. $this->success('', null, $this->dateOrderTrend());
  24. }
  25. // 沟通处理中
  26. $pending_wo_total = Db::name('workorder_orders')
  27. ->where('status', 'in', '2,3')
  28. ->where('deletetime', null)
  29. ->count('id');
  30. // 未结单
  31. $open_wo_total = Db::name('workorder_orders')
  32. ->where('status', 'in', '0,1,2,3')
  33. ->where('deletetime', null)
  34. ->count('id');
  35. // 待分派
  36. $assign_wo_total = Db::name('workorder_orders')->where('status', '0')->where('deletetime', null)->count('id');
  37. // 解决率和满意度
  38. $evaluate = Db::name('workorder_evaluate')
  39. ->alias('e')
  40. ->field('e.stars,e.solved')
  41. ->join('workorder_orders o', 'o.id=e.order_id')
  42. ->where('o.deletetime', null)
  43. ->select();
  44. $not_evaluated = Db::name('workorder_orders')->where('status', '4')->where('deletetime', null)->count('id');
  45. $solved_temp = [0, 0];
  46. $stars_temp = [0, 0, 0, 0, 0];
  47. foreach ($evaluate as $index => $item) {
  48. if ($item['solved'] == 0) {
  49. $solved_temp[0]++;
  50. } else {
  51. $solved_temp[1]++;
  52. }
  53. $stars_temp[($item['stars'] - 1)]++;
  54. }
  55. if ($solved_temp[0] > 0) {
  56. $solved[] = [
  57. 'value' => $solved_temp[0],
  58. 'name' => __('unresolved')
  59. ];
  60. }
  61. if ($solved_temp[1] > 0) {
  62. $solved[] = [
  63. 'value' => $solved_temp[1],
  64. 'name' => __('resolved')
  65. ];
  66. }
  67. for ($i = 0; $i < 5; $i++) {
  68. if ($stars_temp[$i] > 0) {
  69. $stars[] = [
  70. 'value' => $stars_temp[$i],
  71. 'name' => __('star ' . $i)
  72. ];
  73. }
  74. }
  75. if ($not_evaluated > 0) {
  76. $stars[] = [
  77. 'value' => $not_evaluated,
  78. 'name' => __('Not evaluated')
  79. ];
  80. $solved[] = [
  81. 'value' => $not_evaluated,
  82. 'name' => __('Not evaluated')
  83. ];
  84. }
  85. if (!isset($stars)) {
  86. $stars[] = [
  87. 'value' => 0,
  88. 'name' => __('No data available')
  89. ];
  90. }
  91. if (!isset($solved)) {
  92. $solved[] = [
  93. 'value' => 0,
  94. 'name' => __('No data available')
  95. ];
  96. }
  97. $average_time['solution'] = Db::name('workorder_time_statistics')
  98. ->alias('s')
  99. ->join('workorder_orders o', 'o.id=s.order_id')
  100. ->where('o.deletetime', null)
  101. ->where('s.type', 0)
  102. ->where('s.time_consum', '>', 0)
  103. ->avg('s.time_consum');
  104. $average_time['response'] = Db::name('workorder_time_statistics')
  105. ->alias('s')
  106. ->join('workorder_orders o', 'o.id=s.order_id')
  107. ->where('o.deletetime', null)
  108. ->where('s.type', 'in', '1,2')
  109. ->where('s.time_consum', '>', 0)
  110. ->avg('s.time_consum');
  111. $average_time['first_response'] = Db::name('workorder_time_statistics')
  112. ->alias('s')
  113. ->join('workorder_orders o', 'o.id=s.order_id')
  114. ->where('o.deletetime', null)
  115. ->where('s.type', 2)
  116. ->where('s.time_consum', '>', 0)
  117. ->avg('s.time_consum');
  118. foreach ($average_time as $key => $value) {
  119. if ($value) {
  120. $h = floor($value / 3600);
  121. $m = ceil(($value % 3600) / 60);
  122. $average_time[$key] = [
  123. 'value' => __('%s hour %s minute', [$h, $m]),
  124. 'progress' => ceil($h . '.' . $m)
  125. ];
  126. $average_time[$key]['progress'] = ($average_time[$key]['progress'] > 100) ? 100 : $average_time[$key]['progress'];
  127. } else {
  128. $average_time[$key] = [
  129. 'value' => __('No data'),
  130. 'progress' => 0
  131. ];
  132. }
  133. }
  134. $prefix = config('database.prefix');
  135. // 类别工单量TOP10
  136. $sql = "SELECT wc.id,wc.name,
  137. (SELECT count(id) FROM {$prefix}workorder_orders wo WHERE wo.category_id=wc.id AND wo.deletetime IS NULL) as order_quantity
  138. FROM {$prefix}workorder_category wc WHERE wc.pid>0 AND wc.deletetime IS NULL ORDER BY order_quantity DESC";
  139. $workorder_category_top10 = Db::query($sql);
  140. $order_quantity_sum = array_sum(array_map(function ($val) {
  141. return $val['order_quantity'];
  142. }, $workorder_category_top10));
  143. foreach ($workorder_category_top10 as $index => $item) {
  144. if ($index <= 9) {
  145. if ($item['order_quantity'] > 0) {
  146. $workorder_category_top10[$index]['progress'] = round(($item['order_quantity'] / $order_quantity_sum) * 100, 2);
  147. } else {
  148. $workorder_category_top10[$index]['progress'] = 0;
  149. }
  150. } else {
  151. unset($workorder_category_top10[$index]);
  152. }
  153. }
  154. $workorder_engineers_top10 = Db::name('workorder_engineers')
  155. ->field('id,title,work_order_quantity')
  156. ->where('deletetime', null)
  157. ->where('status', '1')
  158. ->order('work_order_quantity desc')
  159. ->limit(10)
  160. ->select();
  161. $avg_response_time_top10 = Db::name('workorder_engineers')
  162. ->field('id,title,avg_response_time')
  163. ->where('deletetime', null)
  164. ->where('status', '1')
  165. ->order('avg_response_time desc')
  166. ->limit(10)
  167. ->select();
  168. foreach ($avg_response_time_top10 as $index => $item) {
  169. if ($item['avg_response_time'] > 0) {
  170. $h = floor($item['avg_response_time'] / 3600);
  171. $m = ceil(($item['avg_response_time'] % 3600) / 60);
  172. $avg_response_time_top10[$index]['avg_response_time'] = __('%s hour %s minute', [$h, $m]);
  173. } else {
  174. $avg_response_time_top10[$index]['avg_response_time'] = __('No data');
  175. }
  176. }
  177. $this->view->assign([
  178. 'wo_total' => Db::name('workorder_orders')->where('deletetime', null)->count('id'),
  179. 'pending_wo_total' => $pending_wo_total,
  180. 'open_wo_total' => $open_wo_total,
  181. 'assign_wo_total' => $assign_wo_total,
  182. 'average_time' => $average_time,
  183. 'workorder_category_top10' => $workorder_category_top10,
  184. 'workorder_engineers_top10' => $workorder_engineers_top10,
  185. 'avg_response_time_top10' => $avg_response_time_top10
  186. ]);
  187. $this->assignconfig([
  188. 'orderTrend' => $this->dateOrderTrend(),
  189. 'solved' => $solved,
  190. 'stars' => $stars
  191. ]);
  192. return $this->view->fetch();
  193. }
  194. /**
  195. * 日期范围内的订单趋势
  196. */
  197. public function dateOrderTrend()
  198. {
  199. $date = $this->request->request('date');
  200. if ($date) {
  201. $date = explode(' - ', $date);
  202. $date = array_map("strtotime", $date);
  203. } else {
  204. $date[0] = \fast\Date::unixtime('day', -6);
  205. $date[1] = \fast\Date::unixtime('day', 0, 'end');
  206. }
  207. if ($date[0] >= $date[1]) {
  208. $this->error(__('The start time must be less than the end time'));
  209. }
  210. $orders = Db::name('workorder_orders')
  211. ->field("id,createtime")
  212. ->where('deletetime', null)
  213. ->where('createtime', 'BETWEEN', implode(',', $date))
  214. ->order('createtime asc')
  215. ->select();
  216. $temp = [];
  217. $columns = [];
  218. $data = [];
  219. if (($date[1] - $date[0]) <= 86400) {
  220. // 时间数组准备
  221. for ($i = 0; $i <= 23; $i++) {
  222. $temp[($i < 10 ? '0' . $i : $i) . ':00'] = 0;
  223. }
  224. // 累计各个时间的订单量
  225. foreach ($orders as $index => $item) {
  226. $createtime = date('H', $item['createtime']) . ':00';
  227. $temp[$createtime]++;
  228. }
  229. } else {
  230. // 日期数组准备
  231. do {
  232. $temp[date('Y-m-d', $date[0])] = 0;
  233. $date[0] = $date[0] + 86400;
  234. } while ($date[0] < $date[1]);
  235. // 累计各个日期的订单量
  236. foreach ($orders as $index => $item) {
  237. $createtime = date('Y-m-d', $item['createtime']);
  238. $temp[$createtime]++;
  239. }
  240. }
  241. foreach ($temp as $index => $item) {
  242. $columns[] = $index;
  243. $data[] = $item;
  244. }
  245. return [
  246. 'columns' => $columns,
  247. 'data' => $data,
  248. 'sum' => array_sum($data)
  249. ];
  250. }
  251. }