Common.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. <?php
  2. namespace app\api\controller;
  3. use AliPay\App;
  4. use app\common\constant\CommonConstant;
  5. use app\common\constant\MaintainConstant;
  6. use app\common\model\Goods;
  7. use app\common\service\ApproveInfoService;
  8. use app\common\service\CommonService;
  9. use app\common\service\GoodsCategoryService;
  10. use app\common\service\UserService;
  11. use hg\apidoc\annotation as Apidoc;
  12. use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
  13. use PhpOffice\PhpSpreadsheet\Reader\Csv;
  14. use PhpOffice\PhpSpreadsheet\Reader\Xls;
  15. use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
  16. use think\db\exception\BindParamException;
  17. use think\Exception;
  18. use think\exception\PDOException;
  19. use think\Db;
  20. /**
  21. * @Apidoc\Title("公用")
  22. * @Apidoc\Group("api")
  23. * @Apidoc\Sort("4")
  24. */
  25. class Common extends Base
  26. {
  27. // 需要登录
  28. protected $need_login = ['get_user_list'];
  29. public function initialize()
  30. {
  31. parent::initialize();
  32. }
  33. /**
  34. * 类型数据
  35. *
  36. * @Apidoc\Method("POST")
  37. * @Apidoc\Returned("module_list", type="array", desc="模块列表")
  38. * @Apidoc\Returned("degree_list", type="array", desc="缓急程度列表")
  39. * @Apidoc\Returned("pay_type_list", type="array", desc="采购支付方式列表")
  40. * @Apidoc\Returned("time_list", type="array", desc="请假周期列表")
  41. * @Apidoc\Returned("data1", type="array", desc="采购类型列表")
  42. * @Apidoc\Returned("data2", type="array", desc="呈批类型列表")
  43. * @Apidoc\Returned("data5", type="array", desc="出差类型列表")
  44. * @Apidoc\Returned("data6", type="array", desc="请假类型列表")
  45. * @Apidoc\Returned("data8", type="array", desc="维修类型列表")
  46. * @Apidoc\Returned("data9", type="array", desc="合同类型列表")
  47. */
  48. public function get_type_list()
  49. {
  50. $data = CommonService::get_data();
  51. $this->success('类型数据', $data);
  52. }
  53. /**
  54. * 发起人列表
  55. *
  56. * @Apidoc\Desc("入库模块")
  57. * @Apidoc\Method("POST")
  58. * @Apidoc\Param("page", type="integer",require=true, desc="页数")
  59. * @Apidoc\Param("page_num", type="integer", require=true, desc="每页数量")
  60. * @Apidoc\Returned("userid", type="string", desc="userid")
  61. * @Apidoc\Returned("name", type="string", desc="姓名")
  62. **/
  63. public function get_user_list()
  64. {
  65. $offset = $this->off_set;
  66. $length = $this->page_num;
  67. $user = $this->user;
  68. $list = UserService::get_list(0,$offset, $length);
  69. $this->success('发起人列表', $list);
  70. }
  71. /**
  72. * 维修人员列表
  73. *
  74. * @Apidoc\Desc("维修模块")
  75. * @Apidoc\Method("POST")
  76. * @Apidoc\Param("type", type="integer", require=true, desc="类型:1=物业主管,2=信息负责人")
  77. **/
  78. public function get_maintain_user(){
  79. $type = $this->request->post('type');
  80. if (!array_key_exists($type, MaintainConstant::get_type_list())) {
  81. $this->success('维修人员列表.');
  82. }
  83. $list = UserService::get_maintain_user($type);
  84. $this->success('维修人员列表',$list);
  85. }
  86. /**
  87. * 获取导入模板
  88. *
  89. * @Apidoc\Desc("申购模块,入库模块,领用模块")
  90. * @Apidoc\Method("POST")
  91. * @Apidoc\Param("module", type="integer", require=true, desc="模块类型:1=申购申请,3=入库申请,4=领用申请")
  92. * @Apidoc\Returned("url", type="string", desc="导入模板路径")
  93. **/
  94. public function get_import_template(){
  95. $module = $this->request->post('module');
  96. if (!in_array($module, [CommonConstant::MODULE_1, CommonConstant::MODULE_3, CommonConstant::MODULE_4])) {
  97. $this->error('请选择正确的模块类型');
  98. }
  99. switch ($module){
  100. case CommonConstant::MODULE_1:
  101. $url = $this->request->domain().'/导入模板-采购物品.xlsx';
  102. break;
  103. case CommonConstant::MODULE_3:
  104. $url = $this->request->domain().'/导入模板-入库物品.xlsx';
  105. break;
  106. case CommonConstant::MODULE_4:
  107. $url = $this->request->domain().'/导入模板-领用物品.xlsx';
  108. break;
  109. }
  110. $data = compact("url");
  111. $this->success('导入模板',$data);
  112. }
  113. /**
  114. * 导入
  115. *
  116. * @Apidoc\Desc("申购模块,入库模块,领用模块")
  117. * @Apidoc\Method("POST")
  118. * @Apidoc\Param("module", type="integer", require=true, desc="模块类型:1=申购申请,3=入库申请,4=领用申请")
  119. * @Apidoc\Param("file", type="string", require=true, desc="上传后的文件路径")
  120. * @return void
  121. * @throws PDOException
  122. * @throws BindParamException
  123. */
  124. public function import()
  125. {
  126. $module = $this->request->post('module');
  127. $file = $this->request->post('file');
  128. if (!in_array($module, [CommonConstant::MODULE_1, CommonConstant::MODULE_3, CommonConstant::MODULE_4])) {
  129. $this->error('请选择正确的模块类型');
  130. }
  131. if (!$file) {
  132. $this->error('请选择文件');
  133. }
  134. $filePath = $_SERVER['DOCUMENT_ROOT'] . '/' . $file;
  135. if (!is_file($filePath)) {
  136. $this->error('文件未找到');
  137. }
  138. //实例化reader
  139. $ext = pathinfo($filePath, PATHINFO_EXTENSION);
  140. if (!in_array($ext, ['csv', 'xls', 'xlsx'])) {
  141. $this->error('未知的数据格式');
  142. }
  143. if ($ext === 'csv') {
  144. $file = fopen($filePath, 'r');
  145. $filePath = tempnam(sys_get_temp_dir(), 'import_csv');
  146. $fp = fopen($filePath, 'w');
  147. $n = 0;
  148. while ($line = fgets($file)) {
  149. $line = rtrim($line, "\n\r\0");
  150. $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']);
  151. if ($encoding !== 'utf-8') {
  152. $line = mb_convert_encoding($line, 'utf-8', $encoding);
  153. }
  154. if ($n == 0 || preg_match('/^".*"$/', $line)) {
  155. fwrite($fp, $line . "\n");
  156. } else {
  157. fwrite($fp, '"' . str_replace(['"', ','], ['""', '","'], $line) . "\"\n");
  158. }
  159. $n++;
  160. }
  161. fclose($file) || fclose($fp);
  162. $reader = new Csv();
  163. } elseif ($ext === 'xls') {
  164. $reader = new Xls();
  165. } else {
  166. $reader = new Xlsx();
  167. }
  168. //加载文件
  169. $insert = [];
  170. $data = []; // 导入的同一一级分类和二级分类和商品名称的数组
  171. $category_first_data = []; // 导入的分类数组
  172. $use_data = []; // 筛选后的领用数组
  173. $apply_goods_data = []; // 返回的数组
  174. $error_data = []; // 错误提示数组
  175. $flag = 2; // 默认批量导入
  176. try {
  177. if (!$PHPExcel = $reader->load($filePath)) {
  178. $this->error('未知的数据格式!');
  179. }
  180. $currentSheet = $PHPExcel->getSheet(0); //读取文件中的第一个工作表
  181. $allColumn = $currentSheet->getHighestDataColumn(); //取得最大的列号
  182. $allRow = $currentSheet->getHighestRow(); //取得一共有多少行
  183. $maxColumnNumber = Coordinate::columnIndexFromString($allColumn);
  184. if ($module == CommonConstant::MODULE_4) {
  185. $fields = ['goods_no', 'goods_category_first', 'goods_category_id', 'goods_name', 'goods_sku_value', 'stock'];
  186. } else {
  187. $fields = ['goods_no', 'goods_category_first', 'goods_category_id', 'goods_brand', 'goods_name', 'goods_sku_value', 'stock', 'price', 'total_price'];
  188. }
  189. for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) {
  190. $values = [];
  191. for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
  192. $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
  193. $values[] = is_null($val) ? '' : trim($val); // 消除空格
  194. }
  195. $values = array_filter($values); // 过滤空值
  196. $temp = array_combine($fields, $values); // 合并两个数组来创建一个新数组,其中的一个数组元素为键名,另一个数组元素为键值
  197. if ($temp) {
  198. $insert[] = $temp;
  199. if ($module == CommonConstant::MODULE_4) {
  200. $data[$values[1] . ',' . $values[2] . ',' . $values[3]][] = $temp;
  201. $category_first_data[$values[1]][$values[2]] = $values[2];
  202. } else {
  203. $data[$values[1] . ',' . $values[2] . ',' . $values[4]][] = $temp;
  204. }
  205. }
  206. }
  207. } catch (Exception $exception) {
  208. $this->error('出现错误:' . $exception->getMessage());
  209. }
  210. if (!$insert) {
  211. $this->error('记录未找到');
  212. }
  213. if ($module == CommonConstant::MODULE_4) {
  214. $category_first_list = GoodsCategoryService::get_list([['name', 'in', array_keys($category_first_data)]],1);
  215. $category_first_object = $category_first_list ? array_column($category_first_list->toArray(), null, 'name') : [];
  216. $msg = '导入的物品:';
  217. foreach ($data as $key => $value) {
  218. $arr = explode(',', $key);
  219. $goods_name = $arr[2];
  220. if(array_key_exists($arr[0],$category_first_object)){
  221. // 一级里有该商品分类
  222. $category_first_info = $category_first_object[$arr[0]];
  223. $goods_category_first_id = $category_first_info['id'];
  224. $category_second_object = $category_first_info['childlist'] ? array_column($category_first_info['childlist'], null, 'name') : [];
  225. if(array_key_exists($arr[1],$category_second_object)){
  226. // 二级里有该商品分类
  227. $category_second_info = $category_second_object[$arr[1]];
  228. $goods_category_id = $category_second_info['id'];
  229. $goods_info = Goods::field('status,is_deleted,create_at', true)
  230. ->where('goods_category_first', $goods_category_first_id)
  231. ->where('goods_category_id', $goods_category_id)
  232. ->where('goods_name', $goods_name)
  233. ->where('is_deleted', CommonConstant::IS_DELETED_0)
  234. ->with([
  235. 'goodsStock',
  236. ])
  237. ->find();
  238. if ($goods_info) {
  239. // 商品库里有该商品
  240. $goods_info = $goods_info->toArray();
  241. $goods_stock_object = array_column($goods_info['goods_stock'], null, 'name');
  242. foreach ($value as $kk=>$val) {
  243. if (array_key_exists($val['goods_sku_value'], $goods_stock_object)) {
  244. // 商品库里有该商品规格
  245. $goods_stock_info = $goods_stock_object[$val['goods_sku_value']];
  246. $total_stock = $goods_stock_info['stock']; // 商品库的库存
  247. $stock = isset($val['stock']) && $val['stock'] > 0 ? $val['stock'] : 0; // 要领用的数量
  248. $lack_stock = $stock - $total_stock;
  249. if($total_stock > 0){
  250. // 商品规格有库存
  251. $use_data[$key][] = $val;
  252. $use_data[$key][$kk]['goods_id'] = $goods_info['id'];
  253. $use_data[$key][$kk]['goods_category_first'] = $goods_category_first_id;
  254. $use_data[$key][$kk]['goods_category_id'] = $goods_category_id;
  255. $use_data[$key][$kk]['id'] = $goods_stock_info['id'];
  256. if($lack_stock > 0){
  257. // 商品规格库存不足
  258. $use_data[$key][$kk]['stock'] = $total_stock; // 替换库存
  259. $error_data[] = [
  260. 'msg' => $msg . $goods_name . '-' . $val['goods_sku_value'] . '库存不足,缺少' . $lack_stock . '件',
  261. ];
  262. }
  263. } else{
  264. $error_data[] = [
  265. 'msg' => $msg . $goods_name . '-' . $val['goods_sku_value'] . '库存不足,缺少' . $lack_stock . '件',
  266. ];
  267. }
  268. } else {
  269. // 商品库里没有该商品规格
  270. $error_data[] = [
  271. 'msg' => $msg . $goods_name . '-' . $val['goods_sku_value'] . '商品库不存在',
  272. ];
  273. }
  274. }
  275. } else {
  276. // 商品库里没有该商品
  277. $error_data[] = [
  278. 'msg' => $msg . $goods_name . '商品库不存在',
  279. ];
  280. }
  281. } else{
  282. // 二级里没有该商品分类
  283. $error_data[] = [
  284. 'msg' => $msg . $goods_name . '商品库不存在',
  285. ];
  286. }
  287. } else{
  288. // 一级里没有该商品分类
  289. $error_data[] = [
  290. 'msg' => $msg . $goods_name . '商品库不存在',
  291. ];
  292. }
  293. }
  294. $data = $use_data;
  295. $flag = 3; // 商品库选择
  296. }
  297. foreach ($data as $key => $value) {
  298. // 商品
  299. $goods_data = [];
  300. $goods_stock_data = [];
  301. $total_price = 0;
  302. foreach ($value as $kk => $val) {
  303. // 规格值
  304. $stock = isset($val['stock']) && $val['stock'] > 0 ? $val['stock'] : 0;
  305. $price = isset($val['price']) && $val['price'] > 0 ? $val['price'] : 0;
  306. $total_price = bcadd($total_price, $stock * $price, 2);
  307. $goods_stock_data[] = [
  308. 'id' => isset($val['id']) ? $val['id'] : 0,
  309. 'name' => $val['goods_sku_value'],
  310. 'stock' => $stock,
  311. 'price' => $price,
  312. ];
  313. $goods_data = [
  314. 'goods_id' => isset($val['goods_id']) ? $val['goods_id'] : 0,
  315. 'goods_category_first' => $val['goods_category_first'],
  316. 'goods_category_id' => $val['goods_category_id'],
  317. 'goods_no' => $val['goods_no'],
  318. 'goods_name' => $val['goods_name'],
  319. 'goods_brand' => isset($val['goods_brand']) ? $val['goods_brand'] : '',
  320. ];
  321. }
  322. $goods_data['flag'] = $flag;
  323. $goods_data['total_price'] = $total_price;
  324. $goods_data['goods_stock'] = $goods_stock_data;
  325. $apply_goods_data[] = $goods_data;
  326. }
  327. $data = compact("apply_goods_data", "error_data");
  328. $error_data ? $this->success('领用物品提示', $data) : $this->success('导入成功', $data);
  329. }
  330. /**
  331. * 导入1
  332. */
  333. public function import1()
  334. {
  335. $file = $this->request->post('file');
  336. if (!$file) {
  337. $this->error('请选择文件');
  338. }
  339. $filePath = $_SERVER['DOCUMENT_ROOT'] . '/' . $file;
  340. if (!is_file($filePath)) {
  341. $this->error('文件未找到');
  342. }
  343. //实例化reader
  344. $ext = pathinfo($filePath, PATHINFO_EXTENSION);
  345. if (!in_array($ext, ['csv', 'xls', 'xlsx'])) {
  346. $this->error('未知的数据格式');
  347. }
  348. if ($ext === 'csv') {
  349. $file = fopen($filePath, 'r');
  350. $filePath = tempnam(sys_get_temp_dir(), 'import_csv');
  351. $fp = fopen($filePath, 'w');
  352. $n = 0;
  353. while ($line = fgets($file)) {
  354. $line = rtrim($line, "\n\r\0");
  355. $encoding = mb_detect_encoding($line, ['utf-8', 'gbk', 'latin1', 'big5']);
  356. if ($encoding !== 'utf-8') {
  357. $line = mb_convert_encoding($line, 'utf-8', $encoding);
  358. }
  359. if ($n == 0 || preg_match('/^".*"$/', $line)) {
  360. fwrite($fp, $line . "\n");
  361. } else {
  362. fwrite($fp, '"' . str_replace(['"', ','], ['""', '","'], $line) . "\"\n");
  363. }
  364. $n++;
  365. }
  366. fclose($file) || fclose($fp);
  367. $reader = new Csv();
  368. } elseif ($ext === 'xls') {
  369. $reader = new Xls();
  370. } else {
  371. $reader = new Xlsx();
  372. }
  373. //加载文件
  374. $insert = [];
  375. try {
  376. if (!$PHPExcel = $reader->load($filePath)) {
  377. $this->error('未知的数据格式!');
  378. }
  379. $currentSheet = $PHPExcel->getSheet(0); //读取文件中的第一个工作表
  380. $allColumn = $currentSheet->getHighestDataColumn(); //取得最大的列号
  381. $allRow = $currentSheet->getHighestRow(); //取得一共有多少行
  382. $maxColumnNumber = Coordinate::columnIndexFromString($allColumn);
  383. for ($currentRow = 2; $currentRow <= $allRow; $currentRow++) {
  384. $values = [];
  385. for ($currentColumn = 1; $currentColumn <= $maxColumnNumber; $currentColumn++) {
  386. $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue();
  387. $values[] = is_null($val) ? '' : trim($val); // 消除空格
  388. }
  389. $values = array_filter($values); // 过滤空值
  390. $first[$values[0]] = $values[0];
  391. $second[$values[0]][$values[1]] = $values[1];
  392. $third[$values[1]][$values[2]] = $values[2];
  393. }
  394. } catch (Exception $exception) {
  395. $this->error('出现错误:' . $exception->getMessage());
  396. }
  397. // p($first);
  398. // p($second);
  399. // p($third);
  400. // exit;
  401. foreach ($first as $key=>$val){
  402. if(array_key_exists($val,$second)){
  403. $first1 = Db::table('dd_category_job')->insertGetId(['name'=>$val]);
  404. $second_list = $second[$val];
  405. foreach ($second_list as $v){
  406. if(array_key_exists($v,$third)){
  407. $second1 = Db::table('dd_category_job')->insertGetId(['pid'=>$first1,'name'=>$v]);
  408. $third_list = $third[$v];
  409. foreach ($third_list as $vv){
  410. Db::table('dd_category_job')->insertGetId(['pid'=>$second1,'name'=>$vv]);
  411. }
  412. }
  413. }
  414. }
  415. }
  416. $this->success('导入成功');
  417. }
  418. /**
  419. * 重置合同编号(定时任务 每年1月1日0点1分执行)
  420. *
  421. * @Apidoc\Method("POST")
  422. **/
  423. public function change_contract_no(){
  424. $data = date('md') == '0101' ? CommonService::change_contract_no() : [];
  425. $this->success('重置合同编号成功',$data);
  426. }
  427. /**
  428. * 测试
  429. *
  430. * @Apidoc\Method("POST")
  431. * @Apidoc\Param("id", type="integer",require=true, desc="ID")
  432. */
  433. public function test()
  434. {
  435. $id = input('id') ?: 0;
  436. $data = '';
  437. $name = '';
  438. $html = ApproveInfoService::get_html($data);
  439. $realpath = ApproveInfoService::getPath($name);
  440. $pdf = new \TCPDF();
  441. $pdf = ApproveInfoService::setPdfAttr($pdf);
  442. ApproveInfoService::exportPdf($pdf, $html, $realpath);
  443. $this->success('success',['url' => $realpath, 'fullurl' => 'https://' . $_SERVER['HTTP_HOST'] . $realpath]);
  444. }
  445. }