Commit 16170b76f82313ba2827096e019f26015dfe8817

Authored by 房远帅
2 parents fd958458 55489fa9

Merge branch 'master_after0506_report02_1' into master_test

Showing 31 changed files with 366 additions and 31 deletions
... ... @@ -409,7 +409,7 @@ CREATE TABLE IF NOT EXISTS `tbl_purchase_order_revoke_line`
409 409 `length_tol_neg` decimal(10, 4) DEFAULT NULL COMMENT '长度公差负',
410 410 `status` varchar(50) DEFAULT NULL COMMENT '状态',
411 411 `quantity` decimal(15, 4) NOT NULL COMMENT '原数量kg',
412   - `sales_price` decimal(15, 4) NOT NULL COMMENT '销售价格',
  412 + `sales_price` decimal(15, 4) DEFAULT NULL COMMENT '销售价格',
413 413 `delivery_date` date DEFAULT NULL COMMENT '发货日期',
414 414 `revoke_quantity` decimal(15, 4) DEFAULT NULL COMMENT '撤销数量',
415 415 `show_order` int DEFAULT '0' COMMENT '排序',
... ...
... ... @@ -145,6 +145,12 @@ public class GetPurchaseOrderRevokeBo extends BaseBo<PurchaseOrderRevoke> {
145 145 @ApiModelProperty("订货单撤销表物料行")
146 146 private List<PurchaseOrderRevokeLine> purchaseOrderRevokeLineList;
147 147
  148 + /**
  149 + * 合同类型
  150 + */
  151 + @ApiModelProperty("合同类型")
  152 + private String contractType;
  153 +
148 154 public GetPurchaseOrderRevokeBo() {
149 155
150 156 }
... ...
... ... @@ -260,6 +260,12 @@ public class OrderChangeRecordBo extends BaseBo<OrderInfoChangeRecord> {
260 260 @ApiModelProperty("是否是变更发起人")
261 261 private Boolean changeCreateBy;
262 262
  263 + /**
  264 + * 合同类型
  265 + */
  266 + @ApiModelProperty("合同类型")
  267 + private String contractType;
  268 +
263 269
264 270 public OrderChangeRecordBo() {
265 271
... ...
... ... @@ -152,6 +152,12 @@ public class GetReplenishmentOrderBo extends BaseBo<ReplenishmentOrder> {
152 152 @ApiModelProperty("补货单物料行")
153 153 private List<GetReplenishmentOrderLineBo> replenishmentOrderLineList;
154 154
  155 + /**
  156 + * 合同类型
  157 + */
  158 + @ApiModelProperty("合同类型")
  159 + private String contractType;
  160 +
155 161 public GetReplenishmentOrderBo() {
156 162
157 163 }
... ...
... ... @@ -523,7 +523,7 @@ public class ContractDistributorStandardController extends DefaultBaseController
523 523 SysUser sysUser = sysUserService.findById(currentUserId);
524 524 String officeCode = resolveOfficeCodeByUser(sysUser);
525 525 if (StringUtils.isBlank(officeCode)) {
526   - throw new DefaultClientException("当前用不属于九大办事处,无法生成合同编号!");
  526 + throw new DefaultClientException("当前用户不属于办事处,无法生成合同编号!");
527 527 }
528 528
529 529 String monthCode = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMM"));
... ...
... ... @@ -5,9 +5,13 @@ import com.lframework.starter.web.core.annotations.security.HasPermission;
5 5 import com.lframework.starter.web.core.controller.DefaultBaseController;
6 6 import com.lframework.starter.web.core.utils.JsonUtil;
7 7 import com.lframework.xingyun.sc.bo.order.change.OrderChangeRecordBo;
  8 +import com.lframework.xingyun.sc.entity.ContractDistributorStandard;
8 9 import com.lframework.xingyun.sc.entity.OrderInfoChangeRecord;
  10 +import com.lframework.xingyun.sc.entity.PurchaseOrderInfo;
9 11 import com.lframework.xingyun.sc.entity.PurchaseOrderLine;
10 12 import com.lframework.xingyun.sc.enums.OrderSpecChangeStatus;
  13 +import com.lframework.xingyun.sc.service.contract.ContractDistributorStandardService;
  14 +import com.lframework.xingyun.sc.service.order.PurchaseOrderInfoService;
11 15 import com.lframework.xingyun.sc.utils.ExcelUtil;
12 16 import com.lframework.xingyun.sc.utils.LatexFormulaExcelExporterUtil;
13 17 import com.lframework.xingyun.sc.utils.ResponseUtil;
... ... @@ -60,6 +64,10 @@ public class OrderChangeRecordController extends DefaultBaseController {
60 64
61 65 @Resource
62 66 private OrderChangeRecordService orderChangeRecordService;
  67 + @Resource
  68 + private PurchaseOrderInfoService purchaseOrderInfoService;
  69 + @Resource
  70 + private ContractDistributorStandardService contractDistributorStandardService;
63 71
64 72 /**
65 73 * 查询列表
... ... @@ -90,6 +98,16 @@ public class OrderChangeRecordController extends DefaultBaseController {
90 98 throw new DefaultClientException("订货单变更记录不存在!");
91 99 }
92 100 OrderChangeRecordBo result = new OrderChangeRecordBo(data);
  101 + PurchaseOrderInfo purchaseOrderInfo = purchaseOrderInfoService.findById(result.getOrderId());
  102 + if (purchaseOrderInfo != null) {
  103 + String contractId = purchaseOrderInfo.getContractId();
  104 + if (StringUtils.isNotEmpty(contractId)) {
  105 + ContractDistributorStandard contractDistributorStandard = contractDistributorStandardService.findById(contractId);
  106 + if (contractDistributorStandard != null) {
  107 + result.setContractType(contractDistributorStandard.getType());
  108 + }
  109 + }
  110 + }
93 111
94 112 return InvokeResultBuilder.success(result);
95 113 }
... ...
... ... @@ -419,7 +419,7 @@ public class PurchaseOrderInfoController extends DefaultBaseController {
419 419
420 420 String latex = LatexFormulaExcelExporterUtil.convertToContractSpecLatexSingleLineFixed3(formulaComponentList);
421 421 if (StringUtils.isNotBlank(latex)) {
422   - LatexFormulaExcelExporterUtil.insertLatexImageToCell(workbook, sheet, latex, startRow, 4, 1, 7);
  422 + LatexFormulaExcelExporterUtil.insertLatexImageToCellLeftAligned(workbook, sheet, latex, startRow, 4, 1, 7);
423 423 }
424 424
425 425 setCellValue(sheet, startRow, 11, currentOrderLine.getStatus());
... ... @@ -459,6 +459,7 @@ public class PurchaseOrderInfoController extends DefaultBaseController {
459 459 dataMap.put("performanceance", data.getPerformance());
460 460 dataMap.put("packaging", data.getPackaging());
461 461 dataMap.put("shippingCost", data.getShippingCost());
  462 + dataMap.put("destination", ExcelUtil.buildPrintDestination(data.getContractType(), data.getDestination(), data.getForeignDestination()));
462 463 dataMap.put("remarks", data.getRemarks());
463 464 dataMap.put("createUser", data.getCreateBy());
464 465 dataMap.put("element", data.getElement());
... ... @@ -491,6 +492,7 @@ public class PurchaseOrderInfoController extends DefaultBaseController {
491 492
492 493 if ("PDF".equals(exportType)) {
493 494 ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "具体质量要求", true);
  495 + ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "备注", true);
494 496 ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "生产工艺", false);
495 497 ResponseUtil.setPDFResponseHead(response, data.getOrderNo() + "-"
496 498 + data.getOrderingUnitName() + "-" + data.getWorkshopName() + "-订货单打印.pdf");
... ...
... ... @@ -16,6 +16,7 @@ import javax.validation.constraints.NotBlank;
16 16 import com.lframework.xingyun.sc.bo.order.GetPurchaseOrderInfoBo;
17 17 import com.lframework.xingyun.sc.bo.order.GetPurchaseOrderRevokeBo;
18 18 import com.lframework.xingyun.sc.entity.*;
  19 +import com.lframework.xingyun.sc.service.contract.ContractDistributorStandardService;
19 20 import com.lframework.xingyun.sc.service.order.PurchaseOrderInfoService;
20 21 import com.lframework.xingyun.sc.service.order.PurchaseOrderLineService;
21 22 import com.lframework.xingyun.sc.service.order.PurchaseOrderRevokeLineService;
... ... @@ -28,6 +29,7 @@ import io.swagger.annotations.ApiOperation;
28 29 import com.lframework.starter.common.utils.CollectionUtil;
29 30 import io.swagger.annotations.Api;
30 31 import org.apache.commons.collections.CollectionUtils;
  32 +import org.apache.commons.lang3.StringUtils;
31 33 import org.springframework.web.bind.annotation.DeleteMapping;
32 34 import org.springframework.beans.factory.annotation.Autowired;
33 35 import org.springframework.validation.annotation.Validated;
... ... @@ -58,6 +60,8 @@ public class PurchaseOrderRevokeController extends DefaultBaseController {
58 60 private PurchaseOrderRevokeLineService purchaseOrderRevokeLineService;
59 61 @Resource
60 62 private FlowTaskWrapperMapper flowTaskWrapperMapper;
  63 + @Resource
  64 + private ContractDistributorStandardService contractDistributorStandardService;
61 65
62 66 /**
63 67 * 查询列表
... ... @@ -124,6 +128,16 @@ public class PurchaseOrderRevokeController extends DefaultBaseController {
124 128 if (CollectionUtil.isNotEmpty(query)) {
125 129 result.setPurchaseOrderRevokeLineList(query);
126 130 }
  131 + PurchaseOrderInfo purchaseOrderInfo = purchaseOrderInfoService.findById(data.getPurchaseOrderId());
  132 + if (purchaseOrderInfo != null) {
  133 + String contractId = purchaseOrderInfo.getContractId();
  134 + if (StringUtils.isNotEmpty(contractId)) {
  135 + ContractDistributorStandard contractDistributorStandard = contractDistributorStandardService.findById(contractId);
  136 + if (contractDistributorStandard != null) {
  137 + result.setContractType(contractDistributorStandard.getType());
  138 + }
  139 + }
  140 + }
127 141
128 142 return InvokeResultBuilder.success(result);
129 143 }
... ...
... ... @@ -293,7 +293,7 @@ public class ProductSampleConfirmationSlipController extends DefaultBaseControll
293 293 dataMap.put("workshopName", result.getWorkshopName() == null ? "" : result.getWorkshopName());
294 294 dataMap.put("belongingBreed", result.getBelongingBreed() == null ? "" : result.getBelongingBreed());
295 295 dataMap.put("originalSupplierPeer", result.getOriginalSupplierPeer() == null ? "" : result.getOriginalSupplierPeer());
296   - dataMap.put("totalQuantity", result.getTotalQuantity() == null ? "" : result.getTotalQuantity().stripTrailingZeros());
  296 + dataMap.put("totalQuantity", result.getTotalQuantity() == null ? "" : result.getTotalQuantity());
297 297 dataMap.put("sampleQuantityRegulation", result.isSampleQuantityRegulation() ? "是" : "否");
298 298 dataMap.put("specificationQuantityRegulation", result.isSpecificationQuantityRegulation() ? "是" : "否");
299 299 dataMap.put("sampleFrequency", result.getSampleFrequency() == null ? "" : result.getSampleFrequency());
... ...
... ... @@ -26,9 +26,11 @@ import com.lframework.xingyun.basedata.vo.customer.QueryCustomerVo;
26 26 import com.lframework.xingyun.sc.bo.purchase.GetReplenishmentOrderBo;
27 27 import com.lframework.xingyun.sc.bo.purchase.GetReplenishmentOrderLineBo;
28 28 import com.lframework.xingyun.sc.bo.purchase.QueryReplenishmentOrderBo;
  29 +import com.lframework.xingyun.sc.entity.ContractDistributorStandard;
29 30 import com.lframework.xingyun.sc.entity.PurchaseOrderInfo;
30 31 import com.lframework.xingyun.sc.entity.ReplenishmentOrder;
31 32 import com.lframework.xingyun.sc.entity.ReplenishmentOrderLine;
  33 +import com.lframework.xingyun.sc.service.contract.ContractDistributorStandardService;
32 34 import com.lframework.xingyun.sc.service.order.PurchaseOrderInfoService;
33 35 import com.lframework.xingyun.sc.service.purchase.ReplenishmentOrderLineService;
34 36 import com.lframework.xingyun.sc.service.purchase.ReplenishmentOrderService;
... ... @@ -77,6 +79,8 @@ public class ReplenishmentOrderController extends DefaultBaseController {
77 79 private ReplenishmentOrderLineService replenishmentOrderLineService;
78 80 @Resource
79 81 private FlowTaskWrapperMapper flowTaskWrapperMapper;
  82 + @Resource
  83 + private ContractDistributorStandardService contractDistributorStandardService;
80 84
81 85
82 86 public static final String AUDIT_STATUS_DIC_CODE = "AUDIT_STATUS"; // 审核状态
... ... @@ -195,6 +199,13 @@ public class ReplenishmentOrderController extends DefaultBaseController {
195 199 result.setStatusName(sysDataDicItem == null ? "" : sysDataDicItem.getName());
196 200 PurchaseOrderInfo purchaseOrderInfo = purchaseOrderInfoService.findById(data.getPurchaseOrderId());
197 201 result.setPurchaseOrderName(purchaseOrderInfo == null ? "" : purchaseOrderInfo.getOrderNo());
  202 + String contractId = purchaseOrderInfo.getContractId();
  203 + if (StringUtils.isNotEmpty(contractId)) {
  204 + ContractDistributorStandard contractDistributorStandard = contractDistributorStandardService.findById(contractId);
  205 + if (contractDistributorStandard != null) {
  206 + result.setContractType(contractDistributorStandard.getType());
  207 + }
  208 + }
198 209
199 210 Wrapper<ReplenishmentOrderLine> lineWrapper = Wrappers.lambdaQuery(ReplenishmentOrderLine.class)
200 211 .eq(ReplenishmentOrderLine::getReplenishmentOrderId, id)
... ...
... ... @@ -293,7 +293,7 @@ public class ShipmentsOrderInfoController extends DefaultBaseController {
293 293 // 加载模板文件
294 294 String templatePath = "templates/shipmentsOrderTemplate_02.xlsx";
295 295 if ("TYPE_1".equals(vo.getType())) {
296   - templatePath = "templates/shipmentsOrderTemplate_01.xlsx";
  296 + templatePath = "templates/shipmentsOrderTemplate_03.xlsx";
297 297 }
298 298 // 创建临时目录
299 299 Path tempDir = null;
... ...
... ... @@ -258,6 +258,7 @@ public class BusinessDataExportHandler implements ExportHandler {
258 258 dataMap.put("performanceance", orderInfo.getPerformance());
259 259 dataMap.put("packaging", orderInfo.getPackaging());
260 260 dataMap.put("shippingCost", orderInfo.getShippingCost());
  261 + dataMap.put("destination", ExcelUtil.buildPrintDestination(orderInfo.getContractType(), orderInfo.getDestination(), orderInfo.getForeignDestination()));
261 262 dataMap.put("remarks", orderInfo.getRemarks());
262 263 dataMap.put("createUser", orderInfo.getCreateBy());
263 264 dataMap.put("element", orderInfo.getElement());
... ... @@ -281,6 +282,7 @@ public class BusinessDataExportHandler implements ExportHandler {
281 282 String createTime = orderInfo.getCreateTime().format(dateTimeFormatter);
282 283 if ("PDF".equals(queryVo.getExportFileType())) {
283 284 ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "具体质量要求", true);
  285 + ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "备注", true);
284 286 ExcelUtil.adjustVerticalTitleForPdf(workbook, sheet, "生产工艺", false);
285 287 // 输出PDF
286 288 File tempExcel = File.createTempFile("purchase_order_" + orderInfo.getOrderNo(), ".xlsx");
... ...
... ... @@ -1455,6 +1455,7 @@ public class ContractDistributorStandardServiceImpl extends
1455 1455 data.setPerformance(vo.getPerformance());
1456 1456 data.setComponent(vo.getComponent());
1457 1457 data.setPackaging(vo.getPackaging());
  1458 + data.setRemarks(vo.getRemarks());
1458 1459 // data.setStandardizedAt(LocalDateTime.now());
1459 1460 getBaseMapper().insert(data);
1460 1461
... ...
... ... @@ -36,6 +36,7 @@ import com.lframework.xingyun.sc.service.customer.CustomerCreditService;
36 36 import com.lframework.xingyun.sc.service.order.PurchaseOrderInfoService;
37 37 import com.lframework.xingyun.sc.service.order.PurchaseOrderLineService;
38 38 import com.lframework.xingyun.sc.service.statistics.OrderDetailReportService;
  39 +import com.lframework.xingyun.sc.utils.OrderDetailReportUtil;
39 40 import com.lframework.xingyun.sc.vo.order.CreatePurchaseOrderLineVo;
40 41 import com.lframework.xingyun.sc.vo.order.QueryPurchaseOrderInfoVo;
41 42 import com.lframework.xingyun.sc.vo.order.QueryPurchaseOrderLineVo;
... ... @@ -586,7 +587,8 @@ public class OrderChangeRecordServiceImpl extends BaseMpServiceImpl<OrderChangeR
586 587 vo.setQuality(line.getQuality());
587 588 vo.setContractType(orderDetailReport.getContractType());
588 589 vo.setStockUpCompanyName(orderInfo.getStockUpCompanyName());
589   - //vo.setOrderType();
  590 + vo.setType(orderInfo.getType());
  591 + vo.setOrderType(OrderDetailReportUtil.buildOrderType(type, orderInfo.getType()));
590 592 vo.setShowOrder(2);
591 593 vo.setCreateById(contractCreateById);
592 594 orderDetailReportService.create(vo);
... ...
... ... @@ -38,6 +38,7 @@ import com.lframework.xingyun.sc.service.customer.CustomerCreditService;
38 38 import com.lframework.xingyun.sc.service.order.PurchaseOrderInfoService;
39 39 import com.lframework.xingyun.sc.service.order.PurchaseOrderLineService;
40 40 import com.lframework.xingyun.sc.service.statistics.OrderDetailReportService;
  41 +import com.lframework.xingyun.sc.utils.OrderDetailReportUtil;
41 42 import com.lframework.xingyun.sc.vo.customer.credit.QueryCustomerCreditVo;
42 43 import com.lframework.xingyun.sc.vo.order.*;
43 44 import com.lframework.xingyun.sc.vo.statistics.orderDetail.CreateOrderDetailReportVo;
... ... @@ -131,8 +132,12 @@ public class PurchaseOrderInfoServiceImpl extends BaseMpServiceImpl<PurchaseOrde
131 132
132 133 @Override
133 134 public PurchaseOrderInfo findById(String id) {
134   -
135   - return getBaseMapper().findById(id);
  135 + PurchaseOrderInfo data = getBaseMapper().findById(id);
  136 + if (data == null) {
  137 + return null;
  138 + }
  139 + fillContractDestination(data);
  140 + return data;
136 141 }
137 142
138 143 @Override
... ... @@ -412,7 +417,7 @@ public class PurchaseOrderInfoServiceImpl extends BaseMpServiceImpl<PurchaseOrde
412 417 }
413 418 }
414 419 vo.setStockUpCompanyName(purchaseOrderInfo.getStockUpCompanyName());
415   -// vo.setOrderType();
  420 + vo.setOrderType(OrderDetailReportUtil.buildOrderType(type, purchaseOrderInfo.getType()));
416 421 vo.setShowOrder(0);
417 422 vo.setType(purchaseOrderInfo.getType());
418 423 vo.setCreateById(purchaseOrderInfo.getContractCreateById());
... ... @@ -763,17 +768,46 @@ public class PurchaseOrderInfoServiceImpl extends BaseMpServiceImpl<PurchaseOrde
763 768 }
764 769 Map<String, ContractDistributorStandard> contractMap = contractList.stream().collect(Collectors.toMap(ContractDistributorStandard::getId, Function.identity()));
765 770 for (PurchaseOrderInfo orderInfo : orderInfoList) {
766   - String contractId = orderInfo.getContractId();
767   - ContractDistributorStandard contract = contractMap.get(contractId);
768   - if (contract == null) {
769   - continue;
770   - }
771   - orderInfo.setDestination(contract.getDestination());
772   - orderInfo.setForeignDestination(contract.getForeignDestination());
  771 + fillContractDestination(orderInfo, contractMap);
773 772 }
774 773 return orderInfoList;
775 774 }
776 775
  776 + /**
  777 + * 回填订货单上的合同目的地字段,供打印等场景使用。
  778 + *
  779 + * @param orderInfo 订货单
  780 + */
  781 + private void fillContractDestination(PurchaseOrderInfo orderInfo) {
  782 + if (orderInfo == null || StringUtils.isBlank(orderInfo.getContractId())) {
  783 + return;
  784 + }
  785 + ContractDistributorStandard contract = contractDistributorStandardService.findById(orderInfo.getContractId());
  786 + if (contract == null) {
  787 + return;
  788 + }
  789 + orderInfo.setDestination(contract.getDestination());
  790 + orderInfo.setForeignDestination(contract.getForeignDestination());
  791 + }
  792 +
  793 + /**
  794 + * 根据合同映射批量回填订货单上的合同目的地字段。
  795 + *
  796 + * @param orderInfo 订货单
  797 + * @param contractMap 合同映射
  798 + */
  799 + private void fillContractDestination(PurchaseOrderInfo orderInfo, Map<String, ContractDistributorStandard> contractMap) {
  800 + if (orderInfo == null || contractMap == null || StringUtils.isBlank(orderInfo.getContractId())) {
  801 + return;
  802 + }
  803 + ContractDistributorStandard contract = contractMap.get(orderInfo.getContractId());
  804 + if (contract == null) {
  805 + return;
  806 + }
  807 + orderInfo.setDestination(contract.getDestination());
  808 + orderInfo.setForeignDestination(contract.getForeignDestination());
  809 + }
  810 +
777 811 @Override
778 812 public List<PurchaseOrderInfo> listByCustomerIds(List<String> customerIds) {
779 813 if (CollectionUtils.isEmpty(customerIds)) {
... ...
... ... @@ -26,6 +26,7 @@ import com.lframework.xingyun.sc.service.customer.CustomerCreditService;
26 26 import com.lframework.xingyun.sc.service.order.PurchaseOrderInfoService;
27 27 import com.lframework.xingyun.sc.service.order.PurchaseOrderLineService;
28 28 import com.lframework.xingyun.sc.service.statistics.OrderDetailReportService;
  29 +import com.lframework.xingyun.sc.utils.OrderDetailReportUtil;
29 30 import com.lframework.xingyun.sc.vo.order.QueryPurchaseOrderInfoVo;
30 31 import com.lframework.xingyun.sc.vo.order.QueryPurchaseOrderLineVo;
31 32 import com.lframework.xingyun.sc.vo.statistics.orderDetail.CreateOrderDetailReportVo;
... ... @@ -408,7 +409,7 @@ public class OrderDetailReportServiceImpl extends BaseMpServiceImpl<OrderDetailR
408 409 }
409 410 }
410 411 vo.setStockUpCompanyName(purchaseOrderInfo.getStockUpCompanyName());
411   - //vo.setOrderType();
  412 + vo.setOrderType(OrderDetailReportUtil.buildOrderType(type, purchaseOrderInfo.getType()));
412 413 vo.setShowOrder(0);
413 414 vo.setType(purchaseOrderInfo.getType());
414 415 vo.setCreateById(purchaseOrderInfo.getContractCreateById());
... ...
1 1 package com.lframework.xingyun.sc.utils;
2 2
  3 +import com.lframework.starter.web.core.utils.ApplicationUtil;
  4 +import com.lframework.starter.web.inner.dto.dic.city.DicCityDto;
  5 +import com.lframework.starter.web.inner.service.DicCityService;
3 6 import lombok.extern.slf4j.Slf4j;
  7 +import org.apache.commons.lang3.StringUtils;
4 8 import org.apache.poi.ss.usermodel.*;
5 9 import org.apache.poi.ss.util.CellRangeAddress;
6 10
... ... @@ -41,6 +45,76 @@ public class ExcelUtil {
41 45 }
42 46 }
43 47
  48 + /**
  49 + * 构建打印使用的目的地文本。
  50 + * 外贸合同直接展示外贸目的地,其他合同将层级地址中的斜杠替换为中文逗号。
  51 + *
  52 + * @param contractType 合同类型
  53 + * @param destination 普通目的地
  54 + * @param foreignDestination 外贸目的地
  55 + * @return 打印使用的目的地文本
  56 + */
  57 + public static String buildPrintDestination(String contractType, String destination, String foreignDestination) {
  58 + if (isForeignContractType(contractType)) {
  59 + return StringUtils.defaultString(foreignDestination).trim();
  60 + }
  61 +
  62 + String domesticDestination = buildDomesticDestination(destination);
  63 + if (StringUtils.isNotBlank(domesticDestination)) {
  64 + return domesticDestination;
  65 + } else {
  66 + return "";
  67 + }
  68 + }
  69 +
  70 + /**
  71 + * 将国内目的地城市ID转换为中文地址路径。
  72 + *
  73 + * @param destination 目的地ID
  74 + * @return 中文地址路径
  75 + */
  76 + private static String buildDomesticDestination(String destination) {
  77 + if (StringUtils.isBlank(destination)) {
  78 + return "";
  79 + }
  80 +
  81 + try {
  82 + DicCityService dicCityService = ApplicationUtil.getBean(DicCityService.class);
  83 + List<DicCityDto> allCity = dicCityService.getAll();
  84 + List<DicCityDto> fullPath = dicCityService.getFullPath(destination, allCity);
  85 + if (fullPath == null || fullPath.isEmpty()) {
  86 + return "";
  87 + }
  88 +
  89 + StringBuilder builder = new StringBuilder();
  90 + for (DicCityDto cityDto : fullPath) {
  91 + if (cityDto == null || StringUtils.isBlank(cityDto.getName())) {
  92 + continue;
  93 + }
  94 + if (builder.length() > 0) {
  95 + builder.append(",");
  96 + }
  97 + builder.append(cityDto.getName());
  98 + }
  99 + return builder.toString();
  100 + } catch (Exception e) {
  101 + log.warn("转换国内目的地失败, destination={}", destination, e);
  102 + return "";
  103 + }
  104 + }
  105 +
  106 + /**
  107 + * 判断是否为外贸合同类型。
  108 + *
  109 + * @param contractType 合同类型
  110 + * @return true=外贸合同
  111 + */
  112 + private static boolean isForeignContractType(String contractType) {
  113 + return "INTL_STD_CONTRACT".equals(contractType)
  114 + || "INTL_INVENTORY_AGMT".equals(contractType)
  115 + || "INTL_OPEN_SPEC_AGMT".equals(contractType);
  116 + }
  117 +
44 118
45 119 /**
46 120 * 解析占位符
... ... @@ -292,17 +366,6 @@ public class ExcelUtil {
292 366
293 367 cell.setCellValue(buildVerticalText(text));
294 368
295   - CellStyle baseStyle = cell.getCellStyle();
296   - CellStyle pdfStyle = workbook.createCellStyle();
297   - if (baseStyle != null) {
298   - pdfStyle.cloneStyleFrom(baseStyle);
299   - }
300   - pdfStyle.setAlignment(HorizontalAlignment.CENTER);
301   - pdfStyle.setVerticalAlignment(VerticalAlignment.CENTER);
302   - pdfStyle.setWrapText(true);
303   - pdfStyle.setRotation((short) 0);
304   - pdfStyle.setIndention((short) 0);
305   -
306 369 if (mergedCell) {
307 370 CellRangeAddress mergedRegion = findMergedRegion(sheet, cell.getRowIndex(), cell.getColumnIndex());
308 371 if (mergedRegion != null) {
... ... @@ -316,20 +379,36 @@ public class ExcelUtil {
316 379 if (currentCell == null) {
317 380 currentCell = currentRow.createCell(c);
318 381 }
319   - currentCell.setCellStyle(pdfStyle);
  382 + currentCell.setCellStyle(buildPdfVerticalTitleStyle(workbook, currentCell.getCellStyle()));
320 383 }
321 384 }
322 385 } else {
323   - cell.setCellStyle(pdfStyle);
  386 + cell.setCellStyle(buildPdfVerticalTitleStyle(workbook, cell.getCellStyle()));
324 387 }
325 388 } else {
326   - cell.setCellStyle(pdfStyle);
  389 + cell.setCellStyle(buildPdfVerticalTitleStyle(workbook, cell.getCellStyle()));
327 390 }
328 391 return;
329 392 }
330 393 }
331 394 }
332 395
  396 + /**
  397 + * 构建 PDF 竖排标题样式,保留原单元格边框等样式,只覆盖对齐和换行属性。
  398 + */
  399 + private static CellStyle buildPdfVerticalTitleStyle(Workbook workbook, CellStyle baseStyle) {
  400 + CellStyle pdfStyle = workbook.createCellStyle();
  401 + if (baseStyle != null) {
  402 + pdfStyle.cloneStyleFrom(baseStyle);
  403 + }
  404 + pdfStyle.setAlignment(HorizontalAlignment.CENTER);
  405 + pdfStyle.setVerticalAlignment(VerticalAlignment.CENTER);
  406 + pdfStyle.setWrapText(true);
  407 + pdfStyle.setRotation((short) 0);
  408 + pdfStyle.setIndention((short) 0);
  409 + return pdfStyle;
  410 + }
  411 +
333 412 private static String buildVerticalText(String text) {
334 413 StringBuilder builder = new StringBuilder();
335 414 for (int i = 0; i < text.length(); i++) {
... ...
... ... @@ -319,6 +319,14 @@ public class LatexFormulaExcelExporterUtil {
319 319 }
320 320
321 321 /**
  322 + * 将 LaTeX 公式作为图片左对齐插入到指定单元格区域内,并确保图片不会超出区域边界。
  323 + */
  324 + public static void insertLatexImageToCellLeftAligned(Workbook workbook, Sheet sheet, String latex,
  325 + int rowIndex, int colIndex, int rowRange, int colRange) throws IOException {
  326 + insertLatexImageToRegionLeftAligned(workbook, sheet, latex, rowIndex, colIndex, rowRange, colRange, 16, null);
  327 + }
  328 +
  329 + /**
322 330 * 合同规格专用:按照模板单元格区域高度优先铺满,并根据区域大小动态选择更合适的渲染字号。
323 331 */
324 332 public static void insertContractLatexImageToCellFillTemplate(Workbook workbook, Sheet sheet, String latex,
... ... @@ -562,6 +570,103 @@ public class LatexFormulaExcelExporterUtil {
562 570 drawing.createPicture(anchor, pictureIdx);
563 571 }
564 572
  573 + /**
  574 + * 将 LaTeX 公式作为图片左对齐插入到指定区域,并保留左右留白避免压线。
  575 + */
  576 + private static void insertLatexImageToRegionLeftAligned(Workbook workbook, Sheet sheet, String latex,
  577 + int rowIndex, int colIndex, int rowRange, int colRange,
  578 + int fontSize, Double maxScale) throws IOException {
  579 + byte[] imageBytes = latexToImageBytes(latex, fontSize);
  580 + BufferedImage image;
  581 + try (ByteArrayInputStream in = new ByteArrayInputStream(imageBytes)) {
  582 + image = ImageIO.read(in);
  583 + }
  584 +
  585 + if (image == null) {
  586 + return;
  587 + }
  588 +
  589 + int regionWidthPx = 0;
  590 + for (int c = colIndex; c < colIndex + colRange; c++) {
  591 + regionWidthPx += getColumnWidthPx(sheet, c);
  592 + }
  593 + int regionHeightPx = 0;
  594 + for (int r = rowIndex; r < rowIndex + rowRange; r++) {
  595 + regionHeightPx += getRowHeightPx(sheet, r);
  596 + }
  597 +
  598 + int paddingXPx = 6;
  599 + int paddingYPx = 2;
  600 + double scale = Math.min(
  601 + (double) (regionWidthPx - paddingXPx * 2) / Math.max(1, image.getWidth()),
  602 + (double) (regionHeightPx - paddingYPx * 2) / Math.max(1, image.getHeight())
  603 + );
  604 + scale = Math.min(scale, 1.0);
  605 + if (maxScale != null) {
  606 + scale = Math.min(scale, maxScale);
  607 + }
  608 +
  609 + int scaledWidthPx = Math.max(1, (int) Math.round(image.getWidth() * scale));
  610 + int scaledHeightPx = Math.max(1, (int) Math.round(image.getHeight() * scale));
  611 +
  612 + int offsetXPx = paddingXPx;
  613 + int offsetYPx = Math.max(paddingYPx, (regionHeightPx - scaledHeightPx) / 2);
  614 +
  615 + int pictureIdx = workbook.addPicture(imageBytes, Workbook.PICTURE_TYPE_PNG);
  616 + Drawing<?> drawing = sheet.createDrawingPatriarch();
  617 +
  618 + ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor();
  619 + anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_DONT_RESIZE);
  620 +
  621 + AnchorCoord x1 = resolveAnchorX(sheet, colIndex, colRange, offsetXPx);
  622 + AnchorCoord x2 = resolveAnchorX(sheet, colIndex, colRange, offsetXPx + scaledWidthPx);
  623 + AnchorCoord y1 = resolveAnchorY(sheet, rowIndex, rowRange, offsetYPx);
  624 + AnchorCoord y2 = resolveAnchorY(sheet, rowIndex, rowRange, offsetYPx + scaledHeightPx);
  625 +
  626 + anchor.setCol1(x1.index);
  627 + anchor.setCol2(x2.index);
  628 + anchor.setRow1(y1.index);
  629 + anchor.setRow2(y2.index);
  630 +
  631 + if (anchor instanceof org.apache.poi.hssf.usermodel.HSSFClientAnchor) {
  632 + int dx1 = pxToHssfDx(sheet, x1.index, x1.offsetPx);
  633 + int dx2 = pxToHssfDx(sheet, x2.index, x2.offsetPx);
  634 + int dy1 = pxToHssfDy(sheet, y1.index, y1.offsetPx);
  635 + int dy2 = pxToHssfDy(sheet, y2.index, y2.offsetPx);
  636 +
  637 + if (x2.index == x1.index && dx2 <= dx1) {
  638 + dx2 = Math.min(1023, dx1 + 1);
  639 + }
  640 + if (y2.index == y1.index && dy2 <= dy1) {
  641 + dy2 = Math.min(255, dy1 + 1);
  642 + }
  643 +
  644 + anchor.setDx1(dx1);
  645 + anchor.setDx2(dx2);
  646 + anchor.setDy1(dy1);
  647 + anchor.setDy2(dy2);
  648 + } else {
  649 + int dx1 = x1.offsetPx * EMU_PER_PX;
  650 + int dx2 = x2.offsetPx * EMU_PER_PX;
  651 + int dy1 = y1.offsetPx * EMU_PER_PX;
  652 + int dy2 = y2.offsetPx * EMU_PER_PX;
  653 +
  654 + if (x2.index == x1.index && dx2 <= dx1) {
  655 + dx2 = dx1 + 1;
  656 + }
  657 + if (y2.index == y1.index && dy2 <= dy1) {
  658 + dy2 = dy1 + 1;
  659 + }
  660 +
  661 + anchor.setDx1(dx1);
  662 + anchor.setDx2(dx2);
  663 + anchor.setDy1(dy1);
  664 + anchor.setDy2(dy2);
  665 + }
  666 +
  667 + drawing.createPicture(anchor, pictureIdx);
  668 + }
  669 +
565 670 private static void insertContractLatexImageToRegionFillTemplate(Workbook workbook, Sheet sheet, String latex,
566 671 int rowIndex, int colIndex, int rowRange, int colRange,
567 672 int baseFontSize, Double maxScale) throws IOException {
... ...
  1 +package com.lframework.xingyun.sc.utils;
  2 +
  3 +/**
  4 + * 订单明细报表工具类。
  5 + */
  6 +public final class OrderDetailReportUtil {
  7 +
  8 + private OrderDetailReportUtil() {
  9 + }
  10 +
  11 + /**
  12 + * 根据合同类型和订货单类型构建订单类型展示值。
  13 + *
  14 + * @param contractType 合同类型
  15 + * @param purchaseOrderType 订货单类型
  16 + * @return 订单类型展示值
  17 + */
  18 + public static String buildOrderType(String contractType, String purchaseOrderType) {
  19 + if ("DISTRIB_STD".equals(contractType)) {
  20 + return "经销";
  21 + }
  22 + if ("INTL_STD_CONTRACT".equals(contractType)) {
  23 + return "外贸";
  24 + }
  25 + if ("PROCESS_STD_AGMT".equals(contractType)) {
  26 + return "加工";
  27 + }
  28 + if ("DIST_STOCK_CONTRACT".equals(contractType) || "INTL_INVENTORY_AGMT".equals(contractType)) {
  29 + if ("NO_PRODUCTION".equals(purchaseOrderType)) {
  30 + return "库存已锁价";
  31 + }
  32 + if ("PRODUCTION".equals(purchaseOrderType)) {
  33 + return "库存未锁价";
  34 + }
  35 + return "库存";
  36 + }
  37 + if ("DRAFT_DIST_AGMT".equals(contractType) || "INTL_OPEN_SPEC_AGMT".equals(contractType)) {
  38 + if ("NO_PRODUCTION".equals(purchaseOrderType)) {
  39 + return "未锁规";
  40 + }
  41 + if ("PRODUCTION".equals(purchaseOrderType)) {
  42 + return "已锁规";
  43 + }
  44 + return "未锁规";
  45 + }
  46 + return "";
  47 + }
  48 +}
... ...