TimePeriodExamRoomServiceImpl.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. package com.qmth.exam.reserve.service.impl;
  2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  3. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  4. import com.qmth.boot.core.concurrent.service.ConcurrentService;
  5. import com.qmth.boot.core.exception.StatusException;
  6. import com.qmth.exam.reserve.bean.applytask.CurrentApplyTaskVO;
  7. import com.qmth.exam.reserve.bean.examsite.ExamSiteCacheBean;
  8. import com.qmth.exam.reserve.bean.login.LoginUser;
  9. import com.qmth.exam.reserve.bean.org.OrgInfo;
  10. import com.qmth.exam.reserve.bean.timeperiod.TimePeriodExamSiteBean;
  11. import com.qmth.exam.reserve.bean.timeperiod.TimePeriodExamSiteInfo;
  12. import com.qmth.exam.reserve.bean.timeperiod.TimePeriodExamSiteReq;
  13. import com.qmth.exam.reserve.bean.timeperiod.TimePeriodExamSiteVo;
  14. import com.qmth.exam.reserve.cache.CacheConstants;
  15. import com.qmth.exam.reserve.cache.impl.ApplyTaskCacheService;
  16. import com.qmth.exam.reserve.cache.impl.ExamSiteCacheService;
  17. import com.qmth.exam.reserve.cache.impl.OrgCacheService;
  18. import com.qmth.exam.reserve.dao.TimePeriodExamRoomDao;
  19. import com.qmth.exam.reserve.entity.ExamRoomEntity;
  20. import com.qmth.exam.reserve.entity.TimePeriodEntity;
  21. import com.qmth.exam.reserve.entity.TimePeriodExamRoomEntity;
  22. import com.qmth.exam.reserve.enums.Role;
  23. import com.qmth.exam.reserve.service.ExamRoomService;
  24. import com.qmth.exam.reserve.service.ExamSiteService;
  25. import com.qmth.exam.reserve.service.TimePeriodExamRoomService;
  26. import com.qmth.exam.reserve.service.TimePeriodService;
  27. import com.qmth.exam.reserve.util.DateUtil;
  28. import com.qmth.exam.reserve.util.UnionUtil;
  29. import org.apache.commons.collections4.CollectionUtils;
  30. import org.apache.commons.lang3.StringUtils;
  31. import org.redisson.api.RLock;
  32. import org.slf4j.Logger;
  33. import org.slf4j.LoggerFactory;
  34. import org.springframework.beans.BeanUtils;
  35. import org.springframework.beans.factory.annotation.Autowired;
  36. import org.springframework.stereotype.Service;
  37. import org.springframework.transaction.annotation.Isolation;
  38. import org.springframework.transaction.annotation.Transactional;
  39. import java.util.*;
  40. import java.util.stream.Collectors;
  41. @Service
  42. public class TimePeriodExamRoomServiceImpl extends ServiceImpl<TimePeriodExamRoomDao, TimePeriodExamRoomEntity> implements TimePeriodExamRoomService {
  43. private static final Logger log = LoggerFactory.getLogger(TimePeriodExamRoomServiceImpl.class);
  44. @Autowired
  45. private ApplyTaskCacheService applyTaskCacheService;
  46. @Autowired
  47. private OrgCacheService orgCacheService;
  48. @Autowired
  49. private TimePeriodService timePeriodService;
  50. @Autowired
  51. private ExamSiteCacheService examSiteCacheService;
  52. @Autowired
  53. private ExamRoomService examRoomService;
  54. @Autowired
  55. private ConcurrentService concurrentService;
  56. @Autowired
  57. private ExamSiteService examSiteService;
  58. @Override
  59. public List<TimePeriodExamSiteVo> ListDetail(LoginUser loginUser, Long examRoomId) {
  60. //获取当前机构
  61. OrgInfo org = orgCacheService.currentOrg();
  62. if (org == null) {
  63. log.warn("[考场排班设置列表]未找到当前机构");
  64. return Collections.emptyList();
  65. }
  66. //判断考场是否存在
  67. ExamRoomEntity examRoom = examRoomService.getById(examRoomId);
  68. if (examRoom == null) {
  69. log.warn("[考场排班设置列表]未找到考场:{}", examRoomId);
  70. return Collections.emptyList();
  71. }
  72. //教学点管理员权限限制
  73. ExamSiteCacheBean examSite = examSiteCacheService.getExamSiteById(examRoom.getExamSiteId());
  74. if (examSite == null) {
  75. log.warn("[考场排班设置列表]考场:{}未找到所属考点", examRoomId);
  76. return Collections.emptyList();
  77. }
  78. if (loginUser.getRole().equals(Role.TEACHING) && !loginUser.getCategoryId().equals(examSite.getCategoryId())) {
  79. return Collections.emptyList();
  80. }
  81. //获取当前任务
  82. CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(org.getOrgId());
  83. if (curApplyTask == null) {
  84. log.warn("[考场排班设置列表]机构:{},当前未有启用的任务", org.getOrgId());
  85. return Collections.emptyList();
  86. }
  87. // 所有的预约日期
  88. List<String> dateList = timePeriodService.listTimePeriodDate(curApplyTask.getTaskId());
  89. if (CollectionUtils.isEmpty(dateList)) {
  90. log.warn("[考场排班设置列表]当前任务:{}未设置预约日期", curApplyTask.getTaskId());
  91. return Collections.emptyList();
  92. }
  93. //教学点管理员设置的所有的考点时段
  94. List<TimePeriodExamSiteBean> timePeriodExamRoomList = timePeriodService.listTimePeriodByExamRoomId(curApplyTask.getTaskId(), examRoomId);
  95. //学校管理员设置的所有预约时段
  96. List<TimePeriodExamSiteBean> timePeriodList = timePeriodService.listTimePeriodByTask(curApplyTask.getTaskId());
  97. List<TimePeriodExamSiteBean> resultList;
  98. if (CollectionUtils.isEmpty(timePeriodExamRoomList)) {
  99. resultList = timePeriodList;
  100. } else {
  101. //取并集
  102. resultList = UnionUtil.unionByAttribute(timePeriodExamRoomList, timePeriodList, TimePeriodExamSiteBean::getTimePeriodId);
  103. }
  104. //按日期封装
  105. List<TimePeriodExamSiteVo> list = new ArrayList<>();
  106. for (String date : dateList) {
  107. TimePeriodExamSiteVo timePeriodVo = new TimePeriodExamSiteVo();
  108. timePeriodVo.setDateStr(getDateStr(date));
  109. timePeriodVo.setTimePeriodList(filterTimePeriod(date, resultList, curApplyTask.getAllowApplyCancelDays()));
  110. list.add(timePeriodVo);
  111. }
  112. return list;
  113. }
  114. private String getDateStr(String date) {
  115. if (StringUtils.isEmpty(date)) {
  116. return "";
  117. }
  118. String[] dateArr = date.split("-");
  119. if (dateArr.length != 3) {
  120. return "";
  121. }
  122. return dateArr[1] + "月" + dateArr[2] + "日";
  123. }
  124. private List<TimePeriodExamSiteInfo> filterTimePeriod(String date, List<TimePeriodExamSiteBean> timePeriodList, Integer canCancelDay) {
  125. // 参数校验
  126. if (timePeriodList == null || date == null || canCancelDay == null || canCancelDay < 0) {
  127. return new ArrayList<>();
  128. }
  129. List<TimePeriodExamSiteInfo> resultList = new ArrayList<>();
  130. // 过滤符合条件的时间段
  131. List<TimePeriodExamSiteBean> filteredTimePeriodList = timePeriodList.stream()
  132. .filter(item -> DateUtil.getShortDateByLongTime(item.getStartTime()).equals(date))
  133. .sorted(Comparator.comparing(TimePeriodExamSiteBean::getStartTime))
  134. .collect(Collectors.toList());
  135. // 计算可取消时间范围
  136. Long longToday = DateUtil.getLongTimeByDate(DateUtil.formatShortSplitDateString(new Date()) + " 00:00:00");
  137. Date today = new Date(longToday);
  138. Date otherDay = DateUtil.addValues(today, Calendar.DAY_OF_MONTH, canCancelDay);
  139. long longOtherDay = DateUtil.getLongTimeByDate(DateUtil.formatShortSplitDateString(otherDay) + " 23:59:59");
  140. // 当前时间
  141. long now = System.currentTimeMillis();
  142. for (TimePeriodExamSiteBean time : filteredTimePeriodList) {
  143. // 检查时间是否有效
  144. if (time.getStartTime() == null || time.getEndTime() == null) {
  145. continue; // 跳过无效时间段
  146. }
  147. TimePeriodExamSiteInfo bean = new TimePeriodExamSiteInfo();
  148. bean.setId(time.getId());
  149. bean.setTimePeriodId(time.getTimePeriodId());
  150. bean.setEnable(time.getEnable());
  151. bean.setTimePeriodStr(DateUtil.getStartToEndTime(time.getStartTime(), time.getEndTime()));
  152. // 判断是否可编辑
  153. boolean isEditable = isTimeEditable(now, time.getEndTime(), longOtherDay, time.getStartTime());
  154. bean.setEditable(isEditable);
  155. resultList.add(bean);
  156. }
  157. return resultList;
  158. }
  159. private boolean isTimeEditable(long now, long endTime, long longOtherDay, long startTime) {
  160. return !(endTime < now || startTime < longOtherDay);
  161. }
  162. @Transactional(isolation = Isolation.READ_COMMITTED)
  163. @Override
  164. public void save(Long userId, Long examRoomId, List<TimePeriodExamSiteReq> timePeriodExamRoomList) {
  165. if (concurrentService.isLocked(CacheConstants.LOCK_AUTO_APPLY)) {
  166. log.warn("[考场排班保存]系统自动预约中,不允许操作考场排班!lockKey:{}", CacheConstants.LOCK_AUTO_APPLY);
  167. throw new StatusException("系统正在自动预约中,不允许修改");
  168. }
  169. if (CollectionUtils.isEmpty(timePeriodExamRoomList)) {
  170. log.warn("[考场排班设置]时间段列表为空");
  171. throw new StatusException("保存失败,时间段列表为空");
  172. }
  173. try {
  174. // 获取当前机构
  175. OrgInfo org = orgCacheService.currentOrg();
  176. if (org == null) {
  177. log.warn("[考场排班设置]未找到当前机构");
  178. throw new StatusException("保存失败,未找到当前机构");
  179. }
  180. // 获取当前任务
  181. CurrentApplyTaskVO curApplyTask = applyTaskCacheService.currentApplyTask(org.getOrgId());
  182. if (curApplyTask == null) {
  183. log.warn("[考场排班设置]机构:{},当前未有启用的任务", org.getOrgId());
  184. throw new StatusException("保存失败,未有启用的任务");
  185. }
  186. // 校验考场信息
  187. ExamRoomEntity examRoom = examRoomService.getById(examRoomId);
  188. if (examRoom == null) {
  189. log.warn("[考场排班设置]未找到考场:{}", examRoomId);
  190. throw new StatusException("保存失败,未找到考场");
  191. }
  192. if (!examRoom.getEnable()) {
  193. log.warn("[考场排班设置]考场已被禁用:{}", examRoomId);
  194. throw new StatusException("保存失败,考场已被禁用");
  195. }
  196. // 校验考点信息
  197. ExamSiteCacheBean examSiteCacheBean = examSiteCacheService.getExamSiteById(examRoom.getExamSiteId());
  198. if (examSiteCacheBean == null) {
  199. log.warn("[考场排班设置]未找到考点:{}", examRoom.getExamSiteId());
  200. throw new StatusException("保存失败,未找到考点");
  201. }
  202. // 获取考场对应的所有时段
  203. List<TimePeriodExamSiteBean> timePeriodList = timePeriodService.listTimePeriodByExamRoomId(curApplyTask.getTaskId(), examRoomId);
  204. // 时段Map
  205. Map<Long, TimePeriodExamSiteBean> timePeriodMap = timePeriodList.stream()
  206. .collect(Collectors.toMap(TimePeriodExamSiteBean::getId, tp -> tp));
  207. //只处理可编辑的数据
  208. timePeriodExamRoomList = timePeriodExamRoomList.stream().filter(TimePeriodExamSiteReq::getEditable).collect(Collectors.toList());
  209. List<TimePeriodExamRoomEntity> timePeriodExamRoomEntityList = new ArrayList<>(timePeriodExamRoomList.size());
  210. if (CollectionUtils.isEmpty(timePeriodList)) {
  211. //是否可编辑判断
  212. List<Long> listTimePeriodIds = timePeriodExamRoomList.stream()
  213. .filter(item -> !item.getEnable()) //禁用
  214. .map(TimePeriodExamSiteReq::getTimePeriodId)
  215. .collect(Collectors.toList());
  216. canEdit(listTimePeriodIds, curApplyTask);
  217. handleFirstTimeSave(userId, examRoomId, timePeriodExamRoomList, timePeriodExamRoomEntityList, examRoom);
  218. } else {
  219. handleUpdateOrSave(userId, examRoomId, timePeriodExamRoomList, timePeriodExamRoomEntityList, timePeriodMap, examRoom, curApplyTask);
  220. }
  221. } catch (Exception e) {
  222. log.error("[考场排班设置]保存失败,原因:{}", e.getMessage(), e);
  223. throw new StatusException(e.getMessage());
  224. }
  225. }
  226. @Override
  227. public List<ExamRoomEntity> listExamRoom(Long examSiteId, Long timePeriodId, Boolean enable) {
  228. return getBaseMapper().listExamRoom(examSiteId, timePeriodId, enable);
  229. }
  230. @Override
  231. public List<TimePeriodExamRoomEntity> listExamRoom(Long examRoomId) {
  232. LambdaQueryWrapper<TimePeriodExamRoomEntity> wrapper = new LambdaQueryWrapper<>();
  233. wrapper.eq(TimePeriodExamRoomEntity::getExamRoomId, examRoomId);
  234. return list(wrapper);
  235. }
  236. @Override
  237. public int getExamSiteTimePeriodCapacity(Long examSiteId, Long timePeriodId) {
  238. // 判断考点是否存在
  239. ExamSiteCacheBean examSiteCacheBean = examSiteCacheService.getExamSiteById(examSiteId);
  240. if (examSiteCacheBean == null) {
  241. log.error("[获取考点时段可预约数量]考点不存在,examSiteId:{}", examSiteId);
  242. return 0;
  243. }
  244. // 判断时段是否存在
  245. TimePeriodEntity timePeriod = timePeriodService.getById(timePeriodId);
  246. if (timePeriod == null) {
  247. log.error("[获取考点时段可预约数量]时段不存在,timePeriodId:{}", timePeriodId);
  248. return 0;
  249. }
  250. // 获取考点对应的所有考场
  251. List<ExamRoomEntity> examRoomList = examRoomService.listExamRoom(examSiteId);
  252. if (examRoomList.isEmpty()) {
  253. return 0;
  254. }
  255. // 获取所有考场ids
  256. List<Long> examRoomIds = examRoomList.stream()
  257. .map(ExamRoomEntity::getId)
  258. .collect(Collectors.toList());
  259. List<TimePeriodExamRoomEntity> periodList = getBaseMapper().listByExamRoomIdsAndTimePeriodId(examRoomIds, timePeriodId);
  260. Map<Long, Boolean> enableMap = new HashMap<>();
  261. for (TimePeriodExamRoomEntity entity : periodList) {
  262. enableMap.put(entity.getExamRoomId(), entity.getEnable());
  263. }
  264. // 计算启用状态下的考场总容量
  265. return examRoomList.stream()
  266. .filter(examRoom -> {
  267. Boolean enabled = enableMap.get(examRoom.getId());
  268. return enabled == null || enabled; // 默认启用
  269. })
  270. .mapToInt(ExamRoomEntity::getCapacity)
  271. .sum();
  272. }
  273. private TimePeriodExamRoomEntity getTimePeriodExamRoomEntity(Long examRoomId, Long timePeriodId) {
  274. LambdaQueryWrapper<TimePeriodExamRoomEntity> queryWrapper = new LambdaQueryWrapper<>();
  275. queryWrapper.eq(TimePeriodExamRoomEntity::getExamRoomId, examRoomId);
  276. queryWrapper.eq(TimePeriodExamRoomEntity::getTimePeriodId, timePeriodId);
  277. return getOne(queryWrapper);
  278. }
  279. // 校验是否可编辑
  280. private void canEdit(List<Long> timePeriodExamRoomList, CurrentApplyTaskVO curApplyTask) {
  281. if (CollectionUtils.isNotEmpty(timePeriodExamRoomList)) {
  282. Long longToday = DateUtil.getLongTimeByDate(DateUtil.formatShortSplitDateString(new Date()) + " 00:00:00");
  283. Date today = new Date(longToday);
  284. Date otherDay = DateUtil.addValues(today, Calendar.DAY_OF_MONTH, curApplyTask.getAllowApplyCancelDays());
  285. long longOtherDay = DateUtil.getLongTimeByDate(DateUtil.formatShortSplitDateString(otherDay) + " 23:59:59");
  286. // 当前时间
  287. long now = System.currentTimeMillis();
  288. List<TimePeriodEntity> timePeriodEntities = timePeriodService.listByIds(timePeriodExamRoomList);
  289. Map<Long, TimePeriodEntity> timePeriodEntityMap = timePeriodEntities.stream()
  290. .collect(Collectors.toMap(TimePeriodEntity::getId, tpe -> tpe));
  291. for (Long timePeriodId : timePeriodExamRoomList) {
  292. TimePeriodEntity timePeriod = timePeriodEntityMap.get(timePeriodId);
  293. if (!isTimeEditable(now, timePeriod.getEndTime(), longOtherDay, timePeriod.getStartTime())) {
  294. throw new StatusException("保存失败," + DateUtil.getShortDateByLongTime(timePeriod.getStartTime()) + "可编辑时间范围已过");
  295. }
  296. }
  297. }
  298. }
  299. private void handleFirstTimeSave(Long userId, Long examRoomId, List<TimePeriodExamSiteReq> timePeriodExamRoomList,
  300. List<TimePeriodExamRoomEntity> timePeriodExamRoomEntityList, ExamRoomEntity examRoom) {
  301. timePeriodExamRoomList.forEach(item -> {
  302. TimePeriodExamRoomEntity entity = createTimePeriodExamRoomEntity(item, examRoomId, userId);
  303. timePeriodExamRoomEntityList.add(entity);
  304. });
  305. saveBatch(timePeriodExamRoomEntityList);
  306. //刷新缓存
  307. refreshDisableTimePeriodCache(timePeriodExamRoomEntityList, examRoom);
  308. }
  309. private void handleUpdateOrSave(Long userId, Long examRoomId, List<TimePeriodExamSiteReq> timePeriodExamRoomList,
  310. List<TimePeriodExamRoomEntity> timePeriodExamRoomEntityList,
  311. Map<Long, TimePeriodExamSiteBean> timePeriodMap, ExamRoomEntity examRoom, CurrentApplyTaskVO curApplyTask) {
  312. List<TimePeriodExamRoomEntity> toBeSaveList = new ArrayList<>();
  313. List<TimePeriodExamRoomEntity> toBeUpdateList = new ArrayList<>();
  314. timePeriodExamRoomList.forEach(item -> {
  315. TimePeriodExamRoomEntity entity = createTimePeriodExamRoomEntity(item, examRoomId, userId);
  316. timePeriodExamRoomEntityList.add(entity);
  317. if (item.getId() == null) {
  318. toBeSaveList.add(entity);
  319. } else {
  320. toBeUpdateList.add(entity);
  321. }
  322. });
  323. //新增的记录
  324. List<Long> resultList = new ArrayList<>();
  325. for(TimePeriodExamRoomEntity item : toBeSaveList) {
  326. resultList.add(item.getTimePeriodId());
  327. }
  328. //更新的记录,值有变化
  329. for (TimePeriodExamRoomEntity item : toBeUpdateList) {
  330. TimePeriodExamSiteBean timePeriod = timePeriodMap.get(item.getId());
  331. if(timePeriod != null && !timePeriod.getEnable().equals(item.getEnable())) {
  332. resultList.add(item.getTimePeriodId());
  333. }
  334. }
  335. // 判断考场+时段是否在库中已经存在
  336. if (CollectionUtils.isNotEmpty(toBeSaveList)) {
  337. // 提取所有要检查的examRoomId和timePeriodId组合
  338. List<Long> examRoomIds = toBeSaveList.stream()
  339. .map(TimePeriodExamRoomEntity::getExamRoomId)
  340. .distinct()
  341. .collect(Collectors.toList());
  342. List<Long> timePeriodIds = toBeSaveList.stream()
  343. .map(TimePeriodExamRoomEntity::getTimePeriodId)
  344. .distinct()
  345. .collect(Collectors.toList());
  346. // 批量查询已存在的记录
  347. List<TimePeriodExamRoomEntity> existingRecords = getBaseMapper().listByExamRoomIdsAndTimePeriodIds(examRoomIds, timePeriodIds);
  348. // 构建已存在的记录集合,用于快速查找
  349. Set<String> existingKeySet = existingRecords.stream()
  350. .map(e -> e.getExamRoomId() + "-" + e.getTimePeriodId())
  351. .collect(Collectors.toSet());
  352. // 检查是否有重复的记录
  353. for (TimePeriodExamRoomEntity item : toBeSaveList) {
  354. String key = item.getExamRoomId() + "-" + item.getTimePeriodId();
  355. if (existingKeySet.contains(key)) {
  356. log.error("[考场排班设置]保存失败,该时间段已存在: examRoomId={}, timePeriodId={}", item.getExamRoomId(), item.getTimePeriodId());
  357. throw new StatusException("保存失败,该时间段已存在");
  358. }
  359. }
  360. }
  361. canEdit(resultList, curApplyTask);
  362. saveOrUpdateBatch(timePeriodExamRoomEntityList);
  363. //新增的记录,刷新缓存,只考虑禁用的情况
  364. refreshDisableTimePeriodCache(toBeSaveList, examRoom);
  365. //更新的记录,刷新缓存
  366. refreshUpdatedTimePeriodCache(toBeUpdateList, timePeriodMap, examRoom);
  367. }
  368. private TimePeriodExamRoomEntity createTimePeriodExamRoomEntity(TimePeriodExamSiteReq item, Long examRoomId, Long userId) {
  369. TimePeriodExamRoomEntity entity = new TimePeriodExamRoomEntity();
  370. BeanUtils.copyProperties(item, entity);
  371. entity.setExamRoomId(examRoomId);
  372. entity.setOperateId(userId);
  373. return entity;
  374. }
  375. private void refreshDisableTimePeriodCache(List<TimePeriodExamRoomEntity> disableList, ExamRoomEntity examRoom) {
  376. disableList.stream()
  377. .filter(item -> !item.getEnable())
  378. .forEach(item -> {
  379. String examSiteTimePeriodLockKey = String.format(CacheConstants.LOCK_EXAM_SITE_TIME_PERIOD, examRoom.getExamSiteId(),
  380. item.getTimePeriodId());
  381. RLock examSiteTimePeriodLock = (RLock) concurrentService.getLock(examSiteTimePeriodLockKey);
  382. try {
  383. if (!examSiteTimePeriodLock.tryLock()) {
  384. log.warn("[考场排班设置] 获取锁失败,不能同时修改考场排班设置, lockKey:{}", examSiteTimePeriodLock);
  385. throw new StatusException("考场排班保存失败,请稍后再试");
  386. } else {
  387. // 更新容量缓存,禁用需要减考场容量
  388. applyTaskCacheService.refreshApplyAvailableCountCache(
  389. examRoom.getExamSiteId(),
  390. item.getTimePeriodId(),
  391. // examSite.getCapacity(),
  392. // examSite.getCapacity()- examRoom.getCapacity()
  393. examRoom.getCapacity(),
  394. 0
  395. );
  396. }
  397. } catch (Exception e) {
  398. log.error("[考场排班设置] 考场排班失败, msg:{}", e.getMessage());
  399. throw new StatusException("考场排班保存失败,请稍后再试");
  400. } finally {
  401. try {
  402. if (examSiteTimePeriodLock.isLocked() && examSiteTimePeriodLock.isHeldByCurrentThread()) {
  403. examSiteTimePeriodLock.unlock();
  404. log.info("[考场排班设置] 解锁成功,lockKey:{}", examSiteTimePeriodLock);
  405. }
  406. } catch (Exception e) {
  407. log.warn(e.getMessage());
  408. }
  409. }
  410. });
  411. }
  412. private void refreshUpdatedTimePeriodCache(List<TimePeriodExamRoomEntity> updateList,
  413. Map<Long, TimePeriodExamSiteBean> timePeriodMap, ExamRoomEntity examRoom) {
  414. updateList.forEach(item -> {
  415. TimePeriodExamSiteBean timePeriod = timePeriodMap.get(item.getId());
  416. String examSiteTimePeriodLockKey = String.format(CacheConstants.LOCK_EXAM_SITE_TIME_PERIOD, examRoom.getExamSiteId(),
  417. item.getTimePeriodId());
  418. RLock examSiteTimePeriodLock = (RLock) concurrentService.getLock(examSiteTimePeriodLockKey);
  419. try {
  420. if (!examSiteTimePeriodLock.tryLock()) {
  421. log.warn("[考场排班设置] 获取锁失败,不能同时修改考场排班设置, lockKey:{}", examSiteTimePeriodLock);
  422. throw new StatusException("考场排班保存失败,请稍后再试");
  423. } else {
  424. //由启用变为禁用,缓存容量=-考场的容量
  425. if (timePeriod != null && Boolean.TRUE.equals(timePeriod.getEnable()) && !item.getEnable()) {
  426. // 更新容量缓存
  427. applyTaskCacheService.refreshApplyAvailableCountCache(
  428. examRoom.getExamSiteId(),
  429. timePeriod.getTimePeriodId(),
  430. // examSite.getCapacity(),
  431. // examSite.getCapacity() - examRoom.getCapacity()
  432. examRoom.getCapacity(),
  433. 0
  434. );
  435. }
  436. //由禁用变为启用,缓存容量=+考场的容量
  437. if (timePeriod != null && Boolean.FALSE.equals(timePeriod.getEnable()) && item.getEnable()) {
  438. //更新容量缓存
  439. applyTaskCacheService.refreshApplyAvailableCountCache(
  440. examRoom.getExamSiteId(),
  441. timePeriod.getTimePeriodId(),
  442. // examSite.getCapacity(),
  443. // examSite.getCapacity() + examRoom.getCapacity()
  444. 0,
  445. examRoom.getCapacity()
  446. );
  447. }
  448. }
  449. } catch (Exception e) {
  450. log.error("[考场排班设置] 考场排班失败, msg:{}", e.getMessage());
  451. throw new StatusException("考场排班保存失败,请稍后再试");
  452. } finally {
  453. try {
  454. if (examSiteTimePeriodLock.isLocked() && examSiteTimePeriodLock.isHeldByCurrentThread()) {
  455. examSiteTimePeriodLock.unlock();
  456. log.info("[考场排班设置] 解锁成功,lockKey:{}", examSiteTimePeriodLock);
  457. }
  458. } catch (Exception e) {
  459. log.warn(e.getMessage());
  460. }
  461. }
  462. });
  463. }
  464. }