|
|
|
@@ -16,6 +16,7 @@ import com.gxwebsoft.approval.mapper.ApprovalInstanceMapper;
|
|
|
|
|
import com.gxwebsoft.approval.mapper.ApprovalRecordMapper;
|
|
|
|
|
import com.gxwebsoft.approval.mapper.ApprovalTaskMapper;
|
|
|
|
|
import com.gxwebsoft.approval.param.ApprovalCompletionParam;
|
|
|
|
|
import com.gxwebsoft.approval.param.ApprovalCoordinationParam;
|
|
|
|
|
import com.gxwebsoft.approval.param.ApprovalMineParam;
|
|
|
|
|
import com.gxwebsoft.approval.param.ApprovalTaskListParam;
|
|
|
|
|
import com.gxwebsoft.approval.support.ApprovalApprover;
|
|
|
|
@@ -99,6 +100,30 @@ public class ApprovalInstanceService {
|
|
|
|
|
return inTransaction(() -> createDraft(param, user, definition, organizationId, organizationName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 新建或更新内部协调单草稿,返回实例id。
|
|
|
|
|
*
|
|
|
|
|
* <p>报送部门与经办人取登录态;受理部门必须是启用组织,保存时即校验。</p>
|
|
|
|
|
*/
|
|
|
|
|
public Long saveCoordination(ApprovalCoordinationParam param, User user) {
|
|
|
|
|
validateCoordination(param);
|
|
|
|
|
ApprovalOrganizationVO acceptOrganization = directoryService.getOrganization(param.getAcceptOrgId());
|
|
|
|
|
if (acceptOrganization == null) {
|
|
|
|
|
throw new BusinessException("受理部门不存在或已停用");
|
|
|
|
|
}
|
|
|
|
|
Integer organizationId = user.getOrganizationId();
|
|
|
|
|
ApprovalOrganizationVO organization = directoryService.getOrganization(organizationId);
|
|
|
|
|
String organizationName = organization == null ? null : organization.getOrganizationName();
|
|
|
|
|
|
|
|
|
|
if (param.getId() != null) {
|
|
|
|
|
return inTransaction(() ->
|
|
|
|
|
updateCoordinationDraft(param, user, organizationId, organizationName, acceptOrganization));
|
|
|
|
|
}
|
|
|
|
|
ApprovalFlowDefinition definition = flowService.getOrCreate(ApprovalConstants.FLOW_COORDINATION_INTERNAL);
|
|
|
|
|
return inTransaction(() ->
|
|
|
|
|
createCoordinationDraft(param, user, definition, organizationId, organizationName, acceptOrganization));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 提交或重提,返回节点缺配提示;正常提交返回 null。
|
|
|
|
|
*/
|
|
|
|
@@ -113,7 +138,14 @@ public class ApprovalInstanceService {
|
|
|
|
|
if (!ApprovalConstants.EDITABLE_STATUSES.contains(instance.getStatus())) {
|
|
|
|
|
throw new BusinessException(submitBlockedMessage(instance.getStatus()));
|
|
|
|
|
}
|
|
|
|
|
if (completionForm(instanceId) == null) {
|
|
|
|
|
boolean coordination = ApprovalConstants.DOC_COORDINATION.equals(instance.getDocType());
|
|
|
|
|
ApprovalCoordinationForm coordinationForm = null;
|
|
|
|
|
if (coordination) {
|
|
|
|
|
coordinationForm = coordinationForm(instanceId);
|
|
|
|
|
if (coordinationForm == null) {
|
|
|
|
|
throw new BusinessException("单据内容不存在");
|
|
|
|
|
}
|
|
|
|
|
} else if (completionForm(instanceId) == null) {
|
|
|
|
|
throw new BusinessException("单据内容不存在");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -130,6 +162,10 @@ public class ApprovalInstanceService {
|
|
|
|
|
if (leaders.isEmpty()) {
|
|
|
|
|
throw new BusinessException("报送部门负责人角色缺配");
|
|
|
|
|
}
|
|
|
|
|
ApprovalOrganizationVO acceptOrganization = null;
|
|
|
|
|
if (coordination) {
|
|
|
|
|
acceptOrganization = preflightAcceptOrganization(coordinationForm);
|
|
|
|
|
}
|
|
|
|
|
if (directoryService.listRoleMembers(ApprovalConstants.ROLE_ARCHIVIST).isEmpty()) {
|
|
|
|
|
throw new BusinessException("收文员角色缺配");
|
|
|
|
|
}
|
|
|
|
@@ -141,11 +177,30 @@ public class ApprovalInstanceService {
|
|
|
|
|
.map(this::toApprover)
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
|
|
|
|
return inTransaction(() -> doSubmit(instanceId, user, organization, approvers));
|
|
|
|
|
ApprovalOrganizationVO acceptOrg = acceptOrganization;
|
|
|
|
|
return inTransaction(() -> doSubmit(instanceId, user, organization, acceptOrg, approvers));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 协调单提交预检:受理部门负责人角色、受理部门停用。
|
|
|
|
|
*/
|
|
|
|
|
private ApprovalOrganizationVO preflightAcceptOrganization(ApprovalCoordinationForm form) {
|
|
|
|
|
Integer acceptOrgId = form.getAcceptOrgId();
|
|
|
|
|
if (acceptOrgId == null || acceptOrgId <= 0) {
|
|
|
|
|
throw new BusinessException("请选择受理部门");
|
|
|
|
|
}
|
|
|
|
|
if (directoryService.listRoleMembers(ApprovalConstants.departmentLeaderRoleCode(acceptOrgId)).isEmpty()) {
|
|
|
|
|
throw new BusinessException("受理部门负责人角色缺配");
|
|
|
|
|
}
|
|
|
|
|
ApprovalOrganizationVO acceptOrganization = directoryService.getOrganization(acceptOrgId);
|
|
|
|
|
if (acceptOrganization == null) {
|
|
|
|
|
throw new BusinessException("受理部门已停用");
|
|
|
|
|
}
|
|
|
|
|
return acceptOrganization;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String doSubmit(Long instanceId, User user, ApprovalOrganizationVO organization,
|
|
|
|
|
List<ApprovalApprover> approvers) {
|
|
|
|
|
ApprovalOrganizationVO acceptOrganization, List<ApprovalApprover> approvers) {
|
|
|
|
|
ApprovalInstance locked = engineService.lockInstance(instanceId);
|
|
|
|
|
if (!locked.getReporterId().equals(user.getUserId())
|
|
|
|
|
|| !ApprovalConstants.EDITABLE_STATUSES.contains(locked.getStatus())) {
|
|
|
|
@@ -154,8 +209,15 @@ public class ApprovalInstanceService {
|
|
|
|
|
boolean firstSubmit = StrUtil.isBlank(locked.getBizNo());
|
|
|
|
|
locked.setReportOrgId(organization.getOrganizationId());
|
|
|
|
|
locked.setReportOrgName(organization.getOrganizationName());
|
|
|
|
|
if (acceptOrganization != null) {
|
|
|
|
|
locked.setAcceptOrgId(acceptOrganization.getOrganizationId());
|
|
|
|
|
locked.setAcceptOrgName(acceptOrganization.getOrganizationName());
|
|
|
|
|
}
|
|
|
|
|
if (firstSubmit) {
|
|
|
|
|
locked.setBizNo(noService.nextNo(ApprovalConstants.NO_PREFIX_COMPLETION));
|
|
|
|
|
boolean coordination = ApprovalConstants.DOC_COORDINATION.equals(locked.getDocType());
|
|
|
|
|
locked.setBizNo(noService.nextNo(coordination
|
|
|
|
|
? ApprovalConstants.NO_PREFIX_COORDINATION
|
|
|
|
|
: ApprovalConstants.NO_PREFIX_COMPLETION));
|
|
|
|
|
}
|
|
|
|
|
locked.setStatus(ApprovalConstants.STATUS_PENDING);
|
|
|
|
|
locked.setRound((locked.getRound() == null ? 0 : locked.getRound()) + 1);
|
|
|
|
@@ -323,6 +385,79 @@ public class ApprovalInstanceService {
|
|
|
|
|
return instance.getId();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Long createCoordinationDraft(ApprovalCoordinationParam param, User user,
|
|
|
|
|
ApprovalFlowDefinition definition,
|
|
|
|
|
Integer organizationId, String organizationName,
|
|
|
|
|
ApprovalOrganizationVO acceptOrganization) {
|
|
|
|
|
ApprovalInstance instance = new ApprovalInstance();
|
|
|
|
|
instance.setFlowCode(ApprovalConstants.FLOW_COORDINATION_INTERNAL);
|
|
|
|
|
instance.setDefinitionId(definition.getId());
|
|
|
|
|
instance.setDefinitionVersion(definition.getVersion());
|
|
|
|
|
instance.setDocType(ApprovalConstants.DOC_COORDINATION);
|
|
|
|
|
instance.setBizId(0L);
|
|
|
|
|
instance.setStatus(ApprovalConstants.STATUS_DRAFT);
|
|
|
|
|
instance.setRound(0);
|
|
|
|
|
instance.setReporterId(user.getUserId());
|
|
|
|
|
instance.setReporterName(displayName(user));
|
|
|
|
|
instance.setReportOrgId(organizationId);
|
|
|
|
|
instance.setReportOrgName(organizationName);
|
|
|
|
|
instanceMapper.insert(instance);
|
|
|
|
|
|
|
|
|
|
ApprovalCoordinationForm form = new ApprovalCoordinationForm();
|
|
|
|
|
form.setInstanceId(instance.getId());
|
|
|
|
|
form.setAcceptOrgId(acceptOrganization.getOrganizationId());
|
|
|
|
|
form.setAcceptOrgName(acceptOrganization.getOrganizationName());
|
|
|
|
|
form.setTitle(param.getTitle().trim());
|
|
|
|
|
form.setContent(param.getContent().trim());
|
|
|
|
|
form.setRemark(normalizeRemark(param.getRemark()));
|
|
|
|
|
coordinationFormMapper.insert(form);
|
|
|
|
|
|
|
|
|
|
instance.setBizId(form.getId());
|
|
|
|
|
instanceMapper.updateById(instance);
|
|
|
|
|
return instance.getId();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Long updateCoordinationDraft(ApprovalCoordinationParam param, User user,
|
|
|
|
|
Integer organizationId, String organizationName,
|
|
|
|
|
ApprovalOrganizationVO acceptOrganization) {
|
|
|
|
|
ApprovalInstance instance = instanceMapper.selectById(param.getId());
|
|
|
|
|
if (instance == null) {
|
|
|
|
|
throw new BusinessException("单据不存在");
|
|
|
|
|
}
|
|
|
|
|
if (!ApprovalConstants.DOC_COORDINATION.equals(instance.getDocType())) {
|
|
|
|
|
throw new BusinessException("单据类型不匹配");
|
|
|
|
|
}
|
|
|
|
|
if (!instance.getReporterId().equals(user.getUserId())) {
|
|
|
|
|
throw new BusinessException("无权操作该单据");
|
|
|
|
|
}
|
|
|
|
|
if (!ApprovalConstants.EDITABLE_STATUSES.contains(instance.getStatus())) {
|
|
|
|
|
throw new BusinessException("当前状态不可修改");
|
|
|
|
|
}
|
|
|
|
|
ApprovalCoordinationForm form = coordinationForm(instance.getId());
|
|
|
|
|
if (form == null) {
|
|
|
|
|
throw new BusinessException("单据内容不存在");
|
|
|
|
|
}
|
|
|
|
|
form.setAcceptOrgId(acceptOrganization.getOrganizationId());
|
|
|
|
|
form.setAcceptOrgName(acceptOrganization.getOrganizationName());
|
|
|
|
|
form.setTitle(param.getTitle().trim());
|
|
|
|
|
form.setContent(param.getContent().trim());
|
|
|
|
|
form.setRemark(normalizeRemark(param.getRemark()));
|
|
|
|
|
coordinationFormMapper.updateById(form);
|
|
|
|
|
|
|
|
|
|
instance.setReportOrgId(organizationId);
|
|
|
|
|
instance.setReportOrgName(organizationName);
|
|
|
|
|
instanceMapper.updateById(instance);
|
|
|
|
|
return instance.getId();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String normalizeRemark(String remark) {
|
|
|
|
|
if (remark == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
String trimmed = remark.trim();
|
|
|
|
|
return trimmed.isEmpty() ? null : trimmed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ApprovalInstanceVO baseVO(ApprovalInstance instance) {
|
|
|
|
|
ApprovalInstanceVO vo = new ApprovalInstanceVO();
|
|
|
|
|
vo.setId(instance.getId());
|
|
|
|
@@ -502,6 +637,33 @@ public class ApprovalInstanceService {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void validateCoordination(ApprovalCoordinationParam param) {
|
|
|
|
|
if (param == null) {
|
|
|
|
|
throw new BusinessException("参数不能为空");
|
|
|
|
|
}
|
|
|
|
|
if (param.getAcceptOrgId() == null || param.getAcceptOrgId() <= 0) {
|
|
|
|
|
throw new BusinessException("请选择受理部门");
|
|
|
|
|
}
|
|
|
|
|
String title = param.getTitle() == null ? "" : param.getTitle().trim();
|
|
|
|
|
if (title.isEmpty()) {
|
|
|
|
|
throw new BusinessException("标题不能为空");
|
|
|
|
|
}
|
|
|
|
|
if (title.length() > 100) {
|
|
|
|
|
throw new BusinessException("标题不能超过100字");
|
|
|
|
|
}
|
|
|
|
|
String content = param.getContent() == null ? "" : param.getContent().trim();
|
|
|
|
|
if (content.isEmpty()) {
|
|
|
|
|
throw new BusinessException("内容不能为空");
|
|
|
|
|
}
|
|
|
|
|
if (content.length() > 2000) {
|
|
|
|
|
throw new BusinessException("内容不能超过2000字");
|
|
|
|
|
}
|
|
|
|
|
String remark = normalizeRemark(param.getRemark());
|
|
|
|
|
if (remark != null && remark.length() > 500) {
|
|
|
|
|
throw new BusinessException("备注不能超过500字");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String submitBlockedMessage(String status) {
|
|
|
|
|
if (ApprovalConstants.STATUS_PENDING.equals(status)) {
|
|
|
|
|
return "单据正在审批中,不能重复提交";
|
|
|
|
|