Browse Source

会员营期模块:若中间课程删减,后续课程的播课时间自动依次上移,保持时间连贯

zyy 1 week ago
parent
commit
a8e245052f

+ 15 - 0
fs-service/src/main/java/com/fs/course/mapper/FsUserCoursePeriodDaysMapper.java

@@ -122,4 +122,19 @@ public interface FsUserCoursePeriodDaysMapper extends BaseMapper<FsUserCoursePer
 
     @Select("SELECT distinct period_id from fs_user_course_period_days  where start_date_time >=#{periodSTime} and end_date_time <=#{periodETime} ")
     List<Long> selectFsUserCoursePeriodDaysByTime(@Param("periodSTime") String periodSTime,@Param("periodETime") String periodETime);
+
+    /**
+     * 批量查询多个periodId下最早的一条数据
+     */
+    List<FsUserCoursePeriodDays> selectFirstByPeriodIds(@Param("periodIds") List<Long> periodIds);
+
+    /**
+     * 批量查询多个periodId的所有数据
+     */
+    List<FsUserCoursePeriodDays> selectByPeriodIds(@Param("periodIds") List<Long> periodIds);
+
+    /**
+     * 批量更新日期时间字段
+     */
+    int batchUpdateDateTime(@Param("list") List<FsUserCoursePeriodDays> list);
 }

+ 141 - 4
fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodDaysServiceImpl.java

@@ -126,17 +126,154 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
     {
         int flag = 0;
         List<FsUserCoursePeriodDays> fsUserCoursePeriodDays = fsUserCoursePeriodDaysMapper.selectBatchIds(Arrays.asList(ids));
+        if(fsUserCoursePeriodDays.isEmpty()) {
+            return flag;
+        }
+        // 获取要删除的数据信息
         List<Long> periodDayIds = fsUserCoursePeriodDays.stream().map(FsUserCoursePeriodDays::getId).collect(Collectors.toList());
-        List<Long> getPeriodIds = fsUserCoursePeriodDays.stream().map(FsUserCoursePeriodDays::getPeriodId).collect(Collectors.toList());
-        List<Long> videoIds = fsUserCoursePeriodDays.stream().map(FsUserCoursePeriodDays::getVideoId).collect(Collectors.toList());
+        List<Long> videoIds = fsUserCoursePeriodDays.stream().map(FsUserCoursePeriodDays::getVideoId).filter(Objects::nonNull).collect(Collectors.toList());
+        Map<Long, List<FsUserCoursePeriodDays>> groupedByPeriodId = fsUserCoursePeriodDays.stream().collect(Collectors.groupingBy(FsUserCoursePeriodDays::getPeriodId));
+
+        //批量查询所有涉及periodId的第一条数据
+        Set<Long> distinctPeriodIds = groupedByPeriodId.keySet();
+        Map<Long, FsUserCoursePeriodDays> firstDataMap = getFirstDataMap(new ArrayList<>(distinctPeriodIds));
+
+        //批量查询所有periodId的所有数据
+        Map<Long, List<FsUserCoursePeriodDays>> allPeriodDataMap = getAllPeriodDataMap(new ArrayList<>(distinctPeriodIds));
+
+        //用于存储所有需要更新的数据
+        List<FsUserCoursePeriodDays> allToUpdate = new ArrayList<>();
+
+        for(Map.Entry<Long, List<FsUserCoursePeriodDays>> entry : groupedByPeriodId.entrySet()) {
+            Long periodId = entry.getKey();
+            List<FsUserCoursePeriodDays> toDeleteList = entry.getValue();
+
+            //按dayDate排序要删除的数据
+            toDeleteList.sort(Comparator.comparing(FsUserCoursePeriodDays::getDayDate));
+
+            // 获取该periodId下所有未删除的数据
+            List<FsUserCoursePeriodDays> allPeriodData = allPeriodDataMap.get(periodId);
+            if(allPeriodData == null || allPeriodData.isEmpty()) {
+                continue;
+            }
+
+            //创建要删除数据的ID集合
+            Set<Long> toDeleteIds = toDeleteList.stream()
+                    .map(FsUserCoursePeriodDays::getId)
+                    .collect(Collectors.toSet());
+
+            //如果所有数据都要被删除,则跳过日期更新
+            if(allPeriodData.stream().allMatch(d -> toDeleteIds.contains(d.getId()))) {
+                continue;
+            }
+
+            //从Map中获取这个periodId的原始第一条数据
+            FsUserCoursePeriodDays firstOriginalData = firstDataMap.get(periodId);
+            if(firstOriginalData == null) {
+                // 如果没有第一条数据,使用剩余数据的第一条
+                firstOriginalData = allPeriodData.stream().filter(d -> !toDeleteIds.contains(d.getId())).findFirst().orElse(null);
+                if(firstOriginalData == null) {
+                    continue;
+                }
+            }
+            //构建删除后的剩余数据列表(保持原始顺序)
+            List<FsUserCoursePeriodDays> remainingData = allPeriodData.stream().filter(item -> !toDeleteIds.contains(item.getId()))
+                    .collect(Collectors.toList());
+
+            //计算需要更新的数据
+            List<FsUserCoursePeriodDays> toUpdate = calculateDateUpdates(remainingData,firstOriginalData);
+            allToUpdate.addAll(toUpdate);
+        }
+
+        //批量更新日期
+        if(!allToUpdate.isEmpty()) {
+            // 按ID去重,防止重复更新
+            List<FsUserCoursePeriodDays> distinctToUpdate = allToUpdate.stream()
+                    .collect(Collectors.collectingAndThen(
+                            Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(FsUserCoursePeriodDays::getId))),
+                            ArrayList::new
+                    ));
+            fsUserCoursePeriodDaysMapper.batchUpdateDateTime(distinctToUpdate);
+        }
+
+        //执行删除操作
         if(!periodDayIds.isEmpty()){
             flag = fsUserCoursePeriodDaysMapper.updateBatchDelFlag(periodDayIds.toArray(new Long[0]),1);
-            //删除红包记录
-            fsUserCourseVideoRedPackageMapper.deleteFsUserCourseVideoRedPackageByVedioIds(videoIds.toArray(new Long[0]),getPeriodIds.toArray(new Long[0]));
+            // 删除红包记录
+            if(!videoIds.isEmpty() && !distinctPeriodIds.isEmpty()) {
+                fsUserCourseVideoRedPackageMapper.deleteFsUserCourseVideoRedPackageByVedioIds(
+                        videoIds.toArray(new Long[0]),distinctPeriodIds.toArray(new Long[0]));
+            }
         }
         return flag;
     }
 
