docs: reorganize documentation structure
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
package com.gym.manage.application.service;
|
||||
|
||||
import com.gym.manage.api.dto.request.BookingCreateRequest;
|
||||
import com.gym.manage.api.dto.response.BookingRecordResponse;
|
||||
import com.gym.manage.common.constant.ErrorCode;
|
||||
import com.gym.manage.common.exception.BusinessException;
|
||||
import com.gym.manage.domain.entity.BookingRecord;
|
||||
import com.gym.manage.domain.entity.BookingSlot;
|
||||
import com.gym.manage.domain.repository.BookingRecordRepository;
|
||||
import com.gym.manage.domain.repository.BookingSlotRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class BookingService {
|
||||
|
||||
private final BookingSlotRepository bookingSlotRepository;
|
||||
private final BookingRecordRepository bookingRecordRepository;
|
||||
|
||||
@Transactional
|
||||
public Mono<BookingRecordResponse> createBooking(BookingCreateRequest request) {
|
||||
log.info("创建预约: memberId={}, slotId={}", request.getMemberId(), request.getSlotId());
|
||||
|
||||
return validateAndBook(request)
|
||||
.map(this::toBookingRecordResponse)
|
||||
.doOnSuccess(response -> log.info("预约创建成功: bookingId={}", response.getId()))
|
||||
.doOnError(e -> log.error("预约创建失败: memberId={}, slotId={}, error={}",
|
||||
request.getMemberId(), request.getSlotId(), e.getMessage()));
|
||||
}
|
||||
|
||||
private Mono<BookingRecord> validateAndBook(BookingCreateRequest request) {
|
||||
return bookingSlotRepository.findByIdAndDeletedAtIsNull(request.getSlotId())
|
||||
.switchIfEmpty(Mono.error(new BusinessException(ErrorCode.SLOT_NOT_FOUND, "时段不存在")))
|
||||
.flatMap(slot -> {
|
||||
if (!"AVAILABLE".equals(slot.getStatus())) {
|
||||
return Mono.error(new BusinessException(ErrorCode.SLOT_NOT_AVAILABLE, "时段不可预约"));
|
||||
}
|
||||
|
||||
if (slot.getBookedCount() >= slot.getMaxCapacity()) {
|
||||
return Mono.error(new BusinessException(ErrorCode.SLOT_NOT_AVAILABLE, "时段已满"));
|
||||
}
|
||||
|
||||
return bookingRecordRepository.findByMemberIdAndSlotIdAndDeletedAtIsNull(
|
||||
request.getMemberId(), request.getSlotId()
|
||||
).flatMap(existing -> Mono.<BookingRecord>error(
|
||||
new BusinessException(ErrorCode.BOOKING_NOT_FOUND, "已预约该时段")
|
||||
)).switchIfEmpty(createBookingRecord(request, slot));
|
||||
});
|
||||
}
|
||||
|
||||
private Mono<BookingRecord> createBookingRecord(BookingCreateRequest request, BookingSlot slot) {
|
||||
return bookingSlotRepository.incrementBookedCount(request.getSlotId())
|
||||
.flatMap(rows -> {
|
||||
if (rows > 0) {
|
||||
BookingRecord record = new BookingRecord();
|
||||
record.setTenantId(slot.getTenantId());
|
||||
record.setStoreId(slot.getStoreId());
|
||||
record.setMemberId(request.getMemberId());
|
||||
record.setSlotId(request.getSlotId());
|
||||
record.setCoachId(slot.getCoachId());
|
||||
record.setCourseName(slot.getCourseName());
|
||||
record.setBookingTime(LocalDateTime.now());
|
||||
record.setStatus("BOOKED");
|
||||
record.setRemark(request.getRemark());
|
||||
record.setCreatedAt(LocalDateTime.now());
|
||||
record.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
return bookingRecordRepository.save(record);
|
||||
} else {
|
||||
return Mono.error(new BusinessException(ErrorCode.SLOT_NOT_AVAILABLE, "预约失败,请重试"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Mono<BookingRecordResponse> getBooking(Long id) {
|
||||
log.info("查询预约: bookingId={}", id);
|
||||
|
||||
return bookingRecordRepository.findByIdAndDeletedAtIsNull(id)
|
||||
.switchIfEmpty(Mono.error(new BusinessException(ErrorCode.BOOKING_NOT_FOUND, "预约不存在")))
|
||||
.map(this::toBookingRecordResponse);
|
||||
}
|
||||
|
||||
public Flux<BookingRecordResponse> listMemberBookings(Long memberId, int page, int size) {
|
||||
log.info("查询会员预约列表: memberId={}", memberId);
|
||||
|
||||
return bookingRecordRepository.findByMemberIdAndDeletedAtIsNull(memberId,
|
||||
org.springframework.data.domain.PageRequest.of(page, size))
|
||||
.map(this::toBookingRecordResponse);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Mono<Void> cancelBooking(Long id, String reason) {
|
||||
log.info("取消预约: bookingId={}", id);
|
||||
|
||||
return bookingRecordRepository.findByIdAndDeletedAtIsNull(id)
|
||||
.switchIfEmpty(Mono.error(new BusinessException(ErrorCode.BOOKING_NOT_FOUND, "预约不存在")))
|
||||
.flatMap(record -> {
|
||||
if ("CANCELLED".equals(record.getStatus())) {
|
||||
return Mono.error(new BusinessException(ErrorCode.BOOKING_ALREADY_CANCELLED, "预约已取消"));
|
||||
}
|
||||
|
||||
return bookingSlotRepository.decrementBookedCount(record.getSlotId())
|
||||
.flatMap(rows -> {
|
||||
record.setStatus("CANCELLED");
|
||||
record.setCancelReason(reason);
|
||||
record.setCancelTime(LocalDateTime.now());
|
||||
record.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
return bookingRecordRepository.save(record);
|
||||
});
|
||||
})
|
||||
.then();
|
||||
}
|
||||
|
||||
private BookingRecordResponse toBookingRecordResponse(BookingRecord record) {
|
||||
return BookingRecordResponse.builder()
|
||||
.id(record.getId())
|
||||
.memberId(record.getMemberId())
|
||||
.slotId(record.getSlotId())
|
||||
.coachId(record.getCoachId())
|
||||
.courseName(record.getCourseName())
|
||||
.bookingTime(record.getBookingTime())
|
||||
.status(record.getStatus())
|
||||
.cancelReason(record.getCancelReason())
|
||||
.cancelTime(record.getCancelTime())
|
||||
.checkinTime(record.getCheckinTime())
|
||||
.remark(record.getRemark())
|
||||
.createdAt(record.getCreatedAt())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.gym.manage.application.service;
|
||||
|
||||
import com.gym.manage.api.dto.request.MemberCardCreateRequest;
|
||||
import com.gym.manage.api.dto.response.MemberCardResponse;
|
||||
import com.gym.manage.common.constant.ErrorCode;
|
||||
import com.gym.manage.common.exception.BusinessException;
|
||||
import com.gym.manage.domain.entity.Member;
|
||||
import com.gym.manage.domain.entity.MemberCard;
|
||||
import com.gym.manage.domain.repository.MemberCardRepository;
|
||||
import com.gym.manage.domain.repository.MemberRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MemberCardService {
|
||||
|
||||
private final MemberCardRepository memberCardRepository;
|
||||
private final MemberRepository memberRepository;
|
||||
|
||||
public Mono<MemberCardResponse> createMemberCard(MemberCardCreateRequest request) {
|
||||
log.info("创建会员卡: memberId={}, cardNo={}", request.getMemberId(), request.getCardNo());
|
||||
|
||||
return memberRepository.findByIdAndDeletedAtIsNull(request.getMemberId())
|
||||
.switchIfEmpty(Mono.error(new BusinessException(ErrorCode.MEMBER_NOT_FOUND, "会员不存在")))
|
||||
.flatMap(member -> memberCardRepository.findByCardNoAndDeletedAtIsNull(request.getCardNo()))
|
||||
.flatMap(existingCard -> Mono.<MemberCard>error(
|
||||
new BusinessException(ErrorCode.MEMBER_CARD_NOT_FOUND, "卡号已存在")
|
||||
))
|
||||
.switchIfEmpty(Mono.defer(() -> {
|
||||
MemberCard card = new MemberCard();
|
||||
card.setTenantId(request.getMemberId());
|
||||
card.setStoreId(request.getMemberId());
|
||||
card.setMemberId(request.getMemberId());
|
||||
card.setCardNo(request.getCardNo());
|
||||
card.setCardType(request.getCardType());
|
||||
card.setCardName(request.getCardName());
|
||||
card.setTotalCount(request.getTotalCount());
|
||||
card.setRemainingCount(request.getTotalCount());
|
||||
card.setTotalDays(request.getTotalDays());
|
||||
card.setRemainingDays(request.getTotalDays());
|
||||
card.setStartDate(request.getStartDate());
|
||||
card.setEndDate(request.getEndDate());
|
||||
card.setStatus("ACTIVE");
|
||||
card.setPrice(request.getPrice());
|
||||
card.setPaidAmount(request.getPaidAmount());
|
||||
card.setPaymentMethod(request.getPaymentMethod());
|
||||
card.setRemark(request.getRemark());
|
||||
card.setCreatedAt(LocalDateTime.now());
|
||||
card.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
return memberCardRepository.save(card);
|
||||
}))
|
||||
.map(this::toMemberCardResponse)
|
||||
.doOnSuccess(response -> log.info("会员卡创建成功: cardId={}", response.getId()))
|
||||
.doOnError(e -> log.error("会员卡创建失败: memberId={}, error={}", request.getMemberId(), e.getMessage()));
|
||||
}
|
||||
|
||||
public Flux<MemberCardResponse> getMemberCards(Long memberId) {
|
||||
log.info("查询会员卡列表: memberId={}", memberId);
|
||||
|
||||
return memberCardRepository.findByMemberIdAndDeletedAtIsNull(memberId)
|
||||
.map(this::toMemberCardResponse);
|
||||
}
|
||||
|
||||
private MemberCardResponse toMemberCardResponse(MemberCard card) {
|
||||
return MemberCardResponse.builder()
|
||||
.id(card.getId())
|
||||
.memberId(card.getMemberId())
|
||||
.cardNo(card.getCardNo())
|
||||
.cardType(card.getCardType())
|
||||
.cardName(card.getCardName())
|
||||
.totalCount(card.getTotalCount())
|
||||
.remainingCount(card.getRemainingCount())
|
||||
.totalDays(card.getTotalDays())
|
||||
.remainingDays(card.getRemainingDays())
|
||||
.startDate(card.getStartDate())
|
||||
.endDate(card.getEndDate())
|
||||
.status(card.getStatus())
|
||||
.price(card.getPrice())
|
||||
.paidAmount(card.getPaidAmount())
|
||||
.paymentMethod(card.getPaymentMethod())
|
||||
.remark(card.getRemark())
|
||||
.createdAt(card.getCreatedAt())
|
||||
.updatedAt(card.getUpdatedAt())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.gym.manage.application.service;
|
||||
|
||||
import com.gym.manage.api.dto.request.MemberCreateRequest;
|
||||
import com.gym.manage.api.dto.request.MemberUpdateRequest;
|
||||
import com.gym.manage.api.dto.response.MemberResponse;
|
||||
import com.gym.manage.common.constant.ErrorCode;
|
||||
import com.gym.manage.common.exception.BusinessException;
|
||||
import com.gym.manage.domain.entity.Member;
|
||||
import com.gym.manage.domain.repository.MemberRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MemberService {
|
||||
|
||||
private final MemberRepository memberRepository;
|
||||
|
||||
public Mono<MemberResponse> createMember(MemberCreateRequest request) {
|
||||
log.info("创建会员: phone={}", request.getPhone());
|
||||
|
||||
return memberRepository.findByPhoneAndDeletedAtIsNull(request.getPhone())
|
||||
.flatMap(existingMember -> Mono.<Member>error(
|
||||
new BusinessException(ErrorCode.MEMBER_ALREADY_EXISTS, "该手机号已注册")
|
||||
))
|
||||
.switchIfEmpty(Mono.defer(() -> {
|
||||
Member member = new Member();
|
||||
member.setTenantId(request.getTenantId());
|
||||
member.setStoreId(request.getStoreId());
|
||||
member.setName(request.getName());
|
||||
member.setPhone(request.getPhone());
|
||||
member.setGender(request.getGender());
|
||||
member.setBirthday(request.getBirthday());
|
||||
member.setIdCard(request.getIdCard());
|
||||
member.setEmergencyContact(request.getEmergencyContact());
|
||||
member.setEmergencyPhone(request.getEmergencyPhone());
|
||||
member.setLevel(request.getLevel());
|
||||
member.setStatus("ACTIVE");
|
||||
member.setSource(request.getSource());
|
||||
member.setRemark(request.getRemark());
|
||||
member.setCreatedAt(LocalDateTime.now());
|
||||
member.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
return memberRepository.save(member);
|
||||
}))
|
||||
.map(this::toMemberResponse)
|
||||
.doOnSuccess(response -> log.info("会员创建成功: memberId={}", response.getId()))
|
||||
.doOnError(e -> log.error("会员创建失败: phone={}, error={}", request.getPhone(), e.getMessage()));
|
||||
}
|
||||
|
||||
public Mono<MemberResponse> getMember(Long id) {
|
||||
log.info("查询会员: memberId={}", id);
|
||||
|
||||
return memberRepository.findByIdAndDeletedAtIsNull(id)
|
||||
.switchIfEmpty(Mono.error(new BusinessException(ErrorCode.MEMBER_NOT_FOUND, "会员不存在")))
|
||||
.map(this::toMemberResponse)
|
||||
.doOnSuccess(response -> log.info("查询会员成功: memberId={}", id))
|
||||
.doOnError(e -> log.error("查询会员失败: memberId={}, error={}", id, e.getMessage()));
|
||||
}
|
||||
|
||||
public Flux<MemberResponse> listMembers(Long tenantId, Long storeId, int page, int size) {
|
||||
log.info("查询会员列表: tenantId={}, storeId={}, page={}, size={}", tenantId, storeId, page, size);
|
||||
|
||||
return memberRepository.findByTenantIdAndStoreIdAndDeletedAtIsNull(
|
||||
tenantId, storeId, PageRequest.of(page, size)
|
||||
).map(this::toMemberResponse);
|
||||
}
|
||||
|
||||
public Mono<MemberResponse> updateMember(Long id, MemberUpdateRequest request) {
|
||||
log.info("更新会员: memberId={}", id);
|
||||
|
||||
return memberRepository.findByIdAndDeletedAtIsNull(id)
|
||||
.switchIfEmpty(Mono.error(new BusinessException(ErrorCode.MEMBER_NOT_FOUND, "会员不存在")))
|
||||
.flatMap(member -> {
|
||||
member.setName(request.getName());
|
||||
member.setGender(request.getGender());
|
||||
member.setBirthday(request.getBirthday());
|
||||
member.setIdCard(request.getIdCard());
|
||||
member.setEmergencyContact(request.getEmergencyContact());
|
||||
member.setEmergencyPhone(request.getEmergencyPhone());
|
||||
member.setLevel(request.getLevel());
|
||||
member.setStatus(request.getStatus());
|
||||
member.setRemark(request.getRemark());
|
||||
member.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
return memberRepository.save(member);
|
||||
})
|
||||
.map(this::toMemberResponse)
|
||||
.doOnSuccess(response -> log.info("会员更新成功: memberId={}", id))
|
||||
.doOnError(e -> log.error("会员更新失败: memberId={}, error={}", id, e.getMessage()));
|
||||
}
|
||||
|
||||
public Mono<Void> deleteMember(Long id) {
|
||||
log.info("删除会员: memberId={}", id);
|
||||
|
||||
return memberRepository.softDeleteById(id)
|
||||
.flatMap(rows -> {
|
||||
if (rows > 0) {
|
||||
log.info("会员删除成功: memberId={}", id);
|
||||
return Mono.empty();
|
||||
} else {
|
||||
return Mono.error(new BusinessException(ErrorCode.MEMBER_NOT_FOUND, "会员不存在"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private MemberResponse toMemberResponse(Member member) {
|
||||
return MemberResponse.builder()
|
||||
.id(member.getId())
|
||||
.tenantId(member.getTenantId())
|
||||
.storeId(member.getStoreId())
|
||||
.name(member.getName())
|
||||
.phone(member.getPhone())
|
||||
.gender(member.getGender())
|
||||
.birthday(member.getBirthday())
|
||||
.idCard(member.getIdCard())
|
||||
.emergencyContact(member.getEmergencyContact())
|
||||
.emergencyPhone(member.getEmergencyPhone())
|
||||
.level(member.getLevel())
|
||||
.status(member.getStatus())
|
||||
.source(member.getSource())
|
||||
.remark(member.getRemark())
|
||||
.createdAt(member.getCreatedAt())
|
||||
.updatedAt(member.getUpdatedAt())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user