新增活动电子档案模块;

This commit is contained in:
2026-07-28 15:59:45 +08:00
parent 785b9a4b80
commit a8a4052c45
11 changed files with 1975 additions and 0 deletions
@@ -0,0 +1,62 @@
package com.budwk.app.zhgh.archive.constant;
import org.nutz.lang.Strings;
import java.util.List;
import java.util.Map;
/**
* 活动电子档案常量。
*/
public final class ArchiveConstant {
public static final int PROJECT_DRAFT = 0;
public static final int PROJECT_FILING = 1;
public static final int PROJECT_COMPLETED = 2;
public static final int DOCUMENT_DRAFT = 0;
public static final int DOCUMENT_SUBMITTED = 1;
public static final String STAGE_PREPARE = "PREPARE";
public static final String STAGE_PROCESS = "PROCESS";
public static final String STAGE_SUMMARY = "SUMMARY";
public static final Map<String, String> STAGE_LABELS = Map.of(
STAGE_PREPARE, "筹备阶段",
STAGE_PROCESS, "实施阶段",
STAGE_SUMMARY, "总结阶段"
);
private ArchiveConstant() {
}
public static boolean validStage(String stage) {
return Strings.isNotBlank(stage) && STAGE_LABELS.containsKey(stage);
}
public static String stageLabel(String stage) {
return STAGE_LABELS.getOrDefault(stage, stage);
}
public static String projectStatusLabel(Integer status) {
if (status != null && status == PROJECT_COMPLETED) {
return "已完成";
}
if (status != null && status == PROJECT_FILING) {
return "归档中";
}
return "草稿";
}
public static String documentStatusLabel(Integer status) {
return status != null && status == DOCUMENT_SUBMITTED ? "已提交归档" : "草稿";
}
public static List<Map<String, String>> stageOptions() {
return List.of(
Map.of("value", STAGE_PREPARE, "label", STAGE_LABELS.get(STAGE_PREPARE)),
Map.of("value", STAGE_PROCESS, "label", STAGE_LABELS.get(STAGE_PROCESS)),
Map.of("value", STAGE_SUMMARY, "label", STAGE_LABELS.get(STAGE_SUMMARY))
);
}
}
@@ -0,0 +1,221 @@
package com.budwk.app.zhgh.archive.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.zhgh.archive.constant.ArchiveConstant;
import com.budwk.app.zhgh.archive.model.ArchiveDocType;
import com.budwk.app.zhgh.archive.model.ArchiveDocument;
import com.budwk.app.zhgh.archive.model.ArchiveProject;
import com.budwk.app.zhgh.archive.service.ArchiveService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
/**
* 活动电子档案。
*/
@IocBean
@Ok("json:full")
@At("/platform/archive")
@Api(tags = "活动电子档案")
public class ArchiveController {
@Inject
private ArchiveService archiveService;
@Inject
private Dao dao;
@At("/docType")
@Ok("beetl:/platform/zhgh/archive/docType/index.html")
@SaCheckPermission("archive.docType")
public void docTypeIndex() {
}
@At("/docType/pageData")
@SaCheckPermission("archive.docType")
public Result docTypePageData(PageForm pageForm, String name,
String projectStage, Boolean requiredFlag) {
return Result.success(archiveService.pageDocTypes(
pageForm, name, projectStage, requiredFlag));
}
@At("/docType/listData")
public Result docTypeListData(String projectStage) {
return Result.success(archiveService.listDocTypes(projectStage));
}
@At("/docType/fetchOne")
@SaCheckPermission("archive.docType")
public Result docTypeFetchOne(String id) {
return Result.success(dao.fetch(ArchiveDocType.class, id));
}
@At("/docType/onSubmit")
@SLog(tag = "活动电子档案-文档类型", msg = "新增或修改文档类型")
@SaCheckPermission("archive.docType")
public Result docTypeOnSubmit(ArchiveDocType docType) {
try {
archiveService.saveDocType(docType);
return Result.success();
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
@At("/docType/onDelete")
@SLog(tag = "活动电子档案-文档类型", msg = "删除文档类型")
@SaCheckPermission("archive.docType")
public Result docTypeOnDelete(String id) {
try {
archiveService.deleteDocType(id);
return Result.success();
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
@At("/project")
@Ok("beetl:/platform/zhgh/archive/project/index.html")
@SaCheckPermission("archive.project")
public void projectIndex() {
}
@At("/project/pageData")
@SaCheckPermission("archive.project")
public Result projectPageData(PageForm pageForm, Integer year,
String projectName, String unionId, Integer status) {
return Result.success(archiveService.pageProjects(
pageForm, year, projectName, unionId, status));
}
@At("/project/listData")
public Result projectListData() {
return Result.success(archiveService.listProjects());
}
@At("/project/fetchOne")
@SaCheckPermission("archive.project")
public Result projectFetchOne(String id) {
return Result.success(dao.fetch(ArchiveProject.class, id));
}
@At("/project/onSubmit")
@SLog(tag = "活动电子档案-归档项目", msg = "新增或修改归档项目")
@SaCheckPermission("archive.project")
public Result projectOnSubmit(ArchiveProject project) {
try {
archiveService.saveProject(project);
return Result.success();
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
@At("/project/onDelete")
@SLog(tag = "活动电子档案-归档项目", msg = "删除归档项目")
@SaCheckPermission("archive.project")
public Result projectOnDelete(String id) {
try {
archiveService.deleteProject(id);
return Result.success();
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
@At("/filing")
@Ok("beetl:/platform/zhgh/archive/filing/index.html")
@SaCheckPermission("archive.filing")
public void filingIndex() {
}
@At("/filing/pageData")
@SaCheckPermission("archive.filing")
public Result filingPageData(PageForm pageForm, String projectId, Integer year,
String projectStage, String docTypeId,
String documentName, Integer status) {
return Result.success(archiveService.pageDocuments(pageForm, projectId, year,
projectStage, docTypeId, documentName, status));
}
@At("/filing/fetchOne")
@SaCheckPermission("archive.filing")
public Result filingFetchOne(String id) {
return Result.success(archiveService.fetchDocument(id));
}
@At("/filing/saveDraft")
@ApiOperation("保存归档文档草稿")
@SLog(tag = "活动电子档案-资料归档", msg = "保存归档文档草稿")
@SaCheckPermission("archive.filing")
public Result filingSaveDraft(ArchiveDocument document) {
return saveDocument(document, false);
}
@At("/filing/submit")
@ApiOperation("提交归档文档")
@SLog(tag = "活动电子档案-资料归档", msg = "提交归档文档")
@SaCheckPermission("archive.filing")
public Result filingSubmit(ArchiveDocument document) {
return saveDocument(document, true);
}
@At("/filing/onDelete")
@SLog(tag = "活动电子档案-资料归档", msg = "删除归档文档")
@SaCheckPermission("archive.filing")
public Result filingOnDelete(String id) {
archiveService.deleteDocument(id);
return Result.success();
}
@At("/ledger")
@Ok("beetl:/platform/zhgh/archive/ledger/index.html")
@SaCheckPermission("archive.ledger")
public void ledgerIndex() {
}
@At("/ledger/pageData")
@SaCheckPermission("archive.ledger")
public Result ledgerPageData(PageForm pageForm, Integer year,
String projectName, String unionId, Integer status) {
return Result.success(archiveService.pageProjects(
pageForm, year, projectName, unionId, status));
}
@At("/ledger/detail")
@SaCheckPermission("archive.ledger")
public Result ledgerDetail(PageForm pageForm, String projectId,
String projectStage, String docTypeId,
String documentName, Integer status) {
return Result.success(archiveService.pageDocuments(pageForm, projectId,
null, projectStage, docTypeId, documentName, status));
}
@At("/common/stageOptions")
public Result stageOptions() {
return Result.success(ArchiveConstant.stageOptions());
}
@At("/common/unionOptions")
public Result unionOptions() {
return Result.success(archiveService.listUnions());
}
private Result saveDocument(ArchiveDocument document, boolean submit) {
try {
archiveService.saveDocument(document, submit);
return Result.success();
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
}
@@ -0,0 +1,55 @@
package com.budwk.app.zhgh.archive.model;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.nutz.dao.entity.annotation.ColDefine;
import org.nutz.dao.entity.annotation.ColType;
import org.nutz.dao.entity.annotation.Column;
import org.nutz.dao.entity.annotation.Comment;
import org.nutz.dao.entity.annotation.Name;
import org.nutz.dao.interceptor.annotation.PrevInsert;
import org.nutz.dao.entity.annotation.Table;
import org.nutz.dao.entity.annotation.TableMeta;
/**
* 活动电子档案文档类型。
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@Table("act_archive_doc_type")
@TableMeta("{'mysql-charset':'utf8mb4'}")
@Comment("活动电子档案文档类型")
public class ArchiveDocType extends BaseModel {
@Name
@PrevInsert(uu32 = true)
@ColDefine(type = ColType.VARCHAR, width = 32)
@Comment("主键")
private String id;
@Column
@ColDefine(type = ColType.VARCHAR, width = 150)
@Comment("类型名称")
private String name;
@Column
@ColDefine(type = ColType.VARCHAR, width = 32)
@Comment("项目阶段")
private String projectStage;
@Column
@Comment("排序编号")
private Integer sortNo;
@Column
@Comment("是否必选")
private Boolean requiredFlag;
@Column
@ColDefine(type = ColType.VARCHAR, width = 600)
@Comment("备注")
private String remark;
}
@@ -0,0 +1,78 @@
package com.budwk.app.zhgh.archive.model;
import cn.hutool.json.JSONObject;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.nutz.dao.entity.annotation.ColDefine;
import org.nutz.dao.entity.annotation.ColType;
import org.nutz.dao.entity.annotation.Column;
import org.nutz.dao.entity.annotation.Comment;
import org.nutz.dao.entity.annotation.Name;
import org.nutz.dao.interceptor.annotation.PrevInsert;
import org.nutz.dao.entity.annotation.Table;
import org.nutz.dao.entity.annotation.TableMeta;
import java.util.List;
/**
* 活动电子档案归档文档。
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@Table("act_archive_document")
@TableMeta("{'mysql-charset':'utf8mb4'}")
@Comment("活动电子档案归档文档")
public class ArchiveDocument extends BaseModel {
@Name
@PrevInsert(uu32 = true)
@ColDefine(type = ColType.VARCHAR, width = 32)
@Comment("主键")
private String id;
@Column
@ColDefine(type = ColType.VARCHAR, width = 32)
@Comment("项目ID")
private String projectId;
@Column
@ColDefine(type = ColType.VARCHAR, width = 300)
@Comment("文档名称")
private String documentName;
@Column
@ColDefine(type = ColType.VARCHAR, width = 32)
@Comment("项目阶段")
private String projectStage;
@Column
@ColDefine(type = ColType.VARCHAR, width = 32)
@Comment("文档类型ID")
private String docTypeId;
@Column
@Comment("文档状态")
private Integer status;
@Column
@ColDefine(type = ColType.VARCHAR, width = 100)
@Comment("上传人")
private String uploader;
@Column
@Comment("上传时间")
private Long uploadTime;
@Column
@ColDefine(type = ColType.MYSQL_JSON)
@Comment("附件")
private List<JSONObject> files;
@Column
@ColDefine(type = ColType.VARCHAR, width = 600)
@Comment("备注")
private String remark;
}
@@ -0,0 +1,55 @@
package com.budwk.app.zhgh.archive.model;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.nutz.dao.entity.annotation.ColDefine;
import org.nutz.dao.entity.annotation.ColType;
import org.nutz.dao.entity.annotation.Column;
import org.nutz.dao.entity.annotation.Comment;
import org.nutz.dao.entity.annotation.Name;
import org.nutz.dao.interceptor.annotation.PrevInsert;
import org.nutz.dao.entity.annotation.Table;
import org.nutz.dao.entity.annotation.TableMeta;
/**
* 活动电子档案项目。
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@Table("act_archive_project")
@TableMeta("{'mysql-charset':'utf8mb4'}")
@Comment("活动电子档案项目")
public class ArchiveProject extends BaseModel {
@Name
@PrevInsert(uu32 = true)
@ColDefine(type = ColType.VARCHAR, width = 32)
@Comment("主键")
private String id;
@Column
@Comment("年度")
private Integer year;
@Column
@ColDefine(type = ColType.VARCHAR, width = 300)
@Comment("项目名称")
private String projectName;
@Column
@Comment("项目状态")
private Integer status;
@Column
@ColDefine(type = ColType.VARCHAR, width = 32)
@Comment("所属工会ID")
private String unionId;
@Column
@ColDefine(type = ColType.VARCHAR, width = 150)
@Comment("所属工会名称")
private String unionName;
}
@@ -0,0 +1,406 @@
package com.budwk.app.zhgh.archive.service;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.sys.models.Sys_union;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.archive.constant.ArchiveConstant;
import com.budwk.app.zhgh.archive.model.ArchiveDocType;
import com.budwk.app.zhgh.archive.model.ArchiveDocument;
import com.budwk.app.zhgh.archive.model.ArchiveProject;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 活动电子档案领域服务。
*/
@IocBean(args = {"refer:dao"})
public class ArchiveService extends BaseServiceImpl<ArchiveProject> {
public ArchiveService(Dao dao) {
super(dao);
}
public Pagination<NutMap> pageDocTypes(PageForm pageForm, String name,
String projectStage, Boolean requiredFlag) {
Cnd cnd = Cnd.NEW();
cnd.and(Cnd.likeEX("adt.name", name));
cnd.andEX("adt.projectStage", "=", projectStage);
cnd.andEX("adt.requiredFlag", "=", requiredFlag);
cnd.and("adt.delFlag", "=", false);
cnd.asc("adt.projectStage").asc("adt.sortNo").asc("adt.createdAt");
Sql sql = Sqls.create("""
SELECT adt.*,
(SELECT COUNT(1)
FROM act_archive_document ad
WHERE ad.docTypeId = adt.id
AND ad.delFlag = 0) AS documentCount
FROM act_archive_doc_type adt
$condition
""");
sql.setCondition(cnd);
Pagination<NutMap> page = listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
page.getList().forEach(this::enrichDocType);
return page;
}
public List<NutMap> listDocTypes(String projectStage) {
Cnd cnd = Cnd.where("adt.delFlag", "=", false);
cnd.andEX("adt.projectStage", "=", projectStage);
cnd.asc("adt.projectStage").asc("adt.sortNo").asc("adt.createdAt");
Sql sql = Sqls.create("""
SELECT adt.*,
(SELECT COUNT(1)
FROM act_archive_document ad
WHERE ad.docTypeId = adt.id
AND ad.delFlag = 0) AS documentCount
FROM act_archive_doc_type adt
$condition
""");
sql.setCondition(cnd);
List<NutMap> list = listMap(sql);
list.forEach(this::enrichDocType);
return list;
}
@Aop(TransAop.READ_COMMITTED)
public void saveDocType(ArchiveDocType docType) {
if (docType == null || Strings.isBlank(docType.getName())) {
throw new IllegalArgumentException("类型名称不能为空");
}
if (!ArchiveConstant.validStage(docType.getProjectStage())) {
throw new IllegalArgumentException("项目阶段不正确");
}
docType.setName(docType.getName().trim());
if (docType.getSortNo() == null) {
docType.setSortNo(0);
}
if (docType.getRequiredFlag() == null) {
docType.setRequiredFlag(false);
}
Cnd duplicate = Cnd.where("projectStage", "=", docType.getProjectStage())
.and("name", "=", docType.getName())
.and("delFlag", "=", false);
if (Strings.isNotBlank(docType.getId())) {
duplicate.and("id", "<>", docType.getId());
}
if (dao().count(ArchiveDocType.class, duplicate) > 0) {
throw new IllegalArgumentException("同一项目阶段下类型名称不能重复");
}
if (Strings.isBlank(docType.getId())) {
dao().insert(docType);
} else {
ArchiveDocType old = dao().fetch(ArchiveDocType.class, docType.getId());
if (old == null) {
throw new IllegalArgumentException("文档类型不存在");
}
dao().updateIgnoreNull(docType);
}
}
@Aop(TransAop.READ_COMMITTED)
public void deleteDocType(String id) {
if (Strings.isBlank(id)) {
return;
}
if (dao().count(ArchiveDocument.class,
Cnd.where("docTypeId", "=", id).and("delFlag", "=", false)) > 0) {
throw new IllegalArgumentException("文档类型已被归档文档引用,不能删除");
}
dao().delete(ArchiveDocType.class, id);
}
public Pagination<NutMap> pageProjects(PageForm pageForm, Integer year,
String projectName, String unionId, Integer status) {
Cnd cnd = Cnd.NEW();
cnd.andEX("ap.year", "=", year);
cnd.and(Cnd.likeEX("ap.projectName", projectName));
cnd.andEX("ap.unionId", "=", unionId);
cnd.andEX("ap.status", "=", status);
cnd.and("ap.delFlag", "=", false);
cnd.desc("ap.year").desc("ap.createdAt");
Sql sql = Sqls.create("""
SELECT ap.*,
(SELECT COUNT(1)
FROM act_archive_document ad
WHERE ad.projectId = ap.id
AND ad.delFlag = 0) AS documentCount
FROM act_archive_project ap
$condition
""");
sql.setCondition(cnd);
Pagination<NutMap> page = listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
page.getList().forEach(this::enrichProject);
return page;
}
public List<NutMap> listProjects() {
Cnd cnd = Cnd.where("ap.delFlag", "=", false);
cnd.desc("ap.year").desc("ap.createdAt");
Sql sql = Sqls.create("""
SELECT ap.*,
(SELECT COUNT(1)
FROM act_archive_document ad
WHERE ad.projectId = ap.id
AND ad.delFlag = 0) AS documentCount
FROM act_archive_project ap
$condition
""");
sql.setCondition(cnd);
List<NutMap> list = listMap(sql);
list.forEach(this::enrichProject);
return list;
}
@Aop(TransAop.READ_COMMITTED)
public void saveProject(ArchiveProject project) {
if (project == null || project.getYear() == null) {
throw new IllegalArgumentException("年度不能为空");
}
if (Strings.isBlank(project.getProjectName())) {
throw new IllegalArgumentException("项目名称不能为空");
}
if (Strings.isBlank(project.getUnionId())) {
throw new IllegalArgumentException("所属工会不能为空");
}
Sys_union union = dao().fetch(Sys_union.class, project.getUnionId());
if (union == null) {
throw new IllegalArgumentException("所属工会不存在");
}
project.setProjectName(project.getProjectName().trim());
project.setUnionName(union.getName());
Cnd duplicate = Cnd.where("year", "=", project.getYear())
.and("projectName", "=", project.getProjectName())
.and("unionId", "=", project.getUnionId())
.and("delFlag", "=", false);
if (Strings.isNotBlank(project.getId())) {
duplicate.and("id", "<>", project.getId());
}
if (dao().count(ArchiveProject.class, duplicate) > 0) {
throw new IllegalArgumentException("同年度同工会下项目名称不能重复");
}
if (Strings.isBlank(project.getId())) {
project.setStatus(ArchiveConstant.PROJECT_DRAFT);
dao().insert(project);
} else {
ArchiveProject old = dao().fetch(ArchiveProject.class, project.getId());
if (old == null) {
throw new IllegalArgumentException("归档项目不存在");
}
project.setStatus(old.getStatus());
dao().updateIgnoreNull(project);
}
}
@Aop(TransAop.READ_COMMITTED)
public void deleteProject(String id) {
if (Strings.isBlank(id)) {
return;
}
if (dao().count(ArchiveDocument.class,
Cnd.where("projectId", "=", id).and("delFlag", "=", false)) > 0) {
throw new IllegalArgumentException("项目下已存在归档文档,不能删除");
}
dao().delete(ArchiveProject.class, id);
}
public Pagination<NutMap> pageDocuments(PageForm pageForm, String projectId, Integer year,
String projectStage, String docTypeId,
String documentName, Integer status) {
Cnd cnd = Cnd.NEW();
cnd.andEX("ad.projectId", "=", projectId);
cnd.andEX("ap.year", "=", year);
cnd.andEX("ad.projectStage", "=", projectStage);
cnd.andEX("ad.docTypeId", "=", docTypeId);
cnd.and(Cnd.likeEX("ad.documentName", documentName));
cnd.andEX("ad.status", "=", status);
cnd.and("ad.delFlag", "=", false);
cnd.and("ap.delFlag", "=", false);
cnd.desc("ap.year").desc("ad.uploadTime").desc("ad.createdAt");
Sql sql = Sqls.create("""
SELECT ad.*, ap.year, ap.projectName, ap.unionId, ap.unionName,
adt.name AS docTypeName, adt.requiredFlag AS docTypeRequiredFlag
FROM act_archive_document ad
JOIN act_archive_project ap
ON ap.id = ad.projectId
LEFT JOIN act_archive_doc_type adt
ON adt.id = ad.docTypeId
AND adt.delFlag = 0
$condition
""");
sql.setCondition(cnd);
Pagination<NutMap> page = listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
page.getList().forEach(this::enrichDocument);
return page;
}
public NutMap fetchDocument(String id) {
Sql sql = Sqls.create("""
SELECT ad.*, ap.year, ap.projectName, ap.unionId, ap.unionName,
adt.name AS docTypeName, adt.requiredFlag AS docTypeRequiredFlag
FROM act_archive_document ad
JOIN act_archive_project ap
ON ap.id = ad.projectId
LEFT JOIN act_archive_doc_type adt
ON adt.id = ad.docTypeId
AND adt.delFlag = 0
WHERE ad.id = @id
AND ad.delFlag = 0
AND ap.delFlag = 0
""");
sql.params().set("id", id);
NutMap map = fetchMap(sql);
if (map != null) {
enrichDocument(map);
}
return map;
}
@Aop(TransAop.READ_COMMITTED)
public void saveDocument(ArchiveDocument document, boolean submit) {
validateDocument(document, submit);
ArchiveDocument old = Strings.isBlank(document.getId())
? null : dao().fetch(ArchiveDocument.class, document.getId());
if (Strings.isNotBlank(document.getId()) && old == null) {
throw new IllegalArgumentException("归档文档不存在");
}
int targetStatus = submit ? ArchiveConstant.DOCUMENT_SUBMITTED : ArchiveConstant.DOCUMENT_DRAFT;
if (old != null && old.getStatus() != null
&& old.getStatus() == ArchiveConstant.DOCUMENT_SUBMITTED && !submit) {
targetStatus = ArchiveConstant.DOCUMENT_SUBMITTED;
}
document.setStatus(targetStatus);
if (targetStatus == ArchiveConstant.DOCUMENT_SUBMITTED) {
String uploader = SecurityUtil.getUserUsername();
if (Strings.isBlank(uploader)) {
uploader = SecurityUtil.getUserLoginname();
}
document.setUploader(uploader);
document.setUploadTime(System.currentTimeMillis());
} else if (old != null) {
document.setUploader(old.getUploader());
document.setUploadTime(old.getUploadTime());
}
String oldProjectId = old == null ? null : old.getProjectId();
if (old == null) {
dao().insert(document);
} else {
dao().updateIgnoreNull(document);
}
refreshProjectStatus(document.getProjectId());
if (Strings.isNotBlank(oldProjectId) && !oldProjectId.equals(document.getProjectId())) {
refreshProjectStatus(oldProjectId);
}
}
@Aop(TransAop.READ_COMMITTED)
public void deleteDocument(String id) {
ArchiveDocument document = dao().fetch(ArchiveDocument.class, id);
if (document == null) {
return;
}
dao().delete(ArchiveDocument.class, id);
refreshProjectStatus(document.getProjectId());
}
public List<Sys_union> listUnions() {
return dao().query(Sys_union.class, Cnd.where("delFlag", "=", false).asc("unionCode"));
}
private void validateDocument(ArchiveDocument document, boolean submit) {
if (document == null || Strings.isBlank(document.getProjectId())) {
throw new IllegalArgumentException("归档项目不能为空");
}
if (Strings.isBlank(document.getDocumentName())) {
throw new IllegalArgumentException("文档名称不能为空");
}
ArchiveProject project = dao().fetch(ArchiveProject.class,
Cnd.where("id", "=", document.getProjectId()).and("delFlag", "=", false));
if (project == null) {
throw new IllegalArgumentException("归档项目不存在");
}
if (!ArchiveConstant.validStage(document.getProjectStage())) {
throw new IllegalArgumentException("项目阶段不正确");
}
document.setDocumentName(document.getDocumentName().trim());
if (Strings.isNotBlank(document.getDocTypeId())) {
ArchiveDocType docType = dao().fetch(ArchiveDocType.class,
Cnd.where("id", "=", document.getDocTypeId()).and("delFlag", "=", false));
if (docType == null) {
throw new IllegalArgumentException("文档类型不存在");
}
if (!document.getProjectStage().equals(docType.getProjectStage())) {
throw new IllegalArgumentException("文档类型与项目阶段不匹配");
}
}
if (submit && (document.getFiles() == null || document.getFiles().isEmpty())) {
throw new IllegalArgumentException("提交归档前请先上传附件");
}
}
private void refreshProjectStatus(String projectId) {
if (Strings.isBlank(projectId)) {
return;
}
ArchiveProject project = dao().fetch(ArchiveProject.class, projectId);
if (project == null) {
return;
}
List<ArchiveDocument> submitted = dao().query(ArchiveDocument.class,
Cnd.where("projectId", "=", projectId)
.and("status", "=", ArchiveConstant.DOCUMENT_SUBMITTED)
.and("delFlag", "=", false));
int status = ArchiveConstant.PROJECT_DRAFT;
if (!submitted.isEmpty()) {
List<ArchiveDocType> requiredTypes = dao().query(ArchiveDocType.class,
Cnd.where("requiredFlag", "=", true).and("delFlag", "=", false));
if (requiredTypes.isEmpty()) {
status = ArchiveConstant.PROJECT_FILING;
} else {
Set<String> submittedKeys = new HashSet<>();
submitted.forEach(item -> {
if (Strings.isNotBlank(item.getDocTypeId())) {
submittedKeys.add(item.getProjectStage() + "_" + item.getDocTypeId());
}
});
boolean completed = requiredTypes.stream().allMatch(item ->
submittedKeys.contains(item.getProjectStage() + "_" + item.getId()));
status = completed ? ArchiveConstant.PROJECT_COMPLETED : ArchiveConstant.PROJECT_FILING;
}
}
dao().update(ArchiveProject.class, Chain.make("status", status),
Cnd.where("id", "=", projectId));
}
private void enrichDocType(NutMap map) {
map.put("projectStageLabel", ArchiveConstant.stageLabel(map.getString("projectStage")));
}
private void enrichProject(NutMap map) {
map.put("statusLabel", ArchiveConstant.projectStatusLabel(map.getInt("status")));
}
private void enrichDocument(NutMap map) {
map.put("projectStageLabel", ArchiveConstant.stageLabel(map.getString("projectStage")));
map.put("statusLabel", ArchiveConstant.documentStatusLabel(map.getInt("status")));
Object files = map.get("files");
if (files == null || StrUtil.isBlank(String.valueOf(files))) {
map.put("files", Collections.emptyList());
}
}
}