accounting/wwwroot/api/dayend.dspy

49 lines
2.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 日终切日任务端点:日结余额快照 + 日结总账 + 营业日期推进
# GET /accounting/api/dayend.dspy
#
# 安全:本端点是定时任务入口(写库),只允许本机调用——与 fetch_forex_rates.dspy 同模式。
# 判定依据 client_ipnginx 用 $proxy_add_x_forwarded_for 追加模式、中间件取链尾值,
# 外部伪造 X-Forwarded-For 会被追加真实 IP 到链尾,伪造不成立;且应用端口不对外开放。
_ip = request.get('client_ip') or ''
if _ip not in ('127.0.0.1', '::1', 'localhost'):
return json.dumps({'success': False, 'message': '仅允许本机调用(定时任务入口)'},
ensure_ascii=False)
from sqlor.dbpools import get_sor_context
# 切日三步(同一 sor 上下文,全成才提交):
# 1. dayend_balance —— 上一营业日余额快照acc_balance 补齐无当日行的账户)
# 2. accounting_ledger —— 上一营业日总账delete+insert 幂等重建 ledger 当日行)
# 3. new_business_date —— params.business_date 推进 +1 天
# 顺序不可颠倒:前两步都读「上一营业日」,推进日期必须在最后。
async with get_sor_context(request._run_ns, 'accounting') as sor:
try:
from datetime import date
from accounting.dayend_balance import dayend_balance
from accounting.ledger import accounting_ledger
from appbase.businessdate import get_business_date, new_business_date
old_bd = await get_business_date(sor)
# 幂等守卫business_date 已到今天则跳过cron 重跑/手工重放不会多跳日期)
today = date.today().isoformat()
if old_bd >= today:
return json.dumps({
'success': True, 'skipped': True,
'business_date': old_bd,
'message': '已是当日营业日期,跳过切日(幂等)',
}, ensure_ascii=False)
snap_date = await dayend_balance(sor)
await accounting_ledger(sor)
await new_business_date(sor)
new_bd = await get_business_date(sor)
await sor.sqlExe("COMMIT", {})
return json.dumps({
'success': True,
'business_date': '%s -> %s' % (old_bd, new_bd),
'snapshot_date': snap_date,
}, ensure_ascii=False)
except Exception as e:
return json.dumps({'success': False, 'message': 'dayend failed: %s' % str(e)[:200]},
ensure_ascii=False)