|
|
@@ -4,14 +4,18 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
4
|
4
|
import com.huimv.employment.common.exception.BizException;
|
|
5
|
5
|
import com.huimv.employment.common.exception.ErrorCode;
|
|
6
|
6
|
import com.huimv.employment.dao.entity.FeEmploymentOrder;
|
|
|
7
|
+import com.huimv.employment.dao.entity.FeEnterprise;
|
|
7
|
8
|
import com.huimv.employment.dao.entity.FeRegistrationBatch;
|
|
8
|
9
|
import com.huimv.employment.dao.entity.FeWorker;
|
|
9
|
10
|
import com.huimv.employment.dao.entity.FeWorkerRegistration;
|
|
10
|
11
|
import com.huimv.employment.dao.mapper.FeEmploymentOrderMapper;
|
|
11
|
12
|
import com.huimv.employment.dao.mapper.FeRegistrationBatchMapper;
|
|
12
|
13
|
import com.huimv.employment.dao.mapper.FeWorkerRegistrationMapper;
|
|
|
14
|
+import com.huimv.employment.service.enterprise.EnterpriseService;
|
|
13
|
15
|
import com.huimv.employment.service.registration.dto.WorkerRegistrationApplyRequest;
|
|
14
|
16
|
import com.huimv.employment.service.registration.dto.WorkerRegistrationApplyResponse;
|
|
|
17
|
+import com.huimv.employment.service.registration.dto.WorkerRegistrationRejectRequest;
|
|
|
18
|
+import com.huimv.employment.service.registration.dto.WorkerRegistrationReviewResponse;
|
|
15
|
19
|
import com.huimv.employment.service.worker.WorkerService;
|
|
16
|
20
|
import org.springframework.stereotype.Service;
|
|
17
|
21
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
@@ -20,29 +24,40 @@ import org.springframework.util.StringUtils;
|
|
20
|
24
|
import java.time.LocalDateTime;
|
|
21
|
25
|
|
|
22
|
26
|
/**
|
|
23
|
|
- * 用工邀请 / 批次登记:临时工扫码后申请加入。
|
|
|
27
|
+ * 用工邀请 / 批次登记:临时工扫码申请;企业主审核通过/驳回。
|
|
24
|
28
|
*/
|
|
25
|
29
|
@Service
|
|
26
|
30
|
public class WorkerRegistrationService {
|
|
27
|
31
|
|
|
28
|
32
|
private static final String BATCH_ACTIVE = "active";
|
|
29
|
33
|
private static final String REG_UNDER_REVIEW = "under_review";
|
|
|
34
|
+ private static final String REG_COMPLETED = "completed";
|
|
|
35
|
+ /** 企业审核驳回(与实名核验失败 verify_failed 区分) */
|
|
|
36
|
+ private static final String REG_REJECTED = "rejected";
|
|
|
37
|
+ private static final String STEP_REGISTRATION = "registration";
|
|
|
38
|
+ private static final String STEP_ENTERPRISE_AUDIT = "enterprise_audit";
|
|
30
|
39
|
private static final String APPLY_SUCCESS = "success";
|
|
31
|
40
|
private static final String APPLY_ALREADY = "already_applied";
|
|
|
41
|
+ private static final String REVIEW_APPROVED = "approved";
|
|
|
42
|
+ private static final String REVIEW_REJECTED = "rejected";
|
|
|
43
|
+ private static final String REVIEW_ALREADY = "already_reviewed";
|
|
32
|
44
|
|
|
33
|
45
|
private final FeRegistrationBatchMapper feRegistrationBatchMapper;
|
|
34
|
46
|
private final FeEmploymentOrderMapper feEmploymentOrderMapper;
|
|
35
|
47
|
private final FeWorkerRegistrationMapper feWorkerRegistrationMapper;
|
|
36
|
48
|
private final WorkerService workerService;
|
|
|
49
|
+ private final EnterpriseService enterpriseService;
|
|
37
|
50
|
|
|
38
|
51
|
public WorkerRegistrationService(FeRegistrationBatchMapper feRegistrationBatchMapper,
|
|
39
|
52
|
FeEmploymentOrderMapper feEmploymentOrderMapper,
|
|
40
|
53
|
FeWorkerRegistrationMapper feWorkerRegistrationMapper,
|
|
41
|
|
- WorkerService workerService) {
|
|
|
54
|
+ WorkerService workerService,
|
|
|
55
|
+ EnterpriseService enterpriseService) {
|
|
42
|
56
|
this.feRegistrationBatchMapper = feRegistrationBatchMapper;
|
|
43
|
57
|
this.feEmploymentOrderMapper = feEmploymentOrderMapper;
|
|
44
|
58
|
this.feWorkerRegistrationMapper = feWorkerRegistrationMapper;
|
|
45
|
59
|
this.workerService = workerService;
|
|
|
60
|
+ this.enterpriseService = enterpriseService;
|
|
46
|
61
|
}
|
|
47
|
62
|
|
|
48
|
63
|
/**
|
|
|
@@ -108,6 +123,186 @@ public class WorkerRegistrationService {
|
|
108
|
123
|
return toResponse(reg, batch, order, APPLY_SUCCESS, "申请已提交,请等待企业确认");
|
|
109
|
124
|
}
|
|
110
|
125
|
|
|
|
126
|
+ /**
|
|
|
127
|
+ * 企业审核通过用工登记。
|
|
|
128
|
+ * <p>仅 {@code under_review} 可审核;写 reviewed_*,登记置 completed,批次 completed_count+1;
|
|
|
129
|
+ * 若订单仍停在 registration 则推进到 enterprise_audit。</p>
|
|
|
130
|
+ */
|
|
|
131
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
132
|
+ public WorkerRegistrationReviewResponse approve(Long userId, Long registrationId) {
|
|
|
133
|
+ enterpriseService.requireEnterpriseUser(userId);
|
|
|
134
|
+ FeEnterprise enterprise = requireEnterpriseOfUser(userId);
|
|
|
135
|
+ FeWorkerRegistration reg = requireOwnedRegistration(enterprise.getId(), registrationId);
|
|
|
136
|
+ FeRegistrationBatch batch = requireBatch(reg.getBatchId());
|
|
|
137
|
+ FeEmploymentOrder order = requireOrder(reg.getOrderId());
|
|
|
138
|
+
|
|
|
139
|
+ if (REG_COMPLETED.equals(reg.getRegStatus())) {
|
|
|
140
|
+ return toReviewResponse(reg, batch, order, REVIEW_ALREADY, "该登记已审核通过");
|
|
|
141
|
+ }
|
|
|
142
|
+ if (REG_REJECTED.equals(reg.getRegStatus())) {
|
|
|
143
|
+ throw new BizException(ErrorCode.BAD_REQUEST, "该登记已被驳回,无法再通过");
|
|
|
144
|
+ }
|
|
|
145
|
+ if (!REG_UNDER_REVIEW.equals(reg.getRegStatus())) {
|
|
|
146
|
+ throw new BizException(ErrorCode.BAD_REQUEST, "当前状态不可审核:" + reg.getRegStatus());
|
|
|
147
|
+ }
|
|
|
148
|
+
|
|
|
149
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
150
|
+ FeWorkerRegistration update = new FeWorkerRegistration();
|
|
|
151
|
+ update.setId(reg.getId());
|
|
|
152
|
+ update.setRegStatus(REG_COMPLETED);
|
|
|
153
|
+ update.setFailReason(null);
|
|
|
154
|
+ update.setReviewedAt(now);
|
|
|
155
|
+ update.setReviewedBy(userId);
|
|
|
156
|
+ update.setUpdateTime(now);
|
|
|
157
|
+ feWorkerRegistrationMapper.updateById(update);
|
|
|
158
|
+
|
|
|
159
|
+ reg.setRegStatus(REG_COMPLETED);
|
|
|
160
|
+ reg.setFailReason(null);
|
|
|
161
|
+ reg.setReviewedAt(now);
|
|
|
162
|
+ reg.setReviewedBy(userId);
|
|
|
163
|
+
|
|
|
164
|
+ bumpCompletedCounters(batch, now);
|
|
|
165
|
+ maybeAdvanceOrderToEnterpriseAudit(order, now);
|
|
|
166
|
+
|
|
|
167
|
+ // 回读订单步骤
|
|
|
168
|
+ order = feEmploymentOrderMapper.selectById(order.getId());
|
|
|
169
|
+ return toReviewResponse(reg, batch, order, REVIEW_APPROVED, "审核通过");
|
|
|
170
|
+ }
|
|
|
171
|
+
|
|
|
172
|
+ /**
|
|
|
173
|
+ * 企业驳回用工登记。
|
|
|
174
|
+ * <p>仅 {@code under_review} 可驳回;写 fail_reason / reviewed_*,登记置 rejected,并释放名额(registered-1、pending+1)。</p>
|
|
|
175
|
+ */
|
|
|
176
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
177
|
+ public WorkerRegistrationReviewResponse reject(Long userId, Long registrationId,
|
|
|
178
|
+ WorkerRegistrationRejectRequest request) {
|
|
|
179
|
+ enterpriseService.requireEnterpriseUser(userId);
|
|
|
180
|
+ FeEnterprise enterprise = requireEnterpriseOfUser(userId);
|
|
|
181
|
+ if (request == null || !StringUtils.hasText(request.getFailReason())) {
|
|
|
182
|
+ throw new BizException(ErrorCode.BAD_REQUEST, "驳回原因不能为空");
|
|
|
183
|
+ }
|
|
|
184
|
+ String reason = request.getFailReason().trim();
|
|
|
185
|
+ if (reason.length() > 500) {
|
|
|
186
|
+ throw new BizException(ErrorCode.BAD_REQUEST, "驳回原因过长");
|
|
|
187
|
+ }
|
|
|
188
|
+
|
|
|
189
|
+ FeWorkerRegistration reg = requireOwnedRegistration(enterprise.getId(), registrationId);
|
|
|
190
|
+ FeRegistrationBatch batch = requireBatch(reg.getBatchId());
|
|
|
191
|
+ FeEmploymentOrder order = requireOrder(reg.getOrderId());
|
|
|
192
|
+
|
|
|
193
|
+ if (REG_REJECTED.equals(reg.getRegStatus())) {
|
|
|
194
|
+ return toReviewResponse(reg, batch, order, REVIEW_ALREADY, "该登记已驳回");
|
|
|
195
|
+ }
|
|
|
196
|
+ if (REG_COMPLETED.equals(reg.getRegStatus())) {
|
|
|
197
|
+ throw new BizException(ErrorCode.BAD_REQUEST, "该登记已审核通过,无法驳回");
|
|
|
198
|
+ }
|
|
|
199
|
+ if (!REG_UNDER_REVIEW.equals(reg.getRegStatus())) {
|
|
|
200
|
+ throw new BizException(ErrorCode.BAD_REQUEST, "当前状态不可驳回:" + reg.getRegStatus());
|
|
|
201
|
+ }
|
|
|
202
|
+
|
|
|
203
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
204
|
+ FeWorkerRegistration update = new FeWorkerRegistration();
|
|
|
205
|
+ update.setId(reg.getId());
|
|
|
206
|
+ update.setRegStatus(REG_REJECTED);
|
|
|
207
|
+ update.setFailReason(reason);
|
|
|
208
|
+ update.setReviewedAt(now);
|
|
|
209
|
+ update.setReviewedBy(userId);
|
|
|
210
|
+ update.setUpdateTime(now);
|
|
|
211
|
+ feWorkerRegistrationMapper.updateById(update);
|
|
|
212
|
+
|
|
|
213
|
+ reg.setRegStatus(REG_REJECTED);
|
|
|
214
|
+ reg.setFailReason(reason);
|
|
|
215
|
+ reg.setReviewedAt(now);
|
|
|
216
|
+ reg.setReviewedBy(userId);
|
|
|
217
|
+
|
|
|
218
|
+ releaseSlotCounters(batch, order, now);
|
|
|
219
|
+
|
|
|
220
|
+ return toReviewResponse(reg, batch, order, REVIEW_REJECTED, "已驳回");
|
|
|
221
|
+ }
|
|
|
222
|
+
|
|
|
223
|
+ private FeEnterprise requireEnterpriseOfUser(Long userId) {
|
|
|
224
|
+ FeEnterprise enterprise = enterpriseService.findEnterpriseByUserId(userId);
|
|
|
225
|
+ if (enterprise == null) {
|
|
|
226
|
+ throw new BizException(ErrorCode.NOT_FOUND, "企业信息不存在");
|
|
|
227
|
+ }
|
|
|
228
|
+ return enterprise;
|
|
|
229
|
+ }
|
|
|
230
|
+
|
|
|
231
|
+ private FeWorkerRegistration requireOwnedRegistration(Long enterpriseId, Long registrationId) {
|
|
|
232
|
+ if (registrationId == null) {
|
|
|
233
|
+ throw new BizException(ErrorCode.BAD_REQUEST, "registration_id 不能为空");
|
|
|
234
|
+ }
|
|
|
235
|
+ FeWorkerRegistration reg = feWorkerRegistrationMapper.selectById(registrationId);
|
|
|
236
|
+ if (reg == null) {
|
|
|
237
|
+ throw new BizException(ErrorCode.NOT_FOUND, "登记记录不存在");
|
|
|
238
|
+ }
|
|
|
239
|
+ if (reg.getEnterpriseId() == null || !reg.getEnterpriseId().equals(enterpriseId)) {
|
|
|
240
|
+ throw new BizException(ErrorCode.FORBIDDEN, "无权审核该登记");
|
|
|
241
|
+ }
|
|
|
242
|
+ return reg;
|
|
|
243
|
+ }
|
|
|
244
|
+
|
|
|
245
|
+ private FeRegistrationBatch requireBatch(Long batchId) {
|
|
|
246
|
+ FeRegistrationBatch batch = feRegistrationBatchMapper.selectById(batchId);
|
|
|
247
|
+ if (batch == null) {
|
|
|
248
|
+ throw new BizException(ErrorCode.NOT_FOUND, "登记批次不存在");
|
|
|
249
|
+ }
|
|
|
250
|
+ return batch;
|
|
|
251
|
+ }
|
|
|
252
|
+
|
|
|
253
|
+ private FeEmploymentOrder requireOrder(Long orderId) {
|
|
|
254
|
+ FeEmploymentOrder order = feEmploymentOrderMapper.selectById(orderId);
|
|
|
255
|
+ if (order == null) {
|
|
|
256
|
+ throw new BizException(ErrorCode.NOT_FOUND, "用工订单不存在");
|
|
|
257
|
+ }
|
|
|
258
|
+ return order;
|
|
|
259
|
+ }
|
|
|
260
|
+
|
|
|
261
|
+ private void bumpCompletedCounters(FeRegistrationBatch batch, LocalDateTime now) {
|
|
|
262
|
+ int completed = batch.getCompletedCount() != null ? batch.getCompletedCount() : 0;
|
|
|
263
|
+ FeRegistrationBatch update = new FeRegistrationBatch();
|
|
|
264
|
+ update.setId(batch.getId());
|
|
|
265
|
+ update.setCompletedCount(completed + 1);
|
|
|
266
|
+ update.setUpdateTime(now);
|
|
|
267
|
+ feRegistrationBatchMapper.updateById(update);
|
|
|
268
|
+ batch.setCompletedCount(completed + 1);
|
|
|
269
|
+ }
|
|
|
270
|
+
|
|
|
271
|
+ /**
|
|
|
272
|
+ * 驳回后释放名额:申请时 registered+1/pending-1,此处回退。
|
|
|
273
|
+ */
|
|
|
274
|
+ private void releaseSlotCounters(FeRegistrationBatch batch, FeEmploymentOrder order, LocalDateTime now) {
|
|
|
275
|
+ int registered = batch.getRegisteredCount() != null ? batch.getRegisteredCount() : 0;
|
|
|
276
|
+ int pending = batch.getPendingCount() != null ? batch.getPendingCount() : 0;
|
|
|
277
|
+ FeRegistrationBatch batchUpdate = new FeRegistrationBatch();
|
|
|
278
|
+ batchUpdate.setId(batch.getId());
|
|
|
279
|
+ batchUpdate.setRegisteredCount(Math.max(0, registered - 1));
|
|
|
280
|
+ batchUpdate.setPendingCount(pending + 1);
|
|
|
281
|
+ batchUpdate.setUpdateTime(now);
|
|
|
282
|
+ feRegistrationBatchMapper.updateById(batchUpdate);
|
|
|
283
|
+
|
|
|
284
|
+ int orderRegistered = order.getRegisteredCount() != null ? order.getRegisteredCount() : 0;
|
|
|
285
|
+ int orderPending = order.getPendingCount() != null ? order.getPendingCount() : 0;
|
|
|
286
|
+ FeEmploymentOrder orderUpdate = new FeEmploymentOrder();
|
|
|
287
|
+ orderUpdate.setId(order.getId());
|
|
|
288
|
+ orderUpdate.setRegisteredCount(Math.max(0, orderRegistered - 1));
|
|
|
289
|
+ orderUpdate.setPendingCount(orderPending + 1);
|
|
|
290
|
+ orderUpdate.setUpdateTime(now);
|
|
|
291
|
+ feEmploymentOrderMapper.updateById(orderUpdate);
|
|
|
292
|
+ }
|
|
|
293
|
+
|
|
|
294
|
+ private void maybeAdvanceOrderToEnterpriseAudit(FeEmploymentOrder order, LocalDateTime now) {
|
|
|
295
|
+ String step = order.getCurrentStepCode();
|
|
|
296
|
+ if (STEP_REGISTRATION.equals(step) || !StringUtils.hasText(step)) {
|
|
|
297
|
+ FeEmploymentOrder update = new FeEmploymentOrder();
|
|
|
298
|
+ update.setId(order.getId());
|
|
|
299
|
+ update.setCurrentStepCode(STEP_ENTERPRISE_AUDIT);
|
|
|
300
|
+ update.setUpdateTime(now);
|
|
|
301
|
+ feEmploymentOrderMapper.updateById(update);
|
|
|
302
|
+ order.setCurrentStepCode(STEP_ENTERPRISE_AUDIT);
|
|
|
303
|
+ }
|
|
|
304
|
+ }
|
|
|
305
|
+
|
|
111
|
306
|
private FeRegistrationBatch requireActiveBatchByScene(String scene) {
|
|
112
|
307
|
FeRegistrationBatch batch = feRegistrationBatchMapper.selectOne(new LambdaQueryWrapper<FeRegistrationBatch>()
|
|
113
|
308
|
.eq(FeRegistrationBatch::getQrToken, scene)
|
|
|
@@ -185,4 +380,21 @@ public class WorkerRegistrationService {
|
|
185
|
380
|
response.setMessage(message);
|
|
186
|
381
|
return response;
|
|
187
|
382
|
}
|
|
|
383
|
+
|
|
|
384
|
+ private static WorkerRegistrationReviewResponse toReviewResponse(FeWorkerRegistration reg,
|
|
|
385
|
+ FeRegistrationBatch batch,
|
|
|
386
|
+ FeEmploymentOrder order,
|
|
|
387
|
+ String status,
|
|
|
388
|
+ String message) {
|
|
|
389
|
+ WorkerRegistrationReviewResponse response = new WorkerRegistrationReviewResponse();
|
|
|
390
|
+ response.setStatus(status);
|
|
|
391
|
+ response.setRegistrationId(reg.getId());
|
|
|
392
|
+ response.setBatchNo(batch.getBatchNo());
|
|
|
393
|
+ response.setOrderNo(order.getOrderNo());
|
|
|
394
|
+ response.setRegStatus(reg.getRegStatus());
|
|
|
395
|
+ response.setFailReason(reg.getFailReason());
|
|
|
396
|
+ response.setCurrentStepCode(order.getCurrentStepCode());
|
|
|
397
|
+ response.setMessage(message);
|
|
|
398
|
+ return response;
|
|
|
399
|
+ }
|
|
188
|
400
|
}
|