This commit is contained in:
Lx 2025-05-10 16:35:42 +08:00
parent d099d47541
commit ad1015fe88
30 changed files with 812 additions and 20 deletions

View File

@ -153,6 +153,7 @@ public interface DlDriveSchoolStudentService extends IService<DlDriveSchoolStude
*/
Boolean updateStudentPassAndGradTime(Date passTime, Long userId, String courseId, Long tenantId);
Boolean updateStudentGradTime(Long userId, String courseId, Long tenantId);
Boolean adminUpdateStudentPassAndGradTime(Date passTime,Date gradTime, Long userId, String courseId, Long tenantId);
/**
* 根据唯一码查询学员信息

View File

@ -0,0 +1,8 @@
package cn.iocoder.yudao.module.base.service;
import java.util.Map;
public interface WxPushMessagesService {
public void sendSubscribeMessage(String openid, String templateId, String page, Map<String, String> data);
}

View File

@ -9,6 +9,8 @@ import cn.iocoder.yudao.module.base.service.DlDriveSchoolStudentService;
import cn.iocoder.yudao.module.base.vo.*;
import cn.iocoder.yudao.module.course.entity.Process;
import cn.iocoder.yudao.module.course.entity.SchoolCommission;
import cn.iocoder.yudao.module.course.entity.SchoolCourseOrder;
import cn.iocoder.yudao.module.course.mapper.ProcessMapper;
import cn.iocoder.yudao.module.course.mapper.SchoolCommissionMapper;
import cn.iocoder.yudao.module.course.mapper.SchoolCourseOrderMapper;
import cn.iocoder.yudao.module.course.service.ProcessService;
@ -42,6 +44,8 @@ public class DataViewServiceImpl implements DataViewService {
@Autowired
private ProcessService processService;
@Autowired
private ProcessMapper processMapper;
@Autowired
private TrainService trainService;
@Autowired
private TrainMapper trainMapper;
@ -68,9 +72,23 @@ public class DataViewServiceImpl implements DataViewService {
//学员主信息
DlDriveSchoolStudent student = studentService.getStudentByUserId(id);
studentInfoVO.setStudentInfo(student);
// 查询学员订单信息
SchoolCourseOrder orderInfo = courseOrderMapper.getOrderInfo(id);
studentInfoVO.setStudentOrderInfo(orderInfo);
//当前学习进度
Process process = processService.selectByUserId(id,coachId);
studentInfoVO.setProcess(process);
// 学习进度列表
String courseId="";
if(orderInfo != null){
courseId = orderInfo.getCourseId();
}
List<Process> processList = processMapper.getProcessList(id,courseId);
if (processList != null) {
studentInfoVO.setProcessList(processList);
} else {
studentInfoVO.setProcessList(null);;
}
//查这个课程累计总训练时长
studentInfoVO.setTrainTime(processService.getAllTrainTime(id,process.getCourseId()));
//查归属教练信息

View File

@ -446,6 +446,18 @@ public class DlDriveSchoolStudentServiceImpl extends ServiceImpl<DlDriveSchoolSt
return true;
}
@Override
@Transactional
public Boolean adminUpdateStudentPassAndGradTime(Date passTime, Date gradTime, Long userId, String courseId, Long tenantId) {
// 更新学员拿证时间
schoolCourseOrderService.update(Wrappers.lambdaUpdate(SchoolCourseOrder.class)
.eq(SchoolCourseOrder::getUserId, userId)
.eq(SchoolCourseOrder::getCourseId, courseId)
.set(passTime != null, SchoolCourseOrder::getPassTime, passTime)
.set(gradTime != null, SchoolCourseOrder::getGradTime, gradTime));
return true;
}
/**
* 根据唯一码查询学员信息
*

View File

@ -0,0 +1,45 @@
package cn.iocoder.yudao.module.base.service.impl;
import cn.binarywang.wx.miniapp.api.WxMaAnalysisService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.iocoder.yudao.module.base.service.WxPushMessagesService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
@Slf4j
public class WxPushMessagesServiceImpl implements WxPushMessagesService {
@Autowired
private WxMaService wxMaService;
/**
* 发送订阅消息
* @param openid 用户openid
* @param templateId 模板ID
* @param page 跳转页面
* @param data 模板内容
*/
@Override
public void sendSubscribeMessage(String openid, String templateId, String page, Map<String, String> data) {
WxMaSubscribeMessage message = new WxMaSubscribeMessage();
message.setToUser(openid);
message.setTemplateId(templateId);
message.setPage(page);
data.forEach((key, value) ->
message.addData(new WxMaSubscribeMessage.MsgData(key, value))
);
try {
wxMaService.getMsgService().sendSubscribeMsg(message);
} catch (WxErrorException e) {
log.error("微信消息推送失败: {}", e.getMessage());
}
}
}

