QcodeAdd.php 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789
  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 MongoDB\BSON\ObjectId;
  14. use think\Db;
  15. use think\Session;
  16. class QcodeAdd extends Backend{
  17. /**
  18. * 首页展示
  19. */
  20. public function index(){
  21. //获取登录账号信息【厂商信息】
  22. $userinfo = Session::get('admin');
  23. $data = [
  24. 'nickname' => $userinfo['company_name'],
  25. 'postcode' => $userinfo['postcode'],
  26. 'mobile' => $userinfo['mobile'],
  27. 'printer_code' => $userinfo['printer_code'],
  28. 'company_address' => $userinfo['company_address']
  29. ];
  30. $this->view->assign('row',$data);
  31. //将对此账号创建公司唯一id,进行创建公司对应公司表名company id
  32. $user_company_value = Db::name('admin')->where('id', $userinfo['id'])->value('company');
  33. if (empty($user_company_value)) {
  34. $max_company = Db::name('admin')->max('company');
  35. $new_company_value = $max_company ? ($max_company + 1) : 1;
  36. Db::name('admin')->where('id', $userinfo['id'])->update(['company' => $new_company_value]);
  37. } else {
  38. $new_company_value = $user_company_value;
  39. }
  40. $tableNames = [
  41. $new_company_value . '_qcode_bach',
  42. $new_company_value . '_qcode_company',
  43. $new_company_value . '_qcode_large',
  44. $new_company_value . '_qcode_liushui',
  45. $new_company_value . '_qcode_small',
  46. $new_company_value . '_reset_flow',
  47. ];
  48. foreach ($tableNames as $tableName) {
  49. try {
  50. Db::connect('mongodb')->name($tableName)->insert(['init' => 1]);
  51. // 删除测试数据(可选,如果不想保留这个测试数据)
  52. Db::connect('mongodb')->name($tableName)->where('init', 1)->delete();
  53. } catch (\Exception $e) {
  54. echo "创建集合 {$tableName} 失败:" . $e->getMessage();
  55. }
  56. }
  57. return $this->view->fetch();
  58. }
  59. /**
  60. * 获取产品信息
  61. */
  62. public function product(){
  63. $params = input('');
  64. $page = max(1, (int)$params['page']);
  65. $limit = max(1, (int)$params['limit']);
  66. $offset = ($page - 1) * $limit;
  67. // 获取工单编号列表
  68. $db3 = Db::connect(config('database.db3'));
  69. $gdRows = $db3->query("SELECT DISTINCT `Gd_gdbh`, `Gd_客户代号`, `Gd_cpdh` FROM `工单_基本资料` WHERE `Gd_客户代号` = ?", ['J0031']);
  70. $Gd_gdbhList = array_column($gdRows, 'Gd_gdbh');
  71. $gdbhList = array_column($gdRows, 'Gd_cpdh');
  72. if (empty($gdbhList)) {
  73. $this->assign([
  74. 'data' => '',
  75. 'total' => '',
  76. ]);
  77. }
  78. // Mongo 查询
  79. $mongo = \think\Db::connect('mongodb');
  80. $where = ['成品编码' => ['in', $gdbhList],'jjcp_gdbh' => ['in', $Gd_gdbhList], 'jjcp_smb' => '末 板'];
  81. // $where = ['成品编码' => ['in', $gdbhList], 'jjcp_smb' => '末 板'];
  82. if (!empty($params['search'])) {
  83. $where['成品编码|成品名称|jjcp_gdbh|订单编号'] = new \MongoDB\BSON\Regex($params['search'], 'i');
  84. }
  85. // 查询符合条件的成品数据
  86. $al_products = $mongo->name('finished_products')
  87. ->where($where)
  88. ->order('Sys_rq', 'desc')
  89. ->select();
  90. // 查询 texts = 新增产品 的数据
  91. $xz_products = $mongo->name('finished_products')
  92. ->where('texts', '新增产品')
  93. ->order('Sys_rq', 'desc')
  94. ->select();
  95. // 合并数据
  96. $all_products = array_merge($al_products, $xz_products);
  97. // 分组聚合处理
  98. $grouped_products = [];
  99. foreach ($all_products as $item) {
  100. // 转换日期格式(如果是 d/m/Y H:i:s)
  101. $date = \DateTime::createFromFormat('d/m/Y H:i:s', $item['Sys_rq']);
  102. $item['Sys_rq'] = $date ? $date->format('Y-m-d H:i:s') : $item['Sys_rq'];
  103. $group_key = $item['订单编号'] . '_' . $item['jjcp_gdbh'];
  104. if (!isset($grouped_products[$group_key])) {
  105. $grouped_products[$group_key] = [
  106. 'Sys_rq' => $item['Sys_rq'],
  107. 'order_ddbh' => $item['订单编号'],
  108. 'gdbh' => $item['jjcp_gdbh'],
  109. 'cpbm' => $item['成品编码'],
  110. 'cpmc' => $item['成品名称'],
  111. 'sl' => 0,
  112. 'cpdh_list' => [],
  113. 'cpbm_list' => []
  114. ];
  115. }
  116. $grouped_products[$group_key]['sl'] += (int)$item['jjcp_sl'];
  117. if (!in_array($item['jjcp_cpdh'], $grouped_products[$group_key]['cpdh_list'])) {
  118. $grouped_products[$group_key]['cpdh_list'][] = $item['jjcp_cpdh'];
  119. }
  120. if (!in_array($item['成品编码'], $grouped_products[$group_key]['cpbm_list'])) {
  121. $grouped_products[$group_key]['cpbm_list'][] = $item['成品编码'];
  122. }
  123. }
  124. // 格式化列表字符串
  125. foreach ($grouped_products as &$group) {
  126. $group['cpdh'] = implode(',', $group['cpdh_list']);
  127. $group['cpbm'] = implode(',', $group['cpbm_list']);
  128. unset($group['cpdh_list'], $group['cpbm_list']);
  129. }
  130. // 聚合结果排序(按时间降序)
  131. $all_grouped = array_values($grouped_products);
  132. usort($all_grouped, function ($a, $b) {
  133. $timeA = strtotime($a['Sys_rq']) ?: 0;
  134. $timeB = strtotime($b['Sys_rq']) ?: 0;
  135. return $timeB <=> $timeA;
  136. });
  137. // 再分页
  138. $total = count($all_grouped);
  139. $paged_grouped = array_slice($all_grouped, $offset, $limit);
  140. // 查询库存并计算剩余数
  141. foreach ($paged_grouped as &$prod) {
  142. $inventory = $mongo->name('inventory_summary')->where([
  143. 'order_ddbh' => $prod['order_ddbh'],
  144. 'gdbh' => $prod['gdbh'],
  145. 'cpmc' => $prod['cpmc'],
  146. ])->find();
  147. $total_chu_quantity = isset($inventory['total_chu_quantity']) ? (int)$inventory['total_chu_quantity'] : 0;
  148. $prod['total_chu_quantity'] = $total_chu_quantity;
  149. $prod['remaining_quantity'] = $prod['sl'] - $total_chu_quantity;
  150. }
  151. unset($prod);
  152. return json([
  153. 'code' => 1,
  154. 'data' => $paged_grouped,
  155. 'total' => $total,
  156. 'page' => $page,
  157. 'limit' => $limit
  158. ]);
  159. }
  160. // public function add_bach()
  161. // {
  162. // // 1. AJAX请求验证
  163. // if (!$this->request->isAjax()) {
  164. // $this->error('请求必须为AJAX');
  165. // }
  166. //
  167. // // 2. 获取并解析输入数据
  168. // $data = input('row');
  169. // if (empty($data)) {
  170. // $this->error('请求参数不能为空');
  171. // }
  172. //
  173. // $data = json_decode($data, true);
  174. // if (json_last_error() !== JSON_ERROR_NONE) {
  175. // $this->error('JSON数据解析失败');
  176. // }
  177. //
  178. // if (empty($data['products'])) {
  179. // $this->error('产品数据不能为空');
  180. // }
  181. //
  182. // // 3. 用户会话验证
  183. // $userinfo = Session::get('admin');
  184. // if (empty($userinfo) || !isset($userinfo['company'])) {
  185. // $this->error('获取用户信息失败,请重新登录');
  186. // }
  187. //
  188. // // 4. MongoDB连接配置
  189. // $mongo = \think\Db::connect('mongodb');
  190. // $collection = $userinfo['company'] . '_qcode_bach'; // 主表
  191. // $bachdetails = $userinfo['company'] . '_qcode_bachdetails'; // 托盘明细表
  192. // $bachsummary = $userinfo['company'] . '_qcode_bachsummary'; // 批次汇总表
  193. //
  194. // // 5. 生成批次信息
  195. // $currentDate = date('Y-m-d');
  196. // $currentDateTime = date('Y-m-d H:i:s');
  197. // $timestamp = time();
  198. // $bachNum = 'BACH' . date('YmdHis') . mt_rand(1000, 9999); // 批次号规则
  199. //
  200. // // 6. 托盘默认配置
  201. // $config = [
  202. // 'tray_num' => 6, // 每层6箱
  203. // 'pallet_length' => '0.9', // 托盘长度(米)
  204. // 'pallet_width' => '1.2', // 托盘宽度(米)
  205. // 'default_layer_height' => '1.35' // 默认层高(米)
  206. // ];
  207. //
  208. // // 7. 初始化统计容器
  209. // $batchStats = [
  210. // 'total_quantity' => 0, // 总产品数量
  211. // 'total_boxes' => 0, // 总箱数
  212. // 'total_pallets' => 0, // 总托盘数
  213. // 'full_pallets' => 0, // 完整托盘数
  214. // 'partial_pallets' => 0, // 不完整托盘数
  215. // 'product_varieties' => count($data['products']) // 产品种类数
  216. // ];
  217. //
  218. // // 8. 处理每个产品 - 分为两个阶段
  219. // $productDetails = []; // 产品主表数据
  220. // $palletDetails = []; // 托盘明细数据
  221. // $currentPalletNo = 1; // 托盘编号计数器
  222. //
  223. // // 第一阶段:先处理所有完整托盘
  224. // foreach ($data['products'] as $product) {
  225. // // 8.1 计算托盘配置
  226. // $tray_count = $product['tray_count'] ?? 18; // 默认18箱/托盘
  227. // $box_num = $tray_count == 24 ? 4 : 3; // 24箱时为4层,否则3层
  228. // $small_num = $product['items_per_box'] ?? 20; // 每箱数量,默认20
  229. //
  230. // // 8.2 处理实际数量
  231. // $remaining = (int)$product['remaining_quantity'];
  232. // $actual = isset($product['actual_quantity']) ?
  233. // min((int)$product['actual_quantity'], $remaining) : $remaining;
  234. //
  235. // // 8.3 计算托盘分配
  236. // $boxes_per_pallet = $config['tray_num'] * $box_num; // 每托盘总箱数
  237. // $total_boxes = ceil($actual / $small_num); // 总箱数
  238. // $full_pallets = floor($total_boxes / $boxes_per_pallet); // 完整托盘数
  239. // $remaining_boxes = $total_boxes % $boxes_per_pallet; // 剩余箱数
  240. //
  241. // // 8.4 构建产品基础信息
  242. // $baseInfo = [
  243. // 'bach_ids' => $bachNum, // 批次号
  244. // 'userid' => $userinfo['id'], // 操作人ID
  245. // 'gdbh' => $product['gdbh'], // 工单编号
  246. // 'order_ddbh' => $product['order_ddbh'], // 订单编号
  247. // 'cpbm' => $product['cpbm'], // 产品编码
  248. // 'cpmc' => $product['cpmc'], // 产品名称
  249. // 'matter_name' => $product['cpmc'], // 物料名称
  250. // 'remark' => $product['remark'] ?? '', // 备注
  251. // 'small_num' => $small_num, // 每箱数量
  252. // 'unit' => $product['unit'] ?? '套', // 单位
  253. // 'tray_num' => $config['tray_num'], // 每层箱数
  254. // 'box_num' => $box_num, // 层数
  255. // 'tray_count' => $tray_count, // 总箱数/托盘
  256. // 'layer_height' => $product['layer_height'] ?? $config['default_layer_height'], // 层高
  257. // 'pallet_length' => $config['pallet_length'], // 托盘长度
  258. // 'pallet_width' => $config['pallet_width'], // 托盘宽度
  259. // 'bach_status' => 0, // 状态(0:未处理)
  260. // 'sys_rq' => $currentDate, // 系统日期
  261. // 'created_at' => $currentDateTime, // 创建时间
  262. // 'create_time' => $timestamp, // 时间戳
  263. // 'delete_time' => '' // 删除时间
  264. // ];
  265. //
  266. // // 只处理完整托盘部分
  267. // if ($full_pallets > 0) {
  268. // $full_qty = $full_pallets * $boxes_per_pallet * $small_num;
  269. // $endNo = $currentPalletNo + $full_pallets - 1;
  270. //
  271. // $productDetails[] = array_merge($baseInfo, [
  272. // 'actual_quantity' => $full_qty,
  273. // 'total_boxes' => $full_pallets * $boxes_per_pallet,
  274. // 'pallet_count' => $full_pallets,
  275. // 'pallet_type' => 'full',
  276. // 'pallet_range' => "$currentPalletNo-$endNo",
  277. // 'start_pallet_no' => $currentPalletNo,
  278. // 'end_pallet_no' => $endNo
  279. // ]);
  280. //
  281. // // 生成托盘明细
  282. // for ($i = 0; $i < $full_pallets; $i++) {
  283. // $palletDetails[] = [
  284. // 'bach_ids' => $bachNum,
  285. // 'product_id' => $product['gdbh'],
  286. // 'pallet_no' => $currentPalletNo + $i,
  287. // 'pallet_no_display' => $currentPalletNo + $i,
  288. // 'pallet_type' => 'full',
  289. // 'quantity' => $boxes_per_pallet * $small_num,
  290. // 'box_count' => $boxes_per_pallet,
  291. // 'layer_count' => $box_num,
  292. // 'bach_status' => 0,
  293. // 'created_at' => $currentDateTime,
  294. // 'delete_time' => ''
  295. // ];
  296. // }
  297. //
  298. // $batchStats['full_pallets'] += $full_pallets;
  299. // $batchStats['total_quantity'] += $full_qty;
  300. // $batchStats['total_boxes'] += $full_pallets * $boxes_per_pallet;
  301. // $currentPalletNo += $full_pallets;
  302. // $batchStats['total_pallets'] += $full_pallets;
  303. // }
  304. // }
  305. //
  306. // // 第二阶段:再处理所有不完整托盘
  307. // foreach ($data['products'] as $product) {
  308. // //每托箱数
  309. // $tray_count = $product['tray_count'];
  310. //
  311. // //判断:每托箱数=每层箱数*每托层数
  312. // if ($tray_count == 18) {
  313. // $box_num = 3;
  314. // $per_box = 6;
  315. // } elseif ($tray_count == 24) {
  316. // $box_num = 4;
  317. // $per_box = 6;
  318. // } elseif ($tray_count == 36) {
  319. // $box_num = 4;
  320. // $per_box = 9;
  321. // } else {
  322. // $this->error('请联系管理员');
  323. // }
  324. // //每托箱数
  325. // $boxes_per_pallet = $per_box * $box_num;
  326. //
  327. // //每箱个数
  328. // $small_num = $product['items_per_box'];
  329. //
  330. // //可发数量
  331. // $remaining = (int)$product['remaining_quantity'];
  332. // //实际发货数量
  333. // $actual = isset($product['actual_quantity']) ?
  334. // min((int)$product['actual_quantity'], $remaining) : $remaining;
  335. //
  336. // //实际发货数量 / 每箱个数 = 总箱数
  337. // $total_boxes = ceil($actual / $small_num);
  338. // //多少箱 / 每托箱数 = 完整托盘数
  339. // $full_pallets = floor($total_boxes / $boxes_per_pallet);
  340. // // 剩余箱数
  341. // $remaining_boxes = $total_boxes % $boxes_per_pallet;
  342. //
  343. // // 构建产品基础信息(需要重新构建因为baseInfo可能在循环中被修改)
  344. // $baseInfo = [
  345. // 'bach_ids' => $bachNum,
  346. // 'userid' => $userinfo['id'],
  347. // 'gdbh' => $product['gdbh'],
  348. // 'order_ddbh' => $product['order_ddbh'],
  349. // 'cpbm' => $product['cpbm'],
  350. // 'cpmc' => $product['cpmc'],
  351. // 'matter_name' => $product['cpmc'],
  352. // 'remark' => $product['remark'] ?? '',
  353. // 'small_num' => $small_num,
  354. // 'unit' => $product['unit'] ?? '套',
  355. // 'tray_num' => $config['tray_num'],
  356. // 'box_num' => $box_num,
  357. // 'tray_count' => $tray_count,
  358. // 'layer_height' => $product['layer_height'] ?? $config['default_layer_height'],
  359. // 'pallet_length' => $config['pallet_length'],
  360. // 'pallet_width' => $config['pallet_width'],
  361. // 'bach_status' => 0,
  362. // 'sys_rq' => $currentDate,
  363. // 'created_at' => $currentDateTime,
  364. // 'create_time' => $timestamp,
  365. // 'delete_time' => ''
  366. // ];
  367. //
  368. // // 只处理不完整托盘部分
  369. // if ($remaining_boxes > 0) {
  370. // $partial_qty = $remaining_boxes * $small_num;
  371. //
  372. // $productDetails[] = array_merge($baseInfo, [
  373. // 'actual_quantity' => $partial_qty,
  374. // 'total_boxes' => $remaining_boxes,
  375. // 'pallet_count' => 1,
  376. // 'pallet_type' => 'partial',
  377. // 'pallet_range' => (string)$currentPalletNo,
  378. // 'start_pallet_no' => $currentPalletNo,
  379. // 'end_pallet_no' => $currentPalletNo
  380. // ]);
  381. //
  382. // $palletDetails[] = [
  383. // 'bach_ids' => $bachNum,
  384. // 'product_id' => $product['gdbh'],
  385. // 'pallet_no' => $currentPalletNo,
  386. // 'pallet_no_display' => $currentPalletNo,
  387. // 'pallet_type' => 'partial',
  388. // 'quantity' => $partial_qty,
  389. // 'box_count' => $remaining_boxes,
  390. // 'layer_count' => ceil($remaining_boxes / $config['tray_num']),
  391. // 'bach_status' => 0,
  392. // 'created_at' => $currentDateTime,
  393. // 'delete_time' => ''
  394. // ];
  395. //
  396. // $batchStats['partial_pallets']++;
  397. // $batchStats['total_quantity'] += $partial_qty;
  398. // $batchStats['total_boxes'] += $remaining_boxes;
  399. // $currentPalletNo++;
  400. // $batchStats['total_pallets']++;
  401. // }
  402. // }
  403. //
  404. // // 9. 构建批次汇总数据
  405. // $summaryData = [
  406. // 'bach_ids' => $bachNum,
  407. // 'userid' => $userinfo['id'],
  408. // 'total_quantity' => $batchStats['total_quantity'],
  409. // 'total_boxes' => $batchStats['total_boxes'],
  410. // 'total_pallets' => $batchStats['total_pallets'],
  411. // 'product_count' => $batchStats['product_varieties'],
  412. // 'full_pallets' => $batchStats['full_pallets'],
  413. // 'partial_pallets' => $batchStats['partial_pallets'],
  414. // 'bach_status' => 0,
  415. // 'sys_rq' => $currentDate,
  416. // 'created_at' => $currentDateTime,
  417. // 'create_time' => $timestamp,
  418. // 'delete_time' => ''
  419. // ];
  420. //die;
  421. // // 10. 保存所有数据
  422. // $mongo->name($collection)->insertAll($productDetails);
  423. // $mongo->name($bachdetails)->insertAll($palletDetails);
  424. // $mongo->name($bachsummary)->insert($summaryData);
  425. //
  426. // // 11. 更新库存记录
  427. // foreach ($data['products'] as $product) {
  428. // $where = [
  429. // 'gdbh' => $product['gdbh'],
  430. // 'order_ddbh' => $product['order_ddbh'],
  431. // 'cpmc' => $product['cpmc'],
  432. // ];
  433. //
  434. // $actual = (int)($product['actual_quantity'] ?? 0);
  435. // $remaining = (int)$product['remaining_quantity'];
  436. //
  437. // // 处理MongoDB查询结果
  438. // $existing = $mongo->name('inventory_summary')->where($where)->find();
  439. //
  440. // if ($existing) {
  441. // // 转换为数组处理
  442. // if (is_object($existing)) {
  443. // $existing = (array)$existing;
  444. // }
  445. //
  446. // // 处理多结果情况
  447. // if (isset($existing[0])) {
  448. // $existing = $existing[0];
  449. // }
  450. //
  451. // // 安全获取字段值
  452. // $current_chu = (int)($existing['total_chu_quantity'] ?? 0);
  453. // $current_remain = (int)($existing['remaining_quantity'] ?? 0);
  454. //
  455. // $mongo->name('inventory_summary')
  456. // ->where($where)
  457. // ->update([
  458. // 'total_chu_quantity' => $current_chu + $actual,
  459. // 'remaining_quantity' => $current_remain - $actual,
  460. // 'updated_at' => $currentDateTime,
  461. // ]);
  462. // } else {
  463. // // 新记录
  464. // $mongo->name('inventory_summary')->insert([
  465. // 'gdbh' => $product['gdbh'],
  466. // 'order_ddbh' => $product['order_ddbh'],
  467. // 'cpbm' => $product['cpbm'],
  468. // 'cpmc' => $product['cpmc'],
  469. // 'total_ru_quantity' => $remaining,
  470. // 'total_chu_quantity' => $actual,
  471. // 'remaining_quantity' => $remaining - $actual,
  472. // 'created_at' => $currentDateTime,
  473. // 'company' => $data['company_name'] ?? '',
  474. // ]);
  475. // }
  476. //
  477. // // 插入库存流水记录
  478. // $mongo->name('inventory_records')->insert([
  479. // 'gdbh' => $product['gdbh'],
  480. // 'order_ddbh' => $product['order_ddbh'],
  481. // 'cpbm' => $product['cpbm'],
  482. // 'cpmc' => $product['cpmc'],
  483. // 'total_ru_quantity' => $remaining,
  484. // 'total_chu_quantity' => $actual,
  485. // 'remaining_quantity' => $remaining - $actual,
  486. // 'created_at' => $currentDateTime,
  487. // 'company' => $data['company_name'] ?? '',
  488. // ]);
  489. // }
  490. //
  491. // $this->success('批次创建成功');
  492. // }
  493. /**
  494. * 添加批次功能
  495. *
  496. * 功能说明:
  497. * 1. 处理AJAX请求,创建产品批次
  498. * 2. 自动计算托盘分配(完整托盘和不完整托盘)
  499. * 3. 生成批次号和相关统计信息
  500. * 4. 更新库存记录
  501. * 5. 支持多种托盘配置(18箱/24箱/36箱)
  502. *
  503. * 数据流向:
  504. * 前端提交 -> 验证 -> 计算分配 -> 生成记录 -> 更新库存 -> 返回结果
  505. */
  506. public function add_bach()
  507. {
  508. // ==================== 1. 请求验证阶段 ====================
  509. // 1.1 验证必须是AJAX请求
  510. if (!$this->request->isAjax()) {
  511. $this->error('非法请求,必须使用AJAX方式提交');
  512. }
  513. // 1.2 获取并解析输入数据
  514. $data = input('row'); // 获取原始数据
  515. if (empty($data)) {
  516. $this->error('请求参数不能为空');
  517. }
  518. // 1.3 解析JSON数据
  519. $data = json_decode($data, true);
  520. if (json_last_error() !== JSON_ERROR_NONE) {
  521. $this->error('JSON数据解析失败:' . json_last_error_msg());
  522. }
  523. // 1.4 验证产品数据是否存在
  524. if (empty($data['products']) || !is_array($data['products'])) {
  525. $this->error('产品数据不能为空且必须是数组');
  526. }
  527. // ==================== 2. 用户会话验证 ====================
  528. $userinfo = Session::get('admin');
  529. if (empty($userinfo) || !isset($userinfo['company'])) {
  530. $this->error('获取用户信息失败,请重新登录');
  531. }
  532. // ==================== 3. 数据库准备 ====================
  533. // 3.1 连接MongoDB
  534. $mongo = \think\Db::connect('mongodb');
  535. // 3.2 动态生成集合名称(基于公司名称)
  536. $collection = $userinfo['company'] . '_qcode_bach'; // 主表
  537. $bachdetails = $userinfo['company'] . '_qcode_bachdetails'; // 托盘明细表
  538. $bachsummary = $userinfo['company'] . '_qcode_bachsummary'; // 批次汇总表
  539. // ==================== 4. 生成批次信息 ====================
  540. $currentDate = date('Y-m-d');
  541. $currentDateTime = date('Y-m-d H:i:s');
  542. $timestamp = time();
  543. // 批次号规则:BACH + 年月日时分秒 + 4位随机数
  544. $bachNum = 'BACH' . date('YmdHis') . mt_rand(1000, 9999);
  545. // ==================== 5. 初始化统计容器 ====================
  546. $batchStats = [
  547. 'total_quantity' => 0, // 总产品数量
  548. 'total_boxes' => 0, // 总箱数
  549. 'total_pallets' => 0, // 总托盘数
  550. 'full_pallets' => 0, // 完整托盘数
  551. 'partial_pallets' => 0, // 不完整托盘数
  552. 'product_varieties' => count($data['products']) // 产品种类数
  553. ];
  554. // ==================== 6. 处理产品数据 ====================
  555. $productDetails = []; // 产品主表数据
  556. $palletDetails = []; // 托盘明细数据
  557. $currentPalletNo = 1; // 托盘编号计数器
  558. /**
  559. * 第一阶段:处理完整托盘
  560. * 逻辑:先分配完整托盘,确保托盘利用率最大化
  561. */
  562. foreach ($data['products'] as $product) {
  563. // 6.1 动态获取托盘配置
  564. $tray_count = $product['tray_count'] ?? 18; // 默认18箱/托盘
  565. // 6.2 根据托盘配置确定层数和每层箱数
  566. if ($tray_count == 18) {
  567. $box_num = 3; // 3层
  568. $per_box = 6; // 每层6箱
  569. } elseif ($tray_count == 24) {
  570. $box_num = 4; // 4层
  571. $per_box = 6; // 每层6箱
  572. } elseif ($tray_count == 36) {
  573. $box_num = 4; // 4层
  574. $per_box = 9; // 每层9箱
  575. } else {
  576. $this->error('不支持的托盘配置:' . $tray_count);
  577. }
  578. $boxes_per_pallet = $per_box * $box_num; // 每托盘总箱数
  579. $small_num = $product['items_per_box'] ?? 20; // 每箱数量,默认20
  580. $default_layer_height = $product['default_layer_height'] ?? '1.35'; // 默认层高
  581. // 6.3 计算实际发货数量(不超过剩余数量)
  582. $remaining = (int)$product['remaining_quantity'];
  583. $actual = isset($product['actual_quantity']) ?
  584. min((int)$product['actual_quantity'], $remaining) : $remaining;
  585. // 6.4 计算托盘分配
  586. $total_boxes = ceil($actual / $small_num); // 总箱数
  587. $full_pallets = floor($total_boxes / $boxes_per_pallet); // 完整托盘数
  588. $remaining_boxes = $total_boxes % $boxes_per_pallet; // 剩余箱数
  589. // 6.5 构建产品基础信息
  590. $baseInfo = [
  591. 'bach_ids' => $bachNum,
  592. 'userid' => $userinfo['id'],
  593. 'gdbh' => $product['gdbh'],
  594. 'order_ddbh' => $product['order_ddbh'],
  595. 'cpbm' => $product['cpbm'],
  596. 'cpmc' => $product['cpmc'],
  597. 'matter_name' => $product['cpmc'],
  598. 'remark' => $product['remark'] ?? '',
  599. 'small_num' => $small_num,
  600. 'unit' => $product['unit'] ?? '套',
  601. 'tray_num' => $per_box,
  602. 'box_num' => $box_num,
  603. 'tray_count' => $tray_count,
  604. 'layer_height' => $product['layer_height'] ?? $default_layer_height,
  605. 'pallet_length' => $product['pallet_length'] ?? '0.9',
  606. 'pallet_width' => $product['pallet_width'] ?? '1.2',
  607. 'bach_status' => 0, // 状态(0:未处理)
  608. 'sys_rq' => $currentDate,
  609. 'created_at' => $currentDateTime,
  610. 'create_time' => $timestamp,
  611. 'delete_time' => ''
  612. ];
  613. // 6.6 处理完整托盘
  614. if ($full_pallets > 0) {
  615. $full_qty = $full_pallets * $boxes_per_pallet * $small_num;
  616. $endNo = $currentPalletNo + $full_pallets - 1;
  617. $productDetails[] = array_merge($baseInfo, [
  618. 'actual_quantity' => $full_qty,
  619. 'total_boxes' => $full_pallets * $boxes_per_pallet,
  620. 'pallet_count' => $full_pallets,
  621. 'pallet_type' => 'full',
  622. 'pallet_range' => "$currentPalletNo-$endNo",
  623. 'start_pallet_no' => $currentPalletNo,
  624. 'end_pallet_no' => $endNo
  625. ]);
  626. // 生成托盘明细记录
  627. for ($i = 0; $i < $full_pallets; $i++) {
  628. $palletDetails[] = [
  629. 'bach_ids' => $bachNum,
  630. 'product_id' => $product['gdbh'],
  631. 'pallet_no' => $currentPalletNo + $i,
  632. 'pallet_no_display' => $currentPalletNo + $i,
  633. 'pallet_type' => 'full',
  634. 'quantity' => $boxes_per_pallet * $small_num,
  635. 'box_count' => $boxes_per_pallet,
  636. 'layer_count' => $box_num,
  637. 'bach_status' => 0,
  638. 'created_at' => $currentDateTime,
  639. 'delete_time' => ''
  640. ];
  641. }
  642. // 更新统计信息
  643. $batchStats['full_pallets'] += $full_pallets;
  644. $batchStats['total_quantity'] += $full_qty;
  645. $batchStats['total_boxes'] += $full_pallets * $boxes_per_pallet;
  646. $currentPalletNo += $full_pallets;
  647. $batchStats['total_pallets'] += $full_pallets;
  648. }
  649. }
  650. /**
  651. * 第二阶段:处理不完整托盘
  652. * 逻辑:分配剩余不能组成完整托盘的部分
  653. */
  654. foreach ($data['products'] as $product) {
  655. // 同上获取托盘配置
  656. $tray_count = $product['tray_count'] ?? 18;
  657. if ($tray_count == 18) {
  658. $box_num = 3;
  659. $per_box = 6;
  660. } elseif ($tray_count == 24) {
  661. $box_num = 4;
  662. $per_box = 6;
  663. } elseif ($tray_count == 36) {
  664. $box_num = 4;
  665. $per_box = 9;
  666. } else {
  667. continue; // 已在前阶段验证过,这里跳过
  668. }
  669. $boxes_per_pallet = $per_box * $box_num;
  670. $small_num = $product['items_per_box'] ?? 20;
  671. $default_layer_height = $product['default_layer_height'] ?? '1.35';
  672. $remaining = (int)$product['remaining_quantity'];
  673. $actual = isset($product['actual_quantity']) ?
  674. min((int)$product['actual_quantity'], $remaining) : $remaining;
  675. $total_boxes = ceil($actual / $small_num);
  676. $full_pallets = floor($total_boxes / $boxes_per_pallet);
  677. $remaining_boxes = $total_boxes % $boxes_per_pallet;
  678. $baseInfo = [
  679. 'bach_ids' => $bachNum,
  680. 'userid' => $userinfo['id'],
  681. 'gdbh' => $product['gdbh'],
  682. 'order_ddbh' => $product['order_ddbh'],
  683. 'cpbm' => $product['cpbm'],
  684. 'cpmc' => $product['cpmc'],
  685. 'matter_name' => $product['cpmc'],
  686. 'remark' => $product['remark'] ?? '',
  687. 'small_num' => $small_num,
  688. 'unit' => $product['unit'] ?? '套',
  689. 'tray_num' => $per_box,
  690. 'box_num' => $box_num,
  691. 'tray_count' => $tray_count,
  692. 'layer_height' => $product['layer_height'] ?? $default_layer_height,
  693. 'pallet_length' => $product['pallet_length'] ?? '0.9',
  694. 'pallet_width' => $product['pallet_width'] ?? '1.2',
  695. 'bach_status' => 0,
  696. 'sys_rq' => $currentDate,
  697. 'created_at' => $currentDateTime,
  698. 'create_time' => $timestamp,
  699. 'delete_time' => ''
  700. ];
  701. // 处理不完整托盘
  702. if ($remaining_boxes > 0) {
  703. $partial_qty = $remaining_boxes * $small_num;
  704. $productDetails[] = array_merge($baseInfo, [
  705. 'actual_quantity' => $partial_qty,
  706. 'total_boxes' => $remaining_boxes,
  707. 'pallet_count' => 1,
  708. 'pallet_type' => 'partial',
  709. 'pallet_range' => (string)$currentPalletNo,
  710. 'start_pallet_no' => $currentPalletNo,
  711. 'end_pallet_no' => $currentPalletNo
  712. ]);
  713. $palletDetails[] = [
  714. 'bach_ids' => $bachNum,
  715. 'product_id' => $product['gdbh'],
  716. 'pallet_no' => $currentPalletNo,
  717. 'pallet_no_display' => $currentPalletNo,
  718. 'pallet_type' => 'partial',
  719. 'quantity' => $partial_qty,
  720. 'box_count' => $remaining_boxes,
  721. 'layer_count' => ceil($remaining_boxes / $per_box),
  722. 'bach_status' => 0,
  723. 'created_at' => $currentDateTime,
  724. 'delete_time' => ''
  725. ];
  726. // 更新统计信息
  727. $batchStats['partial_pallets']++;
  728. $batchStats['total_quantity'] += $partial_qty;
  729. $batchStats['total_boxes'] += $remaining_boxes;
  730. $currentPalletNo++;
  731. $batchStats['total_pallets']++;
  732. }
  733. }
  734. // ==================== 7. 构建批次汇总数据 ====================
  735. $summaryData = [
  736. 'bach_ids' => $bachNum,
  737. 'userid' => $userinfo['id'],
  738. 'total_quantity' => $batchStats['total_quantity'],
  739. 'total_boxes' => $batchStats['total_boxes'],
  740. 'total_pallets' => $batchStats['total_pallets'],
  741. 'product_count' => $batchStats['product_varieties'],
  742. 'full_pallets' => $batchStats['full_pallets'],
  743. 'partial_pallets' => $batchStats['partial_pallets'],
  744. 'bach_status' => 0,
  745. 'sys_rq' => $currentDate,
  746. 'created_at' => $currentDateTime,
  747. 'create_time' => $timestamp,
  748. 'delete_time' => ''
  749. ];
  750. // ==================== 8. 数据存储 ====================
  751. // try {
  752. // 8.1 开启事务(如果MongoDB支持)
  753. // 8.2 写入产品主表
  754. $mongo->name($collection)->insertAll($productDetails);
  755. // 8.3 写入托盘明细表
  756. $mongo->name($bachdetails)->insertAll($palletDetails);
  757. // 8.4 写入批次汇总表
  758. $mongo->name($bachsummary)->insert($summaryData);
  759. // ==================== 9. 更新库存记录 ====================
  760. foreach ($data['products'] as $product) {
  761. $where = [
  762. 'gdbh' => $product['gdbh'],
  763. 'order_ddbh' => $product['order_ddbh'],
  764. 'cpmc' => $product['cpmc'],
  765. ];
  766. $actual = (int)($product['actual_quantity'] ?? 0);
  767. $remaining = (int)$product['remaining_quantity'];
  768. // 查询现有库存记录
  769. $existing = $mongo->name('inventory_summary')->where($where)->find();
  770. if ($existing) {
  771. // 处理查询结果
  772. if (is_object($existing)) {
  773. $existing = (array)$existing;
  774. }
  775. if (isset($existing[0])) {
  776. $existing = $existing[0];
  777. }
  778. // 更新库存
  779. $mongo->name('inventory_summary')
  780. ->where($where)
  781. ->update([
  782. 'total_chu_quantity' => ($existing['total_chu_quantity'] ?? 0) + $actual,
  783. 'remaining_quantity' => ($existing['remaining_quantity'] ?? 0) - $actual,
  784. 'updated_at' => $currentDateTime,
  785. ]);
  786. } else {
  787. // 新增库存记录
  788. $mongo->name('inventory_summary')->insert([
  789. 'gdbh' => $product['gdbh'],
  790. 'order_ddbh' => $product['order_ddbh'],
  791. 'cpbm' => $product['cpbm'],
  792. 'cpmc' => $product['cpmc'],
  793. 'total_ru_quantity' => $remaining,
  794. 'total_chu_quantity' => $actual,
  795. 'remaining_quantity' => $remaining - $actual,
  796. 'created_at' => $currentDateTime,
  797. 'company' => $data['company_name'] ?? '',
  798. ]);
  799. }
  800. // 添加库存流水记录
  801. $mongo->name('inventory_records')->insert([
  802. 'gdbh' => $product['gdbh'],
  803. 'order_ddbh' => $product['order_ddbh'],
  804. 'cpbm' => $product['cpbm'],
  805. 'cpmc' => $product['cpmc'],
  806. 'operation_type' => 'outbound',
  807. 'quantity' => $actual,
  808. 'remaining_quantity' => $remaining - $actual,
  809. 'operator' => $userinfo['id'],
  810. 'created_at' => $currentDateTime,
  811. 'batch_number' => $bachNum,
  812. 'company' => $data['company_name'] ?? '',
  813. ]);
  814. }
  815. // 返回成功响应
  816. $this->success('批次创建成功');
  817. // } catch (\Exception $e) {
  818. // 错误处理
  819. // $this->error('批次创建失败:' . $e->getMessage());
  820. // }
  821. }
  822. // public function add_bach()
  823. // {
  824. // // 1. 请求验证部分
  825. // if (!$this->request->isAjax()) {
  826. // $this->error('请求必须为AJAX');
  827. // }
  828. //
  829. // $data = input('row');
  830. // if (empty($data)) {
  831. // $this->error('请求参数不能为空');
  832. // }
  833. //
  834. // $data = json_decode($data, true);
  835. // if (json_last_error() !== JSON_ERROR_NONE) {
  836. // $this->error('JSON数据解析失败');
  837. // }
  838. //
  839. // if (empty($data['products'])) {
  840. // $this->error('产品数据不能为空');
  841. // }
  842. //
  843. // // 2. 用户验证
  844. // $userinfo = Session::get('admin');
  845. // if (empty($userinfo) || !isset($userinfo['company'])) {
  846. // $this->error('获取用户信息失败,请重新登录');
  847. // }
  848. //
  849. // // 3. 数据库连接
  850. // $mongo = \think\Db::connect('mongodb');
  851. // $collection = $userinfo['company'] . '_qcode_bach'; // 产品主表
  852. // $bachdetails = $userinfo['company'] . '_qcode_bachdetails'; // 托盘明细表
  853. // $bachsummary = $userinfo['company'] . '_qcode_bachsummary'; // 批次汇总表
  854. //
  855. // // 4. 生成批次信息
  856. // $currentDate = date('Y-m-d');
  857. // $currentDateTime = date('Y-m-d H:i:s');
  858. // $timestamp = time();
  859. // $bachNum = 'BACH' . date('YmdHis') . mt_rand(1000, 9999);
  860. //
  861. // // 5. 托盘配置
  862. // $config = [
  863. // 'tray_num' => 6, // 每层6箱
  864. // 'small_num' => 20, // 每箱20个
  865. // 'pallet_length' => '0.9',
  866. // 'pallet_width' => '1.2',
  867. // 'default_layer_height' => '1.35'
  868. // ];
  869. //
  870. // // 6. 初始化数据容器
  871. // $fullPalletsData = []; // 完整托盘数据
  872. // $partialPalletsData = []; // 不完整托盘数据
  873. // $palletDetails = []; // 托盘明细数据
  874. // $batchStats = [
  875. // 'total_quantity' => 0, // 总产品数量
  876. // 'total_boxes' => 0, // 总箱数
  877. // 'total_pallets' => 0, // 总托盘数
  878. // 'full_pallets' => 0, // 完整托盘数
  879. // 'partial_pallets' => 0, // 不完整托盘数
  880. // 'product_varieties' => count($data['products']) // 产品种类数
  881. // ];
  882. //
  883. // $currentPalletNo = 1; // 全局托盘计数器
  884. //
  885. // // 7. 第一阶段:处理所有完整托盘
  886. // foreach ($data['products'] as $product) {
  887. // // 7.1 计算托盘配置
  888. // $tray_count = isset($product['tray_count']) ? (int)$product['tray_count'] : 18;
  889. // $box_num = $tray_count == 24 ? 4 : 3;
  890. //
  891. // // 7.2 处理数量 - 确保不超过剩余数量
  892. // $remaining_quantity = (int)$product['remaining_quantity'];
  893. // $actual_quantity = isset($product['actual_quantity']) ?
  894. // min((int)$product['actual_quantity'], $remaining_quantity) :
  895. // $remaining_quantity;
  896. //
  897. // // 7.3 计算托盘分配
  898. // $boxes_per_pallet = $config['tray_num'] * $box_num;
  899. // $total_boxes = ceil($actual_quantity / $config['small_num']);
  900. // $full_pallets = floor($total_boxes / $boxes_per_pallet);
  901. // $remaining_boxes = $total_boxes % $boxes_per_pallet;
  902. //
  903. // // 7.4 产品基础信息
  904. // $baseProductInfo = [
  905. // 'bach_ids' => $bachNum,
  906. // 'userid' => $userinfo['id'],
  907. // 'gdbh' => $product['gdbh'],
  908. // 'order_ddbh' => $product['order_ddbh'],
  909. // 'cpbm' => $product['cpbm'],
  910. // 'cpmc' => $product['cpmc'],
  911. // 'matter_name' => $product['cpmc'],
  912. // 'remark' => $product['remark'] ?? '',
  913. // 'small_num' => $config['small_num'],
  914. // 'tray_num' => $config['tray_num'],
  915. // 'box_num' => $box_num,
  916. // 'tray_count' => $tray_count,
  917. // 'layer_height' => $product['layer_height'] ?? $config['default_layer_height'],
  918. // 'pallet_length' => $config['pallet_length'],
  919. // 'pallet_width' => $config['pallet_width'],
  920. // 'bach_status' => 0,
  921. // 'sys_rq' => $currentDate,
  922. // 'created_at' => $currentDateTime,
  923. // 'create_time' => $timestamp,
  924. // 'delete_time' => ''
  925. // ];
  926. //
  927. // // 7.5 处理完整托盘
  928. // if ($full_pallets > 0) {
  929. // $full_quantity = $full_pallets * $boxes_per_pallet * $config['small_num'];
  930. // $endPalletNo = $currentPalletNo + $full_pallets - 1;
  931. //
  932. // $fullPalletsData[] = [
  933. // 'product_info' => array_merge($baseProductInfo, [
  934. // 'actual_quantity' => $full_quantity,
  935. // 'total_boxes' => $full_pallets * $boxes_per_pallet,
  936. // 'pallet_count' => $full_pallets,
  937. // 'pallet_type' => 'full',
  938. // 'pallet_range' => $currentPalletNo . '-' . $endPalletNo,
  939. // 'start_pallet_no' => $currentPalletNo,
  940. // 'end_pallet_no' => $endPalletNo
  941. // ]),
  942. // 'pallet_count' => $full_pallets,
  943. // 'start_no' => $currentPalletNo,
  944. // 'boxes_per_pallet' => $boxes_per_pallet,
  945. // 'box_num' => $box_num
  946. // ];
  947. //
  948. // $batchStats['full_pallets'] += $full_pallets;
  949. // $batchStats['total_quantity'] += $full_quantity;
  950. // $batchStats['total_boxes'] += $full_pallets * $boxes_per_pallet;
  951. // $currentPalletNo += $full_pallets;
  952. // $batchStats['total_pallets'] += $full_pallets;
  953. // }
  954. // }
  955. //
  956. // // 8. 第二阶段:处理所有不完整托盘
  957. // foreach ($data['products'] as $product) {
  958. // // 8.1 计算托盘配置
  959. // $tray_count = isset($product['tray_count']) ? (int)$product['tray_count'] : 18;
  960. // $box_num = $tray_count == 24 ? 4 : 3;
  961. //
  962. // // 8.2 处理数量 - 确保不超过剩余数量
  963. // $remaining_quantity = (int)$product['remaining_quantity'];
  964. // $actual_quantity = isset($product['actual_quantity']) ?
  965. // min((int)$product['actual_quantity'], $remaining_quantity) :
  966. // $remaining_quantity;
  967. //
  968. // // 8.3 计算托盘分配
  969. // $boxes_per_pallet = $config['tray_num'] * $box_num;
  970. // $total_boxes = ceil($actual_quantity / $config['small_num']);
  971. // $full_pallets = floor($total_boxes / $boxes_per_pallet);
  972. // $remaining_boxes = $total_boxes % $boxes_per_pallet;
  973. //
  974. // // 8.4 产品基础信息
  975. // $baseProductInfo = [
  976. // 'bach_ids' => $bachNum,
  977. // 'userid' => $userinfo['id'],
  978. // 'gdbh' => $product['gdbh'],
  979. // 'order_ddbh' => $product['order_ddbh'],
  980. // 'cpbm' => $product['cpbm'],
  981. // 'cpmc' => $product['cpmc'],
  982. // 'matter_name' => $product['cpmc'],
  983. // 'remark' => $product['remark'] ?? '',
  984. // 'small_num' => $config['small_num'],
  985. // 'tray_num' => $config['tray_num'],
  986. // 'box_num' => $box_num,
  987. // 'tray_count' => $tray_count,
  988. // 'layer_height' => $product['layer_height'] ?? $config['default_layer_height'],
  989. // 'pallet_length' => $config['pallet_length'],
  990. // 'pallet_width' => $config['pallet_width'],
  991. // 'bach_status' => 0,
  992. // 'sys_rq' => $currentDate,
  993. // 'created_at' => $currentDateTime,
  994. // 'create_time' => $timestamp,
  995. // 'delete_time' => ''
  996. // ];
  997. //
  998. // // 8.5 处理不完整托盘
  999. // if ($remaining_boxes > 0) {
  1000. // // 计算完整托盘已经处理的数量
  1001. // $full_quantity = $full_pallets * $boxes_per_pallet * $config['small_num'];
  1002. // // 确保不完整托盘数量不超过剩余数量
  1003. // $partial_quantity = min($remaining_boxes * $config['small_num'], $actual_quantity - $full_quantity);
  1004. //
  1005. // $partialPalletsData[] = [
  1006. // 'product_info' => array_merge($baseProductInfo, [
  1007. // 'actual_quantity' => $partial_quantity,
  1008. // 'total_boxes' => $remaining_boxes,
  1009. // 'pallet_count' => 1,
  1010. // 'pallet_type' => 'partial',
  1011. // 'pallet_range' => (string)$currentPalletNo,
  1012. // 'start_pallet_no' => $currentPalletNo,
  1013. // 'end_pallet_no' => $currentPalletNo
  1014. // ]),
  1015. // 'pallet_count' => 1,
  1016. // 'start_no' => $currentPalletNo,
  1017. // 'remaining_boxes' => $remaining_boxes
  1018. // ];
  1019. //
  1020. // $batchStats['partial_pallets']++;
  1021. // $batchStats['total_quantity'] += $partial_quantity;
  1022. // $batchStats['total_boxes'] += $remaining_boxes;
  1023. // $currentPalletNo++;
  1024. // $batchStats['total_pallets']++;
  1025. // }
  1026. // }
  1027. //
  1028. // // 9. 验证总数是否正确
  1029. // $expected_total = array_sum(array_map(function($product) {
  1030. // return isset($product['actual_quantity']) ?
  1031. // min((int)$product['actual_quantity'], (int)$product['remaining_quantity']) :
  1032. // (int)$product['remaining_quantity'];
  1033. // }, $data['products']));
  1034. //
  1035. // if ($batchStats['total_quantity'] != $expected_total) {
  1036. // $this->error('计算数量不一致,预期: '.$expected_total.',实际: '.$batchStats['total_quantity']);
  1037. // }
  1038. //
  1039. // // 10. 合并所有托盘数据(完整托盘在前,不完整托盘在后)
  1040. // $allPalletData = array_merge($fullPalletsData, $partialPalletsData);
  1041. //
  1042. // // 11. 生成最终的产品主表数据和托盘明细数据
  1043. // $productDetails = [];
  1044. // $palletDetails = [];
  1045. // $currentPalletNo = 1; // 重新开始计数
  1046. //
  1047. // foreach ($allPalletData as $pallet) {
  1048. // if (isset($pallet['boxes_per_pallet'])) {
  1049. // // 完整托盘
  1050. // $endPalletNo = $currentPalletNo + $pallet['pallet_count'] - 1;
  1051. //
  1052. // $productDetails[] = array_merge($pallet['product_info'], [
  1053. // 'pallet_range' => $currentPalletNo . '-' . $endPalletNo,
  1054. // 'start_pallet_no' => $currentPalletNo,
  1055. // 'end_pallet_no' => $endPalletNo
  1056. // ]);
  1057. //
  1058. // // 生成托盘明细
  1059. // for ($i = 0; $i < $pallet['pallet_count']; $i++) {
  1060. // $palletDetails[] = [
  1061. // 'bach_ids' => $bachNum,
  1062. // 'product_id' => $pallet['product_info']['gdbh'],
  1063. // 'pallet_no' => $currentPalletNo + $i,
  1064. // 'pallet_no_display' => $currentPalletNo + $i,
  1065. // 'pallet_type' => 'full',
  1066. // 'quantity' => $pallet['boxes_per_pallet'] * $config['small_num'],
  1067. // 'box_count' => $pallet['boxes_per_pallet'],
  1068. // 'layer_count' => $pallet['box_num'],
  1069. // 'bach_status' => 0,
  1070. // 'created_at' => $currentDateTime,
  1071. // 'delete_time' => ''
  1072. // ];
  1073. // }
  1074. //
  1075. // $currentPalletNo += $pallet['pallet_count'];
  1076. // } else {
  1077. // // 不完整托盘
  1078. // $productDetails[] = array_merge($pallet['product_info'], [
  1079. // 'pallet_range' => (string)$currentPalletNo,
  1080. // 'start_pallet_no' => $currentPalletNo,
  1081. // 'end_pallet_no' => $currentPalletNo
  1082. // ]);
  1083. //
  1084. // $palletDetails[] = [
  1085. // 'bach_ids' => $bachNum,
  1086. // 'product_id' => $pallet['product_info']['gdbh'],
  1087. // 'pallet_no' => $currentPalletNo,
  1088. // 'pallet_no_display' => $currentPalletNo,
  1089. // 'pallet_type' => 'partial',
  1090. // 'quantity' => $pallet['product_info']['actual_quantity'],
  1091. // 'box_count' => $pallet['product_info']['total_boxes'],
  1092. // 'layer_count' => ceil($pallet['product_info']['total_boxes'] / $config['tray_num']),
  1093. // 'bach_status' => 0,
  1094. // 'created_at' => $currentDateTime,
  1095. // 'delete_time' => ''
  1096. // ];
  1097. //
  1098. // $currentPalletNo++;
  1099. // }
  1100. // }
  1101. //
  1102. // // 12. 构建批次汇总数据
  1103. // $summaryData = [
  1104. // 'bach_ids' => $bachNum, // 单据编号
  1105. // 'userid' => $userinfo['id'], // 用户ID
  1106. // 'total_quantity' => $batchStats['total_quantity'], // 总发货数量
  1107. // 'total_boxes' => $batchStats['total_boxes'], // 总箱数
  1108. // 'total_pallets' => $batchStats['total_pallets'], // 总托盘数
  1109. // 'product_count' => $batchStats['product_varieties'], // 产品数量
  1110. // 'full_pallets' => $batchStats['full_pallets'], // 完整托盘数
  1111. // 'partial_pallets' => $batchStats['partial_pallets'], // 不完整托盘数
  1112. // 'bach_status' => 0, // 状态
  1113. // 'sys_rq' => $currentDate, // 日期
  1114. // 'created_at' => $currentDateTime, // 操作时间
  1115. // 'create_time' => $timestamp, // 时间戳
  1116. // 'delete_time' => '' // 删除时间
  1117. // ];
  1118. //
  1119. // foreach ($data['products'] as $product) {
  1120. // $where = [
  1121. // 'gdbh' => $product['gdbh'],
  1122. // 'order_ddbh' => $product['order_ddbh'],
  1123. // 'cpmc' => $product['cpmc'],
  1124. // ];
  1125. //
  1126. // // 实际出库数量
  1127. // $actual_quantity = isset($product['actual_quantity']) ? (int)$product['actual_quantity'] : 0;
  1128. // $remaining_quantity = isset($product['remaining_quantity']) ? (int)$product['remaining_quantity'] : 0;
  1129. //
  1130. // // 插入/更新字段
  1131. // $insertData = [
  1132. // 'gdbh' => $product['gdbh'],
  1133. // 'order_ddbh' => $product['order_ddbh'],
  1134. // 'cpbm' => $product['cpbm'],
  1135. // 'cpmc' => $product['cpmc'],
  1136. // 'total_ru_quantity' => $remaining_quantity, // 入库数来自当前剩余
  1137. // 'total_chu_quantity' => $actual_quantity, // 本次出库数
  1138. // 'remaining_quantity' => $remaining_quantity - $actual_quantity, // 计算结存
  1139. // 'created_at' => date('Y-m-d H:i:s'),
  1140. // 'updated_at' => '',
  1141. // 'mod_rq' => '',
  1142. // 'company' => $data['company_name'] ?? '',
  1143. // ];
  1144. //
  1145. // // 查询是否已存在
  1146. // $existing = $mongo->name('inventory_summary')->where($where)->find();
  1147. //
  1148. // if ($existing) {
  1149. // // 累加更新
  1150. // $new_chu = (int)$existing['total_chu_quantity'] + $actual_quantity;
  1151. // $new_remaining = (int)$existing['remaining_quantity'] - $actual_quantity;
  1152. //
  1153. // $mongo->name('inventory_summary')
  1154. // ->where($where)
  1155. // ->update([
  1156. // 'total_ru_quantity' => (int)$existing['total_ru_quantity'], // 保持不变或你可定义逻辑
  1157. // 'total_chu_quantity' => $new_chu,
  1158. // 'remaining_quantity' => $new_remaining,
  1159. // 'updated_at' => date('Y-m-d H:i:s'),
  1160. // ]);
  1161. // } else {
  1162. // // 插入新记录
  1163. // $mongo->name('inventory_summary')->insert($insertData);
  1164. // }
  1165. //
  1166. // // 插入库存明细记录
  1167. // $mongo->name('inventory_records')->insert($insertData);
  1168. // }
  1169. //
  1170. // // 13. 数据入库操作
  1171. // try {
  1172. // $mongo->name($collection)->insertAll($productDetails);
  1173. // $mongo->name($bachdetails)->insertAll($palletDetails);
  1174. // $mongo->name($bachsummary)->insert($summaryData);
  1175. //
  1176. //// $this->success('批次创建成功', null, [
  1177. //// 'bach_num' => $bachNum,
  1178. //// 'total_quantity' => $batchStats['total_quantity'],
  1179. //// 'total_boxes' => $batchStats['total_boxes'],
  1180. //// 'total_pallets' => $batchStats['total_pallets'],
  1181. //// 'product_count' => $batchStats['product_varieties'],
  1182. //// 'pallet_range' => '1-' . ($currentPalletNo - 1)
  1183. //// ]);
  1184. // } catch (\Exception $e) {
  1185. // $this->error('批次创建失败:' . $e->getMessage());
  1186. // }
  1187. // }
  1188. // public function add_bach()
  1189. // {
  1190. // if (!$this->request->isAjax()) {
  1191. // $this->error('请求错误');
  1192. // }
  1193. //
  1194. // $data = input('row');
  1195. // if (empty($data)) {
  1196. // $this->error('参数错误');
  1197. // }
  1198. //
  1199. // $data = json_decode($data, true);
  1200. //
  1201. // if (json_last_error() !== JSON_ERROR_NONE) {
  1202. // $this->error('JSON解析错误');
  1203. // }
  1204. //
  1205. // if (empty($data['products'])) {
  1206. // $this->error('产品数据不能为空');
  1207. // }
  1208. //
  1209. // $userinfo = Session::get('admin');
  1210. // if (empty($userinfo) || !isset($userinfo['company'])) {
  1211. // $this->error('用户信息获取失败');
  1212. // }
  1213. //
  1214. // $mongo = \think\Db::connect('mongodb');
  1215. // $collection = $userinfo['company'] . '_qcode_bach';
  1216. // $bachsummary = $userinfo['company'] . '_qcode_bachsummary';
  1217. //
  1218. // $insertData = [];
  1219. // $currentday = date('Y-m-d');
  1220. // $currentTime = date('Y-m-d H:i:s');
  1221. // $timestamp = time();
  1222. // $bachNum = 'BACH' . date('YmdHis') . mt_rand(1000, 9999);
  1223. //
  1224. // $totalQuantity = 0;
  1225. // $totalBoxes = 0;
  1226. // $totalPallets = 0;
  1227. //
  1228. // foreach ($data['products'] as $product) {
  1229. // $small_num = 20;
  1230. // $tray_num = 6;
  1231. // $box_num = 3;
  1232. // $total_boxes = $tray_num * $box_num;
  1233. //
  1234. // $remaining_quantity = (int)$product['remaining_quantity'];
  1235. // $larger_num = ceil($remaining_quantity / $small_num);
  1236. // $large_num = ceil($larger_num / $total_boxes);
  1237. //
  1238. // $totalQuantity += $remaining_quantity;
  1239. // $totalBoxes += $larger_num;
  1240. // $totalPallets += $large_num;
  1241. //
  1242. // $palletRange = '1-' . $large_num;
  1243. //
  1244. // $insertData[] = [
  1245. // 'userid' => $userinfo['id'],
  1246. // 'supplier_id' => $userinfo['id'],
  1247. // 'supplier_code' => $userinfo['printer_code'],
  1248. // 'supplier_name' => $data['company_name'],
  1249. // 'pallet' => $palletRange,
  1250. // 'matter_no' => $product['gdbh'],
  1251. // 'matter_id' => $product['gdbh'],
  1252. // 'matter_type' => '01',
  1253. // 'order_ddbh' => $product['order_ddbh'],
  1254. // 'cpbm' => $product['cpbm'],
  1255. // 'matter_name' => $product['cpmc'],
  1256. // 'remark' => $product['remark'],
  1257. // 'num_danwei' => '2',
  1258. // 'danwei' => '套',
  1259. // 'num' => $remaining_quantity,
  1260. // 'small_num' => $small_num,
  1261. // 'tray_num' => $tray_num,
  1262. // 'box_num' => $box_num,
  1263. // 'total_boxes' => $total_boxes,
  1264. // 'large_num' => $large_num,
  1265. // 'larger_num' => $larger_num,
  1266. // 'pallet_height' => '1.05',
  1267. // 'pallet_length' => '0.9',
  1268. // 'pallet_width' => '1.2',
  1269. // 'l_reservation' => '',
  1270. // 'l_flow' => '1',
  1271. // 'l_weight' => '',
  1272. // 's_flow' => '',
  1273. // 's_weight' => '',
  1274. // 's_reservation' => '',
  1275. // 'bach_status' => 0,
  1276. // 'bach_ids' => $bachNum,
  1277. // 'large_endnum' => $large_num,
  1278. // 'manufacture_date' => '',
  1279. // 'print_date' => '',
  1280. // 'sys_rq' => $currentday,
  1281. // 'created_at' => $currentTime,
  1282. // 'create_time' => $timestamp,
  1283. // 'updated_at' => '',
  1284. // 'sync_flag' => '0',
  1285. // 'delete_time' => '',
  1286. // 'delect_time' => ''
  1287. // ];
  1288. // }
  1289. //
  1290. // $insertData_bachsummary = [
  1291. // 'bach_ids' => $bachNum,
  1292. // 'userid' => $userinfo['id'],
  1293. // 'supplier_id' => $userinfo['id'],
  1294. // 'supplier_code' => $userinfo['printer_code'],
  1295. // 'supplier_name' => $data['company_name'],
  1296. // 'total_quantity' => $totalQuantity,
  1297. // 'total_boxes' => $totalBoxes,
  1298. // 'total_pallets' => $totalPallets,
  1299. // 'product_count' => count($data['products']),
  1300. // 'bach_status' => 0,
  1301. // 'sys_rq' => $currentday,
  1302. // 'created_at' => $currentTime,
  1303. // 'create_time' => $timestamp,
  1304. // 'updated_at' => '',
  1305. // 'delete_time' => ''
  1306. // ];
  1307. //
  1308. //echo "<pre>";
  1309. //print_r($insertData);
  1310. //echo "<pre>";die;
  1311. // $mongo->name($collection)->insertAll($insertData);
  1312. // $mongo->name($bachsummary)->insert($insertData_bachsummary);
  1313. //
  1314. //
  1315. // foreach ($data['products'] as $product) {
  1316. // $where = [
  1317. // 'gdbh' => $product['gdbh'],
  1318. // 'order_ddbh' => $product['order_ddbh'],
  1319. // 'cpmc' => $product['cpmc'],
  1320. // ];
  1321. //
  1322. // // 实际出库数量
  1323. // $actual_quantity = isset($product['actual_quantity']) ? (int)$product['actual_quantity'] : 0;
  1324. // $remaining_quantity = isset($product['remaining_quantity']) ? (int)$product['remaining_quantity'] : 0;
  1325. //
  1326. // // 插入/更新字段
  1327. // $insertData = [
  1328. // 'gdbh' => $product['gdbh'],
  1329. // 'order_ddbh' => $product['order_ddbh'],
  1330. // 'cpbm' => $product['cpbm'],
  1331. // 'cpmc' => $product['cpmc'],
  1332. // 'total_ru_quantity' => $remaining_quantity, // 入库数来自当前剩余
  1333. // 'total_chu_quantity' => $actual_quantity, // 本次出库数
  1334. // 'remaining_quantity' => $remaining_quantity - $actual_quantity, // 计算结存
  1335. // 'created_at' => date('Y-m-d H:i:s'),
  1336. // 'updated_at' => '',
  1337. // 'mod_rq' => '',
  1338. // 'company' => $data['company_name'] ?? '',
  1339. // ];
  1340. //
  1341. // // 查询是否已存在
  1342. // $existing = $mongo->name('inventory_summary')->where($where)->find();
  1343. //
  1344. // if ($existing) {
  1345. // // 累加更新
  1346. // $new_chu = (int)$existing['total_chu_quantity'] + $actual_quantity;
  1347. // $new_remaining = (int)$existing['remaining_quantity'] - $actual_quantity;
  1348. //
  1349. // $mongo->name('inventory_summary')
  1350. // ->where($where)
  1351. // ->update([
  1352. // 'total_ru_quantity' => (int)$existing['total_ru_quantity'], // 保持不变或你可定义逻辑
  1353. // 'total_chu_quantity' => $new_chu,
  1354. // 'remaining_quantity' => $new_remaining,
  1355. // 'updated_at' => date('Y-m-d H:i:s'),
  1356. // ]);
  1357. // } else {
  1358. // // 插入新记录
  1359. // $mongo->name('inventory_summary')->insert($insertData);
  1360. // }
  1361. //
  1362. // // 插入库存明细记录
  1363. // $mongo->name('inventory_records')->insert($insertData);
  1364. // }
  1365. // $this->success('添加成功');
  1366. //
  1367. // }
  1368. /**
  1369. * 增加新批次
  1370. */
  1371. public function add()
  1372. {
  1373. $product = new QcodeProduct();
  1374. $bach = new QcodeBach();
  1375. $large = new QcodeLarge();
  1376. $small = new QcodeSmall();
  1377. $liushui = new QcodeLiushui();
  1378. $resetFlow = new ResetFlow();
  1379. $QcodeCompany = new QcodeCompany();
  1380. if ($this->request->isAjax() === false){
  1381. $this->error('请求错误');
  1382. }
  1383. $rows = input('row');
  1384. if (empty($rows)){
  1385. $this->error('参数错误');
  1386. }
  1387. $rows = json_decode($rows);
  1388. $data = [];
  1389. foreach ($rows as $value){
  1390. foreach ($value as $k=>$v){
  1391. $data[$k] = $v;
  1392. }
  1393. }
  1394. // echo "接口获取";echo "<pre>";print_r($data);echo "<pre>";die;
  1395. //记录库存操作
  1396. $mongo = \think\Db::connect('mongodb');
  1397. $where = [
  1398. 'gdbh' => $data['gdbh'],
  1399. 'order_ddbh' => $data['order_ddbh'],
  1400. 'cpmc' => $data['cpmc'],
  1401. ];
  1402. //插入字段[inventory_summaryk库存明细]
  1403. $insertData = [
  1404. 'gdbh' => $data['gdbh'],
  1405. 'order_ddbh' => $data['order_ddbh'],
  1406. 'cpbm' => $data['cpbm'],
  1407. 'cpmc' => $data['cpmc'],
  1408. 'total_ru_quantity' => $data['sl'],//入库数
  1409. 'total_chu_quantity' => $data['number'],//出库数
  1410. 'remaining_quantity' => $data['remaining_quantity'] - $data['number'],//剩余数
  1411. 'created_at' => date('Y-m-d H:i:s'),
  1412. 'updated_at' => '',
  1413. 'mod_rq' => '',
  1414. 'company' => '',
  1415. ];
  1416. // 查询库存汇总表数据是否存在记录
  1417. $list = $mongo->name('inventory_summary')->where($where)->find();
  1418. if ($list) {
  1419. // 如果数据存在,更新库存汇总记录
  1420. $chu = $list['total_chu_quantity'] + $data['number'];//累计出库数量
  1421. $jiecun = $list['remaining_quantity'] - $data['number'];//剩余结存数量
  1422. $updateResult = $mongo->name('inventory_summary')
  1423. ->where($where)
  1424. ->update([
  1425. 'total_ru_quantity' => $data['sl'],
  1426. 'total_chu_quantity' => $chu,
  1427. 'remaining_quantity' => $jiecun,
  1428. 'updated_at' => date('Y-m-d H:i:s'),
  1429. ]);
  1430. } else {
  1431. // 数据不存在则插入新记录
  1432. $mongo->name('inventory_summary')->insert($insertData);
  1433. }
  1434. //记录库存明细
  1435. $mongo->name('inventory_records')->insert($insertData);
  1436. // // 调试输出
  1437. // echo "<pre>"; print_r($list); echo "</pre>";die;
  1438. switch ($data['danwei']) {
  1439. case 1:
  1440. $danwei = '个';
  1441. break;
  1442. case 2:
  1443. $danwei = '套';
  1444. break;
  1445. case 3:
  1446. $danwei = '张';
  1447. break;
  1448. default:
  1449. $danwei = '';
  1450. break;
  1451. }
  1452. $userinfo = Session::get('admin');//获取用户信息
  1453. $arr = [
  1454. 'batch' => $data['gdbh'],
  1455. 'create_time' => time(),
  1456. 'delect_time' => '',
  1457. 'sync_flag' => 0,
  1458. ];
  1459. $productres = $QcodeCompany->save($arr);
  1460. if ($productres === 0){
  1461. $this->error('添加失败');
  1462. }
  1463. $batchList = [
  1464. 'userid' => $userinfo['id'],//登录用户id
  1465. 'supplier_id' => $userinfo['id'],//登录用户id
  1466. 'supplier_code' => $userinfo['printer_code'],
  1467. 'supplier_name' => $data['company_name'],//公司名称
  1468. 'cpbm' => $data['cpbm'],//成品编码
  1469. 'matter_name' => $data['cpmc'],//成品名称
  1470. 'matter_no' => $data['gdbh'],//生产批次号-工单编号
  1471. 'order_ddbh' => $data['order_ddbh'],//销售订单号
  1472. 'matter_id' => $data['gdbh'],
  1473. 'matter_type' => '01',
  1474. 'manufacture_date' => (int)date('ymd',strtotime($data['manufacture_date'])),//生产日期
  1475. 'print_date' => (int)date('ymd',strtotime($data['print_date'])),//打码日期
  1476. 'num_danwei' => $data['danwei'],//单位
  1477. 'danwei' => $danwei,//单位
  1478. 'num' => $data['number'],//总数量(张/个)
  1479. 'small_num' => $data['box_number'],//每一箱数量
  1480. 'tray_num' => $data['tray_num'],//每层箱数【箱/层】
  1481. 'box_num' => $data['tray_number'],//每托层数【 层/托】
  1482. 'total_boxes' => $data['total_boxes'],//每托盘箱数【箱/托】
  1483. 'large_num' => $data['box_num'],//本次打包托盘数
  1484. 'larger_num' => $data['small_num'],//总箱数
  1485. 'pallet_height' => $data['pallet_height'],//每托高度
  1486. 'pallet_length' => $data['pallet_length'],//托盘规格
  1487. 'pallet_width' => $data['pallet_width'],//托盘规格
  1488. 'l_reservation' => '',
  1489. // 处理可能为空的流水/重量字段
  1490. 'l_flow' => $data['big_liushui'],//大件流水
  1491. 'l_weight' => $data['big_weight'],//大件重量
  1492. 's_flow' => $data['small_start_liushui'],//小件流水
  1493. 's_weight' => $data['small_weight'],//小件重量
  1494. 's_reservation' => '',
  1495. 'bach_status' => 0,
  1496. 'bach_num' => $data['gdbh'],//生产批次号-工单编号
  1497. 'large_endnum' => $data['big_liushui'] + $data['box_num'] -1,
  1498. 'create_time' => time(),//新增时间
  1499. 'delect_time' => '',//删除时间
  1500. ];
  1501. $res = $bach->save($batchList);
  1502. if ($res === 0){
  1503. $this->error('添加失败');
  1504. }
  1505. $flow = [
  1506. 'l_flow' => (int)$batchList['large_num'],
  1507. 'bach_num' => $batchList['matter_no'],
  1508. ];
  1509. if ($resetFlow->name($userinfo['company'].'_'."reset_flow")->where('product_id',$batchList['matter_no'])->find()){
  1510. $resetFlow->name($userinfo['company'].'_'."reset_flow")->where('product_id',$batchList['matter_no'])->update($flow);
  1511. }else{
  1512. $flow['product_id'] = $batchList['matter_no'];
  1513. $resetFlow->save($flow);
  1514. }
  1515. $last_id = $bach->getLastInsID();
  1516. if ($last_id){
  1517. //插入大小二维码数据 二维码数据不变区域
  1518. // echo "<pre>";print_r($batchList);echo "<pre>";die;
  1519. $fixed_code = '';
  1520. $fixed_code.=$this->intTochar($batchList['matter_type'],2);//2位 辅料种类编码
  1521. $fixed_code .= $this->intTochar($batchList['supplier_code'], 21);//21位 供应商编码
  1522. $fixed_code .= '9'; // 补0一位
  1523. $fixed_code.=$this->intTochar($batchList['cpbm'],10);//10位 辅料编码
  1524. $fixed_code.=$batchList['manufacture_date'];//6位 生产日期
  1525. $print_code=$batchList['print_date'];//6位 打码日期
  1526. $small_liushui = [
  1527. 'onlycode' => 'AB92'.$fixed_code.$print_code,
  1528. 'last_num' => 0,
  1529. 'user_id' => $userinfo['company'],
  1530. 'stype' => 2,
  1531. 'dateTime' => time(),
  1532. ];
  1533. $whereSmall = [
  1534. 'onlycode' => $small_liushui['onlycode'],
  1535. 'user_id' => $userinfo['company'],
  1536. ];
  1537. if ($liushui->name($userinfo['company'].'_'.'qcode_liushui')->where($whereSmall)->find()){
  1538. //小件二维码存在,更新小件二维码最后流水号
  1539. $lastNum = $liushui->name($userinfo['company'].'_'.'qcode_liushui')->where($whereSmall)->find();
  1540. }else{
  1541. //小件二维码不存在,新增记录
  1542. $liushui->save($small_liushui);
  1543. $lastNum['last_num'] = 0;
  1544. }
  1545. //循环插入大件二维码数据
  1546. for ($i=0;$i<$data['box_num'];$i++){
  1547. $large = new QcodeLarge();
  1548. $l_flow = $this->intTochar($batchList['l_flow']+$i,6);
  1549. $l_weight = $this->intTochar($batchList['l_weight']*100,6);
  1550. $l_reservation = $this->intTochar($batchList['matter_no'],10);
  1551. $l_reservation = $l_reservation.'0000000000';
  1552. $remainder = $batchList['num'] - $batchList['total_boxes'] * $i;//最后一托盘小件数量
  1553. if ($remainder < $batchList['tray_num']){
  1554. $small_n = $this->intTochar($remainder,3);//3位小件数量,不足补0
  1555. }else{
  1556. $small_n = $this->intTochar($batchList['tray_num'],3);
  1557. }
  1558. // $l_num = $small_n * $batchList['box_num'];
  1559. $l_num = 0;
  1560. //大件二维码数据
  1561. $code_data = $this->CodeData('AB92',$fixed_code,$small_n,$print_code,$l_flow,$l_weight,'2',$l_reservation);
  1562. //大码数据信息
  1563. $l_data = [
  1564. 'bach_id' => $last_id,
  1565. 'code' => $code_data['code'],
  1566. 'code_cp1' => $code_data['code_cp1'],
  1567. 'code_cp2' => $code_data['code_cp2'],
  1568. 'print_date' => $print_code,
  1569. 'create_time' => time(),
  1570. 'p_nums' => 0,
  1571. 'userid' =>$userinfo['id'],
  1572. 'l_weight' =>$batchList['l_weight']*100,
  1573. 'l_num' =>$l_num,
  1574. 'l_status' => 0,
  1575. 'l_print' => 0
  1576. ];
  1577. $l_res = $large->save($l_data);
  1578. if ($l_res === 0){
  1579. $this->error('大件码插入失败');
  1580. }
  1581. $large_id = $large->getLastInsID();
  1582. if ($large_id){
  1583. // //小件码循环插入
  1584. // for ($j=0;$j<$data['tray_num'] and ($j+$i*$data['tray_num'])<$batchList['small_num'];$j++){
  1585. for ($j=0;$j<$data['total_boxes'] and ($j+$i*$data['total_boxes'])<$batchList['total_boxes'];$j++){
  1586. $small = new QcodeSmall();
  1587. $s_flow = $this->intTochar($batchList['s_flow']+$j+$i*$data['tray_num']+$lastNum['last_num'],6);//小件码序号从1开始
  1588. $s_weight = $this->intTochar($batchList['s_weight'],6);
  1589. $small_sign = '000';
  1590. $s_reservation = $this->intTochar($batchList['bach_num'],10);
  1591. $s_reservation = $s_reservation . '0000000000';
  1592. //生成小件码
  1593. $small_code_data = $this->CodeData('AB92',$fixed_code,$small_sign,$print_code,$s_flow,$s_weight,'1',$s_reservation);
  1594. //小码数据
  1595. $s_data = [
  1596. 'large_id'=>$large_id,
  1597. 'bach_id'=>$last_id,
  1598. 'code'=>$small_code_data['code'],
  1599. 'code_cp1'=>$small_code_data['code_cp1'],
  1600. 'code_cp2'=>$small_code_data['code_cp2'],
  1601. 'l_flow'=>$j+1,
  1602. 'print_date'=>$print_code,
  1603. 'create_time'=>time(),
  1604. 'p_nums'=>0,
  1605. 'userid'=>$userinfo['id'],//小码绑定用户id
  1606. 's_weight'=>$batchList['s_weight'],//单个小件重量
  1607. 'status' => 0,
  1608. ];
  1609. $s_res = $small->save($s_data);
  1610. if ($s_res === 0){
  1611. $this->error('小件码插入失败');
  1612. }
  1613. }
  1614. }else{
  1615. $this->error('添加失败');
  1616. }
  1617. }
  1618. }
  1619. $liushui_res = $liushui->name($userinfo['id'].'_'.'qcode_liushui')->where($whereSmall)->update(['last_num'=>$batchList['small_num']]);
  1620. if ($liushui_res === false){
  1621. $this->error('添加失败');
  1622. }
  1623. return json(['code' => 1, 'msg' => '成功', 'data' => '']);
  1624. // $this->success('成功');
  1625. }
  1626. /**
  1627. * 编码补位
  1628. * @param $num
  1629. * @param $len
  1630. * @return string
  1631. */
  1632. function intTochar($num=0,$len){
  1633. //规定的不足的时候自动补足零
  1634. $code=(string)$num;
  1635. $buwei='';
  1636. if(strlen($code)<$len){
  1637. for($i=strlen($code);$i<$len;$i++){
  1638. $buwei.='0';
  1639. }
  1640. }
  1641. return $buwei.$code;
  1642. }
  1643. /**
  1644. * 二维码编码生成
  1645. * @param $sign
  1646. * @param $fixed_code
  1647. * @param $small_num
  1648. * @param $print_date
  1649. * @param $flow
  1650. * @param $weight
  1651. * @param $large_sign
  1652. * @param $reservation
  1653. * @return array
  1654. */
  1655. function CodeData($sign,$fixed_code,$small_num,$print_date,$flow,$weight,$large_sign,$reservation){
  1656. $code=$sign;//4 位固定标志位
  1657. $code.=$fixed_code; // 固定字符串
  1658. $code.=$small_num;//3位 小件数量
  1659. $code.=$print_date;//6 位 日期
  1660. $code.=$flow;//6位打印流水号
  1661. $code.=$weight;//6位辅料重量
  1662. $code.=$large_sign;//大小件标示位
  1663. $code.=$reservation;//20 位 预留号
  1664. //大码数据信息
  1665. $data=[
  1666. 'code'=>str_replace(" ","",$code),
  1667. 'code_cp1'=>$print_date.$flow,
  1668. 'code_cp2'=>$weight.$reservation,//20位补充
  1669. 'print_date'=>time(),
  1670. 'p_nums'=>0,
  1671. ];
  1672. return $data;
  1673. }
  1674. }