Merge branch 'codex/target-user-profile-step1'

# Conflicts:
#	src/main/java/com/sztzjy/linkCommerce/controller/stu/StudentTrainingAnswerController.java
bugfix/ai-assessment-evidence-rescore
chenyuan 2 months ago
commit d70eae296c

@ -408,6 +408,11 @@ public class StudentTrainingAnswerController {
@Autowired private com.sztzjy.linkCommerce.service.IndustryDemandAnalysisStepTwoService industryDemandAnalysisStepTwoService; @Autowired private com.sztzjy.linkCommerce.service.IndustryDemandAnalysisStepTwoService industryDemandAnalysisStepTwoService;
@Autowired private com.sztzjy.linkCommerce.service.IndustryDemandAnalysisStepThreeService industryDemandAnalysisStepThreeService; @Autowired private com.sztzjy.linkCommerce.service.IndustryDemandAnalysisStepThreeService industryDemandAnalysisStepThreeService;
@Autowired private com.sztzjy.linkCommerce.service.IndustryDemandAnalysisStepFourService industryDemandAnalysisStepFourService; @Autowired private com.sztzjy.linkCommerce.service.IndustryDemandAnalysisStepFourService industryDemandAnalysisStepFourService;
@Autowired private com.sztzjy.linkCommerce.service.TargetUserProfileStepOneService targetUserProfileStepOneService;
@Autowired private com.sztzjy.linkCommerce.service.TargetUserProfileStepTwoService targetUserProfileStepTwoService;
@Autowired private com.sztzjy.linkCommerce.service.TargetUserProfileStepThreeService targetUserProfileStepThreeService;
@Autowired private com.sztzjy.linkCommerce.service.TargetUserProfileStepFourService targetUserProfileStepFourService;
@Autowired private com.sztzjy.linkCommerce.service.TargetUserProfileStepFiveService targetUserProfileStepFiveService;
@Autowired @Autowired
private SupplierEvaluationStepTwoService supplierEvaluationStepTwoService; private SupplierEvaluationStepTwoService supplierEvaluationStepTwoService;
@ -1215,6 +1220,16 @@ public class StudentTrainingAnswerController {
public ResultEntity<com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepThreeValidationResult> validateIndustryDemandAnalysisStepThree(@RequestBody com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepThreeValidationRequest answer, HttpServletRequest request) { try { return new ResultEntity<>(HttpStatus.OK, "校验通过", industryDemandAnalysisStepThreeService.validate(answer, TokenProvider.getJWTUser(request))); } catch (ServiceException e) { return new ResultEntity<>(e.getCode(), e.getMessage()); } } public ResultEntity<com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepThreeValidationResult> validateIndustryDemandAnalysisStepThree(@RequestBody com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepThreeValidationRequest answer, HttpServletRequest request) { try { return new ResultEntity<>(HttpStatus.OK, "校验通过", industryDemandAnalysisStepThreeService.validate(answer, TokenProvider.getJWTUser(request))); } catch (ServiceException e) { return new ResultEntity<>(e.getCode(), e.getMessage()); } }
@PostMapping("/industry-demand-analysis/step-4/validate") @ApiOperation("行业需求分析第四步校验") @PostMapping("/industry-demand-analysis/step-4/validate") @ApiOperation("行业需求分析第四步校验")
public ResultEntity<com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepFourValidationResult> validateIndustryDemandAnalysisStepFour(@RequestBody com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepFourValidationRequest answer, HttpServletRequest request) { try { return new ResultEntity<>(HttpStatus.OK, "校验通过", industryDemandAnalysisStepFourService.validate(answer, TokenProvider.getJWTUser(request))); } catch (ServiceException e) { return new ResultEntity<>(e.getCode(), e.getMessage()); } } public ResultEntity<com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepFourValidationResult> validateIndustryDemandAnalysisStepFour(@RequestBody com.sztzjy.linkCommerce.entity.dto.IndustryDemandAnalysisStepFourValidationRequest answer, HttpServletRequest request) { try { return new ResultEntity<>(HttpStatus.OK, "校验通过", industryDemandAnalysisStepFourService.validate(answer, TokenProvider.getJWTUser(request))); } catch (ServiceException e) { return new ResultEntity<>(e.getCode(), e.getMessage()); } }
@PostMapping("/target-user-profile/step-1/validate") @ApiOperation("目标用户画像第一步校验")
public ResultEntity<com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepOneValidationResult> validateTargetUserProfileStepOne(@RequestBody com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepOneValidationRequest answer, HttpServletRequest request) { try { return new ResultEntity<>(HttpStatus.OK, "校验通过", targetUserProfileStepOneService.validate(answer, TokenProvider.getJWTUser(request))); } catch (ServiceException e) { return new ResultEntity<>(e.getCode(), e.getMessage()); } }
@PostMapping("/target-user-profile/step-2/validate") @ApiOperation("目标用户画像第二步校验")
public ResultEntity<com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepTwoValidationResult> validateTargetUserProfileStepTwo(@RequestBody com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepTwoValidationRequest answer, HttpServletRequest request) { try { return new ResultEntity<>(HttpStatus.OK, "校验通过", targetUserProfileStepTwoService.validate(answer, TokenProvider.getJWTUser(request))); } catch (ServiceException e) { return new ResultEntity<>(e.getCode(), e.getMessage()); } }
@PostMapping("/target-user-profile/step-3/validate") @ApiOperation("目标用户画像第三步校验")
public ResultEntity<com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepThreeValidationResult> validateTargetUserProfileStepThree(@RequestBody com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepThreeValidationRequest answer, HttpServletRequest request) { try { return new ResultEntity<>(HttpStatus.OK, "校验通过", targetUserProfileStepThreeService.validate(answer, TokenProvider.getJWTUser(request))); } catch (ServiceException e) { return new ResultEntity<>(e.getCode(), e.getMessage()); } }
@PostMapping("/target-user-profile/step-4/validate") @ApiOperation("目标用户画像第四步校验")
public ResultEntity<com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepFourValidationResult> validateTargetUserProfileStepFour(@RequestBody com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepFourValidationRequest answer, HttpServletRequest request) { try { return new ResultEntity<>(HttpStatus.OK, "校验通过", targetUserProfileStepFourService.validate(answer, TokenProvider.getJWTUser(request))); } catch (ServiceException e) { return new ResultEntity<>(e.getCode(), e.getMessage()); } }
@PostMapping("/target-user-profile/step-5/validate") @ApiOperation("目标用户画像第五步校验")
public ResultEntity<com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepFiveValidationResult> validateTargetUserProfileStepFive(@RequestBody com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepFiveValidationRequest answer, HttpServletRequest request) { try { return new ResultEntity<>(HttpStatus.OK, "校验通过", targetUserProfileStepFiveService.validate(answer, TokenProvider.getJWTUser(request))); } catch (ServiceException e) { return new ResultEntity<>(e.getCode(), e.getMessage()); } }
@DeleteMapping("/{taskKey}") @DeleteMapping("/{taskKey}")
@ApiOperation("删除当前学生指定实训任务答案") @ApiOperation("删除当前学生指定实训任务答案")
public ResultEntity delete(@PathVariable String taskKey, public ResultEntity delete(@PathVariable String taskKey,

@ -0,0 +1,32 @@
package com.sztzjy.linkCommerce.entity.dto;
import java.util.List;
public class TargetUserProfileStepFiveValidationRequest {
private List<MarketSegment> segments;
private String marketSelection;
public List<MarketSegment> getSegments() { return segments; }
public void setSegments(List<MarketSegment> segments) { this.segments = segments; }
public String getMarketSelection() { return marketSelection; }
public void setMarketSelection(String marketSelection) { this.marketSelection = marketSelection; }
public static class MarketSegment {
private String market;
private String attractiveness;
private String painPoints;
private String behaviorCharacteristics;
private String productOpportunity;
public String getMarket() { return market; }
public void setMarket(String market) { this.market = market; }
public String getAttractiveness() { return attractiveness; }
public void setAttractiveness(String attractiveness) { this.attractiveness = attractiveness; }
public String getPainPoints() { return painPoints; }
public void setPainPoints(String painPoints) { this.painPoints = painPoints; }
public String getBehaviorCharacteristics() { return behaviorCharacteristics; }
public void setBehaviorCharacteristics(String behaviorCharacteristics) { this.behaviorCharacteristics = behaviorCharacteristics; }
public String getProductOpportunity() { return productOpportunity; }
public void setProductOpportunity(String productOpportunity) { this.productOpportunity = productOpportunity; }
}
}

@ -0,0 +1,11 @@
package com.sztzjy.linkCommerce.entity.dto;
public class TargetUserProfileStepFiveValidationResult {
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; }
}

@ -0,0 +1,35 @@
package com.sztzjy.linkCommerce.entity.dto;
import java.util.List;
public class TargetUserProfileStepFourValidationRequest {
private List<UserPortrait> records;
public List<UserPortrait> getRecords() { return records; }
public void setRecords(List<UserPortrait> records) { this.records = records; }
public static class UserPortrait {
private String code;
private String user;
private String basicAttributes;
private String tags;
private String behavior;
private String painPoints;
private String psychology;
public String getCode() { return code; }
public void setCode(String code) { this.code = code; }
public String getUser() { return user; }
public void setUser(String user) { this.user = user; }
public String getBasicAttributes() { return basicAttributes; }
public void setBasicAttributes(String basicAttributes) { this.basicAttributes = basicAttributes; }
public String getTags() { return tags; }
public void setTags(String tags) { this.tags = tags; }
public String getBehavior() { return behavior; }
public void setBehavior(String behavior) { this.behavior = behavior; }
public String getPainPoints() { return painPoints; }
public void setPainPoints(String painPoints) { this.painPoints = painPoints; }
public String getPsychology() { return psychology; }
public void setPsychology(String psychology) { this.psychology = psychology; }
}
}

@ -0,0 +1,11 @@
package com.sztzjy.linkCommerce.entity.dto;
public class TargetUserProfileStepFourValidationResult {
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; }
}

@ -0,0 +1,17 @@
package com.sztzjy.linkCommerce.entity.dto;
public class TargetUserProfileStepOneValidationRequest {
private String excelUrl;
private String excelName;
private Integer previewRowCount;
private Integer previewColumnCount;
public String getExcelUrl() { return excelUrl; }
public void setExcelUrl(String excelUrl) { this.excelUrl = excelUrl; }
public String getExcelName() { return excelName; }
public void setExcelName(String excelName) { this.excelName = excelName; }
public Integer getPreviewRowCount() { return previewRowCount; }
public void setPreviewRowCount(Integer previewRowCount) { this.previewRowCount = previewRowCount; }
public Integer getPreviewColumnCount() { return previewColumnCount; }
public void setPreviewColumnCount(Integer previewColumnCount) { this.previewColumnCount = previewColumnCount; }
}

@ -0,0 +1,11 @@
package com.sztzjy.linkCommerce.entity.dto;
public class TargetUserProfileStepOneValidationResult {
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; }
}

@ -0,0 +1,20 @@
package com.sztzjy.linkCommerce.entity.dto;
import java.util.List;
public class TargetUserProfileStepThreeValidationRequest {
private List<Insight> insights;
public List<Insight> getInsights() { return insights; }
public void setInsights(List<Insight> insights) { this.insights = insights; }
public static class Insight {
private String dimension;
private String analysis;
public String getDimension() { return dimension; }
public void setDimension(String dimension) { this.dimension = dimension; }
public String getAnalysis() { return analysis; }
public void setAnalysis(String analysis) { this.analysis = analysis; }
}
}

@ -0,0 +1,11 @@
package com.sztzjy.linkCommerce.entity.dto;
public class TargetUserProfileStepThreeValidationResult {
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; }
}

