资产管理

本页是一篇完整方案指南:以开源模板插件 asset-management(pluginIdcom.auraboot.template.asset-management,命名空间 tasset)为例,从用户场景一路讲到开发实施和典型错误。它是 config 型插件——3 个 model、23 条命令、9 个页面全部由 DSL JSON 声明,没有一行后端 Java。下面每个 model / 命令 / 权限 / 状态值,你都能在插件目录里 grep 到、对运行实例调得通。

源码:asset-management on GitHub ↗

插件定位是「IT 与办公资产追踪」:从采购、领用、维护到报废。它不含折旧引擎、不含组织/保管链建模、不含位置树——那些属于更重的资产领域插件,模板插件只覆盖一条干净的生命周期主线,适合直接复制改造。


1. 用户场景

一家公司要管自己的 IT 设备、办公家具、车辆和软件许可:

  • 采购到货 → 登记入台账(状态「可用」);
  • 员工领用 → 分配给某人(状态「使用中」),离职/换岗 → 归还;
  • 设备坏了 → 报修送修,修好 → 完成维护回到「可用」;
  • 老旧或损毁 → 报废(终态),从在用资产中剔除;
  • 每次维修/检查/升级要留一条维护记录(类型、技术员、费用、计划与完成日期)。

资产管理员、IT 运维、各部门负责人看到的资产视图和能做的操作各不相同;财务关心的是按类别汇总的资产价值。

2. 需求痛点

  • 台账靠 Excel,状态全凭手填:一台笔电到底是「在用」「送修」还是「已报废」,表里随便改、没人拦,统计永远对不上。
  • 生命周期无约束:已报废的资产还能被「分配」,送修中的资产又被另一个人领走——没有状态机就没有秩序。
  • 操作无授权无审计:谁在什么时候把哪台设备分配给了谁、为什么报废,查不到。
  • 维护记录与资产脱节:报修了却忘记建维护单,或维护单建了却没把资产置为「维护中」,两本账各走各的。

这些都不是「再加一张表」能解决的,而是受控状态变更的问题。

3. 产品方案

在 AuraBoot 里,每一个资产动作都是一条命令,走统一的 命令管道:

  • 「分配资产」按钮调用 tasset:assign_asset,而不是裸写资产表;命令在管道里统一鉴权 → 状态校验 → 执行 → 审计。状态机只允许 available → in_use,已报废或维护中的资产点不动这个按钮。
  • 资产状态存在 tasset_asset.tasset_as_status 上,合法值由字典 tasset_asset_status 约束(available / in_use / under_maintenance / retired),前端按字典渲染状态标签。
  • 同一条命令既是 UI 按钮的目标,也能被自动化规则、BPM 流程、AI agent 调用(每条命令带 cmd_risk_levelagent_hint),所以「报修自动建维护单」这类联动不用人工二次录入——tasset:report_repairsideEffects 会自动派生一条维护工单。

4. 功能设计

4.1 数据模型(3 个)

Model用途关键状态/字典
tasset_asset资产主档(IT/家具/车辆/软件)状态字段 tasset_as_status,字典 tasset_asset_status:available / in_use / under_maintenance / retired
tasset_category资产分类(参考实体,无生命周期)字典 tasset_category:it_equipment / furniture / vehicle / software / other
tasset_maintenance维护/维修/检查记录,通过 tasset_mn_asset_id(reference 字段)关联资产状态字段 tasset_mn_status,字典 tasset_maint_status:scheduled / in_progress / completed;类型 tasset_maint_type:repair / inspection / upgrade

tasset_asset 的字段(节选,全部在 config/fields/tasset_asset.json):tasset_as_code(资产编号,AST-{yyyyMMdd}-{seq} 自动生成、只读)、tasset_as_name(必填)、tasset_as_category(enum,引用 tasset_category 字典)、tasset_as_serial(序列号)、tasset_as_purchase_datetasset_as_purchase_cost(decimal)、tasset_as_locationtasset_as_assigned_to(使用人)、tasset_as_notes(text)。

插件 dependencies 为空——可独立安装到任意 AuraBoot 实例,不耦合 Finance / Org 等其它插件。

4.2 命令与状态机

命令命名 tasset:<动词>_<名词>,全部冒号分隔。23 条命令分三组(资产 11 / 维护 7 / 分类 5):