View File

@ -30,6 +30,10 @@ public class DlDriveSchoolStaffVO {
private Long userId;
/**车辆注册日期*/
private Date carRegisterDate;
/**招生类型*/
private String source;
/**创建时间*/
private Date createTime;
/**车龄*/
private Long carOld;
@ -49,4 +53,4 @@ public class DlDriveSchoolStaffVO {
private String startTime;
/**查询时间范围--结束*/
private String endTime;
}
}

View File

@ -18,4 +18,6 @@ public class StudentCountVO {
private Integer totalNum;
/**userId*/
private Long userId;
/**时间筛选学员人数*/
private Integer timeTotal;
}

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.base.vo;
import cn.iocoder.yudao.module.base.entity.DlDriveSchoolStudent;
import cn.iocoder.yudao.module.course.entity.Process;
import cn.iocoder.yudao.module.course.entity.SchoolCourseOrder;
import cn.iocoder.yudao.module.exam.vo.ExamBatchItemVO;
import cn.iocoder.yudao.module.train.entity.Train;
import lombok.Data;
@ -12,8 +13,12 @@ import java.util.List;
public class StudentInfoVO {
/**学生基本信息*/
private DlDriveSchoolStudent studentInfo;
/**学员订单信息*/
private SchoolCourseOrder studentOrderInfo;
/**学习进度*/
private Process process;
/**学习进度列表*/
private List<Process> processList;
/**训练总时长*/
private Double trainTime;
/**教练信息*/

View File

@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.base.vo.DlDriveSchoolCourseVO;
import cn.iocoder.yudao.module.course.entity.Process;
import cn.iocoder.yudao.module.course.service.ProcessService;
import cn.iocoder.yudao.module.course.vo.ProcessAddVO;
import cn.iocoder.yudao.module.course.vo.ProcessAndExamBatchVO;
import cn.iocoder.yudao.module.course.vo.ProcessNewVO;
import cn.iocoder.yudao.module.course.vo.ProcessVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
@ -102,6 +103,13 @@ public class ProcessController {
return success(BeanUtils.toBean(processService.getById(id), ProcessVO.class));
}
@GetMapping("/getProcessAndBatch")
@Operation(summary = "通过id 查询学员进度课程及批次信息")
public CommonResult<ProcessAndExamBatchVO> getProcessAndBatch(@RequestParam("id") String id) {
ProcessAndExamBatchVO processAndBatch = processService.getProcessAndBatch(id);
return success(processAndBatch);
}
/**
* 财务审核
*

View File

@ -24,6 +24,7 @@ import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -125,4 +126,21 @@ public class SchoolCourseOrderController {
return success(schoolCourseOrderService.fastCreateSchoolCourseOrder(createReqVO));
}
}
/**
* 教练修改学员毕业时间
*/
@GetMapping("/updateStudentGradTime")
public CommonResult<?> updateStudentGraduateTime(String studentId, String gradTime) {
schoolCourseOrderService.updateStudentGradTime(studentId, gradTime);
return success(true);
}
/**
* 教练修改学员拿证时间
*/
@GetMapping("/updateStudentPassTime")
public CommonResult<?> updateStudentGetLicenseTime(String studentId, String passTime) {
schoolCourseOrderService.updateStudentPassTime(studentId, passTime);
return success(true);
}
}

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.course.mapper;
import cn.iocoder.yudao.module.base.vo.DlDriveSchoolCoachPageReqVO;
import cn.iocoder.yudao.module.base.vo.DlDriveSchoolCoachRespVO;
import cn.iocoder.yudao.module.course.entity.Process;
import cn.iocoder.yudao.module.course.vo.ProcessAndExamBatchVO;
import cn.iocoder.yudao.module.course.vo.ProcessVO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
@ -50,11 +51,11 @@ public interface ProcessMapper extends BaseMapper<Process> {
@Param("examScore")Double examScore,
@Param("images")String images,
@Param("examTime")String examTime);
/**
* 查用户最新的一条且科目最大的一条学习记录
* @author vinjor-M
* @date 15:58 2025/2/8
* @author vinjor-M
* @date 15:58 2025/2/8
* @param userId 用户id
* @return cn.iocoder.yudao.module.course.entity.Process
**/
@ -71,4 +72,18 @@ public interface ProcessMapper extends BaseMapper<Process> {
IPage<ProcessVO> pageProcess(@Param("entity") ProcessVO entity, Page<ProcessVO> page);
Double selectAllTrainTime(@Param("userId") Long userId,@Param("courseId") String courseId);
}
/**
* 获取学员课程进度列表
*/
List<Process> getProcessList(@Param("userId") Long userId, @Param("courseId") String courseId);
/**
* 获取学员考试批次信息
*/
ProcessAndExamBatchVO getProcessAndBatch(@Param("courseId") String courseId,
@Param("coachId") Long coachId,
@Param("subject") int subject,
@Param("fraction") double fraction,
@Param("userId") Long userId);
}