@ -0,0 +1,23 @@
package com.sztzjy.linkCommerce.entity.dto;
import java.util.List;
public class TargetUserProfileStepTwoValidationRequest {
private List<ChartUpload> charts;
public List<ChartUpload> getCharts() { return charts; }
public void setCharts(List<ChartUpload> charts) { this.charts = charts; }
public static class ChartUpload {
private String type;
private String url;
private String name;
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
}

@ -0,0 +1,11 @@
package com.sztzjy.linkCommerce.entity.dto;
public class TargetUserProfileStepTwoValidationResult {
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; }
}

@ -0,0 +1,9 @@
package com.sztzjy.linkCommerce.service;
import com.sztzjy.linkCommerce.config.security.JwtUser;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepFiveValidationRequest;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepFiveValidationResult;
public interface TargetUserProfileStepFiveService {
TargetUserProfileStepFiveValidationResult validate(TargetUserProfileStepFiveValidationRequest request, JwtUser user);
}

@ -0,0 +1,9 @@
package com.sztzjy.linkCommerce.service;
import com.sztzjy.linkCommerce.config.security.JwtUser;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepFourValidationRequest;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepFourValidationResult;
public interface TargetUserProfileStepFourService {
TargetUserProfileStepFourValidationResult validate(TargetUserProfileStepFourValidationRequest request, JwtUser user);
}

