tj
2025-06-05 2d549a04870d1315868a7cf19952b64e8071e711
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
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
package com.cloudroam.service.impl;
 
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cloudroam.common.LocalUser;
import com.cloudroam.common.enumeration.FileReTypeEnum;
import com.cloudroam.common.enumeration.ProjectTaskAssignStatusEnum;
import com.cloudroam.common.enumeration.ProjectTaskStatusEnum;
import com.cloudroam.dto.projectDaily.QueryProjectDailyDTO;
import com.cloudroam.dto.projectTask.*;
import com.cloudroam.mapper.ProjectTaskMapperCustom;
import com.cloudroam.model.*;
import com.cloudroam.mapper.ProjectTaskMapper;
import com.cloudroam.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudroam.vo.projectTask.ProjectTaskVO;
import io.github.talelin.autoconfigure.exception.ForbiddenException;
import io.github.talelin.autoconfigure.exception.NotFoundException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author generator@TaoJie
 * @since 2024-12-30
 */
@Service
public class ProjectTaskServiceImpl extends ServiceImpl<ProjectTaskMapper, ProjectTaskDO> implements ProjectTaskService {
 
    @Autowired
    private ProjectInfoService projectInfoService;
 
    @Autowired
    private ProjectModuleService projectModuleService;
 
    @Autowired
    private ProjectTaskUserReService projectTaskUserReService;
 
    @Autowired
    private ProjectTaskMapperCustom projectTaskMapperCustom;
 
    @Autowired
    private ProjectTaskEvaluatorService projectTaskEvaluatorService;
 
    @Autowired
    private ProjectTaskDeveloperService projectTaskDeveloperService;
 
    @Autowired
    private UserService userService;
 
    @Autowired
    private Validator validator;  // 注入 Spring 的 Validator
 
    @Autowired
    private ProjectDailyService projectDailyService;
 
    @Autowired
    private LinFileReService fileReService;
 
 
    @Transactional
    @Override
    public boolean createProjectTask(CreateProjectTaskDTO validator) {
        UserDO user = LocalUser.getLocalUser();
 
        ProjectInfoDO projectInfoDO = projectInfoService.getById(validator.getProjectId());
        if(Objects.isNull(projectInfoDO)){
            throw new NotFoundException("项目不存在");
        }
 
        ProjectModuleDO projectModuleDO = projectModuleService.getById(validator.getModuleId());
        if(Objects.isNull(projectModuleDO)){
            throw new NotFoundException("项目模块不存在");
        }
 
        ProjectTaskDO projectTaskDO=new ProjectTaskDO();
        BeanUtils.copyProperties(validator,projectTaskDO);
        projectTaskDO.setProjectName(projectInfoDO.getProjectName());
        projectTaskDO.setModuleName(projectModuleDO.getModuleName());
        projectTaskDO.setId(IdUtil.simpleUUID());
 
        // 设置任务状态为 未开始
        projectTaskDO.setStatus(ProjectTaskStatusEnum.FN.getCode());
        // 设置排配状态为 待排配
        projectTaskDO.setAssignStatus(ProjectTaskAssignStatusEnum.AN.getCode());
 
        projectTaskDO.create(String.valueOf(user.getId()),user.getNickname());
 
        // 遍历评估表
        List<ProjectTaskEvaluatorDO> evaluatorDOList = validator.getEvaluatorUsers().stream().map(userId -> {
            ProjectTaskEvaluatorDO projectTaskEvaluatorDO = new ProjectTaskEvaluatorDO();
            projectTaskEvaluatorDO.setId(IdUtil.simpleUUID());
            projectTaskEvaluatorDO.setTaskId(projectTaskDO.getId());
            projectTaskEvaluatorDO.setEvaluatorId(userId);
            UserDO evaluatorUser = userService.getUserById(userId);
            projectTaskEvaluatorDO.setEvaluatorName(evaluatorUser.getNickname());
            projectTaskEvaluatorDO.create(String.valueOf(user.getId()), user.getNickname());
 
            return projectTaskEvaluatorDO;
        }).collect(Collectors.toList());
 
        projectTaskEvaluatorService.saveBatch(evaluatorDOList);
 
        // 保存任务附件信息
        fileReService.saveFileAnyReByReIdType(projectTaskDO.getId(),validator.getUploadFileList(),FileReTypeEnum.PROJECT_TASK);
        return this.baseMapper.insert(projectTaskDO)>0;
    }
 
