diff --git a/application/admin/controller/aftersales/Aftersale.php b/application/admin/controller/aftersales/Aftersale.php index 7bf3b54..652e306 100644 --- a/application/admin/controller/aftersales/Aftersale.php +++ b/application/admin/controller/aftersales/Aftersale.php @@ -58,7 +58,7 @@ class Aftersale extends Backend if ($this->request->isAjax()) { $from = $this->request->param('from',1); - $dispatch_admin_id = $this->request->param('dispatch_admin_id'); + $man_id = $this->request->param('man_id'); //如果发送的来源是Selectpage,则转发到Selectpage if ($this->request->request('keyField')) { @@ -73,9 +73,16 @@ class Aftersale extends Backend if($from == 2){ //$builder->where('refund_amount','>',0); //$builder->where('status','<>',-1); - $builder->where('fa_aftersale.dispatch_admin_id',$dispatch_admin_id ?: 0); + $builder->where('fa_aftersale.dispatch_admin_id',$man_id ?: 0); } + + if($from == 3){ + //$builder->where('refund_amount','>',0); + //$builder->where('status','<>',-1); + $builder->where('fa_aftersale.worker_id',$man_id ?: 0); + } + $list = $builder->order($sort, $order) ->paginate($limit); diff --git a/application/admin/controller/statistics/Worker.php b/application/admin/controller/statistics/Worker.php index 43018db..20fb886 100644 --- a/application/admin/controller/statistics/Worker.php +++ b/application/admin/controller/statistics/Worker.php @@ -6,7 +6,10 @@ use app\admin\model\Admin; use app\admin\model\Aftersale; use app\admin\model\Order; use app\admin\model\OrderDispatch; +use app\admin\model\OrderReview; use app\common\controller\Backend; +use PDOStatement; +use think\Collection; use think\Exception; use think\exception\DbException; use think\response\Json; @@ -108,126 +111,140 @@ class Worker extends Backend if ($this->request->request('keyField')) { return $this->selectpage(); } + + + //派单表 + $dispatchSubsql = $this->dispatchSubsql(); + //订单表 + $orderSubsql = $this->oderSubsql(); + //评分表 + $viewSubsql = OrderReview::where('worker_star',5)->field(['worker_id','count(*) as good_count'])->group('worker_id')->buildSql(); + [$where, $sort, $order, $offset, $limit] = $this->buildparams(); - $list = $this->model + $list = $this->model->alias('fa_worker') + ->with(['area']) + ->field([ + 'fa_worker.*', + 'IFNULL(a.dispatch_count, 0) AS dispatch_count', + 'IFNULL(a.get_count, 0) AS get_count', + 'IFNULL(a.refuse_count, 0) AS refuse_count', + 'IFNULL(a.arrive_count, 0) AS arrive_count', + 'IFNULL(a.avg_time_diff, 0) AS avg_time_diff', + 'IFNULL(b.finish_num, 0) AS finish_num', + 'IFNULL(b.total, 0) AS total', + 'IFNULL(b.performance, 0) AS performance', + 'IFNULL(b.refund_total, 0) AS refund_total', + 'IFNULL(b.refund_count, 0) AS refund_count', + 'IFNULL(b.cost, 0) AS cost', + 'IFNULL(c.good_count, 0) AS good_count' + ]) + ->join([$dispatchSubsql => 'a'], 'fa_worker.id = a.worker_id', 'LEFT') + ->join([$orderSubsql => 'b'], 'fa_worker.id = b.worker_id', 'LEFT') + ->join([$viewSubsql => 'c'], 'fa_worker.id = c.worker_id', 'LEFT') ->where($where) ->order($sort, $order) ->paginate($limit); + + $this->_toList($list); $result = ['total' => $list->total(), 'rows' => $list->items()]; return json($result); } + /** + * @return bool|PDOStatement|string|Collection + * @throws DbException + */ + public function dispatchSubsql(): Collection|bool|string|PDOStatement + { + $builder = new OrderDispatch(); + $fields = [ + 'worker_id', + "COUNT(*) AS dispatch_count", //分配数 + "COUNT(CASE WHEN status NOT IN (0, -10) THEN 1 END) AS get_count", //接单数 + //"COUNT(CASE WHEN status IN (60) THEN 1 END) AS finish_count", //完成数 + "COUNT(CASE WHEN status NOT IN (-10) THEN 1 END) AS refuse_count", //拒绝数 + "COUNT(arrive_time) AS arrive_count", //上门数 + "AVG(CASE WHEN status = 60 AND arrive_time IS NOT NULL THEN UNIX_TIMESTAMP(arrive_time) - UNIX_TIMESTAMP(create_time) END) AS avg_time_diff", //联系时效 + ]; + $builder->field($fields); + $builder->group('worker_id'); + return $builder->buildSql(); + } + //图表统计 - public function chart($filter,$getAll=false){ - - - - $orderValid = implode(',',$this->model->tabStatus(Order::TAB_VALID)); + /** + * @throws DbException + */ + public function oderSubsql() + { + $orderValid = implode(',',(new Order())->tabStatus(Order::TAB_VALID)); //"COUNT(CASE WHEN status IN (".$orderValid.") THEN 1 END) AS ing_num", $fields = [ - 'dispatch_admin_id', + 'worker_id', "COUNT(CASE WHEN status = 60 THEN 1 END) AS finish_num", //完成数 - "COUNT(CASE WHEN status IN (".$orderValid.") THEN 1 END) AS count_num", //总订单数 (排除取消 和草稿) + //"COUNT(CASE WHEN status IN (".$orderValid.") THEN 1 END) AS count_num", //总订单数 (排除取消 和草稿) "SUM(CASE WHEN status = 60 THEN total END) AS total", //成效额 "SUM(CASE WHEN status = 60 THEN performance END) AS performance", //业绩 + "SUM(CASE WHEN status = 60 THEN cost END) AS cost", //成效额 - "SUM(CASE WHEN status = 60 THEN (cost + material_cost) END) AS cost_total", //总成本 + // "SUM(CASE WHEN status = 60 THEN (cost + material_cost) END) AS cost_total", //总成本 "SUM(CASE WHEN status = 60 THEN (refund_amount + worker_refund_amount) END) AS refund_total", //退款总数 "COUNT(CASE WHEN refund_amount > 0 OR worker_refund_amount > 0 THEN 1 END) AS refund_count", //退款订单数量 - "AVG(CASE WHEN status > 10 THEN UNIX_TIMESTAMP(dispatch_time) - UNIX_TIMESTAMP(create_time) END) AS avg_time_diff", //派单时效 + //"AVG(CASE WHEN status > 10 THEN UNIX_TIMESTAMP(dispatch_time) - UNIX_TIMESTAMP(create_time) END) AS avg_time_diff", //派单时效 // "SUM(CASE WHEN status = 60 THEN (field1 + field2) END) AS performance", ]; - $builder = $this->model - ->field($fields); + $builder = (new Order())->field($fields); //->where('dispatch_admin_id','>',0); + return $builder->group('worker_id')->buildSql(); - if(!empty($filter['admin_id'])){ - $builder->where('dispatch_admin_id',$filter['admin_id']); - } - - if(!empty($filter['start_time']) && !empty($filter['end_time'])){ - $time_by = $filter['time_by'] ??1; - if($time_by == 1){ //按派单时间 - $time_field = 'dispatch_time'; - }else{ //按录单时间 - $time_field = 'create_time'; - } - $builder->whereBetween($time_field,[$filter['start_time'],$filter['end_time']]); - } - //城市 - if(!empty($filter['area_id'])){ - $builder->where('area_id',$filter['area_id']); - } - //项目 - if(!empty($filter['item_id'])){ - $builder->where('item_id',$filter['item_id']); - } - - if($getAll){ - $data = $builder->group('dispatch_admin_id')->limit(50)->select(); - }else{ - $data = $builder->group('dispatch_admin_id')->paginate(); - } - - $newData = []; - - if(!empty($data)){ - foreach ($data as &$datum){ - //利润率 = 总业绩/总成效额 - $datum->performance_rate = $this->_calc($datum->performance,$datum->total,4,true); - //转化率 = 完单数 / 总订单数 - $datum->trans_rate = $this->_calc($datum->finish_num,$datum->count_num,4,true); - //变现值 = 总业绩 / 总订单数 - $datum->cash_value = $this->_calc($datum->performance,$datum->count_num,2); - //客单利润 = 总利润 / 完单数 - $datum->performance_avg = $this->_calc($datum->performance,$datum->finish_num,2); - //客单价 = 总成效额 / 完单数 - $datum->total_avg = $this->_calc($datum->total,$datum->finish_num,2); - - if(!empty($datum->dispatch_admin_id)){ - $datum->admin_user = Admin::where($datum->dispatch_admin_id)->value('nickname')??'系统'; - }else{ - $datum->admin_user = '系统'; - } - $datum->avg_time_diff = $this->_calc($datum->avg_time_diff,3600*24,2); - - $datum->id = $datum->dispatch_admin_id; - $newData[] = $datum->toArray(); - } - } - - if($getAll){ - return $newData; - }else{ - return $data; - } - //dump($newData);exit; } /** * @param $a * @param $b - * @param $scale + * @param int $scale + * @param bool $is_percent * @return int|string */ - private function _calc($a,$b,$scale=4,$is_percent=false){ - $val = $b > 0 ? bcdiv($a,$b,$scale) : 0; + private function _calc($a, $b, int $scale=4, bool $is_percent=false): int|string + { + $a = $a??0; + $b = $b??0; + $val = $b > 0 ? bcdiv($a,$b,$scale) : '0.00'; if($is_percent){ - return bcmul($val,100,2); } return $val; } + private function _toList(\think\Paginator $list) + { + foreach ($list as &$datum){ + //利润率 = 总业绩/总成效额 + $datum->performance_rate = $this->_calc($datum->performance,$datum->total,4,true); + //转化率 = 完单数 / 总接单数 + $datum->trans_rate = $this->_calc($datum->finish_num,$datum->get_count,4,true); + //变现值 = 总业绩 / 总接单数 + $datum->cash_value = $this->_calc($datum->performance,$datum->get_count,2); + //拒单率 = 拒绝数 / 派单数 + $datum->refuse_rate = $this->_calc($datum->refuse_count,$datum->dispatch_count,4,true); + //上门率 = 打卡数 / 接单数 + $datum->arrive_rate = $this->_calc($datum->arrive_count,$datum->get_count,4,true); + //好评率 + $datum->arrive_rate = $this->_calc($datum->good_count,$datum->finish_num,4,true); + + $datum->avg_time_diff = $this->_calc($datum->avg_time_diff,3600*24,2); + } + } } diff --git a/public/assets/js/backend/statistics/dispatcher.js b/public/assets/js/backend/statistics/dispatcher.js index fa4824e..625344a 100644 --- a/public/assets/js/backend/statistics/dispatcher.js +++ b/public/assets/js/backend/statistics/dispatcher.js @@ -68,7 +68,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts', 'echarts-t title:"售后列表", icon: 'fa fa-list', url: function(row){ - return 'aftersales/aftersale/index?from=2&dispatch_admin_id='+row.id; + return 'aftersales/aftersale/index?from=2&man_id='+row.id; }, extend: 'data-toggle="tooltip" data-container="body"', classname: 'btn btn-xs btn-default btn-dialog', diff --git a/public/assets/js/backend/statistics/worker.js b/public/assets/js/backend/statistics/worker.js index e46ac9c..04596f3 100644 --- a/public/assets/js/backend/statistics/worker.js +++ b/public/assets/js/backend/statistics/worker.js @@ -29,28 +29,31 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts', 'echarts-t columns: [ [ //{field: 'id', title: __('Id')}, - {field: 'id', title: __('ID'),visible:true,operate: false}, - {field: 'admin_user', title: __('派单员'),operate: "LIKE"}, - {field: 'count_num', title: __('总订单数'),operate: false}, - {field: 'finish_num', title: __('完单数'),operate: false}, - {field: 'total', title: __('成效额(¥)'), operate: false}, + {field: 'id', title: __('ID'),visible:true}, + {field: 'name', title: __('姓名'),operate: "="}, + {field: 'tel', title: __('电话'),operate: "="}, + {field: 'area.name', title: __('城市'),operate: false}, + {field: 'star', title: __('评分'),operate: false}, {field: 'performance', title: __('总业绩(¥)'), operate: false}, - {field: 'cost_total', title: __('总成本(¥)'), operate: false}, - {field: 'refund_total', title: __('退款金额(¥)'), operate: false}, - {field: 'refund_count', title: __('退款单数'), operate: false}, - + {field: 'get_count', title: __('接单数'),operate: false}, + {field: 'finish_num', title: __('完单数'),operate: false}, + {field: 'cost', title: __('收入(¥)'), operate: false}, {field: 'performance_rate', title: __('利润率(%)'), operate: false}, {field: 'trans_rate', title: __('转化率(%)'), operate: false}, {field: 'cash_value', title: __('变现值'), operate: false}, - {field: 'performance_avg', title: __('客单利润(¥)'), operate: false}, - {field: 'total_avg', title: __('客单价(¥)'), operate: false}, + {field: 'refuse_rate', title: __('拒单率(%)'), operate: false}, + {field: 'arrive_rate', title: __('上门率(%)'), operate: false}, + {field: 'good_rate', title: __('好评率(%)'), operate: false}, - {field: 'avg_time_diff', title: __('派单时效(天)'), operate: false}, + {field: 'refund_total', title: __('退款金额(¥)'), operate: false}, + {field: 'refund_count', title: __('退款单数'), operate: false}, + + + {field: 'avg_time_diff', title: __('联系时效(天)'), operate: false}, //{field: 'admin_user', title: __('派单员'),operate: "LIKE",visible:false}, //{field: 'city_name', title: __('城市'),operate: "LIKE",visible:false}, //{field: 'city_name', title: __('城市'),operate: "LIKE",visible:false}, - {field: 'time_by', title: __('时间维度'), visible:false,searchList: {"1":__('录单时间'),"2":__('派单时间')},defaultValue:1, formatter: Table.api.formatter.normal}, {field: 'daterange', title: __('时间筛选'), addclass:'datetimerange', autocomplete:false, operate: "RANGE", @@ -68,7 +71,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'echarts', 'echarts-t title:"售后列表", icon: 'fa fa-list', url: function(row){ - return 'aftersales/aftersale/index?from=2&dispatch_admin_id='+row.id; + return 'aftersales/aftersale/index?from=3&man_id='+row.id; }, extend: 'data-toggle="tooltip" data-container="body"', classname: 'btn btn-xs btn-default btn-dialog',