Merge branch 'main' of git.opencomputing.cn:yumoqing/kboss
This commit is contained in:
commit
5ef36caa71
@ -1669,6 +1669,7 @@ CREATE TABLE `model_management` (
|
||||
`provider` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '厂商名称',
|
||||
`model_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '模型标识名',
|
||||
`display_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '展示名称',
|
||||
`model_logo` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '模型logo',
|
||||
`model_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '模型类型',
|
||||
`listing_status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '上架状态:0待上架 1已上架',
|
||||
`sort_order` int(11) NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前',
|
||||
|
||||
@ -1069,10 +1069,10 @@ async def finance_billing_overview(ns=None):
|
||||
include_sub = _parse_bool(ns.get('include_sub_reseller_customers'), True)
|
||||
only_accounted = _parse_bool(ns.get('only_accounted'), False)
|
||||
try:
|
||||
max_bills = int(ns.get('max_bills', 5000) or 5000)
|
||||
max_bills = int(ns.get('max_bills', 50000) or 50000)
|
||||
except (TypeError, ValueError):
|
||||
max_bills = 5000
|
||||
max_bills = max(100, min(max_bills, 20000))
|
||||
max_bills = 50000
|
||||
max_bills = max(100, min(max_bills, 200000))
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext(DBNAME) as sor:
|
||||
@ -1228,11 +1228,13 @@ async def finance_billing_overview(ns=None):
|
||||
return {'status': True, 'msg': 'ok', 'data': data}
|
||||
|
||||
|
||||
_report = params_kw.get('report') or params_kw.get('api') or 'order_list'
|
||||
# _report = params_kw.get('report') or params_kw.get('api') or 'order_list'
|
||||
_report = None
|
||||
if _report in ('overview', 'billing_overview', 'finance_billing_overview'):
|
||||
ret = await finance_billing_overview(params_kw)
|
||||
elif _report in ('detail', 'order_detail'):
|
||||
ret = await finance_order_report_detail(params_kw)
|
||||
else:
|
||||
ret = await finance_order_report(params_kw)
|
||||
return ret
|
||||
return ret
|
||||
1239
b/bill/finance_order_report_overview.dspy
Normal file
1239
b/bill/finance_order_report_overview.dspy
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
# model_management 可写入字段(不含 id、created_at、updated_at)
|
||||
_MODEL_FIELDS = (
|
||||
'llmid', 'provider', 'model_name', 'display_name', 'model_type',
|
||||
'llmid', 'provider', 'model_name', 'display_name', 'model_logo', 'model_type',
|
||||
'context_length', 'input_token_price', 'output_token_price',
|
||||
'cache_hit_input_price', 'billing_method', 'billing_unit',
|
||||
'capabilities', 'limitations', 'highlights', 'is_active',
|
||||
|
||||
@ -5,7 +5,7 @@ def _escape(value):
|
||||
|
||||
# 客户侧可见字段(不含 listing_status、is_active 等运营字段)
|
||||
_CUSTOMER_MODEL_COLUMNS = """
|
||||
id, llmid, provider, model_name, display_name, model_type,
|
||||
id, llmid, provider, model_name, display_name, model_logo, model_type,
|
||||
context_length, input_token_price, output_token_price,
|
||||
cache_hit_input_price, billing_method, billing_unit,
|
||||
capabilities, limitations, highlights, description, sort_order,is_active, experience
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# 可写入/更新的字段(不含 id、created_at、updated_at)
|
||||
_MODEL_FIELDS = (
|
||||
'llmid', 'provider', 'model_name', 'display_name', 'model_type',
|
||||
'llmid', 'provider', 'model_name', 'display_name', 'model_logo', 'model_type',
|
||||
'context_length', 'input_token_price', 'output_token_price',
|
||||
'cache_hit_input_price', 'billing_method', 'billing_unit',
|
||||
'capabilities', 'limitations', 'highlights', 'is_active',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# model_management 可写入字段(不含 id、created_at、updated_at)
|
||||
_MODEL_FIELDS = (
|
||||
'llmid', 'provider', 'model_name', 'display_name', 'model_type',
|
||||
'llmid', 'provider', 'model_name', 'display_name', 'model_logo', 'model_type',
|
||||
'context_length', 'input_token_price', 'output_token_price',
|
||||
'cache_hit_input_price', 'billing_method', 'billing_unit',
|
||||
'capabilities', 'limitations', 'highlights', 'is_active',
|
||||
|
||||
@ -1,3 +1,26 @@
|
||||
async def get_user_role(ns={}):
|
||||
sor = ns['sor']
|
||||
ns['del_flg'] = '0'
|
||||
res_role = await sor.R('userrole', ns)
|
||||
if res_role:
|
||||
user_role = res_role[0]
|
||||
else:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'userrole table, user id can not find...',
|
||||
}
|
||||
roleid = user_role.get('roleid')
|
||||
role_name = await sor.R('role', {'id': roleid})
|
||||
if role_name:
|
||||
role = role_name[0].get('role')
|
||||
else:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'role table, can not get role name',
|
||||
}
|
||||
return role
|
||||
|
||||
|
||||
def _escape(value):
|
||||
if value is None:
|
||||
return None
|
||||
@ -182,18 +205,74 @@ async def _enrich_usage_rows(sor, rows):
|
||||
return items
|
||||
|
||||
|
||||
async def _fetch_customer_users(sor, orgid, customerid=None):
|
||||
"""获取机构下客户及其用户映射。"""
|
||||
org_rows = await sor.R('organization', {'parentid': orgid, 'del_flg': '0'})
|
||||
if customerid:
|
||||
org_rows = [row for row in org_rows if row.get('id') == customerid]
|
||||
org_map = {row['id']: row for row in org_rows}
|
||||
async def _resolve_scope_orgid(sor, user_orgid, user_role):
|
||||
"""
|
||||
解析报表统计范围的机构 id。
|
||||
运营/运营管理员:users.orgid 即所在机构 id。
|
||||
其他管理员:users.orgid 为用户机构 id,所在机构为 organization.parentid。
|
||||
"""
|
||||
if user_role in ('运营', '运营管理员'):
|
||||
return user_orgid
|
||||
org_rows = await sor.R('organization', {'id': user_orgid, 'del_flg': '0'})
|
||||
if org_rows and org_rows[0].get('parentid'):
|
||||
return org_rows[0]['parentid']
|
||||
return user_orgid
|
||||
|
||||
|
||||
async def _fetch_customer_users(sor, institution_orgid, customerid=None):
|
||||
"""
|
||||
获取机构下辖用户。
|
||||
普通用户:users.orgid = organization.id,organization.parentid = 机构 id。
|
||||
管理/运营:users.orgid 直接等于机构 id。
|
||||
邀请注册可能存在二级 organization(parentid 指向上级客户机构)。
|
||||
"""
|
||||
inst_esc = _escape(institution_orgid)
|
||||
if customerid:
|
||||
cid_esc = _escape(customerid)
|
||||
if customerid == institution_orgid:
|
||||
user_scope = """(
|
||||
o.parentid = '%s'
|
||||
OR o.parentid IN (
|
||||
SELECT id FROM organization WHERE parentid = '%s' AND del_flg = '0'
|
||||
)
|
||||
OR u.orgid = '%s'
|
||||
)""" % (inst_esc, inst_esc, inst_esc)
|
||||
else:
|
||||
user_scope = "(u.orgid = '%s' OR o.parentid = '%s')" % (cid_esc, cid_esc)
|
||||
else:
|
||||
user_scope = """(
|
||||
o.parentid = '%s'
|
||||
OR o.parentid IN (
|
||||
SELECT id FROM organization WHERE parentid = '%s' AND del_flg = '0'
|
||||
)
|
||||
OR u.orgid = '%s'
|
||||
)""" % (inst_esc, inst_esc, inst_esc)
|
||||
|
||||
sql = """
|
||||
SELECT u.id, u.username, u.name, u.orgid, o.orgname, o.parentid AS org_parentid
|
||||
FROM users u
|
||||
INNER JOIN organization o ON u.orgid = o.id AND o.del_flg = '0'
|
||||
WHERE u.del_flg = '0' AND %s
|
||||
""" % user_scope
|
||||
rows = await sor.sqlExe(sql, {})
|
||||
|
||||
org_map = {}
|
||||
user_map = {}
|
||||
for oid in org_map:
|
||||
user_rows = await sor.R('users', {'orgid': oid, 'del_flg': '0'})
|
||||
for user in user_rows:
|
||||
user_map[user['id']] = user
|
||||
for row in rows:
|
||||
uid = row['id']
|
||||
oid = row.get('orgid')
|
||||
user_map[uid] = {
|
||||
'id': uid,
|
||||
'username': row.get('username'),
|
||||
'name': row.get('name'),
|
||||
'orgid': oid,
|
||||
}
|
||||
if oid and oid not in org_map:
|
||||
org_map[oid] = {
|
||||
'id': oid,
|
||||
'orgname': row.get('orgname'),
|
||||
'parentid': row.get('org_parentid'),
|
||||
}
|
||||
return org_map, user_map
|
||||
|
||||
|
||||
@ -412,8 +491,8 @@ async def model_usage_admin_report(ns={}):
|
||||
if group_by and group_by not in ('hour', 'day', 'week'):
|
||||
return {'status': False, 'msg': 'group_by 仅支持 hour / day / week'}
|
||||
|
||||
page_size = int(ns.get('page_size', 20))
|
||||
current_page = int(ns.get('current_page', 1))
|
||||
page_size = int(ns.get('page_size')) if ns.get('page_size') else 20
|
||||
current_page = int(ns.get('current_page')) if ns.get('current_page') else 1
|
||||
offset = (current_page - 1) * page_size
|
||||
|
||||
db = DBPools()
|
||||
@ -423,11 +502,12 @@ async def model_usage_admin_report(ns={}):
|
||||
if not user_rows:
|
||||
return {'status': False, 'msg': '用户不存在'}
|
||||
|
||||
orgid = user_rows[0].get('orgid')
|
||||
user_orgid = user_rows[0].get('orgid')
|
||||
user_role = await get_user_role({'userid': userid, 'sor': sor})
|
||||
if user_role not in ('管理员', '运营', '运营管理员'):
|
||||
return {'status': False, 'msg': '无权限,仅机构管理员可查看'}
|
||||
|
||||
orgid = await _resolve_scope_orgid(sor, user_orgid, user_role)
|
||||
org_map, user_map = await _fetch_customer_users(sor, orgid, customerid)
|
||||
user_ids = list(user_map.keys())
|
||||
if not user_ids:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user