Files
ERP/ofbiz-framework/plugins/modern-ui/app/src/oa/api/costing.ts
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

220 lines
7.5 KiB
TypeScript

/**
* 预算成本深化 + 人员证件库 API。
* 成本中心主档 /cost-centers、人材机价格库 /price-items、人员证件库 /personnel-certs。
*/
import { http } from './http'
export interface CostCenter {
id: number
code: string
name: string
ccType: string
owner: string
/** 上级成本中心 id(责任中心多级树);空/0 表示根节点。 */
parentId?: number
parentName: string
budgetTotal: number
actualTotal: number
status: string
createdAt: string
}
/**
* 成本中心责任树节点(GET /cost-centers/tree)。除主档字段外带 level(顶层 0)、
* children(下级,递归)与含整棵子树的 rollupBudget / rollupActual / rollupRate 上卷。
*/
export interface CostCenterTreeNode {
id: number
code: string
name: string
ccType: string
owner: string
parentId?: number
parentName: string
budgetTotal: number
actualTotal: number
status: string
level: number
rollupBudget: number
rollupActual: number
rollupRate: number
children: CostCenterTreeNode[]
}
export interface PriceItem {
id: number
category: string
name: string
spec: string
unit: string
unitPrice: number
region: string
supplier: string
priceType: string
effectiveDate: string
createdAt: string
}
export interface PersonnelCert {
id: number
personName: string
dept: string
certType: string
certNo: string
issuer: string
issueDate: string
expireDate: string
status: string
createdAt: string
}
/**
* 标准成本台账。totalStandard=料+工+费、variance=actual-standard 由后端 create/update 自动计算。
* 需甲方规则:料/工/费的实际归集来源与工时费率属甲方核算口径,前端为手填+自动汇总框架。
*/
export interface StandardCost {
id: number
productCode: string
productName: string
materialCost: number
laborCost: number
overheadCost: number
totalStandard: number
actualCost: number
variance: number
period: string
/** 归属成本中心(用于按成本中心上卷汇总),可空。 */
costCenter: string
note: string
createdAt: string
}
/** 标准成本按成本中心上卷的一行汇总。 */
export interface CostCenterRollup {
costCenter: string
count: number
materialCost: number
laborCost: number
overheadCost: number
totalStandard: number
actualCost: number
variance: number
}
/** GET /standard-costs/rollup 返回结构:按成本中心分组 + 6 口径总计。 */
export interface StandardCostRollup {
byCostCenter: CostCenterRollup[]
totalMaterial: number
totalLabor: number
totalOverhead: number
totalStandard: number
totalActual: number
totalVariance: number
}
/**
* 成本中心责任树上卷的一个节点(GET /standard-costs/rollup-tree 的 tree 项)。
* selfXxx = 直挂本中心的料/工/费/标准/实际/差异(不含子树);
* rollupXxx = 含本节点 + 整棵子树之和;count = 直挂本中心的台账条目数;
* children = 下级成本中心节点(递归)。
*/
export interface CostCenterRollupNode {
costCenterId: number | null
costCenter: string
ccType: string
level: number
count: number
selfMaterial: number
selfLabor: number
selfOverhead: number
selfStandard: number
selfActual: number
selfVariance: number
rollupMaterial: number
rollupLabor: number
rollupOverhead: number
rollupStandard: number
rollupActual: number
rollupVariance: number
children: CostCenterRollupNode[]
}
/** GET /standard-costs/rollup-tree 返回结构:成本中心树(多级上卷)+ 6 口径总计。 */
export interface StandardCostRollupTree {
tree: CostCenterRollupNode[]
totalMaterial: number
totalLabor: number
totalOverhead: number
totalStandard: number
totalActual: number
totalVariance: number
}
export const CC_TYPES = ['项目', '部门', '公司', '工序']
export const PRICE_CATEGORIES = ['人工', '材料', '机械']
export const PRICE_TYPES = ['信息价', '市场价', '历史中标价', '企业标准价']
export const CERT_TYPES = ['身份证', '一级建造师', '二级建造师', '安全员证', '特种作业证', '职称证书', '学历证书']
/** GET /cost-centers[?ccType=&status=] */
export function listCostCenters(filter?: { ccType?: string; status?: string }): Promise<CostCenter[]> {
return http.get<CostCenter[]>('/cost-centers', filter)
}
export function createCostCenter(input: Partial<CostCenter>): Promise<CostCenter> {
return http.post<CostCenter>('/cost-centers', input)
}
export function updateCostCenter(id: number | string, input: Partial<CostCenter>): Promise<CostCenter> {
return http.put<CostCenter>(`/cost-centers/${encodeURIComponent(String(id))}`, input)
}
export function deleteCostCenter(id: number | string): Promise<void> {
return http.del<void>(`/cost-centers/${encodeURIComponent(String(id))}`)
}
/** GET /cost-centers/tree[?status=] —— 成本中心责任树(含预算/实际多级上卷)。 */
export function listCostCenterTree(status?: string): Promise<CostCenterTreeNode[]> {
return http.get<CostCenterTreeNode[]>('/cost-centers/tree', status ? { status } : undefined)
}
/** GET /price-items[?category=&priceType=] */
export function listPriceItems(filter?: { category?: string; priceType?: string }): Promise<PriceItem[]> {
return http.get<PriceItem[]>('/price-items', filter)
}
export function createPriceItem(input: Partial<PriceItem>): Promise<PriceItem> {
return http.post<PriceItem>('/price-items', input)
}
/** GET /personnel-certs[?certType=&status=] */
export function listPersonnelCerts(filter?: { certType?: string; status?: string }): Promise<PersonnelCert[]> {
return http.get<PersonnelCert[]>('/personnel-certs', filter)
}
export function createPersonnelCert(input: Partial<PersonnelCert>): Promise<PersonnelCert> {
return http.post<PersonnelCert>('/personnel-certs', input)
}
export function updatePersonnelCert(id: number | string, input: Partial<PersonnelCert>): Promise<PersonnelCert> {
return http.put<PersonnelCert>(`/personnel-certs/${encodeURIComponent(String(id))}`, input)
}
export function deletePersonnelCert(id: number | string): Promise<void> {
return http.del<void>(`/personnel-certs/${encodeURIComponent(String(id))}`)
}
/** GET /standard-costs[?period=] —— 标准成本台账。 */
export function listStandardCosts(filter?: { period?: string }): Promise<StandardCost[]> {
return http.get<StandardCost[]>('/standard-costs', filter)
}
/** GET /standard-costs/rollup[?period=] —— 按成本中心上卷汇总料/工/费/标准/实际/差异 + 总计。 */
export function listStandardCostRollup(period?: string): Promise<StandardCostRollup> {
return http.get<StandardCostRollup>('/standard-costs/rollup', period ? { period } : undefined)
}
/** GET /standard-costs/rollup-tree[?period=] —— 按成本中心责任树多级上卷(嵌套树)+ 6 口径总计。 */
export function listStandardCostRollupTree(period?: string): Promise<StandardCostRollupTree> {
return http.get<StandardCostRollupTree>('/standard-costs/rollup-tree', period ? { period } : undefined)
}
export function createStandardCost(input: Partial<StandardCost>): Promise<StandardCost> {
return http.post<StandardCost>('/standard-costs', input)
}
export function updateStandardCost(id: number | string, input: Partial<StandardCost>): Promise<StandardCost> {
return http.put<StandardCost>(`/standard-costs/${encodeURIComponent(String(id))}`, input)
}
export function deleteStandardCost(id: number | string): Promise<void> {
return http.del<void>(`/standard-costs/${encodeURIComponent(String(id))}`)
}