    @Transactional
    @Override
    public boolean deleteProjectTask(String id) {
        UserDO user = LocalUser.getLocalUser();
        if(StrUtil.isBlank(id)){
            throw new NotFoundException("传入的Id不能为空");
        }
        ProjectTaskDO existProjectTask = getById(id);
        if(existProjectTask == null){
            throw new NotFoundException("项目任务不存在");
        }
 
        ProjectTaskDO projectTaskDO=new ProjectTaskDO();
        projectTaskDO.setId(id);
        projectTaskDO.delete(String.valueOf(user.getId()), user.getNickname());
        return  removeById(id);
    }
 
    @Transactional
    @Override
    public boolean updateProjectTask(CreateProjectTaskDTO validator) {
        UserDO user = LocalUser.getLocalUser();
        if(StrUtil.isBlank(validator.getId())){
            throw new NotFoundException("传入的Id不能为空");
        }
        ProjectInfoDO projectInfoDO = projectInfoService.getById(validator.getProjectId());
        if(Objects.isNull(projectInfoDO)){
            throw new NotFoundException("项目不存在");
        }
 
        ProjectModuleDO projectModuleDO = projectModuleService.getById(validator.getModuleId());
        if(Objects.isNull(projectModuleDO)){
            throw new NotFoundException("项目模块不存在");
        }
 
        ProjectTaskDO existProjectTask = getById(validator.getId());
        if(existProjectTask == null){
            throw new NotFoundException("项目任务不存在");
        }
        BeanUtils.copyProperties(validator,existProjectTask);
        existProjectTask.update(String.valueOf(user.getId()), user.getNickname());
        existProjectTask.setProjectName(projectInfoDO.getProjectName());
        existProjectTask.setModuleName(projectModuleDO.getModuleName());
 
 
        // 先删除评估表
        projectTaskEvaluatorService.deleteByTaskId(existProjectTask.getId());
 
        // 遍历评估表
        List<ProjectTaskEvaluatorDO> evaluatorDOList = validator.getEvaluatorUsers().stream().map(userId -> {
            ProjectTaskEvaluatorDO projectTaskEvaluatorDO = new ProjectTaskEvaluatorDO();
            projectTaskEvaluatorDO.setId(IdUtil.simpleUUID());
            projectTaskEvaluatorDO.setTaskId(existProjectTask.getId());
            projectTaskEvaluatorDO.setEvaluatorId(userId);
            UserDO evaluatorUser = userService.getUserById(userId);
            projectTaskEvaluatorDO.setEvaluatorName(evaluatorUser.getNickname());
            projectTaskEvaluatorDO.create(String.valueOf(user.getId()), user.getNickname());
 
            return projectTaskEvaluatorDO;
        }).collect(Collectors.toList());
 
        projectTaskEvaluatorService.saveBatch(evaluatorDOList);
 
        // 保存任务附件信息
        fileReService.saveFileAnyReByReIdType(existProjectTask.getId(),validator.getUploadFileList(),FileReTypeEnum.PROJECT_TASK);
 
 
        return baseMapper.updateById(existProjectTask)>0;
    }
 
