|
|
|
@ -2981,7 +2981,11 @@ public class CoDelServiceImpl implements CoDelService { |
|
|
|
Map<Object, Map> palletMap = palletDetailList.stream().collect(Collectors.toMap( o -> o.get("item_no"), o -> o)); |
|
|
|
// 装箱数据 |
|
|
|
List<EcssCoDelPalletHeaderData> palletHeaderDataList = coDelMapper.searchEcssCoDelPalletHeaderData(notifyHeader);// 总托数 |
|
|
|
int totalPlt = palletHeaderDataList.isEmpty()?0:palletHeaderDataList.get(0).getPalletQty(); |
|
|
|
Integer totalPlt = palletHeaderDataList.stream() |
|
|
|
.map(EcssCoDelPalletHeaderData::getPalletQty) |
|
|
|
.filter(Objects::nonNull) // 防止空指针 |
|
|
|
.reduce(0, Integer::sum); |
|
|
|
|
|
|
|
Map poNoMap = new HashMap<>(); |
|
|
|
for (int i = 0; i < detailList.size(); i++) { |
|
|
|
Map eorder = detailList.get(i); |
|
|
|
@ -3048,6 +3052,15 @@ public class CoDelServiceImpl implements CoDelService { |
|
|
|
if (palletHeaderDataList.isEmpty()) { |
|
|
|
totalKgs = BigDecimal.valueOf(0.1); |
|
|
|
} |
|
|
|
List<Map> list = coDelMapper.selectBoxList(notifyHeader); |
|
|
|
BigDecimal totalCartons = BigDecimal.valueOf(0.0); |
|
|
|
for (int m = 0; m < list.size(); m++) { |
|
|
|
totalCartons = totalCartons.add(new BigDecimal(list.get(m).get("box_qty") != null ? |
|
|
|
list.get(m).get("box_qty").toString() : "0")); |
|
|
|
} |
|
|
|
if (palletHeaderDataList.isEmpty()) { |
|
|
|
totalPlt = totalCartons.setScale(0, RoundingMode.HALF_UP).intValue(); |
|
|
|
} |
|
|
|
template.addVar("KGS_qty", data.getKgs()!=null?(totalKgs.multiply(BigDecimal.valueOf(totalPlt))).setScale(2, RoundingMode.HALF_UP):""); |
|
|
|
template.addVar("KGS", "KGS"); |
|
|
|
} |
|
|
|
@ -5746,4 +5759,408 @@ public class CoDelServiceImpl implements CoDelService { |
|
|
|
return emailContent.toString(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @Description 导入物料包装属性(每卷数量、每箱卷数、每卷重量、箱重量、箱类型) |
|
|
|
* @param file Excel文件 |
|
|
|
* @param buNo 业务单元编码 |
|
|
|
* @param username 用户名 |
|
|
|
* @param previewOnly 是否仅预览 |
|
|
|
* @return 预览数据或导入结果 |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
@Transactional |
|
|
|
public Map<String, Object> importPartPackageProperties(MultipartFile file, String buNo, String username, boolean previewOnly) { |
|
|
|
Map<String, Object> result = new HashMap<>(); |
|
|
|
List<Map<String, Object>> previewList = new ArrayList<>(); |
|
|
|
List<Map<String, Object>> detailsList = new ArrayList<>(); |
|
|
|
int successCount = 0; |
|
|
|
int failCount = 0; |
|
|
|
|
|
|
|
try { |
|
|
|
// 获取用户的site信息 |
|
|
|
SysUserEntity sysUser = (SysUserEntity) SecurityUtils.getSubject().getPrincipal(); |
|
|
|
String site = sysUser.getSite(); |
|
|
|
|
|
|
|
// 解析Excel文件 |
|
|
|
XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream()); |
|
|
|
XSSFSheet sheet = workbook.getSheetAt(0); |
|
|
|
DataFormatter dataFormatter = new DataFormatter(); |
|
|
|
|
|
|
|
// 从第二行开始(跳过表头) |
|
|
|
int lastRowNum = sheet.getLastRowNum(); |
|
|
|
for (int rowNum = 1; rowNum <= lastRowNum; rowNum++) { |
|
|
|
XSSFRow row = sheet.getRow(rowNum); |
|
|
|
if (row == null) continue; |
|
|
|
|
|
|
|
Map<String, Object> rowData = new HashMap<>(); |
|
|
|
rowData.put("rowNum", rowNum + 1); |
|
|
|
|
|
|
|
try { |
|
|
|
// 读取Excel字段:物料编码、每卷数量、每箱卷数、每卷重量、箱重量(kg)、Box No、长(米)、宽(米)、高(米) |
|
|
|
String sku = getCellValueAsString(row.getCell(0), dataFormatter); |
|
|
|
String rollQtyStr = getCellValueAsString(row.getCell(1), dataFormatter); |
|
|
|
String boxRollsStr = getCellValueAsString(row.getCell(2), dataFormatter); |
|
|
|
String rollWeightStr = getCellValueAsString(row.getCell(3), dataFormatter); |
|
|
|
String boxWeightStr = getCellValueAsString(row.getCell(4), dataFormatter); |
|
|
|
String boxNo = getCellValueAsString(row.getCell(5), dataFormatter); |
|
|
|
String lengthStr = getCellValueAsString(row.getCell(6), dataFormatter); |
|
|
|
String widthStr = getCellValueAsString(row.getCell(7), dataFormatter); |
|
|
|
String heightStr = getCellValueAsString(row.getCell(8), dataFormatter); |
|
|
|
// 跳过空行 |
|
|
|
if (StringUtils.isBlank(sku)) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
rowData.put("buNo", buNo); |
|
|
|
rowData.put("sku", sku); |
|
|
|
rowData.put("rollQty", rollQtyStr); |
|
|
|
rowData.put("boxRolls", boxRollsStr); |
|
|
|
rowData.put("rollWeight", rollWeightStr); |
|
|
|
rowData.put("boxWeight", boxWeightStr); |
|
|
|
rowData.put("boxNo", boxNo); |
|
|
|
rowData.put("length", lengthStr); |
|
|
|
rowData.put("width", widthStr); |
|
|
|
rowData.put("height", heightStr); |
|
|
|
|
|
|
|
// 验证BU |
|
|
|
if (StringUtils.isBlank(buNo)) { |
|
|
|
rowData.put("hasError", true); |
|
|
|
rowData.put("errorMsg", "BU不能为空"); |
|
|
|
previewList.add(rowData); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
// 根据SKU查询物料信息(一个SKU可能对应多个part) |
|
|
|
Map<String, Object> partParams = new HashMap<>(); |
|
|
|
partParams.put("site", site); |
|
|
|
partParams.put("buNo", buNo); |
|
|
|
partParams.put("sku", sku); |
|
|
|
List<PartData> partList = coDelMapper.getPartListBySku(partParams); |
|
|
|
|
|
|
|
if (partList == null || partList.isEmpty()) { |
|
|
|
rowData.put("hasError", true); |
|
|
|
rowData.put("errorMsg", "物料编码不存在"); |
|
|
|
previewList.add(rowData); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
// 收集所有partNo用于显示 |
|
|
|
String partNos = partList.stream().map(PartData::getPartNo).collect(Collectors.joining(",")); |
|
|
|
rowData.put("partNo", partNos); |
|
|
|
rowData.put("partCount", partList.size()); |
|
|
|
rowData.put("hasError", false); |
|
|
|
|
|
|
|
// 预览模式只返回数据,不执行导入 |
|
|
|
if (previewOnly) { |
|
|
|
previewList.add(rowData); |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
// 导入模式:执行数据导入(为所有匹配的part设置属性) |
|
|
|
StringBuilder successMsg = new StringBuilder(); |
|
|
|
StringBuilder failMsg = new StringBuilder(); |
|
|
|
boolean hasSuccess = false; |
|
|
|
boolean hasFail = false; |
|
|
|
int updatedPartCount = 0; |
|
|
|
|
|
|
|
// 处理属性值:每卷数量(ROLLQTY)、每箱卷数(BOXROLLS)、每卷重量(ROLLWEIGHT)、箱重量(BOXWEIGHT) |
|
|
|
String[] itemNos = {"ROLLQTY", "BOXROLLS", "ROLLWEIGHT", "BOXWEIGHT"}; |
|
|
|
String[] itemValues = {rollQtyStr, boxRollsStr, rollWeightStr, boxWeightStr}; |
|
|
|
String[] itemNames = {"每卷数量", "每箱卷数", "每卷重量", "箱重量"}; |
|
|
|
|
|
|
|
// 为每个匹配的part设置属性 |
|
|
|
for (PartData partData : partList) { |
|
|
|
String partNo = partData.getPartNo(); |
|
|
|
|
|
|
|
for (int i = 0; i < itemNos.length; i++) { |
|
|
|
String itemNo = itemNos[i]; |
|
|
|
String itemValue = itemValues[i]; |
|
|
|
String itemName = itemNames[i]; |
|
|
|
|
|
|
|
if (StringUtils.isNotBlank(itemValue)) { |
|
|
|
try { |
|
|
|
Double numValue = Double.parseDouble(itemValue); |
|
|
|
boolean updated = updateOrInsertPartProperty(site, buNo, partNo, itemNo, numValue, username); |
|
|
|
if (updated) { |
|
|
|
hasSuccess = true; |
|
|
|
} |
|
|
|
} catch (NumberFormatException e) { |
|
|
|
if (!failMsg.toString().contains(itemName + "格式错误")) { |
|
|
|
failMsg.append(itemName).append("格式错误; "); |
|
|
|
} |
|
|
|
hasFail = true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
updatedPartCount++; |
|
|
|
} |
|
|
|
|
|
|
|
if (hasSuccess) { |
|
|
|
successMsg.append("属性更新成功(").append(updatedPartCount).append("个物料); "); |
|
|
|
} |
|
|
|
|
|
|
|
// 处理箱类型:Box No(对应packageType)、长、宽、高 |
|
|
|
// 箱类型只需要处理一次,然后为所有part更新packageNo |
|
|
|
if (StringUtils.isNotBlank(boxNo)) { |
|
|
|
try { |
|
|
|
BigDecimal length = StringUtils.isNotBlank(lengthStr) ? new BigDecimal(lengthStr).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP) : null; |
|
|
|
BigDecimal width = StringUtils.isNotBlank(widthStr) ? new BigDecimal(widthStr).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP) : null; |
|
|
|
BigDecimal height = StringUtils.isNotBlank(heightStr) ? new BigDecimal(heightStr).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP) : null; |
|
|
|
|
|
|
|
// 检查箱类型是否存在(根据packageType),不存在则插入,返回packageNo |
|
|
|
String packageNo = checkAndInsertPackageByType(site, buNo, boxNo, length, width, height, username); |
|
|
|
|
|
|
|
// 为所有匹配的part更新packageNo |
|
|
|
for (PartData partData : partList) { |
|
|
|
updatePartPackageNo(site, partData.getPartNo(), packageNo); |
|
|
|
} |
|
|
|
|
|
|
|
successMsg.append("箱类型更新成功(").append(partList.size()).append("个物料); "); |
|
|
|
hasSuccess = true; |
|
|
|
} catch (Exception e) { |
|
|
|
failMsg.append("箱类型处理失败: ").append(e.getMessage()).append("; "); |
|
|
|
hasFail = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 记录结果 |
|
|
|
Map<String, Object> detail = new HashMap<>(); |
|
|
|
detail.put("sku", sku); |
|
|
|
String partInfo = partList.size() > 1 ? "(共" + partList.size() + "个物料)" : ""; |
|
|
|
if (hasSuccess && !hasFail) { |
|
|
|
detail.put("success", true); |
|
|
|
detail.put("message", "物料[" + sku + "]" + partInfo + " " + successMsg.toString()); |
|
|
|
successCount++; |
|
|
|
} else if (hasFail && !hasSuccess) { |
|
|
|
detail.put("success", false); |
|
|
|
detail.put("message", "物料[" + sku + "]" + partInfo + " " + failMsg.toString()); |
|
|
|
failCount++; |
|
|
|
} else if (hasSuccess && hasFail) { |
|
|
|
detail.put("success", true); |
|
|
|
detail.put("message", "物料[" + sku + "]" + partInfo + " 部分成功: " + successMsg.toString() + " 失败: " + failMsg.toString()); |
|
|
|
successCount++; |
|
|
|
} else { |
|
|
|
detail.put("success", true); |
|
|
|
detail.put("message", "物料[" + sku + "]" + partInfo + " 无需更新"); |
|
|
|
successCount++; |
|
|
|
} |
|
|
|
detailsList.add(detail); |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
log.error("处理行{}时发生错误: {}", rowNum + 1, e.getMessage(), e); |
|
|
|
rowData.put("hasError", true); |
|
|
|
rowData.put("errorMsg", "处理失败: " + e.getMessage()); |
|
|
|
if (previewOnly) { |
|
|
|
previewList.add(rowData); |
|
|
|
} else { |
|
|
|
Map<String, Object> detail = new HashMap<>(); |
|
|
|
detail.put("success", false); |
|
|
|
detail.put("message", "行" + (rowNum + 1) + " 处理失败: " + e.getMessage()); |
|
|
|
detailsList.add(detail); |
|
|
|
failCount++; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
workbook.close(); |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
log.error("导入物料包装属性失败: {}", e.getMessage(), e); |
|
|
|
throw new RuntimeException("导入失败: " + e.getMessage()); |
|
|
|
} |
|
|
|
|
|
|
|
if (previewOnly) { |
|
|
|
result.put("data", previewList); |
|
|
|
} else { |
|
|
|
result.put("successCount", successCount); |
|
|
|
result.put("failCount", failCount); |
|
|
|
result.put("details", detailsList); |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 更新或插入物料属性值 |
|
|
|
* @param site 站点 |
|
|
|
* @param buNo 业务单元 |
|
|
|
* @param partNo 物料编号 |
|
|
|
* @param propertiesItemNo 属性项编号 (ROLLQTY/BOXROLLS/ROLLWEIGHT/BOXWEIGHT) |
|
|
|
* @param numValue 数值 |
|
|
|
* @param username 用户名 |
|
|
|
* @return 是否成功 |
|
|
|
*/ |
|
|
|
private boolean updateOrInsertPartProperty(String site, String buNo, String partNo, String propertiesItemNo, Double numValue, String username) { |
|
|
|
String codeNo = "BG001"; |
|
|
|
String recordType = "ECSSPART"; |
|
|
|
|
|
|
|
// 检查属性是否已存在 |
|
|
|
Map<String, Object> checkParams = new HashMap<>(); |
|
|
|
checkParams.put("site", site); |
|
|
|
checkParams.put("buNo", buNo); |
|
|
|
checkParams.put("partNo", partNo); |
|
|
|
checkParams.put("codeNo", codeNo); |
|
|
|
checkParams.put("recordType", recordType); |
|
|
|
checkParams.put("propertiesItemNo", propertiesItemNo); |
|
|
|
|
|
|
|
Map<String, Object> existingProperty = coDelMapper.checkPartPropertyExists(checkParams); |
|
|
|
|
|
|
|
if (existingProperty != null) { |
|
|
|
// 已存在,执行更新 |
|
|
|
Map<String, Object> updateParams = new HashMap<>(); |
|
|
|
updateParams.put("site", site); |
|
|
|
updateParams.put("buNo", buNo); |
|
|
|
updateParams.put("partNo", partNo); |
|
|
|
updateParams.put("codeNo", codeNo); |
|
|
|
updateParams.put("recordType", recordType); |
|
|
|
updateParams.put("propertiesItemNo", propertiesItemNo); |
|
|
|
updateParams.put("numValue", numValue); |
|
|
|
coDelMapper.updatePartPropertyNumValue(updateParams); |
|
|
|
} else { |
|
|
|
// 不存在,执行插入 |
|
|
|
// 获取当前最大的item_no |
|
|
|
Map<String, Object> maxParams = new HashMap<>(); |
|
|
|
maxParams.put("site", site); |
|
|
|
maxParams.put("buNo", buNo); |
|
|
|
maxParams.put("partNo", partNo); |
|
|
|
maxParams.put("codeNo", codeNo); |
|
|
|
maxParams.put("recordType", recordType); |
|
|
|
Double maxItemNo = coDelMapper.getMaxItemNo(maxParams); |
|
|
|
Double newItemNo = (maxItemNo == null) ? 1.0 : maxItemNo + 1.0; |
|
|
|
|
|
|
|
// 获取属性定义信息 |
|
|
|
Map<String, Object> itemParams = new HashMap<>(); |
|
|
|
itemParams.put("site", site); |
|
|
|
itemParams.put("buNo", buNo); |
|
|
|
itemParams.put("itemNo", propertiesItemNo); |
|
|
|
itemParams.put("itemType", recordType); |
|
|
|
Map<String, Object> itemInfo = coDelMapper.getPropertiesItemInfo(itemParams); |
|
|
|
|
|
|
|
// 插入新记录 |
|
|
|
Map<String, Object> insertParams = new HashMap<>(); |
|
|
|
insertParams.put("site", site); |
|
|
|
insertParams.put("buNo", buNo); |
|
|
|
insertParams.put("partNo", partNo); |
|
|
|
insertParams.put("codeNo", codeNo); |
|
|
|
insertParams.put("subCodeSeqNo", 1); |
|
|
|
insertParams.put("subCodeDesc", itemInfo != null ? itemInfo.get("codeDesc") : "基本信息"); |
|
|
|
insertParams.put("itemNo", newItemNo); |
|
|
|
insertParams.put("propertiesItemNo", propertiesItemNo); |
|
|
|
insertParams.put("textValue", null); |
|
|
|
insertParams.put("numValue", numValue); |
|
|
|
insertParams.put("recordType", recordType); |
|
|
|
coDelMapper.insertPartProperty(insertParams); |
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 根据packageType检查并插入箱类型 |
|
|
|
* @param site 站点 |
|
|
|
* @param buNo 业务单元 |
|
|
|
* @param packageType 箱类型(对应Excel中的Box No) |
|
|
|
* @param length 长 |
|
|
|
* @param width 宽 |
|
|
|
* @param height 高 |
|
|
|
* @param username 用户名 |
|
|
|
* @return packageNo 箱编码(用于更新part表) |
|
|
|
*/ |
|
|
|
private String checkAndInsertPackageByType(String site, String buNo, String packageType, BigDecimal length, BigDecimal width, BigDecimal height, String username) { |
|
|
|
// 根据packageType检查箱类型是否存在 |
|
|
|
Map<String, Object> checkParams = new HashMap<>(); |
|
|
|
checkParams.put("site", site); |
|
|
|
checkParams.put("buNo", buNo); |
|
|
|
checkParams.put("packageType", packageType); |
|
|
|
Map<String, Object> existingPackage = coDelMapper.checkPackageExistsByType(checkParams); |
|
|
|
|
|
|
|
String packageNo; |
|
|
|
|
|
|
|
if (existingPackage == null) { |
|
|
|
// 不存在,插入新箱类型 |
|
|
|
// 获取当前最大的packageNo并+1 |
|
|
|
Map<String, Object> maxParams = new HashMap<>(); |
|
|
|
maxParams.put("site", site); |
|
|
|
maxParams.put("buNo", buNo); |
|
|
|
String maxPackageNo = coDelMapper.getMaxPackageNo(maxParams); |
|
|
|
|
|
|
|
// 生成新的packageNo |
|
|
|
if (StringUtils.isBlank(maxPackageNo)) { |
|
|
|
packageNo = buNo.equals("01-Label")?"10001":buNo.equals("03-RFID")?"20001":"30001"; |
|
|
|
} else { |
|
|
|
// 尝试解析并递增 |
|
|
|
try { |
|
|
|
// 尝试纯数字递增 |
|
|
|
int num = Integer.parseInt(maxPackageNo); |
|
|
|
packageNo = String.valueOf(num + 1); |
|
|
|
} catch (NumberFormatException e) { |
|
|
|
// 无法解析,使用时间戳 |
|
|
|
packageNo = (buNo.equals("01-Label")?"1":buNo.equals("03-RFID")?"2":"3") + System.currentTimeMillis(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 计算体积 |
|
|
|
BigDecimal volume = null; |
|
|
|
if (length != null && width != null && height != null) { |
|
|
|
volume = length.multiply(width).multiply(height); |
|
|
|
} |
|
|
|
|
|
|
|
Map<String, Object> insertParams = new HashMap<>(); |
|
|
|
insertParams.put("site", site); |
|
|
|
insertParams.put("buNo", buNo); |
|
|
|
insertParams.put("packageNo", packageNo); |
|
|
|
insertParams.put("packageType", packageType); |
|
|
|
insertParams.put("length", length); |
|
|
|
insertParams.put("width", width); |
|
|
|
insertParams.put("height", height); |
|
|
|
insertParams.put("volume", volume); |
|
|
|
insertParams.put("weight", null); |
|
|
|
insertParams.put("remark", "导入创建"); |
|
|
|
insertParams.put("createBy", username); |
|
|
|
coDelMapper.insertPackage(insertParams); |
|
|
|
} else { |
|
|
|
// 已存在,获取现有的packageNo并更新长宽高 |
|
|
|
packageNo = (String) existingPackage.get("packageNo"); |
|
|
|
|
|
|
|
Map<String, Object> updateParams = new HashMap<>(); |
|
|
|
updateParams.put("site", site); |
|
|
|
updateParams.put("buNo", buNo); |
|
|
|
updateParams.put("packageType", packageType); |
|
|
|
updateParams.put("length", length); |
|
|
|
updateParams.put("width", width); |
|
|
|
updateParams.put("height", height); |
|
|
|
// 计算体积 |
|
|
|
if (length != null && width != null && height != null) { |
|
|
|
updateParams.put("volume", length.multiply(width).multiply(height)); |
|
|
|
} |
|
|
|
updateParams.put("updateBy", username); |
|
|
|
coDelMapper.updatePackageDimensions(updateParams); |
|
|
|
} |
|
|
|
|
|
|
|
return packageNo; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 更新物料的packageNo |
|
|
|
* @param site 站点 |
|
|
|
* @param partNo 物料编号 |
|
|
|
* @param packageNo 箱编码 |
|
|
|
*/ |
|
|
|
private void updatePartPackageNo(String site, String partNo, String packageNo) { |
|
|
|
Map<String, Object> updateParams = new HashMap<>(); |
|
|
|
updateParams.put("site", site); |
|
|
|
updateParams.put("partNo", partNo); |
|
|
|
updateParams.put("packageNo", packageNo); |
|
|
|
coDelMapper.updatePartPackageNo(updateParams); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取单元格值为字符串 |
|
|
|
*/ |
|
|
|
private String getCellValueAsString(Cell cell, DataFormatter dataFormatter) { |
|
|
|
if (cell == null) { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
return dataFormatter.formatCellValue(cell).trim(); |
|
|
|
} |
|
|
|
|
|
|
|
} |