feat:提交审批逻辑
This commit is contained in:
parent
9035681b05
commit
935db3fe59
@ -0,0 +1,31 @@
|
||||
package com.flyfish.framework.approval.auditor;
|
||||
|
||||
import com.flyfish.framework.approval.domain.ApprovalDomain;
|
||||
import com.flyfish.framework.approval.enums.ApproveStatus;
|
||||
import com.flyfish.framework.auditor.ReactiveBeanAuditor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* 审批拦截审计器
|
||||
* 在用户首次提交审核
|
||||
*
|
||||
* @author wangyu
|
||||
*/
|
||||
@Component
|
||||
public class ApproveAuditor implements ReactiveBeanAuditor<ApprovalDomain> {
|
||||
|
||||
/**
|
||||
* 对实体进行审查,并补全相关字段
|
||||
*
|
||||
* @param data 原数据
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public Mono<ApprovalDomain> audit(ApprovalDomain data) {
|
||||
if (null == data.getApproveStatus()) {
|
||||
data.setApproveStatus(ApproveStatus.DRAFT);
|
||||
}
|
||||
return Mono.just(data);
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package com.flyfish.framework.approval.controller;
|
||||
|
||||
import com.flyfish.framework.approval.domain.ApprovalDomain;
|
||||
import com.flyfish.framework.approval.domain.record.ApproveRecord;
|
||||
import com.flyfish.framework.approval.domain.record.ApproveRecordListVo;
|
||||
import com.flyfish.framework.approval.domain.record.ApproveRecordQo;
|
||||
import com.flyfish.framework.approval.domain.submit.ApprovalSubmitDto;
|
||||
import com.flyfish.framework.approval.domain.todo.ApprovalDto;
|
||||
import com.flyfish.framework.approval.domain.todo.ApprovalListVo;
|
||||
import com.flyfish.framework.approval.service.ApproveRecordService;
|
||||
import com.flyfish.framework.approval.service.ModuleDelegateService;
|
||||
import com.flyfish.framework.bean.Result;
|
||||
import com.flyfish.framework.configuration.annotations.CurrentUser;
|
||||
import com.flyfish.framework.configuration.annotations.PagedQuery;
|
||||
import com.flyfish.framework.domain.base.Vo;
|
||||
import com.flyfish.framework.domain.po.User;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 审批专用controller
|
||||
*
|
||||
* @author wangyu
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("approves")
|
||||
public class ApprovalController {
|
||||
|
||||
@Resource
|
||||
private ApproveRecordService approveRecordService;
|
||||
@Resource
|
||||
private ModuleDelegateService moduleDelegateService;
|
||||
|
||||
/**
|
||||
* 查询视图
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
@GetMapping("records")
|
||||
public Mono<Result<List<Vo<ApproveRecord>>>> views(@PagedQuery ApproveRecordQo qo) {
|
||||
return approveRecordService.getPageList(qo)
|
||||
.map(Result::accept)
|
||||
.map(result -> result.mapList((ApproveRecord item) -> new ApproveRecordListVo().from(item)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询待办列表
|
||||
*
|
||||
* @param qo 查询实体
|
||||
* @param user 用户
|
||||
* @return 结果
|
||||
*/
|
||||
@GetMapping("todos")
|
||||
public Mono<Result<List<Vo<ApproveRecord>>>> todos(@PagedQuery ApproveRecordQo qo, @CurrentUser User user) {
|
||||
qo.setApprover(user.getId());
|
||||
qo.setApproved(false);
|
||||
return approveRecordService.getPageList(qo)
|
||||
.map(Result::accept)
|
||||
.map(result -> result.mapList((ApproveRecord item) -> new ApprovalListVo().from(item)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交审批
|
||||
* 需要指定提交候选人,按顺序审批
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
@PostMapping("submit")
|
||||
public Mono<Result<ApprovalDomain>> submit(@Valid @RequestBody ApprovalSubmitDto body) {
|
||||
return moduleDelegateService.submit(body).map(Result::ok);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 审批数据
|
||||
*
|
||||
* @param approval 数据
|
||||
* @return 结果
|
||||
*/
|
||||
@PostMapping("approval")
|
||||
public Mono<Result<ApprovalDomain>> approval(@RequestBody ApprovalDto approval) {
|
||||
return moduleDelegateService.approval(approval).map(Result::ok);
|
||||
}
|
||||
}
|
@ -1,22 +1,10 @@
|
||||
package com.flyfish.framework.approval.controller;
|
||||
|
||||
import com.flyfish.framework.approval.domain.ApprovalDomain;
|
||||
import com.flyfish.framework.approval.domain.record.ApproveRecord;
|
||||
import com.flyfish.framework.approval.domain.record.ApproveRecordListVo;
|
||||
import com.flyfish.framework.approval.domain.record.ApproveRecordQo;
|
||||
import com.flyfish.framework.approval.domain.todo.ApprovalListVo;
|
||||
import com.flyfish.framework.approval.service.ModuleDelegateService;
|
||||
import com.flyfish.framework.bean.Result;
|
||||
import com.flyfish.framework.configuration.annotations.CurrentUser;
|
||||
import com.flyfish.framework.configuration.annotations.PagedQuery;
|
||||
import com.flyfish.framework.controller.reactive.ReactiveBaseController;
|
||||
import com.flyfish.framework.domain.base.Vo;
|
||||
import com.flyfish.framework.domain.po.User;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 审批记录控制器
|
||||
@ -24,52 +12,7 @@ import java.util.List;
|
||||
* @author wangyu
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("approves")
|
||||
@RequestMapping("approve-records")
|
||||
public class ApproveRecordController extends ReactiveBaseController<ApproveRecord, ApproveRecordQo> {
|
||||
|
||||
@Resource
|
||||
private ModuleDelegateService moduleDelegateService;
|
||||
|
||||
/**
|
||||
* 查询视图
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
@GetMapping("records")
|
||||
public Mono<Result<List<Vo<ApproveRecord>>>> views(@PagedQuery ApproveRecordQo qo) {
|
||||
return reactiveService.getPageList(qo)
|
||||
.map(Result::accept)
|
||||
.map(result -> result.mapList((ApproveRecord item) -> new ApproveRecordListVo().from(item)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询待办列表
|
||||
*
|
||||
* @param qo 查询实体
|
||||
* @param user 用户
|
||||
* @return 结果
|
||||
*/
|
||||
@GetMapping("todos")
|
||||
public Mono<Result<List<Vo<ApproveRecord>>>> todos(@PagedQuery ApproveRecordQo qo, @CurrentUser User user) {
|
||||
qo.setApprover(user.getId());
|
||||
qo.setApproved(false);
|
||||
return reactiveService.getPageList(qo)
|
||||
.map(Result::accept)
|
||||
.map(result -> result.mapList((ApproveRecord item) -> new ApprovalListVo().from(item)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用审批
|
||||
*
|
||||
* @param module 模块
|
||||
* @param dataId 数据id
|
||||
* @return 结果
|
||||
*/
|
||||
@PostMapping("approval/{module}/{dataId}")
|
||||
public Mono<Result<ApprovalDomain>> approval(@PathVariable String module, @PathVariable String dataId,
|
||||
@RequestBody ApproveRecord record) {
|
||||
record.setModule(module);
|
||||
record.setDataId(dataId);
|
||||
return moduleDelegateService.approval(record).map(Result::ok);
|
||||
}
|
||||
}
|
||||
|
@ -23,5 +23,5 @@ public abstract class ApprovalDomain extends AuthorizedDomain {
|
||||
private List<String> approvers;
|
||||
|
||||
// 下个审批人
|
||||
private String nextApprover;
|
||||
private Integer next;
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
package com.flyfish.framework.approval.domain.submit;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 审批提交数据
|
||||
*
|
||||
* @author wangyu
|
||||
*/
|
||||
@Data
|
||||
public class ApprovalSubmitDto {
|
||||
|
||||
// 数据主键
|
||||
@NotBlank(message = "数据主键不可为空!")
|
||||
private String id;
|
||||
|
||||
// 数据模块
|
||||
@NotBlank(message = "数据模块不可为空!")
|
||||
private String module;
|
||||
|
||||
// 待审批人列表
|
||||
@NotEmpty(message = "待审批人不可为空!")
|
||||
private List<String> approvers;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.flyfish.framework.approval.domain.todo;
|
||||
|
||||
import com.flyfish.framework.approval.enums.ApproveAction;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 审批dto
|
||||
*
|
||||
* @author wangyu
|
||||
*/
|
||||
@Data
|
||||
public class ApprovalDto {
|
||||
|
||||
@NotBlank(message = "审批记录id不可为空!")
|
||||
private String id;
|
||||
|
||||
@NotNull(message = "审批操作不可为空!")
|
||||
private ApproveAction action;
|
||||
|
||||
@NotNull(message = "审批意见不可为空!")
|
||||
private String opinion;
|
||||
}
|
@ -6,13 +6,14 @@ import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 审批状态
|
||||
*
|
||||
* @author wangyu
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ApproveStatus implements NamedEnum {
|
||||
|
||||
PENDING("待审批"), APPROVING("审批中"), APPROVED("已审批"), REJECTED("已拒绝");
|
||||
DRAFT("草稿"), PENDING("待审批"), APPROVING("审批中"), APPROVED("已审批"), REJECTED("已拒绝");
|
||||
|
||||
private final String name;
|
||||
}
|
||||
|
@ -2,14 +2,24 @@ package com.flyfish.framework.approval.service;
|
||||
|
||||
import com.flyfish.framework.approval.domain.ApprovalDomain;
|
||||
import com.flyfish.framework.approval.domain.record.ApproveRecord;
|
||||
import com.flyfish.framework.approval.domain.submit.ApprovalSubmitDto;
|
||||
import com.flyfish.framework.approval.domain.todo.ApprovalDto;
|
||||
import com.flyfish.framework.approval.enums.ApproveAction;
|
||||
import com.flyfish.framework.approval.enums.ApproveStatus;
|
||||
import com.flyfish.framework.beans.meta.RestBean;
|
||||
import com.flyfish.framework.domain.base.DomainService;
|
||||
import com.flyfish.framework.exception.biz.InvalidBusinessException;
|
||||
import com.flyfish.framework.service.BaseReactiveService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -21,6 +31,9 @@ import java.util.stream.Collectors;
|
||||
@Service
|
||||
public class ModuleDelegateService {
|
||||
|
||||
@Resource
|
||||
private ApproveRecordService approveRecordService;
|
||||
|
||||
// 审批的服务们
|
||||
private Map<String, BaseReactiveService<ApprovalDomain>> approvalServices;
|
||||
|
||||
@ -41,12 +54,154 @@ public class ModuleDelegateService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交审批
|
||||
* @param record 记录
|
||||
* 审批数据
|
||||
*
|
||||
* @param approval 记录
|
||||
* @return 结果
|
||||
*/
|
||||
public Mono<ApprovalDomain> approval(ApproveRecord record) {
|
||||
getService(record.getModule()).getById(record.getDataId())
|
||||
.map(domain -> domain)
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Mono<ApprovalDomain> approval(ApprovalDto approval) {
|
||||
return approveRecordService.getById(approval.getId())
|
||||
// 保存记录
|
||||
.flatMap(record -> {
|
||||
if (record.getApproved()) {
|
||||
return Mono.error(new InvalidBusinessException("该审批已被处理,请勿重复操作!"));
|
||||
}
|
||||
record.setApproved(true);
|
||||
record.setAction(approval.getAction());
|
||||
record.setOpinion(approval.getOpinion());
|
||||
return approveRecordService.updateById(record);
|
||||
})
|
||||
// 修改主记录
|
||||
.flatMap(record -> {
|
||||
BaseReactiveService<ApprovalDomain> service = getService(record.getModule());
|
||||
return service.getById(record.getDataId())
|
||||
.flatMap(domain -> {
|
||||
// 如果已经审批过,直接返回
|
||||
if (domain.getApproveStatus() == ApproveStatus.APPROVED) {
|
||||
return Mono.error(new InvalidBusinessException("该审批已被处理,请勿重复操作!"));
|
||||
}
|
||||
// 尚未提交审批,不处理
|
||||
if (domain.getApproveStatus() == ApproveStatus.DRAFT || domain.getApproveStatus() == ApproveStatus.REJECTED) {
|
||||
return Mono.error(new InvalidBusinessException("该数据尚未提交审批,请确认后再操作!"));
|
||||
}
|
||||
// 终止标记
|
||||
boolean end = false;
|
||||
// 审批人
|
||||
String approver = null;
|
||||
// 尝试流转
|
||||
switch (record.getAction()) {
|
||||
case AGREE:
|
||||
String next = determineNext(domain);
|
||||
// 下一个为空,代表审批完了,改状态
|
||||
if (null == next) {
|
||||
domain.setApproveStatus(ApproveStatus.APPROVED);
|
||||
domain.setNext(-1);
|
||||
end = true;
|
||||
} else {
|
||||
domain.setApproveStatus(ApproveStatus.APPROVING);
|
||||
domain.setNext(domain.getNext() + 1);
|
||||
approver = next;
|
||||
}
|
||||
break;
|
||||
case REJECT:
|
||||
// 拒绝,如果已经是第一步了,设置拒绝状态
|
||||
if (domain.getNext() == 0) {
|
||||
domain.setApproveStatus(ApproveStatus.REJECTED);
|
||||
end = true;
|
||||
} else {
|
||||
domain.setNext(domain.getNext() - 1);
|
||||
approver = domain.getApprovers().get(domain.getNext());
|
||||
}
|
||||
break;
|
||||
case REJECT_ALL:
|
||||
// 直接打回拒绝状态,需要重新修改提交
|
||||
domain.setNext(0);
|
||||
domain.setApproveStatus(ApproveStatus.REJECTED);
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
// 没结束
|
||||
if (!end) {
|
||||
// 构建下一步操作
|
||||
ApproveRecord nextRecord = new ApproveRecord();
|
||||
nextRecord.setModule(record.getModule());
|
||||
nextRecord.setDataId(record.getId());
|
||||
nextRecord.setApproved(false);
|
||||
nextRecord.setModuleName(moduleName(domain.getClass()));
|
||||
nextRecord.setName(operation(approval.getAction()));
|
||||
nextRecord.setApprover(approver);
|
||||
return approveRecordService.create(nextRecord)
|
||||
.flatMap(r -> service.updateById(domain));
|
||||
}
|
||||
return service.updateById(domain);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交审核
|
||||
*
|
||||
* @param data 数据
|
||||
* @return 结果
|
||||
*/
|
||||
public Mono<ApprovalDomain> submit(ApprovalSubmitDto data) {
|
||||
BaseReactiveService<ApprovalDomain> service = getService(data.getModule());
|
||||
return service.getById(data.getId())
|
||||
.flatMap(domain -> {
|
||||
domain.setApprovers(data.getApprovers());
|
||||
domain.setApproveStatus(ApproveStatus.PENDING);
|
||||
domain.setNext(0);
|
||||
return service.updateById(domain);
|
||||
})
|
||||
.flatMap(domain -> {
|
||||
ApproveRecord record = new ApproveRecord();
|
||||
record.setName("提交审核");
|
||||
record.setModule(data.getModule());
|
||||
record.setDataId(data.getId());
|
||||
record.setApproved(false);
|
||||
record.setApprover(domain.getApprovers().get(domain.getNext()));
|
||||
record.setModuleName(moduleName(domain.getClass()));
|
||||
return approveRecordService.create(record).thenReturn(domain);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取模块名称
|
||||
*
|
||||
* @param clazz 类
|
||||
* @return 结果
|
||||
*/
|
||||
private String moduleName(Class<?> clazz) {
|
||||
return Optional.ofNullable(AnnotationUtils.findAnnotation(clazz, RestBean.class))
|
||||
.map(RestBean::name).orElse("未知模块");
|
||||
}
|
||||
|
||||
/**
|
||||
* 决定下一位审批人
|
||||
*
|
||||
* @param domain 审批实体
|
||||
* @return 结果
|
||||
*/
|
||||
private String determineNext(ApprovalDomain domain) {
|
||||
// 获取当前位置
|
||||
int index = domain.getNext();
|
||||
int next = index + 1;
|
||||
// 下一个位置
|
||||
if (next < domain.getApprovers().size()) {
|
||||
return domain.getApprovers().get(next);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作中文名
|
||||
*
|
||||
* @param action 操作
|
||||
* @return 结果
|
||||
*/
|
||||
private String operation(ApproveAction action) {
|
||||
return "将审批进行了\"" + action.getName() + "\"操作";
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ public class BeanController {
|
||||
BeanInfo info = new BeanInfo();
|
||||
if (clazz.isAnnotationPresent(RestBean.class)) {
|
||||
RestBean annotation = clazz.getAnnotation(RestBean.class);
|
||||
info.setType(clazz.getSuperclass().getSimpleName());
|
||||
info.setName(annotation.name());
|
||||
info.setCode(annotation.value());
|
||||
info.setSearch(BeanProperty.from(annotation.queryClass()));
|
||||
|
Loading…
Reference in New Issue
Block a user