Browse Source

Merge remote-tracking branch 'origin/master'

chenshudong 1 month ago
parent
commit
88f52c6cbe

+ 38 - 1
airport-admin/src/main/java/com/sundot/airport/web/controller/ledger/LedgerCertificateInfoController.java

@@ -17,6 +17,7 @@ import com.sundot.airport.common.core.controller.BaseController;
17
 import com.sundot.airport.common.core.domain.AjaxResult;
17
 import com.sundot.airport.common.core.domain.AjaxResult;
18
 import com.sundot.airport.common.enums.BusinessType;
18
 import com.sundot.airport.common.enums.BusinessType;
19
 import com.sundot.airport.ledger.domain.LedgerCertificateInfo;
19
 import com.sundot.airport.ledger.domain.LedgerCertificateInfo;
20
+import com.sundot.airport.ledger.dto.LedgerCertificateImportTemplate;
20
 import com.sundot.airport.ledger.service.ILedgerCertificateInfoService;
21
 import com.sundot.airport.ledger.service.ILedgerCertificateInfoService;
21
 import com.sundot.airport.common.utils.poi.ExcelUtil;
22
 import com.sundot.airport.common.utils.poi.ExcelUtil;
22
 import com.sundot.airport.common.core.page.TableDataInfo;
23
 import com.sundot.airport.common.core.page.TableDataInfo;
@@ -76,6 +77,10 @@ public class LedgerCertificateInfoController extends BaseController {
76
     @Log(title = "证书信息", businessType = BusinessType.INSERT)
77
     @Log(title = "证书信息", businessType = BusinessType.INSERT)
77
     @PostMapping
78
     @PostMapping
78
     public AjaxResult add(@RequestBody LedgerCertificateInfo ledgerCertificateInfo) {
79
     public AjaxResult add(@RequestBody LedgerCertificateInfo ledgerCertificateInfo) {
80
+        String errorMsg = validateCertificateInfo(ledgerCertificateInfo);
81
+        if (errorMsg != null) {
82
+            return error(errorMsg);
83
+        }
79
         return toAjax(certificateInfoService.insertCertificateInfo(ledgerCertificateInfo));
84
         return toAjax(certificateInfoService.insertCertificateInfo(ledgerCertificateInfo));
80
     }
85
     }
81
 
86
 
@@ -86,6 +91,10 @@ public class LedgerCertificateInfoController extends BaseController {
86
     @Log(title = "证书信息", businessType = BusinessType.UPDATE)
91
     @Log(title = "证书信息", businessType = BusinessType.UPDATE)
87
     @PutMapping
92
     @PutMapping
88
     public AjaxResult edit(@RequestBody LedgerCertificateInfo ledgerCertificateInfo) {
93
     public AjaxResult edit(@RequestBody LedgerCertificateInfo ledgerCertificateInfo) {
94
+        String errorMsg = validateCertificateInfo(ledgerCertificateInfo);
95
+        if (errorMsg != null) {
96
+            return error(errorMsg);
97
+        }
89
         return toAjax(certificateInfoService.updateCertificateInfo(ledgerCertificateInfo));
98
         return toAjax(certificateInfoService.updateCertificateInfo(ledgerCertificateInfo));
90
     }
99
     }
91
 
100
 
@@ -126,7 +135,35 @@ public class LedgerCertificateInfoController extends BaseController {
126
      */
135
      */
127
     @PostMapping("/importTemplate")
136
     @PostMapping("/importTemplate")
128
     public void importTemplate(HttpServletResponse response) {
137
     public void importTemplate(HttpServletResponse response) {
129
-        ExcelUtil<LedgerCertificateInfo> util = new ExcelUtil<LedgerCertificateInfo>(LedgerCertificateInfo.class);
138
+        ExcelUtil<LedgerCertificateImportTemplate> util = new ExcelUtil<>(LedgerCertificateImportTemplate.class);
130
         util.importTemplateExcel(response, "证书信息数据");
139
         util.importTemplateExcel(response, "证书信息数据");
131
     }
140
     }
141
+
142
+    /**
143
+     * 校验证书信息必填参数
144
+     * 
145
+     * @param cert 证书信息
146
+     * @return 校验失败返回错误信息,校验通过返回null
147
+     */
148
+    private String validateCertificateInfo(LedgerCertificateInfo cert) {
149
+        if (cert == null) {
150
+            return "证书信息不能为空";
151
+        }
152
+        if (cert.getPersonName() == null || cert.getPersonName().trim().isEmpty()) {
153
+            return "姓名不能为空";
154
+        }
155
+        if (cert.getCertLevel() == null || cert.getCertLevel().trim().isEmpty()) {
156
+            return "证书等级不能为空";
157
+        }
158
+        if (cert.getIssueDate() == null) {
159
+            return "发证日期不能为空";
160
+        }
161
+        if (cert.getServiceMonths() == null) {
162
+            return "服务期(月)不能为空";
163
+        }
164
+        if (cert.getReviewRecords() == null || cert.getReviewRecords().isEmpty()) {
165
+            return "复审记录不能为空";
166
+        }
167
+        return null;
168
+    }
132
 }
169
 }

+ 16 - 6
airport-ledger/src/main/java/com/sundot/airport/ledger/domain/LedgerCertificateInfo.java

@@ -108,7 +108,7 @@ public class LedgerCertificateInfo extends BaseEntity {
108
      * 评定成绩
108
      * 评定成绩
109
      */
109
      */
110
     @Excel(name = "评定成绩")
110
     @Excel(name = "评定成绩")
111
-    private BigDecimal evalScore;
111
+    private String evalScore;
112
 
112
 
113
     /**
113
     /**
114
      * 用工形式
114
      * 用工形式
@@ -126,19 +126,16 @@ public class LedgerCertificateInfo extends BaseEntity {
126
      * 到期日期
126
      * 到期日期
127
      */
127
      */
128
     @JsonFormat(pattern = "yyyy-MM-dd")
128
     @JsonFormat(pattern = "yyyy-MM-dd")
129
-    @Excel(name = "到期日期", width = 30, dateFormat = "yyyy-MM-dd")
130
     private Date expiryDate;
129
     private Date expiryDate;
131
 
130
 
132
     /**
131
     /**
133
      * 状态
132
      * 状态
134
      */
133
      */
135
-    @Excel(name = "状态")
136
     private String status;
134
     private String status;
137
 
135
 
138
     /**
136
     /**
139
      * 到期天数
137
      * 到期天数
140
      */
138
      */
141
-    @Excel(name = "到期天数")
142
     private Integer expireDays;
139
     private Integer expireDays;
143
 
140
 
144
     /**
141
     /**
@@ -148,6 +145,11 @@ public class LedgerCertificateInfo extends BaseEntity {
148
     private String remark;
145
     private String remark;
149
 
146
 
150
     /**
147
     /**
148
+     * 删除标志(0代表存在 2代表删除)
149
+     */
150
+    private String delFlag;
151
+
152
+    /**
151
      * 复审记录列表(非数据库字段)
153
      * 复审记录列表(非数据库字段)
152
      */
154
      */
153
     @TableField(exist = false)
155
     @TableField(exist = false)
@@ -257,11 +259,11 @@ public class LedgerCertificateInfo extends BaseEntity {
257
         return practiceScore;
259
         return practiceScore;
258
     }
260
     }
259
 
261
 
260
-    public void setEvalScore(BigDecimal evalScore) {
262
+    public void setEvalScore(String evalScore) {
261
         this.evalScore = evalScore;
263
         this.evalScore = evalScore;
262
     }
264
     }
263
 
265
 
264
-    public BigDecimal getEvalScore() {
266
+    public String getEvalScore() {
265
         return evalScore;
267
         return evalScore;
266
     }
268
     }
267
 
269
 
@@ -313,6 +315,14 @@ public class LedgerCertificateInfo extends BaseEntity {
313
         return remark;
315
         return remark;
314
     }
316
     }
315
 
317
 
318
+    public void setDelFlag(String delFlag) {
319
+        this.delFlag = delFlag;
320
+    }
321
+
322
+    public String getDelFlag() {
323
+        return delFlag;
324
+    }
325
+
316
     public void setReviewRecords(List<LedgerCertificateReviewRecord> reviewRecords) {
326
     public void setReviewRecords(List<LedgerCertificateReviewRecord> reviewRecords) {
317
         this.reviewRecords = reviewRecords;
327
         this.reviewRecords = reviewRecords;
318
     }
328
     }

+ 14 - 1
airport-ledger/src/main/java/com/sundot/airport/ledger/domain/LedgerCertificateReviewRecord.java

@@ -12,7 +12,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
12
 import org.apache.commons.lang3.builder.ToStringStyle;
12
 import org.apache.commons.lang3.builder.ToStringStyle;
13
 
13
 
14
 /**
14
 /**
15
- * 证书复审记录对象 certificate_review_record
15
+ * 证书复审记录对象 ledger_certificate_review_record
16
  *
16
  *
17
  * @author ruoyi
17
  * @author ruoyi
18
  * @date 2026-06-29
18
  * @date 2026-06-29
@@ -52,6 +52,11 @@ public class LedgerCertificateReviewRecord extends BaseEntity {
52
     @Excel(name = "备注")
52
     @Excel(name = "备注")
53
     private String remark;
53
     private String remark;
54
 
54
 
55
+    /**
56
+     * 删除标志(0代表存在 2代表删除)
57
+     */
58
+    private String delFlag;
59
+
55
     public void setId(Long id) {
60
     public void setId(Long id) {
56
         this.id = id;
61
         this.id = id;
57
     }
62
     }