@ -0,0 +1,9 @@
package com.sztzjy.linkCommerce.service;
import com.sztzjy.linkCommerce.config.security.JwtUser;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepOneValidationRequest;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepOneValidationResult;
public interface TargetUserProfileStepOneService {
TargetUserProfileStepOneValidationResult validate(TargetUserProfileStepOneValidationRequest request, JwtUser user);
}

@ -0,0 +1,9 @@
package com.sztzjy.linkCommerce.service;
import com.sztzjy.linkCommerce.config.security.JwtUser;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepThreeValidationRequest;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepThreeValidationResult;
public interface TargetUserProfileStepThreeService {
TargetUserProfileStepThreeValidationResult validate(TargetUserProfileStepThreeValidationRequest request, JwtUser user);
}

@ -0,0 +1,9 @@
package com.sztzjy.linkCommerce.service;
import com.sztzjy.linkCommerce.config.security.JwtUser;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepTwoValidationRequest;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepTwoValidationResult;
public interface TargetUserProfileStepTwoService {
TargetUserProfileStepTwoValidationResult validate(TargetUserProfileStepTwoValidationRequest request, JwtUser user);
}

@ -0,0 +1,60 @@
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.TargetUserProfileStepFiveValidationRequest;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepFiveValidationResult;
import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService;
import com.sztzjy.linkCommerce.service.TargetUserProfileStepFiveService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
@Service
public class TargetUserProfileStepFiveServiceImpl implements TargetUserProfileStepFiveService {
private static final String TASK_KEY = "target-user-profile";
private static final int MAX_SEGMENTS = 6;
private static final Set<String> ATTRACTIVENESS_OPTIONS = new LinkedHashSet<>(Arrays.asList("高", "中", "低"));
@Autowired
private StudentTrainingAnswerService studentTrainingAnswerService;
@Override
public TargetUserProfileStepFiveValidationResult validate(TargetUserProfileStepFiveValidationRequest request, JwtUser user) {
if (user == null || StringUtils.isBlank(user.getUserId())) {
throw new ServiceException(HttpStatus.UNAUTHORIZED, "请先登录后再校验");
}
if (user.getRoleId() != 4) {
throw new ServiceException(HttpStatus.FORBIDDEN, "仅学生可进行实训校验");
}
StudentTrainingAnswer savedAnswer = studentTrainingAnswerService.get(TASK_KEY, null, user);
String savedContent = savedAnswer == null ? "" : savedAnswer.getStep1Answer();
if (StringUtils.isBlank(savedContent) || !StringUtils.contains(savedContent, "keyUserRecords")
|| !StringUtils.contains(savedContent, "U01") || !StringUtils.contains(savedContent, "U02") || !StringUtils.contains(savedContent, "U03")) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请先完成并保存第 4 步重点用户画像");
}
if (request == null || request.getSegments() == null || request.getSegments().isEmpty() || request.getSegments().size() > MAX_SEGMENTS) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请完成细分市场分析表,最多可填写 6 行");
}
for (TargetUserProfileStepFiveValidationRequest.MarketSegment segment : request.getSegments()) {
if (segment == null || StringUtils.isBlank(segment.getMarket()) || !ATTRACTIVENESS_OPTIONS.contains(StringUtils.trim(segment.getAttractiveness()))
|| StringUtils.isBlank(segment.getPainPoints()) || StringUtils.isBlank(segment.getBehaviorCharacteristics())
|| StringUtils.isBlank(segment.getProductOpportunity())) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请完整填写每个细分市场的吸引力、需求痛点、行为特征和产品机会");
}
}
if (StringUtils.isBlank(request.getMarketSelection())) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请完成市场选择结论");
}
TargetUserProfileStepFiveValidationResult result = new TargetUserProfileStepFiveValidationResult();
result.setValid(true);
result.setMessage("校验通过");
return result;
}
}

