Merge branch 'master' into feature/20261103-bfi-warehouse-material

# Conflicts:
#	blade-service/blade-transport/src/main/java/org/springblade/transport/support/KingdeeReceivedInvoiceSyncSupport.java
#	doc/docs/业务流程/2026-10-17-结算调整单操作流程说明(分场景).md
#	doc/sql/transport/lqj/20261102/06_blade_invoice_receipt_supplier_code_menu_20261031.sql
#	doc/sql/transport/lqj/20261102/19_blade_dict_fee_category_warehouse_20261103.sql
This commit is contained in:
刘泉佳
2026-11-04 17:27:58 +08:00
202 changed files with 9266 additions and 1150 deletions
@@ -65,6 +65,7 @@ public class SysCache {
private static final String ROLE_NAMES_ID = "roleNames:id:";
private static final String ROLE_ALIAS_ID = "roleAlias:id:";
private static final String ROLE_ALIASES_ID = "roleAliases:id:";
private static final String BUSINESS_DEPT_CONFIG = "businessDeptConfig:platformDept:";
public static final String TENANT_ID = "tenant:id:";
public static final String TENANT_TENANT_ID = "tenant:tenantId:";
public static final String TENANT_PACKAGE_ID = "tenant:packageId:";
@@ -381,4 +382,21 @@ public class SysCache {
}, Boolean.FALSE);
}
/**
* 按平台公司 + 业务部门获取业务部门配置
*
* @param platformCompanyId 平台公司ID
* @param businessDeptId 业务部门ID
* @return 业务部门配置
*/
public static BusinessDeptConfig getBusinessDeptConfig(Long platformCompanyId, Long businessDeptId) {
if (platformCompanyId == null || businessDeptId == null) {
return null;
}
return CacheUtil.get(SYS_CACHE, BUSINESS_DEPT_CONFIG, platformCompanyId + StringPool.DASH + businessDeptId, () -> {
R<BusinessDeptConfig> result = getSysClient().getBusinessDeptConfig(platformCompanyId, businessDeptId);
return result.getData();
});
}
}
@@ -76,6 +76,7 @@ public interface ISysClient {
String MEASUREMENT_UNITS = API_PREFIX + "/measurement-units";
String PERMISSIONS = API_PREFIX + "/permissions";
String INVOICE_ITEMS = API_PREFIX + "/invoice-items";
String BUSINESS_DEPT_CONFIG = API_PREFIX + "/business-dept-config";
/**
* 获取菜单
@@ -345,4 +346,15 @@ public interface ISysClient {
@GetMapping(INVOICE_ITEMS)
R<List<InvoiceItem>> getInvoiceItems();
/**
* 按平台公司 + 业务部门获取业务部门配置
*
* @param platformCompanyId 平台公司ID
* @param businessDeptId 业务部门ID
* @return 业务部门配置
*/
@GetMapping(BUSINESS_DEPT_CONFIG)
R<BusinessDeptConfig> getBusinessDeptConfig(@RequestParam("platformCompanyId") Long platformCompanyId,
@RequestParam("businessDeptId") Long businessDeptId);
}
@@ -189,4 +189,9 @@ public class ISysClientFallback implements ISysClient {
return R.fail("获取数据失败");
}
@Override
public R<BusinessDeptConfig> getBusinessDeptConfig(Long platformCompanyId, Long businessDeptId) {
return R.fail("获取数据失败");
}
}
@@ -0,0 +1,87 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.system.pojo.entity;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springblade.core.tenant.mp.TenantEntity;
import java.io.Serial;
/**
* 业务部门配置实体类
*
* @author Chill
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("blade_business_dept_config")
@Schema(description = "业务部门配置")
public class BusinessDeptConfig extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "平台公司ID")
private Long platformCompanyId;
@Schema(description = "平台公司名称")
private String platformCompanyName;
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "业务部门ID")
private Long businessDeptId;
@Schema(description = "业务部门名称")
private String businessDeptName;
@Schema(description = "合同编码前缀")
private String contractCodePrefix;
@Schema(description = "初始流水号")
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private Integer initialSerial;
@Schema(description = "金蝶公司代码")
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String kingdeeCompanyCode;
@Schema(description = "金蝶部门代码")
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String kingdeeDeptCode;
@Schema(description = "备注")
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String remark;
}
@@ -203,14 +203,18 @@ public class Dept extends TenantEntity {
/**
* 是否平台公司:0否,1是
* ALWAYS:保证「否(0)」也能更新落库,避免被字段策略跳过
*/
@Schema(description = "是否平台公司:0否,1是")
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private Integer isPlatformCompany;
/**
* 是否业务部门:0否,1是
* ALWAYS:保证「否(0)」也能更新落库,避免被字段策略跳过
*/
@Schema(description = "是否业务部门:0否,1是")
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private Integer isBusinessDept;
/**
@@ -0,0 +1,57 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.system.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.system.pojo.entity.BusinessDeptConfig;
import java.io.Serial;
/**
* 业务部门配置视图实体类
*
* @author Chill
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Schema(description = "业务部门配置")
public class BusinessDeptConfigVO extends BusinessDeptConfig {
@Serial
private static final long serialVersionUID = 1L;
@TableField(exist = false)
@Schema(description = "创建人姓名")
private String createUserName;
@TableField(exist = false)
@Schema(description = "更新人姓名")
private String updateUserName;
}
@@ -67,6 +67,18 @@ public class RoleDataScopeVO implements Serializable {
return scope;
}
/**
* 无组织可见(未配置数据权限时的默认结果)
*/
public static RoleDataScopeVO none() {
RoleDataScopeVO scope = new RoleDataScopeVO();
scope.setScopeType(RoleDataScopeType.CUSTOM.getCode());
scope.setAllDept(false);
scope.setOwnCreate(false);
scope.setDeptIds(Collections.emptyList());
return scope;
}
public static RoleDataScopeVO ownCreate() {
RoleDataScopeVO scope = new RoleDataScopeVO();
scope.setScopeType(RoleDataScopeType.OWN_CREATE.getCode());
@@ -0,0 +1,62 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 管理端认证审核请求
* <p>
* 同一字段 body 与 query 都可传,两处都给时以 body 为准。
*
* @author Chill
*/
@Data
@Schema(description = "管理端认证审核请求")
public class CertAuditRequest implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "认证记录主键")
private Long id;
@Schema(description = "true 通过,false 驳回")
private Boolean pass;
@Schema(description = "驳回原因;驳回时必填,≤200 字")
private String rejectReason;
/**
* 审核员修订后的全量认证内容(JSON);空或空白表示不修订
* <p>
* 通过时才生效:它既是写回档案的依据,也会原样留痕到认证记录上。
*/
@Schema(description = "审核员修订后的全量认证内容JSON;空表示不修订")
private String auditedSnapshotJson;
}
@@ -0,0 +1,90 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.pojo.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 异常处置 → 录入维修记录请求
* <p>
* 车牌号与车船类型不接收前端传值:车牌取自异常处置,车船类型固定「车辆」,
* 避免维修记录挂到与异常无关的车上。
*
* @author Chill
*/
@Data
@Schema(description = "异常处置录入维修记录请求")
public class ExceptionMaintenanceRecordRequest implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "异常处置ID")
private Long id;
@Schema(description = "维修时间")
private LocalDateTime maintenanceTime;
@Schema(description = "维修位置")
private String location;
@Schema(description = "维修人")
private String maintainer;
@Schema(description = "维修单位")
private String company;
@Schema(description = "联系方式")
private String contact;
@Schema(description = "更换零件")
private String replacedPart;
@Schema(description = "费用")
private BigDecimal cost;
@Schema(description = "里程数(公里)")
private BigDecimal mileage;
@Schema(description = "出厂时间")
private LocalDateTime factoryTime;
@Schema(description = "详细地址")
private String address;
@Schema(description = "备注说明")
private String remark;
@Schema(description = "附件JSON,[{\"name\":\"...\",\"url\":\"...\"}]")
private String attachments;
}
@@ -103,6 +103,18 @@ public class ContractChange extends TenantEntity {
@Schema(description = "乙方")
private String partyB;
@Schema(description = "甲方客商明细JSON")
private String partyAJson;
@Schema(description = "乙方客商明细JSON")
private String partyBJson;
@Schema(description = "丙方客商明细JSON")
private String partyCJson;
@Schema(description = "丙方")
private String partyC;
@Schema(description = "开始日期")
private LocalDate startDate;
@@ -67,6 +67,12 @@ public class ContractManage extends TenantEntity {
@Schema(description = "合同负责部门")
private String organizationName;
@Schema(description = "平台公司ID")
private Long platformCompanyId;
@Schema(description = "平台公司")
private String platformCompanyName;
@Schema(description = "合同类别")
private String contractCategory;
@@ -79,6 +85,18 @@ public class ContractManage extends TenantEntity {
@Schema(description = "乙方")
private String partyB;
@Schema(description = "甲方客商明细JSON")
private String partyAJson;
@Schema(description = "乙方客商明细JSON")
private String partyBJson;
@Schema(description = "丙方客商明细JSON")
private String partyCJson;
@Schema(description = "丙方")
private String partyC;
@Schema(description = "开始日期")
private LocalDate startDate;
@@ -164,6 +164,14 @@ public class FormalSettlement extends TenantEntity {
* 金蝶推送失败原因(仅 failed 态展示;重推成功转 synced 后残留原因不再回显)
*/
private String kingdeeFailReason;
/**
* 金蝶冲销状态:unwrittenoff-未冲销 writtenoff-已冲销(null=未推送金蝶或未校验)
*/
private String kingdeeWriteOffStatus;
/**
* 金蝶冲销状态确认时间(定时回写/预检回写时间)
*/
private LocalDateTime kingdeeWriteOffTime;
/**
* 附件JSON
*/
@@ -68,6 +68,9 @@ public class LoadingManage extends TenantEntity {
@Schema(description = "联系电话")
private String driverPhone;
@Schema(description = "司机ID")
private Long driverId;
@Schema(description = "押运人")
private String escortName;
@@ -83,6 +86,12 @@ public class LoadingManage extends TenantEntity {
@Schema(description = "承运商合同ID")
private Long carrierContractId;
@Schema(description = "承运客商明细行ID")
private String carrierPartyId;
@Schema(description = "承运客商角色:B/C")
private String carrierPartyRole;
@Schema(description = "发货地址")
private String departureAddress;
@@ -61,6 +61,12 @@ public class MaintenanceRecord extends TenantEntity {
*/
@Schema(description = "车牌号/船号")
private String vehicleNo;
/**
* 关联异常处置ID(小程序录入时写入)
*/
@Schema(description = "关联异常处置ID(小程序录入时写入)")
@TableField(updateStrategy = FieldStrategy.NEVER)
private Long exceptionId;
/**
* 维修人
*/
@@ -28,6 +28,7 @@ package org.springblade.transport.pojo.entity;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -125,6 +126,19 @@ public class TransportCertRecord extends TenantEntity {
@TableField(updateStrategy = FieldStrategy.NEVER)
@Schema(description = "该次提交的全量认证内容JSON")
private String snapshotJson;
/**
* 审核通过时确定的修订版内容(JSON)
* <p>
* 审核员可以在通过时直接改内容:司机提交的是 {@code snapshotJson}(永不可改),
* 最终写回档案、司机端读到的「当前生效内容」以本字段优先,为 null 才回退到
* {@code snapshotJson}。为 null 即「审核员没有修订」。
* <p>
* {@code @JsonIgnore}:司机端的 {@code TransportCertRecordVO} 继承本实体,
* 修订版是审核过程的留痕,不该下发给司机。
*/
@JsonIgnore
@Schema(description = "审核通过时确定的修订版内容JSON;null 表示未修订")
private String auditedSnapshotJson;
/**
* 驳回原因,仅当审核状态为已驳回时有值
*/
@@ -136,6 +136,12 @@ public class Waybill extends TenantEntity {
@Schema(description = "承运商合同ID")
private Long carrierContractId;
@Schema(description = "承运客商明细行ID")
private String carrierPartyId;
@Schema(description = "承运客商角色:B/C")
private String carrierPartyRole;
@Schema(description = "司机ID")
private Long driverId;
@@ -38,7 +38,7 @@ public class AdminHomeBadgesVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "异常处置待办数(disposalStatus≠completed)")
@Schema(description = "异常处置待办数(disposalStatus=pending)")
private long exception;
@Schema(description = "风险记录待办数(disposalStatus=pending)")
@@ -0,0 +1,47 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.pojo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 调度端档案统计(司机 + 车辆证件有效期)
*/
@Data
@Schema(description = "调度端档案统计")
public class ArchiveManageStatsVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "司机证件有效期统计")
private DriverExpiryStatVO driver = new DriverExpiryStatVO();
@Schema(description = "车辆证件有效期统计")
private TransportVehicleExpiryStatVO vehicle = new TransportVehicleExpiryStatVO();
}
@@ -0,0 +1,54 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.pojo.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 营业执照 OCR 识别结果。
*
* @author Chill
*/
@Data
@Schema(description = "营业执照OCR识别结果")
public class BusinessLicenseOcrVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 按第三方返回 key 聚合的字段,例如 uscc、company_name、legal_name。
*/
@Schema(description = "识别字段,键为第三方 OCR 的 key")
private Map<String, String> fields = new LinkedHashMap<>();
}
@@ -81,6 +81,13 @@ public class CertAuditDetailVO implements Serializable {
@Schema(description = "待审快照:本次提交的全量内容")
private String pendingSnapshotJson;
/**
* 审核员在本次审核中填写的修订版内容;未修订时为 null
* <p>
* 只在「通过」时才会落库,驳回不产生生效内容。审核页据此回显审核员改了什么。
*/
@Schema(description = "本次审核提交的修订版内容;未修订时为 null")
private String auditedSnapshotJson;
@Schema(description = "生效快照:该对象当前生效的全量内容;从未认证通过时为 null")
private String effectiveSnapshotJson;
@Schema(description = "生效快照记录ID;null 表示该对象从未认证通过")
@@ -64,9 +64,13 @@ public class ContractManageVO extends ContractManage {
private Boolean hcsSynced;
@TableField(exist = false)
@Schema(description = "生效类型筛选")
@Schema(description = "合同状态筛选")
private String effectiveType;
@TableField(exist = false)
@Schema(description = "客商(匹配甲/乙/丙方)")
private String partyName;
@TableField(exist = false)
@Schema(description = "创建人姓名")
private String createUserName;
@@ -48,6 +48,12 @@ public class DriverVO extends Driver {
@Serial
private static final long serialVersionUID = 1L;
/**
* 搜索关键字:同时模糊匹配姓名与手机号(小程序列表用,管理端不传)
*/
@TableField(exist = false)
@Schema(description = "搜索关键字(姓名 / 手机号)")
private String keyword;
/**
* 证件有效期状态:within30-30天内到期,expired-已到期
*/
@@ -106,6 +106,10 @@ public class ExceptionDisposalVO extends ExceptionDisposal {
@Schema(description = "可调整的路线站点,少于两个站时为空")
private List<RouteNode> routeNodes;
@TableField(exist = false)
@Schema(description = "关联的维修记录(车辆故障维修异常录入,未录入时为空对象,判定须看 id)")
private MaintenanceRecordVO maintenanceRecord;
/**
* 一个可调整的站点:站序声明、地址、该站的装卸标记与项目名
*/
@@ -55,4 +55,17 @@ public class LoadingCarrierContractVO implements Serializable {
@Schema(description = "承运商名称")
private String carrierName;
@Schema(description = "承运客商明细行ID")
private String carrierPartyId;
@Schema(description = "承运客商角色:B/C")
private String carrierPartyRole;
@Schema(description = "统一信用代码")
private String creditCode;
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "客商档案ID")
private Long customerId;
}
@@ -76,4 +76,25 @@ public class MaintenanceRecordVO extends MaintenanceRecord {
@Schema(description = "更新人姓名")
private String updateUserName;
/**
* 关联运单号(由 exception_id 关联异常处置带出)
*/
@TableField(exist = false)
@Schema(description = "关联运单号")
private String waybillNo;
/**
* 关联异常类型(一级)
*/
@TableField(exist = false)
@Schema(description = "关联异常类型")
private String exceptionType;
/**
* 关联异常原因(二级)
*/
@TableField(exist = false)
@Schema(description = "关联异常原因")
private String exceptionReason;
}
@@ -34,4 +34,17 @@ public class MasterOrderCarrierVO implements Serializable {
@Schema(description = "承运商名称")
private String carrierName;
@Schema(description = "承运客商明细行ID")
private String carrierPartyId;
@Schema(description = "承运客商角色:B/C")
private String carrierPartyRole;
@Schema(description = "统一信用代码")
private String creditCode;
@JsonSerialize(using = ToStringSerializer.class)
@Schema(description = "客商档案ID")
private Long customerId;
}
@@ -96,5 +96,13 @@ public class TransportCertRecordVO extends TransportCertRecord {
@TableField(exist = false)
@Schema(description = "司机手机号")
private String driverMobile;
/**
* 该条记录是否经过审核员修订
* <p>
* 由服务层按 {@code auditedSnapshotJson} 是否有内容算出,前端据此打「已修订」标记。
*/
@TableField(exist = false)
@Schema(description = "是否经过审核员修订")
private Boolean revised;
}
@@ -48,6 +48,12 @@ public class TransportVehicleVO extends TransportVehicle {
@Serial
private static final long serialVersionUID = 1L;
/**
* 搜索关键字:同时模糊匹配车牌、VIN 与所有人(小程序列表用,管理端不传)
*/
@TableField(exist = false)
@Schema(description = "搜索关键字(车牌 / VIN / 所有人)")
private String keyword;
/**
* 证件有效期状态:within30-30天内到期,expired-已到期
*/
@@ -34,8 +34,10 @@ import java.util.Set;
/**
* 运次查询条件
* <p>
* 司机端用 {@link #forDriver(String)} 按司机手机号收口;管理端用 {@link #forAdmin()} 不按司机收口。
* 两者都不给时收口为空集——收口一旦缺省就等于把别人的运次发出去,故缺省不放行。
* 司机端用 {@link #forDriver(Long)} 按司机档案 ID 收口;管理端用 {@link #forAdmin()} 不按司机收口。
* 两者都不给时收口为空集。
* <p>
* 归属判据只有司机档案 ID;driver_phone 是派单时的号码快照,不参与判定。
*/
@Data
@Schema(description = "运次查询条件")
@@ -47,8 +49,8 @@ public class TripQueryVO implements Serializable {
@Schema(description = "运次主键(详情按它取单个运次)")
private String tripId;
@Schema(description = "司机手机号")
private String driverPhone;
@Schema(description = "司机档案 ID(司机端收口判据,空或非正数一律不放行)")
private Long driverId;
@Schema(description = "是否不按司机收口(管理端)")
private boolean allDrivers;
@@ -92,9 +94,9 @@ public class TripQueryVO implements Serializable {
@Schema(description = "每页条数(按运次,不是运单)")
private Integer size;
public static TripQueryVO forDriver(String driverPhone) {
public static TripQueryVO forDriver(Long driverId) {
TripQueryVO query = new TripQueryVO();
query.setDriverPhone(driverPhone);
query.setDriverId(driverId);
return query;
}
@@ -35,6 +35,9 @@ import org.springblade.core.tool.utils.StringUtil;
import org.springblade.system.pojo.entity.User;
import org.springblade.system.feign.IUserClient;
import java.util.Collections;
import java.util.List;
import static org.springblade.core.cache.constant.CacheConstant.USER_CACHE;
import static org.springblade.core.launch.constant.FlowConstant.TASK_USR_PREFIX;
@@ -47,6 +50,7 @@ import static org.springblade.core.launch.constant.FlowConstant.TASK_USR_PREFIX;
public class UserCache {
private static final String USER_CACHE_ID = "user:id:";
private static final String USER_CACHE_ACCOUNT = "user:account:";
private static final String USER_CACHE_MANAGE_DEPT = "user:manage-dept:";
private static IUserClient userClient;
@@ -89,6 +93,26 @@ public class UserCache {
}
}
/**
* 获取用户「数据管理权限」组织(含下级展开)
*
* @param userId 用户主键
* @return 可管理组织 ID 集合
*/
@SuppressWarnings("unchecked")
public static List<Long> getManageDeptIds(Long userId) {
if (userId == null || userId <= 0) {
return Collections.emptyList();
}
try {
List<Long> deptIdList = CacheUtil.get(USER_CACHE, USER_CACHE_MANAGE_DEPT, userId, () -> loadManageDeptIds(userId));
return deptIdList == null ? Collections.emptyList() : deptIdList;
} catch (RuntimeException exception) {
log.warn("用户数据管理组织缓存读取失败,改为直连查询, userId={}", userId, exception);
return loadManageDeptIds(userId);
}
}
/**
* 获取用户姓名
*
@@ -153,6 +177,14 @@ public class UserCache {
return result.getData();
}
private static List<Long> loadManageDeptIds(Long userId) {
R<List<Long>> result = getUserClient().manageDeptIds(userId);
if (result == null || !result.isSuccess() || result.getData() == null) {
return Collections.emptyList();
}
return result.getData();
}
private static void clearBrokenUserCache() {
CacheUtil.clear(USER_CACHE);
CacheUtil.clear(USER_CACHE, Boolean.FALSE);
@@ -37,6 +37,8 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/**
* User Feign接口类
*
@@ -62,6 +64,7 @@ public interface IUserClient {
String REGISTER_USER = API_PREFIX + "/register-user";
String REMOVE_USER = API_PREFIX + "/remove-user";
String BIND_WX_MINI_OPENID = API_PREFIX + "/bind-wx-mini-openid";
String MANAGE_DEPT_IDS = API_PREFIX + "/manage-dept-ids";
/**
* 获取用户信息
@@ -72,6 +75,15 @@ public interface IUserClient {
@GetMapping(USER_BY_ID)
R<User> userInfoById(@RequestParam("userId") Long userId);
/**
* 解析用户「数据管理权限」组织(含下级)
*
* @param userId 用户主键
* @return 可管理组织 ID 集合
*/
@GetMapping(MANAGE_DEPT_IDS)
R<List<Long>> manageDeptIds(@RequestParam("userId") Long userId);
/**
* 根据账号获取用户信息