✨ 项目申请平台公司多选,运单导入承运商筛选与复制草稿优化
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+3
-3
@@ -70,10 +70,10 @@ public class ProjectApply extends TenantEntity {
|
||||
@Schema(description = "业务部门")
|
||||
private String businessDeptName;
|
||||
|
||||
@Schema(description = "承办部门ID")
|
||||
private Long undertakeDeptId;
|
||||
@Schema(description = "平台公司ID,多个逗号分隔")
|
||||
private String undertakeDeptId;
|
||||
|
||||
@Schema(description = "承办部门")
|
||||
@Schema(description = "平台公司,多个顿号分隔")
|
||||
private String undertakeDeptName;
|
||||
|
||||
@Schema(description = "项目由来")
|
||||
|
||||
+97
-13
@@ -338,19 +338,23 @@ public class ProjectApplyServiceImpl extends BaseServiceImpl<ProjectApplyMapper,
|
||||
TransportBusinessSupport.validateAllDept(projectApply.getAllDept(), "项目立项");
|
||||
LambdaQueryWrapper<ProjectApply> queryWrapper = Wrappers.<ProjectApply>lambdaQuery().eq(ProjectApply::getIsDeleted, 0);
|
||||
if (TransportBusinessSupport.isAdministrator()) {
|
||||
// 超管默认可查看全部未删除数据;仅在明确指定承办组织时按组织精确筛选。
|
||||
// 超管默认可查看全部未删除数据;仅在明确指定平台公司时按包含匹配筛选。
|
||||
if (Objects.equals(projectApply.getAllDept(), 1) && Func.isNotEmpty(projectApply.getUndertakeDeptId())) {
|
||||
queryWrapper.eq(ProjectApply::getUndertakeDeptId, projectApply.getUndertakeDeptId());
|
||||
applyUndertakeDeptContains(queryWrapper, projectApply.getUndertakeDeptId());
|
||||
}
|
||||
} else if (!Objects.equals(projectApply.getAllDept(), 1)) {
|
||||
Long currentDeptId = TransportBusinessSupport.currentDeptId("项目立项");
|
||||
Long currentUserId = AuthUtil.getUserId();
|
||||
queryWrapper.and(wrapper -> wrapper.eq(ProjectApply::getUndertakeDeptId, currentDeptId)
|
||||
.or().eq(ProjectApply::getCreateUser, currentUserId)
|
||||
.or().eq(ProjectApply::getHandlerUserId, currentUserId)
|
||||
.or().eq(ProjectApply::getPrincipalUserId, currentUserId));
|
||||
queryWrapper.and(wrapper -> {
|
||||
if (currentDeptId != null) {
|
||||
wrapper.apply("FIND_IN_SET({0}, IFNULL(undertake_dept_id,''))", String.valueOf(currentDeptId));
|
||||
}
|
||||
wrapper.or().eq(ProjectApply::getCreateUser, currentUserId)
|
||||
.or().eq(ProjectApply::getHandlerUserId, currentUserId)
|
||||
.or().eq(ProjectApply::getPrincipalUserId, currentUserId);
|
||||
});
|
||||
} else if (Func.isNotEmpty(projectApply.getUndertakeDeptId())) {
|
||||
queryWrapper.eq(ProjectApply::getUndertakeDeptId, projectApply.getUndertakeDeptId());
|
||||
applyUndertakeDeptContains(queryWrapper, projectApply.getUndertakeDeptId());
|
||||
}
|
||||
queryWrapper.like(Func.isNotEmpty(projectApply.getApplyNo()), ProjectApply::getApplyNo, projectApply.getApplyNo())
|
||||
.like(Func.isNotEmpty(projectApply.getProjectCode()), ProjectApply::getProjectCode, projectApply.getProjectCode())
|
||||
@@ -464,6 +468,7 @@ public class ProjectApplyServiceImpl extends BaseServiceImpl<ProjectApplyMapper,
|
||||
}
|
||||
|
||||
private void prepareCreateOrUpdate(ProjectApply projectApply) {
|
||||
normalizeUndertakeDept(projectApply);
|
||||
if (Func.isEmpty(projectApply.getId())) {
|
||||
// 新增项目不产生变更记录,避免客户端误传变更字段导致记录回显。
|
||||
projectApply.setChangeContent(null);
|
||||
@@ -476,12 +481,12 @@ public class ProjectApplyServiceImpl extends BaseServiceImpl<ProjectApplyMapper,
|
||||
}
|
||||
if (Func.isEmpty(projectApply.getUndertakeDeptId())) {
|
||||
Dept dept = TransportBusinessSupport.currentDept("项目立项");
|
||||
projectApply.setUndertakeDeptId(dept.getId());
|
||||
projectApply.setUndertakeDeptId(String.valueOf(dept.getId()));
|
||||
projectApply.setUndertakeDeptName(dept.getDeptName());
|
||||
}
|
||||
if (Func.isEmpty(projectApply.getBusinessDeptId())) {
|
||||
projectApply.setBusinessDeptId(projectApply.getUndertakeDeptId());
|
||||
projectApply.setBusinessDeptName(projectApply.getUndertakeDeptName());
|
||||
projectApply.setBusinessDeptId(firstUndertakeDeptId(projectApply.getUndertakeDeptId()));
|
||||
projectApply.setBusinessDeptName(firstUndertakeDeptName(projectApply.getUndertakeDeptName()));
|
||||
}
|
||||
if (Func.isEmpty(projectApply.getHandlerUserId())) {
|
||||
projectApply.setHandlerUserId(AuthUtil.getUserId());
|
||||
@@ -495,8 +500,11 @@ public class ProjectApplyServiceImpl extends BaseServiceImpl<ProjectApplyMapper,
|
||||
ProjectApply oldRecord = loadEditable(projectApply.getId(), true);
|
||||
projectApply.setApplyNo(oldRecord.getApplyNo());
|
||||
projectApply.setProjectCode(oldRecord.getProjectCode());
|
||||
projectApply.setUndertakeDeptId(oldRecord.getUndertakeDeptId());
|
||||
projectApply.setUndertakeDeptName(oldRecord.getUndertakeDeptName());
|
||||
// 平台公司支持编辑多选保存,不再强制写回旧值
|
||||
if (Func.isEmpty(projectApply.getUndertakeDeptId())) {
|
||||
projectApply.setUndertakeDeptId(oldRecord.getUndertakeDeptId());
|
||||
projectApply.setUndertakeDeptName(oldRecord.getUndertakeDeptName());
|
||||
}
|
||||
}
|
||||
if (Func.isEmpty(projectApply.getEffectiveType())) {
|
||||
projectApply.setEffectiveType(EFFECTIVE_TEMPORARY);
|
||||
@@ -981,10 +989,86 @@ public class ProjectApplyServiceImpl extends BaseServiceImpl<ProjectApplyMapper,
|
||||
}
|
||||
Long currentDeptId = TransportBusinessSupport.currentDeptId("项目立项");
|
||||
Long currentUserId = AuthUtil.getUserId();
|
||||
return Objects.equals(projectApply.getUndertakeDeptId(), currentDeptId)
|
||||
return containsUndertakeDept(projectApply.getUndertakeDeptId(), currentDeptId)
|
||||
|| Objects.equals(projectApply.getCreateUser(), currentUserId)
|
||||
|| Objects.equals(projectApply.getHandlerUserId(), currentUserId)
|
||||
|| Objects.equals(projectApply.getPrincipalUserId(), currentUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台公司多值筛选:历史单 ID 与逗号分隔多 ID 均按包含匹配。
|
||||
*/
|
||||
private void applyUndertakeDeptContains(LambdaQueryWrapper<ProjectApply> queryWrapper, String undertakeDeptId) {
|
||||
if (Func.isBlank(undertakeDeptId) || queryWrapper == null) {
|
||||
return;
|
||||
}
|
||||
List<String> deptIds = Arrays.stream(undertakeDeptId.split("[,,]"))
|
||||
.map(String::trim)
|
||||
.filter(Func::isNotEmpty)
|
||||
.distinct()
|
||||
.toList();
|
||||
if (deptIds.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
queryWrapper.and(wrapper -> {
|
||||
boolean first = true;
|
||||
for (String deptId : deptIds) {
|
||||
if (first) {
|
||||
wrapper.apply("FIND_IN_SET({0}, IFNULL(undertake_dept_id,''))", deptId);
|
||||
first = false;
|
||||
} else {
|
||||
wrapper.or().apply("FIND_IN_SET({0}, IFNULL(undertake_dept_id,''))", deptId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void normalizeUndertakeDept(ProjectApply projectApply) {
|
||||
if (projectApply == null) {
|
||||
return;
|
||||
}
|
||||
List<String> deptIds = Arrays.stream(Func.toStr(projectApply.getUndertakeDeptId()).split("[,,]"))
|
||||
.map(String::trim)
|
||||
.filter(Func::isNotEmpty)
|
||||
.filter(id -> !"-1".equals(id))
|
||||
.distinct()
|
||||
.toList();
|
||||
projectApply.setUndertakeDeptId(deptIds.isEmpty() ? null : String.join(",", deptIds));
|
||||
List<String> deptNames = Arrays.stream(Func.toStr(projectApply.getUndertakeDeptName()).split("[,,、]"))
|
||||
.map(String::trim)
|
||||
.filter(Func::isNotEmpty)
|
||||
.distinct()
|
||||
.toList();
|
||||
projectApply.setUndertakeDeptName(deptNames.isEmpty() ? null : String.join("、", deptNames));
|
||||
}
|
||||
|
||||
private Long firstUndertakeDeptId(String undertakeDeptId) {
|
||||
return Arrays.stream(Func.toStr(undertakeDeptId).split("[,,]"))
|
||||
.map(String::trim)
|
||||
.filter(Func::isNotEmpty)
|
||||
.filter(id -> !"-1".equals(id))
|
||||
.map(Func::toLong)
|
||||
.filter(id -> id != null && id > 0L)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private String firstUndertakeDeptName(String undertakeDeptName) {
|
||||
return Arrays.stream(Func.toStr(undertakeDeptName).split("[,,、]"))
|
||||
.map(String::trim)
|
||||
.filter(Func::isNotEmpty)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private boolean containsUndertakeDept(String undertakeDeptId, Long deptId) {
|
||||
if (deptId == null || Func.isBlank(undertakeDeptId)) {
|
||||
return false;
|
||||
}
|
||||
String target = String.valueOf(deptId);
|
||||
return Arrays.stream(undertakeDeptId.split("[,,]"))
|
||||
.map(String::trim)
|
||||
.anyMatch(target::equals);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+5
@@ -3037,6 +3037,11 @@ public class ReceivablePayableDetailServiceImpl
|
||||
}
|
||||
|
||||
private String formatQuantity(BigDecimal quantity, String unit) {
|
||||
// 无有效运输量(空/0/-1)时不展示数值与单位
|
||||
if (quantity == null || quantity.compareTo(BigDecimal.ZERO) == 0
|
||||
|| quantity.compareTo(BigDecimal.valueOf(-1)) == 0) {
|
||||
return "-";
|
||||
}
|
||||
return money(quantity).stripTrailingZeros().toPlainString() + (unit == null ? "" : " " + unit);
|
||||
}
|
||||
|
||||
|
||||
+55
-3
@@ -342,10 +342,11 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl<WaybillImport
|
||||
.eq(WaybillImportBatch::getIsDeleted, 0)
|
||||
.eq(request.getId() != null, WaybillImportBatch::getId, request.getId())
|
||||
.like(Func.isNotEmpty(request.getBatchNo()), WaybillImportBatch::getBatchNo, request.getBatchNo())
|
||||
.apply(Func.isNotEmpty(request.getCarrierId()), "FIND_IN_SET({0}, carrier_ids)", request.getCarrierId())
|
||||
.eq(Func.isNotEmpty(request.getCarrierName()), WaybillImportBatch::getCarrierName, request.getCarrierName())
|
||||
.eq(Func.isNotEmpty(request.getCreateUser()), WaybillImportBatch::getCreateUser, request.getCreateUser())
|
||||
.orderByDesc(WaybillImportBatch::getCreateTime);
|
||||
// 历史批次可能只落了承运商名称、carrier_ids 为空,筛选时需同时按 ID 与名称兼容匹配
|
||||
applyCarrierFilter(queryWrapper, request.getCarrierId());
|
||||
if (Func.isNotEmpty(request.getCreateTimeStart())) {
|
||||
queryWrapper.ge(WaybillImportBatch::getCreateTime,
|
||||
DateUtil.parse(request.getCreateTimeStart(), DateUtil.PATTERN_DATETIME));
|
||||
@@ -361,6 +362,24 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl<WaybillImport
|
||||
return resultPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 承运商筛选:优先 FIND_IN_SET(carrier_ids),同时兼容仅有 carrier_name 的历史数据。
|
||||
*/
|
||||
private void applyCarrierFilter(LambdaQueryWrapper<WaybillImportBatch> queryWrapper, Long carrierId) {
|
||||
Long normalizedCarrierId = normalizeOptionalId(carrierId);
|
||||
if (normalizedCarrierId == null) {
|
||||
return;
|
||||
}
|
||||
CustomerArchive carrier = customerArchiveService.getById(normalizedCarrierId);
|
||||
String carrierName = carrier == null ? null : Func.toStr(carrier.getFullName()).trim();
|
||||
queryWrapper.and(wrapper -> {
|
||||
wrapper.apply("FIND_IN_SET({0}, IFNULL(carrier_ids,''))", String.valueOf(normalizedCarrierId));
|
||||
if (Func.isNotEmpty(carrierName)) {
|
||||
wrapper.or().eq(WaybillImportBatch::getCarrierName, carrierName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public BusinessRemoveResultVO removeBatches(String ids) {
|
||||
@@ -405,8 +424,9 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl<WaybillImport
|
||||
WaybillImportBatch batch = new WaybillImportBatch();
|
||||
BeanUtil.copyProperties(request, batch);
|
||||
batch.setBatchNo(Func.isEmpty(request.getId()) ? nextCode() : request.getBatchNo());
|
||||
batch.setCarrierIds(joinIds(request.getCarrierIds()));
|
||||
batch.setCarrierName(resolveCarrierNames(request.getCarrierIds(), request.getCarrierName()));
|
||||
List<Long> carrierIds = resolveCarrierIds(request);
|
||||
batch.setCarrierIds(joinIds(carrierIds));
|
||||
batch.setCarrierName(resolveCarrierNames(carrierIds, request.getCarrierName()));
|
||||
batch.setImportStatus(importStatus);
|
||||
batch.setImportType(IMPORT_TYPE_SETTLEMENT.equals(request.getImportType()) ? IMPORT_TYPE_SETTLEMENT : IMPORT_TYPE_WAYBILL);
|
||||
ProjectApply project = projectApplyService.getById(request.getProjectId());
|
||||
@@ -586,6 +606,38 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl<WaybillImport
|
||||
return Func.toLongList(carrierIds).stream().findFirst().orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析承运商 ID 列表:优先 carrierIds,其次 carrierId,最后按承运商名称回查客商档案。
|
||||
*/
|
||||
private List<Long> resolveCarrierIds(WaybillImportBatchRequest request) {
|
||||
if (request == null) {
|
||||
return List.of();
|
||||
}
|
||||
List<Long> carrierIds = Func.isEmpty(request.getCarrierIds())
|
||||
? new ArrayList<>()
|
||||
: request.getCarrierIds().stream()
|
||||
.map(this::normalizeOptionalId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
if (Func.isNotEmpty(carrierIds)) {
|
||||
return carrierIds;
|
||||
}
|
||||
Long carrierId = normalizeOptionalId(request.getCarrierId());
|
||||
if (carrierId != null) {
|
||||
return List.of(carrierId);
|
||||
}
|
||||
String carrierName = Func.toStr(request.getCarrierName()).trim();
|
||||
if (Func.isEmpty(carrierName)) {
|
||||
return List.of();
|
||||
}
|
||||
CustomerArchive carrier = customerArchiveService.getOne(Wrappers.<CustomerArchive>lambdaQuery()
|
||||
.eq(CustomerArchive::getFullName, carrierName)
|
||||
.eq(CustomerArchive::getIsDeleted, 0)
|
||||
.last("limit 1"));
|
||||
return carrier == null || carrier.getId() == null ? List.of() : List.of(carrier.getId());
|
||||
}
|
||||
|
||||
private String resolveCarrierNames(List<Long> carrierIds, String carrierName) {
|
||||
if (Func.isNotEmpty(carrierName)) return carrierName;
|
||||
if (Func.isEmpty(carrierIds)) return null;
|
||||
|
||||
+3
-9
@@ -1344,21 +1344,15 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
||||
target.setFreightJson(source.getFreightJson());
|
||||
target.setAttachmentsJson(source.getAttachmentsJson());
|
||||
target.setRemark(source.getRemark());
|
||||
// 复制后业务状态与原运单保持一致
|
||||
String sourceBusinessStatus = source.getBusinessStatus();
|
||||
target.setBusinessStatus(sourceBusinessStatus);
|
||||
// 复制新建固定为草稿,不沿用原运单业务状态
|
||||
target.setBusinessStatus(STATUS_DRAFT);
|
||||
target.setWaybillNo(nextCode());
|
||||
clearDriverAcceptRecord(target);
|
||||
fillProjectProcessConfig(target);
|
||||
prepare(target);
|
||||
applyDriverAcceptBusinessStatus(target);
|
||||
if (Func.isNotEmpty(sourceBusinessStatus)) {
|
||||
target.setBusinessStatus(sourceBusinessStatus);
|
||||
}
|
||||
target.setBusinessStatus(STATUS_DRAFT);
|
||||
validate(target);
|
||||
save(target);
|
||||
// 原运单已完成时,复制后按合同系统计费规则生成应收应付明细
|
||||
generateReceivablePayableIfCompleted(target);
|
||||
return detail(target.getId());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
-- 平台公司支持多选:ID 逗号分隔,名称顿号分隔
|
||||
ALTER TABLE `blade_project_apply`
|
||||
MODIFY COLUMN `undertake_dept_id` varchar(500) DEFAULT NULL COMMENT '平台公司ID,多个逗号分隔',
|
||||
MODIFY COLUMN `undertake_dept_name` varchar(500) DEFAULT NULL COMMENT '平台公司,多个顿号分隔';
|
||||
@@ -18,8 +18,8 @@ CREATE TABLE `blade_project_apply` (
|
||||
`project_type` varchar(50) DEFAULT NULL COMMENT '项目类型',
|
||||
`business_dept_id` bigint(20) DEFAULT NULL COMMENT '业务部门ID',
|
||||
`business_dept_name` varchar(100) DEFAULT NULL COMMENT '业务部门',
|
||||
`undertake_dept_id` bigint(20) DEFAULT NULL COMMENT '承办部门ID',
|
||||
`undertake_dept_name` varchar(100) DEFAULT NULL COMMENT '承办部门',
|
||||
`undertake_dept_id` varchar(500) DEFAULT NULL COMMENT '平台公司ID,多个逗号分隔',
|
||||
`undertake_dept_name` varchar(500) DEFAULT NULL COMMENT '平台公司,多个顿号分隔',
|
||||
`project_source` varchar(50) DEFAULT NULL COMMENT '项目由来',
|
||||
`source_remark` varchar(500) DEFAULT NULL COMMENT '项目由来说明',
|
||||
`fund_limit` decimal(18,2) DEFAULT NULL COMMENT '项目资金使用额度(万元)',
|
||||
@@ -80,8 +80,8 @@ CREATE TABLE `blade_temporary_credit_limit` (
|
||||
`project_id` bigint(20) DEFAULT NULL COMMENT '项目ID',
|
||||
`project_code` varchar(100) DEFAULT NULL COMMENT '项目编号',
|
||||
`project_name` varchar(100) DEFAULT NULL COMMENT '项目名称',
|
||||
`undertake_dept_id` bigint(20) DEFAULT NULL COMMENT '承办部门ID',
|
||||
`undertake_dept_name` varchar(100) DEFAULT NULL COMMENT '承办部门',
|
||||
`undertake_dept_id` varchar(500) DEFAULT NULL COMMENT '平台公司ID,多个逗号分隔',
|
||||
`undertake_dept_name` varchar(500) DEFAULT NULL COMMENT '平台公司,多个顿号分隔',
|
||||
`project_fund_limit` decimal(18,2) DEFAULT NULL COMMENT '项目资金使用额度(万元)',
|
||||
`used_fund_limit` decimal(18,2) DEFAULT NULL COMMENT '已使用项目资金额度(万元)',
|
||||
`remaining_fund_limit` decimal(18,2) DEFAULT NULL COMMENT '剩余项目资金使用额度(万元)',
|
||||
|
||||
Reference in New Issue
Block a user