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.domain.UserAccount; import com.ruoyi.system.mapper.MedicalInsuranceAccountMapper; import com.ruoyi.system.mapper.MedicalInsuranceDailyClaimMapper; import com.ruoyi.system.service.UserAccountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.interceptor.TransactionAspectSupport; 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<>(); @Autowired UserAccountService userAccountService; @Override public Result getInsuranceBenefit(String account) { synchronized (account) { // 获取账户本地锁 ReentrantLock accountLock = accountLocks.computeIfAbsent(account, k -> new ReentrantLock()); accountLock.lock(); UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper() .eq(UserAccount::getAccount,account)); try { MedicalInsuranceAccount medicalInsuranceAccount = medicalInsuranceAccountMapper.selectOne(new LambdaQueryWrapper() .eq(MedicalInsuranceAccount::getUserId, userAccount.getId()) .eq(MedicalInsuranceAccount::getAccountStatus, MedicalInsuranceAccount.AccountStatus.ACTIVE) ); if (medicalInsuranceAccount == null) { return Result.error("医保账户不存在"); } // 检查账户状态 if (!"ACTIVE".equals(medicalInsuranceAccount.getAccountStatus().name())) { return Result.error("保单已失效"); } // 检查账户有效期 LocalDate now = LocalDate.now(); if (now.isBefore(medicalInsuranceAccount.getEffectiveDate()) || now.isAfter(medicalInsuranceAccount.getExpiryDate())) { return Result.error("已过保单日期"); } // 检查今天是否已经领取 LocalDate today = LocalDate.now(); Long todayCount = medicalInsuranceDailyClaimMapper.selectCount(new LambdaQueryWrapper() .eq(MedicalInsuranceDailyClaim::getUserId, userAccount.getId()) .eq(MedicalInsuranceDailyClaim::getAccountId, medicalInsuranceAccount.getId()) .eq(MedicalInsuranceDailyClaim::getClaimDate, today) ); if (todayCount > 0) { return Result.error("今日已领取过金额"); } if (medicalInsuranceAccount.getTotalQuota().compareTo(medicalInsuranceAccount.getAlreadyReceived()) == 0) { return Result.error("你的保险额度已领取完!"); } // // 计算剩余天数 // long remainingDays = ChronoUnit.DAYS.between(now, medicalInsuranceAccount.getExpiryDate()) + 1; // // // 计算每日金额 // BigDecimal dailyAmount = calculateDailyAmount( // medicalInsuranceAccount.getTotalQuota(), (int) remainingDays); // // // 如果账户余额不足,则领取剩余全部金额 // if (medicalInsuranceAccount.getAmountClaimed().compareTo(dailyAmount) < 0) { // dailyAmount = medicalInsuranceAccount.getAmountClaimed(); // } // // // 更新待领金额 // medicalInsuranceAccount.setAmountClaimed(medicalInsuranceAccount.getAmountClaimed().subtract(dailyAmount)); // 更新已领取金额 BigDecimal currentAmountReceived = medicalInsuranceAccount.getAlreadyReceived() != null ? medicalInsuranceAccount.getAlreadyReceived(): BigDecimal.ZERO; medicalInsuranceAccount.setAlreadyReceived(currentAmountReceived.add(medicalInsuranceAccount.getAmountClaimed())); medicalInsuranceAccountMapper.updateById(medicalInsuranceAccount); // 创建领取记录 MedicalInsuranceDailyClaim claim = new MedicalInsuranceDailyClaim(); claim.setAccountId(medicalInsuranceAccount.getId()); claim.setUserId(userAccount.getId()); claim.setClaimDate(today); claim.setClaimAmount(medicalInsuranceAccount.getAmountClaimed()); claim.setCreatedAt(new Date()); medicalInsuranceDailyClaimMapper.insert(claim); return Result.success("领取成功"); }catch (Exception e){ e.printStackTrace(); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); log.error("领取保险金出错:"+e.getMessage()); }finally { accountLock.unlock(); } } return Result.error("领取失败!"); } @Override public Result getReceiveStatus(String account) { UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper() .eq(UserAccount::getAccount,account)); MedicalInsuranceAccount medicalInsuranceAccount = medicalInsuranceAccountMapper.selectOne(new LambdaQueryWrapper() .eq(MedicalInsuranceAccount::getUserId, userAccount.getId()) .eq(MedicalInsuranceAccount::getAccountStatus, MedicalInsuranceAccount.AccountStatus.ACTIVE) ); if (medicalInsuranceAccount == null) { return Result.success(false); } // 检查账户状态 if (!"ACTIVE".equals(medicalInsuranceAccount.getAccountStatus().name())) { return Result.success(false); } // 检查账户有效期 LocalDate now = LocalDate.now(); if (now.isBefore(medicalInsuranceAccount.getEffectiveDate()) || now.isAfter(medicalInsuranceAccount.getExpiryDate())) { return Result.success(false); } // 检查今天是否已经领取 LocalDate today = LocalDate.now(); Long todayCount = medicalInsuranceDailyClaimMapper.selectCount(new LambdaQueryWrapper() .eq(MedicalInsuranceDailyClaim::getUserId, userAccount.getId()) .eq(MedicalInsuranceDailyClaim::getAccountId, medicalInsuranceAccount.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); } }