forked from liweijie/education
1、正课与学期关系关联;
2、天假删除保护; 3、教学任务计划增加了「结束发布」。已发布或库里的「已发布」都可以结束;结束后写入结束时间,任务书和班次课程任务只读 4、班次学期操作内容调整修改;
This commit is contained in:
+43
@@ -0,0 +1,43 @@
|
||||
package com.roomroot.web.controller.jwgl;
|
||||
|
||||
import com.roomroot.jwgl.dto.calendar.ClassCalendarApplyDTO;
|
||||
import com.roomroot.jwgl.dto.calendar.ClassCalendarEventDTO;
|
||||
import com.roomroot.jwgl.service.ClassEventCalendarService;
|
||||
import com.roomroot.jwgl.unit.Result;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 班历(假期表)。与课程任务接口 /classCalendar 分开。
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/class-calendar")
|
||||
public class ClassEventCalendarController {
|
||||
|
||||
@Resource
|
||||
private ClassEventCalendarService classEventCalendarService;
|
||||
|
||||
@GetMapping("/list")
|
||||
public Result<List<ClassCalendarEventDTO>> list(@RequestParam("xydxqbh") String xydxqbh) {
|
||||
return Result.success(classEventCalendarService.listOrInherit(xydxqbh));
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
public Result<Void> update(@RequestBody ClassCalendarEventDTO event) {
|
||||
classEventCalendarService.update(event);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@PostMapping("/apply")
|
||||
public Result<Integer> apply(@RequestBody ClassCalendarApplyDTO body) {
|
||||
return Result.success(classEventCalendarService.apply(
|
||||
body.getSourceXydxqbh(), body.getTargetBhList(), body.getEventBhList()));
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -344,8 +344,9 @@ public class ElectiveController {
|
||||
public Result<SemesterInitVO> semesterInit(
|
||||
@RequestParam("xydbh") String xydbh,
|
||||
@RequestParam(required = false) String presetKxrq,
|
||||
@RequestParam(required = false) String presetJsrq) {
|
||||
return Result.success(electiveService.getSemesterInit(xydbh, presetKxrq, presetJsrq));
|
||||
@RequestParam(required = false) String presetJsrq,
|
||||
@RequestParam(required = false) Integer xqdc) {
|
||||
return Result.success(electiveService.getSemesterInit(xydbh, presetKxrq, presetJsrq, xqdc));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+9
@@ -545,6 +545,15 @@ public class JYSController {
|
||||
return Result.success("已发布,同步教研室任务书 " + count + " 份", count);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束发布。结束后任务书和课程任务只读。
|
||||
*/
|
||||
@PostMapping("/task/endPublish")
|
||||
public Result<Void> endPublishTask(@RequestParam("bh") String bh) {
|
||||
teachingTaskManageService.endPublish(bh);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 教研室任务书列表。
|
||||
*/
|
||||
|
||||
+78
@@ -401,6 +401,84 @@ public class StudentRecordsController {
|
||||
return Result.success(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* 未毕业、且该年度学期尚未建立班次学期信息的班次。
|
||||
*/
|
||||
@GetMapping("/semester/creatableClasses")
|
||||
public Result<List<XYDB>> creatableClasses(@RequestParam("nd") Integer nd,
|
||||
@RequestParam("xqdc") Integer xqdc) {
|
||||
return Result.success(classSemesterService.listCreatableClasses(nd, xqdc));
|
||||
}
|
||||
|
||||
/**
|
||||
* 按学校学期带出开学/结束日期。
|
||||
*/
|
||||
@GetMapping("/semester/presetDates")
|
||||
public Result<Map<String, String>> presetDates(@RequestParam("nd") Integer nd,
|
||||
@RequestParam("xqdc") Integer xqdc) {
|
||||
return Result.success(classSemesterService.presetDates(nd, xqdc));
|
||||
}
|
||||
|
||||
/**
|
||||
* 为符合条件的全部班次创建班次学期,返回实际创建数。
|
||||
*/
|
||||
@PostMapping("/semester/batchCreate")
|
||||
public Result<Integer> batchCreate(@RequestBody Map<String, Object> params) {
|
||||
Integer nd = asInt(params.get("nd"));
|
||||
Integer xqdc = asInt(params.get("xqdc"));
|
||||
String kxrq = asText(params.get("kxrq"));
|
||||
String jsrq = asText(params.get("jsrq"));
|
||||
int count = classSemesterService.batchCreateEligible(
|
||||
nd,
|
||||
xqdc,
|
||||
kxrq == null ? null : java.time.LocalDate.parse(kxrq),
|
||||
jsrq == null ? null : java.time.LocalDate.parse(jsrq));
|
||||
return Result.success(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* 学期级预设合班,只改预设编班号。
|
||||
*/
|
||||
@PostMapping("/semester/batchWaveMerge")
|
||||
public Result<Integer> batchWaveMerge(@RequestBody Map<String, Object> params) {
|
||||
return Result.success(classSemesterService.batchWaveMerge(asBhList(params)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 学期级预设拆班,所选班次各自独立成波。
|
||||
*/
|
||||
@PostMapping("/semester/batchWaveSplit")
|
||||
public Result<Integer> batchWaveSplit(@RequestBody Map<String, Object> params) {
|
||||
return Result.success(classSemesterService.batchWaveSplit(asBhList(params)));
|
||||
}
|
||||
|
||||
private Integer asInt(Object value) {
|
||||
if (value == null || "".equals(value)) {
|
||||
return null;
|
||||
}
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).intValue();
|
||||
}
|
||||
return Integer.valueOf(String.valueOf(value));
|
||||
}
|
||||
|
||||
private String asText(Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String text = String.valueOf(value).trim();
|
||||
return text.isEmpty() ? null : text;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<String> asBhList(Map<String, Object> params) {
|
||||
Object raw = params.get("bhList");
|
||||
if (!(raw instanceof List)) {
|
||||
return List.of();
|
||||
}
|
||||
return (List<String>) raw;
|
||||
}
|
||||
|
||||
// ======================== 课程成绩查询 ========================
|
||||
|
||||
/**
|
||||
|
||||
+43
@@ -159,4 +159,47 @@ public class StudentTeamTaskController {
|
||||
List<String> newBhList = studentTeamTaskService.copy(bhList, newXydbh);
|
||||
return Result.success(newBhList);
|
||||
}
|
||||
|
||||
@PostMapping("/batchAutoGenerate")
|
||||
public Result<Integer> batchAutoGenerate(@RequestBody List<String> xydxqbhList) {
|
||||
return Result.success(studentTeamTaskService.batchAutoGenerate(xydxqbhList));
|
||||
}
|
||||
|
||||
@GetMapping("/planCourses")
|
||||
public Result<List<com.roomroot.jwgl.vo.PlanCourseVO>> planCourses(
|
||||
@RequestParam("xydxqbh") String xydxqbh,
|
||||
@RequestParam(value = "otherOnly", defaultValue = "true") boolean otherOnly) {
|
||||
return Result.success(studentTeamTaskService.listPlanCourses(xydxqbh, otherOnly));
|
||||
}
|
||||
|
||||
@PostMapping("/addFromLibrary")
|
||||
public Result<Void> addFromLibrary(@RequestParam("xydxqbh") String xydxqbh,
|
||||
@RequestParam("kbh") String kbh) {
|
||||
studentTeamTaskService.addFromLibrary(xydxqbh, kbh);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@PostMapping("/addFromPlan")
|
||||
public Result<Void> addFromPlan(@RequestParam("xydxqbh") String xydxqbh,
|
||||
@RequestParam("planBh") String planBh) {
|
||||
studentTeamTaskService.addFromPlan(xydxqbh, planBh);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@PostMapping("/syncFromPlan")
|
||||
public Result<Integer> syncFromPlan(@RequestBody List<String> bhList) {
|
||||
return Result.success(studentTeamTaskService.syncFromPlan(bhList));
|
||||
}
|
||||
|
||||
@PostMapping("/batchDelete")
|
||||
public Result<Integer> batchDelete(@RequestBody List<String> bhList) {
|
||||
return Result.success(studentTeamTaskService.batchDeleteGuarded(bhList));
|
||||
}
|
||||
|
||||
@PostMapping("/paste")
|
||||
public Result<Integer> paste(@RequestBody Map<String, Object> params) {
|
||||
List<String> bhList = (List<String>) params.get("bhList");
|
||||
String targetXydxqbh = (String) params.get("targetXydxqbh");
|
||||
return Result.success(studentTeamTaskService.pasteToSemester(bhList, targetXydxqbh));
|
||||
}
|
||||
}
|
||||
+9
@@ -92,4 +92,13 @@ public class TeachingTaskController {
|
||||
int count = teachingTaskService.batchPublish(bh);
|
||||
return Result.success(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束发布。结束后教研室不能再改任务书和课程任务。
|
||||
*/
|
||||
@PostMapping("/endPublish")
|
||||
public Result<Void> endPublish(@RequestParam("bh") String bh) {
|
||||
teachingTaskService.endPublish(bh);
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.roomroot.jwgl.dto.calendar;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 把班历事件应用到其它班次。eventBhList 为空时复制整个班历。
|
||||
*/
|
||||
@Data
|
||||
public class ClassCalendarApplyDTO {
|
||||
|
||||
private String sourceXydxqbh;
|
||||
private List<String> targetBhList;
|
||||
private List<String> eventBhList;
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.roomroot.jwgl.dto.calendar;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 班历时间格。日期用 yyyy-MM-dd,便于复用校历编辑器。
|
||||
*/
|
||||
@Data
|
||||
public class ClassCalendarEventDTO {
|
||||
|
||||
private String bh;
|
||||
private Integer nd;
|
||||
private String xydbh;
|
||||
private String xydxqbh;
|
||||
private String jqsj;
|
||||
private String jqmc;
|
||||
private Boolean jc;
|
||||
private String bz;
|
||||
private Boolean kpk;
|
||||
private Boolean bzxs;
|
||||
private Boolean zdpk;
|
||||
private Boolean zk;
|
||||
private String courseClass;
|
||||
}
|
||||
@@ -1,19 +1,17 @@
|
||||
package com.roomroot.jwgl.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.roomroot.jwgl.unit.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 假期表
|
||||
* 假期表。班历时间格,不继承基类,避免写入表中不存在的审计列。
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("假期表")
|
||||
public class JQB extends BaseEntity {
|
||||
public class JQB {
|
||||
|
||||
/**
|
||||
* 编号
|
||||
@@ -21,54 +19,49 @@ public class JQB extends BaseEntity {
|
||||
@TableId(value = "编号", type = IdType.INPUT)
|
||||
private String bh;
|
||||
|
||||
/**
|
||||
* 年度
|
||||
*/
|
||||
@TableField("年度")
|
||||
private Integer nd;
|
||||
|
||||
/**
|
||||
* 学员队编号
|
||||
*/
|
||||
@TableField("学员队编号")
|
||||
private String xydbh;
|
||||
|
||||
/**
|
||||
* 假期时间
|
||||
* 假期时间,库中为整型日期 yyyyMMdd。
|
||||
*/
|
||||
@TableField("假期时间")
|
||||
private Integer jqsj;
|
||||
|
||||
/**
|
||||
* 假期名称
|
||||
*/
|
||||
@TableField("假期名称")
|
||||
private String jqmc;
|
||||
|
||||
/**
|
||||
* 加粗
|
||||
*/
|
||||
@TableField("加粗")
|
||||
private Integer jc;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@TableField("备注")
|
||||
private String bz;
|
||||
|
||||
/**
|
||||
* 可排课
|
||||
*/
|
||||
@TableField("可排课")
|
||||
private Integer kpk;
|
||||
|
||||
/**
|
||||
* 学员队学期编号
|
||||
*/
|
||||
@TableField("学员队学期编号")
|
||||
private String xydxqbh;
|
||||
|
||||
/**
|
||||
* 备注显示
|
||||
*/
|
||||
@TableField("备注显示")
|
||||
private Integer bzxs;
|
||||
|
||||
/**
|
||||
* 自动排课
|
||||
*/
|
||||
@TableField("自动排课")
|
||||
private Integer zdpk;
|
||||
|
||||
/**
|
||||
* 正课。与自动排课分离。
|
||||
*/
|
||||
@TableField("正课")
|
||||
private Integer zk;
|
||||
|
||||
/**
|
||||
* 节次,与校历一致,如 1-2、3-4。
|
||||
*/
|
||||
@TableField("节次")
|
||||
private String courseClass;
|
||||
|
||||
}
|
||||
|
||||
@@ -70,6 +70,12 @@ public class XQXLB extends BaseEntity {
|
||||
@TableField("自动排课")
|
||||
private Boolean zdpk;
|
||||
|
||||
/**
|
||||
* 正课。与自动排课分离:默认星期一至星期五 1-6 节,周末补课也可标为正课。
|
||||
*/
|
||||
@TableField("正课")
|
||||
private Boolean zk;
|
||||
|
||||
/**
|
||||
* 节次
|
||||
*/
|
||||
|
||||
@@ -144,4 +144,28 @@ public class XYDNDXQJBXXB extends BaseEntity {
|
||||
@TableField("分析报告文档3编号")
|
||||
private String fxbgwd3bh;
|
||||
|
||||
/**
|
||||
* 总课程数。列表聚合学员队任务表,不落库。
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Integer zkcs;
|
||||
|
||||
/**
|
||||
* 班次名称。列表联查学员队表,不落库。
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String xydmc;
|
||||
|
||||
/**
|
||||
* 专用教室名称。列表联查教室表,不落库。
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String zyjsmc;
|
||||
|
||||
/**
|
||||
* 列表按预设编班号排序。仅查询参数,不落库。
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Integer sortWave;
|
||||
|
||||
}
|
||||
|
||||
+37
-9
@@ -24,6 +24,9 @@
|
||||
<result column="分析报告文档2编号" property="fxbgwd2bh" />
|
||||
<result column="分析报告文档3编号" property="fxbgwd3bh" />
|
||||
<result column="DEL_FLAG" property="delFlag" />
|
||||
<result column="zkcs" property="zkcs" />
|
||||
<result column="xydmc" property="xydmc" />
|
||||
<result column="zyjsmc" property="zyjsmc" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
@@ -32,25 +35,50 @@
|
||||
分析报告生成时间, 分析报告文档1编号, 分析报告文档2编号, 分析报告文档3编号, DEL_FLAG
|
||||
</sql>
|
||||
|
||||
<sql id="List_Select">
|
||||
SELECT a.编号, a.年度, a.学员队编号, a.开学日期, a.结束日期, a.学期第次, a.专用教室编号, a.教学任务编号,
|
||||
a.变动时间, a.备注, a.序号标识, a.预设编班号, a.节次类别, a.系统模式, a.开放教员排课, a.JSONZD,
|
||||
a.分析报告生成时间, a.分析报告文档1编号, a.分析报告文档2编号, a.分析报告文档3编号, a.DEL_FLAG,
|
||||
(SELECT COUNT(*) FROM 学员队任务表 t
|
||||
WHERE t.学员队学期编号 = a.编号 AND NVL(t.DEL_FLAG, 0) = 0) AS zkcs,
|
||||
b.学员队名称 AS xydmc,
|
||||
NVL(r1.教室名称, r2.教室名称) AS zyjsmc
|
||||
FROM 学员队年度学期基本信息表 a
|
||||
LEFT JOIN 学员队表 b ON a.学员队编号 = b.学员队编号
|
||||
LEFT JOIN 教室表 r1 ON a.专用教室编号 = r1.ID
|
||||
LEFT JOIN 教室表 r2 ON a.专用教室编号 = r2.教室编号 AND r1.ID IS NULL
|
||||
</sql>
|
||||
|
||||
<select id="selectPageList" resultMap="BaseResultMap">
|
||||
SELECT <include refid="Base_Column_List" />
|
||||
FROM 学员队年度学期基本信息表
|
||||
<include refid="List_Select" />
|
||||
<where>
|
||||
<if test="xydndxqjbxxb.delFlag != null">
|
||||
AND DEL_FLAG = #{xydndxqjbxxb.delFlag}
|
||||
AND a.DEL_FLAG = #{xydndxqjbxxb.delFlag}
|
||||
</if>
|
||||
<if test="xydndxqjbxxb.xydbh != null and xydndxqjbxxb.xydbh != ''">
|
||||
AND 学员队编号 LIKE CONCAT('%', #{xydndxqjbxxb.xydbh}, '%')
|
||||
AND a.学员队编号 LIKE CONCAT('%', #{xydndxqjbxxb.xydbh}, '%')
|
||||
</if>
|
||||
<if test="xydndxqjbxxb.nd != null">
|
||||
AND a.年度 = #{xydndxqjbxxb.nd}
|
||||
</if>
|
||||
<if test="xydndxqjbxxb.xqdc != null">
|
||||
AND a.学期第次 = #{xydndxqjbxxb.xqdc}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY 编号
|
||||
<choose>
|
||||
<when test="xydndxqjbxxb.sortWave != null and xydndxqjbxxb.sortWave == 1">
|
||||
ORDER BY NVL(a.预设编班号, 0), a.学员队编号
|
||||
</when>
|
||||
<otherwise>
|
||||
ORDER BY a.年度 DESC, a.学期第次, a.学员队编号
|
||||
</otherwise>
|
||||
</choose>
|
||||
</select>
|
||||
|
||||
<select id="selectAllValid" resultMap="BaseResultMap">
|
||||
SELECT <include refid="Base_Column_List" />
|
||||
FROM 学员队年度学期基本信息表
|
||||
WHERE DEL_FLAG = '0'
|
||||
ORDER BY 编号
|
||||
<include refid="List_Select" />
|
||||
WHERE a.DEL_FLAG = '0'
|
||||
ORDER BY NVL(a.预设编班号, 0), a.学员队编号
|
||||
</select>
|
||||
|
||||
<select id="selectByBcAndNdAndXqdc" resultMap="BaseResultMap">
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.roomroot.jwgl.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.roomroot.jwgl.entity.JQB;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 假期表(班历时间格)
|
||||
*/
|
||||
@Mapper
|
||||
public interface JQBMapper extends BaseMapper<JQB> {
|
||||
}
|
||||
@@ -25,4 +25,9 @@ public interface XYDBMapper extends BaseMapper<XYDB> {
|
||||
* @return 学员队列表
|
||||
*/
|
||||
java.util.List<XYDB> selectByDateRange(@Param("startTime") String startTime, @Param("endTime") String endTime);
|
||||
|
||||
/**
|
||||
* 未毕业、且指定年度学期尚未建立班次学期信息的班次。
|
||||
*/
|
||||
java.util.List<XYDB> selectCreatableClasses(@Param("nd") Integer nd, @Param("xqdc") Integer xqdc);
|
||||
}
|
||||
|
||||
@@ -161,4 +161,19 @@
|
||||
ORDER BY "序号"
|
||||
</select>
|
||||
|
||||
<!-- 未毕业,且该年度学期尚未建立班次学期 -->
|
||||
<select id="selectCreatableClasses" resultMap="BaseResultMap">
|
||||
SELECT <include refid="Base_Column_List" />
|
||||
FROM "学员队表" t
|
||||
WHERE (t."毕业日期" IS NULL OR t."毕业日期" > SYSDATE)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM "学员队年度学期基本信息表" s
|
||||
WHERE s."学员队编号" = t."学员队编号"
|
||||
AND s."年度" = #{nd}
|
||||
AND s."学期第次" = #{xqdc}
|
||||
AND NVL(s.DEL_FLAG, 0) = 0
|
||||
)
|
||||
ORDER BY t."序号", t."学员队编号"
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.dto.calendar.ClassCalendarEventDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 班历(假期表)服务。
|
||||
*/
|
||||
public interface ClassEventCalendarService {
|
||||
|
||||
/**
|
||||
* 按学员队学期编号查询班历。没有记录时按校历复制一份。
|
||||
*/
|
||||
List<ClassCalendarEventDTO> listOrInherit(String xydxqbh);
|
||||
|
||||
/**
|
||||
* 更新一个时间格。班次日期范围外的格子拒绝保存。
|
||||
*/
|
||||
void update(ClassCalendarEventDTO event);
|
||||
|
||||
/**
|
||||
* 把选定或整个班历覆盖到其它班次的对应时间格。不改课程任务。
|
||||
*/
|
||||
int apply(String sourceXydxqbh, List<String> targetBhList, List<String> eventBhList);
|
||||
}
|
||||
+28
@@ -1,10 +1,13 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
import com.roomroot.jwgl.entity.XYDNDXQJBXXB;
|
||||
import com.roomroot.jwgl.entity.XYDB;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 班次学期服务接口
|
||||
@@ -113,4 +116,29 @@ public interface ClassSemesterService {
|
||||
* @return 更新数量
|
||||
*/
|
||||
int batchUpdateDateRange(List<String> bhList, String xqkssj, String xqjssj);
|
||||
|
||||
/**
|
||||
* 未毕业且指定年度学期尚未建班次学期的班次。
|
||||
*/
|
||||
List<XYDB> listCreatableClasses(Integer nd, Integer xqdc);
|
||||
|
||||
/**
|
||||
* 按学校学期表带出开学/结束日期。
|
||||
*/
|
||||
Map<String, String> presetDates(Integer nd, Integer xqdc);
|
||||
|
||||
/**
|
||||
* 为符合条件的全部班次创建班次学期,返回实际创建数。
|
||||
*/
|
||||
int batchCreateEligible(Integer nd, Integer xqdc, LocalDate kxrq, LocalDate jsrq);
|
||||
|
||||
/**
|
||||
* 学期级预设合班:所选班次写入同一预设编班号。
|
||||
*/
|
||||
int batchWaveMerge(List<String> bhList);
|
||||
|
||||
/**
|
||||
* 学期级预设拆班:所选班次各自独立成波。
|
||||
*/
|
||||
int batchWaveSplit(List<String> bhList);
|
||||
}
|
||||
@@ -111,6 +111,11 @@ public interface ElectiveService {
|
||||
*/
|
||||
SemesterInitVO getSemesterInit(String xydbh, String presetKxrq, String presetJsrq);
|
||||
|
||||
/**
|
||||
* 同 {@link #getSemesterInit(String, String, String)}。指定学期第次时按该次取上学期专用教室,学制半年以内仍强制第1学期。
|
||||
*/
|
||||
SemesterInitVO getSemesterInit(String xydbh, String presetKxrq, String presetJsrq, Integer xqdc);
|
||||
|
||||
/**
|
||||
* 创建班次学期信息(教学班次学期信息设置窗口 - 确定按钮)
|
||||
* <p>
|
||||
|
||||
+36
@@ -2,6 +2,7 @@ package com.roomroot.jwgl.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.XYDRWB;
|
||||
import com.roomroot.jwgl.vo.PlanCourseVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -114,4 +115,39 @@ public interface StudentTeamTaskService {
|
||||
* @return 新生成的编号集合
|
||||
*/
|
||||
List<String> copy(List<String> bhList, String newXydbh);
|
||||
|
||||
/**
|
||||
* 按班次学期批量生成必修,已有课程不重复。
|
||||
*/
|
||||
int batchAutoGenerate(List<String> xydxqbhList);
|
||||
|
||||
/**
|
||||
* 本班人培课程。otherOnly 为 true 时只列其它学期,并标是否已加入当前学期。
|
||||
*/
|
||||
List<PlanCourseVO> listPlanCourses(String xydxqbh, boolean otherOnly);
|
||||
|
||||
/**
|
||||
* 从课程库加入当前学期任务,带出课程库默认学时和类型。
|
||||
*/
|
||||
void addFromLibrary(String xydxqbh, String kbh);
|
||||
|
||||
/**
|
||||
* 把人培中的一门课加入当前学期任务。
|
||||
*/
|
||||
void addFromPlan(String xydxqbh, String planBh);
|
||||
|
||||
/**
|
||||
* 按人培覆盖所选任务的学时、类型等字段。
|
||||
*/
|
||||
int syncFromPlan(List<String> bhList);
|
||||
|
||||
/**
|
||||
* 批量删除。已发布教学任务或已排课的行拒绝删除。
|
||||
*/
|
||||
int batchDeleteGuarded(List<String> bhList);
|
||||
|
||||
/**
|
||||
* 复制任务到另一个班次学期,两条任务独立。
|
||||
*/
|
||||
int pasteToSemester(List<String> bhList, String targetXydxqbh);
|
||||
}
|
||||
+5
@@ -29,6 +29,11 @@ public interface TeachingTaskManageService {
|
||||
|
||||
int publish(String bh);
|
||||
|
||||
/**
|
||||
* 结束发布。结束后任务书和课程任务只读。
|
||||
*/
|
||||
void endPublish(String bh);
|
||||
|
||||
List<TeachingOfficeBookVO> listOfficeBooks(String jxrwbh);
|
||||
|
||||
List<TeachingOfficeBookCourseVO> listOfficeBookCourses(String jxrwbh, String jysdh);
|
||||
|
||||
@@ -71,4 +71,11 @@ public interface TeachingTaskService {
|
||||
* @return 更新数量
|
||||
*/
|
||||
int batchPublish(String bh);
|
||||
|
||||
/**
|
||||
* 结束发布。结束后教研室不能再改任务书和课程任务。
|
||||
*
|
||||
* @param bh 教学任务编号
|
||||
*/
|
||||
void endPublish(String bh);
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.roomroot.jwgl.service;
|
||||
|
||||
/**
|
||||
* 教学任务结束后,禁止再改任务书和班次课程任务。
|
||||
*/
|
||||
public interface TeachingTaskWriteGuard {
|
||||
|
||||
void assertTaskWritable(String jxrwbh);
|
||||
|
||||
void assertCourseTaskWritable(String xydxqbh);
|
||||
}
|
||||
+303
@@ -0,0 +1,303 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.roomroot.common.exception.ServiceException;
|
||||
import com.roomroot.jwgl.dto.calendar.ClassCalendarEventDTO;
|
||||
import com.roomroot.jwgl.entity.JQB;
|
||||
import com.roomroot.jwgl.entity.XQXLB;
|
||||
import com.roomroot.jwgl.entity.XYDNDXQJBXXB;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterMapper;
|
||||
import com.roomroot.jwgl.mapper.JQBMapper;
|
||||
import com.roomroot.jwgl.mapper.SemesterCalendarMapper;
|
||||
import com.roomroot.jwgl.service.ClassEventCalendarService;
|
||||
import com.roomroot.jwgl.service.TeachingTaskWriteGuard;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.BAD_REQUEST;
|
||||
|
||||
/**
|
||||
* 班历读写假期表。没有记录时从学期校历复制,不写课程任务。
|
||||
*/
|
||||
@Service
|
||||
public class ClassEventCalendarServiceImpl implements ClassEventCalendarService {
|
||||
|
||||
private static final DateTimeFormatter DAY = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
private static final DateTimeFormatter COMPACT = DateTimeFormatter.ofPattern("yyyyMMdd");
|
||||
private static final List<String> PERIODS = Arrays.asList("1-2", "3-4", "5-6", "7-8", "9-10", "11-12");
|
||||
|
||||
@Resource
|
||||
private JQBMapper jqbMapper;
|
||||
|
||||
@Resource
|
||||
private ClassSemesterMapper classSemesterMapper;
|
||||
|
||||
@Resource
|
||||
private SemesterCalendarMapper semesterCalendarMapper;
|
||||
|
||||
@Resource
|
||||
private TeachingTaskWriteGuard teachingTaskWriteGuard;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public List<ClassCalendarEventDTO> listOrInherit(String xydxqbh) {
|
||||
XYDNDXQJBXXB semester = requireSemester(xydxqbh);
|
||||
List<JQB> rows = listRows(xydxqbh);
|
||||
if (rows.isEmpty()) {
|
||||
inherit(semester);
|
||||
rows = listRows(xydxqbh);
|
||||
}
|
||||
List<ClassCalendarEventDTO> result = new ArrayList<>();
|
||||
for (JQB row : rows) {
|
||||
result.add(toDto(row));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(ClassCalendarEventDTO event) {
|
||||
if (event == null || event.getBh() == null || event.getBh().isEmpty()) {
|
||||
throw new ServiceException("班历编号不能为空", BAD_REQUEST);
|
||||
}
|
||||
JQB existing = jqbMapper.selectById(event.getBh());
|
||||
if (existing == null) {
|
||||
throw new ServiceException("班历时间格不存在", BAD_REQUEST);
|
||||
}
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(existing.getXydxqbh());
|
||||
XYDNDXQJBXXB semester = requireSemester(existing.getXydxqbh());
|
||||
LocalDate day = parseDay(event.getJqsj() == null ? formatDay(existing.getJqsj()) : event.getJqsj());
|
||||
assertInRange(semester, day);
|
||||
existing.setJqmc(event.getJqmc() == null ? "" : event.getJqmc());
|
||||
existing.setBz(event.getBz());
|
||||
existing.setJc(flag(event.getJc()));
|
||||
existing.setKpk(flag(event.getKpk()));
|
||||
existing.setBzxs(flag(event.getBzxs()));
|
||||
existing.setZdpk(flag(event.getZdpk()));
|
||||
existing.setZk(flag(event.getZk()));
|
||||
if (event.getCourseClass() != null && !event.getCourseClass().isEmpty()) {
|
||||
existing.setCourseClass(event.getCourseClass());
|
||||
}
|
||||
existing.setJqsj(Integer.valueOf(day.format(COMPACT)));
|
||||
jqbMapper.updateById(existing);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int apply(String sourceXydxqbh, List<String> targetBhList, List<String> eventBhList) {
|
||||
if (sourceXydxqbh == null || sourceXydxqbh.isEmpty() || CollectionUtils.isEmpty(targetBhList)) {
|
||||
throw new ServiceException("请选择源班次和目标班次", BAD_REQUEST);
|
||||
}
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(sourceXydxqbh);
|
||||
List<JQB> sourceRows = listRows(sourceXydxqbh);
|
||||
if (sourceRows.isEmpty()) {
|
||||
inherit(requireSemester(sourceXydxqbh));
|
||||
sourceRows = listRows(sourceXydxqbh);
|
||||
}
|
||||
Set<String> selected = eventBhList == null ? new HashSet<>() : new HashSet<>(eventBhList);
|
||||
List<JQB> toCopy = new ArrayList<>();
|
||||
for (JQB row : sourceRows) {
|
||||
if (selected.isEmpty() || selected.contains(row.getBh())) {
|
||||
toCopy.add(row);
|
||||
}
|
||||
}
|
||||
int count = 0;
|
||||
for (String targetBh : targetBhList) {
|
||||
if (sourceXydxqbh.equals(targetBh)) {
|
||||
continue;
|
||||
}
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(targetBh);
|
||||
XYDNDXQJBXXB target = requireSemester(targetBh);
|
||||
if (listRows(targetBh).isEmpty()) {
|
||||
inherit(target);
|
||||
}
|
||||
for (JQB source : toCopy) {
|
||||
if (overlay(target, source)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private void inherit(XYDNDXQJBXXB semester) {
|
||||
LocalDate start = semester.getKxrq();
|
||||
LocalDate end = semester.getJsrq();
|
||||
if (start == null || end == null) {
|
||||
throw new ServiceException("班次学期缺少开学或结束日期,不能生成班历", BAD_REQUEST);
|
||||
}
|
||||
List<XQXLB> schoolRows = loadSchoolRows(semester, start, end);
|
||||
if (schoolRows.isEmpty()) {
|
||||
generateEmptyGrid(semester, start, end);
|
||||
return;
|
||||
}
|
||||
for (XQXLB school : schoolRows) {
|
||||
LocalDate day = parseDay(school.getJqsj());
|
||||
if (day.isBefore(start) || day.isAfter(end)) {
|
||||
continue;
|
||||
}
|
||||
insertCell(semester, day, school.getCourseClass(), school.getJqmc(),
|
||||
flag(school.getJc()), flag(school.getKpk()), flag(school.getBzxs()),
|
||||
flag(school.getZdpk()), flag(school.getZk()), school.getBz());
|
||||
}
|
||||
}
|
||||
|
||||
private List<XQXLB> loadSchoolRows(XYDNDXQJBXXB semester, LocalDate start, LocalDate end) {
|
||||
Integer schoolNd = semester.getNd() == null || semester.getXqdc() == null
|
||||
? null : semester.getNd() * 100 + semester.getXqdc();
|
||||
List<XQXLB> rows = querySchool(schoolNd, start, end);
|
||||
if (!rows.isEmpty() || semester.getNd() == null) {
|
||||
return rows;
|
||||
}
|
||||
return querySchool(semester.getNd(), start, end);
|
||||
}
|
||||
|
||||
private List<XQXLB> querySchool(Integer nd, LocalDate start, LocalDate end) {
|
||||
if (nd == null) {
|
||||
return List.of();
|
||||
}
|
||||
return semesterCalendarMapper.selectList(new LambdaQueryWrapper<XQXLB>()
|
||||
.eq(XQXLB::getNd, nd)
|
||||
.ge(XQXLB::getJqsj, start.format(DAY))
|
||||
.le(XQXLB::getJqsj, end.format(DAY)));
|
||||
}
|
||||
|
||||
private void generateEmptyGrid(XYDNDXQJBXXB semester, LocalDate start, LocalDate end) {
|
||||
for (LocalDate day = start; !day.isAfter(end); day = day.plusDays(1)) {
|
||||
boolean weekdayMain = day.getDayOfWeek().getValue() <= 5;
|
||||
for (String period : PERIODS) {
|
||||
boolean mainSlot = weekdayMain && ("1-2".equals(period) || "3-4".equals(period) || "5-6".equals(period));
|
||||
insertCell(semester, day, period, "", 0, mainSlot ? 1 : 0, 0, mainSlot ? 1 : 0, mainSlot ? 1 : 0, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean overlay(XYDNDXQJBXXB target, JQB source) {
|
||||
LocalDate day = parseDay(formatDay(source.getJqsj()));
|
||||
if (target.getKxrq() != null && day.isBefore(target.getKxrq())) {
|
||||
return false;
|
||||
}
|
||||
if (target.getJsrq() != null && day.isAfter(target.getJsrq())) {
|
||||
return false;
|
||||
}
|
||||
List<JQB> matched = jqbMapper.selectList(new LambdaQueryWrapper<JQB>()
|
||||
.eq(JQB::getXydxqbh, target.getBh())
|
||||
.eq(JQB::getJqsj, source.getJqsj())
|
||||
.eq(JQB::getCourseClass, source.getCourseClass()));
|
||||
if (matched.isEmpty()) {
|
||||
insertCell(target, day, source.getCourseClass(), source.getJqmc(),
|
||||
source.getJc(), 0, source.getBzxs(), source.getZdpk(), source.getZk(), source.getBz());
|
||||
return true;
|
||||
}
|
||||
for (JQB row : matched) {
|
||||
row.setJqmc(source.getJqmc());
|
||||
row.setJc(source.getJc());
|
||||
row.setBz(source.getBz());
|
||||
row.setBzxs(source.getBzxs());
|
||||
row.setZdpk(source.getZdpk());
|
||||
row.setZk(source.getZk());
|
||||
row.setKpk(source.getKpk());
|
||||
jqbMapper.updateById(row);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void insertCell(XYDNDXQJBXXB semester, LocalDate day, String courseClass, String name,
|
||||
Integer jc, Integer kpk, Integer bzxs, Integer zdpk, Integer zk, String bz) {
|
||||
if (courseClass == null || courseClass.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
boolean outside = (semester.getKxrq() != null && day.isBefore(semester.getKxrq()))
|
||||
|| (semester.getJsrq() != null && day.isAfter(semester.getJsrq()));
|
||||
JQB row = new JQB();
|
||||
row.setBh(UuidUtil.getUUID());
|
||||
row.setNd(semester.getNd());
|
||||
row.setXydbh(semester.getXydbh());
|
||||
row.setXydxqbh(semester.getBh());
|
||||
row.setJqsj(Integer.valueOf(day.format(COMPACT)));
|
||||
row.setJqmc(name == null ? "" : name);
|
||||
row.setJc(jc == null ? 0 : jc);
|
||||
row.setBz(bz);
|
||||
row.setKpk(outside ? 0 : (kpk == null ? 0 : kpk));
|
||||
row.setBzxs(bzxs == null ? 0 : bzxs);
|
||||
row.setZdpk(zdpk == null ? 0 : zdpk);
|
||||
row.setZk(zk == null ? 0 : zk);
|
||||
row.setCourseClass(courseClass);
|
||||
jqbMapper.insert(row);
|
||||
}
|
||||
|
||||
private List<JQB> listRows(String xydxqbh) {
|
||||
return jqbMapper.selectList(new LambdaQueryWrapper<JQB>()
|
||||
.eq(JQB::getXydxqbh, xydxqbh)
|
||||
.orderByAsc(JQB::getJqsj)
|
||||
.orderByAsc(JQB::getCourseClass));
|
||||
}
|
||||
|
||||
private XYDNDXQJBXXB requireSemester(String xydxqbh) {
|
||||
XYDNDXQJBXXB semester = classSemesterMapper.selectById(xydxqbh);
|
||||
if (semester == null || Integer.valueOf(1).equals(semester.getDelFlag())) {
|
||||
throw new ServiceException("班次学期不存在", BAD_REQUEST);
|
||||
}
|
||||
return semester;
|
||||
}
|
||||
|
||||
private void assertInRange(XYDNDXQJBXXB semester, LocalDate day) {
|
||||
if (semester.getKxrq() != null && day.isBefore(semester.getKxrq())) {
|
||||
throw new ServiceException("班次日期范围外的格子不可排", BAD_REQUEST);
|
||||
}
|
||||
if (semester.getJsrq() != null && day.isAfter(semester.getJsrq())) {
|
||||
throw new ServiceException("班次日期范围外的格子不可排", BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
private ClassCalendarEventDTO toDto(JQB row) {
|
||||
ClassCalendarEventDTO dto = new ClassCalendarEventDTO();
|
||||
dto.setBh(row.getBh());
|
||||
dto.setNd(row.getNd());
|
||||
dto.setXydbh(row.getXydbh());
|
||||
dto.setXydxqbh(row.getXydxqbh());
|
||||
dto.setJqsj(formatDay(row.getJqsj()));
|
||||
dto.setJqmc(row.getJqmc());
|
||||
dto.setJc(Integer.valueOf(1).equals(row.getJc()));
|
||||
dto.setBz(row.getBz());
|
||||
dto.setKpk(Integer.valueOf(1).equals(row.getKpk()));
|
||||
dto.setBzxs(Integer.valueOf(1).equals(row.getBzxs()));
|
||||
dto.setZdpk(Integer.valueOf(1).equals(row.getZdpk()));
|
||||
dto.setZk(Integer.valueOf(1).equals(row.getZk()));
|
||||
dto.setCourseClass(row.getCourseClass());
|
||||
return dto;
|
||||
}
|
||||
|
||||
private String formatDay(Integer value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
String text = String.valueOf(value);
|
||||
if (text.length() != 8) {
|
||||
return text;
|
||||
}
|
||||
return text.substring(0, 4) + "-" + text.substring(4, 6) + "-" + text.substring(6, 8);
|
||||
}
|
||||
|
||||
private LocalDate parseDay(String value) {
|
||||
if (value == null || value.isEmpty()) {
|
||||
throw new ServiceException("班历日期不能为空", BAD_REQUEST);
|
||||
}
|
||||
String text = value.length() >= 10 ? value.substring(0, 10) : value;
|
||||
return LocalDate.parse(text, DAY);
|
||||
}
|
||||
|
||||
private Integer flag(Boolean value) {
|
||||
return Boolean.TRUE.equals(value) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
+14
@@ -6,6 +6,7 @@ import com.roomroot.jwgl.entity.XYDRWB;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterCalendarMapper;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterMapper;
|
||||
import com.roomroot.jwgl.service.ClassSemesterCalendarService;
|
||||
import com.roomroot.jwgl.service.TeachingTaskWriteGuard;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -26,8 +27,19 @@ public class ClassSemesterCalendarServiceImpl implements ClassSemesterCalendarSe
|
||||
@Resource
|
||||
private ClassSemesterMapper classSemesterMapper;
|
||||
|
||||
@Resource
|
||||
private TeachingTaskWriteGuard teachingTaskWriteGuard;
|
||||
|
||||
@Override
|
||||
public void update(XYDRWB xydrwb) {
|
||||
if (xydrwb != null) {
|
||||
String semesterBh = xydrwb.getXydxqbh();
|
||||
if (semesterBh == null && xydrwb.getBh() != null) {
|
||||
XYDRWB existing = classSemesterCalendarMapper.selectById(xydrwb.getBh());
|
||||
semesterBh = existing == null ? null : existing.getXydxqbh();
|
||||
}
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(semesterBh);
|
||||
}
|
||||
classSemesterCalendarMapper.updateById(xydrwb);
|
||||
}
|
||||
|
||||
@@ -50,6 +62,7 @@ public class ClassSemesterCalendarServiceImpl implements ClassSemesterCalendarSe
|
||||
failedTargetBhs.add(targetBh);
|
||||
continue;
|
||||
}
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(targetBh);
|
||||
String newXydbh = targetSemester.getXydbh();
|
||||
|
||||
for (String sourceBh : sourceBhList) {
|
||||
@@ -142,6 +155,7 @@ public class ClassSemesterCalendarServiceImpl implements ClassSemesterCalendarSe
|
||||
failedTargetBhs.add(targetBh);
|
||||
continue;
|
||||
}
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(targetBh);
|
||||
String newXydbh = targetSemester.getXydbh();
|
||||
|
||||
for (XYDRWB source : sourceList) {
|
||||
|
||||
+271
-40
@@ -1,11 +1,17 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.common.exception.ServiceException;
|
||||
import com.roomroot.jwgl.entity.XQ;
|
||||
import com.roomroot.jwgl.entity.XYDNDXQJBXXB;
|
||||
import com.roomroot.jwgl.entity.XYDB;
|
||||
import com.roomroot.jwgl.entity.XYDRWB;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterCalendarMapper;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterMapper;
|
||||
import com.roomroot.jwgl.mapper.SemesterCalendarMapper;
|
||||
import com.roomroot.jwgl.mapper.SemesterMapper;
|
||||
import com.roomroot.jwgl.mapper.XYDBMapper;
|
||||
import com.roomroot.jwgl.service.ClassSemesterService;
|
||||
import com.roomroot.jwgl.service.ElectiveService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
@@ -17,8 +23,16 @@ import org.springframework.util.CollectionUtils;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDate;
|
||||
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.BAD_REQUEST;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.CONFLICT;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 班次学期服务实现类
|
||||
@@ -38,37 +52,88 @@ public class ClassSemesterServiceImpl implements ClassSemesterService {
|
||||
@Resource
|
||||
private ElectiveService electiveService;
|
||||
|
||||
@Resource
|
||||
private XYDBMapper xydbMapper;
|
||||
|
||||
@Resource
|
||||
private SemesterMapper semesterMapper;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void add(XYDNDXQJBXXB xydndxqjbxxb) {
|
||||
String uuid = UuidUtil.getUUID();
|
||||
xydndxqjbxxb.setBh(uuid);
|
||||
if (xydndxqjbxxb == null || xydndxqjbxxb.getXydbh() == null || xydndxqjbxxb.getXydbh().isEmpty()) {
|
||||
throw new ServiceException("班次编号不能为空", BAD_REQUEST);
|
||||
}
|
||||
assertXqdc(xydndxqjbxxb.getXqdc());
|
||||
com.roomroot.jwgl.vo.elective.SemesterInitVO init = electiveService.getSemesterInit(
|
||||
xydndxqjbxxb.getXydbh(), null, null, xydndxqjbxxb.getXqdc());
|
||||
if (Boolean.TRUE.equals(init.getHalfYear()) && !Integer.valueOf(1).equals(xydndxqjbxxb.getXqdc())) {
|
||||
throw new ServiceException("学制半年以内的班次,学期第次只能是第1学期", BAD_REQUEST);
|
||||
}
|
||||
if (xydndxqjbxxb.getZyjsbh() == null || xydndxqjbxxb.getZyjsbh().isEmpty()) {
|
||||
xydndxqjbxxb.setZyjsbh(init.getZyjsbh());
|
||||
}
|
||||
XYDNDXQJBXXB existing = classSemesterMapper.selectByBcAndNdAndXqdc(
|
||||
xydndxqjbxxb.getXydbh(),
|
||||
String.valueOf(xydndxqjbxxb.getNd()),
|
||||
String.valueOf(xydndxqjbxxb.getXqdc()));
|
||||
if (existing != null) {
|
||||
throw new ServiceException("该班次本年度学期已存在,不能重复新建", CONFLICT);
|
||||
}
|
||||
if (xydndxqjbxxb.getYsbbh() == null) {
|
||||
xydndxqjbxxb.setYsbbh(0);
|
||||
}
|
||||
if (xydndxqjbxxb.getKfjypk() == null) {
|
||||
xydndxqjbxxb.setKfjypk(0);
|
||||
}
|
||||
if (xydndxqjbxxb.getXhbs() == null) {
|
||||
xydndxqjbxxb.setXhbs(0);
|
||||
}
|
||||
xydndxqjbxxb.setBh(UuidUtil.getUUID());
|
||||
xydndxqjbxxb.setDelFlag(0);
|
||||
int insert = classSemesterMapper.insert(xydndxqjbxxb);
|
||||
classSemesterMapper.insert(xydndxqjbxxb);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void delete(String bh) {
|
||||
assertNoCourseTasks(bh);
|
||||
XYDNDXQJBXXB xydndxqjbxxb = getByBh(bh);
|
||||
if (xydndxqjbxxb == null) {
|
||||
return;
|
||||
}
|
||||
xydndxqjbxxb.setDelFlag(1);
|
||||
classSemesterMapper.updateById(xydndxqjbxxb);
|
||||
classSemesterCalendarMapper.deleteByBcxqBh(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchDelete(List<String> bhList) {
|
||||
if (bhList == null) {
|
||||
return;
|
||||
}
|
||||
for (String bh : bhList) {
|
||||
XYDNDXQJBXXB xydndxqjbxxb = getByBh(bh);
|
||||
if (xydndxqjbxxb != null) {
|
||||
xydndxqjbxxb.setDelFlag(1);
|
||||
classSemesterMapper.updateById(xydndxqjbxxb);
|
||||
}
|
||||
delete(bh);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertNoCourseTasks(String bh) {
|
||||
Long count = classSemesterCalendarMapper.selectCount(new LambdaQueryWrapper<XYDRWB>()
|
||||
.eq(XYDRWB::getXydxqbh, bh)
|
||||
.eq(XYDRWB::getDelFlag, 0));
|
||||
if (count != null && count > 0) {
|
||||
throw new ServiceException("该班次学期已有 " + count + " 条课程教学计划,请先删除课程任务后再删除", CONFLICT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(XYDNDXQJBXXB xydndxqjbxxb) {
|
||||
if (xydndxqjbxxb != null && xydndxqjbxxb.getXydbh() != null && xydndxqjbxxb.getXqdc() != null) {
|
||||
com.roomroot.jwgl.vo.elective.SemesterInitVO init = electiveService.getSemesterInit(
|
||||
xydndxqjbxxb.getXydbh(), null, null, xydndxqjbxxb.getXqdc());
|
||||
if (Boolean.TRUE.equals(init.getHalfYear()) && !Integer.valueOf(1).equals(xydndxqjbxxb.getXqdc())) {
|
||||
throw new ServiceException("学制半年以内的班次,学期第次只能是第1学期", BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
classSemesterMapper.updateById(xydndxqjbxxb);
|
||||
}
|
||||
|
||||
@@ -102,40 +167,13 @@ public class ClassSemesterServiceImpl implements ClassSemesterService {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xqdcNum = parseXqdc(xqdc);
|
||||
int year = Integer.parseInt(nd);
|
||||
int count = 0;
|
||||
for (XYDB xydb : xydbList) {
|
||||
// 校验是否已存在:根据班次编号、年度、学期第次查询
|
||||
XYDNDXQJBXXB existing = classSemesterMapper.selectByBcAndNdAndXqdc(xydb.getXydbh(), nd, xqdc);
|
||||
if (existing != null) {
|
||||
// 已存在,跳过
|
||||
continue;
|
||||
if (insertClassSemester(xydb, year, xqdcNum, LocalDate.parse(xqkssj), LocalDate.parse(xqjssj))) {
|
||||
count++;
|
||||
}
|
||||
|
||||
// 创建学员队年度学期基本信息
|
||||
XYDNDXQJBXXB xydndxqjbxxb = new XYDNDXQJBXXB();
|
||||
String uuid = UuidUtil.getUUID();
|
||||
xydndxqjbxxb.setBh(uuid);
|
||||
xydndxqjbxxb.setXydbh(xydb.getXydbh());
|
||||
xydndxqjbxxb.setNd(Integer.valueOf(nd));
|
||||
if("春季学期".equals(xqdc)){
|
||||
xqdc = "1";
|
||||
} else if("夏季学期".equals(xqdc)){
|
||||
xqdc = "2";
|
||||
} else if("秋季学期".equals(xqdc)){
|
||||
xqdc = "3";
|
||||
}
|
||||
xydndxqjbxxb.setXhbs(0);
|
||||
xydndxqjbxxb.setXqdc(Integer.valueOf(xqdc));
|
||||
xydndxqjbxxb.setKxrq(LocalDate.parse(xqkssj));
|
||||
xydndxqjbxxb.setJsrq(LocalDate.parse(xqjssj));
|
||||
xydndxqjbxxb.setYsbbh(0);
|
||||
xydndxqjbxxb.setJclb("双节次");
|
||||
xydndxqjbxxb.setXtms("");
|
||||
xydndxqjbxxb.setKfjypk(0);
|
||||
xydndxqjbxxb.setDelFlag(0);
|
||||
|
||||
int insert = classSemesterMapper.insert(xydndxqjbxxb);
|
||||
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@@ -159,6 +197,7 @@ public class ClassSemesterServiceImpl implements ClassSemesterService {
|
||||
|
||||
@Override
|
||||
public int batchUpdateXqdc(List<String> bhList, Integer xqdc) {
|
||||
assertXqdc(xqdc);
|
||||
if (CollectionUtils.isEmpty(bhList)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -210,6 +249,7 @@ public class ClassSemesterServiceImpl implements ClassSemesterService {
|
||||
xydndxqjbxxb.setKxrq(LocalDate.parse(xqkssj));
|
||||
xydndxqjbxxb.setJsrq(LocalDate.parse(xqjssj));
|
||||
classSemesterMapper.updateById(xydndxqjbxxb);
|
||||
count++;
|
||||
|
||||
// // 删除日期范围之外的日历记录
|
||||
// classSemesterCalendarMapper.deleteOutsideDateRange(bh, xqkssj, xqjssj);
|
||||
@@ -250,4 +290,195 @@ public class ClassSemesterServiceImpl implements ClassSemesterService {
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<XYDB> listCreatableClasses(Integer nd, Integer xqdc) {
|
||||
assertYearAndXqdc(nd, xqdc);
|
||||
return xydbMapper.selectCreatableClasses(nd, xqdc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> presetDates(Integer nd, Integer xqdc) {
|
||||
assertYearAndXqdc(nd, xqdc);
|
||||
XQ school = findSchoolSemester(nd, xqdc);
|
||||
Map<String, String> result = new HashMap<>();
|
||||
if (school == null || school.getKxrq() == null || school.getJsrq() == null) {
|
||||
result.put("kxrq", "");
|
||||
result.put("jsrq", "");
|
||||
return result;
|
||||
}
|
||||
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
result.put("kxrq", school.getKxrq().toLocalDate().format(fmt));
|
||||
result.put("jsrq", school.getJsrq().toLocalDate().format(fmt));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int batchCreateEligible(Integer nd, Integer xqdc, LocalDate kxrq, LocalDate jsrq) {
|
||||
assertYearAndXqdc(nd, xqdc);
|
||||
if (kxrq == null || jsrq == null) {
|
||||
Map<String, String> preset = presetDates(nd, xqdc);
|
||||
if (kxrq == null && preset.get("kxrq") != null && !preset.get("kxrq").isEmpty()) {
|
||||
kxrq = LocalDate.parse(preset.get("kxrq"));
|
||||
}
|
||||
if (jsrq == null && preset.get("jsrq") != null && !preset.get("jsrq").isEmpty()) {
|
||||
jsrq = LocalDate.parse(preset.get("jsrq"));
|
||||
}
|
||||
}
|
||||
if (kxrq == null || jsrq == null) {
|
||||
throw new ServiceException("请先维护学校学期的开学/结束日期,或手工填写", BAD_REQUEST);
|
||||
}
|
||||
if (!jsrq.isAfter(kxrq)) {
|
||||
throw new ServiceException("结束日期必须晚于开学日期", BAD_REQUEST);
|
||||
}
|
||||
List<XYDB> classes = xydbMapper.selectCreatableClasses(nd, xqdc);
|
||||
int count = 0;
|
||||
for (XYDB clazz : classes) {
|
||||
if (insertClassSemester(clazz, nd, xqdc, kxrq, jsrq)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int batchWaveMerge(List<String> bhList) {
|
||||
List<XYDNDXQJBXXB> rows = loadRows(bhList);
|
||||
if (rows.size() < 2) {
|
||||
throw new ServiceException("请至少选择两个班次进行预设合班", BAD_REQUEST);
|
||||
}
|
||||
Set<Integer> waves = new HashSet<>();
|
||||
for (XYDNDXQJBXXB row : rows) {
|
||||
if (row.getYsbbh() != null && row.getYsbbh() > 0) {
|
||||
waves.add(row.getYsbbh());
|
||||
}
|
||||
}
|
||||
int wave = waves.size() == 1 ? waves.iterator().next() : nextWaveNo();
|
||||
int count = 0;
|
||||
for (XYDNDXQJBXXB row : rows) {
|
||||
row.setYsbbh(wave);
|
||||
classSemesterMapper.updateById(row);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int batchWaveSplit(List<String> bhList) {
|
||||
List<XYDNDXQJBXXB> rows = loadRows(bhList);
|
||||
if (rows.isEmpty()) {
|
||||
throw new ServiceException("请先选择要拆班的班次", BAD_REQUEST);
|
||||
}
|
||||
int next = nextWaveNo();
|
||||
int count = 0;
|
||||
for (XYDNDXQJBXXB row : rows) {
|
||||
row.setYsbbh(next++);
|
||||
classSemesterMapper.updateById(row);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private boolean insertClassSemester(XYDB clazz, int nd, int xqdc, LocalDate kxrq, LocalDate jsrq) {
|
||||
XYDNDXQJBXXB existing = classSemesterMapper.selectByBcAndNdAndXqdc(
|
||||
clazz.getXydbh(), String.valueOf(nd), String.valueOf(xqdc));
|
||||
if (existing != null) {
|
||||
return false;
|
||||
}
|
||||
XYDNDXQJBXXB row = new XYDNDXQJBXXB();
|
||||
row.setBh(UuidUtil.getUUID());
|
||||
row.setXydbh(clazz.getXydbh());
|
||||
row.setNd(nd);
|
||||
row.setXqdc(xqdc);
|
||||
row.setKxrq(kxrq);
|
||||
row.setJsrq(jsrq);
|
||||
row.setZyjsbh(resolveRoom(clazz, xqdc));
|
||||
row.setXhbs(0);
|
||||
row.setYsbbh(0);
|
||||
row.setJclb(clazz.getJclb() != null && !clazz.getJclb().isEmpty() ? clazz.getJclb() : "双节次");
|
||||
row.setXtms(clazz.getXtms() == null ? "" : clazz.getXtms());
|
||||
row.setKfjypk(0);
|
||||
row.setDelFlag(0);
|
||||
classSemesterMapper.insert(row);
|
||||
return true;
|
||||
}
|
||||
|
||||
private String resolveRoom(XYDB clazz, int xqdc) {
|
||||
if (clazz.getZyjsbh() != null && !clazz.getZyjsbh().isEmpty()) {
|
||||
return clazz.getZyjsbh();
|
||||
}
|
||||
if (xqdc <= 1) {
|
||||
return null;
|
||||
}
|
||||
List<XYDNDXQJBXXB> prev = classSemesterMapper.selectList(new LambdaQueryWrapper<XYDNDXQJBXXB>()
|
||||
.eq(XYDNDXQJBXXB::getXydbh, clazz.getXydbh())
|
||||
.eq(XYDNDXQJBXXB::getXqdc, xqdc - 1)
|
||||
.eq(XYDNDXQJBXXB::getDelFlag, 0)
|
||||
.orderByDesc(XYDNDXQJBXXB::getNd));
|
||||
if (prev.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return prev.get(0).getZyjsbh();
|
||||
}
|
||||
|
||||
private XQ findSchoolSemester(Integer nd, Integer xqdc) {
|
||||
String key = String.valueOf(nd * 100 + xqdc);
|
||||
XQ school = semesterMapper.selectById(key);
|
||||
if (school != null) {
|
||||
return school;
|
||||
}
|
||||
return semesterMapper.selectById(String.valueOf(nd));
|
||||
}
|
||||
|
||||
private List<XYDNDXQJBXXB> loadRows(List<String> bhList) {
|
||||
if (CollectionUtils.isEmpty(bhList)) {
|
||||
return List.of();
|
||||
}
|
||||
return bhList.stream()
|
||||
.map(classSemesterMapper::selectById)
|
||||
.filter(row -> row != null && !Integer.valueOf(1).equals(row.getDelFlag()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private int nextWaveNo() {
|
||||
int max = 0;
|
||||
for (XYDNDXQJBXXB row : classSemesterMapper.selectAllValid()) {
|
||||
if (row.getYsbbh() != null && row.getYsbbh() > max) {
|
||||
max = row.getYsbbh();
|
||||
}
|
||||
}
|
||||
return max + 1;
|
||||
}
|
||||
|
||||
private void assertYearAndXqdc(Integer nd, Integer xqdc) {
|
||||
if (nd == null || nd < 2000) {
|
||||
throw new ServiceException("请选择有效年度", BAD_REQUEST);
|
||||
}
|
||||
assertXqdc(xqdc);
|
||||
}
|
||||
|
||||
private void assertXqdc(Integer xqdc) {
|
||||
if (xqdc == null || xqdc < 1 || xqdc > 3) {
|
||||
throw new ServiceException("学期第次只能是 1、2、3", BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
private int parseXqdc(String xqdc) {
|
||||
if (xqdc == null || xqdc.isEmpty()) {
|
||||
throw new ServiceException("请选择学期第次", BAD_REQUEST);
|
||||
}
|
||||
if ("春季学期".equals(xqdc)) {
|
||||
return 1;
|
||||
}
|
||||
if ("夏季学期".equals(xqdc)) {
|
||||
return 2;
|
||||
}
|
||||
if ("秋季学期".equals(xqdc)) {
|
||||
return 3;
|
||||
}
|
||||
return Integer.parseInt(xqdc);
|
||||
}
|
||||
}
|
||||
+30
-10
@@ -211,7 +211,10 @@ public class ElectiveServiceImpl implements ElectiveService {
|
||||
wrapper.eq(JSB::getJxldh, jxldh);
|
||||
}
|
||||
if (py != null && !py.isEmpty()) {
|
||||
wrapper.like(JSB::getPy, py);
|
||||
wrapper.and(w -> w.like(JSB::getPy, py)
|
||||
.or().like(JSB::getJsmc, py)
|
||||
.or().like(JSB::getJsbh, py)
|
||||
.or().like(JSB::getId, py));
|
||||
}
|
||||
wrapper.orderByAsc(JSB::getXh);
|
||||
return classRoomMapper.selectList(wrapper);
|
||||
@@ -219,6 +222,11 @@ public class ElectiveServiceImpl implements ElectiveService {
|
||||
|
||||
@Override
|
||||
public SemesterInitVO getSemesterInit(String xydbh, String presetKxrq, String presetJsrq) {
|
||||
return getSemesterInit(xydbh, presetKxrq, presetJsrq, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SemesterInitVO getSemesterInit(String xydbh, String presetKxrq, String presetJsrq, Integer xqdc) {
|
||||
XYDB clazz = xydbMapper.selectById(xydbh);
|
||||
if (clazz == null) {
|
||||
throw new BusinessException("教学班次不存在:" + xydbh);
|
||||
@@ -230,8 +238,12 @@ public class ElectiveServiceImpl implements ElectiveService {
|
||||
// 判断学制是否半年以内
|
||||
boolean halfYear = isHalfYear(rx, by);
|
||||
|
||||
// 学期第次:半年以内固定第一学期;半年以上按入学日期智能推断
|
||||
Integer xqdc = halfYear ? 1 : inferXqdc(rx, by, LocalDate.now());
|
||||
// 学期第次:半年以内固定第一学期;半年以上优先用窗口已选学期第次,否则按入学日期推断
|
||||
if (halfYear) {
|
||||
xqdc = 1;
|
||||
} else if (xqdc == null || xqdc < 1 || xqdc > 3) {
|
||||
xqdc = inferXqdc(rx, by, LocalDate.now());
|
||||
}
|
||||
// 人才培养方案总学期数(半年一学期,向上取整)
|
||||
Integer totalXqdc = calcTotalXqdc(rx, by);
|
||||
|
||||
@@ -246,15 +258,12 @@ public class ElectiveServiceImpl implements ElectiveService {
|
||||
jsrq = parseDate(presetJsrq);
|
||||
}
|
||||
|
||||
// 第二以上学期:默认预设上学期的专用教室
|
||||
// 第二以上学期优先上学期专用教室;没有则用班次专业教室
|
||||
String zyjsbh = getPrevRoom(xydbh, xqdc);
|
||||
String zyjsmc = null;
|
||||
if (zyjsbh != null && !zyjsbh.isEmpty()) {
|
||||
JSB room = classRoomMapper.selectById(zyjsbh);
|
||||
if (room != null) {
|
||||
zyjsmc = room.getJsmc();
|
||||
}
|
||||
if (zyjsbh == null || zyjsbh.isEmpty()) {
|
||||
zyjsbh = clazz.getZyjsbh();
|
||||
}
|
||||
String zyjsmc = roomName(zyjsbh);
|
||||
|
||||
SemesterInitVO vo = new SemesterInitVO();
|
||||
vo.setXydbh(xydbh);
|
||||
@@ -405,6 +414,17 @@ public class ElectiveServiceImpl implements ElectiveService {
|
||||
* @param xqdc 当前学期第次(<=1 时返回 null)
|
||||
* @return 上学期专用教室编号,不存在返回 null
|
||||
*/
|
||||
private String roomName(String zyjsbh) {
|
||||
if (zyjsbh == null || zyjsbh.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
JSB room = classRoomMapper.selectById(zyjsbh);
|
||||
if (room == null) {
|
||||
room = classRoomMapper.selectOne(new LambdaQueryWrapper<JSB>().eq(JSB::getJsbh, zyjsbh));
|
||||
}
|
||||
return room == null ? null : room.getJsmc();
|
||||
}
|
||||
|
||||
private String getPrevRoom(String xydbh, Integer xqdc) {
|
||||
if (xqdc == null || xqdc <= 1) {
|
||||
return null;
|
||||
|
||||
+16
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.jwgl.entity.JYSRWS;
|
||||
import com.roomroot.jwgl.mapper.OfficeTaskBookMapper;
|
||||
import com.roomroot.jwgl.service.OfficeTaskBookService;
|
||||
import com.roomroot.jwgl.service.TeachingTaskWriteGuard;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
@@ -22,8 +23,14 @@ public class OfficeTaskBookServiceImpl implements OfficeTaskBookService {
|
||||
@Resource
|
||||
private OfficeTaskBookMapper officeTaskBookMapper;
|
||||
|
||||
@Resource
|
||||
private TeachingTaskWriteGuard teachingTaskWriteGuard;
|
||||
|
||||
@Override
|
||||
public void add(JYSRWS jysrws) {
|
||||
if (jysrws != null) {
|
||||
teachingTaskWriteGuard.assertTaskWritable(jysrws.getJxrwbh());
|
||||
}
|
||||
String uuid = UuidUtil.getUUID();
|
||||
jysrws.setBh(uuid);
|
||||
jysrws.setDelFlag(0);
|
||||
@@ -37,6 +44,7 @@ public class OfficeTaskBookServiceImpl implements OfficeTaskBookService {
|
||||
public void delete(String bh) {
|
||||
JYSRWS jysrws = getByBh(bh);
|
||||
if (jysrws != null) {
|
||||
teachingTaskWriteGuard.assertTaskWritable(jysrws.getJxrwbh());
|
||||
jysrws.setDelFlag(1);
|
||||
officeTaskBookMapper.updateById(jysrws);
|
||||
}
|
||||
@@ -51,6 +59,14 @@ public class OfficeTaskBookServiceImpl implements OfficeTaskBookService {
|
||||
|
||||
@Override
|
||||
public void update(JYSRWS jysrws) {
|
||||
if (jysrws != null) {
|
||||
String taskBh = jysrws.getJxrwbh();
|
||||
if (taskBh == null && jysrws.getBh() != null) {
|
||||
JYSRWS existing = getByBh(jysrws.getBh());
|
||||
taskBh = existing == null ? null : existing.getJxrwbh();
|
||||
}
|
||||
teachingTaskWriteGuard.assertTaskWritable(taskBh);
|
||||
}
|
||||
officeTaskBookMapper.updateById(jysrws);
|
||||
}
|
||||
|
||||
|
||||
+85
@@ -3,8 +3,15 @@ package com.roomroot.jwgl.service.impl;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.roomroot.common.exception.ServiceException;
|
||||
import com.roomroot.jwgl.entity.JXRW;
|
||||
import com.roomroot.jwgl.entity.XQ;
|
||||
import com.roomroot.jwgl.entity.XQXLB;
|
||||
import com.roomroot.jwgl.entity.XYDNDXQJBXXB;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterMapper;
|
||||
import com.roomroot.jwgl.mapper.SemesterCalendarMapper;
|
||||
import com.roomroot.jwgl.mapper.SemesterMapper;
|
||||
import com.roomroot.jwgl.mapper.TeachingTaskMapper;
|
||||
import com.roomroot.jwgl.service.SemesterCalendarService;
|
||||
import com.roomroot.jwgl.service.SemesterService;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
@@ -14,8 +21,12 @@ import org.springframework.stereotype.Service;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.BAD_REQUEST;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.CONFLICT;
|
||||
|
||||
/**
|
||||
* 学期服务实现类
|
||||
*/
|
||||
@@ -31,8 +42,19 @@ public class SemesterServiceImpl extends ServiceImpl<SemesterMapper, XQ> impleme
|
||||
@Resource
|
||||
SemesterCalendarService semesterCalendarService;
|
||||
|
||||
@Resource
|
||||
private ClassSemesterMapper classSemesterMapper;
|
||||
|
||||
@Resource
|
||||
private TeachingTaskMapper teachingTaskMapper;
|
||||
|
||||
@Resource
|
||||
private SemesterCalendarMapper semesterCalendarMapper;
|
||||
|
||||
@Override
|
||||
public void add(XQ xq) {
|
||||
normalizeSemester(xq);
|
||||
assertNoOverlap(xq);
|
||||
xq.setDelFlag(0);
|
||||
xq.setTkbsp(true);
|
||||
int insert = semesterMapper.insert(xq);
|
||||
@@ -59,14 +81,77 @@ public class SemesterServiceImpl extends ServiceImpl<SemesterMapper, XQ> impleme
|
||||
|
||||
@Override
|
||||
public void delete(Integer nd) {
|
||||
if (nd == null) {
|
||||
throw new ServiceException("学期不能为空", BAD_REQUEST);
|
||||
}
|
||||
List<String> blocked = new ArrayList<>();
|
||||
Long classSemesterCount = classSemesterMapper.selectCount(new LambdaQueryWrapper<XYDNDXQJBXXB>()
|
||||
.eq(XYDNDXQJBXXB::getNd, nd)
|
||||
.and(w -> w.isNull(XYDNDXQJBXXB::getDelFlag).or().ne(XYDNDXQJBXXB::getDelFlag, 1)));
|
||||
if (classSemesterCount != null && classSemesterCount > 0) {
|
||||
blocked.add("班次学期 " + classSemesterCount + " 条");
|
||||
}
|
||||
Long taskCount = teachingTaskMapper.selectCount(new LambdaQueryWrapper<JXRW>()
|
||||
.eq(JXRW::getNd, nd)
|
||||
.and(w -> w.isNull(JXRW::getDelFlag).or().ne(JXRW::getDelFlag, 1)));
|
||||
if (taskCount != null && taskCount > 0) {
|
||||
blocked.add("教学任务 " + taskCount + " 条");
|
||||
}
|
||||
Long eventCount = semesterCalendarMapper.selectCount(new LambdaQueryWrapper<XQXLB>()
|
||||
.eq(XQXLB::getNd, nd)
|
||||
.isNotNull(XQXLB::getJqmc)
|
||||
.ne(XQXLB::getJqmc, ""));
|
||||
if (eventCount != null && eventCount > 0) {
|
||||
blocked.add("校历事件 " + eventCount + " 条");
|
||||
}
|
||||
if (!blocked.isEmpty()) {
|
||||
throw new ServiceException("该学期已有关联数据,不能删除:" + String.join("、", blocked), CONFLICT);
|
||||
}
|
||||
semesterMapper.deleteById(nd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(XQ xq) {
|
||||
normalizeSemester(xq);
|
||||
assertNoOverlap(xq);
|
||||
semesterMapper.updateById(xq);
|
||||
}
|
||||
|
||||
/**
|
||||
* 年度末两位是学期次,只允许 01/02/03,序号与末位保持一致。
|
||||
*/
|
||||
private void normalizeSemester(XQ xq) {
|
||||
if (xq == null || xq.getNd() == null || xq.getNd().isBlank()) {
|
||||
throw new ServiceException("学期年度不能为空", BAD_REQUEST);
|
||||
}
|
||||
String nd = xq.getNd().trim();
|
||||
if (!nd.matches("\\d{6}")) {
|
||||
throw new ServiceException("学期年度必须是6位,如202601", BAD_REQUEST);
|
||||
}
|
||||
String suffix = nd.substring(4);
|
||||
if (!suffix.equals("01") && !suffix.equals("02") && !suffix.equals("03")) {
|
||||
throw new ServiceException("一年最多三个学期,学期次只能是01、02、03", BAD_REQUEST);
|
||||
}
|
||||
xq.setNd(nd);
|
||||
xq.setXh(Integer.parseInt(suffix));
|
||||
if (xq.getKxrq() == null || xq.getJsrq() == null) {
|
||||
throw new ServiceException("开学时间和结束时间不能为空", BAD_REQUEST);
|
||||
}
|
||||
if (!xq.getJsrq().isAfter(xq.getKxrq())) {
|
||||
throw new ServiceException("学期结束时间必须晚于开学时间", BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertNoOverlap(XQ xq) {
|
||||
Long overlap = semesterMapper.selectCount(new LambdaQueryWrapper<XQ>()
|
||||
.ne(XQ::getNd, xq.getNd())
|
||||
.lt(XQ::getKxrq, xq.getJsrq())
|
||||
.gt(XQ::getJsrq, xq.getKxrq()));
|
||||
if (overlap != null && overlap > 0) {
|
||||
throw new ServiceException("学期时间范围与已有学期重叠", CONFLICT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public XQ getByNd(Integer nd) {
|
||||
return semesterMapper.selectById(nd);
|
||||
|
||||
+316
@@ -3,25 +3,44 @@ package com.roomroot.jwgl.service.impl;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.roomroot.common.exception.ServiceException;
|
||||
import com.roomroot.jwgl.entity.JXRW;
|
||||
import com.roomroot.jwgl.entity.KB;
|
||||
import com.roomroot.jwgl.entity.SSKC;
|
||||
import com.roomroot.jwgl.entity.SSKCXYD;
|
||||
import com.roomroot.jwgl.entity.XYDB;
|
||||
import com.roomroot.jwgl.entity.XYDNDXQJBXXB;
|
||||
import com.roomroot.jwgl.entity.XYDRWB;
|
||||
import com.roomroot.jwgl.entity.ZYJXJHB;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterMapper;
|
||||
import com.roomroot.jwgl.mapper.KBMapper;
|
||||
import com.roomroot.jwgl.mapper.SSKCMapper;
|
||||
import com.roomroot.jwgl.mapper.SSKCXYDMapper;
|
||||
import com.roomroot.jwgl.mapper.StudentTeamTaskMapper;
|
||||
import com.roomroot.jwgl.mapper.TeachingTaskMapper;
|
||||
import com.roomroot.jwgl.mapper.XYDBMapper;
|
||||
import com.roomroot.jwgl.mapper.ZYJXJHBMapper;
|
||||
import com.roomroot.jwgl.service.StudentTeamTaskService;
|
||||
import com.roomroot.jwgl.service.TeachingTaskWriteGuard;
|
||||
import com.roomroot.jwgl.utils.TeachingTaskStatus;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
import com.roomroot.jwgl.vo.PlanCourseVO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.BAD_REQUEST;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.CONFLICT;
|
||||
|
||||
/**
|
||||
* 学员队任务表 Service实现
|
||||
*/
|
||||
@@ -40,8 +59,26 @@ public class StudentTeamTaskServiceImpl implements StudentTeamTaskService {
|
||||
@Autowired
|
||||
private ZYJXJHBMapper zyjxjhbMapper;
|
||||
|
||||
@Autowired
|
||||
private TeachingTaskWriteGuard teachingTaskWriteGuard;
|
||||
|
||||
@Autowired
|
||||
private KBMapper kbMapper;
|
||||
|
||||
@Autowired
|
||||
private TeachingTaskMapper teachingTaskMapper;
|
||||
|
||||
@Autowired
|
||||
private SSKCMapper sskcMapper;
|
||||
|
||||
@Autowired
|
||||
private SSKCXYDMapper sskcxydMapper;
|
||||
|
||||
@Override
|
||||
public void add(XYDRWB xydrwb) {
|
||||
if (xydrwb != null) {
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(xydrwb.getXydxqbh());
|
||||
}
|
||||
xydrwb.setBh(UuidUtil.getUUID());
|
||||
xydrwb.setDelFlag(0);
|
||||
xydrwbMapper.insert(xydrwb);
|
||||
@@ -49,11 +86,23 @@ public class StudentTeamTaskServiceImpl implements StudentTeamTaskService {
|
||||
|
||||
@Override
|
||||
public void delete(String bh) {
|
||||
XYDRWB existing = xydrwbMapper.selectById(bh);
|
||||
if (existing != null) {
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(existing.getXydxqbh());
|
||||
}
|
||||
xydrwbMapper.deleteById(bh);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(XYDRWB xydrwb) {
|
||||
if (xydrwb != null) {
|
||||
String semesterBh = xydrwb.getXydxqbh();
|
||||
if (semesterBh == null && xydrwb.getBh() != null) {
|
||||
XYDRWB existing = xydrwbMapper.selectById(xydrwb.getBh());
|
||||
semesterBh = existing == null ? null : existing.getXydxqbh();
|
||||
}
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(semesterBh);
|
||||
}
|
||||
xydrwbMapper.updateById(xydrwb);
|
||||
}
|
||||
|
||||
@@ -168,6 +217,7 @@ public class StudentTeamTaskServiceImpl implements StudentTeamTaskService {
|
||||
}
|
||||
Integer nd = semester.getNd();
|
||||
String xydxqbh = semester.getBh();
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(xydxqbh);
|
||||
|
||||
// 4. 查询当前班次已存在的课程编号集合
|
||||
LambdaQueryWrapper<XYDRWB> existWrapper = new LambdaQueryWrapper<>();
|
||||
@@ -231,9 +281,275 @@ public class StudentTeamTaskServiceImpl implements StudentTeamTaskService {
|
||||
source.setBh(newBh);
|
||||
source.setXydbh(newXydbh);
|
||||
source.setDelFlag(0);
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(source.getXydxqbh());
|
||||
xydrwbMapper.insert(source);
|
||||
newBhList.add(newBh);
|
||||
}
|
||||
return newBhList;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int batchAutoGenerate(List<String> xydxqbhList) {
|
||||
if (CollectionUtils.isEmpty(xydxqbhList)) {
|
||||
return 0;
|
||||
}
|
||||
int count = 0;
|
||||
for (String xydxqbh : xydxqbhList) {
|
||||
XYDNDXQJBXXB semester = classSemesterMapper.selectById(xydxqbh);
|
||||
if (semester == null || semester.getXydbh() == null || semester.getXqdc() == null) {
|
||||
continue;
|
||||
}
|
||||
count += autoGenerateRequiredCourses(semester.getXydbh(), semester.getXqdc());
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PlanCourseVO> listPlanCourses(String xydxqbh, boolean otherOnly) {
|
||||
XYDNDXQJBXXB semester = requireSemester(xydxqbh);
|
||||
XYDB clazz = xydbMapper.selectById(semester.getXydbh());
|
||||
if (clazz == null || clazz.getZydh() == null) {
|
||||
return List.of();
|
||||
}
|
||||
LambdaQueryWrapper<ZYJXJHB> wrapper = new LambdaQueryWrapper<ZYJXJHB>()
|
||||
.eq(ZYJXJHB::getZydh, clazz.getZydh())
|
||||
.eq(ZYJXJHB::getTy, 0);
|
||||
if (otherOnly && semester.getXqdc() != null) {
|
||||
wrapper.ne(ZYJXJHB::getXqdc, semester.getXqdc());
|
||||
}
|
||||
List<ZYJXJHB> plans = zyjxjhbMapper.selectList(wrapper);
|
||||
Set<String> done = currentCourseCodes(xydxqbh);
|
||||
List<PlanCourseVO> result = new ArrayList<>();
|
||||
for (ZYJXJHB plan : plans) {
|
||||
PlanCourseVO vo = new PlanCourseVO();
|
||||
vo.setBh(plan.getBh());
|
||||
vo.setKbh(plan.getKbh());
|
||||
vo.setJc(plan.getJc());
|
||||
vo.setXqdc(plan.getXqdc());
|
||||
vo.setXs(plan.getXs());
|
||||
vo.setKlx(plan.getKlx());
|
||||
vo.setXf(plan.getXf());
|
||||
vo.setZks(plan.getZks());
|
||||
vo.setCompleted(done.contains(plan.getKbh()));
|
||||
result.add(vo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void addFromLibrary(String xydxqbh, String kbh) {
|
||||
XYDNDXQJBXXB semester = requireWritableSemester(xydxqbh);
|
||||
KB course = kbMapper.selectById(kbh);
|
||||
if (course == null) {
|
||||
throw new ServiceException("课程不存在", BAD_REQUEST);
|
||||
}
|
||||
if (currentCourseCodes(xydxqbh).contains(kbh)) {
|
||||
throw new ServiceException("当前学期已有该课程", CONFLICT);
|
||||
}
|
||||
XYDRWB row = new XYDRWB();
|
||||
row.setBh(UuidUtil.getUUID());
|
||||
row.setNd(semester.getNd());
|
||||
row.setXydbh(semester.getXydbh());
|
||||
row.setXydxqbh(xydxqbh);
|
||||
row.setXqdc(semester.getXqdc());
|
||||
row.setKbh(course.getKbh());
|
||||
row.setJc(course.getJc());
|
||||
row.setXs(course.getXs());
|
||||
row.setKlx(course.getKlx() == null ? course.getKclx() : course.getKlx());
|
||||
row.setXf(course.getXf());
|
||||
row.setZks(course.getZks());
|
||||
row.setLlxs(course.getLlxs());
|
||||
row.setSjxs(course.getSjxs());
|
||||
row.setCjfz(course.getCjfz());
|
||||
row.setKsks(course.getKsks());
|
||||
row.setJysdh(course.getJysdh());
|
||||
row.setDelFlag(0);
|
||||
xydrwbMapper.insert(row);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void addFromPlan(String xydxqbh, String planBh) {
|
||||
XYDNDXQJBXXB semester = requireWritableSemester(xydxqbh);
|
||||
ZYJXJHB plan = zyjxjhbMapper.selectById(planBh);
|
||||
if (plan == null) {
|
||||
throw new ServiceException("人培课程不存在", BAD_REQUEST);
|
||||
}
|
||||
if (currentCourseCodes(xydxqbh).contains(plan.getKbh())) {
|
||||
throw new ServiceException("当前学期已有该课程", CONFLICT);
|
||||
}
|
||||
xydrwbMapper.insert(fromPlan(semester, plan));
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int syncFromPlan(List<String> bhList) {
|
||||
if (CollectionUtils.isEmpty(bhList)) {
|
||||
return 0;
|
||||
}
|
||||
int count = 0;
|
||||
for (String bh : bhList) {
|
||||
XYDRWB row = xydrwbMapper.selectById(bh);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(row.getXydxqbh());
|
||||
ZYJXJHB plan = findPlan(row);
|
||||
if (plan == null) {
|
||||
continue;
|
||||
}
|
||||
row.setXs(plan.getXs());
|
||||
row.setKlx(plan.getKlx());
|
||||
row.setXf(plan.getXf());
|
||||
row.setJc(plan.getJc());
|
||||
row.setZks(plan.getZks());
|
||||
row.setLlxs(plan.getLlxs());
|
||||
row.setSjxs(plan.getSjxs());
|
||||
row.setJysdh(plan.getJysdh());
|
||||
row.setCjfz(plan.getCjfz());
|
||||
xydrwbMapper.updateById(row);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int batchDeleteGuarded(List<String> bhList) {
|
||||
if (CollectionUtils.isEmpty(bhList)) {
|
||||
return 0;
|
||||
}
|
||||
int count = 0;
|
||||
for (String bh : bhList) {
|
||||
XYDRWB row = xydrwbMapper.selectById(bh);
|
||||
if (row == null) {
|
||||
continue;
|
||||
}
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(row.getXydxqbh());
|
||||
assertDeletable(row);
|
||||
xydrwbMapper.deleteById(bh);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int pasteToSemester(List<String> bhList, String targetXydxqbh) {
|
||||
XYDNDXQJBXXB semester = requireWritableSemester(targetXydxqbh);
|
||||
if (CollectionUtils.isEmpty(bhList)) {
|
||||
return 0;
|
||||
}
|
||||
int count = 0;
|
||||
for (String bh : bhList) {
|
||||
XYDRWB source = xydrwbMapper.selectById(bh);
|
||||
if (source == null) {
|
||||
continue;
|
||||
}
|
||||
source.setBh(UuidUtil.getUUID());
|
||||
source.setXydbh(semester.getXydbh());
|
||||
source.setXydxqbh(semester.getBh());
|
||||
source.setNd(semester.getNd());
|
||||
source.setXqdc(semester.getXqdc());
|
||||
source.setDelFlag(0);
|
||||
xydrwbMapper.insert(source);
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private XYDRWB fromPlan(XYDNDXQJBXXB semester, ZYJXJHB plan) {
|
||||
XYDRWB row = new XYDRWB();
|
||||
row.setBh(UuidUtil.getUUID());
|
||||
row.setNd(semester.getNd());
|
||||
row.setXydbh(semester.getXydbh());
|
||||
row.setXydxqbh(semester.getBh());
|
||||
row.setXqdc(semester.getXqdc());
|
||||
row.setKbh(plan.getKbh());
|
||||
row.setKlx(plan.getKlx());
|
||||
row.setXs(plan.getXs());
|
||||
row.setJc(plan.getJc());
|
||||
row.setZks(plan.getZks());
|
||||
row.setXf(plan.getXf());
|
||||
row.setKsks(plan.getKsks());
|
||||
row.setCjfz(plan.getCjfz());
|
||||
row.setBjrxypjf(plan.getBjrxypjf());
|
||||
row.setLlxs(plan.getLlxs());
|
||||
row.setSjxs(plan.getSjxs());
|
||||
row.setKsksbxs(plan.getKsksbxs());
|
||||
row.setJysdh(plan.getJysdh());
|
||||
row.setDelFlag(0);
|
||||
return row;
|
||||
}
|
||||
|
||||
private ZYJXJHB findPlan(XYDRWB row) {
|
||||
XYDB clazz = xydbMapper.selectById(row.getXydbh());
|
||||
if (clazz == null || clazz.getZydh() == null || row.getKbh() == null) {
|
||||
return null;
|
||||
}
|
||||
List<ZYJXJHB> plans = zyjxjhbMapper.selectList(new LambdaQueryWrapper<ZYJXJHB>()
|
||||
.eq(ZYJXJHB::getZydh, clazz.getZydh())
|
||||
.eq(ZYJXJHB::getKbh, row.getKbh())
|
||||
.eq(ZYJXJHB::getTy, 0));
|
||||
for (ZYJXJHB plan : plans) {
|
||||
if (Objects.equals(plan.getXqdc(), row.getXqdc())) {
|
||||
return plan;
|
||||
}
|
||||
}
|
||||
return plans.isEmpty() ? null : plans.get(0);
|
||||
}
|
||||
|
||||
private void assertDeletable(XYDRWB row) {
|
||||
XYDNDXQJBXXB semester = classSemesterMapper.selectById(row.getXydxqbh());
|
||||
if (semester != null && semester.getJxrwbh() != null) {
|
||||
JXRW task = teachingTaskMapper.selectById(semester.getJxrwbh());
|
||||
if (task != null && (TeachingTaskStatus.isPublished(task.getZt()) || TeachingTaskStatus.isEnded(task.getZt()))) {
|
||||
throw new ServiceException("课程已发布到教学任务,不能删除", CONFLICT);
|
||||
}
|
||||
}
|
||||
if (isScheduled(row)) {
|
||||
throw new ServiceException("课程已排课,不能删除", CONFLICT);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isScheduled(XYDRWB row) {
|
||||
if (row.getKbh() == null || row.getXydbh() == null) {
|
||||
return false;
|
||||
}
|
||||
List<SSKC> courses = sskcMapper.selectList(new LambdaQueryWrapper<SSKC>().eq(SSKC::getKmbh, row.getKbh()));
|
||||
for (SSKC course : courses) {
|
||||
Long linked = sskcxydMapper.selectCount(new LambdaQueryWrapper<SSKCXYD>()
|
||||
.eq(SSKCXYD::getSskcbh, course.getBh())
|
||||
.eq(SSKCXYD::getXydbh, row.getXydbh()));
|
||||
if (linked != null && linked > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Set<String> currentCourseCodes(String xydxqbh) {
|
||||
return xydrwbMapper.selectList(new LambdaQueryWrapper<XYDRWB>()
|
||||
.eq(XYDRWB::getXydxqbh, xydxqbh)
|
||||
.eq(XYDRWB::getDelFlag, 0))
|
||||
.stream()
|
||||
.map(XYDRWB::getKbh)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
}
|
||||
|
||||
private XYDNDXQJBXXB requireSemester(String xydxqbh) {
|
||||
XYDNDXQJBXXB semester = classSemesterMapper.selectById(xydxqbh);
|
||||
if (semester == null) {
|
||||
throw new ServiceException("班次学期不存在", BAD_REQUEST);
|
||||
}
|
||||
return semester;
|
||||
}
|
||||
|
||||
private XYDNDXQJBXXB requireWritableSemester(String xydxqbh) {
|
||||
teachingTaskWriteGuard.assertCourseTaskWritable(xydxqbh);
|
||||
return requireSemester(xydxqbh);
|
||||
}
|
||||
}
|
||||
+37
-1
@@ -24,6 +24,7 @@ import com.roomroot.jwgl.mapper.XYDBMapper;
|
||||
import com.roomroot.jwgl.mapper.ZYJXJHBMapper;
|
||||
import com.roomroot.jwgl.service.StudentTeamTaskService;
|
||||
import com.roomroot.jwgl.service.TeachingTaskManageService;
|
||||
import com.roomroot.jwgl.utils.TeachingTaskStatus;
|
||||
import com.roomroot.jwgl.unit.PageQuery;
|
||||
import com.roomroot.jwgl.unit.PageResult;
|
||||
import com.roomroot.jwgl.utils.UuidUtil;
|
||||
@@ -150,6 +151,9 @@ public class TeachingTaskManageServiceImpl implements TeachingTaskManageService
|
||||
if (entity == null || Integer.valueOf(1).equals(entity.getDelFlag())) {
|
||||
throw new ServiceException("教学任务不存在", NOT_FOUND);
|
||||
}
|
||||
if (TeachingTaskStatus.isEnded(entity.getZt())) {
|
||||
throw new ServiceException("教学任务已结束,不能再修改", CONFLICT);
|
||||
}
|
||||
fillSemester(dto);
|
||||
entity.setRwmc(dto.getRwmc().trim());
|
||||
if (dto.getJssj() != null) {
|
||||
@@ -195,7 +199,10 @@ public class TeachingTaskManageServiceImpl implements TeachingTaskManageService
|
||||
if (entity == null || Integer.valueOf(1).equals(entity.getDelFlag())) {
|
||||
throw new ServiceException("教学任务不存在", NOT_FOUND);
|
||||
}
|
||||
if (STATUS_PUBLISHED.equals(entity.getZt())) {
|
||||
if (TeachingTaskStatus.isEnded(entity.getZt())) {
|
||||
throw new ServiceException("该教学任务已结束", CONFLICT);
|
||||
}
|
||||
if (TeachingTaskStatus.isPublished(entity.getZt())) {
|
||||
throw new ServiceException("该教学任务已发布", CONFLICT);
|
||||
}
|
||||
generateCourseTasksAndOfficeBooks(bh);
|
||||
@@ -213,6 +220,35 @@ public class TeachingTaskManageServiceImpl implements TeachingTaskManageService
|
||||
return books.size();
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void endPublish(String bh) {
|
||||
if (StringUtils.isEmpty(bh)) {
|
||||
throw new ServiceException("教学任务编号不能为空", BAD_REQUEST);
|
||||
}
|
||||
JXRW entity = teachingTaskMapper.selectById(bh);
|
||||
if (entity == null || Integer.valueOf(1).equals(entity.getDelFlag())) {
|
||||
throw new ServiceException("教学任务不存在", NOT_FOUND);
|
||||
}
|
||||
if (TeachingTaskStatus.isEnded(entity.getZt())) {
|
||||
throw new ServiceException("该教学任务已结束", CONFLICT);
|
||||
}
|
||||
if (!TeachingTaskStatus.isPublished(entity.getZt())) {
|
||||
throw new ServiceException("只有已发布的教学任务才能结束", CONFLICT);
|
||||
}
|
||||
entity.setZt(TeachingTaskStatus.ENDED);
|
||||
entity.setJssj(LocalDateTime.now());
|
||||
teachingTaskMapper.updateById(entity);
|
||||
|
||||
List<JYSRWS> books = officeTaskBookMapper.selectList(new LambdaQueryWrapper<JYSRWS>()
|
||||
.eq(JYSRWS::getJxrwbh, bh)
|
||||
.eq(JYSRWS::getDelFlag, 0));
|
||||
for (JYSRWS book : books) {
|
||||
book.setZt(TeachingTaskStatus.ENDED);
|
||||
officeTaskBookMapper.updateById(book);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TeachingOfficeBookVO> listOfficeBooks(String jxrwbh) {
|
||||
if (StringUtils.isEmpty(jxrwbh)) {
|
||||
|
||||
+42
@@ -2,8 +2,10 @@ package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.roomroot.common.exception.ServiceException;
|
||||
import com.roomroot.jwgl.entity.JXRW;
|
||||
import com.roomroot.jwgl.entity.JYSRWS;
|
||||
import com.roomroot.jwgl.utils.TeachingTaskStatus;
|
||||
import com.roomroot.jwgl.mapper.TeachingTaskMapper;
|
||||
import com.roomroot.jwgl.mapper.OfficeTaskBookMapper;
|
||||
import com.roomroot.jwgl.service.TeachingTaskService;
|
||||
@@ -14,8 +16,12 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.BAD_REQUEST;
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.CONFLICT;
|
||||
|
||||
/**
|
||||
* 教学任务服务实现类
|
||||
*/
|
||||
@@ -69,6 +75,10 @@ public class TeachingTaskServiceImpl implements TeachingTaskService {
|
||||
|
||||
@Override
|
||||
public void update(JXRW jxrw) {
|
||||
JXRW existing = jxrw == null ? null : getByBh(jxrw.getBh());
|
||||
if (existing != null && TeachingTaskStatus.isEnded(existing.getZt())) {
|
||||
throw new ServiceException("教学任务已结束,不能再修改", CONFLICT);
|
||||
}
|
||||
teachingTaskMapper.updateById(jxrw);
|
||||
}
|
||||
|
||||
@@ -105,6 +115,9 @@ public class TeachingTaskServiceImpl implements TeachingTaskService {
|
||||
if (jxrw == null || jxrw.getDelFlag() != 0) {
|
||||
return 0;
|
||||
}
|
||||
if (TeachingTaskStatus.isEnded(jxrw.getZt())) {
|
||||
throw new ServiceException("教学任务已结束,不能再次发布", CONFLICT);
|
||||
}
|
||||
|
||||
// 更新教学任务状态为"发布"
|
||||
jxrw.setZt("发布");
|
||||
@@ -125,4 +138,33 @@ public class TeachingTaskServiceImpl implements TeachingTaskService {
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void endPublish(String bh) {
|
||||
if (bh == null || bh.isEmpty()) {
|
||||
throw new ServiceException("教学任务编号不能为空", BAD_REQUEST);
|
||||
}
|
||||
JXRW jxrw = teachingTaskMapper.selectById(bh);
|
||||
if (jxrw == null || Integer.valueOf(1).equals(jxrw.getDelFlag())) {
|
||||
throw new ServiceException("教学任务不存在", BAD_REQUEST);
|
||||
}
|
||||
if (TeachingTaskStatus.isEnded(jxrw.getZt())) {
|
||||
throw new ServiceException("该教学任务已结束", CONFLICT);
|
||||
}
|
||||
if (!TeachingTaskStatus.isPublished(jxrw.getZt())) {
|
||||
throw new ServiceException("只有已发布的教学任务才能结束", CONFLICT);
|
||||
}
|
||||
jxrw.setZt(TeachingTaskStatus.ENDED);
|
||||
jxrw.setJssj(LocalDateTime.now());
|
||||
teachingTaskMapper.updateById(jxrw);
|
||||
|
||||
List<JYSRWS> books = officeTaskBookMapper.selectList(new LambdaQueryWrapper<JYSRWS>()
|
||||
.eq(JYSRWS::getJxrwbh, bh)
|
||||
.eq(JYSRWS::getDelFlag, 0));
|
||||
for (JYSRWS book : books) {
|
||||
book.setZt(TeachingTaskStatus.ENDED);
|
||||
officeTaskBookMapper.updateById(book);
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.roomroot.jwgl.service.impl;
|
||||
|
||||
import com.roomroot.common.exception.ServiceException;
|
||||
import com.roomroot.common.utils.StringUtils;
|
||||
import com.roomroot.jwgl.entity.JXRW;
|
||||
import com.roomroot.jwgl.entity.XYDNDXQJBXXB;
|
||||
import com.roomroot.jwgl.mapper.ClassSemesterMapper;
|
||||
import com.roomroot.jwgl.mapper.TeachingTaskMapper;
|
||||
import com.roomroot.jwgl.service.TeachingTaskWriteGuard;
|
||||
import com.roomroot.jwgl.utils.TeachingTaskStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import static com.roomroot.jwgl.utils.BasicManagementConstants.CONFLICT;
|
||||
|
||||
/**
|
||||
* 按教学任务状态拦截已结束任务的改写。
|
||||
*/
|
||||
@Service
|
||||
public class TeachingTaskWriteGuardImpl implements TeachingTaskWriteGuard {
|
||||
|
||||
@Resource
|
||||
private TeachingTaskMapper teachingTaskMapper;
|
||||
|
||||
@Resource
|
||||
private ClassSemesterMapper classSemesterMapper;
|
||||
|
||||
@Override
|
||||
public void assertTaskWritable(String jxrwbh) {
|
||||
if (StringUtils.isEmpty(jxrwbh)) {
|
||||
return;
|
||||
}
|
||||
JXRW task = teachingTaskMapper.selectById(jxrwbh);
|
||||
if (task == null || Integer.valueOf(1).equals(task.getDelFlag())) {
|
||||
return;
|
||||
}
|
||||
if (TeachingTaskStatus.isEnded(task.getZt())) {
|
||||
throw new ServiceException("教学任务已结束,不能再修改任务书或课程任务", CONFLICT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertCourseTaskWritable(String xydxqbh) {
|
||||
if (StringUtils.isEmpty(xydxqbh)) {
|
||||
return;
|
||||
}
|
||||
XYDNDXQJBXXB semester = classSemesterMapper.selectById(xydxqbh);
|
||||
if (semester == null) {
|
||||
return;
|
||||
}
|
||||
assertTaskWritable(semester.getJxrwbh());
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -160,10 +160,10 @@ public final class SystemInitializationUtil {
|
||||
// 第三步:校验同一年度内的学期序号。
|
||||
if (dto.getSequenceNumber() == null
|
||||
|| dto.getSequenceNumber().intValue() < 1
|
||||
|| dto.getSequenceNumber().intValue() > 10) {
|
||||
|| dto.getSequenceNumber().intValue() > 3) {
|
||||
throw new BusinessException(
|
||||
BAD_REQUEST,
|
||||
"学期序号必须在1至10之间");
|
||||
"一年最多三个学期,学期序号必须在1至3之间");
|
||||
}
|
||||
|
||||
// 第四步:开学和结束时间均为学期初始化必填参数。
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.roomroot.jwgl.utils;
|
||||
|
||||
/**
|
||||
* 教学任务状态。库中同时存在「发布」和历史值「已发布」。
|
||||
*/
|
||||
public final class TeachingTaskStatus {
|
||||
|
||||
public static final String DRAFT = "上报";
|
||||
public static final String PUBLISHED = "发布";
|
||||
public static final String PUBLISHED_LEGACY = "已发布";
|
||||
public static final String ENDED = "已结束";
|
||||
|
||||
private TeachingTaskStatus() {
|
||||
}
|
||||
|
||||
public static boolean isPublished(String status) {
|
||||
return PUBLISHED.equals(status) || PUBLISHED_LEGACY.equals(status);
|
||||
}
|
||||
|
||||
public static boolean isEnded(String status) {
|
||||
return ENDED.equals(status);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.roomroot.jwgl.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 人培课程及在当前班次学期的完成情况。
|
||||
*/
|
||||
@Data
|
||||
public class PlanCourseVO {
|
||||
|
||||
private String bh;
|
||||
private String kbh;
|
||||
private String jc;
|
||||
private Integer xqdc;
|
||||
private Integer xs;
|
||||
private String klx;
|
||||
private Float xf;
|
||||
private Integer zks;
|
||||
private Boolean completed;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
-- 阶段0:正课列、学期序号校正
|
||||
-- 正课与自动排课分离。回填只覆盖星期一至星期五的 1-6 节且可排课的格子。
|
||||
-- 假期时间在学期校历表中是 VARCHAR(10),直接 TO_CHAR 即可。列已存在时不要重复执行 ALTER。
|
||||
|
||||
ALTER TABLE "学期校历表" ADD "正课" TINYINT DEFAULT 0 NOT NULL;
|
||||
|
||||
ALTER TABLE "假期表" ADD "正课" TINYINT DEFAULT 0 NOT NULL;
|
||||
|
||||
UPDATE "学期校历表"
|
||||
SET "正课" = 1
|
||||
WHERE "可排课" = 1
|
||||
AND "节次" IN ('1-2', '3-4', '5-6')
|
||||
AND TO_CHAR("假期时间", 'D') IN ('2', '3', '4', '5', '6');
|
||||
|
||||
-- 年度末位即学期次(202602 -> 2)。校正现有序号与末位不一致的记录。
|
||||
UPDATE "学期"
|
||||
SET "序号" = MOD("年度", 10)
|
||||
WHERE "年度" >= 200001
|
||||
AND "年度" <= 210003
|
||||
AND MOD("年度", 100) BETWEEN 1 AND 3
|
||||
AND "序号" <> MOD("年度", 10);
|
||||
@@ -0,0 +1,4 @@
|
||||
-- 阶段2:班历时间格需要节次。假期表原先没有该列,不新建表。
|
||||
-- 列已存在时不要重复执行。
|
||||
|
||||
ALTER TABLE "假期表" ADD "节次" VARCHAR(10) DEFAULT '' NOT NULL;
|
||||
Reference in New Issue
Block a user