Common.php 16 KB

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