+    /**
+     * 批量查询第一条数据并转换为Map
+     */
+    private Map<Long, FsUserCoursePeriodDays> getFirstDataMap(List<Long> periodIds) {
+        if(periodIds == null || periodIds.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        List<FsUserCoursePeriodDays> firstDataList = fsUserCoursePeriodDaysMapper.selectFirstByPeriodIds(periodIds);
+        return firstDataList.stream()
+                .filter(Objects::nonNull)
+                .collect(Collectors.toMap(
+                        FsUserCoursePeriodDays::getPeriodId,
+                        Function.identity(),
+                        (existing, replacement) -> existing
+                ));
+    }
+
+    /**
+     * 批量查询所有periodId的数据并转换为Map
+     */
+    private Map<Long, List<FsUserCoursePeriodDays>> getAllPeriodDataMap(List<Long> periodIds) {
+        if(periodIds == null || periodIds.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        List<FsUserCoursePeriodDays> allData = fsUserCoursePeriodDaysMapper.selectByPeriodIds(periodIds);
+        return allData.stream().filter(Objects::nonNull).collect(Collectors.groupingBy(
+                        FsUserCoursePeriodDays::getPeriodId,Collectors.collectingAndThen(Collectors.toList(),
+                        list -> {list.sort(Comparator.comparing(FsUserCoursePeriodDays::getDayDate));
+                                    return list;
+                                }
+                        )
+                ));
+    }
+
+    /**
+     * 计算需要更新的数据
+     */
+    private List<FsUserCoursePeriodDays> calculateDateUpdates(List<FsUserCoursePeriodDays> remainingData,FsUserCoursePeriodDays firstOriginalData) {
+        List<FsUserCoursePeriodDays> toUpdate = new ArrayList<>();
+        if(remainingData.isEmpty() || firstOriginalData == null) {
+            return toUpdate;
+        }
+        LocalDate baseDate = firstOriginalData.getDayDate();
+        LocalDateTime baseStartDateTime = firstOriginalData.getStartDateTime();
+        LocalDateTime baseEndDateTime = firstOriginalData.getEndDateTime();
+
+        for(int i = 0; i < remainingData.size(); i++) {
+            FsUserCoursePeriodDays currentItem = remainingData.get(i);
+            // 计算期望的日期(基准日期 + i天)
+            LocalDate expectedDayDate = baseDate.plusDays(i);
+            LocalDateTime expectedStartDateTime = baseStartDateTime.plusDays(i);
+            LocalDateTime expectedEndDateTime = baseEndDateTime.plusDays(i);
+
+            // 如果当前日期不等于期望日期,则需要更新
+            if(!expectedDayDate.equals(currentItem.getDayDate()) || !expectedStartDateTime.equals(currentItem.getStartDateTime()) || !expectedEndDateTime.equals(currentItem.getEndDateTime())) {
+                FsUserCoursePeriodDays updateItem = new FsUserCoursePeriodDays();
+                updateItem.setId(currentItem.getId());
+                updateItem.setDayDate(expectedDayDate);
+                updateItem.setStartDateTime(expectedStartDateTime);
+                updateItem.setEndDateTime(expectedEndDateTime);
+                toUpdate.add(updateItem);
+            }
+        }
+        return toUpdate;
+    }
+
     /**
      * 删除营期课程信息
      *

+ 53 - 0
fs-service/src/main/resources/mapper/course/FsUserCoursePeriodDaysMapper.xml

@@ -239,4 +239,57 @@
         ORDER BY
             a.day_date
     </select>
+
+    <!-- 批量查询第一条数据 -->
+    <select id="selectFirstByPeriodIds" resultType="FsUserCoursePeriodDays">
+        SELECT t1.* FROM fs_user_course_period_days t1
+        INNER JOIN (
+        SELECT period_id, MIN(day_date) as min_date
+        FROM fs_user_course_period_days
+        WHERE period_id IN
+        <foreach collection="periodIds" item="periodId" open="(" separator="," close=")">
+            #{periodId}
+        </foreach>
+        AND del_flag = 0
+        GROUP BY period_id
+        ) t2 ON t1.period_id = t2.period_id AND t1.day_date = t2.min_date
+        WHERE t1.del_flag = 0
+    </select>
+
+    <!-- 批量查询所有数据 -->
+    <select id="selectByPeriodIds" resultType="FsUserCoursePeriodDays">
+        SELECT * FROM fs_user_course_period_days
+        WHERE period_id IN
+        <foreach collection="periodIds" item="periodId" open="(" separator="," close=")">
+            #{periodId}
+        </foreach>
+        AND del_flag = 0
+        ORDER BY period_id, day_date ASC
+    </select>
+
+    <update id="batchUpdateDateTime" parameterType="list">
+        UPDATE fs_user_course_period_days
+        SET
+        day_date = CASE id
+        <foreach collection="list" item="item">
+            WHEN #{item.id} THEN #{item.dayDate}
+        </foreach>
+        END,
+        start_date_time = CASE id
+        <foreach collection="list" item="item">
+            WHEN #{item.id} THEN #{item.startDateTime}
+        </foreach>
+        END,
+        end_date_time = CASE id
+        <foreach collection="list" item="item">
+            WHEN #{item.id} THEN #{item.endDateTime}
+        </foreach>
+        END
+        WHERE id IN
+        <foreach collection="list" item="item" open="(" separator="," close=")">
+            #{item.id}
+        </foreach>
+    </update>
+
+
 </mapper>