feat:暂存审批逻辑

This commit is contained in:
wangyu 2021-12-09 23:59:06 +08:00
parent 042eeae7ea
commit 9035681b05
23 changed files with 495 additions and 3 deletions

30
flyfish-approval/pom.xml Normal file
View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>flyfish-framework</artifactId>
<groupId>com.flyfish.framework</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>flyfish-approval</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>com.flyfish.framework</groupId>
<artifactId>flyfish-web</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,26 @@
package com.flyfish.framework.approval.auditor;
import com.flyfish.framework.approval.domain.record.ApproveRecord;
import com.flyfish.framework.auditor.ReactiveBeanAuditor;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
public class ApproveRecordAuditor implements ReactiveBeanAuditor<ApproveRecord> {
/**
* 对实体进行审查并补全相关字段
*
* @param data 原数据
* @return 结果
*/
@Override
public Mono<ApproveRecord> audit(ApproveRecord data) {
if (null != data.getAction()) {
if (null == data.getApproved()) {
data.setApproved(true);
}
}
return Mono.just(data);
}
}

View File

@ -0,0 +1,75 @@
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;
/**
* 审批记录控制器
*
* @author wangyu
*/
@RestController
@RequestMapping("approves")
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);
}
}

View File

@ -0,0 +1,27 @@
package com.flyfish.framework.approval.domain;
import com.flyfish.framework.approval.enums.ApproveStatus;
import com.flyfish.framework.domain.authorized.AuthorizedDomain;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* 审批支持必然是带权限的实体
*
* @author wangyu
*/
@Getter
@Setter
public abstract class ApprovalDomain extends AuthorizedDomain {
// 审批状态
private ApproveStatus approveStatus;
// 审批人按序依次审批
private List<String> approvers;
// 下个审批人
private String nextApprover;
}

View File

@ -0,0 +1,39 @@
package com.flyfish.framework.approval.domain.record;
import com.flyfish.framework.approval.enums.ApproveAction;
import com.flyfish.framework.domain.base.AuditDomain;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.mongodb.core.mapping.Document;
/**
* 审批记录
*
* @author wangyu
*/
@Document(collection = "approve-records")
@Getter
@Setter
public class ApproveRecord extends AuditDomain {
// 是否已审批
private Boolean approved;
// 模块
private String module;
// 模块名称
private String moduleName;
// 数据id
private String dataId;
// 审批人
private String approver;
// 审批动作
private ApproveAction action;
// 审批意见
private String opinion;
}

View File

@ -0,0 +1,41 @@
package com.flyfish.framework.approval.domain.record;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.flyfish.framework.domain.base.Vo;
import lombok.Data;
import java.util.Date;
/**
* 审批记录列表vo
*
* @author wangyu
*/
@Data
public class ApproveRecordListVo implements Vo<ApproveRecord> {
private String id;
private String name;
private String approver;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private Date approveTime;
private String action;
private String opinion;
@Override
public Vo<ApproveRecord> from(ApproveRecord po) {
ApproveRecordListVo vo = new ApproveRecordListVo();
vo.setId(po.getId());
vo.setName(po.getName());
vo.setApprover(po.getModifier());
vo.setApproveTime(po.getModifyTime());
vo.setAction(po.getAction().getName());
vo.setOpinion(po.getOpinion());
return vo;
}
}

View File

@ -0,0 +1,33 @@
package com.flyfish.framework.approval.domain.record;
import com.flyfish.framework.builder.CriteriaBuilder;
import com.flyfish.framework.domain.base.NameLikeQo;
import lombok.Getter;
import lombok.Setter;
/**
* 审批记录查询实体
*
* @author wangyu
*/
@Getter
@Setter
public class ApproveRecordQo extends NameLikeQo<ApproveRecord> {
// 所属模块
private String module;
// 所属数据id
private String dataId;
// 是否审批
private Boolean approved;
// 审批人
private String approver;
@Override
public CriteriaBuilder<ApproveRecord> criteriaBuilder() {
return super.criteriaBuilder().with("module", "dataId", "approved", "approver");
}
}

View File

