From 3a62dbd3a0209c682f6618eccde2b0a4909e00ab Mon Sep 17 00:00:00 2001 From: chenyuan Date: Fri, 7 Aug 2026 16:44:31 +0800 Subject: [PATCH] feat: validate industry demand analysis step two --- .../stu/StudentTrainingAnswerController.java | 17 ++++++ ...emandAnalysisStepTwoValidationRequest.java | 17 ++++++ ...DemandAnalysisStepTwoValidationResult.java | 11 ++++ .../IndustryDemandAnalysisStepTwoService.java | 9 +++ ...ustryDemandAnalysisStepTwoServiceImpl.java | 43 +++++++++++++ .../StudentTrainingAnswerControllerTest.java | 20 ++++++ ...yDemandAnalysisStepTwoServiceImplTest.java | 61 +++++++++++++++++++ 7 files changed, 178 insertions(+) create mode 100644 src/main/java/com/sztzjy/linkCommerce/entity/dto/IndustryDemandAnalysisStepTwoValidationRequest.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/entity/dto/IndustryDemandAnalysisStepTwoValidationResult.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/service/IndustryDemandAnalysisStepTwoService.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/service/impl/IndustryDemandAnalysisStepTwoServiceImpl.java create mode 100644 src/test/java/com/sztzjy/linkCommerce/service/impl/IndustryDemandAnalysisStepTwoServiceImplTest.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 40b347b..48d5034 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java @@ -6,6 +6,8 @@ import com.sztzjy.linkCommerce.config.security.TokenProvider; import com.sztzjy.linkCommerce.entity.StudentTrainingAnswer; import com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepOneValidationRequest; import com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepOneValidationResult; +import com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepTwoValidationResult; import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckRequest; import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckResult; import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepTwoValidationRequest; @@ -32,6 +34,7 @@ import com.sztzjy.linkCommerce.service.ProductDevelopmentFactorsStepThreeService import com.sztzjy.linkCommerce.service.ProductDevelopmentFactorsStepFourService; import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService; import com.sztzjy.linkCommerce.service.IndustryDemandAnalysisStepOneService; +import com.sztzjy.linkCommerce.service.IndustryDemandAnalysisStepTwoService; import com.sztzjy.linkCommerce.util.ResultEntity; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -51,6 +54,9 @@ public class StudentTrainingAnswerController { @Autowired private IndustryDemandAnalysisStepOneService industryDemandAnalysisStepOneService; + @Autowired + private IndustryDemandAnalysisStepTwoService industryDemandAnalysisStepTwoService; + @Autowired private NewProductSurveyStepOneService newProductSurveyStepOneService; @@ -110,6 +116,17 @@ public class StudentTrainingAnswerController { } } + @PostMapping("/industry-demand-analysis/step-2/validate") + @ApiOperation("行业需求分析第二步校验") + public ResultEntity validateIndustryDemandAnalysisStepTwo( + @RequestBody IndustryDemandAnalysisStepTwoValidationRequest answer, HttpServletRequest request) { + try { + return new ResultEntity<>(HttpStatus.OK, "校验通过", industryDemandAnalysisStepTwoService.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/IndustryDemandAnalysisStepTwoValidationRequest.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/IndustryDemandAnalysisStepTwoValidationRequest.java new file mode 100644 index 0000000..2465396 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/IndustryDemandAnalysisStepTwoValidationRequest.java @@ -0,0 +1,17 @@ +package com.sztzjy.linkCommerce.entity.dto; + +public class IndustryDemandAnalysisStepTwoValidationRequest { + private String political; + private String economic; + private String social; + private String technology; + + public String getPolitical() { return political; } + public void setPolitical(String political) { this.political = political; } + public String getEconomic() { return economic; } + public void setEconomic(String economic) { this.economic = economic; } + public String getSocial() { return social; } + public void setSocial(String social) { this.social = social; } + public String getTechnology() { return technology; } + public void setTechnology(String technology) { this.technology = technology; } +} diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/dto/IndustryDemandAnalysisStepTwoValidationResult.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/IndustryDemandAnalysisStepTwoValidationResult.java new file mode 100644 index 0000000..5520dee --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/IndustryDemandAnalysisStepTwoValidationResult.java @@ -0,0 +1,11 @@ +package com.sztzjy.linkCommerce.entity.dto; + +public class IndustryDemandAnalysisStepTwoValidationResult { + 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/IndustryDemandAnalysisStepTwoService.java b/src/main/java/com/sztzjy/linkCommerce/service/IndustryDemandAnalysisStepTwoService.java new file mode 100644 index 0000000..f037e5c --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/IndustryDemandAnalysisStepTwoService.java @@ -0,0 +1,9 @@ +package com.sztzjy.linkCommerce.service; + +import com.sztzjy.linkCommerce.config.security.JwtUser; +import com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepTwoValidationResult; + +public interface IndustryDemandAnalysisStepTwoService { + IndustryDemandAnalysisStepTwoValidationResult validate(IndustryDemandAnalysisStepTwoValidationRequest request, JwtUser user); +} diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/IndustryDemandAnalysisStepTwoServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/IndustryDemandAnalysisStepTwoServiceImpl.java new file mode 100644 index 0000000..4e85ed8 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/IndustryDemandAnalysisStepTwoServiceImpl.java @@ -0,0 +1,43 @@ +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.IndustryDemandAnalysisStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepTwoValidationResult; +import com.sztzjy.linkCommerce.service.IndustryDemandAnalysisStepTwoService; +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; + +@Service +public class IndustryDemandAnalysisStepTwoServiceImpl implements IndustryDemandAnalysisStepTwoService { + private static final String TASK_KEY = "industry-demand-analysis"; + + @Autowired + private StudentTrainingAnswerService studentTrainingAnswerService; + + @Override + public IndustryDemandAnalysisStepTwoValidationResult validate(IndustryDemandAnalysisStepTwoValidationRequest request, JwtUser user) { + requireStudent(user); + StudentTrainingAnswer savedAnswer = studentTrainingAnswerService.get(TASK_KEY, null, user); + if (savedAnswer == null || StringUtils.isBlank(savedAnswer.getStep1Answer())) { + throw new ServiceException(HttpStatus.BAD_REQUEST, "请先完成并保存第 1 步的 PEST 信息归类"); + } + if (request == null || StringUtils.isBlank(request.getPolitical()) || StringUtils.isBlank(request.getEconomic()) + || StringUtils.isBlank(request.getSocial()) || StringUtils.isBlank(request.getTechnology())) { + throw new ServiceException(HttpStatus.BAD_REQUEST, "请为政治、经济、社会和技术环境各补充至少 1 条信息"); + } + IndustryDemandAnalysisStepTwoValidationResult result = new IndustryDemandAnalysisStepTwoValidationResult(); + 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, "仅学生可进行实训校验"); + } +} 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 26325e2..fcdbdbc 100644 --- a/src/test/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerControllerTest.java +++ b/src/test/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerControllerTest.java @@ -5,6 +5,8 @@ import com.sztzjy.linkCommerce.config.security.JwtUser; import com.sztzjy.linkCommerce.config.security.TokenProvider; import com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepOneValidationRequest; import com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepOneValidationResult; +import com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepTwoValidationResult; import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckRequest; import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckResult; import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepTwoValidationRequest; @@ -21,6 +23,7 @@ import com.sztzjy.linkCommerce.entity.dto.ProductDevelopmentFactorsStepThreeVali import com.sztzjy.linkCommerce.entity.dto.ProductDevelopmentFactorsStepThreeValidationResult; import com.sztzjy.linkCommerce.service.NewProductSurveyStepOneService; import com.sztzjy.linkCommerce.service.IndustryDemandAnalysisStepOneService; +import com.sztzjy.linkCommerce.service.IndustryDemandAnalysisStepTwoService; import com.sztzjy.linkCommerce.service.NewProductSurveyStepTwoService; import com.sztzjy.linkCommerce.service.NewProductSurveyStepThreeService; import com.sztzjy.linkCommerce.service.NewProductSurveyStepFourService; @@ -60,6 +63,23 @@ class StudentTrainingAnswerControllerTest { verify(service).validate(any(IndustryDemandAnalysisStepOneValidationRequest.class), any(JwtUser.class)); } + @Test + void validateIndustryDemandAnalysisStepTwoUsesTheAuthenticatedStudentAndReturnsTheValidationResult() { + StudentTrainingAnswerController controller = new StudentTrainingAnswerController(); + IndustryDemandAnalysisStepTwoService service = mock(IndustryDemandAnalysisStepTwoService.class); + ReflectionTestUtils.setField(controller, "industryDemandAnalysisStepTwoService", service); + IndustryDemandAnalysisStepTwoValidationResult validation = new IndustryDemandAnalysisStepTwoValidationResult(); + validation.setValid(true); + when(service.validate(any(IndustryDemandAnalysisStepTwoValidationRequest.class), any(JwtUser.class))).thenReturn(validation); + + ResultEntity result = controller + .validateIndustryDemandAnalysisStepTwo(new IndustryDemandAnalysisStepTwoValidationRequest(), authenticatedStudentRequest()); + + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals(validation, result.getBody().getData()); + verify(service).validate(any(IndustryDemandAnalysisStepTwoValidationRequest.class), any(JwtUser.class)); + } + @Test void checkStepOneUsesTheAuthenticatedStudentAndReturnsTheGrade() { StudentTrainingAnswerController controller = new StudentTrainingAnswerController(); diff --git a/src/test/java/com/sztzjy/linkCommerce/service/impl/IndustryDemandAnalysisStepTwoServiceImplTest.java b/src/test/java/com/sztzjy/linkCommerce/service/impl/IndustryDemandAnalysisStepTwoServiceImplTest.java new file mode 100644 index 0000000..ae200ab --- /dev/null +++ b/src/test/java/com/sztzjy/linkCommerce/service/impl/IndustryDemandAnalysisStepTwoServiceImplTest.java @@ -0,0 +1,61 @@ +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.IndustryDemandAnalysisStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepTwoValidationResult; +import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService; +import org.junit.jupiter.api.Test; +import org.springframework.test.util.ReflectionTestUtils; + +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 IndustryDemandAnalysisStepTwoServiceImplTest { + @Test + void validateAcceptsOneSupplementForEachPestDimensionAfterStepOneIsSaved() { + IndustryDemandAnalysisStepTwoServiceImpl service = serviceWithStepOne(); + IndustryDemandAnalysisStepTwoValidationResult result = service.validate(completedRequest(), student()); + assertTrue(result.isValid()); + } + + @Test + void validateRejectsMissingSupplementAndMissingStepOne() { + IndustryDemandAnalysisStepTwoServiceImpl service = serviceWithStepOne(); + IndustryDemandAnalysisStepTwoValidationRequest missingTechnology = completedRequest(); + missingTechnology.setTechnology(" "); + assertThrows(ServiceException.class, () -> service.validate(missingTechnology, student())); + + IndustryDemandAnalysisStepTwoServiceImpl noStepOneService = new IndustryDemandAnalysisStepTwoServiceImpl(); + StudentTrainingAnswerService answerService = mock(StudentTrainingAnswerService.class); + ReflectionTestUtils.setField(noStepOneService, "studentTrainingAnswerService", answerService); + when(answerService.get(anyString(), any(), any(JwtUser.class))).thenReturn(null); + assertThrows(ServiceException.class, () -> noStepOneService.validate(completedRequest(), student())); + } + + private IndustryDemandAnalysisStepTwoServiceImpl serviceWithStepOne() { + IndustryDemandAnalysisStepTwoServiceImpl service = new IndustryDemandAnalysisStepTwoServiceImpl(); + StudentTrainingAnswerService answerService = mock(StudentTrainingAnswerService.class); + StudentTrainingAnswer savedAnswer = new StudentTrainingAnswer(); + savedAnswer.setStep1Answer("{\"pest\":{\"political\":\"已填写\"}}"); + when(answerService.get(anyString(), any(), any(JwtUser.class))).thenReturn(savedAnswer); + ReflectionTestUtils.setField(service, "studentTrainingAnswerService", answerService); + return service; + } + + private IndustryDemandAnalysisStepTwoValidationRequest completedRequest() { + IndustryDemandAnalysisStepTwoValidationRequest request = new IndustryDemandAnalysisStepTwoValidationRequest(); + request.setPolitical("行业政策与健康管理规范资讯"); + request.setEconomic("家庭健身设备市场增长资讯"); + request.setSocial("居民健康消费需求变化资讯"); + request.setTechnology("AI 视觉识别技术进展资讯"); + return request; + } + + private JwtUser student() { JwtUser user = new JwtUser(); user.setUserId("stu-1"); user.setRoleId(4); return user; } +}