|
@@ -0,0 +1,275 @@
|
|
|
+package com.qmrb.system.service.impl;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.qmrb.system.converter.ParkingCardConverter;
|
|
|
+import com.qmrb.system.mapper.ParkingCardMapper;
|
|
|
+import com.qmrb.system.pojo.entity.ParkingCard;
|
|
|
+import com.qmrb.system.pojo.entity.ParkingCardType;
|
|
|
+import com.qmrb.system.pojo.form.ParkingCardForm;
|
|
|
+import com.qmrb.system.pojo.query.ParkingCardQuery;
|
|
|
+import com.qmrb.system.pojo.vo.ParkingCardVO;
|
|
|
+import com.qmrb.system.service.IParkingCardService;
|
|
|
+import com.qmrb.system.service.IParkingCardTypeService;
|
|
|
+import com.qmrb.system.service.IQuotaUsageService;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import cn.hutool.core.lang.Assert;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.temporal.TemporalAdjusters;
|
|
|
+
|
|
|
+/**
|
|
|
+ * <p>
|
|
|
+ * 月卡购买记录表 服务实现类
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * @author assistant
|
|
|
+ * @since 2025-04-12
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class ParkingCardServiceImpl extends ServiceImpl<ParkingCardMapper, ParkingCard> implements IParkingCardService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ParkingCardConverter converter;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IParkingCardTypeService parkingCardTypeService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IQuotaUsageService quotaUsageService;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Page<ParkingCardVO> getPage(ParkingCardQuery queryParams) {
|
|
|
+ // 查询参数
|
|
|
+ int pageNum = queryParams.getPageNum();
|
|
|
+ int pageSize = queryParams.getPageSize();
|
|
|
+
|
|
|
+ LambdaQueryWrapper<ParkingCard> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
+
|
|
|
+ // 月卡类型ID查询
|
|
|
+ if (queryParams.getTypeId() != null) {
|
|
|
+ queryWrapper.eq(ParkingCard::getTypeId, queryParams.getTypeId());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 车牌号模糊查询
|
|
|
+ if (StrUtil.isNotBlank(queryParams.getPlateNumber())) {
|
|
|
+ queryWrapper.like(ParkingCard::getPlateNumber, queryParams.getPlateNumber());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 联系人姓名模糊查询
|
|
|
+ if (StrUtil.isNotBlank(queryParams.getName())) {
|
|
|
+ queryWrapper.like(ParkingCard::getName, queryParams.getName());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 手机号模糊查询
|
|
|
+ if (StrUtil.isNotBlank(queryParams.getPhone())) {
|
|
|
+ queryWrapper.like(ParkingCard::getPhone, queryParams.getPhone());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 状态查询
|
|
|
+ if (StrUtil.isNotBlank(queryParams.getStatus())) {
|
|
|
+ queryWrapper.eq(ParkingCard::getStatus, queryParams.getStatus());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 时间范围查询
|
|
|
+ if (StrUtil.isNotBlank(queryParams.getStartTimeBegin())) {
|
|
|
+ queryWrapper.ge(ParkingCard::getStartTime, queryParams.getStartTimeBegin());
|
|
|
+ }
|
|
|
+ if (StrUtil.isNotBlank(queryParams.getStartTimeEnd())) {
|
|
|
+ queryWrapper.le(ParkingCard::getStartTime, queryParams.getStartTimeEnd());
|
|
|
+ }
|
|
|
+ if (StrUtil.isNotBlank(queryParams.getEndTimeBegin())) {
|
|
|
+ queryWrapper.ge(ParkingCard::getEndTime, queryParams.getEndTimeBegin());
|
|
|
+ }
|
|
|
+ if (StrUtil.isNotBlank(queryParams.getEndTimeEnd())) {
|
|
|
+ queryWrapper.le(ParkingCard::getEndTime, queryParams.getEndTimeEnd());
|
|
|
+ }
|
|
|
+ if (StrUtil.isNotBlank(queryParams.getCreatedAtBegin())) {
|
|
|
+ queryWrapper.ge(ParkingCard::getCreatedAt, queryParams.getCreatedAtBegin());
|
|
|
+ }
|
|
|
+ if (StrUtil.isNotBlank(queryParams.getCreatedAtEnd())) {
|
|
|
+ queryWrapper.le(ParkingCard::getCreatedAt, queryParams.getCreatedAtEnd());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 默认按创建时间降序排序
|
|
|
+ queryWrapper.orderByDesc(ParkingCard::getCreatedAt);
|
|
|
+
|
|
|
+ // 查询数据
|
|
|
+ Page<ParkingCard> entityPage = this.page(
|
|
|
+ new Page<>(pageNum, pageSize),
|
|
|
+ queryWrapper
|
|
|
+ );
|
|
|
+
|
|
|
+ // 实体转换
|
|
|
+ Page<ParkingCardVO> pageResult = converter.entity2Page(entityPage);
|
|
|
+
|
|
|
+ // 填充月卡类型名称
|
|
|
+ for (ParkingCardVO vo : pageResult.getRecords()) {
|
|
|
+ if (vo.getTypeId() != null) {
|
|
|
+ ParkingCardType cardType = parkingCardTypeService.getById(vo.getTypeId());
|
|
|
+ if (cardType != null) {
|
|
|
+ vo.setTypeName(cardType.getTypeName());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return pageResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public ParkingCardForm saveForm(ParkingCardForm form) {
|
|
|
+ // 校验月卡类型是否存在
|
|
|
+ ParkingCardType cardType = parkingCardTypeService.getById(form.getTypeId());
|
|
|
+ Assert.notNull(cardType, "月卡类型不存在");
|
|
|
+
|
|
|
+ // 校验购买月数是否合法
|
|
|
+ Assert.isTrue(form.getPurchasedMonths() >= 1 && form.getPurchasedMonths() <= 12, "购买月数必须在1-12月之间");
|
|
|
+
|
|
|
+ // 检查配额是否可用
|
|
|
+ boolean quotaAvailable = quotaUsageService.checkQuotaAvailability(form.getTypeId());
|
|
|
+ Assert.isTrue(quotaAvailable, "该月卡类型已无可用配额");
|
|
|
+
|
|
|
+ // 计算费用
|
|
|
+ BigDecimal totalFee = calculatePayment(form.getTypeId(), form.getPurchasedMonths());
|
|
|
+ form.setTotalFee(totalFee);
|
|
|
+
|
|
|
+ // 计算有效期
|
|
|
+ LocalDate[] period = calculatePeriod(form.getPurchasedMonths());
|
|
|
+ form.setStartTime(period[0]);
|
|
|
+ form.setEndTime(period[1]);
|
|
|
+
|
|
|
+ // 设置状态为有效
|
|
|
+ form.setStatus("active");
|
|
|
+
|
|
|
+ // 实体对象转换 form->entity
|
|
|
+ ParkingCard entity = converter.form2Entity(form);
|
|
|
+
|
|
|
+ // 设置创建和更新时间
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
+ entity.setCreatedAt(now);
|
|
|
+ entity.setUpdatedAt(now);
|
|
|
+
|
|
|
+ // 持久化
|
|
|
+ this.save(entity);
|
|
|
+
|
|
|
+ // 增加已使用配额
|
|
|
+ quotaUsageService.incrementUsedQuota(form.getTypeId());
|
|
|
+
|
|
|
+ ParkingCardForm result = converter.entity2Form(entity);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public boolean updateForm(Long id, ParkingCardForm form) {
|
|
|
+ // 获取原记录
|
|
|
+ ParkingCard entity = this.getById(id);
|
|
|
+ Assert.notNull(entity, "月卡记录不存在");
|
|
|
+
|
|
|
+ // 如果更改了月卡类型,需要处理配额变更
|
|
|
+ if (!entity.getTypeId().equals(form.getTypeId())) {
|
|
|
+ // 检查新类型的配额是否可用
|
|
|
+ boolean quotaAvailable = quotaUsageService.checkQuotaAvailability(form.getTypeId());
|
|
|
+ Assert.isTrue(quotaAvailable, "新月卡类型已无可用配额");
|
|
|
+
|
|
|
+ // 减少原类型的已使用配额
|
|
|
+ quotaUsageService.decrementUsedQuota(entity.getTypeId());
|
|
|
+
|
|
|
+ // 增加新类型的已使用配额
|
|
|
+ quotaUsageService.incrementUsedQuota(form.getTypeId());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果更改了购买月数,需要重新计算费用和有效期
|
|
|
+ if (!entity.getPurchasedMonths().equals(form.getPurchasedMonths())) {
|
|
|
+ // 计算费用
|
|
|
+ BigDecimal totalFee = calculatePayment(form.getTypeId(), form.getPurchasedMonths());
|
|
|
+ form.setTotalFee(totalFee);
|
|
|
+
|
|
|
+ // 计算有效期
|
|
|
+ LocalDate[] period = calculatePeriod(form.getPurchasedMonths());
|
|
|
+ form.setStartTime(period[0]);
|
|
|
+ form.setEndTime(period[1]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新实体
|
|
|
+ converter.updateEntityFromForm(form, entity);
|
|
|
+ entity.setUpdatedAt(LocalDateTime.now());
|
|
|
+
|
|
|
+ // 保存更新
|
|
|
+ boolean result = this.updateById(entity);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public ParkingCardForm getFormData(Long id) {
|
|
|
+ // 获取entity
|
|
|
+ ParkingCard entity = this.getById(id);
|
|
|
+ Assert.notNull(entity, "月卡记录不存在");
|
|
|
+
|
|
|
+ // 实体转换
|
|
|
+ ParkingCardForm form = converter.entity2Form(entity);
|
|
|
+ return form;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public LocalDate[] calculatePeriod(Integer months) {
|
|
|
+ Assert.isTrue(months >= 1 && months <= 12, "购买月数必须在1-12月之间");
|
|
|
+
|
|
|
+ LocalDate today = LocalDate.now();
|
|
|
+ LocalDate startDate = today;
|
|
|
+
|
|
|
+ // 计算结束日期:当前日期加上指定月数,然后减去1天
|
|
|
+ LocalDate endDate = today.plusMonths(months).minusDays(1);
|
|
|
+
|
|
|
+ return new LocalDate[] { startDate, endDate };
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public BigDecimal calculatePayment(Long typeId, Integer months) {
|
|
|
+ return parkingCardTypeService.calculateFee(typeId, months);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean checkQuotaAvailability(Long typeId) {
|
|
|
+ return quotaUsageService.checkQuotaAvailability(typeId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public boolean updateStatus(Long id, String status) {
|
|
|
+ ParkingCard entity = this.getById(id);
|
|
|
+ Assert.notNull(entity, "月卡记录不存在");
|
|
|
+
|
|
|
+ // 如果状态没变,直接返回成功
|
|
|
+ if (entity.getStatus().equals(status)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新状态
|
|
|
+ entity.setStatus(status);
|
|
|
+ entity.setUpdatedAt(LocalDateTime.now());
|
|
|
+
|
|
|
+ // 如果从有效变为过期,减少已使用配额
|
|
|
+ if ("active".equals(entity.getStatus()) && "expired".equals(status)) {
|
|
|
+ quotaUsageService.decrementUsedQuota(entity.getTypeId());
|
|
|
+ }
|
|
|
+ // 如果从过期变为有效,增加已使用配额
|
|
|
+ else if ("expired".equals(entity.getStatus()) && "active".equals(status)) {
|
|
|
+ // 检查配额是否可用
|
|
|
+ boolean quotaAvailable = quotaUsageService.checkQuotaAvailability(entity.getTypeId());
|
|
|
+ Assert.isTrue(quotaAvailable, "该月卡类型已无可用配额");
|
|
|
+
|
|
|
+ quotaUsageService.incrementUsedQuota(entity.getTypeId());
|
|
|
+ }
|
|
|
+
|
|
|
+ return this.updateById(entity);
|
|
|
+ }
|
|
|
+}
|