    @Override
    public ProjectTaskVO getProjectTaskById(String id) {
        if(StrUtil.isBlank(id)){
            throw new NotFoundException("传入的Id不能为空");
        }
        ProjectTaskDO projectTaskDO = getById(id);
 
        // 追加关联人员信息
        ProjectTaskVO projectTaskVO=new ProjectTaskVO();
        BeanUtils.copyProperties(projectTaskDO,projectTaskVO);
 
        // 项目信息
        ProjectInfoDO projectInfoDO = projectInfoService.getById(projectTaskDO.getProjectId());
        if(!Objects.isNull(projectInfoDO)){
            projectTaskVO.setProjectNameSrc(projectInfoDO.getProjectName());
        }
        // 模块信息
        ProjectModuleDO projectModuleDO = projectModuleService.getById(projectTaskDO.getModuleId());
        if(!Objects.isNull(projectModuleDO)){
            projectTaskVO.setModuleNameSrc(projectModuleDO.getModuleName());
        }
 
        // 获取评估人员
        List<ProjectTaskEvaluatorDO> projectTaskEvaluatorDOList = projectTaskEvaluatorService.getProjectTaskEvaluatorByTaskId(projectTaskVO.getId());
        projectTaskVO.setEvaluatorUsers(projectTaskEvaluatorDOList);
 
        // 获取已排配的日志信息
        QueryProjectDailyDTO dailyDTO=new QueryProjectDailyDTO();
        dailyDTO.setTaskId(id);
        List<ProjectDailyDO> projectDailyList = projectDailyService.getProjectDailyList(dailyDTO);
        projectTaskVO.setProjectDailyList(projectDailyList);
 
        // 获取上传的附件信息
        List<FileDO> fileList=fileReService.getFileByReIdType(projectTaskVO.getId(),FileReTypeEnum.PROJECT_TASK);
        projectTaskVO.setFileList(fileList);
 
        return projectTaskVO;
    }
 
    @Override
    public IPage<ProjectTaskVO> getProjectTaskPage(QueryProjectTaskDTO dto) {
        Page<ProjectTaskVO> page=new Page<ProjectTaskVO>(dto.getPage(),dto.getCount());
 
        if(StringUtils.isNotBlank(dto.getModuleId())){
            // 查看模块下的所有子模块
            List<ProjectModuleDO> moduleIds=projectModuleService.getChildrenModuleIds(dto.getModuleId());
 
            if(CollectionUtils.isNotEmpty(moduleIds)&&moduleIds.size()>0){
                List<String> moduleIdList=moduleIds.stream().map(ProjectModuleDO::getId).collect(Collectors.toList());
                moduleIdList.add(dto.getModuleId());
                // 查找所有模块下的id
                dto.setModuleIds(moduleIdList);
            }else{
                List<String> moduleIdList=new ArrayList<>();
                moduleIdList.add(dto.getModuleId());
                dto.setModuleIds(moduleIdList);
            }
 
        }
 
        IPage<ProjectTaskVO> projectTaskVOIPage = projectTaskMapperCustom.selectProjectTaskPage(page, dto);
 
        // 遍历查看所有用户
        projectTaskVOIPage.getRecords().stream().forEach(projectTaskVO -> {
            // 查找评估人员
            List<ProjectTaskEvaluatorDO> projectTaskEvaluatorDOList = projectTaskEvaluatorService.getProjectTaskEvaluatorByTaskId(projectTaskVO.getId());
            projectTaskVO.setEvaluatorUsers(projectTaskEvaluatorDOList);
 
            // 查找开发人员
            List<ProjectTaskDeveloperDO> projectTaskDeveloperDOList = projectTaskDeveloperService.getProjectTaskDeveloperByTaskId(projectTaskVO.getId());
            projectTaskVO.setDeveloperUsers(projectTaskDeveloperDOList);
 
            // 获取上传的附件信息
            List<FileDO> fileList=fileReService.getFileByReIdType(projectTaskVO.getId(),FileReTypeEnum.PROJECT_TASK);
            projectTaskVO.setFileList(fileList);
        });
        return projectTaskVOIPage;
 
    }
 
    @Override
    @Transactional
    public void createProjectTaskBatch(CreateProjectTaskBatchDTO validator) {
        validator.getProjectTaskList().stream().forEach(this::validateTask);
        validator.getProjectTaskList().stream().forEach(projectTask -> {
            createProjectTask(projectTask);
        });
    }
 