@@ -84,11 +89,18 @@ public class LedgerCertificateReviewRecord extends BaseEntity {
84
         return reviewTime;
89
         return reviewTime;
85
     }
90
     }
86
 
91
 
92
+    public void setDelFlag(String delFlag) {
93
+        this.delFlag = delFlag;
94
+    }
87
 
95
 
96
+    public String getDelFlag() {
97
+        return delFlag;
98
+    }
88
     public void setRemark(String remark) {
99
     public void setRemark(String remark) {
89
         this.remark = remark;
100
         this.remark = remark;
90
     }
101
     }
91
 
102
 
103
+
92
     public String getRemark() {
104
     public String getRemark() {
93
         return remark;
105
         return remark;
94
     }
106
     }
@@ -101,6 +113,7 @@ public class LedgerCertificateReviewRecord extends BaseEntity {
101
                 .append("reviewSeq", getReviewSeq())
113
                 .append("reviewSeq", getReviewSeq())
102
                 .append("reviewTime", getReviewTime())
114
                 .append("reviewTime", getReviewTime())
103
                 .append("remark", getRemark())
115
                 .append("remark", getRemark())
116
+                .append("delFlag", getDelFlag())
104
                 .toString();
117
                 .toString();
105
     }
118
     }
106
 }
119
 }

+ 0 - 231
airport-ledger/src/main/java/com/sundot/airport/ledger/dto/LedgerCertificateImportDTO.java

@@ -1,231 +0,0 @@
1
-package com.sundot.airport.ledger.dto;
2
-
3
-import java.util.Date;
4
-
5
-import com.sundot.airport.common.annotation.Excel;
6
-import com.sundot.airport.common.core.domain.BaseEntity;
7
-
8
-/**
9
- * 证书信息导入对象(用于Excel导入)
10
- * 
11
- * @author ruoyi
12
- * @date 2026-06-29
13
- */
14
-public class LedgerCertificateImportDTO extends BaseEntity {
15
-    
16
-    @Excel(name = "序号")
17
-    private Integer rowNum;
18
-    
19
-    @Excel(name = "单位")
20
-    private String unitName;
21
-    
22
-    @Excel(name = "姓名")
23
-    private String personName;
24
-    
25
-    @Excel(name = "性别")
26
-    private String gender;
27
-    
28
-    @Excel(name = "出生日期", dateFormat = "yyyy-MM-dd")
29
-    private Date birthDate;
30
-    
31
-    @Excel(name = "身份证号")
32
-    private String idCard;
33
-    
34
-    @Excel(name = "证书等级")
35
-    private String certLevel;
36
-    
37
-    @Excel(name = "发证日期", dateFormat = "yyyy-MM-dd")
38
-    private Date issueDate;
39
-    
40
-    @Excel(name = "证书编号")
41
-    private String certNo;
42
-    
43
-    @Excel(name = "理论考核成绩")
44
-    private Double theoryScore;
45
-    
46
-    @Excel(name = "实操考核成绩")
47
-    private Double practiceScore;
48
-    
49
-    @Excel(name = "评定成绩")
50
-    private Double evalScore;
51
-    
52
-    @Excel(name = "用工形式")
53
-    private String employmentType;
54
-    
55
-    @Excel(name = "服务期(月)")
56
-    private Integer serviceMonths;
57
-    
58
-    @Excel(name = "到期日期", dateFormat = "yyyy-MM-dd")
59
-    private Date expiryDate;
60
-    
61
-    @Excel(name = "状态")
62
-    private String status;
63
-    
64
-    @Excel(name = "到期天数")
65
-    private Integer expireDays;
66
-    
67
-    @Excel(name = "备注")
68
-    private String remark;
69
-    
70
-    // 注意:复审时间不在这里定义,因为数量不固定
71
-    // 在导入时需要动态解析"第1次复审时间"、"第2次复审时间"等列
72
-    
73
-    /**
74
-     * 动态字段:存储所有复审时间
75
-     * Key: 复审次序(1,2,3...)
76
-     * Value: 复审时间
77
-     */
78
-    private java.util.Map<Integer, Date> reviewTimeMap;
79
-
80
-    public Integer getRowNum() {
81
-        return rowNum;
82
-    }
83
-
84
-    public void setRowNum(Integer rowNum) {
85
-        this.rowNum = rowNum;
86
-    }
87
-
88
-    public String getUnitName() {
89
-        return unitName;
90
-    }
91
-
92
-    public void setUnitName(String unitName) {
93
-        this.unitName = unitName;
94
-    }
95
-
96
-    public String getPersonName() {
97
-        return personName;
98
-    }
99
-
100
-    public void setPersonName(String personName) {
101
-        this.personName = personName;
102
-    }
103
-
104
-    public String getGender() {
105
-        return gender;
106
-    }
107
-
108
-    public void setGender(String gender) {
109
-        this.gender = gender;
110
-    }
111
-
112
-    public Date getBirthDate() {
113
-        return birthDate;
114
-    }
115
-
116
-    public void setBirthDate(Date birthDate) {
117
-        this.birthDate = birthDate;
118
-    }
119
-
120
-    public String getIdCard() {
121
-        return idCard;
122
-    }
123
-
124
-    public void setIdCard(String idCard) {
125
-        this.idCard = idCard;
126
-    }
127
-
128
-    public String getCertLevel() {
129
-        return certLevel;
130
-    }
131
-
132
-    public void setCertLevel(String certLevel) {
133
-        this.certLevel = certLevel;
134
-    }
135
-
136
-    public Date getIssueDate() {
137
-        return issueDate;
138
-    }
139
-
140
-    public void setIssueDate(Date issueDate) {
141
-        this.issueDate = issueDate;
142
-    }
143
-
144
-    public String getCertNo() {
145
-        return certNo;
146
-    }
147
-
148
-    public void setCertNo(String certNo) {
149
-        this.certNo = certNo;
150
-    }
151
-
152
-    public Double getTheoryScore() {
153
-        return theoryScore;
154
-    }
155
-
156
-    public void setTheoryScore(Double theoryScore) {
157
-        this.theoryScore = theoryScore;
158
-    }
159
-
160
-    public Double getPracticeScore() {
161
-        return practiceScore;
162
-    }
163
-
164
-    public void setPracticeScore(Double practiceScore) {
165
-        this.practiceScore = practiceScore;
166
-    }
167
-
168
-    public Double getEvalScore() {
169
-        return evalScore;
170
-    }
171
-
172
-    public void setEvalScore(Double evalScore) {
173
-        this.evalScore = evalScore;
174
-    }
175
-
176
-    public String getEmploymentType() {
177
-        return employmentType;
178
-    }
179
-
180
-    public void setEmploymentType(String employmentType) {
181
-        this.employmentType = employmentType;
182
-    }
183
-
184
-    public Integer getServiceMonths() {
185
-        return serviceMonths;
186
-    }
187
-
188
-    public void setServiceMonths(Integer serviceMonths) {
189
-        this.serviceMonths = serviceMonths;
190
-    }
191
-
192
-    public Date getExpiryDate() {
193
-        return expiryDate;
194
-    }
195
-
196
-    public void setExpiryDate(Date expiryDate) {
197
-        this.expiryDate = expiryDate;
198
-    }
199
-
200
-    public String getStatus() {
201
-        return status;
202
-    }
203
-
204
-    public void setStatus(String status) {
205
-        this.status = status;
206
-    }
207
-
208
-    public Integer getExpireDays() {
209
-        return expireDays;
210
-    }
211
-
212
-    public void setExpireDays(Integer expireDays) {
213
-        this.expireDays = expireDays;
214
-    }
215
-
216
-    public String getRemark() {
217
-        return remark;
218
-    }
219
-
220
-    public void setRemark(String remark) {
221
-        this.remark = remark;
222
-    }
223
-
224
-    public java.util.Map<Integer, Date> getReviewTimeMap() {
225
-        return reviewTimeMap;
226
-    }
227
-
228
-    public void setReviewTimeMap(java.util.Map<Integer, Date> reviewTimeMap) {
229
-        this.reviewTimeMap = reviewTimeMap;
230
-    }
231
-}

+ 134 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/dto/LedgerCertificateImportTemplate.java

