diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ShippingTemplate.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ShippingTemplate.java index f543805..48f4d52 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ShippingTemplate.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ShippingTemplate.java @@ -114,6 +114,9 @@ public class ShippingTemplate extends TenantEntity { @Schema(description = "所属组织") private String deptName; + @Schema(description = "基本信息备注") + private String basicRemark; + @Schema(description = "备注") private String remark; diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/TransportPlan.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/TransportPlan.java index 4462cba..13c173e 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/TransportPlan.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/TransportPlan.java @@ -30,6 +30,7 @@ import org.springblade.core.tenant.mp.TenantEntity; import java.io.Serial; import java.time.LocalDate; +import java.time.LocalDateTime; /** * 运输计划实体类 @@ -114,6 +115,9 @@ public class TransportPlan extends TenantEntity { @Schema(description = "货物信息") private String goodsJson; + @Schema(description = "费用信息") + private String freightJson; + @Schema(description = "附件") private String attachmentsJson; @@ -123,6 +127,15 @@ public class TransportPlan extends TenantEntity { @Schema(description = "业务状态") private String businessStatus; + @Schema(description = "调度人ID") + private Long dispatcherUserId; + + @Schema(description = "调度人姓名") + private String dispatcherUserName; + + @Schema(description = "调度时间") + private LocalDateTime dispatchTime; + @Schema(description = "所属组织ID") private Long deptId; diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/TransportPlanVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/TransportPlanVO.java index 7574423..f053294 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/TransportPlanVO.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/TransportPlanVO.java @@ -27,8 +27,10 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import org.springblade.transport.pojo.entity.TransportPlan; +import org.springblade.transport.pojo.entity.Waybill; import java.io.Serial; +import java.util.List; /** * 运输计划视图实体类 @@ -62,5 +64,9 @@ public class TransportPlanVO extends TransportPlan { @Schema(description = "业务状态名称") private String businessStatusName; + @TableField(exist = false) + @Schema(description = "计划调度生成的运单") + private List dispatchRows; + } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/MasterOrderServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/MasterOrderServiceImpl.java index 60b5f6e..f9a2bac 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/MasterOrderServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/MasterOrderServiceImpl.java @@ -186,7 +186,10 @@ public class MasterOrderServiceImpl extends BaseServiceImpl decimal(item, "quantity").multiply(decimal(item, "unitPrice"))).reduce(BigDecimal.ZERO, BigDecimal::add); + plan.setFreightJson(Func.isNotEmpty(freightJson) ? freightJson : buildFreightJson(null, freightTotal, first)); + plan.setDataSource("多联总单调度"); plan.setBusinessStatus("waiting_dispatch"); plan.setRemark(string(first, "remark")); transportPlanService.submit(plan); } @@ -308,6 +315,9 @@ public class MasterOrderServiceImpl extends BaseServiceImpl> goods) { return goods.stream().map(item -> decimal(item, "quantity")).reduce(BigDecimal.ZERO, BigDecimal::add); } + private String buildFreightJson(BigDecimal quantity, BigDecimal freightTotal, Map dispatch) { + Map freight = new LinkedHashMap<>(); + if (quantity != null) freight.put("weightTotal", quantity); + freight.put("freightTotal", freightTotal); + freight.put("totalFreightAmount", freightTotal.add(Objects.requireNonNullElse(nullableDecimal(dispatch, "otherFeeTotal"), BigDecimal.ZERO))); + freight.put("otherFreightAmount", string(dispatch, "otherFeeTotal", "")); + freight.put("currency", string(dispatch, "currency", "CNY")); + return JsonUtil.toJson(freight); + } private String waybillGroupKey(Map dispatch) { return String.join("\u0000", string(dispatch, "segmentNo", ""), string(dispatch, "carrierType", ""), string(dispatch, "carrierName", ""), string(dispatch, "driverName", ""), string(dispatch, "vehicleNo", "")); } private String joinGoodsField(List> dispatches, String field) { return dispatches.stream().map(item -> string(item, field, "")).filter(Func::isNotEmpty).distinct().reduce((left, right) -> left + "、" + right).orElse(""); } private BigDecimal decimal(Map values, String key) { try { return new BigDecimal(string(values, key, "0")); } catch (Exception exception) { return BigDecimal.ZERO; } } + private BigDecimal nullableDecimal(Map values, String key) { String value = string(values, key); if (Func.isEmpty(value)) return null; try { return new BigDecimal(value); } catch (Exception exception) { return null; } } private String goodsKey(Map values) { return goodsKey(string(values, "cargoName"), string(values, "cargoType")); } private String goodsKey(String cargoName, String cargoType) { return String.valueOf(cargoName) + "\u0000" + String.valueOf(cargoType); } private LocalDate date(Map values, String key) { String value = string(values, key); if (Func.isEmpty(value)) return null; try { return LocalDate.parse(value.substring(0, 10)); } catch (Exception exception) { throw new ServiceException("日期格式不正确"); } } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ShippingTemplateServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ShippingTemplateServiceImpl.java index df7dd7f..79baf7e 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ShippingTemplateServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ShippingTemplateServiceImpl.java @@ -160,6 +160,7 @@ public class ShippingTemplateServiceImpl extends BaseServiceImpl selectTransportPlanPage(IPage page, TransportPlanVO transportPlan) { IPage entityPage = page(page, buildQuery(transportPlan)); - return TransportPlanWrapper.build().pageVO(entityPage); + IPage resultPage = TransportPlanWrapper.build().pageVO(entityPage); + fillDispatchRows(resultPage.getRecords()); + return resultPage; } @Override public TransportPlanVO detail(Long id) { - return TransportPlanWrapper.build().entityVO(loadEditable(id, false)); + TransportPlanVO transportPlan = TransportPlanWrapper.build().entityVO(loadEditable(id, false)); + fillDispatchRows(Collections.singletonList(transportPlan)); + return transportPlan; } @Override @@ -321,6 +331,9 @@ public class TransportPlanServiceImpl extends BaseServiceImpl plans) { + if (Func.isEmpty(plans)) { + return; + } + List planIds = plans.stream().map(TransportPlanVO::getId).filter(Objects::nonNull).toList(); + if (Func.isEmpty(planIds)) { + plans.forEach(plan -> plan.setDispatchRows(Collections.emptyList())); + return; + } + Map> waybillsByPlanId = waybillService.list(Wrappers.lambdaQuery() + .eq(Waybill::getIsDeleted, 0) + .in(Waybill::getPlanId, planIds)) + .stream() + .collect(Collectors.groupingBy(Waybill::getPlanId)); + plans.forEach(plan -> plan.setDispatchRows( + waybillsByPlanId.getOrDefault(plan.getId(), Collections.emptyList()) + )); + } + private LambdaQueryWrapper buildQuery(TransportPlanVO transportPlan) { TransportBusinessSupport.validateAllDept(transportPlan.getAllDept(), "运输计划"); LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().eq(TransportPlan::getIsDeleted, 0); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java index bd6019d..934c257 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillServiceImpl.java @@ -422,6 +422,9 @@ public class WaybillServiceImpl extends BaseServiceImpl } private void prepare(Waybill waybill) { + if (isSentinelMinusOne(waybill.getQuantity())) waybill.setQuantity(null); + if (isSentinelMinusOne(waybill.getMileage())) waybill.setMileage(null); + if (isSentinelMinusOne(waybill.getUnitPrice())) waybill.setUnitPrice(null); waybill.setWaybillNo(TransportBusinessSupport.trimToNull(waybill.getWaybillNo())); waybill.setProjectName(TransportBusinessSupport.trimToNull(waybill.getProjectName())); waybill.setContractName(TransportBusinessSupport.trimToNull(waybill.getContractName())); @@ -481,6 +484,10 @@ public class WaybillServiceImpl extends BaseServiceImpl if (Func.isEmpty(waybill.getBusinessStatus())) { waybill.setBusinessStatus("pending"); } } + private boolean isSentinelMinusOne(BigDecimal value) { + return value != null && value.compareTo(BigDecimal.ONE.negate()) == 0; + } + private void validate(Waybill waybill) { TransportBusinessSupport.validateRequired(waybill.getProjectName(), "项目不能为空"); TransportBusinessSupport.validateRequired(waybill.getContractName(), "客户合同不能为空"); diff --git a/doc/sql/transport/blade_shipping_template_basic_remark_20260813.sql b/doc/sql/transport/blade_shipping_template_basic_remark_20260813.sql new file mode 100644 index 0000000..6750f03 --- /dev/null +++ b/doc/sql/transport/blade_shipping_template_basic_remark_20260813.sql @@ -0,0 +1,2 @@ +ALTER TABLE `blade_shipping_template` + ADD COLUMN `basic_remark` varchar(200) DEFAULT NULL COMMENT '基本信息备注' AFTER `dept_name`; diff --git a/doc/sql/transport/blade_tms_business.sql b/doc/sql/transport/blade_tms_business.sql index b0b9f48..3d5ec50 100644 --- a/doc/sql/transport/blade_tms_business.sql +++ b/doc/sql/transport/blade_tms_business.sql @@ -144,6 +144,7 @@ CREATE TABLE `blade_shipping_template` ( `attachments_json` text DEFAULT NULL COMMENT '附件', `dept_id` bigint(20) DEFAULT NULL COMMENT '所属组织ID', `dept_name` varchar(100) DEFAULT NULL COMMENT '所属组织', + `basic_remark` varchar(200) DEFAULT NULL COMMENT '基本信息备注', `remark` varchar(500) DEFAULT NULL COMMENT '备注', PRIMARY KEY (`id`) USING BTREE, KEY `idx_shipping_template_dept` (`dept_id`) USING BTREE, @@ -187,9 +188,13 @@ CREATE TABLE `blade_transport_plan` ( `arrival_contact` varchar(100) DEFAULT NULL COMMENT '收货联系人', `arrival_phone` varchar(100) DEFAULT NULL COMMENT '收货联系方式', `goods_json` text DEFAULT NULL COMMENT '货物信息', + `freight_json` text DEFAULT NULL COMMENT '费用信息', `attachments_json` text DEFAULT NULL COMMENT '附件', `data_source` varchar(100) DEFAULT NULL COMMENT '数据来源', `business_status` varchar(100) DEFAULT NULL COMMENT '业务状态', + `dispatcher_user_id` bigint(20) DEFAULT NULL COMMENT '调度人ID', + `dispatcher_user_name` varchar(100) DEFAULT NULL COMMENT '调度人姓名', + `dispatch_time` datetime DEFAULT NULL COMMENT '调度时间', `dept_id` bigint(20) DEFAULT NULL COMMENT '所属组织ID', `dept_name` varchar(100) DEFAULT NULL COMMENT '所属组织', `remark` varchar(500) DEFAULT NULL COMMENT '备注', @@ -279,6 +284,7 @@ CREATE TABLE `blade_waybill` ( `remark` varchar(200) DEFAULT NULL COMMENT '备注', PRIMARY KEY (`id`) USING BTREE, KEY `idx_waybill_dept` (`dept_id`) USING BTREE, + KEY `idx_waybill_plan_id` (`plan_id`) USING BTREE, KEY `idx_waybill_create_time` (`create_time`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='运单管理'; diff --git a/doc/sql/transport/blade_transport_plan_dispatcher_20260813.sql b/doc/sql/transport/blade_transport_plan_dispatcher_20260813.sql new file mode 100644 index 0000000..bcc19ed --- /dev/null +++ b/doc/sql/transport/blade_transport_plan_dispatcher_20260813.sql @@ -0,0 +1,5 @@ +-- 运输计划计划调度记录调度人和调度时间 +ALTER TABLE `blade_transport_plan` + ADD COLUMN `dispatcher_user_id` bigint(20) DEFAULT NULL COMMENT '调度人ID' AFTER `business_status`, + ADD COLUMN `dispatcher_user_name` varchar(100) DEFAULT NULL COMMENT '调度人姓名' AFTER `dispatcher_user_id`, + ADD COLUMN `dispatch_time` datetime DEFAULT NULL COMMENT '调度时间' AFTER `dispatcher_user_name`; diff --git a/doc/sql/transport/blade_transport_plan_freight_20260813.sql b/doc/sql/transport/blade_transport_plan_freight_20260813.sql new file mode 100644 index 0000000..36b2a4b --- /dev/null +++ b/doc/sql/transport/blade_transport_plan_freight_20260813.sql @@ -0,0 +1,3 @@ +-- 多联总单调度生成运输计划费用信息 +ALTER TABLE `blade_transport_plan` + ADD COLUMN `freight_json` text DEFAULT NULL COMMENT '费用信息' AFTER `goods_json`; diff --git a/doc/sql/transport/blade_waybill_plan_id_index_20260813.sql b/doc/sql/transport/blade_waybill_plan_id_index_20260813.sql new file mode 100644 index 0000000..e0af1a1 --- /dev/null +++ b/doc/sql/transport/blade_waybill_plan_id_index_20260813.sql @@ -0,0 +1,2 @@ +ALTER TABLE `blade_waybill` + ADD KEY `idx_waybill_plan_id` (`plan_id`) USING BTREE;