View File

@ -39,4 +39,8 @@ public interface SchoolCourseOrderMapper extends BaseMapper<SchoolCourseOrder> {
* @return java.util.List<cn.iocoder.yudao.module.course.vo.SchoolCourseOrderVO>
**/
Double selectByCoachUserId(@Param("coachId")Long coachId,@Param("startTime")String startTime,@Param("endTime")String endTime);
/** 学员订单信息 */
SchoolCourseOrderVO getOrderInfo(@Param("userId") Long userId);
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.course.service;
import cn.iocoder.yudao.module.course.entity.Process;
import cn.iocoder.yudao.module.course.vo.ProcessAndExamBatchVO;
import cn.iocoder.yudao.module.course.vo.ProcessNewVO;
import cn.iocoder.yudao.module.exam.vo.ExamVO;
import cn.iocoder.yudao.module.course.vo.ProcessAddVO;
@ -133,4 +134,12 @@ public interface ProcessService extends IService<Process> {
* 教练自招自动分配教练
*/
void autoAssignCoach(ProcessNewVO request);
/**
* 根据进度id查询进度详情并且查询对应考试批次信息
* 修改学员成绩时调用
*/
ProcessAndExamBatchVO getProcessAndBatch(String id);
}

View File

@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.GetMapping;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -98,5 +99,14 @@ public interface SchoolCourseOrderService extends IService<SchoolCourseOrder> {
*/
Boolean sendOrderMessage(String studentName, String courseName, Long coachId);
/**
* 教练修改学员毕业时间
*/
void updateStudentGradTime(String studentId, String gradTime);
/**
* 教练修改学员拿证时间
*/
void updateStudentPassTime(String studentId, String gradTime);
}

View File

@ -21,11 +21,8 @@ import cn.iocoder.yudao.module.course.mapper.ProcessMapper;
import cn.iocoder.yudao.module.course.service.ProcessService;
import cn.iocoder.yudao.module.course.service.SchoolCommissionService;
import cn.iocoder.yudao.module.course.service.SchoolCourseOrderService;
import cn.iocoder.yudao.module.course.vo.ProcessNewVO;
import cn.iocoder.yudao.module.course.vo.SchoolCourseOrderVO;
import cn.iocoder.yudao.module.course.vo.*;
import cn.iocoder.yudao.module.exam.vo.ExamVO;
import cn.iocoder.yudao.module.course.vo.ProcessAddVO;
import cn.iocoder.yudao.module.course.vo.ProcessVO;
import cn.iocoder.yudao.module.exam.mapper.ExamBatchItemMapper;
import cn.iocoder.yudao.module.exam.vo.ExamBatchItemNewVO;
import cn.iocoder.yudao.module.jx.domain.DriveSchoolDeduct;
@ -38,6 +35,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
@ -609,4 +607,31 @@ public class ProcessServiceImpl extends ServiceImpl<ProcessMapper, Process> impl
this.saveProcess(processAddVO);
}
@Override
public ProcessAndExamBatchVO getProcessAndBatch(String id) {
ProcessAndExamBatchVO processAndExamBatchVO = new ProcessAndExamBatchVO();
Process process = processMapper.selectById(id);
BeanUtils.copyProperties(process, processAndExamBatchVO);
if (process != null) {
String courseId = process.getCourseId();
Long coachId = process.getCoachId();
int subject = process.getSubject();
double fraction = process.getExamScore();
Long userId = process.getUserId();
ProcessAndExamBatchVO processAndBatch = processMapper.getProcessAndBatch(courseId, coachId, subject, fraction, userId);
if (processAndBatch != null) {
processAndExamBatchVO.setBatchId(processAndBatch.getBatchId());
processAndExamBatchVO.setBatchItemId(processAndBatch.getBatchItemId());
processAndExamBatchVO.setAddr(processAndBatch.getAddr());
processAndExamBatchVO.setAddrId(processAndBatch.getAddrId());
processAndExamBatchVO.setTransWay(processAndBatch.getTransWay());
processAndExamBatchVO.setStartTime(processAndBatch.getStartTime());
processAndExamBatchVO.setEndTime(processAndBatch.getEndTime());AdminUserRespDTO user = userApi.getUser(userId);
}
}
return processAndExamBatchVO;
}
}

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.course.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.base.constant.SchoolBaseConstants;
import cn.iocoder.yudao.module.base.service.SchoolNotifyMessageSendService;
@ -18,6 +19,7 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.system.api.user.dto.UserDTO;
import cn.iocoder.yudao.module.system.service.permission.RoleService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -29,7 +31,10 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@ -232,6 +237,67 @@ public class SchoolCourseOrderServiceImpl extends ServiceImpl<SchoolCourseOrderM
return Boolean.TRUE;
}
/**
* 教练修改学员毕业时间
*/
@Override
public void updateStudentGradTime(String studentId, String gradTime) {
Long coachId = SecurityFrameworkUtils.getLoginUserId();
List<SchoolCourseOrder> students = schoolCourseOrderMapper.selectList(new LambdaQueryWrapper<SchoolCourseOrder>()
.eq(SchoolCourseOrder::getUserId, studentId)
.eq(SchoolCourseOrder::getCoachUserId, coachId)
.orderByDesc(SchoolCourseOrder::getUpdateTime)
);
if (students != null && !students.isEmpty()) {
SchoolCourseOrder latestStudent = students.get(0);
// 字符串转 Date
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date gradTimeDate;
try {
gradTimeDate = sdf.parse(gradTime);
} catch (ParseException e) {
throw new RuntimeException("毕业时间格式错误,应为 yyyy-MM-dd", e);
}
SchoolCourseOrder updateEntity = new SchoolCourseOrder();
updateEntity.setId(latestStudent.getId());
updateEntity.setGradTime(gradTimeDate);
schoolCourseOrderMapper.updateById(updateEntity);
}
}
/**
* 教练修改学员拿证时间
*/
@Override
public void updateStudentPassTime(String studentId, String passTime) {
Long coachId = SecurityFrameworkUtils.getLoginUserId();
List<SchoolCourseOrder> students = schoolCourseOrderMapper.selectList(new LambdaQueryWrapper<SchoolCourseOrder>()
.eq(SchoolCourseOrder::getUserId, studentId)
.eq(SchoolCourseOrder::getCoachUserId, coachId)
.orderByDesc(SchoolCourseOrder::getUpdateTime)
);
if (students != null && !students.isEmpty()) {
SchoolCourseOrder latestStudent = students.get(0);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date passTimeDate;
try {
passTimeDate = sdf.parse(passTime);
} catch (ParseException e) {
throw new RuntimeException("毕业时间格式错误,应为 yyyy-MM-dd", e);
}
SchoolCourseOrder updateEntity = new SchoolCourseOrder();
updateEntity.setId(latestStudent.getId());
updateEntity.setPassTime(passTimeDate);
schoolCourseOrderMapper.updateById(updateEntity);
}
}
public String generateOrderNumber() {
return "ORDER" + UUID.randomUUID().toString().replace("-", "").substring(0, 10);
}

