123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Description: 商机
  4. // +----------------------------------------------------------------------
  5. // | Author: Michael_xu | gengxiaoxu@5kcrm.com
  6. // +----------------------------------------------------------------------
  7. namespace app\crm\model;
  8. use app\admin\traits\FieldVerificationTrait;
  9. use think\Db;
  10. use app\admin\model\Common;
  11. use app\crm\model\Business as CrmBusinessModel;
  12. class Business extends Common
  13. {
  14. use FieldVerificationTrait;
  15. /**
  16. * 为了数据库的整洁,同时又不影响Model和Controller的名称
  17. * 我们约定每个模块的数据表都加上相同的前缀,比如CRM模块用crm作为数据表前缀
  18. */
  19. protected $name = 'crm_business';
  20. protected $createTime = 'create_time';
  21. protected $updateTime = 'update_time';
  22. protected $autoWriteTimestamp = true;
  23. /**
  24. * [getDataList 商机list]
  25. *
  26. * @param $request
  27. * @return array
  28. * @throws \think\db\exception\DataNotFoundException
  29. * @throws \think\db\exception\ModelNotFoundException
  30. * @throws \think\exception\DbException
  31. */
  32. public function getDataList($request)
  33. {
  34. $userModel = new \app\admin\model\User();
  35. $structureModel = new \app\admin\model\Structure();
  36. $fieldModel = new \app\admin\model\Field();
  37. $search = $request['search'];
  38. $user_id = $request['user_id'];
  39. $scene_id = (int)$request['scene_id'];
  40. $contacts_id = $request['contacts_id'];
  41. $order_field = $request['order_field'];
  42. $order_type = $request['order_type'];
  43. $is_excel = $request['is_excel']; //导出
  44. $getCount = $request['getCount'];
  45. $businessTypeId = $request['typesId']; // 针对mobile
  46. $businessStatusId = $request['statusId']; // 针对mobile
  47. $overdue = $request['overdue']; // 待办事项下需联系商机(逾期)
  48. unset($request['scene_id']);
  49. unset($request['search']);
  50. unset($request['user_id']);
  51. unset($request['contacts_id']);
  52. unset($request['order_field']);
  53. unset($request['order_type']);
  54. unset($request['is_excel']);
  55. unset($request['getCount']);
  56. unset($request['typesId']);
  57. unset($request['statusId']);
  58. unset($request['overdue']);
  59. $request = $this->fmtRequest($request);
  60. $requestMap = $request['map'] ?: [];
  61. $sceneModel = new \app\admin\model\Scene();
  62. # getCount是代办事项传来的参数,代办事项不需要使用场景
  63. $sceneMap = [];
  64. if (empty($getCount)) {
  65. if ($scene_id) {
  66. //自定义场景
  67. $sceneMap = $sceneModel->getDataById($scene_id, $user_id, 'business') ?: [];
  68. } else {
  69. //默认场景
  70. $sceneMap = $sceneModel->getDefaultData('crm_business', $user_id) ?: [];
  71. }
  72. }
  73. if ($search || $search == '0') {
  74. //普通筛选
  75. $sceneMap['name'] = ['condition' => 'contains', 'value' => $search, 'form_type' => 'text', 'name' => '商机名称'];
  76. }
  77. if (isset($requestMap['type_id'])) {
  78. $requestMap['type_id']['value'] = $requestMap['type_id']['type_id'];
  79. if(in_array($requestMap['type_id']['status_id'],[1,2,3])){
  80. $requestMap['is_end']=$requestMap['type_id']['status_id'];
  81. }else{
  82. if ($requestMap['type_id']['status_id']) $requestMap['status_id']['value'] = $requestMap['type_id']['status_id'];
  83. $requestMap['is_end']=0;
  84. }
  85. }
  86. if ($sceneMap['type_id']) {
  87. $requestMap['type_id']['value'] = $sceneMap['type_id']['type_id'];
  88. if(in_array($sceneMap['type_id']['status_id'],[1,2,3])){
  89. $sceneMap['is_end']=$sceneMap['type_id']['status_id'];
  90. }else{
  91. if ($sceneMap['type_id']['status_id']) $requestMap['status_id']['value'] = $sceneMap['type_id']['status_id'];
  92. $sceneMap['is_end']=0;
  93. }
  94. unset($sceneMap['type_id']);
  95. }
  96. $partMap = [];
  97. $teamMap=$requestMap['team_id'];
  98. //团队成员 高级筛选
  99. if($teamMap){
  100. $partMap= advancedQueryFormatForTeam($teamMap,'business','');
  101. unset($requestMap['team_id']);
  102. $map = $requestMap ? array_merge($sceneMap, $requestMap) : $sceneMap;
  103. } else {
  104. $map = $requestMap ? array_merge($sceneMap, $requestMap) : $sceneMap;
  105. }
  106. //高级筛选
  107. $map = advancedQuery($map, 'crm', 'business', 'index');
  108. $authMap = [];
  109. $a = 'index';
  110. if ($is_excel) $a = 'excelExport';
  111. $auth_user_ids = $userModel->getUserByPer('crm', 'business', $a);
  112. if (isset($map['business.owner_user_id'])) {
  113. if (!is_array($map['business.owner_user_id'][1])) {
  114. $map['business.owner_user_id'][1] = [$map['business.owner_user_id'][1]];
  115. }
  116. if (in_array($map['business.owner_user_id'][0], ['neq', 'notin'])) {
  117. $auth_user_ids = array_diff($auth_user_ids, $map['business.owner_user_id'][1]) ?: []; //取差集
  118. } else {
  119. $auth_user_ids = array_intersect($map['business.owner_user_id'][1], $auth_user_ids) ?: []; //取交集
  120. }
  121. unset($map['business.owner_user_id']);
  122. $auth_user_ids = array_merge(array_unique(array_filter($auth_user_ids))) ?: ['-1'];
  123. $authMap['business.owner_user_id'] = array('in', $auth_user_ids);
  124. } else {
  125. $authMapData = [];
  126. $authMapData['auth_user_ids'] = $auth_user_ids;
  127. $authMapData['user_id'] = $user_id;
  128. $authMap = function ($query) use ($authMapData) {
  129. $query->where('business.owner_user_id', array('in', $authMapData['auth_user_ids']))
  130. ->whereOr('business.ro_user_id', array('like', '%,' . $authMapData['user_id'] . ',%'))
  131. ->whereOr('business.rw_user_id', array('like', '%,' . $authMapData['user_id'] . ',%'));
  132. };
  133. }
  134. //联系人商机
  135. if ($contacts_id) {
  136. $business_id = Db::name('crm_contacts_business')->where(['contacts_id' => $contacts_id])->column('business_id');
  137. if ($business_id) {
  138. $map['business.business_id'] = array('in', $business_id);
  139. } else {
  140. $map['business.business_id'] = array('eq', -1);
  141. }
  142. }
  143. //列表展示字段
  144. $indexField = $fieldModel->getIndexField('crm_business', $user_id, 1) ?: array('name');
  145. if (!empty($indexField)) {
  146. foreach ($indexField as $key => $value) {
  147. if ($value == 'business.customer_name') unset($indexField[(int)$key]);
  148. }
  149. }
  150. $userField = $fieldModel->getFieldByFormType('crm_business', 'user'); //人员类型
  151. $structureField = $fieldModel->getFieldByFormType('crm_business', 'structure'); //部门类型
  152. // $fieldGrant = db('admin_field_mask')->where('types', 'business')->select();
  153. # 处理人员和部门类型的排序报错问题(前端传来的是包含_name的别名字段)
  154. $temporaryField = str_replace('_name', '', $order_field);
  155. if (in_array($temporaryField, $userField) || in_array($temporaryField, $structureField)) {
  156. $order_field = $temporaryField;
  157. }
  158. //排序
  159. if ($order_type && $order_field) {
  160. $order = $fieldModel->getOrderByFormtype('crm_business', 'business', $order_field, $order_type);
  161. } else {
  162. $order = 'business.update_time desc';
  163. }
  164. # 商机组和商机状态搜索
  165. if (!empty($businessTypeId)) $map['business.type_id'] = ['eq', $businessTypeId];
  166. if (!empty($businessStatusId)) {
  167. if(preg_match("/^[1-9][0-9]*$/" ,$businessStatusId)){
  168. $map['is_end']=0;
  169. $map['business.status_id'] = ['eq', $businessStatusId];
  170. }else{
  171. $map['is_end']=abs($businessStatusId);
  172. }
  173. }
  174. // 待办事项下需联系商机(逾期)
  175. $overdueWhere = '';
  176. if (!empty($overdue)) {
  177. $overdueWhere = "(FROM_UNIXTIME(`business`.`last_time`,'%Y-%m-%d') < FROM_UNIXTIME(`business`.`next_time`,'%Y-%m-%d') OR (ISNULL(`business`.`last_time`) AND `business`.`next_time` < ".time()."))";
  178. }
  179. $readAuthIds = $userModel->getUserByPer('crm', 'business', 'read');
  180. $updateAuthIds = $userModel->getUserByPer('crm', 'business', 'update');
  181. $deleteAuthIds = $userModel->getUserByPer('crm', 'business', 'delete');
  182. $dataCount = db('crm_business')
  183. ->alias('business')
  184. ->join('__CRM_CUSTOMER__ customer', 'business.customer_id = customer.customer_id', 'LEFT')
  185. ->where($map)->where($partMap)->where($authMap)->where($overdueWhere)->count('business_id');
  186. if (!empty($getCount) && $getCount == 1) {
  187. $data['dataCount'] = !empty($dataCount) ? $dataCount : 0;
  188. # 商机总金额
  189. $sumMoney = Db::name('crm_business')->alias('business')
  190. ->whereIn('is_end', [0, 1])->where($map)->where($partMap)->where($authMap)->sum('money');
  191. $data['extraData']['money'] = ['businessSumMoney' => !empty($sumMoney) ? sprintf("%.2f", $sumMoney) : 0.00];
  192. return $data;
  193. }
  194. $list = db('crm_business')
  195. ->alias('business')
  196. ->join('__CRM_CUSTOMER__ customer', 'business.customer_id = customer.customer_id', 'LEFT')
  197. ->where($map)
  198. ->where($partMap)
  199. ->where($authMap)
  200. ->where($overdueWhere)
  201. ->limit($request['offset'], $request['length'])
  202. ->field('business.*,customer.name as customer_name')
  203. ->orderRaw($order)
  204. ->select();
  205. $endStatus = ['1' => '赢单', '2' => '输单', '3' => '无效'];
  206. # 扩展数据
  207. $extraData = [];
  208. $list=getFieldData($list,'crm_business',$user_id);
  209. foreach ($list as $k => $v) {
  210. $list[$k]['customer_id_info']['customer_id'] = $v['customer_id'];
  211. $list[$k]['customer_id_info']['name'] = $v['customer_name'];
  212. $list[$k]['create_user_id_info'] = isset($v['create_user_id']) ? $userModel->getUserById($v['create_user_id']) : [];
  213. $list[$k]['owner_user_id_info'] = isset($v['owner_user_id']) ? $userModel->getUserById($v['owner_user_id']) : [];
  214. $list[$k]['create_user_name'] = !empty($list[$k]['create_user_id_info']['realname']) ? $list[$k]['create_user_id_info']['realname'] : '';
  215. $list[$k]['owner_user_name'] = !empty($list[$k]['owner_user_id_info']['realname']) ? $list[$k]['owner_user_id_info']['realname'] : '';
  216. $statusInfo = [];
  217. $status_count = 0;
  218. if (!$v['is_end']) {
  219. $statusInfo = db('crm_business_status')->where('status_id', $v['status_id'])->find();
  220. if ($statusInfo['order_id'] < 99) {
  221. $status_count = db('crm_business_status')->where('type_id', ['eq', $v['type_id']])->count();
  222. }
  223. //进度
  224. $list[$k]['status_progress'] = [$statusInfo['order_id'], $status_count + 1];
  225. } else {
  226. $statusInfo['name'] = $endStatus[$v['is_end']];
  227. }
  228. $list[$k]['status_id_info'] = $statusInfo['name'];//销售阶段
  229. $list[$k]['type_id_info'] = db('crm_business_type')->where('type_id', $v['type_id'])->value('name');//商机状态组
  230. //权限
  231. $roPre = $userModel->rwPre($user_id, $v['ro_user_id'], $v['rw_user_id'], 'read');
  232. $rwPre = $userModel->rwPre($user_id, $v['ro_user_id'], $v['rw_user_id'], 'update');
  233. $permission = [];
  234. $is_read = 0;
  235. $is_update = 0;
  236. $is_delete = 0;
  237. if (in_array($v['owner_user_id'], $readAuthIds) || $roPre || $rwPre) $is_read = 1;
  238. if (in_array($v['owner_user_id'], $updateAuthIds) || $rwPre) $is_update = 1;
  239. if (in_array($v['owner_user_id'], $deleteAuthIds)) $is_delete = 1;
  240. $permission['is_read'] = $is_read;
  241. $permission['is_update'] = $is_update;
  242. $permission['is_delete'] = $is_delete;
  243. $list[$k]['permission'] = $permission;
  244. # 下次联系时间
  245. $list[$k]['next_time'] = !empty($v['next_time']) ? date('Y-m-d H:i:s', $v['next_time']) : null;
  246. # 关注
  247. $starWhere = ['user_id' => $user_id, 'target_id' => $v['business_id'], 'type' => 'crm_business'];
  248. $star = Db::name('crm_star')->where($starWhere)->value('star_id');
  249. $list[$k]['star'] = !empty($star) ? 1 : 0;
  250. # 日期
  251. $list[$k]['create_time'] = !empty($v['create_time']) ? date('Y-m-d H:i:s', $v['create_time']) : null;
  252. $list[$k]['update_time'] = !empty($v['update_time']) ? date('Y-m-d H:i:s', $v['update_time']) : null;
  253. $list[$k]['last_time'] = !empty($v['last_time']) ? date('Y-m-d H:i:s', $v['last_time']) : null;
  254. # 系统字段 负责人部门 zjf 20210726
  255. $list[$k]['owner_user_structure_name'] = $list[$k]['owner_user_id_info']['structure_name'];
  256. }
  257. $data = [];
  258. $data['list'] = $list ?: [];
  259. $data['dataCount'] = $dataCount ?: 0;
  260. # 商机总金额
  261. $sumMoney = Db::name('crm_business')->alias('business')
  262. ->join('__CRM_CUSTOMER__ customer', 'business.customer_id = customer.customer_id', 'LEFT')
  263. ->whereIn('is_end', [0, 1])->where($map)->where($partMap)->where($authMap)->sum('money');
  264. $data['extraData']['money'] = ['businessSumMoney' => !empty($sumMoney) ? sprintf("%.2f", $sumMoney) : 0.00];
  265. return $data;
  266. }
  267. /**
  268. * 创建商机主表信息
  269. * @param
  270. * @return
  271. * @author Michael_xu
  272. */
  273. public function createData($param)
  274. {
  275. // 商机扩展表数据
  276. $businessData = [];
  277. $fieldModel = new \app\admin\model\Field();
  278. $productModel = new \app\crm\model\Product();
  279. // 数据验证
  280. $validateResult = $this->fieldDataValidate($param, $this->name, $param['create_user_id']);
  281. if (!empty($validateResult)) {
  282. $this->error = $validateResult;
  283. return false;
  284. }
  285. if (!$param['customer_id']) {
  286. $this->error = '请选择相关客户';
  287. return false;
  288. }
  289. // 处理部门、员工、附件、多选类型字段
  290. $arrFieldAtt = $fieldModel->getArrayField('crm_business');
  291. foreach ($arrFieldAtt as $k => $v) {
  292. $param[$v] = arrayToString($param[$v]);
  293. }
  294. // 处理日期(date)类型
  295. $dateField = $fieldModel->getFieldByFormType('crm_business', 'date');
  296. if (!empty($dateField)) {
  297. foreach ($param AS $key => $value) {
  298. if (in_array($key, $dateField) && empty($value)) $param[$key] = null;
  299. }
  300. }
  301. // 处理手写签名类型
  302. $handwritingField = $fieldModel->getFieldByFormType('crm_business', 'handwriting_sign');
  303. if (!empty($handwritingField)) {
  304. foreach ($param AS $key => $value) {
  305. if (in_array($key, $handwritingField)) {
  306. $param[$key] = !empty($value['file_id']) ? $value['file_id'] : '';
  307. }
  308. }
  309. }
  310. // 处理地址、定位、日期区间、明细表格类型字段
  311. $positionField = $fieldModel->getFieldByFormType($this->name, 'position');
  312. $locationField = $fieldModel->getFieldByFormType($this->name, 'location');
  313. $dateIntervalField = $fieldModel->getFieldByFormType($this->name, 'date_interval');
  314. $detailTableField = $fieldModel->getFieldByFormType($this->name, 'detail_table');
  315. foreach ($param AS $key => $value) {
  316. // 处理地址类型字段数据
  317. if (in_array($key, $positionField)) {
  318. if (!empty($value)) {
  319. $businessData[] = [
  320. 'field' => $key,
  321. 'content' => json_encode($value, JSON_NUMERIC_CHECK),
  322. 'create_time' => time()
  323. ];
  324. $positionNames = array_column($value, 'name');
  325. $param[$key] = implode(',', $positionNames);
  326. } else {
  327. $param[$key] = '';
  328. }
  329. }
  330. // 处理定位类型字段数据
  331. if (in_array($key, $locationField)) {
  332. if (!empty($value)) {
  333. $businessData[] = [
  334. 'field' => $key,
  335. 'content' => json_encode($value, JSON_NUMERIC_CHECK),
  336. 'create_time' => time()
  337. ];
  338. $param[$key] = $value['address'];
  339. } else {
  340. $param[$key] = '';
  341. }
  342. }
  343. // 处理日期区间类型字段数据
  344. if (in_array($key, $dateIntervalField)) {
  345. if (!empty($value)) {
  346. $businessData[] = [
  347. 'field' => $key,
  348. 'content' => json_encode($value, JSON_NUMERIC_CHECK),
  349. 'create_time' => time()
  350. ];
  351. $param[$key] = implode('_', $value);
  352. } else {
  353. $param[$key] = '';
  354. }
  355. }
  356. // 处理明细表格类型字段数据
  357. if (in_array($key, $detailTableField)) {
  358. if (!empty($value)) {
  359. $businessData[] = [
  360. 'field' => $key,
  361. 'content' => json_encode($value, JSON_NUMERIC_CHECK),
  362. 'create_time' => time()
  363. ];
  364. $param[$key] = $key;
  365. } else {
  366. $param[$key] = '';
  367. }
  368. }
  369. }
  370. # 设置今日需联系商机
  371. if (!empty($param['next_time']) && $param['next_time'] >= strtotime(date('Y-m-d 00:00:00'))) $param['is_dealt'] = 0;
  372. $param['money'] = $param['money'] ?: '0.00';
  373. $param['discount_rate'] = $param['discount_rate'] ?: '0.00';
  374. if ($this->data($param)->allowField(true)->save()) {
  375. updateActionLog($param['create_user_id'], 'crm_business', $this->business_id, '', '', '创建了商机');
  376. RecordActionLog($param['create_user_id'],'crm_business','save',$param['name'],'','','新增了商机'.$param['name']);
  377. $business_id = $this->business_id;
  378. $data['business_id'] = $business_id;
  379. if ($param['product']) {
  380. //产品数据处理
  381. $resProduct = $productModel->createObject('crm_business', $param, $business_id);
  382. if ($resProduct == false) {
  383. $this->error = '产品添加失败';
  384. return false;
  385. }
  386. }
  387. //添加商机日志
  388. $data_log['business_id'] = $business_id;
  389. $data_log['is_end'] = 0;
  390. $data_log['status_id'] = $param['status_id'];
  391. $data_log['create_time'] = time();
  392. $data_log['owner_user_id'] = $param['owner_user_id'];
  393. $data_log['remark'] = '新建商机';
  394. Db::name('CrmBusinessLog')->insert($data_log);
  395. # 添加活动记录
  396. Db::name('crm_activity')->insert([
  397. 'type' => 2,
  398. 'activity_type' => 5,
  399. 'activity_type_id' => $data['business_id'],
  400. 'content' => $param['name'],
  401. 'create_user_id' => $param['create_user_id'],
  402. 'update_time' => time(),
  403. 'create_time' => time(),
  404. 'customer_ids' => ',' . $param['customer_id'] . ','
  405. ]);
  406. // 添加商机扩展数据
  407. array_walk($businessData, function (&$val) use ($data) {
  408. $val['business_id'] = $data['business_id'];
  409. });
  410. db('crm_business_data')->insertAll($businessData);
  411. return $data;
  412. } else {
  413. $this->error = '添加失败';
  414. return false;
  415. }
  416. }
  417. /**
  418. * 编辑商机主表信息
  419. * @param
  420. * @return
  421. * @author Michael_xu
  422. */
  423. public function updateDataById($param, $business_id = '')
  424. {
  425. // 商机扩展表数据
  426. $businessData = [];
  427. $productModel = new \app\crm\model\Product();
  428. $dataInfo = $this->getDataById($business_id);
  429. if (!$dataInfo) {
  430. $this->error = '数据不存在或已删除';
  431. return false;
  432. }
  433. $param['business_id'] = $business_id;
  434. //过滤不能修改的字段
  435. $unUpdateField = ['create_user_id', 'is_deleted', 'delete_time'];
  436. foreach ($unUpdateField as $v) {
  437. unset($param[$v]);
  438. }
  439. $fieldModel = new \app\admin\model\Field();
  440. // 数据验证
  441. $validateResult = $this->fieldDataValidate($param, $this->name, $param['user_id'], $param['business_id']);
  442. if (!empty($validateResult)) {
  443. $this->error = $validateResult;
  444. return false;
  445. }
  446. # 商机金额小数处理
  447. if (!empty($param['money']) && is_numeric($param['money']) && strpos($param['money'], ".") === false) {
  448. $param['money'] .= '.00';
  449. }
  450. // 处理部门、员工、附件、多选类型字段
  451. $arrFieldAtt = $fieldModel->getArrayField('crm_business');
  452. foreach ($arrFieldAtt as $k => $v) {
  453. if (isset($param[$v])) $param[$v] = arrayToString($param[$v]);
  454. }
  455. // 处理日期(date)类型
  456. $dateField = $fieldModel->getFieldByFormType('crm_business', 'date');
  457. if (!empty($dateField)) {
  458. foreach ($param AS $key => $value) {
  459. if (in_array($key, $dateField) && empty($value)) $param[$key] = null;
  460. }
  461. }
  462. // 处理手写签名类型
  463. $handwritingField = $fieldModel->getFieldByFormType('crm_business', 'handwriting_sign');
  464. if (!empty($handwritingField)) {
  465. foreach ($param AS $key => $value) {
  466. if (in_array($key, $handwritingField)) {
  467. $param[$key] = !empty($value['file_id']) ? $value['file_id'] : '';
  468. }
  469. }
  470. }
  471. // 处理地址、定位、日期区间、明细表格类型字段
  472. $positionField = $fieldModel->getFieldByFormType($this->name, 'position');
  473. $locationField = $fieldModel->getFieldByFormType($this->name, 'location');
  474. $dateIntervalField = $fieldModel->getFieldByFormType($this->name, 'date_interval');
  475. $detailTableField = $fieldModel->getFieldByFormType($this->name, 'detail_table');
  476. foreach ($param AS $key => $value) {
  477. // 处理地址类型字段数据
  478. if (in_array($key, $positionField)) {
  479. if (!empty($value)) {
  480. $businessData[] = [
  481. 'field' => $key,
  482. 'content' => json_encode($value, JSON_NUMERIC_CHECK),
  483. 'create_time' => time()
  484. ];
  485. $positionNames = array_column($value, 'name');
  486. $param[$key] = implode(',', $positionNames);
  487. } else {
  488. $param[$key] = '';
  489. }
  490. }
  491. // 处理定位类型字段数据
  492. if (in_array($key, $locationField)) {
  493. if (!empty($value)) {
  494. $businessData[] = [
  495. 'field' => $key,
  496. 'content' => json_encode($value, JSON_NUMERIC_CHECK),
  497. 'create_time' => time()
  498. ];
  499. $param[$key] = $value['address'];
  500. } else {
  501. $param[$key] = '';
  502. }
  503. }
  504. // 处理日期区间类型字段数据
  505. if (in_array($key, $dateIntervalField)) {
  506. if (!empty($value)) {
  507. $businessData[] = [
  508. 'field' => $key,
  509. 'content' => json_encode($value, JSON_NUMERIC_CHECK),
  510. 'create_time' => time()
  511. ];
  512. $param[$key] = implode('_', $value);
  513. } else {
  514. $param[$key] = '';
  515. }
  516. }
  517. // 处理明细表格类型字段数据
  518. if (in_array($key, $detailTableField)) {
  519. if (!empty($value)) {
  520. $businessData[] = [
  521. 'field' => $key,
  522. 'content' => json_encode($value, JSON_NUMERIC_CHECK),
  523. 'create_time' => time()
  524. ];
  525. $param[$key] = $key;
  526. } else {
  527. $param[$key] = '';
  528. }
  529. }
  530. }
  531. # 设置今日需联系商机
  532. if (!empty($param['next_time']) && $param['next_time'] >= strtotime(date('Y-m-d 00:00:00'))) $param['is_dealt'] = 0;
  533. $param['money'] = $param['money'] ?: '0.00';
  534. $param['discount_rate'] = $param['discount_rate'] ?: '0.00';
  535. //商机状态改变
  536. $statusInfo = db('crm_business_status')->where(['status_id' => $param['status_id']])->find();
  537. if ($statusInfo['type_id']) {
  538. $param['is_end'] = 0;
  539. } else {
  540. $param['is_end'] = $param['status_id'];
  541. }
  542. if ($this->update($param, ['business_id' => $business_id], true)) {
  543. $data['business_id'] = $business_id;
  544. //产品数据处理
  545. $resProduct = $productModel->createObject('crm_business', $param, $business_id);
  546. //修改记录
  547. updateActionLog($param['user_id'], 'crm_business', $business_id, $dataInfo, $param);
  548. RecordActionLog($param['user_id'], 'crm_business', 'update',$dataInfo['name'], $dataInfo, $param);
  549. // 添加商机扩展数据
  550. db('crm_business_data')->where('business_id', $business_id)->delete();
  551. array_walk($businessData, function (&$val) use ($business_id) {
  552. $val['business_id'] = $business_id;
  553. });
  554. db('crm_business_data')->insertAll($businessData);
  555. return $data;
  556. } else {
  557. $this->rollback();
  558. $this->error = '编辑失败';
  559. return false;
  560. }
  561. }
  562. /**
  563. * 商机数据
  564. *
  565. * @param string $id
  566. * @param int $userId
  567. * @return Common|array|bool|\PDOStatement|string|\think\Model|null
  568. * @throws \think\db\exception\DataNotFoundException
  569. * @throws \think\db\exception\ModelNotFoundException
  570. * @throws \think\exception\DbException
  571. */
  572. public function getDataById($id = '', $userId = 0,$model='')
  573. {
  574. $dataInfo = db('crm_business')->where('business_id', $id)->find();
  575. if (!$dataInfo) {
  576. $this->error = '暂无此数据';
  577. return false;
  578. }
  579. if(empty($model) && $model!='update'){
  580. $grantData = getFieldGrantData($userId);
  581. foreach ($grantData['crm_business'] as $key => $value) {
  582. foreach ($value as $ke => $va) {
  583. if($va['maskType']!=0){
  584. $fieldGrant[$ke]['maskType'] = $va['maskType'];
  585. $fieldGrant[$ke]['form_type'] = $va['form_type'];
  586. $fieldGrant[$ke]['field'] = $va['field'];
  587. }
  588. }
  589. }
  590. foreach ($fieldGrant AS $key => $val){
  591. //掩码相关类型字段
  592. if ($val['maskType']!=0 && $val['form_type'] == 'mobile') {
  593. $pattern = "/(1[3458]{1}[0-9])[0-9]{4}([0-9]{4})/i";
  594. $rs = preg_replace($pattern, "$1****$2", $dataInfo[$val['field']]);
  595. $dataInfo[$val['field']] = !empty($dataInfo[$val['field']]) ? (string)$rs : null;
  596. } elseif ($val['maskType']!=0 && $val['form_type'] == 'email') {
  597. $email_array = explode("@", $dataInfo[$val['field']]);
  598. $prevfix = (strlen($email_array[0]) < 4) ? "" : substr($dataInfo[$val['field']], 0, 2); //邮箱前缀
  599. $str = preg_replace('/([\d\w+_-]{0,100})@/', "***@", $dataInfo[$val['field']], -1, $count);
  600. $rs = $prevfix . $str;
  601. $dataInfo[$val['field']] = !empty($dataInfo[$val['field']]) ?$rs: null;
  602. } elseif ($val['maskType']!=0 && in_array($val['form_type'],['position','floatnumber'])) {
  603. $dataInfo[$val['field']] = !empty($dataInfo[$val['field']]) ? (string)substr_replace($dataInfo[$val['field']], '*****',0,strlen($dataInfo[$val['field']])) : null;
  604. }
  605. }
  606. }
  607. $userModel = new \app\admin\model\User();
  608. $dataInfo['create_user_id_info'] = isset($dataInfo['create_user_id']) ? $userModel->getUserById($dataInfo['create_user_id']) : [];
  609. $dataInfo['owner_user_id_info'] = isset($dataInfo['owner_user_id']) ? $userModel->getUserById($dataInfo['owner_user_id']) : [];
  610. $dataInfo['create_user_name'] = !empty($dataInfo['create_user_id_info']['realname']) ? $dataInfo['create_user_id_info']['realname'] : '';
  611. $dataInfo['owner_user_name'] = !empty($dataInfo['owner_user_id_info']['realname']) ? $dataInfo['owner_user_id_info']['realname'] : '';
  612. $dataInfo['type_id_info'] = db('crm_business_type')->where(['type_id' => $dataInfo['type_id']])->value('name');
  613. $dataInfo['status_id_info'] = db('crm_business_status')->where(['status_id' => $dataInfo['status_id']])->value('name');
  614. $dataInfo['customer_id_info'] = db('crm_customer')->where(['customer_id' => $dataInfo['customer_id']])->field('customer_id,name')->find();
  615. $dataInfo['customer_name'] = !empty($dataInfo['customer_id_info']['name']) ? $dataInfo['customer_id_info']['name'] : '';
  616. # 关注
  617. $starId = empty($userId) ? 0 : Db::name('crm_star')->where(['user_id' => $userId, 'target_id' => $id, 'type' => 'crm_business'])->value('star_id');
  618. $dataInfo['star'] = !empty($starId) ? 1 : 0;
  619. # 首要联系人
  620. $primaryId = Db::name('crm_contacts')->where(['contacts_id' => $dataInfo['contacts_id']])->value('contacts_id');
  621. $dataInfo['contacts_id'] = !empty($primaryId) && $this->getContactsAuth($primaryId) ? $primaryId : 0;
  622. # 处理日期格式
  623. $fieldModel = new \app\admin\model\Field();
  624. $datetimeField = $fieldModel->getFieldByFormType('crm_business', 'datetime'); //日期时间类型
  625. foreach ($datetimeField as $key => $val) {
  626. $dataInfo[$val] = !empty($dataInfo[$val]) ? date('Y-m-d H:i:s', $dataInfo[$val]) : null;
  627. }
  628. if($dataInfo['is_end']!=1){
  629. $dataInfo['statusRemark']=db('crm_business_log')->where(['business_id'=>$id,'is_end'=>$dataInfo['is_end']])->value('remark');
  630. }
  631. $dataInfo['next_time'] = !empty($dataInfo['next_time']) ? date('Y-m-d H:i:s', $dataInfo['next_time']) : null;
  632. $dataInfo['create_time'] = !empty($dataInfo['create_time']) ? date('Y-m-d H:i:s', $dataInfo['create_time']) : null;
  633. $dataInfo['update_time'] = !empty($dataInfo['update_time']) ? date('Y-m-d H:i:s', $dataInfo['update_time']) : null;
  634. $dataInfo['last_time'] = !empty($dataInfo['last_time']) ? date('Y-m-d H:i:s', $dataInfo['last_time']) : null;
  635. // 字段授权
  636. if (!empty($userId)) {
  637. $grantData = getFieldGrantData($userId);
  638. $userLevel = isSuperAdministrators($userId);
  639. foreach ($dataInfo AS $key => $value) {
  640. if (!$userLevel && !empty($grantData['crm_business'])) {
  641. $status = getFieldGrantStatus($key, $grantData['crm_business']);
  642. # 查看权限
  643. if ($status['read'] == 0) unset($dataInfo[$key]);
  644. }
  645. }
  646. }
  647. return $dataInfo;
  648. }
  649. //根据IDs获取数组
  650. public function getDataByStr($idstr)
  651. {
  652. $idArr = stringToArray($idstr);
  653. if (!$idArr) {
  654. return [];
  655. }
  656. $list = Db::name('CrmBusiness')->where(['business_id' => ['in', $idArr]])->select();
  657. return $list;
  658. }
  659. /**
  660. * [商机漏斗]
  661. * @param
  662. * @return
  663. * @author Michael_xu
  664. */
  665. public function getFunnel($request)
  666. {
  667. $merge = $request['merge'] ?: 0;
  668. $perUserIds = $request['perUserIds'] ?: [];
  669. $adminModel = new \app\admin\model\Admin();
  670. $whereArr = $adminModel->getWhere($request, $merge, $perUserIds); //统计查询
  671. $userIds = $whereArr['userIds'];
  672. $between_time = $whereArr['between_time'];
  673. $where['owner_user_id'] = array('in', $userIds);
  674. $where['create_time'] = array('between', $between_time);
  675. //商机状态组
  676. $default_type_id = db('crm_business_type')->order('type_id asc')->value('type_id');
  677. $type_id = $request['type_id'] ? $request['type_id'] : $default_type_id;
  678. $statusList = db('crm_business_status')->where(['type_id' => $type_id])->select();
  679. $map = [];
  680. $map['create_time'] = $where['create_time'];
  681. $map['owner_user_id'] = ['in', $userIds];
  682. $map['type_id'] = $type_id;
  683. $sql_a = CrmBusinessModel::field([
  684. 'SUM(CASE WHEN is_end = 1 THEN money ELSE 0 END) AS sum_ying',
  685. 'SUM(CASE WHEN is_end = 2 THEN money ELSE 0 END) AS sum_shu',
  686. 'type_id'
  687. ])
  688. ->where($map)
  689. ->fetchSql()
  690. ->find();
  691. $res_a = queryCache($sql_a, 200);
  692. $sql = CrmBusinessModel::field([
  693. "status_id",
  694. 'COUNT(*)' => 'count',
  695. 'SUM(`money`)' => 'sum',
  696. 'type_id'
  697. ])
  698. ->where($where)
  699. ->whereNotIn('is_end', '1,2,3')
  700. ->group('status_id')
  701. ->fetchSql()
  702. ->select();
  703. $res = queryCache($sql, 200);
  704. $res = array_column($res, null, 'status_id');
  705. $sum_money = 0;
  706. $count = 0; # 商机数总和
  707. $moneyCount = 0; # 金额总和
  708. foreach ($statusList as $k => $v) {
  709. $v['count'] = $res[$v['status_id']]['count'] ?: 0;
  710. $v['money'] = $res[$v['status_id']]['sum'] ?: 0;
  711. $v['status_name'] = $v['name'];
  712. $statusList[$k] = $v;
  713. $sum_money += $v['money'];
  714. $moneyCount += $v['money'];
  715. $count += $v['count'];
  716. }
  717. $data['list'] = $statusList;
  718. $data['sum_ying'] = $res_a[0]['sum_ying'] ?: 0;
  719. $data['sum_shu'] = $res_a[0]['sum_shu'] ?: 0;
  720. $data['sum_money'] = $sum_money ?: 0;
  721. $data['total'] = ['name' => '合计', 'money_count' => $moneyCount, 'count' => $count];
  722. return $data ?: [];
  723. }
  724. /**
  725. * [商机转移]
  726. * @param ids 商机ID数组
  727. * @param owner_user_id 变更负责人
  728. * @param is_remove 1移出,2转为团队成员
  729. * @return
  730. * @author Michael_xu
  731. */
  732. public function transferDataById($ids, $owner_user_id, $type = 1, $is_remove)
  733. {
  734. $settingModel = new \app\crm\model\Setting();
  735. $errorMessage = [];
  736. foreach ($ids as $id) {
  737. $businessInfo = db('crm_business')->where(['business_id' => $id])->find();
  738. //团队成员
  739. $teamData = [];
  740. $teamData['type'] = $type; //权限 1只读2读写
  741. $teamData['user_id'] = [$businessInfo['owner_user_id']]; //协作人
  742. $teamData['types'] = 'crm_business'; //类型
  743. $teamData['types_id'] = $id; //类型ID
  744. $teamData['is_del'] = ($is_remove == 1) ? 1 : '';
  745. $res = $settingModel->createTeamData($teamData);
  746. $data = [];
  747. $data['owner_user_id'] = $owner_user_id;
  748. $data['update_time'] = time();
  749. if (!db('crm_business')->where(['business_id' => $id])->update($data)) {
  750. $errorMessage[] = '商机:' . $businessInfo['name'] . '"转移失败,错误原因:数据出错;';
  751. continue;
  752. } else {
  753. $businessArray = [];
  754. $teamBusiness = db('crm_business')->field(['owner_user_id', 'ro_user_id', 'rw_user_id'])->where('business_id', $id)->find();
  755. if (!empty($teamBusiness['ro_user_id'])) {
  756. $businessRo = arrayToString(array_diff(stringToArray($teamBusiness['ro_user_id']), [$teamBusiness['owner_user_id']]));
  757. $businessArray['ro_user_id'] = $businessRo;
  758. }
  759. if (!empty($teamBusiness['rw_user_id'])) {
  760. $businessRo = arrayToString(array_diff(stringToArray($teamBusiness['rw_user_id']), [$teamBusiness['owner_user_id']]));
  761. $businessArray['rw_user_id'] = $businessRo;
  762. }
  763. db('crm_business')->where('business_id', $id)->update($businessArray);
  764. }
  765. }
  766. if ($errorMessage) {
  767. return $errorMessage;
  768. } else {
  769. return true;
  770. }
  771. }
  772. /**
  773. * [商机统计]
  774. * @param
  775. * @return
  776. */
  777. public function getTrendql($map)
  778. {
  779. $prefix = config('database.prefix');
  780. $sql = "SELECT
  781. '{$map['type']}' AS type,
  782. '{$map['start_time']}' AS start_time,
  783. '{$map['end_time']}' AS end_time,
  784. IFNULL(
  785. (
  786. SELECT
  787. sum(money)
  788. FROM
  789. {$prefix}crm_business
  790. WHERE
  791. create_time BETWEEN {$map['start_time']} AND {$map['end_time']}
  792. AND owner_user_id IN ({$map['owner_user_id']})
  793. ),
  794. 0
  795. ) AS business_money,
  796. IFNULL(
  797. count(business_id),
  798. 0
  799. ) AS business_num
  800. FROM
  801. {$prefix}crm_business
  802. WHERE
  803. create_time BETWEEN {$map['start_time']} AND {$map['end_time']}
  804. AND owner_user_id IN ({$map['owner_user_id']})";
  805. return $sql;
  806. }
  807. /**
  808. * [赢单机会转化率趋势分析]
  809. * @param
  810. * @return
  811. */
  812. public function getWinSql($map)
  813. {
  814. $prefix = config('database.prefix');
  815. $sql = "SELECT
  816. '{$map['type']}' AS type,
  817. '{$map['start_time']}' AS start_time,
  818. '{$map['end_time']}' AS end_time,
  819. IFNULL(
  820. (
  821. SELECT
  822. count(business_id)
  823. FROM
  824. {$prefix}crm_business
  825. WHERE
  826. create_time BETWEEN {$map['start_time']} AND {$map['end_time']}
  827. AND owner_user_id IN ({$map['owner_user_id']})
  828. AND is_end = 1
  829. ),
  830. 0
  831. ) AS business_end,
  832. IFNULL(
  833. count(business_id),
  834. 0
  835. ) AS business_num
  836. FROM
  837. {$prefix}crm_business
  838. WHERE
  839. create_time BETWEEN {$map['start_time']} AND {$map['end_time']}
  840. AND owner_user_id IN ({$map['owner_user_id']})";
  841. return $sql;
  842. }
  843. /**
  844. * 获取系统信息
  845. *
  846. * @param $id
  847. * @return array
  848. * @throws \think\db\exception\DataNotFoundException
  849. * @throws \think\db\exception\ModelNotFoundException
  850. * @throws \think\exception\DbException
  851. */
  852. public function getSystemInfo($id)
  853. {
  854. # 商机
  855. $business = Db::name('crm_business')->field(['create_user_id' ,'owner_user_id', 'create_time', 'update_time', 'last_time'])->where('business_id', $id)->find();
  856. # 创建人
  857. $realname = Db::name('admin_user')->where('id', $business['create_user_id'])->value('realname');
  858. # zjf 20210726
  859. $userModel = new \app\admin\model\User();
  860. $ownerUserInfo = $userModel->getUserById($business['owner_user_id']);
  861. # 负责人部门
  862. $ownerStructureName = $ownerUserInfo['structure_name'];
  863. # 负责人
  864. $ownerUserName = $ownerUserInfo['realname'];
  865. return [
  866. 'create_user_id' => $realname,
  867. 'owner_user_id' => $ownerUserName,
  868. 'create_time' => date('Y-m-d H:i:s', $business['create_time']),
  869. 'update_time' => date('Y-m-d H:i:s', $business['update_time']),
  870. 'last_time' => !empty($business['last_time']) ? date('Y-m-d H:i:s', $business['last_time']) : '',
  871. 'owner_user_structure_name' => $ownerStructureName
  872. ];
  873. }
  874. /**
  875. * 判断联系人详情权限 todo 客户模块也在用,以后抽成一个公共的方法
  876. *
  877. * @param $contactsId
  878. * @return bool
  879. */
  880. private function getContactsAuth($contactsId)
  881. {
  882. $ownerUserId = db('crm_contacts')->where('contacts_id', $contactsId)->value('owner_user_id');
  883. $authUserIds = (new \app\admin\model\User())->getUserByPer('crm', 'contacts', 'read');
  884. return in_array($ownerUserId, $authUserIds);
  885. }
  886. }