@ -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.StudentTrainingAnswer;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepFourValidationRequest;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepFourValidationResult;
import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService;
import com.sztzjy.linkCommerce.service.TargetUserProfileStepFourService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
@Service
public class TargetUserProfileStepFourServiceImpl implements TargetUserProfileStepFourService {
private static final String TASK_KEY = "target-user-profile";
private static final Set<String> REQUIRED_CODES = new LinkedHashSet<>(Arrays.asList("U01", "U02", "U03"));
private static final Set<String> REQUIRED_INSIGHT_DIMENSIONS = new LinkedHashSet<>(Arrays.asList("高价值用户占比", "用户活跃度", "消费能力", "用户忠诚度", "重点客户群特征"));
@Autowired
private StudentTrainingAnswerService studentTrainingAnswerService;
@Override
public TargetUserProfileStepFourValidationResult validate(TargetUserProfileStepFourValidationRequest request, JwtUser user) {
if (user == null || StringUtils.isBlank(user.getUserId())) {
throw new ServiceException(HttpStatus.UNAUTHORIZED, "请先登录后再校验");
}
if (user.getRoleId() != 4) {
throw new ServiceException(HttpStatus.FORBIDDEN, "仅学生可进行实训校验");
}
StudentTrainingAnswer savedAnswer = studentTrainingAnswerService.get(TASK_KEY, null, user);
if (savedAnswer == null || StringUtils.isBlank(savedAnswer.getStep1Answer())) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请先完成并保存第 3 步 RFM 用户群体特点分析");
}
String savedContent = savedAnswer.getStep1Answer();
if (REQUIRED_INSIGHT_DIMENSIONS.stream().anyMatch(dimension -> !StringUtils.contains(savedContent, dimension))) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请先完整保存第 3 步 RFM 用户群体特点分析");
}
if (request == null || request.getRecords() == null || request.getRecords().size() != REQUIRED_CODES.size()) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请完成三位重点用户的完整画像");
}
Set<String> codes = new LinkedHashSet<>();
for (TargetUserProfileStepFourValidationRequest.UserPortrait record : request.getRecords()) {
String code = record == null ? "" : StringUtils.trimToEmpty(record.getCode());
if (!REQUIRED_CODES.contains(code) || !codes.add(code) || record == null
|| StringUtils.isBlank(record.getUser()) || StringUtils.isBlank(record.getBasicAttributes())
|| StringUtils.isBlank(record.getTags()) || StringUtils.isBlank(record.getBehavior())
|| StringUtils.isBlank(record.getPainPoints()) || StringUtils.isBlank(record.getPsychology())) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请完成三位重点用户的完整画像");
}
}
if (!codes.equals(REQUIRED_CODES)) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "重点用户访谈记录不完整");
}
TargetUserProfileStepFourValidationResult result = new TargetUserProfileStepFourValidationResult();
result.setValid(true);
result.setMessage("校验通过");
return result;
}
}