@ -0,0 +1,42 @@
package com.flyfish.framework.approval.domain.todo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.flyfish.framework.approval.domain.record.ApproveRecord;
import com.flyfish.framework.domain.base.Vo;
import lombok.Data;
import java.util.Date;
/**
* 待审批列表vo
*
* @author wangyu
*/
@Data
public class ApprovalListVo implements Vo<ApproveRecord> {
private String id;
private String module;
private String moduleName;
private String dataId;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private Date createTime;
private String creator;
@Override
public Vo<ApproveRecord> from(ApproveRecord po) {
ApprovalListVo vo = new ApprovalListVo();
vo.setId(po.getId());
vo.setCreator(po.getCreator());
vo.setCreateTime(po.getCreateTime());
vo.setModule(po.getModule());
vo.setModuleName(po.getModuleName());
vo.setDataId(po.getDataId());
return vo;
}
}

View File

@ -0,0 +1,14 @@
package com.flyfish.framework.approval.enums;
import com.flyfish.framework.enums.NamedEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum ApproveAction implements NamedEnum {
AGREE("同意"), REJECT("驳回"), REJECT_ALL("驳回到发起人");
private final String name;
}

View File

@ -0,0 +1,18 @@
package com.flyfish.framework.approval.enums;
import com.flyfish.framework.enums.NamedEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 审批状态
* @author wangyu
*/
@Getter
@AllArgsConstructor
public enum ApproveStatus implements NamedEnum {
PENDING("待审批"), APPROVING("审批中"), APPROVED("已审批"), REJECTED("已拒绝");
private final String name;
}

View File

@ -0,0 +1,11 @@
package com.flyfish.framework.approval.repository;
import com.flyfish.framework.approval.domain.record.ApproveRecord;
import com.flyfish.framework.repository.DefaultReactiveRepository;
/**
* 审批记录仓库
* @author wangyu
*/
public interface ApproveRecordRepository extends DefaultReactiveRepository<ApproveRecord> {
}

View File

@ -0,0 +1,14 @@
package com.flyfish.framework.approval.service;
import com.flyfish.framework.approval.domain.record.ApproveRecord;
import com.flyfish.framework.service.impl.BaseReactiveServiceImpl;
import org.springframework.stereotype.Service;
/**
* 审批记录服务
*
* @author wangyu
*/
@Service
public class ApproveRecordService extends BaseReactiveServiceImpl<ApproveRecord> {
}

View File

@ -0,0 +1,52 @@
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.domain.base.DomainService;
import com.flyfish.framework.service.BaseReactiveService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* rest模块代理服务
* 代理所有带审批的bean服务用于模糊审批
*
* @author wangyu
*/
@Service
public class ModuleDelegateService {
// 审批的服务们
private Map<String, BaseReactiveService<ApprovalDomain>> approvalServices;
@Autowired(required = false)
public void setApprovalServices(List<BaseReactiveService<ApprovalDomain>> services) {
this.approvalServices = services.stream()
.collect(Collectors.toMap(DomainService::getCollectionName, s -> s));
}
/**
* 获取服务
*
* @param module 模块
* @return 结果
*/
public BaseReactiveService<ApprovalDomain> getService(String module) {
return approvalServices.get(module);
}
/**
* 提交审批
* @param record 记录
* @return 结果
*/
public Mono<ApprovalDomain> approval(ApproveRecord record) {
getService(record.getModule()).getById(record.getDataId())
.map(domain -> domain)
}
}

View File

@ -11,6 +11,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors;
/** /**
* 请求结果 * 请求结果
@ -139,11 +140,18 @@ public class Result<T> {
public <R> Result<R> map(Function<T, R> function) { public <R> Result<R> map(Function<T, R> function) {
if (this.data != null) { if (this.data != null) {
this.data = (T) function.apply(this.data); this.data = (T) function.apply(this.data);
return (Result<R>) this;
} }
return (Result<R>) this; return (Result<R>) this;
} }
public <E, R> Result<List<R>> mapList(Function<E, R> function) {
if (this.data instanceof List) {
List<E> list = (List<E>) this.data;
this.data = (T) list.stream().map(function).collect(Collectors.toList());
}
return (Result<List<R>>) this;
}
public <R> Mono<Result<R>> flatMap(Function<T, Mono<R>> function) { public <R> Mono<Result<R>> flatMap(Function<T, Mono<R>> function) {
return Mono.defer(() -> function.apply(data)) return Mono.defer(() -> function.apply(data))
.map(mapped -> { .map(mapped -> {

View File

@ -4,4 +4,11 @@ package com.flyfish.framework.domain.base;
* 占位标记service * 占位标记service
*/ */
public interface DomainService { public interface DomainService {
/**
* 获取集合名称
*
* @return 结果
*/
String getCollectionName();
} }

