InvoiceLogic.php 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. <?php
  2. /**
  3. * 发票逻辑类
  4. *
  5. * @author qifan
  6. * @date 2020-12-07
  7. */
  8. namespace app\crm\logic;
  9. use app\admin\controller\ApiCommon;
  10. use app\admin\model\Common;
  11. use app\crm\model\Invoice;
  12. use think\Db;
  13. class InvoiceLogic
  14. {
  15. private $invoiceType = ['增值税专用发票', '增值税普通发票', '国税通用机打发票', '地税通用机打发票', '收据'];
  16. private $check_status = ['待审核', '审核中', '审核通过', '审核未通过', '撤回'];
  17. /**
  18. * 列表
  19. *
  20. * @param $param
  21. * @param false $search
  22. * @return array
  23. * @throws \think\exception\DbException
  24. */
  25. public function index($param)
  26. {
  27. $fieldModel = new \app\admin\model\Field();
  28. //列表展示字段
  29. $field = $fieldModel->getIndexField('crm_invoice', $param['user_id'], 1) ?: array('name');
  30. if (!empty($param['is_excel']) && !empty($param['invoice_id'])) {
  31. $param['invoice_id'] = ['in', arrayToString($param['invoice_id'])];
  32. }
  33. $getCount = $param['getCount'];
  34. $userId = $param['user_id'];
  35. $invoiceIdArray = $param['invoiceIdArray']; // 待办事项提醒参数
  36. $dealt = $param['dealt'];
  37. $order_field = $param['order_field'];
  38. $order_type = $param['order_type'];
  39. $is_excel = $param['is_excel'];
  40. $search = $param['search'];
  41. $scene_id = $param['scene_id'];
  42. $isMessage = !empty($param['isMessage']);
  43. $common = new Common();
  44. unset($param['getCount']);
  45. // unset($param['limit']); 导出使用 暂未发现为何去掉分页参数
  46. // unset($param['page']);
  47. unset($param['user_id']);
  48. unset($param['invoiceIdArray']);
  49. unset($param['dealt']);
  50. unset($param['search']);
  51. unset($param['order_field']);
  52. unset($param['order_type']);
  53. unset($param['is_excel']);
  54. unset($param['scene_id']);
  55. unset($param['isMessage']);
  56. $request = $common->fmtRequest($param);
  57. $where = [];
  58. # 高级搜索
  59. $requestMap = !empty($request['map']) ? $request['map'] : [];
  60. unset($requestMap['search']);
  61. # 场景
  62. $sceneMap = [];
  63. $sceneModel = new \app\admin\model\Scene();
  64. if ($scene_id) {
  65. //自定义场景
  66. $sceneMap = $sceneModel->getDataById($scene_id, $userId, 'invoice') ?: [];
  67. } else {
  68. //默认场景
  69. $sceneMap = $sceneModel->getDefaultData('crm_invoice', $userId) ?: [];
  70. }
  71. //普通筛选
  72. if ($search) {
  73. # 处理基本参数
  74. $searchWhere = function ($query) use ($search) {
  75. $query->where(function ($query) use ($search) {
  76. $query->whereLike('customer.name', '%' . $search . '%');
  77. })->whereOr(function ($query) use ($search) {
  78. $query->whereLike('contract.num', '%' . $search . '%');
  79. })->whereOr(function ($query) use ($search) {
  80. $query->whereLike('invoice.invoice_apple_number', '%' . $search . '%');
  81. });
  82. };
  83. }
  84. # 合并高级搜索和场景的查询条件
  85. $map = $requestMap ? array_merge($sceneMap, $requestMap) : $sceneMap;
  86. $map = where_arr($map, 'crm', 'invoice', 'index');
  87. # 替换掉字段前缀,不修改公共函数
  88. foreach ($map as $key => $value) {
  89. $k = str_replace('invoice.', '', $key);
  90. $where[$k] = $value;
  91. }
  92. # 待办事项查询参数
  93. $dealtWhere = [];
  94. if (!empty($invoiceIdArray)) $dealtWhere['invoice.invoice_id'] = ['in', $invoiceIdArray];
  95. # 权限,不是待办事项,则加上列表权限
  96. $auth = [];
  97. $userModel = new \app\admin\model\User();
  98. $a = 'index';
  99. if ($is_excel) $a = 'excelExport';
  100. $auth_user_ids = $userModel->getUserByPer('crm', 'invoice', $a);
  101. if (empty($dealt)) {
  102. //过滤权限
  103. if (isset($map['invoice.owner_user_id']) && $map['invoice.owner_user_id'][0] != 'like') {
  104. if (!is_array($map['invoice.owner_user_id'][1])) {
  105. $map['invoice.owner_user_id'][1] = [$map['invoice.owner_user_id'][1]];
  106. }
  107. if (in_array($map['invoice.owner_user_id'][0], ['neq', 'notin'])) {
  108. $auth_user_ids = array_diff($auth_user_ids, $map['invoice.owner_user_id'][1]) ?: []; //取差集
  109. } else {
  110. $auth_user_ids = array_intersect($map['invoice.owner_user_id'][1], $auth_user_ids) ?: []; //取交集
  111. }
  112. unset($map['invoice.owner_user_id']);
  113. }
  114. }
  115. $auth_user_ids = array_merge(array_unique(array_filter($auth_user_ids))) ?: ['-1'];
  116. // 待办事项的待审核发票不一定是自己创建的
  117. if (!$isMessage) {
  118. $auth['invoice.owner_user_id'] = ['in', $auth_user_ids];
  119. }
  120. if ($order_type && $order_field) {
  121. $order = $fieldModel->getOrderByFormtype('crm_invoice', 'invoice', $order_field, $order_type);
  122. } else {
  123. $order = 'invoice.update_time desc';
  124. }
  125. $join = [
  126. ['__CRM_CUSTOMER__ customer', 'customer.customer_id=invoice.customer_id', 'LEFT'],
  127. ['__CRM_CONTRACT__ contract', 'contract.contract_id=invoice.contract_id', 'LEFT'],
  128. ['__ADMIN_USER__ user', 'user.id=invoice.owner_user_id', 'LEFT'],
  129. ['__ADMIN_USER__ u', 'u.id=invoice.create_user_id', 'LEFT'],
  130. ];
  131. # 查询数据
  132. $list = db('crm_invoice')
  133. ->alias('invoice')
  134. ->join($join)
  135. ->field(array_merge($field, [
  136. 'customer.name' => 'customer_name',
  137. 'user.realname' => 'owner_user_name',
  138. 'contract.num' => 'contract_num',
  139. 'contract.money' => 'contract_money',
  140. 'u.realname' => 'create_user_name',
  141. ]))->where($auth)
  142. ->where($map)
  143. ->where($dealtWhere)
  144. ->where($searchWhere)
  145. ->limit($request['offset'], $request['length'])
  146. ->orderRaw($order)
  147. ->select();
  148. $dataCount = db('crm_invoice')
  149. ->alias('invoice')
  150. ->join($join)
  151. ->field(array_merge($field, [
  152. 'customer.name' => 'customer_name',
  153. 'user.realname' => 'owner_user_name',
  154. 'contract.num' => 'contract_num',
  155. 'contract.money' => 'contract_money',
  156. 'u.realname' => 'create_user_name',
  157. ]))->where($auth)
  158. ->where($map)
  159. ->where($dealtWhere)->where($searchWhere)->count();
  160. $userField = $fieldModel->getFieldByFormType('crm_invoice', 'user'); //人员类型
  161. $structureField = $fieldModel->getFieldByFormType('crm_invoice', 'structure'); //部门类型
  162. $datetimeField = $fieldModel->getFieldByFormType('crm_invoice', 'datetime'); //日期时间类型
  163. $booleanField = $fieldModel->getFieldByFormType('crm_invoice', 'boolean_value'); //布尔值
  164. $dateIntervalField = $fieldModel->getFieldByFormType('crm_invoice', 'date_interval'); // 日期区间类型字段
  165. $positionField = $fieldModel->getFieldByFormType('crm_invoice', 'position'); // 地址类型字段
  166. $handwritingField = $fieldModel->getFieldByFormType('crm_invoice', 'handwriting_sign'); // 手写签名类型字段
  167. $locationField = $fieldModel->getFieldByFormType('crm_invoice', 'location'); // 定位类型字段
  168. $boxField = $fieldModel->getFieldByFormType('crm_customer', 'checkbox'); // 多选类型字段
  169. $floatField = $fieldModel->getFieldByFormType('crm_invoice', 'floatnumber'); // 货币类型字段
  170. // $fieldGrant = db('admin_field_mask')->where('types', 'invoice')->select();
  171. # 扩展数据
  172. $extraData = [];
  173. $invoice_id_list = !empty($list) ? array_column($list, 'invoice_id') : [];
  174. $extraList = db('crm_invoice_data')->whereIn('invoice_id', $invoice_id_list)->select();
  175. foreach ($extraList as $key => $value) {
  176. $extraData[$value['invoice_id']][$value['field']] = $value['content'];
  177. }
  178. $grantData = getFieldGrantData($userId);
  179. foreach ($grantData['crm_invoice'] as $key => $value) {
  180. foreach ($value as $ke => $va) {
  181. if($va['maskType']!=0){
  182. $fieldGrant[$ke]['maskType'] = $va['maskType'];
  183. $fieldGrant[$ke]['form_type'] = $va['form_type'];
  184. $fieldGrant[$ke]['field'] = $va['field'];
  185. }
  186. }
  187. }
  188. # 处理发票类型
  189. foreach ($list as $key => $value) {
  190. $list[$key]['check_status_info'] = $this->check_status[$value['check_status']];
  191. $list[$key]['invoice_status'] = !empty($value['invoice_status']) ? '已开票' : '未开票';
  192. $list[$key]['create_time'] = !empty($value['create_time']) ? date('Y-m-d H:i:s', $value['create_time']) : null;
  193. $list[$key]['update_time'] = !empty($value['update_time']) ? date('Y-m-d H:i:s', $value['update_time']) : null;
  194. # 系统字段 负责人部门 zjf 20210726
  195. $ownerUserIdInfo = $userModel->getUserById($value['owner_user_id']);
  196. $list[$key]['owner_user_structure_name'] = $ownerUserIdInfo['structure_name'];
  197. foreach ($userField as $k => $val) {
  198. $usernameField = !empty($value[$val]) ? db('admin_user')->whereIn('id', stringToArray($value[$val]))->column('realname') : [];
  199. $list[$key][$val] = implode($usernameField, ',');
  200. }
  201. foreach ($structureField as $k => $val) {
  202. $structureNameField = !empty($value[$val]) ? db('admin_structure')->whereIn('id', stringToArray($value[$val]))->column('name') : [];
  203. $list[$key][$val] = implode($structureNameField, ',');
  204. }
  205. foreach ($datetimeField as $k => $val) {
  206. $list[$key][$val] = !empty($value[$val]) ? date('Y-m-d H:i:s', $value[$val]) : null;
  207. }
  208. foreach ($booleanField as $k => $val) {
  209. $list[$key][$val] = !empty($value[$val]) ? (string)$value[$val] : '0';
  210. }
  211. // 处理日期区间类型字段的格式
  212. foreach ($dateIntervalField as $k => $val) {
  213. $list[$key][$val] = !empty($extraData[$value['invoice_id']][$val]) ? json_decode($extraData[$value['invoice_id']][$val], true) : null;
  214. }
  215. // 处理地址类型字段的格式
  216. foreach ($positionField as $k => $val) {
  217. $list[$key][$val] = !empty($extraData[$value['invoice_id']][$val]) ? json_decode($extraData[$value['invoice_id']][$val], true) : null;
  218. }
  219. // 手写签名类型字段
  220. foreach ($handwritingField as $k => $val) {
  221. $handwritingData = !empty($value[$val]) ? db('admin_file')->where('file_id', $value[$val])->value('file_path') : null;
  222. $list[$key][$val] = ['url' => !empty($handwritingData) ? getFullPath($handwritingData) : null];
  223. }
  224. // 定位类型字段
  225. foreach ($locationField as $k => $val) {
  226. $list[$key][$val] = !empty($extraData[$value['invoice_id']][$val]) ? json_decode($extraData[$value['invoice_id']][$val], true) : null;
  227. }
  228. // 多选框类型字段
  229. foreach ($boxField as $k => $val) {
  230. $list[$key][$val] = !empty($value[$val]) ? trim($value[$val], ',') : null;
  231. }
  232. //货币类型字段
  233. foreach ($floatField as $k => $val) {
  234. $list[$key][$val] = $value[$val] != '0.00' ? (string)$value[$val] : null;
  235. }
  236. //掩码相关类型字段
  237. foreach ($fieldGrant AS $key => $v){
  238. //掩码相关类型字段
  239. if ($v['maskType']!=0 && $v['form_type'] == 'mobile') {
  240. $pattern = "/(1[3458]{1}[0-9])[0-9]{4}([0-9]{4})/i";
  241. $rs = preg_replace($pattern, "$1****$2", $value[$v['field']]);
  242. $list[$k][$v['field']] = !empty($value[$v['field']]) ? (string)$rs : null;
  243. } elseif ($v['maskType']!=0 && $v['form_type'] == 'email') {
  244. $email_array = explode("@", $value[$v['field']]);
  245. $prevfix = (strlen($email_array[0]) < 4) ? "" : substr($value[$v['field']], 0, 2); //邮箱前缀
  246. $str = preg_replace('/([\d\w+_-]{0,100})@/', "***@", $value[$v['field']], -1, $count);
  247. $rs = $prevfix . $str;
  248. $list[$k][$v['field']] = !empty($value[$v['field']]) ?$rs: null;
  249. } elseif ($v['maskType']!=0 && in_array($v['form_type'],['position','floatnumber'])) {
  250. $list[$k][$v['field']] = !empty($value[$v['field']]) ? (string)substr_replace($value[$v['field']], '*****',0,strlen($value[$v['field']])) : null;
  251. }
  252. }
  253. $data = [];
  254. $data['list'] = $list ?: [];
  255. $data['dataCount'] = $dataCount ?: 0;
  256. return $data;
  257. }
  258. }
  259. /**
  260. * 创建
  261. *
  262. * @param $param
  263. * @return Invoice|int|string
  264. */
  265. public
  266. function save($param)
  267. {
  268. return db('crm_invoice')->insert($param, false, true);
  269. }
  270. /**
  271. * 详情
  272. *
  273. * @param $invoiceId
  274. * @return array
  275. * @throws \think\Exception
  276. * @throws \think\db\exception\DataNotFoundException
  277. * @throws \think\db\exception\ModelNotFoundException
  278. * @throws \think\exception\DbException
  279. */
  280. public
  281. function read($invoiceId, $isUpdate)
  282. {
  283. $apiCommon = new ApiCommon();
  284. $userId = $apiCommon->userInfo['id'];
  285. $result = [];
  286. $dataObject = Invoice::with(['toCustomer', 'toContract'])->where('invoice_id', $invoiceId)->find();
  287. if (empty($dataObject)) return $result;
  288. $dataArray = $dataObject->toArray();
  289. if (!empty($isUpdate)) return $dataArray;
  290. $grantData = getFieldGrantData($userId);
  291. foreach ($grantData['crm_leads'] as $key => $value) {
  292. foreach ($value as $ke => $va) {
  293. if($va['maskType']!=0){
  294. $fieldGrant[$ke]['maskType'] = $va['maskType'];
  295. $fieldGrant[$ke]['form_type'] = $va['form_type'];
  296. $fieldGrant[$ke]['field'] = $va['field'];
  297. }
  298. }
  299. }
  300. foreach ($fieldGrant AS $key => $val){
  301. //掩码相关类型字段
  302. if ($val['maskType']!=0 && $val['form_type'] == 'mobile') {
  303. $pattern = "/(1[3458]{1}[0-9])[0-9]{4}([0-9]{4})/i";
  304. $rs = preg_replace($pattern, "$1****$2", $dataArray[$val['field']]);
  305. $dataArray[$val['field']] = !empty($dataInfo[$val['field']]) ? (string)$rs : null;
  306. } elseif ($val['maskType']!=0 && $val['form_type'] == 'email') {
  307. $email_array = explode("@", $dataArray[$val['field']]);
  308. $prevfix = (strlen($email_array[0]) < 4) ? "" : substr($dataArray[$val['field']], 0, 2); //邮箱前缀
  309. $str = preg_replace('/([\d\w+_-]{0,100})@/', "***@", $dataArray[$val['field']], -1, $count);
  310. $rs = $prevfix . $str;
  311. $dataArray[$val['field']] = !empty($dataInfo[$val['field']]) ?$rs: null;
  312. } elseif ($val['maskType']!=0 && in_array($val['form_type'],['position','floatnumber'])) {
  313. $dataArray[$val['field']] = !empty($dataInfo[$val['field']]) ? (string)substr_replace($dataArray[$val['field']], '*****',0,strlen($dataArray[$val['field']])) : null;
  314. }
  315. }
  316. # 主键ID
  317. $result['invoice_id'] = $dataArray['invoice_id'];
  318. # 是否显示撤回按钮
  319. $result['isShowRecall'] = 0;
  320. if ($userId == $dataArray['owner_user_id'] && $dataArray['check_status'] == 0) $result['isShowRecall'] = 1;
  321. $result['customer_name'] = $dataArray['customer_name']; # 客户名称
  322. $result['invoice_money'] = $dataArray['invoice_money']; # 开票金额
  323. $result['invoice_number'] = $dataArray['invoice_number']; # 发票号码
  324. $result['real_invoice_date'] = $dataArray['real_invoice_date']; # 开票日期
  325. $result['flow_id'] = $dataArray['flow_id']; # 审核ID
  326. $check = ['0' => '待审核', '1' => '审核中', '2' => '审核通过', '3' => '审核未通过', '4' => '撤销', '5' => '草稿(未提交)', '6' => '作废'];
  327. # 基本信息
  328. $result['essential'] = [
  329. 'invoice_apple_number' => $dataArray['invoice_apple_number'],
  330. 'customer_name' => $dataArray['customer_name'],
  331. 'contract_num' => $dataArray['contract_number'],
  332. 'contract_money' => $dataArray['contract_money'],
  333. 'invoice_money' => $dataArray['invoice_money'],
  334. 'invoice_date' => $dataArray['invoice_date'],
  335. 'invoice_type' => $dataArray['invoice_type'],
  336. 'remark' => $dataArray['remark'],
  337. 'create_user_name' => db('admin_user')->where('id', $dataArray['create_user_id'])->value('realname'),
  338. 'owner_user_name' => db('admin_user')->where('id', $dataArray['owner_user_id'])->value('realname'),
  339. 'create_time' => $dataArray['create_time'],
  340. 'update_time' => $dataArray['update_time'],
  341. 'invoice_number' => $dataArray['invoice_number'],
  342. 'real_invoice_date' => $dataArray['real_invoice_date'],
  343. 'customer_id' => $dataArray['customer_id'],
  344. 'check_status' => $check[$dataArray['check_status']]
  345. ];
  346. # 发票信息
  347. $result['invoice'] = [
  348. 'title_type' => $dataArray['title_type'],
  349. 'deposit_bank' => $dataArray['deposit_bank'],
  350. 'invoice_title' => $dataArray['invoice_title'],
  351. 'tax_number' => $dataArray['tax_number'],
  352. 'deposit_account' => $dataArray['deposit_account'],
  353. 'deposit_address' => $dataArray['deposit_address'],
  354. 'phone' => $dataArray['phone']
  355. ];
  356. # 邮寄信息
  357. $result['posting'] = [
  358. 'contacts_name' => $dataArray['contacts_name'],
  359. 'contacts_mobile' => $dataArray['contacts_mobile'],
  360. 'contacts_address' => $dataArray['contacts_address']
  361. ];
  362. return $result;
  363. }
  364. /**
  365. * 编辑
  366. *
  367. * @param $param
  368. * @return Invoice
  369. */
  370. public
  371. function update($param)
  372. {
  373. return Invoice::update($param);
  374. }
  375. /**
  376. * 删除
  377. *
  378. * @param $where
  379. * @return int
  380. */
  381. public
  382. function delete($where)
  383. {
  384. return Invoice::destroy($where);
  385. }
  386. /**
  387. * 获取审批状态
  388. *
  389. * @param $invoiceId
  390. * @param false $isDelete
  391. * @return bool|int|mixed|\PDOStatement|string|\think\Collection|null
  392. * @throws \think\db\exception\DataNotFoundException
  393. * @throws \think\db\exception\ModelNotFoundException
  394. * @throws \think\exception\DbException
  395. */
  396. public
  397. function getExamineStatus($invoiceId, $isDelete = false)
  398. {
  399. # 删除
  400. if ($isDelete) {
  401. return Invoice::field(['check_status'])->whereIn('invoice_id', $invoiceId)->select();
  402. }
  403. # 编辑
  404. return Invoice::where('invoice_id', $invoiceId)->value('check_status');
  405. }
  406. /**
  407. * 转移(变更负责人)
  408. *
  409. * @param $invoiceIds
  410. * @param $ownerUserId
  411. * @return Invoice
  412. */
  413. public
  414. function transfer($invoiceIds, $ownerUserId)
  415. {
  416. return Invoice::whereIn('invoice_id', $invoiceIds)->update(['owner_user_id' => $ownerUserId]);
  417. }
  418. /**
  419. * 设置开票
  420. *
  421. * @param $param
  422. * @return Invoice
  423. */
  424. public
  425. function setInvoice($param)
  426. {
  427. return Invoice::update($param);
  428. }
  429. /**
  430. * 获取发票审核信息
  431. *
  432. * @param $invoiceId
  433. * @return array|bool|\PDOStatement|string|\think\Model|null
  434. * @throws \think\db\exception\DataNotFoundException
  435. * @throws \think\db\exception\ModelNotFoundException
  436. * @throws \think\exception\DbException
  437. */
  438. public
  439. function getExamineInfo($invoiceId)
  440. {
  441. $field = ['check_status', 'flow_id', 'order_id', 'check_user_id', 'flow_user_id', 'invoice_apple_number', 'owner_user_id', 'create_user_id'];
  442. return Invoice::field($field)->where('invoice_id', $invoiceId)->find();
  443. }
  444. /**
  445. * 设置审批信息
  446. *
  447. * @param $data
  448. * @return Invoice
  449. */
  450. public
  451. function setExamineInfo($data)
  452. {
  453. return Invoice::update($data);
  454. }
  455. /**
  456. * 添加撤销审核记录
  457. *
  458. * @param $invoiceId
  459. * @param $examineInfo
  460. * @param $realname
  461. * @param $content
  462. * @param $userId
  463. */
  464. public
  465. function createExamineRecord($invoiceId, $examineInfo, $realname, $content, $userId)
  466. {
  467. $data = [
  468. 'types' => 'crm_invoice',
  469. 'types_id' => $invoiceId,
  470. 'flow_id' => $examineInfo['flow_id'],
  471. 'order_id' => $examineInfo['order_id'],
  472. 'check_user_id' => $userId,
  473. 'check_time' => time(),
  474. 'status' => 2,
  475. 'content' => !empty($content) ? $content : $realname . ' 撤销了审核',
  476. ];
  477. Db::name('admin_examine_record')->insert($data);
  478. }
  479. /**
  480. * 检查发票编号是否重复
  481. *
  482. * @param $where
  483. * @return int|mixed|string|null
  484. */
  485. public
  486. function getInvoiceId($where)
  487. {
  488. return Db::name('crm_invoice')->where($where)->value('invoice_id');
  489. }
  490. }