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<MedicalInsuranceAccountMapper, MedicalInsuranceAccount> implements MedicalInsuranceAccountService {
|
|
@Autowired
|
private MedicalInsuranceAccountMapper medicalInsuranceAccountMapper;
|
|
@Autowired
|
private MedicalInsuranceDailyClaimMapper medicalInsuranceDailyClaimMapper;
|
|
// 使用本地锁避免数据库锁竞争
|
private final ConcurrentHashMap<String, ReentrantLock> 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<UserAccount>()
|
.eq(UserAccount::getAccount,account));
|
try {
|
MedicalInsuranceAccount medicalInsuranceAccount = medicalInsuranceAccountMapper.selectOne(new LambdaQueryWrapper<MedicalInsuranceAccount>()
|
.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<MedicalInsuranceDailyClaim>()
|
.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<UserAccount>()
|
.eq(UserAccount::getAccount,account));
|
MedicalInsuranceAccount medicalInsuranceAccount = medicalInsuranceAccountMapper.selectOne(new LambdaQueryWrapper<MedicalInsuranceAccount>()
|
.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<MedicalInsuranceDailyClaim>()
|
.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);
|
}
|
}
|