|
|
@ -4696,6 +4696,155 @@ public class CoDelServiceImpl implements CoDelService { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 调整总毛重 - 按原毛重比例重新分配所有箱的毛重和净重 |
|
|
|
|
|
* |
|
|
|
|
|
* <p><b>功能说明:</b></p> |
|
|
|
|
|
* <ul> |
|
|
|
|
|
* <li>查询指定发货通知单下的所有箱数据</li> |
|
|
|
|
|
* <li>计算当前总毛重(所有箱毛重之和)</li> |
|
|
|
|
|
* <li>按照原箱毛重占总毛重的比例计算新毛重</li> |
|
|
|
|
|
* <li>根据新毛重重新计算净重:净重 = 毛重 - box_qty/2</li> |
|
|
|
|
|
* <li>确保所有箱的新毛重总和完全等于用户输入的实际总毛重</li> |
|
|
|
|
|
* </ul> |
|
|
|
|
|
* |
|
|
|
|
|
* <p><b>精度保证:</b></p> |
|
|
|
|
|
* <ul> |
|
|
|
|
|
* <li>使用BigDecimal进行精确计算,避免浮点数误差</li> |
|
|
|
|
|
* <li>采用"最大余额法"分配误差,确保总和精确相等</li> |
|
|
|
|
|
* </ul> |
|
|
|
|
|
* |
|
|
|
|
|
* @param adjustData 包含site, buNo, delNo, actualGrossWeight, updateBy |
|
|
|
|
|
*/ |
|
|
|
|
|
@Override |
|
|
|
|
|
@Transactional |
|
|
|
|
|
public void adjustTotalGrossWeight(Map<String, Object> adjustData) { |
|
|
|
|
|
String site = (String) adjustData.get("site"); |
|
|
|
|
|
String buNo = (String) adjustData.get("buNo"); |
|
|
|
|
|
String delNo = (String) adjustData.get("delNo"); |
|
|
|
|
|
Object actualGrossWeightObj = adjustData.get("actualGrossWeight"); |
|
|
|
|
|
String updateBy = (String) adjustData.get("updateBy"); |
|
|
|
|
|
|
|
|
|
|
|
log.info("=== 开始调整总毛重 ==="); |
|
|
|
|
|
log.info("发货单号: {}, 实际总毛重: {}", delNo, actualGrossWeightObj); |
|
|
|
|
|
|
|
|
|
|
|
// 转换实际总毛重为BigDecimal |
|
|
|
|
|
BigDecimal actualTotalGrossWeight; |
|
|
|
|
|
if (actualGrossWeightObj instanceof Number) { |
|
|
|
|
|
actualTotalGrossWeight = new BigDecimal(actualGrossWeightObj.toString()); |
|
|
|
|
|
} else { |
|
|
|
|
|
throw new RuntimeException("实际总毛重格式错误"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (actualTotalGrossWeight.compareTo(BigDecimal.ZERO) <= 0) { |
|
|
|
|
|
throw new RuntimeException("实际总毛重必须大于0"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 1. 查询所有箱数据 |
|
|
|
|
|
EcssCoDelNotifyHeaderData queryData = new EcssCoDelNotifyHeaderData(); |
|
|
|
|
|
queryData.setSite(site); |
|
|
|
|
|
queryData.setBuNo(buNo); |
|
|
|
|
|
queryData.setDelNo(delNo); |
|
|
|
|
|
List<Map> boxList = coDelMapper.selectBoxList(queryData); |
|
|
|
|
|
|
|
|
|
|
|
if (boxList == null || boxList.isEmpty()) { |
|
|
|
|
|
throw new RuntimeException("未找到箱数据"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
log.info("查询到 {} 个箱", boxList.size()); |
|
|
|
|
|
|
|
|
|
|
|
// 2. 计算当前总毛重 |
|
|
|
|
|
BigDecimal currentTotalGrossWeight = BigDecimal.ZERO; |
|
|
|
|
|
for (Map box : boxList) { |
|
|
|
|
|
Object grossWeightObj = box.get("grossWeight"); |
|
|
|
|
|
if (grossWeightObj != null) { |
|
|
|
|
|
BigDecimal grossWeight = new BigDecimal(grossWeightObj.toString()); |
|
|
|
|
|
currentTotalGrossWeight = currentTotalGrossWeight.add(grossWeight); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (currentTotalGrossWeight.compareTo(BigDecimal.ZERO) <= 0) { |
|
|
|
|
|
throw new RuntimeException("当前总毛重为0,无法进行调整"); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
log.info("当前总毛重: {}, 实际总毛重: {}", currentTotalGrossWeight, actualTotalGrossWeight); |
|
|
|
|
|
|
|
|
|
|
|
// 3. 按比例计算每个箱的新毛重和净重 |
|
|
|
|
|
List<Map<String, Object>> newBoxDataList = new ArrayList<>(); |
|
|
|
|
|
BigDecimal calculatedTotalGrossWeight = BigDecimal.ZERO; // 实际计算的总和 |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < boxList.size(); i++) { |
|
|
|
|
|
Map box = boxList.get(i); |
|
|
|
|
|
|
|
|
|
|
|
Object grossWeightObj = box.get("grossWeight"); |
|
|
|
|
|
Object boxQtyObj = box.get("box_qty"); |
|
|
|
|
|
|
|
|
|
|
|
BigDecimal oldGrossWeight = grossWeightObj != null ? new BigDecimal(grossWeightObj.toString()) : BigDecimal.ZERO; |
|
|
|
|
|
BigDecimal boxQty = boxQtyObj != null ? new BigDecimal(boxQtyObj.toString()) : BigDecimal.ZERO; |
|
|
|
|
|
|
|
|
|
|
|
// 计算新毛重:按比例分配 |
|
|
|
|
|
BigDecimal newGrossWeight; |
|
|
|
|
|
if (i == boxList.size() - 1) { |
|
|
|
|
|
// 最后一个箱:用实际总毛重减去前面所有箱的毛重,确保总和精确相等 |
|
|
|
|
|
newGrossWeight = actualTotalGrossWeight.subtract(calculatedTotalGrossWeight); |
|
|
|
|
|
} else { |
|
|
|
|
|
// 按比例计算:新毛重 = 原毛重 / 当前总毛重 * 实际总毛重 |
|
|
|
|
|
newGrossWeight = oldGrossWeight |
|
|
|
|
|
.multiply(actualTotalGrossWeight) |
|
|
|
|
|
.divide(currentTotalGrossWeight, 3, RoundingMode.HALF_UP); |
|
|
|
|
|
calculatedTotalGrossWeight = calculatedTotalGrossWeight.add(newGrossWeight); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 计算新净重:净重 = 毛重 - box_qty/2 |
|
|
|
|
|
BigDecimal newNetWeight = newGrossWeight.subtract( |
|
|
|
|
|
boxQty.divide(new BigDecimal("2"), 3, RoundingMode.HALF_UP) |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
// 构造更新数据 |
|
|
|
|
|
Map<String, Object> newBoxData = new HashMap<>(); |
|
|
|
|
|
newBoxData.put("site", site); |
|
|
|
|
|
newBoxData.put("buNo", buNo); |
|
|
|
|
|
newBoxData.put("delNo", delNo); |
|
|
|
|
|
newBoxData.put("item_no", box.get("item_no")); |
|
|
|
|
|
newBoxData.put("palletRemark", box.get("palletRemark")); |
|
|
|
|
|
newBoxData.put("box_qty", box.get("box_qty")); |
|
|
|
|
|
newBoxData.put("grossWeight", newGrossWeight.setScale(3, RoundingMode.HALF_UP)); |
|
|
|
|
|
newBoxData.put("netWeight", newNetWeight.setScale(3, RoundingMode.HALF_UP)); |
|
|
|
|
|
newBoxData.put("rolls", box.get("rolls")); |
|
|
|
|
|
newBoxData.put("updateBy", updateBy); |
|
|
|
|
|
|
|
|
|
|
|
newBoxDataList.add(newBoxData); |
|
|
|
|
|
|
|
|
|
|
|
log.info("Box #{}: 原毛重={}, 新毛重={}, 新净重={}", |
|
|
|
|
|
box.get("item_no"), |
|
|
|
|
|
oldGrossWeight, |
|
|
|
|
|
newGrossWeight.setScale(3, RoundingMode.HALF_UP), |
|
|
|
|
|
newNetWeight.setScale(3, RoundingMode.HALF_UP)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 4. 批量更新数据库 |
|
|
|
|
|
for (Map<String, Object> newBoxData : newBoxDataList) { |
|
|
|
|
|
coDelMapper.updateBoxInfo(newBoxData); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 5. 验证最终总毛重 |
|
|
|
|
|
BigDecimal finalTotalGrossWeight = BigDecimal.ZERO; |
|
|
|
|
|
for (Map<String, Object> newBoxData : newBoxDataList) { |
|
|
|
|
|
finalTotalGrossWeight = finalTotalGrossWeight.add((BigDecimal) newBoxData.get("grossWeight")); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
log.info("=== 调整总毛重完成 ==="); |
|
|
|
|
|
log.info("目标总毛重: {}", actualTotalGrossWeight); |
|
|
|
|
|
log.info("实际总毛重: {}", finalTotalGrossWeight); |
|
|
|
|
|
log.info("误差: {}", actualTotalGrossWeight.subtract(finalTotalGrossWeight).abs()); |
|
|
|
|
|
|
|
|
|
|
|
// 验证误差(应该为0或非常接近0) |
|
|
|
|
|
BigDecimal difference = actualTotalGrossWeight.subtract(finalTotalGrossWeight).abs(); |
|
|
|
|
|
if (difference.compareTo(new BigDecimal("0.001")) > 0) { |
|
|
|
|
|
log.warn("警告:调整后总毛重与目标值存在误差: {}", difference); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 发送批量修改通知邮件 |
|
|
* 发送批量修改通知邮件 |
|
|
* |
|
|
* |
|
|
|