1.1.45 导出采购审批单 PDF接口

dev
yinq 1 month ago
parent d4e080e83c
commit d7a536d6b9

@ -1,6 +1,7 @@
package org.dromara.oa.erp.controller;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
@ -13,10 +14,14 @@ import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.word.util.WordTemplateUtil;
import com.deepoove.poi.config.Configure;
import org.dromara.oa.erp.word.ErpProjectPurchaseMaterialLoopRowPolicy;
import org.dromara.oa.erp.domain.vo.ErpProjectPurchaseVo;
import org.dromara.oa.erp.domain.vo.ErpProjectPurchaseMaterialVo;
import org.dromara.oa.erp.domain.vo.ErpProjectMaterialsSourceVo;
@ -77,6 +82,28 @@ public class ErpProjectPurchaseController extends BaseController {
ExcelUtil.exportExcel(list, "项目采购单明细", ErpProjectPurchaseMaterialVo.class, response);
}
/**
* PDF Word
*
* @param projectPurchaseId ID
*/
@SaCheckPermission("oa/erp:projectPurchase:export")
@Log(title = "采购审批单PDF导出", businessType = BusinessType.EXPORT)
@GetMapping("/exportApprovalPdf/{projectPurchaseId}")
public void exportApprovalPdf(@NotNull(message = "项目采购ID不能为空")
@PathVariable("projectPurchaseId") Long projectPurchaseId,
HttpServletResponse response) {
Map<String, Object> data = erpProjectPurchaseService.buildApprovalWordExportData(projectPurchaseId);
ErpProjectPurchaseVo vo = erpProjectPurchaseService.queryById(projectPurchaseId);
String fileName = "采购审批单_" + (vo != null && StringUtils.isNotBlank(vo.getProjectCode())
? vo.getProjectCode() : projectPurchaseId);
Configure config = Configure.builder()
.bind("标准物料", new ErpProjectPurchaseMaterialLoopRowPolicy())
.bind("非标准物料", new ErpProjectPurchaseMaterialLoopRowPolicy())
.build();
WordTemplateUtil.renderToPdfResponse("采购审批单模板.docx", fileName, data, config, response);
}
/**
*
*

@ -118,6 +118,11 @@ public class ErpProjectPurchaseMaterialVo implements Serializable {
// @ExcelProperty(value = "单位ID")
private Long unitId;
/**
*
*/
private String unitName;
/**
*
*/

@ -10,6 +10,7 @@ import org.dromara.common.mybatis.core.page.PageQuery;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Service
@ -90,4 +91,12 @@ public interface IErpProjectPurchaseService {
* @param contractId ID
*/
ErpProjectMaterialsSourceVo getProjectMaterialsSourceByProjectId(Long projectId, String spareFlag, Long contractId);
/**
* Word
*
* @param projectPurchaseId ID
* @return Map
*/
Map<String, Object> buildApprovalWordExportData(Long projectPurchaseId);
}

