@dazitech/cli 3.0.8 → 3.1.0
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 +1 -1
- package/dist/clis/dazi-flow.js +1 -1
- package/dist/clis/dazi-onto.js +7 -2
- package/dist/clis/dazi.js +1 -1
- package/dist/docs/flow/flow-project-guide.md +1 -1
- package/dist/docs/guides/troubleshooting.md +12 -1
- package/dist/docs/index.json +21 -2
- package/dist/docs/onto/dazi_script_sdk_reference.md +246 -178
- package/dist/docs/onto/function-guide.md +123 -95
- 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 -0
- 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 +402 -0
- 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 +242 -0
- 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 +339 -249
- package/dist/docs/onto//346/234/254/344/275/223/350/247/204/345/210/222/346/214/207/345/215/227.md +304 -173
- 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 +242 -0
- package/dist/docs/onto//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 +361 -238
- package/dist/docs/onto//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 +385 -300
- package/dist/examples/index.json +22 -16
- package/dist/examples/onto/README.md +13 -5
- package/dist/examples/onto/_templates/ontology_function_template.py +50 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/profit_fn_account_breakdown.py +62 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/profit_fn_budget_vs_actual.py +69 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/profit_fn_cost_center_profit.py +64 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/profit_fn_get_summary.py +61 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/profit_fn_mom_analysis.py +82 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/profit_fn_top_accounts.py +61 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/profit_fn_yoy_analysis.py +79 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/save_test_arguments.ps1 +38 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/test_arguments/profit.fn.account_breakdown.json +1 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/test_arguments/profit.fn.budget_vs_actual.json +1 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/test_arguments/profit.fn.cost_center_profit.json +1 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/test_arguments/profit.fn.get_summary.json +1 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/test_arguments/profit.fn.mom_analysis.json +1 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/test_arguments/profit.fn.top_accounts.json +1 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/functions/test_arguments/profit.fn.yoy_analysis.json +1 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/setup/profit_category_mount.py +85 -0
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/setup/profit_ontology_init.py +169 -74
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/setup/profit_seed_data.py +16 -13
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/sales_fn_channel_mix.py +19 -16
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/sales_fn_customer_segmentation.py +48 -50
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/sales_fn_get_summary.py +3 -6
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/sales_fn_mom_analysis.py +11 -12
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/sales_fn_region_breakdown.py +6 -7
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/sales_fn_top_products.py +5 -8
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/sales_fn_yoy_analysis.py +3 -6
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/save_test_arguments.ps1 +32 -19
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/test_arguments/sales.fn.channel_mix.json +3 -6
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/test_arguments/sales.fn.customer_segmentation.json +2 -7
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/test_arguments/sales.fn.get_summary.json +2 -5
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/test_arguments/sales.fn.mom_analysis.json +2 -5
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/test_arguments/sales.fn.region_breakdown.json +2 -5
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/test_arguments/sales.fn.top_products.json +2 -7
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/test_arguments/sales.fn.yoy_analysis.json +2 -5
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/setup/sales_category_mount.py +82 -0
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/setup/sales_ontology_init.py +240 -155
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/setup/sales_seed_data.py +59 -20
- package/dist/prompts/index.json +8 -1
- package/dist/prompts/onto/function-design.md +73 -53
- package/dist/prompts/onto/planning-design.md +104 -0
- package/dist/prompts/onto/script-publish-run.md +229 -194
- package/package.json +1 -1
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/profit_fn_account_breakdown.py +0 -99
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/profit_fn_budget_vs_actual.py +0 -116
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/profit_fn_cost_center_profit.py +0 -85
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/profit_fn_get_summary.py +0 -76
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/profit_fn_mom_analysis.py +0 -86
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/profit_fn_top_accounts.py +0 -103
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/profit_fn_yoy_analysis.py +0 -86
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/save_test_arguments.ps1 +0 -27
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/test_arguments/profit.fn.account_breakdown.json +0 -10
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/test_arguments/profit.fn.budget_vs_actual.json +0 -10
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/test_arguments/profit.fn.cost_center_profit.json +0 -9
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/test_arguments/profit.fn.get_summary.json +0 -9
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/test_arguments/profit.fn.mom_analysis.json +0 -9
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/test_arguments/profit.fn.top_accounts.json +0 -11
- package/dist/examples/onto//345/210/251/346/266/246/347/244/272/344/276/213/function/test_arguments/profit.fn.yoy_analysis.json +0 -9
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/functions/README.md +0 -25
- package/dist/examples/onto//351/224/200/345/224/256/347/244/272/344/276/213/setup/README.md +0 -5
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""同比分析函数
|
|
2
|
+
|
|
3
|
+
功能:对比当期与去年同期的利润指标变化
|
|
4
|
+
参数:start_date, end_date
|
|
5
|
+
|
|
6
|
+
放置:项目/DAZI_TEST/本体/ontos/利润分析示例/functions/profit_fn_yoy_analysis.py
|
|
7
|
+
发布:dazi onto script publish 项目/DAZI_TEST/本体/ontos/利润分析示例/functions/profit_fn_yoy_analysis.py --space space__misc_01 --register-function-id profit.fn.yoy_analysis
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from datetime import datetime, timedelta
|
|
11
|
+
import json
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _ontology_fn_body(p):
|
|
15
|
+
start_date = p.get("start_date", "2025-01-01")
|
|
16
|
+
end_date = p.get("end_date", datetime.now().strftime("%Y-%m-%d"))
|
|
17
|
+
|
|
18
|
+
start_dt = datetime.strptime(start_date, "%Y-%m-%d")
|
|
19
|
+
end_dt = datetime.strptime(end_date, "%Y-%m-%d")
|
|
20
|
+
|
|
21
|
+
last_year_start = (start_dt - timedelta(days=365)).strftime("%Y-%m-%d")
|
|
22
|
+
last_year_end = (end_dt - timedelta(days=365)).strftime("%Y-%m-%d")
|
|
23
|
+
|
|
24
|
+
output.print(f"当期: {start_date} ~ {end_date}")
|
|
25
|
+
output.print(f"去年同期: {last_year_start} ~ {last_year_end}")
|
|
26
|
+
|
|
27
|
+
def get_period_data(sd, ed):
|
|
28
|
+
sql = """
|
|
29
|
+
SELECT
|
|
30
|
+
sumIf(amount_signed, account_type='收入') as revenue,
|
|
31
|
+
sumIf(amount_signed, account_type='成本') as cost,
|
|
32
|
+
sumIf(amount_signed, account_type='费用') as expense
|
|
33
|
+
FROM fact_gl_journal_entry
|
|
34
|
+
WHERE posting_date >= '{sd}' AND posting_date <= '{ed}'
|
|
35
|
+
""".format(sd=sd, ed=ed)
|
|
36
|
+
result = p.space.sql.query_one(sql)
|
|
37
|
+
return {
|
|
38
|
+
"revenue": result.get("revenue", 0) or 0,
|
|
39
|
+
"cost": result.get("cost", 0) or 0,
|
|
40
|
+
"expense": result.get("expense", 0) or 0,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
current = get_period_data(start_date, end_date)
|
|
44
|
+
last_year = get_period_data(last_year_start, last_year_end)
|
|
45
|
+
|
|
46
|
+
current_profit = current["revenue"] - current["cost"] - current["expense"]
|
|
47
|
+
last_year_profit = last_year["revenue"] - last_year["cost"] - last_year["expense"]
|
|
48
|
+
|
|
49
|
+
def calc_yoy(current, last):
|
|
50
|
+
if last == 0:
|
|
51
|
+
return 0 if current == 0 else None
|
|
52
|
+
return (current - last) / last
|
|
53
|
+
|
|
54
|
+
result = {
|
|
55
|
+
"period": f"{start_date} ~ {end_date}",
|
|
56
|
+
"last_year_period": f"{last_year_start} ~ {last_year_end}",
|
|
57
|
+
"current": {
|
|
58
|
+
"revenue": round(current["revenue"], 2),
|
|
59
|
+
"cost": round(current["cost"], 2),
|
|
60
|
+
"expense": round(current["expense"], 2),
|
|
61
|
+
"operating_profit": round(current_profit, 2),
|
|
62
|
+
},
|
|
63
|
+
"last_year": {
|
|
64
|
+
"revenue": round(last_year["revenue"], 2),
|
|
65
|
+
"cost": round(last_year["cost"], 2),
|
|
66
|
+
"expense": round(last_year["expense"], 2),
|
|
67
|
+
"operating_profit": round(last_year_profit, 2),
|
|
68
|
+
},
|
|
69
|
+
"yoy": {
|
|
70
|
+
"revenue": round(calc_yoy(current["revenue"], last_year["revenue"]), 4) if calc_yoy(current["revenue"], last_year["revenue"]) is not None else None,
|
|
71
|
+
"cost": round(calc_yoy(current["cost"], last_year["cost"]), 4) if calc_yoy(current["cost"], last_year["cost"]) is not None else None,
|
|
72
|
+
"expense": round(calc_yoy(current["expense"], last_year["expense"]), 4) if calc_yoy(current["expense"], last_year["expense"]) is not None else None,
|
|
73
|
+
"operating_profit": round(calc_yoy(current_profit, last_year_profit), 4) if calc_yoy(current_profit, last_year_profit) is not None else None,
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
p.function_result(result)
|
|
78
|
+
|
|
79
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# save_test_arguments.ps1
|
|
2
|
+
# 批量保存各函数的 test_arguments
|
|
3
|
+
# 用法:在 dazi-work 根目录执行 .\项目\DAZI_TEST\本体\ontos\利润分析示例\functions\save_test_arguments.ps1
|
|
4
|
+
|
|
5
|
+
$spaceId = "space__misc_01"
|
|
6
|
+
$itemPath = "项目/DAZI_TEST/本体/ontos/利润分析示例/functions"
|
|
7
|
+
|
|
8
|
+
$functions = @(
|
|
9
|
+
@{fn_id="profit.fn.get_summary"; file="profit.fn.get_summary.json"},
|
|
10
|
+
@{fn_id="profit.fn.yoy_analysis"; file="profit.fn.yoy_analysis.json"},
|
|
11
|
+
@{fn_id="profit.fn.mom_analysis"; file="profit.fn.mom_analysis.json"},
|
|
12
|
+
@{fn_id="profit.fn.budget_vs_actual"; file="profit.fn.budget_vs_actual.json"},
|
|
13
|
+
@{fn_id="profit.fn.account_breakdown"; file="profit.fn.account_breakdown.json"},
|
|
14
|
+
@{fn_id="profit.fn.cost_center_profit"; file="profit.fn.cost_center_profit.json"},
|
|
15
|
+
@{fn_id="profit.fn.top_accounts"; file="profit.fn.top_accounts.json"}
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
Write-Host "获取函数列表..."
|
|
19
|
+
$fnList = & dazi onto function list --space $spaceId 2>$null
|
|
20
|
+
|
|
21
|
+
foreach ($fn in $functions) {
|
|
22
|
+
$fnId = $fn.fn_id
|
|
23
|
+
$fileName = $fn.file
|
|
24
|
+
$jsonPath = "$PSScriptRoot/test_arguments/$fileName"
|
|
25
|
+
|
|
26
|
+
$ofnId = $fnList | Where-Object { $_ -match $fnId } | ForEach-Object {
|
|
27
|
+
if ($_ -match 'id:\s*(\S+)') { $matches[1] }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if ($ofnId) {
|
|
31
|
+
Write-Host "保存 $fnId (ofnId=$ofnId)..."
|
|
32
|
+
& dazi onto function save-test-arguments $ofnId --space $spaceId --arguments-json-file $jsonPath
|
|
33
|
+
} else {
|
|
34
|
+
Write-Host "函数 $fnId 未找到,请先发布函数"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
Write-Host "完成"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"v":1,"meta":{"last_source":"admin_panel","last_saved_at":"2026-06-06T01:00:00.000000+00:00","last_input_shape":"json"},"arguments":{"start_date":"2025-01-01","end_date":"2026-06-30","account_type":"收入"},"object_type_code":"Account"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"v":1,"meta":{"last_source":"admin_panel","last_saved_at":"2026-06-06T01:00:00.000000+00:00","last_input_shape":"json"},"arguments":{"start_date":"2025-01-01","end_date":"2026-06-30"},"object_type_code":"BudgetAnalysis"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"v":1,"meta":{"last_source":"admin_panel","last_saved_at":"2026-06-06T01:00:00.000000+00:00","last_input_shape":"json"},"arguments":{"start_date":"2025-01-01","end_date":"2026-06-30"},"object_type_code":"CostCenter"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"v":1,"meta":{"last_source":"admin_panel","last_saved_at":"2026-06-06T01:00:00.000000+00:00","last_input_shape":"json"},"arguments":{"start_date":"2025-01-01","end_date":"2026-06-30"},"object_type_code":"ProfitAnalysis"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"v":1,"meta":{"last_source":"admin_panel","last_saved_at":"2026-06-06T01:00:00.000000+00:00","last_input_shape":"json"},"arguments":{"start_date":"2025-01-01","end_date":"2026-06-30"},"object_type_code":"ProfitAnalysis"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"v":1,"meta":{"last_source":"admin_panel","last_saved_at":"2026-06-06T01:00:00.000000+00:00","last_input_shape":"json"},"arguments":{"start_date":"2025-01-01","end_date":"2026-06-30","limit":10},"object_type_code":"Account"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"v":1,"meta":{"last_source":"admin_panel","last_saved_at":"2026-06-06T01:00:00.000000+00:00","last_input_shape":"json"},"arguments":{"start_date":"2025-01-01","end_date":"2026-06-30"},"object_type_code":"ProfitAnalysis"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""利润分析本体 — 平台分类挂载(CATEGORY_REGISTRY)
|
|
2
|
+
|
|
3
|
+
与灌数脚本类似,**独立步骤、放在实施流程最后**:
|
|
4
|
+
init → seed → 发布全部函数 → **本脚本**。
|
|
5
|
+
|
|
6
|
+
放置:资源/examples/onto/利润示例/setup/profit_category_mount.py
|
|
7
|
+
发布:dazi onto script publish <item-path>/setup/profit_category_mount.py --space <space-id> --type setup
|
|
8
|
+
规划对照:资源/docs/onto/规划示例_利润分析本体方案.md 附录 B
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
|
|
13
|
+
# 与规划附录 B 一一对应;category 值必须是平台标准分类中文名
|
|
14
|
+
CATEGORY_REGISTRY = {
|
|
15
|
+
"table": {
|
|
16
|
+
"维度表": ["dim_account", "dim_cost_center"],
|
|
17
|
+
"事实表": ["fact_gl_journal_entry", "fact_budget_entry"],
|
|
18
|
+
},
|
|
19
|
+
"cube": {
|
|
20
|
+
"流程型": ["ActualCube", "BudgetCube"],
|
|
21
|
+
"主体型": ["AccountActualCube", "CostCenterActualCube", "TimeActualCube"],
|
|
22
|
+
},
|
|
23
|
+
"object": {
|
|
24
|
+
"主数据": ["Account", "CostCenter"],
|
|
25
|
+
"事务": ["JournalEntry", "BudgetLine"],
|
|
26
|
+
"分析": ["ProfitAnalysis", "BudgetAnalysis"],
|
|
27
|
+
},
|
|
28
|
+
"relation": {
|
|
29
|
+
"时间关联": [
|
|
30
|
+
("fact_gl_journal_entry", "dim_date"),
|
|
31
|
+
("fact_budget_entry", "dim_date"),
|
|
32
|
+
],
|
|
33
|
+
"主数据关联": [
|
|
34
|
+
("fact_gl_journal_entry", "dim_account"),
|
|
35
|
+
("fact_gl_journal_entry", "dim_cost_center"),
|
|
36
|
+
("fact_budget_entry", "dim_account"),
|
|
37
|
+
("fact_budget_entry", "dim_cost_center"),
|
|
38
|
+
],
|
|
39
|
+
"层级自关联": [("dim_account", "dim_account")],
|
|
40
|
+
},
|
|
41
|
+
"link": {
|
|
42
|
+
"归属关系": [
|
|
43
|
+
"entry_belongs_account",
|
|
44
|
+
"entry_belongs_cost_center",
|
|
45
|
+
"budget_for_account",
|
|
46
|
+
"budget_for_cost_center",
|
|
47
|
+
],
|
|
48
|
+
"分析归因": [
|
|
49
|
+
"analysis_by_account",
|
|
50
|
+
"analysis_by_cost_center",
|
|
51
|
+
"account_contributes_profit",
|
|
52
|
+
"cost_center_contributes_profit",
|
|
53
|
+
],
|
|
54
|
+
"层级关系": ["account_has_parent"],
|
|
55
|
+
"对比关系": ["budget_compared_to_actual"],
|
|
56
|
+
},
|
|
57
|
+
"function": {
|
|
58
|
+
"总览分析": ["profit.fn.get_summary"],
|
|
59
|
+
"趋势分析": ["profit.fn.yoy_analysis", "profit.fn.mom_analysis"],
|
|
60
|
+
"结构分析": ["profit.fn.account_breakdown", "profit.fn.top_accounts"],
|
|
61
|
+
"预实分析": ["profit.fn.budget_vs_actual"],
|
|
62
|
+
"组织分析": ["profit.fn.cost_center_profit"],
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def main():
|
|
68
|
+
space_id = "space__misc_01"
|
|
69
|
+
s = space.get(space_id)
|
|
70
|
+
|
|
71
|
+
output.print("=== 利润分析 — 平台分类挂载 ===")
|
|
72
|
+
output.print(f"空间: {space_id}")
|
|
73
|
+
|
|
74
|
+
cat_counts = s.categories.apply_registry(CATEGORY_REGISTRY, skip_missing=True)
|
|
75
|
+
for kind, cnt in cat_counts.items():
|
|
76
|
+
if cnt:
|
|
77
|
+
output.print(f"OK 分类[{kind}] 挂载 {cnt} 项")
|
|
78
|
+
|
|
79
|
+
summary = {
|
|
80
|
+
"ok": True,
|
|
81
|
+
"space_id": space_id,
|
|
82
|
+
"category_mounts": cat_counts,
|
|
83
|
+
}
|
|
84
|
+
output.success("平台分类挂载完成")
|
|
85
|
+
output.print("__JSON_SUMMARY__" + json.dumps(summary, ensure_ascii=True, default=str))
|
|
@@ -1,32 +1,122 @@
|
|
|
1
|
-
"""利润分析本体初始化脚本 —
|
|
1
|
+
"""利润分析本体初始化脚本 — space__misc_01
|
|
2
2
|
|
|
3
3
|
初始化内容:
|
|
4
|
-
1.
|
|
5
|
-
2.
|
|
6
|
-
3. 注册表间关系(
|
|
7
|
-
4. 注册
|
|
8
|
-
5. 定义对象类型(6
|
|
4
|
+
1. 创建物理表(科目表、成本中心维表、实际分录表、预算表)
|
|
5
|
+
2. 注册表到空间(含 display_name / description)
|
|
6
|
+
3. 注册表间关系(7条)
|
|
7
|
+
4. 注册Cube(5个)及派生度量
|
|
8
|
+
5. 定义对象类型(6种)、绑定数据源、属性、链接
|
|
9
9
|
6. 同步指标引用
|
|
10
|
+
7. 平台分类挂载见 profit_category_mount.py(init/seed/函数 publish 之后执行)
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
发布:dazi onto script publish
|
|
12
|
+
放置:资源/examples/onto/利润示例/setup/profit_ontology_init.py(复制到项目 ontos/<实现名>/setup/)
|
|
13
|
+
发布:dazi onto script publish <item-path>/setup/profit_ontology_init.py --space <space-id> --type setup
|
|
14
|
+
规划对照:资源/docs/onto/规划示例_利润分析本体方案.md
|
|
13
15
|
"""
|
|
14
16
|
|
|
15
17
|
import json
|
|
16
18
|
|
|
19
|
+
# 与 规划示例_利润分析本体方案.md §2.3、§3.x 对齐:display_name=侧栏显示名,description=业务说明
|
|
20
|
+
TABLE_REGISTRY = {
|
|
21
|
+
"dim_account": {
|
|
22
|
+
"display_name": "科目维表",
|
|
23
|
+
"description": "会计科目主数据",
|
|
24
|
+
"columns": [
|
|
25
|
+
{"name": "account_id", "display_name": "科目 ID", "description": "主键"},
|
|
26
|
+
{"name": "account_code", "display_name": "科目编码"},
|
|
27
|
+
{"name": "account_name", "display_name": "科目名称"},
|
|
28
|
+
{"name": "account_type", "display_name": "科目类型", "description": "资产/负债/权益/收入/成本/费用"},
|
|
29
|
+
{"name": "pl_category", "display_name": "损益大类"},
|
|
30
|
+
{"name": "parent_account_id", "display_name": "上级科目"},
|
|
31
|
+
{"name": "account_level", "display_name": "层级"},
|
|
32
|
+
{"name": "is_leaf", "display_name": "末级"},
|
|
33
|
+
{"name": "normal_balance", "display_name": "余额方向", "description": "借/贷"},
|
|
34
|
+
{"name": "status", "display_name": "状态", "description": "启用/停用"},
|
|
35
|
+
{"name": "created_at", "display_name": "创建时间"},
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
"dim_cost_center": {
|
|
39
|
+
"display_name": "成本中心维表",
|
|
40
|
+
"description": "组织/利润中心主数据",
|
|
41
|
+
"columns": [
|
|
42
|
+
{"name": "cost_center_id", "display_name": "成本中心 ID", "description": "主键"},
|
|
43
|
+
{"name": "cost_center_code", "display_name": "编码"},
|
|
44
|
+
{"name": "cost_center_name", "display_name": "名称"},
|
|
45
|
+
{"name": "department", "display_name": "部门"},
|
|
46
|
+
{"name": "company_code", "display_name": "公司代码"},
|
|
47
|
+
{"name": "profit_center", "display_name": "利润中心"},
|
|
48
|
+
{"name": "status", "display_name": "状态"},
|
|
49
|
+
{"name": "created_at", "display_name": "创建时间"},
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
"fact_gl_journal_entry": {
|
|
53
|
+
"display_name": "总账实际分录",
|
|
54
|
+
"description": "凭证行粒度损益流水",
|
|
55
|
+
"columns": [
|
|
56
|
+
{"name": "entry_id", "display_name": "凭证 ID"},
|
|
57
|
+
{"name": "line_id", "display_name": "凭证行 ID"},
|
|
58
|
+
{"name": "date_key", "display_name": "日期键", "description": "关联 dim_date,YYYYMMDD"},
|
|
59
|
+
{"name": "posting_date", "display_name": "记账日期"},
|
|
60
|
+
{"name": "fiscal_year", "display_name": "会计年度"},
|
|
61
|
+
{"name": "fiscal_period", "display_name": "会计期间"},
|
|
62
|
+
{"name": "account_id", "display_name": "科目 ID", "description": "关联 dim_account"},
|
|
63
|
+
{"name": "account_code", "display_name": "科目编码", "description": "冗余"},
|
|
64
|
+
{"name": "account_name", "display_name": "科目名称", "description": "冗余"},
|
|
65
|
+
{"name": "account_type", "display_name": "科目类型", "description": "冗余"},
|
|
66
|
+
{"name": "pl_category", "display_name": "损益大类", "description": "冗余"},
|
|
67
|
+
{"name": "account_level", "display_name": "科目层级", "description": "冗余"},
|
|
68
|
+
{"name": "cost_center_id", "display_name": "成本中心 ID", "description": "关联 dim_cost_center"},
|
|
69
|
+
{"name": "cost_center_name", "display_name": "成本中心", "description": "冗余"},
|
|
70
|
+
{"name": "department", "display_name": "部门", "description": "冗余"},
|
|
71
|
+
{"name": "profit_center", "display_name": "利润中心", "description": "冗余"},
|
|
72
|
+
{"name": "debit_amount", "display_name": "借方"},
|
|
73
|
+
{"name": "credit_amount", "display_name": "贷方"},
|
|
74
|
+
{"name": "amount_signed", "display_name": "损益金额", "description": "收入为正、成本费用为负"},
|
|
75
|
+
{"name": "currency", "display_name": "币种"},
|
|
76
|
+
{"name": "voucher_no", "display_name": "凭证号"},
|
|
77
|
+
{"name": "source_system", "display_name": "来源系统"},
|
|
78
|
+
{"name": "description", "display_name": "摘要", "description": "凭证行摘要文本"},
|
|
79
|
+
{"name": "created_at", "display_name": "创建时间"},
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
"fact_budget_entry": {
|
|
83
|
+
"display_name": "预算明细",
|
|
84
|
+
"description": "预算行粒度编制数据",
|
|
85
|
+
"columns": [
|
|
86
|
+
{"name": "budget_id", "display_name": "预算批次"},
|
|
87
|
+
{"name": "line_id", "display_name": "预算行 ID"},
|
|
88
|
+
{"name": "date_key", "display_name": "日期键", "description": "关联 dim_date"},
|
|
89
|
+
{"name": "budget_version", "display_name": "预算版本"},
|
|
90
|
+
{"name": "fiscal_year", "display_name": "预算年度"},
|
|
91
|
+
{"name": "fiscal_period", "display_name": "预算期间", "description": "1-12"},
|
|
92
|
+
{"name": "account_id", "display_name": "科目 ID", "description": "关联 dim_account"},
|
|
93
|
+
{"name": "account_code", "display_name": "科目编码", "description": "冗余"},
|
|
94
|
+
{"name": "account_name", "display_name": "科目名称", "description": "冗余"},
|
|
95
|
+
{"name": "account_type", "display_name": "科目类型", "description": "冗余"},
|
|
96
|
+
{"name": "pl_category", "display_name": "损益大类", "description": "冗余"},
|
|
97
|
+
{"name": "cost_center_id", "display_name": "成本中心 ID", "description": "关联 dim_cost_center"},
|
|
98
|
+
{"name": "cost_center_name", "display_name": "成本中心", "description": "冗余"},
|
|
99
|
+
{"name": "department", "display_name": "部门", "description": "冗余"},
|
|
100
|
+
{"name": "budget_amount", "display_name": "预算金额"},
|
|
101
|
+
{"name": "currency", "display_name": "币种"},
|
|
102
|
+
{"name": "status", "display_name": "状态", "description": "草稿/已发布"},
|
|
103
|
+
{"name": "created_at", "display_name": "创建时间"},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
}
|
|
17
107
|
|
|
18
108
|
def main():
|
|
19
|
-
space_id = "
|
|
109
|
+
space_id = "space__misc_01"
|
|
20
110
|
s = space.get(space_id)
|
|
21
111
|
|
|
22
112
|
output.print("=== 利润分析本体初始化 ===")
|
|
23
113
|
output.print(f"空间: {space_id}")
|
|
24
114
|
|
|
25
115
|
# 1. 创建物理表
|
|
26
|
-
output.print("\n[1/
|
|
116
|
+
output.print("\n[1/10] 创建物理表...")
|
|
27
117
|
|
|
28
118
|
s.sql.execute("""
|
|
29
|
-
CREATE TABLE IF NOT EXISTS
|
|
119
|
+
CREATE TABLE IF NOT EXISTS dim_account (
|
|
30
120
|
account_id String,
|
|
31
121
|
account_code String,
|
|
32
122
|
account_name String,
|
|
@@ -41,10 +131,10 @@ def main():
|
|
|
41
131
|
) ENGINE = MergeTree()
|
|
42
132
|
ORDER BY (account_code)
|
|
43
133
|
""")
|
|
44
|
-
output.print("OK
|
|
134
|
+
output.print("OK dim_account")
|
|
45
135
|
|
|
46
136
|
s.sql.execute("""
|
|
47
|
-
CREATE TABLE IF NOT EXISTS
|
|
137
|
+
CREATE TABLE IF NOT EXISTS dim_cost_center (
|
|
48
138
|
cost_center_id String,
|
|
49
139
|
cost_center_code String,
|
|
50
140
|
cost_center_name String,
|
|
@@ -56,12 +146,13 @@ def main():
|
|
|
56
146
|
) ENGINE = MergeTree()
|
|
57
147
|
ORDER BY (cost_center_id)
|
|
58
148
|
""")
|
|
59
|
-
output.print("OK
|
|
149
|
+
output.print("OK dim_cost_center")
|
|
60
150
|
|
|
61
151
|
s.sql.execute("""
|
|
62
|
-
CREATE TABLE IF NOT EXISTS
|
|
152
|
+
CREATE TABLE IF NOT EXISTS fact_gl_journal_entry (
|
|
63
153
|
entry_id String,
|
|
64
154
|
line_id String,
|
|
155
|
+
date_key Int32,
|
|
65
156
|
posting_date Date,
|
|
66
157
|
fiscal_year Int32,
|
|
67
158
|
fiscal_period Int32,
|
|
@@ -84,14 +175,15 @@ def main():
|
|
|
84
175
|
description String,
|
|
85
176
|
created_at DateTime DEFAULT now()
|
|
86
177
|
) ENGINE = MergeTree()
|
|
87
|
-
ORDER BY (
|
|
178
|
+
ORDER BY (date_key, entry_id, line_id)
|
|
88
179
|
""")
|
|
89
|
-
output.print("OK
|
|
180
|
+
output.print("OK fact_gl_journal_entry")
|
|
90
181
|
|
|
91
182
|
s.sql.execute("""
|
|
92
|
-
CREATE TABLE IF NOT EXISTS
|
|
183
|
+
CREATE TABLE IF NOT EXISTS fact_budget_entry (
|
|
93
184
|
budget_id String,
|
|
94
185
|
line_id String,
|
|
186
|
+
date_key Int32,
|
|
95
187
|
budget_version String,
|
|
96
188
|
fiscal_year Int32,
|
|
97
189
|
fiscal_period Int32,
|
|
@@ -110,88 +202,91 @@ def main():
|
|
|
110
202
|
) ENGINE = MergeTree()
|
|
111
203
|
ORDER BY (fiscal_year, fiscal_period, account_id, line_id)
|
|
112
204
|
""")
|
|
113
|
-
output.print("OK
|
|
114
|
-
|
|
115
|
-
# 2.
|
|
116
|
-
output.print("\n[2/
|
|
117
|
-
|
|
118
|
-
for
|
|
119
|
-
(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
output.print(f"OK {
|
|
205
|
+
output.print("OK fact_budget_entry")
|
|
206
|
+
|
|
207
|
+
# 2. 注册表(含 display_name / description)
|
|
208
|
+
output.print("\n[2/10] 注册表到空间...")
|
|
209
|
+
|
|
210
|
+
for tbl_name, meta in TABLE_REGISTRY.items():
|
|
211
|
+
s.tables.register_with_meta(
|
|
212
|
+
table_name=tbl_name,
|
|
213
|
+
display_name=meta["display_name"],
|
|
214
|
+
description=meta.get("description"),
|
|
215
|
+
columns=meta["columns"],
|
|
216
|
+
force_column_meta=True,
|
|
217
|
+
)
|
|
218
|
+
output.print(f"OK {tbl_name} ({meta['display_name']})")
|
|
127
219
|
|
|
128
220
|
# 3. 注册表间关系
|
|
129
|
-
output.print("\n[3/
|
|
221
|
+
output.print("\n[3/10] 注册表间关系...")
|
|
130
222
|
|
|
131
223
|
table_relationships = [
|
|
132
224
|
{
|
|
133
|
-
"from_table": "
|
|
134
|
-
"to_table": "
|
|
135
|
-
"join_sql": "
|
|
225
|
+
"from_table": "fact_gl_journal_entry",
|
|
226
|
+
"to_table": "dim_date",
|
|
227
|
+
"join_sql": "fact_gl_journal_entry.date_key = dim_date.date_key",
|
|
228
|
+
"join_keys": [{"from": "date_key", "to": "date_key"}],
|
|
229
|
+
"relationship_type": "many_to_one",
|
|
230
|
+
"description": "分录关联日历",
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"from_table": "fact_budget_entry",
|
|
234
|
+
"to_table": "dim_date",
|
|
235
|
+
"join_sql": "fact_budget_entry.date_key = dim_date.date_key",
|
|
236
|
+
"join_keys": [{"from": "date_key", "to": "date_key"}],
|
|
237
|
+
"relationship_type": "many_to_one",
|
|
238
|
+
"description": "预算关联日历",
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"from_table": "fact_gl_journal_entry",
|
|
242
|
+
"to_table": "dim_account",
|
|
243
|
+
"join_sql": "fact_gl_journal_entry.account_id = dim_account.account_id",
|
|
136
244
|
"join_keys": [{"from": "account_id", "to": "account_id"}],
|
|
137
245
|
"relationship_type": "many_to_one",
|
|
138
246
|
"description": "实际分录关联会计科目",
|
|
139
247
|
},
|
|
140
248
|
{
|
|
141
|
-
"from_table": "
|
|
142
|
-
"to_table": "
|
|
143
|
-
"join_sql": "
|
|
249
|
+
"from_table": "fact_gl_journal_entry",
|
|
250
|
+
"to_table": "dim_cost_center",
|
|
251
|
+
"join_sql": "fact_gl_journal_entry.cost_center_id = dim_cost_center.cost_center_id",
|
|
144
252
|
"join_keys": [{"from": "cost_center_id", "to": "cost_center_id"}],
|
|
145
253
|
"relationship_type": "many_to_one",
|
|
146
254
|
"description": "实际分录关联成本中心",
|
|
147
255
|
},
|
|
148
256
|
{
|
|
149
|
-
"from_table": "
|
|
150
|
-
"to_table": "
|
|
151
|
-
"join_sql": "
|
|
257
|
+
"from_table": "fact_budget_entry",
|
|
258
|
+
"to_table": "dim_account",
|
|
259
|
+
"join_sql": "fact_budget_entry.account_id = dim_account.account_id",
|
|
152
260
|
"join_keys": [{"from": "account_id", "to": "account_id"}],
|
|
153
261
|
"relationship_type": "many_to_one",
|
|
154
262
|
"description": "预算关联会计科目",
|
|
155
263
|
},
|
|
156
264
|
{
|
|
157
|
-
"from_table": "
|
|
158
|
-
"to_table": "
|
|
159
|
-
"join_sql": "
|
|
265
|
+
"from_table": "fact_budget_entry",
|
|
266
|
+
"to_table": "dim_cost_center",
|
|
267
|
+
"join_sql": "fact_budget_entry.cost_center_id = dim_cost_center.cost_center_id",
|
|
160
268
|
"join_keys": [{"from": "cost_center_id", "to": "cost_center_id"}],
|
|
161
269
|
"relationship_type": "many_to_one",
|
|
162
270
|
"description": "预算关联成本中心",
|
|
163
271
|
},
|
|
164
272
|
{
|
|
165
|
-
"from_table": "
|
|
166
|
-
"to_table": "
|
|
167
|
-
"join_sql": "
|
|
273
|
+
"from_table": "dim_account",
|
|
274
|
+
"to_table": "dim_account",
|
|
275
|
+
"join_sql": "dim_account.parent_account_id = dim_account.account_id",
|
|
168
276
|
"join_keys": [{"from": "parent_account_id", "to": "account_id"}],
|
|
169
277
|
"relationship_type": "many_to_one",
|
|
170
278
|
"description": "科目上级(树形)",
|
|
171
279
|
},
|
|
172
|
-
{
|
|
173
|
-
"from_table": "budget_entry",
|
|
174
|
-
"to_table": "actual_journal_entry",
|
|
175
|
-
"join_sql": "budget_entry.account_id = actual_journal_entry.account_id AND budget_entry.cost_center_id = actual_journal_entry.cost_center_id AND budget_entry.fiscal_year = actual_journal_entry.fiscal_year AND budget_entry.fiscal_period = actual_journal_entry.fiscal_period",
|
|
176
|
-
"join_keys": [
|
|
177
|
-
{"from": "account_id", "to": "account_id"},
|
|
178
|
-
{"from": "cost_center_id", "to": "cost_center_id"},
|
|
179
|
-
{"from": "fiscal_year", "to": "fiscal_year"},
|
|
180
|
-
{"from": "fiscal_period", "to": "fiscal_period"},
|
|
181
|
-
],
|
|
182
|
-
"relationship_type": "many_to_one",
|
|
183
|
-
"description": "预算与实际同维对齐",
|
|
184
|
-
},
|
|
185
280
|
]
|
|
186
281
|
for rel in table_relationships:
|
|
187
282
|
rid = s.tables.add_relationship(**rel)
|
|
188
|
-
output.print(f"OK {rel['from_table']} -> {rel['to_table']}
|
|
283
|
+
output.print(f"OK {rel['from_table']} -> {rel['to_table']}")
|
|
189
284
|
|
|
190
285
|
# 4. 注册 Cube
|
|
191
|
-
output.print("\n[4/
|
|
286
|
+
output.print("\n[4/10] 注册 Cube...")
|
|
192
287
|
|
|
193
|
-
actual = "
|
|
194
|
-
budget = "
|
|
288
|
+
actual = "fact_gl_journal_entry"
|
|
289
|
+
budget = "fact_budget_entry"
|
|
195
290
|
|
|
196
291
|
s.register_cube(
|
|
197
292
|
name="ActualCube",
|
|
@@ -206,6 +301,7 @@ def main():
|
|
|
206
301
|
dimensions=[
|
|
207
302
|
{"name": "entry_id", "col": "entry_id", "type": "string", "title": "凭证ID"},
|
|
208
303
|
{"name": "line_id", "col": "line_id", "type": "string", "title": "行ID"},
|
|
304
|
+
{"name": "date_key", "col": "date_key", "type": "int", "title": "日期键"},
|
|
209
305
|
{"name": "posting_date", "col": "posting_date", "type": "date", "title": "记账日期"},
|
|
210
306
|
{"name": "fiscal_year", "col": "fiscal_year", "type": "int", "title": "会计年度"},
|
|
211
307
|
{"name": "fiscal_period", "col": "fiscal_period", "type": "int", "title": "会计期间"},
|
|
@@ -294,17 +390,16 @@ def main():
|
|
|
294
390
|
{"name": "line_count", "col": "line_id", "agg": "count", "title": "分录行数"},
|
|
295
391
|
],
|
|
296
392
|
dimensions=[
|
|
393
|
+
{"name": "date_key", "col": "date_key", "type": "int", "title": "日期键"},
|
|
297
394
|
{"name": "posting_date", "col": "posting_date", "type": "date", "title": "记账日期"},
|
|
298
395
|
{"name": "fiscal_year", "col": "fiscal_year", "type": "int", "title": "会计年度"},
|
|
299
396
|
{"name": "fiscal_period", "col": "fiscal_period", "type": "int", "title": "会计期间"},
|
|
300
|
-
{"name": "year_month", "col": "posting_date", "type": "string", "title": "年月"},
|
|
301
|
-
{"name": "quarter", "col": "posting_date", "type": "string", "title": "季度"},
|
|
302
397
|
],
|
|
303
398
|
)
|
|
304
399
|
output.print("OK TimeActualCube")
|
|
305
400
|
|
|
306
401
|
# 5. 派生度量
|
|
307
|
-
output.print("\n[5/
|
|
402
|
+
output.print("\n[5/10] 配置派生度量...")
|
|
308
403
|
|
|
309
404
|
def _pl_measures(cube_name, full=False):
|
|
310
405
|
base = [
|
|
@@ -375,7 +470,7 @@ def main():
|
|
|
375
470
|
output.print("OK 派生度量")
|
|
376
471
|
|
|
377
472
|
# 6. 对象类型
|
|
378
|
-
output.print("\n[6/
|
|
473
|
+
output.print("\n[6/10] 定义对象类型...")
|
|
379
474
|
|
|
380
475
|
object_types = [
|
|
381
476
|
("Account", "会计科目", "会计科目业务对象"),
|
|
@@ -390,7 +485,7 @@ def main():
|
|
|
390
485
|
output.print(f"OK {code}")
|
|
391
486
|
|
|
392
487
|
# 7. 绑定数据源
|
|
393
|
-
output.print("\n[7/
|
|
488
|
+
output.print("\n[7/10] 绑定数据源...")
|
|
394
489
|
|
|
395
490
|
bindings = [
|
|
396
491
|
("Account", "AccountActualCube"),
|
|
@@ -405,7 +500,7 @@ def main():
|
|
|
405
500
|
output.print(f"OK {obj} -> {cube}")
|
|
406
501
|
|
|
407
502
|
# 8. 属性
|
|
408
|
-
output.print("\n[8/
|
|
503
|
+
output.print("\n[8/10] 定义属性...")
|
|
409
504
|
|
|
410
505
|
def define_props(obj_code, props):
|
|
411
506
|
for code, name, role, qn in props:
|
|
@@ -478,7 +573,7 @@ def main():
|
|
|
478
573
|
output.print("OK BudgetAnalysis 属性 (6)")
|
|
479
574
|
|
|
480
575
|
# 9. 链接类型
|
|
481
|
-
output.print("\n[9/
|
|
576
|
+
output.print("\n[9/10] 定义链接与同步指标...")
|
|
482
577
|
|
|
483
578
|
link_types = [
|
|
484
579
|
("entry_belongs_account", "分录归属科目", "JournalEntry", "Account", "分录行对应科目"),
|
|
@@ -509,7 +604,7 @@ def main():
|
|
|
509
604
|
"ok": True,
|
|
510
605
|
"space_id": space_id,
|
|
511
606
|
"tables": 4,
|
|
512
|
-
"table_relationships":
|
|
607
|
+
"table_relationships": 7,
|
|
513
608
|
"cubes": 5,
|
|
514
609
|
"object_types": 6,
|
|
515
610
|
"properties": 42,
|
|
@@ -518,4 +613,4 @@ def main():
|
|
|
518
613
|
|
|
519
614
|
output.print("\n=== 利润分析本体初始化完成 ===")
|
|
520
615
|
output.success("初始化成功")
|
|
521
|
-
output.print("__JSON_SUMMARY__" + json.dumps(summary, ensure_ascii=True, default=str))
|
|
616
|
+
output.print("__JSON_SUMMARY__" + json.dumps(summary, ensure_ascii=True, default=str))
|