소스 검색

Merge remote-tracking branch 'origin/master'

tags/24080901
PoffyZhang 1 년 전
부모
커밋
137be0fcdf
32개의 변경된 파일1123개의 추가작업 그리고 245개의 파일을 삭제
  1. +1
    -1
      ningda-generator/src/main/java/com/ningdatech/generator/config/GeneratorCodeKingbaseConfig.java
  2. +9
    -9
      pmapi/src/main/java/com/ningdatech/pmapi/common/config/GovDingProperties.java
  3. +10
    -10
      pmapi/src/main/java/com/ningdatech/pmapi/common/statemachine/event/ProjectStatusChangeEvent.java
  4. +29
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/ding/model/DingOrgInfoTreeDTO.java
  5. +171
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/ding/task/OrganizationBatchGetTask.java
  6. +20
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/organization/controller/DingOrganizationController.java
  7. +55
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/organization/entity/DingOrganization.java
  8. +16
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/organization/mapper/DingOrganizationMapper.java
  9. +5
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/organization/mapper/DingOrganizationMapper.xml
  10. +16
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/organization/service/IDingOrganizationService.java
  11. +20
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/organization/service/impl/DingOrganizationServiceImpl.java
  12. +3
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/entity/ProcessComment.java
  13. +1
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/entity/ProgressNode.java
  14. +23
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/controller/TodoCenterController.java
  15. +0
    -97
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/enums/ProcessHandlerEnum.java
  16. +1
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/extension/cmd/BackToHisApprovalNodeCmd.java
  17. +104
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/extension/cmd/SaveCommentCmd.java
  18. +174
    -75
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/manage/TodoCenterManage.java
  19. +2
    -42
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/model/dto/req/ReqProcessHandlerDTO.java
  20. +41
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/model/dto/res/ResCcMeExportDTO.java
  21. +3
    -6
      pmapi/src/main/resources/application-dev.yml
  22. +20
    -0
      pmapi/src/main/resources/integration/zwdd-dev.yml
  23. +11
    -0
      pmapi/src/main/resources/integration/zwdd-prod.yml
  24. +31
    -0
      pmapi/src/test/java/com/ningdatech/pmapi/organization/OrganizationTest.java
  25. +168
    -0
      pmapi/src/test/resources/application-dev.yml
  26. +0
    -0
      pmapi/src/test/resources/application-prod.yml
  27. +3
    -0
      pmapi/src/test/resources/application.yml
  28. +14
    -0
      pmapi/src/test/resources/integration/zwdd-dev.yml
  29. +11
    -0
      pmapi/src/test/resources/integration/zwdd-prod.yml
  30. +68
    -0
      pmapi/src/test/resources/logback-spring.xml
  31. +52
    -0
      pmapi/src/test/resources/security/auth-dev.yml
  32. +41
    -0
      pmapi/src/test/resources/security/auth-prod.yml

+ 1
- 1
ningda-generator/src/main/java/com/ningdatech/generator/config/GeneratorCodeKingbaseConfig.java 파일 보기

@@ -56,7 +56,7 @@ public class GeneratorCodeKingbaseConfig {
}

public static void main(String[] args) {
generate("WendyYang", "projectlib", PATH_YYD, "nd_project_application");
generate("Lierbao", "organization", PATH_LXX, "ding_organization");
}

}

+ 9
- 9
pmapi/src/main/java/com/ningdatech/pmapi/common/config/GovDingProperties.java 파일 보기

@@ -44,15 +44,15 @@ public class GovDingProperties {
GovDingProperties.appAuthsecret = appAuthsecret;
}

@Value("${ding.app-sso-auth-key}")
public void setAppSsoAuthKey(String appSsoAuthkey) {
GovDingProperties.appSsoAuthkey = appSsoAuthkey;
}
@Value("${ding.app-sso-auth-secret}")
public void setAppSsoAuthsecret(String appSsoAuthsecret) {
GovDingProperties.appSsoAuthsecret = appSsoAuthsecret;
}
// @Value("${ding.app-sso-auth-key}")
// public void setAppSsoAuthKey(String appSsoAuthkey) {
// GovDingProperties.appSsoAuthkey = appSsoAuthkey;
// }
//
// @Value("${ding.app-sso-auth-secret}")
// public void setAppSsoAuthsecret(String appSsoAuthsecret) {
// GovDingProperties.appSsoAuthsecret = appSsoAuthsecret;
// }

