Browse Source

Merge remote-tracking branch 'origin/dev_jzg_lipf_v20260518' into dev_jzg_lipf_v20260518

# Conflicts:
#	tenant/organization/src/main/java/com/jzg/organization/service/ReceivableService.java
lipf 4 months ago
parent
commit
a8f850fa43

+ 6 - 1
commons/src/main/java/com/jzg/commons/entity/finance/vo/ImportUpdateExcelResultVo.java

@@ -24,10 +24,15 @@ public class ImportUpdateExcelResultVo {
     /**
      * 失败数据  修复这里!
      */
-    private List<ReceivableExportExcelVo> failedData;
+    private List<?> failedData;
 
     /**
      * 新增:失败文件下载链接
      */
     private String failFileUrl;
+
+    /**
+     * 新增成功的订单编号
+     */
+    private List<?> orderNos;
 }

+ 205 - 0
commons/src/main/java/com/jzg/commons/entity/finance/vo/InvoiceReceivableExportExcelVo.java

@@ -0,0 +1,205 @@
+package com.jzg.commons.entity.finance.vo;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.jzg.commons.core.base.BaseModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import java.util.Objects;
+
+/**
+ * @author tz
+ * @description 应收查询VO
+ * @createDate 2024-06-26 10:49:31
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(description = "财务应收表")
+public class InvoiceReceivableExportExcelVo extends BaseModel  {
+
+    @Serial
+    private static final long serialVersionUID = 6263862008363938379L;
+
+    @Schema(description = "选中类型")
+    @ExcelIgnore
+    // 1 全部数据选中  2 选中部分数据
+    private String selectedType;
+
+    @Schema(description = "id")
+    @ExcelIgnore
+    private String id;
+
+    @Schema(description = "签单时间")
+    @ExcelProperty(value = "签单时间", index = 0)
+    private String signingTime;
+
+    @Schema(description = "协议代码")
+    @ExcelProperty(value = "协议代码", index = 1)
+    private String agreementCode;
+
+    @Schema(description = "车牌号")
+    @ExcelProperty(value = "车牌号", index = 2)
+    private String licenseNo;
+
+    @Schema(description = "险种编号")
+    @ExcelProperty(value = "险种编号", index = 3)
+    private String productId;
+
+    @Schema(description = "险种名称")
+    @ExcelProperty(value = "险种名称", index = 4)
+    private String productName;
+
+    @Schema(description = "被保险人姓名")
+    @ExcelProperty(value = "被保险人姓名", index = 5)
+    private String insuredPerson;
+
+    @Schema(description = "订单号")
+    @ExcelProperty(value = "订单号", index = 6)
+    private String orderNo;
+
+    @Schema(description = "交强险保单号")
+    @ExcelProperty(value = "交强险保单号", index = 7)
+    private String jqPolicyNo;
+
+    @Schema(description = "交强险手续费比例")
+    @ExcelProperty(value = "交强险手续费比例(%)", index = 8)
+    private String jqSuperviseCostsProportion;
+
+    @Schema(description = "交强险跟单费比例")
+    @ExcelProperty(value = "交强险跟单费比例(%)", index = 9)
+    private String jqOtherCostsProportion;
+
+    @Schema(description = "商业险保单号")
+    @ExcelProperty(value = "商业险保单号", index = 10)
+    private String syPolicyNo;
+
+    @Schema(description = "商业险手续费比例")
+    @ExcelProperty(value = "商业险手续费比例(%)", index = 11)
+    private String sySuperviseCostsProportion;
+
+    @Schema(description = "商业险跟单费比例")
+    @ExcelProperty(value = "商业险跟单费比例(%)", index = 12)
+    private String syOtherCostsProportion;
+
+    @Schema(description = "非车险保单号")
+    @ExcelProperty(value = "非车险保单号", index = 13)
+    private String jyPolicyNo;
+
+    @Schema(description = "非车险手续费比例")
+    @ExcelProperty(value = "非车险手续费比例(%)", index = 14)
+    private String jySuperviseCostsProportion;
+
+    @Schema(description = "非车险跟单费比例")
+    @ExcelProperty(value = "非车险跟单费比例(%)", index = 15)
+    private String jyOtherCostsProportion;
+
+    @Schema(description = "公司编码")
+    @ExcelProperty(value = "公司编码", index = 16)
+    private String companyId;
+
+    @Schema(description = "错误信息")
+    @ExcelIgnore
+    private String errorMessage;
+
+    public ImportResultVo checkEmpty(){
+        ImportResultVo resultVo = new ImportResultVo();
+        resultVo.setSuccess(false);
+        // 基础必填字段校验
+        if (StrUtil.isBlank(this.getSigningTime())) {
+            resultVo.setMessage("签单时间不能为空");
+            return resultVo;
+        }
+        if (StrUtil.isBlank(this.getAgreementCode())) {
+            resultVo.setMessage("协议代码不能为空");
+            return resultVo;
+        }
+        if (StrUtil.isBlank(this.getOrderNo())) {
+            resultVo.setMessage("订单号不能为空");
+            return resultVo;
+        }
+        if (StrUtil.isBlank(this.getLicenseNo())) {
+            resultVo.setMessage("车牌号不能为空");
+            return resultVo;
+        }
+        if (StrUtil.isBlank(this.getProductId())) {
+            resultVo.setMessage("险种编号不能为空");
+            return resultVo;
+        }
+        if (StrUtil.isBlank(this.getProductName())) {
+            resultVo.setMessage("险种名称不能为空");
+            return resultVo;
+        }
+        if (StrUtil.isBlank(this.getInsuredPerson())) {
+            resultVo.setMessage("被保险人姓名不能为空");
+            return resultVo;
+        }
+        if (StrUtil.isBlank(this.getCompanyId())) {
+            resultVo.setMessage("公司编码不能为空");
+            return resultVo;
+        }
+
+        // 交强险:有保单号 → 手续费、跟单费必填
+        if (StrUtil.isNotBlank(this.getJqPolicyNo())
+                || StrUtil.isNotBlank(this.getJqSuperviseCostsProportion())
+                || StrUtil.isNotBlank(this.getJqOtherCostsProportion())) {
+            if (StrUtil.isBlank(this.getJqPolicyNo())) {
+                resultVo.setMessage("交强险保单号不能为空");
+                return resultVo;
+            }
+            if (StrUtil.isBlank(this.getJqSuperviseCostsProportion())) {
+                resultVo.setMessage("交强险手续费比例不能为空");
+                return resultVo;
+            }
+            if (StrUtil.isBlank(this.getJqOtherCostsProportion())) {
+                resultVo.setMessage("交强险跟单费比例不能为空");
+                return resultVo;
+            }
+        }
+
+        // 商业险:有保单号 → 手续费、跟单费必填
+        if (StrUtil.isNotBlank(this.getSyPolicyNo())
+                || StrUtil.isNotBlank(this.getSySuperviseCostsProportion())
+                || StrUtil.isNotBlank(this.getSyOtherCostsProportion())) {
+            if (StrUtil.isBlank(this.getJqPolicyNo())) {
+                resultVo.setMessage("商业险保单号不能为空");
+                return resultVo;
+            }
+            if (StrUtil.isBlank(this.getSySuperviseCostsProportion())) {
+                resultVo.setMessage("商业险手续费比例不能为空");
+                return resultVo;
+            }
+            if (StrUtil.isBlank(this.getSyOtherCostsProportion())) {
+                resultVo.setMessage("商业险跟单费比例不能为空");
+                return resultVo;
+            }
+        }
+
+        // 非车险:有保单号 → 手续费、跟单费必填
+        if (StrUtil.isNotBlank(this.getJyPolicyNo())
+                || StrUtil.isNotBlank(this.getJySuperviseCostsProportion())
+                || StrUtil.isNotBlank(this.getJyOtherCostsProportion())) {
+            if (StrUtil.isBlank(this.getJqPolicyNo())) {
+                resultVo.setMessage("非车险保单号不能为空");
+                return resultVo;
+            }
+            if (StrUtil.isBlank(this.getJySuperviseCostsProportion())) {
+                resultVo.setMessage("非车险手续费比例不能为空");
+                return resultVo;
+            }
+            if (StrUtil.isBlank(this.getJyOtherCostsProportion())) {
+                resultVo.setMessage("非车险跟单费比例不能为空");
+                return resultVo;
+            }
+        }
+
+        if(Objects.isNull(resultVo.getMessage())){
+            resultVo.setSuccess(true);
+        }
+        return resultVo;
+    }
+
+}

+ 14 - 0
tenant/organization/src/main/java/com/jzg/organization/controller/ReceivableController.java

@@ -107,6 +107,20 @@ public class ReceivableController {
         return HttpResult.ok(importExcelResultVo);
     }
 
+    @PostMapping("/exportAccountsReceivableInvoiceTemplate")
+    @Operation(summary = "导出应收开票模板")
+    public HttpResult<String> exportAccountsReceivableInvoiceTemplate(){
+        String receivablePageIds = receivableService.exportAccountsReceivableInvoiceTemplate();
+        return HttpResult.ok(receivablePageIds);
+    }
+
+    @PostMapping("/importAccountsReceivableInvoice")
+    @Operation(summary = "导入应收开票数据")
+    public HttpResult<ImportUpdateExcelResultVo> importAccountsReceivableInvoice(@RequestParam("file") MultipartFile file){
+        ImportUpdateExcelResultVo importExcelResultVo = receivableService.importAccountsReceivableInvoice(file);
+        return HttpResult.ok(importExcelResultVo);
+    }
+
     /**
      *
      * @author lipf

+ 27 - 0
tenant/organization/src/main/java/com/jzg/organization/excel/listener/InvoiceReceivbleExcelListener.java

@@ -0,0 +1,27 @@
+package com.jzg.organization.excel.listener;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.jzg.commons.entity.finance.vo.InvoiceReceivableExportExcelVo;
+import com.jzg.commons.entity.finance.vo.ReceivableExportExcelVo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class InvoiceReceivbleExcelListener extends AnalysisEventListener<InvoiceReceivableExportExcelVo> {
+    private final List<InvoiceReceivableExportExcelVo> dataList = new ArrayList<>();
+
+    @Override
+    public void invoke(InvoiceReceivableExportExcelVo data, AnalysisContext context) {
+        dataList.add(data);
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+        System.out.println("Total rows: " + dataList.size());
+    }
+
+    public List<InvoiceReceivableExportExcelVo> getDataList() {
+        return dataList;
+    }
+}

+ 11 - 0
tenant/organization/src/main/java/com/jzg/organization/service/ReceivableService.java

@@ -373,5 +373,16 @@ public interface ReceivableService extends IService<InsPlyIncome> {
      */
     ImportUpdateExcelResultVo importReceivableListUpdate(MultipartFile file);
 
