SNAPSHOT W7 已部署稳定态 — 凯迪ERP+OA一体化平台 (MET 73.3%)

恢复点(restore point)。别人改崩后可 git reset --hard 回到此提交。

== 此快照内容 ==
- 后端 oa-backend: 734 控制器 / 711 实体 (Spring Boot 3.2.5 + SQLite, 端口8091)
- 前端 modern-ui/app: Vue3+Vite, 约700页 (构建产物已在 oa-backend/src/main/resources/static)
- 数据库 oa-backend/data/oa.db: 含全部演示数据 (强制入库, 6.6MB)
- 交接文档 go.md + go-code-reference/endpoints/entities/database.md
- 多代理建设脚本 .claude/wf-*.js

== 状态 ==
- 对 凯迪科技ERP_20260507.xlsx 合规 MET ~73.3% (PARTIAL 75: 34可建+6种子/bug+35外部硬天花板)
- 安全: 5轮红队+5轮复检, default-deny分级鉴权, 连续零可利用
- W3~W7 累计补完436缺口; W8末轮(40缺口)为半成品(源码树可编译但未集成)
- 运行: cd oa-backend; java -jar build/libs/oa-backend-0.1.0.jar --server.port=8091; admin/123456

== 排除(gitignore, 可再生) ==
node_modules / oa-backend/build / .jdks / *.log / Backup-ERP-* / 弃用的OFBiz核心(只保留modern-ui)
完整文件夹备份见同目录 Backup-ERP-20260615-191517/ (含上述全部, 仅缺 node_modules)