@@ -0,0 +1,134 @@
1
+package com.sundot.airport.ledger.dto;
2
+
3
+import java.util.Date;
4
+
5
+import com.sundot.airport.common.annotation.Excel;
6
+
7
+/**
8
+ * 证书信息导入模板对象(仅用于生成Excel导入模板,不参与业务逻辑)
9
+ *
10
+ * @author ruoyi
11
+ */
12
+public class LedgerCertificateImportTemplate {
13
+
14
+    @Excel(name = "姓名")
15
+    private String personName;
16
+
17
+    @Excel(name = "单位")
18
+    private String unitName;
19
+
20
+    @Excel(name = "性别", readConverterExp = "男=男,女=女")
21
+    private String gender;
22
+
23
+    @Excel(name = "出生日期", width = 30, dateFormat = "yyyy-MM-dd")
24
+    private Date birthDate;
25
+
26
+    @Excel(name = "身份证号")
27
+    private String idCard;
28
+
29
+    @Excel(name = "证书等级")
30
+    private String certLevel;
31
+
32
+    @Excel(name = "发证日期", width = 30, dateFormat = "yyyy-MM-dd")
33
+    private Date issueDate;
34
+
35
+    @Excel(name = "证书编号")
36
+    private String certNo;
37
+
38
+    @Excel(name = "理论考核成绩")
39
+    private Double theoryScore;
40
+
41
+    @Excel(name = "实操考核成绩")
42
+    private Double practiceScore;
43
+
44
+    @Excel(name = "评定成绩")
45
+    private String evalScore;
46
+
47
+    @Excel(name = "用工形式")
48
+    private String employmentType;
49
+
50
+    @Excel(name = "服务期(月)")
51
+    private Integer serviceMonths;
52
+
53
+    @Excel(name = "备注")
54
+    private String remark;
55
+
56
+    @Excel(name = "第一次复审时间", width = 30, dateFormat = "yyyy-MM-dd")
57
+    private Date reviewTime1;
58
+
59
+    @Excel(name = "第二次复审时间", width = 30, dateFormat = "yyyy-MM-dd")
60
+    private Date reviewTime2;
61
+
62
+    @Excel(name = "第三次复审时间", width = 30, dateFormat = "yyyy-MM-dd")
63
+    private Date reviewTime3;
64
+
65
+    @Excel(name = "第四次复审时间", width = 30, dateFormat = "yyyy-MM-dd")
66
+    private Date reviewTime4;
67
+
68
+    @Excel(name = "第五次复审时间", width = 30, dateFormat = "yyyy-MM-dd")
69
+    private Date reviewTime5;
70
+
71
+    @Excel(name = "第六次复审时间", width = 30, dateFormat = "yyyy-MM-dd")
72
+    private Date reviewTime6;
73
+
74
+
75
+    public String getUnitName() { return unitName; }
76
+    public void setUnitName(String unitName) { this.unitName = unitName; }
77
+
78
+    public String getPersonName() { return personName; }
79
+    public void setPersonName(String personName) { this.personName = personName; }
80
+
81
+    public String getGender() { return gender; }
82
+    public void setGender(String gender) { this.gender = gender; }
83
+
84
+    public Date getBirthDate() { return birthDate; }
85
+    public void setBirthDate(Date birthDate) { this.birthDate = birthDate; }
86
+
87
+    public String getIdCard() { return idCard; }
88
+    public void setIdCard(String idCard) { this.idCard = idCard; }
89
+
90
+    public String getCertLevel() { return certLevel; }
91
+    public void setCertLevel(String certLevel) { this.certLevel = certLevel; }
92
+
93
+    public Date getIssueDate() { return issueDate; }
94
+    public void setIssueDate(Date issueDate) { this.issueDate = issueDate; }
95
+
96
+    public String getCertNo() { return certNo; }
97
+    public void setCertNo(String certNo) { this.certNo = certNo; }
98
+
99
+    public Double getTheoryScore() { return theoryScore; }
100
+    public void setTheoryScore(Double theoryScore) { this.theoryScore = theoryScore; }
101
+
102
+    public Double getPracticeScore() { return practiceScore; }
103
+    public void setPracticeScore(Double practiceScore) { this.practiceScore = practiceScore; }
104
+
105
+    public String getEvalScore() { return evalScore; }
106
+    public void setEvalScore(String evalScore) { this.evalScore = evalScore; }
107
+
108
+    public String getEmploymentType() { return employmentType; }
109
+    public void setEmploymentType(String employmentType) { this.employmentType = employmentType; }
110
+
111
+    public Integer getServiceMonths() { return serviceMonths; }
112
+    public void setServiceMonths(Integer serviceMonths) { this.serviceMonths = serviceMonths; }
113
+
114
+    public String getRemark() { return remark; }
115
+    public void setRemark(String remark) { this.remark = remark; }
116
+
117
+    public Date getReviewTime1() { return reviewTime1; }
118
+    public void setReviewTime1(Date reviewTime1) { this.reviewTime1 = reviewTime1; }
119
+
120
+    public Date getReviewTime2() { return reviewTime2; }
121
+    public void setReviewTime2(Date reviewTime2) { this.reviewTime2 = reviewTime2; }
122
+
123
+    public Date getReviewTime3() { return reviewTime3; }
124
+    public void setReviewTime3(Date reviewTime3) { this.reviewTime3 = reviewTime3; }
125
+
126
+    public Date getReviewTime4() { return reviewTime4; }
127
+    public void setReviewTime4(Date reviewTime4) { this.reviewTime4 = reviewTime4; }
128
+
129
+    public Date getReviewTime5() { return reviewTime5; }
130
+    public void setReviewTime5(Date reviewTime5) { this.reviewTime5 = reviewTime5; }
131
+
132
+    public Date getReviewTime6() { return reviewTime6; }
133
+    public void setReviewTime6(Date reviewTime6) { this.reviewTime6 = reviewTime6; }
134
+}

+ 61 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/enums/CertificateStatusEnum.java

@@ -0,0 +1,61 @@
1
+package com.sundot.airport.ledger.enums;
2
+
3
+import lombok.AllArgsConstructor;
4
+import lombok.Getter;
5
+
6
+/**
7
+ * 证书状态枚举
8
+ * 
9
+ * @author ruoyi
10
+ */
11
+@Getter
12
+@AllArgsConstructor
13
+public enum CertificateStatusEnum {
14
+
15
+    NORMAL("NORMAL", "正常"),
16
+    RETRAINING("RETRAINING", "复训"),
17
+    EXPIRED("EXPIRED", "到期");
18
+
19
+    private final String code;
20
+    private final String desc;
21
+
22
+    /**
23
+     * 根据 code 获取枚举
24
+     */
25
+    public static CertificateStatusEnum getByCode(String code) {
26
+        for (CertificateStatusEnum itemEnum : values()) {
27
+            if (itemEnum.getCode().equals(code)) {
28
+                return itemEnum;
29
+            }
30
+        }
31
+        return null;
32
+    }
33
+
34
+    /**
35
+     * 根据描述获取枚举
36
+     */
37
+    public static CertificateStatusEnum getByDesc(String desc) {
38
+        for (CertificateStatusEnum itemEnum : values()) {
39
+            if (itemEnum.getDesc().equals(desc)) {
40
+                return itemEnum;
41
+            }
42
+        }
43
+        return null;
44
+    }
45
+
46
+    /**
47
+     * 根据到期天数计算证书状态
48
+     * 
49
+     * @param expireDays 到期天数
50
+     * @return 证书状态枚举
51
+     */
52
+    public static CertificateStatusEnum calculateByExpireDays(int expireDays) {
53
+        if (expireDays > 180) {
54
+            return NORMAL;
55
+        } else if (expireDays > 0) {
56
+            return RETRAINING;
57
+        } else {
58
+            return EXPIRED;
59
+        }
60
+    }
61
+}

+ 56 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/mapper/LedgerCertificateInfoMapper.java

@@ -83,4 +83,60 @@ public interface LedgerCertificateInfoMapper {
83
      * @return 证书信息
83
      * @return 证书信息
84
      */
84
      */
85
     public LedgerCertificateInfo selectCertificateInfoByUserIdAndCertNo(@Param("userId") Long userId, @Param("certNo") String certNo);
85
     public LedgerCertificateInfo selectCertificateInfoByUserIdAndCertNo(@Param("userId") Long userId, @Param("certNo") String certNo);
86
+
87
+    /**
88
+     * 根据用户ID和证书等级查询证书信息
89
+     * 
90
+     * @param userId 用户ID
91
+     * @param certLevel 证书等级
92
+     * @return 证书信息
93
+     */
94
+    public LedgerCertificateInfo selectCertificateInfoByUserIdAndCertLevel(@Param("userId") Long userId, @Param("certLevel") String certLevel);
95
+
96
+    /**
97
+     * 根据用户ID查询该用户所有证书信息
98
+     * 
99
+     * @param userId 用户ID
100
+     * @return 证书信息列表
101
+     */
102
+    public List<LedgerCertificateInfo> selectCertificateInfoByUserId(@Param("userId") Long userId);
103
+
104
+    /**
105
+     * 查询所有有效证书信息(用于定时任务)
106
+     * 
107
+     * @return 证书信息列表
108
+     */
109
+    public List<LedgerCertificateInfo> selectAllCertificateInfo();
110
+
111
+    /**
112
+     * 批量更新证书到期信息
113
+     * 
114
+     * @param ledgerCertificateInfo 证书信息(包含expiryDate, expireDays, status)
115
+     * @return 结果
116
+     */
117
+    public int updateCertificateExpiryInfo(LedgerCertificateInfo ledgerCertificateInfo);
118
+
119
+    /**
120
+     * 根据userId和certLevel组合条件批量查询已存在的证书
121
+     * 
122
+     * @param list 证书列表(只需设置userId和certLevel)
123
+     * @return 已存在的证书列表
124
+     */
125
+    List<LedgerCertificateInfo> selectExistingCertificates(@Param("list") List<LedgerCertificateInfo> list);
126
+
127
+    /**
128
+     * 批量插入证书信息
129
+     * 
130
+     * @param list 证书列表
131
+     * @return 结果
132
+     */
133
+    int batchInsertCertificateInfo(@Param("list") List<LedgerCertificateInfo> list);
134
+
135
+    /**
136
+     * 批量更新证书信息
137
+     * 
138
+     * @param list 证书列表
139
+     * @return 结果
140
+     */
141
+    int batchUpdateCertificateInfo(@Param("list") List<LedgerCertificateInfo> list);
86
 }
142
 }

+ 17 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/mapper/LedgerCertificateReviewRecordMapper.java

@@ -1,6 +1,7 @@
1
 package com.sundot.airport.ledger.mapper;
1
 package com.sundot.airport.ledger.mapper;
2
 
2
 
3
 import java.util.List;
3
 import java.util.List;
