From a4f8adf68adc496598afb9fec3b8817e054776c5 Mon Sep 17 00:00:00 2001 From: chenyuan Date: Fri, 7 Aug 2026 17:48:51 +0800 Subject: [PATCH] feat: validate competitive analysis step three --- .../stu/StudentTrainingAnswerController.java | 17 ++++++ ...entAnalysisStepThreeValidationRequest.java | 23 ++++++++ ...mentAnalysisStepThreeValidationResult.java | 11 ++++ ...veEnvironmentAnalysisStepThreeService.java | 9 +++ ...vironmentAnalysisStepThreeServiceImpl.java | 51 ++++++++++++++++ .../StudentTrainingAnswerControllerTest.java | 15 +++++ ...nmentAnalysisStepThreeServiceImplTest.java | 59 +++++++++++++++++++ 7 files changed, 185 insertions(+) create mode 100644 src/main/java/com/sztzjy/linkCommerce/entity/dto/CompetitiveEnvironmentAnalysisStepThreeValidationRequest.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/entity/dto/CompetitiveEnvironmentAnalysisStepThreeValidationResult.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/service/CompetitiveEnvironmentAnalysisStepThreeService.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/service/impl/CompetitiveEnvironmentAnalysisStepThreeServiceImpl.java create mode 100644 src/test/java/com/sztzjy/linkCommerce/service/impl/CompetitiveEnvironmentAnalysisStepThreeServiceImplTest.java diff --git a/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java b/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java index adfd982..66c0dfa 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java @@ -8,6 +8,8 @@ import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepOneV import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepOneValidationResult; import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepTwoValidationRequest; import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepTwoValidationResult; +import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepThreeValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepThreeValidationResult; import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckRequest; import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckResult; import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepTwoValidationRequest; @@ -35,6 +37,7 @@ import com.sztzjy.linkCommerce.service.ProductDevelopmentFactorsStepFourService; import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService; import com.sztzjy.linkCommerce.service.CompetitiveEnvironmentAnalysisStepOneService; import com.sztzjy.linkCommerce.service.CompetitiveEnvironmentAnalysisStepTwoService; +import com.sztzjy.linkCommerce.service.CompetitiveEnvironmentAnalysisStepThreeService; import com.sztzjy.linkCommerce.util.ResultEntity; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -57,6 +60,9 @@ public class StudentTrainingAnswerController { @Autowired private CompetitiveEnvironmentAnalysisStepTwoService competitiveEnvironmentAnalysisStepTwoService; + @Autowired + private CompetitiveEnvironmentAnalysisStepThreeService competitiveEnvironmentAnalysisStepThreeService; + @Autowired private NewProductSurveyStepOneService newProductSurveyStepOneService; @@ -127,6 +133,17 @@ public class StudentTrainingAnswerController { } } + @PostMapping("/competitive-environment-analysis/step-3/validate") + @ApiOperation("竞争环境分析第三步校验") + public ResultEntity validateCompetitiveEnvironmentAnalysisStepThree( + @RequestBody CompetitiveEnvironmentAnalysisStepThreeValidationRequest answer, HttpServletRequest request) { + try { + return new ResultEntity<>(HttpStatus.OK, "校验通过", competitiveEnvironmentAnalysisStepThreeService.validate(answer, TokenProvider.getJWTUser(request))); + } catch (ServiceException e) { + return new ResultEntity<>(e.getCode(), e.getMessage()); + } + } + @PostMapping("/new-product-survey/step-1/check") @ApiOperation("新产品调查与分析第一步判题") public ResultEntity checkNewProductSurveyStepOne( diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/dto/CompetitiveEnvironmentAnalysisStepThreeValidationRequest.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/CompetitiveEnvironmentAnalysisStepThreeValidationRequest.java new file mode 100644 index 0000000..94b2f8c --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/CompetitiveEnvironmentAnalysisStepThreeValidationRequest.java @@ -0,0 +1,23 @@ +package com.sztzjy.linkCommerce.entity.dto; + +import java.util.List; + +public class CompetitiveEnvironmentAnalysisStepThreeValidationRequest { + private List strategies; + + public List getStrategies() { return strategies; } + public void setStrategies(List strategies) { this.strategies = strategies; } + + public static class Strategy { + private String strategyType; + private String recommendation; + private String expectedEffect; + + public String getStrategyType() { return strategyType; } + public void setStrategyType(String strategyType) { this.strategyType = strategyType; } + public String getRecommendation() { return recommendation; } + public void setRecommendation(String recommendation) { this.recommendation = recommendation; } + public String getExpectedEffect() { return expectedEffect; } + public void setExpectedEffect(String expectedEffect) { this.expectedEffect = expectedEffect; } + } +} diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/dto/CompetitiveEnvironmentAnalysisStepThreeValidationResult.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/CompetitiveEnvironmentAnalysisStepThreeValidationResult.java new file mode 100644 index 0000000..4fd5773 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/CompetitiveEnvironmentAnalysisStepThreeValidationResult.java @@ -0,0 +1,11 @@ +package com.sztzjy.linkCommerce.entity.dto; + +public class CompetitiveEnvironmentAnalysisStepThreeValidationResult { + 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; } +} diff --git a/src/main/java/com/sztzjy/linkCommerce/service/CompetitiveEnvironmentAnalysisStepThreeService.java b/src/main/java/com/sztzjy/linkCommerce/service/CompetitiveEnvironmentAnalysisStepThreeService.java new file mode 100644 index 0000000..f102a0f --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/CompetitiveEnvironmentAnalysisStepThreeService.java @@ -0,0 +1,9 @@ +package com.sztzjy.linkCommerce.service; + +import com.sztzjy.linkCommerce.config.security.JwtUser; +import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepThreeValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepThreeValidationResult; + +public interface CompetitiveEnvironmentAnalysisStepThreeService { + CompetitiveEnvironmentAnalysisStepThreeValidationResult validate(CompetitiveEnvironmentAnalysisStepThreeValidationRequest request, JwtUser user); +} diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/CompetitiveEnvironmentAnalysisStepThreeServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/CompetitiveEnvironmentAnalysisStepThreeServiceImpl.java new file mode 100644 index 0000000..c11fe2e --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/CompetitiveEnvironmentAnalysisStepThreeServiceImpl.java @@ -0,0 +1,51 @@ +package com.sztzjy.linkCommerce.service.impl; + +import com.sztzjy.linkCommerce.config.exception.handler.ServiceException; +import com.sztzjy.linkCommerce.config.security.JwtUser; +import com.sztzjy.linkCommerce.entity.StudentTrainingAnswer; +import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepThreeValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepThreeValidationResult; +import com.sztzjy.linkCommerce.service.CompetitiveEnvironmentAnalysisStepThreeService; +import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +@Service +public class CompetitiveEnvironmentAnalysisStepThreeServiceImpl implements CompetitiveEnvironmentAnalysisStepThreeService { + private static final String TASK_KEY = "competitive-environment-analysis"; + private static final Set STRATEGY_TYPES = new HashSet<>(Arrays.asList("so", "wo", "st", "wt")); + + @Autowired private StudentTrainingAnswerService studentTrainingAnswerService; + + @Override + public CompetitiveEnvironmentAnalysisStepThreeValidationResult validate(CompetitiveEnvironmentAnalysisStepThreeValidationRequest request, JwtUser user) { + if (user == null || StringUtils.isBlank(user.getUserId())) throw new ServiceException(HttpStatus.UNAUTHORIZED, "请先登录后再校验"); + if (user.getRoleId() != 4) throw new ServiceException(HttpStatus.FORBIDDEN, "仅学生可进行实训校验"); + StudentTrainingAnswer savedAnswer = studentTrainingAnswerService.get(TASK_KEY, null, user); + if (savedAnswer == null || StringUtils.isBlank(savedAnswer.getStep1Answer()) || StringUtils.isBlank(savedAnswer.getStep2Answer())) { + throw new ServiceException(HttpStatus.BAD_REQUEST, "请先完成并保存前两步的 SWOT 信息归类与补充"); + } + if (request == null || request.getStrategies() == null || request.getStrategies().size() != STRATEGY_TYPES.size()) { + throw new ServiceException(HttpStatus.BAD_REQUEST, "请完成 SO、WO、ST 和 WT 四类策略"); + } + Set submittedTypes = new HashSet<>(); + for (CompetitiveEnvironmentAnalysisStepThreeValidationRequest.Strategy strategy : request.getStrategies()) { + String strategyType = strategy == null ? "" : StringUtils.trimToEmpty(strategy.getStrategyType()); + if (!STRATEGY_TYPES.contains(strategyType) || !submittedTypes.add(strategyType)) { + throw new ServiceException(HttpStatus.BAD_REQUEST, "请完成 SO、WO、ST 和 WT 四类策略"); + } + if (StringUtils.isBlank(strategy.getRecommendation()) || StringUtils.isBlank(strategy.getExpectedEffect())) { + throw new ServiceException(HttpStatus.BAD_REQUEST, "请为每类策略填写建议和预期效果"); + } + } + CompetitiveEnvironmentAnalysisStepThreeValidationResult result = new CompetitiveEnvironmentAnalysisStepThreeValidationResult(); + result.setValid(true); result.setMessage("校验通过"); + return result; + } +} diff --git a/src/test/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerControllerTest.java b/src/test/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerControllerTest.java index c54cf48..1f92189 100644 --- a/src/test/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerControllerTest.java +++ b/src/test/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerControllerTest.java @@ -8,6 +8,8 @@ import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepOneV import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepOneValidationResult; import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepTwoValidationRequest; import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepTwoValidationResult; +import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepThreeValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepThreeValidationResult; import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckResult; import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepTwoValidationRequest; import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepTwoValidationResult; @@ -24,6 +26,7 @@ import com.sztzjy.linkCommerce.entity.dto.ProductDevelopmentFactorsStepThreeVali import com.sztzjy.linkCommerce.service.NewProductSurveyStepOneService; import com.sztzjy.linkCommerce.service.CompetitiveEnvironmentAnalysisStepOneService; import com.sztzjy.linkCommerce.service.CompetitiveEnvironmentAnalysisStepTwoService; +import com.sztzjy.linkCommerce.service.CompetitiveEnvironmentAnalysisStepThreeService; import com.sztzjy.linkCommerce.service.NewProductSurveyStepTwoService; import com.sztzjy.linkCommerce.service.NewProductSurveyStepThreeService; import com.sztzjy.linkCommerce.service.NewProductSurveyStepFourService; @@ -75,6 +78,18 @@ class StudentTrainingAnswerControllerTest { verify(service).validate(any(CompetitiveEnvironmentAnalysisStepTwoValidationRequest.class), any(JwtUser.class)); } + @Test + void validateCompetitiveEnvironmentAnalysisStepThreeUsesTheAuthenticatedStudentAndReturnsTheValidationResult() { + StudentTrainingAnswerController controller = new StudentTrainingAnswerController(); + CompetitiveEnvironmentAnalysisStepThreeService service = mock(CompetitiveEnvironmentAnalysisStepThreeService.class); + ReflectionTestUtils.setField(controller, "competitiveEnvironmentAnalysisStepThreeService", service); + CompetitiveEnvironmentAnalysisStepThreeValidationResult validation = new CompetitiveEnvironmentAnalysisStepThreeValidationResult(); validation.setValid(true); + when(service.validate(any(CompetitiveEnvironmentAnalysisStepThreeValidationRequest.class), any(JwtUser.class))).thenReturn(validation); + ResultEntity result = controller.validateCompetitiveEnvironmentAnalysisStepThree(new CompetitiveEnvironmentAnalysisStepThreeValidationRequest(), authenticatedStudentRequest()); + assertEquals(HttpStatus.OK, result.getStatusCode()); assertEquals(validation, result.getBody().getData()); + verify(service).validate(any(CompetitiveEnvironmentAnalysisStepThreeValidationRequest.class), any(JwtUser.class)); + } + @Test void checkStepOneUsesTheAuthenticatedStudentAndReturnsTheGrade() { StudentTrainingAnswerController controller = new StudentTrainingAnswerController(); diff --git a/src/test/java/com/sztzjy/linkCommerce/service/impl/CompetitiveEnvironmentAnalysisStepThreeServiceImplTest.java b/src/test/java/com/sztzjy/linkCommerce/service/impl/CompetitiveEnvironmentAnalysisStepThreeServiceImplTest.java new file mode 100644 index 0000000..55fc249 --- /dev/null +++ b/src/test/java/com/sztzjy/linkCommerce/service/impl/CompetitiveEnvironmentAnalysisStepThreeServiceImplTest.java @@ -0,0 +1,59 @@ +package com.sztzjy.linkCommerce.service.impl; + +import com.sztzjy.linkCommerce.config.exception.handler.ServiceException; +import com.sztzjy.linkCommerce.config.security.JwtUser; +import com.sztzjy.linkCommerce.entity.StudentTrainingAnswer; +import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepThreeValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.CompetitiveEnvironmentAnalysisStepThreeValidationResult; +import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService; +import org.junit.jupiter.api.Test; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.ArrayList; +import java.util.Arrays; + +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.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class CompetitiveEnvironmentAnalysisStepThreeServiceImplTest { + @Test + void validateAcceptsAllStrategiesAfterFirstTwoStepsAreSaved() { + CompetitiveEnvironmentAnalysisStepThreeValidationResult result = serviceWithFirstTwoSteps().validate(completedRequest(), student()); + assertTrue(result.isValid()); + } + + @Test + void validateRejectsIncompleteStrategiesAndMissingPrerequisiteSteps() { + CompetitiveEnvironmentAnalysisStepThreeValidationRequest incomplete = completedRequest(); + incomplete.getStrategies().get(0).setExpectedEffect(" "); + assertThrows(ServiceException.class, () -> serviceWithFirstTwoSteps().validate(incomplete, student())); + + CompetitiveEnvironmentAnalysisStepThreeServiceImpl service = new CompetitiveEnvironmentAnalysisStepThreeServiceImpl(); + StudentTrainingAnswerService answers = mock(StudentTrainingAnswerService.class); + ReflectionTestUtils.setField(service, "studentTrainingAnswerService", answers); + when(answers.get(anyString(), any(), any(JwtUser.class))).thenReturn(null); + assertThrows(ServiceException.class, () -> service.validate(completedRequest(), student())); + } + + private CompetitiveEnvironmentAnalysisStepThreeServiceImpl serviceWithFirstTwoSteps() { + CompetitiveEnvironmentAnalysisStepThreeServiceImpl service = new CompetitiveEnvironmentAnalysisStepThreeServiceImpl(); + StudentTrainingAnswerService answers = mock(StudentTrainingAnswerService.class); + StudentTrainingAnswer answer = new StudentTrainingAnswer(); answer.setStep1Answer("{\"swot\":{}}"); answer.setStep2Answer("{\"supplements\":{}}"); + when(answers.get(anyString(), any(), any(JwtUser.class))).thenReturn(answer); + ReflectionTestUtils.setField(service, "studentTrainingAnswerService", answers); + return service; + } + + private CompetitiveEnvironmentAnalysisStepThreeValidationRequest completedRequest() { + CompetitiveEnvironmentAnalysisStepThreeValidationRequest request = new CompetitiveEnvironmentAnalysisStepThreeValidationRequest(); + ArrayList strategies = new ArrayList<>(); + Arrays.asList("so", "wo", "st", "wt").forEach(type -> { CompetitiveEnvironmentAnalysisStepThreeValidationRequest.Strategy item = new CompetitiveEnvironmentAnalysisStepThreeValidationRequest.Strategy(); item.setStrategyType(type); item.setRecommendation(type + " 策略建议"); item.setExpectedEffect(type + " 预期效果"); strategies.add(item); }); + request.setStrategies(strategies); return request; + } + + private JwtUser student() { JwtUser user = new JwtUser(); user.setUserId("stu-1"); user.setRoleId(4); return user; } +}