    @Override
    public IPage<ProjectTaskVO> getProjectTaskMineTodoPage(QueryProjectTaskDTO dto) {
 
        UserDO curUser = LocalUser.getLocalUser();
        dto.setCurDeveloperUserId(String.valueOf(curUser.getId()));
 
        Page<ProjectTaskVO> page=new Page<ProjectTaskVO>(dto.getPage(),dto.getCount());
 
        if(StringUtils.isNotBlank(dto.getModuleId())){
            // 查看模块下的所有子模块
            List<ProjectModuleDO> moduleIds=projectModuleService.getChildrenModuleIds(dto.getModuleId());
 
            if(CollectionUtils.isNotEmpty(moduleIds)&&moduleIds.size()>0){
                List<String> moduleIdList=moduleIds.stream().map(ProjectModuleDO::getId).collect(Collectors.toList());
                moduleIdList.add(dto.getModuleId());
                // 查找所有模块下的id
                dto.setModuleIds(moduleIdList);
            }else{
                List<String> moduleIdList=new ArrayList<>();
                moduleIdList.add(dto.getModuleId());
                dto.setModuleIds(moduleIdList);
            }
 
        }
 
        IPage<ProjectTaskVO> projectTaskVOIPage = projectTaskMapperCustom.getProjectTaskMineTodoPage(page, dto);
 
        // 遍历查看所有用户
        projectTaskVOIPage.getRecords().stream().forEach(projectTaskVO -> {
            // 查找评估人员
            List<ProjectTaskEvaluatorDO> projectTaskEvaluatorDOList = projectTaskEvaluatorService.getProjectTaskEvaluatorByTaskId(projectTaskVO.getId());
            projectTaskVO.setEvaluatorUsers(projectTaskEvaluatorDOList);
 
            // 查找开发人员
            List<ProjectTaskDeveloperDO> projectTaskDeveloperDOList = projectTaskDeveloperService.getProjectTaskDeveloperByTaskId(projectTaskVO.getId());
            projectTaskVO.setDeveloperUsers(projectTaskDeveloperDOList);
        });
        return projectTaskVOIPage;
    }
 
    @Override
    @Transactional
    public boolean getStartTaskById(String taskId) {
        UserDO curUser = LocalUser.getLocalUser();
        ProjectTaskDO projectTaskDO = getById(taskId);
        if(Objects.isNull(projectTaskDO)){
            throw new NotFoundException("任务信息不存在!");
        }
 
        // 需要将当前开发人员设置为进行中
        ProjectTaskDeveloperDO projectTaskDeveloperDO = projectTaskDeveloperService.getProjectTaskDeveloperByTaskIdDeveloperId(taskId,String.valueOf(curUser.getId()));
        if(null!=projectTaskDeveloperDO){
            projectTaskDeveloperDO.setDeveloperTaskStatus(ProjectTaskStatusEnum.P.getCode());
 
            // 获取当前开发人员开始时间和累计工时
            QueryTaskDailyDTO projectDailyTaskInfo = projectDailyService.getProjectDailyTaskInfo(taskId, String.valueOf(curUser.getId()));
 
            projectTaskDeveloperDO.setDeveloperStartTime(projectDailyTaskInfo.getMinStartTime());
            projectTaskDeveloperDO.setDeveloperEndTime(projectDailyTaskInfo.getMaxEndTime());
            projectTaskDeveloperDO.setDeveloperHour(projectDailyTaskInfo.getActualHours());
            projectTaskDeveloperService.updateById(projectTaskDeveloperDO);
        }
 
        // 将任务状态设置称进行中
        projectTaskDO.setStatus(ProjectTaskStatusEnum.P.getCode());
 
 
        return baseMapper.updateById(projectTaskDO)>0;
    }
 
