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.transaction.annotation.Transactional; import java.math.BigDecimal; import java.time.Instant; /** * 生物质肥料制造中心·包装物台账 + 会计凭证台账 + 发票台账演示种子数据。 * * 补全审计缺口: * 1. 包装物(编织袋/标签/吨袋)独立台账(4 条,覆盖多规格+多库位+低库存警示); * 2. 会计凭证台账(3 条:草稿/已过账/已反冲,覆盖成本结转 + 期末结转); * 3. 发票台账(4 条:采购发票2条+销售发票2条,覆盖全状态流转)。 * * 幂等:按唯一编码查重后跳过,重启不重复插入。 * Order(201) 保证在 DataSeeder(200) 之后执行。 */ @DemoSeed @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); } } }