package com.kaidi.oa.seed; import com.kaidi.oa.domain.Archive; import com.kaidi.oa.domain.ArchiveVersion; import com.kaidi.oa.repository.ArchiveRepository; import com.kaidi.oa.repository.ArchiveVersionRepository; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import java.time.Instant; /** * 资料室·Module 8「与其它部门的接口要求」— 跨模块归档链演示种子数据。 * *

补齐 integration-dashboard 六条「未激活」链路(activeChains 从 4/10 → 10/10): *

* *

幂等:同 sourceType 在 archive 表已有记录则跳过整批(count 检查)。 * @Order(205) 在所有基础 Seeder 后运行。 */ @DemoSeed @Order(205) public class ArchiveCrossModuleSeeder implements CommandLineRunner { private final ArchiveRepository archiveRepo; private final ArchiveVersionRepository versionRepo; public ArchiveCrossModuleSeeder(ArchiveRepository archiveRepo, ArchiveVersionRepository versionRepo) { this.archiveRepo = archiveRepo; this.versionRepo = versionRepo; } @Override public void run(String... args) { seedLitigationArchives(); seedFinanceArchives(); seedHrArchives(); seedIpArchives(); seedQualityArchives(); seedDrawingArchives(); } // ========================================================================= // 1. 诉讼文书归档(法务风险部 legal.toArchive) // ========================================================================= private void seedLitigationArchives() { long existing = archiveRepo.findAll().stream() .filter(a -> "诉讼".equals(a.getSourceType())) .count(); if (existing > 0) return; archive("合同档案", "靖州供水项目工程款争议仲裁文书", "诉讼", 1L, "靖州供水仲裁申请书及答辩材料.pdf", "pdf", 1_840_000L, "法务专员-王芳", "2026-01-15", "诉讼,仲裁,合同纠纷,靖州供水,已结案", "靖州供水信息化建设合同工程款争议仲裁案,申请仲裁→调解→撤案,文书已归档至资料室。", "机密"); archive("合同档案", "供水设备分包方违约起诉状及判决书", "诉讼", 2L, "供水设备分包违约诉讼案(完整卷宗).pdf", "pdf", 3_260_000L, "法务专员-王芳", "2025-11-20", "诉讼,违约,分包,供水设备,已判决", "供水调度监控设备分包合同违约诉讼,一审判决我方胜诉,文书卷宗完整归档。", "机密"); archive("合同档案", "江山春锦项目咨询费结算纠纷调解协议", "诉讼", 3L, "江山春锦调解协议书.pdf", "pdf", 680_000L, "法务部主任-张伟", "2026-03-05", "诉讼,调解协议,咨询费,江山春锦,已结案", "江山春锦项目工程咨询费结算纠纷经调解达成协议,调解书及结案证明归档。", "机密"); } // ========================================================================= // 2. 会计档案年度归档(财务部 finance.toArchive) // ========================================================================= private void seedFinanceArchives() { long existing = archiveRepo.findAll().stream() .filter(a -> "财务".equals(a.getSourceType())) .count(); if (existing > 0) return; archive("财务档案", "2025年度会计档案(凭证/账簿/报表)", "财务", 2025L, "2025年度会计档案汇编.pdf", "pdf", 12_480_000L, "财务总监-刘洋", "2026-04-30", "年度:2025,类型:会计档案,保存期限:30年,会计凭证,账簿,财务报表", "2025年度财务档案,含记账凭证、总账/明细账、资产负债表/利润表/现金流量表,依《会计档案管理办法》保存30年。", "机密"); archive("财务档案", "2024年度会计档案(凭证/账簿/报表)", "财务", 2024L, "2024年度会计档案汇编.pdf", "pdf", 10_920_000L, "财务总监-刘洋", "2025-04-30", "年度:2024,类型:会计档案,保存期限:30年,凭证,账簿,报表", "2024年度财务档案归档,含年度审计报告及税务申报表副本,永久保存备查。", "机密"); archive("财务档案", "2026年Q1季度财务快报及纳税申报资料", "财务", 20261L, "2026Q1财务快报及纳税申报.pdf", "pdf", 2_340_000L, "财务会计-陈静", "2026-04-15", "季报,Q1,2026,纳税申报,财务快报", "2026年第一季度财务快报及增值税/企业所得税季报材料归档。", "机密"); } // ========================================================================= // 3. 员工档案归档(人力资源部 hr.toArchive) // ========================================================================= private void seedHrArchives() { long existing = archiveRepo.findAll().stream() .filter(a -> a.getSourceType() != null && a.getSourceType().startsWith("人事")) .count(); if (existing > 0) return; archive("人事档案", "李娜(EMP001)离职档案", "人事-离职", null, "EMP001-李娜-离职手续及档案.pdf", "pdf", 560_000L, "人事专员-王芳", "2026-05-10", "员工编号:EMP001,员工姓名:李娜,部门:项目管理部,事件:离职", "项目管理部李娜女士离职手续及人事档案汇编,含离职审批、工作交接记录、薪资结算单。", "机密"); archive("人事档案", "刘洋(EMP003)晋升档案", "人事-晋升", null, "EMP003-刘洋-晋升及绩效材料.pdf", "pdf", 340_000L, "人事专员-王芳", "2026-03-01", "员工编号:EMP003,员工姓名:刘洋,部门:财务管理部,事件:晋升", "财务管理部刘洋晋升为财务总监,含晋升审批、绩效评估报告及新岗位协议。", "机密"); archive("人事档案", "王芳(EMP005)劳动合同续签档案", "人事-续签", null, "EMP005-王芳-劳动合同续签.pdf", "pdf", 220_000L, "人事总监-张伟", "2026-01-15", "员工编号:EMP005,员工姓名:王芳,部门:人力资源部,事件:续签", "人力资源部王芳劳动合同到期续签,含续签审批、新合同文本(2026-2029)。", "机密"); archive("人事档案", "陈静(EMP007)入职档案", "人事-入职", null, "EMP007-陈静-入职材料汇编.pdf", "pdf", 480_000L, "人事专员-王芳", "2026-02-08", "员工编号:EMP007,员工姓名:陈静,部门:财务管理部,事件:入职", "财务管理部陈静入职资料汇编,含录用通知、学历/资质证明、入职登记表、劳动合同。", "机密"); } // ========================================================================= // 4. 知识产权证书归档(知识产权部 ip.toArchive) // ========================================================================= private void seedIpArchives() { long existing = archiveRepo.findAll().stream() .filter(a -> "知识产权".equals(a.getSourceType())) .count(); if (existing > 0) return; archive("知识产权档案", "专利证书:供水智能调度优化方法(ZL202410123456.8)", "知识产权", null, "专利证书-ZL202410123456.8.pdf", "pdf", 860_000L, "知识产权专员-李娜", "2026-04-20", "证书编号:ZL202410123456.8,证书类型:专利证书,权利人:湖南凯迪工程科技有限公司,有效期至:2044-04-20", "供水智能调度优化方法发明专利,授权公告日2026-04-20,权利人凯迪工程,有效期20年。", "机密"); archive("知识产权档案", "软件著作权证书:凯迪ERP+OA一体化平台V1.0(2026SR0567890)", "知识产权", null, "软著证书-凯迪ERP-OA-2026SR0567890.pdf", "pdf", 720_000L, "知识产权专员-李娜", "2026-05-18", "证书编号:2026SR0567890,证书类型:软件著作权证,权利人:湖南凯迪工程科技有限公司,有效期至:永久", "凯迪ERP+OA一体化平台V1.0软件著作权登记证书,登记号2026SR0567890,永久保护。", "机密"); archive("知识产权档案", "商标注册证:凯迪(KAIDI)第30类(3012345678)", "知识产权", null, "商标注册证-凯迪品牌-3012345678.pdf", "pdf", 540_000L, "知识产权总监-张伟", "2026-01-10", "证书编号:3012345678,证书类型:商标注册证,权利人:湖南凯迪工程科技有限公司,有效期至:2036-01-10", "凯迪品牌商标注册证(第30类),有效期10年,到期前12个月提醒续期。", "内部"); } // ========================================================================= // 5. 质量记录归档(质安部 quality.toArchive) // ========================================================================= private void seedQualityArchives() { long existing = archiveRepo.findAll().stream() .filter(a -> "质量".equals(a.getSourceType())) .count(); if (existing > 0) return; archive("质量档案", "检验报告:供水监控设备出厂检验报告(QR2026-001)", "质量", null, "供水监控设备出厂检验报告-QR2026-001.pdf", "pdf", 2_140_000L, "质安专员-刘洋", "2026-04-25", "记录编号:QR2026-001,记录类型:检验报告,项目:靖州供水项目", "靖州供水调度监控设备出厂检验报告,涵盖硬件功能/电磁兼容/防护等级测试,全项合格。", "内部"); archive("质量档案", "体系文件:ISO9001质量管理手册(2026版)", "质量", null, "ISO9001质量管理手册-2026版.pdf", "pdf", 5_680_000L, "质安总监-张伟", "2026-03-01", "记录编号:SYS-QM-2026,记录类型:体系文件,项目:公司质量管理体系", "公司ISO9001:2015质量管理体系手册2026年修订版,通过外部审核,归档保存备查。", "内部"); archive("质量档案", "安全报告:靖州供水项目施工安全专项检查报告(SR2026-003)", "质量", null, "靖州供水施工安全检查报告-SR2026-003.pdf", "pdf", 1_360_000L, "安全专员-王芳", "2026-05-30", "记录编号:SR2026-003,记录类型:安全报告,项目:靖州供水项目", "靖州供水项目第三次施工安全专项检查报告,现场整改措施已闭环,报告存档。", "内部"); archive("质量档案", "特种设备档案:起重机械检验合格证(TSB2026-0078)", "质量", null, "起重机械检验合格证-TSB2026-0078.pdf", "pdf", 680_000L, "设备管理员-陈静", "2026-02-28", "记录编号:TSB2026-0078,记录类型:特种设备档案,项目:靖州供水项目", "靖州施工现场起重机械(额定起重量5t)年度检验合格证,有效期至2027-02-27。", "内部"); } // ========================================================================= // 6. 图纸档案归档(工程监理 supervision.drawing)+ 版本历史 // ========================================================================= private void seedDrawingArchives() { long existingDrawings = archiveRepo.findByCategory("图纸档案").size(); if (existingDrawings > 0) return; // 图纸1:管网总图 V1.0→V2.0(V1.0作废,V2.0现行) Archive d1 = archiveEntity("图纸档案", "靖州供水项目管网系统总图", "图纸档案", 1L, "靖州供水管网总图-V2.0.pdf", "pdf", 8_640_000L, "监理工程师-刘洋", "2026-05-20", "图纸档案,管网总图,靖州供水,现行V2.0", "靖州县供水管网系统总布置图,含主干管/支管/阀门井/消防栓定位,V2.0为现行版。", "内部"); d1 = archiveRepo.save(d1); // V1.0(作废) ArchiveVersion v1d1 = new ArchiveVersion(); v1d1.setArchiveId(d1.getId()); v1d1.setArchiveTitle(d1.getTitle()); v1d1.setVersionNo("V1.0"); v1d1.setIsCurrent(Boolean.FALSE); v1d1.setStatus("作废"); v1d1.setChangeNote("初版管网总图,未含北区延伸段,已作废"); v1d1.setAuthor("监理工程师-王芳"); v1d1.setVersionDate("2026-03-10"); v1d1.setCreatedAt(Instant.now()); versionRepo.save(v1d1); // V2.0(现行) ArchiveVersion v2d1 = new ArchiveVersion(); v2d1.setArchiveId(d1.getId()); v2d1.setArchiveTitle(d1.getTitle()); v2d1.setVersionNo("V2.0"); v2d1.setIsCurrent(Boolean.TRUE); v2d1.setStatus("现行"); v2d1.setChangeNote("补充北区管网延伸段(DN200主管×840m),更新阀门井坐标"); v2d1.setAuthor("监理工程师-刘洋"); v2d1.setVersionDate("2026-05-20"); v2d1.setCreatedAt(Instant.now()); versionRepo.save(v2d1); // 图纸2:调度中心机房平面图 V1.0(现行) Archive d2 = archiveEntity("图纸档案", "靖州供水调度中心机房平面布置图", "图纸档案", 1L, "调度中心机房平面图-V1.0.pdf", "pdf", 3_120_000L, "监理工程师-陈静", "2026-04-08", "图纸档案,机房平面图,靖州供水,调度中心,现行V1.0", "供水调度中心机房设备平面布置图,含服务器机柜/UPS/网络设备/弱电桥架,V1.0现行。", "内部"); d2 = archiveRepo.save(d2); ArchiveVersion v1d2 = new ArchiveVersion(); v1d2.setArchiveId(d2.getId()); v1d2.setArchiveTitle(d2.getTitle()); v1d2.setVersionNo("V1.0"); v1d2.setIsCurrent(Boolean.TRUE); v1d2.setStatus("现行"); v1d2.setChangeNote("初版机房平面布置图,经监理审核通过,作为施工及竣工验收依据"); v1d2.setAuthor("监理工程师-陈静"); v1d2.setVersionDate("2026-04-08"); v1d2.setCreatedAt(Instant.now()); versionRepo.save(v1d2); // 图纸3:OA系统网络拓扑图 V1.0→V1.1→V2.0(仅V2.0现行) Archive d3 = archiveEntity("图纸档案", "凯迪ERP+OA一体化网络拓扑图", "图纸档案", 2L, "凯迪ERP-OA网络拓扑图-V2.0.pdf", "pdf", 2_280_000L, "IT运维-张伟", "2026-06-01", "图纸档案,网络拓扑图,ERP,OA,IT架构,现行V2.0", "凯迪ERP+OA一体化系统网络拓扑图(物理+逻辑),含边界防火墙/核心交换机/服务器集群,V2.0现行。", "内部"); d3 = archiveRepo.save(d3); ArchiveVersion v1d3 = new ArchiveVersion(); v1d3.setArchiveId(d3.getId()); v1d3.setArchiveTitle(d3.getTitle()); v1d3.setVersionNo("V1.0"); v1d3.setIsCurrent(Boolean.FALSE); v1d3.setStatus("作废"); v1d3.setChangeNote("初版拓扑,无DMZ区,安全审计后作废"); v1d3.setAuthor("IT运维-李娜"); v1d3.setVersionDate("2026-02-15"); v1d3.setCreatedAt(Instant.now()); versionRepo.save(v1d3); ArchiveVersion v11d3 = new ArchiveVersion(); v11d3.setArchiveId(d3.getId()); v11d3.setArchiveTitle(d3.getTitle()); v11d3.setVersionNo("V1.1"); v11d3.setIsCurrent(Boolean.FALSE); v11d3.setStatus("作废"); v11d3.setChangeNote("补充DMZ区,增加Web应用防火墙,后发现服务器IP段规划冲突,作废"); v11d3.setAuthor("IT运维-李娜"); v11d3.setVersionDate("2026-04-10"); v11d3.setCreatedAt(Instant.now()); versionRepo.save(v11d3); ArchiveVersion v2d3 = new ArchiveVersion(); v2d3.setArchiveId(d3.getId()); v2d3.setArchiveTitle(d3.getTitle()); v2d3.setVersionNo("V2.0"); v2d3.setIsCurrent(Boolean.TRUE); v2d3.setStatus("现行"); v2d3.setChangeNote("重新规划服务器IP段(10.10.0.0/16),完善安全域划分,通过等保测评"); v2d3.setAuthor("IT运维-张伟"); v2d3.setVersionDate("2026-06-01"); v2d3.setCreatedAt(Instant.now()); versionRepo.save(v2d3); } // ========================================================================= // helpers // ========================================================================= private void archive(String category, String title, String sourceType, Long sourceId, String fileName, String fileType, long fileSize, String uploader, String archiveDate, String tags, String summary, String accessLevel) { Archive a = archiveEntity(category, title, sourceType, sourceId, fileName, fileType, fileSize, uploader, archiveDate, tags, summary, accessLevel); archiveRepo.save(a); } private Archive archiveEntity(String category, String title, String sourceType, Long sourceId, String fileName, String fileType, long fileSize, String uploader, String archiveDate, String tags, String summary, String accessLevel) { Archive a = new Archive(); a.setCategory(category); a.setTitle(title); a.setSourceType(sourceType); a.setSourceId(sourceId); a.setFileName(fileName); a.setFileType(fileType); a.setFileSize(fileSize); a.setUploader(uploader); a.setArchiveDate(archiveDate); a.setTags(tags); a.setSummary(summary); a.setAccessLevel(accessLevel); a.setCreatedAt(Instant.now()); return a; } }