    @Override
    @Transactional
    public boolean getFinishTaskById(String taskId) {
 
        UserDO curUser = LocalUser.getLocalUser();
 
        boolean res=false;
 
        ProjectTaskDO projectTaskDO = getById(taskId);
        if(Objects.isNull(projectTaskDO)){
            throw new NotFoundException("任务信息不存在!");
        }
 
        // TODO 需要查看当天的任务日志是否有未完成的
        int projectDailyUnCommited =projectDailyService.getProjectTaskDailyUnCommited(taskId,String.valueOf(curUser.getId()));
        if(projectDailyUnCommited>0){
            throw new ForbiddenException(20000);
        }
 
 
        // 需要将当前开发人员设置为已完成
        // 需要将当前开发人员设置为进行中
        ProjectTaskDeveloperDO projectTaskDeveloperDO = projectTaskDeveloperService.getProjectTaskDeveloperByTaskIdDeveloperId(taskId,String.valueOf(curUser.getId()));
        if(null!=projectTaskDeveloperDO){
            projectTaskDeveloperDO.setDeveloperTaskStatus(ProjectTaskStatusEnum.T.getCode());
            res=projectTaskDeveloperService.updateById(projectTaskDeveloperDO);
        }
 
        // 获取当前开发人员开始时间和累计工时
        QueryTaskDailyDTO projectDailyTaskInfo = projectDailyService.getProjectDailyTaskInfo(taskId, null);
        projectTaskDO.setActualBeginDate(projectDailyTaskInfo.getMinStartTime());
        projectTaskDO.setActualEndDate(projectDailyTaskInfo.getMaxEndTime());
        projectTaskDO.setActualHour(projectDailyTaskInfo.getActualHours());
 
        // 这里要查看所有所有developer的状态都是待测试的
        List<ProjectTaskDeveloperDO> projectTaskDeveloperByTaskId = projectTaskDeveloperService.getProjectTaskDeveloperByTaskId(taskId);
        // 假设 ProjectTaskDeveloperDO 有一个 getStatus() 方法返回状态
        long count = projectTaskDeveloperByTaskId.stream()
                .filter(developer -> developer.getDeveloperTaskStatus().equals(ProjectTaskStatusEnum.T.getCode())) // 过滤状态为 'T' 的记录
                .count();
        if(count==projectTaskDeveloperByTaskId.size()){
            // 点击完成,任务进入待测试
            projectTaskDO.setStatus(ProjectTaskStatusEnum.T.getCode());
        }
 
        // 获取所有已提交的任务的实际工时,与任务的计划工时相除得到百分比
        QueryProjectTaskHoursDTO processPercent=projectDailyService.getCommitedActualHoursStatisticByTaskId(taskId);
        if(null!=processPercent && null!=processPercent.getActualHours() && null!=projectTaskDO.getPlanHour()){
                   BigDecimal process = processPercent.getActualHours()
                    .divide(projectTaskDO.getPlanHour(), 10, RoundingMode.HALF_UP)  // 指定小数位数和舍入模式
                    .multiply(BigDecimal.valueOf(100));
 
            projectTaskDO.setProcess(process);
        }
       return baseMapper.updateById(projectTaskDO)>0;
    }
 
    @Transactional
    @Override
    public boolean getTestPass(String taskId) {
        UserDO curUser = LocalUser.getLocalUser();
        ProjectTaskDO projectTaskDO = getById(taskId);
        if(Objects.isNull(projectTaskDO)){
            throw new NotFoundException("任务信息不存在!");
        }
 
        projectTaskDO.setTestUserId(String.valueOf(curUser.getId()));
        projectTaskDO.setTestUserName(curUser.getNickname());
        projectTaskDO.setTestTime(LocalDateTime.now());
        projectTaskDO.setTestStatus(ProjectTaskStatusEnum.TY.getCode());
 
        projectTaskDO.setStatus(ProjectTaskStatusEnum.TY.getCode());
 
        return baseMapper.updateById(projectTaskDO)>0;
    }
 
    @Transactional
    @Override
    public boolean getTestUnpass(String taskId) {
        UserDO curUser = LocalUser.getLocalUser();
        ProjectTaskDO projectTaskDO = getById(taskId);
        if(Objects.isNull(projectTaskDO)){
            throw new NotFoundException("任务信息不存在!");
        }
 
        projectTaskDO.setTestUserId(String.valueOf(curUser.getId()));
        projectTaskDO.setTestUserName(curUser.getNickname());
        projectTaskDO.setTestTime(LocalDateTime.now());
        projectTaskDO.setTestStatus(ProjectTaskStatusEnum.TN.getCode());
 
        projectTaskDO.setStatus(ProjectTaskStatusEnum.TN.getCode());
 
        return baseMapper.updateById(projectTaskDO)>0;
    }
 
