diff --git a/admin/src/app/api/contract_sign.ts b/admin/src/app/api/contract_sign.ts new file mode 100644 index 00000000..b56db4e7 --- /dev/null +++ b/admin/src/app/api/contract_sign.ts @@ -0,0 +1,58 @@ +import request from '@/utils/request' + + + +// USER_CODE_BEGIN -- contract_sign +/** + * 获取合同关系列表 + * @param params + * @returns + */ +export function getContractSignList(params: Record) { + return request.get(`contract_sign/contract_sign`, {params}) +} + +/** + * 获取合同关系详情 + * @param id 合同关系id + * @returns + */ +export function getContractSignInfo(id: number) { + return request.get(`contract_sign/contract_sign/${id}`); +} + +/** + * 添加合同关系 + * @param params + * @returns + */ +export function addContractSign(params: Record) { + return request.post('contract_sign/contract_sign', params, { showErrorMessage: true, showSuccessMessage: true }) +} + +/** + * 编辑合同关系 + * @param id + * @param params + * @returns + */ +export function editContractSign(params: Record) { + return request.put(`contract_sign/contract_sign/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true }) +} + +/** + * 删除合同关系 + * @param id + * @returns + */ +export function deleteContractSign(id: number) { + return request.delete(`contract_sign/contract_sign/${id}`, { showErrorMessage: true, showSuccessMessage: true }) +} + +export function getWithContractList(params: Record){ + return request.get('contract_sign/contract_all', {params}) +}export function getWithPersonnelList(params: Record){ + return request.get('contract_sign/personnel_all', {params}) +} + +// USER_CODE_END -- contract_sign diff --git a/admin/src/app/lang/zh-cn/contract_sign.contract_sign.json b/admin/src/app/lang/zh-cn/contract_sign.contract_sign.json new file mode 100644 index 00000000..f3fddfa9 --- /dev/null +++ b/admin/src/app/lang/zh-cn/contract_sign.contract_sign.json @@ -0,0 +1,17 @@ +{ + "contractId":"合同", + "contractIdPlaceholder":"请输入合同", + "personnelId":"下发人员", + "personnelIdPlaceholder":"请输入下发人员", + "status":"签署状态", + "statusPlaceholder":"请输入签署状态", + "createdAt":"创建时间", + "createdAtPlaceholder":"请输入创建时间", + "signTime":"签署时间", + "signTimePlaceholder":"请输入签署时间", + "addContractSign":"添加合同关系", + "updateContractSign":"编辑合同关系", + "contractSignDeleteTips":"确定要删除该数据吗?", + "startDate":"请选择开始时间", + "endDate":"请选择结束时间" +} \ No newline at end of file diff --git a/admin/src/app/views/contract_sign/components/contract-sign-edit.vue b/admin/src/app/views/contract_sign/components/contract-sign-edit.vue new file mode 100644 index 00000000..a454500a --- /dev/null +++ b/admin/src/app/views/contract_sign/components/contract-sign-edit.vue @@ -0,0 +1,184 @@ + + + + + + diff --git a/admin/src/app/views/contract_sign/contract_sign.vue b/admin/src/app/views/contract_sign/contract_sign.vue new file mode 100644 index 00000000..30c1f410 --- /dev/null +++ b/admin/src/app/views/contract_sign/contract_sign.vue @@ -0,0 +1,235 @@ + + + + + diff --git a/niucloud/app/adminapi/controller/contract_sign/ContractSign.php b/niucloud/app/adminapi/controller/contract_sign/ContractSign.php new file mode 100644 index 00000000..cc914b0e --- /dev/null +++ b/niucloud/app/adminapi/controller/contract_sign/ContractSign.php @@ -0,0 +1,97 @@ +request->params([ + ["status",""], + ["created_at",["",""]], + ["sign_time",["",""]] + ]); + return success((new ContractSignService())->getPage($data)); + } + + /** + * 合同关系详情 + * @param int $id + * @return \think\Response + */ + public function info(int $id){ + return success((new ContractSignService())->getInfo($id)); + } + + /** + * 添加合同关系 + * @return \think\Response + */ + public function add(){ + $data = $this->request->params([ + ["contract_id",0], + ["personnel_id",0], + + ]); + $this->validate($data, 'app\validate\contract_sign\ContractSign.add'); + $id = (new ContractSignService())->add($data); + return success('ADD_SUCCESS', ['id' => $id]); + } + + /** + * 合同关系编辑 + * @param $id 合同关系id + * @return \think\Response + */ + public function edit(int $id){ + $data = $this->request->params([ + ["contract_id",0], + ["personnel_id",0], + + ]); + $this->validate($data, 'app\validate\contract_sign\ContractSign.edit'); + (new ContractSignService())->edit($id, $data); + return success('EDIT_SUCCESS'); + } + + /** + * 合同关系删除 + * @param $id 合同关系id + * @return \think\Response + */ + public function del(int $id){ + (new ContractSignService())->del($id); + return success('DELETE_SUCCESS'); + } + + + public function getContractAll(){ + return success(( new ContractSignService())->getContractAll()); + } + + public function getPersonnelAll(){ + return success(( new ContractSignService())->getPersonnelAll()); + } + +} diff --git a/niucloud/app/adminapi/route/contract_sign.php b/niucloud/app/adminapi/route/contract_sign.php new file mode 100644 index 00000000..945f781c --- /dev/null +++ b/niucloud/app/adminapi/route/contract_sign.php @@ -0,0 +1,42 @@ +middleware([ + AdminCheckToken::class, + AdminCheckRole::class, + AdminLog::class +]); +// USER_CODE_END -- contract_sign diff --git a/niucloud/app/api/controller/apiController/Statistics.php b/niucloud/app/api/controller/apiController/Statistics.php index 19e6c2e2..b640f2b8 100644 --- a/niucloud/app/api/controller/apiController/Statistics.php +++ b/niucloud/app/api/controller/apiController/Statistics.php @@ -11,9 +11,17 @@ namespace app\api\controller\apiController; +use app\model\market_performance\MarketPerformance; +use app\model\order_table\OrderTable; use app\Request; use app\service\api\apiService\CommonService; use core\base\BaseApiService; +use app\model\customer_resources\CustomerResources; +use think\facade\Db; + + +use app\model\resource_sharing\ResourceSharing; +use app\model\six_speed\SixSpeed; /** * 统计控制器相关接口 @@ -28,6 +36,12 @@ class Statistics extends BaseApiService */ public function marketHome(Request $request) { + $customerResources = new CustomerResources(); + $resourceSharing = new ResourceSharing(); + $communication_records = new CommunicationRecords(); + $market_performance = new MarketPerformance(); + $six_speed = new SixSpeed(); + $order = new OrderTable(); $personnel_id = $request->param('personnel_id','');//员工表id $role_key_arr = $request->param('role_key_arr','');//array 角色key //字符转数组 @@ -42,63 +56,184 @@ class Statistics extends BaseApiService // $role_key_arr = ['sale'];//@todo 调试使用 if(in_array('market',$role_key_arr) || in_array('market_manager',$role_key_arr)){ + $yesterdayStart = date('Y-m-d', strtotime('-1 day')); + $lastMonthStart = date('Y-m', strtotime('-1 month')); + $customer_list = $customerResources->where(['consultant' => $personnel_id])->select(); + $newTotal = 0; + $assignedSales = 0; + $yesterdayNew = 0; + $todayNew = 0; + $yjsr = 0; + $wfpsl = 0; + $bytc = 0; + $gdsl = 0; + $lastNewTotal = 0; + $lastAssignedSales = 0; + foreach($customer_list as $item){ + if($item['create_year_month'] == date("Y-m")){ + $newTotal++; + if($resourceSharing->where(['resource_id' => $item['id']])->find()){ + $assignedSales++; + } + } + + if($item['create_year_month'] == $lastMonthStart){ + $lastNewTotal++; + if($resourceSharing->where(['resource_id' => $item['id']])->find()){ + $lastAssignedSales++; + } + } + + if($item['create_date'] == $yesterdayStart){ + $yesterdayNew++; + } + + if($item['create_date'] == date("Y-m-d")){ + $todayNew++; + } + + if(!$resourceSharing->where(['resource_id' => $item['id']])->find()){ + $wfpsl++; + } + + if($order->where(['resource_id' => $item['id'],'order_type' => '1'])->find()){ + if($six_speed->where(['resource_id' => $item['id'],'is_closed' => 1])->find()){ + $gdsl++; + } + } + + } + + $yjsr = $market_performance->where([ + 'performance_date' => date('Y-m-d'), + 'personnel_id' => $personnel_id + ])->Sum('performance_amount'); + + + $bytc = $market_performance + ->where(['personnel_id' => $personnel_id]) + ->whereTime('performance_date', 'month') + ->sum('performance_amount'); + //市场人员统计数据(地推拉人头的) $data = [ 'date_range'=>$dateRange,//拼接日期范围字符串 'role_type'=>'market_type',//角色类型|market_type=市场,sale_type=销售 //本月 'month' => [ - 'new_total' => ($newTotal = rand(100, 500)),//拉新总人数 + 'new_total' => $newTotal,//拉新总人数 'new_total_rate' => min(100, round($newTotal / 1000 * 100, 2)),//拉新总人数比例(不超过100%) - 'assigned_sales' => ($assignedSales = rand(50, 300)),//已分配给销售的人数 - 'assigned_sales_rate' => min(100, round($assignedSales / $newTotal * 100, 2)),//已分配给销售的人数比例(不超过100%) - 'yesterday_new' => ($yesterdayNew = rand(5, 50)),//昨日拉新 - 'yesterday_new_rate' => min(100, round($yesterdayNew / $newTotal * 100, 2)),//昨日拉新比例(不超过100%) - 'today_new' => ($todayNew = rand(1, 20)),//今日拉新 - 'today_new_rate' => min(100, round($todayNew / $newTotal * 100, 2)),//今日拉新比例(不超过100%) + 'assigned_sales' => $assignedSales,//已分配给销售的人数 + 'assigned_sales_rate' => $newTotal ? min(100, round($assignedSales / $newTotal * 100, 2)) : 0,//已分配给销售的人数比例(不超过100%) + 'yesterday_new' => $yesterdayNew,//昨日拉新 + 'yesterday_new_rate' => $newTotal ? min(100, round($yesterdayNew / $newTotal * 100, 2)) : 0,//昨日拉新比例(不超过100%) + 'today_new' => $todayNew,//今日拉新 + 'today_new_rate' => $newTotal ? min(100, round($todayNew / $newTotal * 100, 2)) : 0,//今日拉新比例(不超过100%) + ], //上月 'last_month' => [ - 'new_total' => ($lastNewTotal = rand(80, 400)),//拉新总人数 + 'new_total' => $lastNewTotal,//拉新总人数 'new_total_rate' => min(100, round($lastNewTotal / 800 * 100, 2)),//拉新总人数比例(不超过100%) - 'assigned_sales' => ($lastAssignedSales = rand(40, 250)),//已分配给销售的人数 - 'assigned_sales_rate' => min(100, round($lastAssignedSales / $lastNewTotal * 100, 2)),//已分配给销售的人数比例(不超过100%) - 'yesterday_new' => ($lastYesterdayNew = rand(3, 40)),//昨日拉新人数 - 'yesterday_new_rate' => min(100, round($lastYesterdayNew / $lastNewTotal * 100, 2)),//昨日拉新人数比例(不超过100%) - 'today_new' => ($lastTodayNew = rand(1, 15)),//今日拉新人数 - 'today_new_rate' => min(100, round($lastTodayNew / $lastNewTotal * 100, 2)),//今日拉新人数比例(不超过100%) + 'assigned_sales' => $lastAssignedSales,//已分配给销售的人数 + 'assigned_sales_rate' => $lastNewTotal ? min(100, round($lastAssignedSales / $lastNewTotal * 100, 2)) : 0,//已分配给销售的人数比例(不超过100%) + 'yesterday_new' =>$yesterdayNew,//昨日拉新人数 + 'yesterday_new_rate' => $lastNewTotal ? min(100, round($yesterdayNew / $lastNewTotal * 100, 2)) : 0,//昨日拉新人数比例(不超过100%) + 'today_new' => $todayNew,//今日拉新人数 + 'today_new_rate' => $lastNewTotal ? min(100, round($todayNew / $lastNewTotal * 100, 2)) : 0,//今日拉新人数比例(不超过100%) + 'xzzy' => $todayNew, + 'yjsr' => $yjsr, + 'wfpsl' => $wfpsl, + 'bytc' => $bytc, + 'gdsl' => $gdsl ] ]; }elseif(in_array('sale',$role_key_arr) || in_array('sale_manager',$role_key_arr)){ + + $startTime = date('Y-m-01 00:00:00'); + $endTime = date('Y-m-t 23:59:59'); + + $last_monthstartTime = date('Y-m-01 00:00:00', strtotime('first day of last month')); + $last_monthendTime = date('Y-m-t 23:59:59', strtotime('last day of last month')); + + $resource_list = $resourceSharing->where(['shared_by' => $personnel_id])->select(); + $assigned = 0; + $contacted = 0; + $unconverted = 0; + $renewal = 0; + $closed = 0; + + $lastAssigned = 0; + $lastContacted = 0; + $lastUnconverted = 0; + $lastClosed = 0; + foreach($resource_list as $item){ + $sharedAt = strtotime($item['shared_at']); + + if ($sharedAt >= strtotime($startTime) && $sharedAt <= strtotime($endTime)) { + $assigned++; + $records = $communication_records->where(['resource_id' => $item['resource_id']])->order("id desc")->find(); + if($records){ + $contacted++; + if($records['communication_result'] !== 'success'){ + $unconverted++; + } + } + + if($six_speed->where(['resource_id' => $item['resource_id'],'is_closed' => 1])->find()){ + $closed++; + } + } + + + if ($sharedAt >= strtotime($last_monthstartTime) && $sharedAt <= strtotime($last_monthendTime)) { + $lastAssigned++; + $records = $communication_records->where(['resource_id' => $item['resource_id']])->order("id desc")->find(); + if($records){ + $lastContacted++; + if($records['communication_result'] !== 'success'){ + $lastUnconverted++; + } + } + + if($six_speed->where(['resource_id' => $item['resource_id'],'is_closed' => 1])->find()){ + $lastClosed++; + } + } + + + } + + //销售人员统计数据(买课的) $data = [ 'date_range'=>$dateRange,//拼接日期范围字符串 'role_type'=>'sale_type',//角色类型|market_type=市场,sale_type=销售 infoData.month //本月 'month' => [ - 'assigned_clients' => ($assigned = rand(50, 300)),//分配给我的客户人数 - 'contacted_clients' => ($contacted = rand(20, 150)),//已沟通的客户人数 - 'contact_rate' => min(100, round($contacted / $assigned * 100, 2)),//沟通率(不超过100%) - 'unconverted_clients' => ($unconverted = rand(10, 50)),//已沟通但没成交的客户人数 - 'unconverted_rate' => min(100, round($unconverted / $contacted * 100, 2)),//未成交率(不超过100%) + 'assigned_clients' => $assigned,//分配给我的客户人数 + 'contacted_clients' => $contacted,//已沟通的客户人数 + 'contact_rate' => $assigned ? min(100, round($contacted / $assigned * 100, 2)) : 0,//沟通率(不超过100%) + 'unconverted_clients' => $unconverted,//已沟通但没成交的客户人数 + 'unconverted_rate' => $contacted ? min(100, round($unconverted / $contacted * 100, 2)) : 0,//未成交率(不超过100%) 'renewal_clients' => ($renewal = rand(5, 30)),//待续费的客户人数 - 'renewal_rate' => min(100, round($renewal / $assigned * 100, 2)),//待续费率(不超过100%) - 'closed_clients' => ($closed = rand(1, 20)),//已关单的客户人数 - 'closed_rate' => min(100, round($closed / $contacted * 100, 2)),//关单率(不超过100%) - 'conversion_rate' => min(100, round($closed / $assigned * 100, 2)),//整体转化率(不超过100%) + 'renewal_rate' => $assigned ? min(100, round($renewal / $assigned * 100, 2)) : 0,//待续费率(不超过100%) + 'closed_clients' => $closed,//已关单的客户人数 + 'closed_rate' => $contacted ? min(100, round($closed / $contacted * 100, 2)) : 0,//关单率(不超过100%) + 'conversion_rate' => $assigned ? min(100, round($closed / $assigned * 100, 2)) : 0,//整体转化率(不超过100%) ], //上月 'last_month' => [ - 'assigned_clients' => ($lastAssigned = rand(40, 250)),//分配给我的客户人数 - 'contacted_clients' => ($lastContacted = rand(15, 120)),//已沟通的客户人数 - 'contact_rate' => min(100, round($lastContacted / $lastAssigned * 100, 2)),//沟通率(不超过100%) - 'unconverted_clients' => ($lastUnconverted = rand(8, 40)),//已沟通但没成交的客户人数 - 'unconverted_rate' => min(100, round($lastUnconverted / $lastContacted * 100, 2)),//未成交率(不超过100%) + 'assigned_clients' => $lastAssigned,//分配给我的客户人数 + 'contacted_clients' => $lastContacted,//已沟通的客户人数 + 'contact_rate' => $lastAssigned ? min(100, round($lastContacted / $lastAssigned * 100, 2)) : 0,//沟通率(不超过100%) + 'unconverted_clients' => $lastUnconverted,//已沟通但没成交的客户人数 + 'unconverted_rate' => $lastContacted ? min(100, round($lastUnconverted / $lastContacted * 100, 2)) : 0,//未成交率(不超过100%) 'renewal_clients' => ($lastRenewal = rand(3, 25)),//待续费的客户人数 - 'renewal_rate' => min(100, round($lastRenewal / $lastAssigned * 100, 2)),//待续费率(不超过100%) - 'closed_clients' => ($lastClosed = rand(1, 15)),//已关单的客户人数 - 'closed_rate' => min(100, round($lastClosed / $lastContacted * 100, 2)),//关单率(不超过100%) - 'conversion_rate' => min(100, round($lastClosed / $lastAssigned * 100, 2)),//整体转化率(不超过100%) + 'renewal_rate' => $lastAssigned ? min(100, round($lastRenewal / $lastAssigned * 100, 2)) : 0,//待续费率(不超过100%) + 'closed_clients' => $lastClosed,//已关单的客户人数 + 'closed_rate' => $lastContacted ? min(100, round($lastClosed / $lastContacted * 100, 2)) : 0,//关单率(不超过100%) + 'conversion_rate' => $lastAssigned ? min(100, round($lastClosed / $lastAssigned * 100, 2)) : 0,//整体转化率(不超过100%) ] ]; }else{ diff --git a/niucloud/app/model/contract_sign/ContractSign.php b/niucloud/app/model/contract_sign/ContractSign.php new file mode 100644 index 00000000..4a569f96 --- /dev/null +++ b/niucloud/app/model/contract_sign/ContractSign.php @@ -0,0 +1,118 @@ +where("status", $value); + } + } + + /** + * 搜索器:合同关系创建时间 + * @param $value + * @param $data + */ + public function searchCreatedAtAttr($query, $value, $data) + { + $start = empty($value[0]) ? 0 : strtotime($value[0]); + $end = empty($value[1]) ? 0 : strtotime($value[1]); + if ($start > 0 && $end > 0) { + $query->where([["created_at", "between", [$start, $end]]]); + } else if ($start > 0 && $end == 0) { + $query->where([["created_at", ">=", $start]]); + } else if ($start == 0 && $end > 0) { + $query->where([["created_at", "<=", $end]]); + } + } + + /** + * 搜索器:合同关系签署时间 + * @param $value + * @param $data + */ + public function searchSignTimeAttr($query, $value, $data) + { + $start = empty($value[0]) ? 0 : strtotime($value[0]); + $end = empty($value[1]) ? 0 : strtotime($value[1]); + if ($start > 0 && $end > 0) { + $query->where([["sign_time", "between", [$start, $end]]]); + } else if ($start > 0 && $end == 0) { + $query->where([["sign_time", ">=", $start]]); + } else if ($start == 0 && $end > 0) { + $query->where([["sign_time", "<=", $end]]); + } + } + + + + + + + public function contract(){ + return $this->hasOne(Contract::class, 'id', 'contract_id')->joinType('left')->withField('contract_name,id')->bind(['contract_id_name'=>'contract_name']); + } + + public function personnel(){ + return $this->hasOne(Personnel::class, 'id', 'personnel_id')->joinType('left')->withField('name,id')->bind(['personnel_id_name'=>'name']); + } + +} diff --git a/niucloud/app/service/admin/contract_sign/ContractSignService.php b/niucloud/app/service/admin/contract_sign/ContractSignService.php new file mode 100644 index 00000000..47d83a73 --- /dev/null +++ b/niucloud/app/service/admin/contract_sign/ContractSignService.php @@ -0,0 +1,111 @@ +model = new ContractSign(); + } + + /** + * 获取合同关系列表 + * @param array $where + * @return array + */ + public function getPage(array $where = []) + { + $field = 'id,contract_id,personnel_id,sign_file,status,created_at,sign_time,updated_at,deleted_at'; + $order = 'id desc'; + + $search_model = $this->model->withSearch(["status","created_at","sign_time"], $where)->with(['contract','personnel'])->field($field)->order($order); + $list = $this->pageQuery($search_model); + return $list; + } + + /** + * 获取合同关系信息 + * @param int $id + * @return array + */ + public function getInfo(int $id) + { + $field = 'id,contract_id,personnel_id,sign_file,status,created_at,sign_time,updated_at,deleted_at'; + + $info = $this->model->field($field)->where([['id', "=", $id]])->with(['contract','personnel'])->findOrEmpty()->toArray(); + return $info; + } + + /** + * 添加合同关系 + * @param array $data + * @return mixed + */ + public function add(array $data) + { + $res = $this->model->create($data); + return $res->id; + + } + + /** + * 合同关系编辑 + * @param int $id + * @param array $data + * @return bool + */ + public function edit(int $id, array $data) + { + + $this->model->where([['id', '=', $id]])->update($data); + return true; + } + + /** + * 删除合同关系 + * @param int $id + * @return bool + */ + public function del(int $id) + { + $model = $this->model->where([['id', '=', $id]])->find(); + $res = $model->delete(); + return $res; + } + + + public function getContractAll(){ + $contractModel = new Contract(); + return $contractModel->select()->toArray(); + } + + public function getPersonnelAll(){ + $personnelModel = new Personnel(); + return $personnelModel->select()->toArray(); + } + + +} diff --git a/niucloud/app/validate/contract_sign/ContractSign.php b/niucloud/app/validate/contract_sign/ContractSign.php new file mode 100644 index 00000000..ae9a8c5c --- /dev/null +++ b/niucloud/app/validate/contract_sign/ContractSign.php @@ -0,0 +1,37 @@ + 'require', + 'personnel_id' => 'require', + ]; + + protected $message = [ + 'contract_id.require' => ['common_validate.require', ['contract_id']], + 'personnel_id.require' => ['common_validate.require', ['personnel_id']], + ]; + + protected $scene = [ + "add" => ['contract_id', 'personnel_id'], + "edit" => ['contract_id', 'personnel_id'] + ]; + +}