liu
2026-10-27 17ce55a3b038ed61d332bb54916de4fa55ba19c6
fix: 修复导出表头缺失、权限码不一致及生产链路断点

一、导入导出
- 12 个导出 VO 补齐 @ExcelIgnoreUnannotated + @ExcelProperty 中文表头
(杂项出库/入库、领料、退料、销售退货、供应商退货、调拨、生产任务、
请假/离职/调动审批、SRM 供应商),避免导出文件表头为英文字段名并泄露内部 ID
- HRM 考勤与薪酬导出权限改用 hasAnyPermissions,兼容菜单中两套权限码
- 用户导入、员工导入支持「初始密码」列:填写则使用填写值,
未填写则读取系统参数 system.user.init-password,均无时明确报错

二、业务流程
- 修复 MPS 合并下发后 getMpsByWorkOrderId 使用 selectOne 抛
TooManyResultsException 导致报工无法完工的问题,改为 LIMIT 1
- 合同生成销售订单明细默认 needProduction=1,打通「合同→订单→MPS」链路

三、配套
- AdminUserApi 新增 updateUserPassword,供员工编辑时同步修改登录密码
- 新增 EMPLOYEE_INIT_PASSWORD_NOT_CONFIGURED 精确错误提示

Co-Authored-By: Claude <noreply@anthropic.com>
已修改29个文件
331 ■■■■■ 文件已修改
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/api/sale/dto/ErpSaleOrderCreateReqDTO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/approval/vo/HrmLeaveApplicationRespVO.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/approval/vo/HrmResignationApplicationRespVO.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/approval/vo/HrmTransferApplicationRespVO.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/HrmAttendanceHolidayController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/HrmAttendanceRecordController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/HrmAttendanceRuleController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/HrmAttendanceSummaryController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeImportExcelVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeSaveReqVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/HrmSalaryCalculationController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueRespVO.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptRespVO.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/MesWmProductIssueRespVO.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/MesWmReturnIssueRespVO.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnSalesRespVO.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/MesWmReturnVendorRespVO.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/MesWmTransferRespVO.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/mps/MesProMpsMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/supplier/vo/SrmSupplierRespVO.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportExcelVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java
@@ -579,6 +579,10 @@
                    item.setProductId(cp.getItemId());
                    item.setProductPrice(cp.getContractPrice());
                    item.setCount(cp.getCount());
                    // 合同产品默认需要生产:订单审批通过后才能自动创建 MPS,
                    // 否则「合同 → 订单 → 生产」链路在合同来源的订单上会断掉。
                    // 若个别产品为外购/转售,可在销售订单明细中把「需要生产」改为否。
                    item.setNeedProduction(1);
                    return item;
                })
                .toList();
yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/api/sale/dto/ErpSaleOrderCreateReqDTO.java
@@ -58,6 +58,9 @@
        @Schema(description = "税率,百分比", example = "10")
        private BigDecimal taxPercent;
        @Schema(description = "是否需要生产:1-是 0-否", example = "1")
        private Integer needProduction;
        @Schema(description = "备注", example = "备注")
        private String remark;
    }
