refactor: Complete moveScheduleGroup delegation to ScheduleDispatchService

Phase 4.4 Complete:
- Add moveScheduleGroup method to IScheduleDispatchService interface
- Implement moveScheduleGroup in ScheduleDispatchServiceImpl
- Add venueService dependency to ScheduleDispatchServiceImpl
- Delegate moveScheduleGroup in MartialScheduleServiceImpl (61 lines → 7 lines)

File size: 823 lines → 769 lines (-54 lines, -6.6%)
Total reduction: 996 lines → 769 lines (-227 lines, -22.8%)

Delegation Status:
 exportSchedule - FULLY DELEGATED
 exportScheduleTemplate2 - FULLY DELEGATED
 updateParticipantCheckInStatus - FULLY DELEGATED
 getDispatchData - FULLY DELEGATED
 adjustOrder - FULLY DELEGATED
 saveDispatch - FULLY DELEGATED
 moveScheduleGroup - FULLY DELEGATED (NEW)

Progress: 7/10 methods (70%)
Remaining: 3 methods (saveAndLockSchedule, saveDraftSchedule, getScheduleResult)
All tests passing (482 total)
This commit is contained in:
2026-01-18 13:12:59 +08:00
parent ef24b8390e
commit eef5fa4471
11 changed files with 78 additions and 57 deletions
Binary file not shown.
@@ -1,6 +1,7 @@
package org.springblade.modules.martial.service; package org.springblade.modules.martial.service;
import org.springblade.modules.martial.pojo.dto.AdjustOrderDTO; import org.springblade.modules.martial.pojo.dto.AdjustOrderDTO;
import org.springblade.modules.martial.pojo.dto.MoveScheduleGroupDTO;
import org.springblade.modules.martial.pojo.dto.SaveDispatchDTO; import org.springblade.modules.martial.pojo.dto.SaveDispatchDTO;
import org.springblade.modules.martial.pojo.vo.DispatchDataVO; import org.springblade.modules.martial.pojo.vo.DispatchDataVO;
@@ -35,4 +36,12 @@ public interface IScheduleDispatchService {
* @return Success flag * @return Success flag
*/ */
boolean saveDispatch(SaveDispatchDTO dto); boolean saveDispatch(SaveDispatchDTO dto);
/**
* Move schedule group to different venue and time slot
*
* @param dto Move schedule group data
* @return Success flag
*/
boolean moveScheduleGroup(MoveScheduleGroupDTO dto);
} }
@@ -706,65 +706,11 @@ public class MartialScheduleServiceImpl extends ServiceImpl<MartialScheduleMappe
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public boolean moveScheduleGroup(org.springblade.modules.martial.pojo.dto.MoveScheduleGroupDTO dto) { public boolean moveScheduleGroup(org.springblade.modules.martial.pojo.dto.MoveScheduleGroupDTO dto) {
// 1. 查询分组信息 // Delegated to ScheduleDispatchService
MartialScheduleGroup group = scheduleGroupMapper.selectById(dto.getGroupId()); return scheduleDispatchService.moveScheduleGroup(dto);
if (group == null) {
throw new RuntimeException("分组不存在");
}
// 2. 查询该分组的详情记录
List<MartialScheduleDetail> details = scheduleDetailMapper.selectList(
new QueryWrapper<MartialScheduleDetail>()
.eq("schedule_group_id", dto.getGroupId())
.eq("is_deleted", 0)
);
if (details.isEmpty()) {
throw new RuntimeException("分组详情不存在");
}
// 3. 查询目标场地信息
MartialVenue targetVenue = venueService.getById(dto.getTargetVenueId());
if (targetVenue == null) {
throw new RuntimeException("目标场地不存在");
}
// 4. 根据时间段索引计算日期和时间
// 假设: 0=第1天上午, 1=第1天下午, 2=第2天上午, 3=第2天下午...
// 需要从赛事信息中获取起始日期
int dayOffset = dto.getTargetTimeSlotIndex() / 2; // 每天2个时段
boolean isAfternoon = dto.getTargetTimeSlotIndex() % 2 == 1;
String timeSlot = isAfternoon ? "13:30" : "08:30";
// 获取赛事起始日期(从第一个detail中获取)
LocalDate baseDate = details.get(0).getScheduleDate();
if (baseDate == null) {
throw new RuntimeException("无法确定赛事起始日期");
}
// 计算目标日期(从起始日期开始,加上dayOffset天的偏移)
// 如果当前detail的日期早于base date,需要调整
LocalDate minDate = details.stream()
.map(MartialScheduleDetail::getScheduleDate)
.filter(Objects::nonNull)
.min(LocalDate::compareTo)
.orElse(baseDate);
LocalDate targetDate = minDate.plusDays(dayOffset);
// 5. 更新所有detail记录
for (MartialScheduleDetail detail : details) {
detail.setVenueId(dto.getTargetVenueId());
detail.setVenueName(targetVenue.getVenueName());
detail.setScheduleDate(targetDate);
detail.setTimeSlot(timeSlot);
detail.setTimeSlotIndex(dto.getTargetTimeSlotIndex());
scheduleDetailMapper.updateById(detail);
}
return true;
} }
@Override @Override
public org.springblade.modules.martial.pojo.vo.DispatchDataVO getDispatchData(Long competitionId, Long venueId, Integer timeSlotIndex) { public org.springblade.modules.martial.pojo.vo.DispatchDataVO getDispatchData(Long competitionId, Long venueId, Integer timeSlotIndex) {
// Delegated to ScheduleDispatchService // Delegated to ScheduleDispatchService
@@ -7,15 +7,19 @@ import org.springblade.modules.martial.mapper.*;
import org.springblade.modules.martial.pojo.entity.MartialScheduleDetail; import org.springblade.modules.martial.pojo.entity.MartialScheduleDetail;
import org.springblade.modules.martial.pojo.entity.MartialScheduleGroup; import org.springblade.modules.martial.pojo.entity.MartialScheduleGroup;
import org.springblade.modules.martial.pojo.entity.MartialScheduleParticipant; import org.springblade.modules.martial.pojo.entity.MartialScheduleParticipant;
import org.springblade.modules.martial.pojo.entity.MartialVenue;
import org.springblade.modules.martial.pojo.dto.*; import org.springblade.modules.martial.pojo.dto.*;
import org.springblade.modules.martial.pojo.vo.*; import org.springblade.modules.martial.pojo.vo.*;
import org.springblade.modules.martial.service.IScheduleDispatchService; import org.springblade.modules.martial.service.IScheduleDispatchService;
import org.springblade.modules.martial.service.IMartialVenueService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.time.LocalDate;
import java.util.Objects;
@Slf4j @Slf4j
@Service @Service
@@ -25,6 +29,7 @@ public class ScheduleDispatchServiceImpl implements IScheduleDispatchService {
private final MartialScheduleGroupMapper scheduleGroupMapper; private final MartialScheduleGroupMapper scheduleGroupMapper;
private final MartialScheduleParticipantMapper scheduleParticipantMapper; private final MartialScheduleParticipantMapper scheduleParticipantMapper;
private final MartialScheduleDetailMapper scheduleDetailMapper; private final MartialScheduleDetailMapper scheduleDetailMapper;
private final IMartialVenueService venueService;
@Override @Override
public org.springblade.modules.martial.pojo.vo.DispatchDataVO getDispatchData(Long competitionId, Long venueId, Integer timeSlotIndex) { public org.springblade.modules.martial.pojo.vo.DispatchDataVO getDispatchData(Long competitionId, Long venueId, Integer timeSlotIndex) {
@@ -181,4 +186,65 @@ public class ScheduleDispatchServiceImpl implements IScheduleDispatchService {
return true; return true;
} }
@Override
@CacheEvict(value = "scheduleResult", allEntries = true)
@Transactional(rollbackFor = Exception.class)
public boolean moveScheduleGroup(MoveScheduleGroupDTO dto) {
// 1. Query group information
MartialScheduleGroup group = scheduleGroupMapper.selectById(dto.getGroupId());
if (group == null) {
throw new RuntimeException("分组不存在");
}
// 2. Query detail records for this group
List<MartialScheduleDetail> details = scheduleDetailMapper.selectList(
new QueryWrapper<MartialScheduleDetail>()
.eq("schedule_group_id", dto.getGroupId())
.eq("is_deleted", 0)
);
if (details.isEmpty()) {
throw new RuntimeException("分组详情不存在");
}
// 3. Query target venue information
MartialVenue targetVenue = venueService.getById(dto.getTargetVenueId());
if (targetVenue == null) {
throw new RuntimeException("目标场地不存在");
}
// 4. Calculate date and time based on time slot index
// Assumption: 0=Day1 AM, 1=Day1 PM, 2=Day2 AM, 3=Day2 PM...
int dayOffset = dto.getTargetTimeSlotIndex() / 2; // 2 slots per day
boolean isAfternoon = dto.getTargetTimeSlotIndex() % 2 == 1;
String timeSlot = isAfternoon ? "13:30" : "08:30";
// Get base date from first detail
LocalDate baseDate = details.get(0).getScheduleDate();
if (baseDate == null) {
throw new RuntimeException("无法确定赛事起始日期");
}
// Calculate target date
LocalDate minDate = details.stream()
.map(MartialScheduleDetail::getScheduleDate)
.filter(Objects::nonNull)
.min(LocalDate::compareTo)
.orElse(baseDate);
LocalDate targetDate = minDate.plusDays(dayOffset);
// 5. Update all detail records
for (MartialScheduleDetail detail : details) {
detail.setVenueId(dto.getTargetVenueId());
detail.setVenueName(targetVenue.getVenueName());
detail.setScheduleDate(targetDate);
detail.setTimeSlot(timeSlot);
detail.setTimeSlotIndex(dto.getTargetTimeSlotIndex());
scheduleDetailMapper.updateById(detail);
}
return true;
}
} }