Merge remote-tracking branch 'origin/feature/REQ-3581' into feature/REQ-3581

This commit is contained in:
yanglin 2025-02-18 15:20:36 +08:00
commit 83ea8da3c5
38 changed files with 1105 additions and 203 deletions

View File

@ -4,6 +4,7 @@ import cn.axzo.framework.domain.web.result.ApiPageResult;
import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.nanopart.visa.api.request.ChangeRecordButtonOperationReq;
import cn.axzo.nanopart.visa.api.request.ChangeStatusRequest;
import cn.axzo.nanopart.visa.api.request.CheckVisaWithVisaIdReq;
import cn.axzo.nanopart.visa.api.request.FetchVisaAllConfirmReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeApproveCreateReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeApproveOnlyReq;
@ -147,4 +148,10 @@ public interface ChangeRecordApi {
*/
@PostMapping("/api/visa/change/delete")
ApiResult<Void> deleteChangeRecord(@Validated @RequestBody ChangeRecordButtonOperationReq req);
/**
* 校验
*/
@PostMapping("/api/visa/change/checkVisaWithVisaId")
ApiResult<Void> checkVisaWithVisaId(@Validated @RequestBody CheckVisaWithVisaIdReq req);
}

View File

@ -16,7 +16,8 @@ public interface VisaConstant {
/**
* 用于发送待办的变量名
*/
String WORKFLOW_PENDING_TOPIC = "theme";
String WORKFLOW_PENDING_TOPIC = "topic";
String WORKFLOW_PENDING_INITIATOR_NAME = "initiatorName";
String MSG_CENTER_APP_CODE = "nanopart-visa";
/**
* IM 群的扩展信息变洽签 ID
@ -45,8 +46,14 @@ public interface VisaConstant {
String FORM_FIELD_REASON = "reason";
// 发生区域
String FORM_FIELD_RELATION_AREA = "relationArea";
// 发生内容
// 发生内容及说明
String FORM_FIELD_CONTEXT_DESCRIPTION = "contextDescription";
String FORM_FIELD_CONTEXT = "context";
String FORM_FIELD_DESCRIPTION = "description";
// 相关单位和人员
String FORM_FIELD_UNIT_PERSON = "unitPerson";
String FORM_FIELD_UNIT = "unit";
String FORM_FIELD_PERSON = "person";
// 变更金额
String FORM_FIELD_AMOUNT_CHANGE = "amountChange";
// 关联的任务单单据

View File

@ -3,8 +3,6 @@ package cn.axzo.nanopart.visa.api.enums;
import cn.axzo.framework.rocketmq.Event;
import lombok.Getter;
import java.util.Arrays;
/**
* @Author zr
* @Date 2024/3/19 18:01
@ -30,7 +28,4 @@ public enum MQEventEnum {
this.desc = desc;
}
public static MQEventEnum getByName(String name){
return Arrays.stream(MQEventEnum.values()).filter(item -> item.name().equals(name)).findFirst().orElse(null);
}
}

View File

@ -28,6 +28,7 @@ public enum VisaButtonTypeEnum {
EXECUTE("execute", "发起执行"),
REDECISION("redecision", "重新发起"),
TO_APPROVE("to_approve", "提交审批"),
AGAIN_TO_APPROVE("again_to_approve", "重新提交审批"),
AGREE("agree", "同意"),
REJECT("reject", "拒绝"),
UPLOAD_FILE("upload_file", "上传附件"),
@ -35,6 +36,7 @@ public enum VisaButtonTypeEnum {
APPROVAL_RECORD("approval_record", "查看审批记录"),
TO_HANDLE("to_handle", "去处理"),
PRINT("print", "打印"),
DETAIL("detail", "详情"),
;
@ -42,10 +44,11 @@ public enum VisaButtonTypeEnum {
private String desc;
//分页列表页Map,key:角色+单据状态value功能权限的按钮列表
private static Map<String, Set<VisaButtonTypeEnum>> bizTypeBtnMap = Maps.newHashMap();
static {
// 发起人不同状态按钮权限
// 发起人不同状态按钮权限-详情页
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.TO_REPORT.name(), Sets.newHashSet(UPDATE, DELETE));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.REPORT_FROM_APPROVE.name(), Sets.newHashSet(UPDATE, FORBID));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.DECIDING.name(), Sets.newHashSet(UPDATE, EXECUTE, TO_APPROVE, FORBID, CHAT_GROUP_RECORD,PRINT));
@ -55,7 +58,7 @@ public enum VisaButtonTypeEnum {
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.COMPLETED.name(), Sets.newHashSet(UPLOAD_FILE, CHAT_GROUP_RECORD, APPROVAL_RECORD,PRINT));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.FORBIDED.name(), Sets.newHashSet(CHAT_GROUP_RECORD, APPROVAL_RECORD));
// 决策人不同状态按钮权限
// 决策人不同状态按钮权限-详情页
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.DECIDING.name(), Sets.newHashSet(UPDATE, CHAT_GROUP_RECORD,PRINT));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.DECIDING_FROM_APPROVE.name(), Sets.newHashSet(UPDATE, CHAT_GROUP_RECORD,PRINT));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.EXECUTING.name(), Sets.newHashSet(UPDATE, CHAT_GROUP_RECORD,PRINT));
@ -63,10 +66,10 @@ public enum VisaButtonTypeEnum {
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.COMPLETED.name(), Sets.newHashSet(UPLOAD_FILE, CHAT_GROUP_RECORD, APPROVAL_RECORD,PRINT));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.FORBIDED.name(), Sets.newHashSet(CHAT_GROUP_RECORD, APPROVAL_RECORD));
//审核人不同状态按钮权限
//审核人不同状态按钮权限-详情页
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.APPROVE.name() + VisaStatusEnum.APPROVING.name(), Sets.newHashSet(TO_HANDLE, CHAT_GROUP_RECORD,PRINT));
//其他不同状态按钮权限
//其他不同状态按钮权限-详情页
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.DECIDING.name(), Sets.newHashSet(PRINT, CHAT_GROUP_RECORD));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.DECIDING_FROM_APPROVE.name(), Sets.newHashSet(PRINT, CHAT_GROUP_RECORD));
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.EXECUTING.name(), Sets.newHashSet(PRINT, CHAT_GROUP_RECORD));
@ -75,6 +78,44 @@ public enum VisaButtonTypeEnum {
bizTypeBtnMap.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.FORBIDED.name(), Sets.newHashSet(CHAT_GROUP_RECORD, APPROVAL_RECORD));
//[打印]按钮是通过OMS统一配置故此处不处理
}
//分页列表页Map,key:角色+单据状态value功能权限的按钮列表
private static Map<String, Set<VisaButtonTypeEnum>> bizTypeBtnMapWhenPage = Maps.newHashMap();
static {
// 发起人不同状态按钮权限-分页列表页
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.TO_REPORT.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.REPORT_FROM_APPROVE.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.DECIDING.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.DECIDING_FROM_APPROVE.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.EXECUTING.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.APPROVING.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.COMPLETED.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CREATE.name() + VisaStatusEnum.FORBIDED.name(), Sets.newHashSet(DETAIL));
// 确认人不同状态按钮权限-分页列表页
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.TO_REPORT.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.REPORT_FROM_APPROVE.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.DECIDING.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.DECIDING_FROM_APPROVE.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.EXECUTING.name(), Sets.newHashSet(DETAIL, UPDATE));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.APPROVING.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.COMPLETED.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.CONFIRM.name() + VisaStatusEnum.FORBIDED.name(), Sets.newHashSet(DETAIL));
// 其他人不同状态按钮权限-分页列表页
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.TO_REPORT.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.REPORT_FROM_APPROVE.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.DECIDING.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.DECIDING_FROM_APPROVE.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.EXECUTING.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.APPROVING.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.COMPLETED.name(), Sets.newHashSet(DETAIL));
bizTypeBtnMapWhenPage.put(VisaConfirmBizTypeEnum.OTHER.name() + VisaStatusEnum.FORBIDED.name(), Sets.newHashSet(DETAIL));
}
/**
@ -117,6 +158,32 @@ public enum VisaButtonTypeEnum {
}
}
/**
* 根据角色与单据状态获取按钮权限
*/
public static Set<VisaButtonTypeEnum> fetchBtnsByBizTypeAndStatusWhenPage(Set<VisaConfirmBizTypeEnum> bizTypeSet, VisaStatusEnum status) {
if (Objects.isNull(bizTypeSet) || Objects.isNull(status)) {
return Sets.newHashSet();
}
Set<VisaButtonTypeEnum> returnBtnSet = Sets.newHashSet();
bizTypeSet.stream().filter(Objects::nonNull).forEach(item -> {
switch (item) {
case CREATE:
case CONFIRM:
case OTHER:
case APPROVE:
Set<VisaButtonTypeEnum> buttonTypeEnumSet = bizTypeBtnMapWhenPage.get(item.name() + status.name());
returnBtnSet.addAll(CollectionUtils.isNotEmpty(buttonTypeEnumSet) ? buttonTypeEnumSet : Sets.newHashSet());
break;
default:
throw new ServiceException("单据确认业务类型不匹配");
}
});
return returnBtnSet;
}
public static Set<VisaButtonTypeEnum> all() {
return Sets.newHashSet(VisaButtonTypeEnum.values());
}

View File

@ -20,7 +20,8 @@ public enum VisaRelationFieldEnum {
RECTIFICATION_ORDER("rectification_order", "整改单"),
VISA_ORDER("visa_order", "变洽签变更单"),
ATTACHMENT("attachment", "附件"),
PROCESS_INSTANCE("process_instance", "审批实例"),
PROCESS_INSTANCE_OF_VISA("process_instance_of_visa", "变洽签审批实例"),
PROCESS_INSTANCE_OF_ESS("process_instance_of_ess", "用印审批实例"),
ORDER("order", "单据"),
IM_GROUP_PARTICIPATE("im_group_participate", "im群聊参与人"),
;

View File

@ -0,0 +1,50 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.nanopart.visa.api.response.VisaDetailByIdResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.apache.commons.collections4.CollectionUtils;
import javax.validation.constraints.NotNull;
/**
* @author xudawei@axzo.cn
* @version 1.0
* @date 2025/1/16 11:53
*/
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class CheckVisaWithVisaIdReq {
/**
* 变更单号Id
*/
@NotNull(message = "变更签证单据Id不能为空")
private Long visaId;
/**
* 校验
*/
public void check(VisaDetailByIdResponse response) {
AssertUtil.notNull(response.getRelationWorkspaceId(), "关联项目不能为空");
AssertUtil.notNull(response.getType(), "单据类型不能为空");
AssertUtil.notEmpty(response.getNo(), "单号不能为空");
AssertUtil.notEmpty(response.getTopic(), "主题不能为空");
AssertUtil.notNull(response.getRelationProject(), "关联工程不能为空");
AssertUtil.notEmpty(response.getHappenTime(), "提出时间不能为空");
AssertUtil.notEmpty(response.getReason(), "发生原因不能为空");
AssertUtil.notEmpty(response.getRelationProfessionalList(), "专业不能为空");
if (CollectionUtils.isNotEmpty(response.getRelationOuAndPersonList())) {
response.getRelationOuAndPersonList().forEach(item -> {
AssertUtil.notEmpty(item.getRelationPersonList(), "专业不能为空");
});
}
}
}

View File

@ -33,6 +33,9 @@ public class VisaChangeApproveCreateReq extends VisaChangeTempCreateReq {
*/
private List<ApprovePersonInfo> approvePersonInfoList;
// 是否调整单号唯一性校验
private transient boolean skipNoOnlyOnce = false;
@Data
@Builder
@NoArgsConstructor

View File

@ -1,7 +1,7 @@
package cn.axzo.nanopart.visa.api.request;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -68,8 +68,11 @@ public class VisaChangePageSearchReq {
/**
* 变更金额区间
* <p>
* 0最小值 1最大值
* 当最小最大值均为正值表示增加均为负值表示减少
* 元素均为0表示金额不变
* </p>
*/
private List<BigDecimal> amountChange;
@ -111,4 +114,28 @@ public class VisaChangePageSearchReq {
*/
private Boolean needRelatedBill = false;
/**
* 调用场景
* <p>
* PAGE: 分页列表页面调用
* SELECT: 选择器页面调用
* </p>
*/
private FromEnum from;
public static enum FromEnum {
PAGE("分页列表页面调用"),
SELECT("选择器页面调用");
private final String desc;
FromEnum(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
}
}

View File

@ -138,7 +138,7 @@ public class VisaChangeTempCreateReq {
*
* @see VisaBillTypeEnum
*/
private Map<String, List<Long>> relationOrderMap;
private Map<String, List<OrderSimpleModel>> relationOrderMap;
/**
* 附件json列表
@ -157,11 +157,33 @@ public class VisaChangeTempCreateReq {
private Integer operatorOuType;
private Long operatorNodeId;
/**
* 操作人peronId
*/
private Long operatorPersonId;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class OrderSimpleModel {
/**
* 单据主键 ID
*/
private Long id;
/**
* 单据编号
*/
private String no;
/**
* 单据名称
*/
private String name;
}
@Data
@Builder
@ -222,6 +244,11 @@ public class VisaChangeTempCreateReq {
*/
private Long annotationId;
/**
* 图纸图框id{@code type}为2时使用
*/
private Long borderId;
/**
* 内容说明
*/

View File

@ -1,6 +1,7 @@
package cn.axzo.nanopart.visa.api.response;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -28,4 +29,8 @@ public class ImGroupTipsResp {
private List<ImGroupButton> buttonList;
private VisaTypeEnum visaType;
private String visaTypeText;
}

View File

@ -1,5 +1,6 @@
package cn.axzo.nanopart.visa.api.response;
import cn.axzo.nanopart.visa.api.enums.VisaButtonTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import lombok.AllArgsConstructor;
@ -10,6 +11,7 @@ import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;
import java.util.Set;
/**
* @author chenwenjian
@ -117,6 +119,19 @@ public class VisaChangePageSearchResp {
*/
private Boolean isRelated;
/**
* 操作按钮
* <p>
* UPDATE: 编辑
* DETAIL: 详情
* UPLOAD_FILE: 上传附件
* APPROVE_RECORD: 查看审批记录
* </p>
*
* @see VisaButtonTypeEnum
*/
private Set<VisaButtonTypeEnum> operateBtnSet;
public String getTypeDesc() {
if (Objects.isNull(type)) {
return null;
@ -128,6 +143,12 @@ public class VisaChangePageSearchResp {
if (Objects.isNull(status)) {
return null;
}
if (VisaStatusEnum.REPORT_FROM_APPROVE.equals(status)) {
return VisaStatusEnum.TO_REPORT.getDesc();
}
if (VisaStatusEnum.DECIDING_FROM_APPROVE.equals(status)) {
return VisaStatusEnum.DECIDING.getDesc();
}
return status.getDesc();
}

View File

@ -241,6 +241,10 @@ public class VisaDetailByIdResponse {
* 单位名称
*/
private String ouName;
/**
* 节点Id
*/
private Long nodeId;
}
@Data
@ -263,6 +267,11 @@ public class VisaDetailByIdResponse {
*/
private String realName;
/**
* 头像
*/
private String avatarUrl;
/**
* 确认人personId
*/
@ -277,6 +286,15 @@ public class VisaDetailByIdResponse {
* 工程Id
*/
private Long projectId;
/**
* 岗位Id
*/
private Long jobId;
/**
* 岗位名称
*/
private String jobName;
}
@ -339,7 +357,12 @@ public class VisaDetailByIdResponse {
if (CollectionUtils.isEmpty(professionalList)) {
return Lists.newArrayList();
}
return professionalList;
List<RelationProfessionalDetail> filter = professionalList.stream().filter(item -> Objects.nonNull(item) && StringUtils.isNotBlank(item.getCode())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(filter)) {
return Lists.newArrayList();
}
return filter;
}
/**
@ -378,7 +401,7 @@ public class VisaDetailByIdResponse {
/**
* id
*/
private Long id;
private Long areaId;
public static List<VisaDetailByIdResponse.RelationAreaDetail> buildAreaWithObject(JSONArray relationArea) {
@ -389,7 +412,11 @@ public class VisaDetailByIdResponse {
if (CollectionUtils.isEmpty(relationAreaList)) {
return Lists.newArrayList();
}
return relationAreaList;
List<RelationAreaDetail> filter = relationAreaList.stream().filter(item -> Objects.nonNull(item) && Objects.nonNull(item.getAreaId())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(filter)) {
return Lists.newArrayList();
}
return filter;
}
public static List<Long> buildAreaWithId(JSONArray relationArea) {
@ -398,7 +425,7 @@ public class VisaDetailByIdResponse {
if (CollectionUtils.isEmpty(areaDetailList)) {
return Lists.newArrayList();
}
return areaDetailList.stream().map(VisaDetailByIdResponse.RelationAreaDetail::getId).collect(Collectors.toList());
return areaDetailList.stream().map(VisaDetailByIdResponse.RelationAreaDetail::getAreaId).collect(Collectors.toList());
}
}

View File

@ -114,5 +114,19 @@
<artifactId>karma-api</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.axzo.platform</groupId>
<artifactId>axzo-log-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.axzo.digital</groupId>
<artifactId>digital-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -44,4 +44,10 @@ public class RefreshableConfiguration {
*/
@Value("${visa.verifyVisaLimit: 5}")
private Integer verifyVisaLimit;
/**
* 发生内容及说明数量限制
*/
@Value("${visa.verifyChangeContextLimit: 50}")
private Integer verifyChangeContextLimit;
}

View File

@ -5,8 +5,10 @@ import cn.axzo.framework.domain.web.result.ApiResult;
import cn.axzo.framework.domain.web.result.PageData;
import cn.axzo.nanopart.visa.api.changerecord.ChangeRecordApi;
import cn.axzo.nanopart.visa.api.enums.VisaButtonTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.request.ChangeRecordButtonOperationReq;
import cn.axzo.nanopart.visa.api.request.ChangeStatusRequest;
import cn.axzo.nanopart.visa.api.request.CheckVisaWithVisaIdReq;
import cn.axzo.nanopart.visa.api.request.FetchVisaAllConfirmReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeApproveCreateReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeApproveOnlyReq;
@ -24,12 +26,14 @@ import cn.axzo.nanopart.visa.server.service.ChangeRecordConfirmService;
import cn.axzo.nanopart.visa.server.service.ChangeRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
import java.util.Objects;
/**
* @author xudawei
@ -52,6 +56,12 @@ public class ChangeRecordController implements ChangeRecordApi {
return ApiResult.ok(changeRecordService.tempCreateVisaChangeRecord(req));
}
@Override
public ApiResult<Void> checkVisaWithVisaId(CheckVisaWithVisaIdReq req) {
changeRecordService.checkVisaWithVisaId(req);
return ApiResult.ok();
}
@Override
public ApiResult<VisaChangeDiscussCreateResp> discussCreateVisaChangeRecord(VisaChangeDiscussCreateReq req) {
return ApiResult.ok(changeRecordService.discussCreateVisaChangeRecord(req));
@ -77,17 +87,34 @@ public class ChangeRecordController implements ChangeRecordApi {
@Override
public ApiResult<VisaDetailByIdResponse> visaDetailById(@RequestBody @Valid VisaDetailByIdRequest req) {
VisaDetailByIdResponse resp = changeRecordService.detailById(req.getVisaId());
resp.setBtnList(VisaButtonTypeEnum.all());
// resp.setBtnList(changeRecordConfirmService.fetchBtnsByCondition(req.getVisaId(), req.getPersonId(), req.getOuId(), req.getWorkspaceId(), resp.getStatus()));
// resp.setBtnList(VisaButtonTypeEnum.all());
resp.setBtnList(changeRecordConfirmService.fetchBtnsByCondition(req.getVisaId(), req.getPersonId(), req.getOuId(), req.getWorkspaceId(), resp.getStatus()));
return ApiResult.ok(resp);
}
@Override
public ApiPageResult<VisaChangePageSearchResp> pageSearchVisaChangeRecord(VisaChangePageSearchReq req) {
//重新赋值属性,待提报:TO_REPORT/REPORT_FROM_APPROVE,决策中:DECIDING/DECIDING_FROM_APPROVE
this.rechangeAttr(req);
PageData<VisaChangePageSearchResp> pageData = changeRecordService.page(req);
return ApiPageResult.ok(pageData.getList(), pageData.getTotalCount(), pageData.getPage(), pageData.getPageSize());
}
/**
* 重新赋值属性
* 待提报:TO_REPORT/REPORT_FROM_APPROVE
* 决策中:DECIDING/DECIDING_FROM_APPROVE
*/
private void rechangeAttr(VisaChangePageSearchReq req) {
if (Objects.nonNull(req) && CollectionUtils.isNotEmpty(req.getStatuses()) && req.getStatuses().contains(VisaStatusEnum.TO_REPORT)) {
req.getStatuses().add(VisaStatusEnum.REPORT_FROM_APPROVE);
}
if (Objects.nonNull(req) && CollectionUtils.isNotEmpty(req.getStatuses()) && req.getStatuses().contains(VisaStatusEnum.DECIDING)) {
req.getStatuses().add(VisaStatusEnum.DECIDING_FROM_APPROVE);
}
}
@Override
public ApiResult<Void> exportVisaChangeRecord(VisaChangeExportReq req) {
changeRecordService.export(req);

View File

@ -36,7 +36,7 @@ public class ChangeRecordRelationController implements ChangeRecordRelationApi {
public ApiResult<List<VisaRelationResp>> listByVisaId(VisaRelationReq req) {
return ApiResult.ok(changeRecordRelationService.findByCondition(VisaRelationDto.builder()
.visaId(req.getVisaId())
.varName(VisaRelationFieldEnum.PROCESS_INSTANCE.name())
.varName(VisaRelationFieldEnum.PROCESS_INSTANCE_OF_VISA.name())
.build())
.stream().sorted(Comparator.comparing(ChangeRecordRelation::getCreateAt))
.map(i -> VisaRelationResp.builder()

View File

@ -5,6 +5,7 @@ import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
@ -127,7 +128,7 @@ public class ChangeRecord extends BaseEntity<ChangeRecord> {
/**
* 最终审批时间
*/
@TableField(value = "approval_complete_time")
@TableField(value = "approval_complete_time", updateStrategy = FieldStrategy.IGNORED)
private Date approvalCompleteTime;
/**

View File

@ -1,8 +1,8 @@
package cn.axzo.nanopart.visa.server.domain;
import cn.axzo.nanopart.visa.api.enums.VisaBillTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
import cn.axzo.nanopart.visa.api.enums.VisaBillTypeEnum;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
@ -57,6 +57,13 @@ public class ChangeRecordBill extends BaseEntity<ChangeRecordBill> {
*/
@TableField(value = "bill_type")
private VisaBillTypeEnum billType;
/**
* 单据被关联状态
*/
@TableField(value = "relation_status")
private Boolean relationStatus;
/**
* 额外信息
*/

View File

@ -66,9 +66,10 @@ public class ImGroupAddMembersEventHandler implements EventHandler, Initializing
Map<Long, PersonProfileDto> profileMap = visaProfileGateway.getProfileMap(Lists.newArrayList(group.getOwnerPersonId(), member.getPersonId()));
String visaId = (String) group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_VISA_ID, "");
Long visaId = Long.valueOf(group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_VISA_ID, 0).toString());
String visaType = (String) group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_VISA_TYPE, "");
Long workspaceId = (Long) group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_INITIATOR_WORKSPACE_ID, 0L);
Long workspaceId = Long.valueOf(group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_INITIATOR_WORKSPACE_ID, 0).toString());
PersonProfileDto memberProfile = profileMap.getOrDefault(member.getPersonId(), null);
PersonProfileDto ownerProfile = profileMap.getOrDefault(group.getOwnerPersonId(), null);
@ -83,7 +84,7 @@ public class ImGroupAddMembersEventHandler implements EventHandler, Initializing
.imReceiveModel(new PersonV3DTO.ReceiveModel(member.getPersonOuId(), workspaceId))
.build()));
notice.setBizEventMappingCode(refreshableConfiguration.getImGroupAddMemberNoticeEventCode());
notice.setBizCode(visaId);
notice.setBizCode(String.valueOf(visaId));
notice.setBizExtParams(new JSONObject(Maps.of(
"initiatorName", ownerProfile.getRealName(),
"visaType", VisaTypeEnum.valueOfCode(visaType).getDesc(),

View File

@ -55,8 +55,7 @@ public class ImGroupRemoveMembersEventHandler implements EventHandler, Initializ
}
private void removeMemberVote(GroupInfo group, GroupMemberInfo member) {
Long visaId = (Long) group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_VISA_ID, "");
Long visaId = Long.valueOf(group.getBizGroupInfo().getOrDefault(IM_GROUP_BIZ_INFO_VISA_ID, 0).toString());
changeRecordRelationService.clearImOperationParticipate(ImGroupOperationClearReq.builder()
.clearAll(false)

View File

@ -27,6 +27,7 @@ import cn.axzo.nanopart.visa.server.rpc.OrganizationalUnitGateway;
import cn.axzo.nanopart.visa.server.rpc.VisaProfileGateway;
import cn.axzo.nanopart.visa.server.service.ChangeRecordConfirmService;
import cn.axzo.nanopart.visa.server.service.ChangeRecordService;
import cn.axzo.nanopart.visa.server.service.VisaHelper;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Sets;
@ -37,7 +38,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -91,13 +91,14 @@ public class ImGroupsCreatedEventHandler implements EventHandler, InitializingBe
Map<String, Object> bizGroupInfo = group.getBizGroupInfo();
HashSet<String> imReceiveAccounts = Sets.newHashSet(String.valueOf(group.getTid()));
GroupGetOwnerRequest ownerRequest = new GroupGetOwnerRequest();
ownerRequest.setTid(group.getTid());
GroupGetOwnerResponse groupOwner = msgCenterGateway.getGroupOwner(ownerRequest);
AssertUtil.isTrue(Objects.nonNull(groupOwner) && Objects.nonNull(groupOwner.getOwner()), "im group owner is null");
GroupMemberInfo owner = groupOwner.getOwner();
Long visaId = (Long) bizGroupInfo.getOrDefault(IM_GROUP_BIZ_INFO_VISA_ID, "");
Long visaId = Long.valueOf(bizGroupInfo.getOrDefault(IM_GROUP_BIZ_INFO_VISA_ID, 0).toString());
String visaType = (String) bizGroupInfo.getOrDefault(IM_GROUP_BIZ_INFO_VISA_TYPE, "");
Long ownerWorkspaceId = (Long) bizGroupInfo.getOrDefault(IM_GROUP_BIZ_INFO_INITIATOR_WORKSPACE_ID, 0L);
Long ownerWorkspaceId = Long.valueOf(bizGroupInfo.getOrDefault(IM_GROUP_BIZ_INFO_INITIATOR_WORKSPACE_ID, 0).toString());
ChangeRecord visa = changeRecordService.getById(visaId);
AssertUtil.notNull(visa, "visa record is null");
@ -121,20 +122,14 @@ public class ImGroupsCreatedEventHandler implements EventHandler, InitializingBe
ChangeRecordConfirm creator = creators.get(0);
OrganizationalUnitVO unitInfo = organizationalUnitGateway.getUnitInfo(creator.getOuId());
PersonProfileDto profile = visaProfileGateway.getProfile(creator.getPersonId());
String amountDesc = "不变";
if (visa.getAmountChange().compareTo(BigDecimal.ZERO) > 0) {
amountDesc = "增加" + visa.getAmountChange().toPlainString() + "";
} else if (visa.getAmountChange().compareTo(BigDecimal.ZERO) < 0) {
amountDesc = "减少" + visa.getAmountChange().toPlainString() + "";
}
cardRequest.setBizParam(new JSONObject(Maps.of(
"topic", group.getName(),
"reason", visa.getReason(),
"initiatorName", profile.getRealName(),
"initiatorUnitName", unitInfo.getName(),
"visaType", VisaTypeEnum.valueOfCode(visaType).getDesc(),
"amountChange", amountDesc
"visaType", VisaTypeEnum.valueOf(visaType).getDesc(),
"amountChange", VisaHelper.buildChangeAmount(visa.getAmountChange())
)));
msgCenterGateway.sendCardToCroup(cardRequest);

View File

@ -29,7 +29,7 @@ public abstract class BasicLogSupport {
return buildLogUserInfo(oneUserInfo);
}
protected String buildLogUserInfo(OrgNodeUserBriefInfoResp user) {
String userInfo = "";
String userInfo = "";
if (Objects.nonNull(user)) {
userInfo = user.getRealName() + "" + user.getJob().getName() + "-" + user.getOrganizationalUnitName() + "";
}
@ -37,10 +37,15 @@ public abstract class BasicLogSupport {
}
protected OrgNodeUserBriefInfoResp getOneUserInfo(BpmnTaskDelegateAssigner assigner) {
if (Objects.isNull(assigner)) {
return null;
}
List<OrgNodeUserBriefInfoResp> users = visaOrganizationalNodeUserGateway.listOrgNodeUsers(OrgNodeUserBriefInfoListReq.builder()
.workspaceId(Long.valueOf(assigner.getTenantId()))
.ouId(Long.valueOf(assigner.getOuId()))
.personIds(Lists.newArrayList(Long.valueOf(assigner.getPersonId())))
.needUnit(true)
.needJob(true)
.build());
return CollectionUtils.isEmpty(users) ? null : users.get(0);
}

View File

@ -10,6 +10,7 @@ import cn.axzo.nanopart.visa.server.domain.ChangeRecordRelation;
import cn.axzo.nanopart.visa.server.mq.listener.workflow.BasicLogSupport;
import cn.axzo.nanopart.visa.server.mq.producer.VisaChangeLogPayload;
import cn.axzo.nanopart.visa.server.rpc.VisaOrganizationalNodeUserGateway;
import cn.axzo.nanopart.visa.server.service.ChangeRecordBillService;
import cn.axzo.nanopart.visa.server.service.ChangeRecordRelationService;
import cn.axzo.nanopart.visa.server.service.ChangeRecordService;
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
@ -27,7 +28,7 @@ import static cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum.APPROVE_COMPLETED;
import static cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum.REJECT_APPROVE;
import static cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum.REVERT_APPROVE;
import static cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum.TO_APPRROVE;
import static cn.axzo.nanopart.visa.api.enums.VisaRelationFieldEnum.PROCESS_INSTANCE;
import static cn.axzo.nanopart.visa.api.enums.VisaRelationFieldEnum.PROCESS_INSTANCE_OF_VISA;
/**
* 工作流广播的实例维度的所有事件类型
@ -39,14 +40,17 @@ import static cn.axzo.nanopart.visa.api.enums.VisaRelationFieldEnum.PROCESS_INST
public class ProcessInstanceAllEventHandler extends BasicLogSupport implements ProcessInstanceEventHandler {
protected final ChangeRecordService changeRecordService;
protected final ChangeRecordRelationService changeRecordRelationService;
protected final ChangeRecordBillService changeRecordBillService;
public ProcessInstanceAllEventHandler(EventProducer eventProducer,
VisaOrganizationalNodeUserGateway visaOrganizationalNodeUserGateway,
ChangeRecordService changeRecordService,
ChangeRecordRelationService changeRecordRelationService) {
ChangeRecordRelationService changeRecordRelationService,
ChangeRecordBillService changeRecordBillService) {
super(eventProducer, visaOrganizationalNodeUserGateway);
this.changeRecordService = changeRecordService;
this.changeRecordRelationService = changeRecordRelationService;
this.changeRecordBillService = changeRecordBillService;
}
@Override
@ -77,6 +81,7 @@ public class ProcessInstanceAllEventHandler extends BasicLogSupport implements P
String visaType = (String) dto.getVariables().getOrDefault(WORKFLOW_VAR_VISA_TYPE_KEY, "");
return StringUtils.hasText(visaType) ? VisaTypeEnum.valueOf(visaType).getDesc() : "";
}
@Override
public void onCompleted(ProcessInstanceDTO dto) {
String visaTypeDesc = parseVisaType(dto);
@ -140,7 +145,7 @@ public class ProcessInstanceAllEventHandler extends BasicLogSupport implements P
}
private void updateChangeRecordApprovalStatus(ProcessInstanceDTO dto, BpmnProcessInstanceResultEnum resultEnum) {
// 更新主表审批信息
// 更新主表审批状态信息
Long visaId = Long.valueOf(dto.getBusinessKey());
changeRecordService.lambdaQuery()
.eq(ChangeRecord::getId, visaId)
@ -148,15 +153,21 @@ public class ProcessInstanceAllEventHandler extends BasicLogSupport implements P
.eq(ChangeRecord::getIsDelete, 0)
.oneOpt()
.ifPresent(changeRecord -> {
changeRecord.setApprovalStatus(resultEnum.getStatus());
changeRecord.setApprovalCompleteTime(new Date());
if (Objects.equals(resultEnum, BpmnProcessInstanceResultEnum.APPROVED)) {
changeRecord.setApprovalStatus(resultEnum.getStatus());
changeRecord.setApprovalCompleteTime(new Date());
} else {
changeRecord.setApprovalId("");
changeRecord.setApprovalStatus("");
changeRecord.setApprovalCompleteTime(null);
}
changeRecordService.updateById(changeRecord);
});
// 更新关联表审批信息
changeRecordRelationService.lambdaQuery()
.eq(ChangeRecordRelation::getVisaId, visaId)
.eq(ChangeRecordRelation::getVarName, PROCESS_INSTANCE.getCode())
.eq(ChangeRecordRelation::getVarName, PROCESS_INSTANCE_OF_VISA.name())
.eq(ChangeRecordRelation::getContent, dto.getProcessInstanceId())
.oneOpt()
.ifPresent(changeRecordRelation -> {
@ -164,14 +175,22 @@ public class ProcessInstanceAllEventHandler extends BasicLogSupport implements P
changeRecordRelationService.updateById(changeRecordRelation);
});
ChangeRecord visa = changeRecordService.getById(visaId);
if (Objects.equals(resultEnum, BpmnProcessInstanceResultEnum.APPROVED)) {
changeRecordService.changeStatus(ChangeStatusRequest.builder()
.visaId(visaId)
.updateStatus(VisaStatusEnum.COMPLETED)
.build());
return;
}
// 回退到待提报或决策中
ChangeRecord visa = changeRecordService.getById(visaId);
changeRecordService.changeStatus(ChangeStatusRequest.builder()
.visaId(visaId)
.updateStatus(Objects.isNull(visa.getImGroupId()) ? VisaStatusEnum.REPORT_FROM_APPROVE : VisaStatusEnum.DECIDING_FROM_APPROVE)
.build());
// 取消当前主单据关联的其他单据的关联状态
changeRecordBillService.billRelationStatus(visaId, false);
}
}

View File

@ -10,6 +10,8 @@ import cn.axzo.workflow.common.model.response.mq.ProcessTaskDTO;
import cn.axzo.workflow.starter.handler.ProcessTaskEventHandler;
import org.springframework.stereotype.Component;
import java.util.Objects;
import static cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum.APPROVED_AGRESS;
import static cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum.TRANSMIT_APPROVE;
@ -53,8 +55,8 @@ public class ProcessTaskAllEventHandler extends BasicLogSupport implements Proce
ChangeRecordLog log = ChangeRecordLog.builder()
.visaId(Long.valueOf(dto.getBusinessKey()))
.action(dto.getType().getTag())
.title(String.format(APPROVED_AGRESS.getTitle(), user.getRealName()))
.content(String.format(APPROVED_AGRESS.getContent(), buildLogUserInfo(user)))
.title(String.format(APPROVED_AGRESS.getTitle(), Objects.isNull(user) ? "" : user.getRealName()))
.content(String.format(APPROVED_AGRESS.getContent(), Objects.isNull(user) ? "系统自动通过" : buildLogUserInfo(user)))
.build();
eventProducer.send(VisaChangeLogPayload.form(log));
}

View File

@ -0,0 +1,28 @@
package cn.axzo.nanopart.visa.server.rpc;
import cn.axzo.apollo.api.ApolloTaskOrderApi;
import cn.axzo.apollo.api.req.QueryOrderToBasicReq;
import cn.axzo.apollo.api.res.TaskOrderToBasicRes;
import cn.axzo.apollo.core.domain.PageResult;
import cn.axzo.nanopart.visa.server.utils.RpcUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/2/12 11:18
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class ApolloTaskOrderApiGateway {
private final ApolloTaskOrderApi apolloTaskOrderApi;
public PageResult<TaskOrderToBasicRes> pageOrderByForBasic(QueryOrderToBasicReq req) {
return RpcUtil.rpcResultProcessor(() -> apolloTaskOrderApi.pageOrderByForBasic(req),
"Page query task orders", req);
}
}

View File

@ -0,0 +1,50 @@
package cn.axzo.nanopart.visa.server.rpc;
/**
* @author xudawei@axzo.cn
* @date 2025/2/12
* @description 日志RPC
*/
import cn.axzo.log.platform.client.feign.LogApi;
import cn.axzo.log.platform.client.model.req.LogAddReq;
import cn.azxo.framework.common.model.CommonResponse;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 日志RPC
* @author xudawei@axzo.cn
* @since 2025-02-05 15:08
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class LogApiGateway {
private final LogApi logApi;
public void addLog(LogAddReq req) {
try {
log.info("LogApiGateway-addLog, req: {}", JSONUtil.toJsonStr(req));
CommonResponse<String> stringCommonResponse = logApi.addLog(req);
log.info("LogApiGateway-addLog, result: {}", JSONUtil.toJsonStr(stringCommonResponse));
} catch (Exception e) {
log.warn("LogApiGateway-addLog Exception", e);
}
}
public void addLog(String scene, String level, List<String> tags, String msg) {
logApi.addLog(LogAddReq.builder()
.scene(scene)
.level(level)
.tags(tags)
.message(msg)
.build());
}
}

View File

@ -0,0 +1,29 @@
package cn.axzo.nanopart.visa.server.rpc;
import cn.axzo.digital.RectifyApi;
import cn.axzo.digital.req.ListRectifyOrderReq;
import cn.axzo.digital.resp.RectifyOrderResp;
import cn.axzo.nanopart.visa.server.utils.RpcUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author chenwenjian
* @version 1.0
* @date 2025/2/12 11:37
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class RectifyApiGateway {
private final RectifyApi rectifyApi;
public List<RectifyOrderResp> listRectifyOrders(ListRectifyOrderReq req) {
return RpcUtil.rpcApiResultProcessor(() -> rectifyApi.listRectifyOrders(req),
"Get rectify orders by ids", req);
}
}

View File

@ -30,8 +30,8 @@ public class WorkflowGateway {
}
@MethodAroundLog(target = "workflow-engine", source = "nanopart", value = "中止流程实例")
public void processInstanceAbort(BpmnProcessInstanceAbortDTO dto) {
workflowCoreService.abortProcessInstance(dto);
public Boolean processInstanceAbort(BpmnProcessInstanceAbortDTO dto) {
return workflowCoreService.abortProcessInstance(dto);
}
@MethodAroundLog(target = "workflow-engine", source = "nanopart", value = "查询某个人是否是指定流程的审批人")

View File

@ -3,6 +3,7 @@ package cn.axzo.nanopart.visa.server.service;
import cn.axzo.nanopart.visa.api.enums.VisaBillTypeEnum;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordBill;
import cn.axzo.nanopart.visa.server.dto.VisaBillDto;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
@ -11,7 +12,7 @@ import java.util.List;
* @date 2025/01/15
* @desc 变更签证记录内容关系表
*/
public interface ChangeRecordBillService {
public interface ChangeRecordBillService extends IService<ChangeRecordBill> {
/**
@ -24,11 +25,21 @@ public interface ChangeRecordBillService {
*/
Boolean updateBill(Long visaId, List<VisaBillDto> dtoList);
/**
* 更新关联单据的被关联状态
*
* @param visaId
* @param related
* @return
*/
Boolean billRelationStatus(Long visaId, Boolean related);
/**
* 删除
*/
Boolean deleteByVisaId(Long visaId);
Boolean deleteByCondition(List<Long> billIds, VisaBillTypeEnum billType);
/**
* 查询记录
*/
@ -48,4 +59,12 @@ public interface ChangeRecordBillService {
*/
List<ChangeRecordBill> findMainBill(VisaBillTypeEnum billType, List<Long> billIds);
/**
* 获取任务单的主单据
*
* @param taskNos 任务单单号
* @return 主单据信息
*/
List<ChangeRecordBill> findTaskMainBill(List<String> taskNos);
}

View File

@ -45,7 +45,7 @@ public interface ChangeRecordConfirmService {
/**
* 变更签证Id获取map
*/
List<VisaDetailByIdResponse.RelationOuAndPerson> listRelationByVisaId(List<ChangeRecordConfirm> list);
List<VisaDetailByIdResponse.RelationOuAndPerson> listRelationByVisaId(List<ChangeRecordConfirm> list, Long workspaceId);
/**
* 根据条件查询

View File

@ -4,6 +4,7 @@ import cn.axzo.framework.domain.web.result.PageData;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.request.ChangeRecordButtonOperationReq;
import cn.axzo.nanopart.visa.api.request.ChangeStatusRequest;
import cn.axzo.nanopart.visa.api.request.CheckVisaWithVisaIdReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeApproveCreateReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeApproveOnlyReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeDiscussCreateReq;
@ -121,4 +122,9 @@ public interface ChangeRecordService extends IService<ChangeRecord> {
void delete(ChangeRecordButtonOperationReq req);
/**
* 校验
*/
void checkVisaWithVisaId(CheckVisaWithVisaIdReq req);
}

View File

@ -1,18 +1,25 @@
package cn.axzo.nanopart.visa.server.service;
import cn.axzo.nanopart.visa.api.enums.VisaButtonTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaConfirmBizTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.request.ChangeStatusRequest;
import cn.axzo.nanopart.visa.api.response.VisaDetailByIdResponse;
import cn.axzo.nanopart.visa.server.domain.ChangeRecord;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordConfirm;
import cn.axzo.nanopart.visa.server.dto.VisaAddLogContext;
import cn.axzo.nanopart.visa.server.dto.VisaConfirmDto;
import cn.axzo.nanopart.visa.server.dto.VisaLogParam;
import cn.axzo.nanopart.visa.server.rpc.ApolloConstructionAreaGateway;
import cn.axzo.nanopart.visa.server.rpc.DrawingMajorGateway;
import cn.axzo.nanopart.visa.server.rpc.LogApiGateway;
import cn.axzo.nanopart.visa.server.utils.Constants;
import cn.axzo.thor.client.model.DrawingMajorResp;
import cn.hutool.core.lang.Pair;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
@ -20,6 +27,7 @@ import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -27,6 +35,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
@ -53,6 +62,9 @@ public class VisaHelper {
@Resource
private ChangeRecordConfirmService changeRecordConfirmService;
@Resource
private LogApiGateway logApiGateway;
/**
* 状态更新与添加日志此时新增记录时状态没有维护
*/
@ -70,6 +82,16 @@ public class VisaHelper {
//编辑时
if (Objects.nonNull(oldContext) && Objects.nonNull(newContext)) {
// [决策中执行中] -> [审批中] 执行变更签证属性变更
if (Objects.nonNull(oldContext.getStatus()) && Objects.nonNull(newContext.getStatus())
&& VisaStatusEnum.isEditForm(oldContext.getStatus())
&& newContext.getStatus().equals(VisaStatusEnum.APPROVING)) {
logApiGateway.addLog(Constants.VISA_LOG_SNAPSHOT_SCENE
, Constants.VISA_LOG_SNAPSHOT_LEVEL
, Lists.newArrayList(Constants.VISA_LOG_SNAPSHOT_TAG_SNAPSHOT)
, JSONUtil.toJsonStr(Pair.of(oldContext, newContext)));
}
changeRecordService.changeStatus(ChangeStatusRequest.builder()
.visaId(newContext.getChangeRecord().getId())
.updateStatus(newContext.getStatus())
@ -138,24 +160,31 @@ public class VisaHelper {
* 递归专业
* codeNameMap,key:叶子结点codevalue父节点+子节点的名字
*/
private void recursionProfessional(DrawingMajorResp drawingMajorResp, String name, Map<String, String> codeNameMap) {
if (Objects.isNull(drawingMajorResp) || CollectionUtils.isEmpty(drawingMajorResp.getChildren())) {
private void recursionProfessional(DrawingMajorResp drawingMajorResp, String currentName, Map<String, String> codeNameMap) {
if (CollectionUtils.isEmpty(drawingMajorResp.getChildren())) {
codeNameMap.put(drawingMajorResp.getCode(), currentName);
return;
}
for (DrawingMajorResp resp : drawingMajorResp.getChildren()) {
if (CollectionUtils.isNotEmpty(resp.getChildren())) {
recursionProfessional(resp, name + Constants.SPLIT_TREE_NODE_CHAT + resp.getName(), codeNameMap);
} else {
codeNameMap.put(resp.getCode(), name + Constants.SPLIT_TREE_NODE_CHAT + resp.getName());
}
recursionProfessional(resp, currentName + Constants.SPLIT_TREE_NODE_CHAT + resp.getName(), codeNameMap);
}
}
/**
* 查询单据与当前人的角色:[发起人确认人其他用户]
*/
public Map<Long,Set<VisaConfirmBizTypeEnum>> fetchConfirmBizTypes(Collection<Long> visaIds, Long personId, Long ouId, Long workspaceId) {
public Map<Long,Set<VisaConfirmBizTypeEnum>> fetchConfirmBizTypes(Collection<ChangeRecord> visaList, Long personId, Long ouId, Long workspaceId) {
if (CollectionUtils.isEmpty(visaList)) {
return Collections.emptyMap();
}
List<Long> visaIds = visaList.stream().filter(item -> Objects.nonNull(item.getId()))
.map(ChangeRecord::getId).collect(Collectors.toList());
if (CollectionUtils.isEmpty(visaIds)) {
return Collections.emptyMap();
}
List<ChangeRecordConfirm> confirmList = changeRecordConfirmService.findByCondition(VisaConfirmDto.builder()
.visaIds(visaIds)
.personId(personId)
@ -172,4 +201,46 @@ public class VisaHelper {
return visaBizTypeMap;
}
/**
* 获取按钮集合
* 确认人与发起人的不同的单据状态按钮列表不相同
*/
public Map<Long, Set<VisaButtonTypeEnum>> fetchBtnsByBizTypeAndStatus(Collection<ChangeRecord> visaList, Long personId, Long ouId, Long workspaceId) {
if (CollectionUtils.isEmpty(visaList)) {
return Collections.emptyMap();
}
Map<Long, ChangeRecord> visaIdMap = visaList.stream()
.filter(item -> Objects.nonNull(item.getId()))
.collect(Collectors.toMap(ChangeRecord::getId, Function.identity(), (x, y) -> x));
Map<Long, Set<VisaConfirmBizTypeEnum>> visaIdBizTypeMap = fetchConfirmBizTypes(visaList, personId, ouId, workspaceId);
if (Objects.isNull(visaIdBizTypeMap) || visaIdBizTypeMap.isEmpty()) {
return Collections.emptyMap();
}
Map<Long, Set<VisaButtonTypeEnum>> returnMap = Maps.newHashMap();
visaIdBizTypeMap.entrySet().stream().forEach(entry -> {
Long key = entry.getKey();
Set<VisaConfirmBizTypeEnum> value = entry.getValue();
ChangeRecord changeRecord = visaIdMap.get(key);
if (Objects.nonNull(changeRecord) && Objects.nonNull(changeRecord.getStatus())) {
returnMap.put(key, VisaButtonTypeEnum.fetchBtnsByBizTypeAndStatusWhenPage(value, changeRecord.getStatus()));
}
});
return returnMap;
}
public static String buildChangeAmount(BigDecimal changeAmount) {
if (Objects.isNull(changeAmount)) {
return "";
}
String amountDesc = "不变";
if (changeAmount.compareTo(BigDecimal.ZERO) > 0) {
amountDesc = "增加" + changeAmount.abs().toPlainString() + "";
} else if (changeAmount.compareTo(BigDecimal.ZERO) < 0) {
amountDesc = "减少" + changeAmount.abs().toPlainString() + "";
}
return amountDesc;
}
}

View File

@ -1,6 +1,5 @@
package cn.axzo.nanopart.visa.server.service.impl;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.nanopart.visa.api.enums.VisaBillTypeEnum;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordBill;
import cn.axzo.nanopart.visa.server.dto.VisaBillDto;
@ -11,10 +10,12 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@ -40,13 +41,19 @@ public class ChangeRecordBillServiceImpl extends ServiceImpl<ChangeRecordBillDao
* 更新
*/
public Boolean updateBill(Long visaId, List<VisaBillDto> dtoList) {
List<ChangeRecordBill> billList = BeanUtil.copyToList(dtoList, ChangeRecordBill.class);
// 删除
this.deleteByVisaId(visaId);
// 插入
return this.addBill(dtoList);
}
public Boolean billRelationStatus(Long visaId, Boolean related) {
return this.lambdaUpdate().eq(ChangeRecordBill::getVisaId, visaId)
.eq(ChangeRecordBill::getIsDelete, 0)
.set(ChangeRecordBill::getRelationStatus, related)
.update();
}
/**
* 删除
*/
@ -59,6 +66,17 @@ public class ChangeRecordBillServiceImpl extends ServiceImpl<ChangeRecordBillDao
.setSql("is_delete = id").update();
}
public Boolean deleteByCondition(List<Long> billIds, VisaBillTypeEnum billType) {
if (CollectionUtils.isEmpty(billIds)) {
return false;
}
return this.lambdaUpdate().in(ChangeRecordBill::getBillId, billIds)
.eq(ChangeRecordBill::getBillType, billType)
.eq(ChangeRecordBill::getIsDelete, 0)
.setSql("is_delete = id").update();
}
/**
* 查询记录
*/
@ -79,12 +97,20 @@ public class ChangeRecordBillServiceImpl extends ServiceImpl<ChangeRecordBillDao
@Override
public List<ChangeRecordBill> findMainBill(VisaBillTypeEnum billType, List<Long> billIds) {
AssertUtil.notNull(billType, "单据类型不能为空");
AssertUtil.notEmpty(billIds, "单据Id不能为空");
if (Objects.isNull(billIds) || CollectionUtils.isEmpty(billIds)) {
return Collections.emptyList();
}
return lambdaQuery().in(ChangeRecordBill::getBillId, billIds)
.eq(ChangeRecordBill::getBillType, billType)
.eq(ChangeRecordBill::getIsDelete, 0)
.orderByDesc(ChangeRecordBill::getUpdateAt)
.list();
}
@Override
public List<ChangeRecordBill> findTaskMainBill(List<String> taskNos) {
return lambdaQuery().in(ChangeRecordBill::getBillNo, taskNos)
.eq(ChangeRecordBill::getBillType, VisaBillTypeEnum.TASK)
.eq(ChangeRecordBill::getIsDelete, 0)
.list();
}

View File

@ -2,6 +2,7 @@ package cn.axzo.nanopart.visa.server.service.impl;
import cn.axzo.basics.common.BeanMapper;
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
import cn.axzo.foundation.page.PageResp;
import cn.axzo.karma.client.feign.tyr.request.MatchDataObjectReq;
import cn.axzo.karma.client.feign.tyr.response.MatchDataObjectResp;
import cn.axzo.karma.client.feign.tyr.response.MergeMatchDataResp;
@ -20,11 +21,16 @@ import cn.axzo.nanopart.visa.server.dto.VisaConfirmDto;
import cn.axzo.nanopart.visa.server.mapper.ChangeRecordConfirmDao;
import cn.axzo.nanopart.visa.server.rpc.DataObjectApiGateway;
import cn.axzo.nanopart.visa.server.rpc.OrganizationalUnitGateway;
import cn.axzo.nanopart.visa.server.rpc.VisaOrganizationalNodeUserGateway;
import cn.axzo.nanopart.visa.server.rpc.VisaProfileGateway;
import cn.axzo.nanopart.visa.server.rpc.WorkflowGateway;
import cn.axzo.nanopart.visa.server.service.ChangeRecordConfirmService;
import cn.axzo.nanopart.visa.server.service.ChangeRecordLogService;
import cn.axzo.nanopart.visa.server.service.ChangeRecordService;
import cn.axzo.nanopart.visa.server.utils.Constants;
import cn.axzo.orggateway.api.nodeuser.dto.OrgNodeUserDTO;
import cn.axzo.orggateway.api.nodeuser.req.ListOrgNodeUserReq;
import cn.axzo.orgmanax.dto.nodeuser.req.ListNodeUserReq;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCheckApproverDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
@ -71,6 +77,10 @@ public class ChangeRecordConfirmServiceImpl extends ServiceImpl<ChangeRecordConf
@Resource
private DataObjectApiGateway dataObjectApiGateway;
@Resource
private VisaOrganizationalNodeUserGateway visaOrganizationalNodeUserGateway;
/**
* 新增变更签证确认信息
*
@ -127,6 +137,16 @@ public class ChangeRecordConfirmServiceImpl extends ServiceImpl<ChangeRecordConf
//没有去审批记录则不展示[查看审批记录]按钮
if (!changeRecordLogService.hasLogType(visaId, VisaLogTypeEnum.TO_APPRROVE)) {
visaButtonTypeEnums.remove(VisaButtonTypeEnum.APPROVAL_RECORD);
} else {
if (visaButtonTypeEnums.contains(VisaButtonTypeEnum.TO_APPROVE)) {
visaButtonTypeEnums.remove(VisaButtonTypeEnum.TO_APPROVE);
visaButtonTypeEnums.add(VisaButtonTypeEnum.AGAIN_TO_APPROVE);
}
}
//没有去审批记录则不展示[查看审批记录]按钮
if (!changeRecordLogService.hasLogType(visaId, VisaLogTypeEnum.CHAT_GROUP)) {
visaButtonTypeEnums.remove(VisaButtonTypeEnum.CHAT_GROUP_RECORD);
}
return visaButtonTypeEnums;
}
@ -182,21 +202,34 @@ public class ChangeRecordConfirmServiceImpl extends ServiceImpl<ChangeRecordConf
* 变更签证Id获取map
*/
@Override
public List<VisaDetailByIdResponse.RelationOuAndPerson> listRelationByVisaId(List<ChangeRecordConfirm> list) {
public List<VisaDetailByIdResponse.RelationOuAndPerson> listRelationByVisaId(List<ChangeRecordConfirm> list, Long workspaceId) {
if (CollectionUtils.isEmpty(list)) {
return Lists.newArrayList();
}
// 2-1 构建人员的集合key:personId,value:realName
Set<Long> personSet = list.stream().map(ChangeRecordConfirm::getPersonId).collect(Collectors.toSet());
Map<Long, String> personMap = this.buildPersonMap(personSet);
// 2-2 构建公司的MaporgIdAndNameMap,key:ouId,value:ouName
Set<Long> ouIdSet = list.stream().map(ChangeRecordConfirm::getOuId).collect(Collectors.toSet());
Map<Long, String> orgIdAndNameMap = this.buildOrgIdAndNameMap(ouIdSet);
// 3 构建关联单位与人员最终处理成一个类型与单位下对应多个确认人
Map<String, List<ChangeRecordConfirm>> listMap = list.stream().collect(Collectors.groupingBy(e -> e.getType() + "#" + e.getOuId()));
return this.buildRelationOuAndPerson(listMap, personMap, orgIdAndNameMap);
Map<String, List<ChangeRecordConfirm>> listMap = list.stream().collect(Collectors.groupingBy(e -> {
if (Objects.isNull(e.getNodeId())) {
return e.getType() + "#" + e.getOuId() + "#0";
}
return e.getType() + "#" + e.getOuId() + "#" + e.getNodeId();
}));
return this.buildRelationOuAndPerson(listMap, workspaceId);
}
/**
* 获取OrgNodeUserDTO集合
*/
private List<OrgNodeUserDTO> fetchOrgNodeUserDTOList(List<Long> personIds, Long ouId, Long workspaceId) {
PageResp<OrgNodeUserDTO> pageResp = visaOrganizationalNodeUserGateway.list(ListOrgNodeUserReq.builder()
.personIds(personIds)
.organizationalUnitId(ouId)
.workspaceId(workspaceId)
.needs(ListNodeUserReq.Needs.builder().job(true).unit(true).personProfile(true).build()).build());
if (Objects.isNull(pageResp) || CollectionUtils.isEmpty(pageResp.getData())) {
return Lists.newArrayList();
}
return pageResp.getData();
}
/**
@ -218,16 +251,30 @@ public class ChangeRecordConfirmServiceImpl extends ServiceImpl<ChangeRecordConf
* listMap key:type#ouId,value:ChangeRecordConfirm集合按照[单位]以及[类型]进行分类
* personMap key:personId,value:realName,对于确认人进行姓名赋值
*/
private List<VisaDetailByIdResponse.RelationOuAndPerson> buildRelationOuAndPerson(Map<String, List<ChangeRecordConfirm>> listMap, Map<Long, String> personMap, Map<Long, String> orgIdAndNameMap) {
private List<VisaDetailByIdResponse.RelationOuAndPerson> buildRelationOuAndPerson(Map<String, List<ChangeRecordConfirm>> listMap, Long workspaceId) {
List<VisaDetailByIdResponse.RelationOuAndPerson> returnList = Lists.newArrayList();
for (Map.Entry<String, List<ChangeRecordConfirm>> entry : listMap.entrySet()) {
String key = entry.getKey();
List<ChangeRecordConfirm> confirmList = entry.getValue();
if (CollectionUtils.isEmpty(confirmList)) {
continue;
}
List<OrgNodeUserDTO> orgNodeUserDTOS = this.fetchOrgNodeUserDTOList(confirmList.stream().map(ChangeRecordConfirm::getPersonId).collect(Collectors.toList()), Long.valueOf(key.split("#")[1]), workspaceId);
Map<Long, String> unitNodeUserMap = orgNodeUserDTOS.stream()
.filter(item -> Objects.nonNull(item.getUnit()) && Objects.nonNull(item.getUnit().getId()))
.collect(Collectors.toMap(k -> k.getUnit().getId(), v -> StringUtils.hasText(v.getUnit().getName()) ? v.getUnit().getName() : "", (x, y) -> x));
Map<Long, List<OrgNodeUserDTO>> personNodeUserMap = orgNodeUserDTOS.stream()
.filter(item -> Objects.nonNull(item.getPersonId()))
.collect(Collectors.groupingBy(OrgNodeUserDTO::getPersonId));
//构建单位
VisaDetailByIdResponse.RelationUnit relationUnit = this.buildRelationUnit(key, orgIdAndNameMap);
VisaDetailByIdResponse.RelationUnit relationUnit = this.buildRelationUnit(key, unitNodeUserMap);
//构建确认人
List<VisaDetailByIdResponse.RelationPerson> relationPersonList = this.buildRelationPersonList(confirmList, personMap);
List<VisaDetailByIdResponse.RelationPerson> relationPersonList = this.buildRelationPersonList(confirmList, personNodeUserMap);
returnList.add(VisaDetailByIdResponse.RelationOuAndPerson.builder()
.relationOu(relationUnit)
@ -239,30 +286,52 @@ public class ChangeRecordConfirmServiceImpl extends ServiceImpl<ChangeRecordConf
/**
* 构建单位
*/
private VisaDetailByIdResponse.RelationUnit buildRelationUnit(String key, Map<Long, String> orgIdAndNameMap) {
private VisaDetailByIdResponse.RelationUnit buildRelationUnit(String key, Map<Long, String> unitNodeUserMap) {
String[] keySplit = key.split("#");
Long ouId = Long.valueOf(keySplit[1]);
return VisaDetailByIdResponse.RelationUnit.builder()
.ouId(ouId)
.type(keySplit[0])
.ouName(StringUtils.hasText(orgIdAndNameMap.get(ouId)) ? orgIdAndNameMap.get(ouId) : "").build();
.nodeId(keySplit.length > 2 ? Long.valueOf(keySplit[2]) : 0L)
.ouName(StringUtils.hasText(unitNodeUserMap.get(ouId)) ? unitNodeUserMap.get(ouId) : "").build();
}
/**
* 构建确认人
*/
private List<VisaDetailByIdResponse.RelationPerson> buildRelationPersonList(List<ChangeRecordConfirm> confirmList, Map<Long, String> personMap) {
return confirmList.stream().map(item -> VisaDetailByIdResponse.RelationPerson.builder()
.ouId(item.getOuId())
.workspaceId(item.getWorkspaceId())
.personId(item.getPersonId())
.projectId(item.getProjectId())
.type(item.getType())
.realName(personMap.get(item.getPersonId()))
.build()
private List<VisaDetailByIdResponse.RelationPerson> buildRelationPersonList(List<ChangeRecordConfirm> confirmList,Map<Long, List<OrgNodeUserDTO>> personNodeUserMap) {
return confirmList.stream().map(item -> {
List<OrgNodeUserDTO> orgNodeUserDTOS = personNodeUserMap.get(item.getPersonId());
//有班组时优先取班组岗位
OrgNodeUserDTO nodeUserDTO = Constants.nodeUserDTOByList(orgNodeUserDTOS);
VisaDetailByIdResponse.RelationPerson relationPerson = VisaDetailByIdResponse.RelationPerson.builder()
.ouId(item.getOuId())
.workspaceId(item.getWorkspaceId())
.personId(item.getPersonId())
.projectId(item.getProjectId())
.type(item.getType())
.build();
if (Objects.nonNull(nodeUserDTO)) {
relationPerson.setRealName(nodeUserDTO.getRealName());
if (Objects.nonNull(nodeUserDTO.getPersonProfile())) {
relationPerson.setAvatarUrl(nodeUserDTO.getPersonProfile().getAvatarUrl());
}
if (Objects.nonNull(nodeUserDTO.getJob())) {
relationPerson.setJobId(nodeUserDTO.getJob().getId());
relationPerson.setJobName(nodeUserDTO.getJob().getName());
}
}
return relationPerson;
}
).collect(Collectors.toList());
}
/**
* 构建人员的集合key:personId,value:realName
*/

View File

@ -2,20 +2,20 @@ package cn.axzo.nanopart.visa.server.service.impl;
import cn.axzo.foundation.page.PageResp;
import cn.axzo.framework.domain.ServiceException;
import cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum;
import cn.axzo.nanopart.visa.api.response.FetchVisaLogByVisaIdResponse;
import cn.axzo.nanopart.visa.server.domain.ChangeRecord;
import cn.axzo.nanopart.visa.server.domain.ChangeRecordLog;
import cn.axzo.nanopart.visa.server.dto.VisaLogDto;
import cn.axzo.nanopart.visa.server.dto.VisaLogParam;
import cn.axzo.nanopart.visa.server.mapper.ChangeRecordLogDao;
import cn.axzo.nanopart.visa.server.rpc.VisaOrganizationalNodeUserGateway;
import cn.axzo.nanopart.visa.server.service.ChangeRecordLogService;
import cn.axzo.nanopart.visa.server.service.ChangeRecordService;
import cn.axzo.nanopart.visa.server.utils.Constants;
import cn.axzo.orggateway.api.nodeuser.dto.OrgNodeUserDTO;
import cn.axzo.orggateway.api.nodeuser.req.ListOrgNodeUserReq;
import cn.axzo.orgmanax.dto.nodeuser.req.ListNodeUserReq;
import cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum;
import cn.axzo.nanopart.visa.api.response.FetchVisaLogByVisaIdResponse;
import cn.axzo.nanopart.visa.server.service.ChangeRecordLogService;
import cn.axzo.nanopart.visa.server.service.ChangeRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
@ -255,7 +255,7 @@ public class ChangeRecordLogServiceImpl extends ServiceImpl<ChangeRecordLogDao,
if (Objects.isNull(pageResp) || CollectionUtils.isEmpty(pageResp.getData())) {
return "";
}
OrgNodeUserDTO orgNodeUserDTO = pageResp.getData().get(0);
OrgNodeUserDTO orgNodeUserDTO = Constants.nodeUserDTOByList(pageResp.getData());
return orgNodeUserDTO.getRealName() + "" + orgNodeUserDTO.getJob().getName() + "-" + orgNodeUserDTO.getUnit().getName() + "";
}

View File

@ -217,6 +217,8 @@ public class ChangeRecordRelationServiceImpl extends ServiceImpl<ChangeRecordRel
ImGroupTipsResp resp = new ImGroupTipsResp();
resp.setStatus(record.getStatus());
resp.setStatusText(record.getStatus().getDesc());
resp.setVisaType(record.getType());
resp.setVisaTypeText(record.getType().getDesc());
List<ChangeRecordRelation> imGroupParticipate = findByCondition(VisaRelationDto.builder()
.visaId(req.getVisaId())
.varName(VisaRelationFieldEnum.IM_GROUP_PARTICIPATE.name())
@ -226,8 +228,8 @@ public class ChangeRecordRelationServiceImpl extends ServiceImpl<ChangeRecordRel
if (Boolean.TRUE.equals(req.getIsGroupOwner())) {
Map<String, Long> countMap = imGroupParticipate.stream()
.collect(Collectors.groupingBy(ChangeRecordRelation::getVarExt, Collectors.counting()));
Long agreeCount = countMap.getOrDefault(VisaButtonTypeEnum.AGREE.getCode(), 0L);
Long rejectCount = countMap.getOrDefault(VisaButtonTypeEnum.REJECT.getCode(), 0L);
Long agreeCount = countMap.getOrDefault(VisaButtonTypeEnum.AGREE.name(), 0L);
Long rejectCount = countMap.getOrDefault(VisaButtonTypeEnum.REJECT.name(), 0L);
resp.setTipsText(String.format(IM_GROUP_OWNER_TIPS, req.getGroupTotalPersonCount() - 1,
imGroupParticipate.size(), agreeCount, rejectCount));
switch (record.getStatus()) {
@ -236,20 +238,20 @@ public class ChangeRecordRelationServiceImpl extends ServiceImpl<ChangeRecordRel
// 全部同意
buttons.add(ImGroupButton.builder()
.name(VisaButtonTypeEnum.TO_APPROVE.getDesc())
.type(VisaButtonTypeEnum.TO_APPROVE.getCode())
.type(VisaButtonTypeEnum.TO_APPROVE.name())
.build());
buttons.add(ImGroupButton.builder()
.name(VisaButtonTypeEnum.EXECUTE.getDesc())
.type(VisaButtonTypeEnum.EXECUTE.getCode())
.type(VisaButtonTypeEnum.EXECUTE.name())
.build());
} else {
buttons.add(ImGroupButton.builder()
.name(VisaButtonTypeEnum.FORBID.getDesc())
.type(VisaButtonTypeEnum.FORBID.getCode())
.type(VisaButtonTypeEnum.FORBID.name())
.build());
buttons.add(ImGroupButton.builder()
.name(VisaButtonTypeEnum.REDECISION.getDesc())
.type(VisaButtonTypeEnum.REDECISION.getCode())
.type(VisaButtonTypeEnum.REDECISION.name())
.build());
}
break;
@ -258,16 +260,16 @@ public class ChangeRecordRelationServiceImpl extends ServiceImpl<ChangeRecordRel
// 全部同意
buttons.add(ImGroupButton.builder()
.name(VisaButtonTypeEnum.EXECUTE.getDesc())
.type(VisaButtonTypeEnum.EXECUTE.getCode())
.type(VisaButtonTypeEnum.EXECUTE.name())
.build());
} else {
buttons.add(ImGroupButton.builder()
.name(VisaButtonTypeEnum.FORBID.getDesc())
.type(VisaButtonTypeEnum.FORBID.getCode())
.type(VisaButtonTypeEnum.FORBID.name())
.build());
buttons.add(ImGroupButton.builder()
.name(VisaButtonTypeEnum.REDECISION.getDesc())
.type(VisaButtonTypeEnum.REDECISION.getCode())
.type(VisaButtonTypeEnum.REDECISION.name())
.build());
}
break;
@ -279,7 +281,7 @@ public class ChangeRecordRelationServiceImpl extends ServiceImpl<ChangeRecordRel
// IM 群中非群主的人
Optional<ChangeRecordRelation> any = imGroupParticipate.stream()
.filter(i -> Objects.equals(i.getCreateBy(), req.getPersonId()))
.filter(i -> Objects.equals(i.getContentExt(), String.valueOf(req.getOuId())))
.filter(i -> Objects.equals(i.getContent(), String.valueOf(req.getOuId())))
.findAny();
PersonProfileDto profile = visaProfileGateway.getProfile(record.getCreateBy());
if (any.isPresent()) {
@ -289,12 +291,12 @@ public class ChangeRecordRelationServiceImpl extends ServiceImpl<ChangeRecordRel
} else {
resp.setTipsText(String.format(IM_GROUP_PARTICIPATE_TIPS, profile.getRealName(), record.getTopic()));
buttons.add(ImGroupButton.builder()
.name(VisaButtonTypeEnum.AGREE.getDesc())
.type(VisaButtonTypeEnum.AGREE.getCode())
.name(VisaButtonTypeEnum.REJECT.getDesc())
.type(VisaButtonTypeEnum.REJECT.name())
.build());
buttons.add(ImGroupButton.builder()
.name(VisaButtonTypeEnum.REJECT.getDesc())
.type(VisaButtonTypeEnum.REJECT.getCode())
.name(VisaButtonTypeEnum.AGREE.getDesc())
.type(VisaButtonTypeEnum.AGREE.name())
.build());
}
@ -347,6 +349,9 @@ public class ChangeRecordRelationServiceImpl extends ServiceImpl<ChangeRecordRel
@Override
public boolean deleteByIds(List<Long> ids) {
if (CollectionUtils.isEmpty(ids)) {
return false;
}
return lambdaUpdate().in(ChangeRecordRelation::getId, ids)
.setSql("is_delete = id")
.update();

View File

@ -1,9 +1,12 @@
package cn.axzo.nanopart.visa.server.service.impl;
import cn.axzo.apollo.api.req.QueryOrderToBasicReq;
import cn.axzo.apollo.api.res.TaskOrderToBasicRes;
import cn.axzo.apollo.workspace.api.workspace.res.GetDetailRes;
import cn.axzo.apollo.workspace.api.workspace.res.ProjectBriefResp;
import cn.axzo.apollo.workspace.api.workspace.res.ProjectDetailRes;
import cn.axzo.basics.common.constant.enums.OrganizationalNodeTypeEnum;
import cn.axzo.basics.common.constant.enums.OrganizationalUnitTypeEnum;
import cn.axzo.basics.common.util.AssertUtil;
import cn.axzo.basics.common.util.NumberUtil;
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
@ -11,6 +14,8 @@ import cn.axzo.basics.report.api.ReportServiceSDK;
import cn.axzo.basics.report.api.ReportUserContext;
import cn.axzo.basics.report.api.req.ReportFileReq;
import cn.axzo.basics.report.api.sheet.SheetWrapper;
import cn.axzo.digital.req.ListRectifyOrderReq;
import cn.axzo.digital.resp.RectifyOrderResp;
import cn.axzo.foundation.page.PageResp;
import cn.axzo.framework.domain.ServiceException;
import cn.axzo.framework.domain.web.result.PageData;
@ -20,15 +25,15 @@ import cn.axzo.im.center.api.vo.req.GroupDismissRequest;
import cn.axzo.im.center.api.vo.resp.GroupCreateResponse;
import cn.axzo.im.center.common.enums.AppTypeEnum;
import cn.axzo.im.center.common.enums.GroupType;
import cn.axzo.maokai.api.vo.request.CooperateShipQueryReq;
import cn.axzo.maokai.api.vo.request.OrgNodeUserBriefInfoListReq;
import cn.axzo.maokai.api.vo.response.CooperateShipResp;
import cn.axzo.maokai.api.vo.request.OrganizationalUnitQuery;
import cn.axzo.maokai.api.vo.response.OrgNodeUserBriefInfoResp;
import cn.axzo.maokai.api.vo.response.OrganizationalUnitVO;
import cn.axzo.maokai.common.enums.SaasCooperateShipCooperateTypeEnum;
import cn.axzo.msg.center.service.dto.PeerPerson;
import cn.axzo.msg.center.service.pending.request.CardSendRequest;
import cn.axzo.nanopart.visa.api.enums.VisaBillTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaButtonTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaChangeFieldEnum;
import cn.axzo.nanopart.visa.api.enums.VisaConfirmBizTypeEnum;
import cn.axzo.nanopart.visa.api.enums.VisaLogTypeEnum;
@ -38,6 +43,7 @@ import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
import cn.axzo.nanopart.visa.api.request.ChangeRecordButtonOperationReq;
import cn.axzo.nanopart.visa.api.request.ChangeStatusRequest;
import cn.axzo.nanopart.visa.api.request.CheckVisaWithVisaIdReq;
import cn.axzo.nanopart.visa.api.request.ImGroupOperationClearReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeApproveCreateReq;
import cn.axzo.nanopart.visa.api.request.VisaChangeApproveOnlyReq;
@ -63,9 +69,11 @@ import cn.axzo.nanopart.visa.server.dto.VisaExportDto;
import cn.axzo.nanopart.visa.server.dto.VisaLogParam;
import cn.axzo.nanopart.visa.server.mapper.ChangeRecordDao;
import cn.axzo.nanopart.visa.server.rpc.ApolloConstructionAreaGateway;
import cn.axzo.nanopart.visa.server.rpc.ApolloTaskOrderApiGateway;
import cn.axzo.nanopart.visa.server.rpc.DrawingMajorGateway;
import cn.axzo.nanopart.visa.server.rpc.MsgCenterGateway;
import cn.axzo.nanopart.visa.server.rpc.OrganizationalUnitGateway;
import cn.axzo.nanopart.visa.server.rpc.RectifyApiGateway;
import cn.axzo.nanopart.visa.server.rpc.VisaCooperateShipGateway;
import cn.axzo.nanopart.visa.server.rpc.VisaOrganizationalNodeUserGateway;
import cn.axzo.nanopart.visa.server.rpc.VisaProfileGateway;
@ -82,7 +90,6 @@ import cn.axzo.nanopart.visa.server.utils.Constants;
import cn.axzo.orggateway.api.nodeuser.dto.OrgNodeUserDTO;
import cn.axzo.orggateway.api.nodeuser.req.ListOrgNodeUserReq;
import cn.axzo.orgmanax.dto.nodeuser.req.ListNodeUserReq;
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
import cn.axzo.workflow.common.model.dto.CooperationOrgDTO;
import cn.axzo.workflow.common.model.dto.UploadFieldDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO;
@ -112,6 +119,7 @@ import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
@ -120,15 +128,19 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_AMOUNT_CHANGE;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_ATTACH;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_CONTEXT;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_CONTEXT_DESCRIPTION;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_DESCRIPTION;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_HAPPEN_TIME;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_NO;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_PERSON;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_REASON;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_RELATION_AREA;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_RELATION_PROFESSIONAL;
@ -137,12 +149,17 @@ import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_RELATIO
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_RELATION_TASK_ORDER;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_RELATION_VISA_ORDER;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_TOPIC;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_UNIT;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_UNIT_PERSON;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_INITIATOR_WORKSPACE_ID;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_VISA_ID;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.IM_GROUP_BIZ_INFO_VISA_TYPE;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.MSG_CENTER_APP_CODE;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.WORKFLOW_PENDING_INITIATOR_NAME;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.WORKFLOW_PENDING_TOPIC;
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.WORKFLOW_VAR_VISA_TYPE_KEY;
import static cn.axzo.nanopart.visa.server.utils.Constants.DATE_FORMAT;
import static cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum.PROCESSING;
/**
* @author xudawei
@ -186,12 +203,12 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
/**
* 最大变化金额
*/
private final BigDecimal maxAmount = new BigDecimal("9999999999");
private final BigDecimal maxAmount = new BigDecimal("99999999.99");
/**
* 最小变化金额
*/
private final BigDecimal minAmount = new BigDecimal("-9999999999");
private final BigDecimal minAmount = new BigDecimal("-99999999.99");
@Resource
private ChangeRecordBillService changeRecordBillService;
@ -215,6 +232,10 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
private VisaCooperateShipGateway visaCooperateShipGateway;
@Autowired
private ChangeRecordService changeRecordService;
@Resource
private RectifyApiGateway rectifyApiGateway;
@Resource
private ApolloTaskOrderApiGateway taskOrderApiGateway;
/**
* 状态变更
@ -226,7 +247,9 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
// 1 构建前置状态与日志
List<VisaStatusEnum> preStatusList = this.buildPreStatus(request.getUpdateStatus());
// 2 更新状态
this.updateVisaStatus(request.getVisaId(), preStatusList, request.getUpdateStatus());
if (!this.updateVisaStatus(request.getVisaId(), preStatusList, request.getUpdateStatus())) {
return false;
}
// 3 新增日志
this.addLogWhenChangeStatus(request, VisaLogParam.builder()
.personId(request.getPersonId())
@ -259,6 +282,11 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
.set(ChangeRecord::getStatus, updateStatus)
.update();
if (!update) {
//单据最新的状态是更新状态
VisaDetailByIdResponse response = this.detailById(visaId);
if (response.getStatus().equals(updateStatus)) {
return false;
}
throw new ServiceException("更新状态失败");
}
return update;
@ -346,6 +374,9 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
return VisaDetailByIdResponse.builder().build();
}
ChangeRecord visa = this.getById(visaId);
if (Objects.isNull(visa) || Objects.isNull(visa.getId())) {
throw new ServiceException("未查询到单据信息");
}
PersonProfileDto profile = visaProfileGateway.getProfile(visa.getCreateBy());
List<ChangeRecordBill> changeRecordBills = changeRecordBillService.listById(visaId);
@ -373,8 +404,8 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
.createOuName((Objects.nonNull(orgNodeUserDTO) && Objects.nonNull(orgNodeUserDTO.getUnit())) ? orgNodeUserDTO.getUnit().getName() : "") //发起人单位名称
.createOuId((Objects.nonNull(orgNodeUserDTO) && Objects.nonNull(orgNodeUserDTO.getUnit())) ? orgNodeUserDTO.getUnit().getId() : 0l) // 发起人单位
.createBy(visa.getCreateBy()) //发起人Id
.happenTime(Objects.nonNull(visa.getHappenTime()) ? DateUtil.format(visa.getHappenTime(), "yyyy-MM-dd") : "") // 提出时间
.approvalCompleteTime(Objects.nonNull(visa.getApprovalCompleteTime()) ? DateUtil.format(visa.getApprovalCompleteTime(), "yyyy-MM-dd HH:mm:ss") : "") //最终审批时间
.happenTime(Objects.nonNull(visa.getHappenTime()) ? DateUtil.format(visa.getHappenTime(), DATE_FORMAT) : "") // 提出时间
.approvalCompleteTime(Objects.nonNull(visa.getApprovalCompleteTime()) ? DateUtil.format(visa.getApprovalCompleteTime(), Constants.DATE_TIME_FORMAT) : "") //最终审批时间
.relationProfessionalList(VisaDetailByIdResponse.RelationProfessionalDetail.buildProfessionWithObject(visa.getRelationProfessional()))//专业
.relationProfessionalName(this.visaHelper.buildProfessionalName(visa.getRelationProject(), visa.getRelationProfessional())) //专业名称
.relationAreaList(VisaDetailByIdResponse.RelationAreaDetail.buildAreaWithObject(visa.getRelationArea())) //区域
@ -383,11 +414,11 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
.relationProjectName((Objects.nonNull(projectDetailRes) && Objects.nonNull(projectDetailRes.getProjectInfo())) ? projectDetailRes.getProjectInfo().getName() : "") // 工程名称
.relationWorkspaceId(visa.getRelationWorkspaceId()) // 项目Id
.relationWorkspaceName(Objects.nonNull(workspace) ? workspace.getName() : "") // 项目名称
.relationOuAndPersonList(changeRecordConfirmService.listRelationByVisaId(pair.getKey())) // 相关单位与确认人
.relationOuAndPersonList(changeRecordConfirmService.listRelationByVisaId(pair.getKey(), visa.getRelationWorkspaceId())) // 相关单位与确认人
.relationTaskList(CollectionUtils.isEmpty(billMap.get(VisaBillTypeEnum.TASK)) ? Lists.newArrayList() : billMap.get(VisaBillTypeEnum.TASK)) // 关联任务单
.relationRectifyList(CollectionUtils.isEmpty(billMap.get(VisaBillTypeEnum.RECTIFY)) ? Lists.newArrayList() : billMap.get(VisaBillTypeEnum.RECTIFY)) //关联整改单
.relationVisaList(CollectionUtils.isEmpty(billMap.get(VisaBillTypeEnum.DESIGN_VISA)) ? Lists.newArrayList() : billMap.get(VisaBillTypeEnum.DESIGN_VISA)) // 关联变更单
.amountChange(Objects.nonNull(visa.getAmountChange()) ? visa.getAmountChange().toPlainString() : "") // 变更金额
.amountChange(Objects.nonNull(visa.getAmountChange()) ? visa.getAmountChange().toPlainString() : null) // 变更金额
.changeContextAndDescriptionList(this.buildDesc(visaId)) //发生内容及说明
.status(visa.getStatus()) //状态TO_REPORT:待提报;DECIDING:决策中;EXECUTING:执行中;APPROVING:审批中;COMPLETED:已完成;FORBIDED:已废除;REPORT_FROM_APPROVE:审批到待提报;DECIDING_FROM_APPROVE:审批到决策中 EXECUTING
.attach(this.buildAttachUploadFile(visaId)) // 附件
@ -480,18 +511,12 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
@Transactional(rollbackFor = Exception.class)
public Long tempCreateVisaChangeRecord(VisaChangeTempCreateReq req) {
AssertUtil.isTrue(NumberUtil.isPositiveNumber(req.getRelationWorkspaceId()), "关联项目不能为空");
AssertUtil.isTrue(NumberUtil.isPositiveNumber(req.getOperatorOuId()) && NumberUtil.isPositiveNumber(req.getOperatorPersonId()),
AssertUtil.isTrue(NumberUtil.isPositiveNumber(req.getOperatorOuId())
&& NumberUtil.isPositiveNumber(req.getOperatorPersonId())
&& NumberUtil.isPositiveNumber(req.getOperatorNodeId())
&& NumberUtil.isPositiveNumber(req.getOperatorOuType()),
"操作人信息不能为空");
if (NumberUtil.isNotPositiveNumber(req.getOperatorOuType())) {
CooperateShipQueryReq shipQueryReq = CooperateShipQueryReq.builder()
.personId(req.getOperatorPersonId())
.workspaceId(req.getRelationWorkspaceId())
.ouId(req.getOperatorOuId())
.build();
List<CooperateShipResp> shipRespList = visaCooperateShipGateway.genericQuery(shipQueryReq);
AssertUtil.notEmpty(shipRespList, "操作人所在单位信息不能为空");
req.setOperatorOuType(shipRespList.get(0).getCooperateType());
}
ChangeRecord changeRecord;
List<VisaConfirmDto> confirmPerson = Lists.newArrayList();
VisaAddLogContext oldContext = null;
@ -570,7 +595,8 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
.map(o -> VisaBillDto.builder()
.visaId(changeRecord.getId())
.visaType(changeRecord.getType())
.billId(o)
.billId(o.getId())
.billNo(o.getNo())
.billType(VisaBillTypeEnum.valueOf(os.getKey()))
.createBy(req.getOperatorPersonId())
.updateBy(req.getOperatorPersonId())
@ -620,6 +646,7 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
IM_GROUP_BIZ_INFO_INITIATOR_WORKSPACE_ID, req.getRelationWorkspaceId(),
IM_GROUP_BIZ_INFO_VISA_TYPE, req.getType().name()));
GroupCreateResponse imGroup = msgCenterGateway.createImGroup(request);
AssertUtil.notNull(imGroup, "IM 群创建失败");
updateImInfo(visaId, imGroup);
// 更新主表状态
@ -695,53 +722,127 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
Map<String, Object> formVariables = new HashMap<>();
// 传递表单数据
formVariables.put(FORM_FIELD_NO, req.getNo());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
final SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
formVariables.put(FORM_FIELD_HAPPEN_TIME, sdf.format(req.getHappenTime()));
formVariables.put(FORM_FIELD_TOPIC, req.getTopic());
formVariables.put(FORM_FIELD_RELATION_PROJECT, req.getRelationProject());
ProjectDetailRes projectDetailRes = visaProjectApiGateway.getProjectById(req.getRelationProject());
formVariables.put(FORM_FIELD_RELATION_PROJECT, projectDetailRes.getProjectInfo().getName());
formVariables.put(FORM_FIELD_RELATION_PROFESSIONAL, visaHelper.buildProfessionalName(req.getRelationProject(), req.getRelationProfessional()));
formVariables.put(FORM_FIELD_REASON, req.getReason());
formVariables.put(FORM_FIELD_RELATION_AREA, visaHelper.buildAreaName(req.getRelationArea()));
formVariables.put(FORM_FIELD_CONTEXT_DESCRIPTION, req.getChangeContextAndDescriptionList());
formVariables.put(FORM_FIELD_CONTEXT_DESCRIPTION, buildContextDescription(req.getChangeContextAndDescriptionList()));
formVariables.put(FORM_FIELD_UNIT_PERSON, buildUnitPerson(req.getRelationUnitAndPersonList(), req.getRelationWorkspaceId()));
// 非必填项
if (Objects.nonNull(req.getAmountChange())) {
String amountDesc = "不变";
if (req.getAmountChange().compareTo(BigDecimal.ZERO) > 0) {
amountDesc = "增加" + req.getAmountChange().toPlainString() + "";
} else if (req.getAmountChange().compareTo(BigDecimal.ZERO) < 0) {
amountDesc = "减少" + req.getAmountChange().toPlainString() + "";
}
formVariables.put(FORM_FIELD_AMOUNT_CHANGE, amountDesc);
formVariables.put(FORM_FIELD_AMOUNT_CHANGE, VisaHelper.buildChangeAmount(req.getAmountChange()));
}
// 三种单据
if (MapUtils.isNotEmpty(req.getRelationOrderMap())) {
List<Long> taskOrderIds = req.getRelationOrderMap().getOrDefault(VisaBillTypeEnum.TASK.name(), null);
if (CollectionUtils.isNotEmpty(taskOrderIds)) {
formVariables.put(FORM_FIELD_RELATION_TASK_ORDER, taskOrderIds);
List<VisaChangeTempCreateReq.OrderSimpleModel> taskOrders = req.getRelationOrderMap().getOrDefault(VisaBillTypeEnum.TASK.name(), null);
if (CollectionUtils.isNotEmpty(taskOrders)) {
formVariables.put(FORM_FIELD_RELATION_TASK_ORDER, taskOrders);
}
List<Long> rectificationOrderIds = req.getRelationOrderMap().getOrDefault(VisaBillTypeEnum.RECTIFY.name(), null);
if (CollectionUtils.isNotEmpty(rectificationOrderIds)) {
formVariables.put(FORM_FIELD_RELATION_RECTIFICATION_ORDER, rectificationOrderIds);
List<VisaChangeTempCreateReq.OrderSimpleModel> rectificationOrders = req.getRelationOrderMap().getOrDefault(VisaBillTypeEnum.RECTIFY.name(), null);
if (CollectionUtils.isNotEmpty(rectificationOrders)) {
formVariables.put(FORM_FIELD_RELATION_RECTIFICATION_ORDER, rectificationOrders);
}
List<Long> visaOrderIds = req.getRelationOrderMap().getOrDefault(VisaBillTypeEnum.DESIGN_VISA.name(), null);
if (CollectionUtils.isNotEmpty(visaOrderIds)) {
formVariables.put(FORM_FIELD_RELATION_VISA_ORDER, visaOrderIds);
List<VisaChangeTempCreateReq.OrderSimpleModel> visaOrders = req.getRelationOrderMap().getOrDefault(VisaBillTypeEnum.DESIGN_VISA.name(), null);
List<Map<String, String>> visaOrderMaps = new ArrayList<>();
visaOrders.forEach(i -> {
Map<String, String> visaOrderMap = new HashMap<>();
visaOrderMap.put("id", i.getNo());
visaOrderMap.put("name", i.getName());
visaOrderMaps.add(visaOrderMap);
});
if (CollectionUtils.isNotEmpty(visaOrders)) {
formVariables.put(FORM_FIELD_RELATION_VISA_ORDER, visaOrderMaps);
}
}
formVariables.put(FORM_FIELD_ATTACH, req.getAttach());
processDto.setStartFormVariables(formVariables);
processDto.setProcessDefinitionKey(req.getType().getProcessDefinitionKey());
Map<String, Object> pendingVariables = new HashMap<>();
PersonProfileDto profile = visaProfileGateway.getProfile(req.getOperatorPersonId());
pendingVariables.put(WORKFLOW_PENDING_INITIATOR_NAME, profile.getRealName());
pendingVariables.put(WORKFLOW_PENDING_TOPIC, req.getTopic());
processDto.setPendingVariables(pendingVariables);
processDto.setCooperationOrg(new CooperationOrgDTO());
return workflowGateway.processInstanceCreate(processDto);
}
private List<Map<String, Object>> buildUnitPerson(List<VisaChangeTempCreateReq.RelationUnitAndPerson> list, Long workspaceId) {
if (CollectionUtils.isEmpty(list)) {
return Collections.emptyList();
}
List<Long> ouIds = list.stream().map(VisaChangeTempCreateReq.RelationUnitAndPerson::getOuId).distinct().collect(Collectors.toList());
Map<Long, OrganizationalUnitVO> unitMap = organizationalUnitGateway.list(OrganizationalUnitQuery.builder().unitIds(ouIds).build())
.stream().collect(Collectors.toMap(OrganizationalUnitVO::getId, Function.identity(), (s, t) -> s));
Map<Long, List<VisaChangeTempCreateReq.RelationUnitAndPerson>> unitGroupBy = list.stream().collect(Collectors.groupingBy(VisaChangeTempCreateReq.RelationUnitAndPerson::getOuId, Collectors.toList()));
List<Map<String, Object>> unitPersons = new ArrayList<>();
unitGroupBy.forEach((unitId, persons) -> {
Map<String, Object> unitPerson = new HashMap<>();
OrganizationalUnitVO unitVo = unitMap.get(unitId);
unitPerson.put(FORM_FIELD_UNIT, Objects.isNull(unitVo) ? "" : unitVo.getName() + "(" + OrganizationalUnitTypeEnum.getByType(unitVo.getType()).getDesc() + ")");
List<OrgNodeUserDTO> personInfos = getPersonInfos(workspaceId, unitId, persons);
unitPerson.put(FORM_FIELD_PERSON, buildPersonInfosStr(personInfos));
unitPersons.add(unitPerson);
});
return unitPersons;
}
private String buildPersonInfosStr(List<OrgNodeUserDTO> personInfos) {
StringBuilder personInfosStr = new StringBuilder();
if (CollectionUtils.isEmpty(personInfos)) {
return personInfosStr.toString();
}
for (OrgNodeUserDTO info : personInfos) {
if (personInfosStr.length() > 0) {
personInfosStr.append(",");
}
personInfosStr.append(info.getPersonProfile().getRealName())
.append(Objects.isNull(info.getJob()) ? "" : "-" + info.getJob().getName());
}
return personInfosStr.toString();
}
private List<OrgNodeUserDTO> getPersonInfos(Long workspaceId, Long unitId, List<VisaChangeTempCreateReq.RelationUnitAndPerson> persons) {
PageResp<OrgNodeUserDTO> pageResp = visaOrganizationalNodeUserGateway.list(ListOrgNodeUserReq.builder()
.personIds(persons.stream().map(VisaChangeTempCreateReq.RelationUnitAndPerson::getPersonId).collect(Collectors.toList()))
.organizationalUnitId(unitId)
.workspaceId(workspaceId)
.needs(ListNodeUserReq.Needs.builder().job(true).personProfile(true).build()).build());
if (Objects.isNull(pageResp) || CollectionUtils.isEmpty(pageResp.getData())) {
return Collections.emptyList();
}
return pageResp.getData();
}
private List<Map<String, Object>> buildContextDescription(List<VisaChangeTempCreateReq.ChangeContextAndDescription> list) {
if (CollectionUtils.isEmpty(list)) {
return Collections.emptyList();
}
List<Map<String, Object>> contextDescriptions = new ArrayList<>();
list.forEach(i -> {
Map<String, Object> contextDescription = new HashMap<>();
UploadFieldDTO uploadFieldDTO = new UploadFieldDTO();
uploadFieldDTO.setFileKey(i.getFileKey());
uploadFieldDTO.setFileName(i.getFileName());
uploadFieldDTO.setFileUrl(i.getFileUrl());
contextDescription.put(FORM_FIELD_CONTEXT, uploadFieldDTO);
contextDescription.put(FORM_FIELD_DESCRIPTION, i.getText());
contextDescriptions.add(contextDescription);
});
return contextDescriptions;
}
/**
* 更新
*
@ -753,17 +854,20 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
ChangeRecord changeRecord = new ChangeRecord();
changeRecord.setId(visaId);
changeRecord.setApprovalId(processInstanceId);
changeRecord.setApprovalStatus(BpmnProcessInstanceResultEnum.PROCESSING.getStatus());
changeRecord.setApprovalStatus(PROCESSING.getStatus());
updateById(changeRecord);
// 设置关联表的审批信息
ChangeRecordRelation processRelation = new ChangeRecordRelation();
processRelation.setVisaId(visaId);
processRelation.setVarName(VisaRelationFieldEnum.PROCESS_INSTANCE.getCode());
processRelation.setVarName(VisaRelationFieldEnum.PROCESS_INSTANCE_OF_VISA.name());
processRelation.setVarType(VisaRelationVarTypeEnum.STRING.getType());
processRelation.setContent(processInstanceId);
processRelation.setContentExt(BpmnProcessInstanceResultEnum.PROCESSING.getStatus());
processRelation.setContentExt(PROCESSING.getStatus());
changeRecordRelationService.save(processRelation);
// 更新单据关联状态为 true
changeRecordBillService.billRelationStatus(visaId, true);
}
private List<BpmnTaskDelegateAssigner> buildApprovers(List<VisaChangeApproveCreateReq.ApprovePersonInfo> approvePersonInfoList) {
@ -790,8 +894,8 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
*/
@Override
public PageData<VisaChangePageSearchResp> page(VisaChangePageSearchReq req) {
/*筛查条件校验*/
validSearchCondition(req);
/*筛查条件校验与修正*/
validAndAmendSearchCondition(req);
// Set<Long> permissionVisaIdSet = this.fetchPermissionVisaIdSet(req);
// if (CollectionUtils.isEmpty(permissionVisaIdSet)) {
@ -829,9 +933,10 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
Map<Long, OrgNodeUserBriefInfoResp> initiatorMap = getPersonBriefInfoMap(req.getWorkspaceId(), initiatorPersonIds);
AssertUtil.isTrue(CollUtil.isNotEmpty(initiatorMap), "发起人信息获取失败");
/*组装数据*/
return initiators.stream()
return new ArrayList<>(initiators.stream()
.map(i -> buildInitiatorResp(initiatorMap, i))
.collect(Collectors.toList());
.collect(Collectors.toMap(i -> i.getPersonId() + ":" + i.getJobId(), Function.identity(), (v1, v2) -> v1))
.values());
}
@Override
@ -843,6 +948,10 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
fields = Arrays.asList(VisaChangeFieldEnum.values());
}
filter.setCurrentPersonId(req.getPersonId());
filter.setCurrentOuId(req.getOuId());
filter.setCurrentWorkspaceId(req.getWorkspaceId());
// Set<Long> permissionVisaIdSet = this.fetchPermissionVisaIdSet(filter);
List<ChangeRecord> changeRecordList = Lists.newArrayList();
// if (CollectionUtils.isNotEmpty(permissionVisaIdSet)) {
@ -923,8 +1032,10 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
// .in(ChangeRecord::getId, permissionVisaIdSet)
.eq(NumberUtil.isPositiveNumber(filter.getWorkspaceId()), ChangeRecord::getRelationWorkspaceId, filter.getWorkspaceId())
.eq(Objects.nonNull(filter.getType()), ChangeRecord::getType, filter.getType())
.eq(StringUtils.hasText(filter.getKeyword()), ChangeRecord::getNo, filter.getKeyword())
.or(StringUtils.hasText(filter.getKeyword()), wrapper -> wrapper.like(ChangeRecord::getTopic, filter.getKeyword()))
.and(StringUtils.hasText(filter.getKeyword()),
wrapper -> wrapper.like(ChangeRecord::getTopic, filter.getKeyword())
.or()
.eq(ChangeRecord::getNo, filter.getKeyword()))
.eq(NumberUtil.isPositiveNumber(filter.getProjectId()), ChangeRecord::getRelationProject, filter.getProjectId())
.in(CollectionUtils.isNotEmpty(filter.getInitiators()), ChangeRecord::getCreateBy, filter.getInitiators())
.in(CollectionUtils.isNotEmpty(filter.getStatuses()), ChangeRecord::getStatus, filter.getStatuses())
@ -939,6 +1050,17 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
queryChainWrapper.between(ChangeRecord::getApprovalCompleteTime, filter.getApproveCompletedDate().get(0), filter.getApproveCompletedDate().get(1));
queryChainWrapper.eq(ChangeRecord::getStatus, VisaStatusEnum.COMPLETED);
}
queryChainWrapper.apply(" CASE WHEN status = 'TO_REPORT' THEN create_by = " + filter.getCurrentPersonId() + " else true end");
// 单据选择器调用需要过滤掉待提报和已废止的记录
if (Objects.nonNull(filter.getFrom()) && VisaChangePageSearchReq.FromEnum.SELECT.equals(filter.getFrom())) {
queryChainWrapper.apply("CASE " +
"WHEN STATUS = 'TO_REPORT' THEN FALSE " +
"WHEN STATUS = 'FORBIDED' THEN FALSE " +
"ELSE TRUE " +
"END");
}
return queryChainWrapper;
}
@ -1033,6 +1155,8 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
} else {
billMainMap = null;
}
// 操作列按钮
Map<Long, Set<VisaButtonTypeEnum>> operateBtnMap = visaHelper.fetchBtnsByBizTypeAndStatus(records, req.getCurrentPersonId(), req.getCurrentOuId(), req.getCurrentWorkspaceId());
/*组装信息*/
return records.stream()
@ -1043,7 +1167,9 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
// 发起人
resp.setInitiator(buildInitiatorResp(initiatorMap, visaIdInitiatorMap.get(r.getId())));
// 是否被其他单据关联
resp.setIsRelated(req.getNeedRelatedBill() ? Objects.nonNull(billMainMap) && Objects.nonNull(billMainMap.get(r.getId())) : null);
resp.setIsRelated(req.getNeedRelatedBill() ? CollUtil.isNotEmpty(billMainMap) && Objects.nonNull(billMainMap.get(r.getId())) : null);
// 操作列按钮
resp.setOperateBtnSet(CollUtil.isNotEmpty(operateBtnMap) ? operateBtnMap.get(r.getId()) : null);
return resp;
})
.collect(Collectors.toList());
@ -1070,20 +1196,35 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
return initiators.stream().collect(Collectors.toMap(ChangeRecordConfirm::getVisaId, Function.identity()));
}
private static void validSearchCondition(VisaChangePageSearchReq req) {
private static void validAndAmendSearchCondition(VisaChangePageSearchReq req) {
if (CollectionUtils.isNotEmpty(req.getAmountChange())) {
AssertUtil.isFalse(req.getAmountChange().size() < 2, "请填写金额范围");
// 最大最小值的符号必须相同
AssertUtil.isTrue(Objects.equals(req.getAmountChange().get(0).signum(), req.getAmountChange().get(1).signum()), "请输入合法的变更金额范围");
AssertUtil.isTrue(req.getAmountChange().get(0).compareTo(req.getAmountChange().get(1)) < 0, "最大金额不能小于最小金额");
BigDecimal min = req.getAmountChange().get(0);
BigDecimal max = req.getAmountChange().get(1);
BigDecimal zero = new BigDecimal("0");
// 若元素不存在0则最大最小值的符号必须相同
if (!Objects.equals(min, zero) && !Objects.equals(max, zero)) {
AssertUtil.isTrue(Objects.equals(min.signum(), max.signum()), "请输入合法的变更金额范围");
}
AssertUtil.isTrue(min.compareTo(max) <= 0, "最大金额不能小于最小金额");
}
if (CollectionUtils.isNotEmpty(req.getHappenTime())) {
AssertUtil.isFalse(req.getHappenTime().size() < 2, "请填写提出时间范围");
AssertUtil.isTrue(req.getHappenTime().get(0).compareTo(req.getHappenTime().get(1)) < 0, "提出结束时间不能小于开始时间");
Date start = req.getHappenTime().get(0);
Date end = req.getHappenTime().get(1);
AssertUtil.isTrue(start.compareTo(end) <= 0, "提出结束时间不能小于开始时间");
// 时间修正补充时分秒数据起始时间为0000:00:00结束时间为23:59:59
req.getHappenTime().set(0, DateUtil.beginOfDay(start));
req.getHappenTime().set(1, DateUtil.endOfDay(end));
}
if (CollectionUtils.isNotEmpty(req.getApproveCompletedDate())) {
AssertUtil.isFalse(req.getApproveCompletedDate().size() < 2, "请填写审批完成时间范围");
AssertUtil.isTrue(req.getApproveCompletedDate().get(0).compareTo(req.getApproveCompletedDate().get(1)) < 0, "审批完成结束时间不能小于开始时间");
Date start = req.getApproveCompletedDate().get(0);
Date end = req.getApproveCompletedDate().get(1);
AssertUtil.isTrue(start.compareTo(end) <= 0, "审批完成结束时间不能小于开始时间");
// 时间修正补充时分秒数据起始时间为0000:00:00结束时间为23:59:59
req.getApproveCompletedDate().set(0, DateUtil.beginOfDay(start));
req.getApproveCompletedDate().set(1, DateUtil.endOfDay(end));
}
}
@ -1097,6 +1238,7 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
.ouId(req.getOperatorOuId())
.workspaceId(req.getRelationWorkspaceId())
.projectId(req.getRelationProject())
.nodeId(req.getOperatorNodeId())
.operator(req.getOperatorPersonId())
.build();
}
@ -1117,9 +1259,11 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
}
private void validVisaChangeForm(VisaChangeApproveCreateReq req) {
// 单号项目内唯一性
ChangeRecord visaRecord = getVisaByWorkspaceIdAndNo(req.getRelationWorkspaceId(), req.getNo());
AssertUtil.isNull(visaRecord, "已存在相同单号的变更签证单据,请修改");
if (!req.isSkipNoOnlyOnce()) {
// 单号项目内唯一性
ChangeRecord visaRecord = getVisaByWorkspaceIdAndNo(req.getRelationWorkspaceId(), req.getNo());
AssertUtil.isNull(visaRecord, "已存在相同单号的变更签证单据,请修改");
}
// 工程存在性
ProjectDetailRes projectById = visaProjectApiGateway.getProjectById(req.getRelationProject());
AssertUtil.notNull(projectById, "工程不存在");
@ -1129,6 +1273,7 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
AssertUtil.isTrue(DateUtil.isIn(req.getHappenTime(), DateUtil.offsetDay(now, -30), now), "提出时间不可早于一个月前/晚于当前日期,请重新选择");
// 发生内容及说明合法性
if (CollectionUtils.isNotEmpty(req.getChangeContextAndDescriptionList())) {
AssertUtil.isTrue(req.getChangeContextAndDescriptionList().size() <= refreshableConfiguration.getVerifyChangeContextLimit(), "发生内容及说明数量过多,请重新填写");
req.getChangeContextAndDescriptionList().forEach(c -> {
AssertUtil.isTrue(1 == c.getType() || 2 == c.getType(), "请选择发生内容类型");
AssertUtil.isFalse(!StringUtils.hasText(c.getText()) && !StringUtils.hasText(c.getFileUrl()), "存在为空的发生内容及说明,请填写");
@ -1168,32 +1313,29 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
// 关联单据合法性
if (CollUtil.isNotEmpty(req.getRelationOrderMap())) {
req.getRelationOrderMap().forEach((key, value) -> {
if (Objects.equals(VisaRelationFieldEnum.TASK_ORDER.name(), key)) {
// 关联单据数量限制
AssertUtil.isTrue(value.size() <= refreshableConfiguration.getVerifyVisaLimit(),
String.format("最多可关联%d个%s单请重新选择", refreshableConfiguration.getVerifyVisaLimit(), VisaBillTypeEnum.valueOf(key).getDesc()));
if (Objects.equals(VisaBillTypeEnum.TASK.name(), key)) {
/*任务单*/
// 关联单据数量限制
AssertUtil.isTrue(value.size() <= refreshableConfiguration.getVerifyVisaLimit(),
String.format("最多可关联%d个变更单请重新选择", refreshableConfiguration.getVerifyVisaLimit()));
validBillIfRelated(VisaBillTypeEnum.TASK, value, req.getType());
} else if (Objects.equals(VisaRelationFieldEnum.RECTIFICATION_ORDER.name(), key)) {
List<String> taskNos = value.stream().map(VisaChangeTempCreateReq.OrderSimpleModel::getNo).collect(Collectors.toList());
validTaskBillIfRelated(taskNos, req.getType());
} else if (Objects.equals(VisaBillTypeEnum.RECTIFY.name(), key)) {
/*整改单*/
// 关联单据数量限制
AssertUtil.isTrue(value.size() <= refreshableConfiguration.getVerifyVisaLimit(),
String.format("最多可关联%d个变更单请重新选择", refreshableConfiguration.getVerifyVisaLimit()));
validBillIfRelated(VisaBillTypeEnum.RECTIFY, value, req.getType());
} else if (Objects.equals(VisaRelationFieldEnum.VISA_ORDER.name(), key)) {
List<Long> billIds = value.stream().map(VisaChangeTempCreateReq.OrderSimpleModel::getId).collect(Collectors.toList());
validBillIfRelated(VisaBillTypeEnum.RECTIFY, billIds, req.getType());
} else if (Objects.equals(VisaBillTypeEnum.DESIGN_VISA.name(), key)) {
/*变更单*/
AssertUtil.isTrue(VisaTypeEnum.TECHNOLOGY_APPROVED.equals(req.getType()) || VisaTypeEnum.PROJECT_VISA.equals(req.getType()), "变更单关联单据仅支持技术核定/工程签证");
// 关联单据数量限制
AssertUtil.isTrue(value.size() <= refreshableConfiguration.getVerifyVisaLimit(),
String.format("最多可关联%d个变更单请重新选择", refreshableConfiguration.getVerifyVisaLimit()));
// 关联单据合法性是否存在状态是否合法
List<ChangeRecord> relationVisa = listByIds(value);
List<Long> billIds = value.stream().map(VisaChangeTempCreateReq.OrderSimpleModel::getId).collect(Collectors.toList());
List<ChangeRecord> relationVisa = listByIds(billIds);
AssertUtil.notEmpty(relationVisa, "关联的单据不存在");
relationVisa.forEach(r -> {
AssertUtil.isTrue(Objects.equals(r.getRelationWorkspaceId(), req.getRelationWorkspaceId()), "关联的单据所属项目不匹配");
AssertUtil.isFalse(Objects.equals(r.getStatus(), VisaStatusEnum.TO_REPORT) || Objects.equals(r.getStatus(), VisaStatusEnum.FORBIDED), String.format("单据%s状态为%s不允许被关联", r.getNo(), r.getStatus().getDesc()));
});
validBillIfRelated(VisaBillTypeEnum.DESIGN_VISA, value, req.getType());
validBillIfRelated(VisaBillTypeEnum.DESIGN_VISA, billIds, req.getType());
} else {
throw new ServiceException("不支持的关联单据类型");
}
@ -1225,6 +1367,21 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
}));
}
private void validTaskBillIfRelated(List<String> taskNos, VisaTypeEnum visaType) {
AssertUtil.notEmpty(taskNos, "关联单据Id不能为空");
AssertUtil.notNull(visaType, "单据类型不能为空");
List<ChangeRecordBill> mainBill = changeRecordBillService.findTaskMainBill(taskNos);
mainBill.stream()
.collect(Collectors.groupingBy(ChangeRecordBill::getBillNo))
.forEach((k, v) -> v.stream()
.filter(m -> Objects.equals(m.getVisaType(), visaType))
.findAny()
.ifPresent(m -> {
log.info("{} bill {} is related by {} visa {}", m.getBillType(), m.getBillId(), m.getVisaType(), m.getVisaId());
throw new ServiceException(String.format("单据%s已被其他单据关联请重新选择", m.getBillNo()));
}));
}
/**
* 通过变更签证Id获取Entity
*
@ -1236,10 +1393,12 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
return ChangeRecord.builder().build();
}
return this.lambdaQuery()
.eq(ChangeRecord::getId, visaId).one();
.eq(ChangeRecord::getId, visaId)
.eq(ChangeRecord::getIsDelete, 0).one();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void forbid(ChangeRecordButtonOperationReq req) {
ChangeRecord record = getById(req.getVisaId());
@ -1255,9 +1414,10 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
changeStatus(changeStatusRequest);
if (Objects.nonNull(record.getImGroupId())) {
GroupDismissRequest request = new GroupDismissRequest();
req.setVisaId(req.getVisaId());
request.setTid(record.getImGroupId());
// 解散 IM 群聊
msgCenterGateway.dismissImGroup(request);
log.info("dismiss im group success");
}
if (StringUtils.hasText(record.getApprovalId())) {
BpmnProcessInstanceAbortDTO abort = new BpmnProcessInstanceAbortDTO();
@ -1268,7 +1428,8 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
.ouId(String.valueOf(req.getOperatorOuId()))
.tenantId(String.valueOf(req.getOperatorWorkspaceId()))
.build());
workflowGateway.processInstanceAbort(abort);
Boolean result = workflowGateway.processInstanceAbort(abort);
log.info("invoke abort process instance result:{}", result);
}
// 取消已关联整改单任务单变更单
changeRecordBillService.deleteByVisaId(record.getId());
@ -1315,25 +1476,28 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
}
@Override
@Transactional(rollbackFor = Exception.class)
public Long approveCreateOnlyVisaChangeRecord(VisaChangeApproveOnlyReq req) {
ChangeRecord visa = getById(req.getVisaId());
req.setOperatorWorkspaceId(visa.getRelationWorkspaceId());
validOperationPermission(req.getVisaId(), req.getOperatorPersonId(), req.getOperatorOuId(), req.getOperatorWorkspaceId());
AssertUtil.isTrue(!StringUtils.hasText(visa.getApprovalId())
|| (StringUtils.hasText(visa.getApprovalId()) && !Objects.equals(VisaStatusEnum.APPROVING.name(), visa.getApprovalStatus())),
"当前单据审批中,不允许操作");
// 组装 REQ 参数
VisaChangeApproveCreateReq createReq = buildVisaChangeApproveCreateReqByVisaId(req.getVisaId());
AssertUtil.notNull(createReq, "未找到变洽签单据");
createReq.setSkipNoOnlyOnce(true);
// 校验
validVisaChangeForm(createReq);
createReq.setActivityId(req.getActivityId());
createReq.setApprovePersonInfoList(req.getApprovePersonInfoList());
createReq.setOperatorOuId(req.getOperatorOuId());
createReq.setOperatorPersonId(req.getOperatorPersonId());
createReq.setRelationWorkspaceId(req.getOperatorWorkspaceId());
String processInstanceId = createProcessInstance(createReq, req.getVisaId());
// 更新主表中的审批字段记录变量表的审批的信息
updateApprovalInfo(visa.getId(), processInstanceId);
// 更新主表状态
changeStatus(ChangeStatusRequest.builder()
@ -1343,6 +1507,10 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
.ouId(req.getOperatorOuId())
.workspaceId(req.getOperatorWorkspaceId())
.build());
String processInstanceId = createProcessInstance(createReq, req.getVisaId());
// 更新主表中的审批字段记录变量表的审批的信息
updateApprovalInfo(visa.getId(), processInstanceId);
return req.getVisaId();
}
@ -1373,12 +1541,6 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
OrganizationalUnitVO unitInfo = organizationalUnitGateway.getUnitInfo(req.getOperatorOuId());
PersonProfileDto profile = visaProfileGateway.getProfile(req.getOperatorPersonId());
String amountDesc = "不变";
if (visa.getAmountChange().compareTo(BigDecimal.ZERO) > 0) {
amountDesc = "增加" + visa.getAmountChange().toPlainString() + "";
} else if (visa.getAmountChange().compareTo(BigDecimal.ZERO) < 0) {
amountDesc = "减少" + visa.getAmountChange().toPlainString() + "";
}
cardRequest.setBizParam(new JSONObject(Maps.of(
"topic", visa.getTopic(),
@ -1386,7 +1548,7 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
"initiatorName", profile.getRealName(),
"initiatorUnitName", unitInfo.getName(),
"visaType", visa.getType().getDesc(),
"amountChange", amountDesc
"amountChange", VisaHelper.buildChangeAmount(visa.getAmountChange())
)));
msgCenterGateway.sendCardToCroup(cardRequest);
}
@ -1466,10 +1628,69 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
}
// 关联单据
List<ChangeRecordBill> bills = changeRecordBillService.listById(changeRecord.getId());
// 实时构建单据名称 TODO 此处应该可以使用异步进行优化
if (CollectionUtils.isNotEmpty(bills)) {
req.setRelationOrderMap(bills.stream().collect(Collectors.groupingBy(b -> b.getBillType().name(),
Collectors.mapping(ChangeRecordBill::getBillId, Collectors.toList())))
);
Map<String, List<VisaChangeTempCreateReq.OrderSimpleModel>> relationOrderMap = com.google.common.collect.Maps.newHashMap();
bills.stream().collect(Collectors.groupingBy(b -> b.getBillType().name(),
Collectors.mapping(Function.identity(), Collectors.toList())))
.forEach((k, v) -> {
if (VisaBillTypeEnum.TASK.name().equals(k)) {
// 获取任务单数据
QueryOrderToBasicReq queryOrderToBasicReq = new QueryOrderToBasicReq();
queryOrderToBasicReq.setWorkspaceId(req.getRelationWorkspaceId());
queryOrderToBasicReq.setTaskNos(v.stream().map(ChangeRecordBill::getBillNo).collect(Collectors.toList()));
queryOrderToBasicReq.setPage(1);
queryOrderToBasicReq.setPageSize(v.size());
Map<String, TaskOrderToBasicRes> taskOrderMap = taskOrderApiGateway.pageOrderByForBasic(queryOrderToBasicReq).getData()
.stream()
.collect(Collectors.toMap(TaskOrderToBasicRes::getTaskNo, Function.identity()));
// 构建关联任务单
relationOrderMap.put(k, v.stream()
.map(item -> VisaChangeTempCreateReq.OrderSimpleModel.builder()
.id(item.getBillId())
.no(item.getBillNo())
.name(Optional.ofNullable(taskOrderMap.get(item.getBillNo()))
.map(TaskOrderToBasicRes::getTaskName)
.orElse(""))
.build())
.collect(Collectors.toList()));
} else if (VisaBillTypeEnum.RECTIFY.name().equals(k)) {
// 获取整改单数据
ListRectifyOrderReq rectifyOrderReq = ListRectifyOrderReq.builder()
.ids(v.stream().map(ChangeRecordBill::getBillId).collect(Collectors.toSet()))
.build();
Map<Long, RectifyOrderResp> rectifyOrderMap = rectifyApiGateway.listRectifyOrders(rectifyOrderReq)
.stream()
.collect(Collectors.toMap(RectifyOrderResp::getId, Function.identity(), (v1, v2) -> v1));
// 构建关联整改单
relationOrderMap.put(k, v.stream()
.map(item -> VisaChangeTempCreateReq.OrderSimpleModel.builder()
.id(item.getBillId())
.no(item.getBillNo())
.name(Optional.ofNullable(rectifyOrderMap.get(item.getBillId()))
.map(RectifyOrderResp::getBizName)
.orElse(""))
.build())
.collect(Collectors.toList()));
} else if (VisaBillTypeEnum.DESIGN_VISA.name().equals(k)) {
// 获取设计单数据
Map<Long, ChangeRecord> changeRecordMap = listByIds(v.stream().map(ChangeRecordBill::getBillId).collect(Collectors.toSet()))
.stream()
.collect(Collectors.toMap(ChangeRecord::getId, Function.identity(), (v1, v2) -> v1));
// 构建关联设计单
relationOrderMap.put(k, v.stream()
.map(item -> VisaChangeTempCreateReq.OrderSimpleModel.builder()
.id(item.getBillId())
.no(item.getBillNo())
.name(Optional.ofNullable(changeRecordMap.get(item.getBillId()))
.map(ChangeRecord::getTopic)
.orElse(""))
.build())
.collect(Collectors.toList())
);
}
});
req.setRelationOrderMap(relationOrderMap);
}
// 附件
List<ChangeRecordRelation> attach = changeRecordRelationService.findByVisaAndVarName(changeRecord.getId(), VisaRelationFieldEnum.ATTACHMENT.name());
@ -1486,4 +1707,14 @@ public class ChangeRecordServiceImpl extends ServiceImpl<ChangeRecordDao, Change
}
return req;
}
/**
* 根据读取详情中的变签-校验
*/
@Override
public void checkVisaWithVisaId(CheckVisaWithVisaIdReq req) {
VisaDetailByIdResponse response = this.detailById(req.getVisaId());
req.check(response);
// this.validVisaChangeForm(this.buildVisaChangeApproveCreateReqByVisaId(req.getVisaId()));
}
}

View File

@ -1,5 +1,12 @@
package cn.axzo.nanopart.visa.server.utils;
import cn.axzo.orggateway.api.nodeuser.dto.OrgNodeUserDTO;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Objects;
/**
* @author xudawei@axzo.cn
* @date 2025/2/7
@ -50,4 +57,52 @@ public class Constants {
* 工程签证数据权限的code
*/
public static final String SPLIT_TREE_NODE_CHAT = "-";
/**
* 变更签证日志
*/
public static final String VISA_LOG_SNAPSHOT_SCENE = "visa_log";
/**
* 变更签证日志-快照
*/
public static final String VISA_LOG_SNAPSHOT_TAG_SNAPSHOT = "visa_log_snapshot";
/**
* 变更签证日志-快照
*/
public static final String VISA_LOG_SNAPSHOT_LEVEL = "INFO";
/**
* 年月日格式
*/
public static final String DATE_FORMAT = "yyyy.MM.dd";
/**
* 年月日 时分秒格式
*/
public static final String DATE_TIME_FORMAT = "yyyy.MM.dd HH:mm:ss";
/**
* 班组长岗位code
*/
public static String PROJECT_TEAM_LEADER_JOB_CODE = "projTeamLeader";
/**
* 有班组时优先取班组岗位
*/
public static OrgNodeUserDTO nodeUserDTOByList(List<OrgNodeUserDTO> orgNodeUserDTOS) {
OrgNodeUserDTO nodeUserDTO = CollectionUtils.isEmpty(orgNodeUserDTOS) ? OrgNodeUserDTO.builder().build() : orgNodeUserDTOS.get(0);
if (CollectionUtils.isNotEmpty(orgNodeUserDTOS)) {
for (OrgNodeUserDTO orgNodeUserDTO : orgNodeUserDTOS) {
if (Objects.nonNull(orgNodeUserDTO.getJob())
&& StringUtils.hasText(orgNodeUserDTO.getJob().getCode())
&& orgNodeUserDTO.getJob().getCode().equals(Constants.PROJECT_TEAM_LEADER_JOB_CODE)) {
nodeUserDTO = orgNodeUserDTO;
}
}
}
return nodeUserDTO;
}
}