修复后端bug,更新测试数据
This commit was merged in pull request #36.
This commit is contained in:
+7
-2
@@ -40,6 +40,10 @@ public interface GroupCourseDao extends R2dbcRepository<GroupCourseEntity, Long>
|
||||
@Query("UPDATE group_course SET deleted_at = :deletedAt WHERE id = :id")
|
||||
Mono<Integer> softDelete(Long id, LocalDateTime deletedAt);
|
||||
|
||||
@Modifying
|
||||
@Query("UPDATE group_course SET status = '2', updated_at = :updatedAt WHERE status = '0' AND end_time <= NOW() AND deleted_at IS NULL")
|
||||
Mono<Integer> completeExpiredCourses(LocalDateTime updatedAt);
|
||||
|
||||
Flux<GroupCourseEntity> findByCourseTypeAndDeletedAtIsNull(Long courseType);
|
||||
|
||||
/**
|
||||
@@ -49,8 +53,9 @@ public interface GroupCourseDao extends R2dbcRepository<GroupCourseEntity, Long>
|
||||
StringBuilder sql = new StringBuilder("SELECT * FROM group_course WHERE deleted_at IS NULL");
|
||||
List<String> conditions = new ArrayList<>();
|
||||
|
||||
// 默认不查询不可预约的团课(仅查询 status = '0')
|
||||
// 默认不查询可预约团课(status = '0' 且未过期)
|
||||
conditions.add("status = '0'");
|
||||
conditions.add("end_time > NOW()");
|
||||
|
||||
// 1. 团课名称模糊查询
|
||||
if (query.getCourseName() != null && !query.getCourseName().isEmpty()) {
|
||||
@@ -154,7 +159,6 @@ public interface GroupCourseDao extends R2dbcRepository<GroupCourseEntity, Long>
|
||||
entity.setLocation(row.get("location", String.class));
|
||||
entity.setCoverImage(row.get("cover_image", String.class));
|
||||
entity.setDescription(row.get("description", String.class));
|
||||
entity.setPointCardAmount(row.get("point_card_amount", Integer.class));
|
||||
entity.setStoredValueAmount(row.get("stored_value_amount", java.math.BigDecimal.class));
|
||||
entity.setCreateBy(row.get("create_by", String.class));
|
||||
entity.setUpdateBy(row.get("update_by", String.class));
|
||||
@@ -173,6 +177,7 @@ public interface GroupCourseDao extends R2dbcRepository<GroupCourseEntity, Long>
|
||||
List<String> conditions = new ArrayList<>();
|
||||
|
||||
conditions.add("status = '0'");
|
||||
conditions.add("end_time > NOW()");
|
||||
|
||||
if (query.getCourseName() != null && !query.getCourseName().isEmpty()) {
|
||||
conditions.add("course_name ILIKE :courseName");
|
||||
|
||||
-12
@@ -52,10 +52,6 @@ public class GroupCourse extends BaseDomain{
|
||||
@Schema(description = "课程描述", example = "从入门到入土")
|
||||
private String description;
|
||||
|
||||
//点卡额度(消耗次数)
|
||||
@Schema(description = "点卡额度(消耗次数)", example = "1")
|
||||
private Integer pointCardAmount;
|
||||
|
||||
//储值卡额度(消耗金额)
|
||||
@Schema(description = "储值卡额度(消耗金额)", example = "50.00")
|
||||
private java.math.BigDecimal storedValueAmount;
|
||||
@@ -152,14 +148,6 @@ public class GroupCourse extends BaseDomain{
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Integer getPointCardAmount() {
|
||||
return pointCardAmount;
|
||||
}
|
||||
|
||||
public void setPointCardAmount(Integer pointCardAmount) {
|
||||
this.pointCardAmount = pointCardAmount;
|
||||
}
|
||||
|
||||
public java.math.BigDecimal getStoredValueAmount() {
|
||||
return storedValueAmount;
|
||||
}
|
||||
|
||||
-11
@@ -48,9 +48,6 @@ public class GroupCourseDetail extends BaseDomain {
|
||||
@Schema(description = "课程描述", example = "适合初学者的瑜伽课程")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "点卡额度(消耗次数)", example = "1")
|
||||
private Integer pointCardAmount;
|
||||
|
||||
@Schema(description = "储值卡额度(消耗金额)", example = "50.00")
|
||||
private BigDecimal storedValueAmount;
|
||||
|
||||
@@ -174,14 +171,6 @@ public class GroupCourseDetail extends BaseDomain {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Integer getPointCardAmount() {
|
||||
return pointCardAmount;
|
||||
}
|
||||
|
||||
public void setPointCardAmount(Integer pointCardAmount) {
|
||||
this.pointCardAmount = pointCardAmount;
|
||||
}
|
||||
|
||||
public BigDecimal getStoredValueAmount() {
|
||||
return storedValueAmount;
|
||||
}
|
||||
|
||||
-12
@@ -54,10 +54,6 @@ public class GroupCourseEntity extends BaseEntity {
|
||||
@Column("description")
|
||||
private String description;
|
||||
|
||||
//点卡额度(消耗次数)
|
||||
@Column("point_card_amount")
|
||||
private Integer pointCardAmount;
|
||||
|
||||
//储值卡额度(消耗金额)
|
||||
@Column("stored_value_amount")
|
||||
private java.math.BigDecimal storedValueAmount;
|
||||
@@ -154,14 +150,6 @@ public class GroupCourseEntity extends BaseEntity {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Integer getPointCardAmount() {
|
||||
return pointCardAmount;
|
||||
}
|
||||
|
||||
public void setPointCardAmount(Integer pointCardAmount) {
|
||||
this.pointCardAmount = pointCardAmount;
|
||||
}
|
||||
|
||||
public java.math.BigDecimal getStoredValueAmount() {
|
||||
return storedValueAmount;
|
||||
}
|
||||
|
||||
+4
-3
@@ -109,8 +109,8 @@ public class BookingSagaHandler {
|
||||
|
||||
switch (cardType) {
|
||||
case COUNT_CARD:
|
||||
// 次卡扣除次数
|
||||
return deductCardUsage(recordId, 1, 0.0);
|
||||
// 次数卡不再支持团课预约
|
||||
return Mono.error(new RuntimeException("团课预约仅支持储值卡支付"));
|
||||
case STORED_VALUE_CARD:
|
||||
// 储值卡扣除金额
|
||||
return deductCardUsage(recordId, 0, DEFAULT_GROUP_COURSE_PRICE);
|
||||
@@ -168,7 +168,8 @@ public class BookingSagaHandler {
|
||||
|
||||
switch (cardType) {
|
||||
case COUNT_CARD:
|
||||
return restoreCardUsage(recordId, 1, 0.0);
|
||||
// 次数卡不再支持团课预约,无需恢复
|
||||
return Mono.empty();
|
||||
case STORED_VALUE_CARD:
|
||||
return restoreCardUsage(recordId, 0, DEFAULT_GROUP_COURSE_PRICE);
|
||||
case TIME_CARD:
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package cn.novalon.gym.manage.groupcourse.scheduler;
|
||||
|
||||
import cn.novalon.gym.manage.groupcourse.dao.GroupCourseDao;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 团课过期状态自动更新定时任务
|
||||
*
|
||||
* 功能:定期检查已过期的团课(end_time <= NOW()),自动将 status 从 0 更新为 2(已结束)
|
||||
*
|
||||
* @date 2026-06-24
|
||||
*/
|
||||
@Component
|
||||
public class GroupCourseExpireScheduler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(GroupCourseExpireScheduler.class);
|
||||
|
||||
private final GroupCourseDao groupCourseDao;
|
||||
|
||||
public GroupCourseExpireScheduler(GroupCourseDao groupCourseDao) {
|
||||
this.groupCourseDao = groupCourseDao;
|
||||
}
|
||||
|
||||
/**
|
||||
* 每分钟检查一次,将已过期但状态仍为 0 的团课标记为已结束(status = 2)
|
||||
*/
|
||||
@Scheduled(fixedRate = 60000)
|
||||
public void completeExpiredCourses() {
|
||||
logger.debug("定时任务开始检查已过期团课,更新状态为已结束");
|
||||
|
||||
groupCourseDao.completeExpiredCourses(LocalDateTime.now())
|
||||
.subscribe(
|
||||
count -> {
|
||||
if (count > 0) {
|
||||
logger.info("定时任务完成,更新了 {} 条过期团课状态为已结束", count);
|
||||
}
|
||||
},
|
||||
error -> logger.error("过期团课状态更新定时任务执行失败:{}", error.getMessage(), error)
|
||||
);
|
||||
}
|
||||
}
|
||||
+8
-15
@@ -155,7 +155,6 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
detail.setLocation(course.getLocation());
|
||||
detail.setCoverImage(course.getCoverImage());
|
||||
detail.setDescription(course.getDescription());
|
||||
detail.setPointCardAmount(course.getPointCardAmount());
|
||||
detail.setStoredValueAmount(course.getStoredValueAmount());
|
||||
detail.setQrCodePath(course.getQrCodePath());
|
||||
detail.setCreatedAt(course.getCreatedAt());
|
||||
@@ -342,9 +341,6 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
if (groupCourse.getDescription() != null) {
|
||||
existing.setDescription(groupCourse.getDescription());
|
||||
}
|
||||
if (groupCourse.getPointCardAmount() != null) {
|
||||
existing.setPointCardAmount(groupCourse.getPointCardAmount());
|
||||
}
|
||||
if (groupCourse.getStoredValueAmount() != null) {
|
||||
existing.setStoredValueAmount(groupCourse.getStoredValueAmount());
|
||||
}
|
||||
@@ -400,12 +396,11 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
return groupCourseRepository.findByIdAndDeletedAtIsNull(courseId)
|
||||
.switchIfEmpty(Mono.error(new RuntimeException("课程不存在")))
|
||||
.flatMap(course -> {
|
||||
Integer pointCardAmount = course.getPointCardAmount() != null ? course.getPointCardAmount() : 1;
|
||||
Double storedValueAmount = course.getStoredValueAmount() != null ?
|
||||
course.getStoredValueAmount().doubleValue() : DEFAULT_GROUP_COURSE_PRICE;
|
||||
|
||||
logger.info("课程权益信息: courseId={}, pointCardAmount={}, storedValueAmount={}",
|
||||
courseId, pointCardAmount, storedValueAmount);
|
||||
logger.info("课程权益信息: courseId={}, storedValueAmount={}",
|
||||
courseId, storedValueAmount);
|
||||
|
||||
return bookingRepository.findByCourseId(courseId)
|
||||
.filter(booking -> "0".equals(booking.getStatus())) // 只处理已预约状态的记录
|
||||
@@ -416,8 +411,8 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
// 根据会员卡类型返还权益
|
||||
return refundCardUsage(booking.getId(), memberCardRecordId, pointCardAmount, storedValueAmount)
|
||||
// 根据会员卡类型返还权益(仅储值卡返还金额)
|
||||
return refundCardUsage(booking.getId(), memberCardRecordId, storedValueAmount)
|
||||
.doOnSuccess(unused -> logger.info("会员权益返还成功: bookingId={}, memberId={}",
|
||||
booking.getId(), booking.getMemberId()))
|
||||
.doOnError(error -> logger.error("会员权益返还失败: bookingId={}, memberId={}, error={}",
|
||||
@@ -433,11 +428,10 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
*
|
||||
* @param bookingId 预约ID
|
||||
* @param recordId 会员卡记录ID
|
||||
* @param pointCardAmount 次卡返还次数
|
||||
* @param storedValueAmount 储值卡返还金额
|
||||
* @return 空Mono
|
||||
*/
|
||||
private Mono<Void> refundCardUsage(Long bookingId, Long recordId, Integer pointCardAmount, Double storedValueAmount) {
|
||||
private Mono<Void> refundCardUsage(Long bookingId, Long recordId, Double storedValueAmount) {
|
||||
return memberCardRecordService.findById(recordId)
|
||||
.switchIfEmpty(Mono.error(new RuntimeException("会员卡记录不存在")))
|
||||
.flatMap(record -> {
|
||||
@@ -448,10 +442,9 @@ public class GroupCourseService implements IGroupCourseService {
|
||||
Mono<Void> refundOperation;
|
||||
switch (cardType) {
|
||||
case COUNT_CARD:
|
||||
// 次卡返还次数(基于课程设置的pointCardAmount)
|
||||
logger.debug("返还次卡次数: recordId={}, amount={}", recordId, pointCardAmount);
|
||||
refundOperation = memberCardRecordService.renewCard(recordId, pointCardAmount, 0.0, record.getExpireTime())
|
||||
.then(Mono.empty());
|
||||
// 次卡不再支持团课预约,无需返还
|
||||
logger.debug("次卡不返还权益: bookingId={}", bookingId);
|
||||
refundOperation = Mono.empty();
|
||||
break;
|
||||
case STORED_VALUE_CARD:
|
||||
// 储值卡返还金额(基于课程设置的storedValueAmount)
|
||||
|
||||
Reference in New Issue
Block a user