Commit 89d18b1d874e316632105a7e632230d734b78b54

Authored by 房远帅
1 parent 0ead1424

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

... ... @@ -9,6 +9,7 @@ import com.lframework.starter.bpm.mappers.FlowTaskWrapperMapper;
9 9 import com.lframework.starter.bpm.service.FlowInstanceWrapperService;
10 10 import com.lframework.starter.bpm.vo.flow.task.QueryTodoTaskListVo;
11 11 import com.lframework.starter.common.utils.StringUtil;
  12 +import com.lframework.starter.mq.core.utils.ExportTaskUtil;
12 13 import com.lframework.starter.web.core.annotations.security.HasPermission;
13 14 import com.lframework.starter.web.core.components.redis.RedisHandler;
14 15 import com.lframework.starter.web.core.components.security.SecurityUtil;
... ... @@ -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 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 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 +}
... ...