fix: 罚单申请时锁定分红利率与应得金额,缴纳按锁定值入账
This commit is contained in:
@@ -6658,6 +6658,8 @@ class FaKuanChuangJianView(APIView):
|
||||
ImageURL=relative_url,
|
||||
Purpose=1
|
||||
)
|
||||
from users.fadan_fenhong_utils import lock_penalty_bonus
|
||||
lock_penalty_bonus(penalty)
|
||||
|
||||
logger.info(f"罚款创建成功: {penalty.id}")
|
||||
return Response({'code': 0, 'msg': '罚款已创建', 'data': {'id': penalty.id}})
|
||||
@@ -6760,6 +6762,8 @@ class FineApplyView(APIView):
|
||||
ImageURL=relative_url,
|
||||
Purpose=1
|
||||
)
|
||||
from users.fadan_fenhong_utils import lock_penalty_bonus
|
||||
lock_penalty_bonus(penalty)
|
||||
|
||||
logger.info(f"客服罚款申请成功: 订单 {OrderID}, 打手 {dashou_id}, 金额 {FineAmount}")
|
||||
return Response({'code': 0, 'msg': '罚款已生成', 'data': {'id': penalty.id}})
|
||||
|
||||
31
orders/migrations/0009_penalty_bonus_lock_fields.py
Normal file
31
orders/migrations/0009_penalty_bonus_lock_fields.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('orders', '0008_order_waibu_penalty_staff'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='penalty',
|
||||
name='ApplicantBonusRate',
|
||||
field=models.DecimalField(
|
||||
db_column='shenqingren_fenhong_lilv',
|
||||
decimal_places=4,
|
||||
default=0.0,
|
||||
max_digits=5,
|
||||
verbose_name='申请人分红锁定利率',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='penalty',
|
||||
name='BonusCredited',
|
||||
field=models.BooleanField(
|
||||
db_column='fenhong_yiruzhang',
|
||||
default=False,
|
||||
verbose_name='分红是否已入账',
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -510,6 +510,14 @@ class Penalty(QModel):
|
||||
max_digits=12, decimal_places=2, default=0.00,
|
||||
db_column='shenqingren_fenhong_jine', verbose_name='申请人分红金额',
|
||||
)
|
||||
ApplicantBonusRate = models.DecimalField(
|
||||
max_digits=5, decimal_places=4, default=0.0000,
|
||||
db_column='shenqingren_fenhong_lilv', verbose_name='申请人分红锁定利率',
|
||||
)
|
||||
BonusCredited = models.BooleanField(
|
||||
default=False,
|
||||
db_column='fenhong_yiruzhang', verbose_name='分红是否已入账',
|
||||
)
|
||||
ClubID = models.CharField(
|
||||
max_length=16, default='xq', db_index=True,
|
||||
db_column='club_id', verbose_name='所属俱乐部',
|
||||
|
||||
@@ -64,6 +64,8 @@ from jituan.services.club_config import get_commission_rate, get_commission_rate
|
||||
from jituan.services.club_context import resolve_club_id_from_request
|
||||
from jituan.services.club_user import get_payment_openid
|
||||
from jituan.services.club_penalty import resolve_penalty_club_id
|
||||
from users.fadan_fenhong_utils import lock_penalty_bonus
|
||||
from users.fadan_fenhong_utils import lock_penalty_bonus
|
||||
from products.models import Shangpin, ShangpinLeixing, Huiyuangoumai
|
||||
from users.models import UserDashou, UserShangjia, UserBoss
|
||||
from users.business_models import User
|
||||
@@ -2293,25 +2295,21 @@ class ShangjiaDingdanXiangqingView(APIView):
|
||||
'shensuliyou': fadan_obj.AppealReason or '',
|
||||
'tongyi_chufaliyou': fadan_obj.ApproveReason or '',
|
||||
'bohuiliyou': fadan_obj.RejectReason or '',
|
||||
'yingde_fenhong': float(fadan_obj.ApplicantBonusAmount or 0),
|
||||
'fenhong_lilv': float(fadan_obj.ApplicantBonusRate or 0),
|
||||
'fenhong_yiruzhang': bool(fadan_obj.BonusCredited),
|
||||
'CreateTime': ct,
|
||||
'create_time': ct,
|
||||
'UpdateTime': ut,
|
||||
'update_time': ut,
|
||||
}
|
||||
|
||||
# 7. 商家分红利率(申请页预览):个人记录优先,否则全局 fadan_fenhong_lilv shenfen=5
|
||||
# 7. 商家分红利率(申请页预览):与缴纳后分红同一套规则
|
||||
fenhong_lilv = 0.0
|
||||
try:
|
||||
last_fenhong = PenaltyBonus.query.filter(
|
||||
BeneficiaryID=yonghuid,
|
||||
Identity=1, # fadan_fenhong 表:1=商家
|
||||
).order_by('-CreateTime').first()
|
||||
if last_fenhong and last_fenhong.IndividualRate:
|
||||
fenhong_lilv = float(last_fenhong.IndividualRate)
|
||||
else:
|
||||
global_rate = PenaltyBonusRate.query.filter(Identity=5).first()
|
||||
if global_rate and global_rate.Rate:
|
||||
fenhong_lilv = float(global_rate.Rate)
|
||||
from users.fadan_fenhong_utils import get_merchant_fenhong_lilv
|
||||
order_club_id = getattr(order, 'ClubID', None) or 'xq'
|
||||
fenhong_lilv = get_merchant_fenhong_lilv(yonghuid, club_id=order_club_id)
|
||||
except Exception as e:
|
||||
logger.warning(f'获取分红利率失败: {e}')
|
||||
|
||||
@@ -6531,7 +6529,7 @@ class ShangjiaFakuanApplyView(APIView):
|
||||
staff_kefu_id = getattr(staff_member, 'staff_user_id', None) or None
|
||||
|
||||
with transaction.atomic():
|
||||
Penalty.query.create(
|
||||
fadan = Penalty.query.create(
|
||||
PenalizedUserID=dashou_id,
|
||||
ApplicantID=shangjia_id, # 申请人为当前商家
|
||||
Identity=1, # 被打者身份:1=打手
|
||||
@@ -6544,6 +6542,7 @@ class ShangjiaFakuanApplyView(APIView):
|
||||
ClubID=resolve_penalty_club_id(order=order, penalized_user_id=dashou_id),
|
||||
ShopStaffUserID=staff_kefu_id,
|
||||
)
|
||||
lock_penalty_bonus(fadan)
|
||||
logger.info(f"商家{shangjia_id}对订单{dingdan_id}打手{dashou_id}罚款成功,金额{fakuanjine}")
|
||||
return Response({'code': 0, 'msg': '罚款申请已提交'})
|
||||
|
||||
@@ -6647,6 +6646,7 @@ class ShangjiaFakuaiXiugaiView(APIView):
|
||||
fadan.ProcessorID = processor_id
|
||||
fadan.ProcessorIdentity = 5 # 小程序商家自行处理
|
||||
fadan.save()
|
||||
lock_penalty_bonus(fadan)
|
||||
return Response({'code': 0, 'msg': '罚款修改成功'})
|
||||
|
||||
def _cancel_penalty(self, fadan, liyou, processor_id=None):
|
||||
@@ -6685,6 +6685,7 @@ class ShangjiaFakuaiXiugaiView(APIView):
|
||||
fadan.ProcessorID = processor_id
|
||||
fadan.ProcessorIdentity = 5
|
||||
fadan.save()
|
||||
lock_penalty_bonus(fadan)
|
||||
logger.info(f"商家重新申请罚单{fadan.id},金额={jine}")
|
||||
return Response({'code': 0, 'msg': '已重新申请罚款'})
|
||||
|
||||
|
||||
@@ -3096,7 +3096,7 @@ class ShopFineApplyView(APIView):
|
||||
|
||||
# ---------- 6. 创建罚单 ----------
|
||||
with transaction.atomic():
|
||||
Penalty.query.create(
|
||||
penalty = Penalty.query.create(
|
||||
PenalizedUserID=dashou_id,
|
||||
ApplicantID=str(shop_id), # 申请人记为店铺ID
|
||||
Identity=1, # 被处罚人身份:1 打手
|
||||
@@ -3107,6 +3107,8 @@ class ShopFineApplyView(APIView):
|
||||
AffectsGrabbing=yingxiang_qiangdan,
|
||||
ApplicantIdentity=4, # 申请人身份:4 店铺管理员
|
||||
)
|
||||
from users.fadan_fenhong_utils import lock_penalty_bonus
|
||||
lock_penalty_bonus(penalty)
|
||||
logger.info(f"本地罚款成功: 订单 {dingdan_id}, 打手 {dashou_id}, 金额 {fakuanjine}")
|
||||
return Response({'code': 200, 'msg': '罚款已生成'})
|
||||
|
||||
|
||||
@@ -20,89 +20,179 @@ IDENTITY_MAP = {
|
||||
5: {'fenhong': 1, 'lilv': 5}, # 商家
|
||||
}
|
||||
|
||||
MERCHANT_LILV_SHENFEN = 5
|
||||
MERCHANT_FENHONG_SHENFEN = 1
|
||||
|
||||
|
||||
def _normalize_club_id(club_id):
|
||||
cid = (club_id or '').strip()
|
||||
return cid or 'xq'
|
||||
|
||||
|
||||
def _read_global_fenhong_rate(lilv_shenfen):
|
||||
try:
|
||||
global_rate = PenaltyBonusRate.objects.get(Identity=lilv_shenfen)
|
||||
rate = global_rate.Rate
|
||||
if rate is not None and Decimal(str(rate)) > 0:
|
||||
return rate
|
||||
except PenaltyBonusRate.DoesNotExist:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def _get_fenhong_rate(fenhongzhe_id, fenhong_shenfen, lilv_shenfen, club_id='xq'):
|
||||
"""
|
||||
获取分红利率:个人单独利率 > 0 时优先;否则回退全局 fadan_fenhong_lilv。
|
||||
"""
|
||||
club_id = _normalize_club_id(club_id)
|
||||
try:
|
||||
individual = PenaltyBonus.objects.get(
|
||||
BeneficiaryID=fenhongzhe_id,
|
||||
Identity=fenhong_shenfen,
|
||||
ClubID=club_id,
|
||||
IsIndividualRate=True,
|
||||
)
|
||||
ind_rate = individual.IndividualRate
|
||||
if ind_rate is not None and Decimal(str(ind_rate)) > 0:
|
||||
return ind_rate
|
||||
except PenaltyBonus.DoesNotExist:
|
||||
pass
|
||||
|
||||
return _read_global_fenhong_rate(lilv_shenfen)
|
||||
|
||||
|
||||
def _calc_bonus_amount(fine_amount, rate):
|
||||
if fine_amount is None or rate is None:
|
||||
return Decimal('0.00')
|
||||
fine = Decimal(str(fine_amount))
|
||||
r = Decimal(str(rate))
|
||||
if fine <= 0 or r <= 0:
|
||||
return Decimal('0.00')
|
||||
return (fine * r).quantize(Decimal('0.01'))
|
||||
|
||||
|
||||
def lock_penalty_bonus(fadan):
|
||||
"""
|
||||
申请/改价/再次申请时锁定应得分红利率与金额,写入罚单供前端展示;
|
||||
缴纳时按此锁定值入账,不再现场重算。
|
||||
"""
|
||||
if getattr(fadan, 'BonusCredited', False):
|
||||
return fadan
|
||||
|
||||
zero_rate = Decimal('0.0000')
|
||||
zero_amount = Decimal('0.00')
|
||||
applicant_id = fadan.ApplicantID
|
||||
src_shenfen = fadan.ApplicantIdentity
|
||||
|
||||
if not applicant_id or src_shenfen not in IDENTITY_MAP:
|
||||
fadan.ApplicantBonusRate = zero_rate
|
||||
fadan.ApplicantBonusAmount = zero_amount
|
||||
fadan.save(update_fields=['ApplicantBonusRate', 'ApplicantBonusAmount'])
|
||||
return fadan
|
||||
|
||||
mapped = IDENTITY_MAP[src_shenfen]
|
||||
club_id = _normalize_club_id(fadan.ClubID)
|
||||
rate = _get_fenhong_rate(
|
||||
applicant_id, mapped['fenhong'], mapped['lilv'], club_id=club_id,
|
||||
)
|
||||
if rate is None:
|
||||
fadan.ApplicantBonusRate = zero_rate
|
||||
fadan.ApplicantBonusAmount = zero_amount
|
||||
else:
|
||||
fadan.ApplicantBonusRate = Decimal(str(rate))
|
||||
fadan.ApplicantBonusAmount = _calc_bonus_amount(fadan.FineAmount, rate)
|
||||
|
||||
fadan.save(update_fields=['ApplicantBonusRate', 'ApplicantBonusAmount'])
|
||||
return fadan
|
||||
|
||||
|
||||
def get_merchant_fenhong_lilv(yonghuid, club_id='xq'):
|
||||
"""商家申请罚单页预览利率(尚无罚单时)。"""
|
||||
club_id = _normalize_club_id(club_id)
|
||||
rate = _get_fenhong_rate(
|
||||
yonghuid,
|
||||
MERCHANT_FENHONG_SHENFEN,
|
||||
MERCHANT_LILV_SHENFEN,
|
||||
club_id=club_id,
|
||||
)
|
||||
return float(rate) if rate is not None else 0.0
|
||||
|
||||
|
||||
def process_fadan_fenhong(fadan_id):
|
||||
"""
|
||||
罚款缴纳后的分红处理(在回调中调用)
|
||||
参数:
|
||||
fadan_id: 罚单 ID
|
||||
返回:
|
||||
(success, message)
|
||||
罚款缴纳后的分红入账:优先使用申请时已锁定的利率/金额,不现场重算。
|
||||
"""
|
||||
try:
|
||||
# 1. 获取罚单对象(必须是已缴纳状态)
|
||||
try:
|
||||
fadan = Penalty.objects.get(id=fadan_id, Status=2)
|
||||
except Penalty.DoesNotExist:
|
||||
logger.error(f"罚单 {fadan_id} 不存在或状态不是已缴纳")
|
||||
return False, "罚单不存在或状态异常"
|
||||
|
||||
# 防重复分红(微信回调重试时不可二次加钱)
|
||||
if fadan.ApplicantBonusAmount and Decimal(str(fadan.ApplicantBonusAmount)) > 0:
|
||||
logger.info(
|
||||
f"罚单 {fadan_id} 已分红 {fadan.ApplicantBonusAmount} 元,跳过重复处理"
|
||||
)
|
||||
if fadan.BonusCredited:
|
||||
logger.info(f"罚单 {fadan_id} 分红已入账,跳过")
|
||||
return True, "已分红"
|
||||
|
||||
# 2. 获取申请处罚者ID和身份(源身份数字)
|
||||
shenqing_chufa = fadan.ApplicantID
|
||||
src_shenfen = fadan.ApplicantIdentity
|
||||
|
||||
if not shenqing_chufa:
|
||||
logger.info(f"罚单 {fadan_id} 无申请处罚者,不进行分红")
|
||||
# 即使无申请者,也可将分红金额字段设为0(默认已是0)
|
||||
return True, "无申请处罚者,无需分红"
|
||||
|
||||
# 3. 映射身份数字
|
||||
if src_shenfen not in IDENTITY_MAP:
|
||||
logger.error(f"未知的申请处罚者身份: {src_shenfen},罚单 {fadan_id}")
|
||||
return False, f"未知身份 {src_shenfen}"
|
||||
|
||||
mapped = IDENTITY_MAP[src_shenfen]
|
||||
fenhong_shenfen = mapped['fenhong'] # 用于 FadanFenhong.shenfen
|
||||
lilv_shenfen = mapped['lilv'] # 用于 FadanFenhongLilv.shenfen
|
||||
fenhong_shenfen = mapped['fenhong']
|
||||
club_id = _normalize_club_id(fadan.ClubID)
|
||||
|
||||
# 4. 获取罚款金额
|
||||
fakuan_jine = fadan.FineAmount
|
||||
if fakuan_jine <= 0:
|
||||
logger.info(f"罚单 {fadan_id} 罚款金额为0,不产生分红")
|
||||
fadan.ApplicantBonusAmount = Decimal('0.00')
|
||||
fadan.save(update_fields=['ApplicantBonusAmount'])
|
||||
return True, "罚款金额为0,无分红"
|
||||
locked_amount = Decimal(str(fadan.ApplicantBonusAmount or 0))
|
||||
locked_rate = fadan.ApplicantBonusRate
|
||||
|
||||
# 5. 确定分红利率
|
||||
rate = _get_fenhong_rate(shenqing_chufa, fenhong_shenfen, lilv_shenfen, club_id=fadan.ClubID)
|
||||
if rate is None:
|
||||
logger.warning(f"未找到身份 {src_shenfen} (映射后 fenhong_shenfen={fenhong_shenfen}, lilv_shenfen={lilv_shenfen}) 的分红利率,罚单 {fadan_id} 不进行分红")
|
||||
fadan.ApplicantBonusAmount = Decimal('0.00')
|
||||
fadan.save(update_fields=['ApplicantBonusAmount'])
|
||||
return True, "未配置分红利率,无分红"
|
||||
if locked_amount > 0:
|
||||
fenhong_jine = locked_amount
|
||||
rate = locked_rate
|
||||
else:
|
||||
# 旧数据兼容:未锁定时按当前利率现场算一次并回写
|
||||
fakuan_jine = fadan.FineAmount
|
||||
if fakuan_jine <= 0:
|
||||
fadan.ApplicantBonusAmount = Decimal('0.00')
|
||||
fadan.save(update_fields=['ApplicantBonusAmount'])
|
||||
return True, "罚款金额为0,无分红"
|
||||
|
||||
rate = _get_fenhong_rate(
|
||||
shenqing_chufa, fenhong_shenfen, mapped['lilv'], club_id=club_id,
|
||||
)
|
||||
if rate is None:
|
||||
logger.warning(f"罚单 {fadan_id} 未配置分红利率")
|
||||
fadan.ApplicantBonusAmount = Decimal('0.00')
|
||||
fadan.save(update_fields=['ApplicantBonusAmount'])
|
||||
return True, "未配置分红利率,无分红"
|
||||
|
||||
fenhong_jine = _calc_bonus_amount(fakuan_jine, rate)
|
||||
fadan.ApplicantBonusRate = Decimal(str(rate))
|
||||
fadan.ApplicantBonusAmount = fenhong_jine
|
||||
fadan.save(update_fields=['ApplicantBonusRate', 'ApplicantBonusAmount'])
|
||||
|
||||
# 6. 计算分红金额
|
||||
fenhong_jine = (Decimal(str(fakuan_jine)) * Decimal(str(rate))).quantize(Decimal('0.01'))
|
||||
if fenhong_jine <= 0:
|
||||
logger.info(f"罚单 {fadan_id} 计算分红金额为0,无需处理")
|
||||
fadan.ApplicantBonusAmount = Decimal('0.00')
|
||||
fadan.save(update_fields=['ApplicantBonusAmount'])
|
||||
logger.info(f"罚单 {fadan_id} 锁定分红金额为0,无需入账")
|
||||
fadan.BonusCredited = True
|
||||
fadan.save(update_fields=['BonusCredited'])
|
||||
return True, "分红金额为0"
|
||||
|
||||
club_id = fadan.ClubID or 'xq'
|
||||
|
||||
# 7. 根据申请处罚者身份执行不同的分红逻辑
|
||||
# src_shenfen == 5 代表商家(源身份)
|
||||
if src_shenfen == 5:
|
||||
# 商家:分红统计累加 + 余额入账(可提现分红字段保持0,钱进商家余额)
|
||||
with transaction.atomic():
|
||||
fadan = Penalty.objects.select_for_update().get(id=fadan_id, Status=2)
|
||||
if fadan.ApplicantBonusAmount and Decimal(str(fadan.ApplicantBonusAmount)) > 0:
|
||||
logger.info(f"罚单 {fadan_id} 事务内检测到已分红,跳过")
|
||||
if fadan.BonusCredited:
|
||||
return True, "已分红"
|
||||
|
||||
if not UserShangjia.objects.filter(user__UserUID=shenqing_chufa).exists():
|
||||
logger.error(f"商家 {shenqing_chufa} 扩展表不存在,无法分红入账")
|
||||
return False, "商家资料不存在,无法分红"
|
||||
|
||||
fenhong_record, created = PenaltyBonus.objects.get_or_create(
|
||||
fenhong_record, _created = PenaltyBonus.objects.get_or_create(
|
||||
BeneficiaryID=shenqing_chufa,
|
||||
Identity=fenhong_shenfen,
|
||||
ClubID=club_id,
|
||||
@@ -111,33 +201,28 @@ def process_fadan_fenhong(fadan_id):
|
||||
'WithdrawableAmount': Decimal('0.00'),
|
||||
'BonusCount': 0,
|
||||
'IndividualRate': rate,
|
||||
'is_individual_rate': False
|
||||
}
|
||||
'IsIndividualRate': False,
|
||||
},
|
||||
)
|
||||
fenhong_record.TotalAmount += fenhong_jine
|
||||
# 可提现分红不累加,保持0
|
||||
fenhong_record.BonusCount += 1
|
||||
fenhong_record.save()
|
||||
|
||||
# 直接增加商家余额(UserShangjia.yue)
|
||||
shangjia = UserShangjia.objects.select_for_update().get(user__UserUID=shenqing_chufa)
|
||||
shangjia.yue += fenhong_jine
|
||||
shangjia.save(update_fields=['yue'])
|
||||
logger.info(f"商家 {shenqing_chufa} 余额增加 {fenhong_jine} 元")
|
||||
logger.info(f"商家 {shenqing_chufa} 余额增加 {fenhong_jine} 元(锁定值)")
|
||||
|
||||
# 更新罚单中的申请人分红金额
|
||||
fadan.ApplicantBonusAmount = fenhong_jine
|
||||
fadan.save(update_fields=['ApplicantBonusAmount'])
|
||||
fadan.BonusCredited = True
|
||||
fadan.save(update_fields=['BonusCredited'])
|
||||
|
||||
else:
|
||||
# 其他身份(客服、售后、管理员、店铺):累加可提现分红
|
||||
with transaction.atomic():
|
||||
fadan = Penalty.objects.select_for_update().get(id=fadan_id, Status=2)
|
||||
if fadan.ApplicantBonusAmount and Decimal(str(fadan.ApplicantBonusAmount)) > 0:
|
||||
logger.info(f"罚单 {fadan_id} 事务内检测到已分红,跳过")
|
||||
if fadan.BonusCredited:
|
||||
return True, "已分红"
|
||||
|
||||
fenhong_record, created = PenaltyBonus.objects.get_or_create(
|
||||
fenhong_record, _created = PenaltyBonus.objects.get_or_create(
|
||||
BeneficiaryID=shenqing_chufa,
|
||||
Identity=fenhong_shenfen,
|
||||
ClubID=club_id,
|
||||
@@ -146,43 +231,23 @@ def process_fadan_fenhong(fadan_id):
|
||||
'WithdrawableAmount': Decimal('0.00'),
|
||||
'BonusCount': 0,
|
||||
'IndividualRate': rate,
|
||||
'is_individual_rate': False
|
||||
}
|
||||
'IsIndividualRate': False,
|
||||
},
|
||||
)
|
||||
fenhong_record.TotalAmount += fenhong_jine
|
||||
fenhong_record.WithdrawableAmount += fenhong_jine
|
||||
fenhong_record.BonusCount += 1
|
||||
fenhong_record.save()
|
||||
|
||||
# 更新罚单中的申请人分红金额
|
||||
fadan.ApplicantBonusAmount = fenhong_jine
|
||||
fadan.save(update_fields=['ApplicantBonusAmount'])
|
||||
fadan.BonusCredited = True
|
||||
fadan.save(update_fields=['BonusCredited'])
|
||||
|
||||
logger.info(f"罚单 {fadan_id} 分红处理成功: 申请者 {shenqing_chufa}, 分红金额 {fenhong_jine} 元, 源身份 {src_shenfen}, 映射后分红身份 {fenhong_shenfen}")
|
||||
logger.info(
|
||||
f"罚单 {fadan_id} 分红入账成功: 申请者 {shenqing_chufa}, "
|
||||
f"锁定金额 {fenhong_jine} 元, 锁定利率 {rate}"
|
||||
)
|
||||
return True, "分红处理成功"
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"罚单 {fadan_id} 分红处理异常: {str(e)}", exc_info=True)
|
||||
return False, f"分红处理异常: {str(e)}"
|
||||
|
||||
|
||||
def _get_fenhong_rate(fenhongzhe_id, fenhong_shenfen, lilv_shenfen, club_id='xq'):
|
||||
"""
|
||||
获取分红利率(优先使用个人单独配置,否则使用全局身份配置)
|
||||
"""
|
||||
try:
|
||||
individual = PenaltyBonus.objects.get(
|
||||
BeneficiaryID=fenhongzhe_id,
|
||||
Identity=fenhong_shenfen,
|
||||
ClubID=club_id,
|
||||
is_individual_rate=True
|
||||
)
|
||||
return individual.IndividualRate
|
||||
except PenaltyBonus.DoesNotExist:
|
||||
pass
|
||||
|
||||
try:
|
||||
global_rate = PenaltyBonusRate.objects.get(Identity=lilv_shenfen)
|
||||
return global_rate.Rate
|
||||
except PenaltyBonusRate.DoesNotExist:
|
||||
return None
|
||||
@@ -11741,7 +11741,10 @@ class ShangjiaCufaTongjiView(APIView):
|
||||
shensuzhong_jine=Sum('FineAmount', filter=Q(Status=3)),
|
||||
yibohui=Count('id', filter=Q(Status=4)),
|
||||
yibohui_jine=Sum('FineAmount', filter=Q(Status=4)),
|
||||
shijidaozhang_jine=Sum('ApplicantBonusAmount', filter=Q(Status=2)),
|
||||
shijidaozhang_jine=Sum(
|
||||
'ApplicantBonusAmount',
|
||||
filter=Q(Status=2, BonusCredited=True),
|
||||
),
|
||||
)
|
||||
|
||||
jifen_agg = PenaltyRecord.query.filter(ApplicantID=yonghuid).aggregate(
|
||||
@@ -11875,6 +11878,8 @@ class ShangjiaFakuanLieBiaoView(APIView):
|
||||
'shensuliyou': r.AppealReason or '',
|
||||
'bohuiliyou': r.RejectReason or '',
|
||||
'applicant_bonus_amount': str(r.ApplicantBonusAmount or 0),
|
||||
'applicant_bonus_rate': str(r.ApplicantBonusRate or 0),
|
||||
'bonus_credited': bool(r.BonusCredited),
|
||||
'shop_staff_user_id': r.ShopStaffUserID or '',
|
||||
'staff_display_name': staff_name_map.get(r.ShopStaffUserID or '', ''),
|
||||
'zhengju_tupian': zhengju_map.get(rid, []),
|
||||
@@ -12006,7 +12011,7 @@ class FaKuanPayView(APIView):
|
||||
yonghuid=request.user.UserUID,
|
||||
jine=jine,
|
||||
leixing=4,
|
||||
shuoming=settings.FAKUAN_PAY_DESCRIPTION,
|
||||
shuoming=f'{settings.FAKUAN_PAY_DESCRIPTION}#fadan:{fadan.id}',
|
||||
club_id=resolve_club_id_for_write(request, request.user),
|
||||
)
|
||||
|
||||
@@ -12225,12 +12230,20 @@ class FaKuanHuitiaoView(View):
|
||||
|
||||
# 8. 更新罚单状态为已缴纳(2)
|
||||
try:
|
||||
# 根据订单中的用户ID和金额匹配待缴纳的罚单
|
||||
fadan = Penalty.query.filter(
|
||||
PenalizedUserID=order.yonghuid,
|
||||
FineAmount=order.jine,
|
||||
Status__in=[1, 3]
|
||||
).first()
|
||||
fadan = None
|
||||
m = re.search(r'#fadan:(\d+)', order.shuoming or '')
|
||||
if m:
|
||||
fadan = Penalty.query.filter(
|
||||
id=int(m.group(1)),
|
||||
PenalizedUserID=order.yonghuid,
|
||||
Status__in=[1, 3],
|
||||
).first()
|
||||
if not fadan:
|
||||
fadan = Penalty.query.filter(
|
||||
PenalizedUserID=order.yonghuid,
|
||||
FineAmount=order.jine,
|
||||
Status__in=[1, 3],
|
||||
).order_by('-CreateTime').first()
|
||||
if fadan:
|
||||
fadan.Status = 2 # 已缴纳
|
||||
fadan.save(update_fields=['Status'])
|
||||
|
||||
Reference in New Issue
Block a user