    @Transactional
    @Override
    public boolean getConfirm(String taskId) {
        UserDO curUser = LocalUser.getLocalUser();
        ProjectTaskDO projectTaskDO = getById(taskId);
        if(Objects.isNull(projectTaskDO)){
            throw new NotFoundException("任务信息不存在!");
        }
 
        projectTaskDO.setConfirmUserId(String.valueOf(curUser.getId()));
        projectTaskDO.setConfirmUserName(curUser.getNickname());
        projectTaskDO.setConfirmTime(LocalDateTime.now());
        projectTaskDO.setStatus(ProjectTaskStatusEnum.FY.getCode());
 
        return baseMapper.updateById(projectTaskDO)>0;
    }
 
    @Transactional
    @Override
    public boolean editProcess(CreateProjectTaskProcessDTO validator) {
        UserDO curUser = LocalUser.getLocalUser();
        ProjectTaskDO projectTaskDO = getById(validator.getId());
        if(Objects.isNull(projectTaskDO)){
            throw new NotFoundException("任务信息不存在!");
        }
 
        BeanUtils.copyProperties(validator,projectTaskDO);
 
        return baseMapper.updateById(projectTaskDO)>0;
    }
 
    @Override
    @Transactional
    public boolean deleteProjectTaskDaily(String dailyId) {
        UserDO curUser = LocalUser.getLocalUser();
        // 删除日志信息
        ProjectDailyDO projectDailyDO = projectDailyService.getById(dailyId);
        if(Objects.isNull(projectDailyDO)){
            throw new NotFoundException("任务排配日志信息不存在!");
        }
        projectDailyDO.delete(String.valueOf(curUser.getId()),curUser.getNickname());
        projectDailyService.removeById(dailyId);
        // 查看当前开发当前任务的日志记录,如果没有则更新当前开发的任务状态设置为未开始
        if(StringUtils.isNotBlank(projectDailyDO.getTaskId())){
            String createUserId = projectDailyDO.getCreateUserId();
            String taskId = projectDailyDO.getTaskId();
 
            QueryTaskDailyDTO projectDailyTaskInfo = projectDailyService.getProjectDailyTaskInfo(taskId, createUserId);
            if(Objects.isNull(projectDailyTaskInfo)){
                // 如果当前人员下没有当前任务日志,那么则删除当前任务的开发信息
                projectTaskDeveloperService.deleteProjectTaskDeveloperByTaskIdDeveloperId(taskId, createUserId);
            }
 
        }
        // 如果当前任务下一条日志记录都没有,那么更新当前任务为未开始
        return updateProjectTask2Unstart(projectDailyDO.getTaskId());
    }
 
