feat: validate product development process step two
parent
763d0870e9
commit
9c5ef5bb9d
@ -0,0 +1,29 @@
|
||||
package com.sztzjy.linkCommerce.entity.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ProductDevelopmentProcessStepTwoValidationRequest {
|
||||
private List<Item> items;
|
||||
|
||||
public List<Item> getItems() { return items; }
|
||||
public void setItems(List<Item> items) { this.items = items; }
|
||||
|
||||
public static class Item {
|
||||
private String taskNo;
|
||||
private String classification;
|
||||
private String startDate;
|
||||
private String endDate;
|
||||
private String dependency;
|
||||
|
||||
public String getTaskNo() { return taskNo; }
|
||||
public void setTaskNo(String taskNo) { this.taskNo = taskNo; }
|
||||
public String getClassification() { return classification; }
|
||||
public void setClassification(String classification) { this.classification = classification; }
|
||||
public String getStartDate() { return startDate; }
|
||||
public void setStartDate(String startDate) { this.startDate = startDate; }
|
||||
public String getEndDate() { return endDate; }
|
||||
public void setEndDate(String endDate) { this.endDate = endDate; }
|
||||
public String getDependency() { return dependency; }
|
||||
public void setDependency(String dependency) { this.dependency = dependency; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.sztzjy.linkCommerce.entity.dto;
|
||||
|
||||
public class ProductDevelopmentProcessStepTwoValidationResult {
|
||||
private boolean valid;
|
||||
private String message;
|
||||
|
||||
public boolean isValid() { return valid; }
|
||||
public void setValid(boolean valid) { this.valid = valid; }
|
||||
public String getMessage() { return message; }
|
||||
public void setMessage(String message) { this.message = message; }
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.sztzjy.linkCommerce.service;
|
||||
|
||||
import com.sztzjy.linkCommerce.config.security.JwtUser;
|
||||
import com.sztzjy.linkCommerce.entity.dto.ProductDevelopmentProcessStepTwoValidationRequest;
|
||||
import com.sztzjy.linkCommerce.entity.dto.ProductDevelopmentProcessStepTwoValidationResult;
|
||||
|
||||
public interface ProductDevelopmentProcessStepTwoService {
|
||||
ProductDevelopmentProcessStepTwoValidationResult validate(ProductDevelopmentProcessStepTwoValidationRequest request, JwtUser user);
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
package com.sztzjy.linkCommerce.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.sztzjy.linkCommerce.config.exception.handler.ServiceException;
|
||||
import com.sztzjy.linkCommerce.config.security.JwtUser;
|
||||
import com.sztzjy.linkCommerce.entity.dto.ProductDevelopmentProcessStepTwoValidationRequest;
|
||||
import com.sztzjy.linkCommerce.entity.dto.ProductDevelopmentProcessStepTwoValidationResult;
|
||||
import com.sztzjy.linkCommerce.service.ProductDevelopmentProcessStepTwoService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Service
|
||||
public class ProductDevelopmentProcessStepTwoServiceImpl implements ProductDevelopmentProcessStepTwoService {
|
||||
private static final String TASK_KEY = "product-development-process";
|
||||
private static final int STEP_NO = 1;
|
||||
private static final String KEY_TASK = "关键任务";
|
||||
private static final String NON_KEY_TASK = "非关键任务";
|
||||
private static final Set<String> ALLOWED_CLASSIFICATIONS = new LinkedHashSet<>(Arrays.asList(KEY_TASK, NON_KEY_TASK));
|
||||
private static final Set<String> TASK_NUMBERS = new LinkedHashSet<>(Arrays.asList(
|
||||
"1.1", "1.2", "2.1", "2.2", "2.3", "3.1", "3.2", "3.3", "3.4", "3.5", "3.6",
|
||||
"4.1", "4.2", "4.3", "4.4", "5.1", "5.2", "5.3", "5.4"));
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
public ProductDevelopmentProcessStepTwoServiceImpl(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; }
|
||||
|
||||
@Override
|
||||
public ProductDevelopmentProcessStepTwoValidationResult validate(ProductDevelopmentProcessStepTwoValidationRequest request, JwtUser user) {
|
||||
requireStudent(user);
|
||||
Map<String, String> standardAnswers = loadStandardAnswers();
|
||||
validateItems(request == null ? null : request.getItems(), standardAnswers);
|
||||
ProductDevelopmentProcessStepTwoValidationResult result = new ProductDevelopmentProcessStepTwoValidationResult();
|
||||
result.setValid(true);
|
||||
result.setMessage("校验通过");
|
||||
return result;
|
||||
}
|
||||
|
||||
private void requireStudent(JwtUser user) {
|
||||
if (user == null || StringUtils.isBlank(user.getUserId())) throw new ServiceException(HttpStatus.UNAUTHORIZED, "请先登录后再校验");
|
||||
if (user.getRoleId() != 4) throw new ServiceException(HttpStatus.FORBIDDEN, "仅学生可进行实训校验");
|
||||
}
|
||||
|
||||
private void validateItems(List<ProductDevelopmentProcessStepTwoValidationRequest.Item> items, Map<String, String> standardAnswers) {
|
||||
if (items == null || items.size() != TASK_NUMBERS.size()) throw new ServiceException(HttpStatus.BAD_REQUEST, "请完整填写全部任务的工期与项目依赖关系");
|
||||
Set<String> submittedTasks = new LinkedHashSet<>();
|
||||
for (ProductDevelopmentProcessStepTwoValidationRequest.Item item : items) {
|
||||
String taskNo = item == null ? "" : StringUtils.trimToEmpty(item.getTaskNo());
|
||||
String classification = item == null ? "" : StringUtils.trimToEmpty(item.getClassification());
|
||||
String dependency = item == null ? "" : StringUtils.trimToEmpty(item.getDependency());
|
||||
if (!TASK_NUMBERS.contains(taskNo) || !submittedTasks.add(taskNo) || !ALLOWED_CLASSIFICATIONS.contains(classification)) {
|
||||
throw new ServiceException(HttpStatus.BAD_REQUEST, "提交的任务数据不合法");
|
||||
}
|
||||
if (!classification.equals(standardAnswers.get(taskNo))) throw new ServiceException(HttpStatus.BAD_REQUEST, "请先完成并通过第一步关键任务判断");
|
||||
if (dependency.isEmpty()) throw new ServiceException(HttpStatus.BAD_REQUEST, "请填写任务 " + taskNo + " 的项目依赖关系");
|
||||
LocalDate startDate = parseDate(item.getStartDate(), taskNo, "开始时间");
|
||||
LocalDate endDate = parseDate(item.getEndDate(), taskNo, "完成时间");
|
||||
if (endDate.isBefore(startDate)) throw new ServiceException(HttpStatus.BAD_REQUEST, "任务 " + taskNo + " 的完成时间不能早于开始时间");
|
||||
}
|
||||
if (!submittedTasks.equals(TASK_NUMBERS)) throw new ServiceException(HttpStatus.BAD_REQUEST, "提交的任务数据不完整");
|
||||
}
|
||||
|
||||
private LocalDate parseDate(String value, String taskNo, String label) {
|
||||
try {
|
||||
return LocalDate.parse(StringUtils.trimToEmpty(value));
|
||||
} catch (DateTimeParseException e) {
|
||||
throw new ServiceException(HttpStatus.BAD_REQUEST, "请填写任务 " + taskNo + " 的" + label);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, String> loadStandardAnswers() {
|
||||
String answerJson = jdbcTemplate.queryForObject(
|
||||
"SELECT answer_json FROM training_step_standard_answer WHERE task_key = ? AND step_no = ?",
|
||||
String.class, TASK_KEY, STEP_NO);
|
||||
Map<String, Object> raw = JSON.parseObject(answerJson, LinkedHashMap.class);
|
||||
Map<String, String> answers = new LinkedHashMap<>();
|
||||
for (String taskNo : TASK_NUMBERS) {
|
||||
String classification = raw == null || raw.get(taskNo) == null ? "" : String.valueOf(raw.get(taskNo));
|
||||
if (!ALLOWED_CLASSIFICATIONS.contains(classification)) throw new ServiceException(HttpStatus.INTERNAL_SERVER_ERROR, "第一步标准答案未正确配置");
|
||||
answers.put(taskNo, classification);
|
||||
}
|
||||
if (raw == null || raw.size() != answers.size()) throw new ServiceException(HttpStatus.INTERNAL_SERVER_ERROR, "第一步标准答案未正确配置");
|
||||
return answers;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package com.sztzjy.linkCommerce.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.sztzjy.linkCommerce.config.exception.handler.ServiceException;
|
||||
import com.sztzjy.linkCommerce.config.security.JwtUser;
|
||||
import com.sztzjy.linkCommerce.entity.dto.ProductDevelopmentProcessStepTwoValidationRequest;
|
||||
import com.sztzjy.linkCommerce.entity.dto.ProductDevelopmentProcessStepTwoValidationResult;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class ProductDevelopmentProcessStepTwoServiceImplTest {
|
||||
@Test
|
||||
void validateAcceptsAllTasksWithAValidSchedule() {
|
||||
ProductDevelopmentProcessStepTwoServiceImpl service = new ProductDevelopmentProcessStepTwoServiceImpl(standardAnswerJdbcTemplate());
|
||||
|
||||
ProductDevelopmentProcessStepTwoValidationResult result = service.validate(request(defaultItems()), student());
|
||||
|
||||
assertTrue(result.isValid());
|
||||
}
|
||||
|
||||
@Test
|
||||
void validateRejectsMissingDependencyInvertedDatesAndWrongFirstStepClassification() {
|
||||
ProductDevelopmentProcessStepTwoServiceImpl service = new ProductDevelopmentProcessStepTwoServiceImpl(standardAnswerJdbcTemplate());
|
||||
List<ProductDevelopmentProcessStepTwoValidationRequest.Item> missingDependency = defaultItems();
|
||||
missingDependency.get(0).setDependency("");
|
||||
assertThrows(ServiceException.class, () -> service.validate(request(missingDependency), student()));
|
||||
|
||||
List<ProductDevelopmentProcessStepTwoValidationRequest.Item> invertedDates = defaultItems();
|
||||
invertedDates.get(0).setEndDate("2026-01-01");
|
||||
assertThrows(ServiceException.class, () -> service.validate(request(invertedDates), student()));
|
||||
|
||||
List<ProductDevelopmentProcessStepTwoValidationRequest.Item> wrongClassification = defaultItems();
|
||||
wrongClassification.get(3).setClassification("关键任务");
|
||||
assertThrows(ServiceException.class, () -> service.validate(request(wrongClassification), student()));
|
||||
}
|
||||
|
||||
private JdbcTemplate standardAnswerJdbcTemplate() {
|
||||
JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class);
|
||||
Map<String, String> answers = new LinkedHashMap<>();
|
||||
for (ProductDevelopmentProcessStepTwoValidationRequest.Item item : defaultItems()) answers.put(item.getTaskNo(), item.getClassification());
|
||||
when(jdbcTemplate.queryForObject(any(String.class), any(Class.class), any(), any())).thenReturn(JSON.toJSONString(answers));
|
||||
return jdbcTemplate;
|
||||
}
|
||||
|
||||
private ProductDevelopmentProcessStepTwoValidationRequest request(List<ProductDevelopmentProcessStepTwoValidationRequest.Item> items) {
|
||||
ProductDevelopmentProcessStepTwoValidationRequest request = new ProductDevelopmentProcessStepTwoValidationRequest();
|
||||
request.setItems(items);
|
||||
return request;
|
||||
}
|
||||
|
||||
private List<ProductDevelopmentProcessStepTwoValidationRequest.Item> defaultItems() {
|
||||
return Arrays.asList(
|
||||
item("1.1", "关键任务"), item("1.2", "关键任务"), item("2.1", "关键任务"), item("2.2", "非关键任务"), item("2.3", "关键任务"),
|
||||
item("3.1", "关键任务"), item("3.2", "关键任务"), item("3.3", "非关键任务"), item("3.4", "关键任务"), item("3.5", "关键任务"), item("3.6", "关键任务"),
|
||||
item("4.1", "关键任务"), item("4.2", "关键任务"), item("4.3", "关键任务"), item("4.4", "关键任务"),
|
||||
item("5.1", "关键任务"), item("5.2", "关键任务"), item("5.3", "关键任务"), item("5.4", "关键任务"));
|
||||
}
|
||||
|
||||
private ProductDevelopmentProcessStepTwoValidationRequest.Item item(String taskNo, String classification) {
|
||||
ProductDevelopmentProcessStepTwoValidationRequest.Item item = new ProductDevelopmentProcessStepTwoValidationRequest.Item();
|
||||
item.setTaskNo(taskNo);
|
||||
item.setClassification(classification);
|
||||
item.setStartDate("2026-02-01");
|
||||
item.setEndDate("2026-02-02");
|
||||
item.setDependency("无");
|
||||
return item;
|
||||
}
|
||||
|
||||
private JwtUser student() { JwtUser user = new JwtUser(); user.setUserId("stu-1"); user.setRoleId(4); return user; }
|
||||
}
|
||||
Loading…
Reference in New Issue