@Value("${ding.tenantId}")
public void setTenantId(Long tenantId) {


+ 10
- 10
pmapi/src/main/java/com/ningdatech/pmapi/common/statemachine/event/ProjectStatusChangeEvent.java 파일 보기

@@ -26,43 +26,43 @@ public enum ProjectStatusChangeEvent {
/**
* 项目申报提交(项目状态进入:单位内部审核中)
*/
PROJECT_APPLICATION_SUBMIT(1015,null,null),
PROJECT_APPLICATION_SUBMIT(10015,null,null),
/**
* 单位内部审核驳回(项目状态进入:单位内部审核不通过)
*/
UNDER_INTERNAL_REJECT(null,1001,null),
UNDER_INTERNAL_REJECT(null,10001,null),
/**
* 单位内部审核通过(项目状态进入:待预审)
*/
UNDER_INTERNAL_PASS(1001,null,null),
UNDER_INTERNAL_PASS(10001,null,null),
/**
* 预审申报(项目状态进入:待预审选择,有判断条件:市级项目且申报金额大于1000万项目状态变为:省级部门联审中;否则项目状态变为:预审中)
*/
PRELIMINARY_REVIEW_DECLARE(1003,null,null),
PRELIMINARY_REVIEW_DECLARE(10003,null,null),
/**
* 省级部门联审不通过(项目状态变为:省级部门联审不通过)
*/
PROVINCIAL_DEPARTMENT_REVIEW_REJECT(null,1004,null),
PROVINCIAL_DEPARTMENT_REVIEW_REJECT(null,10004,null),
/**
* 省级部门联审通过(项目状态变为:预审中)
*/
PROVINCIAL_DEPARTMENT_REVIEW_PASS(1004,null,null),
PROVINCIAL_DEPARTMENT_REVIEW_PASS(10004,null,null),
/**
* 预审驳回(项目状态变为:预审不通过)
*/
PRELIMINARY_REVIEW_REJECT(null,1006,null),
PRELIMINARY_REVIEW_REJECT(null,10006,null),
/**
* 预审通过(项目状态变为:部门联审中)
*/
PRELIMINARY_REVIEW_PASS(1006,null,null),
PRELIMINARY_REVIEW_PASS(10006,null,null),
/**
* 部门联审驳回(项目状态变为:部门联审不通过)
*/
DEPARTMENT_UNITED_REVIEW_REJECT(null,1008,null),
DEPARTMENT_UNITED_REVIEW_REJECT(null,10008,null),
/**
* 部门联审通过(项目状态变为:年度计划中)
*/
DEPARTMENT_UNITED_REVIEW_PASS(1008,null,null),
DEPARTMENT_UNITED_REVIEW_PASS(10008,null,null),
/**
* 年度计划暂缓(项目状态变为:被暂缓)
*/


+ 29
- 0
pmapi/src/main/java/com/ningdatech/pmapi/ding/model/DingOrgInfoTreeDTO.java 파일 보기

@@ -0,0 +1,29 @@
package com.ningdatech.pmapi.ding.model;

import com.ningdatech.zwdd.model.dto.DingOrgInfoDTO;
import lombok.Data;

import java.util.List;

/**
* @author liuxinxin
* @date 2022/8/24 上午11:06
* 钉钉组织结构树状结构
*/
@Data
public class DingOrgInfoTreeDTO {

/**
* 钉钉code码
*/
private String code;

/**
* 组织信息
*/
private DingOrgInfoDTO dingOrgInfoDTO;
/**
* 子节点code
*/
private List<DingOrgInfoTreeDTO> childCodes;
}

+ 171
- 0
pmapi/src/main/java/com/ningdatech/pmapi/ding/task/OrganizationBatchGetTask.java 파일 보기

@@ -0,0 +1,171 @@

package com.ningdatech.pmapi.ding.task;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.common.collect.Lists;
import com.ningdatech.basic.model.GenericResult;
import com.ningdatech.pmapi.ding.model.DingOrgInfoTreeDTO;
import com.ningdatech.pmapi.organization.entity.DingOrganization;
import com.ningdatech.pmapi.organization.service.IDingOrganizationService;
import com.ningdatech.zwdd.client.ZwddAuthClient;
import com.ningdatech.zwdd.client.ZwddClient;
import com.ningdatech.zwdd.model.dto.DingOrgInfoDTO;
import com.ningdatech.zwdd.model.dto.DingScopesV2DTO;
import com.ningdatech.zwdd.model.dto.PageSubOrganizationCodeDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
* @author liuxinxin
* @date 2023/2/7 上午10:15
*/

@Slf4j
@Component
public class OrganizationBatchGetTask {

@Autowired
private ZwddClient zwddClient;

@Autowired
private ZwddAuthClient zwddAuthClient;

private static final Integer GROUP_SIZE = 100;

@Autowired
private IDingOrganizationService iDingOrganizationService;

/**
* 获取浙政钉组织架构
*/
@Transactional(rollbackFor = Exception.class)
public void batchGetOrganizationTask() {
// List<DingOrganization> allList = iDingOrganizationService.list();
// List<String> currentAllOrganizationCodeList = allList.stream().map(DingOrganization::getOrganizationCode).collect(Collectors.toList());
// 全量删除
// iDingOrganizationService.remove(Wrappers.lambdaQuery(DingOrganization.class).isNotNull(DingOrganization::getId));
// 获取顶级组织code
GenericResult<DingScopesV2DTO> scopesV2Result = zwddClient.getScopesV2();
DingScopesV2DTO scopesV2 = scopesV2Result.getData();

if (Objects.nonNull(scopesV2)) {
// 顶级组织code
List<String> deptVisibleScopes = scopesV2.getDeptVisibleScopes();
log.info("顶级组织code: size = " + deptVisibleScopes.size() + "列表:" + JSONObject.toJSONString(deptVisibleScopes));
// 获取顶级节点信息
GenericResult<List<DingOrgInfoDTO>> listGenericResult = zwddClient.listOrganizationsByCodes(deptVisibleScopes);
List<DingOrgInfoDTO> dingOrgInfoDtos = listGenericResult.getData();
for (String orgCode : deptVisibleScopes) {
// if (currentAllOrganizationCodeList.contains(orgCode)) {
// log.info("已存在组织架构---{}", orgCode);
// continue;
// }
List<DingOrgInfoTreeDTO> treeDTOList = new ArrayList<>();

DingOrgInfoTreeDTO childDingOrgInfoTreeDTO = new DingOrgInfoTreeDTO();
//设置节点详情
if (dingOrgInfoDtos != null && !dingOrgInfoDtos.isEmpty()) {
for (DingOrgInfoDTO orgInfo : dingOrgInfoDtos) {
if (orgInfo.getOrganizationCode().equals(orgCode)) {
childDingOrgInfoTreeDTO.setDingOrgInfoDTO(orgInfo);
}
}
}
childDingOrgInfoTreeDTO.setCode(orgCode);
childDingOrgInfoTreeDTO.setChildCodes(new ArrayList<>());
getDingOrgChild(childDingOrgInfoTreeDTO);
treeDTOList.add(childDingOrgInfoTreeDTO);

if (CollectionUtils.isNotEmpty(treeDTOList)) {
List<DingOrganization> saveRecordList = new ArrayList<>();
buildSaveRecordList(treeDTOList, saveRecordList);

// 批量保存
if (saveRecordList.size() <= GROUP_SIZE) {
iDingOrganizationService.saveBatch(saveRecordList);
} else {
List<List<DingOrganization>> split = Lists.partition(saveRecordList, GROUP_SIZE);
for (List<DingOrganization> segment : split) {
iDingOrganizationService.saveBatch(segment);
}
}
}
log.info("----拉取浙政钉组织结构结束---,顶级code:" + orgCode);
}
}
}

private void buildSaveRecordList(List<DingOrgInfoTreeDTO> treeDTOList, List<DingOrganization> saveRecordList) {
if (CollectionUtils.isEmpty(treeDTOList)) {
return;
}
for (DingOrgInfoTreeDTO dingOrgInfoTreeDTO : treeDTOList) {
DingOrganization saveRecord = new DingOrganization();
DingOrgInfoDTO dingOrgInfoDTO = dingOrgInfoTreeDTO.getDingOrgInfoDTO();
List<DingOrgInfoTreeDTO> childCodes = dingOrgInfoTreeDTO.getChildCodes();
saveRecord.setDisplayOrder(dingOrgInfoDTO.getDisplayOrder());
// saveRecord.setEnabled("1");
saveRecord.setParentCode(dingOrgInfoDTO.getParentCode());
saveRecord.setOrganizationCode(dingOrgInfoDTO.getOrganizationCode());
// saveRecord.setSubCount((long) dingOrgInfoTreeDTO.getChildCodes().size());
saveRecord.setOrganizationName(dingOrgInfoDTO.getOrganizationName());
saveRecordList.add(saveRecord);
if (CollectionUtils.isNotEmpty(childCodes)) {
buildSaveRecordList(childCodes, saveRecordList);
}
}

}

private void getDingOrgChild(DingOrgInfoTreeDTO parentDingOrgInfoTreeDTO) {
String parentOrgCode = parentDingOrgInfoTreeDTO.getCode();
DingOrgInfoDTO orgInfoDTO = parentDingOrgInfoTreeDTO.getDingOrgInfoDTO();
boolean leaf = orgInfoDTO.getLeaf();
if (!leaf) {
int currentPage = 1;
int pageSize = 100;
GenericResult<PageSubOrganizationCodeDTO> pageSubOrganizationCodeDTOGenericResult = zwddClient.pageSubOrganizationCodes(currentPage++, pageSize, parentOrgCode);
PageSubOrganizationCodeDTO pageSubOrganizationCodeDTO = pageSubOrganizationCodeDTOGenericResult.getData();

if (CollUtil.isNotEmpty(pageSubOrganizationCodeDTO.getSubOrganizationCodeList())) {
List<String> subOrganizationCodeList = new ArrayList<>(pageSubOrganizationCodeDTO.getSubOrganizationCodeList());
Long totalSize = pageSubOrganizationCodeDTO.getTotalSize();

while (totalSize > (long) currentPage * pageSize) {
GenericResult<PageSubOrganizationCodeDTO> subPageSubOrganizationCodeDTOGenericResult = zwddClient
.pageSubOrganizationCodes(currentPage++, pageSize, parentOrgCode);
PageSubOrganizationCodeDTO subOrganizationCodeDTO = subPageSubOrganizationCodeDTOGenericResult.getData();
if (CollectionUtils.isNotEmpty(subOrganizationCodeDTO.getSubOrganizationCodeList())) {
subOrganizationCodeList.addAll(subOrganizationCodeDTO.getSubOrganizationCodeList());
}
}

if (CollectionUtils.isNotEmpty(subOrganizationCodeList)) {
GenericResult<List<DingOrgInfoDTO>> listGenericResult = zwddClient
.listOrganizationsByCodes(subOrganizationCodeList);
List<DingOrgInfoDTO> dingOrgInfoDtos = listGenericResult.getData();
List<DingOrgInfoTreeDTO> dingOrgInfoTreeDTOList = dingOrgInfoDtos.stream().map(r -> {
DingOrgInfoTreeDTO dingOrgInfoTreeDTO = new DingOrgInfoTreeDTO();
dingOrgInfoTreeDTO.setCode(r.getOrganizationCode());
dingOrgInfoTreeDTO.setDingOrgInfoDTO(r);
dingOrgInfoTreeDTO.setChildCodes(new ArrayList<>());
getDingOrgChild(dingOrgInfoTreeDTO);
return dingOrgInfoTreeDTO;
}).collect(Collectors.toList());
parentDingOrgInfoTreeDTO.setChildCodes(dingOrgInfoTreeDTOList);
}
}
}
}

}


+ 20
- 0
pmapi/src/main/java/com/ningdatech/pmapi/organization/controller/DingOrganizationController.java 파일 보기

@@ -0,0 +1,20 @@
package com.ningdatech.pmapi.organization.controller;


import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.stereotype.Controller;

/**
* <p>
* 前端控制器
* </p>
*
* @author Lierbao
* @since 2023-02-09
*/
@Controller
@RequestMapping("/pmapi.organization/ding-organization")
public class DingOrganizationController {

}

+ 55
- 0
pmapi/src/main/java/com/ningdatech/pmapi/organization/entity/DingOrganization.java 파일 보기

@@ -0,0 +1,55 @@
package com.ningdatech.pmapi.organization.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import lombok.Data;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
* <p>
*
* </p>
*
* @author Lierbao
* @since 2023-02-09
*/
@TableName("ding_organization")
@ApiModel(value = "DingOrganization对象", description = "")
@Data
public class DingOrganization implements Serializable {

private static final long serialVersionUID = 1L;

private Long id;

private String institutionLevelCode;

private String address;

private String organizationName;

private Long displayOrder;

private Long typeName;

private Integer leaf;

private LocalDateTime gmtCreate;

private String typeCode;

private String divisionCode;

private String parentName;

private String parentCode;

private String organizationCode;

private String businessStripCodes;

private String status;

}

+ 16
- 0
pmapi/src/main/java/com/ningdatech/pmapi/organization/mapper/DingOrganizationMapper.java 파일 보기

@@ -0,0 +1,16 @@
package com.ningdatech.pmapi.organization.mapper;

import com.ningdatech.pmapi.organization.entity.DingOrganization;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
* <p>
* Mapper 接口
* </p>
*
* @author Lierbao
* @since 2023-02-09
*/
public interface DingOrganizationMapper extends BaseMapper<DingOrganization> {

}

+ 5
- 0
pmapi/src/main/java/com/ningdatech/pmapi/organization/mapper/DingOrganizationMapper.xml 파일 보기

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ningdatech.pmapi.organization.mapper.DingOrganizationMapper">

</mapper>

+ 16
- 0
pmapi/src/main/java/com/ningdatech/pmapi/organization/service/IDingOrganizationService.java 파일 보기

@@ -0,0 +1,16 @@
package com.ningdatech.pmapi.organization.service;

import com.ningdatech.pmapi.organization.entity.DingOrganization;
import com.baomidou.mybatisplus.extension.service.IService;

/**
* <p>
* 服务类
* </p>
*
* @author Lierbao
* @since 2023-02-09
*/
public interface IDingOrganizationService extends IService<DingOrganization> {

}

+ 20
- 0
pmapi/src/main/java/com/ningdatech/pmapi/organization/service/impl/DingOrganizationServiceImpl.java 파일 보기

@@ -0,0 +1,20 @@
package com.ningdatech.pmapi.organization.service.impl;

import com.ningdatech.pmapi.organization.entity.DingOrganization;
import com.ningdatech.pmapi.organization.mapper.DingOrganizationMapper;
import com.ningdatech.pmapi.organization.service.IDingOrganizationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

/**
* <p>
* 服务实现类
* </p>
*
* @author Lierbao
* @since 2023-02-09
*/
@Service
public class DingOrganizationServiceImpl extends ServiceImpl<DingOrganizationMapper, DingOrganization> implements IDingOrganizationService {

}

+ 3
- 2
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/entity/ProcessComment.java 파일 보기

@@ -1,5 +1,6 @@
package com.ningdatech.pmapi.todocenter.bean.entity;

import com.ningdatech.pmapi.common.model.FileBasicInfo;
import com.wflow.workflow.bean.vo.ProcessHandlerParamsVo;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -26,9 +27,9 @@ public class ProcessComment {
/**
* 评论附件
*/
protected List<Attachment> attachments;
protected List<FileBasicInfo> attachments;

public ProcessComment(String text, List<Attachment> attachments) {
public ProcessComment(String text, List<FileBasicInfo> attachments) {
this.text = text;
this.attachments = null == attachments ? Collections.emptyList() : attachments;
}


+ 1
- 2
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/bean/entity/ProgressNode.java 파일 보기

@@ -1,11 +1,10 @@
package com.ningdatech.pmapi.todocenter.bean.entity;

import com.ningdatech.pmapi.todocenter.bean.vo.ProgressNodeAuditInfoVo;
import com.ningdatech.pmapi.todocenter.enums.ProcessHandlerEnum;
import com.ningdatech.pmapi.todocenter.model.dto.req.ReqProcessHandlerDTO;
import com.wflow.workflow.bean.process.OrgUser;
import com.wflow.workflow.bean.process.enums.ApprovalModeEnum;
import com.wflow.workflow.bean.process.enums.NodeTypeEnum;
import com.wflow.workflow.enums.ProcessHandlerEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;


+ 23
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/controller/TodoCenterController.java 파일 보기

@@ -128,5 +128,28 @@ public class TodoCenterController {
ExcelDownUtil.downXlsx(response,param,todoCenterManage::exportMySubmittedProjectList);
}

/**
* 待办中心-抄送我的项目列表查询
* @param param
* @return
*/
@GetMapping("/query-CcMe-list")
public ApiResponse<PageVo<ResToBeProcessedDTO>> queryCcMeProjectList(@Valid @ModelAttribute ReqToBeProcessedDTO param){
PageVo<ResToBeProcessedDTO> result = todoCenterManage.queryCcMeProjectList(param);
return ApiResponse.ofSuccess(result);
}

/**
* 待办中心-抄送我的项目列表导出
*
* @param param
* @param response
* @return void
*/
@GetMapping("/exportCcMe")
public void exportCcMeProjectList(ReqToBeProcessedDTO param, HttpServletResponse response){
ExcelDownUtil.downXlsx(response,param,todoCenterManage::exportCcMeProjectList);
}


}

+ 0
- 97
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/enums/ProcessHandlerEnum.java 파일 보기

@@ -1,97 +0,0 @@
package com.ningdatech.pmapi.todocenter.enums;

import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;

import java.util.Objects;

/**
* 流程处理类型
* @author CMM
* @since 2023/02/01 16:58
*/
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "ProcessHandlerEnum", description = "流程处理类型-枚举")
public enum ProcessHandlerEnum {
/**
* 通过
*/

PASS(1, "通过"),

/**
* 盖章并通过
*/
SEAL_PASS(2, "盖章并通过"),

/**
* 退回
*/
BACK(3,"退回"),

/**
* 撤回
*/
WITHDRAW(4,"撤回"),
/**
* 驳回
*/
REJECT(5,"驳回");


private Integer code;
private String desc;

public String getDesc() {
return desc;
}

public void setDesc(String desc) {
this.desc = desc;
}

public static String getDescByCode(Integer code) {
if(Objects.isNull(code)){
return StringUtils.EMPTY;
}
for (ProcessHandlerEnum t : ProcessHandlerEnum.values()) {
if (code.equals(t.getCode())) {
return t.desc;
}
}
return StringUtils.EMPTY;
}

public static Integer getCodeByDesc(String desc) {
if(Objects.isNull(desc)){
return null;
}
for (ProcessHandlerEnum t : ProcessHandlerEnum.values()) {
if (desc.equals(t.getCode())) {
return t.code;
}
}
return null;
}

public static ProcessHandlerEnum getEnumByValue(Integer code) {
if(Objects.isNull(code)){
return null;
}
for (ProcessHandlerEnum t : ProcessHandlerEnum.values()) {
if (code.equals(t.getCode())) {
return t;
}
}
return null;
}

public boolean eq(String val) {
return this.name().equals(val);
}
}

+ 1
- 1
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/extension/cmd/BackToHisApprovalNodeCmd.java 파일 보기

@@ -4,7 +4,7 @@ import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

import com.ningdatech.pmapi.todocenter.enums.ProcessHandlerEnum;
import com.wflow.workflow.enums.ProcessHandlerEnum;
import lombok.RequiredArgsConstructor;
import org.assertj.core.util.Sets;
import org.flowable.bpmn.model.FlowNode;


+ 104
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/extension/cmd/SaveCommentCmd.java 파일 보기

@@ -0,0 +1,104 @@
package com.ningdatech.pmapi.todocenter.extension.cmd;

import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.compatibility.Flowable5CompatibilityHandler;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.engine.impl.persistence.entity.CommentEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.Flowable5Util;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.task.Comment;
import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;

/**
* 保存评论
*
* @author CMM
* @since 2023/02/09 11:43
*/

public class SaveCommentCmd implements Command<Comment> {

protected String taskId;
protected String processInstanceId;
protected String userId;
protected String message;
protected String type;


public SaveCommentCmd(String taskId, String processInstanceId, String userId , String message) {
this.taskId = taskId;
this.processInstanceId = processInstanceId;
this.userId = userId;
this.message = message;
}

@Override
public Comment execute(CommandContext commandContext) {
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
TaskEntity task = null;
if (this.taskId != null) {
task = processEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(this.taskId);
if (task == null) {
throw new FlowableObjectNotFoundException("Cannot find task with id " + this.taskId, Task.class);
}

if (task.isSuspended()) {
throw new FlowableException(this.getSuspendedTaskException());
}
}

ExecutionEntity execution = null;
if (this.processInstanceId != null) {
execution = (ExecutionEntity)processEngineConfiguration.getExecutionEntityManager().findById(this.processInstanceId);
if (execution == null) {
throw new FlowableObjectNotFoundException("execution " + this.processInstanceId + " doesn't exist", Execution.class);
}

if (execution.isSuspended()) {
throw new FlowableException(this.getSuspendedExceptionMessage());
}
}

String processDefinitionId = null;
if (execution != null) {
processDefinitionId = execution.getProcessDefinitionId();
} else if (task != null) {
processDefinitionId = task.getProcessDefinitionId();
}

if (Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, processDefinitionId)) {
Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();
return compatibilityHandler.addComment(this.taskId, this.processInstanceId, this.type, this.message);
} else {
CommentEntity comment = (CommentEntity)processEngineConfiguration.getCommentEntityManager().create();
comment.setUserId(userId);
comment.setType(this.type == null ? "comment" : this.type);
comment.setTime(processEngineConfiguration.getClock().getCurrentTime());
comment.setTaskId(this.taskId);
comment.setProcessInstanceId(this.processInstanceId);
comment.setAction("AddComment");
String eventMessage = this.message.replaceAll("\\s+", " ");
if (eventMessage.length() > 163) {
eventMessage = eventMessage.substring(0, 160) + "...";
}

comment.setMessage(eventMessage);
comment.setFullMessage(this.message);
processEngineConfiguration.getCommentEntityManager().insert(comment);
return comment;
}
}
protected String getSuspendedTaskException() {
return "Cannot add a comment to a suspended task";
}
protected String getSuspendedExceptionMessage() {
return "Cannot add a comment to a suspended execution";
}
}

+ 174
- 75
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/manage/TodoCenterManage.java 파일 보기

@@ -19,7 +19,6 @@ import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.pmapi.common.constant.DingConstant;
import com.ningdatech.pmapi.common.constant.ProjectDeclareConstants;
import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils;
import com.ningdatech.pmapi.common.util.ExcelDownUtil;
import com.ningdatech.pmapi.common.util.ExcelExportStyle;
@@ -31,15 +30,12 @@ import com.ningdatech.pmapi.todocenter.bean.entity.ProgressNode;
import com.ningdatech.pmapi.todocenter.bean.vo.ProcessProgressDetailVo;
import com.ningdatech.pmapi.todocenter.constant.HisProInsEndActId;
import com.ningdatech.pmapi.todocenter.enums.IsAppendProjectEnum;
import com.ningdatech.pmapi.todocenter.enums.ProcessHandlerEnum;
import com.ningdatech.pmapi.todocenter.enums.ProcessStatusEnum;
import com.ningdatech.pmapi.todocenter.extension.cmd.BackToHisApprovalNodeCmd;
import com.ningdatech.pmapi.todocenter.extension.cmd.SaveCommentCmd;
import com.ningdatech.pmapi.todocenter.model.dto.req.ReqProcessHandlerDTO;
import com.ningdatech.pmapi.todocenter.model.dto.req.ReqToBeProcessedDTO;
import com.ningdatech.pmapi.todocenter.model.dto.res.ResHandledExportDTO;
import com.ningdatech.pmapi.todocenter.model.dto.res.ResMySubmittedExportDTO;
import com.ningdatech.pmapi.todocenter.model.dto.res.ResToBeProcessedDTO;
import com.ningdatech.pmapi.todocenter.model.dto.res.ResToBeExportDTO;
import com.ningdatech.pmapi.todocenter.model.dto.res.*;
import com.ningdatech.pmapi.todocenter.zwdd.model.MessageContent;
import com.ningdatech.pmapi.todocenter.zwdd.model.MessageText;
import com.ningdatech.pmapi.user.entity.UserInfo;
@@ -63,9 +59,9 @@ import com.wflow.workflow.bean.process.form.Form;
import com.wflow.workflow.bean.process.props.ApprovalProps;
import com.wflow.workflow.bean.vo.ProcessHandlerParamsVo;
import com.wflow.workflow.bean.vo.ProcessInstanceVo;
import com.wflow.workflow.bean.vo.ProcessProgressVo;
import com.wflow.workflow.bean.vo.ProcessTaskVo;
import com.wflow.workflow.config.WflowGlobalVarDef;
import com.wflow.workflow.enums.ProcessHandlerEnum;
import com.wflow.workflow.service.FormService;
import com.wflow.workflow.service.*;
import com.wflow.workflow.utils.Executor;
@@ -79,6 +75,7 @@ import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.engine.runtime.Execution;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskInfo;
@@ -86,6 +83,7 @@ import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.history.NativeHistoricTaskInstanceQuery;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.flowable.variable.api.history.NativeHistoricVariableInstanceQuery;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

@@ -233,7 +231,7 @@ public class TodoCenterManage {
.sheet(fileName)
.doWrite(collect);
} catch (IOException e) {
throw new RuntimeException(e);
throw new BizException("导出失败!");
}
}
/**
@@ -244,28 +242,32 @@ public class TodoCenterManage {
* @since 2023/02/01 17:43
*/
public void handler(ReqProcessHandlerDTO param) {
Long userId = LoginUserUtil.getUserId();

// 获取登录用户ID
// Long userId = LoginUserUtil.getUserId();

Long userId = 381496L;

Task task = taskService.createTaskQuery().taskId(param.getTaskId()).active().singleResult();
HashMap<String, Object> formData = new HashMap<>(32);
if (Objects.isNull(task)) {
throw new BizException("任务不存在");
}
if (hasComment(param.getAuditInfo())) {
taskService.addComment(param.getTaskId(), param.getInstanceId(), JSONObject.toJSONString(param.getAuditInfo()));
}
switch (param.getAction()) {
// 通过
case PASS:
formService.updateInstanceFormData(param.getInstanceId(), formData);
doPass(task, param);
doPass(task, userId, param);
break;
// 盖章并通过
case SEAL_PASS:
formService.updateInstanceFormData(param.getInstanceId(), formData);
doSealPass(task, param);
doSealPass(task, userId, param);
break;
// 驳回
case REJECT:
formService.updateInstanceFormData(param.getInstanceId(), formData);
doReject(task, param);
doReject(task, userId, param);
break;
// 退回
case BACK:
@@ -274,7 +276,7 @@ public class TodoCenterManage {
break;
// 撤回
case WITHDRAW:
doWithDrawProcess(task);
doWithDrawProcess(task,userId);
break;
default:
throw new IllegalStateException("Unexpected value: " + param.getAction());
@@ -283,16 +285,22 @@ public class TodoCenterManage {

/**
* 审批任务:驳回
*
* @param task 当前任务
* @param param 参数
* @param userId
* @param param 参数
*/
private void doReject(Task task, ReqProcessHandlerDTO param) {
private void doReject(Task task, Long userId, ReqProcessHandlerDTO param) {
// 获取当前申报项目
Project declaredProject = projectService.getOne(Wrappers.lambdaQuery(Project.class)
.eq(Project::getInstCode, task.getProcessInstanceId()));
String projectName = declaredProject.getProjectName();

Map<String, Object> var = new HashMap<>(16);
var.put("approve_" + task.getId(), param.getAction());
// TODO 中止流程并使项目进入对应状态,给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被驳回,请及时处理。
//获取流程定义
Process process = ProcessDefinitionUtil.getProcess(task.getProcessDefinitionId());
String projectName = getProjectName(task);
// 获取根节点即流程发起节点
FlowNode rootNode = (FlowNode) process.getFlowElement("root", true);
// TODO 中止流程并使项目进入对应状态,给项目创建人、流程发起人发送浙政钉工作通知:【项目名称】的【流程名称】被驳回,请及时处理。
@@ -350,68 +358,83 @@ public class TodoCenterManage {

/**
* 审批任务:盖章并通过
*
* @param task 当前任务
* @param param 参数
* @param userId
* @param param 参数
*/
private void doSealPass(Task task, ReqProcessHandlerDTO param) {
private void doSealPass(Task task, Long userId, ReqProcessHandlerDTO param) {
Map<String, Object> var = new HashMap<>(16);
var.put("approve_" + task.getId(), param.getAction());

// TODO 判断项目申报单位级别,区县单位申报有上级主管单位意见栏,市级单位没有

// TODO 市级单位:为大数据局;区县单位:为大数据中心(根据附件区分?)

// 获取当前申报项目
Project declaredProject = projectService.getOne(Wrappers.lambdaQuery(Project.class)
.eq(Project::getInstCode, task.getProcessInstanceId()));
// 更新项目状态到下一个状态
updatePassProjectStatus(task);
updatePassProjectStatus(task, userId, declaredProject);
taskService.complete(param.getTaskId(), var);
}

/**
* 审批任务:通过
*
* @param task 当前任务
* @param param 参数
* @param userId
* @param param 参数
*/
private void doPass(Task task, ReqProcessHandlerDTO param) {
private void doPass(Task task, Long userId, ReqProcessHandlerDTO param) {
String processInstanceId = task.getProcessInstanceId();
// 获取当前申报项目
Project declaredProject = projectService.getOne(Wrappers.lambdaQuery(Project.class)
.eq(Project::getInstCode, task.getProcessInstanceId()));
String projectName = declaredProject.getProjectName();

String projectName = getProjectName(task);
Map<String, Object> var = new HashMap<>(16);
var.put("approve_" + task.getId(), param.getAction());
//获取流程定义
Process process = ProcessDefinitionUtil.getProcess(task.getProcessDefinitionId());
// 获取当前节点
FlowNode currentNode = (FlowNode) process.getFlowElement(task.getTaskDefinitionKey(), true);
// 获取流程下一个节点浙政钉用户ID
String nextUserId = getNextUserId(currentNode);
// 保存审核意见
if (hasComment(param.getAuditInfo())) {
//执行自定义的保存评论的功能
managementService.executeCommand(new SaveCommentCmd(param.getTaskId(),param.getInstanceId(),String.valueOf(userId),JSONObject.toJSONString(param.getAuditInfo())));
}
updatePassProjectStatus(task,userId,declaredProject);
taskService.complete(param.getTaskId(), var);

// 获取bpm对象
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
//传节点定义key 获取当前节点
FlowNode currentNode = (FlowNode) bpmnModel.getFlowElement(task.getTaskDefinitionKey());

// 获取流程下一个节点的审核用户ID
String nextUserId = getNextUserId(currentNode,processInstanceId);
// 若有下一个审核人,向其发送浙政钉工作通知:标题:审核任务 内容:【单位名称】的【项目名称】需要您审核。
if (Objects.nonNull(nextUserId)){
UserInfo auditUserInfo = userInfoService.getById(Long.valueOf(nextUserId));
// TODO 向其发送浙政钉工作通知
// TODO 获取浙政钉用户dingKey,向其发送浙政钉工作通知
String msg = String.format(PASS_MSG_TEMPLATE,null,projectName);
sendWorkNotice(auditUserInfo,msg);
// sendWorkNotice(auditUserInfo,msg);
}else {
// 若没有,向发起人发送浙政钉工作通知:【项目名称】已通过【流程名称】,请及时开始下一步操作。
// TODO 向其发送浙政钉工作通知 获取根节点的孩子节点(即发起人节点),向其发送浙政钉工作通知
// 获取根节点即流程发起节点
FlowNode rootNode = (FlowNode) process.getFlowElement("root", true);
sendWorkNoticeToStartUser(task, projectName, rootNode);
FlowNode rootNode = (FlowNode) bpmnModel.getFlowElement("root");
// sendWorkNoticeToStartUser(task, projectName, rootNode);
}

updatePassProjectStatus(task);
taskService.complete(param.getTaskId(), var);
}

/**
* 当为通过操作时,更新项目表中项目状态
* @param task 当前任务
*
* @param task 当前任务
* @param userId
* @param declaredProject
* @return void
* @author CMM
* @since 2023/02/08 20:38
*/
private void updatePassProjectStatus(Task task) {
// 获取当前登录用户
Long userId = LoginUserUtil.getUserId();
// 获取当前申报项目
Project declaredProject = projectService.getOne(Wrappers.lambdaQuery(Project.class)
.eq(Project::getInstCode, task.getProcessInstanceId()));
private void updatePassProjectStatus(Task task, Long userId, Project declaredProject) {
// 获取当前流程项目状态
Integer projectStatusSecond = declaredProject.getProjectStatusSecond();
// 根据当前状态获取对应的通过事件
@@ -474,13 +497,15 @@ public class TodoCenterManage {
}

/**
* 获取当前节点的下一个节点的浙政钉用户ID
* @param currentNode 当前节点
* 获取当前节点的下一个节点的审核用户ID
*
* @param currentNode 当前节点
* @param processInstanceId
* @return java.lang.String 下一个节点的浙政钉用户ID
* @author CMM
* @since 2023/02/02 16:49
*/
private String getNextUserId(FlowNode currentNode) {
private String getNextUserId(FlowNode currentNode, String processInstanceId) {
String nextUserId = null;
// 输出连线
List<SequenceFlow> outgoingFlows = currentNode.getOutgoingFlows();
@@ -488,32 +513,25 @@ public class TodoCenterManage {
for (SequenceFlow currentOutgoingFlow : outgoingFlows) {
// 类型自己判断
FlowElement targetFlowElement = currentOutgoingFlow.getTargetFlowElement();
// 如果下个审批节点为结束节点,那么跳过该节点
if (targetFlowElement instanceof EndEvent){
continue;
}
// TODO 若要会签需判断候选人
// 用户任务
if (targetFlowElement instanceof UserTask) {
UserTask userTask = (UserTask) targetFlowElement;
nextUserId = userTask.getAssignee();
String actId = targetFlowElement.getId();
ActivityInstance activityInstance = runtimeService.createActivityInstanceQuery()
.processInstanceId(processInstanceId)
.activityId(actId).singleResult();
String executionId = activityInstance.getExecutionId();
nextUserId = runtimeService.getVariable(executionId, "assignee", String.class);
break;
}
}
return nextUserId;
}
/**
* 获取任务节点的申报项目名称
* @param task 当前任务
* @return java.lang.String 项目名称
* @author CMM
* @since 2023/02/01 17:27
*/
private String getProjectName(Task task) {
String nodeId = task.getTaskDefinitionKey();
String instanceId = task.getProcessInstanceId();
ProcessProgressVo instanceProgress = processService.getInstanceProgress(nodeId, instanceId);
Map<String, Object> formData = instanceProgress.getFormData();
String projectName = (String) formData.get(ProjectDeclareConstants.BasicInformation.PROJECT_NAME);
return projectName;
}
/**
* 判断处理操作是否含有审核意见
* @param comment 审核意见
* @return boolean
@@ -563,9 +581,10 @@ public class TodoCenterManage {
/**
* 撤销流程处理
*
* @param task 当前任务
* @param task 当前任务
* @param userId
*/
private void doWithDrawProcess(Task task) {
private void doWithDrawProcess(Task task, Long userId) {
//获取流程定义
Process process = ProcessDefinitionUtil.getProcess(task.getProcessDefinitionId());
// 获取当前运行流程的发起人节点信息
@@ -574,7 +593,6 @@ public class TodoCenterManage {
FlowNode currentNode = (FlowNode) process.getFlowElement(task.getTaskDefinitionKey(), true);
String rootUserId = getRootUserId(rootNode);
// 判断当前登录用户是否是流程发起人
Long userId = LoginUserUtil.getUserId();
if (rootUserId.equals(String.valueOf(userId))){
// TODO 若是流程发起人点击撤回,项目回到上一个状态,并删除当前审核人对应的待办记录
updateWithdrawProjectStatus(task, userId);
@@ -618,7 +636,7 @@ public class TodoCenterManage {

/**
* 当为撤回操作时,更新项目表中的项目状态为前一个状态
* @param task
* @param task 当前任务
* @param userId
* @return void
* @author CMM
@@ -652,8 +670,10 @@ public class TodoCenterManage {
* @param param 参数
*/
private void doBackTask(Task task, Long userId, ReqProcessHandlerDTO param) {
// 获取项目名称
String projectName = getProjectName(task);
// 获取当前申报项目
Project declaredProject = projectService.getOne(Wrappers.lambdaQuery(Project.class)
.eq(Project::getInstCode, task.getProcessInstanceId()));
String projectName = declaredProject.getProjectName();
//获取流程定义
Process process = ProcessDefinitionUtil.getProcess(task.getProcessDefinitionId());
// 获取根节点即流程发起节点
@@ -679,7 +699,7 @@ public class TodoCenterManage {
HistoricVariableInstance forms = historyService.createHistoricVariableInstanceQuery()
.processInstanceId(instanceId).variableName(WflowGlobalVarDef.WFLOW_FORMS).singleResult();
List<HistoricVariableInstance> formDatas = historyService.createHistoricVariableInstanceQuery()
.processInstanceId(instanceId).variableNameLike("field%").list();
.processInstanceId(instanceId).list();
// 取节点设置
HistoricVariableInstance nodeProps = historyService.createHistoricVariableInstanceQuery()
.processInstanceId(instanceId).variableName(WflowGlobalVarDef.WFLOW_NODE_PROPS).singleResult();
@@ -944,7 +964,7 @@ public class TodoCenterManage {
.sheet(fileName)
.doWrite(collect);
} catch (IOException e) {
throw new RuntimeException(e);
throw new BizException("导出失败!");
}
}

@@ -1087,8 +1107,87 @@ public class TodoCenterManage {
.sheet(fileName)
.doWrite(collect);
} catch (IOException e) {
throw new RuntimeException(e);
throw new BizException("导出失败!");
}

}

public PageVo<ResToBeProcessedDTO> queryCcMeProjectList(ReqToBeProcessedDTO param) {
// 获取当前登录用户ID
// Long userId = LoginUserUtil.getUserId();

Long userId = 381496L;
Page<Project> page = param.page();
Set<String> staterUsers = new HashSet<>();
List<WflowCcTasks> ccTasks = ccTasksMapper.selectList(Wrappers.lambdaQuery(WflowCcTasks.class)
.eq(WflowCcTasks::getUserId, String.valueOf(userId))
.orderByDesc(WflowCcTasks::getCreateTime));

LambdaQueryWrapper<Project> wrapper = Wrappers.lambdaQuery(Project.class);
wrapper.like(StrUtil.isNotBlank(param.getProjectName()),Project::getProjectName,param.getProjectName())
.like(StrUtil.isNotBlank(param.getBuildUnitName()),Project::getBuildUnitName,param.getBuildUnitName())
.eq(Objects.nonNull(param.getProjectYear()),Project::getProjectYear,param.getProjectYear())
.eq(Objects.nonNull(param.getIsSupplement()),Project::getIsTemporaryAugment,param.getIsSupplement())
.ge(Objects.nonNull(param.getProcessLaunchStartTime()),Project::getBeginTime,param.getProcessLaunchStartTime())
.le(Objects.nonNull(param.getProcessLaunchEndTime()),Project::getEndTime,param.getProcessLaunchEndTime());
projectService.page(page,wrapper);

// 将抄送我的流程实例一次性取出来,减少查询次数
Map<String, HistoricProcessInstance> instanceMap = CollectionUtil.isNotEmpty(ccTasks) ?
historyService.createHistoricProcessInstanceQuery().processInstanceIds(ccTasks.stream()
.map(WflowCcTasks::getInstanceId).collect(Collectors.toSet()))
.list().stream().collect(Collectors.toMap(HistoricProcessInstance::getId, v -> v)) : new HashMap<>();
List<String> processInsIds = ccTasks.stream().map(WflowCcTasks::getInstanceId).collect(Collectors.toList());
List<ResToBeProcessedDTO> resVos = page.getRecords().stream().filter(d -> processInsIds.contains(d.getInstCode())).map(d -> {
ResToBeProcessedDTO res = new ResToBeProcessedDTO();
BeanUtils.copyProperties(d, res);
res.setProcessStatusName(ProcessStatusEnum.getDescByCode(d.getProcessStatus()));
LocalDateTime processLaunchTime = d.getCreateOn();
String launchTimeFormat = NdDateUtils.format(processLaunchTime, "yyyy-MM-dd HH:mm");
LocalDateTime launchTime = LocalDateTime.parse(launchTimeFormat, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
res.setProcessLaunchTime(launchTime);
HistoricProcessInstance ist = instanceMap.get(d.getInstCode());
staterUsers.add(ist.getStartUserId());
ProcessInstanceVo processInstanceVo = getProcessInstanceVos(ist);
res.setProcessInstanceInfo(processInstanceVo);
return res;
}).collect(Collectors.toList());

if (CollectionUtil.isNotEmpty(staterUsers)) {
Map<String, OrgUser> userMap = userDeptOrLeaderService.getUserMapByIds(staterUsers);
resVos.stream().map(v -> {
v.getProcessInstanceInfo().setStaterUser(userMap.get(v.getProcessInstanceInfo().getStaterUserId()));
return v;
}).collect(Collectors.toList());
}

//if (CollectionUtil.isNotEmpty(staterUsers)) {
// Map<Long, UserInfo> userMap = userInfoService.getUserMapByIds(staterUsers);
// resVos.stream().peek(v -> v.setOwner(userMap.get(startUserId)))
// .collect(Collectors.toList());
//}
return PageVo.of(resVos,resVos.size());
}

public void exportCcMeProjectList(HttpServletResponse response, ReqToBeProcessedDTO param) {
PageVo<ResToBeProcessedDTO> page = queryCcMeProjectList(param);
List<ResToBeProcessedDTO> collect = (List<ResToBeProcessedDTO>) page.getRecords();
String fileName = null;
if (IsAppendProjectEnum.APPEND_PROJECT.getCode().equals(param.getIsSupplement())){
fileName = "待办中心_抄送我的_增补项目列表";
}else if (IsAppendProjectEnum.NOT_APPEND_PROJECT.getCode().equals(param.getIsSupplement())){
fileName = "待办中心_抄送我的_非增补项目列表";
}
ExcelDownUtil.setFileName(fileName,response);
//数据导出处理函数
try {
EasyExcel.write(response.getOutputStream(), ResCcMeExportDTO.class)
.autoCloseStream(false)
.registerWriteHandler(ExcelExportStyle.formalStyle())
.sheet(fileName)
.doWrite(collect);
} catch (IOException e) {
throw new BizException("导出失败!");
}
}
}

+ 2
- 42
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/model/dto/req/ReqProcessHandlerDTO.java 파일 보기

@@ -1,11 +1,10 @@
package com.ningdatech.pmapi.todocenter.model.dto.req;
import com.ningdatech.pmapi.common.model.FileBasicInfo;
import com.ningdatech.pmapi.todocenter.bean.entity.ProcessComment;
import com.ningdatech.pmapi.todocenter.enums.ProcessHandlerEnum;
import com.wflow.workflow.enums.ProcessHandlerEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;

/**
* 流程处理操作参数实体
@@ -47,43 +46,4 @@ public class ReqProcessHandlerDTO {
* 审核信息
*/
private ProcessComment auditInfo;
///**
// * 审核通过意见
// */
//private String auditPassOpinion;
//
///**
// * 审核通过附件
// */
//private FileBasicInfo auditPassAppendix;
///**
// * 盖章通过意见
// */
//private String sealPassOpinion;
//
///**
// * 盖章通过附件
// */
//private FileBasicInfo sealPassAppendix;
///**
// * 审核退回意见
// */
//private String auditBackOpinion;
///**
// * 审核退回附件
// */
//private FileBasicInfo auditBackAppendix;
///**
// * 审核驳回意见
// */
//private String auditRejectOpinion;
//
///**
// * 审核驳回附件
// */
//private FileBasicInfo auditRejectAppendix;
//public enum Action{
// //通过、盖章并通过、退回、撤回、驳回
// pass, seal_pass ,back, withdraw, reject;
//}
}

+ 41
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/model/dto/res/ResCcMeExportDTO.java 파일 보기

@@ -0,0 +1,41 @@
package com.ningdatech.pmapi.todocenter.model.dto.res;

import java.io.Serializable;
import java.time.LocalDateTime;

import com.alibaba.excel.annotation.ExcelProperty;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
* 待办中心抄送我的项目列表导出实体
*
* @author CMM
* @since 2023/01/19 16:42
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ResCcMeExportDTO implements Serializable {
private static final long serialVersionUID = 1L;

@ExcelProperty("项目名称")
private String projectName;

@ExcelProperty("申报单位")
private String reportUnitName;

@ExcelProperty("申报金额")
private Integer reportAmount;

@ExcelProperty("预算年度")
private Integer budgetYear;

@ExcelProperty("流程状态")
private String processStatusName;

@ExcelProperty("发起时间")
private LocalDateTime processLaunchTime;
}

+ 3
- 6
pmapi/src/main/resources/application-dev.yml 파일 보기

@@ -158,12 +158,9 @@ sa-token:
#专有钉钉
ding:
#扫码
app-auth-key: file-manage_dingoa-zte2LbiAfIj
app-auth-secret: H794aFZf271QbfUr50pbBpBTlXSrWIP71q9RTR34
#扫码
app-sso-auth-key: fgdn_wjlzjkxt_hz
app-sso-auth-secret: dafe1e6f7d424032acb81f5c2a797a1f
#免登/获取信息
app-auth-key: expert-base_dingoa-c5nnefYVnie
app-auth-secret: nm8qtST8uK431HYrjr7srcE23sT4889QgMcYFM3L
# #免登/获取信息
app-key: file-manage-4Mjx9358wuxjyYFjY3
app-secret: hE41938wqyQ5LOpc1QDRA9e7gb5YugoClWD3nY4O
#专有钉钉在开发管理工作台,右键查看网页源码realmId: '31141',浙政钉固定196729


+ 20
- 0
pmapi/src/main/resources/integration/zwdd-dev.yml 파일 보기

@@ -0,0 +1,20 @@
#专有钉钉
integration:
zzd:
#扫码
app-auth-key: expert-base_dingoa-c5nnefYVnie
app-auth-secret: nm8qtST8uK431HYrjr7srcE23sT4889QgMcYFM3L
# #免登/获取信息
# app-key: file-manage-4Mjx9358wuxjyYFjY3
# app-secret: hE41938wqyQ5LOpc1QDRA9e7gb5YugoClWD3nY4O
app-key: ls_rebuild-10c8n5X0707yFV7jURr
app-secret: gN8J3WazyXLMWKDuFmx6C4yaH5lFUY41x8rYLLo6
#专有钉钉在开发管理工作台,右键查看网页源码realmId: '31141',浙政钉固定196729
tenantId: 31141
domain: openplatform.dg-work.cn

# integration.zzd.enabled=true
# #扫码
# integration.zzd.app-auth-key=file-manage_dingoa-zte2LbiAfIj
# integration.zzd.app-auth-secret=H794aFZf271QbfUr50pbBpBTlXSrWIP71q9RTR34
# integration.zzd.domain=openplatform.dg-work.cn

+ 11
- 0
pmapi/src/main/resources/integration/zwdd-prod.yml 파일 보기

@@ -0,0 +1,11 @@
#专有钉钉
ding:
#扫码
app-auth-key: expert-base_dingoa-c5nnefYVnie
app-auth-secret: nm8qtST8uK431HYrjr7srcE23sT4889QgMcYFM3L
# #免登/获取信息
app-key: file-manage-4Mjx9358wuxjyYFjY3
app-secret: hE41938wqyQ5LOpc1QDRA9e7gb5YugoClWD3nY4O
#专有钉钉在开发管理工作台,右键查看网页源码realmId: '31141',浙政钉固定196729
tenantId: 31141
domain: openplatform.dg-work.cn

+ 31
- 0
pmapi/src/test/java/com/ningdatech/pmapi/organization/OrganizationTest.java 파일 보기

@@ -0,0 +1,31 @@
package com.ningdatech.pmapi.organization;

import com.ningdatech.pmapi.AppTests;
import com.ningdatech.pmapi.ding.task.OrganizationBatchGetTask;
import com.ningdatech.zwdd.client.ZwddAuthClient;
import com.ningdatech.zwdd.client.ZwddClient;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

/**
* @author liuxinxin
* @date 2023/2/9 下午3:54
*/

class OrganizationTest extends AppTests {

@Autowired
private ZwddClient zwddClient;

@Autowired
private ZwddAuthClient zwddAuthClient;

@Autowired
private OrganizationBatchGetTask organizationBatchGetTask;

@Test
public void testBatchGetOrganization() {
organizationBatchGetTask.batchGetOrganizationTask();
}

}

+ 168
- 0
pmapi/src/test/resources/application-dev.yml 파일 보기

@@ -0,0 +1,168 @@
server:
port: 28888
servlet:
context-path: /pm

spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
session:
store-type: redis
redis:
namespace: "spring:session"
redis:
timeout: 5000
host: 47.98.125.47
port: 26379
database: 0
password: Ndkj1234
jedis:
pool:
max-active: 200
max-idle: 500
min-idle: 8
max-wait: 10000
application:
name: pm
jackson:
default-property-inclusion: non_null
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
jpa:
properties:
hibernate:
default_schema: PUBLIC
hbm2ddl:
auto: update
show_sql: true
show-sql: true
hibernate:
ddl-auto: update
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.kingbase8.Driver
# 数据源
druid:
url: jdbc:kingbase8://120.26.44.207:54321/nd_project_management?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
username: SYSTEM
password: Ndkj1234
# 初始连接数
initialSize: 5
# 最小连接池数量
minIdle: 10
# 最大连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
#mysql使用:SELECT 1 FROM DUAL
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: admin
login-password: admin
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
logic-delete-value: true
logic-not-delete-value: false
logging:
config: classpath:logback-spring.xml
#日志配置
level:
root: info
file:
path: logs
nd:
log:
enabled: true
type: DB
# 日志文件配置
log:
path: ./logs
info:
file-size: 50MB
max-size: 5
total-size: 200MB
error:
file-size: 10MB
max-size: 5
total-size: 50MB

swagger:
enabled: true

flowable:
async-executor-activate: true
#关闭一些不需要的功能服务
rest-api-enabled: false
idm:
enabled: false
common:
enabled: false
dmn:
enabled: false
form:
enabled: false
app:
enabled: false

wflow:
file:
max-size: 20 #最大文件上传大小,MB

sa-token:
# token 名称 (同时也是cookie名称)
token-name: wflowToken
# token 有效期,单位s 默认30天, -1代表永不过期
timeout: 172800
# token 临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
activity-timeout: -1
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# token风格
token-style: uuid
# 是否输出操作日志
is-log: false

#专有钉钉
ding:
#扫码
app-auth-key: expert-base_dingoa-c5nnefYVnie
app-auth-secret: nm8qtST8uK431HYrjr7srcE23sT4889QgMcYFM3L
# #免登/获取信息
app-key: file-manage-4Mjx9358wuxjyYFjY3
app-secret: hE41938wqyQ5LOpc1QDRA9e7gb5YugoClWD3nY4O
#专有钉钉在开发管理工作台,右键查看网页源码realmId: '31141',浙政钉固定196729
tenantId: 31141
domain: openplatform.dg-work.cn

+ 0
- 0
pmapi/src/test/resources/application-prod.yml 파일 보기


+ 3
- 0
pmapi/src/test/resources/application.yml 파일 보기

@@ -0,0 +1,3 @@
spring:
profiles:
active: dev

+ 14
- 0
pmapi/src/test/resources/integration/zwdd-dev.yml 파일 보기

@@ -0,0 +1,14 @@
#专有钉钉
integration:
zwdd:
#扫码
app-auth-key: expert-base_dingoa-c5nnefYVnie
app-auth-secret: nm8qtST8uK431HYrjr7srcE23sT4889QgMcYFM3L
# #免登/获取信息
# app-key: file-manage-4Mjx9358wuxjyYFjY3
# app-secret: hE41938wqyQ5LOpc1QDRA9e7gb5YugoClWD3nY4O
app-key: ls_rebuild-10c8n5X0707yFV7jURr
app-secret: gN8J3WazyXLMWKDuFmx6C4yaH5lFUY41x8rYLLo6
#专有钉钉在开发管理工作台,右键查看网页源码realmId: '31141',浙政钉固定196729
tenantId: 31141
domain: openplatform.dg-work.cn

+ 11
- 0
pmapi/src/test/resources/integration/zwdd-prod.yml 파일 보기

@@ -0,0 +1,11 @@
#专有钉钉
ding:
#扫码
app-auth-key: expert-base_dingoa-c5nnefYVnie
app-auth-secret: nm8qtST8uK431HYrjr7srcE23sT4889QgMcYFM3L
# #免登/获取信息
app-key: file-manage-4Mjx9358wuxjyYFjY3
app-secret: hE41938wqyQ5LOpc1QDRA9e7gb5YugoClWD3nY4O
#专有钉钉在开发管理工作台,右键查看网页源码realmId: '31141',浙政钉固定196729
tenantId: 31141
domain: openplatform.dg-work.cn

+ 68
- 0
pmapi/src/test/resources/logback-spring.xml 파일 보기

@@ -0,0 +1,68 @@
<configuration scan="true" scanPeriod="10 seconds">
<springProperty name="logPath" scope="context" source="log.path" defaultValue="./logs"/>
<springProperty name="infoFileSize" scope="context" source="log.info.file-size"/>
<springProperty name="infoMaxSize" scope="context" source="log.info.max-size"/>
<springProperty name="infoTotalSize" scope="context" source="log.info.total-size"/>
<springProperty name="errorFileSize" scope="context" source="log.error.file-size"/>
<springProperty name="errorMaxSize" scope="context" source="log.error.max-size"/>
<springProperty name="errorTotalSize" scope="context" source="log.error.total-size"/>

<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${logPath}/info.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logPath}/info-%d{yyyyMMdd}-%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${infoFileSize}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>${infoMaxSize}</maxHistory>
<totalSizeCap>${infoTotalSize}</totalSizeCap>
</rollingPolicy>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n
</Pattern>
</layout>
<charset>UTF-8</charset>
</encoder>
</appender>

<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<File>${logPath}/error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logPath}/error-%d{yyyyMMdd}-%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${errorFileSize}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>${errorMaxSize}</maxHistory>
<totalSizeCap>${errorTotalSize}</totalSizeCap>
</rollingPolicy>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n
</Pattern>
</layout>
<charset>UTF-8</charset>
</encoder>
</appender>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n
</pattern>
<charset>UTF-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>

<root level="INFO">
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
<appender-ref ref="STDOUT"/>
</root>
</configuration>

+ 52
- 0
pmapi/src/test/resources/security/auth-dev.yml 파일 보기

@@ -0,0 +1,52 @@
security:
auth:
auth-require-url: /api/v1/user/auth/auth-require
invalid-session-url: /api/v1/user/auth/invalid-session
password-login-url: /api/v1/user/auth/login/password
logout-url: /api/v1/user/auth/logout
ignore-auth-urls:
- /v2/api-docs
- /swagger-ui.html
- /webjars/**
- /swagger-resources/**
- /webjars/
- /api/v1/user/auth/register
- /api/v1/user/auth/auth-require
- /api/v1/user/auth/invalid-session
- /api/v1/user/auth/login/password
- /api/v1/user/auth/forget-password
- /api/v1/**
- /doc.html
- /ok.html
- /open/api/**
- /oa/**
- /wflow/**
- /sys/**
ignore-csrf-urls:
- /api/v1/user/auth/**
- /v2/api-docs
- /swagger-ui.html
- /webjars/**
- /swagger-resources/**
- /webjars/
- /doc.html
- /ok.html
- /api/v1/**
- /file/**
- /optLog/**
- /dict/**
- /oa/**
- /wflow/**
- /sys/**
role-map:
"engineer":
"project_manager":
- /api/v1/user-info/kick-off/**
"enterprise_admin":
"regional_general_manager":
"driver":
"super_admin":
- /api/v1/user-info/save
- /api/v1/user-info/del
- /api/v1/user-info/kick-off/**
- /api/v1/user-info/password/mod

+ 41
- 0
pmapi/src/test/resources/security/auth-prod.yml 파일 보기

@@ -0,0 +1,41 @@
security:
auth:
auth-require-url: /api/v1/user/auth/auth-require
invalid-session-url: /api/v1/user/auth/invalid-session
password-login-url: /api/v1/user/auth/login/password
logout-url: /api/v1/user/auth/logout
ignore-auth-urls:
- /v2/api-docs
- /swagger-ui.html
- /webjars/**
- /swagger-resources/**
- /webjars/
- /api/v1/user/auth/register
- /api/v1/user/auth/login/password
- /api/v1/user/auth/forget-password
- /doc.html
- /ok.html
ignore-csrf-urls:
- /api/v1/user/auth/**
- /v2/api-docs
- /swagger-ui.html
- /webjars/**
- /swagger-resources/**
- /webjars/
- /doc.html
- /ok.html
- /api/v1/**
- /file/**
- /optLog/**
- /dict/**
role-map:
"engineer":
"project_manager":
"enterprise_admin":
"regional_general_manager":
"driver":
"super_admin":
- /api/v1/user-info/save
- /api/v1/user-info/del
- /api/v1/user-info/kick-off/**
- /api/v1/user-info/password/mod

불러오는 중...
취소
저장