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 9c7bfe5..57e035b 100644 --- a/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java +++ b/src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java @@ -4,6 +4,12 @@ import com.sztzjy.linkCommerce.config.exception.handler.ServiceException; import com.sztzjy.linkCommerce.config.security.JwtUser; import com.sztzjy.linkCommerce.config.security.TokenProvider; import com.sztzjy.linkCommerce.entity.StudentTrainingAnswer; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckRequest; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckResult; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepTwoValidationResult; +import com.sztzjy.linkCommerce.service.NewProductSurveyStepOneService; +import com.sztzjy.linkCommerce.service.NewProductSurveyStepTwoService; import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService; import com.sztzjy.linkCommerce.util.ResultEntity; import io.swagger.annotations.Api; @@ -21,6 +27,12 @@ public class StudentTrainingAnswerController { @Autowired private StudentTrainingAnswerService studentTrainingAnswerService; + @Autowired + private NewProductSurveyStepOneService newProductSurveyStepOneService; + + @Autowired + private NewProductSurveyStepTwoService newProductSurveyStepTwoService; + @GetMapping("/{taskKey}") @ApiOperation("查询当前学生指定实训任务答案") public ResultEntity detail(@PathVariable String taskKey, @@ -47,6 +59,30 @@ public class StudentTrainingAnswerController { } } + @PostMapping("/new-product-survey/step-1/check") + @ApiOperation("新产品调查与分析第一步判题") + public ResultEntity checkNewProductSurveyStepOne( + @RequestBody NewProductSurveyStepOneCheckRequest answer, HttpServletRequest request) { + try { + JwtUser user = TokenProvider.getJWTUser(request); + return new ResultEntity<>(HttpStatus.OK, "判题完成", newProductSurveyStepOneService.check(answer, user)); + } catch (ServiceException e) { + return new ResultEntity<>(e.getCode(), e.getMessage()); + } + } + + @PostMapping("/new-product-survey/step-2/validate") + @ApiOperation("新产品调查与分析第二步校验") + public ResultEntity validateNewProductSurveyStepTwo( + @RequestBody NewProductSurveyStepTwoValidationRequest answer, HttpServletRequest request) { + try { + JwtUser user = TokenProvider.getJWTUser(request); + return new ResultEntity<>(HttpStatus.OK, "校验通过", newProductSurveyStepTwoService.validate(answer, user)); + } catch (ServiceException e) { + return new ResultEntity<>(e.getCode(), e.getMessage()); + } + } + @DeleteMapping("/{taskKey}") @ApiOperation("删除当前学生指定实训任务答案") public ResultEntity delete(@PathVariable String taskKey, diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepOneCheckRequest.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepOneCheckRequest.java new file mode 100644 index 0000000..4f40260 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepOneCheckRequest.java @@ -0,0 +1,36 @@ +package com.sztzjy.linkCommerce.entity.dto; + +import java.util.List; + +public class NewProductSurveyStepOneCheckRequest { + private List items; + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + + public static class Item { + private String id; + private String category; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + } +} diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepOneCheckResult.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepOneCheckResult.java new file mode 100644 index 0000000..cb5b6aa --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepOneCheckResult.java @@ -0,0 +1,73 @@ +package com.sztzjy.linkCommerce.entity.dto; + +import java.util.ArrayList; +import java.util.List; + +public class NewProductSurveyStepOneCheckResult { + private List items = new ArrayList<>(); + private int correctCount; + private int totalCount; + private boolean allCorrect; + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } + + public int getCorrectCount() { + return correctCount; + } + + public void setCorrectCount(int correctCount) { + this.correctCount = correctCount; + } + + public int getTotalCount() { + return totalCount; + } + + public void setTotalCount(int totalCount) { + this.totalCount = totalCount; + } + + public boolean isAllCorrect() { + return allCorrect; + } + + public void setAllCorrect(boolean allCorrect) { + this.allCorrect = allCorrect; + } + + public static class ItemResult { + private String id; + private boolean correct; + private String message; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public boolean isCorrect() { + return correct; + } + + public void setCorrect(boolean correct) { + this.correct = correct; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + } +} diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepTwoValidationRequest.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepTwoValidationRequest.java new file mode 100644 index 0000000..c4a550d --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepTwoValidationRequest.java @@ -0,0 +1,25 @@ +package com.sztzjy.linkCommerce.entity.dto; + +import java.util.List; + +public class NewProductSurveyStepTwoValidationRequest { + private String platform; + private String scene; + private String customScene; + private String keyword; + private String productName; + private List imageUrls; + + public String getPlatform() { return platform; } + public void setPlatform(String platform) { this.platform = platform; } + public String getScene() { return scene; } + public void setScene(String scene) { this.scene = scene; } + public String getCustomScene() { return customScene; } + public void setCustomScene(String customScene) { this.customScene = customScene; } + public String getKeyword() { return keyword; } + public void setKeyword(String keyword) { this.keyword = keyword; } + public String getProductName() { return productName; } + public void setProductName(String productName) { this.productName = productName; } + public List getImageUrls() { return imageUrls; } + public void setImageUrls(List imageUrls) { this.imageUrls = imageUrls; } +} diff --git a/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepTwoValidationResult.java b/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepTwoValidationResult.java new file mode 100644 index 0000000..256c8e9 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/entity/dto/NewProductSurveyStepTwoValidationResult.java @@ -0,0 +1,11 @@ +package com.sztzjy.linkCommerce.entity.dto; + +public class NewProductSurveyStepTwoValidationResult { + 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/NewProductSurveyStepOneService.java b/src/main/java/com/sztzjy/linkCommerce/service/NewProductSurveyStepOneService.java new file mode 100644 index 0000000..c081ebd --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/NewProductSurveyStepOneService.java @@ -0,0 +1,9 @@ +package com.sztzjy.linkCommerce.service; + +import com.sztzjy.linkCommerce.config.security.JwtUser; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckRequest; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckResult; + +public interface NewProductSurveyStepOneService { + NewProductSurveyStepOneCheckResult check(NewProductSurveyStepOneCheckRequest request, JwtUser user); +} diff --git a/src/main/java/com/sztzjy/linkCommerce/service/NewProductSurveyStepTwoService.java b/src/main/java/com/sztzjy/linkCommerce/service/NewProductSurveyStepTwoService.java new file mode 100644 index 0000000..31b1896 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/NewProductSurveyStepTwoService.java @@ -0,0 +1,9 @@ +package com.sztzjy.linkCommerce.service; + +import com.sztzjy.linkCommerce.config.security.JwtUser; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepTwoValidationResult; + +public interface NewProductSurveyStepTwoService { + NewProductSurveyStepTwoValidationResult validate(NewProductSurveyStepTwoValidationRequest request, JwtUser user); +} diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepOneServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepOneServiceImpl.java new file mode 100644 index 0000000..a58b37f --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepOneServiceImpl.java @@ -0,0 +1,143 @@ +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.NewProductSurveyStepOneCheckRequest; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckResult; +import com.sztzjy.linkCommerce.service.NewProductSurveyStepOneService; +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 javax.annotation.PostConstruct; +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 NewProductSurveyStepOneServiceImpl implements NewProductSurveyStepOneService { + private static final String TASK_KEY = "new-product-survey"; + private static final int STEP_NO = 1; + private static final String CORRECT_MESSAGE = "分类正确"; + private static final String INCORRECT_MESSAGE = "分类有误,请重新选择"; + private static final Set ALLOWED_CATEGORIES = new LinkedHashSet<>(Arrays.asList("核心层", "有形层", "延伸层")); + private static final Map DEFAULT_ANSWERS = createDefaultAnswers(); + + private final JdbcTemplate jdbcTemplate; + + @Autowired + public NewProductSurveyStepOneServiceImpl(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @PostConstruct + public void initializeStandardAnswers() { + jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS training_step_standard_answer (" + + "id varchar(64) NOT NULL COMMENT 'primary id'," + + "task_key varchar(128) NOT NULL COMMENT 'training task key'," + + "step_no int NOT NULL COMMENT 'step number'," + + "answer_json longtext NOT NULL COMMENT 'standard answer json'," + + "create_time datetime NULL COMMENT 'create time'," + + "update_time datetime NULL COMMENT 'update time'," + + "PRIMARY KEY (id)," + + "UNIQUE KEY uk_training_step_standard_answer (task_key, step_no)" + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='training step standard answer'"); + jdbcTemplate.update("INSERT IGNORE INTO training_step_standard_answer " + + "(id, task_key, step_no, answer_json, create_time, update_time) VALUES (?, ?, ?, ?, NOW(), NOW())", + "new-product-survey-step-1", TASK_KEY, STEP_NO, JSON.toJSONString(DEFAULT_ANSWERS)); + } + + @Override + public NewProductSurveyStepOneCheckResult check(NewProductSurveyStepOneCheckRequest request, JwtUser user) { + requireStudent(user); + Map submitted = validateSubmittedItems(request == null ? null : request.getItems()); + Map standardAnswers = loadStandardAnswers(); + + NewProductSurveyStepOneCheckResult result = new NewProductSurveyStepOneCheckResult(); + int correctCount = 0; + for (String id : standardAnswers.keySet()) { + boolean correct = standardAnswers.get(id).equals(submitted.get(id)); + NewProductSurveyStepOneCheckResult.ItemResult itemResult = new NewProductSurveyStepOneCheckResult.ItemResult(); + itemResult.setId(id); + itemResult.setCorrect(correct); + itemResult.setMessage(correct ? CORRECT_MESSAGE : INCORRECT_MESSAGE); + result.getItems().add(itemResult); + if (correct) { + correctCount++; + } + } + result.setCorrectCount(correctCount); + result.setTotalCount(standardAnswers.size()); + result.setAllCorrect(correctCount == standardAnswers.size()); + 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 Map validateSubmittedItems(List items) { + if (items == null || items.size() != DEFAULT_ANSWERS.size()) { + throw new ServiceException(HttpStatus.BAD_REQUEST, "请完成全部卖点分类后再判题"); + } + Map submitted = new LinkedHashMap<>(); + for (NewProductSurveyStepOneCheckRequest.Item item : items) { + String id = item == null ? null : StringUtils.trimToEmpty(item.getId()); + String category = item == null ? null : StringUtils.trimToEmpty(item.getCategory()); + if (!DEFAULT_ANSWERS.containsKey(id) || !ALLOWED_CATEGORIES.contains(category) || submitted.put(id, category) != null) { + throw new ServiceException(HttpStatus.BAD_REQUEST, "提交的卖点分类数据不合法"); + } + } + if (!submitted.keySet().equals(DEFAULT_ANSWERS.keySet())) { + throw new ServiceException(HttpStatus.BAD_REQUEST, "提交的卖点分类数据不完整"); + } + return submitted; + } + + @SuppressWarnings("unchecked") + private Map 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 raw = JSON.parseObject(answerJson, LinkedHashMap.class); + Map answers = new LinkedHashMap<>(); + for (String id : DEFAULT_ANSWERS.keySet()) { + Object category = raw == null ? null : raw.get(id); + if (category == null || !ALLOWED_CATEGORIES.contains(String.valueOf(category))) { + throw new ServiceException(HttpStatus.INTERNAL_SERVER_ERROR, "第一步标准答案未正确配置"); + } + answers.put(id, String.valueOf(category)); + } + if (raw == null || raw.size() != answers.size()) { + throw new ServiceException(HttpStatus.INTERNAL_SERVER_ERROR, "第一步标准答案未正确配置"); + } + return answers; + } + + private static Map createDefaultAnswers() { + Map answers = new LinkedHashMap<>(); + answers.put("selling-point-1", "核心层"); + answers.put("selling-point-2", "有形层"); + answers.put("selling-point-3", "核心层"); + answers.put("selling-point-4", "核心层"); + answers.put("selling-point-5", "有形层"); + answers.put("selling-point-6", "有形层"); + answers.put("selling-point-7", "有形层"); + answers.put("selling-point-8", "延伸层"); + answers.put("selling-point-9", "延伸层"); + answers.put("selling-point-10", "延伸层"); + answers.put("selling-point-11", "有形层"); + return answers; + } +} diff --git a/src/main/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepTwoServiceImpl.java b/src/main/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepTwoServiceImpl.java new file mode 100644 index 0000000..6b0b8a7 --- /dev/null +++ b/src/main/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepTwoServiceImpl.java @@ -0,0 +1,76 @@ +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.NewProductSurveyStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepTwoValidationResult; +import com.sztzjy.linkCommerce.service.NewProductSurveyStepTwoService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +@Service +public class NewProductSurveyStepTwoServiceImpl implements NewProductSurveyStepTwoService { + private static final Set PLATFORMS = new LinkedHashSet<>(Arrays.asList("京东", "天猫", "抖音电商")); + private static final String OTHER_SCENE = "其他场景"; + + @Override + public NewProductSurveyStepTwoValidationResult validate(NewProductSurveyStepTwoValidationRequest request, JwtUser user) { + requireStudent(user); + if (request == null) { + throw badRequest("请完成第二步信息后再进入下一步"); + } + if (!PLATFORMS.contains(StringUtils.trimToEmpty(request.getPlatform()))) { + throw badRequest("请选择调查平台"); + } + String scene = StringUtils.trimToEmpty(request.getScene()); + if (StringUtils.isBlank(scene)) { + throw badRequest("请选择调查场景"); + } + if (OTHER_SCENE.equals(scene) && StringUtils.isBlank(request.getCustomScene())) { + throw badRequest("请填写自定义调查场景"); + } + if (StringUtils.isBlank(request.getKeyword())) { + throw badRequest("请填写搜索关键词"); + } + if (StringUtils.isBlank(request.getProductName())) { + throw badRequest("请填写产品名称"); + } + validateImageUrls(request.getImageUrls()); + + NewProductSurveyStepTwoValidationResult result = new NewProductSurveyStepTwoValidationResult(); + 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 validateImageUrls(List imageUrls) { + if (imageUrls == null || imageUrls.isEmpty()) { + throw badRequest("请上传至少 1 张产品图片"); + } + if (imageUrls.size() > 5) { + throw badRequest("产品图片最多上传 5 张"); + } + if (imageUrls.stream().anyMatch(StringUtils::isBlank)) { + throw badRequest("产品图片地址不完整,请重新上传"); + } + } + + private ServiceException badRequest(String message) { + return new ServiceException(HttpStatus.BAD_REQUEST, message); + } +} diff --git a/src/test/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerControllerTest.java b/src/test/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerControllerTest.java new file mode 100644 index 0000000..59256c2 --- /dev/null +++ b/src/test/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerControllerTest.java @@ -0,0 +1,72 @@ +package com.sztzjy.linkCommerce.controller.stu; + +import com.sztzjy.linkCommerce.config.Constant; +import com.sztzjy.linkCommerce.config.security.JwtUser; +import com.sztzjy.linkCommerce.config.security.TokenProvider; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckRequest; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckResult; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepTwoValidationResult; +import com.sztzjy.linkCommerce.service.NewProductSurveyStepOneService; +import com.sztzjy.linkCommerce.service.NewProductSurveyStepTwoService; +import com.sztzjy.linkCommerce.util.ResultEntity; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.test.util.ReflectionTestUtils; + +import javax.servlet.http.HttpServletRequest; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class StudentTrainingAnswerControllerTest { + + @Test + void checkStepOneUsesTheAuthenticatedStudentAndReturnsTheGrade() { + StudentTrainingAnswerController controller = new StudentTrainingAnswerController(); + NewProductSurveyStepOneService service = mock(NewProductSurveyStepOneService.class); + ReflectionTestUtils.setField(controller, "newProductSurveyStepOneService", service); + NewProductSurveyStepOneCheckResult grade = new NewProductSurveyStepOneCheckResult(); + grade.setAllCorrect(true); + when(service.check(any(NewProductSurveyStepOneCheckRequest.class), any(JwtUser.class))).thenReturn(grade); + + NewProductSurveyStepOneCheckRequest answer = new NewProductSurveyStepOneCheckRequest(); + ResultEntity result = controller.checkNewProductSurveyStepOne(answer, authenticatedStudentRequest()); + + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals(grade, result.getBody().getData()); + verify(service).check(any(NewProductSurveyStepOneCheckRequest.class), any(JwtUser.class)); + } + + @Test + void validateStepTwoUsesTheAuthenticatedStudentAndReturnsTheValidationResult() { + StudentTrainingAnswerController controller = new StudentTrainingAnswerController(); + NewProductSurveyStepTwoService service = mock(NewProductSurveyStepTwoService.class); + ReflectionTestUtils.setField(controller, "newProductSurveyStepTwoService", service); + NewProductSurveyStepTwoValidationResult validation = new NewProductSurveyStepTwoValidationResult(); + validation.setValid(true); + when(service.validate(any(NewProductSurveyStepTwoValidationRequest.class), any(JwtUser.class))).thenReturn(validation); + + NewProductSurveyStepTwoValidationRequest answer = new NewProductSurveyStepTwoValidationRequest(); + ResultEntity result = controller.validateNewProductSurveyStepTwo(answer, authenticatedStudentRequest()); + + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals(validation, result.getBody().getData()); + verify(service).validate(any(NewProductSurveyStepTwoValidationRequest.class), any(JwtUser.class)); + } + + private HttpServletRequest authenticatedStudentRequest() { + JwtUser user = new JwtUser(); + user.setUserId("stu-1"); + user.setRoleId(4); + String token = TokenProvider.createToken(user); + HttpServletRequest request = mock(HttpServletRequest.class); + when(request.getUserPrincipal()).thenReturn(new UsernamePasswordAuthenticationToken("student", null)); + when(request.getHeader(Constant.AUTHORIZATION)).thenReturn("Bearer " + token); + return request; + } +} diff --git a/src/test/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepOneServiceImplTest.java b/src/test/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepOneServiceImplTest.java new file mode 100644 index 0000000..22f708b --- /dev/null +++ b/src/test/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepOneServiceImplTest.java @@ -0,0 +1,114 @@ +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.NewProductSurveyStepOneCheckRequest; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepOneCheckResult; +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.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +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.contains; +import static org.mockito.ArgumentMatchers.startsWith; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class NewProductSurveyStepOneServiceImplTest { + + @Test + void checkReturnsPerItemFeedbackWithoutExposingCorrectCategories() { + JdbcTemplate jdbcTemplate = standardAnswerJdbcTemplate(); + NewProductSurveyStepOneServiceImpl service = new NewProductSurveyStepOneServiceImpl(jdbcTemplate); + + NewProductSurveyStepOneCheckResult result = service.check(requestWithSecondCategory("核心层"), student()); + + assertEquals(10, result.getCorrectCount()); + assertEquals(11, result.getTotalCount()); + assertFalse(result.isAllCorrect()); + assertTrue(result.getItems().get(0).isCorrect()); + assertFalse(result.getItems().get(1).isCorrect()); + assertEquals("分类有误,请重新选择", result.getItems().get(1).getMessage()); + assertFalse(JSON.toJSONString(result).contains("correctCategory")); + } + + @Test + void checkRejectsIncompleteAnswersInvalidCategoriesAndNonStudents() { + NewProductSurveyStepOneServiceImpl service = new NewProductSurveyStepOneServiceImpl(standardAnswerJdbcTemplate()); + + assertThrows(ServiceException.class, () -> service.check(request(Arrays.asList(item("selling-point-1", "核心层"))), student())); + assertThrows(ServiceException.class, () -> service.check(requestWithSecondCategory("错误层级"), student())); + assertThrows(ServiceException.class, () -> service.check(requestWithSecondCategory("有形层"), teacher())); + } + + @Test + void initializationCreatesTheTableAndDoesNotOverwriteExistingAnswers() { + JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class); + NewProductSurveyStepOneServiceImpl service = new NewProductSurveyStepOneServiceImpl(jdbcTemplate); + + service.initializeStandardAnswers(); + + verify(jdbcTemplate).execute(contains("CREATE TABLE IF NOT EXISTS training_step_standard_answer")); + verify(jdbcTemplate).update(startsWith("INSERT IGNORE INTO training_step_standard_answer"), any(), any(), any(), any()); + } + + private JdbcTemplate standardAnswerJdbcTemplate() { + JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class); + Map answers = new LinkedHashMap<>(); + for (NewProductSurveyStepOneCheckRequest.Item item : defaultAnswers()) { + answers.put(item.getId(), item.getCategory()); + } + when(jdbcTemplate.queryForObject(any(String.class), any(Class.class), any(), any())).thenReturn(JSON.toJSONString(answers)); + return jdbcTemplate; + } + + private List defaultAnswers() { + return Arrays.asList( + item("selling-point-1", "核心层"), item("selling-point-2", "有形层"), item("selling-point-3", "核心层"), + item("selling-point-4", "核心层"), item("selling-point-5", "有形层"), item("selling-point-6", "有形层"), + item("selling-point-7", "有形层"), item("selling-point-8", "延伸层"), item("selling-point-9", "延伸层"), + item("selling-point-10", "延伸层"), item("selling-point-11", "有形层")); + } + + private NewProductSurveyStepOneCheckRequest requestWithSecondCategory(String category) { + List items = defaultAnswers(); + items.get(1).setCategory(category); + return request(items); + } + + private NewProductSurveyStepOneCheckRequest request(List items) { + NewProductSurveyStepOneCheckRequest request = new NewProductSurveyStepOneCheckRequest(); + request.setItems(items); + return request; + } + + private NewProductSurveyStepOneCheckRequest.Item item(String id, String category) { + NewProductSurveyStepOneCheckRequest.Item item = new NewProductSurveyStepOneCheckRequest.Item(); + item.setId(id); + item.setCategory(category); + return item; + } + + private JwtUser student() { + JwtUser user = new JwtUser(); + user.setUserId("stu-1"); + user.setRoleId(4); + return user; + } + + private JwtUser teacher() { + JwtUser user = student(); + user.setRoleId(3); + return user; + } +} diff --git a/src/test/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepTwoServiceImplTest.java b/src/test/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepTwoServiceImplTest.java new file mode 100644 index 0000000..386f9b1 --- /dev/null +++ b/src/test/java/com/sztzjy/linkCommerce/service/impl/NewProductSurveyStepTwoServiceImplTest.java @@ -0,0 +1,68 @@ +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.NewProductSurveyStepTwoValidationRequest; +import com.sztzjy.linkCommerce.entity.dto.NewProductSurveyStepTwoValidationResult; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class NewProductSurveyStepTwoServiceImplTest { + + @Test + void validatesACompleteStudentSubmission() { + NewProductSurveyStepTwoServiceImpl service = new NewProductSurveyStepTwoServiceImpl(); + + NewProductSurveyStepTwoValidationResult result = service.validate( + request("京东", "AI儿童玩具", "", Arrays.asList("/profile/upload/main.png", "/profile/upload/detail.png")), student()); + + assertTrue(result.isValid()); + } + + @Test + void rejectsOtherSceneWithoutCustomSceneAndMoreThanFiveImages() { + NewProductSurveyStepTwoServiceImpl service = new NewProductSurveyStepTwoServiceImpl(); + + assertThrows(ServiceException.class, () -> service.validate(request("京东", "其他场景", "", Collections.singletonList("/profile/upload/main.png")), student())); + assertThrows(ServiceException.class, () -> service.validate(request("京东", "AI儿童玩具", "", Arrays.asList("1", "2", "3", "4", "5", "6")), student())); + } + + @Test + void rejectsNonStudentsAndMissingRequiredFields() { + NewProductSurveyStepTwoServiceImpl service = new NewProductSurveyStepTwoServiceImpl(); + + assertThrows(ServiceException.class, () -> service.validate(request("拼多多", "AI儿童玩具", "", Collections.singletonList("/profile/upload/main.png")), student())); + assertThrows(ServiceException.class, () -> service.validate(request("京东", "AI儿童玩具", "", Collections.emptyList()), student())); + assertThrows(ServiceException.class, () -> service.validate(request("京东", "AI儿童玩具", "", Collections.singletonList("/profile/upload/main.png")), teacher())); + } + + private NewProductSurveyStepTwoValidationRequest request(String platform, String scene, String customScene, List imageUrls) { + NewProductSurveyStepTwoValidationRequest request = new NewProductSurveyStepTwoValidationRequest(); + request.setPlatform(platform); + request.setScene(scene); + request.setCustomScene(customScene); + request.setKeyword("AI智能对话机器人 3-6岁 玩具"); + request.setProductName("AI 智能机器人"); + request.setImageUrls(imageUrls); + return request; + } + + private JwtUser student() { + JwtUser user = new JwtUser(); + user.setUserId("stu-1"); + user.setRoleId(4); + return user; + } + + private JwtUser teacher() { + JwtUser user = student(); + user.setRoleId(3); + return user; + } +}