diff --git a/build.sh b/build.sh index cc1bce4..30d8fb7 100644 --- a/build.sh +++ b/build.sh @@ -53,7 +53,7 @@ for mod in pipeline_core pipeline_ops pipeline_dist; do done # 5. Install business modules (clone external, local already in pkgs) -for mod in pipeline-sdlc showcase evaluate pipeline-service pipeline-task tenant app_audit product_management discount pricing unipay smssend; do +for mod in pipeline-sdlc showcase evaluate pipeline-service pipeline-task tenant app_audit product_management discount pricing unipay smssend accounting; do cd "$cdir/pkgs" if [ ! -d "$mod" ]; then git clone https://git.opencomputing.cn/yumoqing/$mod || echo "SKIP: $mod" @@ -62,7 +62,7 @@ for mod in pipeline-sdlc showcase evaluate pipeline-service pipeline-task tenant done # 6. pip install all modules from pkgs/(pipeline-service 是普通 install 非 editable,部署必 pull+pip install 都做) -for mod in pipeline_core pipeline_ops pipeline_dist pipeline-sdlc showcase pipeline-service tenant app_audit product_management discount pricing unipay smssend; do +for mod in pipeline_core pipeline_ops pipeline_dist pipeline-sdlc showcase pipeline-service tenant app_audit product_management discount pricing unipay smssend accounting; do if [ -d "pkgs/$mod" ]; then "$cdir/py3/bin/pip" install "pkgs/$mod/" 2>&1 | tail -1 fi @@ -89,7 +89,7 @@ if [ -d "pkgs/pipeline_core/skills_library" ]; then fi # 7. Regenerate CRUD from json for all pipeline modules -for mod in appbase pipeline_core pipeline_ops pipeline_dist pipeline-sdlc rbac dapi; do +for mod in appbase pipeline_core pipeline_ops pipeline_dist pipeline-sdlc rbac dapi accounting; do json_dir="pkgs/$mod/json" models_dir="pkgs/$mod/models" wwwroot_dir="pkgs/$mod/wwwroot" @@ -102,7 +102,7 @@ done # 8. Link module wwwroot directories (symlinks from pkgs/) -for mod in pipeline-sdlc showcase tenant pipeline_core pipeline_ops pipeline_dist appbase app_audit product_management discount pricing unipay rbac dapi; do +for mod in pipeline-sdlc showcase tenant pipeline_core pipeline_ops pipeline_dist appbase app_audit product_management discount pricing unipay rbac dapi accounting; do src="pkgs/$mod/wwwroot" dst="wwwroot/$mod" if [ -d "$src" ]; then @@ -200,5 +200,18 @@ else echo " WARN: scripts/import_rp.py not found" fi +# 11.5 汇率自动获取定时任务(每日 8:00 抓取中国银行外汇牌价) +# accounting 模块 fetch_forex_rates.dspy:USD/JPY/GBP → CNY,幂等写入 exchange_rate +if [ -f "$cdir/pkgs/accounting/wwwroot/api/fetch_forex_rates.dspy" ]; then + forex_cron="0 8 * * * curl -s http://localhost:9090/accounting/api/fetch_forex_rates.dspy" + cc=$(crontab -l 2>/dev/null || true) + if ! echo "$cc" | grep -Fq "fetch_forex_rates"; then + (echo "$cc"; echo "$forex_cron") | crontab - + echo " cron: 汇率任务已添加(每日 8:00)" + else + echo " cron: 汇率任务已存在,未重复添加" + fi +fi + chmod +x "$cdir/start.sh" "$cdir/stop.sh" 2>/dev/null || true echo "=== Build complete ===" diff --git a/conf/rp.json b/conf/rp.json index b39c7e7..320b70d 100644 --- a/conf/rp.json +++ b/conf/rp.json @@ -17,7 +17,8 @@ "/pricing/menu.ui", "/unipay/usermenu.ui", "/univer-office", - "/univer-office/**" + "/univer-office/**", + "/accounting/api/fetch_forex_rates.dspy" ], "logined": [ "/pipeline-sdlc", "/pipeline-sdlc/**", @@ -33,7 +34,8 @@ "/pipeline_dist", "/pipeline_dist/**", "/pipeline_task", "/pipeline_task/**", "/app_audit", "/app_audit/**", - "/office", "/office/**" + "/office", "/office/**", + "/accounting", "/accounting/**" ], "owner.superuser": [ "/rbac", "/rbac/**", diff --git a/scripts/create_tables.py b/scripts/create_tables.py index aa2b7ae..59142a1 100644 --- a/scripts/create_tables.py +++ b/scripts/create_tables.py @@ -23,7 +23,8 @@ TABLE_MODULES = ['product_management', 'discount', 'pricing', 'unipay', 'smssend # 幂等建表模块(不 DROP,用 IF NOT EXISTS,避免清空运行时数据如 llm/pipelines/skill_proposals/tasks 等) # appbase 也放这里:svgicon/appcodes/appcodes_kv/params 是系统级配置表,含种子数据,幂等建(params 另在下方手动 ensure 默认参数) # dapi 放这里:downapp/downapikey 是下位系统接入表,幂等建(不 DROP,避免误删已注册的下位系统) -IDEMPOTENT_MODULES = ['pipeline_core', 'pipeline-service', 'appbase', 'dapi'] +# accounting 放这里:subject/account_config/accounting_config 是记账配置,account/ledger 是运行时数据,幂等建(不 DROP) +IDEMPOTENT_MODULES = ['pipeline_core', 'pipeline-service', 'appbase', 'dapi', 'accounting'] # appbase 系统级配置表(幂等建表 + 默认参数,不 DROP 以免清空运行时数据) diff --git a/scripts/import_init.py b/scripts/import_init.py index 8eec5d0..0922242 100644 --- a/scripts/import_init.py +++ b/scripts/import_init.py @@ -29,6 +29,7 @@ INIT_MODULES = [ ('pipeline-sdlc', 'pkgs/pipeline-sdlc/init/data.json'), ('app_audit', 'pkgs/app_audit/init/data.json'), ('rbac', 'pkgs/rbac/init/data.json'), + ('accounting', 'pkgs/accounting/init/data.json'), ] @@ -117,7 +118,24 @@ async def main(): 'name': r.get('name', ''), }) total['roles'] += 1 - print(f'import_init: appcodes {total["appcodes"]}, appcodes_kv {total["appcodes_kv"]}, organization {total["organization"]}, roles {total["roles"]}') + # 记账配置表(accounting 模块:subject/account_config/accounting_config/currency/exchange_rate) + # 幂等按主键 id 检查,字段名与表结构一致 + for tbl, recs_data in [ + ('subject', data.get('subject', [])), + ('account_config', data.get('account_config', [])), + ('accounting_config', data.get('accounting_config', [])), + ('currency', data.get('currency', [])), + ('exchange_rate', data.get('exchange_rate', [])), + ]: + for rec in recs_data: + existing = await sor.R(tbl, {'id': rec.get('id')}) + if not existing: + # 去掉 None 值字段(DB 用 NULL 而非 None) + clean = {k: v for k, v in rec.items() if v is not None} + await sor.C(tbl, clean) + total[tbl] = total.get(tbl, 0) + 1 + summary = ' '.join(f'{k} {v}' for k, v in total.items()) + print(f'import_init: {summary}') if __name__ == '__main__':