fix bug
This commit is contained in:
+3
@@ -80,6 +80,9 @@ public class LoadingManage extends TenantEntity {
|
|||||||
@Schema(description = "承运商")
|
@Schema(description = "承运商")
|
||||||
private String carrierName;
|
private String carrierName;
|
||||||
|
|
||||||
|
@Schema(description = "承运商合同ID")
|
||||||
|
private Long carrierContractId;
|
||||||
|
|
||||||
@Schema(description = "发货地址")
|
@Schema(description = "发货地址")
|
||||||
private String departureAddress;
|
private String departureAddress;
|
||||||
|
|
||||||
|
|||||||
+3
@@ -127,6 +127,9 @@ public class Waybill extends TenantEntity {
|
|||||||
@Schema(description = "承运商名称")
|
@Schema(description = "承运商名称")
|
||||||
private String carrierName;
|
private String carrierName;
|
||||||
|
|
||||||
|
@Schema(description = "承运商合同ID")
|
||||||
|
private Long carrierContractId;
|
||||||
|
|
||||||
@Schema(description = "司机ID")
|
@Schema(description = "司机ID")
|
||||||
private Long driverId;
|
private Long driverId;
|
||||||
|
|
||||||
|
|||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* BladeX Commercial License Agreement
|
||||||
|
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||||
|
* <p>
|
||||||
|
* Use of this software is governed by the Commercial License Agreement
|
||||||
|
* obtained after purchasing a license from BladeX.
|
||||||
|
* <p>
|
||||||
|
* 1. This software is for development use only under a valid license
|
||||||
|
* from BladeX.
|
||||||
|
* <p>
|
||||||
|
* 2. Redistribution of this software's source code to any third party
|
||||||
|
* without a commercial license is strictly prohibited.
|
||||||
|
* <p>
|
||||||
|
* 3. Licensees may copyright their own code but cannot use segments
|
||||||
|
* from this software for such purposes. Copyright of this software
|
||||||
|
* remains with BladeX.
|
||||||
|
* <p>
|
||||||
|
* Using this software signifies agreement to this License, and the software
|
||||||
|
* must not be used for illegal purposes.
|
||||||
|
* <p>
|
||||||
|
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||||
|
* not liable for any claims arising from secondary or illegal development.
|
||||||
|
* <p>
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
}
|
||||||
+37
@@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
+9
@@ -21,6 +21,7 @@ import org.springblade.core.tool.utils.DateUtil;
|
|||||||
import org.springblade.transport.excel.LoadingManageExcel;
|
import org.springblade.transport.excel.LoadingManageExcel;
|
||||||
import org.springblade.transport.pojo.entity.LoadingManage;
|
import org.springblade.transport.pojo.entity.LoadingManage;
|
||||||
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
|
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.pojo.vo.LoadingManageVO;
|
||||||
import org.springblade.transport.service.ILoadingManageService;
|
import org.springblade.transport.service.ILoadingManageService;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@@ -53,6 +54,14 @@ public class LoadingManageController extends BladeController {
|
|||||||
return R.data(loadingManageService.detail(id));
|
return R.data(loadingManageService.detail(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/carrier-contracts")
|
||||||
|
@ApiOperationSupport(order = 13)
|
||||||
|
@Operation(summary = "可选承运商合同", description = "根据运单ID集合查询共同可用的承运商合同")
|
||||||
|
public R<List<LoadingCarrierContractVO>> carrierContracts(
|
||||||
|
@Parameter(description = "运单ID集合", required = true) @RequestParam List<Long> waybillIds) {
|
||||||
|
return R.data(loadingManageService.carrierContracts(waybillIds));
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@ApiOperationSupport(order = 2)
|
@ApiOperationSupport(order = 2)
|
||||||
@Operation(summary = "分页", description = "传入loadingManage")
|
@Operation(summary = "分页", description = "传入loadingManage")
|
||||||
|
|||||||
+4
@@ -15,6 +15,7 @@ import org.springblade.core.secure.annotation.PreAuth;
|
|||||||
import org.springblade.core.tool.api.R;
|
import org.springblade.core.tool.api.R;
|
||||||
import org.springblade.transport.pojo.dto.MasterOrderDispatchRequest;
|
import org.springblade.transport.pojo.dto.MasterOrderDispatchRequest;
|
||||||
import org.springblade.transport.excel.MasterOrderWaybillExcel;
|
import org.springblade.transport.excel.MasterOrderWaybillExcel;
|
||||||
|
import org.springblade.transport.pojo.vo.MasterOrderCarrierVO;
|
||||||
import org.springblade.transport.pojo.vo.MasterOrderVO;
|
import org.springblade.transport.pojo.vo.MasterOrderVO;
|
||||||
import org.springblade.transport.service.IMasterOrderService;
|
import org.springblade.transport.service.IMasterOrderService;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
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.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多联总单控制器
|
* 多联总单控制器
|
||||||
*
|
*
|
||||||
@@ -38,6 +41,7 @@ public class MasterOrderController extends BladeController {
|
|||||||
|
|
||||||
private final IMasterOrderService masterOrderService;
|
private final IMasterOrderService masterOrderService;
|
||||||
@GetMapping("/detail") @ApiOperationSupport(order = 1) @Operation(summary = "详情") public R<MasterOrderVO> detail(@RequestParam Long id) { return R.data(masterOrderService.detail(id)); }
|
@GetMapping("/detail") @ApiOperationSupport(order = 1) @Operation(summary = "详情") public R<MasterOrderVO> detail(@RequestParam Long id) { return R.data(masterOrderService.detail(id)); }
|
||||||
|
@GetMapping("/carriers") @ApiOperationSupport(order = 2) @Operation(summary = "调度可选承运商") public R<List<MasterOrderCarrierVO>> carriers(@RequestParam Long id) { return R.data(masterOrderService.carriers(id)); }
|
||||||
@GetMapping("/list") @ApiOperationSupport(order = 2) @Operation(summary = "分页") public R<IPage<MasterOrderVO>> list(MasterOrderVO query, Query page) { return R.data(masterOrderService.selectPage(Condition.getPage(page), query)); }
|
@GetMapping("/list") @ApiOperationSupport(order = 2) @Operation(summary = "分页") public R<IPage<MasterOrderVO>> list(MasterOrderVO query, Query page) { return R.data(masterOrderService.selectPage(Condition.getPage(page), query)); }
|
||||||
@PostMapping("/submit") @ApiOperationSupport(order = 3) @Operation(summary = "确认创建或编辑") public R<MasterOrderVO> submit(@RequestBody MasterOrderVO data) { return R.data(masterOrderService.submit(data, false)); }
|
@PostMapping("/submit") @ApiOperationSupport(order = 3) @Operation(summary = "确认创建或编辑") public R<MasterOrderVO> submit(@RequestBody MasterOrderVO data) { return R.data(masterOrderService.submit(data, false)); }
|
||||||
@PostMapping("/draft") @ApiOperationSupport(order = 4) @Operation(summary = "暂存草稿") public R<MasterOrderVO> draft(@RequestBody MasterOrderVO data) { return R.data(masterOrderService.submit(data, true)); }
|
@PostMapping("/draft") @ApiOperationSupport(order = 4) @Operation(summary = "暂存草稿") public R<MasterOrderVO> draft(@RequestBody MasterOrderVO data) { return R.data(masterOrderService.submit(data, true)); }
|
||||||
|
|||||||
+3
@@ -9,6 +9,7 @@ import org.springblade.core.mp.base.BaseService;
|
|||||||
import org.springblade.transport.excel.LoadingManageExcel;
|
import org.springblade.transport.excel.LoadingManageExcel;
|
||||||
import org.springblade.transport.pojo.entity.LoadingManage;
|
import org.springblade.transport.pojo.entity.LoadingManage;
|
||||||
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
|
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.pojo.vo.LoadingManageVO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -24,6 +25,8 @@ public interface ILoadingManageService extends BaseService<LoadingManage> {
|
|||||||
|
|
||||||
LoadingManageVO detail(Long id);
|
LoadingManageVO detail(Long id);
|
||||||
|
|
||||||
|
List<LoadingCarrierContractVO> carrierContracts(List<Long> waybillIds);
|
||||||
|
|
||||||
boolean saveDraft(LoadingManage loadingManage);
|
boolean saveDraft(LoadingManage loadingManage);
|
||||||
|
|
||||||
boolean submit(LoadingManage loadingManage);
|
boolean submit(LoadingManage loadingManage);
|
||||||
|
|||||||
+2
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
|||||||
import org.springblade.core.mp.base.BaseService;
|
import org.springblade.core.mp.base.BaseService;
|
||||||
import org.springblade.transport.pojo.dto.MasterOrderDispatchRequest;
|
import org.springblade.transport.pojo.dto.MasterOrderDispatchRequest;
|
||||||
import org.springblade.transport.pojo.entity.MasterOrder;
|
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.pojo.vo.MasterOrderVO;
|
||||||
import org.springblade.transport.excel.MasterOrderWaybillExcel;
|
import org.springblade.transport.excel.MasterOrderWaybillExcel;
|
||||||
|
|
||||||
@@ -18,6 +19,7 @@ import java.util.List;
|
|||||||
public interface IMasterOrderService extends BaseService<MasterOrder> {
|
public interface IMasterOrderService extends BaseService<MasterOrder> {
|
||||||
IPage<MasterOrderVO> selectPage(IPage<MasterOrder> page, MasterOrderVO query);
|
IPage<MasterOrderVO> selectPage(IPage<MasterOrder> page, MasterOrderVO query);
|
||||||
MasterOrderVO detail(Long id);
|
MasterOrderVO detail(Long id);
|
||||||
|
List<MasterOrderCarrierVO> carriers(Long id);
|
||||||
MasterOrderVO submit(MasterOrderVO masterOrder, boolean draft);
|
MasterOrderVO submit(MasterOrderVO masterOrder, boolean draft);
|
||||||
MasterOrderVO copy(Long id);
|
MasterOrderVO copy(Long id);
|
||||||
boolean removeMasterOrder(Long id);
|
boolean removeMasterOrder(Long id);
|
||||||
|
|||||||
+4
-1
@@ -77,6 +77,9 @@ public interface IReceivablePayableDetailService extends BaseService<ReceivableP
|
|||||||
/** 完成运单后按合同系统计费模式自动生成应收、应付明细。 */
|
/** 完成运单后按合同系统计费模式自动生成应收、应付明细。 */
|
||||||
void generateForCompletedWaybills(List<Long> waybillIds);
|
void generateForCompletedWaybills(List<Long> waybillIds);
|
||||||
|
|
||||||
/** 关闭总单调度后按合同系统计费模式自动生成总单应收、应付明细。 */
|
/** 完成配载单后按其记录的承运商合同自动生成应付明细。 */
|
||||||
|
void generateForCompletedLoading(List<Long> waybillIds, Long carrierContractId);
|
||||||
|
|
||||||
|
/** 关闭总单调度后生成总单客户合同应收,并按所属运单记录的承运商合同生成应付。 */
|
||||||
void generateForClosedMasterOrder(MasterOrder masterOrder);
|
void generateForClosedMasterOrder(MasterOrder masterOrder);
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -507,12 +507,15 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
|
|||||||
}
|
}
|
||||||
Long count = count(Wrappers.<ContractManage>lambdaQuery()
|
Long count = count(Wrappers.<ContractManage>lambdaQuery()
|
||||||
.eq(ContractManage::getIsDeleted, 0)
|
.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::getContractCategory, contractManage.getContractCategory())
|
||||||
.eq(ContractManage::getPartyA, contractManage.getPartyA())
|
.eq(ContractManage::getPartyA, contractManage.getPartyA())
|
||||||
.eq(ContractManage::getPartyB, contractManage.getPartyB())
|
.eq(ContractManage::getPartyB, contractManage.getPartyB())
|
||||||
.ne(Func.isNotEmpty(contractManage.getId()), ContractManage::getId, contractManage.getId()));
|
.ne(Func.isNotEmpty(contractManage.getId()), ContractManage::getId, contractManage.getId()));
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
throw new ServiceException("相同合同类别、甲方和乙方的合同已存在,不能重复提交");
|
throw new ServiceException("相同项目、合同类别、甲方和乙方的合同已存在,不能重复提交");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+132
-7
@@ -17,10 +17,13 @@ import org.springblade.system.pojo.entity.Dept;
|
|||||||
import org.springblade.transport.excel.LoadingManageExcel;
|
import org.springblade.transport.excel.LoadingManageExcel;
|
||||||
import org.springblade.transport.mapper.LoadingManageMapper;
|
import org.springblade.transport.mapper.LoadingManageMapper;
|
||||||
import org.springblade.transport.mapper.WaybillMapper;
|
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.LoadingManage;
|
||||||
import org.springblade.transport.pojo.entity.Waybill;
|
import org.springblade.transport.pojo.entity.Waybill;
|
||||||
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
|
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.pojo.vo.LoadingManageVO;
|
||||||
|
import org.springblade.transport.service.IContractManageService;
|
||||||
import org.springblade.transport.service.ILoadingManageService;
|
import org.springblade.transport.service.ILoadingManageService;
|
||||||
import org.springblade.transport.service.IReceivablePayableDetailService;
|
import org.springblade.transport.service.IReceivablePayableDetailService;
|
||||||
import org.springblade.transport.support.TransportBusinessSupport;
|
import org.springblade.transport.support.TransportBusinessSupport;
|
||||||
@@ -36,7 +39,10 @@ import java.time.LocalDateTime;
|
|||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配载管理 服务实现类
|
* 配载管理 服务实现类
|
||||||
@@ -52,12 +58,14 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
|||||||
private static final String STATUS_COMPLETED = "completed";
|
private static final String STATUS_COMPLETED = "completed";
|
||||||
private static final String STATUS_CANCELLED = "cancelled";
|
private static final String STATUS_CANCELLED = "cancelled";
|
||||||
private static final String CARRIER_SELF = "自运";
|
private static final String CARRIER_SELF = "自运";
|
||||||
private static final String CARRIER_COMPANY = "承运商";
|
private static final String CARRIER_PLATFORM = "网货平台";
|
||||||
private static final String CARRIER_PLATFORM = "网签平台";
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private WaybillMapper waybillMapper;
|
private WaybillMapper waybillMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IContractManageService contractManageService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
@Lazy
|
@Lazy
|
||||||
private IReceivablePayableDetailService receivablePayableDetailService;
|
private IReceivablePayableDetailService receivablePayableDetailService;
|
||||||
@@ -77,6 +85,17 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
|||||||
return loadingManageVO;
|
return loadingManageVO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<LoadingCarrierContractVO> carrierContracts(List<Long> 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
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public boolean saveDraft(LoadingManage loadingManage) {
|
public boolean saveDraft(LoadingManage loadingManage) {
|
||||||
@@ -96,6 +115,7 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
|||||||
loadingManage.setLoadingNo(nextCode());
|
loadingManage.setLoadingNo(nextCode());
|
||||||
}
|
}
|
||||||
validateWaybillsAvailable(loadingManage, waybillIds(loadingManage.getWaybillIdsJson()));
|
validateWaybillsAvailable(loadingManage, waybillIds(loadingManage.getWaybillIdsJson()));
|
||||||
|
validateCarrierContract(loadingManage, false);
|
||||||
boolean result = saveOrUpdate(loadingManage);
|
boolean result = saveOrUpdate(loadingManage);
|
||||||
syncAssociatedWaybills(loadingManage, STATUS_DRAFT, oldWaybillIds);
|
syncAssociatedWaybills(loadingManage, STATUS_DRAFT, oldWaybillIds);
|
||||||
return result;
|
return result;
|
||||||
@@ -120,6 +140,7 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
|||||||
loadingManage.setLoadingNo(nextCode());
|
loadingManage.setLoadingNo(nextCode());
|
||||||
}
|
}
|
||||||
validateWaybillsAvailable(loadingManage, waybillIds(loadingManage.getWaybillIdsJson()));
|
validateWaybillsAvailable(loadingManage, waybillIds(loadingManage.getWaybillIdsJson()));
|
||||||
|
validateCarrierContract(loadingManage, true);
|
||||||
boolean result = saveOrUpdate(loadingManage);
|
boolean result = saveOrUpdate(loadingManage);
|
||||||
syncAssociatedWaybills(loadingManage, STATUS_PENDING, oldWaybillIds);
|
syncAssociatedWaybills(loadingManage, STATUS_PENDING, oldWaybillIds);
|
||||||
return result;
|
return result;
|
||||||
@@ -187,6 +208,7 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
|||||||
target.setEscortPhone(source.getEscortPhone());
|
target.setEscortPhone(source.getEscortPhone());
|
||||||
target.setCarrierType(source.getCarrierType());
|
target.setCarrierType(source.getCarrierType());
|
||||||
target.setCarrierName(source.getCarrierName());
|
target.setCarrierName(source.getCarrierName());
|
||||||
|
target.setCarrierContractId(source.getCarrierContractId());
|
||||||
target.setDepartureAddress(source.getDepartureAddress());
|
target.setDepartureAddress(source.getDepartureAddress());
|
||||||
target.setTransitAddress(source.getTransitAddress());
|
target.setTransitAddress(source.getTransitAddress());
|
||||||
target.setArrivalAddress(source.getArrivalAddress());
|
target.setArrivalAddress(source.getArrivalAddress());
|
||||||
@@ -229,6 +251,7 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
|||||||
loadingManage.setDeptName(oldRecord.getDeptName());
|
loadingManage.setDeptName(oldRecord.getDeptName());
|
||||||
loadingManage.setBusinessStatus(STATUS_PENDING);
|
loadingManage.setBusinessStatus(STATUS_PENDING);
|
||||||
validateWaybillsAvailable(loadingManage, waybillIds(loadingManage.getWaybillIdsJson()));
|
validateWaybillsAvailable(loadingManage, waybillIds(loadingManage.getWaybillIdsJson()));
|
||||||
|
validateCarrierContract(loadingManage, true);
|
||||||
boolean result = updateById(loadingManage);
|
boolean result = updateById(loadingManage);
|
||||||
syncAssociatedWaybills(loadingManage, STATUS_PENDING, oldWaybillIds);
|
syncAssociatedWaybills(loadingManage, STATUS_PENDING, oldWaybillIds);
|
||||||
return result;
|
return result;
|
||||||
@@ -267,6 +290,7 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
|||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public boolean complete(Long id) {
|
public boolean complete(Long id) {
|
||||||
LoadingManage loadingManage = loadEditable(id, true);
|
LoadingManage loadingManage = loadEditable(id, true);
|
||||||
|
validateCompletedCarrierContract(loadingManage);
|
||||||
if (!Objects.equals(loadingManage.getBusinessStatus(), STATUS_RUNNING)
|
if (!Objects.equals(loadingManage.getBusinessStatus(), STATUS_RUNNING)
|
||||||
&& !(Objects.equals(loadingManage.getBusinessStatus(), STATUS_PENDING)
|
&& !(Objects.equals(loadingManage.getBusinessStatus(), STATUS_PENDING)
|
||||||
&& allAssociatedWaybillsCompletable(loadingManage))) {
|
&& allAssociatedWaybillsCompletable(loadingManage))) {
|
||||||
@@ -277,7 +301,8 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
|||||||
List<Long> associatedWaybillIds = waybillIds(loadingManage.getWaybillIdsJson());
|
List<Long> associatedWaybillIds = waybillIds(loadingManage.getWaybillIdsJson());
|
||||||
syncAssociatedWaybills(loadingManage, STATUS_COMPLETED, new ArrayList<>());
|
syncAssociatedWaybills(loadingManage, STATUS_COMPLETED, new ArrayList<>());
|
||||||
if (result) {
|
if (result) {
|
||||||
receivablePayableDetailService.generateForCompletedWaybills(associatedWaybillIds);
|
receivablePayableDetailService.generateForCompletedLoading(
|
||||||
|
associatedWaybillIds, loadingManage.getCarrierContractId());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -298,6 +323,7 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
|||||||
|| Objects.equals(loadingManage.getBusinessStatus(), STATUS_DRAFT)) {
|
|| Objects.equals(loadingManage.getBusinessStatus(), STATUS_DRAFT)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
validateCompletedCarrierContract(loadingManage);
|
||||||
List<Long> waybillIdList = waybillIds(loadingManage.getWaybillIdsJson());
|
List<Long> waybillIdList = waybillIds(loadingManage.getWaybillIdsJson());
|
||||||
if (Func.isEmpty(waybillIdList)) {
|
if (Func.isEmpty(waybillIdList)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -311,7 +337,12 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
loadingManage.setBusinessStatus(STATUS_COMPLETED);
|
loadingManage.setBusinessStatus(STATUS_COMPLETED);
|
||||||
return updateById(loadingManage);
|
boolean result = updateById(loadingManage);
|
||||||
|
if (result) {
|
||||||
|
receivablePayableDetailService.generateForCompletedLoading(
|
||||||
|
waybillIdList, loadingManage.getCarrierContractId());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -478,11 +509,14 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
|||||||
TransportBusinessSupport.validateRequired(loadingManage.getVehicleNo(), "车/船/航班/班列不能为空");
|
TransportBusinessSupport.validateRequired(loadingManage.getVehicleNo(), "车/船/航班/班列不能为空");
|
||||||
TransportBusinessSupport.validateRequired(loadingManage.getDepartureAddress(), "发货地不能为空");
|
TransportBusinessSupport.validateRequired(loadingManage.getDepartureAddress(), "发货地不能为空");
|
||||||
TransportBusinessSupport.validateRequired(loadingManage.getArrivalAddress(), "到货地不能为空");
|
TransportBusinessSupport.validateRequired(loadingManage.getArrivalAddress(), "到货地不能为空");
|
||||||
if (Objects.equals(loadingManage.getCarrierType(), CARRIER_SELF)) {
|
if (!Objects.equals(loadingManage.getCarrierType(), CARRIER_SELF)
|
||||||
|
&& Func.isEmpty(loadingManage.getCarrierContractId())) {
|
||||||
|
throw new ServiceException("请选择承运商合同");
|
||||||
|
}
|
||||||
|
if (Objects.equals(loadingManage.getCarrierType(), CARRIER_SELF)
|
||||||
|
|| Objects.equals(loadingManage.getCarrierType(), CARRIER_PLATFORM)) {
|
||||||
TransportBusinessSupport.validateRequired(loadingManage.getDriverName(), "司机不能为空");
|
TransportBusinessSupport.validateRequired(loadingManage.getDriverName(), "司机不能为空");
|
||||||
TransportBusinessSupport.validateRequired(loadingManage.getDriverPhone(), "联系电话不能为空");
|
TransportBusinessSupport.validateRequired(loadingManage.getDriverPhone(), "联系电话不能为空");
|
||||||
} else if (Objects.equals(loadingManage.getCarrierType(), CARRIER_COMPANY) || Objects.equals(loadingManage.getCarrierType(), CARRIER_PLATFORM)) {
|
|
||||||
TransportBusinessSupport.validateRequired(loadingManage.getCarrierName(), "承运商不能为空");
|
|
||||||
}
|
}
|
||||||
TransportBusinessSupport.validateLength(loadingManage.getLoadingNo(), 100, "配载单号不能超过100字");
|
TransportBusinessSupport.validateLength(loadingManage.getLoadingNo(), 100, "配载单号不能超过100字");
|
||||||
TransportBusinessSupport.validateLength(loadingManage.getLoadingSubNos(), 200, "配载子单号不能超过200字");
|
TransportBusinessSupport.validateLength(loadingManage.getLoadingSubNos(), 200, "配载子单号不能超过200字");
|
||||||
@@ -557,6 +591,97 @@ public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMappe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateCarrierContract(LoadingManage loadingManage, boolean required) {
|
||||||
|
if (Objects.equals(loadingManage.getCarrierType(), CARRIER_SELF)) {
|
||||||
|
loadingManage.setCarrierContractId(null);
|
||||||
|
loadingManage.setCarrierName(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Func.isEmpty(loadingManage.getCarrierContractId())) {
|
||||||
|
if (required) {
|
||||||
|
throw new ServiceException("请选择承运商合同");
|
||||||
|
}
|
||||||
|
loadingManage.setCarrierName(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ContractManage carrierContract = findCarrierContracts(
|
||||||
|
waybillIds(loadingManage.getWaybillIdsJson())).stream()
|
||||||
|
.filter(contract -> 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<ContractManage> findCarrierContracts(List<Long> waybillIds) {
|
||||||
|
if (Func.isEmpty(waybillIds)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
List<Long> distinctWaybillIds = waybillIds.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.distinct()
|
||||||
|
.toList();
|
||||||
|
if (Func.isEmpty(distinctWaybillIds)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
List<Waybill> waybillList = waybillMapper.selectList(Wrappers.<Waybill>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<Long> customerContractIds = waybillList.stream()
|
||||||
|
.map(Waybill::getContractId)
|
||||||
|
.distinct()
|
||||||
|
.toList();
|
||||||
|
Map<Long, ContractManage> 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.<ContractManage>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<Long> oldWaybillIds) {
|
private void syncAssociatedWaybills(LoadingManage loadingManage, String status, List<Long> oldWaybillIds) {
|
||||||
List<Long> newWaybillIds = waybillIds(loadingManage.getWaybillIdsJson());
|
List<Long> newWaybillIds = waybillIds(loadingManage.getWaybillIdsJson());
|
||||||
if (Func.isNotEmpty(oldWaybillIds)) {
|
if (Func.isNotEmpty(oldWaybillIds)) {
|
||||||
|
|||||||
+58
-4
@@ -20,6 +20,7 @@ import org.springblade.transport.pojo.entity.ContractManage;
|
|||||||
import org.springblade.transport.pojo.entity.ProjectApply;
|
import org.springblade.transport.pojo.entity.ProjectApply;
|
||||||
import org.springblade.transport.pojo.entity.TransportPlan;
|
import org.springblade.transport.pojo.entity.TransportPlan;
|
||||||
import org.springblade.transport.pojo.entity.Waybill;
|
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.pojo.vo.MasterOrderVO;
|
||||||
import org.springblade.transport.service.IMasterOrderService;
|
import org.springblade.transport.service.IMasterOrderService;
|
||||||
import org.springblade.transport.service.IContractManageService;
|
import org.springblade.transport.service.IContractManageService;
|
||||||
@@ -77,6 +78,17 @@ public class MasterOrderServiceImpl extends BaseServiceImpl<MasterOrderMapper, M
|
|||||||
return toVO(masterOrder);
|
return toVO(masterOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<MasterOrderCarrierVO> 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
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public MasterOrderVO submit(MasterOrderVO request, boolean draft) {
|
public MasterOrderVO submit(MasterOrderVO request, boolean draft) {
|
||||||
@@ -203,7 +215,7 @@ public class MasterOrderServiceImpl extends BaseServiceImpl<MasterOrderMapper, M
|
|||||||
waybill.setContractId(masterOrder.getContractId()); waybill.setContractName(masterOrder.getContractName());
|
waybill.setContractId(masterOrder.getContractId()); waybill.setContractName(masterOrder.getContractName());
|
||||||
waybill.setCustomerName(masterOrder.getCustomerName()); waybill.setMasterNo(masterOrder.getMasterNo());
|
waybill.setCustomerName(masterOrder.getCustomerName()); waybill.setMasterNo(masterOrder.getMasterNo());
|
||||||
waybill.setTransportType(string(dispatch, "transportType")); waybill.setCarrierType(string(dispatch, "carrierType"));
|
waybill.setTransportType(string(dispatch, "transportType")); waybill.setCarrierType(string(dispatch, "carrierType"));
|
||||||
waybill.setCarrierName(string(dispatch, "carrierName")); waybill.setDriverName(string(dispatch, "driverName"));
|
waybill.setCarrierContractId(longValue(dispatch, "carrierContractId")); waybill.setCarrierName(string(dispatch, "carrierName")); waybill.setDriverName(string(dispatch, "driverName"));
|
||||||
waybill.setDriverPhone(string(dispatch, "driverPhone")); waybill.setVehicleNo(string(dispatch, "vehicleNo")); waybill.setTrailerVehicleNo(string(dispatch, "trailerVehicleNo"));
|
waybill.setDriverPhone(string(dispatch, "driverPhone")); waybill.setVehicleNo(string(dispatch, "vehicleNo")); waybill.setTrailerVehicleNo(string(dispatch, "trailerVehicleNo"));
|
||||||
waybill.setCaptainName(string(dispatch, "captainName")); waybill.setCabinNo(string(dispatch, "cabinNo")); waybill.setContainerNo(string(dispatch, "containerNo"));
|
waybill.setCaptainName(string(dispatch, "captainName")); waybill.setCabinNo(string(dispatch, "cabinNo")); waybill.setContainerNo(string(dispatch, "containerNo"));
|
||||||
waybill.setEscortName(string(dispatch, "escortName")); waybill.setEscortPhone(string(dispatch, "escortPhone")); waybill.setMileage(nullableDecimal(dispatch, "mileage"));
|
waybill.setEscortName(string(dispatch, "escortName")); waybill.setEscortPhone(string(dispatch, "escortPhone")); waybill.setMileage(nullableDecimal(dispatch, "mileage"));
|
||||||
@@ -343,6 +355,8 @@ public class MasterOrderServiceImpl extends BaseServiceImpl<MasterOrderMapper, M
|
|||||||
private List<Map<String, Object>> parseArray(String json) { if (Func.isEmpty(json)) return new ArrayList<>(); try { return JsonUtil.parse(json, List.class); } catch (Exception exception) { return new ArrayList<>(); } }
|
private List<Map<String, Object>> 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<Map<String, Object>> dispatches) {
|
private void validateDispatches(MasterOrder masterOrder, List<Map<String, Object>> dispatches) {
|
||||||
Map<String, BigDecimal> available = availableGoods(masterOrder);
|
Map<String, BigDecimal> available = availableGoods(masterOrder);
|
||||||
|
Map<Long, ContractManage> availableCarrierContracts = availableCarrierContracts(masterOrder).stream()
|
||||||
|
.collect(java.util.stream.Collectors.toMap(ContractManage::getId, contract -> contract));
|
||||||
Map<String, Map<String, BigDecimal>> usedBySegment = new LinkedHashMap<>();
|
Map<String, Map<String, BigDecimal>> usedBySegment = new LinkedHashMap<>();
|
||||||
for (Map<String, Object> dispatch : dispatches) {
|
for (Map<String, Object> dispatch : dispatches) {
|
||||||
String segmentNo = string(dispatch, "segmentNo");
|
String segmentNo = string(dispatch, "segmentNo");
|
||||||
@@ -357,7 +371,9 @@ public class MasterOrderServiceImpl extends BaseServiceImpl<MasterOrderMapper, M
|
|||||||
LocalDate startDate = date(dispatch, "estimatedStartTime"); LocalDate endDate = date(dispatch, "estimatedEndTime");
|
LocalDate startDate = date(dispatch, "estimatedStartTime"); LocalDate endDate = date(dispatch, "estimatedEndTime");
|
||||||
if (startDate == null || endDate == null) throw new ServiceException("预计发货日期和预计完成日期不能为空");
|
if (startDate == null || endDate == null) throw new ServiceException("预计发货日期和预计完成日期不能为空");
|
||||||
if (startDate.isAfter(endDate)) throw new ServiceException("预计发货日期不能晚于预计完成日期");
|
if (startDate.isAfter(endDate)) throw new ServiceException("预计发货日期不能晚于预计完成日期");
|
||||||
if ("运单".equals(string(dispatch, "documentType", "运单"))) validateCarrier(dispatch);
|
if ("运单".equals(string(dispatch, "documentType", "运单"))) {
|
||||||
|
validateCarrier(dispatch, availableCarrierContracts);
|
||||||
|
}
|
||||||
Map<String, BigDecimal> used = usedBySegment.computeIfAbsent(segmentNo, value -> dispatchedGoods(masterOrder.getMasterNo(), value));
|
Map<String, BigDecimal> used = usedBySegment.computeIfAbsent(segmentNo, value -> dispatchedGoods(masterOrder.getMasterNo(), value));
|
||||||
used.merge(key, quantity, BigDecimal::add);
|
used.merge(key, quantity, BigDecimal::add);
|
||||||
if (used.get(key).compareTo(available.get(key)) > 0) throw new ServiceException("货物【" + string(dispatch, "cargoName") + "】的调度数量超过可调度数量");
|
if (used.get(key).compareTo(available.get(key)) > 0) throw new ServiceException("货物【" + string(dispatch, "cargoName") + "】的调度数量超过可调度数量");
|
||||||
@@ -372,8 +388,45 @@ public class MasterOrderServiceImpl extends BaseServiceImpl<MasterOrderMapper, M
|
|||||||
Map<String, BigDecimal> dispatched = dispatchedGoods(masterNo, segmentNo);
|
Map<String, BigDecimal> dispatched = dispatchedGoods(masterNo, segmentNo);
|
||||||
return available.entrySet().stream().allMatch(item -> dispatched.getOrDefault(item.getKey(), BigDecimal.ZERO).compareTo(item.getValue()) >= 0);
|
return available.entrySet().stream().allMatch(item -> dispatched.getOrDefault(item.getKey(), BigDecimal.ZERO).compareTo(item.getValue()) >= 0);
|
||||||
}
|
}
|
||||||
private void validateCarrier(Map<String, Object> dispatch) {
|
private List<ContractManage> availableCarrierContracts(MasterOrder masterOrder) {
|
||||||
|
if (Func.isEmpty(masterOrder.getContractId())) {
|
||||||
|
throw new ServiceException("总单未绑定客户合同");
|
||||||
|
}
|
||||||
|
ContractManage customerContract = contractManageService.getById(masterOrder.getContractId());
|
||||||
|
if (customerContract == null || !Objects.equals(customerContract.getContractCategory(), "客户合同")
|
||||||
|
|| Func.isEmpty(customerContract.getProjectId())) {
|
||||||
|
throw new ServiceException("总单绑定的客户合同不存在或项目信息不完整");
|
||||||
|
}
|
||||||
|
if (!Objects.equals(masterOrder.getProjectId(), customerContract.getProjectId())) {
|
||||||
|
throw new ServiceException("总单项目与客户合同所属项目不一致");
|
||||||
|
}
|
||||||
|
Map<String, ContractManage> contractsByCarrier = new LinkedHashMap<>();
|
||||||
|
contractManageService.list(new LambdaQueryWrapper<ContractManage>()
|
||||||
|
.eq(ContractManage::getIsDeleted, 0)
|
||||||
|
.eq(ContractManage::getProjectId, customerContract.getProjectId())
|
||||||
|
.eq(ContractManage::getContractCategory, "承运商合同")
|
||||||
|
.in(ContractManage::getApprovalStatus, "approved", "change_approved")
|
||||||
|
.and(wrapper -> wrapper.isNull(ContractManage::getContractStage)
|
||||||
|
.or().ne(ContractManage::getContractStage, "terminated"))
|
||||||
|
.orderByDesc(ContractManage::getCreateTime))
|
||||||
|
.stream().filter(contract -> Func.isNotEmpty(contract.getPartyB()))
|
||||||
|
.forEach(contract -> contractsByCarrier.putIfAbsent(contract.getPartyB(), contract));
|
||||||
|
return new ArrayList<>(contractsByCarrier.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateCarrier(Map<String, Object> dispatch, Map<Long, ContractManage> availableCarrierContracts) {
|
||||||
String carrierType = string(dispatch, "carrierType", "承运商");
|
String carrierType = string(dispatch, "carrierType", "承运商");
|
||||||
|
if ("自运".equals(carrierType)) {
|
||||||
|
dispatch.remove("carrierContractId");
|
||||||
|
dispatch.remove("carrierName");
|
||||||
|
}
|
||||||
|
String carrierName = string(dispatch, "carrierName");
|
||||||
|
Long carrierContractId = longValue(dispatch, "carrierContractId");
|
||||||
|
ContractManage carrierContract = carrierContractId == null ? null : availableCarrierContracts.get(carrierContractId);
|
||||||
|
if (!"自运".equals(carrierType) && (carrierContract == null
|
||||||
|
|| !Objects.equals(carrierContract.getPartyB(), carrierName))) {
|
||||||
|
throw new ServiceException("所选承运商不属于总单客户合同对应项目的有效承运商合同乙方");
|
||||||
|
}
|
||||||
boolean road = string(dispatch, "transportType", "").toLowerCase().contains("road") || string(dispatch, "transportType", "").contains("公路");
|
boolean road = string(dispatch, "transportType", "").toLowerCase().contains("road") || string(dispatch, "transportType", "").contains("公路");
|
||||||
if (!road) {
|
if (!road) {
|
||||||
if (Func.isEmpty(string(dispatch, "vehicleNo")) || Func.isEmpty(string(dispatch, "captainName")) || Func.isEmpty(string(dispatch, "driverPhone")) || Func.isEmpty(string(dispatch, "containerNo")) || Func.isEmpty(string(dispatch, "cabinNo")) || Func.isEmpty(string(dispatch, "mileage")) || decimal(dispatch, "mileage").compareTo(BigDecimal.ZERO) <= 0 || ("承运商".equals(carrierType) && Func.isEmpty(string(dispatch, "carrierName")))) {
|
if (Func.isEmpty(string(dispatch, "vehicleNo")) || Func.isEmpty(string(dispatch, "captainName")) || Func.isEmpty(string(dispatch, "driverPhone")) || Func.isEmpty(string(dispatch, "containerNo")) || Func.isEmpty(string(dispatch, "cabinNo")) || Func.isEmpty(string(dispatch, "mileage")) || decimal(dispatch, "mileage").compareTo(BigDecimal.ZERO) <= 0 || ("承运商".equals(carrierType) && Func.isEmpty(string(dispatch, "carrierName")))) {
|
||||||
@@ -453,10 +506,11 @@ public class MasterOrderServiceImpl extends BaseServiceImpl<MasterOrderMapper, M
|
|||||||
freight.put("currency", string(dispatch, "currency", "CNY"));
|
freight.put("currency", string(dispatch, "currency", "CNY"));
|
||||||
return JsonUtil.toJson(freight);
|
return JsonUtil.toJson(freight);
|
||||||
}
|
}
|
||||||
private String waybillGroupKey(Map<String, Object> dispatch) { return String.join("\u0000", string(dispatch, "segmentNo", ""), string(dispatch, "carrierType", ""), string(dispatch, "carrierName", ""), string(dispatch, "driverName", ""), string(dispatch, "driverPhone", ""), string(dispatch, "vehicleNo", ""), string(dispatch, "captainName", ""), string(dispatch, "containerNo", ""), string(dispatch, "cabinNo", "")); }
|
private String waybillGroupKey(Map<String, Object> dispatch) { return String.join("\u0000", string(dispatch, "segmentNo", ""), string(dispatch, "carrierType", ""), string(dispatch, "carrierContractId", ""), string(dispatch, "carrierName", ""), string(dispatch, "driverName", ""), string(dispatch, "driverPhone", ""), string(dispatch, "vehicleNo", ""), string(dispatch, "captainName", ""), string(dispatch, "containerNo", ""), string(dispatch, "cabinNo", "")); }
|
||||||
private String joinGoodsField(List<Map<String, Object>> dispatches, String field) { return dispatches.stream().map(item -> string(item, field, "")).filter(Func::isNotEmpty).distinct().reduce((left, right) -> left + "、" + right).orElse(""); }
|
private String joinGoodsField(List<Map<String, Object>> 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<String, Object> values, String key) { try { return new BigDecimal(string(values, key, "0")); } catch (Exception exception) { return BigDecimal.ZERO; } }
|
private BigDecimal decimal(Map<String, Object> values, String key) { try { return new BigDecimal(string(values, key, "0")); } catch (Exception exception) { return BigDecimal.ZERO; } }
|
||||||
private BigDecimal nullableDecimal(Map<String, Object> 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 BigDecimal nullableDecimal(Map<String, Object> 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 Long longValue(Map<String, Object> values, String key) { String value = string(values, key); if (Func.isEmpty(value)) return null; try { return Long.valueOf(value); } catch (Exception exception) { return null; } }
|
||||||
private String goodsKey(Map<String, Object> values) { return goodsKey(string(values, "cargoName"), string(values, "cargoType")); }
|
private String goodsKey(Map<String, Object> 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 String goodsKey(String cargoName, String cargoType) { return String.valueOf(cargoName) + "\u0000" + String.valueOf(cargoType); }
|
||||||
private LocalDate date(Map<String, Object> 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("日期格式不正确"); } }
|
private LocalDate date(Map<String, Object> 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("日期格式不正确"); } }
|
||||||
|
|||||||
+240
-100
@@ -84,6 +84,10 @@ import java.util.Map;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.BooleanSupplier;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应收应付明细服务实现类
|
* 应收应付明细服务实现类
|
||||||
@@ -535,25 +539,46 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
@Transactional(propagation = org.springframework.transaction.annotation.Propagation.REQUIRES_NEW,
|
@Transactional(propagation = org.springframework.transaction.annotation.Propagation.REQUIRES_NEW,
|
||||||
rollbackFor = Exception.class)
|
rollbackFor = Exception.class)
|
||||||
public void generateForCompletedWaybills(List<Long> waybillIds) {
|
public void generateForCompletedWaybills(List<Long> waybillIds) {
|
||||||
if (Func.isEmpty(waybillIds)) return;
|
generateAutomaticWaybillDetails(loadWaybills(waybillIds), true,
|
||||||
Long currentUserId = AuthUtil.getUserId();
|
this::resolveWaybillCarrierContract, AuthUtil.getUserId(), new Date());
|
||||||
Date generateTime = new Date();
|
}
|
||||||
for (Long waybillId : waybillIds) {
|
|
||||||
Waybill waybill = waybillService.getById(waybillId);
|
@Override
|
||||||
if (waybill == null) continue;
|
@Transactional(propagation = org.springframework.transaction.annotation.Propagation.REQUIRES_NEW,
|
||||||
|
rollbackFor = Exception.class)
|
||||||
|
public void generateForCompletedLoading(List<Long> waybillIds, Long carrierContractId) {
|
||||||
|
ContractManage carrierContract = carrierContractId == null
|
||||||
|
? null : contractManageService.getById(carrierContractId);
|
||||||
|
if (carrierContractId != null && (carrierContract == null
|
||||||
|
|| !"承运商合同".equals(carrierContract.getContractCategory()))) {
|
||||||
|
throw new ServiceException("配载单记录的承运商合同不存在或合同类别不正确");
|
||||||
|
}
|
||||||
|
generateAutomaticWaybillDetails(loadWaybills(waybillIds), true,
|
||||||
|
waybill -> carrierContract, AuthUtil.getUserId(), new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Waybill> loadWaybills(List<Long> waybillIds) {
|
||||||
|
if (Func.isEmpty(waybillIds)) return List.of();
|
||||||
|
return waybillService.list(Wrappers.<Waybill>lambdaQuery()
|
||||||
|
.eq(Waybill::getIsDeleted, 0)
|
||||||
|
.in(Waybill::getId, waybillIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateAutomaticWaybillDetails(List<Waybill> waybills, boolean generateReceivable,
|
||||||
|
Function<Waybill, ContractManage> payableContractResolver,
|
||||||
|
Long currentUserId, Date generateTime) {
|
||||||
|
for (Waybill waybill : waybills) {
|
||||||
|
try {
|
||||||
|
if (generateReceivable) {
|
||||||
ContractManage receivableContract = Func.isEmpty(waybill.getContractId())
|
ContractManage receivableContract = Func.isEmpty(waybill.getContractId())
|
||||||
? null : contractManageService.getById(waybill.getContractId());
|
? null : contractManageService.getById(waybill.getContractId());
|
||||||
try {
|
generateAutomaticWaybillDetail(waybill, receivableContract, "receivable",
|
||||||
if (receivableContract != null && "客户合同".equals(receivableContract.getContractCategory())
|
currentUserId, generateTime);
|
||||||
&& isSystemGeneration(receivableContract)) {
|
|
||||||
generateCompletedWaybillDetail(waybill, receivableContract, "receivable", currentUserId, generateTime);
|
|
||||||
}
|
|
||||||
if (Func.isNotEmpty(waybill.getCarrierName())) {
|
|
||||||
ContractManage payableContract = findCarrierContract(waybill);
|
|
||||||
if (payableContract != null && isSystemGeneration(payableContract)) {
|
|
||||||
generateCompletedWaybillDetail(waybill, payableContract, "payable", currentUserId, generateTime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ContractManage payableContract = payableContractResolver == null
|
||||||
|
? null : payableContractResolver.apply(waybill);
|
||||||
|
generateAutomaticWaybillDetail(waybill, payableContract, "payable",
|
||||||
|
currentUserId, generateTime);
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
log.error("自动生成运单费用明细失败,waybillId:{}, waybillNo:{}, receivableContractId:{}, failureReason:{}",
|
log.error("自动生成运单费用明细失败,waybillId:{}, waybillNo:{}, receivableContractId:{}, failureReason:{}",
|
||||||
waybill.getId(), waybill.getWaybillNo(), waybill.getContractId(), exception.getMessage(), exception);
|
waybill.getId(), waybill.getWaybillNo(), waybill.getContractId(), exception.getMessage(), exception);
|
||||||
@@ -565,24 +590,24 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateCompletedWaybillDetail(Waybill waybill, ContractManage contract, String settlementType,
|
private void generateAutomaticWaybillDetail(Waybill waybill, ContractManage contract, String settlementType,
|
||||||
Long currentUserId, Date generateTime) {
|
Long currentUserId, Date generateTime) {
|
||||||
if (existsByWaybill(waybill.getId(), settlementType)) return;
|
generateAutomaticDetail(contract, settlementType,
|
||||||
String planId = matchedPlanId(waybill, contract);
|
() -> existsByWaybill(waybill.getId(), settlementType), List.of(waybill),
|
||||||
if (Func.isEmpty(planId)) return;
|
(fees, unitPrice) -> buildDetail(waybill, contract, settlementType, fees, unitPrice),
|
||||||
// 自动生成只按合同默认计费方案计算,matchOnly=true 禁止回退读取运单自身其他费用。
|
false, currentUserId, generateTime);
|
||||||
List<ReceivablePayableCargoFee> matchedFees = calculatedFees(waybill, contract, planId, true);
|
|
||||||
if (matchedFees.isEmpty()) return;
|
|
||||||
BigDecimal contractUnitPrice = resolveContractUnitPrice(matchedFees);
|
|
||||||
ReceivablePayableDetail detail = buildDetail(waybill, contract, settlementType, matchedFees, contractUnitPrice);
|
|
||||||
save(detail);
|
|
||||||
for (ReceivablePayableCargoFee fee : matchedFees) {
|
|
||||||
ReceivablePayableCargoFee copy = BeanUtil.copyProperties(fee, ReceivablePayableCargoFee.class);
|
|
||||||
copy.setId(null);
|
|
||||||
copy.setDetailId(detail.getId());
|
|
||||||
fillGeneratedAuditFields(copy, currentUserId, generateTime);
|
|
||||||
cargoFeeMapper.insert(copy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ContractManage resolveWaybillCarrierContract(Waybill waybill) {
|
||||||
|
if (Func.isNotEmpty(waybill.getLoadingNo())) return null;
|
||||||
|
if (Func.isNotEmpty(waybill.getCarrierContractId())) {
|
||||||
|
ContractManage contract = contractManageService.getById(waybill.getCarrierContractId());
|
||||||
|
if (contract == null || !"承运商合同".equals(contract.getContractCategory())) {
|
||||||
|
throw new ServiceException("运单记录的承运商合同不存在或合同类别不正确");
|
||||||
|
}
|
||||||
|
return contract;
|
||||||
|
}
|
||||||
|
return findCarrierContract(waybill);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContractManage findCarrierContract(Waybill waybill) {
|
private ContractManage findCarrierContract(Waybill waybill) {
|
||||||
@@ -611,39 +636,14 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
@Transactional(propagation = org.springframework.transaction.annotation.Propagation.REQUIRES_NEW,
|
@Transactional(propagation = org.springframework.transaction.annotation.Propagation.REQUIRES_NEW,
|
||||||
rollbackFor = Exception.class)
|
rollbackFor = Exception.class)
|
||||||
public void generateForClosedMasterOrder(MasterOrder masterOrder) {
|
public void generateForClosedMasterOrder(MasterOrder masterOrder) {
|
||||||
if (masterOrder == null || Func.isEmpty(masterOrder.getId()) || Func.isEmpty(masterOrder.getContractId())) {
|
if (masterOrder == null || Func.isEmpty(masterOrder.getId()) || Func.isEmpty(masterOrder.getMasterNo())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ContractManage contract = contractManageService.getById(masterOrder.getContractId());
|
|
||||||
if (contract == null || !isSystemGeneration(contract)) return;
|
|
||||||
Long currentUserId = AuthUtil.getUserId();
|
Long currentUserId = AuthUtil.getUserId();
|
||||||
Date generateTime = new Date();
|
Date generateTime = new Date();
|
||||||
try {
|
try {
|
||||||
List<Waybill> masterGoods = masterOrderGoods(masterOrder);
|
generateClosedMasterOrderReceivable(masterOrder, currentUserId, generateTime);
|
||||||
if (masterGoods.isEmpty()) return;
|
generateClosedMasterOrderPayables(masterOrder, currentUserId, generateTime);
|
||||||
List<ReceivablePayableCargoFee> matchedFees = new ArrayList<>();
|
|
||||||
for (Waybill masterGoodsItem : masterGoods) {
|
|
||||||
String planId = matchedPlanId(masterGoodsItem, contract);
|
|
||||||
if (Func.isEmpty(planId)) continue;
|
|
||||||
matchedFees.addAll(calculatedFees(masterGoodsItem, contract, planId, true));
|
|
||||||
}
|
|
||||||
if (matchedFees.isEmpty()) return;
|
|
||||||
normalizeMasterFeeLines(matchedFees);
|
|
||||||
BigDecimal contractUnitPrice = resolveContractUnitPrice(matchedFees);
|
|
||||||
for (String settlementType : List.of("payable", "receivable")) {
|
|
||||||
if (existsByMasterOrder(masterOrder.getMasterNo(), settlementType)) continue;
|
|
||||||
ReceivablePayableDetail detail = buildMasterOrderDetail(masterOrder, contract, masterGoods,
|
|
||||||
settlementType, matchedFees, contractUnitPrice);
|
|
||||||
save(detail);
|
|
||||||
for (ReceivablePayableCargoFee fee : matchedFees) {
|
|
||||||
ReceivablePayableCargoFee copy = BeanUtil.copyProperties(fee, ReceivablePayableCargoFee.class);
|
|
||||||
copy.setId(null);
|
|
||||||
copy.setDetailId(detail.getId());
|
|
||||||
copy.setWaybillId(null);
|
|
||||||
fillGeneratedAuditFields(copy, currentUserId, generateTime);
|
|
||||||
cargoFeeMapper.insert(copy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
log.error("自动生成总单费用明细失败,masterOrderId:{}, masterNo:{}, contractId:{}, failureReason:{}",
|
log.error("自动生成总单费用明细失败,masterOrderId:{}, masterNo:{}, contractId:{}, failureReason:{}",
|
||||||
masterOrder.getId(), masterOrder.getMasterNo(), masterOrder.getContractId(), exception.getMessage(), exception);
|
masterOrder.getId(), masterOrder.getMasterNo(), masterOrder.getContractId(), exception.getMessage(), exception);
|
||||||
@@ -654,6 +654,85 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void generateClosedMasterOrderReceivable(MasterOrder masterOrder, Long currentUserId,
|
||||||
|
Date generateTime) {
|
||||||
|
if (Func.isEmpty(masterOrder.getContractId())) return;
|
||||||
|
ContractManage customerContract = contractManageService.getById(masterOrder.getContractId());
|
||||||
|
List<Waybill> masterGoods = masterOrderGoods(masterOrder);
|
||||||
|
if (masterGoods.isEmpty()) return;
|
||||||
|
generateAutomaticDetail(customerContract, "receivable",
|
||||||
|
() -> existsByMasterOrder(masterOrder.getMasterNo(), "receivable"), masterGoods,
|
||||||
|
(fees, unitPrice) -> {
|
||||||
|
normalizeMasterFeeLines(fees);
|
||||||
|
return buildMasterOrderDetail(masterOrder, customerContract, masterGoods,
|
||||||
|
"receivable", fees, unitPrice);
|
||||||
|
}, true, currentUserId, generateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateClosedMasterOrderPayables(MasterOrder masterOrder, Long currentUserId,
|
||||||
|
Date generateTime) {
|
||||||
|
List<Waybill> waybills = waybillService.list(Wrappers.<Waybill>lambdaQuery()
|
||||||
|
.eq(Waybill::getIsDeleted, 0)
|
||||||
|
.eq(Waybill::getMasterNo, masterOrder.getMasterNo())
|
||||||
|
.isNotNull(Waybill::getCarrierContractId));
|
||||||
|
if (waybills.isEmpty()) return;
|
||||||
|
Map<Long, ContractManage> carrierContracts = contractManageService.listByIds(waybills.stream()
|
||||||
|
.map(Waybill::getCarrierContractId).distinct().toList()).stream()
|
||||||
|
.collect(Collectors.toMap(ContractManage::getId, contract -> contract));
|
||||||
|
generateAutomaticWaybillDetails(waybills, false, waybill -> {
|
||||||
|
ContractManage carrierContract = carrierContracts.get(waybill.getCarrierContractId());
|
||||||
|
if (carrierContract == null || !"承运商合同".equals(carrierContract.getContractCategory())) {
|
||||||
|
throw new ServiceException("运单【" + waybill.getWaybillNo() + "】记录的承运商合同不存在或合同类别不正确");
|
||||||
|
}
|
||||||
|
return carrierContract;
|
||||||
|
}, currentUserId, generateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isAutomaticContract(ContractManage contract, String settlementType) {
|
||||||
|
if (contract == null) return false;
|
||||||
|
String expectedCategory = "payable".equals(settlementType) ? "承运商合同" : "客户合同";
|
||||||
|
return Objects.equals(expectedCategory, contract.getContractCategory()) && isSystemGeneration(contract);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ReceivablePayableCargoFee> calculateAutomaticFees(List<Waybill> waybills,
|
||||||
|
ContractManage contract) {
|
||||||
|
List<ReceivablePayableCargoFee> matchedFees = new ArrayList<>();
|
||||||
|
for (Waybill waybill : waybills) {
|
||||||
|
String planId = matchedPlanId(waybill, contract);
|
||||||
|
if (Func.isEmpty(planId)) continue;
|
||||||
|
// 自动生成统一使用合同默认计费方案,且禁止回退读取运单自身其他费用。
|
||||||
|
matchedFees.addAll(calculatedFees(waybill, contract, planId, true));
|
||||||
|
}
|
||||||
|
return matchedFees;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateAutomaticDetail(ContractManage contract, String settlementType,
|
||||||
|
BooleanSupplier exists, List<Waybill> billingWaybills,
|
||||||
|
BiFunction<List<ReceivablePayableCargoFee>, BigDecimal,
|
||||||
|
ReceivablePayableDetail> detailBuilder,
|
||||||
|
boolean clearWaybillId, Long currentUserId, Date generateTime) {
|
||||||
|
if (!isAutomaticContract(contract, settlementType) || exists.getAsBoolean()) return;
|
||||||
|
List<ReceivablePayableCargoFee> matchedFees = calculateAutomaticFees(billingWaybills, contract);
|
||||||
|
if (matchedFees.isEmpty()) return;
|
||||||
|
BigDecimal contractUnitPrice = resolveContractUnitPrice(matchedFees);
|
||||||
|
ReceivablePayableDetail detail = detailBuilder.apply(matchedFees, contractUnitPrice);
|
||||||
|
saveAutomaticDetail(detail, matchedFees, clearWaybillId, currentUserId, generateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveAutomaticDetail(ReceivablePayableDetail detail,
|
||||||
|
List<ReceivablePayableCargoFee> fees, boolean clearWaybillId,
|
||||||
|
Long currentUserId, Date generateTime) {
|
||||||
|
save(detail);
|
||||||
|
for (ReceivablePayableCargoFee fee : fees) {
|
||||||
|
ReceivablePayableCargoFee copy = BeanUtil.copyProperties(fee, ReceivablePayableCargoFee.class);
|
||||||
|
copy.setId(null);
|
||||||
|
copy.setDetailId(detail.getId());
|
||||||
|
if (clearWaybillId) copy.setWaybillId(null);
|
||||||
|
fillGeneratedAuditFields(copy, currentUserId, generateTime);
|
||||||
|
cargoFeeMapper.insert(copy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isSystemGeneration(ContractManage contract) {
|
private boolean isSystemGeneration(ContractManage contract) {
|
||||||
if (Func.isNotEmpty(contract.getFeeGenerationMode())) {
|
if (Func.isNotEmpty(contract.getFeeGenerationMode())) {
|
||||||
return "system".equalsIgnoreCase(contract.getFeeGenerationMode()) || "系统生成".equals(contract.getFeeGenerationMode());
|
return "system".equalsIgnoreCase(contract.getFeeGenerationMode()) || "系统生成".equals(contract.getFeeGenerationMode());
|
||||||
@@ -833,7 +912,8 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
|
|
||||||
private ReceivablePayableDetail buildDetail(Waybill waybill, ContractManage contract, String settlementType,
|
private ReceivablePayableDetail buildDetail(Waybill waybill, ContractManage contract, String settlementType,
|
||||||
List<ReceivablePayableCargoFee> fees, BigDecimal unitPrice) {
|
List<ReceivablePayableCargoFee> fees, BigDecimal unitPrice) {
|
||||||
BigDecimal freight = fees.stream().filter(this::isFreight).map(ReceivablePayableCargoFee::getAfterAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
BigDecimal freight = fees.stream().map(fee -> money(fee.getFreightAmount()))
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
BigDecimal total = fees.stream().map(ReceivablePayableCargoFee::getAfterAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
BigDecimal total = fees.stream().map(ReceivablePayableCargoFee::getAfterAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
BigDecimal other = total.subtract(freight).setScale(2, RoundingMode.HALF_UP);
|
BigDecimal other = total.subtract(freight).setScale(2, RoundingMode.HALF_UP);
|
||||||
ReceivablePayableDetail detail = new ReceivablePayableDetail();
|
ReceivablePayableDetail detail = new ReceivablePayableDetail();
|
||||||
@@ -1008,8 +1088,9 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
if (plan == null || !(plan.get("rules") instanceof List<?>)) {
|
if (plan == null || !(plan.get("rules") instanceof List<?>)) {
|
||||||
return matchOnly ? List.of() : buildCargoFees(waybill);
|
return matchOnly ? List.of() : buildCargoFees(waybill);
|
||||||
}
|
}
|
||||||
List<ReceivablePayableCargoFee> result = new ArrayList<>();
|
Map<List<String>, ReceivablePayableCargoFee> feesByCargo = new LinkedHashMap<>();
|
||||||
int line = 1;
|
Map<List<String>, Map<String, BigDecimal>> feeItemsByCargo = new LinkedHashMap<>();
|
||||||
|
Set<List<String>> freightBillingCargoKeys = new LinkedHashSet<>();
|
||||||
for (Object value : (List<?>) plan.get("rules")) {
|
for (Object value : (List<?>) plan.get("rules")) {
|
||||||
if (!(value instanceof Map<?, ?> raw)) continue;
|
if (!(value instanceof Map<?, ?> raw)) continue;
|
||||||
Map<String, Object> rule = new LinkedHashMap<>();
|
Map<String, Object> rule = new LinkedHashMap<>();
|
||||||
@@ -1020,23 +1101,67 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
if (amount == null) continue;
|
if (amount == null) continue;
|
||||||
String feeItem = stringValue(rule, "feeItem", "费用");
|
String feeItem = stringValue(rule, "feeItem", "费用");
|
||||||
Map<String, String> feeGoods = summarizeFeeGoods(rule, feeWaybill);
|
Map<String, String> feeGoods = summarizeFeeGoods(rule, feeWaybill);
|
||||||
|
List<String> cargoKey = cargoFeeKey(feeWaybill, feeGoods);
|
||||||
|
ReceivablePayableCargoFee fee = feesByCargo.computeIfAbsent(cargoKey,
|
||||||
|
key -> buildCalculatedCargoFee(waybill, feeWaybill, feeGoods, rule));
|
||||||
|
Map<String, BigDecimal> feeItems = feeItemsByCargo.computeIfAbsent(cargoKey,
|
||||||
|
key -> new LinkedHashMap<>());
|
||||||
|
feeItems.merge(feeItem, amount, BigDecimal::add);
|
||||||
|
fee.setFeeItemsJson(JsonUtil.toJson(feeItems));
|
||||||
|
fee.setOriginalAmount(money(fee.getOriginalAmount()).add(amount));
|
||||||
|
fee.setAfterAmount(fee.getOriginalAmount());
|
||||||
|
if (isFreightRule(rule)) {
|
||||||
|
fee.setFreightAmount(money(fee.getFreightAmount()).add(amount));
|
||||||
|
if (freightBillingCargoKeys.add(cargoKey)) {
|
||||||
|
fillCalculatedBillingFields(fee, feeWaybill, rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<ReceivablePayableCargoFee> result = new ArrayList<>(feesByCargo.values());
|
||||||
|
for (int index = 0; index < result.size(); index++) {
|
||||||
|
ReceivablePayableCargoFee fee = result.get(index);
|
||||||
|
fee.setLineNo(String.format("%04d", index + 1));
|
||||||
|
}
|
||||||
|
return result.isEmpty() && !matchOnly ? buildCargoFees(waybill) : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReceivablePayableCargoFee buildCalculatedCargoFee(Waybill waybill, Waybill feeWaybill,
|
||||||
|
Map<String, String> feeGoods, Map<String, Object> rule) {
|
||||||
ReceivablePayableCargoFee fee = new ReceivablePayableCargoFee();
|
ReceivablePayableCargoFee fee = new ReceivablePayableCargoFee();
|
||||||
fee.setWaybillId(waybill.getId()); fee.setLineNo(String.format("%04d", line++));
|
fee.setWaybillId(waybill.getId());
|
||||||
fee.setCargoName(feeGoods.getOrDefault("cargoName", feeWaybill.getCargoName()));
|
fee.setCargoName(feeGoods.getOrDefault("cargoName", feeWaybill.getCargoName()));
|
||||||
fee.setCargoType(feeGoods.getOrDefault("cargoType", feeWaybill.getCargoType()));
|
fee.setCargoType(feeGoods.getOrDefault("cargoType", feeWaybill.getCargoType()));
|
||||||
fee.setSpecification(feeGoods.getOrDefault("specification", feeWaybill.getSpecification()));
|
fee.setSpecification(feeGoods.getOrDefault("specification", feeWaybill.getSpecification()));
|
||||||
fee.setModel(feeGoods.getOrDefault("model", feeWaybill.getModel()));
|
fee.setModel(feeGoods.getOrDefault("model", feeWaybill.getModel()));
|
||||||
fee.setBillingFactor(stringValue(rule, "billingElement", "")); fee.setBillingType(stringValue(rule, "billingType", ""));
|
|
||||||
fee.setTransportQuantity(measure(rule, feeWaybill));
|
|
||||||
fee.setQuantityUnit(feeGoods.getOrDefault("quantityUnit", feeWaybill.getQuantityUnit()));
|
fee.setQuantityUnit(feeGoods.getOrDefault("quantityUnit", feeWaybill.getQuantityUnit()));
|
||||||
fee.setPriceUnit(stringValue(rule, "billingUnit", feeWaybill.getPriceUnit())); fee.setUnitPrice(decimal(rule.get("unitPrice")));
|
fillCalculatedBillingFields(fee, feeWaybill, rule);
|
||||||
fee.setMileage(normalizeGeneratedMileage(feeWaybill.getMileage())); fee.setFreightAmount(isFreightRule(rule) ? amount : BigDecimal.ZERO);
|
fee.setMileage(normalizeGeneratedMileage(feeWaybill.getMileage()));
|
||||||
fee.setFeeItemsJson(JsonUtil.toJson(Map.of(feeItem, amount)));
|
fee.setFreightAmount(BigDecimal.ZERO);
|
||||||
fee.setOriginalAmount(amount); fee.setAdjustAmount(BigDecimal.ZERO); fee.setAfterAmount(amount); fee.setRemark(stringValue(rule, "remark", feeWaybill.getRemark()));
|
fee.setOriginalAmount(BigDecimal.ZERO);
|
||||||
result.add(fee);
|
fee.setAdjustAmount(BigDecimal.ZERO);
|
||||||
|
fee.setAfterAmount(BigDecimal.ZERO);
|
||||||
|
fee.setRemark(stringValue(rule, "remark", feeWaybill.getRemark()));
|
||||||
|
return fee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fillCalculatedBillingFields(ReceivablePayableCargoFee fee, Waybill feeWaybill,
|
||||||
|
Map<String, Object> rule) {
|
||||||
|
fee.setBillingFactor(stringValue(rule, "billingElement", ""));
|
||||||
|
fee.setBillingType(stringValue(rule, "billingType", ""));
|
||||||
|
fee.setTransportQuantity(measure(rule, feeWaybill));
|
||||||
|
fee.setPriceUnit(stringValue(rule, "billingUnit", feeWaybill.getPriceUnit()));
|
||||||
|
fee.setUnitPrice(decimal(rule.get("unitPrice")));
|
||||||
}
|
}
|
||||||
return result.isEmpty() && !matchOnly ? buildCargoFees(waybill) : result;
|
|
||||||
|
private List<String> cargoFeeKey(Waybill waybill, Map<String, String> feeGoods) {
|
||||||
|
return List.of(
|
||||||
|
Objects.toString(feeGoods.getOrDefault("cargoName", waybill.getCargoName()), ""),
|
||||||
|
Objects.toString(feeGoods.getOrDefault("cargoType", waybill.getCargoType()), ""),
|
||||||
|
Objects.toString(feeGoods.getOrDefault("specification", waybill.getSpecification()), ""),
|
||||||
|
Objects.toString(feeGoods.getOrDefault("model", waybill.getModel()), ""),
|
||||||
|
Objects.toString(feeGoods.getOrDefault("quantityUnit", waybill.getQuantityUnit()), ""),
|
||||||
|
money(waybill.getQuantity()).stripTrailingZeros().toPlainString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Waybill> feeWaybills(Map<String, Object> rule, Waybill waybill) {
|
private List<Waybill> feeWaybills(Map<String, Object> rule, Waybill waybill) {
|
||||||
@@ -1354,22 +1479,26 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
if (rules.isEmpty()) {
|
if (rules.isEmpty()) {
|
||||||
throw new ServiceException("未找到费用明细对应的合同计费规则,请先更新费用");
|
throw new ServiceException("未找到费用明细对应的合同计费规则,请先更新费用");
|
||||||
}
|
}
|
||||||
Map<BigDecimal, Map<String, Object>> results = new LinkedHashMap<>();
|
Map<String, BigDecimal> calculatedAmounts = new LinkedHashMap<>();
|
||||||
|
BigDecimal calculatedFreight = BigDecimal.ZERO;
|
||||||
|
boolean freightRuleMatched = false;
|
||||||
for (Map<String, Object> rule : rules) {
|
for (Map<String, Object> rule : rules) {
|
||||||
BigDecimal amount = calculateRule(rule, adjustedWaybill);
|
BigDecimal amount = calculateRule(rule, adjustedWaybill);
|
||||||
if (amount != null) results.putIfAbsent(money(amount), rule);
|
if (amount == null) continue;
|
||||||
}
|
|
||||||
if (results.size() != 1) {
|
|
||||||
throw new ServiceException("费用明细对应多个计费结果,无法唯一试算,请先更新费用");
|
|
||||||
}
|
|
||||||
Map.Entry<BigDecimal, Map<String, Object>> calculated = results.entrySet().iterator().next();
|
|
||||||
BigDecimal amount = calculated.getKey();
|
|
||||||
Map<String, Object> rule = calculated.getValue();
|
|
||||||
String feeItem = stringValue(rule, "feeItem", "费用");
|
String feeItem = stringValue(rule, "feeItem", "费用");
|
||||||
|
calculatedAmounts.merge(feeItem, amount, BigDecimal::add);
|
||||||
|
if (isFreightRule(rule)) {
|
||||||
|
calculatedFreight = calculatedFreight.add(amount);
|
||||||
|
freightRuleMatched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (calculatedAmounts.isEmpty()) {
|
||||||
|
throw new ServiceException("费用明细对应的合同计费规则无法试算,请先更新费用");
|
||||||
|
}
|
||||||
Map<String, BigDecimal> calculatedFeeItems = new LinkedHashMap<>(feeItems);
|
Map<String, BigDecimal> calculatedFeeItems = new LinkedHashMap<>(feeItems);
|
||||||
calculatedFeeItems.put(feeItem, amount);
|
calculatedAmounts.forEach(calculatedFeeItems::put);
|
||||||
BigDecimal calculatedFreight = isFreightRule(rule) ? amount : freightAmount;
|
return new AdjustedFeeCalculation(freightRuleMatched ? calculatedFreight : freightAmount,
|
||||||
return new AdjustedFeeCalculation(calculatedFreight, calculatedFeeItems);
|
calculatedFeeItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Waybill adjustedWaybill(ReceivablePayableDetail detail, ReceivablePayableCargoFee fee,
|
private Waybill adjustedWaybill(ReceivablePayableDetail detail, ReceivablePayableCargoFee fee,
|
||||||
@@ -1402,28 +1531,38 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
private List<Map<String, Object>> matchingAdjustedRules(ContractManage contract,
|
private List<Map<String, Object>> matchingAdjustedRules(ContractManage contract,
|
||||||
ReceivablePayableCargoFee fee, Waybill waybill) {
|
ReceivablePayableCargoFee fee, Waybill waybill) {
|
||||||
Set<String> feeItemNames = parseMap(fee.getFeeItemsJson()).keySet();
|
Set<String> feeItemNames = parseMap(fee.getFeeItemsJson()).keySet();
|
||||||
List<Map<String, Object>> candidates = new ArrayList<>();
|
List<Map<String, Object>> firstCandidates = List.of();
|
||||||
|
List<Map<String, Object>> defaultCandidates = List.of();
|
||||||
|
List<Map<String, Object>> billingMatchedCandidates = List.of();
|
||||||
for (Map<String, Object> plan : parseList(contract.getBillingPlanJson())) {
|
for (Map<String, Object> plan : parseList(contract.getBillingPlanJson())) {
|
||||||
if (!(plan.get("rules") instanceof List<?> rules)) continue;
|
if (!(plan.get("rules") instanceof List<?> rules)) continue;
|
||||||
|
List<Map<String, Object>> candidates = new ArrayList<>();
|
||||||
for (Object value : rules) {
|
for (Object value : rules) {
|
||||||
if (!(value instanceof Map<?, ?> raw)) continue;
|
if (!(value instanceof Map<?, ?> raw)) continue;
|
||||||
Map<String, Object> rule = new LinkedHashMap<>();
|
Map<String, Object> rule = new LinkedHashMap<>();
|
||||||
raw.forEach((key, item) -> rule.put(String.valueOf(key), item));
|
raw.forEach((key, item) -> rule.put(String.valueOf(key), item));
|
||||||
if (!Objects.equals(stringValue(rule, "billingElement"), fee.getBillingFactor())
|
if (!feeItemNames.contains(stringValue(rule, "feeItem")) || !matchesRule(rule, waybill)) continue;
|
||||||
|| !Objects.equals(stringValue(rule, "billingType"), fee.getBillingType())
|
|
||||||
|| !feeItemNames.contains(stringValue(rule, "feeItem"))) continue;
|
|
||||||
if (Func.isNotEmpty(fee.getPriceUnit())
|
|
||||||
&& !Objects.equals(stringValue(rule, "billingUnit"), fee.getPriceUnit())) continue;
|
|
||||||
candidates.add(rule);
|
candidates.add(rule);
|
||||||
}
|
}
|
||||||
|
if (candidates.isEmpty()) continue;
|
||||||
|
if (firstCandidates.isEmpty()) firstCandidates = candidates;
|
||||||
|
if (isDefaultPlan(plan)) defaultCandidates = candidates;
|
||||||
|
if (candidates.stream().anyMatch(rule -> matchesBillingFields(rule, fee))) {
|
||||||
|
if (billingMatchedCandidates.isEmpty() || isDefaultPlan(plan)) {
|
||||||
|
billingMatchedCandidates = candidates;
|
||||||
}
|
}
|
||||||
List<Map<String, Object>> unitPriceMatched = candidates.stream()
|
}
|
||||||
.filter(rule -> decimal(rule.get("unitPrice")).compareTo(money(fee.getUnitPrice())) == 0)
|
}
|
||||||
.toList();
|
if (!billingMatchedCandidates.isEmpty()) return billingMatchedCandidates;
|
||||||
if (!unitPriceMatched.isEmpty()) candidates = unitPriceMatched;
|
return defaultCandidates.isEmpty() ? firstCandidates : defaultCandidates;
|
||||||
List<Map<String, Object>> conditionMatched = candidates.stream()
|
}
|
||||||
.filter(rule -> matchesRule(rule, waybill)).toList();
|
|
||||||
return conditionMatched.isEmpty() ? candidates : conditionMatched;
|
private boolean matchesBillingFields(Map<String, Object> rule, ReceivablePayableCargoFee fee) {
|
||||||
|
if (!Objects.equals(stringValue(rule, "billingElement"), fee.getBillingFactor())
|
||||||
|
|| !Objects.equals(stringValue(rule, "billingType"), fee.getBillingType())) return false;
|
||||||
|
if (Func.isNotEmpty(fee.getPriceUnit())
|
||||||
|
&& !Objects.equals(stringValue(rule, "billingUnit"), fee.getPriceUnit())) return false;
|
||||||
|
return decimal(rule.get("unitPrice")).compareTo(money(fee.getUnitPrice())) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigDecimal adjustedAfterAmount(BigDecimal freightAmount, Map<String, BigDecimal> feeItems) {
|
private BigDecimal adjustedAfterAmount(BigDecimal freightAmount, Map<String, BigDecimal> feeItems) {
|
||||||
@@ -1488,7 +1627,8 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
List<ReceivablePayableCargoFee> fees = calculatedFees(waybill, contract, billingPlanId);
|
List<ReceivablePayableCargoFee> fees = calculatedFees(waybill, contract, billingPlanId);
|
||||||
cargoFeeMapper.delete(Wrappers.<ReceivablePayableCargoFee>lambdaQuery().eq(ReceivablePayableCargoFee::getDetailId, detail.getId()));
|
cargoFeeMapper.delete(Wrappers.<ReceivablePayableCargoFee>lambdaQuery().eq(ReceivablePayableCargoFee::getDetailId, detail.getId()));
|
||||||
fees.forEach(fee -> { fee.setDetailId(detail.getId()); cargoFeeMapper.insert(fee); });
|
fees.forEach(fee -> { fee.setDetailId(detail.getId()); cargoFeeMapper.insert(fee); });
|
||||||
BigDecimal freight = fees.stream().filter(this::isFreight).map(ReceivablePayableCargoFee::getAfterAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
BigDecimal freight = fees.stream().map(fee -> money(fee.getFreightAmount()))
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
BigDecimal total = fees.stream().map(ReceivablePayableCargoFee::getAfterAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
BigDecimal total = fees.stream().map(ReceivablePayableCargoFee::getAfterAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
detail.setFreightAmount(freight);
|
detail.setFreightAmount(freight);
|
||||||
detail.setOtherFeeAmount(total.subtract(freight));
|
detail.setOtherFeeAmount(total.subtract(freight));
|
||||||
@@ -1517,8 +1657,8 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
fee.setWaybillId(null);
|
fee.setWaybillId(null);
|
||||||
cargoFeeMapper.insert(fee);
|
cargoFeeMapper.insert(fee);
|
||||||
});
|
});
|
||||||
BigDecimal freight = fees.stream().filter(this::isFreight)
|
BigDecimal freight = fees.stream().map(fee -> money(fee.getFreightAmount()))
|
||||||
.map(ReceivablePayableCargoFee::getAfterAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
BigDecimal total = fees.stream().map(ReceivablePayableCargoFee::getAfterAmount)
|
BigDecimal total = fees.stream().map(ReceivablePayableCargoFee::getAfterAmount)
|
||||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
detail.setFreightAmount(freight);
|
detail.setFreightAmount(freight);
|
||||||
|
|||||||
+1
@@ -235,6 +235,7 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
|||||||
target.setCarrierType(source.getCarrierType());
|
target.setCarrierType(source.getCarrierType());
|
||||||
target.setCarrierId(source.getCarrierId());
|
target.setCarrierId(source.getCarrierId());
|
||||||
target.setCarrierName(source.getCarrierName());
|
target.setCarrierName(source.getCarrierName());
|
||||||
|
target.setCarrierContractId(source.getCarrierContractId());
|
||||||
target.setDriverId(source.getDriverId());
|
target.setDriverId(source.getDriverId());
|
||||||
target.setDriverName(source.getDriverName());
|
target.setDriverName(source.getDriverName());
|
||||||
target.setDriverPhone(source.getDriverPhone());
|
target.setDriverPhone(source.getDriverPhone());
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ CREATE TABLE IF NOT EXISTS `blade_loading_manage` (
|
|||||||
`escort_phone` varchar(50) DEFAULT NULL COMMENT '押运人手机号',
|
`escort_phone` varchar(50) DEFAULT NULL COMMENT '押运人手机号',
|
||||||
`carrier_type` varchar(50) DEFAULT NULL COMMENT '承运类型',
|
`carrier_type` varchar(50) DEFAULT NULL COMMENT '承运类型',
|
||||||
`carrier_name` varchar(100) DEFAULT NULL COMMENT '承运商',
|
`carrier_name` varchar(100) DEFAULT NULL COMMENT '承运商',
|
||||||
|
`carrier_contract_id` bigint(20) DEFAULT NULL COMMENT '承运商合同ID',
|
||||||
`departure_address` varchar(100) DEFAULT NULL COMMENT '发货地',
|
`departure_address` varchar(100) DEFAULT NULL COMMENT '发货地',
|
||||||
`transit_address` varchar(200) DEFAULT NULL COMMENT '途经地',
|
`transit_address` varchar(200) DEFAULT NULL COMMENT '途经地',
|
||||||
`arrival_address` varchar(100) DEFAULT NULL COMMENT '到货地',
|
`arrival_address` varchar(100) DEFAULT NULL COMMENT '到货地',
|
||||||
@@ -47,6 +48,7 @@ CREATE TABLE IF NOT EXISTS `blade_loading_manage` (
|
|||||||
`business_status` varchar(100) DEFAULT NULL COMMENT '业务状态',
|
`business_status` varchar(100) DEFAULT NULL COMMENT '业务状态',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
UNIQUE KEY `uk_loading_manage_no` (`loading_no`) USING BTREE,
|
UNIQUE KEY `uk_loading_manage_no` (`loading_no`) USING BTREE,
|
||||||
|
KEY `idx_loading_manage_carrier_contract_id` (`carrier_contract_id`) USING BTREE,
|
||||||
KEY `idx_loading_manage_dept` (`dept_id`) USING BTREE,
|
KEY `idx_loading_manage_dept` (`dept_id`) USING BTREE,
|
||||||
KEY `idx_loading_manage_create_time` (`create_time`) USING BTREE
|
KEY `idx_loading_manage_create_time` (`create_time`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配载管理';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配载管理';
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE `blade_loading_manage`
|
||||||
|
ADD COLUMN `carrier_contract_id` bigint(20) DEFAULT NULL COMMENT '承运商合同ID' AFTER `carrier_name`,
|
||||||
|
ADD KEY `idx_loading_manage_carrier_contract_id` (`carrier_contract_id`) USING BTREE;
|
||||||
@@ -244,6 +244,7 @@ CREATE TABLE `blade_waybill` (
|
|||||||
`carrier_type` varchar(50) DEFAULT NULL COMMENT '承运类型',
|
`carrier_type` varchar(50) DEFAULT NULL COMMENT '承运类型',
|
||||||
`carrier_id` bigint(20) DEFAULT NULL COMMENT '承运商ID',
|
`carrier_id` bigint(20) DEFAULT NULL COMMENT '承运商ID',
|
||||||
`carrier_name` varchar(100) DEFAULT NULL COMMENT '承运商名称',
|
`carrier_name` varchar(100) DEFAULT NULL COMMENT '承运商名称',
|
||||||
|
`carrier_contract_id` bigint(20) DEFAULT NULL COMMENT '承运商合同ID',
|
||||||
`driver_id` bigint(20) DEFAULT NULL COMMENT '司机ID',
|
`driver_id` bigint(20) DEFAULT NULL COMMENT '司机ID',
|
||||||
`driver_name` varchar(100) DEFAULT NULL COMMENT '司机姓名',
|
`driver_name` varchar(100) DEFAULT NULL COMMENT '司机姓名',
|
||||||
`driver_phone` varchar(50) DEFAULT NULL COMMENT '司机手机号',
|
`driver_phone` varchar(50) DEFAULT NULL COMMENT '司机手机号',
|
||||||
@@ -285,6 +286,7 @@ CREATE TABLE `blade_waybill` (
|
|||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
KEY `idx_waybill_dept` (`dept_id`) USING BTREE,
|
KEY `idx_waybill_dept` (`dept_id`) USING BTREE,
|
||||||
KEY `idx_waybill_plan_id` (`plan_id`) USING BTREE,
|
KEY `idx_waybill_plan_id` (`plan_id`) USING BTREE,
|
||||||
|
KEY `idx_waybill_carrier_contract_id` (`carrier_contract_id`) USING BTREE,
|
||||||
KEY `idx_waybill_create_time` (`create_time`) USING BTREE
|
KEY `idx_waybill_create_time` (`create_time`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='运单管理';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='运单管理';
|
||||||
|
|
||||||
@@ -319,6 +321,7 @@ CREATE TABLE `blade_loading_manage` (
|
|||||||
`escort_phone` varchar(50) DEFAULT NULL COMMENT '押运人手机号',
|
`escort_phone` varchar(50) DEFAULT NULL COMMENT '押运人手机号',
|
||||||
`carrier_type` varchar(50) DEFAULT NULL COMMENT '承运类型',
|
`carrier_type` varchar(50) DEFAULT NULL COMMENT '承运类型',
|
||||||
`carrier_name` varchar(100) DEFAULT NULL COMMENT '承运商',
|
`carrier_name` varchar(100) DEFAULT NULL COMMENT '承运商',
|
||||||
|
`carrier_contract_id` bigint(20) DEFAULT NULL COMMENT '承运商合同ID',
|
||||||
`departure_address` varchar(100) DEFAULT NULL COMMENT '发货地',
|
`departure_address` varchar(100) DEFAULT NULL COMMENT '发货地',
|
||||||
`transit_address` varchar(200) DEFAULT NULL COMMENT '途经地',
|
`transit_address` varchar(200) DEFAULT NULL COMMENT '途经地',
|
||||||
`arrival_address` varchar(100) DEFAULT NULL COMMENT '到货地',
|
`arrival_address` varchar(100) DEFAULT NULL COMMENT '到货地',
|
||||||
@@ -341,6 +344,7 @@ CREATE TABLE `blade_loading_manage` (
|
|||||||
`business_status` varchar(100) DEFAULT NULL COMMENT '业务状态',
|
`business_status` varchar(100) DEFAULT NULL COMMENT '业务状态',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
UNIQUE KEY `uk_loading_manage_no` (`loading_no`) USING BTREE,
|
UNIQUE KEY `uk_loading_manage_no` (`loading_no`) USING BTREE,
|
||||||
|
KEY `idx_loading_manage_carrier_contract_id` (`carrier_contract_id`) USING BTREE,
|
||||||
KEY `idx_loading_manage_dept` (`dept_id`) USING BTREE,
|
KEY `idx_loading_manage_dept` (`dept_id`) USING BTREE,
|
||||||
KEY `idx_loading_manage_create_time` (`create_time`) USING BTREE
|
KEY `idx_loading_manage_create_time` (`create_time`) USING BTREE
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配载管理';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配载管理';
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE `blade_waybill`
|
||||||
|
ADD COLUMN `carrier_contract_id` bigint(20) DEFAULT NULL COMMENT '承运商合同ID' AFTER `carrier_name`,
|
||||||
|
ADD KEY `idx_waybill_carrier_contract_id` (`carrier_contract_id`) USING BTREE;
|
||||||
Reference in New Issue
Block a user