1、修复菜单无法编辑

2、完善运输计划
3、完善运单管理
4、新增配置管理
This commit is contained in:
2026-08-04 20:53:57 +08:00
parent 30c51ba271
commit 62a110b6de
23 changed files with 2081 additions and 22 deletions

View File

@@ -37,9 +37,33 @@ public class FileCertificateBatchRecognitionDTO implements Serializable {
* 目录名称 * 目录名称
*/ */
private String dirName; private String dirName;
/**
* 磅单 obs key列表
*/
private List<String> poundUrls;
/**
* 车头 obs key列表
*/
private List<String> carFrontUrls;
/**
* 驾驶证 obs key列表
*/
private List<String> driverLicenseUrls;
/**
* 行驶证 obs key列表
*/
private List<String> vehicleLicenseUrls;
public FileCertificateBatchRecognitionDTO(List<String> objectKeys) { public FileCertificateBatchRecognitionDTO(List<String> objectKeys) {
this.objectKeys = objectKeys; this.objectKeys = objectKeys;
} }
public FileCertificateBatchRecognitionDTO(
List<String> objectKeys, String projectAbbreviation, String code, String dirName) {
this.objectKeys = objectKeys;
this.projectAbbreviation = projectAbbreviation;
this.code = code;
this.dirName = dirName;
}
} }

View File

@@ -0,0 +1,143 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.pojo.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.tenant.mp.TenantEntity;
import java.io.Serial;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* 配载管理实体类
*
* @author Chill
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("blade_loading_manage")
@Schema(description = "配载管理")
public class LoadingManage extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "配载单号")
private String loadingNo;
@Schema(description = "配载子单号")
private String loadingSubNos;
@Schema(description = "运单ID集合")
private String waybillIdsJson;
@Schema(description = "项目ID")
private Long projectId;
@Schema(description = "项目名称")
private String projectName;
@Schema(description = "客户名称")
private String customerName;
@Schema(description = "运输类型")
private String transportType;
@Schema(description = "货物类型")
private String cargoType;
@Schema(description = "货物名称")
private String cargoName;
@Schema(description = "车/船/航班/班列")
private String vehicleNo;
@Schema(description = "挂车车牌号")
private String trailerVehicleNo;
@Schema(description = "司机")
private String driverName;
@Schema(description = "联系电话")
private String driverPhone;
@Schema(description = "押运人")
private String escortName;
@Schema(description = "押运人手机号")
private String escortPhone;
@Schema(description = "承运类型")
private String carrierType;
@Schema(description = "承运商")
private String carrierName;
@Schema(description = "发货地址")
private String departureAddress;
@Schema(description = "途经地")
private String transitAddress;
@Schema(description = "到货地")
private String arrivalAddress;
@Schema(description = "原始单号")
private String originalNo;
@Schema(description = "数据来源")
private String dataSource;
@Schema(description = "开始日期")
private LocalDate startDate;
@Schema(description = "结束日期")
private LocalDate endDate;
@Schema(description = "计划名称")
private String planName;
@Schema(description = "运单批次号")
private String batchNo;
@Schema(description = "当前过程节点")
private String currentProcessNode;
@Schema(description = "里程")
private BigDecimal mileage;
@Schema(description = "预计发货日期")
private LocalDate estimatedStartDate;
@Schema(description = "预计完成日期")
private LocalDate estimatedEndDate;
@Schema(description = "任务备注")
private String taskRemark;
@Schema(description = "货物信息")
private String goodsJson;
@Schema(description = "路线信息")
private String routeJson;
@Schema(description = "任务信息")
private String taskInfoJson;
@Schema(description = "所属组织ID")
private Long deptId;
@Schema(description = "所属组织")
private String deptName;
@Schema(description = "业务状态")
private String businessStatus;
}

View File

@@ -29,7 +29,9 @@ import lombok.EqualsAndHashCode;
import org.springblade.core.tenant.mp.TenantEntity; import org.springblade.core.tenant.mp.TenantEntity;
import java.io.Serial; import java.io.Serial;
import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime;
/** /**
* 运单管理实体类 * 运单管理实体类
@@ -72,21 +74,102 @@ public class Waybill extends TenantEntity {
@Schema(description = "货物类型") @Schema(description = "货物类型")
private String cargoType; private String cargoType;
@Schema(description = "规格")
private String specification;
@Schema(description = "型号")
private String model;
@Schema(description = "数量")
private BigDecimal quantity;
@Schema(description = "数量单位")
private String quantityUnit;
@Schema(description = "发货地址ID")
private Long departureAddressId;
@Schema(description = "发货地")
private String departureName;
@Schema(description = "发货地址") @Schema(description = "发货地址")
private String departureAddress; private String departureAddress;
@Schema(description = "发货联系人")
private String departureContact;
@Schema(description = "发货联系方式")
private String departurePhone;
@Schema(description = "收货地址ID")
private Long arrivalAddressId;
@Schema(description = "收货地")
private String arrivalName;
@Schema(description = "收货地址") @Schema(description = "收货地址")
private String arrivalAddress; private String arrivalAddress;
@Schema(description = "收货联系人")
private String arrivalContact;
@Schema(description = "收货联系方式")
private String arrivalPhone;
@Schema(description = "任务录入模式")
private String taskEntryMode;
@Schema(description = "承运类型")
private String carrierType;
@Schema(description = "承运商ID")
private Long carrierId;
@Schema(description = "承运商名称") @Schema(description = "承运商名称")
private String carrierName; private String carrierName;
@Schema(description = "司机ID")
private Long driverId;
@Schema(description = "司机姓名") @Schema(description = "司机姓名")
private String driverName; private String driverName;
@Schema(description = "司机手机号")
private String driverPhone;
@Schema(description = "车/船/航班/班列号") @Schema(description = "车/船/航班/班列号")
private String vehicleNo; private String vehicleNo;
@Schema(description = "挂车车牌号")
private String trailerVehicleNo;
@Schema(description = "押运人")
private String escortName;
@Schema(description = "押运人手机号")
private String escortPhone;
@Schema(description = "里程")
private BigDecimal mileage;
@Schema(description = "预计发货时间")
private LocalDateTime estimatedStartTime;
@Schema(description = "预计完成时间")
private LocalDateTime estimatedEndTime;
@Schema(description = "单价")
private BigDecimal unitPrice;
@Schema(description = "计价单位")
private String priceUnit;
@Schema(description = "其他费用合计")
private BigDecimal otherFeeTotal;
@Schema(description = "任务备注")
private String taskRemark;
@Schema(description = "原始单号") @Schema(description = "原始单号")
private String originalNo; private String originalNo;
@@ -129,6 +212,9 @@ public class Waybill extends TenantEntity {
@Schema(description = "承运信息") @Schema(description = "承运信息")
private String carrierJson; private String carrierJson;
@Schema(description = "任务信息")
private String taskInfoJson;
@Schema(description = "过程节点") @Schema(description = "过程节点")
private String processJson; private String processJson;

View File

@@ -0,0 +1,69 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.pojo.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.transport.pojo.entity.LoadingManage;
import java.io.Serial;
import java.time.LocalDate;
/**
* 配载管理视图实体类
*
* @author Chill
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "配载管理")
public class LoadingManageVO extends LoadingManage {
@Serial
private static final long serialVersionUID = 1L;
@TableField(exist = false)
@Schema(description = "是否查看全部组织")
private Integer allDept;
@TableField(exist = false)
@Schema(description = "是否只读")
private Boolean readonly;
@TableField(exist = false)
@Schema(description = "创建人姓名")
private String createUserName;
@TableField(exist = false)
@Schema(description = "更新人姓名")
private String updateUserName;
@TableField(exist = false)
@Schema(description = "业务状态名称")
private String businessStatusName;
@TableField(exist = false)
@Schema(description = "运单号")
private String waybillNo;
@TableField(exist = false)
@Schema(description = "开始日期起")
private LocalDate startDateStart;
@TableField(exist = false)
@Schema(description = "开始日期止")
private LocalDate startDateEnd;
@TableField(exist = false)
@Schema(description = "结束日期起")
private LocalDate endDateStart;
@TableField(exist = false)
@Schema(description = "结束日期止")
private LocalDate endDateEnd;
}

View File

@@ -62,5 +62,8 @@ public class WaybillVO extends Waybill {
@Schema(description = "业务状态名称") @Schema(description = "业务状态名称")
private String businessStatusName; private String businessStatusName;
@TableField(exist = false)
@Schema(description = "是否仅查询未配载运单")
private Integer onlyUnassignedLoading;
} }

View File

@@ -29,7 +29,9 @@ import org.springframework.context.ApplicationEvent;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
/** /**
@@ -145,8 +147,94 @@ public class FileController extends BladeController {
@ApiLog("OCR识别-识别车辆运输凭证(不知道类型)") @ApiLog("OCR识别-识别车辆运输凭证(不知道类型)")
@Operation(summary = "识别车辆运输凭证,不知道类型", description = "参数:objectKeylist") @Operation(summary = "识别车辆运输凭证,不知道类型", description = "参数:objectKeylist")
@PostMapping("/recognitionTransportCertificates") @PostMapping("/recognitionTransportCertificates")
public R<TransportCertificateVO> recognitionTransportCertificates(@RequestBody List<String> objectKeys, @RequestParam(value = "projectAbbreviation", required = false) String projectAbbreviation, @RequestParam(value = "code", required = false) String code) { public R<TransportCertificateVO> recognitionTransportCertificates(
return R.data(ocrConvertService.recognitionTransportCertificate(new FileCertificateBatchRecognitionDTO(objectKeys, projectAbbreviation, code, null))); @RequestBody List<Object> attachments,
@RequestParam(value = "projectAbbreviation", required = false) String projectAbbreviation,
@RequestParam(value = "code", required = false) String code) {
return R.data(ocrConvertService.recognitionTransportCertificate(
buildCertificateBatchRecognitionDTO(attachments, projectAbbreviation, code)
));
}
private FileCertificateBatchRecognitionDTO buildCertificateBatchRecognitionDTO(
List<Object> attachments, String projectAbbreviation, String code) {
List<String> objectKeys = new ArrayList<>();
List<String> poundUrls = new ArrayList<>();
List<String> carFrontUrls = new ArrayList<>();
List<String> driverLicenseUrls = new ArrayList<>();
List<String> vehicleLicenseUrls = new ArrayList<>();
for (Object attachment : Optional.ofNullable(attachments).orElse(List.of())) {
if (attachment instanceof String objectKey) {
if (StringUtil.isNotBlank(objectKey)) {
objectKeys.add(objectKey);
}
continue;
}
if (attachment instanceof Map<?, ?> attachmentMap) {
String objectKey = getAttachmentObjectKey(attachmentMap);
if (StringUtil.isBlank(objectKey)) {
continue;
}
objectKeys.add(objectKey);
addTypedObjectKeys(attachmentMap, poundUrls, carFrontUrls, driverLicenseUrls, vehicleLicenseUrls);
}
}
FileCertificateBatchRecognitionDTO dto = new FileCertificateBatchRecognitionDTO(
objectKeys, projectAbbreviation, code, null
);
dto.setPoundUrls(poundUrls);
dto.setCarFrontUrls(carFrontUrls);
dto.setDriverLicenseUrls(driverLicenseUrls);
dto.setVehicleLicenseUrls(vehicleLicenseUrls);
return dto;
}
private String getAttachmentObjectKey(Map<?, ?> map) {
String objectKey = getMapString(map, "objectKey");
if (StringUtil.isNotBlank(objectKey)) {
return objectKey;
}
String url = getMapString(map, "url");
if (StringUtil.isNotBlank(url)) {
return url;
}
String poundUrl = getMapString(map, "poundUrl");
if (StringUtil.isNotBlank(poundUrl)) {
return poundUrl;
}
String carFrontUrl = getMapString(map, "carFrontUrl");
if (StringUtil.isNotBlank(carFrontUrl)) {
return carFrontUrl;
}
String driverLicenseUrl = getMapString(map, "driverLicenseUrl");
if (StringUtil.isNotBlank(driverLicenseUrl)) {
return driverLicenseUrl;
}
return getMapString(map, "vehicleLicenseUrl");
}
private void addTypedObjectKeys(
Map<?, ?> map,
List<String> poundUrls,
List<String> carFrontUrls,
List<String> driverLicenseUrls,
List<String> vehicleLicenseUrls) {
addMapString(map, "poundUrl", poundUrls);
addMapString(map, "carFrontUrl", carFrontUrls);
addMapString(map, "driverLicenseUrl", driverLicenseUrls);
addMapString(map, "vehicleLicenseUrl", vehicleLicenseUrls);
}
private void addMapString(Map<?, ?> map, String key, List<String> values) {
String value = getMapString(map, key);
if (StringUtil.isNotBlank(value)) {
values.add(value);
}
}
private String getMapString(Map<?, ?> map, String key) {
Object value = map.get(key);
return value == null ? "" : String.valueOf(value);
} }
@ApiLog("OCR识别-识别车辆运输凭证(知道类型)") @ApiLog("OCR识别-识别车辆运输凭证(知道类型)")

View File

@@ -37,12 +37,36 @@ public class OCRConvertServiceImpl implements IOCRConvertService {
throw new ServiceException("图像obs key不能为空"); throw new ServiceException("图像obs key不能为空");
} }
CertificateBatchRecognitionDTO ocrParam = converter.dto2ocr(param); CertificateBatchRecognitionDTO ocrParam = converter.dto2ocr(param);
// 转换文件链接 ocrParam.setPoundUrls(resolveFileUrls(param.getPoundUrls()));
List<String> fileUrls = param.getObjectKeys().stream() ocrParam.setCarFrontUrls(resolveFileUrls(param.getCarFrontUrls()));
ocrParam.setDriverLicenseUrls(resolveFileUrls(param.getDriverLicenseUrls()));
ocrParam.setVehicleLicenseUrls(resolveFileUrls(param.getVehicleLicenseUrls()));
if (!hasTypedObjectKeys(param)) {
// 旧格式字符串数组仍按通用 urls 传递。
List<String> fileUrls = param.getObjectKeys().stream()
.map(this::resolveFileUrl)
.toList();
ocrParam.setUrls(fileUrls);
} else {
ocrParam.setUrls(null);
}
return ocrService.recognitionTransportCertificate(ocrParam);
}
private boolean hasTypedObjectKeys(FileCertificateBatchRecognitionDTO param) {
return CollectionUtil.isNotEmpty(param.getPoundUrls())
|| CollectionUtil.isNotEmpty(param.getCarFrontUrls())
|| CollectionUtil.isNotEmpty(param.getDriverLicenseUrls())
|| CollectionUtil.isNotEmpty(param.getVehicleLicenseUrls());
}
private List<String> resolveFileUrls(List<String> objectKeys) {
if (CollectionUtil.isEmpty(objectKeys)) {
return null;
}
return objectKeys.stream()
.map(this::resolveFileUrl) .map(this::resolveFileUrl)
.toList(); .toList();
ocrParam.setUrls(fileUrls);
return ocrService.recognitionTransportCertificate(ocrParam);
} }
private String resolveFileUrl(String objectKey) { private String resolveFileUrl(String objectKey) {

View File

@@ -293,14 +293,19 @@ public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IM
@Override @Override
public boolean submit(Menu menu) { public boolean submit(Menu menu) {
boolean isNewMenu = menu.getId() == null; boolean isNewMenu = menu.getId() == null;
Menu oldMenu = isNewMenu ? null : getById(menu.getId());
// 验证code和name唯一性 // 验证code和name唯一性
LambdaQueryWrapper<Menu> menuQueryWrapper = Wrappers.<Menu>lambdaQuery() boolean codeChanged = isNewMenu || oldMenu == null || !Objects.equals(oldMenu.getCode(), menu.getCode());
.and(!isNewMenu, w -> w.ne(Menu::getId, menu.getId())) boolean nameChanged = isNewMenu || oldMenu == null || !Objects.equals(oldMenu.getName(), menu.getName()) || !Objects.equals(oldMenu.getCategory(), menu.getCategory());
.and(w -> w.eq(Menu::getCode, menu.getCode()) boolean duplicateCode = codeChanged && Func.isNotBlank(menu.getCode()) && baseMapper.selectCount(Wrappers.<Menu>lambdaQuery()
.or(o -> o.eq(Menu::getName, menu.getName()).eq(Menu::getCategory, MENU_CATEGORY))); .ne(!isNewMenu, Menu::getId, menu.getId())
.eq(Menu::getCode, menu.getCode())) > 0L;
if (baseMapper.selectCount(menuQueryWrapper) > 0L) { boolean duplicateName = nameChanged && Objects.equals(menu.getCategory(), MENU_CATEGORY) && Func.isNotBlank(menu.getName()) && baseMapper.selectCount(Wrappers.<Menu>lambdaQuery()
.ne(!isNewMenu, Menu::getId, menu.getId())
.eq(Menu::getName, menu.getName())
.eq(Menu::getCategory, MENU_CATEGORY)) > 0L;
if (duplicateCode || duplicateName) {
throw new ServiceException("菜单名或编号已存在!"); throw new ServiceException("菜单名或编号已存在!");
} }

View File

@@ -0,0 +1,128 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
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.LoadingManageVO;
import org.springblade.transport.service.ILoadingManageService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
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;
/**
* 配载管理 控制器
*
* @author Chill
*/
@RestController
@AllArgsConstructor
@PreAuth(menu = "loading_manage")
@RequestMapping("/loading-manage")
@Tag(name = "配载管理", description = "配载管理")
public class LoadingManageController extends BladeController {
private final ILoadingManageService loadingManageService;
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入id")
public R<LoadingManageVO> detail(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.data(loadingManageService.detail(id));
}
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入loadingManage")
public R<IPage<LoadingManageVO>> list(LoadingManageVO loadingManage, Query query) {
return R.data(loadingManageService.selectLoadingManagePage(Condition.getPage(query), loadingManage));
}
@PostMapping("/save-draft")
@ApiOperationSupport(order = 3)
@Operation(summary = "保存草稿", description = "传入loadingManage")
public R<LoadingManageVO> saveDraft(@RequestBody LoadingManage loadingManage) {
loadingManageService.saveDraft(loadingManage);
return R.data(loadingManageService.detail(loadingManage.getId()));
}
@PostMapping("/submit")
@ApiOperationSupport(order = 4)
@Operation(summary = "新增或修改", description = "传入loadingManage")
public R submit(@RequestBody LoadingManage loadingManage) {
return R.status(loadingManageService.submit(loadingManage));
}
@PostMapping("/remove")
@ApiOperationSupport(order = 5)
@Operation(summary = "逻辑删除", description = "传入ids")
public R<BusinessRemoveResultVO> remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.data(loadingManageService.removeLoadingManage(ids));
}
@GetMapping("/export-loading-manage")
@ApiOperationSupport(order = 6)
@Operation(summary = "导出配载管理")
public void exportLoadingManage(LoadingManageVO loadingManage, @RequestParam(required = false) String ids, HttpServletResponse response) {
List<LoadingManageExcel> list = loadingManageService.exportLoadingManage(loadingManage, ids);
ExcelUtil.export(response, "配载管理" + DateUtil.time(), "配载管理", list, LoadingManageExcel.class);
}
@PostMapping("/copy")
@ApiOperationSupport(order = 7)
@Operation(summary = "复制", description = "传入id")
public R<LoadingManageVO> copy(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.data(loadingManageService.copy(id));
}
@PostMapping("/reassign")
@ApiOperationSupport(order = 8)
@Operation(summary = "重新派单", description = "传入loadingManage")
public R reassign(@RequestBody LoadingManage loadingManage) {
return R.status(loadingManageService.reassign(loadingManage));
}
@PostMapping("/cancel")
@ApiOperationSupport(order = 9)
@Operation(summary = "取消", description = "传入id")
public R cancel(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(loadingManageService.cancel(id));
}
@PostMapping("/complete")
@ApiOperationSupport(order = 10)
@Operation(summary = "完成", description = "传入id")
public R complete(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(loadingManageService.complete(id));
}
@PostMapping("/batch-complete")
@ApiOperationSupport(order = 11)
@Operation(summary = "批量完成", description = "传入ids")
public R<BusinessRemoveResultVO> batchComplete(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.data(loadingManageService.batchComplete(ids));
}
}