View File

@ -89,4 +89,11 @@ public interface QueryModelExecutor<T> {
* @return {@literal true} if the data store contains elements that match the given {@link Qo}. * @return {@literal true} if the data store contains elements that match the given {@link Qo}.
*/ */
boolean exists(Qo<T> query); boolean exists(Qo<T> query);
/**
* 获取集合名称
*
* @return 结果
*/
String getCollectionName();
} }

View File

@ -99,4 +99,11 @@ public interface ReactiveQueryModelExecutor<T> {
* @return 结果 * @return 结果
*/ */
Mono<Void> deleteAll(Qo<T> qo); Mono<Void> deleteAll(Qo<T> qo);
/**
* 获取集合名称
*
* @return 结果
*/
String getCollectionName();
} }

View File

@ -177,4 +177,14 @@ public class DefaultReactiveRepositoryImpl<T extends Domain> extends SimpleReact
entityInformation.getCollectionName())) entityInformation.getCollectionName()))
.then(Mono.empty()); .then(Mono.empty());
} }
/**
* 获取集合名称
*
* @return 结果
*/
@Override
public String getCollectionName() {
return entityInformation.getCollectionName();
}
} }

View File

@ -169,4 +169,14 @@ public class DefaultRepositoryImpl<T extends Domain> extends SimpleMongoReposito
.orElse(false); .orElse(false);
} }
/**
* 获取集合名称
*
* @return 结果
*/
@Override
public String getCollectionName() {
return entityInformation.getCollectionName();
}
} }

View File

@ -4,6 +4,7 @@ import com.flyfish.framework.bean.SyncVo;
import com.flyfish.framework.domain.base.Domain; import com.flyfish.framework.domain.base.Domain;
import com.flyfish.framework.domain.base.DomainService; import com.flyfish.framework.domain.base.DomainService;
import com.flyfish.framework.domain.base.Qo; import com.flyfish.framework.domain.base.Qo;
import com.flyfish.framework.repository.DefaultReactiveRepository;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;

View File

@ -404,5 +404,15 @@ public class BaseReactiveServiceImpl<T extends Domain> implements BaseReactiveSe
public <R extends DefaultReactiveRepository<T>> R getRepository() { public <R extends DefaultReactiveRepository<T>> R getRepository() {
return CastUtils.cast(repository); return CastUtils.cast(repository);
} }
/**
* 获取集合名称
*
* @return 结果
*/
@Override
public String getCollectionName() {
return getRepository().getCollectionName();
}
} }

View File

@ -7,7 +7,6 @@ import com.flyfish.framework.domain.authorized.AuthorizedDomain;
import com.flyfish.framework.domain.base.AuditDomain; import com.flyfish.framework.domain.base.AuditDomain;
import com.flyfish.framework.domain.base.Domain; import com.flyfish.framework.domain.base.Domain;
import com.flyfish.framework.domain.base.Qo; import com.flyfish.framework.domain.base.Qo;
import com.flyfish.framework.repository.DefaultReactiveRepository;
import com.flyfish.framework.repository.DefaultRepository; import com.flyfish.framework.repository.DefaultRepository;
import com.flyfish.framework.service.BaseService; import com.flyfish.framework.service.BaseService;
import com.flyfish.framework.utils.Assert; import com.flyfish.framework.utils.Assert;
@ -372,7 +371,17 @@ public class BaseServiceImpl<T extends Domain> implements BaseService<T> {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <R extends DefaultReactiveRepository<T>> R getRepository() { public <R extends DefaultRepository<T>> R getRepository() {
return (R) repository; return (R) repository;
} }
/**
* 获取集合名称
*
* @return 结果
*/
@Override
public String getCollectionName() {
return getRepository().getCollectionName();
}
} }

View File

@ -45,6 +45,7 @@
<module>flyfish-logging</module> <module>flyfish-logging</module>
<module>flyfish-dict</module> <module>flyfish-dict</module>
<module>flyfish-form</module> <module>flyfish-form</module>
<module>flyfish-approval</module>
</modules> </modules>
<repositories> <repositories>