资产状态机(tasset_as_status):

                 ┌──────────── tasset:retire_asset ───────────┐
                 │                                            ▼
  available ──assign──▶ in_use ──return──▶ available    retired (终态)
     │  ▲                  │
 send_maintenance      send_maintenance
     │  │                  │
     ▼  │ finish_maintenance
 under_maintenance ────────┘
     │
 report_repair → repair(同时派生维护工单)

代表性命令:

命令形态状态流转
tasset:create_assetcreate新建,自动落 tasset_as_code + 状态 available
tasset:assign_assetstate_transitionavailable → in_use(填 tasset_as_assigned_to)
tasset:return_assetstate_transitionin_use → available(清空使用人)
tasset:send_maintenancestate_transitionavailable / in_use → under_maintenance
tasset:finish_maintenancestate_transitionunder_maintenance → available
tasset:report_repairstate_transitionavailable / in_use → repair,并派生维护工单
tasset:retire_assetstate_transitionavailable / in_use / under_maintenance → retired(终态,带确认门)
tasset:create_maintenance / tasset:start_maintenance / tasset:complete_maintenancecreate / state_transition维护单:scheduled → in_progress → completed

每条命令都是一段声明。例如 tasset:assign_asset(config/commands/tasset_asset.json)的真实定义:

{
  "code": "tasset:assign_asset",
  "displayName:zh-CN": "分配资产",
  "type": "state_transition",
  "modelCode": "tasset_asset",
  "stateField": "tasset_as_status",
  "fromStates": ["available"],
  "toState": "in_use",
  "inputFields": ["tasset_as_assigned_to"],
  "permissions": ["tasset.asset.manage"],
  "agent_hint": "Assign asset to a person. Sets status to IN_USE.",
  "cmd_risk_level": "L1",
  "precondition_description": "Asset must be AVAILABLE.",
  "idempotent": false,
  "reversible": false
}

读出来的设计信息:这是一条 state_transition(只允许 available → in_use),执行时收集 tasset_as_assigned_to(使用人)写入资产,要求 tasset.asset.manage 权限,风险级 L1,并通过 agent_hint 告诉 agent 它能做什么。资产不在 available 时这条命令会被状态机拒绝。

tasset:report_repair 更进一步——它带 sideEffects,在把资产置为 repair 的同时自动 create_record 一条 tasset_maintenance(type=repair、status=scheduled),字段映射里用 ${recordId} 回填 tasset_mn_asset_id、用 ${tasset_as_notes} 带上故障描述,资产单与维护单一次操作两本账同时落地。

4.3 权限与角色

插件声明 6 个权限码(config/permissions.json,命名 <模块>.<资源>.<动作>,每资源 manage + read):

tasset.asset.manage          tasset.asset.read
tasset.category.manage       tasset.category.read
tasset.maintenance.manage    tasset.maintenance.read

manage 是写操作权限(create / update / 状态流转 / delete 都要它),read 是查看/列表权限。命令在 permissions 字段里直接绑这些码——例如所有资产写命令绑 tasset.asset.manage,tasset:detail_asset / tasset:list_assetstasset.asset.read

这个模板插件不自带 roles.json——它只声明权限码,角色和授权由平台/租户侧组装(把若干权限码组合成「资产管理员」「IT 运维」「只读审计」等角色)。这是模板插件的常见取舍:留权限原子,角色交给落地方按组织结构定义。

4.4 页面

9 个页面(config/pages/):3 个 model 各一套 list / form / detail——资产列表/录单/详情、分类列表/录单/详情、维护列表/录单/详情。菜单在 config/menus.json 下挂一个「资产管理」根节点,三个子项分别指向 /p/tasset_asset/p/tasset_category/p/tasset_maintenance,各受对应 .read 权限控制可见性。

资产价值汇总走 named query tasset_value_by_category(config/named-queries.json):按类别 GROUP BY 统计在用资产数量与总采购成本,可挂到 dashboard / chart 块上做财务视图。

5. 具体开发与实施

先掌握基础。本插件没有任何后端 Java,全靠平台的几个核心契约。动手前请先读:Model 与 Field · Command · 命令管道 · Permission · 插件清单 · 纯配置 Plugin · Page Designer