4
+import org.apache.ibatis.annotations.Param;
4
 import com.sundot.airport.ledger.domain.LedgerCertificateReviewRecord;
5
 import com.sundot.airport.ledger.domain.LedgerCertificateReviewRecord;
5
 
6
 
6
 /**
7
 /**
@@ -73,4 +74,20 @@ public interface LedgerCertificateReviewRecordMapper {
73
      * @return 结果
74
      * @return 结果
74
      */
75
      */
75
     public int deleteCertificateReviewRecordByCertId(Long certId);
76
     public int deleteCertificateReviewRecordByCertId(Long certId);
77
+
78
+    /**
79
+     * 根据多个证书ID批量删除复审记录
80
+     * 
81
+     * @param certIds 证书ID列表
82
+     * @return 结果
83
+     */
84
+    public int deleteReviewRecordsByCertIds(@Param("certIds") List<Long> certIds);
85
+
86
+    /**
87
+     * 批量插入复审记录
88
+     * 
89
+     * @param list 复审记录列表
90
+     * @return 结果
91
+     */
92
+    public int batchInsertReviewRecords(@Param("list") List<LedgerCertificateReviewRecord> list);
76
 }
93
 }

+ 19 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/service/ILedgerCertificateInfoService.java

@@ -67,4 +67,23 @@ public interface ILedgerCertificateInfoService {
67
      * @return 结果
67
      * @return 结果
68
      */
68
      */
69
     public String importCertificate(List<LedgerCertificateInfo> certificateList, Boolean isUpdateSupport, String operName);
69
     public String importCertificate(List<LedgerCertificateInfo> certificateList, Boolean isUpdateSupport, String operName);
70
+
71
+    /**
72
+     * 计算证书到期信息(到期日期、到期天数、状态)
73
+     * 
74
+     * @param certificate 证书信息
75
+     */
76
+    public void calculateExpiryInfo(LedgerCertificateInfo certificate);
77
+
78
+    /**
79
+     * 重新计算用户资质等级(根据用户所有证书到期状态)
80
+     * 
81
+     * @param userId 用户ID
82
+     */
83
+    public void recalculateUserQualification(Long userId);
84
+
85
+    /**
86
+     * 每日定时更新证书到期信息
87
+     */
88
+    public void dailyUpdateExpiryInfo();
70
 }
89
 }

+ 341 - 96
airport-ledger/src/main/java/com/sundot/airport/ledger/service/impl/LedgerLedgerCertificateInfoServiceImpl.java

@@ -1,11 +1,15 @@
1
 package com.sundot.airport.ledger.service.impl;
1
 package com.sundot.airport.ledger.service.impl;
2
 
2
 
3
 import java.util.ArrayList;
3
 import java.util.ArrayList;
4
+import java.util.Calendar;
5
+import java.util.Date;
4
 import java.util.HashMap;
6
 import java.util.HashMap;
5
 import java.util.List;
7
 import java.util.List;
6
 import java.util.Map;
8
 import java.util.Map;
7
 import java.util.stream.Collectors;
9
 import java.util.stream.Collectors;
8
 
10
 
11
+import org.slf4j.Logger;
12
+import org.slf4j.LoggerFactory;
9
 import org.springframework.beans.factory.annotation.Autowired;
13
 import org.springframework.beans.factory.annotation.Autowired;
10
 import org.springframework.stereotype.Service;
14
 import org.springframework.stereotype.Service;
11
 import org.springframework.transaction.annotation.Transactional;
15
 import org.springframework.transaction.annotation.Transactional;
@@ -15,6 +19,7 @@ import com.sundot.airport.ledger.mapper.LedgerCertificateInfoMapper;
15
 import com.sundot.airport.ledger.mapper.LedgerCertificateReviewRecordMapper;
19
 import com.sundot.airport.ledger.mapper.LedgerCertificateReviewRecordMapper;
16
 import com.sundot.airport.ledger.domain.LedgerCertificateInfo;
20
 import com.sundot.airport.ledger.domain.LedgerCertificateInfo;
17
 import com.sundot.airport.ledger.domain.LedgerCertificateReviewRecord;
21
 import com.sundot.airport.ledger.domain.LedgerCertificateReviewRecord;
22
+import com.sundot.airport.ledger.enums.CertificateStatusEnum;
18
 import com.sundot.airport.ledger.service.ILedgerCertificateInfoService;
23
 import com.sundot.airport.ledger.service.ILedgerCertificateInfoService;
19
 import com.sundot.airport.system.service.ISysUserService;
24
 import com.sundot.airport.system.service.ISysUserService;
20
 
25
 
@@ -26,6 +31,8 @@ import com.sundot.airport.system.service.ISysUserService;
26
  */
31
  */
27
 @Service
32
 @Service