@ -1,5 +1,6 @@
package org.dromara.oa.erp.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
@ -11,6 +12,7 @@ import org.apache.seata.spring.annotation.GlobalTransactional;
import org.dromara.common.core.enums.BusinessStatusEnum;
import org.dromara.common.core.enums.OAStatusEnum;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
@ -34,6 +36,7 @@ import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@ -48,6 +51,18 @@ import java.util.stream.Collectors;
@Slf4j
public class ErpProjectPurchaseServiceImpl implements IErpProjectPurchaseService {
private static final String MATERIAL_DATE_FORMAT = "yyyy-MM-dd";
private static final String NODE_PURCHASE_MANAGER = "采购经理";
private static final String NODE_PROJECT_MANAGER = "项目经理";
private static final String NODE_CHARGE = "部门经理";
private static final String NODE_DEPUTY = "副总审核";
private static final String NODE_GENERAL_MANAGER = "总经理";
private final ErpProjectPurchaseMapper baseMapper;
private final ErpProjectPurchaseMaterialMapper purchaseMaterialMapper;
@ -327,6 +342,198 @@ public class ErpProjectPurchaseServiceImpl implements IErpProjectPurchaseService
return result;
}
@Override
public Map<String, Object> buildApprovalWordExportData(Long projectPurchaseId) {
ErpProjectPurchaseVo purchase = queryById(projectPurchaseId);
if (purchase == null) {
throw new ServiceException("项目采购单不存在ID" + projectPurchaseId);
}
if (!OAStatusEnum.COMPLETED.getStatus().equals(purchase.getProjectPurchaseStatus())) {
throw new ServiceException("仅项目采购状态为“审批完成”时允许导出采购审批单");
}
Map<String, Object> data = new HashMap<>(32);
data.put("采购编号", strVal(purchase.getPurchaseCode()));
data.put("项目号", strVal(purchase.getProjectCode()));
data.put("项目名称", strVal(purchase.getProjectName()));
data.put("项目经理", strVal(purchase.getManagerName()));
data.put("部门负责人", strVal(purchase.getChargeName()));
data.put("分管副总", strVal(purchase.getDeputyName()));
data.put("收货人", strVal(purchase.getConsigneeUser()));
data.put("收货地址", strVal(purchase.getConsigneeAddress()));
data.put("收货人联系方式", strVal(purchase.getConsigneeContact()));
List<ErpProjectPurchaseMaterialVo> materials = purchase.getPurchaseMaterialList();
if (materials == null) {
materials = Collections.emptyList();
}
data.put("标准物料", buildMaterialLoopData(materials, "1"));
data.put("非标准物料", buildMaterialLoopData(materials, "2"));
Map<String, Object> flowData = remoteWorkflowService.flowHisTaskList(String.valueOf(projectPurchaseId));
List<Map<String, Object>> handledTasks = extractHandledTasks(flowData == null ? null : flowData.get("list"));
data.put("采购经理意见", resolveApprovalOpinion(findLatestTaskByNodeName(handledTasks, NODE_PURCHASE_MANAGER)));
data.put("项目经理审批意见", resolveApprovalOpinion(findLatestTaskByNodeName(handledTasks, NODE_PROJECT_MANAGER)));
data.put("部门负责人审批意见", resolveApprovalOpinion(findLatestTaskByNodeName(handledTasks, NODE_CHARGE)));
data.put("分管副总审批意见", resolveApprovalOpinion(findLatestTaskByNodeName(handledTasks, NODE_DEPUTY)));
data.put("总经理意见", resolveApprovalOpinion(findLatestTaskByNodeName(handledTasks, NODE_GENERAL_MANAGER)));
data.put("是否需要总经理审批", resolveNeedGeneralManagerApproval(handledTasks, flowData));
return data;
}
private List<Map<String, Object>> buildMaterialLoopData(List<ErpProjectPurchaseMaterialVo> materials, String materialFlag) {
List<Map<String, Object>> rows = materials.stream()
.filter(m -> materialFlag.equals(m.getMaterialFlag()))
.map(this::toMaterialLoopRow)
.collect(Collectors.toCollection(ArrayList::new));
if (rows.isEmpty()) {
rows.add(toEmptyMaterialLoopRow());
}
return rows;
}
private Map<String, Object> toMaterialLoopRow(ErpProjectPurchaseMaterialVo material) {
String name = strVal(material.getMaterialName());
if (StringUtils.isBlank(name)) {
name = strVal(material.getPurchaseMaterialName());
}
String qty = "";
if (material.getPurchaseAmount() != null) {
qty = material.getPurchaseAmount().stripTrailingZeros().toPlainString();
}
Map<String, Object> row = new HashMap<>(8);
row.put("materialName", name);
row.put("materialCode", strVal(material.getMaterialCode()));
row.put("specificationDescription", strVal(material.getSpecificationDescription()));
row.put("unitName", strVal(material.getUnitName()));
row.put("quantity", qty);
row.put("arrivalTime", formatMaterialDate(material.getArrivalTime()));
return row;
}
private Map<String, Object> toEmptyMaterialLoopRow() {
Map<String, Object> row = new HashMap<>(8);
row.put("materialName", "");
row.put("materialCode", "");
row.put("specificationDescription", "");
row.put("unitName", "");
row.put("quantity", "");
row.put("arrivalTime", "");
return row;
}
private String resolveNeedGeneralManagerApproval(List<Map<String, Object>> handledTasks, Map<String, Object> flowData) {
if (findLatestTaskByNodeName(handledTasks, NODE_GENERAL_MANAGER) != null) {
return "是";
}
Object instanceId = flowData == null ? null : flowData.get("instanceId");
if (instanceId != null) {
try {
Map<String, Object> variables = remoteWorkflowService.instanceVariable(Convert.toLong(instanceId));
if (variables != null) {
for (String key : List.of("needGmApproval", "needGeneralManager", "generalManagerApproval", "gmApproval")) {
Object val = variables.get(key);
if (val != null) {
return Boolean.TRUE.equals(val) || "1".equals(String.valueOf(val)) || "true".equalsIgnoreCase(String.valueOf(val)) ? "是" : "否";
}
}
}
} catch (Exception e) {
log.warn("读取项目采购流程变量失败, instanceId={}", instanceId, e);
}
}
return "否";
}
private String resolveApprovalOpinion(Map<String, Object> task) {
if (task == null) {
return "";
}
String message = strVal(task.get("message"));
return StringUtils.isNotBlank(message) ? message : "同意";
}
private List<Map<String, Object>> extractHandledTasks(Object listObj) {
if (!(listObj instanceof List<?> taskList) || taskList.isEmpty()) {
return Collections.emptyList();
}
List<Map<String, Object>> handledTasks = new ArrayList<>();
for (Object taskObj : taskList) {
Map<String, Object> taskMap = toMap(taskObj);
if (!taskMap.isEmpty() && taskMap.get("updateTime") != null) {
handledTasks.add(taskMap);
}
}
handledTasks.sort(Comparator.comparing(task -> {
Date updateTime = parseDate(task.get("updateTime"));
return updateTime == null ? new Date(0L) : updateTime;
}));
return handledTasks;
}
private Map<String, Object> findLatestTaskByNodeName(List<Map<String, Object>> handledTasks, String nodeName) {
if (StringUtils.isBlank(nodeName) || handledTasks == null || handledTasks.isEmpty()) {
return null;
}
for (int i = handledTasks.size() - 1; i >= 0; i--) {
Map<String, Object> task = handledTasks.get(i);
String taskNodeName = strVal(task.get("nodeName"));
String targetNodeName = strVal(task.get("targetNodeName"));
if (nodeName.equals(taskNodeName) || nodeName.equals(targetNodeName)) {
return task;
}
}
return null;
}
private Map<String, Object> toMap(Object obj) {
if (obj == null) {
return Collections.emptyMap();
}
if (obj instanceof Map<?, ?> rawMap) {
Map<String, Object> result = new HashMap<>(rawMap.size());
for (Map.Entry<?, ?> entry : rawMap.entrySet()) {
result.put(String.valueOf(entry.getKey()), entry.getValue());
}
return result;
}
return BeanUtil.beanToMap(obj);
}
private Date parseDate(Object rawDate) {
if (rawDate == null) {
return null;
}
if (rawDate instanceof Date date) {
return date;
}
if (rawDate instanceof Number number) {
long millis = number.longValue();
if (String.valueOf(millis).length() == 10) {
millis = millis * 1000;
}
return new Date(millis);
}
return DateUtils.parseDate(rawDate);
}
private String formatMaterialDate(Date date) {
if (date == null) {
return "";
}
return DateUtils.parseDateToStr(MATERIAL_DATE_FORMAT, date);
}
private String strVal(Object value) {
if (value == null) {
return "";
}
if (value instanceof BigDecimal decimal) {
return decimal.stripTrailingZeros().toPlainString();
}
return String.valueOf(value);
}
/**
*
*

@ -0,0 +1,15 @@
package org.dromara.oa.erp.word;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
/**
* poi-tl LoopRowTableRenderPolicy
* <p>
* onSameLine=true [materialName]
*/
public class ErpProjectPurchaseMaterialLoopRowPolicy extends LoopRowTableRenderPolicy {
public ErpProjectPurchaseMaterialLoopRowPolicy() {
super(true);
}
}
Loading…
Cancel
Save