From a936b92da595515c4ea573ab4a19e2934a6c7053 Mon Sep 17 00:00:00 2001 From: chenyuan Date: Tue, 11 Aug 2026 22:18:59 +0800 Subject: [PATCH] feat: validate consumer scenario journey ordering --- .../stu/StudentTrainingAnswerController.java | 17 ++++++ ...sumerScenarioStepOneValidationRequest.java | 15 +++++ ...nsumerScenarioStepOneValidationResult.java | 22 +++++++ .../ConsumerScenarioStepOneService.java | 9 +++ .../ConsumerScenarioStepOneServiceImpl.java | 54 +++++++++++++++++ ...onsumerScenarioStepOneServiceImplTest.java | 58 +++++++++++++++++++ 6 files changed, 175 insertions(+) create mode 100644 src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepOneValidationRequest.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepOneValidationResult.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/service/ConsumerScenarioStepOneService.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepOneServiceImpl.java create mode 100644 src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepOneServiceImplTest.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 ea3673c..5d79e4d 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java @@ -37,6 +37,8 @@ import com.sztzjy.linkCommerce.entity.dto.ConsumerBehaviorStepThreeValidationRes import com.sztzjy.linkCommerce.entity.dto.ConsumerBehaviorStepFourValidationRequest; import com.sztzjy.linkCommerce.entity.dto.ConsumerBehaviorStepFourValidationResult; import com.sztzjy.linkCommerce.entity.dto.ConsumerBehaviorWordPreviewResult; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepOneValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepOneValidationResult; import com.sztzjy.linkCommerce.service.NewProductSurveyStepOneService; import com.sztzjy.linkCommerce.service.MarketOpportunitySelectionStepOneService; import com.sztzjy.linkCommerce.service.MarketOpportunitySelectionStepTwoService; @@ -53,6 +55,7 @@ import com.sztzjy.linkCommerce.service.ConsumerBehaviorStepOneService; import com.sztzjy.linkCommerce.service.ConsumerBehaviorStepTwoService; import com.sztzjy.linkCommerce.service.ConsumerBehaviorStepThreeService; import com.sztzjy.linkCommerce.service.ConsumerBehaviorStepFourService; +import com.sztzjy.linkCommerce.service.ConsumerScenarioStepOneService; import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService; import com.sztzjy.linkCommerce.util.ResultEntity; import io.swagger.annotations.Api; @@ -117,6 +120,9 @@ public class StudentTrainingAnswerController { @Autowired private ConsumerBehaviorStepFourService consumerBehaviorStepFourService; + @Autowired + private ConsumerScenarioStepOneService consumerScenarioStepOneService; + @GetMapping("/{taskKey}") @ApiOperation("查询当前学生指定实训任务答案") public ResultEntity detail(@PathVariable String taskKey, @@ -321,6 +327,17 @@ public class StudentTrainingAnswerController { } } + @PostMapping("/consumer-scenario/step-1/validate") + @ApiOperation("消费场景解构第一步校验") + public ResultEntity validateConsumerScenarioStepOne( + @RequestBody ConsumerScenarioStepOneValidationRequest answer, HttpServletRequest request) { + try { + return new ResultEntity<>(HttpStatus.OK, "校验完成", consumerScenarioStepOneService.validate(answer, TokenProvider.getJWTUser(request))); + } catch (ServiceException e) { + return new ResultEntity<>(e.getCode(), e.getMessage()); + } + } + @PostMapping(value = "/consumer-behavior/step-3/word-preview", consumes = "multipart/form-data") @ApiOperation("消费者需求与行为第三步Word预览") public ResultEntity previewConsumerBehaviorStepThreeWord( diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepOneValidationRequest.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepOneValidationRequest.java new file mode 100644 index 0000000..4b4f38e --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepOneValidationRequest.java @@ -0,0 +1,15 @@ +package com.sztzjy.linkCommerce.entity.dto; + +import java.util.List; + +public class ConsumerScenarioStepOneValidationRequest { + private List stageOrder; + + public List getStageOrder() { + return stageOrder; + } + + public void setStageOrder(List stageOrder) { + this.stageOrder = stageOrder; + } +} diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepOneValidationResult.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepOneValidationResult.java new file mode 100644 index 0000000..7d15af2 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepOneValidationResult.java @@ -0,0 +1,22 @@ +package com.sztzjy.linkCommerce.entity.dto; + +public class ConsumerScenarioStepOneValidationResult { + 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/ConsumerScenarioStepOneService.java b/src/main/java/com/sztzjy/linkCommerce/service/ConsumerScenarioStepOneService.java new file mode 100644 index 0000000..ccbe7d2 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/ConsumerScenarioStepOneService.java @@ -0,0 +1,9 @@ +package com.sztzjy.linkCommerce.service; + +import com.sztzjy.linkCommerce.config.security.JwtUser; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepOneValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepOneValidationResult; + +public interface ConsumerScenarioStepOneService { + ConsumerScenarioStepOneValidationResult validate(ConsumerScenarioStepOneValidationRequest request, JwtUser user); +} diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepOneServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepOneServiceImpl.java new file mode 100644 index 0000000..d4b1555 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepOneServiceImpl.java @@ -0,0 +1,54 @@ +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.dto.ConsumerScenarioStepOneValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepOneValidationResult; +import com.sztzjy.linkCommerce.service.ConsumerScenarioStepOneService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.List; + +@Service +public class ConsumerScenarioStepOneServiceImpl implements ConsumerScenarioStepOneService { + private static final List STANDARD_ORDER = Arrays.asList( + "problem-awareness", + "information-search", + "evaluation-decision", + "purchase-conversion", + "post-purchase" + ); + + @Override + public ConsumerScenarioStepOneValidationResult validate(ConsumerScenarioStepOneValidationRequest request, JwtUser user) { + requireStudent(user); + List stageOrder = request == null ? null : request.getStageOrder(); + if (stageOrder == null || stageOrder.size() != STANDARD_ORDER.size() + || stageOrder.stream().distinct().count() != STANDARD_ORDER.size() + || !stageOrder.containsAll(STANDARD_ORDER)) { + throw badRequest("提交的购买旅程阶段不完整,请重新排序"); + } + + boolean valid = STANDARD_ORDER.equals(stageOrder); + ConsumerScenarioStepOneValidationResult result = new ConsumerScenarioStepOneValidationResult(); + result.setValid(valid); + result.setMessage(valid ? "排序正确,可以进入下一步。" : "排序还不正确,请根据消费者购买旅程再次调整。"); + 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 ServiceException badRequest(String message) { + return new ServiceException(HttpStatus.BAD_REQUEST, message); + } +} diff --git a/src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepOneServiceImplTest.java b/src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepOneServiceImplTest.java new file mode 100644 index 0000000..c6044ce --- /dev/null +++ b/src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepOneServiceImplTest.java @@ -0,0 +1,58 @@ +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.dto.ConsumerScenarioStepOneValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepOneValidationResult; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ConsumerScenarioStepOneServiceImplTest { + @Test + void acceptsTheStandardJourneyOrder() { + ConsumerScenarioStepOneValidationResult result = new ConsumerScenarioStepOneServiceImpl().validate(request( + "problem-awareness", "information-search", "evaluation-decision", "purchase-conversion", "post-purchase"), student()); + + assertTrue(result.isValid()); + } + + @Test + void returnsAnIncorrectResultForAnUnorderedJourney() { + ConsumerScenarioStepOneValidationResult result = new ConsumerScenarioStepOneServiceImpl().validate(request( + "information-search", "problem-awareness", "evaluation-decision", "purchase-conversion", "post-purchase"), student()); + + assertFalse(result.isValid()); + } + + @Test + void rejectsIncompleteJourneyData() { + assertThrows(ServiceException.class, () -> new ConsumerScenarioStepOneServiceImpl().validate(request( + "problem-awareness", "information-search"), student())); + } + + @Test + void rejectsNonStudent() { + JwtUser teacher = new JwtUser(); + teacher.setRoleId(2); + assertThrows(ServiceException.class, () -> new ConsumerScenarioStepOneServiceImpl().validate(request( + "problem-awareness", "information-search", "evaluation-decision", "purchase-conversion", "post-purchase"), teacher)); + } + + private ConsumerScenarioStepOneValidationRequest request(String... stageOrder) { + ConsumerScenarioStepOneValidationRequest request = new ConsumerScenarioStepOneValidationRequest(); + request.setStageOrder(Arrays.asList(stageOrder)); + return request; + } + + private JwtUser student() { + JwtUser user = new JwtUser(); + user.setUserId("stu-1"); + user.setRoleId(4); + return user; + } +}