28
 public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificateInfoService {
33
 public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificateInfoService {
34
+    private static final Logger log = LoggerFactory.getLogger(LedgerLedgerCertificateInfoServiceImpl.class);
35
+
29
     @Autowired
36
     @Autowired
30
     private LedgerCertificateInfoMapper ledgerCertificateInfoMapper;
37
     private LedgerCertificateInfoMapper ledgerCertificateInfoMapper;
31
 
38
 
@@ -73,11 +80,20 @@ public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificat
73
     @Transactional
80
     @Transactional
74
     public int insertCertificateInfo(LedgerCertificateInfo ledgerCertificateInfo) {
81
     public int insertCertificateInfo(LedgerCertificateInfo ledgerCertificateInfo) {
75
         ledgerCertificateInfo.setCreateTime(DateUtils.getNowDate());
82
         ledgerCertificateInfo.setCreateTime(DateUtils.getNowDate());
83
+        
84
+        // 计算到期信息
85
+        calculateExpiryInfo(ledgerCertificateInfo);
86
+        
76
         int rows = ledgerCertificateInfoMapper.insertCertificateInfo(ledgerCertificateInfo);
87
         int rows = ledgerCertificateInfoMapper.insertCertificateInfo(ledgerCertificateInfo);
77
         
88
         
78
         // 保存复审记录
89
         // 保存复审记录
79
         saveReviewRecords(ledgerCertificateInfo.getId(), ledgerCertificateInfo.getReviewRecords());
90
         saveReviewRecords(ledgerCertificateInfo.getId(), ledgerCertificateInfo.getReviewRecords());
80
         
91
         
92
+        // 同步用户资质等级
93
+        if (ledgerCertificateInfo.getUserId() != null) {
94
+            recalculateUserQualification(ledgerCertificateInfo.getUserId());
95
+        }
96
+        
81
         return rows;
97
         return rows;
82
     }
98
     }
83
 
99
 
@@ -91,12 +107,21 @@ public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificat
91
     @Transactional
107
     @Transactional
92
     public int updateCertificateInfo(LedgerCertificateInfo ledgerCertificateInfo) {
108
     public int updateCertificateInfo(LedgerCertificateInfo ledgerCertificateInfo) {
93
         ledgerCertificateInfo.setUpdateTime(DateUtils.getNowDate());
109
         ledgerCertificateInfo.setUpdateTime(DateUtils.getNowDate());
110
+        
111
+        // 计算到期信息
112
+        calculateExpiryInfo(ledgerCertificateInfo);
113
+        
94
         int rows = ledgerCertificateInfoMapper.updateCertificateInfo(ledgerCertificateInfo);
114
         int rows = ledgerCertificateInfoMapper.updateCertificateInfo(ledgerCertificateInfo);
95
         
115
         
96
         // 先删除旧的复审记录,再保存新的
116
         // 先删除旧的复审记录,再保存新的
97
         ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordByCertId(ledgerCertificateInfo.getId());
117
         ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordByCertId(ledgerCertificateInfo.getId());
98
         saveReviewRecords(ledgerCertificateInfo.getId(), ledgerCertificateInfo.getReviewRecords());
118
         saveReviewRecords(ledgerCertificateInfo.getId(), ledgerCertificateInfo.getReviewRecords());
99
         
119
         
120
+        // 同步用户资质等级
121
+        if (ledgerCertificateInfo.getUserId() != null) {
122
+            recalculateUserQualification(ledgerCertificateInfo.getUserId());
123
+        }
124
+        
100
         return rows;
125
         return rows;
101
     }
126
     }
102
 
127
 
@@ -109,11 +134,23 @@ public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificat
109
     @Override
134
     @Override
110
     @Transactional
135
     @Transactional
111
     public int deleteCertificateInfoByIds(Long[] ids) {
136
     public int deleteCertificateInfoByIds(Long[] ids) {
112
-        // 删除复审记录
137
+        // 收集需要刷新资质的userId
138
+        List<Long> userIds = new ArrayList<>();
113
         for (Long id : ids) {
139
         for (Long id : ids) {
140
+            LedgerCertificateInfo cert = ledgerCertificateInfoMapper.selectCertificateInfoById(id);
141
+            if (cert != null && cert.getUserId() != null) {
142
+                userIds.add(cert.getUserId());
143
+            }
114
             ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordByCertId(id);
144
             ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordByCertId(id);
115
         }
145
         }
116
-        return ledgerCertificateInfoMapper.deleteCertificateInfoByIds(ids);
146
+        int rows = ledgerCertificateInfoMapper.deleteCertificateInfoByIds(ids);
147
+        
148
+        // 同步用户资质等级
149
+        for (Long userId : userIds) {
150
+            recalculateUserQualification(userId);
151
+        }
152
+        
153
+        return rows;
117
     }
154
     }
118
 
155
 
119
     /**
156
     /**
@@ -125,9 +162,17 @@ public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificat
125
     @Override
162
     @Override
126
     @Transactional
163
     @Transactional
127
     public int deleteCertificateInfoById(Long id) {
164
     public int deleteCertificateInfoById(Long id) {
165
+        LedgerCertificateInfo cert = ledgerCertificateInfoMapper.selectCertificateInfoById(id);
128
         // 删除复审记录
166
         // 删除复审记录
129
         ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordByCertId(id);
167
         ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordByCertId(id);
130
-        return ledgerCertificateInfoMapper.deleteCertificateInfoById(id);
168
+        int rows = ledgerCertificateInfoMapper.deleteCertificateInfoById(id);
169
+        
170
+        // 同步用户资质等级
171
+        if (cert != null && cert.getUserId() != null) {
172
+            recalculateUserQualification(cert.getUserId());
173
+        }
174
+        
175
+        return rows;
131
     }
176
     }
132
 
177
 
133
     /**
178
     /**
@@ -145,11 +190,6 @@ public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificat
145
             throw new RuntimeException("导入证书数据不能为空!");
190
             throw new RuntimeException("导入证书数据不能为空!");
146
         }
191
         }
147
         
192
         
148
-        int successNum = 0;
149
-        int failureNum = 0;
150
-        StringBuilder successMsg = new StringBuilder();
151
-        StringBuilder failureMsg = new StringBuilder();
152
-        
153
         // 第一步: 收集所有姓名,批量查询用户信息
193
         // 第一步: 收集所有姓名,批量查询用户信息
154
         List<String> personNames = certificateList.stream()
194
         List<String> personNames = certificateList.stream()
155
                 .map(LedgerCertificateInfo::getPersonName)
195
                 .map(LedgerCertificateInfo::getPersonName)
@@ -163,7 +203,6 @@ public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificat
163
         // 构建姓名到用户的映射 Map<姓名, SysUser>
203
         // 构建姓名到用户的映射 Map<姓名, SysUser>
164
         Map<String, SysUser> userMap = new HashMap<>();
204
         Map<String, SysUser> userMap = new HashMap<>();
165
         for (SysUser user : users) {
205
         for (SysUser user : users) {
166
-            // 优先使用 nickName(用户名称),如果没有则使用 userName(登录名称)
167
             String key = user.getNickName() != null && !user.getNickName().isEmpty() 
206
             String key = user.getNickName() != null && !user.getNickName().isEmpty() 
168
                     ? user.getNickName() : user.getUserName();
207
                     ? user.getNickName() : user.getUserName();
169
             userMap.put(key, user);
208
             userMap.put(key, user);
@@ -177,7 +216,6 @@ public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificat
177
             }
216
             }
178
         }
217
         }
179
         
218
         
180
-        // 如果有未找到的用户,报错提醒
181
         if (!notFoundNames.isEmpty()) {
219
         if (!notFoundNames.isEmpty()) {
182
             throw new RuntimeException("以下人员未在系统中找到:" + String.join("、", notFoundNames));
220
             throw new RuntimeException("以下人员未在系统中找到:" + String.join("、", notFoundNames));
183
         }
221
         }
@@ -191,77 +229,102 @@ public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificat
191
             }
229
             }
192
         }
230
         }
193
         
231
         
194
-        // 第四步: 批量查询已存在的证书信息(根据 userId 和 certNo)
232
+        // 第四步: 批量查询已存在的证书
233
+        List<LedgerCertificateInfo> queryKeys = certificateList.stream()
234
+                .filter(c -> c.getUserId() != null && c.getCertLevel() != null)
235
+                .collect(Collectors.toList());
236
+        
195
         Map<String, LedgerCertificateInfo> existingCertMap = new HashMap<>();
237
         Map<String, LedgerCertificateInfo> existingCertMap = new HashMap<>();
196
-        for (LedgerCertificateInfo certificate : certificateList) {
197
-            if (certificate.getUserId() != null && certificate.getCertNo() != null) {
198
-                LedgerCertificateInfo existCert = ledgerCertificateInfoMapper.selectCertificateInfoByUserIdAndCertNo(
199
-                        certificate.getUserId(), certificate.getCertNo());
200
-                if (existCert != null) {
201
-                    String key = certificate.getUserId() + "_" + certificate.getCertNo();
202
-                    existingCertMap.put(key, existCert);
203
-                }
238
+        if (!queryKeys.isEmpty()) {
239
+            List<LedgerCertificateInfo> existingCerts = ledgerCertificateInfoMapper.selectExistingCertificates(queryKeys);
240
+            for (LedgerCertificateInfo cert : existingCerts) {
241
+                String mapKey = cert.getUserId() + "_" + cert.getCertLevel();
242
+                existingCertMap.put(mapKey, cert);
204
             }
243
             }
205
         }
244
         }
206
         
245
         
207
-        // 第五步: 处理每个证书的导入(新增或更新)
246
+        // 第五步: 分类为新增和更新列表,计算到期信息
247
+        List<LedgerCertificateInfo> toInsert = new ArrayList<>();
248
+        List<LedgerCertificateInfo> toUpdate = new ArrayList<>();
249
+        List<Long> affectedUserIds = new ArrayList<>();
250
+        
208
         for (LedgerCertificateInfo certificate : certificateList) {
251
         for (LedgerCertificateInfo certificate : certificateList) {
209
-            try {
210
-                String key = certificate.getUserId() + "_" + certificate.getCertNo();
211
-                LedgerCertificateInfo existCert = existingCertMap.get(key);
212
-                
213
-                if (existCert != null) {
214
-                    // 存在则更新
215
-                    if (isUpdateSupport) {
216
-                        certificate.setId(existCert.getId());
217
-                        certificate.setUpdateBy(operName);
218
-                        ledgerCertificateInfoMapper.updateCertificateInfo(certificate);
219
-                        
220
-                        // 更新复审记录
221
-                        ledgerCertificateReviewRecordMapper.deleteCertificateReviewRecordByCertId(existCert.getId());
222
-                        saveReviewRecords(existCert.getId(), certificate.getReviewRecords());
223
-                        
224
-                        successNum++;
225
-                        successMsg.append("<br/>").append(successNum).append("、")
226
-                                .append(certificate.getPersonName()).append(" 的证书编号 ")
227
-                                .append(certificate.getCertNo()).append(" 更新成功");
228
-                    } else {
229
-                        failureNum++;
230
-                        failureMsg.append("<br/>").append(failureNum).append("、")
231
-                                .append(certificate.getPersonName()).append(" 的证书编号 ")
232
-                                .append(certificate.getCertNo()).append(" 已存在");
233
-                    }
234
-                } else {
235
-                    // 不存在则新增
236
-                    certificate.setCreateBy(operName);
237
-                    ledgerCertificateInfoMapper.insertCertificateInfo(certificate);
238
-                    
239
-                    // 保存复审记录
240
-                    saveReviewRecords(certificate.getId(), certificate.getReviewRecords());
241
-                    
242
-                    successNum++;
243
-                    successMsg.append("<br/>").append(successNum).append("、")
244
-                            .append(certificate.getPersonName()).append(" 的证书编号 ")
245
-                            .append(certificate.getCertNo()).append(" 导入成功");
252
+            String key = certificate.getUserId() + "_" + certificate.getCertLevel();
253
+            LedgerCertificateInfo existCert = existingCertMap.get(key);
254
+            
255
+            // 计算到期信息
256
+            calculateExpiryInfo(certificate);
257
+            
258
+            if (existCert != null) {
259
+                certificate.setId(existCert.getId());
260
+                certificate.setUpdateBy(operName);
261
+                toUpdate.add(certificate);
262
+            } else {
263
+                certificate.setCreateBy(operName);
264
+                toInsert.add(certificate);
265
+            }
266
+            
267
+            if (!affectedUserIds.contains(certificate.getUserId())) {
268
+                affectedUserIds.add(certificate.getUserId());
269
+            }
270
+        }
271
+        
272
+        // 第六步: 批量新增
273
+        if (!toInsert.isEmpty()) {
274
+            ledgerCertificateInfoMapper.batchInsertCertificateInfo(toInsert);
275
+        }
276
+        
277
+        // 第七步: 批量更新
278
+        if (!toUpdate.isEmpty()) {
279
+            ledgerCertificateInfoMapper.batchUpdateCertificateInfo(toUpdate);
280
+        }
281
+        
282
+        // 第八步: 批量处理复审记录
283
+        // 批量删除需要更新的证书的复审记录
284
+        List<Long> updateCertIds = toUpdate.stream()
285
+                .map(LedgerCertificateInfo::getId)
286
+                .collect(Collectors.toList());
287
+        if (!updateCertIds.isEmpty()) {
288
+            ledgerCertificateReviewRecordMapper.deleteReviewRecordsByCertIds(updateCertIds);
289
+        }
290
+        
291
+        // 批量插入所有复审记录
292
+        List<LedgerCertificateReviewRecord> allReviewRecords = new ArrayList<>();
293
+        for (LedgerCertificateInfo cert : toUpdate) {
294
+            if (cert.getReviewRecords() != null) {
295
+                for (int i = 0; i < cert.getReviewRecords().size(); i++) {
296
+                    LedgerCertificateReviewRecord record = cert.getReviewRecords().get(i);
297
+                    record.setCertId(cert.getId());
298
+                    record.setReviewSeq(i + 1);
299
+                    record.setCreateTime(DateUtils.getNowDate());
300
+                    allReviewRecords.add(record);
301
+                }
302
+            }
303
+        }
304
+        for (LedgerCertificateInfo cert : toInsert) {
305
+            if (cert.getReviewRecords() != null) {
306
+                for (int i = 0; i < cert.getReviewRecords().size(); i++) {
307
+                    LedgerCertificateReviewRecord record = cert.getReviewRecords().get(i);
308
+                    record.setCertId(cert.getId());
309
+                    record.setReviewSeq(i + 1);
310
+                    record.setCreateTime(DateUtils.getNowDate());
311
+                    allReviewRecords.add(record);
246
                 }
312
                 }
247
-                
248
-                // 第六步: 同步更新用户表的证书等级(5<4<3<2<1,数字越小等级越高)
249
-                syncUserQualificationLevel(certificate.getUserId(), certificate.getCertLevel());
250
-                
251
-            } catch (Exception e) {
252
-                failureNum++;
253
-                String msg = "<br/>" + failureNum + "、" + certificate.getPersonName() + " 的证书编号 " 
254
-                        + certificate.getCertNo() + " 导入失败:";
255
-                failureMsg.append(msg + e.getMessage());
256
             }
313
             }
257
         }
314
         }
315
+        if (!allReviewRecords.isEmpty()) {
316
+            ledgerCertificateReviewRecordMapper.batchInsertReviewRecords(allReviewRecords);
317
+        }
258
         
318
         
259
-        if (failureNum > 0) {
260
-            failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
261
-            throw new RuntimeException(failureMsg.toString());
262
-        } else {
263
-            successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
319
+        // 第九步: 刷新所有受影响用户的资质等级
320
+        for (Long userId : affectedUserIds) {
321
+            recalculateUserQualification(userId);
264
         }
322
         }
323
+        
324
+        // 构建返回消息
325
+        int successNum = toInsert.size() + toUpdate.size();
326
+        StringBuilder successMsg = new StringBuilder();
327
+        successMsg.insert(0, "数据已全部导入成功!共 " + successNum + " 条");
265
         return successMsg.toString();
328
         return successMsg.toString();
266
     }
329
     }
267
 
330
 
@@ -276,7 +339,7 @@ public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificat
276
             for (int i = 0; i < reviewRecords.size(); i++) {
339
             for (int i = 0; i < reviewRecords.size(); i++) {
277
                 LedgerCertificateReviewRecord record = reviewRecords.get(i);
340
                 LedgerCertificateReviewRecord record = reviewRecords.get(i);
278
                 record.setCertId(certId);
341
                 record.setCertId(certId);
279
-                record.setReviewSeq(i + 1); // 设置复审次序
342
+                record.setReviewSeq(i + 1);
280
                 record.setCreateTime(DateUtils.getNowDate());
343
                 record.setCreateTime(DateUtils.getNowDate());
281
                 ledgerCertificateReviewRecordMapper.insertCertificateReviewRecord(record);
344
                 ledgerCertificateReviewRecordMapper.insertCertificateReviewRecord(record);
282
             }
345
             }
@@ -284,46 +347,228 @@ public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificat
284
     }
347
     }
285
 
348
 
286
     /**
349
     /**
287
-     * 同步更新用户表的证书等级
288
-     * 等级规则: 5<4<3<2<1 (数字越小等级越高)
289
-     * 如果出现更高等级,就更新用户表
350
+     * 计算证书到期信息(到期日期、到期天数、状态)
351
+     * 到期日期 = 最后复审时间 + 服务期月 - 1天,如果复审时间为空则取发证时间
352
+     * 到期天数 = 到期日期 - 当前时间
353
+     * 状态: >180天=正常, >0且<=180=复训, <=0=到期
290
      * 
354
      * 
291
-     * @param userId 用户ID
292
-     * @param newCertLevel 新证书等级
355
+     * @param certificate 证书信息
293
      */
356
      */
294
-    private void syncUserQualificationLevel(Long userId, String newCertLevel) {
295
-        if (userId == null || newCertLevel == null || newCertLevel.trim().isEmpty()) {
357
+    @Override
358
+    public void calculateExpiryInfo(LedgerCertificateInfo certificate) {
359
+        if (certificate == null) return;
360
+        
361
+        Date baseDate = calculateExpiryBaseDate(certificate);
362
+        if (baseDate == null || certificate.getServiceMonths() == null) {
296
             return;
363
             return;
297
         }
364
         }
298
         
365
         
366
+        // 计算到期日期: baseDate + serviceMonths - 1天
367
+        Date expiryDate = calculateExpiryDate(baseDate, certificate.getServiceMonths());
368
+        certificate.setExpiryDate(expiryDate);
369
+        
370
+        // 计算到期天数
371
+        int expireDays = calculateExpireDays(expiryDate);
372
+        certificate.setExpireDays(expireDays);
373
+        
374
+        // 计算状态
375
+        String status = calculateStatus(expireDays);
376
+        certificate.setStatus(status);
377
+    }
378
+
379
+    /**
380
+     * 计算到期基准日期:取最后复审时间,如果为空则取发证时间
381
+     */
382
+    private Date calculateExpiryBaseDate(LedgerCertificateInfo certificate) {
383
+        // 优先从传入的复审记录中查找(用于新增/导入场景)
384
+        List<LedgerCertificateReviewRecord> reviewRecords = certificate.getReviewRecords();
385
+        
386
+        // 如果没有传入复审记录,从数据库查询
387
+        if ((reviewRecords == null || reviewRecords.isEmpty()) && certificate.getId() != null) {
388
+            reviewRecords = ledgerCertificateReviewRecordMapper.selectCertificateReviewRecordByCertId(certificate.getId());
389
+        }
390
+        
391
+        if (reviewRecords != null && !reviewRecords.isEmpty()) {
392
+            // 找到最新的复审时间(列表最后一个,按 reviewSeq 升序)
393
+            LedgerCertificateReviewRecord latestRecord = reviewRecords.get(reviewRecords.size() - 1);
394
+            if (latestRecord.getReviewTime() != null) {
395
+                return latestRecord.getReviewTime();
396
+            }
397
+        }
398
+        
399
+        // 如果没有复审记录或复审时间为空,取发证时间
400
+        return certificate.getIssueDate();
401
+    }
402
+
403
+    /**
404
+     * 计算到期日期: baseDate + months 月 - 1天
405
+     */
406
+    private Date calculateExpiryDate(Date baseDate, int months) {
407
+        Calendar cal = Calendar.getInstance();
408
+        cal.setTime(baseDate);
409
+        cal.add(Calendar.MONTH, months);
410
+        cal.add(Calendar.DAY_OF_MONTH, -1);
411
+        return cal.getTime();
412
+    }
413
+
414
+    /**
415
+     * 计算到期天数: expiryDate - 当前日期
416
+     */
417
+    private int calculateExpireDays(Date expiryDate) {
418
+        if (expiryDate == null) return 0;
419
+        Date now = DateUtils.getNowDate();
420
+        long diff = expiryDate.getTime() - now.getTime();
421
+        return (int) (diff / (1000 * 60 * 60 * 24));
422
+    }
423
+
424
+    /**
425
+     * 计算状态: >180天=正常, >0且<=180=复训, <=0=到期
426
+     */
427
+    private String calculateStatus(int expireDays) {
428
+        return CertificateStatusEnum.calculateByExpireDays(expireDays).getDesc();
429
+    }
430
+
431
+    /**
432
+     * 重新计算用户资质等级
433
+     * 规则: 查询用户所有证书,找到最高等级(数字最小)且未到期的证书
434
+     * 如果所有证书都到期,则清空资质
435
+     * 
436
+     * @param userId 用户ID
437
+     */
438
+    @Override
439
+    public void recalculateUserQualification(Long userId) {
440
+        if (userId == null) return;
441
+        
299
         try {
442
         try {
300
-            // 查询用户当前资质等级
301
-            SysUser user = sysUserService.selectUserById(userId);
302
-            if (user == null) {
443
+            // 查询用户所有证书
444
+            List<LedgerCertificateInfo> allCerts = ledgerCertificateInfoMapper.selectCertificateInfoByUserId(userId);
445
+            
446
+            if (allCerts == null || allCerts.isEmpty()) {
447
+                // 没有证书,清空资质
448
+                updateUserQualification(userId, null);
303
                 return;
449
                 return;
304
             }
450
             }
305
             
451
             
306
-            String currentLevel = user.getQualificationLevel();
452
+            // 重新计算每张证书的到期信息
453
+            for (LedgerCertificateInfo cert : allCerts) {
454
+                // 对于已有id的证书,查询复审记录来计算到期信息
455
+                Date baseDate = calculateExpiryBaseDate(cert);
456
+                if (baseDate != null && cert.getServiceMonths() != null) {
457
+                    Date expiryDate = calculateExpiryDate(baseDate, cert.getServiceMonths());
458
+                    cert.setExpiryDate(expiryDate);
459
+                    int expireDays = calculateExpireDays(expiryDate);
460
+                    cert.setExpireDays(expireDays);
461
+                    cert.setStatus(calculateStatus(expireDays));
462
+                    
463
+                    // 更新到期信息到数据库
464
+                    ledgerCertificateInfoMapper.updateCertificateExpiryInfo(cert);
465
+                }
466
+            }
467
+            
468
+            // 找到最高等级(数字最小)且未到期的证书
469
+            LedgerCertificateInfo bestValidCert = null;
470
+            int bestLevel = Integer.MAX_VALUE;
307
             
471
             
308
-            // 如果用户当前没有等级,直接设置
309
-            if (currentLevel == null || currentLevel.trim().isEmpty()) {
310
-                updateUserQualificationLevel(userId, newCertLevel);
472
+            for (LedgerCertificateInfo cert : allCerts) {
473
+                // 使用刚计算的状态
474
+                if (!CertificateStatusEnum.EXPIRED.getDesc().equals(cert.getStatus())) {
475
+                    int level = parseLevelToNumber(cert.getCertLevel());
476
+                    if (level < bestLevel) {
477
+                        bestLevel = level;
478
+                        bestValidCert = cert;
479
+                    }
480
+                }
481
+            }
482
+            
483
+            if (bestValidCert != null) {
484
+                // 找到未到期证书,设置资质为最高等级
485
+                String qualificationLevel = convertCertLevelToQualificationFormat(bestValidCert.getCertLevel());
486
+                updateUserQualification(userId, qualificationLevel);
487
+            } else {
488
+                // 所有证书都到期,清空资质
489
+                updateUserQualification(userId, null);
490
+            }
491
+        } catch (Exception e) {
492
+            log.error("重新计算用户资质等级失败, userId={}", userId, e);
493
+        }
494
+    }
495
+
496
+    /**
497
+     * 每日定时更新证书到期信息
498
+     * 更新所有证书的到期日期、到期天数、状态,并同步用户资质等级
499
+     */
500
+    @Override
501
+    public void dailyUpdateExpiryInfo() {
502
+        log.info("========== 开始执行证书到期信息每日更新 ==========");
503
+        
504
+        try {
505
+            // 查询所有有效证书
506
+            List<LedgerCertificateInfo> allCerts = ledgerCertificateInfoMapper.selectAllCertificateInfo();
507
+            
508
+            if (allCerts == null || allCerts.isEmpty()) {
509
+                log.info("没有证书数据需要更新");
311
                 return;
510
                 return;
312
             }
511
             }
313
             
512
             
314
-            // 比较等级高低(数字越小等级越高)
315
-            int currentLevelNum = parseLevelToNumber(currentLevel);
316
-            int newLevelNum = parseLevelToNumber(newCertLevel);
513
+            int updatedCount = 0;
514
+            List<Long> processedUserIds = new ArrayList<>();
317
             
515
             
318
-            // 如果新等级更高,则更新用户表
319
-            if (newLevelNum < currentLevelNum) {
320
-                updateUserQualificationLevel(userId, newCertLevel);
516
+            for (LedgerCertificateInfo cert : allCerts) {
517
+                // 计算到期基准日期
518
+                Date baseDate = calculateExpiryBaseDate(cert);
519
+                if (baseDate != null && cert.getServiceMonths() != null) {
520
+                    Date expiryDate = calculateExpiryDate(baseDate, cert.getServiceMonths());
521
+                    cert.setExpiryDate(expiryDate);
522
+                    int expireDays = calculateExpireDays(expiryDate);
523
+                    cert.setExpireDays(expireDays);
524
+                    cert.setStatus(calculateStatus(expireDays));
525
+                    
526
+                    // 更新到期信息到数据库
527
+                    ledgerCertificateInfoMapper.updateCertificateExpiryInfo(cert);
528
+                    updatedCount++;
529
+                }
530
+                
531
+                // 收集用户ID
532
+                if (cert.getUserId() != null && !processedUserIds.contains(cert.getUserId())) {
533
+                    processedUserIds.add(cert.getUserId());
534
+                }
321
             }
535
             }
536
+            
537
+            log.info("已更新 {} 条证书到期信息", updatedCount);
538
+            
539
+            // 统一刷新所有用户的资质等级
540
+            for (Long userId : processedUserIds) {
541
+                recalculateUserQualification(userId);
542
+            }
543
+            
544
+            log.info("已刷新 {} 个用户的资质等级", processedUserIds.size());
545
+            log.info("========== 证书到期信息每日更新完成 ==========");
546
+            
322
         } catch (Exception e) {
547
         } catch (Exception e) {
323
-            e.printStackTrace();
548
+            log.error("证书到期信息每日更新失败", e);
324
         }
549
         }
325
     }
550
     }
326
-    
551
+
552
+    /**
553
+     * 将证书等级格式转换为资质等级格式
554
+     * 如: "一级" -> "LEVEL_ONE", "2" -> "LEVEL_TWO"
555
+     */
556
+    private String convertCertLevelToQualificationFormat(String certLevel) {
557
+        if (certLevel == null || certLevel.trim().isEmpty()) return null;
558
+        
559
+        certLevel = certLevel.trim();
560
+        
561
+        if (certLevel.contains("一") || certLevel.equals("1")) return "LEVEL_ONE";
562
+        if (certLevel.contains("二") || certLevel.equals("2")) return "LEVEL_TWO";
563
+        if (certLevel.contains("三") || certLevel.equals("3")) return "LEVEL_THREE";
564
+        if (certLevel.contains("四") || certLevel.equals("4")) return "LEVEL_FOUR";
565
+        if (certLevel.contains("五") || certLevel.equals("5")) return "LEVEL_FIVE";
566
+        
567
+        if (certLevel.toUpperCase().startsWith("LEVEL_")) return certLevel.toUpperCase();
568
+        
569
+        return certLevel;
570
+    }
571
+
327
     /**
572
     /**
328
      * 将等级字符串转换为数字进行比较
573
      * 将等级字符串转换为数字进行比较
329
      * 支持格式: "一级"、"LEVEL_ONE"、"1" 等
574
      * 支持格式: "一级"、"LEVEL_ONE"、"1" 等
@@ -367,14 +612,14 @@ public class LedgerLedgerCertificateInfoServiceImpl implements ILedgerCertificat
367
      * @param userId 用户ID
612
      * @param userId 用户ID
368
      * @param qualificationLevel 资质等级
613
      * @param qualificationLevel 资质等级
369
      */
614
      */
370
-    private void updateUserQualificationLevel(Long userId, String qualificationLevel) {
615
+    private void updateUserQualification(Long userId, String qualificationLevel) {
371
         try {
616
         try {
372
             SysUser user = new SysUser();
617
             SysUser user = new SysUser();
373
             user.setUserId(userId);
618
             user.setUserId(userId);
374
             user.setQualificationLevel(qualificationLevel);
619
             user.setQualificationLevel(qualificationLevel);
375
             sysUserService.updateUserProfile(user);
620
             sysUserService.updateUserProfile(user);
376
         } catch (Exception e) {
621
         } catch (Exception e) {
377
-            e.printStackTrace();
622
+            log.error("更新用户资质等级失败, userId={}, level={}", userId, qualificationLevel, e);
378
         }
623
         }
379
     }
624
     }
380
 }
625
 }