    @Transactional
    @Override
    public boolean updateProjectTaskDaily(CreateProjectTaskDailyDTO validator) {
        if(StringUtils.isNotBlank(validator.getId())){
            ProjectDailyDO projectDailyDO = projectDailyService.getById(validator.getId());
            if(Objects.isNull(projectDailyDO)){
                throw new NotFoundException("任务排配日志信息不存在!");
            }
 
 
            // 查看排配日期是否小于今天,如果小于今天则抛出,只是比年月日
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());  // 设置为当前时间
            calendar.set(Calendar.HOUR_OF_DAY, 0);  // 设置时为 00
            calendar.set(Calendar.MINUTE, 0);  // 设置分为 00
            calendar.set(Calendar.SECOND, 0);  // 设置秒为 00
            calendar.set(Calendar.MILLISECOND, 0);  // 设置毫秒为 00
            Date todayAtMidnight = calendar.getTime();  // 获取清除时间部分后的日期
            if(validator.getDailyDate().before(todayAtMidnight)){
                throw new ForbiddenException(20003);
            }
            projectDailyDO.setDailyContent(validator.getDailyContent());
            projectDailyDO.setEstimatedHours(validator.getEstimatedHours());
            projectDailyDO.setRemark(validator.getRemark());
 
            projectDailyService.updateById(projectDailyDO);
 
            // 查看当前排配的总工时是否大于整个任务的计划工时
            projectDailyService.checkProjectDailyTaskPlanHours(projectDailyDO.getTaskId());
 
            return true;
        }
        return false;
    }
 
    @Transactional
    @Override
    public boolean updateProjectTaskPlan(CreateProjectTaskPlanDTO validator) {
        if(StringUtils.isNotBlank(validator.getId())){
            ProjectTaskDO projectTaskDO = getById(validator.getId());
            if(Objects.isNull(projectTaskDO)){
                throw new NotFoundException("任务信息不存在!");
            }
 
            QueryProjectDailyDTO queryProjectDailyDTO = new QueryProjectDailyDTO();
            queryProjectDailyDTO.setTaskId(validator.getId());
            List<ProjectDailyDO> projectDailyList = projectDailyService.getProjectDailyList(queryProjectDailyDTO);
            // 计划工时不能小于已经分配的工时
            if(CollectionUtils.isNotEmpty(projectDailyList)){
                BigDecimal totalPlanHour = projectDailyList.stream()
                        .map(ProjectDailyDO::getEstimatedHours)   // 获取 BigDecimal 类型的 plan_hour
                        .reduce(BigDecimal.ZERO, BigDecimal::add);  // 求和
                // 检查排配时间是否大于计划时间
                if(validator.getPlanHour().compareTo(totalPlanHour)<0){
                    throw new ForbiddenException(20004);
                }
            }
 
            // 判断结束时间是否大于开始时间
            if (validator.getPlanEndDate().isBefore(validator.getPlanBeginDate())) {  // 使用 isBefore()
                throw new ForbiddenException(20005); // 结束时间小于开始时间
            }
 
 
            projectTaskDO.setPlanHour(validator.getPlanHour());
            projectTaskDO.setPlanBeginDate(validator.getPlanBeginDate());
            projectTaskDO.setPlanEndDate(validator.getPlanEndDate());
 
            // 重新设置process
            // 获取所有已提交的任务的实际工时,与任务的计划工时相除得到百分比
            QueryProjectTaskHoursDTO processPercent=projectDailyService.getCommitedActualHoursStatisticByTaskId(validator.getId());
            if(null!=processPercent && null!=processPercent.getActualHours() && null!=projectTaskDO.getPlanHour()){
                BigDecimal process = processPercent.getActualHours()
                        .divide(projectTaskDO.getPlanHour(), 10, RoundingMode.HALF_UP)  // 指定小数位数和舍入模式
                        .multiply(BigDecimal.valueOf(100));
 
                projectTaskDO.setProcess(process);
            }
           return baseMapper.updateById(projectTaskDO)>0;
        }
        return false;
    }
 
    private boolean updateProjectTask2Unstart(String taskId) {
        // 如果任务下没有开发人员,那么更新当前任务的状态为未开始
        List<ProjectTaskDeveloperDO> projectTaskDeveloperByTaskId = projectTaskDeveloperService.getProjectTaskDeveloperByTaskId(taskId);
        if(CollectionUtils.isEmpty(projectTaskDeveloperByTaskId)){
            ProjectTaskDO projectTaskDO = getById(taskId);
            if(Objects.isNull(projectTaskDO)){
                throw new NotFoundException("任务信息不存在!");
            }
            projectTaskDO.setStatus(ProjectTaskStatusEnum.FN.getCode());
            projectTaskDO.setAssignStatus(ProjectTaskAssignStatusEnum.AN.getCode());
            return baseMapper.updateById(projectTaskDO)>0;
        }
        return true;
    }
 
    public void validateTask(CreateProjectTaskDTO task) {
        // 手动调用验证
        Set<ConstraintViolation<CreateProjectTaskDTO>> violations = validator.validate(task);
 
        // 如果有验证错误
        if (!violations.isEmpty()) {
            StringBuilder errorMessage = new StringBuilder("批量任务保存失败: ");
            for (ConstraintViolation<CreateProjectTaskDTO> violation : violations) {
                errorMessage.append(violation.getMessage()).append(", ");
            }
            throw new ConstraintViolationException(errorMessage.toString(),violations);
        }
    }
 
}