Merge branch 'master' into feature/REQ-3846
# Conflicts: # doc/doc-api/src/main/java/cn/axzo/nanopart/doc/api/anonymous/DocAnonymousDatabaseApi.java # doc/doc-server/src/main/java/cn/axzo/nanopart/doc/dao/IndexNodeDao.java # doc/doc-server/src/main/java/cn/axzo/nanopart/doc/file/anonymous/DocAnonymousDatabaseApiController.java
This commit is contained in:
commit
c33deb72eb
@ -12,7 +12,11 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import cn.axzo.nanopart.doc.api.anonymous.request.AnonymousCreateDirRequest;
|
||||
import cn.axzo.nanopart.doc.api.anonymous.request.AnonymousCreateFileRequest;
|
||||
import cn.axzo.nanopart.doc.api.anonymous.request.AnonymousUploadFileRequest;
|
||||
import cn.axzo.nanopart.doc.api.domain.IndexNodeInfo;
|
||||
import cn.axzo.nanopart.doc.api.index.request.CopyNodeRequest;
|
||||
import cn.axzo.nanopart.doc.api.index.request.DeleteNodeRequest;
|
||||
import cn.axzo.nanopart.doc.api.index.request.GetNodeInfoRequest;
|
||||
import cn.axzo.nanopart.doc.api.index.request.RenameNodeRequest;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
|
||||
import java.util.Map;
|
||||
@ -39,6 +43,14 @@ public interface DocAnonymousDatabaseApi {
|
||||
@PostMapping("/api/anonymous/createFile")
|
||||
CommonResponse<String> createFile(@RequestBody @Valid AnonymousCreateFileRequest request);
|
||||
|
||||
/**
|
||||
* 创建新文件
|
||||
*
|
||||
* @return 文件编码, 需要由业务存储
|
||||
*/
|
||||
@PostMapping("/api/anonymous/createFile2")
|
||||
CommonResponse<IndexNodeInfo> createFile2(@RequestBody @Valid AnonymousCreateFileRequest request);
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
@ -47,6 +59,14 @@ public interface DocAnonymousDatabaseApi {
|
||||
@PostMapping("/api/anonymous/uploadFile")
|
||||
CommonResponse<String> uploadFile(@RequestBody @Valid AnonymousUploadFileRequest request);
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @return 文件编码, 需要由业务存储
|
||||
*/
|
||||
@PostMapping("/api/anonymous/uploadFile2")
|
||||
CommonResponse<IndexNodeInfo> uploadFile2(@RequestBody @Valid AnonymousUploadFileRequest request);
|
||||
|
||||
/**
|
||||
* 拷贝节点 (文件)
|
||||
*
|
||||
@ -55,6 +75,24 @@ public interface DocAnonymousDatabaseApi {
|
||||
@PostMapping("/api/anonymous/copy")
|
||||
CommonResponse<String> copy(@RequestBody @Valid CopyNodeRequest request);
|
||||
|
||||
/**
|
||||
* 删除节点 (文件)
|
||||
*/
|
||||
@PostMapping("/api/anonymous/delete")
|
||||
CommonResponse<Void> delete(@RequestBody @Valid DeleteNodeRequest request);
|
||||
|
||||
/**
|
||||
* 重命名节点 (文件)
|
||||
*/
|
||||
@PostMapping("/api/anonymous/rename")
|
||||
CommonResponse<Void> rename(@RequestBody @Valid RenameNodeRequest request);
|
||||
|
||||
/**
|
||||
* 获取节点信息
|
||||
*/
|
||||
@PostMapping("/api/anonymous/getNodeInfo")
|
||||
CommonResponse<IndexNodeInfo> getNodeInfo(@RequestBody @Valid GetNodeInfoRequest request);
|
||||
|
||||
/**
|
||||
* 批量获取节点信息集合
|
||||
*/
|
||||
|
||||
@ -38,6 +38,7 @@ abstract class NodeCreateAnonymous implements NodeCreate, IndexNodeScope {
|
||||
/**
|
||||
* 业务编码
|
||||
*/
|
||||
@NotBlank(message = "bizCode不能为空")
|
||||
private String bizCode;
|
||||
|
||||
/**
|
||||
|
||||
@ -89,6 +89,11 @@ public class IndexNodeInfo implements NodeValue, ValueContainer<IndexNodeInfo> {
|
||||
*/
|
||||
private String icon;
|
||||
|
||||
/**
|
||||
* 文件的大小(bytes), 只有文件才存这个字段
|
||||
*/
|
||||
private Integer size;
|
||||
|
||||
/**
|
||||
* 状态. VALID: 有效的
|
||||
*/
|
||||
|
||||
@ -4,7 +4,6 @@ package cn.axzo.nanopart.doc.api.domain;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
import cn.axzo.nanopart.doc.api.enums.FileFormat;
|
||||
import cn.axzo.nanopart.doc.api.util.BizAssertions;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@ -41,13 +40,6 @@ public class OssFile {
|
||||
return ossFile;
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
BizAssertions.assertNotNull(format, "format不能为空");
|
||||
BizAssertions.assertTrue(size > 0, "size必须大于0");
|
||||
BizAssertions.assertNotBlank(ossFileKey, "ossFileKey不能为空");
|
||||
BizAssertions.assertNotBlank(extension, "后缀不能为空");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JSON.toJSONString(this);
|
||||
|
||||
@ -26,6 +26,10 @@ public enum DatabaseScope {
|
||||
private final Boolean childNameDuplicatable;
|
||||
private final Boolean limitChildrenCount;
|
||||
|
||||
public boolean isFeeAware() {
|
||||
return databaseType != DatabaseType.NONE;
|
||||
}
|
||||
|
||||
public Integer getWorkspaceType() {
|
||||
if (this == ENT_DATABASE)
|
||||
return 1;
|
||||
|
||||
@ -17,7 +17,7 @@ public enum FileFormat {
|
||||
EXCEL(true, "Excel", "xlsx"),
|
||||
WORD(true, "Word", "docx"),
|
||||
PDF(false, "PDF", "pdf"),
|
||||
PPT(false, "PPT", "pptx");
|
||||
PPT(true, "PPT", "pptx");
|
||||
|
||||
private final boolean creatable;
|
||||
private final String readableName;
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
package cn.axzo.nanopart.doc.api.file;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import cn.axzo.nanopart.doc.api.domain.IndexNodeInfo;
|
||||
import cn.axzo.nanopart.doc.api.index.request.GetNodeInfoRequest;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@FeignClient(name = "nanopart", url = "${axzo.service.nanopart:http://nanopart:8080}")
|
||||
public interface IndexNodeApi {
|
||||
|
||||
/**
|
||||
* 获取节点信息
|
||||
*/
|
||||
@PostMapping("/api/indexNode/getNodeInfo")
|
||||
CommonResponse<IndexNodeInfo> getNodeInfo(@RequestBody @Valid GetNodeInfoRequest request);
|
||||
|
||||
}
|
||||
@ -1,9 +1,11 @@
|
||||
|
||||
package cn.axzo.nanopart.doc.api.filedb.response;
|
||||
|
||||
import cn.axzo.nanopart.doc.api.enums.DatabaseType;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
import cn.axzo.nanopart.doc.api.enums.DatabaseType;
|
||||
import cn.axzo.nanopart.doc.api.enums.FileDatabaseState;
|
||||
import cn.axzo.nanopart.doc.api.templatedb.domain.TemplateDatabaseInfo;
|
||||
import lombok.Getter;
|
||||
@ -79,7 +81,7 @@ public class FileDatabaseInfoResponse {
|
||||
/**
|
||||
* 已使用的容量, 单位GB
|
||||
*/
|
||||
private Integer usedCapacity;
|
||||
private BigDecimal usedCapacity;
|
||||
|
||||
/**
|
||||
* 资料库信息
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
package cn.axzo.nanopart.doc.api.index.request;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
public class GetNodeInfoRequest {
|
||||
|
||||
/**
|
||||
* 节点编码
|
||||
*/
|
||||
@NotBlank(message = "节点编码不能为空")
|
||||
private String code;
|
||||
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
|
||||
package cn.axzo.nanopart.doc.dao;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
@ -19,9 +20,10 @@ import cn.axzo.nanopart.doc.mapper.FileDatabaseMapper;
|
||||
@Repository
|
||||
public class FileDatabaseDao extends ServiceImpl<FileDatabaseMapper, FileDatabase> {
|
||||
|
||||
public FileDatabase findForUpdateOrNull(DatabaseScope scope, String scopeUniqueCode) {
|
||||
public FileDatabase findForUpdateOrNull(DatabaseScope scope, String templateDatabaseCode, String scopeUniqueCode) {
|
||||
return lambdaQuery() //
|
||||
.eq(FileDatabase::getScope, scope) //
|
||||
.eq(FileDatabase::getTemplateDatabaseCode, templateDatabaseCode) //
|
||||
.eq(FileDatabase::getScopeUniqueCode, scopeUniqueCode) //
|
||||
.last("FOR UPDATE") //
|
||||
.one();
|
||||
@ -61,10 +63,11 @@ public class FileDatabaseDao extends ServiceImpl<FileDatabaseMapper, FileDatabas
|
||||
.remove();
|
||||
}
|
||||
|
||||
public void updateUsedCapacity(String code, int usedFileSize) {
|
||||
public void updateUsedCapacity(String code, int usedFileSizeKb, BigDecimal usedFileSizeGb) {
|
||||
lambdaUpdate() //
|
||||
.eq(FileDatabase::getCode, code) //
|
||||
.set(FileDatabase::getUsedCapacity, usedFileSize) //
|
||||
.set(FileDatabase::getUsedCapacity, usedFileSizeGb) //
|
||||
.set(FileDatabase::getUsedCapacityKb, usedFileSizeKb) //
|
||||
.update();
|
||||
}
|
||||
|
||||
@ -82,4 +85,13 @@ public class FileDatabaseDao extends ServiceImpl<FileDatabaseMapper, FileDatabas
|
||||
.update();
|
||||
}
|
||||
|
||||
public void expire() {
|
||||
lambdaUpdate() //
|
||||
.eq(FileDatabase::getState, FileDatabaseState.ACTIVATED) //
|
||||
.isNotNull(FileDatabase::getExpireDate)
|
||||
.le(FileDatabase::getExpireDate, new Date()) //
|
||||
.set(FileDatabase::getState, FileDatabaseState.EXPIRED)
|
||||
.update();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
|
||||
package cn.axzo.nanopart.doc.dao;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -16,6 +17,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
|
||||
import cn.axzo.nanopart.doc.api.domain.IndexNodeParentScope;
|
||||
import cn.axzo.nanopart.doc.api.domain.IndexNodeScope;
|
||||
import cn.axzo.nanopart.doc.api.enums.DatabaseScope;
|
||||
import cn.axzo.nanopart.doc.api.enums.IndexNodeState;
|
||||
import cn.axzo.nanopart.doc.api.enums.IndexNodeType;
|
||||
import cn.axzo.nanopart.doc.api.util.BizAssertions;
|
||||
@ -103,10 +105,11 @@ public class IndexNodeDao extends ServiceImpl<IndexNodeMapper, IndexNode> {
|
||||
.update();
|
||||
}
|
||||
|
||||
public List<IndexNode> collectValidSubtreeNodes(IndexNode indexNode) {
|
||||
public List<IndexNode> collectValidSubtreeNodes(IndexNode indexNode, IndexNodeType... nodeTypes) {
|
||||
return lambdaQuery() //
|
||||
.likeRight(IndexNode::getPath, indexNode.getPath()) //
|
||||
.eq(IndexNode::getState, IndexNodeState.VALID) //
|
||||
.in(nodeTypes.length > 0, IndexNode::getNodeType, Arrays.asList(nodeTypes)) //
|
||||
.list();
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ package cn.axzo.nanopart.doc.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cn.axzo.nanopart.doc.api.util.BizAssertions;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@ -18,6 +19,12 @@ import cn.axzo.nanopart.doc.mapper.TemplateDatabaseMapper;
|
||||
@Repository
|
||||
public class TemplateDatabaseDao extends ServiceImpl<TemplateDatabaseMapper, TemplateDatabase> {
|
||||
|
||||
public TemplateDatabase getOrThrow(String code) {
|
||||
TemplateDatabase templateDb = findOrNull(code);
|
||||
BizAssertions.assertNotNull(templateDb, "找不到资料库: {}", code);
|
||||
return templateDb;
|
||||
}
|
||||
|
||||
public TemplateDatabase findOrNull(String code) {
|
||||
return lambdaQuery().eq(TemplateDatabase::getCode, code).one();
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
|
||||
package cn.axzo.nanopart.doc.entity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
@ -76,7 +77,12 @@ public class FileDatabase extends BaseEntity<FileDatabase> implements IndexNodeS
|
||||
/**
|
||||
* 已使用的容量, 单位GB
|
||||
*/
|
||||
private Integer usedCapacity;
|
||||
private BigDecimal usedCapacity;
|
||||
|
||||
/**
|
||||
* 已使用的容量, 单位kb
|
||||
*/
|
||||
private Integer usedCapacityKb;
|
||||
|
||||
public boolean isActivated() {
|
||||
return state == FileDatabaseState.ACTIVATED;
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
|
||||
package cn.axzo.nanopart.doc.entity;
|
||||
|
||||
import cn.axzo.nanopart.doc.api.enums.FileFeeType;
|
||||
import cn.axzo.nanopart.doc.api.enums.FileTemplateFeeType;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@ -56,6 +58,10 @@ public class TemplateDatabase extends BaseEntity<TemplateDatabase> implements In
|
||||
@TableField(typeHandler = FastjsonTypeHandler.class)
|
||||
private DatabaseAccessConfig accessConfig;
|
||||
|
||||
public FileTemplateFeeType getFeeType() {
|
||||
return feeConfig == null ? null : feeConfig.getFeeType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String indexNodeCode() {
|
||||
return code;
|
||||
|
||||
@ -25,7 +25,6 @@ public class BizCodeGenerator {
|
||||
.append(create.nodeScope().scope() == DatabaseScope.ENT_DATABASE ? "ent" : "pro") //
|
||||
.append(nodeType == IndexNodeType.DATABASE ? "space" : "folder") //
|
||||
.append(create.nodeScope().context() == IndexNodeContext.TEMPLATE_DATABASE ? "oms" : workspaceId) //
|
||||
.append("") //
|
||||
.build();
|
||||
create.setBizCode(bizCode);
|
||||
}
|
||||
|
||||
@ -19,12 +19,17 @@ import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import cn.axzo.basics.common.BeanMapper;
|
||||
import cn.axzo.nanopart.doc.api.anonymous.DocAnonymousDatabaseApi;
|
||||
import cn.axzo.nanopart.doc.api.anonymous.request.AnonymousCreateDirRequest;
|
||||
import cn.axzo.nanopart.doc.api.anonymous.request.AnonymousCreateFileRequest;
|
||||
import cn.axzo.nanopart.doc.api.anonymous.request.AnonymousUploadFileRequest;
|
||||
import cn.axzo.nanopart.doc.api.domain.IndexNodeInfo;
|
||||
import cn.axzo.nanopart.doc.api.domain.OssFile;
|
||||
import cn.axzo.nanopart.doc.api.index.request.CopyNodeRequest;
|
||||
import cn.axzo.nanopart.doc.api.index.request.DeleteNodeRequest;
|
||||
import cn.axzo.nanopart.doc.api.index.request.GetNodeInfoRequest;
|
||||
import cn.axzo.nanopart.doc.api.index.request.RenameNodeRequest;
|
||||
import cn.axzo.nanopart.doc.entity.IndexNode;
|
||||
import cn.axzo.nanopart.doc.file.index.IndexManager;
|
||||
import cn.axzo.nanopart.doc.utils.AsyncUtils;
|
||||
@ -57,13 +62,26 @@ public class DocAnonymousDatabaseApiController implements DocAnonymousDatabaseAp
|
||||
return CommonResponse.success(indexManager.createFile(request, ossFile).getCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<IndexNodeInfo> createFile2(AnonymousCreateFileRequest request) {
|
||||
OssFile ossFile = indexManager.prepareEmptyOssFile(request, request.getFormat());
|
||||
IndexNode fileNode = indexManager.createFile(request, ossFile);
|
||||
return CommonResponse.success(BeanMapper.map(fileNode, IndexNodeInfo.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<String> uploadFile(AnonymousUploadFileRequest request) {
|
||||
log.info("upload file request:{}", request);
|
||||
request.getOssFile().validate();
|
||||
return CommonResponse.success(indexManager.uploadFile(request, request.getOssFile()).getCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<IndexNodeInfo> uploadFile2(AnonymousUploadFileRequest request) {
|
||||
log.info("upload file2 request:{}", request);
|
||||
IndexNode fileNode = indexManager.uploadFile(request, request.getOssFile());
|
||||
return CommonResponse.success(BeanMapper.map(fileNode, IndexNodeInfo.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<String> copy(CopyNodeRequest request) {
|
||||
log.info("copy request:{}", request);
|
||||
@ -71,6 +89,26 @@ public class DocAnonymousDatabaseApiController implements DocAnonymousDatabaseAp
|
||||
return CommonResponse.success(asyncUtils.getOrTimeout(future, 60, "克隆").getCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<Void> delete(DeleteNodeRequest request) {
|
||||
log.info("delete request:{}", request);
|
||||
indexManager.delete(request.getCode());
|
||||
return CommonResponse.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<Void> rename(RenameNodeRequest request) {
|
||||
log.info("rename request:{}", request);
|
||||
indexManager.rename(request.getCode(), request.getNewName());
|
||||
return CommonResponse.success();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResponse<IndexNodeInfo> getNodeInfo(GetNodeInfoRequest request) {
|
||||
IndexNode indexNode = indexManager.getOrThrow(request.getCode());
|
||||
return CommonResponse.success(BeanMapper.copyBean(indexNode, IndexNodeInfo.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量获取节点信息集合
|
||||
*/
|
||||
|
||||
@ -1,17 +1,10 @@
|
||||
|
||||
package cn.axzo.nanopart.doc.file.filedb;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.xxl.job.core.biz.model.ReturnT;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
|
||||
import cn.axzo.nanopart.doc.api.enums.FileDatabaseState;
|
||||
import cn.axzo.nanopart.doc.dao.FileDatabaseDao;
|
||||
import cn.axzo.nanopart.doc.entity.FileDatabase;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
@ -21,14 +14,11 @@ import lombok.RequiredArgsConstructor;
|
||||
@SuppressWarnings({ "unused", "used by job" })
|
||||
public class FileDatabaseExpireJob {
|
||||
|
||||
private final FileDatabaseDao fileDatabaseDao;
|
||||
private final FileDatabaseService fileDatabaseService;
|
||||
|
||||
@XxlJob("fileDatabaseExpireJob")
|
||||
public ReturnT<String> exec(String paramStr) {
|
||||
fileDatabaseDao.lambdaUpdate() //
|
||||
.eq(FileDatabase::getState, FileDatabaseState.ACTIVATED) //
|
||||
.le(FileDatabase::getExpireDate, new Date()) //
|
||||
.update();
|
||||
fileDatabaseService.expire();
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,8 @@ package cn.axzo.nanopart.doc.file.filedb;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
@ -26,10 +28,13 @@ import cn.axzo.apollo.workspace.api.workspace.res.SimpleWorkspaceRes;
|
||||
import cn.axzo.apollo.workspace.common.enums.WorkspaceTypeEnum;
|
||||
import cn.axzo.maokai.api.vo.response.tree.ValueNode;
|
||||
import cn.axzo.maokai.api.vo.response.tree.WalkingDecision;
|
||||
import cn.axzo.nanopart.doc.api.domain.DatabaseFeeConfig;
|
||||
import cn.axzo.nanopart.doc.api.domain.IndexNodeScope;
|
||||
import cn.axzo.nanopart.doc.api.enums.DatabaseScope;
|
||||
import cn.axzo.nanopart.doc.api.enums.DatabaseType;
|
||||
import cn.axzo.nanopart.doc.api.enums.FileDatabaseState;
|
||||
import cn.axzo.nanopart.doc.api.enums.FileTemplateFeeType;
|
||||
import cn.axzo.nanopart.doc.api.enums.IndexNodeContext;
|
||||
import cn.axzo.nanopart.doc.api.enums.IndexNodeType;
|
||||
import cn.axzo.nanopart.doc.api.filedb.request.FileDatabaseAbortRequest;
|
||||
import cn.axzo.nanopart.doc.api.filedb.request.FileDatabaseActiveRequest;
|
||||
@ -88,26 +93,26 @@ public class FileDatabaseService {
|
||||
|
||||
private FileDatabase addWorkspace0(FileDatabaseAddWorkspaceRequest request) {
|
||||
String scopeUniqueCode = String.valueOf(request.getWorkspaceId());
|
||||
TemplateDatabase templateDatabase = templateDatabaseQueryService.getOrThrow(request.getTemplateDatabaseCode());
|
||||
FileDatabase savedDb = fileDatabaseDao.findForUpdateOrNull(templateDatabase.getScope(), scopeUniqueCode);
|
||||
TemplateDatabase templateDb = templateDatabaseQueryService.getOrThrow(request.getTemplateDatabaseCode());
|
||||
FileDatabase savedDb = fileDatabaseDao.findForUpdateOrNull(templateDb.getScope(), templateDb.getCode(),
|
||||
scopeUniqueCode);
|
||||
if (savedDb != null)
|
||||
throw new FileDatabaseExistsException("无法重复创建, 请刷新页面查询已创建的记录");
|
||||
SimpleWorkspaceRes workspace = RpcExternalUtil.rpcApolloProcessor(
|
||||
() -> workspaceApi.getOne(request.getWorkspaceId()), "查询租户", request.getWorkspaceId());
|
||||
BizAssertions.assertNotNull(workspace, "找不到对应的租户");
|
||||
BizAssertions.assertEquals(workspace.getType(), templateDatabase.getScope().getWorkspaceType(),
|
||||
"请求租户类型和资料库的租户类型不匹配");
|
||||
BizAssertions.assertEquals(workspace.getType(), templateDb.getScope().getWorkspaceType(), "请求租户类型和资料库的租户类型不匹配");
|
||||
FileDatabase db = new FileDatabase();
|
||||
db.setCode(UUIDUtil.uuidString());
|
||||
db.setTemplateDatabaseCode(templateDatabase.getCode());
|
||||
db.setScope(templateDatabase.getScope());
|
||||
db.setTemplateDatabaseCode(templateDb.getCode());
|
||||
db.setScope(templateDb.getScope());
|
||||
db.setScopeUniqueCode(scopeUniqueCode);
|
||||
db.setWorkspaceId(request.getWorkspaceId());
|
||||
db.setState(FileDatabaseState.ACTIVATING);
|
||||
if (request.getExpiredDateMs() != null)
|
||||
if (templateDb.getFeeType() == FileTemplateFeeType.ANNUAL && request.getExpiredDateMs() != null)
|
||||
db.setExpireDate(new Date(request.getExpiredDateMs()));
|
||||
db.setAllowedCapacity(request.getAllowedCapacity());
|
||||
db.setUsedCapacity(0);
|
||||
db.setUsedCapacity(BigDecimal.ZERO);
|
||||
db.setCreateAt(new Date());
|
||||
db.setUpdateAt(new Date());
|
||||
fileDatabaseDao.save(db);
|
||||
@ -140,7 +145,8 @@ public class FileDatabaseService {
|
||||
public WalkingDecision visit(ValueNode<IndexNode> node) {
|
||||
WalkingDecision walkingDecision = super.visit(node);
|
||||
IndexNode indexNode = node.getValue();
|
||||
BizCodeGenerator.gen(indexNode, indexNode.getNodeType(), db.getWorkspaceId());
|
||||
if (indexNode.isDatabase() || indexNode.isDirectory())
|
||||
BizCodeGenerator.gen(indexNode, indexNode.getNodeType(), db.getWorkspaceId());
|
||||
return walkingDecision;
|
||||
}
|
||||
});
|
||||
@ -167,14 +173,16 @@ public class FileDatabaseService {
|
||||
@BizTransactional
|
||||
public void fileSizeChanged(String indexNodeCode) {
|
||||
IndexNode indexNode = indexManager.findOrNull(indexNodeCode);
|
||||
if (indexNode == null || !indexNode.isFile())
|
||||
if (indexNode == null || !indexNode.isFile() || indexNode.context() != IndexNodeContext.FILE_DATABASE)
|
||||
return;
|
||||
FileDatabase db = fileDatabaseDao.findForUpdateOrNull(indexNode.scopeCode());
|
||||
if (db == null)
|
||||
return;
|
||||
int usedFileSize = indexQueryService.getUsedFileSize(db);
|
||||
fileDatabaseDao.updateUsedCapacity(db.getCode(), usedFileSize);
|
||||
if (db.isActivated() && db.getAllowedCapacity() <= usedFileSize)
|
||||
int sizeByte = indexQueryService.getUsedFileSize(db);
|
||||
BigDecimal sizeGb = BigDecimal.valueOf(sizeByte) //
|
||||
.divide(BigDecimal.valueOf(1024 * 1024 * 1024), 2, RoundingMode.HALF_UP);
|
||||
fileDatabaseDao.updateUsedCapacity(db.getCode(), sizeByte, sizeGb);
|
||||
if (db.isActivated() && isCapacityExhausted(db.getAllowedCapacity(), sizeGb))
|
||||
fileDatabaseDao.updateState(db.getCode(), FileDatabaseState.CAPACITY_EXHAUSTED);
|
||||
}
|
||||
|
||||
@ -184,21 +192,31 @@ public class FileDatabaseService {
|
||||
FileDatabase db = fileDatabaseDao.getForUpdateOrThrow(request.getCode());
|
||||
updateCapacity(request) //
|
||||
.set(FileDatabase::getState, //
|
||||
request.getAllowedCapacity() <= db.getUsedCapacity() //
|
||||
isCapacityExhausted(request.getAllowedCapacity(), db.getUsedCapacity()) //
|
||||
? FileDatabaseState.CAPACITY_EXHAUSTED //
|
||||
: FileDatabaseState.ACTIVATED) //
|
||||
.update();
|
||||
}
|
||||
|
||||
private boolean isCapacityExhausted(Integer allowedCapacity, BigDecimal usedCapacity) {
|
||||
return BigDecimal.valueOf(allowedCapacity).compareTo(usedCapacity) <= 0;
|
||||
}
|
||||
|
||||
@BizTransactional
|
||||
public void expandCapacity(FileDatabaseExpandCapacityRequest request) {
|
||||
docLogDao.logRequest("expandCapacity", request.getCode(), request);
|
||||
FileDatabase db = fileDatabaseDao.getForUpdateOrThrow(request.getCode());
|
||||
BizAssertions.assertTrue(db.isActivated(), "只有激活状态的资料库才能扩容");
|
||||
DatabaseFeeConfig feeConfig = templateDatabaseQueryService.getOrThrow(
|
||||
db.getTemplateDatabaseCode()).getFeeConfig();
|
||||
if (feeConfig != null)
|
||||
BizAssertions.assertTrue(feeConfig.getExtendable(), "资料库不支持扩容");
|
||||
updateCapacity(request).update();
|
||||
}
|
||||
|
||||
private LambdaUpdateChainWrapper<FileDatabase> updateCapacity(FileDatabaseActiveRequest request) {
|
||||
FileDatabase db = fileDatabaseDao.getOrThrow(request.getCode());
|
||||
TemplateDatabase templateDb = templateDatabaseQueryService.getOrThrow(db.getTemplateDatabaseCode());
|
||||
Date expireDate = null;
|
||||
if (request.getExpiredDateMs() != null && request.getExpiredDateMs() > 0)
|
||||
expireDate = new Date(request.getExpiredDateMs());
|
||||
@ -206,7 +224,8 @@ public class FileDatabaseService {
|
||||
.eq(FileDatabase::getCode, request.getCode()) //
|
||||
.set(FileDatabase::getAllowedCapacity, request.getAllowedCapacity()) //
|
||||
.set(FileDatabase::getPurchaseDate, new Date()) //
|
||||
.set(expireDate != null, FileDatabase::getExpireDate, expireDate);
|
||||
.set(templateDb.getFeeType() == FileTemplateFeeType.ANNUAL && expireDate != null,
|
||||
FileDatabase::getExpireDate, expireDate);
|
||||
}
|
||||
|
||||
@BizTransactional
|
||||
@ -294,4 +313,8 @@ public class FileDatabaseService {
|
||||
.collect(toList());
|
||||
return Page.toPage(request.getPage(), request.getPageSize(), page.getTotal(), records);
|
||||
}
|
||||
|
||||
public void expire() {
|
||||
this.fileDatabaseDao.expire();
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,7 +67,6 @@ public class FileTemplateApiController implements FileTemplateApi {
|
||||
@Override
|
||||
public CommonResponse<String> uploadFile(FileTemplateUploadFileRequest request) {
|
||||
log.info("upload file request:{}", request);
|
||||
request.getOssFile().validate();
|
||||
return CommonResponse.success(fileTemplateManager.uploadFile(request));
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
|
||||
package cn.axzo.nanopart.doc.file.filetemplate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import cn.axzo.nanopart.doc.api.domain.OssFile;
|
||||
import cn.axzo.nanopart.doc.api.enums.FileTemplateState;
|
||||
import cn.axzo.nanopart.doc.api.enums.IndexNodeContext;
|
||||
import cn.axzo.nanopart.doc.api.enums.IndexNodeType;
|
||||
import cn.axzo.nanopart.doc.api.filetemplate.request.FileTemplateCreateDirRequest;
|
||||
import cn.axzo.nanopart.doc.api.filetemplate.request.FileTemplateCreateFileRequest;
|
||||
@ -18,6 +21,7 @@ import cn.axzo.nanopart.doc.dao.FileTemplateDao;
|
||||
import cn.axzo.nanopart.doc.entity.FileTemplate;
|
||||
import cn.axzo.nanopart.doc.entity.IndexNode;
|
||||
import cn.axzo.nanopart.doc.file.index.IndexManager;
|
||||
import cn.axzo.nanopart.doc.file.index.SubtreeCopyEventTransactional;
|
||||
import cn.axzo.nanopart.doc.file.index.domain.IndexNodes;
|
||||
import cn.axzo.nanopart.doc.utils.BizTransactional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -27,11 +31,11 @@ import lombok.RequiredArgsConstructor;
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class FileTemplateManager {
|
||||
public class FileTemplateManager implements ApplicationListener<SubtreeCopyEventTransactional> {
|
||||
|
||||
private final IndexManager indexManager;
|
||||
private final FileTemplateDao fileTemplateDao;
|
||||
private final TransactionTemplate transactionTemplate;
|
||||
private final TransactionTemplate transaction;
|
||||
|
||||
public String createDir(FileTemplateCreateDirRequest request) {
|
||||
return indexManager.createDir(request).getCode();
|
||||
@ -39,7 +43,7 @@ public class FileTemplateManager {
|
||||
|
||||
public String createFile(FileTemplateCreateFileRequest request) {
|
||||
OssFile ossFile = indexManager.prepareEmptyOssFile(request, request.getFormat());
|
||||
return transactionTemplate.execute(unused -> createFileTemplate(indexManager.createFile(request, ossFile)));
|
||||
return transaction.execute(unused -> createFileTemplate(indexManager.createFile(request, ossFile)));
|
||||
}
|
||||
|
||||
@BizTransactional
|
||||
@ -48,11 +52,16 @@ public class FileTemplateManager {
|
||||
}
|
||||
|
||||
private String createFileTemplate(IndexNode fileNode) {
|
||||
FileTemplate fileTemplate = buildFileTemplate(fileNode);
|
||||
fileTemplateDao.save(fileTemplate);
|
||||
return fileNode.getCode();
|
||||
}
|
||||
|
||||
private static FileTemplate buildFileTemplate(IndexNode fileNode) {
|
||||
FileTemplate fileTemplate = new FileTemplate();
|
||||
fileTemplate.setCode(fileNode.getCode());
|
||||
fileTemplate.setState(FileTemplateState.UNPUBLISH);
|
||||
fileTemplateDao.save(fileTemplate);
|
||||
return fileNode.getCode();
|
||||
return fileTemplate;
|
||||
}
|
||||
|
||||
@BizTransactional
|
||||
@ -81,4 +90,16 @@ public class FileTemplateManager {
|
||||
.set(request.getState() != null, FileTemplate::getState, request.getState()) //
|
||||
.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(SubtreeCopyEventTransactional event) {
|
||||
if (event.getCopiedRoot().getContext() != IndexNodeContext.FILE_TEMPLATE)
|
||||
return;
|
||||
ArrayList<FileTemplate> fileTemplates = new ArrayList<>();
|
||||
for (IndexNode fileNode : indexManager.collectValidSubtreeNodes(event.getCopiedRoot(), IndexNodeType.FILE))
|
||||
fileTemplates.add(buildFileTemplate(fileNode));
|
||||
if (!fileTemplates.isEmpty())
|
||||
fileTemplateDao.saveBatch(fileTemplates);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import java.util.concurrent.Future;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
@ -52,16 +53,17 @@ public class IndexManager {
|
||||
private final FileBroadcaster fileBroadcaster;
|
||||
private final TransactionTemplate transaction;
|
||||
private final DocLogDao docLogDao;
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
@BizTransactional
|
||||
public IndexNode createDatabase(NodeCreate create) {
|
||||
ensureChildNameNotUsed(create, IndexNodeType.DATABASE, true);
|
||||
indexSupport.ensureChildNameNotUsed(create, IndexNodeType.DATABASE, true);
|
||||
return indexSupport.createNode(create, IndexNodeType.DATABASE);
|
||||
}
|
||||
|
||||
@BizTransactional
|
||||
public IndexNode createDir(NodeCreate create) {
|
||||
ensureChildNameNotUsed(create, IndexNodeType.DIRECTORY, true);
|
||||
indexSupport.ensureChildNameNotUsed(create, IndexNodeType.DIRECTORY, true);
|
||||
return indexSupport.createNode(create, IndexNodeType.DIRECTORY);
|
||||
}
|
||||
|
||||
@ -69,7 +71,7 @@ public class IndexManager {
|
||||
BizAssertions.assertTrue(format.creatable(), "无法创建: {}", format.readableName());
|
||||
BizAssertions.assertFalse(TransactionSynchronizationManager.isActualTransactionActive(), "不能在事务中使用");
|
||||
// check without lock
|
||||
ensureChildNameNotUsed(create, IndexNodeType.FILE, false);
|
||||
indexSupport.ensureChildNameNotUsed(create, IndexNodeType.FILE, false);
|
||||
String fullFileName = String.format("%s.%s", create.name(), format.createFileExtension());
|
||||
String emptyOssFileKey = format == FileFormat.WORD //
|
||||
? docProps.getCreateFileOssFileKeyWord() //
|
||||
@ -83,9 +85,10 @@ public class IndexManager {
|
||||
@BizTransactional
|
||||
public IndexNode uploadFile(NodeCreate node, OssFile ossFile) {
|
||||
BizAssertions.assertNotNull(ossFile.getFormat(), "format不能为空");
|
||||
BizAssertions.assertTrue(ossFile.getSize() > 0, "size必须大于0");
|
||||
BizAssertions.assertNotBlank(ossFile.getOssFileKey(), "oosFileKey不能为空");
|
||||
BizAssertions.assertNotBlank(ossFile.getExtension(), "extension不能为空");
|
||||
if (node.nodeScope().scope().isFeeAware())
|
||||
BizAssertions.assertTrue(ossFile.getSize() >= 0, "size必须大于等于0");
|
||||
IndexNode fileNode = createFile(node, ossFile);
|
||||
updateFileSize(fileNode, ossFile.getSize());
|
||||
return fileNode;
|
||||
@ -93,7 +96,7 @@ public class IndexManager {
|
||||
|
||||
@BizTransactional
|
||||
public void updateFileSize(IndexNode fileNode, int size) {
|
||||
if (fileNode == null || !fileNode.isFile())
|
||||
if (fileNode == null || !fileNode.isFile() || size < 0)
|
||||
return;
|
||||
indexNodeDao.updateFileSize(fileNode.getCode(), size);
|
||||
fileBroadcaster.fireFileSizeChanged(fileNode.getCode());
|
||||
@ -105,7 +108,7 @@ public class IndexManager {
|
||||
return transaction.execute(unused -> {
|
||||
try {
|
||||
// check with lock
|
||||
ensureChildNameNotUsed(create, IndexNodeType.FILE, true);
|
||||
indexSupport.ensureChildNameNotUsed(create, IndexNodeType.FILE, true);
|
||||
}
|
||||
catch (NameUsedException e) {
|
||||
deleteOssFile.set(true);
|
||||
@ -128,14 +131,6 @@ public class IndexManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureChildNameNotUsed(NodeCreate create, IndexNodeType nodeType, boolean withLock) {
|
||||
if (indexSupport.childrenNameDuplicatable(create))
|
||||
return;
|
||||
if (withLock)
|
||||
indexSupport.lockParentAndReleaseOnCommit(create);
|
||||
indexSupport.ensureChildNameNotUsed(create, nodeType, create.name());
|
||||
}
|
||||
|
||||
@BizTransactional
|
||||
public void rename(String code, String newName) {
|
||||
IndexNode indexNode = getOrThrow(code);
|
||||
@ -158,7 +153,7 @@ public class IndexManager {
|
||||
public List<IndexNode> delete(String code) {
|
||||
IndexNode indexNode = getOrThrow(code);
|
||||
docLogDao.log("indexNode:delete", code);
|
||||
List<IndexNode> subtree = indexNodeDao.collectValidSubtreeNodes(indexNode);
|
||||
List<IndexNode> subtree = collectValidSubtreeNodes(indexNode);
|
||||
indexNodeDao.stateDeleteSubtree(indexNode);
|
||||
return subtree;
|
||||
}
|
||||
@ -176,7 +171,7 @@ public class IndexManager {
|
||||
IndexNode srcNode = getOrThrow(srcCode);
|
||||
BizAssertions.assertTrue(indexNodeDao.validSubtreeFileCount(srcNode) <= docProps.getIndexNodeMaxCopyFileSize(),
|
||||
"拷贝文件数超过限制: {}", docProps.getIndexNodeMaxCopyFileSize());
|
||||
IndexNode destParentNode = determineDestParentNode(srcNode, destParentCode, "克隆");
|
||||
IndexNode destParentNode = determineDestParentNode(srcNode, destParentCode, Op.COPY);
|
||||
return async(() -> {
|
||||
// don't inline in transaction
|
||||
CopyFileVisitor copyNodeVisitor = new CopyFileVisitor(copySubtreeOssFiles(srcNode));
|
||||
@ -193,7 +188,7 @@ public class IndexManager {
|
||||
*/
|
||||
public Future<IndexNode> asyncMove(String srcCode, @Nullable String destParentCode) {
|
||||
IndexNode srcNode = getOrThrow(srcCode);
|
||||
IndexNode destParentNode = determineDestParentNode(srcNode, destParentCode, "移动");
|
||||
IndexNode destParentNode = determineDestParentNode(srcNode, destParentCode, Op.MOVE);
|
||||
return async(() -> transaction.execute(unused -> {
|
||||
docLogDao.log("indexNode:asyncMove", srcCode, "srcCode", srcCode, "destParentCode", destParentCode);
|
||||
if (docProps.isLockSubtreeWhenMove())
|
||||
@ -204,18 +199,20 @@ public class IndexManager {
|
||||
}));
|
||||
}
|
||||
|
||||
private IndexNode determineDestParentNode(IndexNode srcNode, String destParentCode, String op) {
|
||||
private IndexNode determineDestParentNode(IndexNode srcNode, String destParentCode, Op op) {
|
||||
IndexNode parent = StringUtils.isBlank(destParentCode) ? null : getOrThrow(destParentCode);
|
||||
if (parent == null)
|
||||
return null;
|
||||
BizAssertions.assertFalse(srcNode.isDirectory() && parent.isFile(), "不能{}文件夹到文件下", op);
|
||||
BizAssertions.assertFalse(srcNode.isSameNodeWith(parent), "不能{}到同一节点下", op);
|
||||
BizAssertions.assertFalse(srcNode.isParentOf(parent), "不能{}到子节点下", op);
|
||||
if (op == Op.MOVE)
|
||||
BizAssertions.assertFalse(srcNode.isSameNodeWith(parent), "不能{}到同一节点下", op);
|
||||
List<IndexNode> subtreeNodes = indexSupport.collectValidSubtreeAsValueRoot(srcNode);
|
||||
int subtreeMaxDepth = IndexNodeTreeUtils.build(subtreeNodes).getChildren().stream() //
|
||||
int subtreeMaxDepth = IndexNodeTreeUtils.build(subtreeNodes).getValueNodes().stream() //
|
||||
.mapToInt(Node::getLevel) //
|
||||
.max() //
|
||||
.orElse(0);
|
||||
// 这里不加1, 因为root node其实不是真实的值节点, 不用算在内
|
||||
indexSupport.validateDepthWhenAddChild(parent.path().depth() + subtreeMaxDepth);
|
||||
return parent;
|
||||
}
|
||||
@ -226,7 +223,9 @@ public class IndexManager {
|
||||
RootNode<IndexNode> srcRoot = TreeUtils.transform(subtreeNodes, IndexNode.class, true);
|
||||
srcRoot.walkDown(copyNodeVisitor);
|
||||
indexNodeDao.saveBatch(TreeUtils.collectValues(srcRoot));
|
||||
return connectNodes(srcRoot, destParent);
|
||||
IndexNode copiedRoot = connectNodes(srcRoot, destParent);
|
||||
applicationContext.publishEvent(new SubtreeCopyEventTransactional(this, src, copiedRoot));
|
||||
return copiedRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -244,6 +243,10 @@ public class IndexManager {
|
||||
return indexNodeDao.findOrNull(rootNode.getCode());
|
||||
}
|
||||
|
||||
public List<IndexNode> collectValidSubtreeNodes(IndexNode indexNode, IndexNodeType... nodeTypes) {
|
||||
return indexNodeDao.collectValidSubtreeNodes(indexNode, nodeTypes);
|
||||
}
|
||||
|
||||
public IndexNode findOrNull(String code) {
|
||||
if (StringUtils.isBlank(code))
|
||||
return null;
|
||||
@ -280,4 +283,14 @@ public class IndexManager {
|
||||
});
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private enum Op {
|
||||
MOVE("移动"), COPY("克隆");
|
||||
private final String name;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
|
||||
package cn.axzo.nanopart.doc.file.index;
|
||||
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import cn.axzo.basics.common.BeanMapper;
|
||||
import cn.axzo.nanopart.doc.api.domain.IndexNodeInfo;
|
||||
import cn.axzo.nanopart.doc.api.file.IndexNodeApi;
|
||||
import cn.axzo.nanopart.doc.api.index.request.GetNodeInfoRequest;
|
||||
import cn.axzo.nanopart.doc.entity.IndexNode;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class IndexNodeApiController implements IndexNodeApi {
|
||||
|
||||
private final IndexManager indexManager;
|
||||
|
||||
@Override
|
||||
public CommonResponse<IndexNodeInfo> getNodeInfo(GetNodeInfoRequest request) {
|
||||
IndexNode indexNode = indexManager.getOrThrow(request.getCode());
|
||||
return CommonResponse.success(BeanMapper.copyBean(indexNode, IndexNodeInfo.class));
|
||||
}
|
||||
|
||||
}
|
||||
@ -100,8 +100,8 @@ public class IndexSupport {
|
||||
"创建失败, 子节点数量不能超过 {}", docProps.getIndexNodeMaxChildrenSize());
|
||||
}
|
||||
|
||||
public void validateDepthWhenAddChild(int pendingDepth) {
|
||||
BizAssertions.assertTrue(pendingDepth >= docProps.getIndexNodeMaxDepth(), //
|
||||
public void validateDepthWhenAddChild(int targetDepth) {
|
||||
BizAssertions.assertTrue(targetDepth <= docProps.getIndexNodeMaxDepth(), //
|
||||
"节点深度超过限制{}, 无法再创建新节点", docProps.getIndexNodeMaxDepth());
|
||||
}
|
||||
|
||||
@ -134,6 +134,14 @@ public class IndexSupport {
|
||||
indexNodeDao.rename(rename.getCode(), newName);
|
||||
}
|
||||
|
||||
void ensureChildNameNotUsed(NodeCreate create, IndexNodeType nodeType, boolean withLock) {
|
||||
if (childrenNameDuplicatable(create))
|
||||
return;
|
||||
if (withLock)
|
||||
lockParentAndReleaseOnCommit(create);
|
||||
ensureChildNameNotUsed(create, nodeType, create.name());
|
||||
}
|
||||
|
||||
void ensureChildNameNotUsed(IndexNodeParentScope parentScope, IndexNodeType nodeType, String childName) {
|
||||
IndexNode child = indexNodeDao.findValidChildByName(parentScope, nodeType, childName);
|
||||
// don't use BizAssertions.assertNull
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
|
||||
package cn.axzo.nanopart.doc.file.index;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import cn.axzo.nanopart.doc.entity.IndexNode;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author yanglin
|
||||
*/
|
||||
@Getter
|
||||
public class SubtreeCopyEventTransactional extends ApplicationEvent {
|
||||
|
||||
private final IndexNode srcNode;
|
||||
private final IndexNode copiedRoot;
|
||||
|
||||
public SubtreeCopyEventTransactional(Object source, IndexNode srcNode, IndexNode copiedRoot) {
|
||||
super(source);
|
||||
this.srcNode = srcNode;
|
||||
this.copiedRoot = copiedRoot;
|
||||
}
|
||||
|
||||
}
|
||||
@ -29,6 +29,12 @@ public class IndexNodes {
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
public List<IndexNode> collectNodes(IndexNodeType nodeType) {
|
||||
return indexNodes.stream() //
|
||||
.filter(node -> node.getNodeType() == nodeType) //
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
public IndexNode findOrNull(String code) {
|
||||
return indexNodes.stream() //
|
||||
.filter(node -> node.getCode().equals(code)) //
|
||||
|
||||
@ -78,7 +78,6 @@ public class TemplateDatabaseApiController implements TemplateDatabaseApi {
|
||||
@Override
|
||||
public CommonResponse<String> uploadFile(TemplateDatabaseUploadFileRequest request) {
|
||||
log.info("upload file request:{}", request);
|
||||
request.getOssFile().validate();
|
||||
return CommonResponse.success(templateDatabaseManager.updateFile(request));
|
||||
}
|
||||
|
||||
|
||||
@ -4,11 +4,13 @@ package cn.axzo.nanopart.doc.file.templatedb;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
import cn.axzo.nanopart.doc.api.domain.OssFile;
|
||||
import cn.axzo.nanopart.doc.api.enums.IndexNodeContext;
|
||||
import cn.axzo.nanopart.doc.api.enums.IndexNodeType;
|
||||
import cn.axzo.nanopart.doc.api.index.request.DeleteNodeRequest;
|
||||
import cn.axzo.nanopart.doc.api.templatedb.reqeust.NodeCreateTemplateDatabase;
|
||||
@ -23,6 +25,7 @@ import cn.axzo.nanopart.doc.entity.IndexNode;
|
||||
import cn.axzo.nanopart.doc.entity.TemplateDatabase;
|
||||
import cn.axzo.nanopart.doc.file.BizCodeGenerator;
|
||||
import cn.axzo.nanopart.doc.file.index.IndexManager;
|
||||
import cn.axzo.nanopart.doc.file.index.SubtreeCopyEventTransactional;
|
||||
import cn.axzo.nanopart.doc.file.index.domain.IndexNodes;
|
||||
import cn.axzo.nanopart.doc.utils.BizTransactional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -32,7 +35,7 @@ import lombok.RequiredArgsConstructor;
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class TemplateDatabaseManager {
|
||||
public class TemplateDatabaseManager implements ApplicationListener<SubtreeCopyEventTransactional> {
|
||||
|
||||
private final IndexManager indexManager;
|
||||
private final TemplateDatabaseDao templateDatabaseDao;
|
||||
@ -110,4 +113,19 @@ public class TemplateDatabaseManager {
|
||||
.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(SubtreeCopyEventTransactional event) {
|
||||
if (event.getCopiedRoot().getContext() != IndexNodeContext.TEMPLATE_DATABASE)
|
||||
return;
|
||||
if (event.getCopiedRoot().getNodeType() != IndexNodeType.DATABASE)
|
||||
return;
|
||||
TemplateDatabase templateDb = templateDatabaseDao.getOrThrow(event.getSrcNode().getCode());
|
||||
TemplateDatabase db = new TemplateDatabase();
|
||||
db.setCode(event.getCopiedRoot().getCode());
|
||||
db.setScope(event.getCopiedRoot().getScope());
|
||||
db.setCoopType(templateDb.getCoopType());
|
||||
db.setCreateAt(new Date());
|
||||
db.setUpdateAt(new Date());
|
||||
templateDatabaseDao.save(db);
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ public class AsyncUtils {
|
||||
return result;
|
||||
}
|
||||
catch (CannotAcquireLockException e) {
|
||||
String message = String.format("%s等待超时, 可能正在移动节点, 请稍后刷新页面重试", op);
|
||||
String message = String.format("%s等待超时, 请稍后重试", op);
|
||||
log.warn(message, e);
|
||||
throw fail(message);
|
||||
}
|
||||
|
||||
@ -1,8 +1,18 @@
|
||||
package cn.axzo.nanopart.doc.wps.wpsbase;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import cn.axzo.basics.common.util.AssertUtil;
|
||||
import cn.axzo.basics.profiles.dto.basic.PersonProfileDto;
|
||||
import cn.axzo.nanopart.doc.api.enums.WpsErrorCodeEnum;
|
||||
import cn.axzo.nanopart.doc.api.wps.exception.WpsException;
|
||||
import cn.axzo.nanopart.doc.api.wps.request.WpsPermissionRequest;
|
||||
import cn.axzo.nanopart.doc.api.wps.request.WpsRenameRequest;
|
||||
import cn.axzo.nanopart.doc.api.wps.request.WpsUsersRequest;
|
||||
@ -12,8 +22,9 @@ import cn.axzo.nanopart.doc.api.wps.response.WpsPermissionResponse;
|
||||
import cn.axzo.nanopart.doc.api.wps.response.WpsRenameResponse;
|
||||
import cn.axzo.nanopart.doc.api.wps.response.WpsUsersResponse;
|
||||
import cn.axzo.nanopart.doc.config.DocPermissionProps;
|
||||
import cn.axzo.nanopart.doc.dao.IndexNodeDao;
|
||||
import cn.axzo.nanopart.doc.entity.IndexNode;
|
||||
import cn.axzo.nanopart.doc.file.index.IndexManager;
|
||||
import cn.axzo.nanopart.doc.file.index.domain.NameUsedException;
|
||||
import cn.axzo.nanopart.doc.integration.DocOssGateway;
|
||||
import cn.axzo.nanopart.doc.integration.DocUserProfileGateway;
|
||||
import cn.axzo.nanopart.doc.wps.support.WpsAssertUtil;
|
||||
@ -23,14 +34,7 @@ import cn.axzo.oss.http.model.ApiSignUrlDownloadResponse;
|
||||
import cn.axzo.oss.http.model.file.UpdateFileInfoRequest;
|
||||
import cn.axzo.oss.http.model.file.UpdateFileInfoResponse;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* wps对接基础信息
|
||||
@ -41,7 +45,7 @@ import java.util.stream.Collectors;
|
||||
@RequiredArgsConstructor
|
||||
public class WpsBaseManager {
|
||||
|
||||
private final IndexNodeDao indexNodeDao;
|
||||
private final IndexManager indexManager;
|
||||
private final DocOssGateway docOssGateway;
|
||||
private final DocUserProfileGateway docUserProfileGateway;
|
||||
|
||||
@ -101,7 +105,7 @@ public class WpsBaseManager {
|
||||
* 暂时全部开放权限,REQ-35401期只是OMS没有文件权限功能,待REQ-3540的2期建立权限后,再对接
|
||||
*/
|
||||
public WpsPermissionResponse permission(WpsPermissionRequest request) {
|
||||
IndexNode indexNode = indexNodeDao.findOrNull(request.getDocCode());
|
||||
IndexNode indexNode = indexManager.findOrNull(request.getDocCode());
|
||||
|
||||
if (StringUtils.isNotBlank(indexNode.getOrCreateFileAttributes().getFileExtension())
|
||||
&& indexNode.getOrCreateFileAttributes().getFileExtension().equalsIgnoreCase("pdf")) {
|
||||
@ -152,13 +156,11 @@ public class WpsBaseManager {
|
||||
|| StringUtils.isBlank(node.getAttributes().getFileAttributes().getOssFileKey())) {
|
||||
return WpsRenameResponse.builder().updateFlag(false).build();
|
||||
}
|
||||
//TODO: 文件名重复
|
||||
//try {
|
||||
// 调用IndexManager.rename();
|
||||
//} catch (NameUsedException e) {
|
||||
// // 处理文件已被使用的情况
|
||||
//}
|
||||
indexNodeDao.rename(request.getDocCode(), request.getName());
|
||||
try {
|
||||
indexManager.rename(node.getCode(), request.getName());
|
||||
} catch (NameUsedException e) {
|
||||
throw new WpsException(WpsErrorCodeEnum.FILE_NAME_CONFLICT);
|
||||
}
|
||||
UpdateFileInfoResponse response = this.docOssGateway.updateFileInfo(UpdateFileInfoRequest.builder().fileKey(node.getAttributes().getFileAttributes().getOssFileKey()).build());
|
||||
return WpsRenameResponse.builder().updateFlag(response.isUpdateFlag()).build();
|
||||
}
|
||||
|
||||
@ -62,40 +62,41 @@ public class GuideTenantProcedureStatusServiceImpl extends ServiceImpl<GuideTena
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 将租户操作步骤数量与模板操作步骤数量进行对比,如果模板操作步骤数量大于租户操作步骤数量,则根据模板为租户初始化新步骤点
|
||||
if (templateList.size() > procedureStatusList.size()) {
|
||||
// 将该租户未初始化的步骤点进行初始化
|
||||
List<Long> procedureStatusIdList = procedureStatusList.stream().map(GuideTenantProcedureStatus::getProcedureId).collect(Collectors.toList());
|
||||
respList.addAll(templateList.stream()
|
||||
.filter(t -> !procedureStatusIdList.contains(t.getId()))
|
||||
.map(t -> {
|
||||
GuideTenantProcedureStatusCreateReq createReq = new GuideTenantProcedureStatusCreateReq();
|
||||
createReq.setWorkspaceId(req.getWorkspaceId());
|
||||
createReq.setCategoryCode(t.getCategoryCode());
|
||||
createReq.setProcedureId(t.getId());
|
||||
createReq.setProcedureName(t.getName());
|
||||
createReq.setStatus(GuideProcedureStatus.TODO);
|
||||
create(createReq);
|
||||
return BeanUtil.copyProperties(createReq, GuideTenantProcedureStatusListResp.class);
|
||||
})
|
||||
.collect(Collectors.toList()));
|
||||
} else if (templateList.size() < procedureStatusList.size()) {
|
||||
log.warn("操作步骤模板:{},租户&分类:{},租户操作步骤状态:{}", JSONUtil.toJsonStr(templateList), JSONUtil.toJsonStr(req), JSONUtil.toJsonStr(procedureStatusList));
|
||||
throw new ServiceException("数据异常,操作步骤不存在,请联系管理人员");
|
||||
// 将租户操作步骤数量与模板操作步骤数量进行对比,是否需要根据模板为租户初始化新步骤点
|
||||
// 将该租户未初始化的步骤点进行初始化
|
||||
List<Long> procedureStatusIdList = procedureStatusList.stream().map(GuideTenantProcedureStatus::getProcedureId).distinct().collect(Collectors.toList());
|
||||
List<GuideTenantProcedureStatusListResp> newInitProcedures = templateList.stream()
|
||||
.filter(t -> !procedureStatusIdList.contains(t.getId()))
|
||||
.map(t -> {
|
||||
GuideTenantProcedureStatusCreateReq createReq = new GuideTenantProcedureStatusCreateReq();
|
||||
createReq.setWorkspaceId(req.getWorkspaceId());
|
||||
createReq.setCategoryCode(t.getCategoryCode());
|
||||
createReq.setProcedureId(t.getId());
|
||||
createReq.setProcedureName(t.getName());
|
||||
createReq.setStatus(GuideProcedureStatus.TODO);
|
||||
create(createReq);
|
||||
return BeanUtil.copyProperties(createReq, GuideTenantProcedureStatusListResp.class);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(newInitProcedures)) {
|
||||
respList.addAll(newInitProcedures);
|
||||
}
|
||||
|
||||
// 对租户操作步骤的权限码和跳转链接进行补充
|
||||
Map<Long, GuideProcedureTemplateResp> templateMap = templateList.stream().collect(Collectors.toMap(GuideProcedureTemplateResp::getId, Function.identity(), (v1, v2) -> v1));
|
||||
respList.forEach(r -> {
|
||||
GuideProcedureTemplateResp t = templateMap.get(r.getProcedureId());
|
||||
r.setDescription(t.getDescription());
|
||||
r.setIsMust(t.getIsMust());
|
||||
r.setAuthCode(t.getAuthCode());
|
||||
r.setJumpUrl(t.getJumpUrl());
|
||||
r.setJumpReport(t.getJumpReport());
|
||||
r.setSort(t.getSort());
|
||||
});
|
||||
return respList;
|
||||
return respList.stream()
|
||||
.collect(Collectors.toMap(r -> r.getWorkspaceId() + "_" + r.getProcedureId(), Function.identity(), (v1, v2) -> v1))
|
||||
.values().stream()
|
||||
.peek(r -> {
|
||||
GuideProcedureTemplateResp t = templateMap.get(r.getProcedureId());
|
||||
r.setDescription(t.getDescription());
|
||||
r.setIsMust(t.getIsMust());
|
||||
r.setAuthCode(t.getAuthCode());
|
||||
r.setJumpUrl(t.getJumpUrl());
|
||||
r.setJumpReport(t.getJumpReport());
|
||||
r.setSort(t.getSort());
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -127,12 +128,15 @@ public class GuideTenantProcedureStatusServiceImpl extends ServiceImpl<GuideTena
|
||||
log.info("步骤已完成,无需重复操作,workspaceId: {}, procedureId:{}", req.getWorkspaceId(), req.getProcedureId());
|
||||
return;
|
||||
}
|
||||
tenantProcedure.setStatus(req.getStatus());
|
||||
updateById(tenantProcedure);
|
||||
lambdaUpdate()
|
||||
.eq(GuideTenantProcedureStatus::getWorkspaceId, req.getWorkspaceId())
|
||||
.eq(GuideTenantProcedureStatus::getProcedureId, req.getProcedureId())
|
||||
.set(GuideTenantProcedureStatus::getStatus, req.getStatus())
|
||||
.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long create(GuideTenantProcedureStatusCreateReq req) {
|
||||
public synchronized Long create(GuideTenantProcedureStatusCreateReq req) {
|
||||
// 若操作所属分类或操作名称为空,则从对应模板获取
|
||||
if (Objects.isNull(req.getCategoryCode()) || CharSequenceUtil.isBlank(req.getProcedureName())) {
|
||||
GuideProcedureTemplateResp byProcedureId = procedureTemplateService.getByProcedureId(req.getProcedureId());
|
||||
|
||||
@ -4,6 +4,7 @@ import cn.axzo.framework.domain.web.result.ApiPageResult;
|
||||
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.VisaConfirmBizTypeEnum;
|
||||
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
|
||||
import cn.axzo.nanopart.visa.api.request.BizActivityAssigneeDecisionReq;
|
||||
import cn.axzo.nanopart.visa.api.request.ChangeRecordButtonOperationReq;
|
||||
@ -30,6 +31,7 @@ import cn.axzo.nanopart.visa.server.service.ChangeRecordBillService;
|
||||
import cn.axzo.nanopart.visa.server.service.ChangeRecordConfirmService;
|
||||
import cn.axzo.nanopart.visa.server.service.ChangeRecordService;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
@ -147,7 +149,7 @@ public class ChangeRecordController implements ChangeRecordApi {
|
||||
|
||||
@Override
|
||||
public ApiResult<List<VisaChangeApproveCreateReq.ApprovePersonInfo>> getVisaAllConfirm(FetchVisaAllConfirmReq req) {
|
||||
return ApiResult.ok(changeRecordConfirmService.listAllConfirmByVisaId(req.getVisaId()));
|
||||
return ApiResult.ok(changeRecordConfirmService.listAllConfirmByVisaId(req.getVisaId(), Lists.newArrayList(VisaConfirmBizTypeEnum.CONFIRM)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -46,6 +46,8 @@ public class VisaConfirmDto {
|
||||
*/
|
||||
private VisaConfirmBizTypeEnum bizType;
|
||||
|
||||
private List<VisaConfirmBizTypeEnum> bizTypes;
|
||||
|
||||
/**
|
||||
* 确认人
|
||||
*/
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
package cn.axzo.nanopart.visa.server.mq.listener.workflow.process;
|
||||
|
||||
import cn.axzo.framework.jackson.utility.JSON;
|
||||
import cn.axzo.framework.rocketmq.Event;
|
||||
import cn.axzo.framework.rocketmq.EventConsumer;
|
||||
import cn.axzo.framework.rocketmq.EventProducer;
|
||||
import cn.axzo.msg.center.api.MessageAPIV3;
|
||||
import cn.axzo.msg.center.api.request.v3.MessageSendReqV3;
|
||||
import cn.axzo.msg.center.api.response.v3.MessageSendRespV3;
|
||||
import cn.axzo.msg.center.service.dto.PersonV3DTO;
|
||||
import cn.axzo.nanopart.visa.api.enums.VisaConfirmBizTypeEnum;
|
||||
import cn.axzo.nanopart.visa.api.enums.VisaStampStatusEnum;
|
||||
import cn.axzo.nanopart.visa.api.enums.VisaStatusEnum;
|
||||
import cn.axzo.nanopart.visa.api.enums.VisaTypeEnum;
|
||||
@ -18,14 +21,17 @@ 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.ChangeRecordConfirmService;
|
||||
import cn.axzo.nanopart.visa.server.service.ChangeRecordRelationService;
|
||||
import cn.axzo.nanopart.visa.server.service.ChangeRecordService;
|
||||
import cn.axzo.workflow.common.enums.BpmnProcessInstanceResultEnum;
|
||||
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
|
||||
import cn.axzo.workflow.common.model.response.mq.ProcessInstanceDTO;
|
||||
import cn.axzo.workflow.starter.handler.ProcessInstanceEventHandler;
|
||||
import cn.azxo.framework.common.model.CommonResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.groovy.util.Maps;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
@ -35,6 +41,7 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_TOPIC;
|
||||
import static cn.axzo.nanopart.visa.api.constant.VisaConstant.FORM_FIELD_WORKSPACE_NAME;
|
||||
@ -54,11 +61,13 @@ import static cn.axzo.nanopart.visa.api.enums.VisaTypeEnum.TECHNOLOGY_APPROVED;
|
||||
* @author wangli
|
||||
* @since 2025-01-17 11:35
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class ProcessInstanceOfVisaAllEventHandler extends BasicLogSupport implements ProcessInstanceEventHandler {
|
||||
protected final ChangeRecordService changeRecordService;
|
||||
protected final ChangeRecordRelationService changeRecordRelationService;
|
||||
protected final ChangeRecordBillService changeRecordBillService;
|
||||
protected final ChangeRecordConfirmService changeRecordConfirmService;
|
||||
protected final MessageAPIV3 noticeApi;
|
||||
public final static List<String> SUPPORTED_DEFINITION_KEYS = Lists.newArrayList(
|
||||
DESIGN_CHANGE.getProcessDefinitionKey(),
|
||||
@ -72,11 +81,14 @@ public class ProcessInstanceOfVisaAllEventHandler extends BasicLogSupport implem
|
||||
ChangeRecordService changeRecordService,
|
||||
ChangeRecordRelationService changeRecordRelationService,
|
||||
ChangeRecordBillService changeRecordBillService,
|
||||
MessageAPIV3 noticeApi, RefreshableConfiguration refreshableConfiguration) {
|
||||
ChangeRecordConfirmService changeRecordConfirmService,
|
||||
MessageAPIV3 noticeApi,
|
||||
RefreshableConfiguration refreshableConfiguration) {
|
||||
super(eventProducer, visaOrganizationalNodeUserGateway);
|
||||
this.changeRecordService = changeRecordService;
|
||||
this.changeRecordRelationService = changeRecordRelationService;
|
||||
this.changeRecordBillService = changeRecordBillService;
|
||||
this.changeRecordConfirmService = changeRecordConfirmService;
|
||||
this.noticeApi = noticeApi;
|
||||
this.refreshableConfiguration = refreshableConfiguration;
|
||||
}
|
||||
@ -105,6 +117,10 @@ public class ProcessInstanceOfVisaAllEventHandler extends BasicLogSupport implem
|
||||
public void onCompleted(ProcessInstanceDTO dto) {
|
||||
String visaTypeDesc = parseVisaType(dto);
|
||||
|
||||
log.info("send complete notice");
|
||||
sendCompleteNotice(dto);
|
||||
log.info("send complete notice success");
|
||||
|
||||
updateChangeRecordApprovalStatus(dto, BpmnProcessInstanceResultEnum.APPROVED);
|
||||
|
||||
changeRecordService.lambdaUpdate()
|
||||
@ -112,15 +128,23 @@ public class ProcessInstanceOfVisaAllEventHandler extends BasicLogSupport implem
|
||||
.set(ChangeRecord::getStampStatus, VisaStampStatusEnum.UNPRINTED.name())
|
||||
.update();
|
||||
|
||||
}
|
||||
|
||||
private void sendCompleteNotice(ProcessInstanceDTO dto) {
|
||||
Map<String, Object> variables = dto.getVariables();
|
||||
BpmnTaskDelegateAssigner initiator = dto.getInitiator();
|
||||
MessageSendReqV3 completeNotice = new MessageSendReqV3();
|
||||
completeNotice.setSender(PersonV3DTO.builder().build());
|
||||
completeNotice.setReceivers(Lists.newArrayList(PersonV3DTO.builder().build()));
|
||||
completeNotice.setReceivers(queryConfirm(dto));
|
||||
completeNotice.setBizEventMappingCode(refreshableConfiguration.getProcessInstanceCompleteMsgEventCode());
|
||||
completeNotice.setBizCode(dto.getBusinessKey());
|
||||
String visaType = (String) variables.getOrDefault(WORKFLOW_VAR_VISA_TYPE_KEY, "");
|
||||
String VisaTypeDesc = StringUtils.hasText(visaType) ? VisaTypeEnum.valueOf(visaType).getDesc() : "";
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
completeNotice.setBizExtParams(new JSONObject(Maps.of(
|
||||
"initiatorName", initiator.getAssignerName(),
|
||||
"topic", variables.getOrDefault(FORM_FIELD_TOPIC, ""),
|
||||
"visaTypeDesc", VisaTypeDesc,
|
||||
"workspaceName", variables.getOrDefault(FORM_FIELD_WORKSPACE_NAME, ""),
|
||||
"time", sdf.format(new Date())
|
||||
)));
|
||||
@ -129,7 +153,22 @@ public class ProcessInstanceOfVisaAllEventHandler extends BasicLogSupport implem
|
||||
"ouId", variables.getOrDefault(IM_GROUP_BIZ_INFO_INITIATOR_OU_ID, ""),
|
||||
"workspaceId", variables.getOrDefault(IM_GROUP_BIZ_INFO_INITIATOR_WORKSPACE_ID, "")
|
||||
)));
|
||||
noticeApi.send(completeNotice);
|
||||
CommonResponse<MessageSendRespV3> response = noticeApi.send(completeNotice);
|
||||
if (Objects.nonNull(response) && response.getCode() == 200) {
|
||||
log.info("send complete notice result: {}", JSON.toJSONString(response.getData()));
|
||||
} else {
|
||||
log.error("send complete notice failed: {}", Objects.isNull(response) ? "response is null" : JSON.toJSONString(response.getMsg()));
|
||||
}
|
||||
}
|
||||
|
||||
private List<PersonV3DTO> queryConfirm(ProcessInstanceDTO dto) {
|
||||
Long visaId = Long.valueOf(dto.getBusinessKey());
|
||||
return changeRecordConfirmService.listAllConfirmByVisaId(visaId, Lists.newArrayList(VisaConfirmBizTypeEnum.CREATE, VisaConfirmBizTypeEnum.CONFIRM))
|
||||
.stream().map(e -> PersonV3DTO.builder()
|
||||
.id(e.getPersonId())
|
||||
.name(e.getRealName())
|
||||
.imReceiveModel(new PersonV3DTO.ReceiveModel(e.getOuId(), e.getWorkspaceId()))
|
||||
.build()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -160,6 +199,10 @@ public class ProcessInstanceOfVisaAllEventHandler extends BasicLogSupport implem
|
||||
*/
|
||||
@Override
|
||||
public void onRejected(ProcessInstanceDTO dto) {
|
||||
log.info("send reject notice");
|
||||
sendRejectNotice(dto);
|
||||
log.info("send reject notice success");
|
||||
|
||||
BpmnTaskDelegateAssigner lastOperationAssigner = dto.getLastOperationAssigner();
|
||||
ChangeRecordLog log = ChangeRecordLog.builder()
|
||||
.visaId(Long.valueOf(dto.getBusinessKey()))
|
||||
@ -171,14 +214,23 @@ public class ProcessInstanceOfVisaAllEventHandler extends BasicLogSupport implem
|
||||
|
||||
updateChangeRecordApprovalStatus(dto, BpmnProcessInstanceResultEnum.REJECTED);
|
||||
|
||||
}
|
||||
|
||||
private void sendRejectNotice(ProcessInstanceDTO dto) {
|
||||
Map<String, Object> variables = dto.getVariables();
|
||||
BpmnTaskDelegateAssigner initiator = dto.getInitiator();
|
||||
MessageSendReqV3 rejectNotice = new MessageSendReqV3();
|
||||
rejectNotice.setSender(PersonV3DTO.builder().build());
|
||||
rejectNotice.setReceivers(Lists.newArrayList(PersonV3DTO.builder().build()));
|
||||
rejectNotice.setBizEventMappingCode(refreshableConfiguration.getProcessInstanceCompleteMsgEventCode());
|
||||
rejectNotice.setReceivers(queryConfirm(dto));
|
||||
rejectNotice.setBizEventMappingCode(refreshableConfiguration.getProcessInstanceRejectMsgEventCode());
|
||||
rejectNotice.setBizCode(dto.getBusinessKey());
|
||||
|
||||
String visaType = (String) variables.getOrDefault(WORKFLOW_VAR_VISA_TYPE_KEY, "");
|
||||
String VisaTypeDesc = StringUtils.hasText(visaType) ? VisaTypeEnum.valueOf(visaType).getDesc() : "";
|
||||
rejectNotice.setBizExtParams(new JSONObject(Maps.of(
|
||||
"initiatorName", initiator.getAssignerName(),
|
||||
"topic", variables.getOrDefault(FORM_FIELD_TOPIC, ""),
|
||||
"visaTypeDesc", VisaTypeDesc,
|
||||
"workspaceName", variables.getOrDefault(FORM_FIELD_WORKSPACE_NAME, ""),
|
||||
"reason", dto.getReason()
|
||||
)));
|
||||
@ -187,7 +239,13 @@ public class ProcessInstanceOfVisaAllEventHandler extends BasicLogSupport implem
|
||||
"ouId", variables.getOrDefault(IM_GROUP_BIZ_INFO_INITIATOR_OU_ID, ""),
|
||||
"workspaceId", variables.getOrDefault(IM_GROUP_BIZ_INFO_INITIATOR_WORKSPACE_ID, "")
|
||||
)));
|
||||
noticeApi.send(rejectNotice);
|
||||
|
||||
CommonResponse<MessageSendRespV3> response = noticeApi.send(rejectNotice);
|
||||
if (Objects.nonNull(response) && response.getCode() == 200) {
|
||||
log.info("send reject notice result: {}", JSON.toJSONString(response.getData()));
|
||||
} else {
|
||||
log.error("send reject notice failed: {}", Objects.isNull(response) ? "response is null" : JSON.toJSONString(response.getMsg()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -76,7 +76,7 @@ public interface ChangeRecordConfirmService {
|
||||
* @param visaId
|
||||
* @return
|
||||
*/
|
||||
List<VisaChangeApproveCreateReq.ApprovePersonInfo> listAllConfirmByVisaId(Long visaId);
|
||||
List<VisaChangeApproveCreateReq.ApprovePersonInfo> listAllConfirmByVisaId(Long visaId, List<VisaConfirmBizTypeEnum> bizTypes);
|
||||
|
||||
/**
|
||||
* 构建公司的Map,orgIdAndNameMap,key:ouId,value:ouName
|
||||
|
||||
@ -418,6 +418,7 @@ public class ChangeRecordConfirmServiceImpl extends ServiceImpl<ChangeRecordConf
|
||||
.in(CollectionUtils.isNotEmpty(dto.getProjectIds()), ChangeRecordConfirm::getProjectId, dto.getProjectIds())
|
||||
.eq(Objects.nonNull(dto.getType()), ChangeRecordConfirm::getType, dto.getType())
|
||||
.eq(Objects.nonNull(dto.getBizType()), ChangeRecordConfirm::getBizType, dto.getBizType())
|
||||
.in(CollectionUtils.isNotEmpty(dto.getBizTypes()), ChangeRecordConfirm::getBizType, dto.getBizTypes())
|
||||
.in(CollectionUtils.isNotEmpty(dto.getVisaTypes()), ChangeRecordConfirm::getVisaType, dto.getVisaTypes())
|
||||
.eq(ChangeRecordConfirm::getIsDelete, 0);
|
||||
}
|
||||
@ -450,10 +451,10 @@ public class ChangeRecordConfirmServiceImpl extends ServiceImpl<ChangeRecordConf
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VisaChangeApproveCreateReq.ApprovePersonInfo> listAllConfirmByVisaId(Long visaId) {
|
||||
public List<VisaChangeApproveCreateReq.ApprovePersonInfo> listAllConfirmByVisaId(Long visaId, List<VisaConfirmBizTypeEnum> bizTypes) {
|
||||
VisaConfirmDto dto = VisaConfirmDto.builder()
|
||||
.visaId(visaId)
|
||||
.bizType(VisaConfirmBizTypeEnum.CONFIRM).build();
|
||||
.bizTypes(bizTypes).build();
|
||||
List<ChangeRecordConfirm> list = this.findByCondition(dto);
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return Lists.newArrayList();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user