+ 79 - 0
airport-ledger/src/main/resources/mapper/personnel/LedgerCertificateInfoMapper.xml

@@ -94,6 +94,31 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
94
         <include refid="selectCertificateInfoVo"/>
94
         <include refid="selectCertificateInfoVo"/>
95
         where user_id = #{userId} and cert_no = #{certNo} and del_flag = '0' limit 1
95
         where user_id = #{userId} and cert_no = #{certNo} and del_flag = '0' limit 1
96
     </select>
96
     </select>
97
+
98
+    <select id="selectCertificateInfoByUserIdAndCertLevel" resultMap="CertificateInfoResult">
99
+        <include refid="selectCertificateInfoVo"/>
100
+        where user_id = #{userId} and cert_level = #{certLevel} and del_flag = '0' limit 1
101
+    </select>
102
+
103
+    <select id="selectCertificateInfoByUserId" resultMap="CertificateInfoResult">
104
+        <include refid="selectCertificateInfoVo"/>
105
+        where user_id = #{userId} and del_flag = '0'
106
+        order by cert_level asc
107
+    </select>
108
+
109
+    <select id="selectAllCertificateInfo" resultMap="CertificateInfoResult">
110
+        <include refid="selectCertificateInfoVo"/>
111
+        where del_flag = '0'
112
+    </select>
113
+
114
+    <update id="updateCertificateExpiryInfo" parameterType="LedgerCertificateInfo">
115
+        update ledger_certificate_info
116
+        set expiry_date = #{expiryDate},
117
+            expire_days = #{expireDays},
118
+            status = #{status},
119
+            update_time = sysdate()
120
+        where id = #{id}
121
+    </update>
97
         
