admin
10 天以前 f318c9c7c127b00f353bf45f273096d1dc4b424f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
package com.taoke.autopay.service.impl.js2;
 
import com.taoke.autopay.dao.OrderTaskExecutionDetailMapper;
import com.taoke.autopay.dao.OrderTaskMapper;
import com.taoke.autopay.dto.js2.ClientCountDTO;
import com.taoke.autopay.entity.ClientInfo;
import com.taoke.autopay.entity.js2.OrderTask;
import com.taoke.autopay.entity.js2.OrderTaskExecutionDetail;
import com.taoke.autopay.exception.OrderTaskException;
import com.taoke.autopay.service.ClientInfoService;
import com.taoke.autopay.service.js2.OrderTaskExecutionDetailService;
import com.taoke.autopay.service.js2.OrderTaskService;
import com.taoke.autopay.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import javax.annotation.Resource;
import java.util.*;
 
/**
 * @author 
 * @title: OrderTaskServiceImpl
 * @description: 下单任务服务实现类
 * @date 2025/7/28
 */
@Service
public class OrderTaskServiceImpl implements OrderTaskService {
    
    @Resource
    private OrderTaskMapper orderTaskMapper;
    
    @Resource
    private OrderTaskExecutionDetailMapper orderTaskExecutionDetailMapper;
 
    @Resource
    private ClientInfoService clientInfoService;
    @Autowired
    private OrderTaskExecutionDetailService orderTaskExecutionDetailService;
 
    @Transactional(rollbackFor = Exception.class)
    @Override
    public OrderTask createOrderTask(OrderTask orderTask) throws OrderTaskException {
        // 参数校验
        if (orderTask == null) {
            throw new OrderTaskException(OrderTaskException.CODE_COMMON, "下单任务不能为空");
        }
 
        if(StringUtil.isNullOrEmpty(orderTask.getKeywordContent())){
            throw new OrderTaskException(OrderTaskException.CODE_COMMON, "下单任务口令不能为空");
        }
 
        if(orderTask.getProductSource()==null){
            throw new OrderTaskException(OrderTaskException.CODE_COMMON, "下单任务商品来源不能为空");
        }
 
        if(orderTask.getRequiredOrderCount()==null){
            throw new OrderTaskException(OrderTaskException.CODE_COMMON, "下单任务需求下单数量不能为空");
        }
 
        if(orderTask.getReceiveCycleMinutes()==null){
            throw new OrderTaskException(OrderTaskException.CODE_COMMON, "下单任务收货周期不能为空");
        }
 
        if(orderTask.getOrderStartTime()==null){
            orderTask.setOrderStartTime(new Date());
        }
 
        if(orderTask.getOrderEndTime()==null){
            orderTask.setOrderEndTime(new Date(System.currentTimeMillis()+1000*60*60*24L));
        }
 
        orderTask.setCompletedOrderCount(0);
        orderTask.setReceivedOrderCount(0);
        orderTask.setReviewedOrderCount(0);
        
        // 设置创建时间
        if (orderTask.getCreateTime() == null) {
            orderTask.setCreateTime(new Date());
        }
        
        // 设置更新时间
        orderTask.setUpdateTime(new Date());
        
        // 插入数据库
        orderTaskMapper.insertSelective(orderTask);
        
        return orderTask;
    }
    
    @Override
    public OrderTask getOrderTaskById(Long id) {
        if (id == null) {
            return null;
        }
        return orderTaskMapper.selectByPrimaryKey(id);
    }
 
    @Override
    public List<OrderTask> getOrderTaskByIds(List<Long> ids) {
        if(ids==null||ids.isEmpty()){
            return new ArrayList<>();
        }
       return  orderTaskMapper.listByIds(ids);
    }
 
    @Transactional(rollbackFor = Exception.class)
    @Override
    public OrderTask getOrderTaskByIdForUpdate(Long id) {
        if (id == null) {
            return null;
        }
        return orderTaskMapper.selectByPrimaryKeyForUpdate(id);
    }
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateOrderTask(OrderTask orderTask) throws OrderTaskException {
        // 参数校验
        if (orderTask == null || orderTask.getId() == null) {
            throw new OrderTaskException(OrderTaskException.CODE_COMMON, "下单任务或任务ID不能为空");
        }
        
        // 设置更新时间
        orderTask.setUpdateTime(new Date());
        
        // 更新数据库
        orderTaskMapper.updateByPrimaryKeySelective(orderTask);
    }
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteOrderTask(Long id) throws OrderTaskException {
        if (id == null) {
            throw new OrderTaskException(OrderTaskException.CODE_COMMON, "任务ID不能为空");
        }
        
        // 删除数据库记录
        orderTaskMapper.deleteByPrimaryKey(id);
    }
    
    @Override
    public List<OrderTask> listOrderTasks(OrderTaskMapper.DaoQuery query, int page, int pageSize) {
        if (query == null) {
            query = new OrderTaskMapper.DaoQuery();
        }
        query.start = (long) (page - 1) * pageSize;
        query.count = pageSize;
        return orderTaskMapper.list(query);
    }
    
