fix: separate penalty czjilu from merchant recharge and correct finance stats
This commit is contained in:
81
products/czjilu_types.py
Normal file
81
products/czjilu_types.py
Normal file
@@ -0,0 +1,81 @@
|
||||
"""czjilu 充值类型常量与查询辅助(避免罚款与商家充值混用 leixing=4)。"""
|
||||
from django.conf import settings
|
||||
from django.db.models import Q
|
||||
|
||||
# 与 czjilu.leixing 一致
|
||||
CZJILU_LEIXING_HUIYUAN = 1
|
||||
CZJILU_LEIXING_YAJIN = 2
|
||||
CZJILU_LEIXING_JIFEN = 3
|
||||
CZJILU_LEIXING_SHANGJIA = 4
|
||||
CZJILU_LEIXING_KAOHE = 5
|
||||
CZJILU_LEIXING_FAKUAN = 6
|
||||
|
||||
CZJILU_PAID_STATUS = 3
|
||||
|
||||
FAKUAN_ORDER_PREFIX = 'FK'
|
||||
PENALTY_SHUOMING_MARKER = '罚款'
|
||||
PENALTY_FADAN_TAG = '#fadan:'
|
||||
|
||||
|
||||
def penalty_cz_shuoming(fadan_id):
|
||||
"""罚款微信支付/抵扣流水说明(含罚单 ID 便于对账)。"""
|
||||
desc = getattr(settings, 'FAKUAN_PAY_DESCRIPTION', '罚款缴纳')
|
||||
return f'{desc}{PENALTY_FADAN_TAG}{fadan_id}'
|
||||
|
||||
|
||||
def is_legacy_penalty_leixing4(cz):
|
||||
"""历史误写 leixing=4 的罚款流水。"""
|
||||
dingdan = (getattr(cz, 'dingdan_id', None) or '').strip()
|
||||
shuoming = (getattr(cz, 'shuoming', None) or '')
|
||||
if dingdan.startswith(FAKUAN_ORDER_PREFIX):
|
||||
return True
|
||||
if PENALTY_SHUOMING_MARKER in shuoming:
|
||||
return True
|
||||
if PENALTY_FADAN_TAG in shuoming:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def is_penalty_czjilu(cz):
|
||||
leixing = getattr(cz, 'leixing', None)
|
||||
if leixing == CZJILU_LEIXING_FAKUAN:
|
||||
return True
|
||||
if leixing == CZJILU_LEIXING_SHANGJIA:
|
||||
return is_legacy_penalty_leixing4(cz)
|
||||
return False
|
||||
|
||||
|
||||
def is_merchant_recharge_czjilu(cz):
|
||||
return (
|
||||
getattr(cz, 'leixing', None) == CZJILU_LEIXING_SHANGJIA
|
||||
and not is_legacy_penalty_leixing4(cz)
|
||||
)
|
||||
|
||||
|
||||
def exclude_penalty_from_cz_qs(qs):
|
||||
"""从 czjilu 查询中排除罚款流水(含历史 leixing=4 误标)。"""
|
||||
return qs.exclude(
|
||||
Q(leixing=CZJILU_LEIXING_FAKUAN)
|
||||
| Q(leixing=CZJILU_LEIXING_SHANGJIA, dingdan_id__startswith=FAKUAN_ORDER_PREFIX)
|
||||
| Q(leixing=CZJILU_LEIXING_SHANGJIA, shuoming__icontains=PENALTY_SHUOMING_MARKER)
|
||||
| Q(leixing=CZJILU_LEIXING_SHANGJIA, shuoming__icontains=PENALTY_FADAN_TAG)
|
||||
)
|
||||
|
||||
|
||||
def merchant_recharge_cz_qs(qs):
|
||||
"""仅真·商家余额充值(微信 CzSJ… 或 leixing=4 且非罚款)。"""
|
||||
prefix = getattr(settings, 'SHANGJIA_CZ_PREFIX', 'CzSJ')
|
||||
return exclude_penalty_from_cz_qs(qs).filter(
|
||||
leixing=CZJILU_LEIXING_SHANGJIA,
|
||||
dingdan_id__startswith=prefix,
|
||||
)
|
||||
|
||||
|
||||
def penalty_payment_cz_qs(qs):
|
||||
"""罚款支付流水(微信 FK… 或 leixing=6 / 历史误标)。"""
|
||||
return qs.filter(
|
||||
Q(leixing=CZJILU_LEIXING_FAKUAN)
|
||||
| Q(leixing=CZJILU_LEIXING_SHANGJIA, dingdan_id__startswith=FAKUAN_ORDER_PREFIX)
|
||||
| Q(leixing=CZJILU_LEIXING_SHANGJIA, shuoming__icontains=PENALTY_SHUOMING_MARKER)
|
||||
| Q(leixing=CZJILU_LEIXING_SHANGJIA, shuoming__icontains=PENALTY_FADAN_TAG)
|
||||
)
|
||||
41
products/migrations/0010_backfill_penalty_czjilu_leixing.py
Normal file
41
products/migrations/0010_backfill_penalty_czjilu_leixing.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# 历史罚款 czjilu 从 leixing=4 纠正为 6,club_id 对齐罚单申请人俱乐部
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
from products.czjilu_types import (
|
||||
CZJILU_LEIXING_FAKUAN,
|
||||
CZJILU_LEIXING_SHANGJIA,
|
||||
is_legacy_penalty_leixing4,
|
||||
)
|
||||
|
||||
|
||||
def _backfill_penalty_czjilu(apps, schema_editor):
|
||||
Czjilu = apps.get_model('products', 'Czjilu')
|
||||
Penalty = apps.get_model('orders', 'Penalty')
|
||||
|
||||
for cz in Czjilu.objects.filter(leixing=CZJILU_LEIXING_SHANGJIA).iterator():
|
||||
if not is_legacy_penalty_leixing4(cz):
|
||||
continue
|
||||
updates = {'leixing': CZJILU_LEIXING_FAKUAN}
|
||||
shuoming = (cz.shuoming or '')
|
||||
if '#fadan:' in shuoming:
|
||||
try:
|
||||
fadan_id = int(shuoming.split('#fadan:')[1].split()[0].strip())
|
||||
fadan = Penalty.objects.filter(id=fadan_id).first()
|
||||
if fadan and getattr(fadan, 'ClubID', None):
|
||||
updates['club_id'] = fadan.ClubID
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
Czjilu.objects.filter(pk=cz.pk).update(**updates)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('products', '0006_member_trial_fields'),
|
||||
('orders', '0009_penalty_bonus_lock_fields'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(_backfill_penalty_czjilu, migrations.RunPython.noop),
|
||||
]
|
||||
@@ -215,7 +215,10 @@ class Czjilu(QModel):
|
||||
zhuangtai = models.IntegerField(null=True, blank=True, verbose_name='订单状态')
|
||||
yonghuid = models.CharField(max_length=7, db_index=True, verbose_name='用户ID')
|
||||
jine = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='订单金额')
|
||||
leixing = models.IntegerField(null=True, blank=True, verbose_name='充值类型,1:会员,2:押金,3:积分,4:商家')
|
||||
leixing = models.IntegerField(
|
||||
null=True, blank=True,
|
||||
verbose_name='充值类型,1:会员,2:押金,3:积分,4:商家充值,5:考核,6:罚款缴纳',
|
||||
)
|
||||
shuoming = models.CharField(max_length=100, null=True, blank=True, verbose_name='订单说明')
|
||||
club_id = models.CharField(
|
||||
max_length=16, default='xq', db_index=True, verbose_name='所属俱乐部',
|
||||
|
||||
@@ -2278,6 +2278,14 @@ class ShangjiaHuitiao(View):
|
||||
logger.error(f"商家订单不存在: {out_trade_no}")
|
||||
return self.wechat_response('FAIL', '订单不存在')
|
||||
|
||||
from products.czjilu_types import is_merchant_recharge_czjilu
|
||||
if not is_merchant_recharge_czjilu(order):
|
||||
logger.error(
|
||||
'非商家充值订单误入商家回调: %s, leixing=%s, shuoming=%s',
|
||||
out_trade_no, order.leixing, order.shuoming,
|
||||
)
|
||||
return self.wechat_response('FAIL', '订单类型错误')
|
||||
|
||||
# 5. 检查订单状态是否为未支付(9)
|
||||
if order.zhuangtai != 9:
|
||||
logger.warning(f"商家订单状态不是未支付: {order.dingdan_id}, 当前状态: {order.zhuangtai}")
|
||||
@@ -5986,16 +5994,30 @@ class DsqrgmdhView(APIView):
|
||||
action_desc = f"缴纳罚款 {target_price}元"
|
||||
|
||||
shuoming = f"{identity['name']}抵扣 {action_desc},抵扣金额{required}元"
|
||||
cz_leixing = leixing
|
||||
cz_club_id = club_id
|
||||
cz_zhuangtai = 1
|
||||
if leixing == 4:
|
||||
from jituan.services.club_penalty import penalty_cz_club_id
|
||||
from products.czjilu_types import (
|
||||
CZJILU_LEIXING_FAKUAN,
|
||||
CZJILU_PAID_STATUS,
|
||||
PENALTY_FADAN_TAG,
|
||||
)
|
||||
cz_leixing = CZJILU_LEIXING_FAKUAN
|
||||
cz_club_id = penalty_cz_club_id(fadan_obj)
|
||||
cz_zhuangtai = CZJILU_PAID_STATUS
|
||||
shuoming = f"{shuoming}{PENALTY_FADAN_TAG}{fadan_obj.id}"
|
||||
|
||||
member_purchase_days = 0
|
||||
czjilu_kwargs = {
|
||||
'dingdan_id': dingdan_id,
|
||||
'zhuangtai': 1,
|
||||
'zhuangtai': cz_zhuangtai,
|
||||
'yonghuid': yonghuid,
|
||||
'jine': required,
|
||||
'leixing': leixing,
|
||||
'leixing': cz_leixing,
|
||||
'shuoming': shuoming,
|
||||
'club_id': club_id,
|
||||
'club_id': cz_club_id,
|
||||
}
|
||||
if leixing == 1:
|
||||
from jituan.services.member_recharge import club_huiyuan_sellable
|
||||
|
||||
Reference in New Issue
Block a user