落地一个像 asset-management 这样的 config 插件,步骤是:

  1. 定义 model 与字段 —— config/models.json + config/fields/,字段类型用平台 dataType(string / text / enum / decimal / date / reference…),enum 字段挂 dictCode(如 tasset_as_statustasset_asset_status),reference 字段用 extension.referenceModelCode 指向被引用 model(如 tasset_mn_asset_idtasset_asset)。详见 Model 与 Field
  2. 声明命令 —— 每个 model 一个 config/commands/<model>.json,状态流转用 type: state_transition + stateField + fromStates / toState,自动生成编号用 autoSetFields(如 tasset_as_codeAST-{yyyyMMdd}-{seq}),并在 permissions 绑权限码。详见 Command
  3. 配字典 —— config/dicts.json 声明状态/类别枚举(tasset_asset_status / tasset_category / tasset_maint_type / tasset_maint_status),命令的 fromStates / toState 取值必须落在字典里。
  4. 配 model-field binding —— config/bindings/,并在 resourceDirs 注册(见「典型错误」)。
  5. 设计页面 —— config/pages/,各 model 的 list / form / detailPage Designer 出 DSL;菜单在 config/menus.json
  6. 权限 —— config/permissions.json 声明权限码;模板插件可不带角色,由落地方组装。
  7. 打包导入 —— 用 aura CLI 的 import-directory-sync(参数是目录 path)或平台导入接口;校验返回 success:true 才算导入成功。详见 插件清单

plugin.jsonresourceDirs 把上面每个目录映射进来,provides 声明三个 model(tasset_asset / tasset_category / tasset_maintenance),importOptionsautoPublishModels / autoPublishCommands / autoPublishPages 等开关控制导入时是否自动发布。

6. 常见配置

  • 资产编号规则:tasset:create_assetautoSetFields.tasset_as_codepattern: "AST-{yyyyMMdd}-{seq}",维护单用 MNT-{yyyyMMdd}-{seq};改成本企业的前缀即可,无需写代码。
  • 新增资产类别:tasset_category 字典里加一项(value / label:zh-CN / color),tasset_as_category 字段会自动带出新选项。
  • 报修自动建单:tasset:report_repairsideEffects 已经在派生维护工单;若想让别的命令也联动,照同样的 action: create_record + fieldMapping(用 ${recordId} / ${字段码} 插值)配置即可。
  • 资产价值报表:named query tasset_value_by_category 直接给「按类别的资产数量与总成本」,fromSql 查的是物理表 mt_tasset_asset(dynamic model 的表名前缀是 mt_),挂到 dashboard chart 块即可;排除已报废用 tasset_as_status != 'retired'

7. 典型错误

  • 命令码用点号:写成 tasset.asset.assign 跑不通——真实是冒号 + 动词_名词:tasset:assign_asset。注意命令码用冒号,而权限码用点号(tasset.asset.manage),两者格式不同别混。
  • 绕过命令直接改资产状态:直接 UPDATE mt_tasset_asset.tasset_as_status 会跳过状态机校验、sideEffects(报修派生维护单)和审计。一切状态变更都走命令,从可用到使用中只能经 tasset:assign_asset,不能手动改字段。
  • 状态值写错:fromStates / toState 只能用字典 tasset_asset_status 里的值(available / in_use / under_maintenance / retired)。写成 draftdisposed 这类不存在的状态,导入校验会拒绝;这个插件里没有 draft 态,新建资产直接是 available
  • bindingRules 写进 commands.json 内联:不会被导入;必须独立的 binding 文件(本插件放在 config/bindings/)并在 resourceDirs 注册,否则报 [S-EXT-HANDLER] references unregistered handler。详见 纯配置 Plugin
  • 命令执行 payload 结构:字段放在 { "payload": { ... }, "operationType": ... },目标记录用 targetRecordId(不是 recordId)——放错位会出现「执行成功却字段为空」的迷惑性报错。
  • 以为有折旧/位置树:这个模板插件只到资产生命周期 + 维护记录;没有折旧台账、组织保管链、结构化位置树。需要这些请在它之上自建领域插件,不要假设命令里有 depreciate / transfer

下一步

  • 系统总览 —— 插件、命令与运行时如何拼到一起
  • 命令管道 —— 上面每条命令都走的执行契约
  • 权限 —— tasset.* 权限码背后的五层模型
  • 插件清单 —— plugin.json 如何声明 provides / resourceDirs / importOptions
  • 版本与价格 —— 社区版核心运行时契约在各版本中完全一致