时间戳: 20260615-191517

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Qiufeng
2026-06-15 19:19:15 +08:00
co-authored by Claude Opus 4.8
commit 5e51dc3f56
10584 changed files with 2501339 additions and 0 deletions
@@ -0,0 +1,311 @@
package com.kaidi.oa.seed;
import com.kaidi.oa.common.Money;
import com.kaidi.oa.domain.FertAccountingVoucher;
import com.kaidi.oa.domain.FertInvoiceLedger;
import com.kaidi.oa.domain.FertPkgMaterialLedger;
import com.kaidi.oa.repository.FertAccountingVoucherRepository;
import com.kaidi.oa.repository.FertInvoiceLedgerRepository;
import com.kaidi.oa.repository.FertPkgMaterialLedgerRepository;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.Instant;
/**
* 生物质肥料制造中心·包装物台账 + 会计凭证台账 + 发票台账演示种子数据。
*
* 补全审计缺口:
* 1. 包装物(编织袋/标签/吨袋)独立台账(4 条,覆盖多规格+多库位+低库存警示);
* 2. 会计凭证台账(3 条:草稿/已过账/已反冲,覆盖成本结转 + 期末结转);
* 3. 发票台账(4 条:采购发票2条+销售发票2条,覆盖全状态流转)。
*
* 幂等:按唯一编码查重后跳过,重启不重复插入。
* Order(201) 保证在 DataSeeder(200) 之后执行。
*/
@Component
@Order(201)
public class FertPkgAccountingSeeder implements ApplicationRunner {
private final FertPkgMaterialLedgerRepository pkgRepo;
private final FertAccountingVoucherRepository voucherRepo;
private final FertInvoiceLedgerRepository invoiceRepo;
public FertPkgAccountingSeeder(FertPkgMaterialLedgerRepository pkgRepo,
FertAccountingVoucherRepository voucherRepo,
FertInvoiceLedgerRepository invoiceRepo) {
this.pkgRepo = pkgRepo;
this.voucherRepo = voucherRepo;
this.invoiceRepo = invoiceRepo;
}
@Override
@Transactional
public void run(ApplicationArguments args) {
seedPkgMaterials();
seedAccountingVouchers();
seedInvoiceLedger();
}
// -------- 包装物台账 --------
private void seedPkgMaterials() {
// 编织袋 25kg
if (pkgRepo.findByPkgCode("PKG-WB-25KG").isEmpty()) {
FertPkgMaterialLedger p = new FertPkgMaterialLedger();
p.setPkgCode("PKG-WB-25KG");
p.setPkgName("编织袋(25kg)");
p.setSpec("50cm×80cm,白色印花,凯迪有机肥专用");
p.setWarehouse("包装物库");
p.setBin("A货架-01");
p.setUnit("");
p.setQty(new BigDecimal("8500"));
p.setSafetyStock(new BigDecimal("2000"));
p.setUnitCost(Money.of(new BigDecimal("0.65")));
p.setSupplier("益丰塑编有限公司");
p.setLastInboundDate("2026-05-10");
p.setLinkedBatchNo("FERM-2026-05-003");
p.setPackSpec("25kg");
p.setLastMoveType("入库");
p.setStatus("在库");
p.setRemark("本月采购3万条,已领用2.15万条");
p.setCreatedAt(Instant.now());
pkgRepo.save(p);
}
// 编织袋 50kg
if (pkgRepo.findByPkgCode("PKG-WB-50KG").isEmpty()) {
FertPkgMaterialLedger p = new FertPkgMaterialLedger();
p.setPkgCode("PKG-WB-50KG");
p.setPkgName("编织袋(50kg)");
p.setSpec("60cm×100cm,白色印花,颗粒有机肥专用");
p.setWarehouse("包装物库");
p.setBin("A货架-02");
p.setUnit("");
p.setQty(new BigDecimal("1200"));
p.setSafetyStock(new BigDecimal("1500"));
p.setUnitCost(Money.of(new BigDecimal("0.90")));
p.setSupplier("益丰塑编有限公司");
p.setLastInboundDate("2026-04-28");
p.setLinkedBatchNo("FERM-2026-04-007");
p.setPackSpec("50kg");
p.setLastMoveType("领用");
p.setStatus("低库存");
p.setRemark("库存低于安全库存,建议补货");
p.setCreatedAt(Instant.now());
pkgRepo.save(p);
}
// 吨袋
if (pkgRepo.findByPkgCode("PKG-TB-1000KG").isEmpty()) {
FertPkgMaterialLedger p = new FertPkgMaterialLedger();
p.setPkgCode("PKG-TB-1000KG");
p.setPkgName("吨袋(1000kg)");
p.setSpec("90cm×90cm×130cm,四吊绳,白色");
p.setWarehouse("包装物库");
p.setBin("B货架-01");
p.setUnit("");
p.setQty(new BigDecimal("340"));
p.setSafetyStock(new BigDecimal("100"));
p.setUnitCost(Money.of(new BigDecimal("12.50")));
p.setSupplier("汇鑫集装袋厂");
p.setLastInboundDate("2026-05-20");
p.setLinkedBatchNo("FERM-2026-05-001");
p.setPackSpec("吨袋");
p.setLastMoveType("入库");
p.setStatus("在库");
p.setRemark("大客户专用,与农业合作社订单关联");
p.setCreatedAt(Instant.now());
pkgRepo.save(p);
}
// 产品标签
if (pkgRepo.findByPkgCode("PKG-LBL-STD").isEmpty()) {
FertPkgMaterialLedger p = new FertPkgMaterialLedger();
p.setPkgCode("PKG-LBL-STD");
p.setPkgName("产品标签(自粘)");
p.setSpec("12cm×8cm,自粘不干胶,NY525标准合格证");
p.setWarehouse("包装物库");
p.setBin("发货暂存区");
p.setUnit("");
p.setQty(new BigDecimal("52000"));
p.setSafetyStock(new BigDecimal("5000"));
p.setUnitCost(Money.of(new BigDecimal("0.08")));
p.setSupplier("天成印刷有限公司");
p.setLastInboundDate("2026-06-01");
p.setPackSpec("25kg");
p.setLastMoveType("入库");
p.setStatus("在库");
p.setRemark("含执行标准/生产日期/有效期/合格证内容,已贴标约3万张");
p.setCreatedAt(Instant.now());
pkgRepo.save(p);
}
}
// -------- 会计凭证台账 --------
private void seedAccountingVouchers() {
// 凭证1:已过账的批次成本结转凭证
if (voucherRepo.findByVoucherNo("FTV-BATCH-FERM-2026-05-001-2026-05-31").isEmpty()) {
FertAccountingVoucher v = new FertAccountingVoucher();
v.setVoucherNo("FTV-BATCH-FERM-2026-05-001-2026-05-31");
v.setVoucherType("成本结转");
v.setBatchRef("FERM-2026-05-001");
v.setProductName("有机肥(粉状)");
v.setPeriod("2026-05");
v.setVoucherDate("2026-05-31");
v.setTotalAmount(Money.of(new BigDecimal("186420.00")));
v.setLinesJson("[{\"account\":\"4001\",\"accountName\":\"生产成本-直接材料\",\"direction\":\"\",\"amount\":138600.00,\"summary\":\"FERM-2026-05-001 原料成本\"},{\"account\":\"1211\",\"accountName\":\"原材料\",\"direction\":\"\",\"amount\":138600.00,\"summary\":\"FERM-2026-05-001 原料领用\"},{\"account\":\"4002\",\"accountName\":\"生产成本-直接人工\",\"direction\":\"\",\"amount\":28400.00,\"summary\":\"FERM-2026-05-001 人工成本\"},{\"account\":\"2211\",\"accountName\":\"应付职工薪酬\",\"direction\":\"\",\"amount\":28400.00,\"summary\":\"FERM-2026-05-001 工资分摊\"},{\"account\":\"4003\",\"accountName\":\"生产成本-制造费用\",\"direction\":\"\",\"amount\":19420.00,\"summary\":\"FERM-2026-05-001 制造费用\"},{\"account\":\"4101\",\"accountName\":\"制造费用\",\"direction\":\"\",\"amount\":19420.00,\"summary\":\"FERM-2026-05-001 费用分摊\"},{\"account\":\"1403\",\"accountName\":\"库存商品\",\"direction\":\"\",\"amount\":186420.00,\"summary\":\"FERM-2026-05-001 完工入库\"},{\"account\":\"4001\",\"accountName\":\"生产成本\",\"direction\":\"\",\"amount\":186420.00,\"summary\":\"FERM-2026-05-001 结转完工成本\"}]");
v.setLineCount(8);
v.setStatus("已过账");
v.setPreparer("系统自动");
v.setPoster("李会计");
v.setPostedAt(Instant.parse("2026-05-31T08:30:00Z"));
v.setRemark("5月份第1批有机肥(粉状)成本结转,已过账");
v.setCreatedAt(Instant.parse("2026-05-31T08:00:00Z"));
voucherRepo.save(v);
}
// 凭证2:草稿状态期末结转凭证
if (voucherRepo.findByVoucherNo("FTV-PERIOD-2026-05").isEmpty()) {
FertAccountingVoucher v = new FertAccountingVoucher();
v.setVoucherNo("FTV-PERIOD-2026-05");
v.setVoucherType("期末结转");
v.setBatchRef("期间汇总-6批次");
v.setProductName("2026年5月期末汇总");
v.setPeriod("2026-05");
v.setVoucherDate("2026-05-31");
v.setTotalAmount(Money.of(new BigDecimal("1043680.00")));
v.setLinesJson("[{\"account\":\"4001\",\"accountName\":\"生产成本-直接材料\",\"direction\":\"\",\"amount\":762400.00,\"summary\":\"2026-05 直接原料结转\"},{\"account\":\"4002\",\"accountName\":\"生产成本-直接人工\",\"direction\":\"\",\"amount\":168200.00,\"summary\":\"2026-05 人工成本结转\"},{\"account\":\"4003\",\"accountName\":\"生产成本-制造费用\",\"direction\":\"\",\"amount\":113080.00,\"summary\":\"2026-05 制造费用结转\"},{\"account\":\"1403\",\"accountName\":\"库存商品\",\"direction\":\"\",\"amount\":1043680.00,\"summary\":\"2026-05 完工产品入库\"}]");
v.setLineCount(4);
v.setStatus("草稿");
v.setPreparer("系统自动");
v.setRemark("2026年5月期末成本结转汇总凭证(6个批次),待会计审核过账");
v.setCreatedAt(Instant.now());
voucherRepo.save(v);
}
// 凭证3:已反冲的凭证(演示反冲功能)
if (voucherRepo.findByVoucherNo("FTV-BATCH-FERM-2026-04-002-REVERSED").isEmpty()) {
FertAccountingVoucher v = new FertAccountingVoucher();
v.setVoucherNo("FTV-BATCH-FERM-2026-04-002-REVERSED");
v.setVoucherType("成本结转");
v.setBatchRef("FERM-2026-04-002");
v.setProductName("生物有机肥(颗粒)");
v.setPeriod("2026-04");
v.setVoucherDate("2026-04-30");
v.setTotalAmount(Money.of(new BigDecimal("234850.00")));
v.setLinesJson("[{\"account\":\"4001\",\"accountName\":\"生产成本-直接材料\",\"direction\":\"\",\"amount\":175200.00,\"summary\":\"FERM-2026-04-002 原料成本\"},{\"account\":\"1211\",\"accountName\":\"原材料\",\"direction\":\"\",\"amount\":175200.00,\"summary\":\"FERM-2026-04-002 原料领用\"},{\"account\":\"1403\",\"accountName\":\"库存商品\",\"direction\":\"\",\"amount\":234850.00,\"summary\":\"FERM-2026-04-002 完工入库\"},{\"account\":\"4001\",\"accountName\":\"生产成本\",\"direction\":\"\",\"amount\":234850.00,\"summary\":\"FERM-2026-04-002 结转完工\"}]");
v.setLineCount(4);
v.setStatus("已反冲");
v.setPreparer("系统自动");
v.setPoster("李会计");
v.setPostedAt(Instant.parse("2026-04-30T09:00:00Z"));
v.setRemark("原过账凭证因成本数据更正,已红字冲销;请重新生成");
v.setCreatedAt(Instant.parse("2026-04-30T08:00:00Z"));
voucherRepo.save(v);
}
}
// -------- 发票台账 --------
private void seedInvoiceLedger() {
// 采购发票1:已核销(畜禽粪污原料采购)
if (invoiceRepo.findByInvoiceNo("31120260500123456").isEmpty()) {
FertInvoiceLedger inv = new FertInvoiceLedger();
inv.setInvoiceNo("31120260500123456");
inv.setInvoiceType("采购发票");
inv.setCounterpart("绿源养殖场");
inv.setInvoiceDate("2026-05-08");
inv.setPeriod("2026-05");
inv.setAmountExclTax(Money.of(new BigDecimal("87600.00")));
inv.setTaxAmount(Money.of(new BigDecimal("7884.00")));
inv.setTotalAmount(Money.of(new BigDecimal("95484.00")));
inv.setTaxRate(Money.of(new BigDecimal("9.00")));
inv.setGoodsDesc("畜禽粪污(猪粪)原料采购");
inv.setLinkedOrderNo("PO-2026-05-011");
inv.setLinkedBatchRef("FERM-2026-05-001");
inv.setVoucherNo("FTV-BATCH-FERM-2026-05-001-2026-05-31");
inv.setStatus("已核销");
inv.setCertifyDate("2026-05-12");
inv.setWriteOffDate("2026-05-25");
inv.setHandler("王采购");
inv.setRemark("增值税专票,已抵扣认证,已与付款单核销");
inv.setCreatedAt(Instant.parse("2026-05-08T10:00:00Z"));
invoiceRepo.save(inv);
}
// 采购发票2:已认证(秸秆原料)
if (invoiceRepo.findByInvoiceNo("31120260500234567").isEmpty()) {
FertInvoiceLedger inv = new FertInvoiceLedger();
inv.setInvoiceNo("31120260500234567");
inv.setInvoiceType("采购发票");
inv.setCounterpart("丰收秸秆收储站");
inv.setInvoiceDate("2026-05-18");
inv.setPeriod("2026-05");
inv.setAmountExclTax(Money.of(new BigDecimal("43200.00")));
inv.setTaxAmount(Money.of(new BigDecimal("3888.00")));
inv.setTotalAmount(Money.of(new BigDecimal("47088.00")));
inv.setTaxRate(Money.of(new BigDecimal("9.00")));
inv.setGoodsDesc("秸秆(玉米秸秆)原料采购");
inv.setLinkedOrderNo("PO-2026-05-022");
inv.setLinkedBatchRef("FERM-2026-05-003");
inv.setStatus("已认证");
inv.setCertifyDate("2026-05-22");
inv.setHandler("王采购");
inv.setRemark("已认证,待与付款单核销");
inv.setCreatedAt(Instant.parse("2026-05-18T14:00:00Z"));
invoiceRepo.save(inv);
}
// 销售发票1:已核销(种植大户)
if (invoiceRepo.findByInvoiceNo("60420260500001234").isEmpty()) {
FertInvoiceLedger inv = new FertInvoiceLedger();
inv.setInvoiceNo("60420260500001234");
inv.setInvoiceType("销售发票");
inv.setCounterpart("绿野农业合作社");
inv.setInvoiceDate("2026-05-20");
inv.setPeriod("2026-05");
inv.setAmountExclTax(Money.of(new BigDecimal("136000.00")));
inv.setTaxAmount(Money.of(new BigDecimal("12240.00")));
inv.setTotalAmount(Money.of(new BigDecimal("148240.00")));
inv.setTaxRate(Money.of(new BigDecimal("9.00")));
inv.setGoodsDesc("有机肥料(粉状)800吨");
inv.setLinkedOrderNo("SO-2026-05-008");
inv.setLinkedBatchRef("FERM-2026-05-001");
inv.setStatus("已核销");
inv.setCertifyDate("2026-05-20");
inv.setWriteOffDate("2026-05-30");
inv.setHandler("赵销售");
inv.setRemark("已开票,客户已回款,已核销");
inv.setCreatedAt(Instant.parse("2026-05-20T09:00:00Z"));
invoiceRepo.save(inv);
}
// 销售发票2:待认证(新客户,月底开票)
if (invoiceRepo.findByInvoiceNo("60420260600000321").isEmpty()) {
FertInvoiceLedger inv = new FertInvoiceLedger();
inv.setInvoiceNo("60420260600000321");
inv.setInvoiceType("销售发票");
inv.setCounterpart("远景生态农业有限公司");
inv.setInvoiceDate("2026-06-05");
inv.setPeriod("2026-06");
inv.setAmountExclTax(Money.of(new BigDecimal("68000.00")));
inv.setTaxAmount(Money.of(new BigDecimal("6120.00")));
inv.setTotalAmount(Money.of(new BigDecimal("74120.00")));
inv.setTaxRate(Money.of(new BigDecimal("9.00")));
inv.setGoodsDesc("生物有机肥(颗粒)400吨");
inv.setLinkedOrderNo("SO-2026-06-003");
inv.setLinkedBatchRef("FERM-2026-05-004");
inv.setStatus("待认证");
inv.setHandler("赵销售");
inv.setRemark("6月新客户首单,已发货,发票已开,待客户确认");
inv.setCreatedAt(Instant.parse("2026-06-05T11:00:00Z"));
invoiceRepo.save(inv);
}
}
}