ActivityLogic.php 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. <?php
  2. /**
  3. * 活动逻辑类
  4. *
  5. * @author qifan
  6. * @date 2020-12-09
  7. */
  8. namespace app\crm\logic;
  9. use app\crm\model\Activity;
  10. use think\Db;
  11. class ActivityLogic
  12. {
  13. # 活动类型 1 线索 2 客户 3 联系人 4 产品 5 商机 6 合同 7 回款 8 日志 9 审批 10 日程 11 任务 12 发邮件
  14. private $activityType = [
  15. 1 => ['en' => 'crm_leads', 'cn' => '线索'],
  16. 2 => ['en' => 'crm_customer', 'cn' => '客户'],
  17. 3 => ['en' => 'crm_contacts', 'cn' => '联系人'],
  18. 4 => ['en' => 'crm_product', 'cn' => '产品'],
  19. 5 => ['en' => 'crm_business', 'cn' => '商机'],
  20. 6 => ['en' => 'crm_contract', 'cn' => '合同'],
  21. 7 => ['en' => 'crm_receivables', 'cn' => '回款'],
  22. 8 => ['en' => 'oa_log', 'cn' => '日志'],
  23. 9 => ['en' => 'oa_examine', 'cn' => '审批'],
  24. 10 => ['en' => 'oa_event', 'cn' => '日程'],
  25. 11 => ['en' => 'oa_task', 'cn' => '任务'],
  26. 12 => ['en' => 'mail', 'cn' => '发邮件']
  27. ];
  28. private $moduleToNumber = [
  29. 'leads' => 1,
  30. 'customer' => 2,
  31. 'contacts' => 3,
  32. 'product' => 4,
  33. 'business' => 5,
  34. 'contract' => 6,
  35. 'receivables' => 7,
  36. 'log' => 8,
  37. 'examine' => 9,
  38. 'event' => 10,
  39. 'task' => 11,
  40. 'email' => 12
  41. ];
  42. /**
  43. * 活动列表
  44. *
  45. * @param $param
  46. * @return array
  47. * @throws \think\db\exception\DataNotFoundException
  48. * @throws \think\db\exception\ModelNotFoundException
  49. * @throws \think\exception\DbException
  50. */
  51. public function index($param)
  52. {
  53. $userId = $param['user_id'];
  54. unset($param['user_id']);
  55. unset($param['crmType']);
  56. $param['limit'] = !empty($param['limit']) ? $param['limit'] : 15;
  57. $param['page'] = !empty($param['page']) ? $param['page'] : 1;
  58. $recordWhere = [];
  59. $commonWhere = [];
  60. $leadsWhere = [];
  61. $customerWhere = function () {};
  62. $contactsWhere = function () {};
  63. $businessWhere = function () {};
  64. $contractWhere = function () {};
  65. $dateGroupWhere = function () {};
  66. # 跟进记录权限判断
  67. if (!checkPerByAction('crm', 'activity', 'index')) {
  68. $recordWhere['type'] = ['neq', 1];
  69. }
  70. # 设置时间分组查询条件,第一页就是当天的数据,第二页就是下一天的数据
  71. $datetime = Db::name('crm_activity')
  72. ->field('update_time')
  73. ->where($recordWhere)
  74. ->where('status', 1)
  75. ->where(function ($query) use ($param) {
  76. $query->whereOr(function ($query) use ($param) {
  77. $query->where('activity_type_id', $param['activity_type_id']);
  78. $query->where('activity_type', $this->moduleToNumber[$param['module']]);
  79. });
  80. $query->whereOr('customer_ids', 'like', '%'.$param['activity_type_id'].'%');
  81. $query->whereOr('contacts_ids', 'like', '%'.$param['activity_type_id'].'%');
  82. $query->whereOr('contract_ids', 'like', '%'.$param['activity_type_id'].'%');
  83. $query->whereOr('business_ids', 'like', '%'.$param['activity_type_id'].'%');
  84. $query->whereOr('leads_ids', 'like', '%'.$param['activity_type_id'].'%');
  85. })
  86. ->order('update_time', 'desc')
  87. ->group('update_time')
  88. ->select();
  89. $dateGroup = [0 => '']; // 加一个占位,page是从1开始
  90. $dateWhere = [0 => []]; // 加一个占位,page是从1开始
  91. foreach ($datetime AS $key => $value) {
  92. $date = date('Y-m-d', $value['update_time']);
  93. if (!in_array($date, $dateGroup)) {
  94. $dateGroup[] = $date;
  95. $dateWhere[] = [
  96. 'start_time' => strtotime($date . ' 00:00:00'),
  97. 'end_time' => strtotime($date . ' 23:59:59')
  98. ];
  99. }
  100. }
  101. if (!empty($dateWhere[$param['page']])) {
  102. $dateGroupWhere = function ($query) use ($param, $dateWhere) {
  103. $query->where('update_time', '>=', $dateWhere[$param['page']]['start_time']);
  104. $query->where('update_time', '<=', $dateWhere[$param['page']]['end_time']);
  105. };
  106. }
  107. if (empty($dateWhere[$param['page']])) {
  108. return ['lastPage' => true, 'list' => [], 'time' => ''];
  109. }
  110. # 处理公共查询参数
  111. if (!empty($param['interval_day'])) {
  112. $commonWhere['update_time'] = ['egt', time() - 86400 * $param['interval_day']];
  113. $commonWhere['update_time'] = ['elt', time()];
  114. }
  115. if (!empty($param['start_date']) && !empty($param['end_date'])) {
  116. $commonWhere['update_time'] = ['egt', strtotime($param['start_date'])];
  117. $commonWhere['update_time'] = ['elt', strtotime($param['end_date'])];
  118. }
  119. if (!empty($param['search'])) {
  120. $commonWhere['content'] = ['like', '%' . $param['search'] . '%'];
  121. }
  122. if (!empty($param['activity_type'])) {
  123. $commonWhere['activity_type'] = $param['activity_type'];
  124. }
  125. # 组织线索、客户、联系人、商机、合同下的查询条件
  126. switch ($param['module']) {
  127. case 'leads' :
  128. $leadsWhere = function ($query) use ($param) {
  129. $query->where('activity_type', 1);
  130. $query->where('activity_type_id', $param['activity_type_id']);
  131. };
  132. break;
  133. case 'customer' :
  134. $contactsData = [];
  135. $businessData = [];
  136. $contractData = [];
  137. $receivablesData = [];
  138. # 联系人ID串
  139. $contacts = Db::name('crm_contacts')->field(['contacts_id'])->where('customer_id', $param['activity_type_id'])->select();
  140. if (!empty($contacts)) {
  141. $contactsData['activity_type'] = 3;
  142. $contactsData['activity_type_id'] = array_reduce($contacts, function ($result, $value) {
  143. return array_merge($result, array_values($value));
  144. }, []);
  145. }
  146. # 商机ID串
  147. $business = Db::name('crm_business')->field(['business_id'])->where('customer_id', $param['activity_type_id'])->select();
  148. if (!empty($business)) {
  149. $businessData['activity_type'] = 5;
  150. $businessData['activity_type_id'] = array_reduce($business, function ($result, $value) {
  151. return array_merge($result, array_values($value));
  152. }, []);
  153. }
  154. # 合同ID串
  155. $contract = Db::name('crm_contract')->field(['contract_id'])->where('customer_id', $param['activity_type_id'])->select();
  156. if (!empty($contract)) {
  157. $contractData['activity_type'] = 6;
  158. $contractData['activity_type_id'] = array_reduce($contract, function ($result, $value) {
  159. return array_merge($result, array_values($value));
  160. }, []);
  161. }
  162. # 回款ID串
  163. $receivables = Db::name('crm_receivables')->field(['receivables_id'])->where('customer_id', $param['activity_type_id'])->select();
  164. if (!empty($receivables)) {
  165. $receivablesData['activity_type'] = 7;
  166. $receivablesData['activity_type_id'] = array_reduce($receivables, function ($result, $value) {
  167. return array_merge($result, array_values($value));
  168. }, []);
  169. }
  170. # 客户模块查询条件
  171. $customerWhere = function ($query) use ($param, $contactsData, $businessData, $contractData, $receivablesData) {
  172. $query->whereOr(function ($query) use ($param) {
  173. $query->where('activity_type', 2);
  174. $query->where('activity_type_id', $param['activity_type_id']);
  175. });
  176. $query->whereOr(function ($query) use ($param) {
  177. $query->where('customer_ids', 'like', '%' . $param['activity_type_id'] . '%');
  178. });
  179. if (!empty($contactsData)) {
  180. $query->whereOr(function ($query) use ($contactsData) {
  181. $query->where('activity_type', $contactsData['activity_type']);
  182. $query->whereIn('activity_type_id', $contactsData['activity_type_id']);
  183. });
  184. }
  185. if (!empty($businessData)) {
  186. $query->whereOr(function ($query) use ($businessData) {
  187. $query->where('activity_type', $businessData['activity_type']);
  188. $query->whereIn('activity_type_id', $businessData['activity_type_id']);
  189. });
  190. }
  191. if (!empty($contractData)) {
  192. $query->whereOr(function ($query) use ($contractData) {
  193. $query->where('activity_type', $contractData['activity_type']);
  194. $query->whereIn('activity_type_id', $contractData['activity_type_id']);
  195. });
  196. }
  197. if (!empty($receivablesData)) {
  198. $query->whereOr(function ($query) use ($receivablesData) {
  199. $query->where('activity_type', $receivablesData['activity_type']);
  200. $query->whereIn('activity_type_id', $receivablesData['activity_type_id']);
  201. });
  202. }
  203. };
  204. break;
  205. case 'contacts' :
  206. $customerId = Db::name('crm_contacts')->where('contacts_id', $param['activity_type_id'])->value('customer_id');
  207. $businessData = [];
  208. $contractData = [];
  209. # 商机ID串
  210. $business = Db::name('crm_business')->field(['business_id'])->where('customer_id', $customerId)->select();
  211. if (!empty($business)) {
  212. $businessData['activity_type'] = 5;
  213. $businessData['activity_type_id'] = array_reduce($business, function ($result, $value) {
  214. return array_merge($result, array_values($value));
  215. }, []);
  216. }
  217. # 合同ID串
  218. $contract = Db::name('crm_contract')->field(['contract_id'])->where('contacts_id', $customerId)->select();
  219. if (!empty($contract)) {
  220. $contractData['activity_type'] = 6;
  221. $contractData['activity_type_id'] = array_reduce($contract, function ($result, $value) {
  222. return array_merge($result, array_values($value));
  223. }, []);
  224. }
  225. # 联系人模块查询条件
  226. $contactsWhere = function ($query) use ($param, $businessData, $contractData) {
  227. $query->whereOr(function ($query) use ($param) {
  228. $query->where('activity_type', 3);
  229. $query->where('activity_type_id', $param['activity_type_id']);
  230. });
  231. $query->whereOr(function ($query) use ($param) {
  232. $query->where('contacts_ids', 'like', '%' . $param['activity_type_id'] . '%');
  233. });
  234. if (!empty($businessData)) {
  235. $query->whereOr(function ($query) use ($businessData) {
  236. $query->where('activity_type', $businessData['activity_type']);
  237. $query->whereIn('activity_type_id', $businessData['activity_type_id']);
  238. });
  239. }
  240. if (!empty($contractData)) {
  241. $query->whereOr(function ($query) use ($contractData) {
  242. $query->where('activity_type', $contractData['activity_type']);
  243. $query->whereIn('activity_type_id', $contractData['activity_type_id']);
  244. });
  245. }
  246. };
  247. break;
  248. case 'business' :
  249. $contractData = [];
  250. # 合同ID串
  251. $contract = Db::name('crm_contract')->field(['contract_id'])->where('business_id', $param['activity_type_id'])->select();
  252. if (!empty($contract)) {
  253. $contractData['activity_type'] = 6;
  254. $contractData['activity_type_id'] = array_reduce($contract, function ($result, $value) {
  255. return array_merge($result, array_values($value));
  256. }, []);
  257. }
  258. # 商机模块查询条件
  259. $businessWhere = function ($query) use ($param, $contractData) {
  260. $query->whereOr(function ($query) use ($param) {
  261. $query->where('activity_type', 5);
  262. $query->where('activity_type_id', $param['activity_type_id']);
  263. });
  264. $query->whereOr(function ($query) use ($param) {
  265. $query->where('business_ids', 'like', '%' . $param['activity_type_id'] . '%');
  266. $query->where(['activity_type' => ['neq', 2]]);
  267. });
  268. if (!empty($contractData)) {
  269. $query->whereOr(function ($query) use ($contractData) {
  270. $query->where('activity_type', $contractData['activity_type']);
  271. $query->whereIn('activity_type_id', $contractData['activity_type_id']);
  272. });
  273. }
  274. };
  275. break;
  276. case 'contract' :
  277. $receivablesData = [];
  278. # 回款ID串
  279. $receivables = Db::name('crm_receivables')->field(['receivables_id'])->where('contract_id', $param['activity_type_id'])->select();
  280. if (!empty($receivables)) {
  281. $receivablesData['activity_type'] = 7;
  282. $receivablesData['activity_type_id'] = array_reduce($receivables, function ($result, $value) {
  283. return array_merge($result, array_values($value));
  284. }, []);
  285. }
  286. # 合同模块查询条件
  287. $contractWhere = function ($query) use ($param, $receivables) {
  288. $query->whereOr(function ($query) use ($param) {
  289. $query->where('activity_type', 6);
  290. $query->where('activity_type_id', $param['activity_type_id']);
  291. });
  292. $query->whereOr(function ($query) use ($param) {
  293. $query->where('contract_ids', 'like', '%' . $param['activity_type_id'] . '%');
  294. });
  295. if (!empty($receivablesData)) {
  296. $query->whereOr(function ($query) use ($receivablesData) {
  297. $query->where('activity_type', $receivablesData['activity_type']);
  298. $query->whereIn('activity_type_id', $receivablesData['activity_type_id']);
  299. });
  300. }
  301. };
  302. break;
  303. }
  304. $field = [
  305. 'activity_id',
  306. 'type',
  307. 'category',
  308. 'activity_type',
  309. 'activity_type_id',
  310. 'content',
  311. 'contacts_ids',
  312. 'next_time',
  313. 'create_user_id',
  314. 'update_time',
  315. 'business_ids'
  316. ];
  317. $dataArray = Db::name('crm_activity')->field($field)
  318. ->where($dateGroupWhere)
  319. ->where($recordWhere)
  320. ->where($commonWhere)
  321. ->where($customerWhere)
  322. ->where($contactsWhere)
  323. ->where($businessWhere)
  324. ->where($contractWhere)
  325. ->where($leadsWhere)
  326. ->where('status', 1)
  327. ->order('update_time', 'desc')
  328. ->select();
  329. $fileModel = new \app\admin\model\File();
  330. foreach ($dataArray AS $key => $value) {
  331. # 用户信息 todo 有模型文件,时间问题,暂时将查询写在循环中
  332. $realname = Db::name('admin_user')->where('id', $dataArray[$key]['create_user_id'])->find();
  333. $dataArray[$key]['create_user_name'] = $realname['realname'];
  334. $dataArray[$key]['thumb_img'] = $realname['thumb_img'] ? getFullPath($realname['thumb_img']) : '';;
  335. # 附件信息
  336. if ($value['type'] = 1) {
  337. $files = [];
  338. $images = [];
  339. $fileList = $fileModel->getDataList(['module' => 'crm_activity', 'module_id' => $dataArray[$key]['activity_id']], 'all');
  340. if (!empty($fileList['list'])) {
  341. foreach ($fileList['list'] AS $k => $v) {
  342. if ($v['types'] == 'file') {
  343. $files[] = $v;
  344. } else {
  345. $images[] = $v;
  346. }
  347. }
  348. }
  349. $dataArray[$key]['fileList'] = $files ? : [];
  350. $dataArray[$key]['imgList'] = $images ? : [];
  351. }
  352. # 判断是不是本人添加的,如果不是将禁止删除修改
  353. $dataArray[$key]['auth'] = false;
  354. if ($dataArray[$key]['type'] == 1 && $dataArray[$key]['create_user_id'] == $userId) {
  355. $dataArray[$key]['auth'] = true;
  356. }
  357. # 查询联系人信息
  358. $dataArray[$key]['contacts_name'] = '';
  359. if ($dataArray[$key]['type'] == 1 && !empty($dataArray[$key]['contacts_ids'])) {
  360. $dataArray[$key]['contacts_name'] = Db::name('crm_contacts')->where('contacts_id', $dataArray[$key]['contacts_ids'])->value('name');
  361. }
  362. # 时间格式处理
  363. $dataArray[$key]['update_time'] = date('Y-m-d H:i:s', $value['update_time']);
  364. $dataArray[$key]['create_time'] = date('Y-m-d H:i:s', $value['create_time']);
  365. $dataArray[$key]['next_time'] = !empty($value['next_time']) ? date('Y-m-d H:i:s', $value['next_time']) : '';
  366. # 获取类型名称
  367. $dataArray[$key]['activity_type_name'] = $this->getActivityName($value['activity_type'], $value['activity_type_id']);
  368. # 客户模块跟进记录关联的商机
  369. $dataArray[$key]['business_list'] = $value['activity_type'] == 2 ? $this->getBusinessInfo($value['business_ids']) : [];
  370. }
  371. # 是否是最后一页
  372. $lastPage = !empty($dateGroup[$param['page']]) && $param['page'] < count($dateGroup) - 1 ? false : true;
  373. return ['lastPage' => $lastPage, 'list' => $dataArray, 'time' => !empty($dateGroup[$param['page']]) ? $dateGroup[$param['page']] : ''];
  374. }
  375. /**
  376. * 活动详情【跟进记录】
  377. *
  378. * @param $activityId
  379. * @return array|bool|\PDOStatement|string|\think\Model|null
  380. * @throws \think\db\exception\DataNotFoundException
  381. * @throws \think\db\exception\ModelNotFoundException
  382. * @throws \think\exception\DbException
  383. */
  384. public function read($activityId)
  385. {
  386. # 查询跟进记录信息
  387. $field = ['activity_id', 'category', 'activity_type', 'activity_type_id', 'content', 'next_time', 'customer_ids', 'contacts_ids', 'contract_ids', 'business_ids'];
  388. $activityData = Activity::field($field)->where('type', 1)->where('activity_id', $activityId)->where('status', 1)->find();
  389. if (empty($activityData)) return [];
  390. # 查询与跟进记录关联的客户信息
  391. $customerData = Db::name('crm_customer')->field(['customer_id', 'name'])->whereIn('customer_id', $activityData['customer_ids'])->select();
  392. $activityData['customerInfo'] = $customerData;
  393. # 查询与跟进记录关联的联系人信息
  394. $contactsData = Db::name('crm_contacts')->field(['contacts_id', 'name'])->whereIn('contacts_id', $activityData['contacts_ids'])->select();
  395. $activityData['contactsInfo'] = $contactsData;
  396. # 查询与跟进记录关联的合同信息
  397. $contractData = Db::name('crm_contract')->field(['contract_id', 'name'])->whereIn('contract_id', $activityData['contract_ids'])->select();
  398. $activityData['contractInfo'] = $contractData;
  399. # 查询与跟进记录关联的商机信息
  400. $businessData = Db::name('crm_business')->field(['business_id', 'name'])->whereIn('business_id', $activityData['business_ids'])->select();
  401. $activityData['businessInfo'] = $businessData;
  402. # 查询与跟进记录关联的附件
  403. $fileData = (new \app\admin\model\File())->getDataList(['module' => 'crm_activity', 'module_id' => $activityId], 'all');
  404. $activityData['fileInfo'] = $fileData;
  405. return $activityData;
  406. }
  407. /**
  408. * 创建活动【跟进记录】
  409. *
  410. * @param $param
  411. * @return bool
  412. * @throws \think\Exception
  413. * @throws \think\exception\PDOException
  414. */
  415. public function save($param)
  416. {
  417. $userId = $param['user_id'];
  418. $isEvent = !empty($param['is_event']) ? $param['is_event'] : 0;
  419. $fileIds = !empty($param['file_id']) ? $param['file_id'] : [];
  420. unset($param['is_event']);
  421. unset($param['file_id']);
  422. unset($param['user_id']);
  423. $param['create_user_id'] = $userId;
  424. $param['type'] = 1;
  425. $param['next_time'] = !empty($param['next_time']) ? strtotime($param['next_time']) : 0;
  426. $param['business_ids'] = !empty($param['business_ids']) ? implode(',', $param['business_ids']) : '';
  427. $param['create_time'] = time();
  428. $param['update_time'] = time();
  429. $activityJson = Activity::create($param);
  430. if (empty($activityJson)) return false;
  431. $activityArray = json_decode($activityJson, true);
  432. if (empty($activityArray['activity_id'])) return false;
  433. # 设置最后跟进记录
  434. $this->setFollowRecord($param['activity_type'], $param['activity_type_id'], $param['content']);
  435. # 下次联系时间
  436. $this->updateNextTime($this->activityType[$param['activity_type']]['en'], $param['activity_type_id'], $param['next_time'],false);
  437. # 处理附件关系
  438. if (!empty($fileIds)) {
  439. $fileModel = new \app\admin\model\File();
  440. $fileModel->createDataById($fileIds, 'crm_activity', $activityArray['activity_id']);
  441. }
  442. # 同时创建日程
  443. if ($isEvent) {
  444. $eventModel = new \app\oa\model\Event();
  445. $data['title'] = trim($param['content']);
  446. $data['content'] = trim($param['content']);
  447. $data['start_time'] = !empty($param['next_time']) ? $param['next_time'] : time();
  448. $data['end_time'] = $param['next_time'] + 86399;
  449. $data['create_user_id'] = $param['create_user_id'];
  450. $data['business_ids'] = $param['business_ids'];
  451. $data['contacts_ids'] = $param['contacts_ids'];
  452. $data['is_live'] = true;
  453. if ($param['activity_type'] == 'crm_customer') $data['customer_ids'] = $param['activity_type_id'];
  454. $eventModel->createData($data);
  455. }
  456. return true;
  457. }
  458. /**
  459. * 修改活动【跟进记录】
  460. *
  461. * @param $param
  462. * @return bool
  463. * @throws \think\Exception
  464. * @throws \think\exception\PDOException
  465. */
  466. public function update($param)
  467. {
  468. $isEvent = !empty($param['is_event']) ? $param['is_event'] : 0;
  469. $fileIds = !empty($param['file_id']) ? $param['file_id'] : [];
  470. unset($param['is_event']);
  471. unset($param['file_id']);
  472. $param['type'] = 1;
  473. $param['next_time'] = strtotime($param['next_time']);
  474. $param['business_ids'] = !empty($param['business_ids']) ? implode(',', $param['business_ids']) : '';
  475. $param['update_time'] = time();
  476. if (!Activity::update($param)) return false;
  477. # 设置最后跟进记录
  478. $this->setFollowRecord($param['activity_type'], $param['activity_type_id'], $param['content']);
  479. # 下次联系时间
  480. $this->updateNextTime($this->activityType[$param['activity_type']]['en'], $param['activity_type_id'], $param['next_time'],false);
  481. # 处理附件关系
  482. $fileModel = new \app\admin\model\File();
  483. if (!empty($fileIds)) {
  484. # 删除
  485. $fileModel->delRFileByModule('crm_activity', $param['activity_id']);
  486. # 添加
  487. $fileModel->createDataById($fileIds, 'crm_activity', $param['activity_id']);
  488. } else {
  489. # 删除
  490. $fileModel->delRFileByModule('crm_activity', $param['activity_id']);
  491. }
  492. # 同时创建日程
  493. if ($isEvent) {
  494. $eventModel = new \app\oa\model\Event();
  495. $data['title'] = trim($param['content']);
  496. $data['content'] = trim($param['content']);
  497. $data['start_time'] = !empty($param['next_time']) ? $param['next_time'] : time();
  498. $data['end_time'] = $param['next_time'] + 86399;
  499. $data['create_user_id'] = $param['create_user_id'];
  500. $data['business_ids'] = $param['business_ids'];
  501. $data['contacts_ids'] = $param['contacts_ids'];
  502. if ($param['activity_type'] == 2) $data['customer_ids'] = $param['activity_type_id'];
  503. $eventModel->createData($data);
  504. }
  505. return true;
  506. }
  507. /**
  508. * 删除活动【跟进记录】
  509. *
  510. * @param $activityId
  511. * @return Activity
  512. */
  513. public function delete($activityId)
  514. {
  515. $activityInfo = Db::name('crm_activity')->where(['activity_id' => $activityId])->find();
  516. if (Activity::update(['activity_id' => $activityId, 'status' => 0])) {
  517. $this->updateNextTime($this->activityType[$activityInfo['activity_type']]['en'], $activityInfo['activity_type_id'], '', true);
  518. return true;
  519. } else {
  520. return false;
  521. }
  522. }
  523. /**
  524. * 相关模块下次联系时间
  525. *
  526. * @param $types
  527. * @param $types_id
  528. * @param string $next_time
  529. * @return bool
  530. * @throws \think\Exception
  531. * @throws \think\exception\PDOException
  532. */
  533. private function updateNextTime($types, $types_id, $next_time = '', $is_del = false)
  534. {
  535. switch ($types) {
  536. case 'crm_customer' : $dbName = db('crm_customer'); $dbId = 'customer_id'; $activity_type = 2; break;
  537. case 'crm_leads' : $dbName = db('crm_leads'); $dbId = 'leads_id'; $activity_type = 1; break;
  538. case 'crm_contacts' : $dbName = db('crm_contacts'); $dbId = 'contacts_id'; $activity_type = 3; break;
  539. case 'crm_business' : $dbName = db('crm_business'); $dbId = 'business_id'; $activity_type = 5; break;
  540. default : break;
  541. }
  542. if (!$dbName || !$dbId) return true;
  543. $data = [];
  544. $data['update_time'] = time();
  545. if (!empty($next_time)) {
  546. $data['next_time'] = $next_time;
  547. } else {
  548. if ($is_del) {
  549. # 查找最近一条下次联系时间补上,如果没有就置空
  550. $resActivity = Db::name('crm_activity')->where(['type'=>1, 'activity_type'=>$activity_type, 'activity_type_id' => $types_id,'status'=>['neq',0]])->order('activity_id desc')->find();
  551. $data['next_time'] = $resActivity['next_time'] ? : 0;
  552. unset($data['update_time']);
  553. } else {
  554. # 如果未填写下次联系时间,并且 原下次联系时间为当天,则把下次联系时间置空
  555. $next_time = $dbName->where([$dbId => $types_id])->value('next_time');
  556. list($start, $end) = getTimeByType();
  557. if ($next_time >= $start && $next_time <= $end) {
  558. $data['next_time'] = 0;
  559. }
  560. }
  561. }
  562. if (!$is_del && in_array($types, ['crm_customer', 'crm_leads'])) {
  563. $data['follow'] = '已跟进';
  564. }
  565. $dbName->where([$dbId => $types_id])->update($data);
  566. return true;
  567. }
  568. /**
  569. * 获取常用语
  570. *
  571. * @return mixed
  572. */
  573. public function getPhrase()
  574. {
  575. $dataJson = Db::name('crm_config')->where('name', 'activity_phrase')->value('value');
  576. return !empty($dataJson) ? unserialize($dataJson) : [];
  577. }
  578. /**
  579. * 设置常用语
  580. *
  581. * @param $param
  582. * @return int|string
  583. * @throws \think\Exception
  584. * @throws \think\exception\PDOException
  585. */
  586. public function setPhrase($param)
  587. {
  588. if (!Db::name('crm_config')->where('name', 'activity_phrase')->value('value')) {
  589. return Db::name('crm_config')->insert(['name' => 'activity_phrase', 'value' => serialize($param), 'description' => '跟进记录常用语']);
  590. }
  591. Db::name('crm_config')->where('name', 'activity_phrase')->update(['value' => serialize($param)]);
  592. return true;
  593. }
  594. /**
  595. * 获取修改过的跟进记录信息
  596. *
  597. * @param $activityId
  598. * @param $userId
  599. * @return array|bool|\PDOStatement|string|\think\Model|null
  600. * @throws \think\db\exception\DataNotFoundException
  601. * @throws \think\db\exception\ModelNotFoundException
  602. * @throws \think\exception\DbException
  603. */
  604. public function getFollowData($activityId, $userId)
  605. {
  606. $field = [
  607. 'activity_id',
  608. 'type',
  609. 'category',
  610. 'activity_type',
  611. 'activity_type_id',
  612. 'content',
  613. 'contacts_ids',
  614. 'next_time',
  615. 'create_user_id',
  616. 'update_time',
  617. 'business_ids'
  618. ];
  619. $data = db('crm_activity')->where('activity_id', $activityId)->field($field)->find();
  620. $fileModel = new \app\admin\model\File();
  621. $realname = Db::name('admin_user')->where('id', $data['create_user_id'])->value('realname');
  622. $data['create_user_name'] = $realname;
  623. # 附件信息
  624. if ($data['type'] = 1) {
  625. $files = [];
  626. $images = [];
  627. $fileList = $fileModel->getDataList(['module' => 'crm_activity', 'module_id' => $activityId], 'all');
  628. if (!empty($fileList['list'])) {
  629. foreach ($fileList['list'] AS $k => $v) {
  630. if ($v['types'] == 'file') {
  631. $files[] = $v;
  632. } else {
  633. $images[] = $v;
  634. }
  635. }
  636. }
  637. $data['fileList'] = $files ? : [];
  638. $data['imgList'] = $images ? : [];
  639. }
  640. # 判断是不是本人添加的,如果不是将禁止删除修改
  641. $data['auth'] = false;
  642. if ($data['type'] == 1 && $data['create_user_id'] == $userId) {
  643. $data['auth'] = true;
  644. }
  645. # 查询联系人信息
  646. $data['contacts_name'] = '';
  647. if ($data['type'] == 1 && !empty($data['contacts_ids'])) {
  648. $data['contacts_name'] = Db::name('crm_contacts')->where('contacts_id', $data['contacts_ids'])->value('name');
  649. }
  650. $data['update_time'] = date('Y-m-d H:i:s', $data['update_time']);
  651. $data['next_time'] = !empty($data['next_time']) ? date('Y-m-d H:i:s', $data['next_time']) : null;
  652. # 关联商机
  653. $data['business_list'] = $data['activity_type'] == 2 ? $this->getBusinessInfo($data['business_ids']) : [];
  654. return $data;
  655. }
  656. /**
  657. * 获取活动类型名称
  658. *
  659. * @param $activityType
  660. * @param $activityTypeId
  661. * @return float|mixed|string|\think\db\Query
  662. */
  663. private function getActivityName($activityType, $activityTypeId)
  664. {
  665. $activityTypeName = '';
  666. # 线索
  667. if ($activityType == 1) {
  668. $activityTypeName = Db::name('crm_leads')->where('leads_id', $activityTypeId)->value('name');
  669. }
  670. # 客户
  671. if ($activityType == 2) {
  672. $activityTypeName = Db::name('crm_customer')->where('customer_id', $activityTypeId)->value('name');
  673. }
  674. # 联系人
  675. if ($activityType == 3) {
  676. $activityTypeName = Db::name('crm_contacts')->where('contacts_id', $activityTypeId)->value('name');
  677. }
  678. # 产品
  679. if ($activityType == 4) {
  680. $activityTypeName = Db::name('crm_product')->where('product_id', $activityTypeId)->value('name');
  681. }
  682. # 商机
  683. if ($activityType == 5) {
  684. $activityTypeName = Db::name('crm_business')->where('business_id', $activityTypeId)->value('name');
  685. }
  686. # 合同
  687. if ($activityType == 6) {
  688. $activityTypeName = Db::name('crm_contract')->where('contract_id', $activityTypeId)->value('name');
  689. }
  690. # 回款
  691. if ($activityType == 7) {
  692. $activityTypeName = Db::name('crm_receivables')->where('receivables_id', $activityTypeId)->value('number');
  693. }
  694. # 日志
  695. if ($activityType == 8) {
  696. $activityTypeName = Db::name('oa_log')->where('log_id', $activityTypeId)->value('title');
  697. }
  698. # 审批
  699. if ($activityType == 9) {
  700. $categoryId = Db::name('oa_examine')->where('examine_id', $activityTypeId)->value('category_id');
  701. $activityTypeName = Db::name('oa_examine_category')->where('category_id', $categoryId)->value('title');
  702. }
  703. # 日程
  704. if ($activityType == 10) {
  705. $activityTypeName = Db::name('oa_event')->where('event_id', $activityTypeId)->value('title');
  706. }
  707. # 任务
  708. if ($activityType == 11) {
  709. $activityTypeName = Db::name('task')->where('task_id', $activityTypeId)->value('name');
  710. }
  711. return $activityTypeName;
  712. }
  713. /**
  714. * 获取客户跟进记录关联的商机
  715. *
  716. * @param $businessIds
  717. * @return bool|\PDOStatement|string|\think\Collection
  718. * @throws \think\db\exception\DataNotFoundException
  719. * @throws \think\db\exception\ModelNotFoundException
  720. * @throws \think\exception\DbException
  721. */
  722. private function getBusinessInfo($businessIds)
  723. {
  724. return Db::name('crm_business')->field(['business_id', 'name'])->whereIn('business_id', $businessIds)->select();
  725. }
  726. /**
  727. * 设置跟进记录
  728. *
  729. * @param $type
  730. * @param $typeId
  731. * @param $content
  732. * @throws \think\Exception
  733. * @throws \think\exception\PDOException
  734. */
  735. private function setFollowRecord($type, $typeId, $content)
  736. {
  737. $model = null;
  738. $primaryKey = null;
  739. switch ($type) {
  740. case 1 : $model = db('crm_leads'); $primaryKey = 'leads_id'; break;
  741. case 2 : $model = db('crm_customer'); $primaryKey = 'customer_id'; break;
  742. case 3 : $model = db('crm_contacts'); $primaryKey = 'contacts_id'; break;
  743. case 5 : $model = db('crm_business'); $primaryKey = 'business_id'; break;
  744. case 6 : $model = db('crm_contract'); $primaryKey = 'contract_id'; break;
  745. }
  746. $model->where($primaryKey, $typeId)->update(['last_time' => time(), 'last_record' => $content]);
  747. }
  748. }