@ -0,0 +1,40 @@
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.TargetUserProfileStepOneValidationRequest;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepOneValidationResult;
import com.sztzjy.linkCommerce.service.TargetUserProfileStepOneService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import java.util.Locale;
@Service
public class TargetUserProfileStepOneServiceImpl implements TargetUserProfileStepOneService {
@Override
public TargetUserProfileStepOneValidationResult validate(TargetUserProfileStepOneValidationRequest request, JwtUser user) {
if (user == null || StringUtils.isBlank(user.getUserId())) {
throw new ServiceException(HttpStatus.UNAUTHORIZED, "请先登录后再校验");
}
if (user.getRoleId() != 4) {
throw new ServiceException(HttpStatus.FORBIDDEN, "仅学生可进行实训校验");
}
if (request == null || StringUtils.isBlank(request.getExcelUrl()) || StringUtils.isBlank(request.getExcelName())) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请上传 RFM 用户分层分析结果 Excel 数据");
}
String excelName = request.getExcelName().trim().toLowerCase(Locale.ROOT);
if (!excelName.endsWith(".xls") && !excelName.endsWith(".xlsx")) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "仅支持 .xls、.xlsx 格式的 Excel 文件");
}
if (request.getPreviewRowCount() == null || request.getPreviewRowCount() < 1
|| request.getPreviewColumnCount() == null || request.getPreviewColumnCount() < 1) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "Excel 文件需要包含可预览的表头和数据");
}
TargetUserProfileStepOneValidationResult result = new TargetUserProfileStepOneValidationResult();
result.setValid(true);
result.setMessage("校验通过");
return result;
}
}

@ -0,0 +1,63 @@
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.TargetUserProfileStepThreeValidationRequest;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepThreeValidationResult;
import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService;
import com.sztzjy.linkCommerce.service.TargetUserProfileStepThreeService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
@Service
public class TargetUserProfileStepThreeServiceImpl implements TargetUserProfileStepThreeService {
private static final String TASK_KEY = "target-user-profile";
private static final Set<String> REQUIRED_DIMENSIONS = new LinkedHashSet<>(Arrays.asList("高价值用户占比", "用户活跃度", "消费能力", "用户忠诚度", "重点客户群特征"));
private static final Set<String> REQUIRED_CHART_TYPES = new LinkedHashSet<>(Arrays.asList("segment-share", "average-spend", "score-heatmap"));
@Autowired
private StudentTrainingAnswerService studentTrainingAnswerService;
@Override
public TargetUserProfileStepThreeValidationResult validate(TargetUserProfileStepThreeValidationRequest request, JwtUser user) {
if (user == null || StringUtils.isBlank(user.getUserId())) {
throw new ServiceException(HttpStatus.UNAUTHORIZED, "请先登录后再校验");
}
if (user.getRoleId() != 4) {
throw new ServiceException(HttpStatus.FORBIDDEN, "仅学生可进行实训校验");
}
StudentTrainingAnswer savedAnswer = studentTrainingAnswerService.get(TASK_KEY, null, user);
if (savedAnswer == null || StringUtils.isBlank(savedAnswer.getStep1Answer())) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请先完成并保存第 2 步 RFM 图表");
}
String savedContent = savedAnswer.getStep1Answer();
if (REQUIRED_CHART_TYPES.stream().anyMatch(type -> !StringUtils.contains(savedContent, type))) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请先完整保存第 2 步的三类 RFM 图表");
}
if (request == null || request.getInsights() == null || request.getInsights().size() != REQUIRED_DIMENSIONS.size()) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请完成五个 RFM 用户群体特点分析维度");
}
Set<String> dimensions = new LinkedHashSet<>();
for (TargetUserProfileStepThreeValidationRequest.Insight insight : request.getInsights()) {
String dimension = insight == null ? "" : StringUtils.trimToEmpty(insight.getDimension());
String analysis = insight == null ? "" : StringUtils.trimToEmpty(insight.getAnalysis());
if (!REQUIRED_DIMENSIONS.contains(dimension) || !dimensions.add(dimension) || StringUtils.isBlank(analysis)) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请完成五个 RFM 用户群体特点分析维度");
}
}
if (!dimensions.equals(REQUIRED_DIMENSIONS)) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "提交的分析维度不完整");
}
TargetUserProfileStepThreeValidationResult result = new TargetUserProfileStepThreeValidationResult();
result.setValid(true);
result.setMessage("校验通过");
return result;
}
}

