diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/LoadingManage.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/LoadingManage.java
index 2488c5f..6393fc0 100644
--- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/LoadingManage.java
+++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/LoadingManage.java
@@ -80,6 +80,9 @@ public class LoadingManage extends TenantEntity {
@Schema(description = "承运商")
private String carrierName;
+ @Schema(description = "承运商合同ID")
+ private Long carrierContractId;
+
@Schema(description = "发货地址")
private String departureAddress;
diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/Waybill.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/Waybill.java
index cbd2b07..e712ce0 100644
--- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/Waybill.java
+++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/Waybill.java
@@ -127,6 +127,9 @@ public class Waybill extends TenantEntity {
@Schema(description = "承运商名称")
private String carrierName;
+ @Schema(description = "承运商合同ID")
+ private Long carrierContractId;
+
@Schema(description = "司机ID")
private Long driverId;
diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/LoadingCarrierContractVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/LoadingCarrierContractVO.java
new file mode 100644
index 0000000..22a40b8
--- /dev/null
+++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/LoadingCarrierContractVO.java
@@ -0,0 +1,58 @@
+/**
+ * BladeX Commercial License Agreement
+ * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
+ *
+ * Use of this software is governed by the Commercial License Agreement
+ * obtained after purchasing a license from BladeX.
+ *
+ * 1. This software is for development use only under a valid license
+ * from BladeX.
+ *
+ * 2. Redistribution of this software's source code to any third party
+ * without a commercial license is strictly prohibited.
+ *
+ * 3. Licensees may copyright their own code but cannot use segments
+ * from this software for such purposes. Copyright of this software
+ * remains with BladeX.
+ *
+ * Using this software signifies agreement to this License, and the software
+ * must not be used for illegal purposes.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
+ * not liable for any claims arising from secondary or illegal development.
+ *
+ * Author: Chill Zhuang (bladejava@qq.com)
+ */
+package org.springblade.transport.pojo.vo;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 配载可选承运商合同视图类
+ *
+ * @author Chill
+ */
+@Data
+@Schema(description = "配载可选承运商合同")
+public class LoadingCarrierContractVO implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ @JsonSerialize(using = ToStringSerializer.class)
+ @Schema(description = "承运商合同ID")
+ private Long id;
+
+ @Schema(description = "承运商合同名称")
+ private String contractName;
+
+ @Schema(description = "承运商名称")
+ private String carrierName;
+
+}
diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/MasterOrderCarrierVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/MasterOrderCarrierVO.java
new file mode 100644
index 0000000..1ce202d
--- /dev/null
+++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/MasterOrderCarrierVO.java
@@ -0,0 +1,37 @@
+/**
+ * BladeX Commercial License Agreement
+ * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
+ */
+package org.springblade.transport.pojo.vo;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 总单调度可选承运商视图类
+ *
+ * @author Chill
+ */
+@Data
+@Schema(description = "总单调度可选承运商")
+public class MasterOrderCarrierVO implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ @JsonSerialize(using = ToStringSerializer.class)
+ @Schema(description = "承运商合同ID")
+ private Long contractId;
+
+ @Schema(description = "承运商合同名称")
+ private String contractName;
+
+ @Schema(description = "承运商名称")
+ private String carrierName;
+
+}
diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/LoadingManageController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/LoadingManageController.java
index 939ac35..39b5263 100644
--- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/LoadingManageController.java
+++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/LoadingManageController.java
@@ -21,6 +21,7 @@ import org.springblade.core.tool.utils.DateUtil;
import org.springblade.transport.excel.LoadingManageExcel;
import org.springblade.transport.pojo.entity.LoadingManage;
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
+import org.springblade.transport.pojo.vo.LoadingCarrierContractVO;
import org.springblade.transport.pojo.vo.LoadingManageVO;
import org.springblade.transport.service.ILoadingManageService;
import org.springframework.web.bind.annotation.GetMapping;
@@ -53,6 +54,14 @@ public class LoadingManageController extends BladeController {
return R.data(loadingManageService.detail(id));
}
+ @GetMapping("/carrier-contracts")
+ @ApiOperationSupport(order = 13)
+ @Operation(summary = "可选承运商合同", description = "根据运单ID集合查询共同可用的承运商合同")
+ public R> carrierContracts(
+ @Parameter(description = "运单ID集合", required = true) @RequestParam List waybillIds) {
+ return R.data(loadingManageService.carrierContracts(waybillIds));
+ }
+
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入loadingManage")
diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/MasterOrderController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/MasterOrderController.java
index 9b5151c..bfeb237 100644
--- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/MasterOrderController.java
+++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/MasterOrderController.java
@@ -15,6 +15,7 @@ import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.dto.MasterOrderDispatchRequest;
import org.springblade.transport.excel.MasterOrderWaybillExcel;
+import org.springblade.transport.pojo.vo.MasterOrderCarrierVO;
import org.springblade.transport.pojo.vo.MasterOrderVO;
import org.springblade.transport.service.IMasterOrderService;
import org.springframework.web.bind.annotation.GetMapping;
@@ -24,6 +25,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
+import java.util.List;
+
/**
* 多联总单控制器
*
@@ -38,6 +41,7 @@ public class MasterOrderController extends BladeController {
private final IMasterOrderService masterOrderService;
@GetMapping("/detail") @ApiOperationSupport(order = 1) @Operation(summary = "详情") public R detail(@RequestParam Long id) { return R.data(masterOrderService.detail(id)); }
+ @GetMapping("/carriers") @ApiOperationSupport(order = 2) @Operation(summary = "调度可选承运商") public R> carriers(@RequestParam Long id) { return R.data(masterOrderService.carriers(id)); }
@GetMapping("/list") @ApiOperationSupport(order = 2) @Operation(summary = "分页") public R> list(MasterOrderVO query, Query page) { return R.data(masterOrderService.selectPage(Condition.getPage(page), query)); }
@PostMapping("/submit") @ApiOperationSupport(order = 3) @Operation(summary = "确认创建或编辑") public R submit(@RequestBody MasterOrderVO data) { return R.data(masterOrderService.submit(data, false)); }
@PostMapping("/draft") @ApiOperationSupport(order = 4) @Operation(summary = "暂存草稿") public R draft(@RequestBody MasterOrderVO data) { return R.data(masterOrderService.submit(data, true)); }
diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/ILoadingManageService.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/ILoadingManageService.java
index 50452e8..dbb4539 100644
--- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/ILoadingManageService.java
+++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/ILoadingManageService.java
@@ -9,6 +9,7 @@ import org.springblade.core.mp.base.BaseService;
import org.springblade.transport.excel.LoadingManageExcel;
import org.springblade.transport.pojo.entity.LoadingManage;
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
+import org.springblade.transport.pojo.vo.LoadingCarrierContractVO;
import org.springblade.transport.pojo.vo.LoadingManageVO;
import java.util.List;
@@ -24,6 +25,8 @@ public interface ILoadingManageService extends BaseService {
LoadingManageVO detail(Long id);
+ List carrierContracts(List waybillIds);
+
boolean saveDraft(LoadingManage loadingManage);
boolean submit(LoadingManage loadingManage);
diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IMasterOrderService.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IMasterOrderService.java
index bb78280..f178ad0 100644
--- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IMasterOrderService.java
+++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IMasterOrderService.java
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.core.mp.base.BaseService;
import org.springblade.transport.pojo.dto.MasterOrderDispatchRequest;
import org.springblade.transport.pojo.entity.MasterOrder;
+import org.springblade.transport.pojo.vo.MasterOrderCarrierVO;
import org.springblade.transport.pojo.vo.MasterOrderVO;
import org.springblade.transport.excel.MasterOrderWaybillExcel;
@@ -18,6 +19,7 @@ import java.util.List;
public interface IMasterOrderService extends BaseService {
IPage selectPage(IPage page, MasterOrderVO query);
MasterOrderVO detail(Long id);
+ List carriers(Long id);
MasterOrderVO submit(MasterOrderVO masterOrder, boolean draft);
MasterOrderVO copy(Long id);
boolean removeMasterOrder(Long id);
diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IReceivablePayableDetailService.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IReceivablePayableDetailService.java
index 0cae341..cf922ac 100644
--- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IReceivablePayableDetailService.java
+++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IReceivablePayableDetailService.java
@@ -77,6 +77,9 @@ public interface IReceivablePayableDetailService extends BaseService waybillIds);
- /** 关闭总单调度后按合同系统计费模式自动生成总单应收、应付明细。 */
+ /** 完成配载单后按其记录的承运商合同自动生成应付明细。 */
+ void generateForCompletedLoading(List waybillIds, Long carrierContractId);
+
+ /** 关闭总单调度后生成总单客户合同应收,并按所属运单记录的承运商合同生成应付。 */
void generateForClosedMasterOrder(MasterOrder masterOrder);
}
diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractManageServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractManageServiceImpl.java
index b1e79eb..d8c6f37 100644
--- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractManageServiceImpl.java
+++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ContractManageServiceImpl.java
@@ -507,12 +507,15 @@ public class ContractManageServiceImpl extends BaseServiceImpllambdaQuery()
.eq(ContractManage::getIsDeleted, 0)
+ .eq(Func.isNotEmpty(contractManage.getProjectId()), ContractManage::getProjectId,
+ contractManage.getProjectId())
+ .isNull(Func.isEmpty(contractManage.getProjectId()), ContractManage::getProjectId)
.eq(ContractManage::getContractCategory, contractManage.getContractCategory())
.eq(ContractManage::getPartyA, contractManage.getPartyA())
.eq(ContractManage::getPartyB, contractManage.getPartyB())
.ne(Func.isNotEmpty(contractManage.getId()), ContractManage::getId, contractManage.getId()));
if (count > 0) {
- throw new ServiceException("相同合同类别、甲方和乙方的合同已存在,不能重复提交");
+ throw new ServiceException("相同项目、合同类别、甲方和乙方的合同已存在,不能重复提交");
}
}
diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/LoadingManageServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/LoadingManageServiceImpl.java
index b2a61a7..28cf212 100644
--- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/LoadingManageServiceImpl.java
+++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/LoadingManageServiceImpl.java
@@ -17,10 +17,13 @@ import org.springblade.system.pojo.entity.Dept;
import org.springblade.transport.excel.LoadingManageExcel;
import org.springblade.transport.mapper.LoadingManageMapper;
import org.springblade.transport.mapper.WaybillMapper;
+import org.springblade.transport.pojo.entity.ContractManage;
import org.springblade.transport.pojo.entity.LoadingManage;
import org.springblade.transport.pojo.entity.Waybill;
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
+import org.springblade.transport.pojo.vo.LoadingCarrierContractVO;
import org.springblade.transport.pojo.vo.LoadingManageVO;
+import org.springblade.transport.service.IContractManageService;
import org.springblade.transport.service.ILoadingManageService;
import org.springblade.transport.service.IReceivablePayableDetailService;
import org.springblade.transport.support.TransportBusinessSupport;
@@ -36,7 +39,10 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Collectors;
/**
* 配载管理 服务实现类
@@ -52,12 +58,14 @@ public class LoadingManageServiceImpl extends BaseServiceImpl carrierContracts(List waybillIds) {
+ return findCarrierContracts(waybillIds).stream().map(contract -> {
+ LoadingCarrierContractVO option = new LoadingCarrierContractVO();
+ option.setId(contract.getId());
+ option.setContractName(contract.getContractName());
+ option.setCarrierName(contract.getPartyB());
+ return option;
+ }).toList();
+ }
+
@Override
@Transactional(rollbackFor = Exception.class)
public boolean saveDraft(LoadingManage loadingManage) {
@@ -96,6 +115,7 @@ public class LoadingManageServiceImpl extends BaseServiceImpl associatedWaybillIds = waybillIds(loadingManage.getWaybillIdsJson());
syncAssociatedWaybills(loadingManage, STATUS_COMPLETED, new ArrayList<>());
if (result) {
- receivablePayableDetailService.generateForCompletedWaybills(associatedWaybillIds);
+ receivablePayableDetailService.generateForCompletedLoading(
+ associatedWaybillIds, loadingManage.getCarrierContractId());
}
return result;
}
@@ -298,6 +323,7 @@ public class LoadingManageServiceImpl extends BaseServiceImpl waybillIdList = waybillIds(loadingManage.getWaybillIdsJson());
if (Func.isEmpty(waybillIdList)) {
return false;
@@ -311,7 +337,12 @@ public class LoadingManageServiceImpl extends BaseServiceImpl Objects.equals(contract.getId(), loadingManage.getCarrierContractId()))
+ .findFirst()
+ .orElseThrow(() -> new ServiceException("所选承运商合同与运单绑定的客户合同不匹配或已失效"));
+ loadingManage.setCarrierName(carrierContract.getPartyB());
+ }
+
+ private void validateCompletedCarrierContract(LoadingManage loadingManage) {
+ if (Objects.equals(loadingManage.getCarrierType(), CARRIER_SELF)) {
+ loadingManage.setCarrierContractId(null);
+ loadingManage.setCarrierName(null);
+ return;
+ }
+ if (Func.isEmpty(loadingManage.getCarrierContractId())) {
+ throw new ServiceException("配载单未记录承运商合同,请先重新派单并选择承运商合同");
+ }
+ }
+
+ private List findCarrierContracts(List waybillIds) {
+ if (Func.isEmpty(waybillIds)) {
+ return new ArrayList<>();
+ }
+ List distinctWaybillIds = waybillIds.stream()
+ .filter(Objects::nonNull)
+ .distinct()
+ .toList();
+ if (Func.isEmpty(distinctWaybillIds)) {
+ return new ArrayList<>();
+ }
+ List waybillList = waybillMapper.selectList(Wrappers.lambdaQuery()
+ .eq(Waybill::getIsDeleted, 0)
+ .in(Waybill::getId, distinctWaybillIds));
+ if (waybillList.size() != distinctWaybillIds.size()) {
+ throw new ServiceException("待配载运单不存在或已删除");
+ }
+ waybillList.forEach(waybill ->
+ TransportBusinessSupport.assertCurrentDept(waybill.getDeptId(), "运单管理"));
+ if (waybillList.stream().anyMatch(waybill -> Func.isEmpty(waybill.getContractId()))) {
+ throw new ServiceException("所选运单存在未绑定客户合同的数据");
+ }
+ List customerContractIds = waybillList.stream()
+ .map(Waybill::getContractId)
+ .distinct()
+ .toList();
+ Map customerContractMap = contractManageService.listByIds(customerContractIds)
+ .stream()
+ .filter(contract -> Objects.equals(contract.getIsDeleted(), 0))
+ .collect(Collectors.toMap(ContractManage::getId, Function.identity()));
+ if (customerContractMap.size() != customerContractIds.size()) {
+ throw new ServiceException("所选运单绑定的客户合同不存在或已删除");
+ }
+ Waybill firstWaybill = waybillList.get(0);
+ ContractManage firstCustomerContract = customerContractMap.get(firstWaybill.getContractId());
+ if (!Objects.equals(firstCustomerContract.getContractCategory(), "客户合同")
+ || Func.isEmpty(firstCustomerContract.getPartyA())) {
+ throw new ServiceException("所选运单绑定的客户合同信息不完整");
+ }
+ boolean relationMismatch = waybillList.stream().anyMatch(waybill -> {
+ ContractManage customerContract = customerContractMap.get(waybill.getContractId());
+ return !Objects.equals(customerContract.getContractCategory(), "客户合同")
+ || !Objects.equals(waybill.getProjectId(), firstWaybill.getProjectId())
+ || !Objects.equals(customerContract.getPartyA(), firstCustomerContract.getPartyA());
+ });
+ if (relationMismatch) {
+ throw new ServiceException("所选运单的客户合同不属于同一项目和甲方,无法共用承运商合同");
+ }
+ return contractManageService.list(Wrappers.lambdaQuery()
+ .eq(ContractManage::getIsDeleted, 0)
+ .eq(ContractManage::getProjectId, firstWaybill.getProjectId())
+ .eq(ContractManage::getPartyA, firstCustomerContract.getPartyA())
+ .eq(ContractManage::getContractCategory, "承运商合同")
+ .in(ContractManage::getApprovalStatus, "approved", "change_approved")
+ .and(wrapper -> wrapper.isNull(ContractManage::getContractStage)
+ .or().ne(ContractManage::getContractStage, "terminated"))
+ .orderByDesc(ContractManage::getCreateTime));
+ }
+
private void syncAssociatedWaybills(LoadingManage loadingManage, String status, List oldWaybillIds) {
List newWaybillIds = waybillIds(loadingManage.getWaybillIdsJson());
if (Func.isNotEmpty(oldWaybillIds)) {
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 8ec2c59..38cdfa5 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
@@ -20,6 +20,7 @@ import org.springblade.transport.pojo.entity.ContractManage;
import org.springblade.transport.pojo.entity.ProjectApply;
import org.springblade.transport.pojo.entity.TransportPlan;
import org.springblade.transport.pojo.entity.Waybill;
+import org.springblade.transport.pojo.vo.MasterOrderCarrierVO;
import org.springblade.transport.pojo.vo.MasterOrderVO;
import org.springblade.transport.service.IMasterOrderService;
import org.springblade.transport.service.IContractManageService;
@@ -77,6 +78,17 @@ public class MasterOrderServiceImpl extends BaseServiceImpl carriers(Long id) {
+ return availableCarrierContracts(getRequired(id)).stream().map(contract -> {
+ MasterOrderCarrierVO carrier = new MasterOrderCarrierVO();
+ carrier.setContractId(contract.getId());
+ carrier.setContractName(contract.getContractName());
+ carrier.setCarrierName(contract.getPartyB());
+ return carrier;
+ }).toList();
+ }
+
@Override
@Transactional(rollbackFor = Exception.class)
public MasterOrderVO submit(MasterOrderVO request, boolean draft) {
@@ -203,7 +215,7 @@ public class MasterOrderServiceImpl extends BaseServiceImpl> parseArray(String json) { if (Func.isEmpty(json)) return new ArrayList<>(); try { return JsonUtil.parse(json, List.class); } catch (Exception exception) { return new ArrayList<>(); } }
private void validateDispatches(MasterOrder masterOrder, List