122
         
98
     <insert id="insertCertificateInfo" parameterType="LedgerCertificateInfo" useGeneratedKeys="true" keyProperty="id">
123
     <insert id="insertCertificateInfo" parameterType="LedgerCertificateInfo" useGeneratedKeys="true" keyProperty="id">
99
         insert into ledger_certificate_info
124
         insert into ledger_certificate_info
@@ -185,4 +210,58 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
185
             #{id}
210
             #{id}
186
         </foreach>
211
         </foreach>
187
     </delete>
212
     </delete>
213
+
214
+    <select id="selectExistingCertificates" resultMap="CertificateInfoResult">
215
+        <include refid="selectCertificateInfoVo"/>
216
+        where del_flag = '0' and (
217
+        <foreach collection="list" item="item" separator=" OR ">
218
+            (user_id = #{item.userId} AND cert_level = #{item.certLevel})
219
+        </foreach>
220
+        )
221
+    </select>
222
+
223
+    <insert id="batchInsertCertificateInfo" useGeneratedKeys="true" keyProperty="list.id">
224
+        insert into ledger_certificate_info
225
+        (tenant_id, unit_name, user_id, person_name, gender, birth_date, id_card,
226
+         cert_level, issue_date, cert_no, theory_score, practice_score, eval_score,
227
+         employment_type, service_months, expiry_date, status, expire_days, remark,
228
+         create_by, create_time, del_flag)
229
+        values
230
+        <foreach collection="list" item="item" separator=",">
231
+            (#{item.tenantId}, #{item.unitName}, #{item.userId}, #{item.personName},
232
+             #{item.gender}, #{item.birthDate}, #{item.idCard}, #{item.certLevel},
233
+             #{item.issueDate}, #{item.certNo}, #{item.theoryScore}, #{item.practiceScore},
234
+             #{item.evalScore}, #{item.employmentType}, #{item.serviceMonths},
235
+             #{item.expiryDate}, #{item.status}, #{item.expireDays}, #{item.remark},
236
+             #{item.createBy}, sysdate(), '0')
237
+        </foreach>
238
+    </insert>
239
+
240
+    <update id="batchUpdateCertificateInfo">
241
+        <foreach collection="list" item="item" separator=";">
242
+            update ledger_certificate_info
243
+            set tenant_id = #{item.tenantId},
244
+                unit_name = #{item.unitName},
245
+                user_id = #{item.userId},
246
+                person_name = #{item.personName},
247
+                gender = #{item.gender},
248
+                birth_date = #{item.birthDate},
249
+                id_card = #{item.idCard},
250
+                cert_level = #{item.certLevel},
251
+                issue_date = #{item.issueDate},
252
+                cert_no = #{item.certNo},
253
+                theory_score = #{item.theoryScore},
254
+                practice_score = #{item.practiceScore},
255
+                eval_score = #{item.evalScore},
256
+                employment_type = #{item.employmentType},
257
+                service_months = #{item.serviceMonths},
258
+                expiry_date = #{item.expiryDate},
259
+                status = #{item.status},
260
+                expire_days = #{item.expireDays},
261
+                remark = #{item.remark},
262
+                update_by = #{item.updateBy},
263
+                update_time = sysdate()
264
+            where id = #{item.id}
265
+        </foreach>
266
+    </update>
188
 </mapper>
267
 </mapper>

+ 23 - 6
airport-ledger/src/main/resources/mapper/personnel/LedgerCertificateReviewRecordMapper.xml

@@ -20,7 +20,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
20
     <sql id="selectCertificateReviewRecordVo">
20
     <sql id="selectCertificateReviewRecordVo">
21
         select id, cert_id, review_seq, review_time,  remark,
21
         select id, cert_id, review_seq, review_time,  remark,
22
                create_by, create_time, update_by, update_time, del_flag
22
                create_by, create_time, update_by, update_time, del_flag
23
-        from certificate_review_record
23
+        from ledger_certificate_review_record
24
     </sql>
24
     </sql>
25
 
25
 
26
     <select id="selectCertificateReviewRecordList" parameterType="LedgerCertificateReviewRecord" resultMap="CertificateReviewRecordResult">
26
     <select id="selectCertificateReviewRecordList" parameterType="LedgerCertificateReviewRecord" resultMap="CertificateReviewRecordResult">
@@ -51,7 +51,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
51
     </select>
51
     </select>
52
         
52
         
53
     <insert id="insertCertificateReviewRecord" parameterType="LedgerCertificateReviewRecord" useGeneratedKeys="true" keyProperty="id">
53
     <insert id="insertCertificateReviewRecord" parameterType="LedgerCertificateReviewRecord" useGeneratedKeys="true" keyProperty="id">
54
-        insert into certificate_review_record
54
+        insert into ledger_certificate_review_record
55
         <trim prefix="(" suffix=")" suffixOverrides=",">
55
         <trim prefix="(" suffix=")" suffixOverrides=",">
56
             <if test="certId != null">cert_id,</if>
56
             <if test="certId != null">cert_id,</if>
57
             <if test="reviewSeq != null">review_seq,</if>
57
             <if test="reviewSeq != null">review_seq,</if>
@@ -73,7 +73,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
73
     </insert>
73
     </insert>
74
 
74
 
75
     <update id="updateCertificateReviewRecord" parameterType="LedgerCertificateReviewRecord">
75
     <update id="updateCertificateReviewRecord" parameterType="LedgerCertificateReviewRecord">
76
-        update certificate_review_record
76
+        update ledger_certificate_review_record
77
         <trim prefix="SET" suffixOverrides=",">
77
         <trim prefix="SET" suffixOverrides=",">
78
             <if test="certId != null">cert_id = #{certId},</if>
78
             <if test="certId != null">cert_id = #{certId},</if>
79
             <if test="reviewSeq != null">review_seq = #{reviewSeq},</if>
79
             <if test="reviewSeq != null">review_seq = #{reviewSeq},</if>
@@ -86,17 +86,34 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
86
     </update>
86
     </update>
87
 
87
 
88
     <delete id="deleteCertificateReviewRecordById" parameterType="Long">
88
     <delete id="deleteCertificateReviewRecordById" parameterType="Long">
89
-        update certificate_review_record set del_flag = '2' where id = #{id}
89
+        update ledger_certificate_review_record set del_flag = '2' where id = #{id}
90
     </delete>
90
     </delete>
91
 
91
 
92
     <delete id="deleteCertificateReviewRecordByIds" parameterType="Long">
92
     <delete id="deleteCertificateReviewRecordByIds" parameterType="Long">
93
-        update certificate_review_record set del_flag = '2' where id in
93
+        update ledger_certificate_review_record set del_flag = '2' where id in
94
         <foreach item="id" collection="array" open="(" separator="," close=")">
94
         <foreach item="id" collection="array" open="(" separator="," close=")">
95
             #{id}
95
             #{id}
96
         </foreach>
96
         </foreach>
97
     </delete>
97
     </delete>
98
 
98
 
99
     <delete id="deleteCertificateReviewRecordByCertId" parameterType="Long">
99
     <delete id="deleteCertificateReviewRecordByCertId" parameterType="Long">
100
-        update certificate_review_record set del_flag = '2' where cert_id = #{certId}
100
+        update ledger_certificate_review_record set del_flag = '2' where cert_id = #{certId}
101
     </delete>
101
     </delete>
102
+
103
+    <delete id="deleteReviewRecordsByCertIds">
104
+        update ledger_certificate_review_record set del_flag = '2' where cert_id in
105
+        <foreach collection="certIds" item="certId" open="(" separator="," close=")">
106
+            #{certId}
107
+        </foreach>
108
+    </delete>
109
+
110
+    <insert id="batchInsertReviewRecords">
111
+        insert into ledger_certificate_review_record
112
+        (cert_id, review_seq, review_time, remark, create_by, create_time, del_flag)
113
+        values
114
+        <foreach collection="list" item="item" separator=",">
115
+            (#{item.certId}, #{item.reviewSeq}, #{item.reviewTime}, #{item.remark},
116
+             #{item.createBy}, sysdate(), '0')
117
+        </foreach>
118
+    </insert>
102
 </mapper>
119
 </mapper>

+ 4 - 0
airport-quartz/pom.xml

@@ -42,6 +42,10 @@
42
             <groupId>com.sundot.airport</groupId>
42
             <groupId>com.sundot.airport</groupId>
43
             <artifactId>airport-exam</artifactId>
43
             <artifactId>airport-exam</artifactId>
44
         </dependency>
44
         </dependency>
45
+        <dependency>
46
+            <groupId>com.sundot.airport</groupId>
47
+            <artifactId>airport-ledger</artifactId>
48
+        </dependency>
45
 
49
 
46
     </dependencies>
50
     </dependencies>
47
 
51
 

+ 55 - 0
airport-quartz/src/main/java/com/sundot/airport/quartz/task/CertificateExpiryTask.java

@@ -0,0 +1,55 @@
1
+package com.sundot.airport.quartz.task;
2
+
3
+import org.slf4j.Logger;
4
+import org.slf4j.LoggerFactory;
5
+import org.springframework.beans.factory.annotation.Autowired;
6
+import org.springframework.stereotype.Component;
7
+import com.sundot.airport.ledger.service.ILedgerCertificateInfoService;
8
+import org.springframework.web.bind.annotation.RequestMapping;
9
+
10
+/**
11
+ * 证书到期信息每日更新定时任务
12
+ * 
13
+ * <p>
14
+ * 定时任务配置说明:
15
+ * - 执行时间:每天凌晨2:00执行
16
+ * - Cron表达式:0 0 2 * * ?
17
+ * - 调用目标:certificateExpiryTask.updateExpiryInfo
18
+ * </p>
19
+ * 
20
+ * @author ruoyi
21
+ */
22
+@Component("certificateExpiryTask")
23
+public class CertificateExpiryTask {
24
+
25
+    private static final Logger log = LoggerFactory.getLogger(CertificateExpiryTask.class);
26
+
27
+    @Autowired
28
+    private ILedgerCertificateInfoService certificateInfoService;
29
+
30
+    /**
31
+     * 每日更新证书到期信息
32
+     * <p>
33
+     * 更新所有证书的到期日期、到期天数、状态,并同步更新用户资质等级
34
+     * </p>
35
+     */
36
+    public void updateExpiryInfo() {
37
+        try {
38
+            log.info("========== 开始执行证书到期信息每日更新任务 ==========");
39
+            
40
+            certificateInfoService.dailyUpdateExpiryInfo();
41
+            
42
+            log.info("========== 证书到期信息每日更新任务执行完成 ==========");
43
+        } catch (Exception e) {
44
+            log.error("执行证书到期信息每日更新任务失败", e);
45
+        }
46
+    }
47
+
48
+    /**
49
+     * 手动触发证书到期信息更新(用于测试)
50
+     */
51
+    public void updateExpiryInfoManual() {
52
+        log.info("手动触发证书到期信息更新");
53
+        updateExpiryInfo();
54
+    }
55
+}