package com.ruoyi.web.controller.product; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.im.comm.Result; import com.ruoyi.im.service.InsuranceProductService; import com.ruoyi.im.service.MedicalInsuranceAccountService; import com.ruoyi.im.service.impl.InsurancePositionServiceImpl; import com.ruoyi.im.util.RedisDistributedLock; import com.ruoyi.im.util.UserPolicyUtils; import com.ruoyi.system.domain.*; import com.ruoyi.system.domain.dto.UserPolicyDto; import com.ruoyi.im.service.UserPolicyService; import com.ruoyi.system.service.UserAccountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.interceptor.TransactionAspectSupport; import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; @RestController @RequestMapping("/userPolicy") public class UserPolicyController extends BaseController { @Autowired UserPolicyService userPolicyService; @Autowired MedicalInsuranceAccountService medicalInsuranceAccountService; @Autowired UserAccountService userAccountService; @Autowired InsurancePositionServiceImpl insurancePositionService; @Autowired private RedisDistributedLock redisDistributedLock; @Autowired InsuranceProductService insuranceProductService; /** * 保险购买申请 */ @PostMapping("/purchaseApplication") public Result purchaseApplication(UserPolicyDto dto) { // 生成锁的key:基于用户ID和产品ID,防止同一用户同时购买同一产品 String lockKey = redisDistributedLock.generateLockKey(dto.getAccount(), dto.getProductId()); boolean lockAcquired = false; try { // 尝试获取分布式锁:等待10秒,锁过期30秒 lockAcquired = redisDistributedLock.tryLock(lockKey, 30L, 10L); if (!lockAcquired) { return Result.error("操作过于频繁,请稍后重试"); } // 执行购买逻辑 return userPolicyService.purchaseApplication(dto); } catch (Exception e) { e.printStackTrace(); return Result.error("购买失败"); } finally { // 释放锁 if (lockAcquired) { redisDistributedLock.releaseLock(lockKey); } } } /** * 根据用户id查询保单 */ @GetMapping("/getPolicyById") public Result getPolicyById(@RequestParam(value = "account") String account) { try { UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper() .eq(UserAccount::getAccount,account)); List list = userPolicyService.list(new LambdaQueryWrapper().eq(UserPolicy::getUserId, userAccount.getId())); return Result.success(list); }catch (Exception e){ e.printStackTrace(); return Result.error("查询失败"); } } /** * 保单列表 */ @GetMapping("/list") public TableDataInfo list(@RequestParam(value = "account",required = false) String account, @RequestParam(value = "state",defaultValue = "0") Integer state, @RequestParam(value = "productName",required = false) String productName) { startPage(); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); // 产品名称模糊查询 if (org.apache.commons.lang3.StringUtils.isNotBlank(account)) { wrapper.like(UserPolicy::getAccount, account); } // 产品代码模糊查询 if (org.apache.commons.lang3.StringUtils.isNotBlank(productName)) { wrapper.like(UserPolicy::getProductName, productName); } // 审批状态 if (state != null && state == 3) { wrapper.ne(UserPolicy::getApprovalStatus, 0); }else{ wrapper.eq(UserPolicy::getApprovalStatus, 0); } // 按创建时间倒序排列 wrapper.orderByDesc(UserPolicy::getCreatedAt); List list = userPolicyService.list(wrapper); return getDataTable(list); } /** * 保单审批 */ @GetMapping("/examine") @Transactional public AjaxResult examine(@RequestParam(value = "id") Integer id, @RequestParam(value = "approvalStatus") Integer approvalStatus, @RequestParam(value = "message",required = false) String message) { try { UserPolicy userPolicy = userPolicyService.getById(id); if(ObjectUtil.isEmpty(userPolicy)){ return AjaxResult.error("订单不存在"); } if(userPolicy.getApprovalStatus() != 0){ return AjaxResult.error("订单已审批!"); } if(approvalStatus == 2 && StringUtils.isEmpty(message)){ return AjaxResult.error("驳回理由不能为空!"); } UserAccount userAccount = userAccountService.getById(userPolicy.getUserId()); if(approvalStatus == 2){ userPolicy.setApprovalStatus(approvalStatus); userPolicy.setMessage(message); userPolicy.setUpdatedAt(new Date()); userPolicyService.updateById(userPolicy); userAccount.setBalance(userAccount.getBalance().add(userPolicy.getPremium())); userAccountService.updateById(userAccount); return AjaxResult.success("审批成功"); } //计算到期时间 LocalDate expirationTime = calculateInsuranceEndDateToDay(LocalDate.now(), userPolicy.getTerm()); userPolicy.setApprovalStatus(approvalStatus); userPolicy.setMessage(message); userPolicy.setStartDate(LocalDate.now()); userPolicy.setEndDate(expirationTime); userPolicy.setPolicyStatus(UserPolicy.PolicyStatus.ACTIVE); userPolicy.setUpdatedAt(new Date()); userPolicyService.updateById(userPolicy); MedicalInsuranceAccount medicalInsuranceAccount = new MedicalInsuranceAccount(); medicalInsuranceAccount.setUserId(userPolicy.getUserId()); medicalInsuranceAccount.setPolicyId(userPolicy.getId()); medicalInsuranceAccount.setProductId(userPolicy.getProductId()); medicalInsuranceAccount.setTotalQuota(userPolicy.getCoverageAmount()); medicalInsuranceAccount.setRemainingBalance(BigDecimal.ZERO); medicalInsuranceAccount.setAmountClaimed(userPolicy.getCoverageAmount()); medicalInsuranceAccount.setAlreadyReceived(BigDecimal.ZERO); medicalInsuranceAccount.setAmountAlreadyUsed(BigDecimal.ZERO); medicalInsuranceAccount.setEffectiveDate(userPolicy.getStartDate()); medicalInsuranceAccount.setExpiryDate(userPolicy.getEndDate()); medicalInsuranceAccount.setAccountStatus(MedicalInsuranceAccount.AccountStatus.ACTIVE); medicalInsuranceAccount.setCreatedAt(new Date()); medicalInsuranceAccount.setUpdatedAt(new Date()); medicalInsuranceAccountService.save(medicalInsuranceAccount); //判断上级用户职位达成 if(approvalStatus == 1){ if(StringUtils.isNotEmpty(userAccount.getInvitationAccount())){ //上级 UserAccount superiorUser = userAccountService.getOne(new LambdaQueryWrapper() .eq(UserAccount::getAccount, userAccount.getInvitationAccount()) ); //查询上级的所有下级 List userAccountList = userAccountService.list(new LambdaQueryWrapper() .eq(UserAccount::getInvitationAccount, superiorUser.getAccount()) ); if(userAccountList.size() == 0){ return AjaxResult.success("审批成功"); } List idList = userAccountList.stream() .map(UserAccount::getId) .collect(Collectors.toList()); //查询下级的保单 List userPolicyList = userPolicyService.list(new LambdaQueryWrapper<>(UserPolicy.class) .in(UserPolicy::getUserId, idList) ); // 手动将当前审批的保单加入到列表中(因为事务隔离可能查不到) userPolicyList.add(userPolicy); if(userPolicyList.size() == 0){ return AjaxResult.success("审批成功"); } //生效保单数量 long activePolicies = UserPolicyUtils.countActivePolicies(userPolicyList); //查询所有职位 List positions = insurancePositionService.list(); positions.forEach(f->{ if(activePolicies >= f.getNumberPeople()){ superiorUser.setPosition(f.getPosition()); superiorUser.setAgreedTime(LocalDate.now()); } }); userAccountService.updateById(superiorUser); } return AjaxResult.success("审批成功"); } return AjaxResult.success("审批成功"); }catch (Exception e){ e.printStackTrace(); // 手动设置回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); return AjaxResult.error("审批失败!"); } } /** * 计算保险到期日 * @param startDate 保险开始日期 * @param termDays 保险天数 * @return 保险到期日期 */ public static LocalDate calculateInsuranceEndDateToDay(LocalDate startDate, int termDays) { return calculateDateAfterDays(startDate, termDays); } /** * 计算指定天数后的日期 * @param startDate 开始日期 * @param daysToAdd 要添加的天数 * @return 计算后的日期 */ public static LocalDate calculateDateAfterDays(LocalDate startDate, int daysToAdd) { if (startDate == null) { throw new IllegalArgumentException("开始日期不能为空"); } return startDate.plusDays(daysToAdd); } /** * 计算保险到期日 * @param startDate 保险开始日期 * @param termYears 保险年限 * @return 保险到期日期 */ public static LocalDate calculateInsuranceEndDate(LocalDate startDate, int termYears) { return calculateDateAfterYears(startDate, termYears); } /** * 根据基准日期和年限推算日期 */ public static LocalDate calculateDateAfterYears(LocalDate baseDate, int years) { validateBaseDate(baseDate); return baseDate.plusYears(years); } /** * 验证基准日期 */ private static void validateBaseDate(LocalDate baseDate) { if (baseDate == null) { throw new IllegalArgumentException("基准日期不能为null"); } } }