Files
ERP/.claude/wf-p1-build.js
T
QiufengandClaude Opus 4.8 5e51dc3f56 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>
2026-06-15 19:19:15 +08:00

93 lines
9.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export const meta = {
name: 'erp-p1-build',
description: 'P1核心能力阻断:财务内核/MRP-BOM/合同闭环/存疑MET正名 4工作流并行(各只动自有文件,共享文件回传片段中央合并)',
phases: [{ title: 'P1并行建设' }],
}
const COMMON = `黄金模板与约定(照抄风格):实体 domain/Financing.java、控制器 web/FinancingController.java(CRUD+业务动作+@Transactional级联)、前端 oa/pages/payment/financing.vue(MasterDataPage接真API)与 repayment.vue(自定义联动页)。
硬约束:①金额一律 BigDecimal + com.kaidi.oa.common.Money.of/add/sub/nz(无裸double算钱;乘法用BigDecimal.multiply再Money.of);②日期 String(YYYY-MM-DD),算天/折旧用 java.time.LocalDate/ChronoUnit;③控制器 @RestController @RequestMapping("/api/oa/<资源复数>"),返回 com.kaidi.oa.common.ApiResp.ok(),请求体 record,找不到抛 NotFoundException,校验抛 ApiException(400/409,中文),状态迁移/级联写 @Transactional;④仓库 extends JpaRepository<X,Long> 派生查询;⑤前端真实页接你的真后端(import { http } from 该页相对路径的 api/httphttp.get/post/patch/del 已解包ApiResp.datatoken键 oa.token),列表CRUD套 pages/masterdata/MasterDataPage.vue,工作流/联动页用 el-table+el-dialog;⑥无emoji(图标@element-plus/icons-vue)、无渐变(纯色蓝主调)、排版间距承载形态慎重(美观+简单易用);⑦类名/表名加域前缀,先 grep 确认与现有~94控制器/实体零撞名。
**关键纪律(避免并行冲突)**
- 你**只能新建文件**或编辑**你工作流明确拥有**的现有文件;
- 凡需改动**共享文件**(config/AuthInterceptor.java、data/oaModules.ts、service/TriggerRuleEngine.java、service/WorkflowService.java、web/WorkOrderController.java、web/ContractController.java、web/CustomerController.java、web/OpportunityController.java)**一律不要自己改**,把"目标文件+精确改法(插入位置锚点+代码片段)"放进 sharedFileSnippets 字段,由主代理中央串行合并;
- **不要运行 gradle/npm**(并行争用),逐文件仔细自审语法。`
const RESULT = {
type: 'object', additionalProperties: false,
properties: {
workstream: { type: 'string' },
backendFiles: { type: 'array', items: { type: 'string' } },
frontendFiles: { type: 'array', items: { type: 'string' } },
authFinancePrefixes: { type: 'array', items: { type: 'string' } },
authSensitiveRead: { type: 'array', items: { type: 'string' } },
navEntries: {
type: 'array', items: {
type: 'object', additionalProperties: false,
properties: { moduleId: { type: 'string' }, items: { type: 'array', items: {
type: 'object', additionalProperties: false,
properties: { key: { type: 'string' }, label: { type: 'string' }, kind: { type: 'string' }, path: { type: 'string' } },
required: ['key', 'label', 'kind', 'path'] } } },
required: ['moduleId', 'items'] },
},
sharedFileSnippets: {
type: 'array', items: {
type: 'object', additionalProperties: false,
properties: {
file: { type: 'string' },
anchor: { type: 'string', description: '要插入/替换处的唯一锚点文本(现有代码原文)' },
change: { type: 'string', description: '具体改法:在锚点后插入/替换为...的完整代码片段' },
why: { type: 'string' },
},
required: ['file', 'anchor', 'change', 'why'] },
},
endpoints: { type: 'array', items: { type: 'string' } },
summary: { type: 'string' },
},
required: ['workstream', 'backendFiles', 'frontendFiles', 'authFinancePrefixes', 'authSensitiveRead', 'navEntries', 'sharedFileSnippets', 'endpoints', 'summary'],
}
const WS = [
{
key: 'fin', label: '财务内核',
prompt: `工作流【财务内核】。审计:凭证无状态机/红冲、应收应付不自动生成核销、报销无预算校验、税务整模块缺、资产无折旧计提。
你拥有并可编辑:web/VoucherController.java + domain/Voucher.java(加凭证状态机:草稿→已审核→已过账 + 红冲冲销动作)。
新建(新文件):①税务 domain/TaxFiling.java(税种/所属期/计税依据/税率/应纳税额/状态)+仓库+web/TaxFilingController.java;②固定资产 domain/FixedAsset.java(资产编号/名称/原值/累计折旧/净值/折旧方法 年限平均/月折旧额/状态)+仓库+web/FixedAssetController.java(含 /{id}/depreciate 按月计提:本月折旧=原值/(年限*12),累计折旧累加,净值=原值-累计,折旧达原值即提完);③应收应付 domain/ArApItem.java(类型 应收/应付/关联合同或发票/金额/已核销/未核销/状态)+仓库+web/ArApController.java(含 /{id}/writeoff 核销:核销额累加,全核销置已结清)。
报销预算校验:做 web/ExpenseClaimController.java 或在新建的报销实体里,提交报销时查对应 Budget 剩余(读 BudgetRepository),超预算 ApiException(409,中文)。前端挂 finance 模块(凭证/税务/固定资产/应收应付/报销 真实页)。
共享文件(回传片段勿自改):若要让付款办结自动生成应付/凭证,给 service/TriggerRuleEngine.java 的片段;AuthInterceptor 财务前缀;oaModules finance 模块导航。`,
},
{
key: 'mfg', label: 'MRP/BOM',
prompt: `工作流【MRP/BOM】。审计:MRP净需求(读库存/在途/在制)缺、BOM差异的actualCost/actualQty手填未从工单/领料自动回填。
你拥有并可编辑:web/BomAnalysisController.java(把差异核算的实际量/实际成本改为可从工单领料自动回填的端点)。
新建(新文件):①web/MrpController.java + service/MrpService.javaMRP净需求运算——给一个生产需求(产品+数量),按 BomItem 多级展开毛需求,减去 InventoryItem 现有库存、在途(采购在途,可先建字段或读现有)、在制,得净需求与建议采购/生产量;返回逐物料 {物料,毛需求,现有,在途,在制,净需求,建议}。②领料/工单回填:domain/MaterialIssue.java(工单领料:workOrderId/物料/数量/单价/金额)+仓库+web/MaterialIssueController.java,领料写入后可被 BOM差异核算读取做 actualQty/actualCost 自动回填。
前端挂 mfg 模块(MRP运算/领料 真实页)与 budget/contract 无关。
共享文件(回传片段勿自改):若需 WorkOrderController 暴露在制量,给片段;AuthInterceptor;oaModules mfg 模块导航。`,
},
{
key: 'contract', label: '合同闭环',
prompt: `工作流【合同闭环】。审计(LOGIC_GAP):模板bodyTemplate无页面消费、自动化条款比对不存在、电子签/外部盖章未集成。
你拥有并可编辑:web/ContractTemplateController.java(确保能取模板正文 bodyTemplate)。
新建(新文件):①web/ClauseCompareController.java + service/ClauseCompareService.java:自动化条款比对——给一份合同草稿正文与模板编号,逐条比对(按句/关键条款:金额/工期/质保/违约/付款方式),输出偏差清单 {条款,模板值/草稿值,偏差类型 缺失/修改/新增,风险级别}。可用文本规则(关键词+数值抽取)实现,不需LLM。②电子签/外部盖章:web/EsignController.java——/contracts/{id}/esign 发起电子签(置状态待签→已签,记录签署人/时间/外部签章流水号),外部盖章系统对接标注为对接项留接口。
前端:在 contract 模块新建"模板起草"(选模板→bodyTemplate填充→生成草稿)、"条款比对"(贴草稿→比对→偏差表)、"电子签"页,接真后端。
共享文件(回传片段勿自改):若合同起草要写 Contract,给 web/ContractController.java 片段(新增"从模板起草"端点);AuthInterceptor;oaModules contract 模块导航。`,
},
{
key: 'met', label: '存疑MET正名',
prompt: `工作流【存疑MET正名】。审计:①分公司/办事处无机构级目录与数据隔离(只是opportunity一个自由文本orgUnit);②生物质 autoInventory 联动是控制器私有方法,不走TriggerRuleEngine、无ruleKey/AutomationLog/幂等。
新建(新文件):①机构目录 domain/OrgBranch.java(机构编号/名称/类型 总部/分公司/办事处/上级/地区/负责人/状态)+仓库+web/OrgBranchController.java(CRUD),让分公司/办事处成为真实机构主数据;前端在 crm 或 masterdata 模块建"机构目录(分公司/办事处)"页。②前端建"分支机构经营看板"页:按 OrgBranch 维度聚合商机/客户(调现有 /opportunities /customers 带 orgUnit 过滤),体现机构级视图。
共享文件(回传片段勿自改,关键)
- service/TriggerRuleEngine.java + web/WorkOrderController.java:把"已入库工单→自动生成成品库存"从 WorkOrderController 私有方法改为经 TriggerRuleEngine 正规联动(ruleKey 如 workorder.done.inventory + AutomationLog 留痕 + existsByInstanceIdAndRuleKey 幂等),与其余7条正规链同源。给出精确锚点+片段。
- 若 CustomerController/OpportunityController 需加 orgUnit/branchId 过滤,给片段。
AuthInterceptor(org-branches 写口收口);oaModules 导航。`,
},
]
phase('P1并行建设')
const results = await parallel(WS.map((w) => () =>
agent(
`你是资深全栈工程师,为凯迪 ERP 平台做 P1 深度增强。${w.prompt}\n\n${COMMON}\n\n返回结构化结果:新建文件、你已编辑的自有文件、需中央合并的共享文件片段(sharedFileSnippets:file+anchor原文+change改法+why)、鉴权前缀、导航条目、关键端点、summary。`,
{ label: `P1:${w.key}`, phase: 'P1并行建设', schema: RESULT }
)
)).then((a) => a.filter(Boolean))
return { built: results.length, results }