+    /**
+     * 导出应收开票模板
+     * @return
+     */
+    String exportAccountsReceivableInvoiceTemplate();
 
+    /**
+     * 导入应收开票数据
+     * @param file
+     * @return
+     */
+    ImportUpdateExcelResultVo importAccountsReceivableInvoice(MultipartFile file);
 }

+ 194 - 4
tenant/organization/src/main/java/com/jzg/organization/service/impl/ReceivableServiceImpl.java

@@ -29,10 +29,7 @@ import com.jzg.commons.util.*;
 import com.jzg.commons.util.idgen.IdGenerate;
 import com.jzg.organization.client.EsmInsCompanyClient;
 import com.jzg.organization.client.InsFeeOrdersClient;
-import com.jzg.organization.excel.listener.JyExcelListener;
-import com.jzg.organization.excel.listener.OtherExcelListener;
-import com.jzg.organization.excel.listener.ReceivbleExcelListener;
-import com.jzg.organization.excel.listener.SuperviseExcelListener;
+import com.jzg.organization.excel.listener.*;
 import com.jzg.organization.mapper.*;
 import com.jzg.organization.service.ReceivableService;
 import com.jzg.organization.service.SysUserJzgInfoSalesmanService;
@@ -1045,6 +1042,185 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         return importExcelResultVo;
     }
 