@ -0,0 +1,60 @@
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.TargetUserProfileStepTwoValidationRequest;
import com.sztzjy.linkCommerce.entity.dto.TargetUserProfileStepTwoValidationResult;
import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService;
import com.sztzjy.linkCommerce.service.TargetUserProfileStepTwoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
@Service
public class TargetUserProfileStepTwoServiceImpl implements TargetUserProfileStepTwoService {
private static final String TASK_KEY = "target-user-profile";
private static final Set<String> REQUIRED_CHART_TYPES = new LinkedHashSet<>(Arrays.asList("segment-share", "average-spend", "score-heatmap"));
@Autowired
private StudentTrainingAnswerService studentTrainingAnswerService;
@Override
public TargetUserProfileStepTwoValidationResult validate(TargetUserProfileStepTwoValidationRequest request, JwtUser user) {
if (user == null || StringUtils.isBlank(user.getUserId())) {
throw new ServiceException(HttpStatus.UNAUTHORIZED, "请先登录后再校验");
}
if (user.getRoleId() != 4) {
throw new ServiceException(HttpStatus.FORBIDDEN, "仅学生可进行实训校验");
}
StudentTrainingAnswer savedAnswer = studentTrainingAnswerService.get(TASK_KEY, null, user);
if (savedAnswer == null || StringUtils.isBlank(savedAnswer.getStep1Answer())) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请先完成并保存第 1 步 RFM 用户分层分析");
}
if (request == null || request.getCharts() == null || request.getCharts().size() != REQUIRED_CHART_TYPES.size()) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请上传三类 RFM 可视化图表");
}
Set<String> chartTypes = new LinkedHashSet<>();
for (TargetUserProfileStepTwoValidationRequest.ChartUpload chart : request.getCharts()) {
String type = chart == null ? "" : StringUtils.trimToEmpty(chart.getType());
String url = chart == null ? "" : StringUtils.trimToEmpty(chart.getUrl());
String name = chart == null ? "" : StringUtils.trimToEmpty(chart.getName()).toLowerCase();
if (!REQUIRED_CHART_TYPES.contains(type) || !chartTypes.add(type) || StringUtils.isBlank(url)
|| !(name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".webp"))) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "请完整上传客户分层占比饼图、平均消费对比柱状图和 RFM 分数分布热力图");
}
}
if (!chartTypes.equals(REQUIRED_CHART_TYPES)) {
throw new ServiceException(HttpStatus.BAD_REQUEST, "提交的 RFM 图表类型不完整");
}
TargetUserProfileStepTwoValidationResult result = new TargetUserProfileStepTwoValidationResult();
result.setValid(true);
result.setMessage("校验通过");
return result;
}
}

@ -0,0 +1,72 @@
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.TargetUserProfileStepFiveValidationRequest;
import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.Arrays;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class TargetUserProfileStepFiveServiceImplTest {
@Test
void validatesCompleteMarketSegmentsAfterPortraitsAreSaved() {
assertTrue(serviceWithPortraitHistory().validate(request(), student()).isValid());
}
@Test
void rejectsIncompleteSegmentAndMissingPortraitHistory() {
TargetUserProfileStepFiveValidationRequest incomplete = request();
incomplete.getSegments().get(0).setAttractiveness("");
assertThrows(ServiceException.class, () -> serviceWithPortraitHistory().validate(incomplete, student()));
TargetUserProfileStepFiveServiceImpl service = new TargetUserProfileStepFiveServiceImpl();
StudentTrainingAnswerService answers = mock(StudentTrainingAnswerService.class);
when(answers.get(anyString(), any(), any(JwtUser.class))).thenReturn(new StudentTrainingAnswer());
ReflectionTestUtils.setField(service, "studentTrainingAnswerService", answers);
assertThrows(ServiceException.class, () -> service.validate(request(), student()));
}
private TargetUserProfileStepFiveServiceImpl serviceWithPortraitHistory() {
TargetUserProfileStepFiveServiceImpl service = new TargetUserProfileStepFiveServiceImpl();
StudentTrainingAnswerService answers = mock(StudentTrainingAnswerService.class);
StudentTrainingAnswer answer = new StudentTrainingAnswer();
answer.setStep1Answer("{\"keyUserRecords\":[{\"code\":\"U01\"},{\"code\":\"U02\"},{\"code\":\"U03\"}]}");
when(answers.get(anyString(), any(), any(JwtUser.class))).thenReturn(answer);
ReflectionTestUtils.setField(service, "studentTrainingAnswerService", answers);
return service;
}
private TargetUserProfileStepFiveValidationRequest request() {
TargetUserProfileStepFiveValidationRequest request = new TargetUserProfileStepFiveValidationRequest();
request.setSegments(Arrays.asList(segment("职场白领"), segment("精致妈妈")));
request.setMarketSelection("优先服务有明确助眠需求的职场白领,并开发便捷的智能助眠产品。");
return request;
}
private TargetUserProfileStepFiveValidationRequest.MarketSegment segment(String market) {
TargetUserProfileStepFiveValidationRequest.MarketSegment segment = new TargetUserProfileStepFiveValidationRequest.MarketSegment();
segment.setMarket(market);
segment.setAttractiveness("高");
segment.setPainPoints("睡眠质量差,需要便捷的改善方案");
segment.setBehaviorCharacteristics("愿意尝试智能设备,并会关注健康数据");
segment.setProductOpportunity("提供智能灯光、睡眠内容和数据报告的一体化产品");
return segment;
}
private JwtUser student() {
JwtUser user = new JwtUser();
user.setUserId("stu-1");
user.setRoleId(4);
return user;
}
}