View File

@@ -29,6 +29,7 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springblade.common.excel.ImportFailureExcelUtil;
import org.springblade.core.boot.ctrl.BladeController; import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.excel.util.ExcelUtil; import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.mp.support.Condition; import org.springblade.core.mp.support.Condition;
@@ -48,6 +49,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; 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 org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -102,36 +104,55 @@ public class WaybillController extends BladeController {
ExcelUtil.export(response, "运单管理" + DateUtil.time(), "运单管理", list, WaybillExcel.class); ExcelUtil.export(response, "运单管理" + DateUtil.time(), "运单管理", list, WaybillExcel.class);
} }
@PostMapping("/copy") @PostMapping("/import-waybill-manage")
@ApiOperationSupport(order = 6) @ApiOperationSupport(order = 6)
@Operation(summary = "导入运单管理", description = "传入excel")
public R importWaybill(MultipartFile file, HttpServletResponse response) {
List<WaybillExcel> failureList = waybillService.importWaybill(ExcelUtil.read(file, WaybillExcel.class));
if (Func.isNotEmpty(failureList)) {
ImportFailureExcelUtil.export(response, "运单管理导入失败明细" + DateUtil.time(), "导入失败明细", failureList, WaybillExcel.class);
return null;
}
return R.success("导入数据成功");
}
@GetMapping("/export-template")
@ApiOperationSupport(order = 7)
@Operation(summary = "导出模板")
public void exportTemplate(HttpServletResponse response) {
ExcelUtil.export(response, "运单管理模板", "运单管理导入模板", new ArrayList<WaybillExcel>(), WaybillExcel.class);
}
@PostMapping("/copy")
@ApiOperationSupport(order = 8)
@Operation(summary = "复制", description = "传入id") @Operation(summary = "复制", description = "传入id")
public R<WaybillVO> copy(@Parameter(description = "主键", required = true) @RequestParam Long id) { public R<WaybillVO> copy(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.data(waybillService.copy(id)); return R.data(waybillService.copy(id));
} }
@PostMapping("/cancel") @PostMapping("/cancel")
@ApiOperationSupport(order = 7) @ApiOperationSupport(order = 9)
@Operation(summary = "取消", description = "传入id") @Operation(summary = "取消", description = "传入id")
public R cancel(@Parameter(description = "主键", required = true) @RequestParam Long id) { public R cancel(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(waybillService.cancel(id)); return R.status(waybillService.cancel(id));
} }
@PostMapping("/reassign") @PostMapping("/reassign")
@ApiOperationSupport(order = 8) @ApiOperationSupport(order = 10)
@Operation(summary = "重新派单", description = "传入id") @Operation(summary = "重新派单", description = "传入id")
public R reassign(@Parameter(description = "主键", required = true) @RequestParam Long id) { public R reassign(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(waybillService.reassign(id)); return R.status(waybillService.reassign(id));
} }
@PostMapping("/complete") @PostMapping("/complete")
@ApiOperationSupport(order = 9) @ApiOperationSupport(order = 11)
@Operation(summary = "完成", description = "传入id") @Operation(summary = "完成", description = "传入id")
public R complete(@Parameter(description = "主键", required = true) @RequestParam Long id) { public R complete(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(waybillService.complete(id)); return R.status(waybillService.complete(id));
} }
@PostMapping("/batch-complete") @PostMapping("/batch-complete")
@ApiOperationSupport(order = 10) @ApiOperationSupport(order = 12)
@Operation(summary = "批量完成", description = "传入ids") @Operation(summary = "批量完成", description = "传入ids")
public R<BusinessRemoveResultVO> batchComplete(@Parameter(description = "主键集合", required = true) @RequestParam String ids) { public R<BusinessRemoveResultVO> batchComplete(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.data(waybillService.batchComplete(ids)); return R.data(waybillService.batchComplete(ids));

View File

@@ -0,0 +1,101 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* 配载管理 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(22)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class LoadingManageExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("配载单号")
private String loadingNo;
@ExcelProperty("配载子单号")
private String loadingSubNos;
@ExcelProperty("项目名称")
private String projectName;
@ExcelProperty("客户名称")
private String customerName;
@ExcelProperty("运输类型")
private String transportType;
@ExcelProperty("货物类型")
private String cargoType;
@ExcelProperty("货物名称")
private String cargoName;
@ExcelProperty("车/船/航班/班列")
private String vehicleNo;
@ExcelProperty("司机")
private String driverName;
@ExcelProperty("联系电话")
private String driverPhone;
@ExcelProperty("承运类型")
private String carrierType;
@ExcelProperty("承运商")
private String carrierName;
@ExcelProperty("发货地址")
private String departureAddress;
@ExcelProperty("途经地")
private String transitAddress;
@ExcelProperty("到货地")
private String arrivalAddress;
@ExcelProperty("原始单号")
private String originalNo;
@ExcelProperty("数据来源")
private String dataSource;
@ExcelProperty("开始日期")
private LocalDate startDate;
@ExcelProperty("结束日期")
private LocalDate endDate;
@ExcelProperty("计划名称")
private String planName;
@ExcelProperty("运单批次号")
private String batchNo;
@ExcelProperty("当前过程节点")
private String currentProcessNode;
@ExcelProperty("里程")
private String mileage;
@ExcelProperty("预计发货日期")
private LocalDate estimatedStartDate;
@ExcelProperty("预计完成日期")
private LocalDate estimatedEndDate;
@ExcelProperty("任务备注")
private String taskRemark;
@ExcelProperty("业务状态")
private String businessStatus;
@ExcelProperty("所属组织")
private String deptName;
@ExcelProperty("创建人")
private String createUserName;
@ExcelProperty("更新人")
private String updateUserName;
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@ExcelProperty("更新时间")
private LocalDateTime updateTime;
@ExcelIgnore
private String errorMessage;
}

View File

@@ -23,6 +23,7 @@
package org.springblade.transport.excel; package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.write.style.ColumnWidth; import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight; import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight; import cn.idev.excel.annotation.write.style.HeadRowHeight;
@@ -30,6 +31,7 @@ import lombok.Data;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -61,16 +63,62 @@ public class WaybillExcel implements Serializable {
private String cargoName; private String cargoName;
@ExcelProperty("货物类型") @ExcelProperty("货物类型")
private String cargoType; private String cargoType;
@ExcelProperty("规格")
private String specification;
@ExcelProperty("型号")
private String model;
@ExcelProperty("数量")
private BigDecimal quantity;
@ExcelProperty("数量单位")
private String quantityUnit;
@ExcelProperty("发货地")
private String departureName;
@ExcelProperty("发货地址") @ExcelProperty("发货地址")
private String departureAddress; private String departureAddress;
@ExcelProperty("发货联系人")
private String departureContact;
@ExcelProperty("发货联系方式")
private String departurePhone;
@ExcelProperty("收货地")
private String arrivalName;
@ExcelProperty("收货地址") @ExcelProperty("收货地址")
private String arrivalAddress; private String arrivalAddress;
@ExcelProperty("收货联系人")
private String arrivalContact;
@ExcelProperty("收货联系方式")
private String arrivalPhone;
@ExcelProperty("任务录入模式")
private String taskEntryMode;
@ExcelProperty("承运类型")
private String carrierType;
@ExcelProperty("承运商名称") @ExcelProperty("承运商名称")
private String carrierName; private String carrierName;
@ExcelProperty("司机姓名") @ExcelProperty("司机姓名")
private String driverName; private String driverName;
@ExcelProperty("司机手机号")
private String driverPhone;
@ExcelProperty("车/船/航班/班列号") @ExcelProperty("车/船/航班/班列号")
private String vehicleNo; private String vehicleNo;
@ExcelProperty("挂车车牌号")
private String trailerVehicleNo;
@ExcelProperty("押运人")
private String escortName;
@ExcelProperty("押运人手机号")
private String escortPhone;
@ExcelProperty("里程(km)")
private BigDecimal mileage;
@ExcelProperty("预计发货时间")
private LocalDateTime estimatedStartTime;
@ExcelProperty("预计完成时间")
private LocalDateTime estimatedEndTime;
@ExcelProperty("单价")
private BigDecimal unitPrice;
@ExcelProperty("计价单位")
private String priceUnit;
@ExcelProperty("其他费用合计")
private BigDecimal otherFeeTotal;
@ExcelProperty("任务备注")
private String taskRemark;
@ExcelProperty("原始单号") @ExcelProperty("原始单号")
private String originalNo; private String originalNo;
@ExcelProperty("业务状态") @ExcelProperty("业务状态")
@@ -106,4 +154,7 @@ public class WaybillExcel implements Serializable {
@ExcelProperty("更新时间") @ExcelProperty("更新时间")
private LocalDateTime updateTime; private LocalDateTime updateTime;
@ExcelIgnore
private String errorMessage;
} }

View File

@@ -0,0 +1,17 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.transport.pojo.entity.LoadingManage;
/**
* 配载管理 Mapper 接口
*
* @author Chill
*/
public interface LoadingManageMapper extends BaseMapper<LoadingManage> {
}

View File

@@ -0,0 +1,45 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
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.LoadingManageVO;
import java.util.List;
/**
* 配载管理 服务类
*
* @author Chill
*/
public interface ILoadingManageService extends BaseService<LoadingManage> {
IPage<LoadingManageVO> selectLoadingManagePage(IPage<LoadingManage> page, LoadingManageVO loadingManage);
LoadingManageVO detail(Long id);
boolean saveDraft(LoadingManage loadingManage);
boolean submit(LoadingManage loadingManage);
BusinessRemoveResultVO removeLoadingManage(String ids);
List<LoadingManageExcel> exportLoadingManage(LoadingManageVO loadingManage, String ids);
LoadingManageVO copy(Long id);
boolean reassign(LoadingManage loadingManage);
boolean cancel(Long id);
boolean complete(Long id);
BusinessRemoveResultVO batchComplete(String ids);
}

View File

@@ -43,6 +43,7 @@ public interface IWaybillService extends BaseService<Waybill> {
boolean submit(Waybill waybill); boolean submit(Waybill waybill);
BusinessRemoveResultVO removeWaybill(String ids); BusinessRemoveResultVO removeWaybill(String ids);
List<WaybillExcel> exportWaybill(WaybillVO waybill, String ids); List<WaybillExcel> exportWaybill(WaybillVO waybill, String ids);
List<WaybillExcel> importWaybill(List<WaybillExcel> data);
WaybillVO copy(Long id); WaybillVO copy(Long id);
boolean cancel(Long id); boolean cancel(Long id);
boolean reassign(Long id); boolean reassign(Long id);

View File

@@ -0,0 +1,600 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.jackson.JsonUtil;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.cache.UserCache;
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.LoadingManage;
import org.springblade.transport.pojo.entity.Waybill;
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
import org.springblade.transport.pojo.vo.LoadingManageVO;
import org.springblade.transport.service.ILoadingManageService;
import org.springblade.transport.support.TransportBusinessSupport;
import org.springblade.transport.wrapper.LoadingManageWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* 配载管理 服务实现类
*
* @author Chill
*/
@Service
public class LoadingManageServiceImpl extends BaseServiceImpl<LoadingManageMapper, LoadingManage> implements ILoadingManageService {
private static final String STATUS_DRAFT = "draft";
private static final String STATUS_PENDING = "pending";
private static final String STATUS_RUNNING = "running";
private static final String STATUS_COMPLETED = "completed";
private static final String STATUS_CANCELLED = "cancelled";
private static final String CARRIER_SELF = "自运";
private static final String CARRIER_COMPANY = "承运商";
private static final String CARRIER_PLATFORM = "网签平台";
@Resource
private WaybillMapper waybillMapper;
@Override
public IPage<LoadingManageVO> selectLoadingManagePage(IPage<LoadingManage> page, LoadingManageVO loadingManage) {
IPage<LoadingManage> entityPage = page(page, buildQuery(loadingManage));
IPage<LoadingManageVO> voPage = LoadingManageWrapper.build().pageVO(entityPage);
voPage.getRecords().forEach(this::fillReadonly);
return voPage;
}
@Override
public LoadingManageVO detail(Long id) {
LoadingManageVO loadingManageVO = LoadingManageWrapper.build().entityVO(loadExists(id));
fillReadonly(loadingManageVO);
return loadingManageVO;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean saveDraft(LoadingManage loadingManage) {
prepare(loadingManage);
validate(loadingManage, true);
if (Func.isNotEmpty(loadingManage.getId())) {
LoadingManage oldRecord = loadEditable(loadingManage.getId(), true);
loadingManage.setLoadingNo(oldRecord.getLoadingNo());
loadingManage.setDeptId(oldRecord.getDeptId());
loadingManage.setDeptName(oldRecord.getDeptName());
}
prepareCreateOrUpdate(loadingManage);
loadingManage.setBusinessStatus(STATUS_DRAFT);
if (Func.isEmpty(loadingManage.getLoadingNo())) {
loadingManage.setLoadingNo(nextCode());
}
return saveOrUpdate(loadingManage);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean submit(LoadingManage loadingManage) {
prepare(loadingManage);
validate(loadingManage, false);
List<Long> oldWaybillIds = new ArrayList<>();
if (Func.isNotEmpty(loadingManage.getId())) {
LoadingManage oldRecord = loadEditable(loadingManage.getId(), true);
oldWaybillIds = waybillIds(oldRecord.getWaybillIdsJson());
loadingManage.setLoadingNo(oldRecord.getLoadingNo());
loadingManage.setDeptId(oldRecord.getDeptId());
loadingManage.setDeptName(oldRecord.getDeptName());
}
prepareCreateOrUpdate(loadingManage);
loadingManage.setBusinessStatus(STATUS_PENDING);
if (Func.isEmpty(loadingManage.getLoadingNo())) {
loadingManage.setLoadingNo(nextCode());
}
validateWaybillsAvailable(loadingManage, waybillIds(loadingManage.getWaybillIdsJson()));
boolean result = saveOrUpdate(loadingManage);
syncAssociatedWaybills(loadingManage, STATUS_PENDING, oldWaybillIds);
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public BusinessRemoveResultVO removeLoadingManage(String ids) {
List<Long> idList = Func.toLongList(ids);
if (Func.isEmpty(idList)) {
throw new ServiceException("请选择需要删除的数据");
}
BusinessRemoveResultVO result = new BusinessRemoveResultVO();
List<Long> deleteIdList = new ArrayList<>();
for (LoadingManage loadingManage : listByIds(idList)) {
TransportBusinessSupport.assertCurrentDept(loadingManage.getDeptId(), "配载管理");
if (!Objects.equals(loadingManage.getBusinessStatus(), STATUS_DRAFT)) {
result.setSkippedCount(result.getSkippedCount() + 1);
result.getSkippedCodes().add(loadingManage.getLoadingNo());
continue;
}
deleteIdList.add(loadingManage.getId());
}
if (Func.isNotEmpty(deleteIdList)) {
deleteLogic(deleteIdList);
}
result.setSuccessCount(deleteIdList.size());
return result;
}
@Override
public List<LoadingManageExcel> exportLoadingManage(LoadingManageVO loadingManage, String ids) {
LambdaQueryWrapper<LoadingManage> queryWrapper = buildQuery(loadingManage);
if (Func.isNotEmpty(ids)) {
queryWrapper.in(LoadingManage::getId, Func.toLongList(ids));
}
return list(queryWrapper).stream().map(record -> {
LoadingManageExcel excel = new LoadingManageExcel();
BeanUtil.copyProperties(record, excel);
excel.setCreateUserName(UserCache.getUserRealName(record.getCreateUser()));
excel.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser()));
excel.setMileage(formatMileage(record.getMileage()));
return excel;
}).toList();
}
@Override
@Transactional(rollbackFor = Exception.class)
public LoadingManageVO copy(Long id) {
LoadingManage source = loadEditable(id, true);
LoadingManage target = new LoadingManage();
target.setLoadingSubNos(source.getLoadingSubNos());
target.setWaybillIdsJson(source.getWaybillIdsJson());
target.setProjectId(source.getProjectId());
target.setProjectName(source.getProjectName());
target.setCustomerName(source.getCustomerName());
target.setTransportType(source.getTransportType());
target.setCargoType(source.getCargoType());
target.setCargoName(source.getCargoName());
target.setVehicleNo(source.getVehicleNo());
target.setTrailerVehicleNo(source.getTrailerVehicleNo());
target.setDriverName(source.getDriverName());
target.setDriverPhone(source.getDriverPhone());
target.setEscortName(source.getEscortName());
target.setEscortPhone(source.getEscortPhone());
target.setCarrierType(source.getCarrierType());
target.setCarrierName(source.getCarrierName());
target.setDepartureAddress(source.getDepartureAddress());
target.setTransitAddress(source.getTransitAddress());
target.setArrivalAddress(source.getArrivalAddress());
target.setOriginalNo(source.getOriginalNo());
target.setDataSource(source.getDataSource());
target.setStartDate(source.getStartDate());
target.setEndDate(source.getEndDate());
target.setPlanName(source.getPlanName());
target.setBatchNo(source.getBatchNo());
target.setCurrentProcessNode(source.getCurrentProcessNode());
target.setMileage(source.getMileage());
target.setEstimatedStartDate(source.getEstimatedStartDate());
target.setEstimatedEndDate(source.getEstimatedEndDate());
target.setTaskRemark(source.getTaskRemark());
target.setGoodsJson(source.getGoodsJson());
target.setRouteJson(source.getRouteJson());
target.setTaskInfoJson(source.getTaskInfoJson());
target.setDeptId(source.getDeptId());
target.setDeptName(source.getDeptName());
target.setBusinessStatus(STATUS_DRAFT);
target.setLoadingNo(nextCode());
prepare(target);
validate(target, true);
save(target);
return detail(target.getId());
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean reassign(LoadingManage loadingManage) {
LoadingManage oldRecord = loadEditable(loadingManage.getId(), true);
if (!Objects.equals(oldRecord.getBusinessStatus(), STATUS_PENDING)) {
throw new ServiceException("仅待执行状态允许重新派单");
}
prepare(loadingManage);
validate(loadingManage, false);
List<Long> oldWaybillIds = waybillIds(oldRecord.getWaybillIdsJson());
loadingManage.setLoadingNo(oldRecord.getLoadingNo());
loadingManage.setDeptId(oldRecord.getDeptId());
loadingManage.setDeptName(oldRecord.getDeptName());
loadingManage.setBusinessStatus(STATUS_PENDING);
validateWaybillsAvailable(loadingManage, waybillIds(loadingManage.getWaybillIdsJson()));
boolean result = updateById(loadingManage);
syncAssociatedWaybills(loadingManage, STATUS_PENDING, oldWaybillIds);
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean cancel(Long id) {
LoadingManage loadingManage = loadEditable(id, true);
if (!Objects.equals(loadingManage.getBusinessStatus(), STATUS_PENDING)) {
throw new ServiceException("仅待执行状态允许取消");
}
loadingManage.setBusinessStatus(STATUS_CANCELLED);
boolean result = updateById(loadingManage);
releaseAssociatedWaybills(waybillIds(loadingManage.getWaybillIdsJson()), STATUS_PENDING);
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean complete(Long id) {
LoadingManage loadingManage = loadEditable(id, true);
if (!Objects.equals(loadingManage.getBusinessStatus(), STATUS_RUNNING)) {
throw new ServiceException("仅进行中状态允许完成");
}
loadingManage.setBusinessStatus(STATUS_COMPLETED);
boolean result = updateById(loadingManage);
syncAssociatedWaybills(loadingManage, STATUS_COMPLETED, new ArrayList<>());
return result;
}
@Override
@Transactional(rollbackFor = Exception.class)
public BusinessRemoveResultVO batchComplete(String ids) {
List<Long> idList = Func.toLongList(ids);
if (Func.isEmpty(idList)) {
throw new ServiceException("请选择需要完成的数据");
}
BusinessRemoveResultVO result = new BusinessRemoveResultVO();
for (LoadingManage loadingManage : listByIds(idList)) {
try {
complete(loadingManage.getId());
result.setSuccessCount(result.getSuccessCount() + 1);
} catch (Exception exception) {
result.setSkippedCount(result.getSkippedCount() + 1);
result.getSkippedCodes().add(loadingManage.getLoadingNo());
}
}
return result;
}
private LambdaQueryWrapper<LoadingManage> buildQuery(LoadingManageVO loadingManage) {
TransportBusinessSupport.validateAllDept(loadingManage.getAllDept(), "配载管理");
LambdaQueryWrapper<LoadingManage> queryWrapper = Wrappers.<LoadingManage>lambdaQuery().eq(LoadingManage::getIsDeleted, 0);
if (!Objects.equals(loadingManage.getAllDept(), 1)) {
queryWrapper.eq(LoadingManage::getDeptId, TransportBusinessSupport.currentDeptId("配载管理"));
} else if (Func.isNotEmpty(loadingManage.getDeptId())) {
queryWrapper.eq(LoadingManage::getDeptId, loadingManage.getDeptId());
}
if (Func.isNotEmpty(loadingManage.getLoadingNo())) {
queryWrapper.eq(LoadingManage::getLoadingNo, loadingManage.getLoadingNo());
}
if (Func.isNotEmpty(loadingManage.getWaybillNo())) {
queryWrapper.like(LoadingManage::getLoadingSubNos, loadingManage.getWaybillNo());
}
if (Func.isNotEmpty(loadingManage.getProjectName())) {
queryWrapper.like(LoadingManage::getProjectName, loadingManage.getProjectName());
}
if (Func.isNotEmpty(loadingManage.getCustomerName())) {
queryWrapper.like(LoadingManage::getCustomerName, loadingManage.getCustomerName());
}
if (Func.isNotEmpty(loadingManage.getTransportType())) {
queryWrapper.eq(LoadingManage::getTransportType, loadingManage.getTransportType());
}
if (Func.isNotEmpty(loadingManage.getCargoType())) {
queryWrapper.like(LoadingManage::getCargoType, loadingManage.getCargoType());
}
if (Func.isNotEmpty(loadingManage.getDepartureAddress())) {
queryWrapper.like(LoadingManage::getDepartureAddress, loadingManage.getDepartureAddress());
}
if (Func.isNotEmpty(loadingManage.getArrivalAddress())) {
queryWrapper.like(LoadingManage::getArrivalAddress, loadingManage.getArrivalAddress());
}
if (Func.isNotEmpty(loadingManage.getCargoName())) {
queryWrapper.like(LoadingManage::getCargoName, loadingManage.getCargoName());
}
if (Func.isNotEmpty(loadingManage.getDriverName())) {
queryWrapper.like(LoadingManage::getDriverName, loadingManage.getDriverName());
}
if (Func.isNotEmpty(loadingManage.getVehicleNo())) {
queryWrapper.like(LoadingManage::getVehicleNo, loadingManage.getVehicleNo());
}
if (Func.isNotEmpty(loadingManage.getOriginalNo())) {
queryWrapper.like(LoadingManage::getOriginalNo, loadingManage.getOriginalNo());
}
if (Func.isNotEmpty(loadingManage.getCarrierName())) {
queryWrapper.like(LoadingManage::getCarrierName, loadingManage.getCarrierName());
}
if (Func.isNotEmpty(loadingManage.getDataSource())) {
queryWrapper.eq(LoadingManage::getDataSource, loadingManage.getDataSource());
}
if (Func.isNotEmpty(loadingManage.getStartDateStart())) {
queryWrapper.ge(LoadingManage::getStartDate, loadingManage.getStartDateStart());
}
if (Func.isNotEmpty(loadingManage.getStartDateEnd())) {
queryWrapper.le(LoadingManage::getStartDate, loadingManage.getStartDateEnd());
}
if (Func.isNotEmpty(loadingManage.getEndDateStart())) {
queryWrapper.ge(LoadingManage::getEndDate, loadingManage.getEndDateStart());
}
if (Func.isNotEmpty(loadingManage.getEndDateEnd())) {
queryWrapper.le(LoadingManage::getEndDate, loadingManage.getEndDateEnd());
}
if (Func.isNotEmpty(loadingManage.getBusinessStatus())) {
queryWrapper.eq(LoadingManage::getBusinessStatus, loadingManage.getBusinessStatus());
}
if (Func.isNotEmpty(loadingManage.getPlanName())) {
queryWrapper.like(LoadingManage::getPlanName, loadingManage.getPlanName());
}
if (Func.isNotEmpty(loadingManage.getBatchNo())) {
queryWrapper.like(LoadingManage::getBatchNo, loadingManage.getBatchNo());
}
if (Func.isNotEmpty(loadingManage.getCurrentProcessNode())) {
queryWrapper.like(LoadingManage::getCurrentProcessNode, loadingManage.getCurrentProcessNode());
}
queryWrapper.orderByDesc(LoadingManage::getCreateTime);
return queryWrapper;
}
private void prepare(LoadingManage loadingManage) {
loadingManage.setLoadingNo(TransportBusinessSupport.trimToNull(loadingManage.getLoadingNo()));
loadingManage.setLoadingSubNos(TransportBusinessSupport.trimToNull(loadingManage.getLoadingSubNos()));
loadingManage.setWaybillIdsJson(TransportBusinessSupport.trimToNull(loadingManage.getWaybillIdsJson()));
loadingManage.setProjectName(TransportBusinessSupport.trimToNull(loadingManage.getProjectName()));
loadingManage.setCustomerName(TransportBusinessSupport.trimToNull(loadingManage.getCustomerName()));
loadingManage.setTransportType(TransportBusinessSupport.trimToNull(loadingManage.getTransportType()));
loadingManage.setCargoType(TransportBusinessSupport.trimToNull(loadingManage.getCargoType()));
loadingManage.setCargoName(TransportBusinessSupport.trimToNull(loadingManage.getCargoName()));
loadingManage.setVehicleNo(TransportBusinessSupport.trimToNull(loadingManage.getVehicleNo()));
loadingManage.setTrailerVehicleNo(TransportBusinessSupport.trimToNull(loadingManage.getTrailerVehicleNo()));
loadingManage.setDriverName(TransportBusinessSupport.trimToNull(loadingManage.getDriverName()));
loadingManage.setDriverPhone(TransportBusinessSupport.trimToNull(loadingManage.getDriverPhone()));
loadingManage.setEscortName(TransportBusinessSupport.trimToNull(loadingManage.getEscortName()));
loadingManage.setEscortPhone(TransportBusinessSupport.trimToNull(loadingManage.getEscortPhone()));
loadingManage.setCarrierType(TransportBusinessSupport.trimToNull(loadingManage.getCarrierType()));
loadingManage.setCarrierName(TransportBusinessSupport.trimToNull(loadingManage.getCarrierName()));
loadingManage.setDepartureAddress(TransportBusinessSupport.trimToNull(loadingManage.getDepartureAddress()));
loadingManage.setTransitAddress(TransportBusinessSupport.trimToNull(loadingManage.getTransitAddress()));
loadingManage.setArrivalAddress(TransportBusinessSupport.trimToNull(loadingManage.getArrivalAddress()));
loadingManage.setOriginalNo(TransportBusinessSupport.trimToNull(loadingManage.getOriginalNo()));
loadingManage.setDataSource(TransportBusinessSupport.trimToNull(loadingManage.getDataSource()));
loadingManage.setPlanName(TransportBusinessSupport.trimToNull(loadingManage.getPlanName()));
loadingManage.setBatchNo(TransportBusinessSupport.trimToNull(loadingManage.getBatchNo()));
loadingManage.setCurrentProcessNode(TransportBusinessSupport.trimToNull(loadingManage.getCurrentProcessNode()));
loadingManage.setTaskRemark(TransportBusinessSupport.trimToNull(loadingManage.getTaskRemark()));
loadingManage.setGoodsJson(TransportBusinessSupport.trimToNull(loadingManage.getGoodsJson()));
loadingManage.setRouteJson(TransportBusinessSupport.trimToNull(loadingManage.getRouteJson()));
loadingManage.setTaskInfoJson(TransportBusinessSupport.trimToNull(loadingManage.getTaskInfoJson()));
loadingManage.setDeptName(TransportBusinessSupport.trimToNull(loadingManage.getDeptName()));
if (Func.isEmpty(loadingManage.getDeptId())) {
Dept dept = TransportBusinessSupport.currentDept("配载管理");
loadingManage.setDeptId(dept.getId());
loadingManage.setDeptName(dept.getDeptName());
}
if (Func.isEmpty(loadingManage.getBusinessStatus())) {
loadingManage.setBusinessStatus(STATUS_DRAFT);
}
}
private void validate(LoadingManage loadingManage, boolean draftMode) {
TransportBusinessSupport.validateRequired(loadingManage.getLoadingSubNos(), "配载子单号不能为空");
TransportBusinessSupport.validateRequired(loadingManage.getTransportType(), "运输类型不能为空");
if (draftMode) {
validateCommon(loadingManage);
return;
}
TransportBusinessSupport.validateRequired(loadingManage.getCarrierType(), "承运类型不能为空");
TransportBusinessSupport.validateRequired(loadingManage.getVehicleNo(), "车/船/航班/班列不能为空");
TransportBusinessSupport.validateRequired(loadingManage.getDepartureAddress(), "发货地不能为空");
TransportBusinessSupport.validateRequired(loadingManage.getArrivalAddress(), "到货地不能为空");
if (Objects.equals(loadingManage.getCarrierType(), CARRIER_SELF)) {
TransportBusinessSupport.validateRequired(loadingManage.getDriverName(), "司机不能为空");
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.getLoadingSubNos(), 200, "配载子单号不能超过200字");
TransportBusinessSupport.validateLength(loadingManage.getProjectName(), 100, "项目名称不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getCustomerName(), 100, "客户名称不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getTransportType(), 100, "运输类型不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getCargoType(), 100, "货物类型不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getCargoName(), 100, "货物名称不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getVehicleNo(), 100, "车/船/航班/班列不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getDriverName(), 100, "司机不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getDriverPhone(), 50, "联系电话不能超过50字");
TransportBusinessSupport.validateLength(loadingManage.getTrailerVehicleNo(), 100, "挂车车牌号不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getEscortName(), 100, "押运人不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getEscortPhone(), 50, "押运人手机号不能超过50字");
TransportBusinessSupport.validateLength(loadingManage.getCarrierType(), 50, "承运类型不能超过50字");
TransportBusinessSupport.validateLength(loadingManage.getCarrierName(), 100, "承运商不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getDepartureAddress(), 100, "发货地不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getTransitAddress(), 200, "途经地不能超过200字");
TransportBusinessSupport.validateLength(loadingManage.getArrivalAddress(), 100, "到货地不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getOriginalNo(), 100, "原始单号不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getDataSource(), 100, "数据来源不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getPlanName(), 100, "计划名称不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getBatchNo(), 100, "运单批次号不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getCurrentProcessNode(), 100, "过程节点不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getWaybillIdsJson(), 4000, "运单ID集合不能超过4000字");
TransportBusinessSupport.validateLength(loadingManage.getGoodsJson(), 8000, "货物信息不能超过8000字");
TransportBusinessSupport.validateLength(loadingManage.getRouteJson(), 8000, "路线信息不能超过8000字");
TransportBusinessSupport.validateLength(loadingManage.getTaskInfoJson(), 8000, "任务信息不能超过8000字");
TransportBusinessSupport.validateLength(loadingManage.getTaskRemark(), 500, "任务备注不能超过500字");
TransportBusinessSupport.validatePhone(loadingManage.getDriverPhone(), "联系电话格式不正确");
TransportBusinessSupport.validatePhone(loadingManage.getEscortPhone(), "押运人手机号格式不正确");
TransportBusinessSupport.validateNonNegative(loadingManage.getMileage(), "里程");
TransportBusinessSupport.validateDateRange(loadingManage.getStartDate(), loadingManage.getEndDate(), "开始日期不能晚于结束日期");
if (loadingManage.getEstimatedStartDate() != null && loadingManage.getEstimatedEndDate() != null
&& loadingManage.getEstimatedEndDate().isBefore(loadingManage.getEstimatedStartDate())) {
throw new ServiceException("预计完成日期不能早于预计发货日期");
}
}
private void validateCommon(LoadingManage loadingManage) {
TransportBusinessSupport.validateLength(loadingManage.getLoadingNo(), 100, "配载单号不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getLoadingSubNos(), 200, "配载子单号不能超过200字");
TransportBusinessSupport.validateLength(loadingManage.getProjectName(), 100, "项目名称不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getCustomerName(), 100, "客户名称不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getTransportType(), 100, "运输类型不能超过100字");
TransportBusinessSupport.validateLength(loadingManage.getWaybillIdsJson(), 4000, "运单ID集合不能超过4000字");
TransportBusinessSupport.validateLength(loadingManage.getGoodsJson(), 8000, "货物信息不能超过8000字");
TransportBusinessSupport.validateLength(loadingManage.getRouteJson(), 8000, "路线信息不能超过8000字");
TransportBusinessSupport.validateLength(loadingManage.getTaskInfoJson(), 8000, "任务信息不能超过8000字");
TransportBusinessSupport.validateLength(loadingManage.getTaskRemark(), 500, "任务备注不能超过500字");
}
private void validateWaybillsAvailable(LoadingManage loadingManage, List<Long> waybillIds) {
if (Func.isEmpty(waybillIds)) {
throw new ServiceException("请选择待配载运单");
}
List<Waybill> waybills = waybillMapper.selectList(Wrappers.<Waybill>lambdaQuery()
.eq(Waybill::getIsDeleted, 0)
.in(Waybill::getId, waybillIds));
if (waybills.size() != waybillIds.size()) {
throw new ServiceException("待配载运单不存在或已删除");
}
for (Waybill waybill : waybills) {
TransportBusinessSupport.assertCurrentDept(waybill.getDeptId(), "运单管理");
if (Func.isNotEmpty(waybill.getLoadingNo()) && !Objects.equals(waybill.getLoadingNo(), loadingManage.getLoadingNo())) {
throw new ServiceException("运单" + waybill.getWaybillNo() + "已关联其他配载单");
}
if ((Objects.equals(waybill.getBusinessStatus(), STATUS_COMPLETED) || Objects.equals(waybill.getBusinessStatus(), STATUS_CANCELLED))
&& !Objects.equals(waybill.getLoadingNo(), loadingManage.getLoadingNo())) {
throw new ServiceException("运单" + waybill.getWaybillNo() + "当前状态不允许配载");
}
}
}
private void syncAssociatedWaybills(LoadingManage loadingManage, String status, List<Long> oldWaybillIds) {
List<Long> newWaybillIds = waybillIds(loadingManage.getWaybillIdsJson());
if (Func.isNotEmpty(oldWaybillIds)) {
List<Long> removedIds = new ArrayList<>(oldWaybillIds);
removedIds.removeAll(newWaybillIds);
releaseAssociatedWaybills(removedIds, STATUS_PENDING);
}
if (Func.isEmpty(newWaybillIds)) {
return;
}
waybillMapper.update(null, Wrappers.<Waybill>lambdaUpdate()
.in(Waybill::getId, newWaybillIds)
.set(Waybill::getLoadingNo, loadingManage.getLoadingNo())
.set(Waybill::getBusinessStatus, status)
.set(Waybill::getCarrierType, loadingManage.getCarrierType())
.set(Waybill::getCarrierName, loadingManage.getCarrierName())
.set(Waybill::getDriverName, loadingManage.getDriverName())
.set(Waybill::getDriverPhone, loadingManage.getDriverPhone())
.set(Waybill::getVehicleNo, loadingManage.getVehicleNo())
.set(Waybill::getTrailerVehicleNo, loadingManage.getTrailerVehicleNo())
.set(Waybill::getEscortName, loadingManage.getEscortName())
.set(Waybill::getEscortPhone, loadingManage.getEscortPhone())
.set(Waybill::getMileage, loadingManage.getMileage())
.set(Waybill::getEstimatedStartTime, toDateTime(loadingManage.getEstimatedStartDate()))
.set(Waybill::getEstimatedEndTime, toDateTime(loadingManage.getEstimatedEndDate()))
.set(Waybill::getTaskRemark, loadingManage.getTaskRemark())
.set(Waybill::getTaskInfoJson, loadingManage.getTaskInfoJson())
.set(Waybill::getCurrentProcessNode, loadingManage.getCurrentProcessNode()));
}
private void releaseAssociatedWaybills(List<Long> waybillIds, String status) {
if (Func.isEmpty(waybillIds)) {
return;
}
waybillMapper.update(null, Wrappers.<Waybill>lambdaUpdate()
.in(Waybill::getId, waybillIds)
.set(Waybill::getLoadingNo, null)
.set(Waybill::getBusinessStatus, status));
}
private List<Long> waybillIds(String value) {
if (Func.isEmpty(value)) {
return new ArrayList<>();
}
try {
Object parsed = JsonUtil.parse(value, List.class);
if (parsed instanceof List<?> list) {
return list.stream()
.filter(Objects::nonNull)
.map(item -> Long.valueOf(String.valueOf(item)))
.toList();
}
} catch (Exception ignored) {
// 兼容历史逗号分隔存储。
}
return Func.toLongList(value);
}
private LocalDateTime toDateTime(LocalDate date) {
return date == null ? null : date.atStartOfDay();
}
private LoadingManage loadExists(Long id) {
if (Func.isEmpty(id)) {
throw new ServiceException("主键不能为空");
}
LoadingManage loadingManage = getById(id);
if (Func.isEmpty(loadingManage) || Objects.equals(loadingManage.getIsDeleted(), 1)) {
throw new ServiceException("配载管理不存在");
}
return loadingManage;
}
private LoadingManage loadEditable(Long id, boolean checkDept) {
LoadingManage loadingManage = loadExists(id);
if (checkDept) {
TransportBusinessSupport.assertCurrentDept(loadingManage.getDeptId(), "配载管理");
}
if (Objects.equals(loadingManage.getBusinessStatus(), STATUS_COMPLETED) || Objects.equals(loadingManage.getBusinessStatus(), STATUS_CANCELLED)) {
throw new ServiceException("当前状态不允许修改");
}
return loadingManage;
}
private void prepareCreateOrUpdate(LoadingManage loadingManage) {
if (Func.isEmpty(loadingManage.getId())) {
loadingManage.setLoadingNo(TransportBusinessSupport.trimToNull(loadingManage.getLoadingNo()));
}
}
private void fillReadonly(LoadingManageVO loadingManageVO) {
// 保持与现有业务模块一致,包装类已完成主字段映射,这里预留兼容入口。
}
private String formatMileage(BigDecimal mileage) {
if (mileage == null) {
return null;
}
BigDecimal value = mileage.setScale(2, RoundingMode.HALF_UP).stripTrailingZeros();
return value.toPlainString();
}
private synchronized String nextCode() {
String prefix = "PZ" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE) + "-";
List<LoadingManage> latestList = list(Wrappers.<LoadingManage>lambdaQuery()
.select(LoadingManage::getLoadingNo)
.likeRight(LoadingManage::getLoadingNo, prefix)
.orderByDesc(LoadingManage::getLoadingNo)
.last("LIMIT 1"));
int next = 1;
if (Func.isNotEmpty(latestList) && Func.isNotEmpty(latestList.get(0).getLoadingNo())) {
String serial = latestList.get(0).getLoadingNo().substring(prefix.length());
if (serial.chars().allMatch(Character::isDigit)) {
next = Integer.parseInt(serial) + 1;
}
}
return prefix + String.format("%03d", next);
}
}

View File

@@ -27,6 +27,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.core.log.exception.ServiceException; import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.jackson.JsonUtil;
import org.springblade.core.tool.utils.BeanUtil; import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func; import org.springblade.core.tool.utils.Func;
import org.springblade.system.cache.UserCache; import org.springblade.system.cache.UserCache;
@@ -45,7 +46,9 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
/** /**
@@ -125,6 +128,28 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
}).toList(); }).toList();
} }
@Override
@Transactional(rollbackFor = Exception.class)
public List<WaybillExcel> importWaybill(List<WaybillExcel> data) {
if (Func.isEmpty(data)) {
throw new ServiceException("导入数据不能为空");
}
List<WaybillExcel> errorList = new ArrayList<>();
for (int index = 0; index < data.size(); index++) {
WaybillExcel excel = data.get(index);
try {
Waybill waybill = Objects.requireNonNull(BeanUtil.copyProperties(excel, Waybill.class));
waybill.setDataSource("批量导入");
waybill.setCarrierJson(buildImportCarrierJson(waybill));
submit(waybill);
} catch (Exception exception) {
excel.setErrorMessage("" + (index + 2) + "行:" + exception.getMessage());
errorList.add(excel);
}
}
return errorList;
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public WaybillVO copy(Long id) { public WaybillVO copy(Long id) {
@@ -138,11 +163,38 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
target.setTransportType(source.getTransportType()); target.setTransportType(source.getTransportType());
target.setCargoName(source.getCargoName()); target.setCargoName(source.getCargoName());
target.setCargoType(source.getCargoType()); target.setCargoType(source.getCargoType());
target.setSpecification(source.getSpecification());
target.setModel(source.getModel());
target.setQuantity(source.getQuantity());
target.setQuantityUnit(source.getQuantityUnit());
target.setDepartureAddressId(source.getDepartureAddressId());
target.setDepartureName(source.getDepartureName());
target.setDepartureAddress(source.getDepartureAddress()); target.setDepartureAddress(source.getDepartureAddress());
target.setDepartureContact(source.getDepartureContact());
target.setDeparturePhone(source.getDeparturePhone());
target.setArrivalAddressId(source.getArrivalAddressId());
target.setArrivalName(source.getArrivalName());
target.setArrivalAddress(source.getArrivalAddress()); target.setArrivalAddress(source.getArrivalAddress());
target.setArrivalContact(source.getArrivalContact());
target.setArrivalPhone(source.getArrivalPhone());
target.setTaskEntryMode(source.getTaskEntryMode());
target.setCarrierType(source.getCarrierType());
target.setCarrierId(source.getCarrierId());
target.setCarrierName(source.getCarrierName()); target.setCarrierName(source.getCarrierName());
target.setDriverId(source.getDriverId());
target.setDriverName(source.getDriverName()); target.setDriverName(source.getDriverName());
target.setDriverPhone(source.getDriverPhone());
target.setVehicleNo(source.getVehicleNo()); target.setVehicleNo(source.getVehicleNo());
target.setTrailerVehicleNo(source.getTrailerVehicleNo());
target.setEscortName(source.getEscortName());
target.setEscortPhone(source.getEscortPhone());
target.setMileage(source.getMileage());
target.setEstimatedStartTime(source.getEstimatedStartTime());
target.setEstimatedEndTime(source.getEstimatedEndTime());
target.setUnitPrice(source.getUnitPrice());
target.setPriceUnit(source.getPriceUnit());
target.setOtherFeeTotal(source.getOtherFeeTotal());
target.setTaskRemark(source.getTaskRemark());
target.setOriginalNo(source.getOriginalNo()); target.setOriginalNo(source.getOriginalNo());
target.setBusinessStatus(source.getBusinessStatus()); target.setBusinessStatus(source.getBusinessStatus());
target.setDataSource(source.getDataSource()); target.setDataSource(source.getDataSource());
@@ -157,6 +209,7 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
target.setCurrentProcessNode(source.getCurrentProcessNode()); target.setCurrentProcessNode(source.getCurrentProcessNode());
target.setGoodsJson(source.getGoodsJson()); target.setGoodsJson(source.getGoodsJson());
target.setCarrierJson(source.getCarrierJson()); target.setCarrierJson(source.getCarrierJson());
target.setTaskInfoJson(source.getTaskInfoJson());
target.setProcessJson(source.getProcessJson()); target.setProcessJson(source.getProcessJson());
target.setFreightJson(source.getFreightJson()); target.setFreightJson(source.getFreightJson());
target.setAttachmentsJson(source.getAttachmentsJson()); target.setAttachmentsJson(source.getAttachmentsJson());
@@ -284,6 +337,9 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
if (Func.isNotEmpty(waybill.getLoadingNo())) { if (Func.isNotEmpty(waybill.getLoadingNo())) {
queryWrapper.like(Waybill::getLoadingNo, waybill.getLoadingNo()); queryWrapper.like(Waybill::getLoadingNo, waybill.getLoadingNo());
} }
if (Objects.equals(waybill.getOnlyUnassignedLoading(), 1)) {
queryWrapper.and(wrapper -> wrapper.isNull(Waybill::getLoadingNo).or().eq(Waybill::getLoadingNo, ""));
}
if (Func.isNotEmpty(waybill.getBatchNo())) { if (Func.isNotEmpty(waybill.getBatchNo())) {
queryWrapper.like(Waybill::getBatchNo, waybill.getBatchNo()); queryWrapper.like(Waybill::getBatchNo, waybill.getBatchNo());
} }
@@ -308,11 +364,28 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
waybill.setTransportType(TransportBusinessSupport.trimToNull(waybill.getTransportType())); waybill.setTransportType(TransportBusinessSupport.trimToNull(waybill.getTransportType()));
waybill.setCargoName(TransportBusinessSupport.trimToNull(waybill.getCargoName())); waybill.setCargoName(TransportBusinessSupport.trimToNull(waybill.getCargoName()));
waybill.setCargoType(TransportBusinessSupport.trimToNull(waybill.getCargoType())); waybill.setCargoType(TransportBusinessSupport.trimToNull(waybill.getCargoType()));
waybill.setSpecification(TransportBusinessSupport.trimToNull(waybill.getSpecification()));
waybill.setModel(TransportBusinessSupport.trimToNull(waybill.getModel()));
waybill.setQuantityUnit(TransportBusinessSupport.trimToNull(waybill.getQuantityUnit()));
waybill.setDepartureName(TransportBusinessSupport.trimToNull(waybill.getDepartureName()));
waybill.setDepartureAddress(TransportBusinessSupport.trimToNull(waybill.getDepartureAddress())); waybill.setDepartureAddress(TransportBusinessSupport.trimToNull(waybill.getDepartureAddress()));
waybill.setDepartureContact(TransportBusinessSupport.trimToNull(waybill.getDepartureContact()));
waybill.setDeparturePhone(TransportBusinessSupport.trimToNull(waybill.getDeparturePhone()));
waybill.setArrivalName(TransportBusinessSupport.trimToNull(waybill.getArrivalName()));
waybill.setArrivalAddress(TransportBusinessSupport.trimToNull(waybill.getArrivalAddress())); waybill.setArrivalAddress(TransportBusinessSupport.trimToNull(waybill.getArrivalAddress()));
waybill.setArrivalContact(TransportBusinessSupport.trimToNull(waybill.getArrivalContact()));
waybill.setArrivalPhone(TransportBusinessSupport.trimToNull(waybill.getArrivalPhone()));
waybill.setTaskEntryMode(TransportBusinessSupport.trimToNull(waybill.getTaskEntryMode()));
waybill.setCarrierType(TransportBusinessSupport.trimToNull(waybill.getCarrierType()));
waybill.setCarrierName(TransportBusinessSupport.trimToNull(waybill.getCarrierName())); waybill.setCarrierName(TransportBusinessSupport.trimToNull(waybill.getCarrierName()));
waybill.setDriverName(TransportBusinessSupport.trimToNull(waybill.getDriverName())); waybill.setDriverName(TransportBusinessSupport.trimToNull(waybill.getDriverName()));
waybill.setDriverPhone(TransportBusinessSupport.trimToNull(waybill.getDriverPhone()));
waybill.setVehicleNo(TransportBusinessSupport.trimToNull(waybill.getVehicleNo())); waybill.setVehicleNo(TransportBusinessSupport.trimToNull(waybill.getVehicleNo()));
waybill.setTrailerVehicleNo(TransportBusinessSupport.trimToNull(waybill.getTrailerVehicleNo()));
waybill.setEscortName(TransportBusinessSupport.trimToNull(waybill.getEscortName()));
waybill.setEscortPhone(TransportBusinessSupport.trimToNull(waybill.getEscortPhone()));
waybill.setPriceUnit(TransportBusinessSupport.trimToNull(waybill.getPriceUnit()));
waybill.setTaskRemark(TransportBusinessSupport.trimToNull(waybill.getTaskRemark()));
waybill.setOriginalNo(TransportBusinessSupport.trimToNull(waybill.getOriginalNo())); waybill.setOriginalNo(TransportBusinessSupport.trimToNull(waybill.getOriginalNo()));
waybill.setBusinessStatus(TransportBusinessSupport.trimToNull(waybill.getBusinessStatus())); waybill.setBusinessStatus(TransportBusinessSupport.trimToNull(waybill.getBusinessStatus()));
waybill.setDataSource(TransportBusinessSupport.trimToNull(waybill.getDataSource())); waybill.setDataSource(TransportBusinessSupport.trimToNull(waybill.getDataSource()));
@@ -324,11 +397,13 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
waybill.setCurrentProcessNode(TransportBusinessSupport.trimToNull(waybill.getCurrentProcessNode())); waybill.setCurrentProcessNode(TransportBusinessSupport.trimToNull(waybill.getCurrentProcessNode()));
waybill.setGoodsJson(TransportBusinessSupport.trimToNull(waybill.getGoodsJson())); waybill.setGoodsJson(TransportBusinessSupport.trimToNull(waybill.getGoodsJson()));
waybill.setCarrierJson(TransportBusinessSupport.trimToNull(waybill.getCarrierJson())); waybill.setCarrierJson(TransportBusinessSupport.trimToNull(waybill.getCarrierJson()));
waybill.setTaskInfoJson(TransportBusinessSupport.trimToNull(waybill.getTaskInfoJson()));
waybill.setProcessJson(TransportBusinessSupport.trimToNull(waybill.getProcessJson())); waybill.setProcessJson(TransportBusinessSupport.trimToNull(waybill.getProcessJson()));
waybill.setFreightJson(TransportBusinessSupport.trimToNull(waybill.getFreightJson())); waybill.setFreightJson(TransportBusinessSupport.trimToNull(waybill.getFreightJson()));
waybill.setAttachmentsJson(TransportBusinessSupport.trimToNull(waybill.getAttachmentsJson())); waybill.setAttachmentsJson(TransportBusinessSupport.trimToNull(waybill.getAttachmentsJson()));
waybill.setDeptName(TransportBusinessSupport.trimToNull(waybill.getDeptName())); waybill.setDeptName(TransportBusinessSupport.trimToNull(waybill.getDeptName()));
waybill.setRemark(TransportBusinessSupport.trimToNull(waybill.getRemark())); waybill.setRemark(TransportBusinessSupport.trimToNull(waybill.getRemark()));
fillJsonFromFlatFields(waybill);
if (Func.isEmpty(waybill.getDeptId())) { if (Func.isEmpty(waybill.getDeptId())) {
Dept dept = TransportBusinessSupport.currentDept("运单管理"); Dept dept = TransportBusinessSupport.currentDept("运单管理");
waybill.setDeptId(dept.getId()); waybill.setDeptId(dept.getId());
@@ -344,7 +419,25 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
TransportBusinessSupport.validateRequired(waybill.getTransportType(), "运输类型不能为空"); TransportBusinessSupport.validateRequired(waybill.getTransportType(), "运输类型不能为空");
TransportBusinessSupport.validateRequired(waybill.getCargoName(), "请输入货物名称"); TransportBusinessSupport.validateRequired(waybill.getCargoName(), "请输入货物名称");
TransportBusinessSupport.validateRequired(waybill.getCargoType(), "货物类型不能为空"); TransportBusinessSupport.validateRequired(waybill.getCargoType(), "货物类型不能为空");
TransportBusinessSupport.validateRequired(waybill.getQuantityUnit(), "数量单位不能为空");
TransportBusinessSupport.validateRequired(waybill.getCarrierType(), "承运类型不能为空");
TransportBusinessSupport.validateRequired(waybill.getVehicleNo(), "车牌号不能为空");
if ("承运商".equals(waybill.getCarrierType())) {
TransportBusinessSupport.validateRequired(waybill.getCarrierName(), "承运商不能为空");
} else {
TransportBusinessSupport.validateRequired(waybill.getDriverName(), "司机不能为空");
TransportBusinessSupport.validateRequired(waybill.getDriverPhone(), "司机手机号不能为空");
TransportBusinessSupport.validateRequired(waybill.getTrailerVehicleNo(), "挂车车牌号不能为空");
TransportBusinessSupport.validateRequired(waybill.getEscortName(), "押运人不能为空");
TransportBusinessSupport.validateRequired(waybill.getEscortPhone(), "押运人手机号不能为空");
if (Func.isEmpty(waybill.getMileage())) {
throw new ServiceException("里程不能为空");
}
}
TransportBusinessSupport.validateRequired(waybill.getCarrierJson(), "承运信息不能为空"); TransportBusinessSupport.validateRequired(waybill.getCarrierJson(), "承运信息不能为空");
if (Func.isEmpty(waybill.getQuantity())) {
throw new ServiceException("数量不能为空");
}
TransportBusinessSupport.validateLength(waybill.getWaybillNo(), 255, "运单号不能超过255字"); TransportBusinessSupport.validateLength(waybill.getWaybillNo(), 255, "运单号不能超过255字");
TransportBusinessSupport.validateLength(waybill.getProjectName(), 255, "项目不能超过255字"); TransportBusinessSupport.validateLength(waybill.getProjectName(), 255, "项目不能超过255字");
TransportBusinessSupport.validateLength(waybill.getContractName(), 255, "客户合同不能超过255字"); TransportBusinessSupport.validateLength(waybill.getContractName(), 255, "客户合同不能超过255字");
@@ -352,11 +445,28 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
TransportBusinessSupport.validateLength(waybill.getTransportType(), 255, "运输类型不能超过255字"); TransportBusinessSupport.validateLength(waybill.getTransportType(), 255, "运输类型不能超过255字");
TransportBusinessSupport.validateLength(waybill.getCargoName(), 255, "货物名称不能超过255字"); TransportBusinessSupport.validateLength(waybill.getCargoName(), 255, "货物名称不能超过255字");
TransportBusinessSupport.validateLength(waybill.getCargoType(), 255, "货物类型不能超过255字"); TransportBusinessSupport.validateLength(waybill.getCargoType(), 255, "货物类型不能超过255字");
TransportBusinessSupport.validateLength(waybill.getSpecification(), 255, "规格不能超过255字");
TransportBusinessSupport.validateLength(waybill.getModel(), 255, "型号不能超过255字");
TransportBusinessSupport.validateLength(waybill.getQuantityUnit(), 50, "数量单位不能超过50字");
TransportBusinessSupport.validateLength(waybill.getDepartureName(), 255, "发货地不能超过255字");
TransportBusinessSupport.validateLength(waybill.getDepartureAddress(), 255, "发货地址不能超过255字"); TransportBusinessSupport.validateLength(waybill.getDepartureAddress(), 255, "发货地址不能超过255字");
TransportBusinessSupport.validateLength(waybill.getDepartureContact(), 255, "发货联系人不能超过255字");
TransportBusinessSupport.validateLength(waybill.getDeparturePhone(), 50, "发货联系方式不能超过50字");
TransportBusinessSupport.validateLength(waybill.getArrivalName(), 255, "收货地不能超过255字");
TransportBusinessSupport.validateLength(waybill.getArrivalAddress(), 255, "收货地址不能超过255字"); TransportBusinessSupport.validateLength(waybill.getArrivalAddress(), 255, "收货地址不能超过255字");
TransportBusinessSupport.validateLength(waybill.getArrivalContact(), 255, "收货联系人不能超过255字");
TransportBusinessSupport.validateLength(waybill.getArrivalPhone(), 50, "收货联系方式不能超过50字");
TransportBusinessSupport.validateLength(waybill.getTaskEntryMode(), 50, "任务录入模式不能超过50字");
TransportBusinessSupport.validateLength(waybill.getCarrierType(), 50, "承运类型不能超过50字");
TransportBusinessSupport.validateLength(waybill.getCarrierName(), 255, "承运商名称不能超过255字"); TransportBusinessSupport.validateLength(waybill.getCarrierName(), 255, "承运商名称不能超过255字");
TransportBusinessSupport.validateLength(waybill.getDriverName(), 255, "司机姓名不能超过255字"); TransportBusinessSupport.validateLength(waybill.getDriverName(), 255, "司机姓名不能超过255字");
TransportBusinessSupport.validateLength(waybill.getDriverPhone(), 50, "司机手机号不能超过50字");
TransportBusinessSupport.validateLength(waybill.getVehicleNo(), 255, "车/船/航班/班列号不能超过255字"); TransportBusinessSupport.validateLength(waybill.getVehicleNo(), 255, "车/船/航班/班列号不能超过255字");
TransportBusinessSupport.validateLength(waybill.getTrailerVehicleNo(), 255, "挂车车牌号不能超过255字");
TransportBusinessSupport.validateLength(waybill.getEscortName(), 255, "押运人不能超过255字");
TransportBusinessSupport.validateLength(waybill.getEscortPhone(), 50, "押运人手机号不能超过50字");
TransportBusinessSupport.validateLength(waybill.getPriceUnit(), 50, "计价单位不能超过50字");
TransportBusinessSupport.validateLength(waybill.getTaskRemark(), 200, "任务备注不能超过200字");
TransportBusinessSupport.validateLength(waybill.getOriginalNo(), 255, "原始单号不能超过255字"); TransportBusinessSupport.validateLength(waybill.getOriginalNo(), 255, "原始单号不能超过255字");
TransportBusinessSupport.validateLength(waybill.getBusinessStatus(), 255, "业务状态不能超过255字"); TransportBusinessSupport.validateLength(waybill.getBusinessStatus(), 255, "业务状态不能超过255字");
TransportBusinessSupport.validateLength(waybill.getDataSource(), 255, "数据来源不能超过255字"); TransportBusinessSupport.validateLength(waybill.getDataSource(), 255, "数据来源不能超过255字");
@@ -368,12 +478,26 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
TransportBusinessSupport.validateLength(waybill.getCurrentProcessNode(), 255, "当前过程节点不能超过255字"); TransportBusinessSupport.validateLength(waybill.getCurrentProcessNode(), 255, "当前过程节点不能超过255字");
TransportBusinessSupport.validateLength(waybill.getGoodsJson(), 8000, "货物信息不能超过8000字"); TransportBusinessSupport.validateLength(waybill.getGoodsJson(), 8000, "货物信息不能超过8000字");
TransportBusinessSupport.validateLength(waybill.getCarrierJson(), 8000, "承运信息不能超过8000字"); TransportBusinessSupport.validateLength(waybill.getCarrierJson(), 8000, "承运信息不能超过8000字");
TransportBusinessSupport.validateLength(waybill.getTaskInfoJson(), 8000, "任务信息不能超过8000字");
TransportBusinessSupport.validateLength(waybill.getProcessJson(), 8000, "过程节点不能超过8000字"); TransportBusinessSupport.validateLength(waybill.getProcessJson(), 8000, "过程节点不能超过8000字");
TransportBusinessSupport.validateLength(waybill.getFreightJson(), 8000, "费用信息不能超过8000字"); TransportBusinessSupport.validateLength(waybill.getFreightJson(), 8000, "费用信息不能超过8000字");
TransportBusinessSupport.validateLength(waybill.getAttachmentsJson(), 8000, "附件不能超过8000字"); TransportBusinessSupport.validateLength(waybill.getAttachmentsJson(), 8000, "附件不能超过8000字");
TransportBusinessSupport.validateLength(waybill.getDeptName(), 255, "所属组织不能超过255字"); TransportBusinessSupport.validateLength(waybill.getDeptName(), 255, "所属组织不能超过255字");
TransportBusinessSupport.validateLength(waybill.getRemark(), 500, "备注不能超过500字"); TransportBusinessSupport.validateLength(waybill.getRemark(), 200, "备注不能超过200字");
TransportBusinessSupport.validatePhone(waybill.getDeparturePhone(), "发货联系方式格式不正确");
TransportBusinessSupport.validatePhone(waybill.getArrivalPhone(), "收货联系方式格式不正确");
TransportBusinessSupport.validatePhone(waybill.getDriverPhone(), "司机手机号格式不正确");
TransportBusinessSupport.validatePhone(waybill.getEscortPhone(), "押运人手机号格式不正确");
TransportBusinessSupport.validateNonNegative(waybill.getQuantity(), "数量");
TransportBusinessSupport.validateNonNegative(waybill.getMileage(), "里程");
TransportBusinessSupport.validateNonNegative(waybill.getUnitPrice(), "单价");
TransportBusinessSupport.validateNonNegative(waybill.getOtherFeeTotal(), "其他费用合计");
TransportBusinessSupport.validateDateRange(waybill.getStartDate(), waybill.getEndDate(), "开始日期不能晚于结束日期"); TransportBusinessSupport.validateDateRange(waybill.getStartDate(), waybill.getEndDate(), "开始日期不能晚于结束日期");
if (waybill.getEstimatedStartTime() != null
&& waybill.getEstimatedEndTime() != null
&& waybill.getEstimatedEndTime().isBefore(waybill.getEstimatedStartTime())) {
throw new ServiceException("预计完成时间不能早于预计发货时间");
}
} }
private Waybill loadEditable(Long id, boolean checkDept) { private Waybill loadEditable(Long id, boolean checkDept) {
@@ -394,6 +518,154 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
return false; return false;
} }
private void fillJsonFromFlatFields(Waybill waybill) {
if (Func.isEmpty(waybill.getTaskEntryMode())) {
waybill.setTaskEntryMode("simple");
}
if (Func.isEmpty(waybill.getCarrierJson())) {
waybill.setCarrierJson(buildImportCarrierJson(waybill));
}
if (Func.isEmpty(waybill.getTaskInfoJson())) {
waybill.setTaskInfoJson(buildTaskInfoJson(waybill));
}
if (Func.isEmpty(waybill.getGoodsJson())) {
waybill.setGoodsJson(buildGoodsJson(waybill));
}
if (Func.isEmpty(waybill.getFreightJson())) {
waybill.setFreightJson(buildFreightJson(waybill));
}
}
private String buildImportCarrierJson(Waybill waybill) {
if (!hasAnyValue(
waybill.getCarrierType(),
waybill.getCarrierId(),
waybill.getCarrierName(),
waybill.getDriverId(),
waybill.getDriverName(),
waybill.getDriverPhone(),
waybill.getVehicleNo(),
waybill.getTrailerVehicleNo(),
waybill.getEscortName(),
waybill.getEscortPhone(),
waybill.getMileage()
)) {
return null;
}
Map<String, Object> carrier = new LinkedHashMap<>();
putIfNotEmpty(carrier, "carrierType", waybill.getCarrierType());
putIfNotEmpty(carrier, "carrierId", waybill.getCarrierId());
putIfNotEmpty(carrier, "carrier", waybill.getCarrierName());
putIfNotEmpty(carrier, "carrierName", waybill.getCarrierName());
putIfNotEmpty(carrier, "driverId", waybill.getDriverId());
putIfNotEmpty(carrier, "driverName", waybill.getDriverName());
putIfNotEmpty(carrier, "driverPhone", waybill.getDriverPhone());
putIfNotEmpty(carrier, "vehicleNo", waybill.getVehicleNo());
putIfNotEmpty(carrier, "trailerVehicleNo", waybill.getTrailerVehicleNo());
putIfNotEmpty(carrier, "escortName", waybill.getEscortName());
putIfNotEmpty(carrier, "escortPhone", waybill.getEscortPhone());
putIfNotEmpty(carrier, "mileage", waybill.getMileage());
putIfNotEmpty(carrier, "taskEntryMode", waybill.getTaskEntryMode());
return JsonUtil.toJson(List.of(carrier));
}
private String buildTaskInfoJson(Waybill waybill) {
if (!hasAnyValue(
waybill.getTaskEntryMode(),
waybill.getCarrierType(),
waybill.getCarrierId(),
waybill.getCarrierName(),
waybill.getDriverId(),
waybill.getDriverName(),
waybill.getDriverPhone(),
waybill.getVehicleNo(),
waybill.getTrailerVehicleNo(),
waybill.getEscortName(),
waybill.getEscortPhone(),
waybill.getMileage(),
waybill.getEstimatedStartTime(),
waybill.getEstimatedEndTime(),
waybill.getUnitPrice(),
waybill.getPriceUnit(),
waybill.getOtherFeeTotal(),
waybill.getTaskRemark()
)) {
return null;
}
Map<String, Object> taskInfo = new LinkedHashMap<>();
putIfNotEmpty(taskInfo, "taskEntryMode", waybill.getTaskEntryMode());
putIfNotEmpty(taskInfo, "carrierType", waybill.getCarrierType());
putIfNotEmpty(taskInfo, "carrierId", waybill.getCarrierId());
putIfNotEmpty(taskInfo, "carrierName", waybill.getCarrierName());
putIfNotEmpty(taskInfo, "driverId", waybill.getDriverId());
putIfNotEmpty(taskInfo, "driverName", waybill.getDriverName());
putIfNotEmpty(taskInfo, "driverPhone", waybill.getDriverPhone());
putIfNotEmpty(taskInfo, "vehicleNo", waybill.getVehicleNo());
putIfNotEmpty(taskInfo, "trailerVehicleNo", waybill.getTrailerVehicleNo());
putIfNotEmpty(taskInfo, "escortName", waybill.getEscortName());
putIfNotEmpty(taskInfo, "escortPhone", waybill.getEscortPhone());
putIfNotEmpty(taskInfo, "mileage", waybill.getMileage());
putIfNotEmpty(taskInfo, "estimatedStartTime", waybill.getEstimatedStartTime());
putIfNotEmpty(taskInfo, "estimatedEndTime", waybill.getEstimatedEndTime());
putIfNotEmpty(taskInfo, "unitPrice", waybill.getUnitPrice());
putIfNotEmpty(taskInfo, "priceUnit", waybill.getPriceUnit());
putIfNotEmpty(taskInfo, "otherFeeTotal", waybill.getOtherFeeTotal());
putIfNotEmpty(taskInfo, "taskRemark", waybill.getTaskRemark());
return JsonUtil.toJson(taskInfo);
}
private String buildGoodsJson(Waybill waybill) {
if (!hasAnyValue(
waybill.getCargoName(),
waybill.getCargoType(),
waybill.getSpecification(),
waybill.getModel(),
waybill.getQuantity(),
waybill.getQuantityUnit()
)) {
return null;
}
Map<String, Object> goods = new LinkedHashMap<>();
putIfNotEmpty(goods, "cargoName", waybill.getCargoName());
putIfNotEmpty(goods, "cargoType", waybill.getCargoType());
putIfNotEmpty(goods, "specification", waybill.getSpecification());
putIfNotEmpty(goods, "model", waybill.getModel());
putIfNotEmpty(goods, "quantity", waybill.getQuantity());
putIfNotEmpty(goods, "quantityUnit", waybill.getQuantityUnit());
putIfNotEmpty(goods, "mileage", waybill.getMileage());
putIfNotEmpty(goods, "unitPrice", waybill.getUnitPrice());
putIfNotEmpty(goods, "priceUnit", waybill.getPriceUnit());
putIfNotEmpty(goods, "otherFeeTotal", waybill.getOtherFeeTotal());
putIfNotEmpty(goods, "remark", waybill.getTaskRemark());
return JsonUtil.toJson(List.of(goods));
}
private String buildFreightJson(Waybill waybill) {
if (!hasAnyValue(waybill.getUnitPrice(), waybill.getPriceUnit(), waybill.getOtherFeeTotal())) {
return null;
}
Map<String, Object> freight = new LinkedHashMap<>();
putIfNotEmpty(freight, "unitPrice", waybill.getUnitPrice());
putIfNotEmpty(freight, "priceUnit", waybill.getPriceUnit());
putIfNotEmpty(freight, "otherFeeTotal", waybill.getOtherFeeTotal());
return JsonUtil.toJson(List.of(freight));
}
private boolean hasAnyValue(Object... values) {
for (Object value : values) {
if (Func.isNotEmpty(value)) {
return true;
}
}
return false;
}
private void putIfNotEmpty(Map<String, Object> map, String key, Object value) {
if (Func.isNotEmpty(value)) {
map.put(key, value);
}
}
private synchronized String nextCode() { private synchronized String nextCode() {
String prefix = "YD" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE); String prefix = "YD" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
List<Waybill> latestList = list(Wrappers.<Waybill>lambdaQuery() List<Waybill> latestList = list(Wrappers.<Waybill>lambdaQuery()

View File

@@ -0,0 +1,53 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.wrapper;
import org.springblade.core.mp.support.BaseEntityWrapper;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.cache.UserCache;
import org.springblade.transport.pojo.entity.LoadingManage;
import org.springblade.transport.pojo.vo.LoadingManageVO;
import java.util.Objects;
/**
* 配载管理包装类
*
* @author Chill
*/
public class LoadingManageWrapper extends BaseEntityWrapper<LoadingManage, LoadingManageVO> {
public static LoadingManageWrapper build() {
return new LoadingManageWrapper();
}
@Override
public LoadingManageVO entityVO(LoadingManage loadingManage) {
LoadingManageVO loadingManageVO = Objects.requireNonNull(BeanUtil.copyProperties(loadingManage, LoadingManageVO.class));
loadingManageVO.setCreateUserName(UserCache.getUserRealName(loadingManage.getCreateUser()));
loadingManageVO.setUpdateUserName(UserCache.getUserRealName(loadingManage.getUpdateUser()));
Long currentDeptId = Func.firstLong(AuthUtil.getDeptId());
loadingManageVO.setReadonly(currentDeptId != null && !Objects.equals(loadingManage.getDeptId(), currentDeptId));
loadingManageVO.setBusinessStatusName(businessStatusName(loadingManage.getBusinessStatus()));
return loadingManageVO;
}
private String businessStatusName(String status) {
if (status == null) {
return "未知";
}
return switch (status) {
case "draft" -> "草稿";
case "pending" -> "待执行";
case "running" -> "进行中";
case "completed" -> "已完成";
case "cancelled" -> "已取消";
default -> "未知";
};
}
}

View File

@@ -31,4 +31,20 @@ public class CertificateBatchRecognitionDTO implements Serializable {
* 目录名称 * 目录名称
*/ */
private String dirName; private String dirName;
/**
* 磅单url列表
*/
private List<String> poundUrls;
/**
* 车头url列表
*/
private List<String> carFrontUrls;
/**
* 驾驶证url列表
*/
private List<String> driverLicenseUrls;
/**
* 行驶证url列表
*/
private List<String> vehicleLicenseUrls;
} }

View File

@@ -47,10 +47,26 @@ public class OCRServiceImpl implements IOCRService {
@Override @Override
public TransportCertificateVO recognitionTransportCertificate(CertificateBatchRecognitionDTO param) { public TransportCertificateVO recognitionTransportCertificate(CertificateBatchRecognitionDTO param) {
log.info("ocr 批量识别参数:{}", JSONUtil.toJsonStr(param)); log.info("ocr 批量识别参数:{}", JSONUtil.toJsonStr(param));
if (param == null || CollectionUtils.isEmpty(param.getUrls())) { if (param == null) {
throw new OCRException("图像链接不能为空"); throw new OCRException("图像链接不能为空");
} }
List<OCRResultVO<OCRBigCommonCardVO>> result = this.getCardResult(() -> client.batchRecognition(new OCRBigCommonCardBatchDTO(param.getUrls(), param.getProjectAbbreviation(), param.getDirName()), param.getCode()), "批量磅单卡证识别"); if (hasTypedUrls(param)) {
return convertTransportCertificate(recognitionTransportCertificateWithTypedUrls(param));
}
if (CollectionUtils.isEmpty(param.getUrls())) {
throw new OCRException("图像链接不能为空");
}
List<OCRResultVO<OCRBigCommonCardVO>> result = this.getCardResult(
() -> client.batchRecognition(
new OCRBigCommonCardBatchDTO(
param.getUrls(),
param.getProjectAbbreviation(),
param.getDirName()
),
param.getCode()
),
"批量磅单卡证识别"
);
List<OCRBigCommonCardVO> cards = result.stream() List<OCRBigCommonCardVO> cards = result.stream()
.map(OCRResultVO::getResult) .map(OCRResultVO::getResult)
.toList(); .toList();
@@ -134,6 +150,108 @@ public class OCRServiceImpl implements IOCRService {
} }
} }
private List<OCRBigCommonCardVO> recognitionTransportCertificateWithTypedUrls(CertificateBatchRecognitionDTO param) {
List<OCRBigCommonCardVO> cards = new ArrayList<>(4);
addPoundRecognitionCards(cards, param);
addDriverLicenseRecognitionCards(cards, param);
addVehicleLicenseRecognitionCards(cards, param);
addCarFrontRecognitionCards(cards, param);
return cards;
}
private void addPoundRecognitionCards(List<OCRBigCommonCardVO> cards, CertificateBatchRecognitionDTO param) {
for (String url : Optional.ofNullable(param.getPoundUrls()).orElse(List.of())) {
if (StringUtil.isBlank(url)) {
continue;
}
OCRBigCommonCardVO card = this.getCardResult(
() -> client.poundRecognition(
new OCRSingleDTO(url, param.getProjectAbbreviation()), param.getCode()
),
"磅单单独识别"
);
addCard(cards, card);
}
}
private void addDriverLicenseRecognitionCards(List<OCRBigCommonCardVO> cards, CertificateBatchRecognitionDTO param) {
List<String> driverLicenseUrls = Optional.ofNullable(param.getDriverLicenseUrls()).orElse(List.of());
for (String url : driverLicenseUrls) {
if (StringUtil.isBlank(url)) {
continue;
}
OCRBigCommonCardVO card = this.getCardResult(
() -> client.singleRecognition(
new OCRBigCommonCardDTO(
url,
param.getProjectAbbreviation(),
List.of(
OCRImageType.DRIVER_LICENSE_MAIN.getId(),
OCRImageType.DRIVER_LICENSE_SIDE.getId(),
OCRImageType.DRIVER_LICENSE_ELEC.getId()
)
),
param.getCode()
),
"驾驶证识别"
);
addCard(cards, card);
}
}
private void addVehicleLicenseRecognitionCards(List<OCRBigCommonCardVO> cards, CertificateBatchRecognitionDTO param) {
List<String> vehicleLicenseUrls = Optional.ofNullable(param.getVehicleLicenseUrls()).orElse(List.of());
for (String url : vehicleLicenseUrls) {
if (StringUtil.isBlank(url)) {
continue;
}
OCRBigCommonCardVO card = this.getCardResult(
() -> client.singleRecognition(
new OCRBigCommonCardDTO(
url,
param.getProjectAbbreviation(),
List.of(
OCRImageType.VEHICLE_LICENSE_MAIN_GUA.getId(),
OCRImageType.VEHICLE_LICENSE_MAIN.getId(),
OCRImageType.VEHICLE_LICENSE_SIDE.getId()
)
),
param.getCode()
),
"行驶证识别"
);
addCard(cards, card);
}
}
private void addCarFrontRecognitionCards(List<OCRBigCommonCardVO> cards, CertificateBatchRecognitionDTO param) {
for (String url : Optional.ofNullable(param.getCarFrontUrls()).orElse(List.of())) {
if (StringUtil.isBlank(url)) {
continue;
}
OCRBigCommonCardVO card = this.getCardResult(
() -> client.plateNoRecognition(
new OCRSingleDTO(url, param.getProjectAbbreviation()), param.getCode()
),
"⻋牌单独识别"
);
addCard(cards, card);
}
}
private static boolean hasTypedUrls(CertificateBatchRecognitionDTO param) {
return CollectionUtil.isNotEmpty(param.getPoundUrls())
|| CollectionUtil.isNotEmpty(param.getCarFrontUrls())
|| CollectionUtil.isNotEmpty(param.getDriverLicenseUrls())
|| CollectionUtil.isNotEmpty(param.getVehicleLicenseUrls());
}
private static void addCard(List<OCRBigCommonCardVO> cards, OCRBigCommonCardVO card) {
if (card != null) {
cards.add(card);
}
}
/** /**
* 转换车辆凭证 * 转换车辆凭证
* @param cards * @param cards

View File

@@ -0,0 +1,65 @@
CREATE TABLE IF NOT EXISTS `blade_loading_manage` (
`id` bigint(20) NOT NULL COMMENT '主键',
`tenant_id` varchar(12) DEFAULT '000000' COMMENT '租户ID',
`create_user` bigint(20) DEFAULT NULL COMMENT '创建人',
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`status` int(11) DEFAULT '1' COMMENT '状态',
`is_deleted` int(11) DEFAULT '0' COMMENT '是否已删除',
`loading_no` varchar(100) DEFAULT NULL COMMENT '配载单号',
`loading_sub_nos` varchar(200) DEFAULT NULL COMMENT '配载子单号',
`waybill_ids_json` varchar(4000) DEFAULT NULL COMMENT '运单ID集合',
`project_id` bigint(20) DEFAULT NULL COMMENT '项目ID',
`project_name` varchar(100) DEFAULT NULL COMMENT '项目名称',
`customer_name` varchar(100) DEFAULT NULL COMMENT '客户名称',
`transport_type` varchar(100) DEFAULT NULL COMMENT '运输类型',
`cargo_type` varchar(100) DEFAULT NULL COMMENT '货物类型',
`cargo_name` varchar(100) DEFAULT NULL COMMENT '货物名称',
`vehicle_no` varchar(100) DEFAULT NULL COMMENT '车/船/航班/班列',
`trailer_vehicle_no` varchar(100) DEFAULT NULL COMMENT '挂车车牌号',
`driver_name` varchar(100) DEFAULT NULL COMMENT '司机',
`driver_phone` varchar(50) DEFAULT NULL COMMENT '联系电话',
`escort_name` varchar(100) DEFAULT NULL COMMENT '押运人',
`escort_phone` varchar(50) DEFAULT NULL COMMENT '押运人手机号',
`carrier_type` varchar(50) DEFAULT NULL COMMENT '承运类型',
`carrier_name` varchar(100) DEFAULT NULL COMMENT '承运商',
`departure_address` varchar(100) DEFAULT NULL COMMENT '发货地',
`transit_address` varchar(200) DEFAULT NULL COMMENT '途经地',
`arrival_address` varchar(100) DEFAULT NULL COMMENT '到货地',
`original_no` varchar(100) DEFAULT NULL COMMENT '原始单号',
`data_source` varchar(100) DEFAULT NULL COMMENT '数据来源',
`start_date` date DEFAULT NULL COMMENT '开始日期',
`end_date` date DEFAULT NULL COMMENT '结束日期',
`plan_name` varchar(100) DEFAULT NULL COMMENT '计划名称',
`batch_no` varchar(100) DEFAULT NULL COMMENT '运单批次号',
`current_process_node` varchar(100) DEFAULT NULL COMMENT '当前过程节点',
`mileage` decimal(18,2) DEFAULT NULL COMMENT '里程',
`estimated_start_date` date DEFAULT NULL COMMENT '预计发货日期',
`estimated_end_date` date DEFAULT NULL COMMENT '预计完成日期',
`task_remark` varchar(500) DEFAULT NULL COMMENT '任务备注',
`goods_json` text DEFAULT NULL COMMENT '货物信息',
`route_json` text DEFAULT NULL COMMENT '路线信息',
`task_info_json` text DEFAULT NULL COMMENT '任务信息',
`dept_id` bigint(20) DEFAULT NULL COMMENT '所属组织ID',
`dept_name` varchar(100) DEFAULT NULL COMMENT '所属组织',
`business_status` varchar(100) DEFAULT NULL COMMENT '业务状态',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uk_loading_manage_no` (`loading_no`) USING BTREE,
KEY `idx_loading_manage_dept` (`dept_id`) USING BTREE,
KEY `idx_loading_manage_create_time` (`create_time`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配载管理';
INSERT IGNORE INTO `blade_menu` (`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `component`, `remark`, `is_deleted`) VALUES
(2090000000000000700, 2090000000000000000, 'loading_manage', '配载管理', 'loading_manage', '/business/loading-manage', 'iconfont icon-caidanguanli', 70, 1, 0, 1, NULL, '', 0),
(2090000000000000701, 2090000000000000700, 'loading_manage_view', '查看', 'loading_manage_view', '', '', 1, 2, 0, 1, NULL, '', 0),
(2090000000000000702, 2090000000000000700, 'loading_manage_add', '新增', 'loading_manage_add', '', '', 2, 2, 0, 1, NULL, '', 0),
(2090000000000000703, 2090000000000000700, 'loading_manage_edit', '编辑', 'loading_manage_edit', '', '', 3, 2, 0, 1, NULL, '', 0),
(2090000000000000704, 2090000000000000700, 'loading_manage_delete', '删除', 'loading_manage_delete', '', '', 4, 2, 0, 1, NULL, '', 0),
(2090000000000000705, 2090000000000000700, 'loading_manage_export', '批量导出', 'loading_manage_export', '', '', 5, 2, 0, 1, NULL, '', 0),
(2090000000000000706, 2090000000000000700, 'loading_manage_copy', '复制', 'loading_manage_copy', '', '', 6, 2, 0, 1, NULL, '', 0),
(2090000000000000707, 2090000000000000700, 'loading_manage_reassign', '重新派单', 'loading_manage_reassign', '', '', 7, 2, 0, 1, NULL, '', 0),
(2090000000000000708, 2090000000000000700, 'loading_manage_cancel', '取消', 'loading_manage_cancel', '', '', 8, 2, 0, 1, NULL, '', 0),
(2090000000000000709, 2090000000000000700, 'loading_manage_complete', '完成', 'loading_manage_complete', '', '', 9, 2, 0, 1, NULL, '', 0),
(2090000000000000710, 2090000000000000700, 'loading_manage_batch_complete', '批量完成', 'loading_manage_batch_complete', '', '', 10, 2, 0, 1, NULL, '', 0);

View File

@@ -219,11 +219,38 @@ CREATE TABLE `blade_waybill` (
`transport_type` varchar(100) DEFAULT NULL COMMENT '运输类型', `transport_type` varchar(100) DEFAULT NULL COMMENT '运输类型',
`cargo_name` varchar(100) DEFAULT NULL COMMENT '货物名称', `cargo_name` varchar(100) DEFAULT NULL COMMENT '货物名称',
`cargo_type` varchar(100) DEFAULT NULL COMMENT '货物类型', `cargo_type` varchar(100) DEFAULT NULL COMMENT '货物类型',
`specification` varchar(255) DEFAULT NULL COMMENT '规格',
`model` varchar(255) DEFAULT NULL COMMENT '型号',
`quantity` decimal(18,2) DEFAULT NULL COMMENT '数量',
`quantity_unit` varchar(50) DEFAULT NULL COMMENT '数量单位',
`departure_address_id` bigint(20) DEFAULT NULL COMMENT '发货地址ID',
`departure_name` varchar(100) DEFAULT NULL COMMENT '发货地',
`departure_address` varchar(255) DEFAULT NULL COMMENT '发货地址', `departure_address` varchar(255) DEFAULT NULL COMMENT '发货地址',
`departure_contact` varchar(100) DEFAULT NULL COMMENT '发货联系人',
`departure_phone` varchar(50) DEFAULT NULL COMMENT '发货联系方式',
`arrival_address_id` bigint(20) DEFAULT NULL COMMENT '收货地址ID',
`arrival_name` varchar(100) DEFAULT NULL COMMENT '收货地',
`arrival_address` varchar(255) DEFAULT NULL COMMENT '收货地址', `arrival_address` varchar(255) DEFAULT NULL COMMENT '收货地址',
`arrival_contact` varchar(100) DEFAULT NULL COMMENT '收货联系人',
`arrival_phone` varchar(50) DEFAULT NULL COMMENT '收货联系方式',
`task_entry_mode` varchar(50) DEFAULT NULL COMMENT '任务录入模式',
`carrier_type` varchar(50) DEFAULT NULL COMMENT '承运类型',
`carrier_id` bigint(20) DEFAULT NULL COMMENT '承运商ID',
`carrier_name` varchar(100) DEFAULT NULL COMMENT '承运商名称', `carrier_name` varchar(100) DEFAULT NULL COMMENT '承运商名称',
`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 '司机手机号',
`vehicle_no` varchar(100) DEFAULT NULL COMMENT '车/船/航班/班列号', `vehicle_no` varchar(100) DEFAULT NULL COMMENT '车/船/航班/班列号',
`trailer_vehicle_no` varchar(100) DEFAULT NULL COMMENT '挂车车牌号',
`escort_name` varchar(100) DEFAULT NULL COMMENT '押运人',
`escort_phone` varchar(50) DEFAULT NULL COMMENT '押运人手机号',
`mileage` decimal(18,2) DEFAULT NULL COMMENT '里程',
`estimated_start_time` datetime DEFAULT NULL COMMENT '预计发货时间',
`estimated_end_time` datetime DEFAULT NULL COMMENT '预计完成时间',
`unit_price` decimal(18,2) DEFAULT NULL COMMENT '单价',
`price_unit` varchar(50) DEFAULT NULL COMMENT '计价单位',
`other_fee_total` decimal(18,2) DEFAULT NULL COMMENT '其他费用合计',
`task_remark` varchar(200) DEFAULT NULL COMMENT '任务备注',
`original_no` varchar(100) DEFAULT NULL COMMENT '原始单号', `original_no` varchar(100) DEFAULT NULL COMMENT '原始单号',
`business_status` varchar(100) DEFAULT NULL COMMENT '业务状态', `business_status` varchar(100) DEFAULT NULL COMMENT '业务状态',
`data_source` varchar(100) DEFAULT NULL COMMENT '数据来源', `data_source` varchar(100) DEFAULT NULL COMMENT '数据来源',
@@ -238,17 +265,75 @@ CREATE TABLE `blade_waybill` (
`current_process_node` varchar(100) DEFAULT NULL COMMENT '当前过程节点', `current_process_node` varchar(100) DEFAULT NULL COMMENT '当前过程节点',
`goods_json` text DEFAULT NULL COMMENT '货物信息', `goods_json` text DEFAULT NULL COMMENT '货物信息',
`carrier_json` text DEFAULT NULL COMMENT '承运信息', `carrier_json` text DEFAULT NULL COMMENT '承运信息',
`task_info_json` text DEFAULT NULL COMMENT '任务信息',
`process_json` text DEFAULT NULL COMMENT '过程节点', `process_json` text DEFAULT NULL COMMENT '过程节点',
`freight_json` text DEFAULT NULL COMMENT '费用信息', `freight_json` text DEFAULT NULL COMMENT '费用信息',
`attachments_json` text DEFAULT NULL COMMENT '附件', `attachments_json` text DEFAULT NULL COMMENT '附件',
`dept_id` bigint(20) DEFAULT NULL COMMENT '所属组织ID', `dept_id` bigint(20) DEFAULT NULL COMMENT '所属组织ID',
`dept_name` varchar(100) DEFAULT NULL COMMENT '所属组织', `dept_name` varchar(100) DEFAULT NULL COMMENT '所属组织',
`remark` varchar(500) DEFAULT NULL COMMENT '备注', `remark` varchar(200) DEFAULT NULL COMMENT '备注',
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_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='运单管理';
-- ----------------------------
-- Table structure for blade_loading_manage
-- ----------------------------
DROP TABLE IF EXISTS `blade_loading_manage`;
CREATE TABLE `blade_loading_manage` (
`id` bigint(20) NOT NULL COMMENT '主键',
`tenant_id` varchar(12) DEFAULT '000000' COMMENT '租户ID',
`create_user` bigint(20) DEFAULT NULL COMMENT '创建人',
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`status` int(11) DEFAULT '1' COMMENT '状态',
`is_deleted` int(11) DEFAULT '0' COMMENT '是否已删除',
`loading_no` varchar(100) DEFAULT NULL COMMENT '配载单号',
`loading_sub_nos` varchar(200) DEFAULT NULL COMMENT '配载子单号',
`waybill_ids_json` varchar(4000) DEFAULT NULL COMMENT '运单ID集合',
`project_id` bigint(20) DEFAULT NULL COMMENT '项目ID',
`project_name` varchar(100) DEFAULT NULL COMMENT '项目名称',
`customer_name` varchar(100) DEFAULT NULL COMMENT '客户名称',
`transport_type` varchar(100) DEFAULT NULL COMMENT '运输类型',
`cargo_type` varchar(100) DEFAULT NULL COMMENT '货物类型',
`cargo_name` varchar(100) DEFAULT NULL COMMENT '货物名称',
`vehicle_no` varchar(100) DEFAULT NULL COMMENT '车/船/航班/班列',
`trailer_vehicle_no` varchar(100) DEFAULT NULL COMMENT '挂车车牌号',
`driver_name` varchar(100) DEFAULT NULL COMMENT '司机',
`driver_phone` varchar(50) DEFAULT NULL COMMENT '联系电话',
`escort_name` varchar(100) DEFAULT NULL COMMENT '押运人',
`escort_phone` varchar(50) DEFAULT NULL COMMENT '押运人手机号',
`carrier_type` varchar(50) DEFAULT NULL COMMENT '承运类型',
`carrier_name` varchar(100) DEFAULT NULL COMMENT '承运商',
`departure_address` varchar(100) DEFAULT NULL COMMENT '发货地',
`transit_address` varchar(200) DEFAULT NULL COMMENT '途经地',
`arrival_address` varchar(100) DEFAULT NULL COMMENT '到货地',
`original_no` varchar(100) DEFAULT NULL COMMENT '原始单号',
`data_source` varchar(100) DEFAULT NULL COMMENT '数据来源',
`start_date` date DEFAULT NULL COMMENT '开始日期',
`end_date` date DEFAULT NULL COMMENT '结束日期',
`plan_name` varchar(100) DEFAULT NULL COMMENT '计划名称',
`batch_no` varchar(100) DEFAULT NULL COMMENT '运单批次号',
`current_process_node` varchar(100) DEFAULT NULL COMMENT '当前过程节点',
`mileage` decimal(18,2) DEFAULT NULL COMMENT '里程',
`estimated_start_date` date DEFAULT NULL COMMENT '预计发货日期',
`estimated_end_date` date DEFAULT NULL COMMENT '预计完成日期',
`task_remark` varchar(500) DEFAULT NULL COMMENT '任务备注',
`goods_json` text DEFAULT NULL COMMENT '货物信息',
`route_json` text DEFAULT NULL COMMENT '路线信息',
`task_info_json` text DEFAULT NULL COMMENT '任务信息',
`dept_id` bigint(20) DEFAULT NULL COMMENT '所属组织ID',
`dept_name` varchar(100) DEFAULT NULL COMMENT '所属组织',
`business_status` varchar(100) DEFAULT NULL COMMENT '业务状态',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `uk_loading_manage_no` (`loading_no`) USING BTREE,
KEY `idx_loading_manage_dept` (`dept_id`) USING BTREE,
KEY `idx_loading_manage_create_time` (`create_time`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配载管理';
-- ---------------------------- -- ----------------------------
-- Menu data for business management -- Menu data for business management
-- ---------------------------- -- ----------------------------
@@ -303,4 +388,18 @@ INSERT IGNORE INTO `blade_menu` (`id`, `parent_id`, `code`, `name`, `alias`, `pa
(2090000000000000607, 2090000000000000600, 'waybill_manage_cancel', '取消', 'waybill_manage_cancel', '', '', 7, 2, 0, 1, NULL, '', 0), (2090000000000000607, 2090000000000000600, 'waybill_manage_cancel', '取消', 'waybill_manage_cancel', '', '', 7, 2, 0, 1, NULL, '', 0),
(2090000000000000608, 2090000000000000600, 'waybill_manage_reassign', '重新派单', 'waybill_manage_reassign', '', '', 8, 2, 0, 1, NULL, '', 0), (2090000000000000608, 2090000000000000600, 'waybill_manage_reassign', '重新派单', 'waybill_manage_reassign', '', '', 8, 2, 0, 1, NULL, '', 0),
(2090000000000000609, 2090000000000000600, 'waybill_manage_complete', '完成', 'waybill_manage_complete', '', '', 9, 2, 0, 1, NULL, '', 0), (2090000000000000609, 2090000000000000600, 'waybill_manage_complete', '完成', 'waybill_manage_complete', '', '', 9, 2, 0, 1, NULL, '', 0),
(2090000000000000610, 2090000000000000600, 'waybill_manage_batch_complete', '批量完成', 'waybill_manage_batch_complete', '', '', 10, 2, 0, 1, NULL, '', 0); (2090000000000000610, 2090000000000000600, 'waybill_manage_batch_complete', '批量完成', 'waybill_manage_batch_complete', '', '', 10, 2, 0, 1, NULL, '', 0),
(2090000000000000611, 2090000000000000600, 'waybill_manage_import', '导入运单', 'waybill_manage_import', '', '', 11, 2, 0, 1, NULL, '', 0),
(2090000000000000612, 2090000000000000600, 'waybill_manage_template', '下载模板', 'waybill_manage_template', '', '', 12, 2, 0, 1, NULL, '', 0),
(2090000000000000613, 2090000000000000600, 'waybill_manage_road_loading', '公路配载', 'waybill_manage_road_loading', '', '', 13, 2, 0, 1, NULL, '', 0),
(2090000000000000700, 2090000000000000000, 'loading_manage', '配载管理', 'loading_manage', '/business/loading-manage', 'iconfont icon-caidanguanli', 70, 1, 0, 1, NULL, '', 0),
(2090000000000000701, 2090000000000000700, 'loading_manage_view', '查看', 'loading_manage_view', '', '', 1, 2, 0, 1, NULL, '', 0),
(2090000000000000702, 2090000000000000700, 'loading_manage_add', '新增', 'loading_manage_add', '', '', 2, 2, 0, 1, NULL, '', 0),
(2090000000000000703, 2090000000000000700, 'loading_manage_edit', '编辑', 'loading_manage_edit', '', '', 3, 2, 0, 1, NULL, '', 0),
(2090000000000000704, 2090000000000000700, 'loading_manage_delete', '删除', 'loading_manage_delete', '', '', 4, 2, 0, 1, NULL, '', 0),
(2090000000000000705, 2090000000000000700, 'loading_manage_export', '批量导出', 'loading_manage_export', '', '', 5, 2, 0, 1, NULL, '', 0),
(2090000000000000706, 2090000000000000700, 'loading_manage_copy', '复制', 'loading_manage_copy', '', '', 6, 2, 0, 1, NULL, '', 0),
(2090000000000000707, 2090000000000000700, 'loading_manage_reassign', '重新派单', 'loading_manage_reassign', '', '', 7, 2, 0, 1, NULL, '', 0),
(2090000000000000708, 2090000000000000700, 'loading_manage_cancel', '取消', 'loading_manage_cancel', '', '', 8, 2, 0, 1, NULL, '', 0),
(2090000000000000709, 2090000000000000700, 'loading_manage_complete', '完成', 'loading_manage_complete', '', '', 9, 2, 0, 1, NULL, '', 0),
(2090000000000000710, 2090000000000000700, 'loading_manage_batch_complete', '批量完成', 'loading_manage_batch_complete', '', '', 10, 2, 0, 1, NULL, '', 0);

View File

@@ -0,0 +1,30 @@
ALTER TABLE `blade_waybill`
ADD COLUMN `specification` varchar(255) DEFAULT NULL COMMENT '规格' AFTER `cargo_type`,
ADD COLUMN `model` varchar(255) DEFAULT NULL COMMENT '型号' AFTER `specification`,
ADD COLUMN `quantity` decimal(18,2) DEFAULT NULL COMMENT '数量' AFTER `model`,
ADD COLUMN `quantity_unit` varchar(50) DEFAULT NULL COMMENT '数量单位' AFTER `quantity`,
ADD COLUMN `departure_address_id` bigint(20) DEFAULT NULL COMMENT '发货地址ID' AFTER `quantity_unit`,
ADD COLUMN `departure_name` varchar(100) DEFAULT NULL COMMENT '发货地' AFTER `departure_address_id`,
ADD COLUMN `departure_contact` varchar(100) DEFAULT NULL COMMENT '发货联系人' AFTER `departure_address`,
ADD COLUMN `departure_phone` varchar(50) DEFAULT NULL COMMENT '发货联系方式' AFTER `departure_contact`,
ADD COLUMN `arrival_address_id` bigint(20) DEFAULT NULL COMMENT '收货地址ID' AFTER `departure_phone`,
ADD COLUMN `arrival_name` varchar(100) DEFAULT NULL COMMENT '收货地' AFTER `arrival_address_id`,
ADD COLUMN `arrival_contact` varchar(100) DEFAULT NULL COMMENT '收货联系人' AFTER `arrival_address`,
ADD COLUMN `arrival_phone` varchar(50) DEFAULT NULL COMMENT '收货联系方式' AFTER `arrival_contact`,
ADD COLUMN `task_entry_mode` varchar(50) DEFAULT NULL COMMENT '任务录入模式' AFTER `arrival_phone`,
ADD COLUMN `carrier_type` varchar(50) DEFAULT NULL COMMENT '承运类型' AFTER `task_entry_mode`,
ADD COLUMN `carrier_id` bigint(20) DEFAULT NULL COMMENT '承运商ID' AFTER `carrier_type`,
ADD COLUMN `driver_id` bigint(20) DEFAULT NULL COMMENT '司机ID' AFTER `carrier_name`,
ADD COLUMN `driver_phone` varchar(50) DEFAULT NULL COMMENT '司机手机号' AFTER `driver_name`,
ADD COLUMN `trailer_vehicle_no` varchar(100) DEFAULT NULL COMMENT '挂车车牌号' AFTER `vehicle_no`,
ADD COLUMN `escort_name` varchar(100) DEFAULT NULL COMMENT '押运人' AFTER `trailer_vehicle_no`,
ADD COLUMN `escort_phone` varchar(50) DEFAULT NULL COMMENT '押运人手机号' AFTER `escort_name`,
ADD COLUMN `mileage` decimal(18,2) DEFAULT NULL COMMENT '里程' AFTER `escort_phone`,
ADD COLUMN `estimated_start_time` datetime DEFAULT NULL COMMENT '预计发货时间' AFTER `mileage`,
ADD COLUMN `estimated_end_time` datetime DEFAULT NULL COMMENT '预计完成时间' AFTER `estimated_start_time`,
ADD COLUMN `unit_price` decimal(18,2) DEFAULT NULL COMMENT '单价' AFTER `estimated_end_time`,
ADD COLUMN `price_unit` varchar(50) DEFAULT NULL COMMENT '计价单位' AFTER `unit_price`,
ADD COLUMN `other_fee_total` decimal(18,2) DEFAULT NULL COMMENT '其他费用合计' AFTER `price_unit`,
ADD COLUMN `task_remark` varchar(200) DEFAULT NULL COMMENT '任务备注' AFTER `other_fee_total`,
ADD COLUMN `task_info_json` text DEFAULT NULL COMMENT '任务信息' AFTER `carrier_json`,
MODIFY COLUMN `remark` varchar(200) DEFAULT NULL COMMENT '备注';