@dazitech/cli 3.1.0 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/clis/dazi-app.js +2 -2
- package/dist/clis/dazi-flow.js +2 -2
- package/dist/clis/dazi-onto.js +318 -40
- package/dist/clis/dazi.js +407 -185
- package/dist/docs/flow/flow-project-guide.md +1 -1
- package/dist/docs/guides/cli-reference.md +16 -3
- package/dist/docs/guides/troubleshooting.md +1 -1
- package/dist/docs/index.json +1 -13
- package/dist/docs/onto/dazi_script_sdk_reference.md +1 -1
- package/dist/docs/onto/dazi_script_seed_data_guide.md +1 -1
- package/dist/docs/onto/function-guide.md +6 -6
- package/dist/docs/onto//346/234/254/344/275/223/345/210/206/347/261/273/350/247/204/345/210/222/344/270/216SDK/346/211/251/345/261/225/346/226/271/346/241/210.md +169 -169
- package/dist/docs/onto//346/234/254/344/275/223/345/221/275/345/220/215/350/247/204/350/214/203_/347/211/251/347/220/206/350/241/250Cube/344/270/216/345/257/271/350/261/241.md +3 -2
- package/dist/docs/onto//346/234/254/344/275/223/345/274/200/345/217/221/344/274/230/345/214/226/346/200/273/347/273/223.md +257 -242
- package/dist/docs/onto//346/234/254/344/275/223/350/204/232/346/234/254/347/274/226/345/206/231/346/214/207/345/215/227.md +12 -12
- package/dist/docs/onto//346/234/254/344/275/223/350/247/204/345/210/222/346/214/207/345/215/227.md +14 -13
- package/dist/docs/onto//350/204/232/346/234/254/350/277/220/350/241/214/345/270/270/350/247/201/351/224/231/350/257/257/345/244/204/347/220/206.md +70 -15
- package/dist/examples/index.json +222 -6
- package/dist/examples/onto/README.md +34 -36
- package/dist/examples/onto/_templates/onto_preflight.ps1 +84 -0
- package/dist/examples/onto/index.json +53 -0
- package/dist/examples/onto/index.yaml +29 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/README.md +23 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/save_test_arguments.ps1 +12 -11
- package/dist/{docs/onto → examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/plans}//350/247/204/345/210/222/347/244/272/344/276/213_/345/210/251/346/266/246/345/210/206/346/236/220/346/234/254/344/275/223/346/226/271/346/241/210.md +4 -4
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/setup/profit_category_mount.py +1 -1
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/setup/profit_ontology_init.py +1 -1
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/README.md +24 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_availability_analysis.py +84 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_downtime_breakdown.py +119 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_energy_intensity.py +98 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_get_summary.py +125 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_maintenance_compliance.py +77 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_mom_analysis.py +118 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_oee_analysis.py +126 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_plan_vs_actual.py +105 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_top_fault_equipment.py +104 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_unit_comparison.py +120 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/equip_ops_fn_yoy_analysis.py +115 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/save_test_arguments.ps1 +42 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.availability_analysis.json +7 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.downtime_breakdown.json +8 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.energy_intensity.json +8 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.get_summary.json +7 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.maintenance_compliance.json +7 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.mom_analysis.json +8 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.oee_analysis.json +8 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.plan_vs_actual.json +8 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.top_fault_equipment.json +8 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.unit_comparison.json +8 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/functions/test_arguments/equip_ops.fn.yoy_analysis.json +8 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/plans//345/214/226/345/267/245/350/256/276/345/244/207/350/277/220/350/220/245/345/210/206/346/236/220/346/234/254/344/275/223/346/226/271/346/241/210.md +735 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/setup/equip_ops_category_mount.py +106 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/setup/equip_ops_ontology_init.py +1077 -0
- package/dist/examples/onto//350/256/276/345/244/207/350/277/220/350/220/245/setup/equip_ops_seed_data.py +552 -0
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/README.md +23 -0
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/save_test_arguments.ps1 +13 -12
- package/dist/{docs/onto → examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/plans}//350/247/204/345/210/222/347/244/272/344/276/213_/344/272/247/345/223/201/351/224/200/345/224/256/346/234/254/344/275/223/350/247/204/345/210/222/346/226/271/346/241/210.md +2 -2
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/setup/sales_category_mount.py +1 -1
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/setup/sales_ontology_init.py +1 -1
- package/dist/prompts/index.json +1 -1
- package/dist/prompts/onto/planning-design.md +226 -104
- package/dist/prompts/onto/script-publish-run.md +8 -6
- package/package.json +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0",
|
|
3
|
+
"updatedAt": "2026-06-06",
|
|
4
|
+
"defaultReadOrder": [],
|
|
5
|
+
"examples": [
|
|
6
|
+
{
|
|
7
|
+
"id": "sales",
|
|
8
|
+
"dir": "销售示例",
|
|
9
|
+
"title": "产品销售分析",
|
|
10
|
+
"domain": [
|
|
11
|
+
"销售",
|
|
12
|
+
"订单",
|
|
13
|
+
"产品",
|
|
14
|
+
"渠道",
|
|
15
|
+
"SKU",
|
|
16
|
+
"客户"
|
|
17
|
+
],
|
|
18
|
+
"planPrimary": "plans/规划示例_产品销售本体规划方案.md",
|
|
19
|
+
"featured": true
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "profit",
|
|
23
|
+
"dir": "利润示例",
|
|
24
|
+
"title": "利润 / GL 分析",
|
|
25
|
+
"domain": [
|
|
26
|
+
"利润",
|
|
27
|
+
"科目",
|
|
28
|
+
"预算",
|
|
29
|
+
"GL",
|
|
30
|
+
"成本中心",
|
|
31
|
+
"预实"
|
|
32
|
+
],
|
|
33
|
+
"planPrimary": "plans/规划示例_利润分析本体方案.md",
|
|
34
|
+
"featured": true
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"id": "equip-ops",
|
|
38
|
+
"dir": "设备运营",
|
|
39
|
+
"title": "化工设备运营分析",
|
|
40
|
+
"domain": [
|
|
41
|
+
"设备",
|
|
42
|
+
"OEE",
|
|
43
|
+
"停机",
|
|
44
|
+
"维保",
|
|
45
|
+
"能耗",
|
|
46
|
+
"工厂",
|
|
47
|
+
"运营"
|
|
48
|
+
],
|
|
49
|
+
"planPrimary": "plans/化工设备运营分析本体方案.md",
|
|
50
|
+
"featured": true
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
version: "1.0"
|
|
2
|
+
updatedAt: "2026-06-07"
|
|
3
|
+
|
|
4
|
+
# 规划 / 脚本阶段须至少阅读 defaultReadOrder 中一个完整示例(README + plans 主文档)
|
|
5
|
+
defaultReadOrder:
|
|
6
|
+
- 销售示例
|
|
7
|
+
- 设备运营
|
|
8
|
+
|
|
9
|
+
examples:
|
|
10
|
+
- id: sales
|
|
11
|
+
dir: 销售示例
|
|
12
|
+
title: 产品销售分析
|
|
13
|
+
domain: [销售, 订单, 产品, 渠道, SKU, 客户]
|
|
14
|
+
planPrimary: plans/规划示例_产品销售本体规划方案.md
|
|
15
|
+
featured: true
|
|
16
|
+
|
|
17
|
+
- id: profit
|
|
18
|
+
dir: 利润示例
|
|
19
|
+
title: 利润 / GL 分析
|
|
20
|
+
domain: [利润, 科目, 预算, GL, 成本中心, 预实]
|
|
21
|
+
planPrimary: plans/规划示例_利润分析本体方案.md
|
|
22
|
+
featured: true
|
|
23
|
+
|
|
24
|
+
- id: equip-ops
|
|
25
|
+
dir: 设备运营
|
|
26
|
+
title: 化工设备运营分析
|
|
27
|
+
domain: [设备, OEE, 停机, 维保, 能耗, 工厂, 运营]
|
|
28
|
+
planPrimary: plans/化工设备运营分析本体方案.md
|
|
29
|
+
featured: true
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 利润示例 · GL / 利润分析
|
|
2
|
+
|
|
3
|
+
## 基本信息
|
|
4
|
+
|
|
5
|
+
| 字段 | 内容 |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| 数据空间 | 以示例脚本内 `space_id` 为准(复制后改 README) |
|
|
8
|
+
| 示例 ID | `profit`(见 `../index.yaml` / `index.json`) |
|
|
9
|
+
|
|
10
|
+
## 目录
|
|
11
|
+
|
|
12
|
+
| 路径 | 说明 |
|
|
13
|
+
| --- | --- |
|
|
14
|
+
| [plans/规划示例_利润分析本体方案.md](./plans/规划示例_利润分析本体方案.md) | **规划正文** |
|
|
15
|
+
| `setup/` | `profit_ontology_init.py`、`profit_seed_data.py`、`profit_category_mount.py` |
|
|
16
|
+
| `functions/` | 7 个 `profit_fn_*.py`、`test_arguments/` |
|
|
17
|
+
|
|
18
|
+
## 使用
|
|
19
|
+
|
|
20
|
+
- **规划阶段**:通读 `plans/*.md`;与 [销售示例](../销售示例/) 对照时写清差异说明
|
|
21
|
+
- **实施阶段**:init **不含** `apply_registry`;分类在 `profit_category_mount.py`(最后执行)
|
|
22
|
+
|
|
23
|
+
规范指南:`资源/docs/onto/本体规划指南.md`
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
# 用法:在 dazi-work 根目录执行 .\项目\DAZI_TEST\本体\ontos\利润分析示例\functions\save_test_arguments.ps1
|
|
4
4
|
|
|
5
5
|
$spaceId = "space__misc_01"
|
|
6
|
-
$itemPath = "项目/DAZI_TEST/本体/ontos/利润分析示例/functions"
|
|
7
6
|
|
|
8
7
|
$functions = @(
|
|
9
8
|
@{fn_id="profit.fn.get_summary"; file="profit.fn.get_summary.json"},
|
|
@@ -16,23 +15,25 @@ $functions = @(
|
|
|
16
15
|
)
|
|
17
16
|
|
|
18
17
|
Write-Host "获取函数列表..."
|
|
19
|
-
$
|
|
18
|
+
$fnListRaw = & dazi onto function list --space $spaceId --json 2>&1
|
|
19
|
+
$jsonLines = ($fnListRaw | Where-Object { $_ -notmatch '__JSON_SUMMARY__' }) -join "`n"
|
|
20
|
+
$fnList = $jsonLines | ConvertFrom-Json
|
|
20
21
|
|
|
21
22
|
foreach ($fn in $functions) {
|
|
22
23
|
$fnId = $fn.fn_id
|
|
23
24
|
$fileName = $fn.file
|
|
24
25
|
$jsonPath = "$PSScriptRoot/test_arguments/$fileName"
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
if (-not (Test-Path $jsonPath)) {
|
|
28
|
+
Write-Host "跳过 $fnId:找不到 $jsonPath"
|
|
29
|
+
continue
|
|
28
30
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Write-Host "函数 $fnId 未找到,请先发布函数"
|
|
31
|
+
|
|
32
|
+
Write-Host "保存 $fnId ..."
|
|
33
|
+
& dazi onto function save-test-arguments --function-id $fnId --space $spaceId --arguments-json-file $jsonPath
|
|
34
|
+
if ($LASTEXITCODE -ne 0) {
|
|
35
|
+
Write-Host " ✗ 保存失败" -ForegroundColor Red
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
Write-Host "完成"
|
|
39
|
+
Write-Host "完成"
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> **只读参照**:本文档供学习 GL 域规划**结构**与验收口径,**不得**整篇复制为本项目 `plans/` 充数。新建实现须在 `plans/` **独立撰写**,并含「与参照示例的差异说明」章节(见 [本体规划指南 · 任务模式](./本体规划指南.md#任务模式与反模式))。
|
|
6
6
|
|
|
7
7
|
> 表/Cube/对象命名遵循 [本体命名规范](./本体命名规范_物理表Cube与对象.md)。
|
|
8
|
-
> 工程模式参考:[
|
|
8
|
+
> 工程模式参考:[销售示例 plans](../../销售示例/plans/规划示例_产品销售本体规划方案.md)
|
|
9
9
|
|
|
10
10
|
**占位符**(复制到工作区 `plans/` 后替换为实际值):
|
|
11
11
|
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
|
|
77
77
|
### 3.0 时间维:dim_date(强制)
|
|
78
78
|
|
|
79
|
-
与销售域共用;字段定义见 [
|
|
79
|
+
与销售域共用;字段定义见 [销售示例 §3.0](../../销售示例/plans/规划示例_产品销售本体规划方案.md#30-时间维dim_date强制)。分录 **`date_key = toYYYYMMDD(posting_date)`**;预算行可用 **`toYYYYMMDD(toDate(concat(toString(fiscal_year), '-', lpad(toString(fiscal_period), 2, '0'), '-01')))`** 或 period 末代表日,规划须写清口径。
|
|
80
80
|
|
|
81
81
|
### 3.1 维度表:dim_account
|
|
82
82
|
|
|
@@ -534,7 +534,7 @@ s.tables.add_relationship(
|
|
|
534
534
|
| 来源 | 用途 | 注意 |
|
|
535
535
|
| ---- | ---- | ---- |
|
|
536
536
|
| `资源/examples/onto/利润示例/` | 对照 API 写法或复制后按 **本实现 plans** 改造 | **禁止**无 plans 直接复制 init |
|
|
537
|
-
| [
|
|
537
|
+
| [销售示例](../../销售示例/plans/规划示例_产品销售本体规划方案.md) | 跨域工程模式只读对照 | 表结构与函数逻辑不同 |
|
|
538
538
|
|
|
539
539
|
**seed 数据建议**:
|
|
540
540
|
|
|
@@ -670,7 +670,7 @@ s.tables.add_relationship(
|
|
|
670
670
|
| ---- | ---- |
|
|
671
671
|
| 本体命名规范 | [本体命名规范_物理表Cube与对象.md](./本体命名规范_物理表Cube与对象.md) |
|
|
672
672
|
| 本体规划指南 | [本体规划指南.md](./本体规划指南.md) |
|
|
673
|
-
|
|
|
673
|
+
| 销售示例 | [规划示例_产品销售本体规划方案.md](../../销售示例/plans/规划示例_产品销售本体规划方案.md) |
|
|
674
674
|
| **内置脚本示例** | `资源/examples/onto/利润示例/`(`dazi examples sync`;表名迁移中) |
|
|
675
675
|
| 分类方案 | [本体分类规划与 SDK 扩展方案](./本体分类规划与SDK扩展方案.md) |
|
|
676
676
|
|
|
@@ -5,7 +5,7 @@ init → seed → 发布全部函数 → **本脚本**。
|
|
|
5
5
|
|
|
6
6
|
放置:资源/examples/onto/利润示例/setup/profit_category_mount.py
|
|
7
7
|
发布:dazi onto script publish <item-path>/setup/profit_category_mount.py --space <space-id> --type setup
|
|
8
|
-
规划对照:资源/
|
|
8
|
+
规划对照:资源/examples/onto/利润示例/plans/规划示例_利润分析本体方案.md 附录 B
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
import json
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
放置:资源/examples/onto/利润示例/setup/profit_ontology_init.py(复制到项目 ontos/<实现名>/setup/)
|
|
13
13
|
发布:dazi onto script publish <item-path>/setup/profit_ontology_init.py --space <space-id> --type setup
|
|
14
|
-
规划对照:资源/
|
|
14
|
+
规划对照:资源/examples/onto/利润示例/plans/规划示例_利润分析本体方案.md
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
import json
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# 设备运营 · 化工设备运营分析
|
|
2
|
+
|
|
3
|
+
## 基本信息
|
|
4
|
+
|
|
5
|
+
| 字段 | 内容 |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| 数据空间 | 分类测试01 |
|
|
8
|
+
| 数据空间 ID | `space_cate_test01` |
|
|
9
|
+
| 示例 ID | `equip-ops`(见 `../index.yaml` / `index.json`) |
|
|
10
|
+
|
|
11
|
+
## 目录
|
|
12
|
+
|
|
13
|
+
| 路径 | 说明 |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| [plans/化工设备运营分析本体方案.md](./plans/化工设备运营分析本体方案.md) | **规划正文**(OEE、停机等) |
|
|
16
|
+
| `setup/` | `equip_ops_ontology_init.py`、`equip_ops_seed_data.py`、`equip_ops_category_mount.py` |
|
|
17
|
+
| `functions/` | 11 个 `equip_ops_fn_*.py`、`test_arguments/` |
|
|
18
|
+
|
|
19
|
+
## 使用
|
|
20
|
+
|
|
21
|
+
- **规划阶段**:推荐阅读(含 Cube + 冗余字段策略 + 11 函数清单)
|
|
22
|
+
- **实施阶段**:init 不含 `apply_registry`;见 `equip_ops_category_mount.py`
|
|
23
|
+
|
|
24
|
+
规范指南:`资源/docs/onto/本体规划指南.md`
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""可用率与停机结构分析 equip_ops.fn.availability_analysis
|
|
2
|
+
|
|
3
|
+
参数:start_date, end_date, plant_id(可选)
|
|
4
|
+
返回:planned_downtime_hours, unplanned_downtime_hours, runtime_hours, availability, load_rate
|
|
5
|
+
|
|
6
|
+
发布:
|
|
7
|
+
dazi onto script publish 项目/DAZI_TEST/本体/ontos/设备运营/functions/equip_ops_fn_availability_analysis.py \
|
|
8
|
+
--space space_cate_test01 --register-function-id equip_ops.fn.availability_analysis
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
TEST_ARGUMENTS = {
|
|
12
|
+
"v": 1,
|
|
13
|
+
"arguments": {"start_date": "2025-01-01", "end_date": "2026-06-30"},
|
|
14
|
+
"object_type_code": "EquipmentAnalysis",
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _build_ops_where(start_date, end_date, plant_id=None):
|
|
19
|
+
clauses = []
|
|
20
|
+
if start_date and end_date:
|
|
21
|
+
clauses.append(f"calendar_date >= '{start_date}' AND calendar_date <= '{end_date}'")
|
|
22
|
+
if plant_id:
|
|
23
|
+
clauses.append(f"plant_id = '{plant_id}'")
|
|
24
|
+
return ("WHERE " + " AND ".join(clauses)) if clauses else ""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _ontology_fn_body(p):
|
|
28
|
+
params = dict(p.get_params() or {})
|
|
29
|
+
start_date = params.get("start_date", "")
|
|
30
|
+
end_date = params.get("end_date", "")
|
|
31
|
+
plant_id = params.get("plant_id") or None
|
|
32
|
+
where_clause = _build_ops_where(start_date, end_date, plant_id)
|
|
33
|
+
|
|
34
|
+
sql = f"""
|
|
35
|
+
SELECT
|
|
36
|
+
sum(planned_downtime_min) AS sum_planned_downtime_min,
|
|
37
|
+
sum(unplanned_downtime_min) AS sum_unplanned_downtime_min,
|
|
38
|
+
sum(runtime_min) AS sum_runtime_min,
|
|
39
|
+
sum(calendar_minutes - planned_downtime_min) AS sum_available_min
|
|
40
|
+
FROM fact_equipment_daily_ops
|
|
41
|
+
{where_clause}
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
rows = p.sql.query(sql)
|
|
45
|
+
row = rows[0] if rows else {}
|
|
46
|
+
|
|
47
|
+
sum_runtime = float(row.get("sum_runtime_min") or 0)
|
|
48
|
+
sum_available = float(row.get("sum_available_min") or 0)
|
|
49
|
+
availability = sum_runtime / sum_available if sum_available > 0 else 0.0
|
|
50
|
+
load_rate = availability
|
|
51
|
+
|
|
52
|
+
data = [{
|
|
53
|
+
"planned_downtime_hours": round(float(row.get("sum_planned_downtime_min") or 0) / 60.0, 2),
|
|
54
|
+
"unplanned_downtime_hours": round(
|
|
55
|
+
float(row.get("sum_unplanned_downtime_min") or 0) / 60.0, 2
|
|
56
|
+
),
|
|
57
|
+
"runtime_hours": round(sum_runtime / 60.0, 2),
|
|
58
|
+
"availability": round(availability, 4),
|
|
59
|
+
"load_rate": round(load_rate, 4),
|
|
60
|
+
}]
|
|
61
|
+
|
|
62
|
+
return p.function_result(
|
|
63
|
+
columns=[
|
|
64
|
+
"planned_downtime_hours", "unplanned_downtime_hours",
|
|
65
|
+
"runtime_hours", "availability", "load_rate",
|
|
66
|
+
],
|
|
67
|
+
data=data,
|
|
68
|
+
row_count=1,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def main():
|
|
73
|
+
s = space.get(ctx.space_id or "")
|
|
74
|
+
_Ports = type(
|
|
75
|
+
"_Ports",
|
|
76
|
+
(),
|
|
77
|
+
{
|
|
78
|
+
"get_params": lambda self: dict(ctx.params or {}),
|
|
79
|
+
"function_result": lambda self, **kw: onto.function_result(**kw),
|
|
80
|
+
},
|
|
81
|
+
)
|
|
82
|
+
p = _Ports()
|
|
83
|
+
p.sql = s.sql
|
|
84
|
+
return _ontology_fn_body(p)
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""停机原因结构分析 equip_ops.fn.downtime_breakdown
|
|
2
|
+
|
|
3
|
+
参数:start_date, end_date, reason_level=2, plant_id(可选)
|
|
4
|
+
JOIN dim_downtime_reason,返回 reason_code, reason_name, reason_category,
|
|
5
|
+
is_planned, downtime_hours, event_count, share_pct
|
|
6
|
+
|
|
7
|
+
发布:
|
|
8
|
+
dazi onto script publish 项目/DAZI_TEST/本体/ontos/设备运营/functions/equip_ops_fn_downtime_breakdown.py \
|
|
9
|
+
--space space_cate_test01 --register-function-id equip_ops.fn.downtime_breakdown
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
TEST_ARGUMENTS = {
|
|
13
|
+
"v": 1,
|
|
14
|
+
"arguments": {
|
|
15
|
+
"start_date": "2025-01-01",
|
|
16
|
+
"end_date": "2026-06-30",
|
|
17
|
+
"reason_level": 2,
|
|
18
|
+
},
|
|
19
|
+
"object_type_code": "EquipmentAnalysis",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _build_where(start_date, end_date, plant_id=None):
|
|
24
|
+
clauses = []
|
|
25
|
+
if start_date and end_date:
|
|
26
|
+
clauses.append(
|
|
27
|
+
f"e.start_time >= '{start_date} 00:00:00' AND e.start_time <= '{end_date} 23:59:59'"
|
|
28
|
+
)
|
|
29
|
+
if plant_id:
|
|
30
|
+
clauses.append(f"e.plant_id = '{plant_id}'")
|
|
31
|
+
return ("WHERE " + " AND ".join(clauses)) if clauses else ""
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _ontology_fn_body(p):
|
|
35
|
+
params = dict(p.get_params() or {})
|
|
36
|
+
start_date = params.get("start_date", "")
|
|
37
|
+
end_date = params.get("end_date", "")
|
|
38
|
+
reason_level = int(params.get("reason_level", 2) or 2)
|
|
39
|
+
plant_id = params.get("plant_id") or None
|
|
40
|
+
where_clause = _build_where(start_date, end_date, plant_id)
|
|
41
|
+
|
|
42
|
+
if reason_level <= 1:
|
|
43
|
+
group_cols = "dr.reason_category"
|
|
44
|
+
select_cols = """
|
|
45
|
+
dr.reason_category AS reason_code,
|
|
46
|
+
dr.reason_category AS reason_name,
|
|
47
|
+
dr.reason_category AS reason_category,
|
|
48
|
+
max(dr.is_planned) AS is_planned
|
|
49
|
+
"""
|
|
50
|
+
else:
|
|
51
|
+
group_cols = "dr.reason_code, dr.reason_name, dr.reason_category, dr.is_planned"
|
|
52
|
+
select_cols = """
|
|
53
|
+
dr.reason_code AS reason_code,
|
|
54
|
+
dr.reason_name AS reason_name,
|
|
55
|
+
dr.reason_category AS reason_category,
|
|
56
|
+
dr.is_planned AS is_planned
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
sql = f"""
|
|
60
|
+
SELECT
|
|
61
|
+
{select_cols},
|
|
62
|
+
sum(e.duration_min) AS downtime_min,
|
|
63
|
+
count() AS event_count
|
|
64
|
+
FROM fact_downtime_event AS e
|
|
65
|
+
INNER JOIN dim_downtime_reason AS dr ON e.reason_id = dr.reason_id
|
|
66
|
+
{where_clause}
|
|
67
|
+
GROUP BY {group_cols}
|
|
68
|
+
ORDER BY downtime_min DESC
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
result = p.sql.query(sql)
|
|
72
|
+
if not result:
|
|
73
|
+
return p.function_result(
|
|
74
|
+
columns=[
|
|
75
|
+
"reason_code", "reason_name", "reason_category",
|
|
76
|
+
"is_planned", "downtime_hours", "event_count", "share_pct",
|
|
77
|
+
],
|
|
78
|
+
data=[],
|
|
79
|
+
row_count=0,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
total_min = sum(float(r.get("downtime_min") or 0) for r in result)
|
|
83
|
+
data = []
|
|
84
|
+
for row in result:
|
|
85
|
+
downtime_min = float(row.get("downtime_min") or 0)
|
|
86
|
+
share_pct = downtime_min / total_min if total_min > 0 else 0.0
|
|
87
|
+
data.append({
|
|
88
|
+
"reason_code": str(row.get("reason_code") or ""),
|
|
89
|
+
"reason_name": str(row.get("reason_name") or ""),
|
|
90
|
+
"reason_category": str(row.get("reason_category") or ""),
|
|
91
|
+
"is_planned": int(row.get("is_planned") or 0),
|
|
92
|
+
"downtime_hours": round(downtime_min / 60.0, 2),
|
|
93
|
+
"event_count": int(row.get("event_count") or 0),
|
|
94
|
+
"share_pct": round(share_pct, 4),
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
return p.function_result(
|
|
98
|
+
columns=[
|
|
99
|
+
"reason_code", "reason_name", "reason_category",
|
|
100
|
+
"is_planned", "downtime_hours", "event_count", "share_pct",
|
|
101
|
+
],
|
|
102
|
+
data=data,
|
|
103
|
+
row_count=len(data),
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def main():
|
|
108
|
+
s = space.get(ctx.space_id or "")
|
|
109
|
+
_Ports = type(
|
|
110
|
+
"_Ports",
|
|
111
|
+
(),
|
|
112
|
+
{
|
|
113
|
+
"get_params": lambda self: dict(ctx.params or {}),
|
|
114
|
+
"function_result": lambda self, **kw: onto.function_result(**kw),
|
|
115
|
+
},
|
|
116
|
+
)
|
|
117
|
+
p = _Ports()
|
|
118
|
+
p.sql = s.sql
|
|
119
|
+
return _ontology_fn_body(p)
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""能耗强度分析 equip_ops.fn.energy_intensity
|
|
2
|
+
|
|
3
|
+
参数:start_date, end_date, group_by=plant|unit|equipment, plant_id(可选)
|
|
4
|
+
返回:group_id, group_name, energy_total, output_qty, energy_per_output
|
|
5
|
+
|
|
6
|
+
发布:
|
|
7
|
+
dazi onto script publish 项目/DAZI_TEST/本体/ontos/设备运营/functions/equip_ops_fn_energy_intensity.py \
|
|
8
|
+
--space space_cate_test01 --register-function-id equip_ops.fn.energy_intensity
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
TEST_ARGUMENTS = {
|
|
12
|
+
"v": 1,
|
|
13
|
+
"arguments": {
|
|
14
|
+
"start_date": "2025-01-01",
|
|
15
|
+
"end_date": "2026-06-30",
|
|
16
|
+
"group_by": "plant",
|
|
17
|
+
},
|
|
18
|
+
"object_type_code": "EquipmentAnalysis",
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
_GROUP_BY_MAP = {
|
|
22
|
+
"plant": ("plant_id", "any(plant_name)"),
|
|
23
|
+
"unit": ("unit_id", "any(unit_name)"),
|
|
24
|
+
"equipment": ("equipment_id", "any(equipment_name)"),
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _build_ops_where(start_date, end_date, plant_id=None):
|
|
29
|
+
clauses = []
|
|
30
|
+
if start_date and end_date:
|
|
31
|
+
clauses.append(f"calendar_date >= '{start_date}' AND calendar_date <= '{end_date}'")
|
|
32
|
+
if plant_id:
|
|
33
|
+
clauses.append(f"plant_id = '{plant_id}'")
|
|
34
|
+
return ("WHERE " + " AND ".join(clauses)) if clauses else ""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _ontology_fn_body(p):
|
|
38
|
+
params = dict(p.get_params() or {})
|
|
39
|
+
start_date = params.get("start_date", "")
|
|
40
|
+
end_date = params.get("end_date", "")
|
|
41
|
+
group_by = params.get("group_by", "plant")
|
|
42
|
+
plant_id = params.get("plant_id") or None
|
|
43
|
+
group_id_col, group_name_expr = _GROUP_BY_MAP.get(group_by, _GROUP_BY_MAP["plant"])
|
|
44
|
+
where_clause = _build_ops_where(start_date, end_date, plant_id)
|
|
45
|
+
|
|
46
|
+
sql = f"""
|
|
47
|
+
SELECT
|
|
48
|
+
{group_id_col} AS group_id,
|
|
49
|
+
{group_name_expr} AS group_name,
|
|
50
|
+
sum(energy_consumption) AS energy_total,
|
|
51
|
+
sum(actual_output_qty) AS output_qty
|
|
52
|
+
FROM fact_equipment_daily_ops
|
|
53
|
+
{where_clause}
|
|
54
|
+
GROUP BY {group_id_col}
|
|
55
|
+
ORDER BY energy_total DESC
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
result = p.sql.query(sql)
|
|
59
|
+
if not result:
|
|
60
|
+
return p.function_result(
|
|
61
|
+
columns=["group_id", "group_name", "energy_total", "output_qty", "energy_per_output"],
|
|
62
|
+
data=[],
|
|
63
|
+
row_count=0,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
data = []
|
|
67
|
+
for row in result:
|
|
68
|
+
energy_total = float(row.get("energy_total") or 0)
|
|
69
|
+
output_qty = float(row.get("output_qty") or 0)
|
|
70
|
+
energy_per_output = energy_total / output_qty if output_qty > 0 else 0.0
|
|
71
|
+
data.append({
|
|
72
|
+
"group_id": str(row.get("group_id") or ""),
|
|
73
|
+
"group_name": str(row.get("group_name") or ""),
|
|
74
|
+
"energy_total": round(energy_total, 2),
|
|
75
|
+
"output_qty": round(output_qty, 2),
|
|
76
|
+
"energy_per_output": round(energy_per_output, 4),
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
return p.function_result(
|
|
80
|
+
columns=["group_id", "group_name", "energy_total", "output_qty", "energy_per_output"],
|
|
81
|
+
data=data,
|
|
82
|
+
row_count=len(data),
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def main():
|
|
87
|
+
s = space.get(ctx.space_id or "")
|
|
88
|
+
_Ports = type(
|
|
89
|
+
"_Ports",
|
|
90
|
+
(),
|
|
91
|
+
{
|
|
92
|
+
"get_params": lambda self: dict(ctx.params or {}),
|
|
93
|
+
"function_result": lambda self, **kw: onto.function_result(**kw),
|
|
94
|
+
},
|
|
95
|
+
)
|
|
96
|
+
p = _Ports()
|
|
97
|
+
p.sql = s.sql
|
|
98
|
+
return _ontology_fn_body(p)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""设备运营总览 equip_ops.fn.get_summary
|
|
2
|
+
|
|
3
|
+
参数:start_date, end_date, plant_id(可选)
|
|
4
|
+
返回:equipment_count, avg_availability, avg_oee, total_runtime_hours,
|
|
5
|
+
total_unplanned_downtime_hours, total_output_qty, total_energy,
|
|
6
|
+
energy_per_output, downtime_event_count
|
|
7
|
+
|
|
8
|
+
发布:
|
|
9
|
+
dazi onto script publish 项目/DAZI_TEST/本体/ontos/设备运营/functions/equip_ops_fn_get_summary.py \
|
|
10
|
+
--space space_cate_test01 --register-function-id equip_ops.fn.get_summary
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
TEST_ARGUMENTS = {
|
|
14
|
+
"v": 1,
|
|
15
|
+
"arguments": {"start_date": "2025-01-01", "end_date": "2026-06-30"},
|
|
16
|
+
"object_type_code": "EquipmentAnalysis",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _build_ops_where(start_date, end_date, plant_id=None):
|
|
21
|
+
clauses = []
|
|
22
|
+
if start_date and end_date:
|
|
23
|
+
clauses.append(f"calendar_date >= '{start_date}' AND calendar_date <= '{end_date}'")
|
|
24
|
+
if plant_id:
|
|
25
|
+
clauses.append(f"plant_id = '{plant_id}'")
|
|
26
|
+
return ("WHERE " + " AND ".join(clauses)) if clauses else ""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _build_downtime_where(start_date, end_date, plant_id=None):
|
|
30
|
+
clauses = []
|
|
31
|
+
if start_date and end_date:
|
|
32
|
+
clauses.append(
|
|
33
|
+
f"toDate(start_time) >= '{start_date}' AND toDate(start_time) <= '{end_date}'"
|
|
34
|
+
)
|
|
35
|
+
if plant_id:
|
|
36
|
+
clauses.append(f"plant_id = '{plant_id}'")
|
|
37
|
+
return ("WHERE " + " AND ".join(clauses)) if clauses else ""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _calc_oee_from_sums(row):
|
|
41
|
+
sum_runtime = float(row.get("sum_runtime_min") or 0)
|
|
42
|
+
sum_available = float(row.get("sum_available_min") or 0)
|
|
43
|
+
sum_actual = float(row.get("sum_actual_output") or 0)
|
|
44
|
+
sum_qualified = float(row.get("sum_qualified_output") or 0)
|
|
45
|
+
sum_theoretical = float(row.get("sum_theoretical_output") or 0)
|
|
46
|
+
availability = sum_runtime / sum_available if sum_available > 0 else 0.0
|
|
47
|
+
quality = sum_qualified / sum_actual if sum_actual > 0 else 0.0
|
|
48
|
+
performance = sum_actual / sum_theoretical if sum_theoretical > 0 else 0.0
|
|
49
|
+
oee = availability * performance * quality
|
|
50
|
+
return round(availability, 4), round(oee, 4)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _ontology_fn_body(p):
|
|
54
|
+
params = dict(p.get_params() or {})
|
|
55
|
+
start_date = params.get("start_date", "")
|
|
56
|
+
end_date = params.get("end_date", "")
|
|
57
|
+
plant_id = params.get("plant_id") or None
|
|
58
|
+
where_clause = _build_ops_where(start_date, end_date, plant_id)
|
|
59
|
+
|
|
60
|
+
sql = f"""
|
|
61
|
+
SELECT
|
|
62
|
+
uniq(equipment_id) AS equipment_count,
|
|
63
|
+
sum(runtime_min) AS sum_runtime_min,
|
|
64
|
+
sum(calendar_minutes - planned_downtime_min) AS sum_available_min,
|
|
65
|
+
sum(actual_output_qty) AS sum_actual_output,
|
|
66
|
+
sum(qualified_output_qty) AS sum_qualified_output,
|
|
67
|
+
sumIf(runtime_min * ideal_cycle_rate, runtime_min > 0) AS sum_theoretical_output,
|
|
68
|
+
sum(unplanned_downtime_min) AS sum_unplanned_downtime_min,
|
|
69
|
+
sum(energy_consumption) AS sum_energy
|
|
70
|
+
FROM fact_equipment_daily_ops
|
|
71
|
+
{where_clause}
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
rows = p.sql.query(sql)
|
|
75
|
+
row = rows[0] if rows else {}
|
|
76
|
+
avg_availability, avg_oee = _calc_oee_from_sums(row)
|
|
77
|
+
|
|
78
|
+
sum_runtime = float(row.get("sum_runtime_min") or 0)
|
|
79
|
+
sum_actual = float(row.get("sum_actual_output") or 0)
|
|
80
|
+
sum_energy = float(row.get("sum_energy") or 0)
|
|
81
|
+
energy_per_output = sum_energy / sum_actual if sum_actual > 0 else 0.0
|
|
82
|
+
|
|
83
|
+
dt_where = _build_downtime_where(start_date, end_date, plant_id)
|
|
84
|
+
dt_sql = f"SELECT count() AS event_count FROM fact_downtime_event {dt_where}"
|
|
85
|
+
dt_rows = p.sql.query(dt_sql)
|
|
86
|
+
downtime_event_count = int((dt_rows[0] if dt_rows else {}).get("event_count") or 0)
|
|
87
|
+
|
|
88
|
+
data = [{
|
|
89
|
+
"equipment_count": int(row.get("equipment_count") or 0),
|
|
90
|
+
"avg_availability": avg_availability,
|
|
91
|
+
"avg_oee": avg_oee,
|
|
92
|
+
"total_runtime_hours": round(sum_runtime / 60.0, 2),
|
|
93
|
+
"total_unplanned_downtime_hours": round(
|
|
94
|
+
float(row.get("sum_unplanned_downtime_min") or 0) / 60.0, 2
|
|
95
|
+
),
|
|
96
|
+
"total_output_qty": round(sum_actual, 2),
|
|
97
|
+
"total_energy": round(sum_energy, 2),
|
|
98
|
+
"energy_per_output": round(energy_per_output, 4),
|
|
99
|
+
"downtime_event_count": downtime_event_count,
|
|
100
|
+
}]
|
|
101
|
+
|
|
102
|
+
return p.function_result(
|
|
103
|
+
columns=[
|
|
104
|
+
"equipment_count", "avg_availability", "avg_oee", "total_runtime_hours",
|
|
105
|
+
"total_unplanned_downtime_hours", "total_output_qty", "total_energy",
|
|
106
|
+
"energy_per_output", "downtime_event_count",
|
|
107
|
+
],
|
|
108
|
+
data=data,
|
|
109
|
+
row_count=1,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def main():
|
|
114
|
+
s = space.get(ctx.space_id or "")
|
|
115
|
+
_Ports = type(
|
|
116
|
+
"_Ports",
|
|
117
|
+
(),
|
|
118
|
+
{
|
|
119
|
+
"get_params": lambda self: dict(ctx.params or {}),
|
|
120
|
+
"function_result": lambda self, **kw: onto.function_result(**kw),
|
|
121
|
+
},
|
|
122
|
+
)
|
|
123
|
+
p = _Ports()
|
|
124
|
+
p.sql = s.sql
|
|
125
|
+
return _ontology_fn_body(p)
|