QcodeAdd.php 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. <?php
  2. namespace app\admin\controller;
  3. use app\admin\model\QcodeCompany;
  4. use app\admin\model\QcodeGsmc;
  5. use app\admin\model\QcodeProduct;
  6. use app\common\controller\Backend;
  7. use app\admin\model\ResetFlow;
  8. use app\admin\model\QcodeLarge;
  9. use app\admin\model\QcodeBach;
  10. use app\admin\model\QcodeSmall;
  11. use app\admin\model\QcodeLiushui;
  12. use fast\Arr;
  13. use think\Db;
  14. use think\Session;
  15. class QcodeAdd extends Backend{
  16. /**
  17. * 首页展示
  18. */
  19. public function index(){
  20. //获取登录账号信息【厂商信息】
  21. $userinfo = Session::get('admin');
  22. $data = [
  23. 'nickname' => $userinfo['company_name'],
  24. 'postcode' => $userinfo['postcode'],
  25. 'mobile' => $userinfo['mobile'],
  26. 'printer_code' => $userinfo['printer_code'],
  27. 'company_address' => $userinfo['company_address']
  28. ];
  29. $this->view->assign('row',$data);
  30. //将对此账号创建公司唯一id,进行创建公司对应公司表名company id
  31. $user_company_value = Db::name('admin')->where('id', $userinfo['id'])->value('company');
  32. if (empty($user_company_value)) {
  33. $max_company = Db::name('admin')->max('company');
  34. $new_company_value = $max_company ? ($max_company + 1) : 1;
  35. Db::name('admin')->where('id', $userinfo['id'])->update(['company' => $new_company_value]);
  36. } else {
  37. $new_company_value = $user_company_value;
  38. }
  39. $tableNames = [
  40. $new_company_value . '_qcode_bach',
  41. $new_company_value . '_qcode_company',
  42. $new_company_value . '_qcode_large',
  43. $new_company_value . '_qcode_liushui',
  44. $new_company_value . '_qcode_small',
  45. $new_company_value . '_reset_flow',
  46. ];
  47. foreach ($tableNames as $tableName) {
  48. try {
  49. Db::connect('mongodb')->name($tableName)->insert(['init' => 1]);
  50. // 删除测试数据(可选,如果不想保留这个测试数据)
  51. Db::connect('mongodb')->name($tableName)->where('init', 1)->delete();
  52. } catch (\Exception $e) {
  53. echo "创建集合 {$tableName} 失败:" . $e->getMessage();
  54. }
  55. }
  56. return $this->view->fetch();
  57. }
  58. /**
  59. * 获取产品信息
  60. */
  61. public function product(){
  62. $params = input('');
  63. $page = max(1, (int)$params['page']);
  64. $limit = max(1, (int)$params['limit']);
  65. $offset = ($page - 1) * $limit;
  66. // 获取工单编号列表
  67. $db3 = Db::connect(config('database.db3'));
  68. $gdRows = $db3->query("SELECT DISTINCT `Gd_gdbh`, `Gd_客户代号`, `Gd_cpdh` FROM `工单_基本资料` WHERE `Gd_客户代号` = ?", ['J0031']);
  69. $Gd_gdbhList = array_column($gdRows, 'Gd_gdbh');
  70. $gdbhList = array_column($gdRows, 'Gd_cpdh');
  71. if (empty($gdbhList)) {
  72. $this->assign([
  73. 'data' => '',
  74. 'total' =>'',
  75. ]);
  76. }
  77. // Mongo 查询
  78. $mongo = \think\Db::connect('mongodb');
  79. $where = ['jjcp_cpdh' => ['in', $gdbhList],'jjcp_gdbh' => ['in', $Gd_gdbhList], 'jjcp_smb' => '末 板'];
  80. if (!empty($params['search'])) {
  81. $where['成品编码|成品名称|jjcp_gdbh|订单编号'] = new \MongoDB\BSON\Regex($params['search'], 'i');
  82. }
  83. // 1. 查询所有符合条件的成品数据(不分页)
  84. $all_products = $mongo->name('finished_products')
  85. ->where($where)
  86. ->order('UniqId', 'desc')
  87. ->select();
  88. // 2. 按订单编号 + 工单编号分组聚合,并处理多个cpdh与成品编码
  89. $grouped_products = [];
  90. foreach ($all_products as $item) {
  91. $group_key = $item['订单编号'] . '_' . $item['jjcp_gdbh'];
  92. if (!isset($grouped_products[$group_key])) {
  93. $grouped_products[$group_key] = [
  94. 'order_ddbh' => $item['订单编号'],
  95. 'gdbh' => $item['jjcp_gdbh'],
  96. 'cpbm' => $item['成品编码'],
  97. 'cpmc' => $item['成品名称'],
  98. 'sl' => 0, // 库存总数
  99. 'cpdh_list' => [],
  100. 'cpbm_list' => []
  101. ];
  102. }
  103. $grouped_products[$group_key]['sl'] += (int)$item['jjcp_sl']; // 累计库存数量
  104. // 收集不同的cpdh和cpbm(成品编码)
  105. if (!in_array($item['jjcp_cpdh'], $grouped_products[$group_key]['cpdh_list'])) {
  106. $grouped_products[$group_key]['cpdh_list'][] = $item['jjcp_cpdh'];
  107. }
  108. if (!in_array($item['成品编码'], $grouped_products[$group_key]['cpbm_list'])) {
  109. $grouped_products[$group_key]['cpbm_list'][] = $item['成品编码'];
  110. }
  111. }
  112. // 格式化成用逗号连接的字符串
  113. foreach ($grouped_products as &$group) {
  114. $group['cpdh'] = implode(',', $group['cpdh_list']);
  115. $group['cpbm'] = implode(',', $group['cpbm_list']);
  116. unset($group['cpdh_list'], $group['cpbm_list']); // 清理临时字段
  117. }
  118. // 3. 将聚合后结果分页(稳定分页)
  119. $all_grouped = array_values($grouped_products);
  120. $total = count($all_grouped);
  121. $paged_grouped = array_slice($all_grouped, $offset, $limit);
  122. // 4. 获取库存出货数据并计算剩余数
  123. foreach ($paged_grouped as &$prod) {
  124. $inventory = $mongo->name('inventory_summary')->where([
  125. 'order_ddbh' => $prod['order_ddbh'],
  126. 'gdbh' => $prod['gdbh'],
  127. 'cpmc' => $prod['cpmc'],
  128. ])->find();
  129. // 出货数量(若无数据则为 0)
  130. $total_chu_quantity = isset($inventory['total_chu_quantity']) ? (int)$inventory['total_chu_quantity'] : 0;
  131. $prod['total_chu_quantity'] = $total_chu_quantity;
  132. // 计算剩余数 = sl - 出货数
  133. $prod['remaining_quantity'] = $prod['sl'] - $total_chu_quantity;
  134. }
  135. unset($prod);
  136. return json([
  137. 'code' => 1,
  138. 'data' => $paged_grouped,
  139. 'total' => $total,
  140. 'page' => $page,
  141. 'limit' => $limit
  142. ]);
  143. }
  144. /**
  145. * 增加新批次
  146. */
  147. public function add()
  148. {
  149. $product = new QcodeProduct();
  150. $bach = new QcodeBach();
  151. $large = new QcodeLarge();
  152. $small = new QcodeSmall();
  153. $liushui = new QcodeLiushui();
  154. $resetFlow = new ResetFlow();
  155. $QcodeCompany = new QcodeCompany();
  156. if ($this->request->isAjax() === false){
  157. $this->error('请求错误');
  158. }
  159. $rows = input('row');
  160. if (empty($rows)){
  161. $this->error('参数错误');
  162. }
  163. $rows = json_decode($rows);
  164. $data = [];
  165. foreach ($rows as $value){
  166. foreach ($value as $k=>$v){
  167. $data[$k] = $v;
  168. }
  169. }
  170. //打印信息
  171. // echo "接口获取";echo "<pre>";print_r($data);echo "<pre>";die;
  172. //记录库存操作
  173. $mongo = \think\Db::connect('mongodb');
  174. $where = [
  175. 'gdbh' => $data['gdbh'],
  176. 'order_ddbh' => $data['order_ddbh'],
  177. 'cpmc' => $data['cpmc'],
  178. ];
  179. //插入字段[inventory_summaryk库存明细]
  180. $insertData = [
  181. 'gdbh' => $data['gdbh'],
  182. 'order_ddbh' => $data['order_ddbh'],
  183. 'cpbm' => $data['cpbm'],
  184. 'cpmc' => $data['cpmc'],
  185. 'total_ru_quantity' => $data['sl'],//入库数
  186. 'total_chu_quantity' => $data['number'],//出库数
  187. 'remaining_quantity' => $data['remaining_quantity'] - $data['number'],//剩余数
  188. 'created_at' => date('Y-m-d H:i:s'),
  189. 'updated_at' => '',
  190. 'mod_rq' => '',
  191. 'company' => '',
  192. ];
  193. // 查询库存汇总表数据是否存在记录
  194. $list = $mongo->name('inventory_summary')->where($where)->find();
  195. if ($list) {
  196. // 如果数据存在,更新库存汇总记录
  197. $chu = $list['total_chu_quantity'] + $data['number'];//累计出库数量
  198. $jiecun = $list['remaining_quantity'] - $data['number'];//剩余结存数量
  199. $updateResult = $mongo->name('inventory_summary')
  200. ->where($where)
  201. ->update([
  202. 'total_ru_quantity' => $data['sl'],
  203. 'total_chu_quantity' => $chu,
  204. 'remaining_quantity' => $jiecun,
  205. 'updated_at' => date('Y-m-d H:i:s'),
  206. ]);
  207. } else {
  208. // 数据不存在则插入新记录
  209. $mongo->name('inventory_summary')->insert($insertData);
  210. }
  211. //记录库存明细
  212. $mongo->name('inventory_records')->insert($insertData);
  213. // // 调试输出
  214. // echo "<pre>"; print_r($list); echo "</pre>";die;
  215. // if ($data['danwei'] == 1){
  216. // $num = $data['number'];
  217. // $tray_num = $data['tray_num'];
  218. // $box_number = $data['box_number'];
  219. // //$small_num = (int)ceil((int)总数量(张/个)/(int)张数);
  220. // $small_num = (int)ceil((int)$data['number']/(int)$data['box_number']);
  221. // $large_num = (int)ceil($small_num/$tray_num);
  222. // }else{
  223. // $num = 0;
  224. // $tray_num = $data['volume_num'];
  225. // $small_num = $data['small_num'];
  226. // $large_num = (int)ceil($small_num/$tray_num);
  227. // $box_number = 1;
  228. // $tray_num1 = 1;
  229. // }
  230. switch ($data['danwei']) {
  231. case 1:
  232. $danwei = '个';
  233. break;
  234. case 2:
  235. $danwei = '套';
  236. break;
  237. case 3:
  238. $danwei = '张';
  239. break;
  240. default:
  241. $danwei = '';
  242. break;
  243. }
  244. $userinfo = Session::get('admin');//获取用户信息
  245. $arr = [
  246. 'batch' => $data['gdbh'],
  247. 'create_time' => time(),
  248. 'delect_time' => '',
  249. 'sync_flag' => 0,
  250. ];
  251. $productres = $QcodeCompany->save($arr);
  252. if ($productres === 0){
  253. $this->error('添加失败');
  254. }
  255. $batchList = [
  256. 'userid' => $userinfo['id'],//登录用户id
  257. 'supplier_id' => $userinfo['id'],//登录用户id
  258. 'supplier_code' => $userinfo['printer_code'],
  259. 'supplier_name' => $data['company_name'],//公司名称
  260. 'cpbm' => $data['cpbm'],//成品编码
  261. 'matter_name' => $data['cpmc'],//成品名称
  262. 'matter_no' => $data['gdbh'],//生产批次号-工单编号
  263. 'order_ddbh' => $data['order_ddbh'],//销售订单号
  264. 'matter_id' => $data['gdbh'],
  265. 'matter_type' => '01',
  266. 'manufacture_date' => (int)date('ymd',strtotime($data['manufacture_date'])),//生产日期
  267. 'print_date' => (int)date('ymd',strtotime($data['print_date'])),//打码日期
  268. 'num_danwei' => $data['danwei'],//单位
  269. 'danwei' => $danwei,//单位
  270. 'num' => $data['number'],//总数量(张/个)
  271. 'small_num' => $data['box_number'],//每一箱数量
  272. 'tray_num' => $data['tray_num'],//每层箱数【箱/层】
  273. 'box_num' => $data['tray_number'],//每托层数【 层/托】
  274. 'total_boxes' => $data['total_boxes'],//每托盘箱数【箱/托】
  275. 'large_num' => $data['box_num'],//本次打包托盘数
  276. 'larger_num' => $data['small_num'],//总箱数
  277. 'pallet_height' => $data['pallet_height'],//每托高度
  278. 'pallet_length' => $data['pallet_length'],//托盘规格
  279. 'pallet_width' => $data['pallet_width'],//托盘规格
  280. 'l_reservation' => '',
  281. // 处理可能为空的流水/重量字段
  282. 'l_flow' => $data['big_liushui'],//大件流水
  283. 'l_weight' => $data['big_weight'],//大件重量
  284. 's_flow' => $data['small_start_liushui'],//小件流水
  285. 's_weight' => $data['small_weight'],//小件重量
  286. 's_reservation' => '',
  287. 'bach_status' => 0,
  288. 'bach_num' => $data['gdbh'],//生产批次号-工单编号
  289. 'large_endnum' => $data['big_liushui'] + $data['box_num'] -1,
  290. 'create_time' => time(),//新增时间
  291. 'delect_time' => '',//删除时间
  292. ];
  293. $res = $bach->save($batchList);
  294. if ($res === 0){
  295. $this->error('添加失败');
  296. }
  297. $flow = [
  298. 'l_flow' => (int)$batchList['large_num'],
  299. 'bach_num' => $batchList['matter_no'],
  300. ];
  301. if ($resetFlow->name($userinfo['company'].'_'."reset_flow")->where('product_id',$batchList['matter_no'])->find()){
  302. $resetFlow->name($userinfo['company'].'_'."reset_flow")->where('product_id',$batchList['matter_no'])->update($flow);
  303. }else{
  304. $flow['product_id'] = $batchList['matter_no'];
  305. $resetFlow->save($flow);
  306. }
  307. $last_id = $bach->getLastInsID();
  308. if ($last_id){
  309. //插入大小二维码数据 二维码数据不变区域
  310. // echo "<pre>";print_r($batchList);echo "<pre>";die;
  311. $fixed_code = '';
  312. $fixed_code.=$this->intTochar($batchList['matter_type'],2);//2位 辅料种类编码
  313. $fixed_code .= $this->intTochar($batchList['supplier_code'], 21);//21位 供应商编码
  314. $fixed_code .= '9'; // 补0一位
  315. $fixed_code.=$this->intTochar($batchList['cpbm'],10);//10位 辅料编码
  316. $fixed_code.=$batchList['manufacture_date'];//6位 生产日期
  317. $print_code=$batchList['print_date'];//6位 打码日期
  318. $small_liushui = [
  319. 'onlycode' => 'AB92'.$fixed_code.$print_code,
  320. 'last_num' => 0,
  321. 'user_id' => $userinfo['company'],
  322. 'stype' => 2,
  323. 'dateTime' => time(),
  324. ];
  325. $whereSmall = [
  326. 'onlycode' => $small_liushui['onlycode'],
  327. 'user_id' => $userinfo['company'],
  328. ];
  329. if ($liushui->name($userinfo['company'].'_'.'qcode_liushui')->where($whereSmall)->find()){
  330. //小件二维码存在,更新小件二维码最后流水号
  331. $lastNum = $liushui->name($userinfo['company'].'_'.'qcode_liushui')->where($whereSmall)->find();
  332. }else{
  333. //小件二维码不存在,新增记录
  334. $liushui->save($small_liushui);
  335. $lastNum['last_num'] = 0;
  336. }
  337. //循环插入大件二维码数据
  338. for ($i=0;$i<$data['box_num'];$i++){
  339. $large = new QcodeLarge();
  340. $l_flow = $this->intTochar($batchList['l_flow']+$i,6);
  341. $l_weight = $this->intTochar($batchList['l_weight']*100,6);
  342. $l_reservation = $this->intTochar($batchList['matter_no'],10);
  343. $l_reservation = $l_reservation.'0000000000';
  344. $remainder = $batchList['num'] - $batchList['total_boxes'] * $i;//最后一托盘小件数量
  345. if ($remainder < $batchList['tray_num']){
  346. $small_n = $this->intTochar($remainder,3);//3位小件数量,不足补0
  347. }else{
  348. $small_n = $this->intTochar($batchList['tray_num'],3);
  349. }
  350. // $l_num = $small_n * $batchList['box_num'];
  351. $l_num = 0;
  352. //大件二维码数据
  353. $code_data = $this->CodeData('AB92',$fixed_code,$small_n,$print_code,$l_flow,$l_weight,'2',$l_reservation);
  354. //大码数据信息
  355. $l_data = [
  356. 'bach_id' => $last_id,
  357. 'code' => $code_data['code'],
  358. 'code_cp1' => $code_data['code_cp1'],
  359. 'code_cp2' => $code_data['code_cp2'],
  360. 'print_date' => $print_code,
  361. 'create_time' => time(),
  362. 'p_nums' => 0,
  363. 'userid' =>$userinfo['id'],
  364. 'l_weight' =>$batchList['l_weight']*100,
  365. 'l_num' =>$l_num,
  366. 'l_status' => 0,
  367. 'l_print' => 0
  368. ];
  369. $l_res = $large->save($l_data);
  370. if ($l_res === 0){
  371. $this->error('大件码插入失败');
  372. }
  373. $large_id = $large->getLastInsID();
  374. if ($large_id){
  375. // //小件码循环插入
  376. for ($j=0;$j<$data['tray_num'] and ($j+$i*$data['tray_num'])<$batchList['small_num'];$j++){
  377. $small = new QcodeSmall();
  378. $s_flow = $this->intTochar($batchList['s_flow']+$j+$i*$data['tray_num']+$lastNum['last_num'],6);//小件码序号从1开始
  379. $s_weight = $this->intTochar($batchList['s_weight'],6);
  380. $small_sign = '000';
  381. $s_reservation = $this->intTochar($batchList['bach_num'],10);
  382. $s_reservation = $s_reservation . '0000000000';
  383. //生成小件码
  384. $small_code_data = $this->CodeData('AB92',$fixed_code,$small_sign,$print_code,$s_flow,$s_weight,'1',$s_reservation);
  385. //小码数据
  386. $s_data = [
  387. 'large_id'=>$large_id,
  388. 'bach_id'=>$last_id,
  389. 'code'=>$small_code_data['code'],
  390. 'code_cp1'=>$small_code_data['code_cp1'],
  391. 'code_cp2'=>$small_code_data['code_cp2'],
  392. 'l_flow'=>$j+1,
  393. 'print_date'=>$print_code,
  394. 'create_time'=>time(),
  395. 'p_nums'=>0,
  396. 'userid'=>$userinfo['id'],//小码绑定用户id
  397. 's_weight'=>$batchList['s_weight'],//单个小件重量
  398. 'status' => 0,
  399. ];
  400. $s_res = $small->save($s_data);
  401. if ($s_res === 0){
  402. $this->error('小件码插入失败');
  403. }
  404. }
  405. }else{
  406. $this->error('添加失败');
  407. }
  408. }
  409. }
  410. $liushui_res = $liushui->name($userinfo['id'].'_'.'qcode_liushui')->where($whereSmall)->update(['last_num'=>$batchList['small_num']]);
  411. if ($liushui_res === false){
  412. $this->error('添加失败');
  413. }
  414. return json(['code' => 1, 'msg' => '成功', 'data' => '']);
  415. // $this->success('成功');
  416. }
  417. /**
  418. * 编码补位
  419. * @param $num
  420. * @param $len
  421. * @return string
  422. */
  423. function intTochar($num=0,$len){
  424. //规定的不足的时候自动补足零
  425. $code=(string)$num;
  426. $buwei='';
  427. if(strlen($code)<$len){
  428. for($i=strlen($code);$i<$len;$i++){
  429. $buwei.='0';
  430. }
  431. }
  432. return $buwei.$code;
  433. }
  434. /**
  435. * 二维码编码生成
  436. * @param $sign
  437. * @param $fixed_code
  438. * @param $small_num
  439. * @param $print_date
  440. * @param $flow
  441. * @param $weight
  442. * @param $large_sign
  443. * @param $reservation
  444. * @return array
  445. */
  446. function CodeData($sign,$fixed_code,$small_num,$print_date,$flow,$weight,$large_sign,$reservation){
  447. $code=$sign;//4 位固定标志位
  448. $code.=$fixed_code; // 固定字符串
  449. $code.=$small_num;//3位 小件数量
  450. $code.=$print_date;//6 位 日期
  451. $code.=$flow;//6位打印流水号
  452. $code.=$weight;//6位辅料重量
  453. $code.=$large_sign;//大小件标示位
  454. $code.=$reservation;//20 位 预留号
  455. //大码数据信息
  456. $data=[
  457. 'code'=>str_replace(" ","",$code),
  458. 'code_cp1'=>$print_date.$flow,
  459. 'code_cp2'=>$weight.$reservation,//20位补充
  460. 'print_date'=>time(),
  461. 'p_nums'=>0,
  462. ];
  463. return $data;
  464. }
  465. }