accounting/wwwroot/proxy_recharge_submit.dspy
Hermes Agent 656fe2fc51 feat: 新增代客充值和错帐处理页面
- proxy_recharge.ui: Form表单输入客户用户名+充值金额
- proxy_recharge_submit.dspy: 查找用户+创建payment_log+调用recharge_accounting
- error_accounting.ui: 错帐处理管理页面(placeholder,含设计文档)
2026-06-18 13:33:16 +08:00

149 lines
3.8 KiB
Plaintext

action = params_kw.get('action', 'submit')
# ---- Lookup mode: find customer by username, return info ----
if action == 'lookup':
username = params_kw.get('username', '').strip()
if not username:
return json.dumps({'status': 'error', 'message': '用户名不能为空'}, ensure_ascii=False, default=str)
db = DBPools()
dbname = get_module_dbname('accounting')
async with db.sqlorContext(dbname) as sor:
sql = """
select
u.username,
u.orgid as customerid,
o.orgname,
a.id as accountid,
a.balance
from users u
left join organization o on u.orgid = o.id COLLATE utf8mb4_unicode_ci
left join account a on a.orgid = u.orgid COLLATE utf8mb4_unicode_ci
where u.username = ${username}$
limit 1
"""
recs = await sor.sqlExe(sql, {'username': username})
if not recs or len(recs) == 0:
return json.dumps({'status': 'error', 'message': f'用户 {username} 不存在'}, ensure_ascii=False, default=str)
rec = recs[0]
return json.dumps({
'status': 'ok',
'data': {
'username': rec.username,
'customerid': rec.customerid,
'orgname': rec.orgname or '',
'accountid': rec.accountid or '',
'balance': float(rec.balance) if rec.balance else 0.0
}
}, ensure_ascii=False, default=str)
# ---- Submit mode: process the proxy recharge ----
username = params_kw.get('username', '').strip()
amount_raw = params_kw.get('amount', 0)
if not username:
return {
"widgettype": "Text",
"options": {"text": "❌ 用户名不能为空", "color": "#EF4444"}
}
try:
amount = float(amount_raw)
except (ValueError, TypeError):
return {
"widgettype": "Text",
"options": {"text": "❌ 充值金额格式错误", "color": "#EF4444"}
}
if amount <= 0:
return {
"widgettype": "Text",
"options": {"text": "❌ 充值金额必须大于0", "color": "#EF4444"}
}
userid = await get_user()
userorgid = await get_userorgid()
db = DBPools()
# Look up the target customer by username
dbname = get_module_dbname('accounting')
async with db.sqlorContext(dbname) as sor:
sql = """
select
u.username,
u.orgid as customerid,
o.orgname,
a.id as accountid
from users u
left join organization o on u.orgid = o.id COLLATE utf8mb4_unicode_ci
left join account a on a.orgid = u.orgid COLLATE utf8mb4_unicode_ci
where u.username = ${username}$
limit 1
"""
recs = await sor.sqlExe(sql, {'username': username})
if not recs or len(recs) == 0:
return {
"widgettype": "Text",
"options": {"text": f"❌ 找不到用户名: {username}", "color": "#EF4444"}
}
customer = recs[0]
customerid = customer.customerid
if customerid == userorgid:
return {
"widgettype": "Text",
"options": {"text": "❌ 不能给自己进行代客充值", "color": "#EF4444"}
}
# Create payment log in unipay for audit trail
unipay_dbname = get_module_dbname('unipay')
async with db.sqlorContext(unipay_dbname) as unipay_sor:
plog_id = getID()
biz_date = await get_business_date(sor)
now_str = timestampstr()
plog_data = {
"id": plog_id,
"customerid": customerid,
"channelid": "proxy",
"payment_name": "充值",
"payer_client_ip": "admin_proxy",
"amount_total": amount,
"pay_feerate": 0.0,
"pay_fee": 0.0,
"currency": "CNY",
"payment_status": "1",
"init_timestamp": now_str,
"payed_timestamp": now_str,
"cancel_timestamp": "2000-01-01 00:00:00.001",
"userid": userid
}
await unipay_sor.C('payment_log', plog_data.copy())
# Perform recharge accounting
await recharge_accounting(
sor,
customerid,
'RECHARGE',
plog_id,
biz_date,
amount,
0.0
)
debug(f'Proxy recharge: user={username}, customerid={customerid}, amount={amount}, operator={userid}')
orgname = customer.orgname or ''
return {
"widgettype": "Text",
"options": {
"text": f"✅ 代客充值成功 — 已为用户 {username} ({orgname}) 充值 ¥{amount:.2f}",
"color": "#22C55E",
"fontSize": "14px",
"fontWeight": "500"
}
}