diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/ProjectGroupController.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/ProjectGroupController.java index ca14ace..3bf7fcd 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/ProjectGroupController.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/ProjectGroupController.java @@ -20,6 +20,7 @@ import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import java.util.Map; import java.util.Objects; /** @@ -122,4 +123,20 @@ public class ProjectGroupController { } return ResponseList.ofSuccess(taskService.getProjectProcessOfStaff(token, projectId)); } + + //TODO: TEST + @Operation(description = "请求体是一个key为taskId,value为staffId的map") + @SneakyThrows + @PutMapping("/{staffId}/transfer") + public ResponseMap transferStaffTasks( + @RequestHeader("Token") String token, + @PathVariable Integer projectId, + @PathVariable Integer staffId, + @RequestBody Map transferMap + ) { + if (taskService.transferStaffTasks(token, projectId, staffId, transferMap)) { + return ResponseMap.ofSuccess(); + } + throw new BadRequestException(BadRequestException.OPERATE_FAILED); + } } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/StaffController.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/StaffController.java index 38622db..891b42f 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/StaffController.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/controller/StaffController.java @@ -2,8 +2,11 @@ package cn.edu.hfut.rmdjzz.projectmanagement.controller; import cn.edu.hfut.rmdjzz.projectmanagement.entity.Staff; import cn.edu.hfut.rmdjzz.projectmanagement.exception.BadRequestException; +import cn.edu.hfut.rmdjzz.projectmanagement.exception.ForbiddenException; import cn.edu.hfut.rmdjzz.projectmanagement.exception.TokenException; import cn.edu.hfut.rmdjzz.projectmanagement.service.IStaffService; +import cn.edu.hfut.rmdjzz.projectmanagement.utils.FileUtils; +import cn.edu.hfut.rmdjzz.projectmanagement.utils.TokenUtils; import cn.edu.hfut.rmdjzz.projectmanagement.utils.http.ResponseMap; import io.swagger.v3.oas.annotations.Parameter; import lombok.SneakyThrows; @@ -12,6 +15,7 @@ import org.springframework.util.DigestUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; import java.util.Objects; /** @@ -43,8 +47,12 @@ public class StaffController { } @SneakyThrows - @PostMapping(value = "/staff/import") - public ResponseMap upload(@RequestHeader("Token") String token, @RequestParam("uploadFile") MultipartFile uploadFile,@RequestParam("digest") String digest) { + @PostMapping(value = "/import") + public ResponseMap importStaffs( + @RequestHeader("Token") String token, + @RequestParam("File-Digest") String digest, + @RequestParam("uploadFile") MultipartFile uploadFile + ) { if (null == uploadFile) { throw new BadRequestException("文件传输错误"); } @@ -52,10 +60,25 @@ public class StaffController { if (!fileName.endsWith(".xlsx")) { throw new BadRequestException("文件类型错误"); } - if(!Objects.equals(DigestUtils.md5DigestAsHex(uploadFile.getBytes()).toLowerCase(),digest.toLowerCase())){ + if (!Objects.equals(DigestUtils.md5DigestAsHex(uploadFile.getBytes()).toLowerCase(), digest.toLowerCase())) { throw new BadRequestException("文件传输错误"); } Integer successCount = staffService.multiImport(token, uploadFile); return ResponseMap.ofSuccess("成功导入" + successCount + "条数据"); } + + @SneakyThrows + @GetMapping("/import/template") + public ResponseMap downloadTemplate( + @RequestHeader("Token") String token, + HttpServletResponse response + ) { + if (TokenUtils.getStaffGlobalLevel(token) > 2) { + throw new ForbiddenException(ForbiddenException.UNABLE_TO_OPERATE); + } + if (FileUtils.downloadResource("static/账户导入模板.xlsx", response)) { + return ResponseMap.ofSuccess(); + } + throw new BadRequestException(BadRequestException.OPERATE_FAILED); + } } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/entity/Task.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/entity/Task.java index 66a7b38..fdf749c 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/entity/Task.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/entity/Task.java @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; import lombok.Data; import java.time.LocalDateTime; @@ -17,6 +18,7 @@ import java.util.Objects; * @author 阳勇权 * @since 2022/7/4 11:07 */ +@Builder @Data public class Task { diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/ITaskService.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/ITaskService.java index 08d2893..ff6aaf5 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/ITaskService.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/ITaskService.java @@ -45,4 +45,7 @@ public interface ITaskService extends IService { Task modifyTask(String token, Task task) throws BadRequestException, ForbiddenException; Map> getProjectTaskTrend(String token, Integer projectId) throws BadRequestException, ForbiddenException; + + Boolean transferStaffTasks(String token, Integer projectId, Integer transferredStaffId, Map transferMap) throws ForbiddenException, BadRequestException; + } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/TaskServiceImpl.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/TaskServiceImpl.java index c8b9762..2e31c74 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/TaskServiceImpl.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/service/impl/TaskServiceImpl.java @@ -12,6 +12,7 @@ import cn.edu.hfut.rmdjzz.projectmanagement.service.ITaskService; import cn.edu.hfut.rmdjzz.projectmanagement.utils.TokenUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SimpleQuery; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -353,4 +354,57 @@ public class TaskServiceImpl extends ServiceImpl implements IT return taskTrendDTO; } + //不需要定义为事务,因为updateBatch已经定义为事务 + @Override + public Boolean transferStaffTasks(String token, Integer projectId, Integer transferredStaffId, Map transferMap) throws ForbiddenException, BadRequestException { + if (projectGroupService.getProjectAccessLevel(token, projectId) == 0 + || projectGroupService.getProjectAccessLevelIgnoreGlobalLevel(transferredStaffId, projectId) == 0) { + throw new ForbiddenException(IProjectGroupService.UNABLE_TO_ACCESS_PROJECT); + } + if (projectGroupService.compareProjectAccessLevel(projectId, token, transferredStaffId) < 0) { + throw new ForbiddenException(ForbiddenException.UNABLE_TO_OPERATE); + } + + Map originTransferTaskMap = SimpleQuery.keyMap( + Wrappers.lambdaQuery() + .eq(Task::getTaskProjectId, projectId) + .eq(Task::getTaskHolderId, transferredStaffId), + Task::getTaskId, + true + ); + if (originTransferTaskMap.size() != transferMap.size()) { + throw new BadRequestException("未交接该员工的全部项目"); + } + + Set targetStaffIdCache = new HashSet<>(); + Set> transferEntrySet = transferMap.entrySet(); + for (Map.Entry transferEntry : transferEntrySet) { + Integer targetStaffId = transferEntry.getValue(); + if (Objects.equals(targetStaffId, transferredStaffId)) { + throw new BadRequestException("不能将工作项交接给原员工"); + } + if (!targetStaffIdCache.contains(targetStaffId)) { + if (projectGroupService.getProjectAccessLevelIgnoreGlobalLevel(targetStaffId, projectId) == 0) { + throw new BadRequestException("交接目标员工不在该项目组中"); + } + targetStaffIdCache.add(targetStaffId); + } + Task targetTask = originTransferTaskMap.remove(transferEntry.getKey()); + if (targetTask == null || !Objects.equals(targetTask.getTaskHolderId(), transferredStaffId)) { + throw new BadRequestException("指定的交接任务不属于该项目或被交接员工"); + } + } + if (!originTransferTaskMap.isEmpty()) { + throw new BadRequestException("未交接该员工的全部项目"); + } + + return updateBatchById( + transferEntrySet.parallelStream() + .map(entry -> Task.builder() + .taskId(entry.getKey()) + .taskHolderId(entry.getValue()).build()) + .collect(Collectors.toList()) + ); + } + } diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/FileUtils.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/FileUtils.java new file mode 100644 index 0000000..6a5420b --- /dev/null +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/FileUtils.java @@ -0,0 +1,31 @@ +package cn.edu.hfut.rmdjzz.projectmanagement.utils; + +import lombok.Cleanup; +import org.springframework.util.DigestUtils; +import org.springframework.util.MimeTypeUtils; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.*; + +/** + * @author 佘语殊 + * @since 2022/7/11 9:32 + */ +public class FileUtils { + public static Boolean downloadResource(String resourceName, HttpServletResponse response) throws IOException { + @Cleanup InputStream is = FileUtils.class.getResourceAsStream(resourceName); + if (is == null) { + throw new FileNotFoundException("该文件不存在"); + } + @Cleanup BufferedInputStream bis = new BufferedInputStream(is); + response.setContentType(MimeTypeUtils.APPLICATION_OCTET_STREAM_VALUE); + response.setCharacterEncoding("UTF-8"); + ServletOutputStream out = response.getOutputStream(); + response.addHeader("File-Digest", DigestUtils.md5DigestAsHex(bis)); + @Cleanup BufferedOutputStream bos = new BufferedOutputStream(out); + bis.transferTo(bos); + bos.flush(); + return true; + } +} diff --git a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/ResponseMap.java b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/ResponseMap.java index 55f23c2..40e7407 100644 --- a/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/ResponseMap.java +++ b/src/main/java/cn/edu/hfut/rmdjzz/projectmanagement/utils/http/ResponseMap.java @@ -75,7 +75,13 @@ public class ResponseMap implements IResponse { return of(HttpStatus.OK.value(), msg, data); } + /** + * @param data 类型为String则填入msg,否则填入data + */ public static ResponseMap ofSuccess(Object data) { + if (data instanceof String msg) { + return of(HttpStatus.OK.value(), msg); + } return of(HttpStatus.OK.value(), SUCCESS, data); } @@ -83,10 +89,6 @@ public class ResponseMap implements IResponse { return of(HttpStatus.OK.value(), msg, data, putNulls); } - public static ResponseMap ofSuccess(String msg) { - return of(HttpStatus.OK.value(), msg); - } - public static ResponseMap ofSuccess() { return of(HttpStatus.OK.value(), SUCCESS); }