Commit 33f4e34caf479f0971bde8dba499d9342068f79d

Authored by 杨鸣坤
1 parent 4fe232dc

楚江ERP:经销合同打印

1 1 package com.lframework.xingyun.sc.controller.contract;
2 2
  3 +import cn.hutool.core.io.resource.ClassPathResource;
3 4 import com.baomidou.mybatisplus.core.conditions.Wrapper;
4 5 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
5 6 import com.lframework.starter.common.exceptions.impl.DefaultClientException;
... ... @@ -21,8 +22,10 @@ import com.lframework.starter.web.inner.service.system.SysDataDicItemService;
21 22 import com.lframework.starter.web.inner.service.system.SysDeptService;
22 23 import com.lframework.starter.web.inner.service.system.SysUserService;
23 24 import com.lframework.xingyun.basedata.entity.Customer;
  25 +import com.lframework.xingyun.basedata.entity.ProductVariety;
24 26 import com.lframework.xingyun.basedata.entity.Workshop;
25 27 import com.lframework.xingyun.basedata.service.customer.CustomerService;
  28 +import com.lframework.xingyun.basedata.service.product.ProductVarietyService;
26 29 import com.lframework.xingyun.basedata.service.workshop.WorkshopService;
27 30 import com.lframework.xingyun.basedata.vo.customer.QueryCustomerVo;
28 31 import com.lframework.xingyun.sc.bo.contract.GetContractDistributorLineBo;
... ... @@ -31,26 +34,38 @@ import com.lframework.xingyun.sc.bo.contract.QueryContractDistributorStandardBo;
31 34 import com.lframework.xingyun.sc.components.code.GenerateCodeTypePool;
32 35 import com.lframework.xingyun.sc.entity.ContractDistributorLine;
33 36 import com.lframework.xingyun.sc.entity.ContractDistributorStandard;
  37 +import com.lframework.xingyun.sc.entity.ContractFramework;
34 38 import com.lframework.xingyun.sc.service.contract.ContractDistributorLineService;
35 39 import com.lframework.xingyun.sc.service.contract.ContractDistributorStandardService;
  40 +import com.lframework.xingyun.sc.service.contract.ContractFrameworkService;
36 41 import com.lframework.xingyun.sc.vo.contract.createVo.CreateContractDistributorStandardVo;
37 42 import com.lframework.xingyun.sc.vo.contract.queryVo.QueryContractDistributorStandardVo;
38 43 import com.lframework.xingyun.sc.vo.contract.updateVo.UpdateContractDistributorStandardVo;
39 44 import io.swagger.annotations.Api;
40 45 import io.swagger.annotations.ApiImplicitParam;
41 46 import io.swagger.annotations.ApiOperation;
  47 +import lombok.extern.slf4j.Slf4j;
42 48 import org.apache.commons.collections4.CollectionUtils;
  49 +import org.apache.commons.lang3.BooleanUtils;
43 50 import org.apache.commons.lang3.StringUtils;
  51 +import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  52 +import org.apache.poi.ss.usermodel.*;
  53 +import org.apache.poi.util.IOUtils;
44 54 import org.springframework.beans.factory.annotation.Autowired;
45 55 import org.springframework.validation.annotation.Validated;
46 56 import org.springframework.web.bind.annotation.*;
47 57
  58 +import javax.servlet.http.HttpServletResponse;
48 59 import javax.validation.Valid;
49 60 import javax.validation.constraints.NotBlank;
50   -import java.util.ArrayList;
51   -import java.util.Arrays;
52   -import java.util.List;
53   -import java.util.Map;
  61 +import java.io.FileNotFoundException;
  62 +import java.io.IOException;
  63 +import java.io.InputStream;
  64 +import java.math.BigDecimal;
  65 +import java.net.URLEncoder;
  66 +import java.time.LocalDate;
  67 +import java.time.format.DateTimeFormatter;
  68 +import java.util.*;
54 69 import java.util.function.Function;
55 70 import java.util.stream.Collectors;
56 71
... ... @@ -61,6 +76,7 @@ import java.util.stream.Collectors;
61 76 @Validated
62 77 @RestController
63 78 @RequestMapping("/contract/contractDistributorStandard")
  79 +@Slf4j