View File

@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.course.vo;
import lombok.Data;
import java.util.Date;
@Data
public class ProcessAndExamBatchVO extends ProcessVO{
/**
* 考试开始时间
*/
private Date startTime;
/**
* 考试结束时间
*/
private Date endTime;
/**
* 考试地址id
*/
private String addrId;
/**
* 考试地址
*/
private String addr;
/**
* 交通方式(字典school_transport_way)
*/
private String transWay;
/**
* 批次id
*/
private String batchId;
/**
* 批次子表id
*/
private String batchItemId;
}

View File

@ -11,4 +11,10 @@ import lombok.Data;
@Data
public class ProcessVO extends Process {
}
/** 学员身份证号 */
private String studentIdCard;
/** 更新人姓名 */
private String updateName;
}

View File

@ -197,6 +197,49 @@ public class ExamBatchItemServiceImpl extends ServiceImpl<ExamBatchItemMapper, E
}
}
/**
* 更新考试批次通过率
* 手动录入/修改成绩使用
*
* @param id 批次ID
* @author vinjor-M
* @date 17:39 2025/2/7
**/
@Transactional(rollbackFor = Exception.class) // 添加事务确保数据一致性
public void updateBatchPassRateNew(String id) {
// 查询考试批次信息
ExamBatch examBatch = examBatchService.getById(id);
if (examBatch == null) {
throw new RuntimeException("考试批次不存在");
}
// 查询该批次下的所有考试项
LambdaQueryWrapper<ExamBatchItem> queryWrapper = new LambdaQueryWrapper<ExamBatchItem>()
.eq(ExamBatchItem::getBatchId, id);
List<ExamBatchItem> allList = this.list(queryWrapper);
// 如果没有考试项直接返回或设为0取决于业务需求
if (allList.isEmpty()) {
examBatchService.updateById(examBatch);
return;
}
// 筛选通过的考试项
List<ExamBatchItem> passList = allList.stream()
.filter(item -> item.getIfPass() != null && item.getIfPass())
.collect(Collectors.toList());
// 计算通过率兼容无人通过的情况
double passRate = passList.isEmpty() ? 0.0 :
new BigDecimal(passList.size())
.divide(new BigDecimal(allList.size()), 2, RoundingMode.HALF_UP)
.doubleValue();
// 更新考试批次通过率
examBatch.setPassRate(passRate);
examBatchService.updateById(examBatch);
}
/**
* 根据学生id和教练ID查询考试记录
*

View File

@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.jx.controller.admin;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.course.vo.ProcessVO;
import cn.iocoder.yudao.module.jx.core.controller.BaseController;
import cn.iocoder.yudao.module.jx.domain.StudentScoreInput;
import cn.iocoder.yudao.module.jx.service.StudentScoreInputService;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@Tag(name = "管理后台 - 学员考试成绩录入")
@RestController
@RequestMapping("/scoreInput")
@Validated
public class StudentScoreInputController extends BaseController {
@Autowired
private StudentScoreInputService studentScoreInputService;
/**
* 录入学员成绩
*/
@PostMapping("/input")
public CommonResult scoreInput(@RequestBody StudentScoreInput studentScoreInput) {
studentScoreInputService.scoreInput(studentScoreInput);
return success();
}
@PutMapping("/update")
public CommonResult scoreEdit(@RequestBody StudentScoreInput studentScoreInput) {
studentScoreInputService.scoreEdit(studentScoreInput);
return success();
}
}

