✨ 完善配载草稿确认与运单数量/里程落库
配载暂存免校验且确认生成待执行正式单,草稿仅预占运单不改其状态;里程 -1 对外置空;多货物运单按 goodsJson 合计回写数量并用于应收应付。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+32
-3
@@ -109,7 +109,7 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean saveDraft(LoadingManage loadingManage) {
|
||||
prepare(loadingManage);
|
||||
validate(loadingManage, true);
|
||||
// 暂存不做任何业务校验,允许空运单、缺字段直接落草稿
|
||||
List<Long> oldWaybillIds = new ArrayList<>();
|
||||
// 新建暂存为草稿;编辑已有单据时保持原业务状态(如待执行),避免被改回草稿
|
||||
String businessStatus = STATUS_DRAFT;
|
||||
@@ -128,10 +128,14 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
||||
if (Func.isEmpty(loadingManage.getLoadingNo())) {
|
||||
loadingManage.setLoadingNo(nextCode());
|
||||
}
|
||||
validateWaybillsAvailable(loadingManage, waybillIds(loadingManage.getWaybillIdsJson()));
|
||||
validateCarrierContract(loadingManage, false);
|
||||
boolean result = saveOrUpdate(loadingManage);
|
||||
syncAssociatedWaybills(loadingManage, businessStatus, oldWaybillIds);
|
||||
// 草稿仅预占运单号,不把运单业务状态改成 draft;正式确认时再完整同步为待执行
|
||||
if (STATUS_DRAFT.equals(businessStatus)) {
|
||||
syncDraftWaybillReservation(loadingManage, oldWaybillIds);
|
||||
} else {
|
||||
syncAssociatedWaybills(loadingManage, businessStatus, oldWaybillIds);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -149,6 +153,7 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
||||
loadingManage.setDeptName(oldRecord.getDeptName());
|
||||
}
|
||||
prepareCreateOrUpdate(loadingManage);
|
||||
// 确认提交:草稿/新建统一生成正式配载单(待执行)
|
||||
loadingManage.setBusinessStatus(STATUS_PENDING);
|
||||
if (Func.isEmpty(loadingManage.getLoadingNo())) {
|
||||
loadingManage.setLoadingNo(nextCode());
|
||||
@@ -616,6 +621,11 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
||||
loadingManage.setRouteJson(TransportBusinessSupport.trimToNull(loadingManage.getRouteJson()));
|
||||
loadingManage.setTaskInfoJson(TransportBusinessSupport.trimToNull(loadingManage.getTaskInfoJson()));
|
||||
loadingManage.setDeptName(TransportBusinessSupport.trimToNull(loadingManage.getDeptName()));
|
||||
// 未填写里程禁止落库 -1 占位值,统一存 null
|
||||
if (loadingManage.getMileage() != null
|
||||
&& loadingManage.getMileage().compareTo(BigDecimal.valueOf(-1)) == 0) {
|
||||
loadingManage.setMileage(null);
|
||||
}
|
||||
if (Func.isEmpty(loadingManage.getDeptId())) {
|
||||
Dept dept = TransportBusinessSupport.currentDept("配载管理");
|
||||
loadingManage.setDeptId(dept.getId());
|
||||
@@ -813,6 +823,25 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
||||
.set(Waybill::getCurrentProcessNode, loadingManage.getCurrentProcessNode()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 草稿阶段仅预占运单(写入 loadingNo),不改写运单业务状态。
|
||||
* 避免暂存把运单打成 draft,导致确认生成正式配载单时状态异常。
|
||||
*/
|
||||
private void syncDraftWaybillReservation(LoadingManage loadingManage, List<Long> oldWaybillIds) {
|
||||
List<Long> newWaybillIds = waybillIds(loadingManage.getWaybillIdsJson());
|
||||
if (Func.isNotEmpty(oldWaybillIds)) {
|
||||
List<Long> removedIds = new ArrayList<>(oldWaybillIds);
|
||||
removedIds.removeAll(newWaybillIds);
|
||||
releaseAssociatedWaybills(removedIds, STATUS_PENDING);
|
||||
}
|
||||
if (Func.isEmpty(newWaybillIds)) {
|
||||
return;
|
||||
}
|
||||
waybillMapper.update(null, Wrappers.<Waybill>lambdaUpdate()
|
||||
.in(Waybill::getId, newWaybillIds)
|
||||
.set(Waybill::getLoadingNo, loadingManage.getLoadingNo()));
|
||||
}
|
||||
|
||||
private void releaseAssociatedWaybills(List<Long> waybillIds, String status) {
|
||||
if (Func.isEmpty(waybillIds)) {
|
||||
return;
|
||||
|
||||
+16
-1
@@ -1463,7 +1463,7 @@ public class ReceivablePayableDetailServiceImpl
|
||||
detail.setTransportType(waybill.getTransportType());
|
||||
detail.setCargoName(waybill.getCargoName());
|
||||
detail.setCargoType(waybill.getCargoType());
|
||||
detail.setTransportQuantity(waybill.getQuantity());
|
||||
detail.setTransportQuantity(resolveWaybillTransportQuantity(waybill));
|
||||
detail.setQuantityUnit(waybill.getQuantityUnit());
|
||||
detail.setMileage(normalizeGeneratedMileage(waybill.getMileage()));
|
||||
detail.setBatchNo(waybill.getBatchNo());
|
||||
@@ -1477,6 +1477,21 @@ public class ReceivablePayableDetailServiceImpl
|
||||
return detail;
|
||||
}
|
||||
|
||||
/**
|
||||
* 多货物运单优先按 goodsJson 数量合计作为运输总量,避免主表 quantity 只落了首行。
|
||||
*/
|
||||
private BigDecimal resolveWaybillTransportQuantity(Waybill waybill) {
|
||||
List<Map<String, Object>> goods = parseList(waybill.getGoodsJson());
|
||||
if (goods.size() > 1) {
|
||||
BigDecimal total = goods.stream().map(item -> decimal(item.get("quantity")))
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
if (total.signum() > 0) {
|
||||
return total;
|
||||
}
|
||||
}
|
||||
return money(waybill.getQuantity());
|
||||
}
|
||||
|
||||
private ReceivablePayableDetail buildMasterOrderDetail(MasterOrder masterOrder, ContractManage contract,
|
||||
List<Waybill> masterGoods, String settlementType,
|
||||
List<ReceivablePayableCargoFee> fees, BigDecimal unitPrice) {
|
||||
|
||||
+36
@@ -1358,6 +1358,8 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
||||
if (isSentinelMinusOne(waybill.getQuantity())) waybill.setQuantity(null);
|
||||
if (isSentinelMinusOne(waybill.getMileage())) waybill.setMileage(null);
|
||||
if (isSentinelMinusOne(waybill.getUnitPrice())) waybill.setUnitPrice(null);
|
||||
if (isSentinelMinusOne(waybill.getOtherFeeTotal())) waybill.setOtherFeeTotal(null);
|
||||
syncQuantityFromGoodsJson(waybill);
|
||||
waybill.setWaybillNo(TransportBusinessSupport.trimToNull(waybill.getWaybillNo()));
|
||||
waybill.setProjectName(TransportBusinessSupport.trimToNull(waybill.getProjectName()));
|
||||
waybill.setContractName(TransportBusinessSupport.trimToNull(waybill.getContractName()));
|
||||
@@ -1425,6 +1427,40 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
||||
return value != null && value.compareTo(BigDecimal.ONE.negate()) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 完整录入多货物时,运单主表 quantity 按 goodsJson 数量合计回写,避免只落首行数量。
|
||||
*/
|
||||
private void syncQuantityFromGoodsJson(Waybill waybill) {
|
||||
if (waybill == null || Func.isEmpty(waybill.getGoodsJson())) {
|
||||
return;
|
||||
}
|
||||
List<Map> goodsList;
|
||||
try {
|
||||
goodsList = JsonUtil.parseArray(waybill.getGoodsJson(), Map.class);
|
||||
} catch (Exception exception) {
|
||||
return;
|
||||
}
|
||||
if (Func.isEmpty(goodsList) || goodsList.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
boolean hasQuantity = false;
|
||||
for (Map goods : goodsList) {
|
||||
if (goods == null || goods.get("quantity") == null) {
|
||||
continue;
|
||||
}
|
||||
BigDecimal quantity = new BigDecimal(String.valueOf(goods.get("quantity")).trim());
|
||||
if (isSentinelMinusOne(quantity)) {
|
||||
continue;
|
||||
}
|
||||
hasQuantity = true;
|
||||
total = total.add(quantity);
|
||||
}
|
||||
if (hasQuantity) {
|
||||
waybill.setQuantity(total);
|
||||
}
|
||||
}
|
||||
|
||||
private void validate(Waybill waybill) {
|
||||
TransportBusinessSupport.validateRequired(waybill.getProjectName(), "项目不能为空");
|
||||
TransportBusinessSupport.validateRequired(waybill.getContractName(), "客户合同不能为空");
|
||||
|
||||
+6
@@ -12,6 +12,7 @@ import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.transport.pojo.entity.LoadingManage;
|
||||
import org.springblade.transport.pojo.vo.LoadingManageVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -33,6 +34,11 @@ public class LoadingManageWrapper extends BaseEntityWrapper<LoadingManage, Loadi
|
||||
Long currentDeptId = Func.firstLong(AuthUtil.getDeptId());
|
||||
loadingManageVO.setReadonly(currentDeptId != null && !Objects.equals(loadingManage.getDeptId(), currentDeptId));
|
||||
loadingManageVO.setBusinessStatusName(businessStatusName(loadingManage.getBusinessStatus()));
|
||||
// 未维护里程的占位值 -1 对外展示为空
|
||||
if (loadingManageVO.getMileage() != null
|
||||
&& loadingManageVO.getMileage().compareTo(BigDecimal.valueOf(-1)) == 0) {
|
||||
loadingManageVO.setMileage(null);
|
||||
}
|
||||
return loadingManageVO;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user