@ -0,0 +1,77 @@
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.TargetUserProfileStepFourValidationRequest;
import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.ArrayList;
import java.util.Arrays;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class TargetUserProfileStepFourServiceImplTest {
@Test
void validatesThreeCompletePortraitsAfterInsightsAreSaved() {
assertTrue(serviceWithInsights().validate(request(), student()).isValid());
}
@Test
void rejectsIncompletePortraitAndMissingInsightHistory() {
TargetUserProfileStepFourValidationRequest incomplete = request();
incomplete.setRecords(new ArrayList<>(incomplete.getRecords()));
incomplete.getRecords().get(1).setPsychology("");
assertThrows(ServiceException.class, () -> serviceWithInsights().validate(incomplete, student()));
TargetUserProfileStepFourServiceImpl service = new TargetUserProfileStepFourServiceImpl();
StudentTrainingAnswerService answers = mock(StudentTrainingAnswerService.class);
StudentTrainingAnswer answer = new StudentTrainingAnswer();
answer.setStep1Answer("{\"rfmInsights\":[{\"dimension\":\"用户活跃度\"}]} ");
when(answers.get(anyString(), any(), any(JwtUser.class))).thenReturn(answer);
ReflectionTestUtils.setField(service, "studentTrainingAnswerService", answers);
assertThrows(ServiceException.class, () -> service.validate(request(), student()));
}
private TargetUserProfileStepFourServiceImpl serviceWithInsights() {
TargetUserProfileStepFourServiceImpl service = new TargetUserProfileStepFourServiceImpl();
StudentTrainingAnswerService answers = mock(StudentTrainingAnswerService.class);
StudentTrainingAnswer answer = new StudentTrainingAnswer();
answer.setStep1Answer("{\"rfmInsights\":[\"高价值用户占比\",\"用户活跃度\",\"消费能力\",\"用户忠诚度\",\"重点客户群特征\"]}");
when(answers.get(anyString(), any(), any(JwtUser.class))).thenReturn(answer);
ReflectionTestUtils.setField(service, "studentTrainingAnswerService", answers);
return service;
}
private TargetUserProfileStepFourValidationRequest request() {
TargetUserProfileStepFourValidationRequest request = new TargetUserProfileStepFourValidationRequest();
request.setRecords(Arrays.asList(record("U01"), record("U02"), record("U03")));
return request;
}
private TargetUserProfileStepFourValidationRequest.UserPortrait record(String code) {
TargetUserProfileStepFourValidationRequest.UserPortrait record = new TargetUserProfileStepFourValidationRequest.UserPortrait();
record.setCode(code);
record.setUser(code + " 用户");
record.setBasicAttributes("基础属性");
record.setTags("用户标签");
record.setBehavior("行为特征");
record.setPainPoints("需求痛点");
record.setPsychology("消费心理");
return record;
}
private JwtUser student() {
JwtUser user = new JwtUser();
user.setUserId("stu-1");
user.setRoleId(4);
return user;
}
}

@ -0,0 +1,39 @@
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.TargetUserProfileStepOneValidationRequest;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
class TargetUserProfileStepOneServiceImplTest {
@Test
void validatesStudentRfmExcelWithPreview() {
assertTrue(new TargetUserProfileStepOneServiceImpl().validate(request("rfm.xlsx", 20, 6), student()).isValid());
}
@Test
void rejectsNonExcelFileAndUnpreviewableWorkbook() {
TargetUserProfileStepOneServiceImpl service = new TargetUserProfileStepOneServiceImpl();
assertThrows(ServiceException.class, () -> service.validate(request("rfm.pdf", 2, 6), student()));
assertThrows(ServiceException.class, () -> service.validate(request("rfm.xlsx", 0, 0), student()));
}
private TargetUserProfileStepOneValidationRequest request(String excelName, int rows, int columns) {
TargetUserProfileStepOneValidationRequest request = new TargetUserProfileStepOneValidationRequest();
request.setExcelName(excelName);
request.setExcelUrl("/profile/" + excelName);
request.setPreviewRowCount(rows);
request.setPreviewColumnCount(columns);
return request;
}
private JwtUser student() {
JwtUser user = new JwtUser();
user.setUserId("stu-1");
user.setRoleId(4);
return user;
}
}

