feat: add role scoped training task APIs
parent
a1306bd9ad
commit
ac71703e62
@ -0,0 +1,237 @@
|
||||
package com.sztzjy.linkCommerce.controller.stu;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.sztzjy.linkCommerce.config.exception.UnAuthorizedException;
|
||||
import com.sztzjy.linkCommerce.config.security.JwtUser;
|
||||
import com.sztzjy.linkCommerce.config.security.TokenProvider;
|
||||
import com.sztzjy.linkCommerce.entity.TrainingTask;
|
||||
import com.sztzjy.linkCommerce.entity.importDto.TrainingTaskImportDTO;
|
||||
import com.sztzjy.linkCommerce.service.TrainingTaskService;
|
||||
import com.sztzjy.linkCommerce.util.ResultEntity;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "Training task management")
|
||||
@RequestMapping("api/training-tasks")
|
||||
@RestController
|
||||
public class TrainingTaskController {
|
||||
@Autowired
|
||||
private TrainingTaskService trainingTaskService;
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation("Training task list")
|
||||
public ResultEntity<List<TrainingTask>> list(@RequestParam(required = false) String projectName,
|
||||
@RequestParam(required = false) String taskName,
|
||||
@RequestParam(required = false) Boolean enabledOnly,
|
||||
HttpServletRequest request) {
|
||||
JwtUser user = TokenProvider.getJWTUser(request);
|
||||
if (isStudent(user)) {
|
||||
return new ResultEntity<>(HttpStatus.OK, "Query success",
|
||||
trainingTaskService.listForStudent(user.getUserId(), enabledOnly));
|
||||
}
|
||||
return new ResultEntity<>(HttpStatus.OK, "Query success",
|
||||
trainingTaskService.listDefaults(projectName, taskName, enabledOnly));
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@ApiOperation("Training task detail")
|
||||
public ResultEntity<TrainingTask> detail(@PathVariable String id, HttpServletRequest request) {
|
||||
requireAdmin(request);
|
||||
TrainingTask task = trainingTaskService.getById(id);
|
||||
if (task == null) {
|
||||
return new ResultEntity<>(HttpStatus.NOT_FOUND, "Training task not found");
|
||||
}
|
||||
return new ResultEntity<>(HttpStatus.OK, "Query success", task);
|
||||
}
|
||||
|
||||
@GetMapping("/key/{taskKey}")
|
||||
@ApiOperation("Training task detail by key")
|
||||
public ResultEntity<TrainingTask> detailByTaskKey(@PathVariable String taskKey, HttpServletRequest request) {
|
||||
JwtUser user = TokenProvider.getJWTUser(request);
|
||||
TrainingTask task = isStudent(user)
|
||||
? trainingTaskService.getStudentTaskByTaskKey(taskKey, user.getUserId())
|
||||
: trainingTaskService.getByTaskKey(taskKey);
|
||||
if (task == null) {
|
||||
return new ResultEntity<>(HttpStatus.OK, "Training task not configured", null);
|
||||
}
|
||||
return new ResultEntity<>(HttpStatus.OK, "Query success", task);
|
||||
}
|
||||
|
||||
@GetMapping("/classes/{teachingClassId}")
|
||||
@ApiOperation("Training task list for teaching class")
|
||||
public ResultEntity<List<TrainingTask>> listForTeachingClass(@PathVariable String teachingClassId,
|
||||
@RequestParam(required = false) Boolean enabledOnly,
|
||||
HttpServletRequest request) {
|
||||
JwtUser user = requireTeacher(request);
|
||||
try {
|
||||
return new ResultEntity<>(HttpStatus.OK, "Query success",
|
||||
trainingTaskService.listForTeachingClass(teachingClassId, enabledOnly, user.getUserId()));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return new ResultEntity<>(HttpStatus.BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/classes/{teachingClassId}/key/{taskKey}")
|
||||
@ApiOperation("Training task detail for teaching class by key")
|
||||
public ResultEntity<TrainingTask> getClassTaskByTaskKey(@PathVariable String teachingClassId,
|
||||
@PathVariable String taskKey,
|
||||
HttpServletRequest request) {
|
||||
JwtUser user = requireTeacher(request);
|
||||
try {
|
||||
TrainingTask task = trainingTaskService.getClassTaskByTaskKey(teachingClassId, taskKey, user.getUserId());
|
||||
if (task == null) {
|
||||
return new ResultEntity<>(HttpStatus.OK, "Training task not configured", null);
|
||||
}
|
||||
return new ResultEntity<>(HttpStatus.OK, "Query success", task);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return new ResultEntity<>(HttpStatus.BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PutMapping("/classes/{teachingClassId}/{taskKey}")
|
||||
@ApiOperation("Save training task for teaching class")
|
||||
public ResultEntity<TrainingTask> saveClassTask(@PathVariable String teachingClassId,
|
||||
@PathVariable String taskKey,
|
||||
@RequestBody TrainingTask task,
|
||||
HttpServletRequest request) {
|
||||
JwtUser user = requireTeacher(request);
|
||||
try {
|
||||
return new ResultEntity<>(HttpStatus.OK, "Save success",
|
||||
trainingTaskService.saveClassTask(teachingClassId, taskKey, task, user.getUserId()));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return new ResultEntity<>(HttpStatus.BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@ApiOperation("Create training task")
|
||||
public ResultEntity<TrainingTask> create(@RequestBody TrainingTask task, HttpServletRequest request) {
|
||||
JwtUser user = requireAdmin(request);
|
||||
try {
|
||||
return new ResultEntity<>(HttpStatus.OK, "Create success", trainingTaskService.create(task, user.getUserId()));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return new ResultEntity<>(HttpStatus.BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@ApiOperation("Update training task")
|
||||
public ResultEntity<TrainingTask> update(@PathVariable String id,
|
||||
@RequestBody TrainingTask task,
|
||||
HttpServletRequest request) {
|
||||
requireAdmin(request);
|
||||
if (trainingTaskService.getById(id) == null) {
|
||||
return new ResultEntity<>(HttpStatus.NOT_FOUND, "Training task not found");
|
||||
}
|
||||
try {
|
||||
return new ResultEntity<>(HttpStatus.OK, "Update success", trainingTaskService.update(id, task));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return new ResultEntity<>(HttpStatus.BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@ApiOperation("Delete training task")
|
||||
public ResultEntity delete(@PathVariable String id, HttpServletRequest request) {
|
||||
requireAdmin(request);
|
||||
if (trainingTaskService.getById(id) == null) {
|
||||
return new ResultEntity<>(HttpStatus.NOT_FOUND, "Training task not found");
|
||||
}
|
||||
try {
|
||||
trainingTaskService.delete(id);
|
||||
return new ResultEntity<>(HttpStatus.OK, "Delete success");
|
||||
} catch (IllegalArgumentException e) {
|
||||
return new ResultEntity<>(HttpStatus.BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/import")
|
||||
@ApiOperation("Import training tasks")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResultEntity importTasks(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
|
||||
JwtUser user = requireAdmin(request);
|
||||
ResultEntity fileError = validateImportFile(file);
|
||||
if (fileError != null) {
|
||||
return fileError;
|
||||
}
|
||||
|
||||
try (InputStream inputStream = file.getInputStream()) {
|
||||
List<TrainingTaskImportDTO> rows = EasyExcel.read(inputStream)
|
||||
.head(TrainingTaskImportDTO.class)
|
||||
.sheet()
|
||||
.doReadSync();
|
||||
List<String> errors = new ArrayList<>();
|
||||
int count = trainingTaskService.importTasks(rows, user.getUserId(), errors);
|
||||
if (!errors.isEmpty()) {
|
||||
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
||||
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "Data validation failed", errors);
|
||||
}
|
||||
return new ResultEntity<>(HttpStatus.OK, "Import success, total " + count + " rows");
|
||||
} catch (IllegalArgumentException e) {
|
||||
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
||||
return new ResultEntity<>(HttpStatus.BAD_REQUEST, e.getMessage());
|
||||
} catch (Exception e) {
|
||||
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
||||
return new ResultEntity<>(HttpStatus.ACCEPTED, "Import failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/template")
|
||||
@ApiOperation("Download training task import template")
|
||||
public void downloadTemplate(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||
requireAdmin(request);
|
||||
String filename = URLEncoder.encode("training-task-import-template.xlsx", StandardCharsets.UTF_8.name()).replaceAll("\\+", "%20");
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + filename);
|
||||
EasyExcel.write(response.getOutputStream(), TrainingTaskImportDTO.class)
|
||||
.sheet("training-tasks")
|
||||
.doWrite(trainingTaskService.templateRows());
|
||||
}
|
||||
|
||||
private boolean isStudent(JwtUser user) {
|
||||
return user != null && user.getRoleId() == 4;
|
||||
}
|
||||
|
||||
private JwtUser requireAdmin(HttpServletRequest request) {
|
||||
JwtUser user = TokenProvider.getJWTUser(request);
|
||||
if (user == null || user.getRoleId() != 1) {
|
||||
throw new UnAuthorizedException("Admin only");
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
private JwtUser requireTeacher(HttpServletRequest request) {
|
||||
JwtUser user = TokenProvider.getJWTUser(request);
|
||||
if (user == null || (user.getRoleId() != 1 && user.getRoleId() != 3)) {
|
||||
throw new UnAuthorizedException("Teacher only");
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
private ResultEntity validateImportFile(MultipartFile file) {
|
||||
if (file == null || file.isEmpty()) {
|
||||
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "Please select an Excel file");
|
||||
}
|
||||
String filename = StringUtils.defaultString(file.getOriginalFilename());
|
||||
if (!StringUtils.endsWithIgnoreCase(filename, ".xls") && !StringUtils.endsWithIgnoreCase(filename, ".xlsx")) {
|
||||
return new ResultEntity<>(HttpStatus.BAD_REQUEST, "Only xls or xlsx files are supported");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue