fix(product): 账号/存储产品展示缺失——建树KeyError+幽灵列+IN占位符三处修复

根因链(2026-09-06):
1. core.get_category_tree 单遍建树隐含「父节点排序在子前」假设:
   子类别 sort_order=0 < 顶级 10/20,ORDER BY 后子先处理,
   parent['children'].append 时父未初始化 → KeyError → storefront 500
2. storefront get_products.dspy SELECT p.icon——product 表无 icon 列 → 1054
3. 同文件 IN 占位符 f'${key}$' 生成 $cid_0$(缺花括号)sqlor 不识别

配套:init/data.json resource_module 字典补 account_resource/storage_resource
(类别编辑下拉可选),product_type 字典对应项由测试库同步补充。

数据:测试库已建账号资源/存储资源顶级类别并执行导入
(账号3产品:试用7天/月租/年租;存储1产品:工作空间标准存储)。
This commit is contained in:
yumoqing 2026-09-06 14:03:44 +08:00
parent 8f3bd268ad
commit 275806c1cc
3 changed files with 15 additions and 5 deletions

View File

@ -126,7 +126,9 @@
{"id": "resource_module_llmage", "parentid": "resource_module", "k": "llmage", "v": "大模型管理"},
{"id": "resource_module_supplychain", "parentid": "resource_module", "k": "supplychain", "v": "供应链管理"},
{"id": "resource_module_pipeline_llm", "parentid": "resource_module", "k": "pipeline_llm", "v": "产线模型治理"}
{"id": "resource_module_pipeline_llm", "parentid": "resource_module", "k": "pipeline_llm", "v": "产线模型治理"},
{"id": "resource_module_account_resource", "parentid": "resource_module", "k": "account_resource", "v": "账号资源"},
{"id": "resource_module_storage_resource", "parentid": "resource_module", "k": "storage_resource", "v": "存储资源"}
],
"_note_product_category": "产品类别树由每个 reseller (org_id) 自行管理,不在 init/data.json 中预设全局数据。新机构注册时自动创建根类别。"
}

View File

@ -47,12 +47,18 @@ class ProductManager:
rows = rows or []
# Build tree
# 两遍建树2026-09-06 根治 KeyError先给全部节点初始化 children
# 再挂父子关系。单遍写法隐含「父节点排序在子节点前」的假设——
# ORDER BY sort_order ASC, name ASC 下子类别 sort_order 更小(如导入引擎
# 给子类别 0、顶级类别 10/20子先被处理父还未初始化 children
# → parent['children'].append 抛 KeyError → storefront 整页 500。
nodes = [dict(r) for r in rows]
for n in nodes:
n['children'] = []
node_map = {n['id']: n for n in nodes}
tree = []
for node in nodes:
node['children'] = []
parent_id = node.get('parent_id', '0')
if parent_id == '0' or parent_id not in node_map:
tree.append(node)

View File

@ -20,21 +20,23 @@ else:
queue.append(c.id)
# Build IN clause
# sqlor 占位符格式 ${name}$f-string 里花括号需转义,否则 ${key} 会被求值
param_keys = []
params = {'org_id': org_id}
for i, cid in enumerate(all_ids):
key = f'cid_{i}'
param_keys.append(f'${key}$')
param_keys.append('${' + key + '}$')
params[key] = cid
placeholders = ','.join(param_keys)
# f-string 里 sqlor 占位符须写成 ${{name}}$,否则 {name} 被 Python 求值
sql = f"""SELECT p.id, p.product_name, p.product_code, p.brief_intro,
p.product_type, p.price, p.currency, p.icon,
p.product_type, p.price, p.currency,
pc.name as category_name
FROM product p
LEFT JOIN product_category pc ON p.category_id = pc.id
WHERE p.category_id IN ({placeholders})
AND p.org_id = ${org_id}$
AND p.org_id = ${{org_id}}$
AND p.status = '1'
ORDER BY p.sort_order ASC, p.product_name ASC"""
params['org_id'] = org_id