Contract.php 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723
  1. <?php
  2. namespace app\admin\controller\qingdongams\customer;
  3. use addons\qingdongams\model\Receivables;
  4. use addons\qingdongams\model\BusinessProduct;
  5. use addons\qingdongams\model\ContactsOther;
  6. use addons\qingdongams\model\ContractProduct;
  7. use addons\qingdongams\model\Quote;
  8. use addons\qingdongams\model\ExamineRecord;
  9. use addons\qingdongams\model\File;
  10. use addons\qingdongams\model\FormField;
  11. use addons\qingdongams\model\ProductPart;
  12. use addons\qingdongams\model\Product;
  13. use addons\qingdongams\model\QuoteProduct;
  14. use addons\qingdongams\model\Ratio;
  15. use addons\qingdongams\model\Staff;
  16. use addons\qingdongams\model\WordTemplate;
  17. use app\admin\controller\qingdongams\Base;
  18. use addons\qingdongams\model\ContractOther;
  19. use addons\qingdongams\model\Form;
  20. use addons\qingdongams\model\Contacts;
  21. use addons\qingdongams\model\Customer;
  22. use addons\qingdongams\model\OperationLog;
  23. use addons\qingdongams\model\Record;
  24. use addons\qingdongams\model\ContractFile;
  25. use addons\qingdongams\model\Flow;
  26. use addons\qingdongams\model\Business;
  27. use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
  28. use PhpOffice\PhpSpreadsheet\Reader\Csv;
  29. use PhpOffice\PhpSpreadsheet\Reader\Xls;
  30. use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
  31. use PhpOffice\PhpSpreadsheet\RichText\RichText;
  32. use PhpOffice\PhpWord\Settings;
  33. use PhpOffice\PhpWord\TemplateProcessor;
  34. use addons\qingdongams\model\Contract as ContractModel;
  35. use addons\qingdongams\model\Message;
  36. use think\Db;
  37. use think\Exception;
  38. /**
  39. * 合同管理
  40. * @desc 操作文档:https://doc.fastadmin.net/qingdongams
  41. * @desc 软件介绍:https://www.fastadmin.net/store/qingdongams.html
  42. * @desc 售后微信:qingdong_crm
  43. */
  44. class Contract extends Base {
  45. protected $relationSearch = true;
  46. /**
  47. * @var \addons\qingdongams\model\Contract
  48. */
  49. protected $model = null;
  50. protected $Equipmentdevice = null;
  51. protected $noNeedRight = ['index1'];
  52. protected $noNeedLogin = ['index1'];
  53. public function _initialize() {
  54. parent::_initialize();
  55. $this->model = new \addons\qingdongams\model\Contract;
  56. $this->Equipmentdevice = new \app\admin\model\qingdongams\customer\Equipmentdevice;
  57. }
  58. /**
  59. * 查看
  60. */
  61. public function index() {
  62. //设置过滤方法
  63. $this->request->filter(['strip_tags', 'trim']);
  64. if ($this->request->isAjax()) {
  65. if ($this->request->request('keyField')) {
  66. return $this->selectpage();
  67. }
  68. //0:全部 1:我负责的 2:下属负责的 3:今日待跟进 4:今日已跟进 5:从未跟进的
  69. $type = input('type',0);
  70. list($where, $sort, $order, $offset, $limit) = $this->buildparams();
  71. switch($type){
  72. case 1:
  73. $staff = Staff::info();
  74. $wheres['owner_staff_id'] = $staff->id;
  75. break;
  76. case 2:
  77. $wheres['owner_staff_id'] = array('in',Staff::getLowerStaffId());
  78. break;
  79. case 3:
  80. $start = date('Y-m-d 00:00:00');
  81. $end = date('Y-m-d 23:59:59');
  82. $record = collection(Record::where(array('relation_type'=>3,'next_time'=>array(array('egt',$start),array('elt',$end))))->field("id,relation_id")->select())->toArray();
  83. $relationId = [];
  84. foreach($record as $k=>$v){
  85. $whereRe['id'] = array('gt',$v['id']);
  86. $whereRe['relation_id'] = $v['relation_id'];
  87. $recordData = Record::where($whereRe)->count();
  88. if($recordData == 0){
  89. $relationId[] = $v['relation_id'];
  90. }
  91. }
  92. $wheres['id'] = array('in',$relationId);
  93. $staff = Staff::info();
  94. $wheres['owner_staff_id'] = $staff->id;
  95. break;
  96. case 4:
  97. $start = date('Y-m-d 00:00:00');
  98. $end = date('Y-m-d 23:59:59');
  99. $record = collection(Record::where(array('relation_type'=>3,'next_time'=>array(array('egt',$start),array('elt',$end))))->field("id,relation_id")->select())->toArray();
  100. $relationId = [];
  101. foreach($record as $k=>$v){
  102. $whereRe['id'] = array('gt',$v['id']);
  103. $whereRe['relation_id'] = $v['relation_id'];
  104. $recordData = Record::where($whereRe)->count();
  105. if($recordData >=1){
  106. $relationId[] = $v['relation_id'];
  107. }
  108. }
  109. $wheres['id'] = array('in',$relationId);
  110. $staff = Staff::info();
  111. $wheres['owner_staff_id'] = $staff->id;
  112. break;
  113. case 5:
  114. $record = collection(Record::where(array('relation_type'=>3,'next_time'=>array('neq','')))->column('relation_id'))->toArray();
  115. $wheres['id'] = array('not in',$record);
  116. $staff = Staff::info();
  117. $wheres['owner_staff_id'] = $staff->id;
  118. break;
  119. default:
  120. $wheres['owner_staff_id'] = array('in',Staff::getMyStaffIds());
  121. break;
  122. }
  123. $ids=[];
  124. $group_id=input('group_id');
  125. $staff_id=input('staff_id');
  126. if ($group_id) {//角色组
  127. $ids = Staff::getGroupStaffIds($group_id);
  128. }
  129. if ($staff_id) {
  130. $ids = $staff_id;
  131. }
  132. if ($group_id || $staff_id) {
  133. $wheres['owner_staff_id'] = ['in', $ids];
  134. }
  135. $list = $this->model->where($where)
  136. ->where($wheres)
  137. ->with([
  138. 'customer',
  139. 'orderStaff',
  140. 'contacts',
  141. 'receivables',
  142. 'invoice'
  143. ])->order($sort, $order)->paginate($limit);
  144. $result = array("total" => $list->total(), "rows" => $list->items());
  145. return json($result);
  146. }
  147. $field = FormField::getFields(FormField::CONTRACT_TYPE);
  148. $this->assignconfig('fields', $field);
  149. return $this->view->fetch();
  150. }
  151. public function index1() {
  152. //设置过滤方法
  153. $this->request->filter(['strip_tags', 'trim']);
  154. if ($this->request->isAjax()) {
  155. if ($this->request->request('keyField')) {
  156. return $this->selectpage();
  157. }
  158. //0:全部 1:我负责的 2:下属负责的 3:今日待跟进 4:今日已跟进 5:从未跟进的
  159. $type = input('type',0);
  160. list($where, $sort, $order, $offset, $limit) = $this->buildparams();
  161. switch($type){
  162. case 1:
  163. $staff = Staff::info();
  164. $wheres['owner_staff_id'] = $staff->id;
  165. break;
  166. case 2:
  167. $wheres['owner_staff_id'] = array('in',Staff::getLowerStaffId());
  168. break;
  169. case 3:
  170. $start = date('Y-m-d 00:00:00');
  171. $end = date('Y-m-d 23:59:59');
  172. $record = collection(Record::where(array('relation_type'=>3,'next_time'=>array(array('egt',$start),array('elt',$end))))->field("id,relation_id")->select())->toArray();
  173. $relationId = [];
  174. foreach($record as $k=>$v){
  175. $whereRe['id'] = array('gt',$v['id']);
  176. $whereRe['relation_id'] = $v['relation_id'];
  177. $recordData = Record::where($whereRe)->count();
  178. if($recordData == 0){
  179. $relationId[] = $v['relation_id'];
  180. }
  181. }
  182. $wheres['id'] = array('in',$relationId);
  183. $staff = Staff::info();
  184. $wheres['owner_staff_id'] = $staff->id;
  185. break;
  186. case 4:
  187. $start = date('Y-m-d 00:00:00');
  188. $end = date('Y-m-d 23:59:59');
  189. $record = collection(Record::where(array('relation_type'=>3,'next_time'=>array(array('egt',$start),array('elt',$end))))->field("id,relation_id")->select())->toArray();
  190. $relationId = [];
  191. foreach($record as $k=>$v){
  192. $whereRe['id'] = array('gt',$v['id']);
  193. $whereRe['relation_id'] = $v['relation_id'];
  194. $recordData = Record::where($whereRe)->count();
  195. if($recordData >=1){
  196. $relationId[] = $v['relation_id'];
  197. }
  198. }
  199. $wheres['id'] = array('in',$relationId);
  200. $staff = Staff::info();
  201. $wheres['owner_staff_id'] = $staff->id;
  202. break;
  203. case 5:
  204. $record = collection(Record::where(array('relation_type'=>3,'next_time'=>array('neq','')))->column('relation_id'))->toArray();
  205. $wheres['id'] = array('not in',$record);
  206. $staff = Staff::info();
  207. $wheres['owner_staff_id'] = $staff->id;
  208. break;
  209. default:
  210. $wheres['owner_staff_id'] = array('in',Staff::getMyStaffIds());
  211. break;
  212. }
  213. $ids=[];
  214. $group_id=input('group_id');
  215. $staff_id=input('staff_id');
  216. if ($group_id) {//角色组
  217. $ids = Staff::getGroupStaffIds($group_id);
  218. }
  219. if ($staff_id) {
  220. $ids = $staff_id;
  221. }
  222. if ($group_id || $staff_id) {
  223. $wheres['owner_staff_id'] = ['in', $ids];
  224. }
  225. $list = $this->model->where($where)
  226. ->where($wheres)
  227. ->with([
  228. 'customer',
  229. 'orderStaff',
  230. 'contacts',
  231. 'receivables',
  232. 'invoice'
  233. ])->order($sort, $order)->paginate(5);
  234. $result = array("total" => $list->total(), "rows" => $list->items());
  235. return json($result);
  236. }
  237. $field = FormField::getFields(FormField::CONTRACT_TYPE);
  238. $this->assignconfig('fields', $field);
  239. return $this->view->fetch();
  240. }
  241. /**
  242. * 添加
  243. */
  244. public function add()
  245. {
  246. if ($this->request->isPost()) {
  247. $params = $this->request->post("row/a");
  248. if ($params) {
  249. $params = $this->preExcludeFields($params);
  250. // 表单验证
  251. if (($result = $this->qingdongamsValidate($params, 'Contract', 'create')) !== true) {
  252. $this->error($result);
  253. }
  254. $result = FormField::checkFields(FormField::CONTRACT_TYPE, $params);
  255. if ($result !== true) {
  256. $this->error($result);
  257. }
  258. if(isset($params['flow_staff_ids'])){
  259. if(!$params['flow_staff_ids']){
  260. $this->error('请选择审批人');
  261. }
  262. }
  263. $result = false;
  264. Db::startTrans();
  265. try {
  266. $params = Form::updateFormParams(Form::CONTRACT_TYPE, $params);
  267. $res=true;
  268. if ($params['start_time'] && $params['end_time']) {
  269. if (strtotime($params['start_time']) >= strtotime($params['end_time'])) {
  270. $this->error('生效时间不能大于等于结束时间');
  271. }
  272. }
  273. if($params['product']){
  274. $params['product']=json_decode($params['product'],true);
  275. }
  276. $result = $this->model::createContract($params);
  277. if($params['device_ids']){
  278. $exp=explode(",",$params['device_ids']);
  279. if(count($exp)>0){
  280. foreach($exp as $key=>$val){
  281. //查询设备信息
  282. $info= $this->Equipmentdevice->where(array('id'=>$val))->find();
  283. if(!$info){
  284. $this->error("设备信息不存在");
  285. }
  286. //更新当前设备绑定信息
  287. //$result 合同id
  288. //customer_id 客户id
  289. $res=$this->Equipmentdevice->where(array('id'=>$val))->update(array('status'=>1,'customer_id'=>$params['customer_id'],'contract_id'=>$result));
  290. if($res){
  291. $res=true;
  292. }else{
  293. $res=false;
  294. }
  295. }
  296. }
  297. }
  298. if($res && $result){
  299. Db::commit();
  300. }else{
  301. Db::rollback();
  302. $this->error("创建失败");
  303. }
  304. } catch (Exception $e) {
  305. Db::rollback();
  306. $this->error($e->getMessage());
  307. }
  308. if ($result !== false) {
  309. $this->success();
  310. } else {
  311. $this->error(__('No rows were inserted'));
  312. }
  313. }
  314. $this->error(__('Parameter %s can not be empty', ''));
  315. }
  316. $flow= Flow::getsteplist(Flow::CONTRACT_STATUS);
  317. if (empty($flow)) {
  318. $this->error('无可用审批流,请联系管理员');
  319. }
  320. $customer_id = input('customer_id');
  321. if($customer_id){
  322. $business = Business::where(array('customer_id'=>$customer_id))->select();
  323. }else{
  324. $business = Business::getList();
  325. }
  326. $this->assign('flow',$flow);
  327. $this->assign('staff', Staff::getStaff());
  328. $this->assign('customers', Customer::getList());
  329. $this->assign('business', $business);
  330. $this->assign('customer_id', $customer_id);
  331. $this->assign('customer', Customer::get($customer_id));
  332. $this->assign('business_id', input('business_id'));
  333. $this->assign('staffs', Staff::allList());
  334. $this->assign('form_data', Form::getDataValue('contract'));
  335. $this->assign('ratio',Ratio::where(['status'=>1])->select());
  336. $this->assign('contractNum', 'C'.date('Ymd').rand(10000,99999));
  337. return $this->view->fetch();
  338. }
  339. /**
  340. * 修改合同
  341. */
  342. public function edit($ids = null) {
  343. $map['id'] = $ids;
  344. if ($this->request->isAjax()) {
  345. $params = $this->request->post('row/a');
  346. $params = $this->preExcludeFields($params);
  347. $row = $this->model::where(['id' => $ids, 'check_status' => ['in', [3, 4]]])->find();
  348. if (empty($row)) {
  349. $this->error('合同审核中或已审核通过无法修改');
  350. }
  351. // 表单验证
  352. if (($result = $this->qingdongamsValidate($params, 'Contract', 'create')) !== true) {
  353. $this->error($result);
  354. }
  355. $result = FormField::checkFields(FormField::CONTRACT_TYPE, $params,$ids);
  356. if ($result !== true) {
  357. $this->error($result);
  358. }
  359. Db::startTrans();
  360. try {
  361. $params = Form::updateFormParams(Form::CONTRACT_TYPE, $params);
  362. $params['id']=$ids;
  363. $params['owner_staff_id'] = $row['owner_staff_id'];
  364. if($params['product']){
  365. $params['product']=json_decode($params['product'],true);
  366. }
  367. $result = $this->model::updateContract($params);
  368. Db::commit();
  369. } catch (Exception $e) {
  370. Db::rollback();
  371. $this->error($e->getMessage());
  372. }
  373. $this->success('修改成功');
  374. }
  375. $row = $this->model->where($map)->with(['customer','contacts','business'])->find();
  376. if(empty($row)){
  377. $this->error('信息不存在');
  378. }
  379. $row = $row->toArray();
  380. $row = ContractOther::getOther($row);
  381. $product=ContractProduct::where(['contract_id'=>$ids])->with(['productinfo'])->select();
  382. foreach ($product as $k=>$v){
  383. if($v['productinfo']){
  384. $v['product_name']=$v['productinfo']['name'];
  385. $v['cost_price']=$v['productinfo']['cost_price'];
  386. $v['type']=$v['productinfo']['type'];
  387. if($v['productinfo']['goods']){
  388. $v['goods_name']=$v['productinfo']['goods']['name'];
  389. }
  390. }
  391. $product[$k]=$v;
  392. }
  393. $row['product']=json_encode($product);
  394. $row['ratios']=json_decode($row['ratios'],true);
  395. $flow= Flow::getsteplist(Flow::CONTRACT_STATUS);
  396. if (empty($flow)) {
  397. $this->error('无可用审批流,请联系管理员');
  398. }
  399. $this->assign('flow',$flow);
  400. $this->view->assign("row", $row);
  401. $this->assign('customers', Customer::getList());
  402. $this->assign('business', Business::getList());
  403. $this->assign('staffs', Staff::getList());
  404. $this->assign('staff', Staff::getStaff());
  405. $this->assign('ratio',Ratio::where(['status'=>1])->select());
  406. $this->assign('form_data', Form::getDataValue('contract',$row));
  407. $this->assign('contacts', Contacts::where(['customer_id'=>$row['customer_id']])->field('id,name')->select());
  408. return $this->view->fetch();
  409. }
  410. /**
  411. * 获取附件记录
  412. */
  413. public function get_file($ids = null) {
  414. list($where, $sort, $order, $offset, $limit) = $this->buildparams();
  415. $list = ContractFile::where(['contract_id' => $ids])->with(['file'])->field('file_id')->paginate($limit);
  416. $result = array("total" => $list->total(), "rows" => $list->items());
  417. return json($result);
  418. }
  419. /**
  420. * 合同详情
  421. */
  422. public function detail($ids = null) {
  423. $row = $this->model->where(['id' => $ids])->with([
  424. 'customer',
  425. 'contacts',
  426. 'orderStaff',
  427. 'ownerStaff',
  428. 'business'
  429. ])->find();
  430. if (empty($row)) {
  431. $this->error(__('No Results were found'));
  432. }
  433. $row=$row->toArray();
  434. $row=ContractOther::getOther($row);
  435. $row['ratios'] = json_decode($row['ratios'], true);
  436. if ($row['ratios']) {
  437. foreach ($row['ratios'] as $k => $v) {
  438. $v['staff'] = Staff::where(['id' => $v['staff_id']])->field('id,name,img,post')->find()->toArray();
  439. $v['money'] = $row['money'] * ($v['ratio'] / 100);
  440. $row['ratios'][$k] = $v;
  441. }
  442. }
  443. $row['repayment_money'] = Receivables::where(['contract_id'=>$ids])->sum('money'); //已回款
  444. $row['no_money'] = $row['money'] -$row['repayment_money'];
  445. if($row['no_money'] <= 0){
  446. $row['no_money'] = 0;
  447. }
  448. $this->assign('examine_record',ExamineRecord::getList(ExamineRecord::CONTRACT_TYPE,$ids));
  449. $this->assign('flow',Flow::getstepdetail(Flow::CONTRACT_STATUS, $ids));
  450. //跟进记录
  451. $this->assign('records', Record::getList(Record::CONTRACT_TYPE, $ids));
  452. //操作记录
  453. $log=OperationLog::getList(OperationLog::CONTRACT_TYPE, $ids);
  454. //标记通知已读
  455. Message::setRead(Message::CONTRACT_TYPE, $ids, $this->_staff->id);
  456. $this->assign('operation_log',$log);
  457. $this->assign('row', $row);
  458. $this->assign('ids', $ids);
  459. $this->assign('form_data', Form::getDataValue('contract',$row));
  460. $this->assignconfig("idinfo", ['id' => $ids]);
  461. return $this->view->fetch();
  462. }
  463. /**
  464. * 获取联系人select
  465. */
  466. public function get_contacts_list(){
  467. $pageSize = input('pageSize');
  468. $pageNumber = input('pageNumber');
  469. $where = [];
  470. if ($keyValue = $this->request->request("keyValue")) {
  471. $where['id'] = ['in',$keyValue];
  472. }
  473. $ids=input('ids');
  474. $name = input('name');
  475. if(!empty($name)){
  476. $where['name'] = ['like','%'.$name.'%'];
  477. }
  478. $staff = Contacts::where($where)->where(['customer_id'=>$ids])
  479. ->field('id,name')->order('id desc')->paginate($pageSize, false, ['page' => $pageNumber]);
  480. return json(['list' => $staff->items(), 'total' => $staff->total()]);
  481. }
  482. //获取设备列表
  483. public function get_contract_product(){
  484. $contract_id=input('contract_id',0,'intval');
  485. if(empty($contract_id)){
  486. $this->error('参数不能为空');
  487. }
  488. $list=$this->Equipmentdevice->where(array('contract_id'=>$contract_id))->select();
  489. return json(['rows' =>$list, 'total' => count($list)]);
  490. }
  491. /**
  492. * 获取产品明细
  493. */
  494. // public function get_contract_product(){
  495. // $contract_id=input('contract_id',0,'intval');
  496. // if(empty($contract_id)){
  497. // $this->error('参数不能为空');
  498. // }
  499. // $products=ContractProduct::where(['contract_id'=>$contract_id])
  500. // ->with(['productinfo'])->select();
  501. // foreach($products as $k=>$v){
  502. // if(!$v['productinfo']['id']){
  503. // unset($products[$k]);
  504. // }
  505. // }
  506. // return json(['rows' =>$products, 'total' => count($products)]);
  507. // }
  508. /**
  509. * 获取回款计划
  510. */
  511. public function get_receivables_plan($ids = null) {
  512. list($where, $sort, $order, $offset, $limit) = $this->buildparams();
  513. $list = \addons\qingdongams\model\ReceivablesPlan::where([
  514. 'contract_id' => $ids
  515. ])->with(['customer'])->paginate($limit);
  516. $result = array("total" => $list->total(), "rows" => $list->items());
  517. return json($result);
  518. }
  519. /**
  520. * 获取回款记录
  521. */
  522. public function get_receivables($ids = null) {
  523. list($where, $sort, $order, $offset, $limit) = $this->buildparams();
  524. $list = \addons\qingdongams\model\Receivables::where([
  525. 'contract_id' => $ids
  526. ])->with(['customer','ownerStaff'])->paginate($limit);
  527. $result = array("total" => $list->total(), "rows" => $list->items());
  528. return json($result);
  529. }
  530. /**
  531. * 获取商机关联产品
  532. */
  533. public function get_business_product(){
  534. $business_id=input('business_id');
  535. if(empty($business_id)){
  536. $this->error('参数不能为空');
  537. }
  538. $business=BusinessProduct::where(['business_id'=>$business_id])->with(['productinfo'])->select();
  539. $this->success('请求成功','',$business);
  540. }
  541. /**
  542. * 获取产品
  543. */
  544. public function get_product()
  545. {
  546. $where = [];
  547. if ($keyValue = $this->request->request("keyValue")) {
  548. $where['id'] = $keyValue;
  549. }
  550. $name = input('name');
  551. if(!empty($name)){
  552. $where['name'] = ['like','%'.$name.'%'];
  553. }
  554. $countrys = Product::where($where)->field('id,name')->order('id desc')->select();
  555. return json(['list' => $countrys, 'total' => count($countrys)]);
  556. }
  557. /**
  558. * 获取产品配置
  559. */
  560. public function get_product_part()
  561. {
  562. $where = [];
  563. if ($keyValue = $this->request->request("keyValue")) {
  564. $where['id'] = $keyValue;
  565. }
  566. $name = input('name');
  567. if(!empty($name)){
  568. $where['name'] = ['like','%'.$name.'%'];
  569. }
  570. $countrys = ProductPart::where($where)->field('id,name')->order('id desc')->select();
  571. return json(['list' => $countrys, 'total' => count($countrys)]);
  572. }
  573. /**
  574. * 获取产品价格
  575. */
  576. public function get_product_price()
  577. {
  578. $id = input('id', 0);
  579. $price = Product::where(['id' => $id])->value('price') ?? 0;
  580. $this->success('请求成功', '', ['price' => $price]);
  581. }
  582. /**
  583. * 获取审批人列表
  584. */
  585. public function getstaff(){
  586. $pageSize = input('pageSize');
  587. $pageNumber = input('pageNumber');
  588. $where = [];
  589. if ($keyValue = $this->request->request("keyValue")) {
  590. $where['id'] = ['in',$keyValue];
  591. }
  592. $name = input('name');
  593. if(!empty($name)){
  594. $where['name'] = ['like','%'.$name.'%'];
  595. }
  596. $staff = Staff::where($where)->where(['id'=>['neq',$this->_staff->id]])->field('id,name')->order('id desc')->paginate($pageSize, false, ['page' => $pageNumber]);
  597. return json(['list' => $staff->items(), 'total' => $staff->total()]);
  598. }
  599. /**
  600. * 删除
  601. */
  602. public function del($ids = "") {
  603. if (!$this->request->isPost()) {
  604. $this->error(__("Invalid parameters"));
  605. }
  606. $map['id'] = array('in', $ids);
  607. // 修改绑定设备的设备状态
  608. \app\admin\model\qingdongams\customer\Equipmentdevice::updateStatus($ids);
  609. // 更新合同表时间
  610. $contract = \addons\qingdongams\model\Contract::where(['id' => $ids])->find();
  611. $contract->updatetime = time();
  612. $contract->save();
  613. $result = $this->model->destroy($map);
  614. if (!$result) {
  615. $this->error('删除失败');
  616. }
  617. $this->success('删除成功');
  618. }
  619. /**
  620. * 导入合同
  621. * @return string|void
  622. */
  623. public function import()
  624. {
  625. set_time_limit(0);
  626. if ($this->request->isPost()) {
  627. $file = $this->request->request('file');
  628. if (!$file) {
  629. $this->error(__('Parameter %s can not be empty', 'file'));
  630. }
  631. $filePath = ROOT_PATH . 'public' . $file;
  632. if (!is_file($filePath)) {
  633. $this->error(__('No results were found'));
  634. }
  635. //实例化reader
  636. $ext = pathinfo($filePath, PATHINFO_EXTENSION);
  637. if (!in_array($ext, ['csv', 'xls', 'xlsx'])) {
  638. $this->error(__('Unknown data format'));
  639. }
  640. if ($ext === 'csv') {
  641. $file = fopen($filePath, 'r');
  642. $filePath = tempnam(sys_get_temp_dir(), 'import_csv');
  643. $fp = fopen($filePath, "w");
  644. $n = 0;
  645. while ($line = fgets($file)) {
  646. $line = rtrim($line, "\n\r\0");
  647. $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']);
  648. if ($encoding != 'utf-8') {
  649. $line = mb_convert_encoding($line, 'utf-8', $encoding);
  650. }
  651. if ($n == 0 || preg_match('/^".*"$/', $line)) {
  652. fwrite($fp, $line . "\n");
  653. } else {
  654. fwrite($fp, '"' . str_replace(['"', ','], ['""', '","'], $line) . "\"\n");
  655. }
  656. $n++;
  657. }
  658. fclose($file) || fclose($fp);
  659. $reader = new Csv();
  660. } elseif ($ext === 'xls') {
  661. $reader = new Xls();
  662. } else {
  663. $reader = new Xlsx();
  664. }
  665. if (!$PHPExcel = $reader->load($filePath)) {
  666. $this->error(__('Unknown data format'));
  667. }
  668. $currentSheet = $PHPExcel->getSheet(0); //读取文件中的第一个工作表
  669. $allColumn = $currentSheet->getHighestDataColumn(); //取得最大的列号
  670. $allRow = $currentSheet->getHighestRow(); //取得一共有多少行
  671. $maxColumnNumber = Coordinate::columnIndexFromString($allColumn);
  672. //开始读取数据
  673. $fields = [];
  674. for ($currentRow = 1; $currentRow <= 1; $currentRow++) {
  675. for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
  676. $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
  677. $fields[$currentRow][] = $val;
  678. if ($val instanceof RichText) {//富文本转换字符串
  679. $val = $val->__toString();
  680. }
  681. $values[] = is_null($val) ? NULL : trim($val);
  682. }
  683. }
  684. if (!isset($fields[1])) {
  685. $this->error('导入文件第一行没有数据');
  686. }
  687. $lastid = $this->model->withTrashed()->order('id desc')->value('id');
  688. $lastid = $lastid + 5;//防止重复
  689. $contractRow = [];
  690. $errorInfo = [];
  691. $fieldnames = FormField::where(['types' => FormField::CONTRACT_TYPE])->column('field', 'name');
  692. if(!$fieldnames){
  693. $this->error('请在系统管理->字段管理中保存合同管理表单生成合同导入字段');
  694. }
  695. $customerNames=Customer::where([])->column('id,owner_staff_id','name');
  696. $contacts = Contacts::where([])->field('id,name,customer_id')->select();
  697. $contacts = collection($contacts)->toArray();
  698. $contactsNames = [];
  699. foreach ($contacts as $v) {
  700. $contactsNames[$v['customer_id']][$v['name']] = $v;
  701. }
  702. $businessNames=Business::where([])->column('id','name');
  703. $staffNames=Staff::where([])->column('id','name');
  704. $fn = [];
  705. $nums=$this->model->where([])->column('num');
  706. for ($currentRow = 1; $currentRow <= 1; $currentRow++) {
  707. $values = [];
  708. for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
  709. $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
  710. $values[] = is_null($val) ? '' : $val;
  711. }
  712. foreach ($values as $l) {
  713. $fn[] = $fieldnames[$l] ?? '';
  714. }
  715. }
  716. for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) {
  717. $values = [];
  718. for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
  719. $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
  720. if ($val instanceof RichText) {//富文本转换字符串
  721. $val = $val->__toString();
  722. }
  723. $values[] = is_null($val) ? NULL : trim($val);
  724. }
  725. $lastid++;
  726. $addContract = ['id' => $lastid];
  727. $customer=isset($customerNames[$values[0]])?$customerNames[$values[0]]:0;
  728. if(empty($customer)){
  729. $errorInfo[] = "第{$currentRow}行,客户名称不存在;";
  730. continue;
  731. }
  732. $addContract['customer_id']=$customer['id'];
  733. $addContract['owner_staff_id']=$customer['owner_staff_id'];
  734. $addContract['create_staff_id']=$customer['owner_staff_id'];
  735. $contacts = isset($contactsNames[$addContract['customer_id']])?(isset($contactsNames[$addContract['customer_id']][$values[1]]) ? $contactsNames[$addContract['customer_id']][$values[1]] : []):[];
  736. if (!empty($values[1]) && empty($contacts)) {
  737. $errorInfo[] = "第{$currentRow}行,客户签约人名称不存在;";
  738. continue;
  739. }
  740. $addContract['contacts_id']=$contacts['id']??0;
  741. $business=isset($businessNames[$values[2]])?$businessNames[$values[2]]:[];
  742. if (!empty($values[2]) && empty($business)) {
  743. $errorInfo[] = "第{$currentRow}行,商机名称不存在;";
  744. continue;
  745. }
  746. $addContract['business_id']=$business['id']??0;
  747. $orderstaff=isset($staffNames[$values[3]])?$staffNames[$values[3]]:[];
  748. if (!empty($values[3]) && empty($orderstaff)) {
  749. $errorInfo[] = "第{$currentRow}行,商机名称不存在;";
  750. continue;
  751. }
  752. $addContract['order_staff_id']=$orderstaff['id']??0;
  753. foreach ($values as $kv => $value) {
  754. if (!isset($fn[$kv]) || empty($fn[$kv])) {
  755. continue;
  756. }
  757. $addContract[$fn[$kv]] = $value;
  758. }
  759. if (empty($addContract['num'])) {
  760. $errorInfo[] = "第{$currentRow}行,合同编号不能为空;";
  761. continue;
  762. }
  763. if (in_array($addContract['num'], $nums)) {
  764. $errorInfo[] = "第{$currentRow}行,合同编号`{$addContract['num']}`已存在;";
  765. continue;
  766. }
  767. if (empty($addContract['name'])) {
  768. $errorInfo[] = "第{$currentRow}行,合同名称不能为空;";
  769. continue;
  770. }
  771. $contractRow[] = $addContract;
  772. }
  773. if (!empty($errorInfo)) {
  774. $this->error(implode(',', $errorInfo));
  775. }
  776. Db::startTrans();
  777. try {
  778. $this->model::importContract($contractRow);
  779. Db::commit();
  780. } catch (Exception $e) {
  781. Db::rollback();
  782. $this->error($e->getMessage());
  783. }
  784. $this->success('导入成功');
  785. }
  786. $this->assign('staffs', Staff::getList());
  787. return $this->view->fetch();
  788. }
  789. /**
  790. * 模板
  791. */
  792. public function template()
  793. {
  794. $title = [
  795. '客户名称',
  796. '客户签约人',
  797. '商机名称',
  798. '公司签约人',
  799. ];
  800. $contractData = Form::getDataValue(Form::CONTRACT_TYPE);
  801. foreach ($contractData as $val) {
  802. $title[] = $val['config']['label'];
  803. }
  804. $file = export_excel($title, [], '合同');
  805. header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  806. header('Content-Disposition: attachment;filename=' . $file['fileName']);
  807. header('Cache-Control: max-age=0');
  808. $obj = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
  809. // 以下内容是excel文件的信息描述信息
  810. $obj->getProperties()->setTitle('导出文件'); //设置标题
  811. $obj->setActiveSheetIndex(0);
  812. $obj->getActiveSheet()->setTitle('导出文件');
  813. /* 循环读取每个单元格的数据 */
  814. $a = 'A';
  815. $currentSheet = $obj->getActiveSheet();
  816. foreach ($title as $key => $value) {
  817. //读取工作表1
  818. // 设置第一行加粗
  819. $obj->getActiveSheet()->getStyle($a . '1')->getFont()->setBold(true);
  820. //这里是设置单元格的内容
  821. $currentSheet->getCell($a . '1')->setValue($value);
  822. $a++;
  823. }
  824. $PHPWriter = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($obj);
  825. $PHPWriter->save('php://output');
  826. }
  827. /**
  828. * 导出信息
  829. */
  830. public function export()
  831. {
  832. $this->request->filter(['strip_tags', 'trim']);
  833. $ids = input('ids');
  834. $isall = input('isall');
  835. $wheres = array();
  836. //导出其中几条
  837. if (isset($ids)) {
  838. $wheres['id'] = array('in', $ids);
  839. }
  840. //导出全部
  841. if (isset($isall)) {
  842. if ($isall == 3) {
  843. unset($wheres['id']);
  844. }
  845. }
  846. //0:全部 1:我负责的 2:下属负责的 3:今日待跟进 4:今日已跟进 5:从未跟进的
  847. $type = input('type',0);
  848. list($where, $sort, $order, $offset, $limit) = $this->buildparams();
  849. switch($type){
  850. case 1:
  851. $staff = Staff::info();
  852. $wheres['owner_staff_id'] = $staff->id;
  853. break;
  854. case 2:
  855. $wheres['owner_staff_id'] = array('in',Staff::getLowerStaffId());
  856. break;
  857. case 3:
  858. $start = date('Y-m-d 00:00:00');
  859. $end = date('Y-m-d 23:59:59');
  860. $record = collection(Record::where(array('relation_type'=>3,'next_time'=>array(array('egt',$start),array('elt',$end))))->field("id,relation_id")->select())->toArray();
  861. $relationId = [];
  862. foreach($record as $k=>$v){
  863. $whereRe['id'] = array('gt',$v['id']);
  864. $whereRe['relation_id'] = $v['relation_id'];
  865. $recordData = Record::where($whereRe)->count();
  866. if($recordData == 0){
  867. $relationId[] = $v['relation_id'];
  868. }
  869. }
  870. $wheres['id'] = array('in',$relationId);
  871. $staff = Staff::info();
  872. $wheres['owner_staff_id'] = $staff->id;
  873. break;
  874. case 4:
  875. $start = date('Y-m-d 00:00:00');
  876. $end = date('Y-m-d 23:59:59');
  877. $record = collection(Record::where(array('relation_type'=>3,'next_time'=>array(array('egt',$start),array('elt',$end))))->field("id,relation_id")->select())->toArray();
  878. $relationId = [];
  879. foreach($record as $k=>$v){
  880. $whereRe['id'] = array('gt',$v['id']);
  881. $whereRe['relation_id'] = $v['relation_id'];
  882. $recordData = Record::where($whereRe)->count();
  883. if($recordData >=1){
  884. $relationId[] = $v['relation_id'];
  885. }
  886. }
  887. $wheres['id'] = array('in',$relationId);
  888. $staff = Staff::info();
  889. $wheres['owner_staff_id'] = $staff->id;
  890. break;
  891. case 5:
  892. $record = collection(Record::where(array('relation_type'=>3,'next_time'=>array('neq','')))->column('relation_id'))->toArray();
  893. $wheres['id'] = array('not in',$record);
  894. $staff = Staff::info();
  895. $wheres['owner_staff_id'] = $staff->id;
  896. break;
  897. default:
  898. $wheres['owner_staff_id'] = array('in',Staff::getMyStaffIds());
  899. break;
  900. }
  901. $list = $this->model->with([
  902. 'customer',
  903. 'orderStaff',
  904. 'contacts',
  905. 'ownerStaff','contractOther',
  906. ])->where($where)->where($wheres)->order($sort, $order)->select();
  907. $list = collection($list)->toArray();
  908. if (!$list) {
  909. $this->error('无导出数据');
  910. }
  911. $title = [
  912. '序号',
  913. '客户名称',
  914. '客户签约人',
  915. '公司签约人',
  916. '归属人',
  917. '创建时间',
  918. ];
  919. $dataValue = Form::getDataValue(Form::CONTRACT_TYPE);
  920. foreach ($dataValue as $val) {
  921. $title[] = $val['config']['label'];
  922. }
  923. foreach ($list as $k => $v) {
  924. if($v['contract_other']){//其他客户
  925. $other=$v['contract_other']['otherdata'];
  926. $other=json_decode($other,true);
  927. $v = array_merge($v, $other);
  928. }
  929. $field = array(
  930. $v['id'],
  931. $v['customer']['name'],
  932. $v['contacts']['name']??'',
  933. $v['order_staff']['name']??'',
  934. $v['owner_staff']['name']??'',
  935. $v['createtime'],
  936. );
  937. foreach ($dataValue as $val) {
  938. if ($val['component'] == 'uploadImage' || $val['component'] == 'uploadFile') {
  939. $field[] = $v[$val['id'] . '_str'] ?? '';
  940. } else {
  941. $field[] = ($v[$val['id']] ?? '');
  942. }
  943. }
  944. $data[] = $field;
  945. }
  946. $file = export_excel($title, $data, '合同');
  947. if ($file['filePath']) {
  948. $this->success('导出成功', '', $file);
  949. }
  950. $this->error('导出失败');
  951. }
  952. /**
  953. * 导入产品明细
  954. * @return string|void
  955. */
  956. public function import_product()
  957. {
  958. set_time_limit(0);
  959. if ($this->request->isPost()) {
  960. $file = $this->request->request('file');
  961. if (!$file) {
  962. $this->error(__('Parameter %s can not be empty', 'file'));
  963. }
  964. $filePath = ROOT_PATH . 'public' . $file;
  965. if (!is_file($filePath)) {
  966. $this->error(__('No results were found'));
  967. }
  968. //实例化reader
  969. $ext = pathinfo($filePath, PATHINFO_EXTENSION);
  970. if (!in_array($ext, ['csv', 'xls', 'xlsx'])) {
  971. $this->error(__('Unknown data format'));
  972. }
  973. if ($ext === 'csv') {
  974. $file = fopen($filePath, 'r');
  975. $filePath = tempnam(sys_get_temp_dir(), 'import_csv');
  976. $fp = fopen($filePath, "w");
  977. $n = 0;
  978. while ($line = fgets($file)) {
  979. $line = rtrim($line, "\n\r\0");
  980. $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']);
  981. if ($encoding != 'utf-8') {
  982. $line = mb_convert_encoding($line, 'utf-8', $encoding);
  983. }
  984. if ($n == 0 || preg_match('/^".*"$/', $line)) {
  985. fwrite($fp, $line . "\n");
  986. } else {
  987. fwrite($fp, '"' . str_replace(['"', ','], ['""', '","'], $line) . "\"\n");
  988. }
  989. $n++;
  990. }
  991. fclose($file) || fclose($fp);
  992. $reader = new Csv();
  993. } elseif ($ext === 'xls') {
  994. $reader = new Xls();
  995. } else {
  996. $reader = new Xlsx();
  997. }
  998. if (!$PHPExcel = $reader->load($filePath)) {
  999. $this->error(__('Unknown data format'));
  1000. }
  1001. $currentSheet = $PHPExcel->getSheet(0); //读取文件中的第一个工作表
  1002. $allColumn = $currentSheet->getHighestDataColumn(); //取得最大的列号
  1003. $allRow = $currentSheet->getHighestRow(); //取得一共有多少行
  1004. $maxColumnNumber = Coordinate::columnIndexFromString($allColumn);
  1005. //开始读取数据
  1006. $fields = [];
  1007. for ($currentRow = 1; $currentRow <= 1; $currentRow++) {
  1008. for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
  1009. $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
  1010. $fields[$currentRow][] = $val;
  1011. if ($val instanceof RichText) {//富文本转换字符串
  1012. $val = $val->__toString();
  1013. }
  1014. $values[] = is_null($val) ? '' : trim($val);
  1015. }
  1016. }
  1017. if (!isset($fields[1])) {
  1018. $this->error('导入文件第一行没有数据');
  1019. }
  1020. $lastid = ContractProduct::order('id desc')->value('id');
  1021. $lastid = $lastid + 5;//防止重复
  1022. $contractProductRow = [];
  1023. $errorInfo = [];
  1024. $contractNum=$this->model::where([])->column('id,name','num');
  1025. $productName=Product::where([])->column('id,price','name');
  1026. $fn = [];
  1027. for ($currentRow = 1; $currentRow <= 1; $currentRow++) {
  1028. $values = [];
  1029. for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
  1030. $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
  1031. $values[] = is_null($val) ? '' : $val;
  1032. }
  1033. }
  1034. for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) {
  1035. $values = [];
  1036. for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
  1037. $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
  1038. if ($val instanceof RichText) {//富文本转换字符串
  1039. $val = $val->__toString();
  1040. }
  1041. $values[] = is_null($val) ? NULL : trim($val);
  1042. }
  1043. $lastid++;
  1044. $addContractProduct = ['id' => $lastid];
  1045. $contract = isset($contractNum[$values[0]]) ? $contractNum[$values[0]] : 0;
  1046. if (empty($contract)) {
  1047. $errorInfo[] = "第{$currentRow}行,合同编号不存在;";
  1048. continue;
  1049. }
  1050. $product = isset($productName[$values[1]]) ? $productName[$values[1]] : 0;
  1051. if (empty($product)) {
  1052. $errorInfo[] = "第{$currentRow}行,产品名称不存在;";
  1053. continue;
  1054. }
  1055. if (empty($values[2])) {
  1056. $errorInfo[] = "第{$currentRow}行,产品数量不能为空;";
  1057. continue;
  1058. }
  1059. if (empty($values[3])) {
  1060. $errorInfo[] = "第{$currentRow}行,产品售价不能为空;";
  1061. continue;
  1062. }
  1063. $addContractProduct['contract_id'] = $contract['id'];
  1064. $addContractProduct['product_id'] = $product['id'];
  1065. $addContractProduct['number'] = $values[2];
  1066. $addContractProduct['price'] = $values[3];
  1067. $contractProductRow[]=$addContractProduct;
  1068. }
  1069. if (!empty($errorInfo)) {
  1070. $this->error(implode(',', $errorInfo));
  1071. }
  1072. Db::startTrans();
  1073. try {
  1074. ContractProduct::importProduct($contractProductRow);
  1075. Db::commit();
  1076. } catch (Exception $e) {
  1077. Db::rollback();
  1078. $this->error($e->getMessage());
  1079. }
  1080. $this->success('导入成功');
  1081. }
  1082. $this->assign('staffs', Staff::getList());
  1083. return $this->view->fetch();
  1084. }
  1085. /**
  1086. * 模板
  1087. */
  1088. public function template_product()
  1089. {
  1090. $title = [
  1091. '合同编号',
  1092. '商品名称',
  1093. '数量',
  1094. '售价',
  1095. ];
  1096. $file = export_excel($title, [], '产品明细');
  1097. header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  1098. header('Content-Disposition: attachment;filename=' . $file['fileName']);
  1099. header('Cache-Control: max-age=0');
  1100. $obj = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
  1101. // 以下内容是excel文件的信息描述信息
  1102. $obj->getProperties()->setTitle('导出文件'); //设置标题
  1103. $obj->setActiveSheetIndex(0);
  1104. $obj->getActiveSheet()->setTitle('导出文件');
  1105. /* 循环读取每个单元格的数据 */
  1106. $a = 'A';
  1107. $currentSheet = $obj->getActiveSheet();
  1108. foreach ($title as $key => $value) {
  1109. //读取工作表1
  1110. // 设置第一行加粗
  1111. $obj->getActiveSheet()->getStyle($a . '1')->getFont()->setBold(true);
  1112. //这里是设置单元格的内容
  1113. $currentSheet->getCell($a . '1')->setValue($value);
  1114. $a++;
  1115. }
  1116. $PHPWriter = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($obj);
  1117. $PHPWriter->save('php://output');
  1118. }
  1119. /**
  1120. * 导出信息
  1121. */
  1122. public function export_product()
  1123. {
  1124. $ids = input('ids');
  1125. $type = input('type');
  1126. $wheres = array();
  1127. //导出其中几条
  1128. if (isset($ids)) {
  1129. $wheres['contract_id'] = array('in', $ids);
  1130. }
  1131. //导出全部
  1132. if (isset($type)) {
  1133. if ($type == 3) {
  1134. unset($wheres['contract_id']);
  1135. }
  1136. }
  1137. $list=ContractProduct::where($wheres)->with(['contract','productinfo'])->select();
  1138. $list = collection($list)->toArray();
  1139. if (!$list) {
  1140. $this->error('无导出数据');
  1141. }
  1142. $title = [
  1143. '序号',
  1144. '合同编号',
  1145. '合同名称',
  1146. '商品名称',
  1147. '售价',
  1148. '批发价',
  1149. '产品',
  1150. '规格',
  1151. '数量',
  1152. ];
  1153. $data=[];
  1154. foreach ($list as $k => $v) {
  1155. $field = array(
  1156. $v['id'],
  1157. $v['contract']['num'],
  1158. $v['contract']['name'],
  1159. $v['productinfo']['name']??'',
  1160. $v['price']??'',
  1161. $v['productinfo']['cost_price']??'',
  1162. $v['productinfo']['goods']['name']??'',
  1163. $v['productinfo']['unit']??'',
  1164. $v['number']??'',
  1165. );
  1166. $data[] = $field;
  1167. }
  1168. $file = export_excel($title, $data, '产品明细');
  1169. if ($file['filePath']) {
  1170. $this->success('导出成功', '', $file);
  1171. }
  1172. $this->error('导出失败');
  1173. }
  1174. /**
  1175. * 导出word
  1176. */
  1177. public function words($ids = null)
  1178. {
  1179. if ($this->request->isPost()) {
  1180. $file = input('file', '');
  1181. $is_template=input('is_template',0);
  1182. $template_name=input('template_name','');
  1183. if (empty($file)) {
  1184. $this->error('导出模板');
  1185. }
  1186. if($is_template == 1){
  1187. if(empty($template_name)){
  1188. $this->error('模板名称不能为空');
  1189. }
  1190. $create=[
  1191. 'type'=>'contract',
  1192. 'name'=>$template_name,
  1193. 'url'=>$file
  1194. ];
  1195. $wordTemplateModel = new WordTemplate();
  1196. $wordTemplateModel->save($create);
  1197. }
  1198. $tmp = new TemplateProcessor('.' . $file);
  1199. Settings::setCompatibility(true);
  1200. Settings::setOutputEscapingEnabled(true);
  1201. $row = $this->model->where(['id'=>$ids])->with(['customer','contacts','business','orderStaff'])->find();
  1202. $row = $row->toArray();
  1203. $row = ContractOther::getOther($row);
  1204. $form = Form::getDataValue(Form::CONTRACT_TYPE);
  1205. $imgNames=[];
  1206. foreach($form as $k=>$v){
  1207. if($v['component'] == 'uploadImage'){
  1208. $imgNames[]=$v['id'];
  1209. }
  1210. }
  1211. foreach ($row as $key => $item) {
  1212. if(in_array($key,$imgNames) && $item ){
  1213. if(is_array($item)){
  1214. foreach ($item as $it){
  1215. $tmp->setImageValue($key,ltrim(parse_url($it['file_path'])['path'],'/'));
  1216. }
  1217. }else{
  1218. $fileinfo = File::where(['id'=>['in',$item]])->field('id,name,file_path,save_name')->select();
  1219. foreach ($fileinfo as $it){
  1220. $tmp->setImageValue($key,ltrim(parse_url($it['file_path'])['path'],'/'));
  1221. }
  1222. }
  1223. }else{
  1224. if(is_array($item)){
  1225. $tmp->setValue($key , '');//
  1226. continue;
  1227. }
  1228. $tmp->setValue($key , $item);//
  1229. }
  1230. }
  1231. $contractProduct=ContractProduct::where(['contract_id'=>$ids])
  1232. ->with(['productinfo'])->select();
  1233. $contractProduct=collection($contractProduct)->toArray();
  1234. $c = count($contractProduct);//总行数
  1235. $tmp->cloneRow('product_name', $c);//复制行
  1236. for ($i = 0; $i < $c; $i++) {
  1237. $p=$contractProduct[$i];
  1238. $tmp->setValue("product_name#" . ($i + 1), $p['productinfo']['name'] ?? '');//名称
  1239. $tmp->setValue("product_unit#" . ($i + 1), $p['productinfo']['unit'] ?? '');//单位
  1240. $tmp->setValue("product_num#" . ($i + 1), $p['productinfo']['num'] ?? '');//编码
  1241. $tmp->setValue("product_type#" . ($i + 1), $p['productinfo']['type'] ?? '');//规格
  1242. $tmp->setValue("product_number#" . ($i + 1), $p['number']);//数量
  1243. $tmp->setValue("product_price#" . ($i + 1), $p['price']);//总价格
  1244. $tmp->setValue("product_total#" . ($i + 1), $p['price'] * $p['number']);//总价格
  1245. }
  1246. $tmp->setValue('money_big', convertAmountToCn($row['money']));
  1247. $tmp->setValue('customer_name', $row['customer']['name'] ?? '');
  1248. $tmp->setValue('contacts_name', $row['contacts']['name'] ?? '');
  1249. $tmp->setValue('business_name', $row['business']['name'] ?? '');
  1250. $tmp->setValue('order_staff_name', $row['order_staff']['name'] ?? '');
  1251. //end 配置
  1252. $filename = $row['name'];
  1253. $filepath = $filename . '.docx';
  1254. $fileurl = './uploads/' . date('Ymd') . '/';
  1255. if (!file_exists($fileurl)) {
  1256. mkdir($fileurl);
  1257. }
  1258. $tmp->saveAs($fileurl . $filepath);//另存为
  1259. $model = new File();
  1260. $data = [
  1261. 'types' => 'file',
  1262. 'name' => $filepath,
  1263. 'save_name' => $fileurl . $filepath,
  1264. 'size' => filesize($fileurl . $filepath),
  1265. 'file_path' => trim($fileurl, '.') . $filepath,
  1266. ];
  1267. $model->save($data);
  1268. $lastid = $model->id;
  1269. $file = cdnurl($model::getUrl($lastid), true);
  1270. $this->success('成功', '', ['file' => $file, 'id' => $lastid, 'filename' => $filepath]);
  1271. }
  1272. $templates=WordTemplate::where(['type'=>'contract'])->select();
  1273. $contract = Form::getDataValue(Form::CONTRACT_TYPE);
  1274. $columns = array();
  1275. $columns[] = ['key' => 'customer_name', 'name' => '客户名称'];
  1276. $columns[] = ['key' => 'contacts_name', 'name' => '联系人名称'];
  1277. $columns[] = ['key' => 'business_name', 'name' => '商机名称'];
  1278. $columns[] = ['key' => 'order_staff_name', 'name' => '公司签约人名称'];
  1279. $columns[] = ['key' => 'money_big', 'name' => '合同金额人民币大写'];
  1280. foreach ($contract as $k => $v) {
  1281. $columns[] = array(
  1282. 'key' => $v['id'],
  1283. 'name' => $v['config']['label'],
  1284. );
  1285. }
  1286. $columns[] = ['key' => 'product_name', 'name' => '产品名称'];
  1287. $columns[] = ['key' => 'product_unit', 'name' => '产品单位'];
  1288. $columns[] = ['key' => 'product_num', 'name' => '产品编码'];
  1289. $columns[] = ['key' => 'product_type', 'name' => '产品规格'];
  1290. $columns[] = ['key' => 'product_number', 'name' => '产品数量'];
  1291. $columns[] = ['key' => 'product_price', 'name' => '产品单价'];
  1292. $columns[] = ['key' => 'product_total', 'name' => '产品合计'];
  1293. $this->assign('column', $columns);
  1294. $this->assign('templates', $templates);
  1295. $this->assign('ids', $ids);
  1296. return $this->view->fetch();
  1297. }
  1298. /**
  1299. * 报价单转为合同
  1300. */
  1301. public function quote_change()
  1302. {
  1303. $quote_id = input('quote_id');
  1304. if ($this->request->isPost()) {
  1305. $params = $this->request->post("row/a");
  1306. if ($params) {
  1307. $params = $this->preExcludeFields($params);
  1308. // 表单验证
  1309. if (($result = $this->qingdongamsValidate($params, 'Contract', 'create')) !== true) {
  1310. $this->error($result);
  1311. }
  1312. $result = FormField::checkFields(FormField::CONTRACT_TYPE, $params);
  1313. if ($result !== true) {
  1314. $this->error($result);
  1315. }
  1316. $result = false;
  1317. Db::startTrans();
  1318. try {
  1319. $params = Form::updateFormParams(Form::CONTRACT_TYPE, $params);
  1320. if ($params['product']) {
  1321. $params['product'] = json_decode($params['product'], true);
  1322. }
  1323. $result = $this->model::createContract($params);
  1324. Db::commit();
  1325. } catch (Exception $e) {
  1326. Db::rollback();
  1327. $this->error($e->getMessage());
  1328. }
  1329. if ($result !== false) {
  1330. $this->success();
  1331. } else {
  1332. $this->error(__('No rows were inserted'));
  1333. }
  1334. }
  1335. $this->error(__('Parameter %s can not be empty', ''));
  1336. }
  1337. $flow = Flow::getsteplist(Flow::CONTRACT_STATUS);
  1338. if (empty($flow)) {
  1339. $this->error('无可用审批流,请联系管理员');
  1340. }
  1341. $customer_id = input('customer_id');
  1342. if ($customer_id) {
  1343. $business = Business::where(array('customer_id' => $customer_id))->select();
  1344. } else {
  1345. $business = Business::getList();
  1346. }
  1347. $quote = Quote::where(['id' => $quote_id])->with(['customer','contacts'])->find();
  1348. $product=QuoteProduct::where(['quote_id'=>$quote['id']])->with(['productinfo'])->select();
  1349. foreach ($product as $k=>$v){
  1350. if($v['productinfo']){
  1351. $v['product_name']=$v['productinfo']['name'];
  1352. $v['cost_price']=$v['productinfo']['cost_price'];
  1353. $v['type']=$v['productinfo']['type'];
  1354. if($v['productinfo']['goods']){
  1355. $v['goods_name']=$v['productinfo']['goods']['name'];
  1356. }
  1357. }
  1358. $product[$k]=$v;
  1359. }
  1360. $quote['product']=json_encode($product);
  1361. $quote['num']=getItemNumber('contract');
  1362. $quote['money']=$quote['quote_amount'];
  1363. $this->assign('row', $quote);
  1364. $this->assign('flow', $flow);
  1365. $this->assign('staff', Staff::getStaff());
  1366. $this->assign('customers', Customer::getList());
  1367. $this->assign('business', $business);
  1368. $this->assign('customer_id', $customer_id);
  1369. $this->assign('business_id', input('business_id'));
  1370. $this->assign('staffs', Staff::allList());
  1371. $this->assign('form_data', Form::getDataValue('contract'));
  1372. $this->assign('ratio', Ratio::where(['status' => 1])->select());
  1373. return $this->view->fetch();
  1374. }
  1375. /**下载合同
  1376. */
  1377. public function download_quote($id = null)
  1378. {
  1379. $contract = ContractModel::where(['id' => $id])->with(['customer', 'contacts','orderStaff',])->find();
  1380. if (empty($contract)) {
  1381. $this->error('不能为空');
  1382. }
  1383. $contract = $contract->toArray();
  1384. $contractProduct = ContractProduct::where(['contract_id' => $id])->with(['product'])->select();
  1385. $tmp = new TemplateProcessor('assets/addons/qingdongams/phpword/contract.docx');
  1386. \PhpOffice\PhpWord\Settings::setCompatibility(true);
  1387. \PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true);
  1388. $tmp->setValue('number', $contract['num']);//合同编号
  1389. $tmp->setValue('name', $contract['customer']['name']);//乙方
  1390. $tmp->setValue('signing_time', date('Y年m月d日', strtotime($contract['order_date'])));//签订时间
  1391. $tmp->setValue('signed_at', $contract['signed_at']);//签订地点
  1392. $tmp->setValue('order_name', $contract['order_staff']['name']);
  1393. $tmp->setValue('order_mobile', $contract['order_staff']['mobile']);
  1394. $rows = count($contractProduct);//总行数
  1395. $tmp->cloneRow('one', $rows);//复制行
  1396. for ($i = 0; $i < $rows; $i++) {
  1397. $tmp->setValue("one#" . ($i + 1), $contractProduct[$i]['name'] ?? '');//名称
  1398. $tmp->setValue("two#" . ($i + 1), $contractProduct[$i]['num'] ?? '');//型号
  1399. $tmp->setValue("three#" . ($i + 1), $contractProduct[$i]['number'] ?? '');//数量
  1400. $tmp->setValue("four#" . ($i + 1), $contractProduct[$i]['price'] ?? '');//总价格
  1401. }
  1402. //start 配置
  1403. $configs = [];
  1404. $tmp->setValue("discount_rate", $contract['discount_rate']);//金额
  1405. $tmp->setValue("price", $contract['money']);//金额
  1406. $tmp->setValue("price_big", convertAmountToCn($contract['money'] ?? 0));//汉字金额
  1407. $tmp->setValue("remarks", $contract['remarks']);//备注
  1408. $tmp->setValue("payment", $contract['payment']);//支付方式
  1409. $tmp->setValue("be_overdue", $contract['be_overdue']);//到期条款
  1410. $tmp->setValue("delivery_time", $contract['delivery_time']);//
  1411. $tmp->setValue("account", $contract['collection_account']);//
  1412. $tmp->setValue("account_name", $contract['collection_deposit']);//
  1413. $tmp->setValue("bank_name", $contract['collection_name']);//
  1414. $tmp->setValue("effective", $contract['effective']);//
  1415. $tmp->setValue("guarantee", $contract['guarantee']);//
  1416. $tmp->setValue("address", $contract['customer']['address']);//
  1417. $tmp->setValue("legal", $contract['legal']);//
  1418. $tmp->setValue("entrust", $contract['entrust']);//
  1419. $tmp->setValue("handler", $contract['handler']);//
  1420. $tmp->setValue("mobile", $contract['mobile']);//
  1421. $tmp->setValue("fax", $contract['fax']);//
  1422. $tmp->setValue("deposit", $contract['deposit']);//
  1423. $tmp->setValue("y_account", $contract['account']);//
  1424. //end 配置
  1425. $filename = $contract['customer']['name'] . $contract['num'] . '.docx';
  1426. $fileurl = './uploads/' . date('Ymd') . '/';
  1427. if (!file_exists($fileurl)) {
  1428. mkdir($fileurl);
  1429. }
  1430. $tmp->saveAs($fileurl . $filename);//另存为
  1431. $model = new File();
  1432. $data = [
  1433. 'types' => 'file',
  1434. 'name' => $filename,
  1435. 'save_name' => $fileurl . $filename,
  1436. 'size' => filesize($fileurl . $filename),
  1437. 'file_path' => trim($fileurl, '.') . $filename,
  1438. ];
  1439. $model->save($data);
  1440. $lastid = $model->getLastInsID();
  1441. $file = cdnurl($model::getUrl($lastid), true);
  1442. $this->success('成功', '', ['file' => $file, 'id' => $lastid, 'filename' => $filename]);
  1443. }
  1444. /**
  1445. * 添加收货地址
  1446. */
  1447. public function address($ids = null)
  1448. {
  1449. if ($this->request->isAjax()) {
  1450. $params = $this->request->post('row/a');
  1451. $row = ContractModel::where(['id' => $ids])->find();
  1452. if (empty($row)) {
  1453. $this->error('合同信息不存在');
  1454. }
  1455. $params['id'] = $ids;
  1456. Db::startTrans();
  1457. try {
  1458. ContractModel::updateContractAddress($params);
  1459. // 更新合同表时间
  1460. $contract = \addons\qingdongams\model\Contract::where(['id' => $ids])->find();
  1461. $contract->updatetime = time();
  1462. $contract->save();
  1463. Db::commit();
  1464. } catch (Exception $e) {
  1465. Db::rollback();
  1466. $this->error($e->getMessage());
  1467. }
  1468. $this->success('添加收货地址信息成功');
  1469. }
  1470. $row = $this->model->where(['id' => $ids])->find();
  1471. $this->view->assign("row", $row);
  1472. $this->view->assign("id", $ids);
  1473. return $this->view->fetch();
  1474. }
  1475. /**
  1476. * 发票物流
  1477. */
  1478. public function invoice_contract($ids = null)
  1479. {
  1480. if ($this->request->isAjax()) {
  1481. $params = $this->request->post('row/a');
  1482. $row = ContractModel::where(['id' => $ids])->find();
  1483. if (empty($row)) {
  1484. $this->error('合同信息不存在');
  1485. }
  1486. $params['id'] = $ids;
  1487. Db::startTrans();
  1488. try {
  1489. $params['invoice_file_ids'] = File::getId($params['invoice_file_ids']);
  1490. ContractModel::invoiceContract($params);
  1491. // 更新合同表时间
  1492. $contract = \addons\qingdongams\model\Contract::where(['id' => $ids])->find();
  1493. $contract->updatetime = time();
  1494. $contract->save();
  1495. Db::commit();
  1496. } catch (Exception $e) {
  1497. Db::rollback();
  1498. $this->error($e->getMessage());
  1499. }
  1500. $this->success('添加收货地址信息成功');
  1501. }
  1502. $row = $this->model->where(['id' => $ids])->find()->toArray();
  1503. $row['invoice_file_ids'] = implode(',', $row['invoice_file_ids']);
  1504. $this->view->assign("row", $row);
  1505. $this->view->assign("id", $ids);
  1506. return $this->view->fetch();
  1507. }
  1508. /**
  1509. * 发票回执单
  1510. */
  1511. public function receipt_contract($ids = null)
  1512. {
  1513. if ($this->request->isAjax()) {
  1514. $params = $this->request->post('row/a');
  1515. if (empty($params['receipt_file_ids'])) {
  1516. $this->error('回执单不能为空');
  1517. }
  1518. if (empty($params['receipt_date'])) {
  1519. $this->error('回执时间不能为空');
  1520. }
  1521. Db::startTrans();
  1522. try {
  1523. $params['id'] = $ids;
  1524. $params['receipt_file_ids'] = File::getId($params['receipt_file_ids']);
  1525. ContractModel::receiptContract($params);
  1526. // 更新合同表时间
  1527. $contract = \addons\qingdongams\model\Contract::where(['id' => $ids])->find();
  1528. $contract->updatetime = time();
  1529. $contract->save();
  1530. Db::commit();
  1531. } catch (Exception $e) {
  1532. Db::rollback();
  1533. $this->error($e->getMessage());
  1534. }
  1535. $this->success('回执成功');
  1536. }
  1537. $row = $this->model->where(['id' => $ids])->find()->toArray();
  1538. $row['receipt_file_ids'] = implode(',', $row['receipt_file_ids']);
  1539. $this->view->assign("row", $row);
  1540. $this->view->assign("id", $ids);
  1541. return $this->view->fetch();
  1542. }
  1543. /**
  1544. * 终止合同
  1545. */
  1546. public function revoke_contract()
  1547. {
  1548. $id = input('id');
  1549. $model = new ContractModel();
  1550. $row = $model->get($id);
  1551. if (empty($row)) {
  1552. $this->error('信息不存在');
  1553. }
  1554. $files = $model->where(['id' => $id])->update(['contract_status' => 2, 'check_status' => 9]);
  1555. // 修改绑定设备的设备状态
  1556. \app\admin\model\qingdongams\customer\Equipmentdevice::updateStatus($id);
  1557. OperationLog::createLog(OperationLog::CONTRACT_TYPE, $id, '终止合同');
  1558. $this->success('操作成功', $files);
  1559. }
  1560. }