Showing
2 changed files
with
229 additions
and
122 deletions
xingyun-sc/src/main/java/com/lframework/xingyun/sc/controller/customer/CustomerCreditController.java
| ... | ... | @@ -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 | +} | ... | ... |