规则:怎样改对象与关系
六种规则,外键与多对多链接怎么选,一次改一批对象;规则只搬运值,不做计算。

本课目标
读完这一课,你将能够
- 说出六种规则各改什么,并选对「改外键」还是「建链接」
- 写出
flag-defect与hold-work-order的规则 - 说出规则做不到什么,遇到时怎么办
六种规则
参数只是输入。把输入变成对象和关系上的改动,靠规则。AIDC 的 Action 现在有六种规则:
新建对象
主键必须有值:来自参数,或写 $uuid 让平台生成。
修改对象
改已有对象的属性,对象来自对象参数或对象集参数,命中几个改几个。不能改主键,也不能改本次新建的对象。
新建或修改
按主键判断:有就改,没有就建。
删除对象
删除对象参数指向的对象。删除只发生在 Semantic 里,数据源里的那一行不动。
建立链接
在两个对象之间建立一条多对多链接,两端都是对象参数。
解除链接
解除一条多对多链接。
规则里每个属性的值有四种来源:
- 来自参数:
$goodQty,取调用方填的值。 - 来自对象参数的属性:
$line.lineCode,取被选中那条产线的编码。 - 写死的字面量:
released,调用方改不了。 - 来自上下文:
$user(执行人)、$userName、$now(提交时间)、$uuid(新主键)。
modifyObject 只写要改的属性,没写的保持原样:report-output 更新累计数,不会碰工单的计划数量和产线。
下面的 create-purchase-order 把这四种来源用全了。ownerId 与 createdAt 是示例工厂的共享属性,这里假设 purchaseOrder 带着它们:
{
"kind": "actionType",
"apiName": "create-purchase-order",
"title": "创建采购订单",
"schema": {
"parameters": [
{ "name": "supplier", "type": "object", "objectType": "supplier", "title": "供应商", "required": true },
{ "name": "material", "type": "object", "objectType": "material", "title": "物料", "required": true },
{ "name": "qty", "type": "integer", "title": "数量", "required": true, "min": 1 },
{ "name": "expectedAt", "type": "date", "title": "期望到货日", "required": true }
],
"rules": [
{
"type": "createObject",
"objectType": "purchaseOrder",
"values": {
"poNo": "$uuid",
"status": "draft",
"qty": "$qty",
"expectedAt": "$expectedAt",
"supplierId": "$supplier.supplierId",
"materialCode": "$material.materialCode",
"ownerId": "$user",
"createdAt": "$now"
}
}
],
"actionLog": true
}
}
关系怎么改:外键还是链接
关系怎么改,取决于它怎么存。两条路别混:
| 一对多、一对一 | 多对多 | |
|---|---|---|
| 关系存在哪 | 多的一端对象上的外键属性 | 每条链接是自己的一条记录 |
| 用哪种规则 | createObject 或 modifyObject 写外键 | createLink、deleteLink |
| 示例工厂 | 新缺陷挂到检验上:defect.inspectionId | 产品和物料的 productMaterials |
缺陷与检验是一对多(inspectionDefects),关系存在 defect.inspectionId 上。所以 flag-defect 新建缺陷时写好这个外键,就等于把它挂到了检验下面,不需要 createLink。severity 的三个取值(minor、major、critical)由值类型 defectSeverity 约束。多对多则不同:createLink 的两端都取自对象参数,一条链接是自己的一条记录,解除它只是删掉这条记录,两端的对象都还在。
{
"kind": "actionType",
"apiName": "flag-defect",
"title": "登记缺陷",
"schema": {
"parameters": [
{ "name": "inspection", "type": "object", "objectType": "inspection", "title": "检验", "required": true },
{ "name": "code", "type": "string", "title": "缺陷代码", "required": true, "maxLength": 40 },
{ "name": "severity", "type": "string", "valueType": "defectSeverity", "title": "严重程度", "required": true },
{ "name": "description", "type": "string", "title": "说明", "maxLength": 200 }
],
"rules": [
{
"type": "createObject",
"objectType": "defect",
"values": {
"defectId": "$uuid",
"code": "$code",
"severity": "$severity",
"description": "$description",
"status": "open",
"inspectionId": "$inspection.inspectionId"
}
}
],
"summary": "检验 {inspection} 登记缺陷 {code}",
"actionLog": true
}
}
一次改一批,与规则的组合
质量出了问题,常常要一次暂停一批工单。这时参数用对象集,一条 modifyObject 就改掉命中的每一个对象:
{
"kind": "actionType",
"apiName": "hold-work-order",
"title": "暂停工单",
"schema": {
"parameters": [
{ "name": "workOrders", "type": "objectSet", "objectType": "workOrder", "title": "工单", "required": true },
{ "name": "reason", "type": "string", "title": "暂停原因", "required": true, "maxLength": 200 }
],
"rules": [
{ "type": "modifyObject", "objectType": "workOrder", "object": "$workOrders", "values": { "status": "paused" } }
],
"actionLog": true
}
}
reason 没有写进任何属性,但它是参数,会进日志,事后能查到「为什么暂停」。一次最多改 10,000 个对象、涉及 50 个对象类型。
一个 Action 可以放多条规则,发运订单就是「新建发运单」加「改订单状态」(第 7 节)。多条规则会被合成每个对象一条编辑:如果两条规则给同一个对象的同一个属性写值,结果就是后一条的,所以规则的顺序会影响结果,而且有三种组合不成立:
- 先删除、再新增或修改同一个对象。
- 先修改、再新增同一个对象。
- 同一次提交里新建同一个对象两次。
规则不做什么
规则只搬运值,不做计算。receive-material 想把收到的数量加到 material.onHandQty 上,「原值加收货数」这个加法写不进规则。
- 一种办法:调用方先算好「收货后现存量」,作为参数传入。也可以用编辑 Function 在 Action 内读取对象并计算。
- 需要在 Action 里读多个对象再计算,是 Function 驱动的 Action 的活,第 7 节讲。
- 主键不能用 Action 改。想换主键,就删掉这个对象再新建一个。
下面是 receive-material 使用声明式规则的写法:调用方先算好「收货后现存量」,作为 onHandQtyAfter 传入。receivedQty 留在日志里,事后能对账。两条 modifyObject 分别改采购订单和物料,在同一个事务里。
{
"kind": "actionType",
"apiName": "receive-material",
"title": "收料",
"schema": {
"parameters": [
{ "name": "purchaseOrder", "type": "object", "objectType": "purchaseOrder", "title": "采购订单", "required": true },
{ "name": "material", "type": "object", "objectType": "material", "title": "物料", "required": true },
{ "name": "receivedQty", "type": "integer", "title": "本次收到数量", "required": true, "min": 1 },
{ "name": "onHandQtyAfter", "type": "integer", "title": "收货后现存量", "required": true, "min": 0 }
],
"rules": [
{ "type": "modifyObject", "objectType": "purchaseOrder", "object": "$purchaseOrder", "values": { "status": "received" } },
{ "type": "modifyObject", "objectType": "material", "object": "$material", "values": { "onHandQty": "$onHandQtyAfter" } }
],
"submissionCriteria": [
{
"condition": { "type": "comparison", "left": { "param": "purchaseOrder", "property": "status" }, "operator": "is", "right": { "literal": "approved" } },
"failureMessage": "只有已批准的采购订单可以收料"
},
{
"condition": { "type": "comparison", "left": { "param": "purchaseOrder", "property": "materialCode" }, "operator": "is", "right": { "param": "material", "property": "materialCode" } },
"failureMessage": "这张采购订单采购的不是所选的物料"
}
],
"actionLog": true
}
}
改什么、怎么改都定了,下一节讲最重要的一道关:提交条件,它决定什么时候、谁不能改。
要点
- 六种规则:新建、修改、新建或修改、删除对象,建立、解除链接。
- 一对多、一对一的关系改外键,多对多才用链接规则。
- 对象集参数加一条
modifyObject,一次改一批;一次最多 10,000 个对象、50 个对象类型。 - 规则只搬运值,不做计算。调用方可以先算好,也可以让编辑 Function 读取对象、计算并产生编辑。
练一练
为采购与工单写规则
三个小任务,从写到判断到检查。
把一张采购订单的负责人换成另一位同事:参数是采购订单和新负责人的账号(string),一条 modifyObject 改 ownerId。再想一想:这个 Action 应该加哪条提交条件,才不会有人把别人的订单抢走?
下面四件事各用哪种规则:给产品加一种物料;把一次检验的 result 改成 fail;撤掉一张误建的草稿采购订单;给工单换一条产线。
把 hold-work-order 存成文件放进 ontology/ 目录,运行 aidc semantic define ontology/ --dry-run,看引用是否闭合:workOrder 这个对象类型必须已经存在。
小测
选一个答案,马上看解析。
Q1flag-defect 要把新缺陷挂到一次检验上,应该怎么做?
一对多的关系存在多的一端的外键上,写外键就是建立关系。createLink 只用于多对多。
Q2receive-material 想让 onHandQty 变成「原值加收货数量」,规则里能这样写吗?
声明式规则没有算术表达式。可以先在调用方算好,或用编辑 Function 计算,再由 Action 统一提交编辑。
Q3同一个 Action 里先 deleteObject 一个对象,再 modifyObject 同一个对象,会怎样?
多条规则会被合成每个对象一条编辑,先删除再修改这种组合没有意义,不被支持。