commit
03d412be5d
18
b/.mcp.json
Normal file
18
b/.mcp.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"mysql": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "mcp-mysql-multi-db"],
|
||||
"env": { // <-- 就是这里!env 是一个对象
|
||||
"MYSQL_HOST": "localhost",
|
||||
"MYSQL_PORT": "3306",
|
||||
"MYSQL_USER": "root",
|
||||
"MYSQL_PASSWORD": "lima2018",
|
||||
"MYSQL_DATABASE": "kprod",
|
||||
// 👇 要执行 INSERT/UPDATE 等写操作,就在这里添加下面两行
|
||||
// "ALLOW_DML": "true",
|
||||
// "ALLOW_DDL": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,7 +75,7 @@ async def affirmbz_order(ns={}):
|
||||
await sor.U('customer_goods', {'id': resource_find_id, 'del_flg': '1'})
|
||||
|
||||
# 处理续费逻辑
|
||||
elif order_type == 'RENEW':
|
||||
elif order_type == 'RENEW' or order_type == 'DILATATION':
|
||||
# 找到资源并更新时间
|
||||
resource_find_sql = """select id from customer_goods where FIND_IN_SET('%s', resourceid) and del_flg = '0';""" % j['resourceids']
|
||||
resource_find_li = await sor.sqlExe(resource_find_sql, {})
|
||||
@ -488,6 +488,8 @@ async def get_baidu_orderlist(ns={}):
|
||||
business_op = 'BUY'
|
||||
elif order_type == 'RENEW':
|
||||
business_op = 'RENEW'
|
||||
elif order_type == 'DILATATION':
|
||||
business_op = 'DILATATION'
|
||||
elif order_type == 'REFUND':
|
||||
business_op = 'BUY_REVERSE'
|
||||
else:
|
||||
@ -498,6 +500,8 @@ async def get_baidu_orderlist(ns={}):
|
||||
'reason': '支付形式目前仅包含购买,续费,退订'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
# 取消订单
|
||||
await baidu_order_cancel({'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')})
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '线上暂不支持, 请联系售后'
|
||||
@ -605,8 +609,11 @@ async def get_baidu_orderlist(ns={}):
|
||||
with open('baidu_error.log', 'a') as f:
|
||||
f.write('保存配置configurations失败' + str(e) + '\n')
|
||||
|
||||
if order_type == 'DILATATION':
|
||||
# 暂时不确定升降配是否需要重新计算日期
|
||||
pass
|
||||
# 如果是续费订单 由于没有返回日期, 重新计算日期
|
||||
if order_type == 'RENEW':
|
||||
elif order_type == 'RENEW':
|
||||
history_time_sql = "select resourcestarttime, resourceendtime from order_goods where FIND_IN_SET('%s', resourceids) order by resourceendtime desc;" % \
|
||||
nss['resourceids']
|
||||
history_time = await sor.sqlExe(history_time_sql, {})
|
||||
|
||||
@ -75,7 +75,6 @@ SALEMODE_LABEL = {
|
||||
}
|
||||
|
||||
INCOME_SUBJECTS = ('折扣收入', '底价收入')
|
||||
PARENT_SETTLE_SUBJECT = '分销商存放资金'
|
||||
SUPPLIER_SETTLE_PREFIX = '待结转'
|
||||
|
||||
_SALEMODE_SQL_OWN = """
|
||||
@ -116,6 +115,15 @@ def _round_money(v):
|
||||
return round(float(v), 2)
|
||||
|
||||
|
||||
def _is_reverse_op(business_op):
|
||||
"""退订/红冲类操作(BUY_REVERSE 等 *_REVERSE)。
|
||||
|
||||
数据中退订账单的 bill_detail 方向与正常单一致(均为贷),仅靠 business_op 区分。
|
||||
退订口径:销售额、利润取反(减少);上游结算/应付供应商仍正向累加(增加)。
|
||||
"""
|
||||
return str(business_op or '').upper().endswith('_REVERSE')
|
||||
|
||||
|
||||
def _salemode_label(code):
|
||||
if code is None:
|
||||
return None
|
||||
@ -194,9 +202,12 @@ async def _org_name(sor, orgid):
|
||||
|
||||
|
||||
async def _is_business_owner(sor, orgid):
|
||||
# 业主机构 parentid 为空串(非 NULL),org_type='0';两者都视为顶级机构。
|
||||
rows = await sor.sqlExe(
|
||||
"SELECT id FROM organization WHERE id=${id}$ AND parentid IS NULL AND del_flg='0'",
|
||||
{'id': orgid},
|
||||
"""SELECT id FROM organization
|
||||
WHERE id=${id}$ AND del_flg='0'
|
||||
AND ((parentid IS NULL OR parentid='') OR org_type=${owner_type}$)""",
|
||||
{'id': orgid, 'owner_type': OWNER_OGR},
|
||||
)
|
||||
return len(rows) > 0
|
||||
|
||||
@ -324,8 +335,14 @@ async def _protocol_snapshot(sor, accounting_orgid, customerid, providerid, prod
|
||||
}
|
||||
|
||||
|
||||
def _estimate_finance(catalog_amount, protocol, is_owner):
|
||||
"""未记账:估算本级利润与本级应付(不含代付费单独字段)。"""
|
||||
def _estimate_finance(catalog_amount, protocol, is_reverse=False):
|
||||
"""未记账:估算本级利润与本级应付(本级成本)。
|
||||
|
||||
与已记账口径一致,本级应付取「本级作为采购方(bid)的协议」即 own_*,
|
||||
对业主机构与分销商统一(own_discount 即上级给本级的折扣/底价)。
|
||||
|
||||
退订(is_reverse):利润取反(减少);上游结算仍正向(增加)。
|
||||
"""
|
||||
catalog_amount = float(catalog_amount or 0)
|
||||
qty = protocol.get('quantity') or 1
|
||||
profit = None
|
||||
@ -335,29 +352,23 @@ def _estimate_finance(catalog_amount, protocol, is_owner):
|
||||
cust_mode = protocol.get('customer_salemode')
|
||||
own_disc = protocol.get('own_discount')
|
||||
cust_disc = protocol.get('customer_discount')
|
||||
reseller_disc = protocol.get('reseller_discount')
|
||||
|
||||
if own_mode == '0' or cust_mode == '0':
|
||||
if own_disc is not None and cust_disc is not None:
|
||||
profit = catalog_amount * (float(cust_disc) - float(own_disc))
|
||||
if is_owner:
|
||||
if own_disc is not None:
|
||||
settle_upstream = catalog_amount * float(own_disc)
|
||||
elif reseller_disc is not None:
|
||||
settle_upstream = catalog_amount * float(reseller_disc)
|
||||
if own_disc is not None:
|
||||
settle_upstream = catalog_amount * float(own_disc)
|
||||
|
||||
elif own_mode == '2' or cust_mode == '2':
|
||||
own_price = protocol.get('own_floor_unit_price')
|
||||
cust_price = protocol.get('customer_floor_unit_price')
|
||||
reseller_price = protocol.get('reseller_floor_unit_price')
|
||||
if own_price is not None and cust_price is not None:
|
||||
profit = (float(cust_price) - float(own_price)) * qty
|
||||
if is_owner and own_price is not None:
|
||||
if own_price is not None:
|
||||
settle_upstream = float(own_price) * qty
|
||||
elif not is_owner and reseller_price is not None:
|
||||
settle_upstream = float(reseller_price) * qty
|
||||
elif not is_owner and cust_price is not None:
|
||||
settle_upstream = float(cust_price) * qty
|
||||
|
||||
if is_reverse and profit is not None:
|
||||
profit = -profit
|
||||
|
||||
return {
|
||||
'profit_amount': _round_money(profit),
|
||||
@ -379,8 +390,15 @@ async def _bill_detail_rows(sor, billid):
|
||||
))
|
||||
|
||||
|
||||
async def _finance_from_bill_detail(sor, billid, accounting_orgid, is_owner, parent_orgid):
|
||||
"""已记账:从 bill_detail 取本级利润与本级应付。"""
|
||||
async def _finance_from_bill_detail(sor, billid, accounting_orgid, is_reverse=False):
|
||||
"""已记账:从 bill_detail 取本级利润与本级应付。
|
||||
|
||||
统一口径(业主机构与分销商一致):
|
||||
- profit_amount = 本级账本「折扣收入/底价收入」贷方合计
|
||||
- settle_upstream = 本级账本「待结转*销售收入」贷方合计(本级成本/本级应付上级)
|
||||
|
||||
退订(is_reverse):利润取反(减少);上游结算仍正向累加(增加)。
|
||||
"""
|
||||
rows = await _bill_detail_rows(sor, billid)
|
||||
profit = 0.0
|
||||
settle_upstream = 0.0
|
||||
@ -400,25 +418,14 @@ async def _finance_from_bill_detail(sor, billid, accounting_orgid, is_owner, par
|
||||
subj = r['subjectname'] or ''
|
||||
direction = r['accounting_dir']
|
||||
|
||||
if book == accounting_orgid and subj in INCOME_SUBJECTS and direction == '贷':
|
||||
profit += amt
|
||||
if book == accounting_orgid and direction == '贷':
|
||||
if subj in INCOME_SUBJECTS:
|
||||
profit += amt
|
||||
elif subj.startswith(SUPPLIER_SETTLE_PREFIX):
|
||||
settle_upstream += amt
|
||||
|
||||
if is_owner:
|
||||
if (
|
||||
book == accounting_orgid
|
||||
and subj.startswith(SUPPLIER_SETTLE_PREFIX)
|
||||
and direction == '贷'
|
||||
):
|
||||
settle_upstream += amt
|
||||
else:
|
||||
if (
|
||||
parent_orgid
|
||||
and book == parent_orgid
|
||||
and subj == PARENT_SETTLE_SUBJECT
|
||||
and direction == '借'
|
||||
and r.get('participantid') == accounting_orgid
|
||||
):
|
||||
settle_upstream += amt
|
||||
if is_reverse:
|
||||
profit = -profit
|
||||
|
||||
return {
|
||||
'profit_amount': _round_money(profit),
|
||||
@ -438,20 +445,21 @@ async def _build_report_row(sor, row, accounting_orgid, is_owner):
|
||||
catalog_amount = _round_money(_row_get(row, 'catalog_amount'))
|
||||
customer_pay = _round_money(_row_get(row, 'customer_pay_amount'))
|
||||
customer_parentid = _row_get(row, 'customer_parentid')
|
||||
is_reverse = _is_reverse_op(_row_get(row, 'business_op'))
|
||||
if is_reverse and customer_pay is not None:
|
||||
# 退订:客户实付(销售额)取负,使汇总相应减少
|
||||
customer_pay = _round_money(-customer_pay)
|
||||
|
||||
protocol = await _protocol_snapshot(
|
||||
sor, accounting_orgid, customerid, providerid, productid, bill_date, quantity,
|
||||
)
|
||||
parent_orgid = protocol['parent_orgid']
|
||||
settle_meta = await _settle_upstream_meta(sor, accounting_orgid, providerid)
|
||||
|
||||
bill_state = _row_get(row, 'bill_state')
|
||||
if str(bill_state) == '1':
|
||||
amounts = await _finance_from_bill_detail(
|
||||
sor, bill_id, accounting_orgid, is_owner, parent_orgid,
|
||||
)
|
||||
amounts = await _finance_from_bill_detail(sor, bill_id, accounting_orgid, is_reverse)
|
||||
else:
|
||||
amounts = _estimate_finance(catalog_amount, protocol, is_owner)
|
||||
amounts = _estimate_finance(catalog_amount, protocol, is_reverse)
|
||||
amounts['bill_detail_legs'] = []
|
||||
|
||||
product_name = _row_get(row, 'product_name')
|
||||
@ -652,17 +660,21 @@ def _customer_segment(customer_parentid, accounting_orgid, reseller_id_set):
|
||||
return None
|
||||
|
||||
|
||||
async def _bill_finance_amounts(sor, row, accounting_orgid, is_owner, parent_orgid):
|
||||
"""单笔:销售额、本级利润、本级应付上级/供应商。"""
|
||||
async def _bill_finance_amounts(sor, row, accounting_orgid):
|
||||
"""单笔:销售额、本级利润、本级应付上级/供应商。
|
||||
|
||||
退订(BUY_REVERSE 等):销售额、利润取负(减少);应付上级仍正向(增加)。
|
||||
"""
|
||||
sales = float(_row_get(row, 'customer_pay_amount') or 0)
|
||||
bill_id = _row_get(row, 'bill_id')
|
||||
bill_state = _row_get(row, 'bill_state')
|
||||
quantity = int(_row_get(row, 'quantity') or 1)
|
||||
is_reverse = _is_reverse_op(_row_get(row, 'business_op'))
|
||||
if is_reverse:
|
||||
sales = -sales
|
||||
|
||||
if str(bill_state) == '1':
|
||||
fin = await _finance_from_bill_detail(
|
||||
sor, bill_id, accounting_orgid, is_owner, parent_orgid,
|
||||
)
|
||||
fin = await _finance_from_bill_detail(sor, bill_id, accounting_orgid, is_reverse)
|
||||
else:
|
||||
catalog = float(_row_get(row, 'catalog_amount') or 0)
|
||||
protocol = await _protocol_snapshot(
|
||||
@ -674,7 +686,7 @@ async def _bill_finance_amounts(sor, row, accounting_orgid, is_owner, parent_org
|
||||
_row_get(row, 'bill_date'),
|
||||
quantity,
|
||||
)
|
||||
fin = _estimate_finance(catalog, protocol, is_owner)
|
||||
fin = _estimate_finance(catalog, protocol, is_reverse)
|
||||
|
||||
profit = float(fin.get('profit_amount') or 0)
|
||||
settle = float(fin.get('settle_upstream_amount') or 0)
|
||||
@ -786,7 +798,7 @@ async def _fetch_bill_row_via_R(sor, bill_id):
|
||||
'customer_pay_amount': b.get('amount'),
|
||||
'quantity': b.get('quantity'),
|
||||
'order_date': o.get('order_date'),
|
||||
'business_op': o.get('business_op'),
|
||||
'business_op': b.get('business_op') or o.get('business_op'),
|
||||
'servicename': o.get('servicename'),
|
||||
'customer_name': cust.get('orgname'),
|
||||
'customer_parentid': cust.get('parentid'),
|
||||
@ -878,9 +890,9 @@ async def finance_order_report(ns=None):
|
||||
userid, start_date, end_date, customerid, productid, order_id, bill_state
|
||||
current_page (默认1), page_size (默认20, 最大100)
|
||||
|
||||
返回 finance.settle_upstream_*:
|
||||
- 本机构:应付供应商(待结转* 贷方,仅本机构账本)
|
||||
- 分销商:应付直接上级(上级账本「分销商存放资金」借方,participant=本级)
|
||||
返回 finance.settle_upstream_*(统一口径,取本级账本「待结转*销售收入」贷方):
|
||||
- 本机构:应付供应商
|
||||
- 分销商:应付直接上级机构(金额=本级成本,与本级账本待结转一致)
|
||||
"""
|
||||
ns = ns or {}
|
||||
accounting_orgid = ns.get('accounting_orgid')
|
||||
@ -1053,7 +1065,7 @@ async def finance_billing_overview(ns=None):
|
||||
口径(与订单明细接口一致):
|
||||
sales_total = 客户实付合计 bill.amount
|
||||
profit_total = 本级账本折扣收入+底价收入(bill_detail)或协议估算
|
||||
settle_upstream_total= 本机构→供应商待结转;分销→上级账本分销商存放资金借方
|
||||
settle_upstream_total= 本级账本「待结转*销售收入」贷方合计(本级成本/应付上级,业主与分销统一)
|
||||
|
||||
分段:
|
||||
direct_customers 直属客户(cust.parentid = accounting_orgid)
|
||||
@ -1084,7 +1096,6 @@ async def finance_billing_overview(ns=None):
|
||||
sor, accounting_orgid, include_sub,
|
||||
)
|
||||
is_owner = await _is_business_owner(sor, accounting_orgid)
|
||||
parent_orgid = await get_parent_orgid(sor, accounting_orgid)
|
||||
|
||||
conditions = ["b.del_flg = '0'", "o.del_flg = '0'", scope_sql]
|
||||
params = dict(scope_params)
|
||||
@ -1128,7 +1139,7 @@ async def finance_billing_overview(ns=None):
|
||||
continue
|
||||
try:
|
||||
sales, profit, settle, _src = await _bill_finance_amounts(
|
||||
sor, row, accounting_orgid, is_owner, parent_orgid,
|
||||
sor, row, accounting_orgid,
|
||||
)
|
||||
except Exception as exc:
|
||||
errors.append({
|
||||
@ -1230,11 +1241,10 @@ async def finance_billing_overview(ns=None):
|
||||
|
||||
# _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)
|
||||
# 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
|
||||
@ -75,7 +75,6 @@ SALEMODE_LABEL = {
|
||||
}
|
||||
|
||||
INCOME_SUBJECTS = ('折扣收入', '底价收入')
|
||||
PARENT_SETTLE_SUBJECT = '分销商存放资金'
|
||||
SUPPLIER_SETTLE_PREFIX = '待结转'
|
||||
|
||||
_SALEMODE_SQL_OWN = """
|
||||
@ -116,6 +115,15 @@ def _round_money(v):
|
||||
return round(float(v), 2)
|
||||
|
||||
|
||||
def _is_reverse_op(business_op):
|
||||
"""退订/红冲类操作(BUY_REVERSE 等 *_REVERSE)。
|
||||
|
||||
数据中退订账单的 bill_detail 方向与正常单一致(均为贷),仅靠 business_op 区分。
|
||||
退订口径:销售额、利润取反(减少);上游结算/应付供应商仍正向累加(增加)。
|
||||
"""
|
||||
return str(business_op or '').upper().endswith('_REVERSE')
|
||||
|
||||
|
||||
def _salemode_label(code):
|
||||
if code is None:
|
||||
return None
|
||||
@ -194,9 +202,12 @@ async def _org_name(sor, orgid):
|
||||
|
||||
|
||||
async def _is_business_owner(sor, orgid):
|
||||
# 业主机构 parentid 为空串(非 NULL),org_type='0';两者都视为顶级机构。
|
||||
rows = await sor.sqlExe(
|
||||
"SELECT id FROM organization WHERE id=${id}$ AND parentid IS NULL AND del_flg='0'",
|
||||
{'id': orgid},
|
||||
"""SELECT id FROM organization
|
||||
WHERE id=${id}$ AND del_flg='0'
|
||||
AND ((parentid IS NULL OR parentid='') OR org_type=${owner_type}$)""",
|
||||
{'id': orgid, 'owner_type': OWNER_OGR},
|
||||
)
|
||||
return len(rows) > 0
|
||||
|
||||
@ -324,8 +335,14 @@ async def _protocol_snapshot(sor, accounting_orgid, customerid, providerid, prod
|
||||
}
|
||||
|
||||
|
||||
def _estimate_finance(catalog_amount, protocol, is_owner):
|
||||
"""未记账:估算本级利润与本级应付(不含代付费单独字段)。"""
|
||||
def _estimate_finance(catalog_amount, protocol, is_reverse=False):
|
||||
"""未记账:估算本级利润与本级应付(本级成本)。
|
||||
|
||||
与已记账口径一致,本级应付取「本级作为采购方(bid)的协议」即 own_*,
|
||||
对业主机构与分销商统一(own_discount 即上级给本级的折扣/底价)。
|
||||
|
||||
退订(is_reverse):利润取反(减少);上游结算仍正向(增加)。
|
||||
"""
|
||||
catalog_amount = float(catalog_amount or 0)
|
||||
qty = protocol.get('quantity') or 1
|
||||
profit = None
|
||||
@ -335,29 +352,23 @@ def _estimate_finance(catalog_amount, protocol, is_owner):
|
||||
cust_mode = protocol.get('customer_salemode')
|
||||
own_disc = protocol.get('own_discount')
|
||||
cust_disc = protocol.get('customer_discount')
|
||||
reseller_disc = protocol.get('reseller_discount')
|
||||
|
||||
if own_mode == '0' or cust_mode == '0':
|
||||
if own_disc is not None and cust_disc is not None:
|
||||
profit = catalog_amount * (float(cust_disc) - float(own_disc))
|
||||
if is_owner:
|
||||
if own_disc is not None:
|
||||
settle_upstream = catalog_amount * float(own_disc)
|
||||
elif reseller_disc is not None:
|
||||
settle_upstream = catalog_amount * float(reseller_disc)
|
||||
if own_disc is not None:
|
||||
settle_upstream = catalog_amount * float(own_disc)
|
||||
|
||||
elif own_mode == '2' or cust_mode == '2':
|
||||
own_price = protocol.get('own_floor_unit_price')
|
||||
cust_price = protocol.get('customer_floor_unit_price')
|
||||
reseller_price = protocol.get('reseller_floor_unit_price')
|
||||
if own_price is not None and cust_price is not None:
|
||||
profit = (float(cust_price) - float(own_price)) * qty
|
||||
if is_owner and own_price is not None:
|
||||
if own_price is not None:
|
||||
settle_upstream = float(own_price) * qty
|
||||
elif not is_owner and reseller_price is not None:
|
||||
settle_upstream = float(reseller_price) * qty
|
||||
elif not is_owner and cust_price is not None:
|
||||
settle_upstream = float(cust_price) * qty
|
||||
|
||||
if is_reverse and profit is not None:
|
||||
profit = -profit
|
||||
|
||||
return {
|
||||
'profit_amount': _round_money(profit),
|
||||
@ -379,8 +390,15 @@ async def _bill_detail_rows(sor, billid):
|
||||
))
|
||||
|
||||
|
||||
async def _finance_from_bill_detail(sor, billid, accounting_orgid, is_owner, parent_orgid):
|
||||
"""已记账:从 bill_detail 取本级利润与本级应付。"""
|
||||
async def _finance_from_bill_detail(sor, billid, accounting_orgid, is_reverse=False):
|
||||
"""已记账:从 bill_detail 取本级利润与本级应付。
|
||||
|
||||
统一口径(业主机构与分销商一致):
|
||||
- profit_amount = 本级账本「折扣收入/底价收入」贷方合计
|
||||
- settle_upstream = 本级账本「待结转*销售收入」贷方合计(本级成本/本级应付上级)
|
||||
|
||||
退订(is_reverse):利润取反(减少);上游结算仍正向累加(增加)。
|
||||
"""
|
||||
rows = await _bill_detail_rows(sor, billid)
|
||||
profit = 0.0
|
||||
settle_upstream = 0.0
|
||||
@ -400,25 +418,14 @@ async def _finance_from_bill_detail(sor, billid, accounting_orgid, is_owner, par
|
||||
subj = r['subjectname'] or ''
|
||||
direction = r['accounting_dir']
|
||||
|
||||
if book == accounting_orgid and subj in INCOME_SUBJECTS and direction == '贷':
|
||||
profit += amt
|
||||
if book == accounting_orgid and direction == '贷':
|
||||
if subj in INCOME_SUBJECTS:
|
||||
profit += amt
|
||||
elif subj.startswith(SUPPLIER_SETTLE_PREFIX):
|
||||
settle_upstream += amt
|
||||
|
||||
if is_owner:
|
||||
if (
|
||||
book == accounting_orgid
|
||||
and subj.startswith(SUPPLIER_SETTLE_PREFIX)
|
||||
and direction == '贷'
|
||||
):
|
||||
settle_upstream += amt
|
||||
else:
|
||||
if (
|
||||
parent_orgid
|
||||
and book == parent_orgid
|
||||
and subj == PARENT_SETTLE_SUBJECT
|
||||
and direction == '借'
|
||||
and r.get('participantid') == accounting_orgid
|
||||
):
|
||||
settle_upstream += amt
|
||||
if is_reverse:
|
||||
profit = -profit
|
||||
|
||||
return {
|
||||
'profit_amount': _round_money(profit),
|
||||
@ -438,20 +445,21 @@ async def _build_report_row(sor, row, accounting_orgid, is_owner):
|
||||
catalog_amount = _round_money(_row_get(row, 'catalog_amount'))
|
||||
customer_pay = _round_money(_row_get(row, 'customer_pay_amount'))
|
||||
customer_parentid = _row_get(row, 'customer_parentid')
|
||||
is_reverse = _is_reverse_op(_row_get(row, 'business_op'))
|
||||
if is_reverse and customer_pay is not None:
|
||||
# 退订:客户实付(销售额)取负,使汇总相应减少
|
||||
customer_pay = _round_money(-customer_pay)
|
||||
|
||||
protocol = await _protocol_snapshot(
|
||||
sor, accounting_orgid, customerid, providerid, productid, bill_date, quantity,
|
||||
)
|
||||
parent_orgid = protocol['parent_orgid']
|
||||
settle_meta = await _settle_upstream_meta(sor, accounting_orgid, providerid)
|
||||
|
||||
bill_state = _row_get(row, 'bill_state')
|
||||
if str(bill_state) == '1':
|
||||
amounts = await _finance_from_bill_detail(
|
||||
sor, bill_id, accounting_orgid, is_owner, parent_orgid,
|
||||
)
|
||||
amounts = await _finance_from_bill_detail(sor, bill_id, accounting_orgid, is_reverse)
|
||||
else:
|
||||
amounts = _estimate_finance(catalog_amount, protocol, is_owner)
|
||||
amounts = _estimate_finance(catalog_amount, protocol, is_reverse)
|
||||
amounts['bill_detail_legs'] = []
|
||||
|
||||
product_name = _row_get(row, 'product_name')
|
||||
@ -652,17 +660,21 @@ def _customer_segment(customer_parentid, accounting_orgid, reseller_id_set):
|
||||
return None
|
||||
|
||||
|
||||
async def _bill_finance_amounts(sor, row, accounting_orgid, is_owner, parent_orgid):
|
||||
"""单笔:销售额、本级利润、本级应付上级/供应商。"""
|
||||
async def _bill_finance_amounts(sor, row, accounting_orgid):
|
||||
"""单笔:销售额、本级利润、本级应付上级/供应商。
|
||||
|
||||
退订(BUY_REVERSE 等):销售额、利润取负(减少);应付上级仍正向(增加)。
|
||||
"""
|
||||
sales = float(_row_get(row, 'customer_pay_amount') or 0)
|
||||
bill_id = _row_get(row, 'bill_id')
|
||||
bill_state = _row_get(row, 'bill_state')
|
||||
quantity = int(_row_get(row, 'quantity') or 1)
|
||||
is_reverse = _is_reverse_op(_row_get(row, 'business_op'))
|
||||
if is_reverse:
|
||||
sales = -sales
|
||||
|
||||
if str(bill_state) == '1':
|
||||
fin = await _finance_from_bill_detail(
|
||||
sor, bill_id, accounting_orgid, is_owner, parent_orgid,
|
||||
)
|
||||
fin = await _finance_from_bill_detail(sor, bill_id, accounting_orgid, is_reverse)
|
||||
else:
|
||||
catalog = float(_row_get(row, 'catalog_amount') or 0)
|
||||
protocol = await _protocol_snapshot(
|
||||
@ -674,7 +686,7 @@ async def _bill_finance_amounts(sor, row, accounting_orgid, is_owner, parent_org
|
||||
_row_get(row, 'bill_date'),
|
||||
quantity,
|
||||
)
|
||||
fin = _estimate_finance(catalog, protocol, is_owner)
|
||||
fin = _estimate_finance(catalog, protocol, is_reverse)
|
||||
|
||||
profit = float(fin.get('profit_amount') or 0)
|
||||
settle = float(fin.get('settle_upstream_amount') or 0)
|
||||
@ -786,7 +798,7 @@ async def _fetch_bill_row_via_R(sor, bill_id):
|
||||
'customer_pay_amount': b.get('amount'),
|
||||
'quantity': b.get('quantity'),
|
||||
'order_date': o.get('order_date'),
|
||||
'business_op': o.get('business_op'),
|
||||
'business_op': b.get('business_op') or o.get('business_op'),
|
||||
'servicename': o.get('servicename'),
|
||||
'customer_name': cust.get('orgname'),
|
||||
'customer_parentid': cust.get('parentid'),
|
||||
@ -878,9 +890,9 @@ async def finance_order_report(ns=None):
|
||||
userid, start_date, end_date, customerid, productid, order_id, bill_state
|
||||
current_page (默认1), page_size (默认20, 最大100)
|
||||
|
||||
返回 finance.settle_upstream_*:
|
||||
- 本机构:应付供应商(待结转* 贷方,仅本机构账本)
|
||||
- 分销商:应付直接上级(上级账本「分销商存放资金」借方,participant=本级)
|
||||
返回 finance.settle_upstream_*(统一口径,取本级账本「待结转*销售收入」贷方):
|
||||
- 本机构:应付供应商
|
||||
- 分销商:应付直接上级机构(金额=本级成本,与本级账本待结转一致)
|
||||
"""
|
||||
ns = ns or {}
|
||||
accounting_orgid = ns.get('accounting_orgid')
|
||||
@ -1053,7 +1065,7 @@ async def finance_billing_overview(ns=None):
|
||||
口径(与订单明细接口一致):
|
||||
sales_total = 客户实付合计 bill.amount
|
||||
profit_total = 本级账本折扣收入+底价收入(bill_detail)或协议估算
|
||||
settle_upstream_total= 本机构→供应商待结转;分销→上级账本分销商存放资金借方
|
||||
settle_upstream_total= 本级账本「待结转*销售收入」贷方合计(本级成本/应付上级,业主与分销统一)
|
||||
|
||||
分段:
|
||||
direct_customers 直属客户(cust.parentid = accounting_orgid)
|
||||
@ -1084,7 +1096,6 @@ async def finance_billing_overview(ns=None):
|
||||
sor, accounting_orgid, include_sub,
|
||||
)
|
||||
is_owner = await _is_business_owner(sor, accounting_orgid)
|
||||
parent_orgid = await get_parent_orgid(sor, accounting_orgid)
|
||||
|
||||
conditions = ["b.del_flg = '0'", "o.del_flg = '0'", scope_sql]
|
||||
params = dict(scope_params)
|
||||
@ -1128,7 +1139,7 @@ async def finance_billing_overview(ns=None):
|
||||
continue
|
||||
try:
|
||||
sales, profit, settle, _src = await _bill_finance_amounts(
|
||||
sor, row, accounting_orgid, is_owner, parent_orgid,
|
||||
sor, row, accounting_orgid,
|
||||
)
|
||||
except Exception as exc:
|
||||
errors.append({
|
||||
|
||||
@ -178,7 +178,7 @@ async def getbz_order(ns={}):
|
||||
'BUY': '购买',
|
||||
'RENEW': '续费',
|
||||
'BUY_REVERSE': '退款',
|
||||
# 'UPGRADE': '升级'
|
||||
'DILATATION': '升降配'
|
||||
}
|
||||
item['business_op_text'] = business_op_mapping.get(item['business_op'], item['business_op'])
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ def _normalize_usage_row(row, bill_amount_map=None):
|
||||
'prompt_tokens': int(usage.get('prompt_tokens') or 0),
|
||||
'completion_tokens': int(usage.get('completion_tokens') or 0),
|
||||
'total_tokens': int(usage.get('total_tokens') or 0),
|
||||
'amount': round(amount, 8),
|
||||
'amount': round(amount, 4),
|
||||
'bill_status': row.get('bill_status'),
|
||||
'orderid': orderid,
|
||||
'usage_time': row.get('created_at'),
|
||||
@ -224,7 +224,7 @@ def _aggregate_admin_summary(items, user_map, org_map):
|
||||
bucket['prompt_tokens'] += item.get('prompt_tokens') or 0
|
||||
bucket['completion_tokens'] += item.get('completion_tokens') or 0
|
||||
bucket['total_tokens'] += item.get('total_tokens') or 0
|
||||
bucket['amount'] = round(bucket['amount'] + float(item.get('amount') or 0), 8)
|
||||
bucket['amount'] = round(bucket['amount'] + float(item.get('amount') or 0), 4)
|
||||
bucket['request_count'] += 1
|
||||
usage_time = item.get('usage_time')
|
||||
if usage_time:
|
||||
@ -267,7 +267,7 @@ def _aggregate_items(items, group_by=None):
|
||||
bucket['prompt_tokens'] += item.get('prompt_tokens') or 0
|
||||
bucket['completion_tokens'] += item.get('completion_tokens') or 0
|
||||
bucket['total_tokens'] += item.get('total_tokens') or 0
|
||||
bucket['amount'] = round(bucket['amount'] + float(item.get('amount') or 0), 8)
|
||||
bucket['amount'] = round(bucket['amount'] + float(item.get('amount') or 0), 4)
|
||||
bucket['request_count'] += 1
|
||||
|
||||
return sorted(buckets.values(), key=lambda x: x['period'], reverse=True)
|
||||
@ -279,7 +279,7 @@ def _summarize(items):
|
||||
'prompt_tokens': sum(i.get('prompt_tokens') or 0 for i in items),
|
||||
'completion_tokens': sum(i.get('completion_tokens') or 0 for i in items),
|
||||
'total_tokens': sum(i.get('total_tokens') or 0 for i in items),
|
||||
'amount': round(sum(float(i.get('amount') or 0) for i in items), 8),
|
||||
'amount': round(sum(float(i.get('amount') or 0) for i in items), 4),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -129,19 +129,19 @@ export const reqModelInfoConfig = (params = {}) => {
|
||||
const isFormData = params instanceof FormData
|
||||
return request({
|
||||
url: '/cntoai/model_management_add.dspy',
|
||||
method: isFormData ? 'post' : 'get',
|
||||
method: 'post',
|
||||
params: isFormData ? undefined : params,
|
||||
data: isFormData ? params : undefined,
|
||||
headers: isFormData ? { 'Content-Type': 'multipart/form-data' } : undefined
|
||||
})
|
||||
}
|
||||
|
||||
// 模型信息配置编辑(编辑时需要额外传 id)
|
||||
// 模型信息配置编辑
|
||||
export const reqModelInfoConfigEdit = (params = {}) => {
|
||||
const isFormData = params instanceof FormData
|
||||
return request({
|
||||
url: '/cntoai/model_management_update.dspy',
|
||||
method: isFormData ? 'post' : 'get',
|
||||
method: 'post',
|
||||
params: isFormData ? undefined : params,
|
||||
data: isFormData ? params : undefined,
|
||||
headers: isFormData ? { 'Content-Type': 'multipart/form-data' } : undefined
|
||||
|
||||
@ -10,10 +10,10 @@
|
||||
<p>核算机构:<b>{{ displayValue(billingData.accounting_orgname) }}</b></p>
|
||||
<p>机构编号:{{ displayValue(billingData.accounting_orgid) }}</p>
|
||||
</div>
|
||||
<div class="view-info">
|
||||
<!-- <div class="view-info">
|
||||
<strong>管理员视图</strong>
|
||||
<small>生成于 2026/5/29 17:00:06</small>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<div class="summary-grid">
|
||||
@ -179,7 +179,7 @@
|
||||
<td>{{ displayValue(leg.subjectname) }}</td>
|
||||
<td><span class="dir-tag" :class="leg.accounting_dir === '贷' ? 'credit' : 'debit'">{{ displayValue(leg.accounting_dir) }}</span></td>
|
||||
<td>{{ displayValue(leg.participanttype) }}</td>
|
||||
<td>{{ displayValue(leg.accounting_orgid) }}</td>
|
||||
<td>{{ displayValue(leg.accounting_orgid) }}</td>
|
||||
<td class="num">{{ money(leg.amount) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@ -18,9 +18,9 @@
|
||||
<span>数据截断:<b>{{ financialOverview.truncated ? '是' : '否' }}</b></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="view-meta">
|
||||
查看计费统计
|
||||
</div>
|
||||
<!-- <div class="view-meta">
|
||||
查看计费统计
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<div class="summary-grid">
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -89,7 +89,7 @@ import { reqModelInfoConfigList } from '@/api/model/model'
|
||||
export default {
|
||||
name: 'ModelInfoConfig',
|
||||
components: {
|
||||
ModelInfoEditDialog,
|
||||
ModelInfoEditDialog,
|
||||
ModelInfoDetailDialog
|
||||
},
|
||||
data() {
|
||||
|
||||
@ -84,11 +84,11 @@
|
||||
|
||||
<el-table v-loading="loading" :data="usageList" class="usage-table" style="width: 100%">
|
||||
<el-table-column prop="model" label="模型名称" min-width="180" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="request_count" label="调用次数" width="120"></el-table-column>
|
||||
<!-- <el-table-column prop="request_count" label="调用次数" width="120"></el-table-column> -->
|
||||
<el-table-column prop="prompt_tokens" label="输入Token" min-width="140"></el-table-column>
|
||||
<el-table-column prop="completion_tokens" label="输出Token" min-width="140"></el-table-column>
|
||||
<el-table-column prop="total_tokens" label="总Token" min-width="140"></el-table-column>
|
||||
<el-table-column prop="amount" label="预估费用" width="130">
|
||||
<el-table-column prop="amount" label="费用" width="130">
|
||||
<template slot-scope="scope">¥ {{ formatAmount(scope.row.amount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="usage_time" label="使用时间" min-width="170" show-overflow-tooltip></el-table-column>
|
||||
@ -131,7 +131,7 @@ export default {
|
||||
statCards: [
|
||||
{ label: '总消耗 Token', value: '0', desc: '当前筛选范围', type: 'primary', icon: 'el-icon-coin' },
|
||||
{ label: '调用次数', value: '0', desc: '当前筛选范围', type: 'success', icon: 'el-icon-s-promotion' },
|
||||
{ label: '预估费用', value: '¥ 0.00', desc: '按当前单价估算', type: 'warning', icon: 'el-icon-wallet' },
|
||||
{ label: ' 费用', value: '¥ 0.00', desc: '按当前单价估算', type: 'warning', icon: 'el-icon-wallet' },
|
||||
{ label: '输入/输出 Token', value: '0 / 0', desc: 'Prompt / Completion', type: 'purple', icon: 'el-icon-pie-chart' }
|
||||
],
|
||||
usageList: [],
|
||||
@ -165,11 +165,27 @@ export default {
|
||||
return this.rangeLabel
|
||||
},
|
||||
modelUsageRank() {
|
||||
const maxTokens = Math.max(...this.usageList.map(item => Number(item.total_tokens || 0)), 0)
|
||||
return this.usageList
|
||||
const modelMap = this.usageList.reduce((map, item) => {
|
||||
const model = item.model || item.model_name || item.display_name || '-'
|
||||
const totalTokens = Number(item.total_tokens || 0) || Number(item.prompt_tokens || 0) + Number(item.completion_tokens || 0)
|
||||
if (!map[model]) {
|
||||
map[model] = {
|
||||
model,
|
||||
total_tokens: 0,
|
||||
request_count: 0,
|
||||
amount: 0
|
||||
}
|
||||
}
|
||||
map[model].total_tokens += totalTokens
|
||||
map[model].request_count += Number(item.request_count || 0)
|
||||
map[model].amount += Number(item.amount || 0)
|
||||
return map
|
||||
}, {})
|
||||
const rankSource = Object.values(modelMap)
|
||||
const maxTokens = Math.max(...rankSource.map(item => Number(item.total_tokens || 0)), 0)
|
||||
return rankSource
|
||||
.map(item => ({
|
||||
model: item.model,
|
||||
total_tokens: Number(item.total_tokens || 0),
|
||||
...item,
|
||||
percent: maxTokens ? Math.round((Number(item.total_tokens || 0) / maxTokens) * 100) : 0
|
||||
}))
|
||||
.sort((a, b) => b.total_tokens - a.total_tokens)
|
||||
@ -328,7 +344,14 @@ export default {
|
||||
},
|
||||
formatter: params => {
|
||||
const item = params && params[0]
|
||||
return item ? `${item.name}<br/>${this.formatNumber(item.value)} Token` : ''
|
||||
if (!item) return ''
|
||||
const rankItem = rankList[item.dataIndex] || {}
|
||||
return [
|
||||
item.name,
|
||||
`${this.formatNumber(item.value)} Token`,
|
||||
`调用次数:${this.formatNumber(rankItem.request_count)}`,
|
||||
`预估费用:¥ ${this.formatAmount(rankItem.amount)}`
|
||||
].join('<br/>')
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user