package cn.palmte.work.service; import org.springframework.beans.BeanUtils; import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.TypedQuery; import cn.palmte.work.config.activiti.ActConstant; import cn.palmte.work.config.activiti.ActProjectTypeEnum; import cn.palmte.work.model.Admin; import cn.palmte.work.model.AdminRepository; import cn.palmte.work.model.Dept; import cn.palmte.work.model.DeptRepository; import cn.palmte.work.model.ProcurementType; import cn.palmte.work.model.ProcurementTypeRepository; import cn.palmte.work.model.Project; import cn.palmte.work.model.ProjectBudgetCostDetail; import cn.palmte.work.model.ProjectRepository; import cn.palmte.work.model.enums.ProcessStatus; import cn.palmte.work.model.process.BudgetPurchaseAmount; import cn.palmte.work.model.process.BudgetPurchaseDetail; import cn.palmte.work.model.process.ProcurementContract; import cn.palmte.work.model.process.ProcurementDetail; import cn.palmte.work.model.process.ProjectProcess; import cn.palmte.work.model.process.SaleContract; import cn.palmte.work.model.process.SupplierMaterial; import cn.palmte.work.model.process.form.SaleContractDetailForm; import lombok.Data; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; /** * @author <a href="https://github.com/TAKETODAY">Harry Yang</a> * @since 2.0 2022/12/23 09:39 */ @Service @RequiredArgsConstructor public class ProjectProcessService { private final JdbcTemplate jdbcTemplate; private final EntityManager entityManager; private final ProjectInstanceService projectInstanceService; private final ProjectRepository projectRepository; private final DeptRepository deptRepository; private final AdminRepository userRepository; private final ProcurementTypeRepository procurementTypeRepository; @Data static class DeptReturnValue { private int id; private int leaderId; private String leaderName; private String name; private List<DeptReturnValue> children; public void addChildren(DeptReturnValue child) { if (children == null) { children = new ArrayList<>(); } children.add(child); } } public List<DeptReturnValue> filterDept() { List<Dept> deptList = deptRepository.findEnable(); List<Dept> level1 = filterByLevel(deptList, 1); List<Dept> level2 = filterByLevel(deptList, 2); List<Dept> level3 = filterByLevel(deptList, 3); List<DeptReturnValue> returnValues = new ArrayList<>(); for (Dept dept : level1) { // 只需要一级领导 Admin leader = userRepository.getAdminById(dept.getManagerId()); String leaderName = leader.getRealName(); DeptReturnValue returnValue = createReturnValue(dept, leaderName); for (Dept dept2 : level2) { if (Objects.equals(dept2.getParentId(), dept.getId())) { DeptReturnValue returnValue2 = createReturnValue(dept2, leaderName); for (Dept dept3 : level3) { if (Objects.equals(dept3.getParentId(), dept2.getId())) { returnValue2.addChildren(createReturnValue(dept3, leaderName)); } } returnValue.addChildren(returnValue2); } } returnValues.add(returnValue); } return returnValues; } private static List<Dept> filterByLevel(List<Dept> deptList, int level) { ArrayList<Dept> ret = new ArrayList<>(); for (Dept dept : deptList) { if (Objects.equals(dept.getLevel(), level)) { ret.add(dept); } } return ret; } private DeptReturnValue createReturnValue(Dept dept, String leaderName) { DeptReturnValue returnValue = new DeptReturnValue(); returnValue.setId(dept.getId()); returnValue.setName(dept.getName()); returnValue.setLeaderId(dept.getManagerId()); returnValue.setLeaderName(leaderName); return returnValue; } /** * 更新流程 审批人,和状态 * * @param processId 流程Id * @param auditId 审批人ID * @param status 流程状态 可以为空,为空的时候不修改 */ public void updateAudit(int processId, ProcessStatus status, List<Integer> auditId) { String currentAudit = getCurrentAudit(auditId); String currentAuditId = auditId.stream().map(String::valueOf).collect(Collectors.joining(",")); if (status != null) { if (!CollectionUtils.isEmpty(auditId)) { jdbcTemplate.update( "update project_process set current_audit=?,current_audit_id=?,status=? where id=?", currentAudit, currentAuditId, status.getValue(), processId); } } else { jdbcTemplate.update("update project_process set current_audit=?,current_audit_id=? where id=?", currentAudit, currentAuditId, processId); } } private String getCurrentAudit(List<Integer> auditId) { TypedQuery<Admin> query = entityManager.createQuery("from Admin where id in (:ids)", Admin.class); query.setParameter("ids", auditId); List<Admin> resultList = query.getResultList(); return resultList.stream().map(Admin::getRealName) .collect(Collectors.joining(",")); } /** * 只更新状态 */ public void updateProcessStatus(int processId, ProcessStatus status) { jdbcTemplate.update("update project_process set `status`=? where id=?", status.getValue(), processId); } /** * 根据流程ID查询销售合同 * * @param processId 流程ID * @return 销售合同 */ public SaleContract findSaleContract(int processId) { TypedQuery<SaleContract> query = entityManager.createQuery( "from SaleContract where processId=:processId", SaleContract.class); query.setParameter("processId", processId); return query.getSingleResult(); } /** * 根据流程ID查询采购合同 * * @param processId 流程ID * @return 采购合同 */ public ProcurementContract findProcurementContract(int processId) { TypedQuery<ProcurementContract> query = entityManager.createQuery( "from ProcurementContract where processId=:processId", ProcurementContract.class); query.setParameter("processId", processId); return query.getSingleResult(); } public List<SupplierMaterial> getSupplierMaterials(int processId) { TypedQuery<SupplierMaterial> query = entityManager.createQuery( "from SupplierMaterial where processId=:processId", SupplierMaterial.class); query.setParameter("processId", processId); return query.getResultList(); } /** * 获取 采购清单 * * @param projectId 项目ID * @param processId 流程ID 一般用于获取详情 */ public List<ProcurementDetail> getProcurementDetails(int projectId, Integer processId) { List<ProcurementDetail> ret = new ArrayList<>(); List<ProjectBudgetCostDetail> costDetails = getCostDetails(projectId); for (ProjectBudgetCostDetail costDetail : costDetails) { ProcurementDetail detail = new ProcurementDetail(); BeanUtils.copyProperties(costDetail, detail); // 可能为 0 BigDecimal amountAlready = getAmountAlready(costDetail.getId()); detail.setAmountAlready(amountAlready); if (processId != null) { // 根据 processId 确定唯一的 BudgetPurchaseAmount 用作获取详情 , 可能还未创建 BudgetPurchaseAmount purchaseAmount = getPurchaseAmount(projectId, processId); if (purchaseAmount != null) { Integer amountId = purchaseAmount.getId(); List<BudgetPurchaseDetail> purchaseDetails = getBudgetPurchaseDetails(amountId); detail.setPurchaseDetails(purchaseDetails); } } // TODO 查询太频繁 detail.setCategory(getCategory(costDetail)); detail.setBudgetCostId(costDetail.getId()); ret.add(detail); } return ret; } private String getCategory(ProjectBudgetCostDetail costDetail) { int category = costDetail.getCategory(); TypedQuery<ProcurementType> query = entityManager.createQuery( "from ProcurementType where id=:category and isDeleted=0 and enabled=1", ProcurementType.class); query.setParameter("category", category); try { ProcurementType procurementType = query.getSingleResult(); return procurementType.getName(); } catch (NoResultException e) { return String.valueOf(category); } } private List<BudgetPurchaseDetail> getBudgetPurchaseDetails(int amountId) { TypedQuery<BudgetPurchaseDetail> query = entityManager.createQuery( "from BudgetPurchaseDetail where amountId=:amountId", BudgetPurchaseDetail.class); query.setParameter("amountId", amountId); return query.getResultList(); } private List<ProjectBudgetCostDetail> getCostDetails(int projectId) { TypedQuery<ProjectBudgetCostDetail> query = entityManager.createQuery( "from ProjectBudgetCostDetail where projectId=:projectId", ProjectBudgetCostDetail.class); query.setParameter("projectId", projectId); return query.getResultList(); } public BudgetPurchaseAmount getPurchaseAmount(int budgetCostId, Integer processId) { TypedQuery<BudgetPurchaseAmount> amountQuery = entityManager.createQuery( "from BudgetPurchaseAmount where budgetCostId=:budgetCostId and processId=:processId", BudgetPurchaseAmount.class); amountQuery.setParameter("budgetCostId", budgetCostId); amountQuery.setParameter("processId", processId); try { return amountQuery.getSingleResult(); } catch (NoResultException e) { return null; } } public List<BudgetPurchaseAmount> getPurchaseAmountList(int budgetCostId) { TypedQuery<BudgetPurchaseAmount> amountQuery = entityManager.createQuery( "from BudgetPurchaseAmount where budgetCostId=:budgetCostId", BudgetPurchaseAmount.class); amountQuery.setParameter("budgetCostId", budgetCostId); return amountQuery.getResultList(); } public BigDecimal getAmountAlready(int budgetCostId) { return getPurchaseAmountList(budgetCostId).stream() .map(BudgetPurchaseAmount::getAmountAlready) .reduce(BigDecimal.ZERO, BigDecimal::add); } public ProjectProcess getById(int id) { return entityManager.find(ProjectProcess.class, id); } /** * 更新 销售合同 的 质保期 */ public void updateIncomeDetails(List<SaleContractDetailForm> incomeDetails) { if (!CollectionUtils.isEmpty(incomeDetails)) { jdbcTemplate.batchUpdate("update project_budget_income_detail set expiration_date =? where id =? ", new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { SaleContractDetailForm detailForm = incomeDetails.get(i); ps.setString(1, detailForm.getExpirationDate()); ps.setInt(2, detailForm.getId()); } @Override public int getBatchSize() { return incomeDetails.size(); } }); } } public BigDecimal getProjectRepaidAmount(int projectId) { Map<String, Object> map = jdbcTemplate.queryForMap( "select ifnull(sum(underwritten_plan), 0) repaidAmount from project_budget_plan_detail where project_id = ?", projectId); return (BigDecimal) map.values().iterator().next(); } /** * 发起流程审批 */ public void startAuditProgress(ProjectProcess entity) { HashMap<String, Object> variables = new HashMap<>(); Project project = projectRepository.findById(entity.getProjectId()); // 是否垫资 variables.put("isPrepaid", isProjectPrepaid(project)); // 垫资金额 BigDecimal repaidAmount = getProjectRepaidAmount(entity.getProjectId()); variables.put("repaidAmount", repaidAmount); // 合同金额 variables.put("contractAmount", project.getContractAmount() == null ? 0 : project.getContractAmount()); // 项目类型 variables.put("projectType", project.getType()); // 合作类型 variables.put("cooperationType", project.getCooperateType() == null ? 0 : project.getCooperateType()); // 部门领导ID variables.put(ActConstant.DEPT_LEADER_ID, entity.getApplyDeptLeaderId()); startAuditProgress(entity, variables); } /** * 是否垫资 */ public boolean isProjectPrepaid(Project project) { return project.getUnderwrittenMode() == 2 || project.getUnderwrittenMode() == 3; } /** * 发起流程审批 */ @SneakyThrows public void startAuditProgress(ProjectProcess entity, Map<String, Object> variables) { if (entity.getStatus() == ProcessStatus.to_be_audit) { switch (entity.getProcessType()) { case sale_contract: projectInstanceService.startProcessByProjectId(entity.getId(), ActProjectTypeEnum.SALE_CONTRACT, variables); break; case procurement_contract: projectInstanceService.startProcessByProjectId(entity.getId(), ActProjectTypeEnum.BUSINESS_PURCHASE, variables); break; default: throw new UnsupportedOperationException("还不支持"); } } } }