yudao-module-hrm-api/src/main/java/cn/iocoder/yudao/module/hrm/enums/ErrorCodeConstants.java
@@ -31,6 +31,8 @@
    ErrorCode CERTIFICATE_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_030_000_018, "导入证书资质数据不能为空");
    ErrorCode CERTIFICATE_EXISTS = new ErrorCode(1_030_000_019, "已存在证书资质【{}】,且未开启覆盖!");
    ErrorCode CERTIFICATE_EMPLOYEE_NOT_EXISTS = new ErrorCode(1_030_000_020, "员工【{}】不存在");
    ErrorCode EMPLOYEE_INIT_PASSWORD_NOT_CONFIGURED = new ErrorCode(1_030_000_021,
            "未填写初始密码,且系统参数 system.user.init-password 未配置。请在导入文件中填写该行初始密码,或先在参数设置中配置 system.user.init-password");
    // ========== 请假申请 1-030-001-000 ==========
    ErrorCode LEAVE_APPLICATION_NOT_EXISTS = new ErrorCode(1_030_001_000, "请假申请不存在");
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/approval/vo/HrmLeaveApplicationRespVO.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.hrm.controller.admin.approval.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -10,72 +12,88 @@
@Schema(description = "管理后台 - 请假申请 Response VO")
@Data
@ExcelIgnoreUnannotated
public class HrmLeaveApplicationRespVO {
    @Schema(description = "申请ID", example = "1")
    private Long id;
    @Schema(description = "申请单号", example = "LA202401001")
    @ExcelProperty("申请单号")
    private String no;
    @Schema(description = "申请人ID", example = "1")
    private Long userId;
    @Schema(description = "申请人姓名", example = "张三")
    @ExcelProperty("申请人")
    private String userName;
    @Schema(description = "部门ID", example = "1")
    private Long deptId;
    @Schema(description = "部门名称", example = "研发部")
    @ExcelProperty("部门")
    private String deptName;
    @Schema(description = "请假类型", example = "1")
    private Integer leaveType;
    @Schema(description = "请假类型名称", example = "年假")
    @ExcelProperty("请假类型")
    private String leaveTypeName;
    @Schema(description = "开始时间", example = "2024-01-01 09:00:00")
    @ExcelProperty("开始时间")
    private LocalDateTime startTime;
    @Schema(description = "结束时间", example = "2024-01-02 18:00:00")
    @ExcelProperty("结束时间")
    private LocalDateTime endTime;
    @Schema(description = "请假时长(天)", example = "1.5")
    @ExcelProperty("请假时长(天)")
    private BigDecimal duration;
    @Schema(description = "请假原因", example = "个人事务")
    @ExcelProperty("请假事由")
    private String reason;
    @Schema(description = "审批状态", example = "0")
    private Integer status;
    @Schema(description = "审批状态名称", example = "草稿")
    @ExcelProperty("状态")
    private String statusName;
    @Schema(description = "审核人用户编号", example = "1")
    private Long reviewerId;
    @Schema(description = "审核人姓名", example = "张三")
    @ExcelProperty("审核人")
    private String reviewerName;
    @Schema(description = "审核时间", example = "2024-01-01 10:00:00")
    @ExcelProperty("审核时间")
    private LocalDateTime reviewTime;
    @Schema(description = "审核意见(审核通过时的意见 / 审核不通过时的原因)", example = "同意")
    @ExcelProperty("审核意见")
    private String reviewRemark;
    @Schema(description = "审批完成时间", example = "2024-01-01 10:00:00")
    @ExcelProperty("审批通过时间")
    private LocalDateTime approveTime;
    @Schema(description = "附件列表")
    private List<StorageBlobRespDTO> attachmentList;
    @Schema(description = "备注", example = "备注信息")
    @ExcelProperty("备注")
    private String remark;
    @Schema(description = "创建时间", example = "2024-01-01 09:00:00")
    @ExcelProperty("创建时间")
    private LocalDateTime createTime;
}
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/approval/vo/HrmResignationApplicationRespVO.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.hrm.controller.admin.approval.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -10,81 +12,98 @@
@Schema(description = "管理后台 - 离职申请 Response VO")
@Data
@ExcelIgnoreUnannotated
public class HrmResignationApplicationRespVO {
    @Schema(description = "申请ID", example = "1")
    private Long id;
    @Schema(description = "申请单号", example = "RA202401001")
    @ExcelProperty("申请单号")
    private String no;
    @Schema(description = "申请人ID", example = "1")
    private Long userId;
    @Schema(description = "申请人姓名", example = "张三")
    @ExcelProperty("申请人")
    private String userName;
    @Schema(description = "部门ID", example = "1")
    private Long deptId;
    @Schema(description = "部门名称", example = "研发部")
    @ExcelProperty("部门")
    private String deptName;
    @Schema(description = "离职类型", example = "1")
    private Integer resignationType;
    @Schema(description = "离职类型名称", example = "主动离职")
    @ExcelProperty("离职类型")
    private String resignationTypeName;
    @Schema(description = "预计离职日期", example = "2024-02-01")
    @ExcelProperty("期望离职日期")
    private LocalDate expectedDate;
    @Schema(description = "实际离职日期", example = "2024-02-01")
    @ExcelProperty("实际离职日期")
    private LocalDate actualDate;
    @Schema(description = "离职原因", example = "个人发展")
    @ExcelProperty("离职原因")
    private String reason;
    @Schema(description = "交接人ID", example = "1")
    private Long handoverUserId;
    @Schema(description = "交接人姓名", example = "李四")
    @ExcelProperty("交接人")
    private String handoverUserName;
    @Schema(description = "交接状态", example = "0")
    private Integer handoverStatus;
    @Schema(description = "交接状态名称", example = "未开始")
    @ExcelProperty("交接状态")
    private String handoverStatusName;
    @Schema(description = "交接说明", example = "交接说明")
    @ExcelProperty("交接说明")
    private String handoverRemark;
    @Schema(description = "审批状态", example = "0")
    private Integer status;
    @Schema(description = "审批状态名称", example = "草稿")
    @ExcelProperty("状态")
    private String statusName;
    @Schema(description = "审核人用户编号", example = "1")
    private Long reviewerId;
    @Schema(description = "审核人姓名", example = "张三")
    @ExcelProperty("审核人")
    private String reviewerName;
    @Schema(description = "审核时间", example = "2024-01-01 10:00:00")
    @ExcelProperty("审核时间")
    private LocalDateTime reviewTime;
    @Schema(description = "审核意见(审核通过时的意见 / 审核不通过时的原因)", example = "同意")
    @ExcelProperty("审核意见")
    private String reviewRemark;
    @Schema(description = "审批完成时间", example = "2024-01-01 10:00:00")
    @ExcelProperty("审批通过时间")
    private LocalDateTime approveTime;
    @Schema(description = "附件列表")
    private List<StorageBlobRespDTO> attachmentList;
    @Schema(description = "备注", example = "备注信息")
    @ExcelProperty("备注")
    private String remark;
    @Schema(description = "创建时间", example = "2024-01-01 09:00:00")
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/approval/vo/HrmTransferApplicationRespVO.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.hrm.controller.admin.approval.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -10,81 +12,97 @@
@Schema(description = "管理后台 - 调岗申请 Response VO")
@Data
@ExcelIgnoreUnannotated
public class HrmTransferApplicationRespVO {
    @Schema(description = "申请ID", example = "1")
    private Long id;
    @Schema(description = "申请单号", example = "TA202401001")
    @ExcelProperty("申请单号")
    private String no;
    @Schema(description = "申请人ID", example = "1")
    private Long userId;
    @Schema(description = "申请人姓名", example = "张三")
    @ExcelProperty("申请人")
    private String userName;
    @Schema(description = "原部门ID", example = "1")
    private Long currentDeptId;
    @Schema(description = "原部门名称", example = "研发部")
    @ExcelProperty("原部门")
    private String currentDeptName;
    @Schema(description = "原岗位ID", example = "1")
    private Long currentPostId;
    @Schema(description = "原岗位名称", example = "Java开发工程师")
    @ExcelProperty("原岗位")
    private String currentPostName;
    @Schema(description = "目标部门ID", example = "2")
    private Long targetDeptId;
    @Schema(description = "目标部门名称", example = "产品部")
    @ExcelProperty("目标部门")
    private String targetDeptName;
    @Schema(description = "目标岗位ID", example = "2")
    private Long targetPostId;
    @Schema(description = "目标岗位名称", example = "产品经理")
    @ExcelProperty("目标岗位")
    private String targetPostName;
    @Schema(description = "调岗类型", example = "1")
    private Integer transferType;
    @Schema(description = "调岗类型名称", example = "平调")
    @ExcelProperty("调动类型")
    private String transferTypeName;
    @Schema(description = "生效日期", example = "2024-02-01")
    @ExcelProperty("生效日期")
    private LocalDate effectiveDate;
    @Schema(description = "调岗原因", example = "业务需要")
    @ExcelProperty("调动原因")
    private String reason;
    @Schema(description = "审批状态", example = "0")
    private Integer status;
    @Schema(description = "审批状态名称", example = "草稿")
    @ExcelProperty("状态")
    private String statusName;
    @Schema(description = "审核人用户编号", example = "1")
    private Long reviewerId;
    @Schema(description = "审核人姓名", example = "李四")
    @ExcelProperty("审核人")
    private String reviewerName;
    @Schema(description = "审核时间", example = "2024-01-01 10:00:00")
    @ExcelProperty("审核时间")
    private LocalDateTime reviewTime;
    @Schema(description = "审核意见(审核通过时的意见 / 审核不通过时的原因)", example = "同意调岗")
    @ExcelProperty("审核意见")
    private String reviewRemark;
    @Schema(description = "审批完成时间", example = "2024-01-01 10:00:00")
    @ExcelProperty("审批通过时间")
    private LocalDateTime approveTime;
    @Schema(description = "附件列表")
    private List<StorageBlobRespDTO> attachmentList;
    @Schema(description = "备注", example = "备注信息")
    @ExcelProperty("备注")
    private String remark;
    @Schema(description = "创建时间", example = "2024-01-01 09:00:00")
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/HrmAttendanceHolidayController.java
@@ -84,7 +84,7 @@
    @GetMapping("/export-excel")
    @Operation(summary = "导出节假日配置 Excel")
    @PreAuthorize("@ss.hasPermission('hrm:attendance:export')")
    @PreAuthorize("@ss.hasAnyPermissions('hrm:attendance:export', 'hrm:attendance-holiday:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportAttendanceHolidayExcel(@Valid HrmAttendanceHolidayPageReqVO pageReqVO,
                                               HttpServletResponse response) throws IOException {
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/HrmAttendanceRecordController.java
@@ -315,7 +315,7 @@
    @GetMapping("/export-excel")
    @Operation(summary = "导出考勤记录 Excel")
    @PreAuthorize("@ss.hasPermission('hrm:attendance:export')")
    @PreAuthorize("@ss.hasAnyPermissions('hrm:attendance:export', 'hrm:attendance-record:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportAttendanceRecordExcel(@Valid HrmAttendanceRecordPageReqVO pageReqVO,
                                              HttpServletResponse response) throws IOException {
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/HrmAttendanceRuleController.java
@@ -124,7 +124,7 @@
    @GetMapping("/export-excel")
    @Operation(summary = "导出考勤规则 Excel")
    @PreAuthorize("@ss.hasPermission('hrm:attendance:export')")
    @PreAuthorize("@ss.hasAnyPermissions('hrm:attendance:export', 'hrm:attendance-rule:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportAttendanceRuleExcel(@Valid HrmAttendanceRulePageReqVO pageReqVO,
                                            HttpServletResponse response) throws IOException {
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/HrmAttendanceSummaryController.java
@@ -138,7 +138,7 @@
    @GetMapping("/export-excel")
    @Operation(summary = "导出考勤统计汇总 Excel")
    @PreAuthorize("@ss.hasPermission('hrm:attendance:export')")
    @PreAuthorize("@ss.hasAnyPermissions('hrm:attendance:export', 'hrm:attendance-summary:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportAttendanceSummaryExcel(@Valid HrmAttendanceSummaryPageReqVO pageReqVO,
                                               HttpServletResponse response) throws IOException {
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeImportExcelVO.java
@@ -29,6 +29,9 @@
    @ExcelProperty("手机号")
    private String phone;
    @ExcelProperty("初始密码")
    private String password;
    @ExcelProperty("部门名称")
    private String deptName;
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/HrmEmployeeSaveReqVO.java
@@ -49,6 +49,9 @@
    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号码格式不正确")
    private String phone;
    @Schema(description = "初始密码(为空时读取系统参数 system.user.init-password)", example = "123456")
    private String password;
    @Schema(description = "邮箱", example = "zhangsan@example.com")
    @Email(message = "邮箱格式不正确")
    private String email;
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/HrmSalaryCalculationController.java
@@ -163,7 +163,7 @@
    @GetMapping("/export-excel")
    @Operation(summary = "导出薪酬核算 Excel")
    @PreAuthorize("@ss.hasPermission('hrm:salary:export')")
    @PreAuthorize("@ss.hasAnyPermissions('hrm:salary:export', 'hrm:salary-calculation:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportSalaryCalculationExcel(@Valid HrmSalaryCalculationPageReqVO pageReqVO,
                                               HttpServletResponse response) throws IOException {
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/service/employee/HrmEmployeeServiceImpl.java
@@ -28,6 +28,7 @@
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeMapper;
import cn.iocoder.yudao.module.hrm.dal.mysql.employee.HrmEmployeeWorkHistoryMapper;
import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.PostApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
@@ -87,6 +88,13 @@
    @Resource
    private MesCalTeamApi mesCalTeamApi;
    @Resource
    private ConfigApi configApi;
    /**
     * 用户初始密码的系统参数配置项
     */
    private static final String USER_INIT_PASSWORD_KEY = "system.user.init-password";
    @Resource
    @Lazy // 自注入需延迟加载,否则 bean 被代理包装后注入原始版本导致启动失败
    private HrmEmployeeService self;
@@ -108,7 +116,8 @@
        userCreateReqDTO.setDeptId(createReqVO.getDeptId());
        userCreateReqDTO.setPostIds(Collections.singleton(createReqVO.getPostId()));
        userCreateReqDTO.setMobile(createReqVO.getPhone());
        userCreateReqDTO.setPassword(createReqVO.getPhone());
        // 初始密码:优先用导入/新增时指定的密码,否则读取系统参数;两者都没有则报错
        userCreateReqDTO.setPassword(resolveInitialPassword(createReqVO.getPassword()));
        userCreateReqDTO.setSex(createReqVO.getGender());
        userCreateReqDTO.setEmail(createReqVO.getEmail());
        userCreateReqDTO.setRemark(createReqVO.getRemark());
@@ -186,6 +195,11 @@
        }
        employeeMapper.updateById(updateObj);
        Long employeeId = updateReqVO.getId();
        // 同步系统用户密码:仅当显式填写了密码时才更新,未填写保持原密码不变
        if (StrUtil.isNotBlank(updateReqVO.getPassword()) && employee.getUserId() != null) {
            adminUserApi.updateUserPassword(employee.getUserId(), updateReqVO.getPassword());
        }
        // 同步教育经历
        syncEducationList(employeeId, updateReqVO.getEducations());
@@ -413,6 +427,23 @@
        return respVO;
    }
    /**
     * 解析员工初始密码:
     * 1. 导入/新增时显式指定了密码,优先使用;
     * 2. 未指定则读取系统参数 {@code system.user.init-password};
     * 3. 两者都没有时明确报错,避免悄悄用手机号等弱口令兜底。
     */
    private String resolveInitialPassword(String specifiedPassword) {
        if (StrUtil.isNotBlank(specifiedPassword)) {
            return specifiedPassword;
        }
        String initPassword = configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY);
        if (StrUtil.isBlank(initPassword)) {
            throw exception(EMPLOYEE_INIT_PASSWORD_NOT_CONFIGURED);
        }
        return initPassword;
    }
    private HrmEmployeeSaveReqVO buildImportSaveReqVO(HrmEmployeeImportExcelVO importEmployee,
                                                      Long deptId, Long postId, Set<Long> roleIds) {
        if (StrUtil.isBlank(importEmployee.getName())) {
@@ -428,6 +459,7 @@
        reqVO.setName(importEmployee.getName());
        reqVO.setGender(importEmployee.getGender() != null ? importEmployee.getGender() : 1); // 默认男
        reqVO.setPhone(importEmployee.getPhone());
        reqVO.setPassword(importEmployee.getPassword());
        reqVO.setDeptId(deptId);
        reqVO.setPostId(postId);
        reqVO.setRoleIds(CollUtil.isEmpty(roleIds) ? null : new ArrayList<>(roleIds));
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -9,33 +11,40 @@
@Schema(description = "管理后台 - MES 生产任务 Response VO")
@Data
@ExcelIgnoreUnannotated
public class MesProTaskRespVO {
    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
    private Long id;
    @Schema(description = "任务编码", example = "PT202503150001")
    @ExcelProperty("任务编码")
    private String code;
    @Schema(description = "任务名称", example = "注塑任务")
    @ExcelProperty("任务名称")
    private String name;
    @Schema(description = "生产工单编号", example = "1")
    private Long workOrderId;
    @Schema(description = "工单编码", example = "WO-001")
    @ExcelProperty("生产工单编号")
    private String workOrderCode;
    @Schema(description = "工单名称", example = "生产工单-A")
    @ExcelProperty("生产工单名称")
    private String workOrderName;
    @Schema(description = "工作站编号", example = "1")
    private Long workstationId;
    @Schema(description = "工作站编码", example = "WS-001")
    @ExcelProperty("工作站编码")
    private String workstationCode;
    @Schema(description = "工作站名称", example = "注塑工作站")
    @ExcelProperty("工作站")
    private String workstationName;
    @Schema(description = "工艺路线编号", example = "1")
@@ -45,51 +54,65 @@
    private Long processId;
    @Schema(description = "工序名称", example = "注塑")
    @ExcelProperty("工序")
    private String processName;
    @Schema(description = "班组编号", example = "1")
    private Long teamId;
    @Schema(description = "班组名称", example = "运维一班")
    @ExcelProperty("班组")
    private String teamName;
    @Schema(description = "产品物料编号", example = "100")
    private Long itemId;
    @Schema(description = "产品编码", example = "P-001")
    @ExcelProperty("物料编码")
    private String itemCode;
    @Schema(description = "产品名称", example = "电路板")
    @ExcelProperty("物料名称")
    private String itemName;
    @Schema(description = "规格型号", example = "100x200mm")
    @ExcelProperty("规格型号")
    private String itemSpecification;
    @Schema(description = "计量单位名称", example = "个")
    @ExcelProperty("单位")
    private String unitMeasureName;
    @Schema(description = "排产数量", example = "100.00")
    @ExcelProperty("计划数量")
    private BigDecimal quantity;
    @Schema(description = "已生产数量", example = "50.00")
    @ExcelProperty("已生产数量")
    private BigDecimal producedQuantity;
    @Schema(description = "合格品数量", example = "48.00")
    @ExcelProperty("合格数量")
    private BigDecimal qualifyQuantity;
    @Schema(description = "不良品数量", example = "2.00")
    @ExcelProperty("不合格数量")
    private BigDecimal unqualifyQuantity;
    @Schema(description = "待报工数量", example = "50.00")
    @ExcelProperty("待生产数量")
    private BigDecimal pendingQuantity;
    @Schema(description = "在途报工数量", example = "20.00")
    @ExcelProperty("在途报工数量")
    private BigDecimal inTransitQuantity;
    @Schema(description = "可报工数量", example = "30.00")
    @ExcelProperty("可报工数量")
    private BigDecimal reportableQuantity;
    @Schema(description = "报工完成率(%)", example = "50.00")
    @ExcelProperty("报工完成率(%)")
    private BigDecimal feedbackRate;
    @Schema(description = "调整数量", example = "0")
@@ -99,42 +122,54 @@
    private Long clientId;
    @Schema(description = "客户名称", example = "客户A")
    @ExcelProperty("客户")
    private String clientName;
    @Schema(description = "开始生产时间")
    @ExcelProperty("开始生产时间")
    private LocalDateTime startTime;
    @Schema(description = "生产时长(工作日)", example = "3")
    @ExcelProperty("生产时长(工作日)")
    private Integer duration;
    @Schema(description = "结束生产时间")
    @ExcelProperty("结束生产时间")
    private LocalDateTime endTime;
    @Schema(description = "甘特图显示颜色", example = "#00AEF3")
    private String colorCode;
    @Schema(description = "需求日期")
    @ExcelProperty("需求日期")
    private LocalDateTime requestDate;
    @Schema(description = "完成日期")
    @ExcelProperty("完成日期")
    private LocalDateTime finishDate;
    @Schema(description = "取消日期")
    @ExcelProperty("取消日期")
    private LocalDateTime cancelDate;
    @Schema(description = "任务状态", example = "0")
    @ExcelProperty("任务状态")
    private Integer status;
    @Schema(description = "是否质检(派生自工艺路线工序 checkFlag)", example = "true")
    @ExcelProperty("是否质检")
    private Boolean checkFlag;
    @Schema(description = "是否倒冲(派生自工艺路线工序 backflushFlag)", example = "true")
    @ExcelProperty("是否倒冲")
    private Boolean backflushFlag;
    @Schema(description = "备注", example = "备注")
    @ExcelProperty("备注")
    private String remark;
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("创建时间")
    private LocalDateTime createTime;
    @Schema(description = "停工历史记录")
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueRespVO.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.mes.controller.admin.wm.miscissue.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -7,50 +9,63 @@
@Schema(description = "管理后台 - MES 杂项出库单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class MesWmMiscIssueRespVO {
    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long id;
    @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "MI20260302001")
    @ExcelProperty("出库单编号")
    private String code;
    @Schema(description = "出库单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "库存调整出库")
    @ExcelProperty("出库单名称")
    private String name;
    @Schema(description = "杂项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    @ExcelProperty("杂项类型")
    private Integer type;
    @Schema(description = "来源单据类型", example = "PURCHASE_ORDER")
    @ExcelProperty("来源单据类型")
    private String sourceDocType;
    @Schema(description = "来源单据ID", example = "1")
    private Long sourceDocId;
    @Schema(description = "来源单据编号", example = "DOC20260302001")
    @ExcelProperty("来源单据编号")
    private String sourceDocCode;
    @Schema(description = "出库日期", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("出库日期")
    private LocalDateTime issueDate;
    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
    @ExcelProperty("状态")
    private Integer status;
    @Schema(description = "审核人用户编号", example = "1")
    private Long reviewerId;
    @Schema(description = "审核人姓名", example = "张三")
    @ExcelProperty("审核人")
    private String reviewerName;
    @Schema(description = "审核时间")
    @ExcelProperty("审核时间")
    private LocalDateTime reviewTime;
    @Schema(description = "审核意见(通过时的意见 / 不通过时的原因)", example = "出库数量需再次核对")
    @ExcelProperty("审核意见")
    private String reviewRemark;
    @Schema(description = "备注", example = "备注")
    @ExcelProperty("备注")
    private String remark;
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("创建时间")
    private LocalDateTime createTime;
}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptRespVO.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.mes.controller.admin.wm.miscreceipt.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -7,50 +9,63 @@
@Schema(description = "管理后台 - MES 杂项入库单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class MesWmMiscReceiptRespVO {
    @Schema(description = "编号", example = "1024")
    private Long id;
    @Schema(description = "入库单编码", example = "MR2026030001")
    @ExcelProperty("入库单编码")
    private String code;
    @Schema(description = "入库单名称", example = "退料入库单")
    @ExcelProperty("入库单名称")
    private String name;
    @Schema(description = "杂项类型", example = "1")
    @ExcelProperty("杂项类型")
    private Integer type;
    @Schema(description = "来源单据类型", example = "WORK_ORDER")
    @ExcelProperty("来源单据类型")
    private String sourceDocType;
    @Schema(description = "来源单据 ID", example = "1")
    private Long sourceDocId;
    @Schema(description = "来源单据编码", example = "WO2026030001")
    @ExcelProperty("来源单据编码")
    private String sourceDocCode;
    @Schema(description = "入库日期")
    @ExcelProperty("入库日期")
    private LocalDateTime receiptDate;
    @Schema(description = "状态", example = "0")
    @ExcelProperty("状态")
    private Integer status;
    @Schema(description = "审核人用户编号", example = "1")
    private Long reviewerId;
    @Schema(description = "审核人姓名", example = "张三")
    @ExcelProperty("审核人")
    private String reviewerName;
    @Schema(description = "审核时间")
    @ExcelProperty("审核时间")
    private LocalDateTime reviewTime;
    @Schema(description = "审核意见(通过时的意见 / 不通过时的原因)", example = "入库数量需再次核对")
    @ExcelProperty("审核意见")
    private String reviewRemark;
    @Schema(description = "备注", example = "备注")
    @ExcelProperty("备注")
    private String remark;
    @Schema(description = "创建时间")
    @ExcelProperty("创建时间")
    private LocalDateTime createTime;
}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/MesWmProductIssueRespVO.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.mes.controller.admin.wm.productissue.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -7,60 +9,74 @@
@Schema(description = "管理后台 - MES 领料出库单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class MesWmProductIssueRespVO {
    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long id;
    @Schema(description = "领料单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "ISSUE20250226001")
    @ExcelProperty("领料单编号")
    private String code;
    @Schema(description = "领料单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "生产领料")
    @ExcelProperty("领料单名称")
    private String name;
    @Schema(description = "生产工单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long workOrderId;
    @Schema(description = "生产工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "WO20250226001")
    @ExcelProperty("生产工单编号")
    private String workOrderCode;
    @Schema(description = "工作站 ID", example = "1")
    private Long workstationId;
    @Schema(description = "工作站名称", example = "装配工作站")
    @ExcelProperty("工作站")
    private String workstationName;
    @Schema(description = "客户编号", example = "C001")
    private String clientCode;
    @Schema(description = "客户名称", example = "某某客户")
    @ExcelProperty("客户")
    private String clientName;
    @Schema(description = "生产任务 ID", example = "1")
    private Long taskId;
    @Schema(description = "生产任务编码", example = "TASK001")
    @ExcelProperty("生产任务编码")
    private String taskCode;
    @Schema(description = "生产任务名称", example = "注塑任务")
    @ExcelProperty("生产任务名称")
    private String taskName;
    @Schema(description = "领料日期")
    @ExcelProperty("领料日期")
    private LocalDateTime issueDate;
    @Schema(description = "需求时间", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("需求时间")
    private LocalDateTime requiredTime;
    @Schema(description = "单据类型(1=正常领料,2=紧急补料)", example = "1")
    @ExcelProperty("单据类型")
    private Integer issueType;
    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
    @ExcelProperty("状态")
    private Integer status;
    @Schema(description = "备注", example = "备注")
    @ExcelProperty("备注")
    private String remark;
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("创建时间")
    private LocalDateTime createTime;
}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/MesWmReturnIssueRespVO.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -7,51 +9,63 @@
@Schema(description = "管理后台 - MES 生产退料单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class MesWmReturnIssueRespVO {
    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long id;
    @Schema(description = "退料单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "RI20250226001")
    @ExcelProperty("退料单编号")
    private String code;
    @Schema(description = "退料单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "生产退料")
    @ExcelProperty("退料单名称")
    private String name;
    @Schema(description = "生产工单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long workOrderId;
    @Schema(description = "生产工单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "WO20250226001")
    @ExcelProperty("生产工单编号")
    private String workOrderCode;
    @Schema(description = "生产任务 ID", example = "1")
    private Long taskId;
    @Schema(description = "生产任务编码", example = "TASK001")
    @ExcelProperty("生产任务编码")
    private String taskCode;
    @Schema(description = "生产任务名称", example = "注塑任务")
    @ExcelProperty("生产任务名称")
    private String taskName;
    @Schema(description = "工作站 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long workstationId;
    @Schema(description = "工作站名称", example = "装配工作站")
    @ExcelProperty("工作站")
    private String workstationName;
    @Schema(description = "退料类型", example = "1")
    @ExcelProperty("退料类型")
    private Integer type;
    @Schema(description = "退料日期")
    @ExcelProperty("退料日期")
    private LocalDateTime returnDate;
    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
    @ExcelProperty("状态")
    private Integer status;
    @Schema(description = "备注", example = "备注")
    @ExcelProperty("备注")
    private String remark;
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("创建时间")
    private LocalDateTime createTime;
}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/MesWmReturnSalesRespVO.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -13,42 +15,52 @@
 */
@Schema(description = "管理后台 - MES 销售退货单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class MesWmReturnSalesRespVO {
    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long id;
    @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "RS202603010001")
    @ExcelProperty("退货单编号")
    private String code;
    @Schema(description = "退货单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "销售退货")
    @ExcelProperty("退货单名称")
    private String name;
    @Schema(description = "销售订单 ID", example = "1")
    private Long saleOrderId;
    @Schema(description = "销售订单编号", example = "SO202603010001")
    @ExcelProperty("销售订单编号")
    private String salesOrderCode;
    @Schema(description = "客户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long clientId;
    @Schema(description = "客户名称", example = "XX客户")
    @ExcelProperty("客户")
    private String clientName;
    @Schema(description = "退货日期")
    @ExcelProperty("退货日期")
    private LocalDate returnDate;
    @Schema(description = "退货原因", example = "质量问题")
    @ExcelProperty("退货原因")
    private String returnReason;
    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
    @ExcelProperty("状态")
    private Integer status;
    @Schema(description = "备注", example = "备注")
    @ExcelProperty("备注")
    private String remark;
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("创建时间")
    private LocalDateTime createTime;
}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/MesWmReturnVendorRespVO.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -7,63 +9,79 @@
@Schema(description = "管理后台 - MES 供应商退货单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class MesWmReturnVendorRespVO {
    @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long id;
    @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "RV20250226001")
    @ExcelProperty("退货单编号")
    private String code;
    @Schema(description = "退货单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "供应商退货")
    @ExcelProperty("退货单名称")
    private String name;
    @Schema(description = "采购订单编号", example = "PO20250226001")
    @ExcelProperty("采购订单编号")
    private String purchaseOrderCode;
    @Schema(description = "供应商 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
    private Long vendorId;
    @Schema(description = "供应商编码", example = "V001")
    @ExcelProperty("供应商编码")
    private String vendorCode;
    @Schema(description = "供应商名称", example = "XX供应商")
    @ExcelProperty("供应商名称")
    private String vendorName;
    @Schema(description = "供应商简称", example = "XX")
    private String vendorNickname;
    @Schema(description = "退货日期")
    @ExcelProperty("退货日期")
    private LocalDateTime returnDate;
    @Schema(description = "退货原因", example = "质量不合格")
    @ExcelProperty("退货原因")
    private String returnReason;
    @Schema(description = "物流单号", example = "SF1234567890")
    @ExcelProperty("物流单号")
    private String transportCode;
    @Schema(description = "物流联系电话", example = "13800138000")
    @ExcelProperty("物流联系电话")
    private String transportTelephone;
    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
    @ExcelProperty("状态")
    private Integer status;
    @Schema(description = "审核人用户编号", example = "1")
    private Long reviewerId;
    @Schema(description = "审核人姓名", example = "张三")
    @ExcelProperty("审核人")
    private String reviewerName;
    @Schema(description = "审核时间")
    @ExcelProperty("审核时间")
    private LocalDateTime reviewTime;
    @Schema(description = "审核意见(通过时的意见 / 不通过时的原因)", example = "退货数量需再次核对")
    @ExcelProperty("审核意见")
    private String reviewRemark;
    @Schema(description = "备注", example = "备注")
    @ExcelProperty("备注")
    private String remark;
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("创建时间")
    private LocalDateTime createTime;
}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/MesWmTransferRespVO.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.mes.controller.admin.wm.transfer.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -7,48 +9,62 @@
@Schema(description = "管理后台 - MES 转移单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class MesWmTransferRespVO {
    @Schema(description = "编号", example = "1")
    private Long id;
    @Schema(description = "转移单编号", example = "TR2026020001")
    @ExcelProperty("转移单编号")
    private String code;
    @Schema(description = "转移单名称", example = "钢板转移单")
    @ExcelProperty("转移单名称")
    private String name;
    @Schema(description = "转移单类型", example = "1")
    @ExcelProperty("转移单类型")
    private Integer type;
    @Schema(description = "是否配送", example = "true")
    @ExcelProperty("是否配送")
    private Boolean deliveryFlag;
    @Schema(description = "收货人", example = "张三")
    @ExcelProperty("收货人")
    private String recipientName;
    @Schema(description = "联系方式", example = "13800138000")
    @ExcelProperty("联系方式")
    private String recipientTelephone;
    @Schema(description = "目的地", example = "上海市浦东新区")
    @ExcelProperty("目的地")
    private String destinationAddress;
    @Schema(description = "承运商", example = "顺丰速运")
    @ExcelProperty("承运商")
    private String carrier;
    @Schema(description = "运输单号", example = "SF123456789")
    @ExcelProperty("运输单号")
    private String shippingNumber;
    @Schema(description = "是否已确认", example = "false")
    @ExcelProperty("是否已确认")
    private Boolean confirmFlag;
    @Schema(description = "转移日期")
    @ExcelProperty("转移日期")
    private LocalDateTime transferDate;
    @Schema(description = "单据状态", example = "0")
    @ExcelProperty("单据状态")
    private Integer status;
    @Schema(description = "备注", example = "备注信息")
    @ExcelProperty("备注")
    private String remark;
}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/mps/MesProMpsMapper.java
@@ -63,6 +63,19 @@
        return selectOne(MesProMpsDO::getCode, code);
    }
    /**
     * 按工单查询 MPS。
     *
     * 合并下发时多个 MPS 会指向同一个工单,因此这里必须限制只取一条,
     * 否则 MyBatis-Plus 的 selectOne 会抛 TooManyResultsException,导致报工无法完工。
     */
    default MesProMpsDO selectByWorkOrderId(Long workOrderId) {
        return selectOne(new LambdaQueryWrapperX<MesProMpsDO>()
                .eq(MesProMpsDO::getWorkOrderId, workOrderId)
                .orderByDesc(MesProMpsDO::getId)
                .last("LIMIT 1"));
    }
    default MesProMpsDO selectBySaleOrderItemId(Long saleOrderItemId) {
        return selectOne(new LambdaQueryWrapperX<MesProMpsDO>()
                .eq(MesProMpsDO::getSaleOrderItemId, saleOrderItemId)
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java
@@ -402,7 +402,7 @@
        if (workOrderId == null) {
            return null;
        }
        return mpsMapper.selectOne(MesProMpsDO::getWorkOrderId, workOrderId);
        return mpsMapper.selectByWorkOrderId(workOrderId);
    }
    @Override
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/supplier/vo/SrmSupplierRespVO.java
@@ -1,5 +1,7 @@
package cn.iocoder.yudao.module.srm.controller.admin.supplier.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -8,66 +10,86 @@
@Schema(description = "管理后台 - 供应商 Response VO")
@Data
@ExcelIgnoreUnannotated
public class SrmSupplierRespVO {
    @Schema(description = "供应商ID")
    private Long id;
    @Schema(description = "供应商编码")
    @ExcelProperty("供应商编码")
    private String code;
    @Schema(description = "供应商名称")
    @ExcelProperty("供应商名称")
    private String name;
    @Schema(description = "供应商简称")
    @ExcelProperty("供应商简称")
    private String shortName;
    @Schema(description = "供应商类型")
    @ExcelProperty("供应商类型")
    private String type;
    @Schema(description = "企业性质")
    @ExcelProperty("公司性质")
    private String companyNature;
    @Schema(description = "注册资金(万元)")
    @ExcelProperty("注册资本")
    private BigDecimal registeredCapital;
    @Schema(description = "营业执照编号")
    @ExcelProperty("营业执照号")
    private String businessLicenseNo;
    @Schema(description = "税号")
    @ExcelProperty("税号")
    private String taxNo;
    @Schema(description = "法人代表")
    @ExcelProperty("法人")
    private String legalPerson;
    @Schema(description = "公司地址")
    @ExcelProperty("地址")
    private String address;
    @Schema(description = "公司网址")
    @ExcelProperty("网址")
    private String website;
    @Schema(description = "联系人")
    @ExcelProperty("联系人")
    private String contactName;
    @Schema(description = "联系电话")
    @ExcelProperty("联系电话")
    private String contactMobile;
    @Schema(description = "邮箱")
    @ExcelProperty("联系邮箱")
    private String contactEmail;
    @Schema(description = "开户银行")
    @ExcelProperty("开户银行")
    private String bankName;
    @Schema(description = "银行账号")
    @ExcelProperty("银行账号")
    private String bankAccount;
    @Schema(description = "状态(0启用 1禁用)")
    @ExcelProperty("状态")
    private Integer status;
    @Schema(description = "备注")
    @ExcelProperty("备注")
    private String remark;
    @Schema(description = "创建时间")
    @ExcelProperty("创建时间")
    private LocalDateTime createTime;
}
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java
@@ -25,6 +25,14 @@
    Long createUser(AdminUserCreateReqDTO createReqDTO);
    /**
     * 更新用户密码
     *
     * @param id 用户编号
     * @param password 明文密码
     */
    void updateUserPassword(Long id, String password);
    /**
     * 通过用户 ID 查询用户
     *
     * @param id 用户ID
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApiImpl.java
@@ -36,6 +36,11 @@
    private DeptService deptService;
    @Override
    public void updateUserPassword(Long id, String password) {
        userService.updateUserPassword(id, password);
    }
    @Override
    public Long createUser(AdminUserCreateReqDTO createReqDTO) {
        UserSaveReqVO createReqVO = new UserSaveReqVO();
        createReqVO.setUsername(createReqDTO.getUsername());
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportExcelVO.java
@@ -33,6 +33,9 @@
    @ExcelProperty("手机号码")
    private String mobile;
    @ExcelProperty("初始密码")
    private String password;
    @ExcelProperty(value = "用户性别", converter = DictConvert.class)
    @DictFormat(DictTypeConstants.USER_SEX)
    private Integer sex;
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
@@ -512,11 +512,8 @@
        if (CollUtil.isEmpty(importUsers)) {
            throw exception(USER_IMPORT_LIST_IS_EMPTY);
        }
        // 1.2 初始化密码不能为空
        // 1.2 系统参数中的初始密码,作为 Excel 未填写密码时的兜底
        String initPassword = configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY);
        if (StrUtil.isEmpty(initPassword)) {
            throw exception(USER_IMPORT_INIT_PASSWORD);
        }
        // 2. 遍历,逐个创建 or 更新
        UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>())
@@ -524,11 +521,20 @@
        AtomicInteger index = new AtomicInteger(1);
        importUsers.forEach(importUser -> {
            int currentIndex = index.getAndIncrement();
            String key = StrUtil.blankToDefault(importUser.getUsername(), "第 " + currentIndex + " 行");
            // 2.1.0 解析该行初始密码:Excel 填写了就用填写的,否则读取系统参数
            String effectivePassword = StrUtil.isNotBlank(importUser.getPassword())
                    ? importUser.getPassword() : initPassword;
            if (StrUtil.isBlank(effectivePassword)) {
                respVO.getFailureUsernames().put(key,
                        "未填写初始密码,且系统参数 system.user.init-password 未配置。"
                                + "请在 Excel 中填写该行初始密码,或先在参数设置中配置 system.user.init-password");
                return;
            }
            // 2.1.1 校验字段是否符合要求
            try {
                ValidationUtils.validate(BeanUtils.toBean(importUser, UserSaveReqVO.class).setPassword(initPassword));
                ValidationUtils.validate(BeanUtils.toBean(importUser, UserSaveReqVO.class).setPassword(effectivePassword));
            } catch (ConstraintViolationException ex) {
                String key = StrUtil.blankToDefault(importUser.getUsername(), "第 " + currentIndex + " 行");
                respVO.getFailureUsernames().put(key, ex.getMessage());
                return;
            }
@@ -545,7 +551,7 @@
            AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername());
            if (existUser == null) {
                userMapper.insert(BeanUtils.toBean(importUser, AdminUserDO.class)
                        .setPassword(encodePassword(initPassword)).setPostIds(new HashSet<>())); // 设置默认密码及空岗位编号数组
                        .setPassword(encodePassword(effectivePassword)).setPostIds(new HashSet<>())); // 设置初始密码及空岗位编号数组
                respVO.getCreateUsernames().add(importUser.getUsername());
                return;
            }
@@ -556,6 +562,9 @@
            }
            AdminUserDO updateUser = BeanUtils.toBean(importUser, AdminUserDO.class);
            updateUser.setId(existUser.getId());
            // 密码单独处理:Excel 填写了才更新;未填写则置空,保持原密码不变(避免把明文写进库)
            updateUser.setPassword(StrUtil.isNotBlank(importUser.getPassword())
                    ? encodePassword(importUser.getPassword()) : null);
            userMapper.updateById(updateUser);
            respVO.getUpdateUsernames().add(importUser.getUsername());
        });