64 80 public class ContractDistributorStandardController extends DefaultBaseController {
65 81
66 82 @Autowired
... ... @@ -81,6 +97,10 @@ public class ContractDistributorStandardController extends DefaultBaseController
81 97 private DicCityService dicCityService;
82 98 @Autowired
83 99 private WorkshopService workshopService;
  100 + @Autowired
  101 + private ContractFrameworkService contractFrameworkService;
  102 + @Autowired
  103 + private ProductVarietyService productVarietyService;
84 104
85 105
86 106 public static final String SUPPLIER_DIC_CODE = "SUPPLIER"; // 所属单位/供方
... ... @@ -407,4 +427,203 @@ public class ContractDistributorStandardController extends DefaultBaseController
407 427
408 428 return InvokeResultBuilder.success(new GetContractDistributorStandardBo(contractDistributorStandard));
409 429 }
  430 +
  431 + /**
  432 + * 标准合同模版打印
  433 + */
  434 + @ApiOperation("标准合同模版打印")
  435 + @GetMapping("/printStandardContract")
  436 + public void printStandardContract(@NotBlank(message = "合同不可为空") String id, HttpServletResponse response) throws IOException {
  437 + InvokeResult<GetContractDistributorStandardBo> result = get(id);
  438 + GetContractDistributorStandardBo data = result.getData();
  439 +
  440 + // 设置响应头
  441 + setupResponse(response, data.getCode() + "_" + data.getBuyerName() + "-合同打印.xls");
  442 +
  443 + Wrapper<ContractFramework> contractFrameworkWrapper = Wrappers.lambdaQuery(ContractFramework.class)
  444 + .eq(ContractFramework::getCustomerId, data.getBuyer())
  445 + .ge(ContractFramework::getValidityTime, LocalDate.now())
  446 + .eq(ContractFramework::getHasFrameworkAgreement, true);
  447 + List<ContractFramework> contractFrameworkList = contractFrameworkService.list(contractFrameworkWrapper);
  448 + List<String> productNameList = new ArrayList<>();
  449 + if (CollectionUtils.isNotEmpty(contractFrameworkList)) {
  450 + List<String> materialTypeIdList = contractFrameworkList.stream()
  451 + .filter(bo -> StringUtils.isNotBlank(bo.getMaterialTypeId()))
  452 + .flatMap(bo -> Arrays.stream(bo.getMaterialTypeId().split(",")))
  453 + .map(String::trim)
  454 + .filter(StringUtils::isNotBlank)
  455 + .distinct()
  456 + .collect(Collectors.toList());
  457 + List<ProductVariety> productVarietyList = productVarietyService.listByIds(materialTypeIdList);
  458 + CollectionUtils.emptyIfNull(productVarietyList).forEach(productVariety -> {
  459 + if (productVariety == null || StringUtils.isBlank(productVariety.getName())) {
  460 + return;
  461 + }
  462 +
  463 + productNameList.add(productVariety.getName().substring(0, 2));
  464 + });
  465 + }
  466 +
  467 + try {
  468 + // 加载模板文件
  469 + ClassPathResource templateResource = new ClassPathResource("templates/standardContractTemplate.xls");
  470 + try (InputStream inputStream = templateResource.getStream();
  471 + Workbook workbook = new HSSFWorkbook(inputStream)) {
  472 + try {
  473 + Sheet sheet = workbook.getSheetAt(0);
  474 + DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  475 + int startRow = 6; // 产品开始行
  476 + String contractTitle = "销售订单(经销)";
  477 + if (CollectionUtils.isNotEmpty(data.getContractDistributorLineList())) {
  478 + for (GetContractDistributorLineBo contractDistributorLineBo : data.getContractDistributorLineList()) {
  479 + if (StringUtils.isNotBlank(contractDistributorLineBo.getProductName())
  480 + && !productNameList.contains(contractDistributorLineBo.getProductName().substring(0, 2))) {
  481 + contractTitle = "销售合同(经销)";
  482 + }
  483 +
  484 + setCellValue(sheet, startRow, 1, contractDistributorLineBo.getProductName()); // B列
  485 + setCellValue(sheet, startRow, 4, contractDistributorLineBo.getBrand()); // D列
  486 +// setCellValue(sheet, startRow, 5, contractDistributorLineBo.getSpecification()); // E列
  487 + setCellValue(sheet, startRow, 6, contractDistributorLineBo.getStatus()); // F列
  488 + setCellValue(sheet, startRow, 7, contractDistributorLineBo.getQuantity()); // G列
  489 + setCellValue(sheet, startRow, 9, contractDistributorLineBo.getUnitPrice()); // I列
  490 + setCellValue(sheet, startRow, 10, contractDistributorLineBo.getAmountExcludingTax()); // K列
  491 + setCellValue(sheet, startRow, 11, contractDistributorLineBo.getTotalAmount()); // L列
  492 + setCellValue(sheet, startRow, 12, contractDistributorLineBo.getDeliveryDate() != null ?
  493 + contractDistributorLineBo.getDeliveryDate().format(dateFormatter) : ""); // L列
  494 + startRow++;
  495 + }
  496 + }
  497 +
  498 + Map<String, Object> dataMap = new HashMap<>();
  499 + dataMap.put("title", contractTitle);
  500 + dataMap.put("code", data.getCode());
  501 + dataMap.put("orderDate", data.getOrderDate().format(dateFormatter));
  502 + dataMap.put("supplierName", data.getSupplierName());
  503 + dataMap.put("buyerName", data.getBuyerName());
  504 + dataMap.put("unitName", data.getUnitName());
  505 +
  506 + dataMap.put("totalQuantity", data.getTotalQuantity());
  507 + dataMap.put("totalAmountExcludingTax", data.getTotalAmountExcludingTax());
  508 + dataMap.put("totalAmountIncludingTax", data.getTotalAmountIncludingTax());
  509 + dataMap.put("totalAmountCapital", data.getTotalAmountCapital());
  510 +
  511 + dataMap.put("depositInfo", data.getDepositInfo());
  512 + dataMap.put("paymentTerms", data.getPaymentTerms());
  513 + dataMap.put("packagingRequirements", data.getPackagingRequirements());
  514 + dataMap.put("transportMode", data.getTransportMode());
  515 + if (BooleanUtils.isTrue(data.getIncludesPackagingFee()) && BooleanUtils.isTrue(data.getIncludesTransportFee())) {
  516 + dataMap.put("includesTransportOrPackaging", "单价中已包含包装费用与运费");
  517 + } else if (BooleanUtils.isTrue(data.getIncludesPackagingFee()) && BooleanUtils.isNotTrue(data.getIncludesTransportFee())) {
  518 + dataMap.put("includesTransportOrPackaging", "单价中已包含包装费用,不包含运费");
  519 + } else if (BooleanUtils.isNotTrue(data.getIncludesPackagingFee()) && BooleanUtils.isTrue(data.getIncludesTransportFee())) {
  520 + dataMap.put("includesTransportOrPackaging", "单价中不包含包装费用,包含运费");
  521 + } else if (BooleanUtils.isNotTrue(data.getIncludesPackagingFee()) && BooleanUtils.isNotTrue(data.getIncludesTransportFee())) {
  522 + dataMap.put("includesTransportOrPackaging", "单价中不包含包装费用与运费");
  523 + }
  524 +
  525 + dataMap.put("remarks", data.getRemarks());
  526 + processTemplate(workbook, dataMap);
  527 +
  528 + // 写入响应流
  529 + workbook.write(response.getOutputStream());
  530 + response.getOutputStream().flush();
  531 + } finally {
  532 + IOUtils.closeQuietly(workbook);
  533 + }
  534 +
  535 + } catch (FileNotFoundException e) {
  536 + throw new RuntimeException("模板文件不存在: templates/standardContractTemplate.xls", e);
  537 + } catch (IOException e) {
  538 + throw new RuntimeException("无法读取模板文件: templates/standardContractTemplate.xls", e);
  539 + }
  540 + } catch (Exception e) {
  541 + log.error("标准合同模版打印: {}", e.getMessage(), e);
  542 + throw e;
  543 + }
  544 + }
  545 +
  546 + private void processTemplate(Workbook workbook, Map<String, Object> dataMap) {
  547 + Sheet sheet = workbook.getSheetAt(0);
  548 +
  549 + for (Row row : sheet) {
  550 + for (Cell cell : row) {
  551 + if (cell.getCellTypeEnum() == CellType.STRING) {
  552 + String cellValue = cell.getStringCellValue();
  553 + String newValue = replacePlaceholders(cellValue, dataMap);
  554 + if (!cellValue.equals(newValue)) {
  555 + cell.setCellValue(newValue);
  556 + }
  557 + }
  558 + }
  559 + }
  560 + }
  561 +
  562 + private String replacePlaceholders(String text, Map<String, Object> dataMap) {
  563 + if (text == null || text.isEmpty()) {
  564 + return text;
  565 + }
  566 +
  567 + String result = text;
  568 + for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
  569 + String placeholder = "${" + entry.getKey() + "}";
  570 + String value = entry.getValue() != null ? entry.getValue().toString() : "";
  571 + // 将数据库中的 \n 转换为 Excel 识别的换行符
  572 + value = value.replace("\\n", "\n");
  573 +
  574 + result = result.replace(placeholder, value);
  575 + }
  576 +
  577 + for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
  578 + String placeholder = "#{" + entry.getKey() + "}";
  579 + String value = entry.getValue() != null ? entry.getValue().toString() : "";
  580 + // 将数据库中的 \n 转换为 Excel 识别的换行符
  581 + value = value.replace("\\n", "\n");
  582 +
  583 + result = result.replace(placeholder, value);
  584 + }
  585 +
  586 + return result;
  587 + }
  588 +
  589 + /**
  590 + * 设置HTTP响应头
  591 + */
  592 + private void setupResponse(HttpServletResponse response, String fileName) throws IOException {
  593 + String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
  594 +
  595 + response.setContentType("application/vnd.ms-excel");
  596 + response.setCharacterEncoding("UTF-8");
  597 + response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName);
  598 + response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
  599 + }
  600 +
  601 + /**
  602 + * 设置单元格值
  603 + */
  604 + private static void setCellValue(Sheet sheet, int rowNum, int colNum, Object value) {
  605 + Row row = sheet.getRow(rowNum);
  606 + if (row == null) {
  607 + row = sheet.createRow(rowNum);
  608 + }
  609 +
  610 + Cell cell = row.getCell(colNum);
  611 + if (cell == null) {
  612 + cell = row.createCell(colNum);
  613 + }
  614 +
  615 + if (value == null) {
  616 + cell.setCellValue("");
  617 + } else if (value instanceof String) {
  618 + cell.setCellValue((String) value);
  619 + } else if (value instanceof Integer) {
  620 + cell.setCellValue((Integer) value);
  621 + } else if (value instanceof Double) {
  622 + cell.setCellValue((Double) value);
  623 + } else if (value instanceof BigDecimal) {
  624 + cell.setCellValue(((BigDecimal) value).doubleValue());
  625 + } else if (value instanceof LocalDate) {
  626 + cell.setCellValue(((LocalDate) value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
  627 + }
  628 + }
410 629 }
... ...
... ... @@ -5,27 +5,19 @@ import com.lframework.starter.common.utils.DateUtil;
5 5 import com.lframework.starter.web.core.bo.BaseBo;
6 6 import com.lframework.starter.web.core.components.excel.ExcelModel;
7 7 import com.lframework.starter.web.core.utils.ApplicationUtil;
8   -import com.lframework.starter.web.inner.dto.dic.city.DicCityDto;
9 8 import com.lframework.starter.web.inner.entity.SysDataDicItem;
10   -import com.lframework.starter.web.inner.service.DicCityService;
11 9 import com.lframework.starter.web.inner.service.system.SysDataDicItemService;
12   -import com.lframework.xingyun.basedata.entity.*;
13   -import com.lframework.xingyun.basedata.enums.AddressEntityType;
  10 +import com.lframework.xingyun.basedata.entity.Customer;
  11 +import com.lframework.xingyun.basedata.entity.ProductVariety;
14 12 import com.lframework.xingyun.basedata.service.customer.CustomerService;
15   -import com.lframework.xingyun.basedata.service.member.MemberService;
16 13 import com.lframework.xingyun.basedata.service.product.ProductVarietyService;
17   -import com.lframework.xingyun.basedata.service.shop.ShopService;
18   -import com.lframework.xingyun.basedata.service.storecenter.StoreCenterService;
19   -import com.lframework.xingyun.basedata.service.supplier.SupplierService;
20 14 import com.lframework.xingyun.sc.controller.contract.ContractFrameworkController;
21 15 import com.lframework.xingyun.sc.entity.ContractFramework;
22   -import io.swagger.annotations.ApiModelProperty;
23 16 import lombok.Data;
24 17 import org.apache.commons.collections4.CollectionUtils;
25 18 import org.apache.commons.lang3.BooleanUtils;
26 19 import org.apache.commons.lang3.StringUtils;
27 20
28   -import java.time.format.DateTimeFormatter;
29 21 import java.util.*;
30 22 import java.util.stream.Collectors;
31 23
... ... @@ -59,7 +51,7 @@ public class ContractFrameworkExportModel extends BaseBo<ContractFramework> impl
59 51 /**
60 52 * 品种名称
61 53 */
62   - @ApiModelProperty("品种")
  54 + @ExcelProperty("品种")
63 55 private String materialTypeName;
64 56
65 57 /**
... ...