|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+package com.huimv.employment.service.registration;
|
|
|
2
|
+
|
|
|
3
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
4
|
+import com.huimv.employment.common.exception.BizException;
|
|
|
5
|
+import com.huimv.employment.common.exception.ErrorCode;
|
|
|
6
|
+import com.huimv.employment.dao.entity.FeEmploymentOrder;
|
|
|
7
|
+import com.huimv.employment.dao.entity.FeRegistrationBatch;
|
|
|
8
|
+import com.huimv.employment.dao.entity.FeWorker;
|
|
|
9
|
+import com.huimv.employment.dao.entity.FeWorkerRegistration;
|
|
|
10
|
+import com.huimv.employment.dao.mapper.FeEmploymentOrderMapper;
|
|
|
11
|
+import com.huimv.employment.dao.mapper.FeRegistrationBatchMapper;
|
|
|
12
|
+import com.huimv.employment.dao.mapper.FeWorkerRegistrationMapper;
|
|
|
13
|
+import com.huimv.employment.service.registration.dto.WorkerRegistrationApplyRequest;
|
|
|
14
|
+import com.huimv.employment.service.registration.dto.WorkerRegistrationApplyResponse;
|
|
|
15
|
+import com.huimv.employment.service.worker.WorkerService;
|
|
|
16
|
+import org.springframework.stereotype.Service;
|
|
|
17
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
18
|
+import org.springframework.util.StringUtils;
|
|
|
19
|
+
|
|
|
20
|
+import java.time.LocalDateTime;
|
|
|
21
|
+
|
|
|
22
|
+/**
|
|
|
23
|
+ * 用工邀请 / 批次登记:临时工扫码后申请加入。
|
|
|
24
|
+ */
|
|
|
25
|
+@Service
|
|
|
26
|
+public class WorkerRegistrationService {
|
|
|
27
|
+
|
|
|
28
|
+ private static final String BATCH_ACTIVE = "active";
|
|
|
29
|
+ private static final String REG_UNDER_REVIEW = "under_review";
|
|
|
30
|
+ private static final String APPLY_SUCCESS = "success";
|
|
|
31
|
+ private static final String APPLY_ALREADY = "already_applied";
|
|
|
32
|
+
|
|
|
33
|
+ private final FeRegistrationBatchMapper feRegistrationBatchMapper;
|
|
|
34
|
+ private final FeEmploymentOrderMapper feEmploymentOrderMapper;
|
|
|
35
|
+ private final FeWorkerRegistrationMapper feWorkerRegistrationMapper;
|
|
|
36
|
+ private final WorkerService workerService;
|
|
|
37
|
+
|
|
|
38
|
+ public WorkerRegistrationService(FeRegistrationBatchMapper feRegistrationBatchMapper,
|
|
|
39
|
+ FeEmploymentOrderMapper feEmploymentOrderMapper,
|
|
|
40
|
+ FeWorkerRegistrationMapper feWorkerRegistrationMapper,
|
|
|
41
|
+ WorkerService workerService) {
|
|
|
42
|
+ this.feRegistrationBatchMapper = feRegistrationBatchMapper;
|
|
|
43
|
+ this.feEmploymentOrderMapper = feEmploymentOrderMapper;
|
|
|
44
|
+ this.feWorkerRegistrationMapper = feWorkerRegistrationMapper;
|
|
|
45
|
+ this.workerService = workerService;
|
|
|
46
|
+ }
|
|
|
47
|
+
|
|
|
48
|
+ /**
|
|
|
49
|
+ * 临时工申请加入用工邀请(scene = 订单编号)。
|
|
|
50
|
+ * <p>要求已完成档案登记({@code fe_worker})。同一批次重复申请返回已有记录。</p>
|
|
|
51
|
+ */
|
|
|
52
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
53
|
+ public WorkerRegistrationApplyResponse apply(Long userId, WorkerRegistrationApplyRequest request) {
|
|
|
54
|
+ workerService.requireWorkerUser(userId);
|
|
|
55
|
+ if (request == null || !StringUtils.hasText(request.getScene())) {
|
|
|
56
|
+ throw new BizException(ErrorCode.BAD_REQUEST, "scene 不能为空");
|
|
|
57
|
+ }
|
|
|
58
|
+ FeWorker worker = workerService.findWorkerByUserId(userId);
|
|
|
59
|
+ if (worker == null) {
|
|
|
60
|
+ throw new BizException(ErrorCode.BAD_REQUEST, "请先完成临时工档案登记");
|
|
|
61
|
+ }
|
|
|
62
|
+
|
|
|
63
|
+ String scene = request.getScene().trim();
|
|
|
64
|
+ FeRegistrationBatch batch = requireActiveBatchByScene(scene);
|
|
|
65
|
+ FeEmploymentOrder order = feEmploymentOrderMapper.selectById(batch.getOrderId());
|
|
|
66
|
+ if (order == null) {
|
|
|
67
|
+ throw new BizException(ErrorCode.NOT_FOUND, "用工订单不存在");
|
|
|
68
|
+ }
|
|
|
69
|
+
|
|
|
70
|
+ FeWorkerRegistration existing = feWorkerRegistrationMapper.selectOne(new LambdaQueryWrapper<FeWorkerRegistration>()
|
|
|
71
|
+ .eq(FeWorkerRegistration::getBatchId, batch.getId())
|
|
|
72
|
+ .eq(FeWorkerRegistration::getWorkerId, worker.getId())
|
|
|
73
|
+ .orderByDesc(FeWorkerRegistration::getId)
|
|
|
74
|
+ .last("LIMIT 1"));
|
|
|
75
|
+ if (existing != null) {
|
|
|
76
|
+ return toResponse(existing, batch, order, APPLY_ALREADY, "您已申请加入该用工,请等待企业确认");
|
|
|
77
|
+ }
|
|
|
78
|
+
|
|
|
79
|
+ assertBatchHasCapacity(batch);
|
|
|
80
|
+
|
|
|
81
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
82
|
+ FeWorkerRegistration reg = new FeWorkerRegistration();
|
|
|
83
|
+ reg.setBatchId(batch.getId());
|
|
|
84
|
+ reg.setOrderId(order.getId());
|
|
|
85
|
+ reg.setEnterpriseId(batch.getEnterpriseId());
|
|
|
86
|
+ reg.setWorkerId(worker.getId());
|
|
|
87
|
+ reg.setRealName(worker.getRealName());
|
|
|
88
|
+ reg.setMobileEnc(worker.getMobileEnc());
|
|
|
89
|
+ reg.setMobileMask(worker.getMobileMask());
|
|
|
90
|
+ reg.setIdCardNoEnc(worker.getIdCardNoEnc());
|
|
|
91
|
+ reg.setBankAccountEnc(worker.getBankAccountEnc());
|
|
|
92
|
+ if (StringUtils.hasText(request.getConfirmedWorkType())) {
|
|
|
93
|
+ reg.setConfirmedWorkType(request.getConfirmedWorkType().trim());
|
|
|
94
|
+ } else if (StringUtils.hasText(order.getWorkType())) {
|
|
|
95
|
+ reg.setConfirmedWorkType(order.getWorkType());
|
|
|
96
|
+ }
|
|
|
97
|
+ reg.setRegStatus(REG_UNDER_REVIEW);
|
|
|
98
|
+ reg.setSubmittedAt(now);
|
|
|
99
|
+ reg.setRemindCount(0);
|
|
|
100
|
+ reg.setCreateTime(now);
|
|
|
101
|
+ reg.setUpdateTime(now);
|
|
|
102
|
+ reg.setDelFlag(0);
|
|
|
103
|
+ feWorkerRegistrationMapper.insert(reg);
|
|
|
104
|
+
|
|
|
105
|
+ bumpBatchCounters(batch, now);
|
|
|
106
|
+ bumpOrderCounters(order, now);
|
|
|
107
|
+
|
|
|
108
|
+ return toResponse(reg, batch, order, APPLY_SUCCESS, "申请已提交,请等待企业确认");
|
|
|
109
|
+ }
|
|
|
110
|
+
|
|
|
111
|
+ private FeRegistrationBatch requireActiveBatchByScene(String scene) {
|
|
|
112
|
+ FeRegistrationBatch batch = feRegistrationBatchMapper.selectOne(new LambdaQueryWrapper<FeRegistrationBatch>()
|
|
|
113
|
+ .eq(FeRegistrationBatch::getQrToken, scene)
|
|
|
114
|
+ .orderByDesc(FeRegistrationBatch::getId)
|
|
|
115
|
+ .last("LIMIT 1"));
|
|
|
116
|
+ if (batch == null) {
|
|
|
117
|
+ FeEmploymentOrder order = feEmploymentOrderMapper.selectOne(new LambdaQueryWrapper<FeEmploymentOrder>()
|
|
|
118
|
+ .eq(FeEmploymentOrder::getOrderNo, scene)
|
|
|
119
|
+ .orderByDesc(FeEmploymentOrder::getId)
|
|
|
120
|
+ .last("LIMIT 1"));
|
|
|
121
|
+ if (order != null) {
|
|
|
122
|
+ batch = feRegistrationBatchMapper.selectOne(new LambdaQueryWrapper<FeRegistrationBatch>()
|
|
|
123
|
+ .eq(FeRegistrationBatch::getOrderId, order.getId())
|
|
|
124
|
+ .orderByDesc(FeRegistrationBatch::getId)
|
|
|
125
|
+ .last("LIMIT 1"));
|
|
|
126
|
+ }
|
|
|
127
|
+ }
|
|
|
128
|
+ if (batch == null) {
|
|
|
129
|
+ throw new BizException(ErrorCode.NOT_FOUND, "未找到对应用工邀请");
|
|
|
130
|
+ }
|
|
|
131
|
+ if (!BATCH_ACTIVE.equals(batch.getStatus())) {
|
|
|
132
|
+ throw new BizException(ErrorCode.BAD_REQUEST, "该用工邀请已关闭或失效");
|
|
|
133
|
+ }
|
|
|
134
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
135
|
+ if (batch.getValidUntil() != null && now.isAfter(batch.getValidUntil())) {
|
|
|
136
|
+ throw new BizException(ErrorCode.BAD_REQUEST, "该用工邀请已过期");
|
|
|
137
|
+ }
|
|
|
138
|
+ if (batch.getValidFrom() != null && now.isBefore(batch.getValidFrom())) {
|
|
|
139
|
+ throw new BizException(ErrorCode.BAD_REQUEST, "该用工邀请尚未生效");
|
|
|
140
|
+ }
|
|
|
141
|
+ return batch;
|
|
|
142
|
+ }
|
|
|
143
|
+
|
|
|
144
|
+ private void assertBatchHasCapacity(FeRegistrationBatch batch) {
|
|
|
145
|
+ int expected = batch.getExpectedCount() != null ? batch.getExpectedCount() : 0;
|
|
|
146
|
+ int registered = batch.getRegisteredCount() != null ? batch.getRegisteredCount() : 0;
|
|
|
147
|
+ if (expected > 0 && registered >= expected) {
|
|
|
148
|
+ throw new BizException(ErrorCode.BAD_REQUEST, "该用工名额已满");
|
|
|
149
|
+ }
|
|
|
150
|
+ }
|
|
|
151
|
+
|
|
|
152
|
+ private void bumpBatchCounters(FeRegistrationBatch batch, LocalDateTime now) {
|
|
|
153
|
+ int registered = batch.getRegisteredCount() != null ? batch.getRegisteredCount() : 0;
|
|
|
154
|
+ int pending = batch.getPendingCount() != null ? batch.getPendingCount() : 0;
|
|
|
155
|
+ FeRegistrationBatch update = new FeRegistrationBatch();
|
|
|
156
|
+ update.setId(batch.getId());
|
|
|
157
|
+ update.setRegisteredCount(registered + 1);
|
|
|
158
|
+ update.setPendingCount(Math.max(0, pending - 1));
|
|
|
159
|
+ update.setUpdateTime(now);
|
|
|
160
|
+ feRegistrationBatchMapper.updateById(update);
|
|
|
161
|
+ }
|
|
|
162
|
+
|
|
|
163
|
+ private void bumpOrderCounters(FeEmploymentOrder order, LocalDateTime now) {
|
|
|
164
|
+ int registered = order.getRegisteredCount() != null ? order.getRegisteredCount() : 0;
|
|
|
165
|
+ int pending = order.getPendingCount() != null ? order.getPendingCount() : 0;
|
|
|
166
|
+ FeEmploymentOrder update = new FeEmploymentOrder();
|
|
|
167
|
+ update.setId(order.getId());
|
|
|
168
|
+ update.setRegisteredCount(registered + 1);
|
|
|
169
|
+ update.setPendingCount(Math.max(0, pending - 1));
|
|
|
170
|
+ update.setUpdateTime(now);
|
|
|
171
|
+ feEmploymentOrderMapper.updateById(update);
|
|
|
172
|
+ }
|
|
|
173
|
+
|
|
|
174
|
+ private static WorkerRegistrationApplyResponse toResponse(FeWorkerRegistration reg,
|
|
|
175
|
+ FeRegistrationBatch batch,
|
|
|
176
|
+ FeEmploymentOrder order,
|
|
|
177
|
+ String status,
|
|
|
178
|
+ String message) {
|
|
|
179
|
+ WorkerRegistrationApplyResponse response = new WorkerRegistrationApplyResponse();
|
|
|
180
|
+ response.setStatus(status);
|
|
|
181
|
+ response.setRegistrationId(reg.getId());
|
|
|
182
|
+ response.setBatchNo(batch.getBatchNo());
|
|
|
183
|
+ response.setOrderNo(order.getOrderNo());
|
|
|
184
|
+ response.setRegStatus(reg.getRegStatus());
|
|
|
185
|
+ response.setMessage(message);
|
|
|
186
|
+ return response;
|
|
|
187
|
+ }
|
|
|
188
|
+}
|