+    /**
+     * 导出应收开票模板
+     * @return
+     */
+    @Override
+    public String exportAccountsReceivableInvoiceTemplate() {
+        List<InvoiceReceivableExportExcelVo> emptyList = ListUtil.empty();
+
+        // 调用动态导出
+        return exportBaseService.upLoadFile(
+                InvoiceReceivableExportExcelVo.class,
+                emptyList,
+                "应收开票-导出模板-" + Instant.now()
+        );
+    }
+
+    @Override
+    public ImportUpdateExcelResultVo importAccountsReceivableInvoice(MultipartFile file) {
+        String userName = baseController.getUserName();
+        log.info("用户[{}]导入平台协议文件",userName);
+        ImportUpdateExcelResultVo importExcelResultVo = new ImportUpdateExcelResultVo();
+        List<InvoiceReceivableExportExcelVo> receivableExportExcelVos = importInvoiceReceivableExcel(file);
+        if (CollUtil.isEmpty(receivableExportExcelVos)){
+            throw new SystemException("数据不能为空,导入失败");
+        }
+        AssertionUtils.isEmpty(receivableExportExcelVos, "数据处理失败,导入失败");
+        // 获取保司名称
+        HttpResult<List<EsmInsCompany>> listHttpResult = esmInsCompanyClient.liveCompanyList();
+        AssertionUtils.isFail(listHttpResult.getCode() != 200, listHttpResult.getMsg());
+
+        int failedNumber = 0;
+        List<InvoiceReceivableExportExcelVo> failedExcel = new ArrayList<>();
+        // 只存储需要【修改】的数据
+        List<InsPlyIncome> updateExcel = new ArrayList<>();
+        List<InsPlyIncome> insertExcel = new ArrayList<>();
+        // 存储导入成功的订单号
+        List<String> successOrderNoList = new ArrayList<>();
+
+        // 校验Excel内部保单号重复
+        Set<String> existPolicyNoSet = new HashSet<>();
+        Set<String> repeatPolicyNoSet = new HashSet<>();
+        Set<String> existCompanyIdSet = new HashSet<>();
+
+        for (InvoiceReceivableExportExcelVo vo : receivableExportExcelVos) {
+            String policyNo = vo.getJqPolicyNo();
+            if (existPolicyNoSet.contains(policyNo)) {
+                repeatPolicyNoSet.add(policyNo);
+            } else {
+                existPolicyNoSet.add(policyNo);
+            }
+            existCompanyIdSet.add(vo.getCompanyId());
+        }
+
+        // 导入只能一个保司
+        if (existCompanyIdSet.size() > 1) {
+            throw new SystemException("导入数据不能包含多个保险公司");
+        }
+
+        // 处理数据
+        for (InvoiceReceivableExportExcelVo vo : receivableExportExcelVos) {
+            // 1. 空数据校验
+            ImportResultVo resultVo = vo.checkEmpty();
+            if (!resultVo.isSuccess()) {
+                failedNumber++;
+                vo.setErrorMessage(resultVo.getMessage());
+                failedExcel.add(vo);
+                continue;
+            }
+
+            // 2. Excel内部保单号重复
+            if (repeatPolicyNoSet.contains(vo.getJqPolicyNo())) {
+                failedNumber++;
+                vo.setErrorMessage("保单号重复");
+                failedExcel.add(vo);
+                continue;
+            }
+
+            // 查询数据库中是否已存在该协议
+            PtlAgreement ptlAgreement = ptlAgreementMapper.selectOne(new LambdaQueryWrapper<PtlAgreement>()
+                    .eq(PtlAgreement::getAgreementCode, vo.getAgreementCode()));
+
+            // 数据库不存在 → 直接失败
+            if (Objects.isNull(ptlAgreement)) {
+                failedNumber++;
+                vo.setErrorMessage("协议编码在协议中不存在");
+                failedExcel.add(vo);
+                continue;
+            }
+
+            // 查询数据库中是否已存在该保单号
+            InsPlyIncome existIncome = baseMapper.selectOne(new LambdaQueryWrapper<InsPlyIncome>()
+                    .eq(InsPlyIncome::getJqPolicyNo, vo.getJqPolicyNo()));
+
+            // 封装修改数据
+            InsPlyIncome insPlyIncome = new InsPlyIncome();
+            insPlyIncome.setId(IdGenerate.nextId());
+            insPlyIncome.setLicenseNo(vo.getLicenseNo());
+            insPlyIncome.setJqPolicyNo(vo.getJqPolicyNo());
+            insPlyIncome.setJqSuperviseCostsProportion(vo.getJqSuperviseCostsProportion());
+            insPlyIncome.setJqOtherCostsProportion(vo.getJqOtherCostsProportion());
+            insPlyIncome.setSyPolicyNo(vo.getSyPolicyNo());
+            insPlyIncome.setSySuperviseCostsProportion(vo.getSySuperviseCostsProportion());
+            insPlyIncome.setSyOtherCostsProportion(vo.getSyOtherCostsProportion());
+            insPlyIncome.setJyPolicyNo(vo.getJyPolicyNo());
+            insPlyIncome.setJySuperviseCostsProportion(vo.getJySuperviseCostsProportion());
+            insPlyIncome.setJyOtherCostsProportion(vo.getJyOtherCostsProportion());
+            // 签单时间
+            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+            insPlyIncome.setSigningTime(LocalDateTime.parse(vo.getSigningTime(), formatter));
+            // 协议编号
+            insPlyIncome.setAgreementId(ptlAgreement.getId());
+            insPlyIncome.setAgreementName(ptlAgreement.getAgreementName());
+            insPlyIncome.setAgreementType(ptlAgreement.getAgreementType().toString());
+            // 险种编号
+            insPlyIncome.setProductId(vo.getProductId());
+            // 险种名称
+            insPlyIncome.setProductName(vo.getProductName());
+            // 被保险人姓名
+            insPlyIncome.setInsuredPerson(vo.getInsuredPerson());
+
+            // 数据库不存在 → 直接失败
+            if (Objects.isNull(existIncome)) {
+                // 加入修改列表
+                // 机构id
+                insPlyIncome.setDeptId(baseController.getUserDeptId());
+                insPlyIncome.setCompanyId(vo.getCompanyId());
+                insPlyIncome.setOrderNo(vo.getOrderNo());
+                insertExcel.add(insPlyIncome);
+                // 新增成功,记录订单号
+                successOrderNoList.add(vo.getOrderNo());
+            }else{
+                // 数据库已存在 → 继续后续校验
+                // 判断已开票 / 已结算
+                String settlementFlag = "1";
+                if (settlementFlag.equals(existIncome.getSuperviseSettlement()) || settlementFlag.equals(existIncome.getOtherSettlement())
+                        || settlementFlag.equals(existIncome.getJySuperviseSettlement()) || settlementFlag.equals(existIncome.getJyOtherSettlement())
+                        || settlementFlag.equals(existIncome.getPlatformSuperviseSettlement()) || settlementFlag.equals(existIncome.getPlatformOtherSettlement())) {
+                    failedNumber++;
+                    vo.setErrorMessage("应收数据已结算");
+                    failedExcel.add(vo);
+                    continue;
+                }
+
+                insPlyIncome.setId(existIncome.getId());
+                // 加入修改列表
+                updateExcel.add(insPlyIncome);
+                // 更新成功,记录订单号
+                successOrderNoList.add(vo.getOrderNo());
+            }
+        }
+
+        // 执行批量更新
+        if (CollUtil.isNotEmpty(updateExcel)) {
+            baseMapper.updateById(updateExcel);
+        }else{
+            baseMapper.insert(insertExcel);
+        }
+
+        // ===================== 生成失败数据下载链接 =====================
+        String failFileUrl = "";
+        if (CollUtil.isNotEmpty(failedExcel)) {
+            failFileUrl = exportBaseService.upLoadFile(
+                    InvoiceReceivableExportExcelVo.class,
+                    failedExcel,
+                    "平台协议应收-导入失败-" + Instant.now()
+            );
+        }
+
+        // 返回结果
+        importExcelResultVo.setFailedData(failedExcel);
+        importExcelResultVo.setFailFileUrl(failFileUrl);
+        importExcelResultVo.setSuccessNumber(CollUtil.isNotEmpty(updateExcel) ? updateExcel.size() : insertExcel.size());
+        importExcelResultVo.setFailedNumber(failedNumber);
+        // 导出成功的orderNos
+        importExcelResultVo.setOrderNos(successOrderNoList);
+
+        return importExcelResultVo;
+    }
+
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -1164,6 +1340,20 @@ public class ReceivableServiceImpl extends ServiceImpl<ReceivableMapper, InsPlyI
         }
     }
 
+    public List<InvoiceReceivableExportExcelVo> importInvoiceReceivableExcel(MultipartFile file) {
+        InvoiceReceivbleExcelListener listener = new InvoiceReceivbleExcelListener();
+        try (InputStream inputStream = file.getInputStream()) {
+            EasyExcel.read(inputStream, InvoiceReceivableExportExcelVo.class, listener)
+                    .sheet()
+                    .doRead();
+            List<InvoiceReceivableExportExcelVo> dataList = listener.getDataList();
+            return dataList;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
     @Override
     public List<JyExcelVo> importJyExcel(MultipartFile file) {
         JyExcelListener listener = new JyExcelListener();