@ -0,0 +1,74 @@
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.TargetUserProfileStepThreeValidationRequest;
import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.ArrayList;
import java.util.Arrays;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class TargetUserProfileStepThreeServiceImplTest {
@Test
void validatesAllInsightsAfterChartsAreSaved() {
assertTrue(serviceWithCharts().validate(request(), student()).isValid());
}
@Test
void rejectsMissingInsightAndMissingChartHistory() {
TargetUserProfileStepThreeValidationRequest incomplete = request();
incomplete.setInsights(new ArrayList<>(incomplete.getInsights()));
incomplete.getInsights().remove(4);
assertThrows(ServiceException.class, () -> serviceWithCharts().validate(incomplete, student()));
TargetUserProfileStepThreeServiceImpl service = new TargetUserProfileStepThreeServiceImpl();
StudentTrainingAnswerService answers = mock(StudentTrainingAnswerService.class);
StudentTrainingAnswer answer = new StudentTrainingAnswer();
answer.setStep1Answer("{\"rfmCharts\":{\"segment-share\":{}}}");
when(answers.get(anyString(), any(), any(JwtUser.class))).thenReturn(answer);
ReflectionTestUtils.setField(service, "studentTrainingAnswerService", answers);
assertThrows(ServiceException.class, () -> service.validate(request(), student()));
}
private TargetUserProfileStepThreeServiceImpl serviceWithCharts() {
TargetUserProfileStepThreeServiceImpl service = new TargetUserProfileStepThreeServiceImpl();
StudentTrainingAnswerService answers = mock(StudentTrainingAnswerService.class);
StudentTrainingAnswer answer = new StudentTrainingAnswer();
answer.setStep1Answer("{\"rfmCharts\":{\"segment-share\":{},\"average-spend\":{},\"score-heatmap\":{}}}");
when(answers.get(anyString(), any(), any(JwtUser.class))).thenReturn(answer);
ReflectionTestUtils.setField(service, "studentTrainingAnswerService", answers);
return service;
}
private TargetUserProfileStepThreeValidationRequest request() {
TargetUserProfileStepThreeValidationRequest request = new TargetUserProfileStepThreeValidationRequest();
request.setInsights(Arrays.asList(
insight("高价值用户占比"), insight("用户活跃度"), insight("消费能力"), insight("用户忠诚度"), insight("重点客户群特征")
));
return request;
}
private TargetUserProfileStepThreeValidationRequest.Insight insight(String dimension) {
TargetUserProfileStepThreeValidationRequest.Insight insight = new TargetUserProfileStepThreeValidationRequest.Insight();
insight.setDimension(dimension);
insight.setAnalysis("已完成" + dimension + "分析");
return insight;
}
private JwtUser student() {
JwtUser user = new JwtUser();
user.setUserId("stu-1");
user.setRoleId(4);
return user;
}
}

@ -0,0 +1,75 @@
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.TargetUserProfileStepTwoValidationRequest;
import com.sztzjy.linkCommerce.service.StudentTrainingAnswerService;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.Arrays;
import java.util.ArrayList;
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 TargetUserProfileStepTwoServiceImplTest {
@Test
void validatesAllThreeRfmChartsAfterStepOneIsSaved() {
assertTrue(serviceWithStepOne().validate(request(), student()).isValid());
}
@Test
void rejectsIncompleteChartsAndMissingStepOne() {
TargetUserProfileStepTwoValidationRequest incomplete = request();
incomplete.setCharts(new ArrayList<>(incomplete.getCharts()));
incomplete.getCharts().remove(2);
assertThrows(ServiceException.class, () -> serviceWithStepOne().validate(incomplete, student()));
TargetUserProfileStepTwoServiceImpl service = new TargetUserProfileStepTwoServiceImpl();
StudentTrainingAnswerService answers = mock(StudentTrainingAnswerService.class);
when(answers.get(anyString(), any(), any(JwtUser.class))).thenReturn(null);
ReflectionTestUtils.setField(service, "studentTrainingAnswerService", answers);
assertThrows(ServiceException.class, () -> service.validate(request(), student()));
}
private TargetUserProfileStepTwoServiceImpl serviceWithStepOne() {
TargetUserProfileStepTwoServiceImpl service = new TargetUserProfileStepTwoServiceImpl();
StudentTrainingAnswerService answers = mock(StudentTrainingAnswerService.class);
StudentTrainingAnswer answer = new StudentTrainingAnswer();
answer.setStep1Answer("{\"profileFileUrl\":\"/rfm.xlsx\"}");
when(answers.get(anyString(), any(), any(JwtUser.class))).thenReturn(answer);
ReflectionTestUtils.setField(service, "studentTrainingAnswerService", answers);
return service;
}
private TargetUserProfileStepTwoValidationRequest request() {
TargetUserProfileStepTwoValidationRequest request = new TargetUserProfileStepTwoValidationRequest();
request.setCharts(Arrays.asList(
chart("segment-share", "share.png"),
chart("average-spend", "spend.jpg"),
chart("score-heatmap", "heatmap.webp")
));
return request;
}
private TargetUserProfileStepTwoValidationRequest.ChartUpload chart(String type, String name) {
TargetUserProfileStepTwoValidationRequest.ChartUpload chart = new TargetUserProfileStepTwoValidationRequest.ChartUpload();
chart.setType(type);
chart.setName(name);
chart.setUrl("/profile/" + name);
return chart;
}
private JwtUser student() {
JwtUser user = new JwtUser();
user.setUserId("stu-1");
user.setRoleId(4);
return user;
}
}
Loading…
Cancel
Save