View File

@ -0,0 +1,132 @@
package cn.iocoder.yudao.module.jx.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StudentScoreInput {
/**
* 考试批次ID
*/
private String examBatchId;
/**
* 课程ID
*/
private String courseId;
/**
* 课程名称
*/
private String courseName;
/**
* 教练ID
*/
private Long coachId;
/**
* 教练姓名
*/
private String coachName;
/**
* 批次编号年月日时分秒
*/
private String batchName;
/**
* 考试开始时间
*/
private Date startTime;
/**
* 考试结束时间
*/
private Date endTime;
/**
* 科目1-科目一2-科目二3科目三4科目四
*/
private Integer subject;
/**
* 考试地址id
*/
private String addrId;
/**
* 考试地址
*/
private String addr;
/**
* 通过率
*/
private Double passRate;
/**
* 交通方式(字典school_transport_way)
*/
private String transWay;
/**
* 备注
*/
private String remark;
/**
* 图片多个英文逗号隔开
*/
private String images;
/**
* 学生电话
*/
private String userMobile;
/**
* 本科目累计训练时长
*/
private Double trainTime;
/**
* 考试类型
*/
private String courseType;
/**
* 进度id
*/
private String processId;
/**
* 用户学员ID
*/
private Long userId;
/**
* 用户学员姓名
*/
private String userName;
/**
* 考试次数第一次考试为1第二次为2...
*/
private Integer examNum;
/**
* 当前状态0-未开始;1-训练中2-已完成
*/
private String status;
/**
* 考试状态0未通过1已通过;9已送考null未送考
*/
private String examStatus;
/**
* 考试分数
*/
private Double examScore;
/**
* 批次表考试分数
*/
private Double fraction;
/**
* 考试时间
*/
private Date examTime;
/**
* 租户ID
*/
private Long tenantId;
}

View File

@ -0,0 +1,16 @@
package cn.iocoder.yudao.module.jx.mapper;
import cn.iocoder.yudao.module.exam.vo.ExamBatchItemNewVO;
import cn.iocoder.yudao.module.jx.domain.DriveSchoolDeduct;
import cn.iocoder.yudao.module.jx.domain.StudentScoreInput;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface StudentScoreInputMapper{
ExamBatchItemNewVO selectBatch(@Param("entity") StudentScoreInput studentScoreInput);
}

View File

@ -0,0 +1,14 @@
package cn.iocoder.yudao.module.jx.service;
import cn.iocoder.yudao.module.course.vo.ProcessVO;
import cn.iocoder.yudao.module.jx.domain.StudentScoreInput;
public interface StudentScoreInputService {
/**
* 录入学员成绩
*/
void scoreInput(StudentScoreInput studentScoreInput);
void scoreEdit(StudentScoreInput studentScoreInput);
}

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.jx.service.impl;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.jx.domain.DriveSchoolGuide;
import cn.iocoder.yudao.module.jx.mapper.DriveSchoolGuideMapper;
import cn.iocoder.yudao.module.jx.service.DriveSchoolGuideService;
@ -27,11 +28,13 @@ public class DriveSchoolGuideServiceImpl extends ServiceImpl<DriveSchoolGuideMap
@Override
@TenantIgnore
public List<DriveSchoolGuide> listByTenantId(String tenantId) {
LambdaQueryWrapper<DriveSchoolGuide> queryWrapper = new LambdaQueryWrapper<>();
if (StringUtils.isNotBlank(tenantId)) {
queryWrapper.eq(DriveSchoolGuide::getTenantId, tenantId);
queryWrapper.eq(DriveSchoolGuide::getTenantId, tenantId).eq(DriveSchoolGuide::getDeleted, 0);
return this.list(queryWrapper);
}
return this.list(queryWrapper);
return null;
}
}

