fix: 修复微信入账重复统计,入账幂等防双记
This commit is contained in:
26
config/migrations/0007_platform_income_log.py
Normal file
26
config/migrations/0007_platform_income_log.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('config', '0006_display_club_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='PlatformIncomeLog',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('biz_ref', models.CharField(db_index=True, max_length=64, unique=True, verbose_name='业务单号')),
|
||||
('club_id', models.CharField(db_index=True, default='xq', max_length=16, verbose_name='俱乐部ID')),
|
||||
('amount', models.DecimalField(decimal_places=2, max_digits=12, verbose_name='入账金额')),
|
||||
('CreateTime', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': '平台入账幂等日志',
|
||||
'verbose_name_plural': '平台入账幂等日志',
|
||||
'db_table': 'platform_income_log',
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -362,6 +362,17 @@ class DailyPayoutStat(QModel):
|
||||
return f"{self.date} - 出款{self.total_amount}元 - {self.total_count}笔"
|
||||
|
||||
|
||||
class PlatformIncomeLog(QModel):
|
||||
"""微信入账幂等日志:同一 biz_ref 只记一次日收入与 szjilu。"""
|
||||
biz_ref = models.CharField(max_length=64, unique=True, db_index=True, verbose_name='业务单号')
|
||||
club_id = models.CharField(max_length=16, default='xq', db_index=True, verbose_name='俱乐部ID')
|
||||
amount = models.DecimalField(max_digits=12, decimal_places=2, verbose_name='入账金额')
|
||||
CreateTime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
|
||||
|
||||
class Meta:
|
||||
db_table = 'platform_income_log'
|
||||
verbose_name = '平台入账幂等日志'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
|
||||
class PopupPage(QModel):
|
||||
|
||||
@@ -33,7 +33,6 @@ from jituan.services.club_config import get_huiyuan_fenchong
|
||||
from jituan.services.club_penalty import resolve_gsfenhong_club_id
|
||||
from jituan.services.club_user import get_user_club_id
|
||||
from jituan.services.wechat_pay import club_id_from_czjilu, get_wechat_v2_config
|
||||
from orders.utils import update_daily_income
|
||||
from products.models import Czjilu, DuociFenhong, Gsfenhong, Huiyuan, Huiyuangoumai
|
||||
from users.business_models import User
|
||||
from users.models import UserDashou, UserGuanshi, UserZuzhang
|
||||
@@ -331,9 +330,8 @@ def fulfill_member_recharge(dingdan_id, paid_amount_yuan=None, source='callback'
|
||||
|
||||
jine_decimal = Decimal(str(order.jine))
|
||||
try:
|
||||
update_daily_income(jine_decimal, club_id)
|
||||
from jituan.services.szjilu_accounting import apply_szjilu_income
|
||||
apply_szjilu_income(jine_decimal, club_id)
|
||||
from jituan.services.szjilu_accounting import record_wechat_income_once
|
||||
record_wechat_income_once(jine_decimal, club_id, biz_ref=f'cz:{dingdan_id}')
|
||||
except Exception as exc:
|
||||
logger.error('会员收支统计更新失败: %s', exc, exc_info=True)
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
"""各俱乐部全局收支流水(szjilu)统一记账。"""
|
||||
import logging
|
||||
from decimal import Decimal
|
||||
|
||||
from django.db import transaction
|
||||
from django.db import IntegrityError, transaction
|
||||
|
||||
from config.models import Szjilu
|
||||
from config.models import PlatformIncomeLog, Szjilu
|
||||
from jituan.constants import CLUB_ID_DEFAULT
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_ZERO = Decimal('0.00')
|
||||
_SZJILU_DEFAULTS = {
|
||||
'TotalIncome': _ZERO,
|
||||
@@ -40,6 +43,39 @@ def apply_szjilu_income(amount, club_id=None):
|
||||
szjilu.save()
|
||||
|
||||
|
||||
def record_wechat_income_once(amount, club_id=None, biz_ref=None):
|
||||
"""
|
||||
微信入账:同一 biz_ref 只记一次 daily_income_stat + szjilu。
|
||||
返回 True=本次新入账;False=已记过(重复回调/重复代码路径)。
|
||||
"""
|
||||
ref = (biz_ref or '').strip()
|
||||
if not ref:
|
||||
raise ValueError('biz_ref 不能为空')
|
||||
cid = normalize_szjilu_club_id(club_id)
|
||||
jine = Decimal(str(amount))
|
||||
from orders.utils import update_daily_income
|
||||
|
||||
try:
|
||||
with transaction.atomic():
|
||||
PlatformIncomeLog.objects.create(
|
||||
biz_ref=ref,
|
||||
club_id=cid,
|
||||
amount=jine,
|
||||
)
|
||||
except IntegrityError:
|
||||
logger.info('平台入账已存在,跳过重复记账 biz_ref=%s', ref)
|
||||
return False
|
||||
|
||||
try:
|
||||
update_daily_income(jine, cid)
|
||||
apply_szjilu_income(jine, cid)
|
||||
except Exception:
|
||||
PlatformIncomeLog.objects.filter(biz_ref=ref).delete()
|
||||
raise
|
||||
logger.info('平台入账记账成功 biz_ref=%s club=%s amount=%s', ref, cid, jine)
|
||||
return True
|
||||
|
||||
|
||||
def apply_szjilu_expense(amount, club_id=None):
|
||||
"""平台出款/支出:总收益减少,总支出、今日支出增加。"""
|
||||
jine = Decimal(str(amount))
|
||||
|
||||
@@ -43,7 +43,7 @@ from utils.fadan_utils import check_fadan_qiangdan_eligible
|
||||
|
||||
from orders.utils import (
|
||||
calc_shangjia_order_fencheng,
|
||||
update_daily_income, update_daily_payout,
|
||||
update_daily_payout,
|
||||
settle_shangjia_order_guanshi_fenhong
|
||||
)
|
||||
from shop.utils import calculate_pingtai_and_dianpu_shouyi, validate_shangpin_and_dianpu, update_dianpu_daily_stat
|
||||
@@ -307,10 +307,10 @@ class WechatPayNotifyView(APIView):
|
||||
|
||||
|
||||
# 更新收支记录(总累计)
|
||||
self._update_szjilu(dingdan.Amount, getattr(dingdan, 'ClubID', None))
|
||||
|
||||
# 更新每日收入统计
|
||||
update_daily_income(dingdan.Amount, getattr(dingdan, 'ClubID', None))
|
||||
from jituan.services.szjilu_accounting import record_wechat_income_once
|
||||
record_wechat_income_once(
|
||||
dingdan.Amount, getattr(dingdan, 'ClubID', None), biz_ref=f'order:{out_trade_no}',
|
||||
)
|
||||
|
||||
# 构建通知数据(你的 _get_game_type_name 方法保留在视图里直接用)
|
||||
order_info = {
|
||||
@@ -568,10 +568,12 @@ class PaymentVerifyView(APIView):
|
||||
|
||||
|
||||
# 更新收支记录
|
||||
self._update_szjilu(dingdan.Amount, getattr(dingdan, 'ClubID', None))
|
||||
|
||||
# 更新每日收入统计
|
||||
update_daily_income(dingdan.Amount, getattr(dingdan, 'ClubID', None))
|
||||
from jituan.services.szjilu_accounting import record_wechat_income_once
|
||||
record_wechat_income_once(
|
||||
dingdan.Amount,
|
||||
getattr(dingdan, 'ClubID', None),
|
||||
biz_ref=f'order:{dingdan.OrderID}',
|
||||
)
|
||||
|
||||
def _query_wechat_payment(self, out_trade_no):
|
||||
"""
|
||||
|
||||
@@ -32,7 +32,6 @@ from rest_framework.throttling import AnonRateThrottle
|
||||
|
||||
# ==================== 项目工具函数 ====================
|
||||
from utils.oss_utils import validate_image, upload_to_oss, delete_from_oss
|
||||
from orders.utils import update_daily_income
|
||||
from backend.utils import (
|
||||
update_guanshi_daily_by_action,
|
||||
update_guanshi_xufei_daily,
|
||||
@@ -705,10 +704,12 @@ class YajinHuitiao(View):
|
||||
# 获取订单金额(确保是Decimal类型)
|
||||
jine_decimal = Decimal(str(order.jine)) if not isinstance(order.jine, Decimal) else order.jine
|
||||
|
||||
# 查询或创建ID=1的收支记录
|
||||
update_daily_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
from jituan.services.szjilu_accounting import apply_szjilu_income
|
||||
apply_szjilu_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
from jituan.services.szjilu_accounting import record_wechat_income_once
|
||||
record_wechat_income_once(
|
||||
jine_decimal,
|
||||
getattr(order, 'club_id', None),
|
||||
biz_ref=f'cz:{order.dingdan_id}',
|
||||
)
|
||||
|
||||
logger.info(f"收支记录更新成功: 订单{order.dingdan_id}, 金额{jine_decimal}元")
|
||||
|
||||
@@ -1208,13 +1209,13 @@ class JifenHuitiao(View):
|
||||
|
||||
# 更新收支记录表
|
||||
try:
|
||||
# 获取订单金额(确保是Decimal类型)
|
||||
jine_decimal = Decimal(str(order.jine)) if not isinstance(order.jine, Decimal) else order.jine
|
||||
update_daily_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
|
||||
update_daily_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
from jituan.services.szjilu_accounting import apply_szjilu_income
|
||||
apply_szjilu_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
from jituan.services.szjilu_accounting import record_wechat_income_once
|
||||
record_wechat_income_once(
|
||||
jine_decimal,
|
||||
getattr(order, 'club_id', None),
|
||||
biz_ref=f'cz:{order.dingdan_id}',
|
||||
)
|
||||
|
||||
logger.info(f"收支记录更新成功: 订单{order.dingdan_id}, 金额{jine_decimal}元")
|
||||
|
||||
@@ -2343,14 +2344,13 @@ class ShangjiaHuitiao(View):
|
||||
# ===== 在这里添加收支记录更新代码 =====
|
||||
# 更新收支记录表
|
||||
try:
|
||||
# 获取订单金额(确保是Decimal类型)
|
||||
jine_decimal = Decimal(str(order.jine)) if not isinstance(order.jine, Decimal) else order.jine
|
||||
|
||||
update_daily_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
|
||||
update_daily_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
from jituan.services.szjilu_accounting import apply_szjilu_income
|
||||
apply_szjilu_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
from jituan.services.szjilu_accounting import record_wechat_income_once
|
||||
record_wechat_income_once(
|
||||
jine_decimal,
|
||||
getattr(order, 'club_id', None),
|
||||
biz_ref=f'cz:{order.dingdan_id}',
|
||||
)
|
||||
|
||||
logger.info(f"收支记录更新成功: 订单{order.dingdan_id}, 金额{jine_decimal}元")
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ from users.fadan_fenhong_utils import process_fadan_fenhong
|
||||
|
||||
from orders.utils import (
|
||||
update_daily_payout,
|
||||
update_daily_income, settle_shangjia_order_guanshi_fenhong
|
||||
settle_shangjia_order_guanshi_fenhong
|
||||
)
|
||||
from backend.utils import (
|
||||
update_dashou_daily_by_action, update_guanshi_daily_by_action,
|
||||
@@ -11967,13 +11967,13 @@ class FaKuanHuitiaoView(View):
|
||||
|
||||
# 9. 更新收支记录表
|
||||
try:
|
||||
|
||||
# 获取订单金额(确保是Decimal类型)
|
||||
jine_decimal = Decimal(str(order.jine)) if not isinstance(order.jine, Decimal) else order.jine
|
||||
|
||||
update_daily_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
from jituan.services.szjilu_accounting import apply_szjilu_income
|
||||
apply_szjilu_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
from jituan.services.szjilu_accounting import record_wechat_income_once
|
||||
record_wechat_income_once(
|
||||
jine_decimal,
|
||||
getattr(order, 'club_id', None),
|
||||
biz_ref=f'cz:{order.dingdan_id}',
|
||||
)
|
||||
|
||||
logger.info(f"收支记录更新成功: 订单{order.dingdan_id}, 金额{jine_decimal}元")
|
||||
|
||||
@@ -12530,11 +12530,13 @@ class KaohePayCallbackView(View):
|
||||
# 更新收支记录
|
||||
try:
|
||||
jine_decimal = Decimal(str(order.jine))
|
||||
update_daily_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
logger.info(f"更新每日收入成功: {jine_decimal}元")
|
||||
from jituan.services.szjilu_accounting import apply_szjilu_income
|
||||
apply_szjilu_income(jine_decimal, getattr(order, 'club_id', None))
|
||||
logger.info(f"更新收支记录成功")
|
||||
from jituan.services.szjilu_accounting import record_wechat_income_once
|
||||
record_wechat_income_once(
|
||||
jine_decimal,
|
||||
getattr(order, 'club_id', None),
|
||||
biz_ref=f'cz:{order.dingdan_id}',
|
||||
)
|
||||
logger.info(f"更新收支记录成功: {jine_decimal}元")
|
||||
except Exception as e:
|
||||
logger.error(f"更新收支记录失败: {str(e)}", exc_info=True)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user