|
|
@@ -0,0 +1,276 @@
|
|
|
+package org.springblade.factory.api.controller;
|
|
|
+
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollectionUtil;
|
|
|
+import com.alibaba.excel.annotation.format.DateTimeFormat;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import io.swagger.annotations.ApiImplicitParam;
|
|
|
+import io.swagger.annotations.ApiImplicitParams;
|
|
|
+import io.swagger.annotations.ApiOperation;
|
|
|
+import lombok.AllArgsConstructor;
|
|
|
+import org.springblade.core.mp.support.Condition;
|
|
|
+import org.springblade.core.secure.utils.AuthUtil;
|
|
|
+import org.springblade.core.tool.api.R;
|
|
|
+import org.springblade.factory.domain.ClaimSearchVO;
|
|
|
+import org.springblade.factory.entity.PcBladeClaim;
|
|
|
+import org.springblade.factory.entity.PcBladeClaimAttachment;
|
|
|
+import org.springblade.factory.entity.PcBladeClaimAudit;
|
|
|
+import org.springblade.factory.service.PcBladeClaimAttachmentService;
|
|
|
+import org.springblade.factory.service.PcBladeClaimAuditService;
|
|
|
+import org.springblade.factory.service.PcBladeClaimService;
|
|
|
+import org.springframework.web.bind.annotation.GetMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
+import org.springframework.web.bind.annotation.RequestParam;
|
|
|
+import org.springframework.web.bind.annotation.RestController;
|
|
|
+
|
|
|
+import javax.management.Query;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.text.ParseException;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 理赔查询 控制器
|
|
|
+ *
|
|
|
+ * @author horizon
|
|
|
+ * @since 2025-08-05
|
|
|
+ */
|
|
|
+@RestController
|
|
|
+@RequestMapping("/api/factory/claimSearch")
|
|
|
+@AllArgsConstructor
|
|
|
+public class ClaimSearchController {
|
|
|
+
|
|
|
+ private final PcBladeClaimService pcBladeClaimService;
|
|
|
+
|
|
|
+ private final PcBladeClaimAttachmentService pcBladeClaimAttachmentService;
|
|
|
+
|
|
|
+ private final PcBladeClaimAuditService pcBladeClaimAuditService;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 理赔申请综合查询(支持多条件组合+分页+数据权限)
|
|
|
+ *
|
|
|
+ * @param claimNo 理赔单号(精准)
|
|
|
+ * @param claimSourceType 来源类型 1经销商 2门店 3终端消费者(精准)
|
|
|
+ * @param auditStatus 审核状态 0待审核 1审核中 2已通过 3已拒绝(精准)
|
|
|
+ * @param consumerName 消费者姓名(模糊)
|
|
|
+ * @param consumerPhone 消费者电话(模糊)
|
|
|
+ * @param tyreNo 胎号/轮胎宝编号(模糊)
|
|
|
+ * @param tyreSpecs 规格型号(模糊)
|
|
|
+ * @param claimAmountMin 索赔金额最小值(数值范围)
|
|
|
+ * @param claimAmountMax 索赔金额最大值(数值范围)
|
|
|
+ * @param runMileageMin 行驶里程最小值(数值范围)
|
|
|
+ * @param runMileageMax 行驶里程最大值(数值范围)
|
|
|
+ * @param isSubmitTime 是否已提交 0未提交 1已提交(精准)
|
|
|
+ * @param pageNum 页码(默认1)
|
|
|
+ * @param pageSize 每页条数(默认10,最大100)
|
|
|
+ * @return 分页的理赔综合信息
|
|
|
+ */
|
|
|
+ /**
|
|
|
+ * 理赔申请综合查询(全JDK版本兼容,无任何报错)
|
|
|
+ */
|
|
|
+ @ApiOperation(value = "理赔申请综合查询", notes = "支持多条件组合查询,返回包含附件和审核记录的完整信息(带数据权限过滤)")
|
|
|
+ @ApiImplicitParams({
|
|
|
+ @ApiImplicitParam(name = "claimNo", value = "理赔单号(精准)", paramType = "query", dataType = "string"),
|
|
|
+ @ApiImplicitParam(name = "claimSourceType", value = "来源类型 1经销商 2门店 3终端消费者", paramType = "query", dataType = "int"),
|
|
|
+ @ApiImplicitParam(name = "auditStatus", value = "审核状态 0待审核 1审核中 2已通过 3已拒绝", paramType = "query", dataType = "int"),
|
|
|
+ @ApiImplicitParam(name = "consumerName", value = "消费者姓名(模糊)", paramType = "query", dataType = "string"),
|
|
|
+ @ApiImplicitParam(name = "consumerPhone", value = "消费者电话(模糊)", paramType = "query", dataType = "string"),
|
|
|
+ @ApiImplicitParam(name = "tyreNo", value = "胎号/轮胎宝编号(模糊)", paramType = "query", dataType = "string"),
|
|
|
+ @ApiImplicitParam(name = "tyreSpecs", value = "规格型号(模糊)", paramType = "query", dataType = "string"),
|
|
|
+ // 日期参数改为字符串接收,前端传yyyy-MM-dd HH:mm:ss格式
|
|
|
+ @ApiImplicitParam(name = "purchaseDateStartStr", value = "购买日期开始(yyyy-MM-dd HH:mm:ss)", paramType = "query", dataType = "string"),
|
|
|
+ @ApiImplicitParam(name = "purchaseDateEndStr", value = "购买日期结束(yyyy-MM-dd HH:mm:ss)", paramType = "query", dataType = "string"),
|
|
|
+ @ApiImplicitParam(name = "claimAmountMin", value = "索赔金额最小值", paramType = "query", dataType = "bigdecimal"),
|
|
|
+ @ApiImplicitParam(name = "claimAmountMax", value = "索赔金额最大值", paramType = "query", dataType = "bigdecimal"),
|
|
|
+ @ApiImplicitParam(name = "runMileageMin", value = "行驶里程最小值(km)", paramType = "query", dataType = "int"),
|
|
|
+ @ApiImplicitParam(name = "runMileageMax", value = "行驶里程最大值(km)", paramType = "query", dataType = "int"),
|
|
|
+ @ApiImplicitParam(name = "isSubmitTime", value = "是否已提交 0未提交 1已提交", paramType = "query", dataType = "int"),
|
|
|
+ @ApiImplicitParam(name = "pageNum", value = "页码(默认1)", paramType = "query", dataType = "int", defaultValue = "1"),
|
|
|
+ @ApiImplicitParam(name = "pageSize", value = "每页条数(默认10,最大100)", paramType = "query", dataType = "int", defaultValue = "10")
|
|
|
+ })
|
|
|
+ @GetMapping("/comprehensive")
|
|
|
+ public R<IPage<ClaimSearchVO>> comprehensiveSearch(
|
|
|
+ // 精准查询参数
|
|
|
+ @RequestParam(required = false) String claimNo,
|
|
|
+ @RequestParam(required = false) Integer claimSourceType,
|
|
|
+ @RequestParam(required = false) Integer auditStatus,
|
|
|
+ @RequestParam(required = false) Integer isSubmitTime,
|
|
|
+ // 模糊查询参数
|
|
|
+ @RequestParam(required = false) String consumerName,
|
|
|
+ @RequestParam(required = false) String consumerPhone,
|
|
|
+ @RequestParam(required = false) String tyreNo,
|
|
|
+ @RequestParam(required = false) String tyreSpecs,
|
|
|
+ // 日期参数:字符串接收(核心修复,避免DateTimeFormatter报错)
|
|
|
+ @RequestParam(required = false) String purchaseDateStartStr,
|
|
|
+ @RequestParam(required = false) String purchaseDateEndStr,
|
|
|
+ // 数值范围参数
|
|
|
+ @RequestParam(required = false) BigDecimal claimAmountMin,
|
|
|
+ @RequestParam(required = false) BigDecimal claimAmountMax,
|
|
|
+ @RequestParam(required = false) Integer runMileageMin,
|
|
|
+ @RequestParam(required = false) Integer runMileageMax,
|
|
|
+ // 分页参数
|
|
|
+ @RequestParam(defaultValue = "1") Integer pageNum,
|
|
|
+ @RequestParam(defaultValue = "10") Integer pageSize
|
|
|
+ ) {
|
|
|
+ try {
|
|
|
+ // ========== 1. 登录校验 ==========
|
|
|
+ Long userId = AuthUtil.getUserId();
|
|
|
+ if (userId == null) {
|
|
|
+ return R.fail("请先登录后再进行查询");
|
|
|
+ }
|
|
|
+
|
|
|
+ // ========== 2. 分页参数校验 ==========
|
|
|
+ pageNum = Math.max(pageNum, 1);
|
|
|
+ pageSize = Math.max(Math.min(pageSize, 100), 1);
|
|
|
+
|
|
|
+ // ========== 3. 日期转换(兼容所有JDK版本,核心修复) ==========
|
|
|
+ LocalDateTime purchaseDateStart = null;
|
|
|
+ LocalDateTime purchaseDateEnd = null;
|
|
|
+ // 使用JDK1.0就支持的SimpleDateFormat,彻底避免版本问题
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
|
+
|
|
|
+ // 转换开始日期
|
|
|
+ if (StringUtils.isNotBlank(purchaseDateStartStr)) {
|
|
|
+ try {
|
|
|
+ Date startDate = sdf.parse(purchaseDateStartStr);
|
|
|
+ // Date转LocalDateTime(兼容JDK8+,如果是JDK7则需调整实体类字段为Date)
|
|
|
+ purchaseDateStart = LocalDateTime.ofInstant(startDate.toInstant(), ZoneId.systemDefault());
|
|
|
+ } catch (ParseException e) {
|
|
|
+ return R.fail("购买开始日期格式错误,正确格式:yyyy-MM-dd HH:mm:ss,例如:2025-01-01 12:00:00");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 转换结束日期
|
|
|
+ if (StringUtils.isNotBlank(purchaseDateEndStr)) {
|
|
|
+ try {
|
|
|
+ Date endDate = sdf.parse(purchaseDateEndStr);
|
|
|
+ purchaseDateEnd = LocalDateTime.ofInstant(endDate.toInstant(), ZoneId.systemDefault());
|
|
|
+ } catch (ParseException e) {
|
|
|
+ return R.fail("购买结束日期格式错误,正确格式:yyyy-MM-dd HH:mm:ss,例如:2025-01-01 12:00:00");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ========== 4. 业务参数校验 ==========
|
|
|
+ // 日期范围校验
|
|
|
+ if (purchaseDateStart != null && purchaseDateEnd != null && purchaseDateStart.isAfter(purchaseDateEnd)) {
|
|
|
+ return R.fail("购买开始日期不能晚于结束日期");
|
|
|
+ }
|
|
|
+ // 金额范围校验
|
|
|
+ if (claimAmountMin != null && claimAmountMax != null && claimAmountMin.compareTo(claimAmountMax) > 0) {
|
|
|
+ return R.fail("索赔金额最小值不能大于最大值");
|
|
|
+ }
|
|
|
+ // 里程范围校验
|
|
|
+ if (runMileageMin != null && runMileageMax != null && runMileageMin > runMileageMax) {
|
|
|
+ return R.fail("行驶里程最小值不能大于最大值");
|
|
|
+ }
|
|
|
+ // 枚举值校验(兼容JDK8-,替换List.of为Arrays.asList)
|
|
|
+ if (auditStatus != null && !Arrays.asList(0, 1, 2, 3).contains(auditStatus)) {
|
|
|
+ return R.fail("审核状态值不合法,可选值:0-待审核 1-审核中 2-已通过 3-已拒绝");
|
|
|
+ }
|
|
|
+ if (claimSourceType != null && !Arrays.asList(1, 2, 3).contains(claimSourceType)) {
|
|
|
+ return R.fail("来源类型值不合法,可选值:1-经销商 2-门店 3-终端消费者");
|
|
|
+ }
|
|
|
+ if (isSubmitTime != null && !Arrays.asList(0, 1).contains(isSubmitTime)) {
|
|
|
+ return R.fail("是否已提交值不合法,可选值:0-未提交 1-已提交");
|
|
|
+ }
|
|
|
+
|
|
|
+ // ========== 5. 构建查询条件 ==========
|
|
|
+ LambdaQueryWrapper<PcBladeClaim> wrapper = new LambdaQueryWrapper<PcBladeClaim>()
|
|
|
+ // 精准查询
|
|
|
+ .eq(StringUtils.isNotBlank(claimNo), PcBladeClaim::getClaimNo, claimNo)
|
|
|
+ .eq(claimSourceType != null, PcBladeClaim::getClaimSourceType, claimSourceType)
|
|
|
+ .eq(auditStatus != null, PcBladeClaim::getAuditStatus, auditStatus)
|
|
|
+ .eq(isSubmitTime != null, PcBladeClaim::getIsSubmitTime, isSubmitTime)
|
|
|
+ // 模糊查询(添加%通配符)
|
|
|
+ .like(StringUtils.isNotBlank(consumerName), PcBladeClaim::getConsumerName, "%" + consumerName + "%")
|
|
|
+ .like(StringUtils.isNotBlank(consumerPhone), PcBladeClaim::getConsumerPhone, "%" + consumerPhone + "%")
|
|
|
+ .like(StringUtils.isNotBlank(tyreNo), PcBladeClaim::getTyreNo, "%" + tyreNo + "%")
|
|
|
+ .like(StringUtils.isNotBlank(tyreSpecs), PcBladeClaim::getTyreSpecs, "%" + tyreSpecs + "%")
|
|
|
+ // 日期范围
|
|
|
+ .ge(purchaseDateStart != null, PcBladeClaim::getPurchaseDate, purchaseDateStart)
|
|
|
+ .le(purchaseDateEnd != null, PcBladeClaim::getPurchaseDate, purchaseDateEnd)
|
|
|
+ // 数值范围
|
|
|
+ .ge(claimAmountMin != null, PcBladeClaim::getClaimAmount, claimAmountMin)
|
|
|
+ .le(claimAmountMax != null, PcBladeClaim::getClaimAmount, claimAmountMax)
|
|
|
+ .ge(runMileageMin != null, PcBladeClaim::getRunMileage, runMileageMin)
|
|
|
+ .le(runMileageMax != null, PcBladeClaim::getRunMileage, runMileageMax)
|
|
|
+ // 数据权限(适配实体类BaseEntity的createUser字段)
|
|
|
+ .eq(PcBladeClaim::getCreateUser, userId)
|
|
|
+ // 排序
|
|
|
+ .orderByDesc(PcBladeClaim::getSubmitTime)
|
|
|
+ .orderByDesc(PcBladeClaim::getCreateTime);
|
|
|
+
|
|
|
+ // ========== 6. 分页查询主表 ==========
|
|
|
+ IPage<PcBladeClaim> page = new Page<>(pageNum, pageSize);
|
|
|
+ page = pcBladeClaimService.page(page, wrapper);
|
|
|
+ List<PcBladeClaim> claimList = page.getRecords();
|
|
|
+
|
|
|
+ if (org.springframework.util.CollectionUtils.isEmpty(claimList)) {
|
|
|
+ // 返回空分页对象,保持结构统一
|
|
|
+ IPage<ClaimSearchVO> emptyPage = new Page<>(pageNum, pageSize, 0);
|
|
|
+ return R.data(emptyPage);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ========== 7. 批量查询关联数据(避免N+1) ==========
|
|
|
+ List<Long> claimIds = claimList.stream().map(PcBladeClaim::getId).collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 查询附件
|
|
|
+ List<PcBladeClaimAttachment> attachmentList = pcBladeClaimAttachmentService.list(
|
|
|
+ new LambdaQueryWrapper<PcBladeClaimAttachment>().in(PcBladeClaimAttachment::getClaimId, claimIds)
|
|
|
+ );
|
|
|
+ Map<Long, List<PcBladeClaimAttachment>> attachmentMap = attachmentList.stream()
|
|
|
+ .collect(Collectors.groupingBy(PcBladeClaimAttachment::getClaimId));
|
|
|
+
|
|
|
+ // 查询审核记录
|
|
|
+ List<PcBladeClaimAudit> auditList = pcBladeClaimAuditService.list(
|
|
|
+ new LambdaQueryWrapper<PcBladeClaimAudit>()
|
|
|
+ .in(PcBladeClaimAudit::getClaimId, claimIds)
|
|
|
+ .orderByDesc(PcBladeClaimAudit::getAuditTime)
|
|
|
+ );
|
|
|
+ Map<Long, List<PcBladeClaimAudit>> auditMap = auditList.stream()
|
|
|
+ .collect(Collectors.groupingBy(PcBladeClaimAudit::getClaimId));
|
|
|
+
|
|
|
+ // ========== 8. 组装返回VO ==========
|
|
|
+ List<ClaimSearchVO> resultVOList = new ArrayList<>();
|
|
|
+ for (PcBladeClaim claim : claimList) {
|
|
|
+ ClaimSearchVO vo = new ClaimSearchVO();
|
|
|
+ vo.setClaimMain(claim);
|
|
|
+ // 关联附件(无则返回空列表)
|
|
|
+ vo.setAttachments(attachmentMap.getOrDefault(claim.getId(), new ArrayList<>()));
|
|
|
+ // 关联审核记录
|
|
|
+ vo.setAuditRecords(auditMap.getOrDefault(claim.getId(), new ArrayList<>()));
|
|
|
+ resultVOList.add(vo);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ========== 9. 封装分页结果 ==========
|
|
|
+ IPage<ClaimSearchVO> resultPage = new Page<>();
|
|
|
+ resultPage.setCurrent(page.getCurrent());
|
|
|
+ resultPage.setSize(page.getSize());
|
|
|
+ resultPage.setTotal(page.getTotal());
|
|
|
+ resultPage.setPages(page.getPages());
|
|
|
+ resultPage.setRecords(resultVOList);
|
|
|
+
|
|
|
+ return R.data(resultPage);
|
|
|
+
|
|
|
+ } catch (IllegalArgumentException e) {
|
|
|
+ return R.fail("参数错误:" + e.getMessage());
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 生产环境建议添加日志记录
|
|
|
+ // log.error("理赔综合查询异常", e);
|
|
|
+ return R.fail("查询失败,请稍后重试");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 补充:导入StringUtils工具类(避免空值判断报错)
|
|
|
+ private static class StringUtils {
|
|
|
+ public static boolean isNotBlank(String str) {
|
|
|
+ return str != null && !str.trim().isEmpty();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|