From a936b92da595515c4ea573ab4a19e2934a6c7053 Mon Sep 17 00:00:00 2001 From: chenyuan Date: Tue, 11 Aug 2026 22:18:59 +0800 Subject: [PATCH 1/4] 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; + } +} From c0e7fc82b0c6ff487b8e650b591d4bd82e8662ff Mon Sep 17 00:00:00 2001 From: chenyuan Date: Tue, 11 Aug 2026 22:29:36 +0800 Subject: [PATCH 2/4] feat: validate consumer scenario journey analysis --- .../stu/StudentTrainingAnswerController.java | 17 +++++ ...sumerScenarioStepTwoValidationRequest.java | 34 ++++++++++ ...nsumerScenarioStepTwoValidationResult.java | 11 ++++ .../ConsumerScenarioStepTwoService.java | 9 +++ .../ConsumerScenarioStepTwoServiceImpl.java | 55 ++++++++++++++++ ...onsumerScenarioStepTwoServiceImplTest.java | 65 +++++++++++++++++++ 6 files changed, 191 insertions(+) create mode 100644 src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepTwoValidationRequest.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepTwoValidationResult.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/service/ConsumerScenarioStepTwoService.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepTwoServiceImpl.java create mode 100644 src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepTwoServiceImplTest.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 5d79e4d..1065cf1 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java @@ -39,6 +39,8 @@ import com.sztzjy.linkCommerce.entity.dto.ConsumerBehaviorStepFourValidationResu 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.entity.dto.ConsumerScenarioStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepTwoValidationResult; import com.sztzjy.linkCommerce.service.NewProductSurveyStepOneService; import com.sztzjy.linkCommerce.service.MarketOpportunitySelectionStepOneService; import com.sztzjy.linkCommerce.service.MarketOpportunitySelectionStepTwoService; @@ -56,6 +58,7 @@ 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.ConsumerScenarioStepTwoService; import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService; import com.sztzjy.linkCommerce.util.ResultEntity; import io.swagger.annotations.Api; @@ -123,6 +126,9 @@ public class StudentTrainingAnswerController { @Autowired private ConsumerScenarioStepOneService consumerScenarioStepOneService; + @Autowired + private ConsumerScenarioStepTwoService consumerScenarioStepTwoService; + @GetMapping("/{taskKey}") @ApiOperation("查询当前学生指定实训任务答案") public ResultEntity detail(@PathVariable String taskKey, @@ -338,6 +344,17 @@ public class StudentTrainingAnswerController { } } + @PostMapping("/consumer-scenario/step-2/validate") + @ApiOperation("消费场景解构第二步校验") + public ResultEntity validateConsumerScenarioStepTwo( + @RequestBody ConsumerScenarioStepTwoValidationRequest answer, HttpServletRequest request) { + try { + return new ResultEntity<>(HttpStatus.OK, "校验完成", consumerScenarioStepTwoService.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/ConsumerScenarioStepTwoValidationRequest.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepTwoValidationRequest.java new file mode 100644 index 0000000..bad4441 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepTwoValidationRequest.java @@ -0,0 +1,34 @@ +package com.sztzjy.linkCommerce.entity.dto; + +import java.util.List; + +public class ConsumerScenarioStepTwoValidationRequest { + private List rows; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public static class JourneyAnalysisRow { + private String stageId; + private String behaviorDescription; + private String keyTouchpoints; + private String emotionExperience; + private String decisionFactors; + + public String getStageId() { return stageId; } + public void setStageId(String stageId) { this.stageId = stageId; } + public String getBehaviorDescription() { return behaviorDescription; } + public void setBehaviorDescription(String behaviorDescription) { this.behaviorDescription = behaviorDescription; } + public String getKeyTouchpoints() { return keyTouchpoints; } + public void setKeyTouchpoints(String keyTouchpoints) { this.keyTouchpoints = keyTouchpoints; } + public String getEmotionExperience() { return emotionExperience; } + public void setEmotionExperience(String emotionExperience) { this.emotionExperience = emotionExperience; } + public String getDecisionFactors() { return decisionFactors; } + public void setDecisionFactors(String decisionFactors) { this.decisionFactors = decisionFactors; } + } +} diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepTwoValidationResult.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepTwoValidationResult.java new file mode 100644 index 0000000..7a0beeb --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepTwoValidationResult.java @@ -0,0 +1,11 @@ +package com.sztzjy.linkCommerce.entity.dto; + +public class ConsumerScenarioStepTwoValidationResult { + 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/ConsumerScenarioStepTwoService.java b/src/main/java/com/sztzjy/linkCommerce/service/ConsumerScenarioStepTwoService.java new file mode 100644 index 0000000..cbb7d29 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/ConsumerScenarioStepTwoService.java @@ -0,0 +1,9 @@ +package com.sztzjy.linkCommerce.service; + +import com.sztzjy.linkCommerce.config.security.JwtUser; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepTwoValidationResult; + +public interface ConsumerScenarioStepTwoService { + ConsumerScenarioStepTwoValidationResult validate(ConsumerScenarioStepTwoValidationRequest request, JwtUser user); +} diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepTwoServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepTwoServiceImpl.java new file mode 100644 index 0000000..4c05c29 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepTwoServiceImpl.java @@ -0,0 +1,55 @@ +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.ConsumerScenarioStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepTwoValidationResult; +import com.sztzjy.linkCommerce.service.ConsumerScenarioStepTwoService; +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 ConsumerScenarioStepTwoServiceImpl implements ConsumerScenarioStepTwoService { + private static final List STAGE_IDS = Arrays.asList( + "problem-awareness", "information-search", "evaluation-decision", "purchase-conversion", "post-purchase" + ); + private static final List EMOTIONS = Arrays.asList("负面", "中性", "正面"); + + @Override + public ConsumerScenarioStepTwoValidationResult validate(ConsumerScenarioStepTwoValidationRequest request, JwtUser user) { + requireStudent(user); + List rows = request == null ? null : request.getRows(); + if (rows == null || rows.size() != STAGE_IDS.size() || rows.stream().anyMatch(row -> row == null) + || rows.stream().map(ConsumerScenarioStepTwoValidationRequest.JourneyAnalysisRow::getStageId).distinct().count() != STAGE_IDS.size() + || rows.stream().anyMatch(row -> !STAGE_IDS.contains(row.getStageId()))) { + throw badRequest("请完整填写五个购买旅程阶段的分析"); + } + for (ConsumerScenarioStepTwoValidationRequest.JourneyAnalysisRow row : rows) { + if (StringUtils.isBlank(row.getBehaviorDescription()) || StringUtils.isBlank(row.getKeyTouchpoints()) + || StringUtils.isBlank(row.getDecisionFactors()) || !EMOTIONS.contains(row.getEmotionExperience())) { + throw badRequest("请完整填写用户行为、关键触点、情感体验和关键决策因素"); + } + } + ConsumerScenarioStepTwoValidationResult result = new ConsumerScenarioStepTwoValidationResult(); + 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 ServiceException badRequest(String message) { + return new ServiceException(HttpStatus.BAD_REQUEST, message); + } +} diff --git a/src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepTwoServiceImplTest.java b/src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepTwoServiceImplTest.java new file mode 100644 index 0000000..109d0bd --- /dev/null +++ b/src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepTwoServiceImplTest.java @@ -0,0 +1,65 @@ +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.ConsumerScenarioStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepTwoValidationResult; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ConsumerScenarioStepTwoServiceImplTest { + @Test + void acceptsFiveCompleteJourneyRows() { + ConsumerScenarioStepTwoValidationResult result = new ConsumerScenarioStepTwoServiceImpl().validate(request(), student()); + + assertTrue(result.isValid()); + } + + @Test + void rejectsIncompleteJourneyRows() { + ConsumerScenarioStepTwoValidationRequest request = request(); + request.getRows().get(2).setDecisionFactors(" "); + + assertThrows(ServiceException.class, () -> new ConsumerScenarioStepTwoServiceImpl().validate(request, student())); + } + + @Test + void rejectsInvalidEmotion() { + ConsumerScenarioStepTwoValidationRequest request = request(); + request.getRows().get(0).setEmotionExperience("高兴"); + + assertThrows(ServiceException.class, () -> new ConsumerScenarioStepTwoServiceImpl().validate(request, student())); + } + + private ConsumerScenarioStepTwoValidationRequest request() { + ConsumerScenarioStepTwoValidationRequest request = new ConsumerScenarioStepTwoValidationRequest(); + request.setRows(Arrays.asList( + row("problem-awareness", "失眠后搜索助眠方案", "短视频与电商搜索页", "负面", "白噪声质量与智能联动"), + row("information-search", "浏览测评和产品详情", "达人测评、详情页", "中性", "参数、口碑与价格"), + row("evaluation-decision", "对比多个品牌", "对比页、评价区", "正面", "性能、价格与售后"), + row("purchase-conversion", "使用优惠完成下单", "直播间、支付页", "正面", "优惠与物流承诺"), + row("post-purchase", "安装使用并分享反馈", "App、售后与社区", "正面", "体验、服务与更新"))); + return request; + } + + private ConsumerScenarioStepTwoValidationRequest.JourneyAnalysisRow row(String stageId, String behavior, String touchpoints, String emotion, String factors) { + ConsumerScenarioStepTwoValidationRequest.JourneyAnalysisRow row = new ConsumerScenarioStepTwoValidationRequest.JourneyAnalysisRow(); + row.setStageId(stageId); + row.setBehaviorDescription(behavior); + row.setKeyTouchpoints(touchpoints); + row.setEmotionExperience(emotion); + row.setDecisionFactors(factors); + return row; + } + + private JwtUser student() { + JwtUser user = new JwtUser(); + user.setUserId("stu-1"); + user.setRoleId(4); + return user; + } +} From 3db2ab087f1f84c899b3e7b2c890d0731a6f2fa9 Mon Sep 17 00:00:00 2001 From: chenyuan Date: Tue, 11 Aug 2026 22:43:46 +0800 Subject: [PATCH 3/4] feat: validate consumer scenario journey map upload --- .../stu/StudentTrainingAnswerController.java | 17 +++++++ ...merScenarioStepThreeValidationRequest.java | 13 ++++++ ...umerScenarioStepThreeValidationResult.java | 22 +++++++++ .../ConsumerScenarioStepThreeService.java | 9 ++++ .../ConsumerScenarioStepThreeServiceImpl.java | 34 ++++++++++++++ ...sumerScenarioStepThreeServiceImplTest.java | 46 +++++++++++++++++++ 6 files changed, 141 insertions(+) create mode 100644 src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepThreeValidationRequest.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepThreeValidationResult.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/service/ConsumerScenarioStepThreeService.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepThreeServiceImpl.java create mode 100644 src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepThreeServiceImplTest.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 1065cf1..611a999 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java @@ -41,6 +41,8 @@ import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepOneValidationReque import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepOneValidationResult; import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepTwoValidationRequest; import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepTwoValidationResult; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepThreeValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepThreeValidationResult; import com.sztzjy.linkCommerce.service.NewProductSurveyStepOneService; import com.sztzjy.linkCommerce.service.MarketOpportunitySelectionStepOneService; import com.sztzjy.linkCommerce.service.MarketOpportunitySelectionStepTwoService; @@ -59,6 +61,7 @@ import com.sztzjy.linkCommerce.service.ConsumerBehaviorStepThreeService; import com.sztzjy.linkCommerce.service.ConsumerBehaviorStepFourService; import com.sztzjy.linkCommerce.service.ConsumerScenarioStepOneService; import com.sztzjy.linkCommerce.service.ConsumerScenarioStepTwoService; +import com.sztzjy.linkCommerce.service.ConsumerScenarioStepThreeService; import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService; import com.sztzjy.linkCommerce.util.ResultEntity; import io.swagger.annotations.Api; @@ -129,6 +132,9 @@ public class StudentTrainingAnswerController { @Autowired private ConsumerScenarioStepTwoService consumerScenarioStepTwoService; + @Autowired + private ConsumerScenarioStepThreeService consumerScenarioStepThreeService; + @GetMapping("/{taskKey}") @ApiOperation("查询当前学生指定实训任务答案") public ResultEntity detail(@PathVariable String taskKey, @@ -355,6 +361,17 @@ public class StudentTrainingAnswerController { } } + @PostMapping("/consumer-scenario/step-3/validate") + @ApiOperation("消费场景解构第三步校验") + public ResultEntity validateConsumerScenarioStepThree( + @RequestBody ConsumerScenarioStepThreeValidationRequest answer, HttpServletRequest request) { + try { + return new ResultEntity<>(HttpStatus.OK, "校验完成", consumerScenarioStepThreeService.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/ConsumerScenarioStepThreeValidationRequest.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepThreeValidationRequest.java new file mode 100644 index 0000000..9d78cc2 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepThreeValidationRequest.java @@ -0,0 +1,13 @@ +package com.sztzjy.linkCommerce.entity.dto; + +public class ConsumerScenarioStepThreeValidationRequest { + private String journeyMapUrl; + + public String getJourneyMapUrl() { + return journeyMapUrl; + } + + public void setJourneyMapUrl(String journeyMapUrl) { + this.journeyMapUrl = journeyMapUrl; + } +} diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepThreeValidationResult.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepThreeValidationResult.java new file mode 100644 index 0000000..1e259ab --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepThreeValidationResult.java @@ -0,0 +1,22 @@ +package com.sztzjy.linkCommerce.entity.dto; + +public class ConsumerScenarioStepThreeValidationResult { + 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/ConsumerScenarioStepThreeService.java b/src/main/java/com/sztzjy/linkCommerce/service/ConsumerScenarioStepThreeService.java new file mode 100644 index 0000000..4f3c09b --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/ConsumerScenarioStepThreeService.java @@ -0,0 +1,9 @@ +package com.sztzjy.linkCommerce.service; + +import com.sztzjy.linkCommerce.config.security.JwtUser; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepThreeValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepThreeValidationResult; + +public interface ConsumerScenarioStepThreeService { + ConsumerScenarioStepThreeValidationResult validate(ConsumerScenarioStepThreeValidationRequest request, JwtUser user); +} diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepThreeServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepThreeServiceImpl.java new file mode 100644 index 0000000..9fe8e14 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepThreeServiceImpl.java @@ -0,0 +1,34 @@ +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.ConsumerScenarioStepThreeValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepThreeValidationResult; +import com.sztzjy.linkCommerce.service.ConsumerScenarioStepThreeService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; + +@Service +public class ConsumerScenarioStepThreeServiceImpl implements ConsumerScenarioStepThreeService { + @Override + public ConsumerScenarioStepThreeValidationResult validate(ConsumerScenarioStepThreeValidationRequest request, JwtUser user) { + requireStudent(user); + if (request == null || StringUtils.isBlank(request.getJourneyMapUrl())) { + throw new ServiceException(HttpStatus.BAD_REQUEST, "请上传用户购买旅程图"); + } + ConsumerScenarioStepThreeValidationResult result = new ConsumerScenarioStepThreeValidationResult(); + 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/service/impl/ConsumerScenarioStepThreeServiceImplTest.java b/src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepThreeServiceImplTest.java new file mode 100644 index 0000000..2f05164 --- /dev/null +++ b/src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepThreeServiceImplTest.java @@ -0,0 +1,46 @@ +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.ConsumerScenarioStepThreeValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepThreeValidationResult; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ConsumerScenarioStepThreeServiceImplTest { + private final ConsumerScenarioStepThreeServiceImpl service = new ConsumerScenarioStepThreeServiceImpl(); + + @Test + void acceptsUploadedJourneyMap() { + ConsumerScenarioStepThreeValidationRequest request = new ConsumerScenarioStepThreeValidationRequest(); + request.setJourneyMapUrl("/profile/upload/journey-map.png"); + + ConsumerScenarioStepThreeValidationResult result = service.validate(request, student()); + + assertTrue(result.isValid()); + } + + @Test + void rejectsMissingJourneyMap() { + assertThrows(ServiceException.class, () -> service.validate(new ConsumerScenarioStepThreeValidationRequest(), student())); + } + + @Test + void rejectsNonStudent() { + ConsumerScenarioStepThreeValidationRequest request = new ConsumerScenarioStepThreeValidationRequest(); + request.setJourneyMapUrl("/profile/upload/journey-map.png"); + JwtUser teacher = student(); + teacher.setRoleId(3); + + assertThrows(ServiceException.class, () -> service.validate(request, teacher)); + } + + private JwtUser student() { + JwtUser user = new JwtUser(); + user.setUserId("stu-1"); + user.setRoleId(4); + return user; + } +} From 3c23050e2c57528225f52ed7518d46b65cc2c250 Mon Sep 17 00:00:00 2001 From: chenyuan Date: Tue, 11 Aug 2026 22:51:49 +0800 Subject: [PATCH 4/4] feat: validate consumer scenario optimization analysis --- .../stu/StudentTrainingAnswerController.java | 17 +++++ ...umerScenarioStepFourValidationRequest.java | 45 +++++++++++++ ...sumerScenarioStepFourValidationResult.java | 22 +++++++ .../ConsumerScenarioStepFourService.java | 9 +++ .../ConsumerScenarioStepFourServiceImpl.java | 51 ++++++++++++++ ...nsumerScenarioStepFourServiceImplTest.java | 66 +++++++++++++++++++ 6 files changed, 210 insertions(+) create mode 100644 src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepFourValidationRequest.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepFourValidationResult.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/service/ConsumerScenarioStepFourService.java create mode 100644 src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepFourServiceImpl.java create mode 100644 src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepFourServiceImplTest.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 611a999..c755c1f 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java @@ -43,6 +43,8 @@ import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepTwoValidationReque import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepTwoValidationResult; import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepThreeValidationRequest; import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepThreeValidationResult; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepFourValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepFourValidationResult; import com.sztzjy.linkCommerce.service.NewProductSurveyStepOneService; import com.sztzjy.linkCommerce.service.MarketOpportunitySelectionStepOneService; import com.sztzjy.linkCommerce.service.MarketOpportunitySelectionStepTwoService; @@ -62,6 +64,7 @@ import com.sztzjy.linkCommerce.service.ConsumerBehaviorStepFourService; import com.sztzjy.linkCommerce.service.ConsumerScenarioStepOneService; import com.sztzjy.linkCommerce.service.ConsumerScenarioStepTwoService; import com.sztzjy.linkCommerce.service.ConsumerScenarioStepThreeService; +import com.sztzjy.linkCommerce.service.ConsumerScenarioStepFourService; import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService; import com.sztzjy.linkCommerce.util.ResultEntity; import io.swagger.annotations.Api; @@ -135,6 +138,9 @@ public class StudentTrainingAnswerController { @Autowired private ConsumerScenarioStepThreeService consumerScenarioStepThreeService; + @Autowired + private ConsumerScenarioStepFourService consumerScenarioStepFourService; + @GetMapping("/{taskKey}") @ApiOperation("查询当前学生指定实训任务答案") public ResultEntity detail(@PathVariable String taskKey, @@ -372,6 +378,17 @@ public class StudentTrainingAnswerController { } } + @PostMapping("/consumer-scenario/step-4/validate") + @ApiOperation("消费场景解构第四步校验") + public ResultEntity validateConsumerScenarioStepFour( + @RequestBody ConsumerScenarioStepFourValidationRequest answer, HttpServletRequest request) { + try { + return new ResultEntity<>(HttpStatus.OK, "校验完成", consumerScenarioStepFourService.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/ConsumerScenarioStepFourValidationRequest.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepFourValidationRequest.java new file mode 100644 index 0000000..a8cccd0 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepFourValidationRequest.java @@ -0,0 +1,45 @@ +package com.sztzjy.linkCommerce.entity.dto; + +import java.util.List; + +public class ConsumerScenarioStepFourValidationRequest { + private List rows; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public static class JourneyOptimizationRow { + private String stageId; + private String painPoint; + private String optimizationSuggestion; + + public String getStageId() { + return stageId; + } + + public void setStageId(String stageId) { + this.stageId = stageId; + } + + public String getPainPoint() { + return painPoint; + } + + public void setPainPoint(String painPoint) { + this.painPoint = painPoint; + } + + public String getOptimizationSuggestion() { + return optimizationSuggestion; + } + + public void setOptimizationSuggestion(String optimizationSuggestion) { + this.optimizationSuggestion = optimizationSuggestion; + } + } +} diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepFourValidationResult.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepFourValidationResult.java new file mode 100644 index 0000000..b0f9c8a --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/ConsumerScenarioStepFourValidationResult.java @@ -0,0 +1,22 @@ +package com.sztzjy.linkCommerce.entity.dto; + +public class ConsumerScenarioStepFourValidationResult { + 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/ConsumerScenarioStepFourService.java b/src/main/java/com/sztzjy/linkCommerce/service/ConsumerScenarioStepFourService.java new file mode 100644 index 0000000..8ee2257 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/ConsumerScenarioStepFourService.java @@ -0,0 +1,9 @@ +package com.sztzjy.linkCommerce.service; + +import com.sztzjy.linkCommerce.config.security.JwtUser; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepFourValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepFourValidationResult; + +public interface ConsumerScenarioStepFourService { + ConsumerScenarioStepFourValidationResult validate(ConsumerScenarioStepFourValidationRequest request, JwtUser user); +} diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepFourServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepFourServiceImpl.java new file mode 100644 index 0000000..a2cad49 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepFourServiceImpl.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.dto.ConsumerScenarioStepFourValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepFourValidationResult; +import com.sztzjy.linkCommerce.service.ConsumerScenarioStepFourService; +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 ConsumerScenarioStepFourServiceImpl implements ConsumerScenarioStepFourService { + private static final List STAGE_IDS = Arrays.asList( + "problem-awareness", "information-search", "evaluation-decision", "purchase-conversion", "post-purchase" + ); + + @Override + public ConsumerScenarioStepFourValidationResult validate(ConsumerScenarioStepFourValidationRequest request, JwtUser user) { + requireStudent(user); + List rows = request == null ? null : request.getRows(); + if (rows == null || rows.size() != STAGE_IDS.size() || rows.stream().anyMatch(row -> row == null) + || rows.stream().map(ConsumerScenarioStepFourValidationRequest.JourneyOptimizationRow::getStageId).distinct().count() != STAGE_IDS.size() + || rows.stream().anyMatch(row -> !STAGE_IDS.contains(row.getStageId()))) { + throw badRequest("请完整填写五个购买旅程阶段的优化分析"); + } + if (rows.stream().anyMatch(row -> StringUtils.isBlank(row.getPainPoint()) || StringUtils.isBlank(row.getOptimizationSuggestion()))) { + throw badRequest("请完整填写五个阶段的痛点和优化建议"); + } + ConsumerScenarioStepFourValidationResult result = new ConsumerScenarioStepFourValidationResult(); + 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 ServiceException badRequest(String message) { + return new ServiceException(HttpStatus.BAD_REQUEST, message); + } +} diff --git a/src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepFourServiceImplTest.java b/src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepFourServiceImplTest.java new file mode 100644 index 0000000..4bc55a2 --- /dev/null +++ b/src/test/java/com/sztzjy/linkCommerce/service/impl/ConsumerScenarioStepFourServiceImplTest.java @@ -0,0 +1,66 @@ +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.ConsumerScenarioStepFourValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.ConsumerScenarioStepFourValidationResult; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ConsumerScenarioStepFourServiceImplTest { + private final ConsumerScenarioStepFourServiceImpl service = new ConsumerScenarioStepFourServiceImpl(); + + @Test + void acceptsCompleteJourneyOptimizations() { + ConsumerScenarioStepFourValidationResult result = service.validate(request(), student()); + + assertTrue(result.isValid()); + } + + @Test + void rejectsIncompleteOptimization() { + ConsumerScenarioStepFourValidationRequest request = request(); + request.getRows().get(1).setOptimizationSuggestion(" "); + + assertThrows(ServiceException.class, () -> service.validate(request, student())); + } + + @Test + void rejectsNonStudent() { + JwtUser teacher = student(); + teacher.setRoleId(3); + + assertThrows(ServiceException.class, () -> service.validate(request(), teacher)); + } + + private ConsumerScenarioStepFourValidationRequest request() { + ConsumerScenarioStepFourValidationRequest request = new ConsumerScenarioStepFourValidationRequest(); + request.setRows(Arrays.asList( + row("problem-awareness"), + row("information-search"), + row("evaluation-decision"), + row("purchase-conversion"), + row("post-purchase") + )); + return request; + } + + private ConsumerScenarioStepFourValidationRequest.JourneyOptimizationRow row(String stageId) { + ConsumerScenarioStepFourValidationRequest.JourneyOptimizationRow row = new ConsumerScenarioStepFourValidationRequest.JourneyOptimizationRow(); + row.setStageId(stageId); + row.setPainPoint("信息不够清晰"); + row.setOptimizationSuggestion("提供清晰指引和服务支持"); + return row; + } + + private JwtUser student() { + JwtUser user = new JwtUser(); + user.setUserId("stu-1"); + user.setRoleId(4); + return user; + } +}