package com.ruoyi.im.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.im.comm.Result; import com.ruoyi.im.service.MedicalInsuranceAccountService; import com.ruoyi.system.domain.MedicalInsuranceAccount; import com.ruoyi.system.domain.MedicalInsuranceDailyClaim; import com.ruoyi.system.mapper.MedicalInsuranceAccountMapper; import com.ruoyi.system.mapper.MedicalInsuranceDailyClaimMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import javax.xml.crypto.Data; import java.math.BigDecimal; import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; @Service public class MedicalInsuranceAccountServiceImpl extends ServiceImpl implements MedicalInsuranceAccountService { @Autowired private MedicalInsuranceAccountMapper medicalInsuranceAccountMapper; @Autowired private MedicalInsuranceDailyClaimMapper medicalInsuranceDailyClaimMapper; // 使用本地锁避免数据库锁竞争 private final ConcurrentHashMap accountLocks = new ConcurrentHashMap<>(); @Override public Result getInsuranceBenefit(Integer userId) { synchronized (userId) { // 获取账户本地锁 ReentrantLock accountLock = accountLocks.computeIfAbsent(userId, k -> new ReentrantLock()); accountLock.lock(); try { MedicalInsuranceAccount account = medicalInsuranceAccountMapper.selectOne(new LambdaQueryWrapper() .eq(MedicalInsuranceAccount::getUserId, userId) .eq(MedicalInsuranceAccount::getAccountStatus, MedicalInsuranceAccount.AccountStatus.ACTIVE) ); if (account == null) { return Result.error("医保账户不存在"); } // 检查账户状态 if (!"ACTIVE".equals(account.getAccountStatus())) { return Result.error("保单已失效"); } // 检查账户有效期 LocalDate now = LocalDate.now(); if (now.isBefore(account.getEffectiveDate()) || now.isAfter(account.getExpiryDate())) { return Result.error("已过保单日期"); } // 检查今天是否已经领取 LocalDate today = LocalDate.now(); Long todayCount = medicalInsuranceDailyClaimMapper.selectCount(new LambdaQueryWrapper() .eq(MedicalInsuranceDailyClaim::getUserId, userId) .eq(MedicalInsuranceDailyClaim::getAccountId, account.getId()) .eq(MedicalInsuranceDailyClaim::getClaimDate, today) ); if (todayCount > 0) { return Result.error("今日已领取过金额"); } if (account.getTotalQuota().compareTo(account.getAlreadyReceived()) == 0) { return Result.error("你的保险额度已领取完!"); } // 计算剩余天数 long remainingDays = ChronoUnit.DAYS.between(now, account.getExpiryDate()) + 1; // 计算每日金额 BigDecimal dailyAmount = calculateDailyAmount( account.getTotalQuota(), (int) remainingDays); // 如果账户余额不足,则领取剩余全部金额 if (account.getAmountClaimed().compareTo(dailyAmount) < 0) { dailyAmount = account.getAmountClaimed(); } // 更新待领金额 account.setAmountClaimed(account.getAmountClaimed().subtract(dailyAmount)); // 更新已领取金额 BigDecimal currentAmountReceived = account.getAlreadyReceived() != null ? account.getAlreadyReceived(): BigDecimal.ZERO; account.setAlreadyReceived(currentAmountReceived.add(dailyAmount)); medicalInsuranceAccountMapper.updateById(account); // 创建领取记录 MedicalInsuranceDailyClaim claim = new MedicalInsuranceDailyClaim(); claim.setAccountId(account.getId()); claim.setUserId(userId); claim.setClaimDate(today); claim.setClaimAmount(dailyAmount); claim.setCreatedAt(new Date()); medicalInsuranceDailyClaimMapper.insert(claim); return Result.success("领取成功"); }catch (Exception e){ e.printStackTrace(); log.error("领取保险金出错:"+e.getMessage()); }finally { accountLock.unlock(); } } return Result.error("领取失败!"); } @Override public Result getReceiveStatus(Integer userId) { MedicalInsuranceAccount account = medicalInsuranceAccountMapper.selectOne(new LambdaQueryWrapper() .eq(MedicalInsuranceAccount::getUserId, userId) .eq(MedicalInsuranceAccount::getAccountStatus, MedicalInsuranceAccount.AccountStatus.ACTIVE) ); if (account == null) { return Result.success(false); } // 检查账户状态 if (!"ACTIVE".equals(account.getAccountStatus())) { return Result.success(false); } // 检查账户有效期 LocalDate now = LocalDate.now(); if (now.isBefore(account.getEffectiveDate()) || now.isAfter(account.getExpiryDate())) { return Result.success(false); } // 检查今天是否已经领取 LocalDate today = LocalDate.now(); Long todayCount = medicalInsuranceDailyClaimMapper.selectCount(new LambdaQueryWrapper() .eq(MedicalInsuranceDailyClaim::getUserId, userId) .eq(MedicalInsuranceDailyClaim::getAccountId, account.getId()) .eq(MedicalInsuranceDailyClaim::getClaimDate, today) ); if (todayCount > 0) { return Result.success(false); } return Result.success(true); } private BigDecimal calculateDailyAmount(BigDecimal totalAmount, int totalDays) { if (totalDays <= 0) { return BigDecimal.ZERO; } // 使用四舍五入到分位 return totalAmount.divide(new BigDecimal(totalDays), 2, BigDecimal.ROUND_DOWN); } }