7.1 KiB
account_resource — 账号资源模块
模块定位
账号类资源的规格 / 权益配额 / 定价映射模块,宿主为 pipeline-app(也可装 sage)。参照 llmage 资源模块范式:
llmage: llm(主表) → llm_api_map(llmid×apiname→ppid) → llmusage(计费六件套)
account_resource: acctres_spec → acctres_pricing_map(spec×charge_mode→ppid) → acctres_usage
账号按「计费方式」挂价:charge_mode = trial(试用)/ month(月付)/ year(年付)。RESOURCE_TYPE = 'account_spec'(product_resource.resource_type 用这个值)。业务口径:账号产品免费管并发(试用/月租/年租三档权益:工作空间数、赠送容量、并发任务数、GPU、成员数上限)。
宿主集成:
from account_resource.init import load_account_resource
load_account_resource()
表清单(models/*.json,共 3 张)
| 表 | 用途 | 关键字段 |
|---|---|---|
acctres_spec |
账号规格(资源主表) | id(pk32), spec_code(唯一64), spec_name, spec_type(trial/standard), workspace_max(可建工作空间数), workspace_gb(赠送容量GB), concurrent_task(并发任务数), gpu_allowed('0'/'1'), member_max, privilege_json(其他权益JSON), sort_order, status(active) |
acctres_pricing_map |
规格×计费方式 → 定价项目 | spec_id, charge_mode(唯一键 spec_id+charge_mode), charge_unit(次/月/年), valid_days(7/30/365), ppid(→pricing_program), is_default('1'=缺省方式), status |
acctres_usage |
账号资源用量(计费落账凭证) | spec_id, charge_mode, subscription_id(订购ID), userid/userorgid, use_date/use_time, period_start/end, quantity, usages(JSON), transno, amount+amount_currency+amount_base, cost+cost_currency+cost_base, discount_rate, accounting_status(pending→accounted), org_id |
种子数据 init/data.json:3 条规格(ACC-TRIAL-7D / ACC-MONTHLY / ACC-YEARLY)+ 3 条定价映射(trial/month/year,各 is_default='1')。种子 ppid 为空串——建好 pricing_program 后必须回填,否则计费金额记 0。
对外 API(load_account_resource() 注册到 ServerEnv)
# 规格 CRUD
env.acctres_spec_list(ns) # ns: {status, spec_type}
env.acctres_spec_create(data) / acctres_spec_update(data) / acctres_spec_delete(data)
env.get_account_spec(spec_id_or_code) # id 或 spec_code 均可
env.get_account_privileges(spec_id_or_code) # → {workspace_max, workspace_gb, concurrent_task,
# gpu_allowed(bool), member_max, **privilege_json}
# 定价映射 CRUD
env.acctres_pricing_map_list(ns) # ns: {spec_id};LEFT JOIN 带出 spec_code/spec_name
env.acctres_pricing_map_create/update/delete(data)
env.get_account_ppid(spec_id_or_code, charge_mode=None) # charge_mode空→取is_default='1'
env.account_charging(spec_id_or_code, charge_mode, userid, userorgid,
subscription_id='', quantity=1, usages=None,
period_start=None, period_end=None, discount_rate=None)
# 解析ppid → env.buffered_charging(ppid, usages) → 原价×discount_rate
# → 写 acctres_usage(accounting_status='pending'),返回 usage dict
# 记账对接
env.get_accounting_acctres_usages(limit=200) # pending 用量,供 accounting 出账扫描
env.mark_acctres_accounted(usage_id, status='accounted')
另有 resolve_ppid(resource_ref_id, ctx)(ctx: {'charge_mode': ...})作为统一定价解析器注册:优先 env.register_resource_pricing_resolver('account_spec', resolve_ppid);产品层未加载时兜底暂存到 env._resource_pricing_resolvers。
页面/CRUD(json/*.json)
json/acctres_spec.json、acctres_pricing_map.json、acctres_usage.json 是 xls2ui 格式的 Bricks CRUD 表定义(editable 指向 ./add_*.dspy、./update_*.dspy、./delete_*.dspy——这些 dspy 端点不在本仓库,由宿主 wwwroot 提供)。scripts/load_path.py 注册 RBAC 路径(全部 logined):/account_resource、/account_resource/{acctres_spec,acctres_pricing_map,acctres_usage}/index.ui。宿主 load_path.sh 自动扫描 pkgs/*/scripts/load_path.py。
与产品/计费链路的集成关系
- product_management:
load_account_resource()末尾把env.product_interface设为本模块product_interface.py的接口字典(module_name / get_product_display / check_product_availability / check_product_consumable / execute_product_service(_stream) / calculate_product_cost / load_product_category_product)。resource_ref_id = acctres_spec.id(产品表存这个)。load_product_category_product(parent_category_id):导出「账号服务」类别 + 每规格一条 product_type='account' 产品,供产品导入。execute_product_service(...):request_data 必须带charge_mode,内部调account_charging落 usage,返回entitlement(duration_days: trial=7/month=30/year=365 + 各项配额),供产品层写 product_subscription。calculate_product_cost(resource_ref_id, usage_data, user_org_id=None):只算原价(buffered_charging 求和,discount 恒 1.0);客户/分销商折扣由产品层 product_management.core 按 product_id 精确计算(commitf2972db特意去掉了资源层折扣)。
- accounting(计费落账链):
account_charging写 acctres_usage(pending) → 产品层*_resource_accounting(usage_record)按 spec_id→product_id → product_accounting_generic/calculate_product_cost → biz_order/biz_orderdetail → consume_accounting 复式记账(acc_balance/acc_detail/bill_detail)→mark_acctres_accounted置 accounted。前置条件:客户已开户(openCustomerAccounts)且余额充足,否则 AccountIdNone/AccountOverDraw。详见 product-billing-accounting-chain 技能。 - 定价引擎(pricing):铁律——出账用
env.buffered_charging(ppid, data)两参、返回价格对象列表,金额sum(getattr(p,'amount',0) for p in prices);用三参pricing_program_charging会报缺参且金额静默记 0(commit3d5fb2c已修)。
部署注意事项
- 库名:一律
env.get_module_dbname('account_resource')(pipeline-app 返回 'pipeline'),禁写死 'sage'/'pipeline'。 - 建表:models/*.json 交宿主建表流程;accounting 相关表幂等不 DROP,product_management 在 TABLE_MODULES 会 DROP 重建——生产库勿跑完整 create_tables.py。
- 种子导入:init/data.json 由宿主 import_init 导入;导完必须回填 ppid(先建 pricing_program + pricing_program_timing.pricing_data)。
- RBAC:部署后在宿主根目录执行
py3/bin/python pkgs/account_resource/scripts/load_path.py。 - 依赖:sqlor、bricks_for_python(pyproject),运行时依赖宿主提供 ahserver/appPublic/pricing/product_management。
- i18n/{zh,en,jp,ko}/msg.txt 已备好词条(账号规格/计费方式/试用/月租/年租等)。
init.py尾部的from .product_interface import load_product_category_product是刻意放在所有函数定义之后的延迟 import(避免与 product_interface 循环导入),改代码时勿上移。