Commit 89d18b1d874e316632105a7e632230d734b78b54

Authored by 房远帅
1 parent 0ead1424

销售客户资信批量导出优化

@@ -9,6 +9,7 @@ import com.lframework.starter.bpm.mappers.FlowTaskWrapperMapper; @@ -9,6 +9,7 @@ import com.lframework.starter.bpm.mappers.FlowTaskWrapperMapper;
9 import com.lframework.starter.bpm.service.FlowInstanceWrapperService; 9 import com.lframework.starter.bpm.service.FlowInstanceWrapperService;
10 import com.lframework.starter.bpm.vo.flow.task.QueryTodoTaskListVo; 10 import com.lframework.starter.bpm.vo.flow.task.QueryTodoTaskListVo;
11 import com.lframework.starter.common.utils.StringUtil; 11 import com.lframework.starter.common.utils.StringUtil;
  12 +import com.lframework.starter.mq.core.utils.ExportTaskUtil;
12 import com.lframework.starter.web.core.annotations.security.HasPermission; 13 import com.lframework.starter.web.core.annotations.security.HasPermission;
13 import com.lframework.starter.web.core.components.redis.RedisHandler; 14 import com.lframework.starter.web.core.components.redis.RedisHandler;
14 import com.lframework.starter.web.core.components.security.SecurityUtil; 15 import com.lframework.starter.web.core.components.security.SecurityUtil;
@@ -501,133 +502,18 @@ public class CustomerCreditController extends DefaultBaseController { @@ -501,133 +502,18 @@ public class CustomerCreditController extends DefaultBaseController {
501 } 502 }
502 503
503 /** 504 /**
504 - * 按筛选条件批量导出(按导入模板结构) 505 + * 按筛选条件批量导出(异步导出,按导入模板结构,核心人员只导出第一个法定代表人)
505 */ 506 */
506 - @ApiOperation("按筛选条件批量导出")  
507 - @HasPermission({"customer-credit-manage:customer-credit-plan:export"}) 507 + @ApiOperation("按筛选条件批量导出(异步)")
508 @GetMapping("/export/list") 508 @GetMapping("/export/list")
509 - public void exportByCondition(@Valid QueryCustomerCreditVo vo, HttpServletResponse response) throws IOException { 509 + public InvokeResult<Void> exportByCondition(@Valid QueryCustomerCreditVo vo) {
  510 + //数据查询权限
510 applyQueryPermission(vo); 511 applyQueryPermission(vo);
  512 + vo.setExportType("CUSTOMER_CREDIT");
511 513
512 - List<CustomerCredit> datas = customerCreditService.query(vo);  
513 - String fileName = "客户资信批量导出.xlsx";  
514 - response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");  
515 - String encoded = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name()).replace("+", "%20");  
516 - response.setHeader("Content-Disposition",  
517 - "attachment; filename=\"" + encoded + "\"; filename*=UTF-8''" + encoded);  
518 -  
519 - DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");  
520 - List<CustomerCreditBatchExportModel> models = new ArrayList<>(datas.size());  
521 - int idx = 1;  
522 - for (CustomerCredit credit : datas) {  
523 - GetCustomerCreditBo bo = packCustomerCreditData(credit);  
524 - CustomerCreditBatchExportModel m = new CustomerCreditBatchExportModel();  
525 - m.setSort(String.valueOf(idx++));  
526 - m.setCode(bo.getSerialNumber());  
527 - m.setDeptName(bo.getDeptName());  
528 - m.setRegionName(bo.getRegionName());  
529 - m.setCustomerShortName(bo.getCustomerShortName());  
530 - m.setRegisterDateStr(bo.getRegisterDate() == null ? "" : bo.getRegisterDate().format(dateFormatter));  
531 - m.setName(bo.getCompanyName());  
532 - m.setEnterpriseType(convertEnterpriseType(bo.getEnterpriseType()));  
533 - m.setCompanyNature(bo.getCompanyNature());  
534 - m.setCompanyAddress(bo.getCompanyAddress());  
535 - m.setRegisteredCapital(bo.getRegisteredCapital());  
536 - m.setBankAccount(bo.getBankAccount());  
537 - m.setBankName(bo.getBankName());  
538 - m.setTaxNumber(bo.getTaxNumber());  
539 - m.setRegistrationTimeStr(bo.getRegistrationTime() == null ? "" : bo.getRegistrationTime().format(dateFormatter));  
540 - m.setBusinessYears(bo.getBusinessYears());  
541 -  
542 - CorePersonnel legal = null;  
543 - if (CollectionUtils.isNotEmpty(bo.getCorePersonnelList())) {  
544 - legal = bo.getCorePersonnelList().stream()  
545 - .filter(p -> "法定代表人".equals(p.getPosition()))  
546 - .findFirst()  
547 - .orElse(null);  
548 - }  
549 - if (legal != null) {  
550 - m.setUserName1(legal.getName());  
551 - m.setAge1(legal.getAge());  
552 - m.setSex1(legal.getSex());  
553 - m.setNativePlace1(legal.getNativePlace());  
554 - m.setAddress1(legal.getAddress());  
555 - m.setMobile1(legal.getMobile());  
556 - m.setPhone1(legal.getPhone());  
557 - m.setEmail1(legal.getEmail());  
558 - } 514 + ExportTaskUtil.exportTask("客户资信批量导出", CustomerCreditBatchExportTaskWorker.class, vo);
559 515
560 - m.setBusinessProperty(bo.getBusinessProperty());  
561 - m.setBusinessScope(bo.getBusinessScope());  
562 - m.setLandArea(bo.getLandArea());  
563 - m.setStorageConditions(bo.getStorageConditions());  
564 - m.setEmployeeCount(bo.getEmployeeCount());  
565 - m.setEquipmentAttributes(bo.getEquipmentAttributes());  
566 - m.setAssetEvaluation(bo.getAssetEvaluation());  
567 - m.setLastYearSales(bo.getLastYearSales());  
568 - m.setMonthlyAvgSales(bo.getMonthlyAvgSales());  
569 - m.setInvoiceItemUnit(bo.getInvoiceItemUnit());  
570 - m.setCertificationCertificate(bo.getCertificationCertificate());  
571 - m.setProductMatch(bo.getProductMatch());  
572 - m.setMajorCustomers(bo.getMajorCustomers());  
573 - m.setMainProjects(bo.getMainProjects());  
574 - m.setIndustryInvolved(bo.getIndustryInvolved());  
575 - m.setIndustryExperience(bo.getIndustryExperience());  
576 - m.setHasDispute(bo.getHasDispute());  
577 - m.setCooperationStartDate(  
578 - StringUtil.isBlank(bo.getCooperationStartDate())  
579 - ? ""  
580 - : bo.getCooperationStartDate());  
581 - m.setMonthlyAvgVolume(bo.getMonthlyAvgVolume());  
582 - m.setIsVerbalAgreement(  
583 - StringUtil.isBlank(bo.getIsVerbalAgreement())  
584 - ? ""  
585 - : bo.getIsVerbalAgreement());  
586 - m.setOtherAgreements(bo.getOtherAgreements());  
587 - m.setHasLongTermContract(  
588 - StringUtil.isBlank(bo.getHasLongTermContract())  
589 - ? ""  
590 - : bo.getHasLongTermContract());  
591 - m.setContractType(bo.getContractType());  
592 - m.setHasInterruption(bo.getHasInterruption());  
593 - m.setSettlementPeriod(bo.getSettlementPeriod());  
594 - m.setMaterialSupplyPlan(bo.getMaterialSupplyPlan());  
595 - m.setSuggestedCategory(  
596 - StringUtil.isNotBlank(bo.getSuggestedCategory())  
597 - ? bo.getSuggestedCategory()  
598 - : bo.getCompanySuggestedCategory());  
599 - m.setCreditLimit(  
600 - StringUtil.isNotBlank(bo.getCreditLimit())  
601 - ? bo.getCreditLimit()  
602 - : bo.getCompanyCreditLimit());  
603 - m.setInvestigatorName(bo.getInvestigatorName());  
604 -  
605 - models.add(m);  
606 - }  
607 -  
608 - try (OutputStream out = response.getOutputStream()) {  
609 - EasyExcel.write(out, CustomerCreditBatchExportModel.class)  
610 - .registerWriteHandler(new AutoColumnWidthHandler())  
611 - .sheet("客户资信")  
612 - .doWrite(models);  
613 - }  
614 - }  
615 -  
616 - private static String convertEnterpriseType(String type) {  
617 - if (StringUtil.isBlank(type)) return "";  
618 - switch (type) {  
619 - case "DEALER":  
620 - case "经销商":  
621 - return "经销商";  
622 - case "TERMINAL":  
623 - case "终端":  
624 - return "终端";  
625 - case "FOREIGN":  
626 - case "外贸":  
627 - return "外贸";  
628 - default:  
629 - return type;  
630 - } 516 + return InvokeResultBuilder.success();
631 } 517 }
632 518
633 /** 519 /**
  1 +package com.lframework.xingyun.sc.excel.customerCredit;
  2 +
  3 +import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  4 +import com.lframework.starter.common.utils.CollectionUtil;
  5 +import com.lframework.starter.common.utils.StringUtil;
  6 +import com.lframework.starter.mq.core.components.export.ExportTaskWorker;
  7 +import com.lframework.starter.web.core.components.resp.PageResult;
  8 +import com.lframework.starter.web.core.utils.ApplicationUtil;
  9 +import com.lframework.starter.web.core.utils.JsonUtil;
  10 +import com.lframework.starter.web.core.utils.PageResultUtil;
  11 +import com.lframework.starter.web.inner.entity.SysUser;
  12 +import com.lframework.starter.web.inner.service.system.SysUserService;
  13 +import com.lframework.xingyun.sc.bo.customer.credit.GetCustomerCreditBo;
  14 +import com.lframework.xingyun.sc.entity.CorePersonnel;
  15 +import com.lframework.xingyun.sc.entity.CustomerCredit;
  16 +import com.lframework.xingyun.sc.service.customer.CorePersonnelService;
  17 +import com.lframework.xingyun.sc.service.customer.CustomerCreditService;
  18 +import com.lframework.xingyun.sc.vo.customer.credit.QueryCustomerCreditVo;
  19 +import org.apache.commons.collections4.CollectionUtils;
  20 +
  21 +import java.time.LocalDate;
  22 +import java.time.format.DateTimeFormatter;
  23 +import java.util.ArrayList;
  24 +import java.util.Collections;
  25 +import java.util.HashMap;
  26 +import java.util.List;
  27 +import java.util.Map;
  28 +import java.util.concurrent.atomic.AtomicInteger;
  29 +import java.util.function.Function;
  30 +import java.util.stream.Collectors;
  31 +
  32 +/**
  33 + * 客户资信按筛选条件批量导出(按导入模板结构,核心人员只导出第一个法定代表人)
  34 + */
  35 +public class CustomerCreditBatchExportTaskWorker implements
  36 + ExportTaskWorker<QueryCustomerCreditVo, GetCustomerCreditBo, CustomerCreditBatchExportModel> {
  37 +
  38 + private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  39 +
  40 + /**
  41 + * 序号自增(异步导出按分页顺序逐行调用 exportData,每次任务实例新建,从 1 开始)
  42 + */
  43 + private final AtomicInteger sortCounter = new AtomicInteger(0);
  44 +
  45 + @Override
  46 + public QueryCustomerCreditVo parseParams(String json) {
  47 + return JsonUtil.parseObject(json, QueryCustomerCreditVo.class);
  48 + }
  49 +
  50 + @Override
  51 + public PageResult<GetCustomerCreditBo> getDataList(int pageIndex, int pageSize, QueryCustomerCreditVo params) {
  52 + CustomerCreditService customerCreditService = ApplicationUtil.getBean(CustomerCreditService.class);
  53 + PageResult<CustomerCredit> pageResult = customerCreditService.query(pageIndex, pageSize, params);
  54 + List<CustomerCredit> dataList = pageResult.getDatas();
  55 + List<GetCustomerCreditBo> results = null;
  56 + if (!CollectionUtil.isEmpty(dataList)) {
  57 + results = this.packCustomerCreditData(dataList);
  58 + }
  59 + return PageResultUtil.rebuild(pageResult, results);
  60 + }
  61 +
  62 + @Override
  63 + public CustomerCreditBatchExportModel exportData(GetCustomerCreditBo data) {
  64 + return this.buildModel(data);
  65 + }
  66 +
  67 + @Override
  68 + public Class<CustomerCreditBatchExportModel> getModelClass() {
  69 + return CustomerCreditBatchExportModel.class;
  70 + }
  71 +
  72 + /**
  73 + * 批量封装关联数据:每个资信的第一个“法定代表人”核心人员 + 调查人姓名
  74 + */
  75 + private List<GetCustomerCreditBo> packCustomerCreditData(List<CustomerCredit> dataList) {
  76 + List<String> creditIds = dataList.stream()
  77 + .map(CustomerCredit::getId)
  78 + .filter(StringUtil::isNotBlank)
  79 + .distinct()
  80 + .collect(Collectors.toList());
  81 +
  82 + // 每个资信的第一个法定代表人(按 id 排序保证多次导出结果稳定)
  83 + Map<String, CorePersonnel> legalMap = new HashMap<>();
  84 + if (CollectionUtils.isNotEmpty(creditIds)) {
  85 + CorePersonnelService corePersonnelService = ApplicationUtil.getBean(CorePersonnelService.class);
  86 + List<CorePersonnel> personnelList = corePersonnelService.list(
  87 + Wrappers.lambdaQuery(CorePersonnel.class)
  88 + .in(CorePersonnel::getCreditId, creditIds)
  89 + .eq(CorePersonnel::getPosition, "法定代表人")
  90 + .orderByAsc(CorePersonnel::getId));
  91 + if (CollectionUtils.isNotEmpty(personnelList)) {
  92 + for (CorePersonnel personnel : personnelList) {
  93 + // keep-first:同一资信只保留第一个法定代表人
  94 + legalMap.putIfAbsent(personnel.getCreditId(), personnel);
  95 + }
  96 + }
  97 + }
  98 +
  99 + // 调查人姓名
  100 + List<String> investigatorIds = dataList.stream()
  101 + .map(CustomerCredit::getInvestigator)
  102 + .filter(StringUtil::isNotBlank)
  103 + .distinct()
  104 + .collect(Collectors.toList());
  105 + Map<String, SysUser> investigatorMap = new HashMap<>();
  106 + if (CollectionUtils.isNotEmpty(investigatorIds)) {
  107 + SysUserService sysUserService = ApplicationUtil.getBean(SysUserService.class);
  108 + List<SysUser> users = sysUserService.listByIds(investigatorIds);
  109 + if (CollectionUtils.isNotEmpty(users)) {
  110 + investigatorMap = users.stream()
  111 + .collect(Collectors.toMap(SysUser::getId, Function.identity(), (k1, k2) -> k1));
  112 + }
  113 + }
  114 +
  115 + List<GetCustomerCreditBo> result = new ArrayList<>(dataList.size());
  116 + for (CustomerCredit credit : dataList) {
  117 + GetCustomerCreditBo bo = new GetCustomerCreditBo(credit);
  118 + CorePersonnel legal = legalMap.get(credit.getId());
  119 + bo.setCorePersonnelList(legal == null
  120 + ? Collections.emptyList()
  121 + : Collections.singletonList(legal));
  122 + SysUser investigator = investigatorMap.get(credit.getInvestigator());
  123 + if (investigator != null) {
  124 + bo.setInvestigatorName(investigator.getName());
  125 + }
  126 + result.add(bo);
  127 + }
  128 + return result;
  129 + }
  130 +
  131 + /**
  132 + * GetCustomerCreditBo → 导入模板结构导出行
  133 + */
  134 + private CustomerCreditBatchExportModel buildModel(GetCustomerCreditBo bo) {
  135 + CustomerCreditBatchExportModel m = new CustomerCreditBatchExportModel();
  136 + m.setSort(String.valueOf(sortCounter.incrementAndGet()));
  137 + m.setCode(bo.getSerialNumber());
  138 + m.setDeptName(bo.getDeptName());
  139 + m.setRegionName(bo.getRegionName());
  140 + m.setCustomerShortName(bo.getCustomerShortName());
  141 + m.setRegisterDateStr(formatDate(bo.getRegisterDate()));
  142 + m.setName(bo.getCompanyName());
  143 + m.setEnterpriseType(convertEnterpriseType(bo.getEnterpriseType()));
  144 + m.setCompanyNature(bo.getCompanyNature());
  145 + m.setCompanyAddress(bo.getCompanyAddress());
  146 + m.setRegisteredCapital(bo.getRegisteredCapital());
  147 + m.setBankAccount(bo.getBankAccount());
  148 + m.setBankName(bo.getBankName());
  149 + m.setTaxNumber(bo.getTaxNumber());
  150 + m.setRegistrationTimeStr(formatDate(bo.getRegistrationTime()));
  151 + m.setBusinessYears(bo.getBusinessYears());
  152 +
  153 + if (CollectionUtils.isNotEmpty(bo.getCorePersonnelList())) {
  154 + CorePersonnel legal = bo.getCorePersonnelList().get(0);
  155 + m.setUserName1(legal.getName());
  156 + m.setAge1(legal.getAge());
  157 + m.setSex1(legal.getSex());
  158 + m.setNativePlace1(legal.getNativePlace());
  159 + m.setAddress1(legal.getAddress());
  160 + m.setMobile1(legal.getMobile());
  161 + m.setPhone1(legal.getPhone());
  162 + m.setEmail1(legal.getEmail());
  163 + }
  164 +
  165 + m.setBusinessProperty(bo.getBusinessProperty());
  166 + m.setBusinessScope(bo.getBusinessScope());
  167 + m.setLandArea(bo.getLandArea());
  168 + m.setStorageConditions(bo.getStorageConditions());
  169 + m.setEmployeeCount(bo.getEmployeeCount());
  170 + m.setEquipmentAttributes(bo.getEquipmentAttributes());
  171 + m.setAssetEvaluation(bo.getAssetEvaluation());
  172 + m.setLastYearSales(bo.getLastYearSales());
  173 + m.setMonthlyAvgSales(bo.getMonthlyAvgSales());
  174 + m.setInvoiceItemUnit(bo.getInvoiceItemUnit());
  175 + m.setCertificationCertificate(bo.getCertificationCertificate());
  176 + m.setProductMatch(bo.getProductMatch());
  177 + m.setMajorCustomers(bo.getMajorCustomers());
  178 + m.setMainProjects(bo.getMainProjects());
  179 + m.setIndustryInvolved(bo.getIndustryInvolved());
  180 + m.setIndustryExperience(bo.getIndustryExperience());
  181 + m.setHasDispute(bo.getHasDispute());
  182 + m.setCooperationStartDate(bo.getCooperationStartDate());
  183 + m.setMonthlyAvgVolume(bo.getMonthlyAvgVolume());
  184 + m.setIsVerbalAgreement(bo.getIsVerbalAgreement());
  185 + m.setOtherAgreements(bo.getOtherAgreements());
  186 + m.setHasLongTermContract(bo.getHasLongTermContract());
  187 + m.setContractType(bo.getContractType());
  188 + m.setHasInterruption(bo.getHasInterruption());
  189 + m.setSettlementPeriod(bo.getSettlementPeriod());
  190 + m.setMaterialSupplyPlan(bo.getMaterialSupplyPlan());
  191 + m.setSuggestedCategory(StringUtil.isNotBlank(bo.getSuggestedCategory())
  192 + ? bo.getSuggestedCategory() : bo.getCompanySuggestedCategory());
  193 + m.setCreditLimit(StringUtil.isNotBlank(bo.getCreditLimit())
  194 + ? bo.getCreditLimit() : bo.getCompanyCreditLimit());
  195 + m.setInvestigatorName(bo.getInvestigatorName());
  196 + return m;
  197 + }
  198 +
  199 + private static String formatDate(LocalDate date) {
  200 + return date == null ? "" : date.format(DATE_FORMATTER);
  201 + }
  202 +
  203 + private static String convertEnterpriseType(String type) {
  204 + if (StringUtil.isBlank(type)) {
  205 + return "";
  206 + }
  207 + switch (type) {
  208 + case "DEALER":
  209 + case "经销商":
  210 + return "经销商";
  211 + case "TERMINAL":
  212 + case "终端":
  213 + return "终端";
  214 + case "FOREIGN":
  215 + case "外贸":
  216 + return "外贸";
  217 + default:
  218 + return type;
  219 + }
  220 + }
  221 +}