From 93c7e6f8f5de134000a9d83cb8f32bb3a543d491 Mon Sep 17 00:00:00 2001 From: b2894lxlx <517289602@qq.com> Date: Thu, 10 Sep 2026 22:50:00 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E8=B0=83=E6=95=B4=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E8=BF=90=E5=8D=95=202=E3=80=81=E8=B0=83=E6=95=B4=E5=AF=B9?= =?UTF-8?q?=E8=B4=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../springblade/system/feign/ISysClient.java | 11 + .../system/feign/ISysClientFallback.java | 5 + .../transport/pojo/entity/Driver.java | 5 + .../transport/pojo/entity/ProjectApply.java | 7 + .../pojo/entity/TransportVehicle.java | 5 + .../transport/pojo/vo/TransportVehicleVO.java | 7 + .../springblade/system/feign/IUserClient.java | 10 + .../springblade/system/feign/SysClient.java | 10 + .../springblade/system/feign/UserClient.java | 6 + .../TransportReconciliationController.java | 10 +- .../controller/WaybillController.java | 9 +- .../excel/CargoReconciliationExcel.java | 4 +- .../transport/excel/ProjectApplyExcel.java | 4 + .../ReconciliationImportTemplateExcel.java | 71 +++++++ .../excel/TransportVehicleExcel.java | 3 + .../excel/VehicleReconciliationExcel.java | 2 +- .../transport/mapper/DriverMapper.xml | 2 + .../mapper/TransportVehicleMapper.xml | 6 + .../mapper/WaybillImportBatchMapper.java | 11 + .../ITransportReconciliationService.java | 1 + .../service/IWaybillImportBatchService.java | 1 + .../service/impl/DriverServiceImpl.java | 191 +++++++++++++++++- .../service/impl/ProjectApplyServiceImpl.java | 8 + .../TransportReconciliationServiceImpl.java | 70 ++++++- .../impl/TransportVehicleServiceImpl.java | 82 +++++++- .../impl/WaybillImportBatchServiceImpl.java | 14 +- ...ply_business_mode_profit_rate_20260910.sql | 4 + .../blade_project_contract_management.sql | 2 + doc/sql/transport/blade_transport_driver.sql | 1 + ...blade_transport_driver_role_alias_note.sql | 6 + ...lade_transport_driver_user_id_20260910.sql | 3 + doc/sql/transport/blade_transport_vehicle.sql | 1 + ...nsport_vehicle_use_department_20260910.sql | 3 + 33 files changed, 553 insertions(+), 22 deletions(-) create mode 100644 blade-service/blade-transport/src/main/java/org/springblade/transport/excel/ReconciliationImportTemplateExcel.java create mode 100644 doc/sql/transport/blade_project_apply_business_mode_profit_rate_20260910.sql create mode 100644 doc/sql/transport/blade_transport_driver_role_alias_note.sql create mode 100644 doc/sql/transport/blade_transport_driver_user_id_20260910.sql create mode 100644 doc/sql/transport/blade_transport_vehicle_use_department_20260910.sql diff --git a/blade-service-api/blade-system-api/src/main/java/org/springblade/system/feign/ISysClient.java b/blade-service-api/blade-system-api/src/main/java/org/springblade/system/feign/ISysClient.java index fb18df7..37e33b1 100644 --- a/blade-service-api/blade-system-api/src/main/java/org/springblade/system/feign/ISysClient.java +++ b/blade-service-api/blade-system-api/src/main/java/org/springblade/system/feign/ISysClient.java @@ -64,6 +64,7 @@ public interface ISysClient { String ROLE_NAMES = API_PREFIX + "/role-names"; String ROLE_ALIAS = API_PREFIX + "/role-alias"; String ROLE_ALIASES = API_PREFIX + "/role-aliases"; + String ROLE_ID_BY_ALIAS = API_PREFIX + "/role-id-by-alias"; String TENANT = API_PREFIX + "/tenant"; String TENANT_ID = API_PREFIX + "/tenant-id"; String TENANT_PACKAGE = API_PREFIX + "/tenant-package"; @@ -240,6 +241,16 @@ public interface ISysClient { @GetMapping(ROLE_ALIASES) R> getRoleAliases(@RequestParam("roleIds") String roleIds); + /** + * 根据角色别名获取角色id + * + * @param tenantId 租户id + * @param roleAlias 角色别名 + * @return 角色id + */ + @GetMapping(ROLE_ID_BY_ALIAS) + R getRoleIdByAlias(@RequestParam("tenantId") String tenantId, @RequestParam("roleAlias") String roleAlias); + /** * 获取租户 * diff --git a/blade-service-api/blade-system-api/src/main/java/org/springblade/system/feign/ISysClientFallback.java b/blade-service-api/blade-system-api/src/main/java/org/springblade/system/feign/ISysClientFallback.java index f31965c..c7598c3 100644 --- a/blade-service-api/blade-system-api/src/main/java/org/springblade/system/feign/ISysClientFallback.java +++ b/blade-service-api/blade-system-api/src/main/java/org/springblade/system/feign/ISysClientFallback.java @@ -129,6 +129,11 @@ public class ISysClientFallback implements ISysClient { return R.fail("获取数据失败"); } + @Override + public R getRoleIdByAlias(String tenantId, String roleAlias) { + return R.fail("获取数据失败"); + } + @Override public R getTenant(Long id) { return R.fail("获取数据失败"); diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/Driver.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/Driver.java index 0ba8076..1d13e2e 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/Driver.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/Driver.java @@ -191,6 +191,11 @@ public class Driver extends TenantEntity { */ @Schema(description = "手机号") private String mobile; + /** + * 关联系统用户ID + */ + @Schema(description = "关联系统用户ID") + private Long userId; /** * 与联系人关系 */ diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ProjectApply.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ProjectApply.java index be872cf..8ba12f4 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ProjectApply.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/ProjectApply.java @@ -118,6 +118,9 @@ public class ProjectApply extends TenantEntity { @Schema(description = "业务类型") private String businessType; + @Schema(description = "业务模式") + private String businessMode; + @Schema(description = "项目规模(万元)") @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private BigDecimal projectScale; @@ -126,6 +129,10 @@ public class ProjectApply extends TenantEntity { @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private BigDecimal estimatedProfit; + @Schema(description = "利润率(%)") + @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) + private BigDecimal profitRate; + @Schema(description = "资金需求(万元)") @TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS) private BigDecimal fundDemand; diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/TransportVehicle.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/TransportVehicle.java index e79e0ef..4829cc3 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/TransportVehicle.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/TransportVehicle.java @@ -53,6 +53,11 @@ public class TransportVehicle extends TenantEntity { */ @Schema(description = "所属组织") private String organizationName; + /** + * 使用部门 + */ + @Schema(description = "使用部门") + private String useDepartment; /** * 车牌号 */ diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/TransportVehicleVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/TransportVehicleVO.java index 46acec1..7536d19 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/TransportVehicleVO.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/TransportVehicleVO.java @@ -69,4 +69,11 @@ public class TransportVehicleVO extends TransportVehicle { @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDate warningDate; + /** + * 绑定司机(按车牌反查司机驾驶车辆,多个用顿号拼接) + */ + @TableField(exist = false) + @Schema(description = "绑定司机") + private String boundDriver; + } diff --git a/blade-service-api/blade-user-api/src/main/java/org/springblade/system/feign/IUserClient.java b/blade-service-api/blade-user-api/src/main/java/org/springblade/system/feign/IUserClient.java index 9dce693..cc78a95 100644 --- a/blade-service-api/blade-user-api/src/main/java/org/springblade/system/feign/IUserClient.java +++ b/blade-service-api/blade-user-api/src/main/java/org/springblade/system/feign/IUserClient.java @@ -57,6 +57,7 @@ public interface IUserClient { String USER_BY_ACCOUNT = API_PREFIX + "/user-by-account"; String USER_AUTH_INFO = API_PREFIX + "/user-auth-info"; String SAVE_USER = API_PREFIX + "/save-user"; + String UPDATE_USER = API_PREFIX + "/update-user"; String SAVE_IAM_USER = API_PREFIX + "/save-iam-user"; String REGISTER_USER = API_PREFIX + "/register-user"; String REMOVE_USER = API_PREFIX + "/remove-user"; @@ -150,6 +151,15 @@ public interface IUserClient { @PostMapping(SAVE_USER) R saveUser(@RequestBody User user); + /** + * 更新用户 + * + * @param user 用户实体 + * @return + */ + @PostMapping(UPDATE_USER) + R updateUser(@RequestBody User user); + /** * 新建IAM用户 * diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/feign/SysClient.java b/blade-service/blade-system/src/main/java/org/springblade/system/feign/SysClient.java index 789db31..49c8613 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/feign/SysClient.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/feign/SysClient.java @@ -167,6 +167,16 @@ public class SysClient implements ISysClient { return R.data(roleService.getRoleAliases(roleIds)); } + @Override + @GetMapping(ROLE_ID_BY_ALIAS) + public R getRoleIdByAlias(String tenantId, String roleAlias) { + Role role = roleService.getOne(Wrappers.lambdaQuery() + .eq(Role::getTenantId, tenantId) + .eq(Role::getRoleAlias, roleAlias) + .last("LIMIT 1")); + return R.data(role == null || role.getId() == null ? null : String.valueOf(role.getId())); + } + @Override @GetMapping(TENANT) public R getTenant(Long id) { diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/feign/UserClient.java b/blade-service/blade-system/src/main/java/org/springblade/system/feign/UserClient.java index df55138..12b97fd 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/feign/UserClient.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/feign/UserClient.java @@ -108,6 +108,12 @@ public class UserClient implements IUserClient { return R.data(service.submit(user)); } + @Override + @PostMapping(UPDATE_USER) + public R updateUser(@RequestBody User user) { + return R.data(service.updateUser(user)); + } + @Override @PostMapping(SAVE_IAM_USER) public R saveIamUser(@RequestBody User user) { diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/TransportReconciliationController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/TransportReconciliationController.java index b1f5b6b..2b5d777 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/TransportReconciliationController.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/TransportReconciliationController.java @@ -23,6 +23,7 @@ import org.springblade.core.excel.util.ExcelUtil; import org.springblade.transport.excel.CargoReconciliationExcel; import org.springblade.transport.excel.CargoReconciliationFeeReader; import org.springblade.transport.excel.CargoReconciliationFailureExcel; +import org.springblade.transport.excel.ReconciliationImportTemplateExcel; import org.springblade.transport.excel.VehicleReconciliationExcel; import org.springblade.transport.excel.VehicleReconciliationFeeReader; import org.springblade.transport.excel.VehicleReconciliationFailureExcel; @@ -154,9 +155,12 @@ public class TransportReconciliationController extends BladeController { @GetMapping("/template") @ApiOperationSupport(order = 8) @Operation(summary = "下载运输对账模板") - public void template(@RequestParam String mode, HttpServletResponse response) { - if ("cargo".equals(mode)) ExcelUtil.export(response, "货物明细对账模板", "货物明细对账模板", new ArrayList(), CargoReconciliationExcel.class); - else ExcelUtil.export(response, "整车总额对账模板", "整车总额对账模板", new ArrayList(), VehicleReconciliationExcel.class); + public void template(@RequestParam String mode, @RequestParam(required = false) Long id, + @RequestParam(required = false) Long formalSettlementId, @RequestParam(required = false) String feeItems, + HttpServletResponse response) { + List extraFeeItems = reconciliationService.templateFeeItems(id, formalSettlementId, feeItems); + if ("cargo".equals(mode)) ReconciliationImportTemplateExcel.exportCargo(response, extraFeeItems); + else ReconciliationImportTemplateExcel.exportVehicle(response, extraFeeItems); } @PostMapping("/match") diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/WaybillController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/WaybillController.java index f7ffb9c..36c761b 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/WaybillController.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/WaybillController.java @@ -131,8 +131,15 @@ public class WaybillController extends BladeController { return R.data(options); } - @GetMapping("/import-batch/list") + @GetMapping("/import-batch/next-code") @ApiOperationSupport(order = 4) + @Operation(summary = "下一个运单批次号") + public R importBatchNextCode() { + return R.data(waybillImportBatchService.nextBatchNo()); + } + + @GetMapping("/import-batch/list") + @ApiOperationSupport(order = 5) @Operation(summary = "运单批量导入批次分页") public R> importBatchList(WaybillImportBatchRequest request, Query query) { return R.data(waybillImportBatchService.page(Condition.getPage(query), request)); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/CargoReconciliationExcel.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/CargoReconciliationExcel.java index 25a6e20..235be05 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/CargoReconciliationExcel.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/CargoReconciliationExcel.java @@ -35,8 +35,8 @@ public class CargoReconciliationExcel implements Serializable { @ExcelProperty("运输单价") @NumberFormat("0.00") private BigDecimal unitPrice; @ExcelProperty("里程(KM)") @NumberFormat("0.00") private BigDecimal mileage; @ExcelProperty("运输费") @NumberFormat("0.00") private BigDecimal freightAmount; - @ExcelProperty("水费") @NumberFormat("0.00") private BigDecimal feeItemOne; - @ExcelProperty("罚款") @NumberFormat("0.00") private BigDecimal feeItemTwo; + @ExcelIgnore @NumberFormat("0.00") private BigDecimal feeItemOne; + @ExcelIgnore @NumberFormat("0.00") private BigDecimal feeItemTwo; @ExcelProperty("结算费用合计") @NumberFormat("0.00") private BigDecimal settlementAmount; @ExcelIgnore private Map feeItems; @ExcelIgnore private String errorMessage; diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/ProjectApplyExcel.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/ProjectApplyExcel.java index 25238f7..cf8bdaa 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/ProjectApplyExcel.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/ProjectApplyExcel.java @@ -86,10 +86,14 @@ public class ProjectApplyExcel implements Serializable { private String transportType; @ExcelProperty("业务类型") private String businessType; + @ExcelProperty("业务模式") + private String businessMode; @ExcelProperty("项目规模(万元)") private BigDecimal projectScale; @ExcelProperty("预计利润(万元)") private BigDecimal estimatedProfit; + @ExcelProperty("利润率(%)") + private BigDecimal profitRate; @ExcelProperty("资金需求(万元)") private BigDecimal fundDemand; @ExcelProperty("结算方式") diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/ReconciliationImportTemplateExcel.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/ReconciliationImportTemplateExcel.java new file mode 100644 index 0000000..9645b2d --- /dev/null +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/ReconciliationImportTemplateExcel.java @@ -0,0 +1,71 @@ +/** + * BladeX Commercial License Agreement + * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved. + *

Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.

+ *

Author: Chill Zhuang (bladejava@qq.com)

+ */ +package org.springblade.transport.excel; + +import cn.idev.excel.FastExcel; +import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import jakarta.servlet.http.HttpServletResponse; + +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +/** 运输对账导入模板导出。费用列按当前内部账单收费项动态生成。 */ +public final class ReconciliationImportTemplateExcel { + + private static final List VEHICLE_HEADERS = List.of( + "车牌号", "发货地址", "到货地址", "实际发货时间", "实际完成时间", "运输类型", + "货物名称", "货物类型", "运输总量", "里程(KM)", "批次号", "运输单价", "运输费" + ); + private static final List CARGO_HEADERS = List.of( + "车牌号", "发货地址", "到货地址", "实际发货时间", "实际完成时间", "货物名称", + "货物类型", "规格", "型号", "运输总量", "运输单价", "里程(KM)", "运输费" + ); + private static final String SETTLEMENT_AMOUNT = "结算费用合计"; + + private ReconciliationImportTemplateExcel() { + } + + public static void exportVehicle(HttpServletResponse response, List extraFeeItems) { + export(response, "整车总额对账模板", VEHICLE_HEADERS, extraFeeItems); + } + + public static void exportCargo(HttpServletResponse response, List extraFeeItems) { + export(response, "货物明细对账模板", CARGO_HEADERS, extraFeeItems); + } + + private static void export(HttpServletResponse response, String fileName, List baseHeaders, + List extraFeeItems) { + List> head = new ArrayList<>(); + for (String header : baseHeaders) { + head.add(List.of(header)); + } + if (extraFeeItems != null) { + for (String feeItem : extraFeeItems) { + if (feeItem != null && !feeItem.isBlank()) { + head.add(List.of(feeItem.trim())); + } + } + } + head.add(List.of(SETTLEMENT_AMOUNT)); + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding(StandardCharsets.UTF_8.name()); + response.setHeader("Content-disposition", + "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8) + ".xlsx"); + try { + FastExcel.write(response.getOutputStream()) + .head(head) + .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) + .sheet(fileName) + .doWrite(List.of()); + } catch (IOException exception) { + throw new IllegalStateException("导出" + fileName + "失败", exception); + } + } +} diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/TransportVehicleExcel.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/TransportVehicleExcel.java index 2bd98ee..ac5c02d 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/TransportVehicleExcel.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/TransportVehicleExcel.java @@ -59,6 +59,9 @@ public class TransportVehicleExcel implements Serializable { @ExcelProperty("所属组织 *") private String organizationName; + @ExcelProperty("使用部门") + private String useDepartment; + @ExcelProperty("业务关系 *") private String businessRelation; diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/VehicleReconciliationExcel.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/VehicleReconciliationExcel.java index f2d3266..9a214fa 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/VehicleReconciliationExcel.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/VehicleReconciliationExcel.java @@ -35,7 +35,7 @@ public class VehicleReconciliationExcel implements Serializable { @ExcelProperty("批次号") private String batchNo; @ExcelProperty("运输单价") @NumberFormat("0.00") private BigDecimal unitPrice; @ExcelProperty("运输费") @NumberFormat("0.00") private BigDecimal freightAmount; - @ExcelProperty("费用项目1") @NumberFormat("0.00") private BigDecimal feeItemOne; + @ExcelIgnore @NumberFormat("0.00") private BigDecimal feeItemOne; @ExcelProperty("结算费用合计") @NumberFormat("0.00") private BigDecimal settlementAmount; @ExcelIgnore private Map feeItems; @ExcelIgnore private String errorMessage; diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/DriverMapper.xml b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/DriverMapper.xml index da48c1d..45ad067 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/DriverMapper.xml +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/DriverMapper.xml @@ -40,6 +40,7 @@ + @@ -85,6 +86,7 @@ qualification_back, driver_type, mobile, + user_id, contact_relation, organization_name, emergency_contact_name, diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/TransportVehicleMapper.xml b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/TransportVehicleMapper.xml index 66e0907..c7411ab 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/TransportVehicleMapper.xml +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/TransportVehicleMapper.xml @@ -13,6 +13,7 @@ + @@ -60,6 +61,7 @@ status, is_deleted, organization_name, + use_department, plate_no, plate_color, vehicle_type, @@ -116,6 +118,10 @@ AND organization_name LIKE #{organizationNameLike} + + + AND use_department LIKE #{useDepartmentLike} + AND plate_no LIKE #{plateNoLike} diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/WaybillImportBatchMapper.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/WaybillImportBatchMapper.java index 5631be8..61724ea 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/WaybillImportBatchMapper.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/WaybillImportBatchMapper.java @@ -6,9 +6,20 @@ package org.springblade.transport.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; import org.springblade.transport.pojo.entity.WaybillImportBatch; /** 运单批次 Mapper。 */ @Mapper public interface WaybillImportBatchMapper extends BaseMapper { + + /** + * 查询指定租户、指定日期前缀下已使用的最大批次流水号。 + * 不过滤逻辑删除数据,避免唯一索引仍占用历史编号时重复生成。 + */ + @Select("SELECT COALESCE(MAX(CAST(SUBSTRING(batch_no, CHAR_LENGTH(#{prefix}) + 1) AS UNSIGNED)), 0) " + + "FROM blade_waybill_import_batch WHERE tenant_id = #{tenantId} " + + "AND batch_no LIKE CONCAT(#{prefix}, '%')") + Long selectMaxDailySequence(@Param("tenantId") String tenantId, @Param("prefix") String prefix); } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/ITransportReconciliationService.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/ITransportReconciliationService.java index 1dc23ff..dc196cd 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/ITransportReconciliationService.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/ITransportReconciliationService.java @@ -25,6 +25,7 @@ import java.util.List; public interface ITransportReconciliationService extends BaseService { IPage selectPage(IPage page, TransportReconciliationVO query); IPage formalOptions(IPage page, String settlementType, String keyword); + List templateFeeItems(Long id, Long formalSettlementId, String feeItems); TransportReconciliationVO detail(Long id); Long saveDraft(TransportReconciliationSaveRequest request); void removeDraft(Long id); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IWaybillImportBatchService.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IWaybillImportBatchService.java index 36ccb57..a06dcd4 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IWaybillImportBatchService.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IWaybillImportBatchService.java @@ -15,4 +15,5 @@ public interface IWaybillImportBatchService extends BaseService page(IPage page, WaybillImportBatchRequest request); BusinessRemoveResultVO removeBatches(String ids); + String nextBatchNo(); } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverServiceImpl.java index bf55063..ee887b7 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverServiceImpl.java @@ -27,13 +27,25 @@ package org.springblade.transport.service.impl; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.RequiredArgsConstructor; import org.springblade.core.log.exception.ServiceException; import org.springblade.core.mp.base.BaseServiceImpl; +import org.springblade.core.secure.utils.AuthUtil; +import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.BeanUtil; import org.springblade.core.tool.utils.Func; +import org.springblade.system.feign.ISysClient; +import org.springblade.system.feign.IUserClient; +import org.springblade.system.pojo.entity.User; +import org.springblade.system.pojo.entity.UserInfo; +import org.springblade.system.pojo.enums.UserSex; +import org.springblade.system.pojo.enums.UserType; import org.springblade.transport.excel.DriverExcel; import org.springblade.transport.mapper.DriverMapper; +import org.springblade.transport.mapper.TransportVehicleMapper; import org.springblade.transport.pojo.entity.Driver; +import org.springblade.transport.pojo.entity.TransportVehicle; import org.springblade.transport.pojo.vo.DriverExpiryStatVO; import org.springblade.transport.pojo.vo.DriverVO; import org.springblade.transport.service.IDriverService; @@ -50,6 +62,7 @@ import java.util.Objects; * @author Chill */ @Service +@RequiredArgsConstructor public class DriverServiceImpl extends BaseServiceImpl implements IDriverService { private static final int NAME_MAX_LENGTH = 10; @@ -62,6 +75,10 @@ public class DriverServiceImpl extends BaseServiceImpl imp private static final int DEFAULT_ENABLED_STATUS = 1; private static final int DEFAULT_FALSE = 0; + private final TransportVehicleMapper transportVehicleMapper; + private final IUserClient userClient; + private final ISysClient sysClient; + @Override public IPage selectDriverPage(IPage page, DriverVO driver) { prepareQuery(driver); @@ -74,7 +91,13 @@ public class DriverServiceImpl extends BaseServiceImpl imp prepare(driver); validate(driver); prepareSubmitTarget(driver); - return saveOrUpdate(driver); + // 编辑场景下字段无变化时 update 可能返回 false,不能据此跳过用户同步 + saveOrUpdate(driver); + if (Func.isEmpty(driver.getId())) { + throw new ServiceException("保存司机失败"); + } + syncDriverUser(driver); + return true; } @Override @@ -228,6 +251,14 @@ public class DriverServiceImpl extends BaseServiceImpl imp validateLength(driver.getMobile(), MOBILE_MAX_LENGTH, "手机号不能超过20字"); validateLength(driver.getEmergencyContactMobile(), MOBILE_MAX_LENGTH, "紧急联系人手机号不能超过20字"); validateLength(driver.getDrivingVehicle(), VEHICLE_NO_MAX_LENGTH, "驾驶车辆不能超过30字"); + if (Func.isNotEmpty(driver.getDrivingVehicle())) { + Long vehicleCount = transportVehicleMapper.selectCount(Wrappers.lambdaQuery() + .eq(TransportVehicle::getIsDeleted, 0) + .eq(TransportVehicle::getPlateNo, driver.getDrivingVehicle())); + if (vehicleCount == null || vehicleCount <= 0) { + throw new ServiceException("驾驶车辆不存在,请重新选择"); + } + } validateLength(driver.getDrivingLicenseNo(), SHORT_TEXT_MAX_LENGTH, "驾驶证档案编号不能超过50字"); validateLength(driver.getQualificationNo(), SHORT_TEXT_MAX_LENGTH, "资格证号不能超过50字"); validateLength(driver.getOrganizationName(), SHORT_TEXT_MAX_LENGTH, "所属组织不能超过50字"); @@ -273,6 +304,164 @@ public class DriverServiceImpl extends BaseServiceImpl imp } } + private void syncDriverUser(Driver driver) { + String tenantId = AuthUtil.getTenantId(); + if (Func.isEmpty(tenantId)) { + tenantId = driver.getTenantId(); + } + if (Func.isEmpty(tenantId)) { + throw new ServiceException("租户信息为空,无法同步系统用户"); + } + String mobile = driver.getMobile(); + if (Func.isEmpty(mobile) || mobile.length() < 6) { + throw new ServiceException("手机号长度不足,无法同步系统用户"); + } + // 编辑时前端可能不传 userId,从库中补齐已关联用户 + if (Func.isEmpty(driver.getUserId()) && Func.isNotEmpty(driver.getId())) { + Driver dbDriver = getById(driver.getId()); + if (dbDriver != null && Func.isNotEmpty(dbDriver.getUserId())) { + driver.setUserId(dbDriver.getUserId()); + } + } + + R roleResult = sysClient.getRoleIdByAlias(tenantId, "driver"); + if (roleResult == null || !R.isSuccess(roleResult) || Func.isEmpty(roleResult.getData())) { + throw new ServiceException("未配置角色别名为driver的角色,请先在系统角色中维护"); + } + String roleId = roleResult.getData(); + + R deptResult = sysClient.getDeptIds(tenantId, driver.getOrganizationName()); + if (deptResult == null || !R.isSuccess(deptResult) || Func.isEmpty(deptResult.getData())) { + throw new ServiceException("所属组织未匹配到系统部门,无法同步用户"); + } + String deptId = deptResult.getData(); + + User existing = findExistingUser(driver, tenantId, mobile); + if (existing == null || Func.isEmpty(existing.getId())) { + // 司机未关联有效用户时新建;密码为手机号后6位 + createAndLinkDriverUser(driver, tenantId, mobile, roleId, deptId); + } else { + updateAndLinkDriverUser(driver, existing, tenantId, mobile, roleId, deptId); + } + } + + private User findExistingUser(Driver driver, String tenantId, String mobile) { + if (Func.isNotEmpty(driver.getUserId())) { + R byId = userClient.userInfoById(driver.getUserId()); + if (byId != null && R.isSuccess(byId) && byId.getData() != null && Func.isNotEmpty(byId.getData().getId())) { + return byId.getData(); + } + // 关联的用户已不存在,清空后按手机号重建 + driver.setUserId(null); + } + return findExistingUserByAccountOrPhone(tenantId, mobile); + } + + private User findExistingUserByAccountOrPhone(String tenantId, String mobile) { + R byAccount = userClient.userByAccount(tenantId, mobile); + if (byAccount != null && R.isSuccess(byAccount) && byAccount.getData() != null + && Func.isNotEmpty(byAccount.getData().getId())) { + return byAccount.getData(); + } + R byPhone = userClient.userInfoByPhone(tenantId, mobile, UserType.WEB.getName()); + if (byPhone != null && R.isSuccess(byPhone) && byPhone.getData() != null + && byPhone.getData().getUser() != null && Func.isNotEmpty(byPhone.getData().getUser().getId())) { + return byPhone.getData().getUser(); + } + return null; + } + + private void createAndLinkDriverUser(Driver driver, String tenantId, String mobile, String roleId, String deptId) { + User user = buildSyncUser(null, tenantId, mobile, driver.getDriverName(), driver.getGender(), roleId, deptId); + user.setPassword(mobile.substring(mobile.length() - 6)); + user.setUserType(UserType.WEB.getCategory()); + + R saveResult = null; + try { + saveResult = userClient.saveUser(user); + } catch (Exception ex) { + User existed = findExistingUserByAccountOrPhone(tenantId, mobile); + if (existed != null) { + updateAndLinkDriverUser(driver, existed, tenantId, mobile, roleId, deptId); + return; + } + throw new ServiceException(Func.isNotEmpty(ex.getMessage()) ? ex.getMessage() : "同步系统用户失败"); + } + if (!isFeignSuccess(saveResult)) { + User existed = findExistingUserByAccountOrPhone(tenantId, mobile); + if (existed != null) { + updateAndLinkDriverUser(driver, existed, tenantId, mobile, roleId, deptId); + return; + } + throw new ServiceException(resolveFeignError(saveResult, "同步系统用户失败")); + } + + R created = userClient.userByAccount(tenantId, mobile); + User createdUser = (created != null && R.isSuccess(created)) ? created.getData() : null; + if (createdUser == null || Func.isEmpty(createdUser.getId())) { + createdUser = findExistingUserByAccountOrPhone(tenantId, mobile); + } + if (createdUser == null || Func.isEmpty(createdUser.getId())) { + throw new ServiceException("系统用户创建成功但无法回查用户ID"); + } + linkDriverUserId(driver, createdUser.getId()); + } + + private void updateAndLinkDriverUser(Driver driver, User existing, String tenantId, String mobile, String roleId, String deptId) { + User user = buildSyncUser(existing.getId(), tenantId, mobile, driver.getDriverName(), driver.getGender(), roleId, deptId); + R updateResult = userClient.updateUser(user); + // updateById 无字段变化时可能返回 false,但业务上仍视为成功,以接口 code 为准 + if (!isFeignSuccess(updateResult)) { + throw new ServiceException(resolveFeignError(updateResult, "同步更新系统用户失败")); + } + linkDriverUserId(driver, existing.getId()); + } + + private boolean isFeignSuccess(R result) { + return result != null && R.isSuccess(result); + } + + private String resolveFeignError(R result, String defaultMsg) { + if (result == null || Func.isEmpty(result.getMsg())) { + return defaultMsg; + } + String msg = result.getMsg().trim(); + // R.data(false) 也会带默认成功文案,不能当作业务错误抛出 + if ("操作成功".equals(msg) || "success".equalsIgnoreCase(msg)) { + return defaultMsg; + } + return msg; + } + + private User buildSyncUser(Long userId, String tenantId, String mobile, String driverName, String gender, + String roleId, String deptId) { + User user = new User(); + user.setId(userId); + user.setTenantId(tenantId); + user.setAccount(mobile); + user.setPhone(mobile); + user.setName(driverName); + user.setRealName(driverName); + user.setSex(UserSex.getCodeByName(gender)); + user.setRoleId(roleId); + user.setDeptId(deptId); + return user; + } + + private void linkDriverUserId(Driver driver, Long userId) { + if (Func.isEmpty(userId)) { + return; + } + if (Objects.equals(driver.getUserId(), userId)) { + return; + } + driver.setUserId(userId); + Driver patch = new Driver(); + patch.setId(driver.getId()); + patch.setUserId(userId); + updateById(patch); + } + private Long defaultZero(Long value) { return value == null ? 0L : value; } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ProjectApplyServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ProjectApplyServiceImpl.java index 9dbbd54..08802b5 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ProjectApplyServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ProjectApplyServiceImpl.java @@ -348,6 +348,7 @@ public class ProjectApplyServiceImpl extends BaseServiceImpl wrapper = Wrappers.lambdaQuery() - .eq(FormalSettlement::getApprovalStatus, "approved") + .eq(FormalSettlement::getApprovalStatus, FORMAL_DRAFT) .eq(Func.isNotEmpty(settlementType), FormalSettlement::getSettlementType, settlementType) .and(Func.isNotEmpty(keyword), value -> value.like(FormalSettlement::getFormalSettlementNo, keyword) .or().like(FormalSettlement::getContractNo, keyword).or().like(FormalSettlement::getContractName, keyword)); @@ -142,6 +144,60 @@ public class TransportReconciliationServiceImpl return formalSettlementMapper.selectPage(page, wrapper.orderByDesc(FormalSettlement::getCreateTime)); } + @Override + public List templateFeeItems(Long id, Long formalSettlementId, String feeItems) { + LinkedHashSet names = new LinkedHashSet<>(); + appendTemplateFeeItems(names, feeItems); + if (id != null) { + for (TransportReconciliationInternal row : internalRows(id)) { + parseFeeItems(row.getFeeItemsJson()).keySet().forEach(name -> appendTemplateFeeItem(names, name)); + } + TransportReconciliation bill = getById(id); + if (bill != null) collectFormalTemplateFeeItems(names, bill.getFormalSettlementId()); + } + collectFormalTemplateFeeItems(names, formalSettlementId); + return new ArrayList<>(names); + } + + private void appendTemplateFeeItems(Set names, String feeItems) { + if (Func.isEmpty(feeItems)) return; + for (String name : feeItems.split(",")) appendTemplateFeeItem(names, name); + } + + private void collectFormalTemplateFeeItems(Set names, Long formalSettlementId) { + if (formalSettlementId == null) return; + List summaries = formalSummaryFeeMapper.selectList( + Wrappers.lambdaQuery() + .eq(FormalSettlementSummaryFee::getFormalSettlementId, formalSettlementId) + .eq(FormalSettlementSummaryFee::getIsDeleted, 0) + .orderByAsc(FormalSettlementSummaryFee::getLineNo)); + for (FormalSettlementSummaryFee summary : summaries) { + appendTemplateFeeItem(names, summary.getFeeItem()); + } + List details = formalDetailMapper.selectList( + Wrappers.lambdaQuery() + .eq(FormalSettlementDetail::getFormalSettlementId, formalSettlementId) + .orderByAsc(FormalSettlementDetail::getLineNo)); + for (FormalSettlementDetail detail : details) { + parseFeeItems(detail.getFeeItemsJson()).keySet().forEach(name -> appendTemplateFeeItem(names, name)); + List fees = formalDetailFeeMapper.selectList( + Wrappers.lambdaQuery() + .eq(FormalSettlementDetailFee::getFormalSettlementDetailId, detail.getId()) + .eq(FormalSettlementDetailFee::getIsDeleted, 0) + .orderByAsc(FormalSettlementDetailFee::getLineNo)); + for (FormalSettlementDetailFee fee : fees) { + parseFeeItems(fee.getFeeItemsJson()).keySet().forEach(name -> appendTemplateFeeItem(names, name)); + } + } + } + + private void appendTemplateFeeItem(Set names, String name) { + if (Func.isEmpty(name)) return; + String trimmed = name.trim(); + if (trimmed.isEmpty() || isFreightFeeItem(trimmed) || "费用项目1".equals(trimmed)) return; + names.add(trimmed); + } + @Override public TransportReconciliationVO detail(Long id) { TransportReconciliationVO vo = TransportReconciliationWrapper.build().entityVO(existing(id)); @@ -166,7 +222,9 @@ public class TransportReconciliationServiceImpl throw new ServiceException("请选择正确的对账模式"); } FormalSettlement formal = formalSettlementMapper.selectById(request.getFormalSettlementId()); - if (formal == null || !"approved".equals(formal.getApprovalStatus())) throw new ServiceException("请选择已生效的正式结算单"); + if (formal == null || !FORMAL_DRAFT.equals(formal.getApprovalStatus())) { + throw new ServiceException("请选择草稿状态的正式结算单"); + } long occupied = count(Wrappers.lambdaQuery() .eq(TransportReconciliation::getFormalSettlementId, formal.getId()) .ne(request.getId() != null, TransportReconciliation::getId, request.getId())); @@ -394,9 +452,9 @@ public class TransportReconciliationServiceImpl external.setActualCompletionTime(parseTimeNullable(row.getActualCompletionTime(), "实际完成时间")); Map feeItems = row.getFeeItems(); if (feeItems == null || feeItems.isEmpty()) { - feeItems = new HashMap<>(); - feeItems.put("水费", money(row.getFeeItemOne())); - feeItems.put("罚款", money(row.getFeeItemTwo())); + feeItems = new LinkedHashMap<>(); + if (row.getFeeItemOne() != null) feeItems.put("水费", money(row.getFeeItemOne())); + if (row.getFeeItemTwo() != null) feeItems.put("罚款", money(row.getFeeItemTwo())); } external.setFeeItemsJson(JsonUtil.toJson(feeItems)); external.setMatchStatus(UNMATCHED); @@ -434,7 +492,7 @@ public class TransportReconciliationServiceImpl addImportDecimalErrors(validationErrors, row.getMileage(), "里程(KM)", 2); addImportDecimalErrors(validationErrors, row.getUnitPrice(), "运输单价", 2); addImportDecimalErrors(validationErrors, row.getFreightAmount(), "运输费", 2); - if (row.getFeeItems() != null) { + if (row.getFeeItems() != null && !row.getFeeItems().isEmpty()) { row.getFeeItems().forEach((name, value) -> addImportDecimalErrors(validationErrors, value, name, 2)); } else { addImportDecimalErrors(validationErrors, row.getFeeItemOne(), "水费", 2); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportVehicleServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportVehicleServiceImpl.java index 10d88ff..32462dc 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportVehicleServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportVehicleServiceImpl.java @@ -28,12 +28,15 @@ package org.springblade.transport.service.impl; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.RequiredArgsConstructor; import org.springblade.core.log.exception.ServiceException; import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.core.tool.utils.BeanUtil; import org.springblade.core.tool.utils.Func; import org.springblade.transport.excel.TransportVehicleExcel; +import org.springblade.transport.mapper.DriverMapper; import org.springblade.transport.mapper.TransportVehicleMapper; +import org.springblade.transport.pojo.entity.Driver; import org.springblade.transport.pojo.entity.TransportVehicle; import org.springblade.transport.pojo.vo.TransportVehicleExpiryStatVO; import org.springblade.transport.pojo.vo.TransportVehicleVO; @@ -42,9 +45,13 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; +import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.regex.Pattern; +import java.util.stream.Collectors; /** * 车辆管理 服务实现类 @@ -52,9 +59,13 @@ import java.util.regex.Pattern; * @author Chill */ @Service +@RequiredArgsConstructor public class TransportVehicleServiceImpl extends BaseServiceImpl implements ITransportVehicleService { private static final Pattern PLATE_NO_PATTERN = Pattern.compile("^[\\u4e00-\\u9fa5][A-Z][A-Z0-9挂学警港澳]{5,6}$"); + private static final String PLATE_COLOR_BLUE = "蓝牌"; + private static final String PLATE_COLOR_YELLOW = "黄牌"; + private static final String PLATE_COLOR_GREEN = "绿牌"; private static final int SHORT_TEXT_MAX_LENGTH = 50; private static final int ORG_MAX_LENGTH = 50; private static final int REMARK_MAX_LENGTH = 200; @@ -64,10 +75,55 @@ public class TransportVehicleServiceImpl extends BaseServiceImpl selectTransportVehiclePage(IPage page, TransportVehicleVO vehicle) { prepareQuery(vehicle); - return page.setRecords(baseMapper.selectTransportVehiclePage(page, vehicle)); + List records = baseMapper.selectTransportVehiclePage(page, vehicle); + fillBoundDrivers(records); + return page.setRecords(records); + } + + /** + * 按车牌反查司机驾驶车辆,填充车辆列表「绑定司机」。 + */ + private void fillBoundDrivers(List records) { + if (Func.isEmpty(records)) { + return; + } + List plateNos = records.stream() + .map(TransportVehicleVO::getPlateNo) + .filter(Func::isNotEmpty) + .map(String::toUpperCase) + .distinct() + .toList(); + if (plateNos.isEmpty()) { + return; + } + List drivers = driverMapper.selectList(Wrappers.lambdaQuery() + .eq(Driver::getIsDeleted, 0) + .in(Driver::getDrivingVehicle, plateNos) + .select(Driver::getDriverName, Driver::getDrivingVehicle)); + Map> namesByPlate = new LinkedHashMap<>(); + for (Driver driver : drivers) { + if (Func.isEmpty(driver.getDrivingVehicle()) || Func.isEmpty(driver.getDriverName())) { + continue; + } + namesByPlate + .computeIfAbsent(driver.getDrivingVehicle().toUpperCase(), key -> new ArrayList<>()) + .add(driver.getDriverName()); + } + for (TransportVehicleVO record : records) { + if (Func.isEmpty(record.getPlateNo())) { + continue; + } + List names = namesByPlate.get(record.getPlateNo().toUpperCase()); + if (Func.isEmpty(names)) { + continue; + } + record.setBoundDriver(names.stream().distinct().collect(Collectors.joining("、"))); + } } @Override @@ -148,8 +204,10 @@ public class TransportVehicleServiceImpl extends BaseServiceImpllambdaQuery().likeRight(WaybillImportBatch::getBatchNo, prefix)); - return prefix + String.format("%04d", count + 1); + String prefix = "PC" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE); + Long maxSequence = baseMapper.selectMaxDailySequence(AuthUtil.getTenantId(), prefix); + return prefix + String.format("%04d", (maxSequence == null ? 0 : maxSequence) + 1); } /** diff --git a/doc/sql/transport/blade_project_apply_business_mode_profit_rate_20260910.sql b/doc/sql/transport/blade_project_apply_business_mode_profit_rate_20260910.sql new file mode 100644 index 0000000..eee711b --- /dev/null +++ b/doc/sql/transport/blade_project_apply_business_mode_profit_rate_20260910.sql @@ -0,0 +1,4 @@ +-- 项目立项增加业务模式、利润率 +ALTER TABLE `blade_project_apply` + ADD COLUMN `business_mode` varchar(50) DEFAULT NULL COMMENT '业务模式' AFTER `business_type`, + ADD COLUMN `profit_rate` decimal(18,2) DEFAULT NULL COMMENT '利润率(%)' AFTER `estimated_profit`; diff --git a/doc/sql/transport/blade_project_contract_management.sql b/doc/sql/transport/blade_project_contract_management.sql index 2f2d194..07920d2 100644 --- a/doc/sql/transport/blade_project_contract_management.sql +++ b/doc/sql/transport/blade_project_contract_management.sql @@ -33,8 +33,10 @@ CREATE TABLE `blade_project_apply` ( `transport_route` varchar(200) DEFAULT NULL COMMENT '运输线路', `transport_type` varchar(100) DEFAULT NULL COMMENT '运输类型', `business_type` varchar(100) DEFAULT NULL COMMENT '业务类型', + `business_mode` varchar(50) DEFAULT NULL COMMENT '业务模式', `project_scale` decimal(18,2) DEFAULT NULL COMMENT '项目规模(万元)', `estimated_profit` decimal(18,2) DEFAULT NULL COMMENT '预计利润(万元)', + `profit_rate` decimal(18,2) DEFAULT NULL COMMENT '利润率(%)', `fund_demand` decimal(18,2) DEFAULT NULL COMMENT '资金需求(万元)', `settlement_mode` varchar(100) DEFAULT NULL COMMENT '结算方式', `handler_user_id` bigint(20) DEFAULT NULL COMMENT '项目经办人ID', diff --git a/doc/sql/transport/blade_transport_driver.sql b/doc/sql/transport/blade_transport_driver.sql index 0b426a5..57ccd4f 100644 --- a/doc/sql/transport/blade_transport_driver.sql +++ b/doc/sql/transport/blade_transport_driver.sql @@ -33,6 +33,7 @@ CREATE TABLE `blade_transport_driver` ( `qualification_back` varchar(1000) DEFAULT NULL COMMENT '从业资格证内容页', `driver_type` varchar(20) NOT NULL COMMENT '司机类型:自有/外协', `mobile` varchar(20) NOT NULL COMMENT '手机号', + `user_id` bigint(20) DEFAULT NULL COMMENT '关联系统用户ID', `contact_relation` varchar(20) DEFAULT NULL COMMENT '与联系人关系', `organization_name` varchar(50) NOT NULL COMMENT '所属组织', `emergency_contact_name` varchar(20) NOT NULL COMMENT '紧急联系人姓名', diff --git a/doc/sql/transport/blade_transport_driver_role_alias_note.sql b/doc/sql/transport/blade_transport_driver_role_alias_note.sql new file mode 100644 index 0000000..31bf863 --- /dev/null +++ b/doc/sql/transport/blade_transport_driver_role_alias_note.sql @@ -0,0 +1,6 @@ +-- 司机同步系统用户依赖角色别名 role_alias = 'driver' +-- 请在系统管理 -> 角色管理中为对应租户新增/维护角色,并设置角色别名为 driver +-- 参考 blade_role 表结构:id, tenant_id, parent_id, role_name, sort, role_alias, status, is_deleted +-- 示例(请按实际租户与主键策略自行调整,勿直接照抄执行): +-- INSERT INTO blade_role (id, tenant_id, parent_id, role_name, sort, role_alias, status, is_deleted) +-- VALUES (你的雪花ID, '你的租户ID', 0, '司机', 10, 'driver', 1, 0); diff --git a/doc/sql/transport/blade_transport_driver_user_id_20260910.sql b/doc/sql/transport/blade_transport_driver_user_id_20260910.sql new file mode 100644 index 0000000..5d85fee --- /dev/null +++ b/doc/sql/transport/blade_transport_driver_user_id_20260910.sql @@ -0,0 +1,3 @@ +-- 司机表增加关联系统用户ID +ALTER TABLE `blade_transport_driver` + ADD COLUMN `user_id` bigint(20) DEFAULT NULL COMMENT '关联系统用户ID' AFTER `mobile`; diff --git a/doc/sql/transport/blade_transport_vehicle.sql b/doc/sql/transport/blade_transport_vehicle.sql index b884f22..a5260fb 100644 --- a/doc/sql/transport/blade_transport_vehicle.sql +++ b/doc/sql/transport/blade_transport_vehicle.sql @@ -6,6 +6,7 @@ CREATE TABLE `blade_transport_vehicle` ( `id` bigint(20) NOT NULL COMMENT '主键', `tenant_id` varchar(12) DEFAULT '000000' COMMENT '租户ID', `organization_name` varchar(50) NOT NULL COMMENT '所属组织', + `use_department` varchar(50) DEFAULT NULL COMMENT '使用部门', `plate_no` varchar(16) NOT NULL COMMENT '车牌号', `plate_color` varchar(20) DEFAULT NULL COMMENT '车牌颜色', `vehicle_type` varchar(50) NOT NULL COMMENT '车辆类型', diff --git a/doc/sql/transport/blade_transport_vehicle_use_department_20260910.sql b/doc/sql/transport/blade_transport_vehicle_use_department_20260910.sql new file mode 100644 index 0000000..c0dabca --- /dev/null +++ b/doc/sql/transport/blade_transport_vehicle_use_department_20260910.sql @@ -0,0 +1,3 @@ +-- 车辆表增加使用部门 +ALTER TABLE `blade_transport_vehicle` + ADD COLUMN `use_department` varchar(50) DEFAULT NULL COMMENT '使用部门' AFTER `organization_name`;