    @Override
    public long countOrderTasks(OrderTaskMapper.DaoQuery query) {
        if (query == null) {
            query = new OrderTaskMapper.DaoQuery();
        }
        return orderTaskMapper.count(query);
    }
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int assignTask(Long taskId) throws OrderTaskException {
        // 如果任务id对应的任务不存在,要抛出异常
        if (taskId == null) {
            throw new OrderTaskException(OrderTaskException.CODE_COMMON, "任务ID不能为空");
        }
        
        OrderTask orderTask = orderTaskMapper.selectByPrimaryKeyForUpdate(taskId);
        if (orderTask == null) {
            throw new OrderTaskException(OrderTaskException.CODE_TASK_NOT_FOUND, "任务不存在");
        }
        
        // 如果任务状态是已分配状态,返回状态
        if (orderTask.getStatus() != null && orderTask.getStatus() == OrderTask.STATUS_ASSIGNED) {
            return orderTask.getStatus();
        }
        
        // 通过查询OrderTaskExecutionDetail获取已经分配的客户端数量与客户端id;
        OrderTaskExecutionDetailMapper.DaoQuery query = new OrderTaskExecutionDetailMapper.DaoQuery();
        query.taskId = taskId;
        query.count = Integer.MAX_VALUE;
        List<OrderTaskExecutionDetail> executionDetails = orderTaskExecutionDetailMapper.list(query);
        
        // 得到剩余的客户端数量
        int assignedClientCount = executionDetails.size();
        int requiredOrderCount = orderTask.getRequiredOrderCount() != null ? orderTask.getRequiredOrderCount() : 0;
        int remainingClientCount = requiredOrderCount - assignedClientCount;
        if(remainingClientCount<=0){
            if(orderTask.getStatus() != OrderTask.STATUS_ASSIGNED){
                orderTask.setStatus(OrderTask.STATUS_ASSIGNED);
                orderTaskMapper.updateByPrimaryKeySelective(OrderTask.builder()
                                .id(orderTask.getId())
                                .status(OrderTask.STATUS_ASSIGNED)
                                .updateTime(new Date())
                        .build());
            }
            return OrderTask.STATUS_ASSIGNED;
        }
 
        // 获取可分配的设备
        List<ClientInfo> clientInfoList =  clientInfoService.getAvailableClientsForOrder();
        // 剔除已经分配了的设备
        Set<Long> excludeClientIds=new HashSet<>();
        executionDetails.forEach(detail -> {
            excludeClientIds.add( detail.getClientId());
        });
        for(int i=0;i<clientInfoList.size();i++){
            if (excludeClientIds.contains(clientInfoList.get(i).getId())){
                clientInfoList.remove(i);
                i--;
            }
        }
        // 统计所有设备正在执行任务的数量
        List<ClientCountDTO> clientCountList =   orderTaskExecutionDetailMapper.statisticClientIdsCountByStatus(Arrays.asList( new Integer[]{OrderTaskExecutionDetail.STATUS_NOT_ORDERED}));
        Map<Long,  Integer> clientCountMap = new HashMap<>();
        for(ClientCountDTO dto:clientCountList){
            clientCountMap.put(dto.getClientId(), dto.getCount());
        }
        // 剔除已经存在2个任务以上的设备
        for(int i=0;i<clientInfoList.size();i++){
            if(clientCountMap.containsKey(clientInfoList.get(i).getId())&&clientCountMap.get(clientInfoList.get(i).getId())>=2){
                clientInfoList.remove(i);
                i--;
            }
        }
 
        clientInfoList.sort(new Comparator<ClientInfo>() {
            @Override
            public int compare(ClientInfo o1, ClientInfo o2) {
                int count1 = clientCountMap.get(o1.getId())==null?0:clientCountMap.get(o1.getId());
                int count2 = clientCountMap.get(o2.getId())==null?0:clientCountMap.get(o2.getId());
                if(count1!=count2){
                    return count1-count2;
                }
                // 根据活跃时间排序
                long time1 = o1.getActiveTime()==null?0:o1.getActiveTime().getTime();
                long time2 = o2.getActiveTime()==null?0:o2.getActiveTime().getTime();
                return  time2-time1 > 0 ? 1:-1;
            }
        });
        if(clientInfoList.size()>remainingClientCount){
            clientInfoList = clientInfoList.subList(0, remainingClientCount);
        }
 
        // 分配任务
        for(ClientInfo clientInfo:clientInfoList) {
            OrderTaskExecutionDetail detail = OrderTaskExecutionDetail.builder()
                    .id(taskId + "-" + clientInfo.getId())
                    .taskId(taskId)
                    .clientId(clientInfo.getId())
                    .executionStatus(OrderTaskExecutionDetail.STATUS_NOT_ORDERED)
                    .createTime(new Date())
                    .statusDescription("未下单")
                    .build();
            orderTaskExecutionDetailMapper.insertSelective(detail);
        }
 
        // 统计已经分配的客户端数量
        OrderTaskExecutionDetailMapper.DaoQuery daoQuery=new OrderTaskExecutionDetailMapper.DaoQuery();
        daoQuery.taskId = taskId;
        long assignedCount = orderTaskExecutionDetailService.countOrderTaskExecutionDetails(daoQuery);
        if(orderTask.getRequiredOrderCount()<=assignedCount){
          // 更新状态
           orderTaskMapper.updateByPrimaryKeySelective( OrderTask.builder().id(taskId)
                    .updateTime(new Date())
                    .statusDescription("已分配")
                    .status(OrderTask.STATUS_ASSIGNED).build());
        }else{
            orderTaskMapper.updateByPrimaryKeySelective( OrderTask.builder().id(taskId)
                    .updateTime(new Date())
                    .statusDescription("分配中")
                    .status(OrderTask.STATUS_ASSIGNING).build());
        }
        return orderTask.getStatus();
    }
}