package com.zy.asrs.controller; import com.baomidou.mybatisplus.annotations.TableField; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.plugins.Page; import com.core.common.Cools; import com.core.common.R; import com.core.annotations.ManagerAuth; import com.zy.asrs.entity.MaterialReceive; import com.zy.asrs.service.MaterialReceiveService; import com.zy.common.web.BaseController; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import com.core.common.DateUtils; import java.lang.reflect.Field; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController public class MaterialReceiveController extends BaseController { @Autowired private MaterialReceiveService materialReceiveService; @RequestMapping(value = "/materialReceive/{id}/auth") @ManagerAuth public R get(@PathVariable("id") String id) { return R.ok(materialReceiveService.selectById(String.valueOf(id))); } @RequestMapping(value = "/materialReceive/list/auth") @ManagerAuth public R list(@RequestParam(defaultValue = "1") Integer curr, @RequestParam(defaultValue = "1000") Integer limit, @RequestParam(required = false) String orderByField, @RequestParam(required = false) String orderByType, @RequestParam(required = false) String condition, @RequestParam(required = false) Boolean pdaQuery, @RequestParam Map param) { EntityWrapper wrapper = new EntityWrapper<>(); excludeTrash(param); // 移除pdaQuery参数,因为它不是数据库字段,只是控制参数 param.remove("pdaQuery"); convert(param, wrapper); allLike(MaterialReceive.class, param.keySet(), wrapper, condition); // 参考其他出库模块,PDA出库查询时过滤掉已全部出库的物料(只显示还有剩余数量的) // 通过 pdaQuery 参数判断是否是PDA出库查询 if (pdaQuery != null && pdaQuery) { // PDA出库查询:只显示剩余数量大于0的记录 wrapper.gt("remain_qty", 0); } if (!Cools.isEmpty(orderByField)) { wrapper.orderBy(humpToLine(orderByField), "asc".equals(orderByType)); } return R.ok(materialReceiveService.selectPage(new Page<>(curr, limit), wrapper)); } @RequestMapping(value = "/materialReceive/batchSave/auth", method = RequestMethod.POST) @ManagerAuth public R batchSave(@RequestBody List> dataList) { if (Cools.isEmpty(dataList)) { return R.error("数据不能为空"); } int successCount = 0; int updateCount = 0; for (Map data : dataList) { try { // 检查是否已存在(根据soCode和invCode和finterid唯一标识) String soCode = data.get("soCode") != null ? String.valueOf(data.get("soCode")) : null; String invCode = data.get("invCode") != null ? String.valueOf(data.get("invCode")) : null; Integer finterid = null; if (data.get("finterid") != null) { try { finterid = Integer.valueOf(String.valueOf(data.get("finterid"))); } catch (Exception e) { // 忽略转换错误 } } MaterialReceive existRecord = null; if (soCode != null && invCode != null && finterid != null) { existRecord = materialReceiveService.selectOne(new EntityWrapper() .eq("so_code", soCode) .eq("inv_code", invCode) .eq("finterid", finterid)); } MaterialReceive materialReceive; if (existRecord != null) { // 已存在,更新数据(不覆盖出库相关字段) materialReceive = existRecord; updateCount++; } else { // 不存在,创建新记录 materialReceive = new MaterialReceive(); materialReceive.setCreateTime(new Date()); // 初始化出库相关字段 materialReceive.setOutQty(BigDecimal.ZERO); materialReceive.setRemainQty(data.get("qty") != null ? new BigDecimal(String.valueOf(data.get("qty"))) : BigDecimal.ZERO); materialReceive.setIsAllOut(0); successCount++; } // 更新/设置字段 materialReceive.setSoCode(soCode); materialReceive.setFbillno(data.get("fbillno") != null ? String.valueOf(data.get("fbillno")) : null); materialReceive.setInvCode(invCode); materialReceive.setInvName(data.get("invName") != null ? String.valueOf(data.get("invName")) : null); materialReceive.setInvStd(data.get("invStd") != null ? String.valueOf(data.get("invStd")) : null); // 数量字段处理(优先使用fqty,如果没有则使用qty) BigDecimal qty = null; if (data.get("fqty") != null) { qty = new BigDecimal(String.valueOf(data.get("fqty"))); materialReceive.setFqty(qty); } else if (data.get("qty") != null) { qty = new BigDecimal(String.valueOf(data.get("qty"))); materialReceive.setQty(qty); } if (data.get("fauxqty") != null) { materialReceive.setFauxqty(new BigDecimal(String.valueOf(data.get("fauxqty")))); } // 如果已存在,更新剩余数量(基于原始数量) if (existRecord == null && qty != null) { materialReceive.setRemainQty(qty); } else if (existRecord != null && qty != null) { // 已存在时,如果数量有变化,重新计算剩余数量 BigDecimal originalQty = existRecord.getFqty() != null ? existRecord.getFqty() : (existRecord.getQty() != null ? existRecord.getQty() : BigDecimal.ZERO); BigDecimal outQty = existRecord.getOutQty() != null ? existRecord.getOutQty() : BigDecimal.ZERO; // 如果新数量与原始数量不同,说明数量更新了,需要重新计算剩余数量 if (qty.compareTo(originalQty) != 0) { // 数量变化,剩余数量 = 新数量 - 已出库数量 materialReceive.setRemainQty(qty.subtract(outQty)); } else { // 数量没变化,保持原有剩余数量 materialReceive.setRemainQty(existRecord.getRemainQty()); } } materialReceive.setUnit(data.get("unit") != null ? String.valueOf(data.get("unit")) : null); materialReceive.setDepName(data.get("depName") != null ? String.valueOf(data.get("depName")) : null); materialReceive.setDepCode(data.get("depCode") != null ? String.valueOf(data.get("depCode")) : null); if (data.get("depId") != null) { try { materialReceive.setDepId(Integer.valueOf(String.valueOf(data.get("depId")))); } catch (Exception e) { // 忽略转换错误 } } if (data.get("fworkshop") != null) { try { materialReceive.setFworkshop(Integer.valueOf(String.valueOf(data.get("fworkshop")))); } catch (Exception e) { // 忽略转换错误 } } if (data.get("whId") != null) { try { materialReceive.setWhId(Integer.valueOf(String.valueOf(data.get("whId")))); } catch (Exception e) { // 忽略转换错误 } } materialReceive.setWhName(data.get("whName") != null ? String.valueOf(data.get("whName")) : null); if (data.get("fplancommitdate") != null && !Cools.isEmpty(String.valueOf(data.get("fplancommitdate")))) { try { String dateStr = String.valueOf(data.get("fplancommitdate")); java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd"); materialReceive.setFplancommitdate(sdf.parse(dateStr)); } catch (Exception ex) { // 忽略日期解析错误 } } if (data.get("fplanfinishdate") != null && !Cools.isEmpty(String.valueOf(data.get("fplanfinishdate")))) { try { String dateStr = String.valueOf(data.get("fplanfinishdate")); java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd"); materialReceive.setFplanfinishdate(sdf.parse(dateStr)); } catch (Exception ex) { // 忽略日期解析错误 } } if (finterid != null) { materialReceive.setFinterid(finterid); } if (data.get("fitemid") != null) { try { materialReceive.setFitemid(Integer.valueOf(String.valueOf(data.get("fitemid")))); } catch (Exception e) { // 忽略转换错误 } } if (data.get("funitid") != null) { try { materialReceive.setFunitid(Integer.valueOf(String.valueOf(data.get("funitid")))); } catch (Exception e) { // 忽略转换错误 } } // 将其他字段存储到ext_data(JSON格式),用于校验生产领料出库数量 Map extDataMap = new HashMap<>(); // 已映射到数据库表字段的字段列表(这些字段不需要存储在ext_data中) java.util.Set mappedFields = new java.util.HashSet<>(); mappedFields.add("soCode"); mappedFields.add("fbillno"); mappedFields.add("invCode"); mappedFields.add("invName"); mappedFields.add("invStd"); mappedFields.add("qty"); mappedFields.add("fqty"); mappedFields.add("fauxqty"); mappedFields.add("unit"); mappedFields.add("depName"); mappedFields.add("depCode"); mappedFields.add("depId"); mappedFields.add("fworkshop"); mappedFields.add("whId"); mappedFields.add("whName"); mappedFields.add("fplancommitdate"); mappedFields.add("fplanfinishdate"); mappedFields.add("finterid"); mappedFields.add("fitemid"); mappedFields.add("funitid"); // 将所有未映射的字段存储到ext_data中(包含所有打印预览和打印相关的字段) for (Map.Entry entry : data.entrySet()) { String key = entry.getKey(); if (!mappedFields.contains(key) && entry.getValue() != null) { extDataMap.put(key, entry.getValue()); } } // 始终更新ext_data,即使为空也要存储(用于后续扩展) materialReceive.setExtData(com.alibaba.fastjson.JSON.toJSONString(extDataMap)); materialReceive.setSyncTime(new Date()); materialReceive.setUpdateTime(new Date()); // 保存或更新 if (existRecord != null) { materialReceiveService.updateById(materialReceive); } else { materialReceiveService.insert(materialReceive); } } catch (Exception e) { // 记录失败的记录,继续处理下一条 e.printStackTrace(); } } return R.ok("成功保存 " + successCount + " 条新数据,更新 " + updateCount + " 条已存在数据"); } @RequestMapping(value = "/materialReceive/update/auth") @ManagerAuth public R update(MaterialReceive materialReceive) { if (Cools.isEmpty(materialReceive) || null == materialReceive.getId()) { return R.error(); } materialReceive.setUpdateTime(new Date()); materialReceiveService.updateById(materialReceive); return R.ok(); } @RequestMapping(value = "/materialReceive/updateOutQty/auth", method = RequestMethod.POST) @ManagerAuth public R updateOutQty(@RequestBody Map param) { Long id = Long.valueOf(String.valueOf(param.get("id"))); BigDecimal addOutQty = new BigDecimal(String.valueOf(param.get("outQty"))); // 本次出库数量 MaterialReceive materialReceive = materialReceiveService.selectById(id); if (materialReceive == null) { return R.error("记录不存在"); } // 累加出库数量 BigDecimal currentOutQty = materialReceive.getOutQty() != null ? materialReceive.getOutQty() : BigDecimal.ZERO; BigDecimal newOutQty = currentOutQty.add(addOutQty); materialReceive.setOutQty(newOutQty); // 计算剩余数量(优先使用fqty,如果没有则使用qty) BigDecimal qty = materialReceive.getFqty() != null ? materialReceive.getFqty() : (materialReceive.getQty() != null ? materialReceive.getQty() : BigDecimal.ZERO); BigDecimal remainQty = qty.subtract(newOutQty); materialReceive.setRemainQty(remainQty.compareTo(BigDecimal.ZERO) > 0 ? remainQty : BigDecimal.ZERO); // 判断是否全部出库完成 materialReceive.setIsAllOut(remainQty.compareTo(BigDecimal.ZERO) <= 0 ? 1 : 0); materialReceive.setUpdateTime(new Date()); materialReceiveService.updateById(materialReceive); return R.ok(); } @RequestMapping(value = "/materialReceive/checkSyncStatus/auth") @ManagerAuth public R checkSyncStatus(@RequestParam String soCode, @RequestParam(required = false) String invCode, @RequestParam(required = false) String fbillno) { EntityWrapper wrapper = new EntityWrapper<>(); wrapper.eq("so_code", soCode); wrapper.eq("fbillno", fbillno); if (!Cools.isEmpty(invCode)) { wrapper.eq("inv_code", invCode); } List list = materialReceiveService.selectList(wrapper); Map result = new HashMap<>(); if (Cools.isEmpty(list)) { result.put("synced", false); result.put("allOut", false); result.put("message", "该生产单号未同步到WMS"); return R.ok(result); } // 检查是否全部出库完成 boolean allOut = true; List> notOutList = new ArrayList<>(); for (MaterialReceive mr : list) { if (mr.getIsAllOut() == null || mr.getIsAllOut() != 1) { allOut = false; Map notOutItem = new HashMap<>(); notOutItem.put("invCode", mr.getInvCode()); notOutItem.put("invName", mr.getInvName()); notOutItem.put("remainQty", mr.getRemainQty()); notOutList.add(notOutItem); } } result.put("synced", true); result.put("allOut", allOut); result.put("records", list); if (!allOut && !notOutList.isEmpty()) { result.put("notOutList", notOutList); result.put("message", "部分物料未全部出库完成"); } else if (allOut) { result.put("message", "全部物料已出库完成"); } return R.ok(result); } private void convert(Map map, EntityWrapper wrapper) { for (Map.Entry entry : map.entrySet()) { String fieldName = entry.getKey(); String columnName = getColumnName(MaterialReceive.class, fieldName); String val = String.valueOf(entry.getValue()); if (val.contains(RANGE_TIME_LINK)) { String[] dates = val.split(RANGE_TIME_LINK); wrapper.ge(columnName, DateUtils.convert(dates[0])); wrapper.le(columnName, DateUtils.convert(dates[1])); } else { wrapper.like(columnName, val); } } } /** * 根据实体类字段名获取数据库列名 * @param cls 实体类 * @param fieldName Java字段名(驼峰命名) * @return 数据库列名(下划线命名) */ private String getColumnName(Class cls, String fieldName) { for (Field field : Cools.getAllFields(cls)) { if (field.getName().equals(fieldName)) { if (field.isAnnotationPresent(TableField.class)) { TableField annotation = field.getAnnotation(TableField.class); if (!annotation.exist()) { continue; } String column = annotation.value(); if (!Cools.isEmpty(column)) { return column; } } // 如果没有@TableField注解,使用humpToLine转换 return humpToLine(fieldName); } } // 如果找不到字段,使用humpToLine转换 return humpToLine(fieldName); } @RequestMapping(value = "/materialReceive/delete/auth") @ManagerAuth public R delete(@RequestParam String param) { com.alibaba.fastjson.JSONArray jsonArray = com.alibaba.fastjson.JSONArray.parseArray(param); List list = jsonArray.toJavaList(MaterialReceive.class); if (Cools.isEmpty(list)) { return R.error("请选择要删除的数据"); } for (MaterialReceive entity : list) { materialReceiveService.deleteById(entity.getId()); } return R.ok(); } }