View File

@ -0,0 +1,177 @@
package cn.iocoder.yudao.module.jx.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.base.service.DlDriveSchoolStudentService;
import cn.iocoder.yudao.module.course.entity.Process;
import cn.iocoder.yudao.module.course.entity.SchoolCourseOrder;
import cn.iocoder.yudao.module.course.service.ProcessService;
import cn.iocoder.yudao.module.course.vo.ProcessVO;
import cn.iocoder.yudao.module.exam.entity.ExamBatch;
import cn.iocoder.yudao.module.exam.entity.ExamBatchItem;
import cn.iocoder.yudao.module.exam.service.ExamBatchItemService;
import cn.iocoder.yudao.module.exam.service.ExamBatchService;
import cn.iocoder.yudao.module.exam.service.impl.ExamBatchItemServiceImpl;
import cn.iocoder.yudao.module.exam.vo.ExamBatchItemNewVO;
import cn.iocoder.yudao.module.jx.domain.StudentScoreInput;
import cn.iocoder.yudao.module.jx.mapper.StudentScoreInputMapper;
import cn.iocoder.yudao.module.jx.service.StudentScoreInputService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class StudentScoreInputServiceImpl implements StudentScoreInputService {
@Autowired
private ProcessService processService;
@Autowired
private ExamBatchService examBatchService;
@Autowired
private ExamBatchItemService examBatchItemService;
@Autowired
private DlDriveSchoolStudentService dlDriveSchoolStudentService;
@Autowired
private ExamBatchItemServiceImpl examBatchItemServiceImpl;
@Autowired
private StudentScoreInputMapper studentScoreInputMapper;
/**
* 录入学员成绩
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void scoreInput(StudentScoreInput studentScoreInput) {
// 获取当前进度信息设置考试成绩等信息
ProcessVO processVO = BeanUtils.toBean(processService.getById(studentScoreInput.getProcessId()), ProcessVO.class);
processVO.setExamStatus(studentScoreInput.getExamStatus());
processVO.setExamScore(studentScoreInput.getExamScore());
processVO.setExamTime(studentScoreInput.getExamTime());
processVO.setExamNum(studentScoreInput.getExamNum());
processVO.setStatus(studentScoreInput.getStatus());
processVO.setImages(studentScoreInput.getImages());
processVO.setRemark(studentScoreInput.getRemark());
processService.updateById(processVO);
// 如果是科2和科3 需要创建批次信息
if(studentScoreInput.getSubject() == 2 || studentScoreInput.getSubject() == 3){
// 生成批次信息
ExamBatch examBatch = new ExamBatch();
String timestamp = DateUtil.format(DateUtil.date(), "yyyyMMddHHmmss");
examBatch.setBatchName(timestamp);
examBatch.setCourseId(studentScoreInput.getCourseId());
examBatch.setCourseName(studentScoreInput.getCourseName());
examBatch.setCoachId(studentScoreInput.getCoachId());
examBatch.setCoachName(studentScoreInput.getCoachName());
examBatch.setStartTime(studentScoreInput.getStartTime());
examBatch.setEndTime(studentScoreInput.getEndTime());
examBatch.setSubject(studentScoreInput.getSubject());
examBatch.setAddrId(studentScoreInput.getAddrId());
examBatch.setAddr(studentScoreInput.getAddr());
examBatch.setRemark(studentScoreInput.getRemark());
examBatch.setImages(studentScoreInput.getImages());
examBatch.setTransWay(studentScoreInput.getTransWay());
examBatchService.save(examBatch);
// 生成批次子表信息
ExamBatchItem examBatchItem = new ExamBatchItem();
examBatchItem.setBatchId(examBatch.getId());
examBatchItem.setUserId(studentScoreInput.getUserId());
examBatchItem.setUserName(studentScoreInput.getUserName());
examBatchItem.setFraction(studentScoreInput.getExamScore());
examBatchItem.setIfPass("1".equals(studentScoreInput.getExamStatus()));
examBatchItem.setImages(studentScoreInput.getImages());
examBatchItemService.save(examBatchItem);
// 更新批次通过率
examBatchItemServiceImpl.updateBatchPassRate(examBatch.getId());
}
// 修改下一课程状态
this.updateNextSubjectStatus(studentScoreInput);
}
/**
* 更新下一个科目的状态
*/
public void updateNextSubjectStatus(StudentScoreInput studentScoreInput) {
Process process = processService.getById(studentScoreInput.getProcessId());
// 通过考试
if(studentScoreInput.getExamStatus().equals("1")){
if(process.getSubject() == 4){
dlDriveSchoolStudentService.adminUpdateStudentPassAndGradTime(studentScoreInput.getExamTime(), null, studentScoreInput.getUserId(), studentScoreInput.getCourseId(), studentScoreInput.getTenantId());
} else if (process.getSubject() == 3) {
processService.update(Wrappers.lambdaUpdate(Process.class)
.eq(Process::getCourseId, studentScoreInput.getCourseId())
.eq(Process::getUserId, studentScoreInput.getUserId())
.eq(Process::getCoachId, studentScoreInput.getCoachId())
.eq(Process::getSubject, 4)
.set(Process::getStatus, 1));
dlDriveSchoolStudentService.adminUpdateStudentPassAndGradTime(null,studentScoreInput.getExamTime(), studentScoreInput.getUserId(), studentScoreInput.getCourseId(), studentScoreInput.getTenantId());
} else if (process.getSubject() == 2) {
processService.update(Wrappers.lambdaUpdate(Process.class)
.eq(Process::getCourseId, studentScoreInput.getCourseId())
.eq(Process::getUserId, studentScoreInput.getUserId())
.eq(Process::getCoachId, studentScoreInput.getCoachId())
.eq(Process::getSubject, 3)
.ne(Process::getStatus, 2)
.set(Process::getStatus, 1));
} else if (process.getSubject() == 1) {
processService.update(Wrappers.lambdaUpdate(Process.class)
.eq(Process::getCourseId, studentScoreInput.getCourseId())
.eq(Process::getUserId, studentScoreInput.getUserId())
.eq(Process::getCoachId, studentScoreInput.getCoachId())
.eq(Process::getSubject, 2)
.set(Process::getStatus, 1));
}
} else {
process.setStatus("1");
processService.updateById(process);
}
}
/**
* 修改学员成绩
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void scoreEdit(StudentScoreInput studentScoreInput) {
// 获取当前进度信息设置考试成绩等信息
ProcessVO processVO = BeanUtils.toBean(processService.getById(studentScoreInput.getProcessId()), ProcessVO.class);
processVO.setExamStatus(studentScoreInput.getExamStatus());
processVO.setExamScore(studentScoreInput.getExamScore());
processVO.setExamTime(studentScoreInput.getExamTime());
processVO.setExamNum(studentScoreInput.getExamNum());
processVO.setStatus(studentScoreInput.getStatus());
processVO.setImages(studentScoreInput.getImages());
processVO.setRemark(studentScoreInput.getRemark());
processService.updateById(processVO);
// 如果是科2和科3 需要查询批次信息,修改对应批次子表的信息以及批次的通过率
if(studentScoreInput.getSubject() == 3 || studentScoreInput.getSubject() == 2){
ExamBatchItemNewVO examBatchItemNewVOS = studentScoreInputMapper.selectBatch(studentScoreInput);
if(examBatchItemNewVOS.getBatchId() != null && examBatchItemNewVOS.getBatchItemId()!= null){
examBatchItemService.update(Wrappers.lambdaUpdate(ExamBatchItem.class)
.eq(ExamBatchItem::getId, examBatchItemNewVOS.getBatchItemId())
.eq(ExamBatchItem::getUserId, studentScoreInput.getUserId())
.set(ExamBatchItem::getFraction, studentScoreInput.getExamScore())
.set(ExamBatchItem::getIfPass, "1".equals(studentScoreInput.getExamStatus()))
.set(ExamBatchItem::getImages, studentScoreInput.getImages()));
examBatchItemServiceImpl.updateBatchPassRateNew(examBatchItemNewVOS.getBatchId());
}
}
}
}

View File

@ -20,6 +20,7 @@
main.deleted = 0
<if test="entity.name != null and entity.name != ''">and main.name like concat('%', #{entity.name}, '%')</if>
</where>
GROUP BY main.user_id
order by main.create_time desc
</select>
<select id="selectCanExamStudentList"
@ -87,6 +88,9 @@
<if test="entity.endTime!=null and entity.endTime!=''">
AND dsco.create_time &lt;= #{entity.endTime}
</if>
<if test="entity.source!=null and entity.source!=''">
AND main.source = #{entity.source}
</if>
GROUP BY
main.id
<choose>
@ -263,7 +267,8 @@
c.user_id AS userId,
COUNT(DISTINCT s.user_id) AS totalNum,
COUNT(DISTINCT CASE WHEN o.course_type = 'C1' THEN o.user_id END) AS c1Num,
COUNT(DISTINCT CASE WHEN o.course_type = 'C2' THEN o.user_id END) AS c2Num
COUNT(DISTINCT CASE WHEN o.course_type = 'C2' THEN o.user_id END) AS c2Num,
COUNT(DISTINCT o.user_id) AS timeTotal
FROM
drive_school_coach c
LEFT JOIN drive_school_student s ON c.user_id = s.source_user_id AND s.deleted=0

View File

@ -42,9 +42,15 @@
AND dsp.course_id = #{courseId}
AND (( dsp.`status` = '2' AND dsp.exam_status = '1' ) OR dsp.`status` = '1' )
</select>
<select id="pageProcess" resultType="cn.iocoder.yudao.module.course.vo.ProcessVO">
SELECT
dsp.* FROM drive_school_process dsp
dsp.*,
dss.id_card AS studentIdCard,
sysu.nickname AS updateName
FROM drive_school_process dsp
LEFT JOIN drive_school_student dss ON dss.user_id = dsp.user_id
LEFT JOIN system_users sysu on sysu.id = dsp.updater
<where>
dsp.deleted = 0
<if test="entity.coachName != null and entity.coachName != '' "> and dsp.coach_name like concat('%', #{entity.coachName}, '%')</if>
@ -52,14 +58,49 @@
<if test="entity.courseName != null and entity.courseName != '' "> and dsp.name like concat('%', #{entity.courseName}, '%')</if>
<if test="entity.userId != null "> and dsp.user_id = #{entity.userId}</if>
<if test="entity.courseId != null and entity.courseId != '' "> and dsp.course_id = #{entity.courseId}</if>
<if test="entity.studentIdCard != null and entity.studentIdCard != '' "> AND RIGHT(dss.id_card, 4) = RIGHT(#{entity.studentIdCard}, 4) </if>
</where>
ORDER BY
(CASE
WHEN exam_status = '1' AND finance_pass IS NULL THEN 1 -- 优先级最高
WHEN exam_status = '9' THEN 2
WHEN status = '1' THEN 2
WHEN dsp.exam_status = '1' AND dsp.finance_pass IS NULL THEN 1 -- 优先级最高
WHEN dsp.exam_status = '9' THEN 2
WHEN dsp.status = '1' THEN 2
ELSE 4
END),
create_time DESC; -- 再按创建时间降序
dsp.create_time DESC; -- 再按创建时间降序
</select>
<select id="getProcessList" resultType="cn.iocoder.yudao.module.course.entity.Process">
SELECT
*
FROM
drive_school_process
WHERE
user_id = #{userId}
AND deleted = 0
<if test="courseId!= null and courseId!= '' ">
AND course_id = #{courseId}
</if>
</select>
<select id="getProcessAndBatch" resultType="cn.iocoder.yudao.module.course.vo.ProcessAndExamBatchVO">
SELECT
dseb.start_time AS startTime,
dseb.end_time AS endTime,
dseb.addr_id AS addrId,
dseb.addr AS addr,
dseb.trans_way AS transWay,
dseb.creator AS creator,
dseb.id AS batchId,
dseb.updater AS updater,
dsebi.id AS batchItemId
from drive_school_exam_batch dseb
left join drive_school_exam_batch_item dsebi ON dseb.id = dsebi.batch_id
WHERE dseb.course_id = #{courseId}
AND dseb.coach_id = #{coachId}
AND dseb.subject = #{subject}
AND dsebi.fraction = #{fraction}
AND dsebi.user_id = #{userId}
ORDER BY dseb.update_time DESC LIMIT 1
</select>
</mapper>

View File

@ -80,4 +80,16 @@
</if>
</select>
<select id="getOrderInfo" resultType="cn.iocoder.yudao.module.course.vo.SchoolCourseOrderVO">
SELECT *
FROM drive_school_course_order
WHERE user_id = #{userId}
AND payment_status IN (2, 3, 4, 5)
AND if_end = 0
AND if_assignment_coach = 1
AND deleted = 0
ORDER BY create_time DESC
LIMIT 1
</select>
</mapper>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.jx.mapper.StudentScoreInputMapper">
<select id="selectBatch" parameterType="cn.iocoder.yudao.module.jx.domain.StudentScoreInput" resultType="cn.iocoder.yudao.module.exam.vo.ExamBatchItemNewVO">
SELECT dseb.id AS batchId, dsebi.id AS batchItemId from drive_school_exam_batch dseb
left join drive_school_exam_batch_item dsebi ON dseb.id = dsebi.batch_id
WHERE dseb.course_id = #{entity.courseId}
AND dseb.coach_id = #{entity.coachId}
AND dseb.subject = #{entity.subject}
AND dsebi.fraction = #{entity.fraction}
AND dsebi.user_id = #{entity.userId}
ORDER BY dseb.update_time DESC
LIMIT 1;
</select>
</mapper>

View File

@ -195,4 +195,4 @@ justauth:
cache:
type: REDIS
prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::
timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟
timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