diff --git a/jituan/services/withdraw_config.py b/jituan/services/withdraw_config.py index 16afacf..ff45c8c 100644 --- a/jituan/services/withdraw_config.py +++ b/jituan/services/withdraw_config.py @@ -8,9 +8,10 @@ from rest_framework.response import Response from backend.models import WithdrawalDailyStats from config.models import TixianQuotaDefault from jituan.constants import CLUB_ID_DEFAULT, DATA_SCOPE_ALL -from jituan.models import ClubLilubiao, ClubTixianQuota, ClubWithdrawConfig +from jituan.models import ClubFadanFenhongLilv, ClubLilubiao, ClubTixianQuota, ClubWithdrawConfig from jituan.services.club_config import get_commission_rate from jituan.services.club_context import resolve_club_id_from_request, resolve_club_scope +from orders.models import PenaltyBonusRate # 提现手续费率 → lilubiao config_type / CommissionRate Platform LEIXING_RATE_KEY = { @@ -22,6 +23,15 @@ LEIXING_RATE_KEY = { 6: '10', # 商家余额 } +# 罚款分红身份(与 fadan_fenhong_lilv.shenfen 一致) +PENALTY_BONUS_SHENFEN = { + 1: '客服', + 2: '售后', + 3: '管理员', + 4: '店铺', + 5: '商家', +} + # 提现身份 leixing → 平台日总限额配置 leixing(club_tixian_quota / TixianQuotaDefault UserType) WITHDRAW_TOTAL_QUOTA_LEIXING = {1: 4, 2: 5, 3: 6, 4: 7, 5: 8, 6: 9} @@ -70,6 +80,39 @@ def _set_lilv(club_id, config_type, rate): row.save(update_fields=['lilv', 'UpdateTime']) +def _get_penalty_bonus_rate(club_id, shenfen): + """有效罚款分红费率:俱乐部 > 全局表。""" + club_id = _normalize_club_id(club_id) + shenfen = int(shenfen) + row = ClubFadanFenhongLilv.query.filter(club_id=club_id, shenfen=shenfen).first() + if row is not None and row.lilv is not None: + return float(row.lilv) + try: + g = PenaltyBonusRate.objects.get(Identity=shenfen) + if g.Rate is not None: + return float(g.Rate) + except PenaltyBonusRate.DoesNotExist: + pass + return 0.0 + + +def _set_penalty_bonus_rate(club_id, shenfen, rate): + club_id = _normalize_club_id(club_id) + shenfen = int(shenfen) + row, created = ClubFadanFenhongLilv.query.get_or_create( + club_id=club_id, + shenfen=shenfen, + defaults={'lilv': rate}, + ) + if not created: + row.lilv = rate + row.save(update_fields=['lilv', 'UpdateTime']) + + +def get_penalty_bonus_rates_map(club_id): + return {s: _get_penalty_bonus_rate(club_id, s) for s in PENALTY_BONUS_SHENFEN} + + def get_tixian_feilv(club_id, leixing): """读取提现手续费率(各俱乐部可不同)。""" rate_key = LEIXING_RATE_KEY.get(leixing) @@ -176,6 +219,7 @@ def build_withdraw_settings_payload(request): 'withdraw_mode': get_withdraw_mode(club_id), 'rates': rate_map, 'order_rates': order_rate_map, + 'penalty_bonus_rates': get_penalty_bonus_rates_map(club_id), 'quotas': quota_map, 'total_limits': total_limit_map, 'today_totals': today_totals, @@ -189,6 +233,7 @@ def apply_withdraw_settings_update(request, permissions): club_id = _club_id(request) rates = request.data.get('rates', {}) order_rates = request.data.get('order_rates', request.data.get('commission_rates', {})) + penalty_bonus_rates = request.data.get('penalty_bonus_rates', {}) quotas = request.data.get('quotas', {}) total_limits = request.data.get('total_limits', {}) @@ -229,6 +274,15 @@ def apply_withdraw_settings_update(request, permissions): } return Response({'code': 403, 'msg': f'无权限修改{order_names[role]}费率'}) + for shenfen in PENALTY_BONUS_SHENFEN: + if _rate_key_present(penalty_bonus_rates, shenfen) and not any( + p in permissions for p in ('5500a', '5500b', '5500c') + ): + return Response({ + 'code': 403, + 'msg': f'无权限修改{PENALTY_BONUS_SHENFEN[shenfen]}罚款分红费率', + }) + for role in [1, 2, 3, 4, 5, 6]: val = rates.get(str(role), rates.get(role)) if val is not None: @@ -239,6 +293,17 @@ def apply_withdraw_settings_update(request, permissions): if val is not None: _set_lilv(club_id, order_rate_code_map[role], Decimal(str(val))) + for shenfen in PENALTY_BONUS_SHENFEN: + val = penalty_bonus_rates.get(str(shenfen), penalty_bonus_rates.get(shenfen)) + if val is not None: + rate = Decimal(str(val)) + if rate < 0 or rate > 1: + return Response({ + 'code': 400, + 'msg': f'{PENALTY_BONUS_SHENFEN[shenfen]}罚款分红费率须在 0~1 之间(如 0.6 表示 60%)', + }) + _set_penalty_bonus_rate(club_id, shenfen, rate) + for role in [1, 2, 3]: if str(role) in quotas: val = quotas[str(role)] diff --git a/users/fadan_fenhong_utils.py b/users/fadan_fenhong_utils.py index 3ae0797..b0e24b6 100644 --- a/users/fadan_fenhong_utils.py +++ b/users/fadan_fenhong_utils.py @@ -43,9 +43,22 @@ def _read_global_fenhong_rate(lilv_shenfen): return None +def _read_club_fenhong_rate(club_id, lilv_shenfen): + """俱乐部级罚款分红费率(club_fadan_fenhong_lilv)。""" + from jituan.models import ClubFadanFenhongLilv + + club_id = _normalize_club_id(club_id) + row = ClubFadanFenhongLilv.query.filter( + club_id=club_id, shenfen=int(lilv_shenfen), + ).first() + if row is not None and row.lilv is not None and Decimal(str(row.lilv)) > 0: + return row.lilv + return None + + def _get_fenhong_rate(fenhongzhe_id, fenhong_shenfen, lilv_shenfen, club_id='xq'): """ - 获取分红利率:个人单独利率 > 0 时优先;否则回退全局 fadan_fenhong_lilv。 + 获取分红利率:个人单独利率 > 0 优先;否则俱乐部配置;再回退全局 fadan_fenhong_lilv。 """ club_id = _normalize_club_id(club_id) try: @@ -61,6 +74,10 @@ def _get_fenhong_rate(fenhongzhe_id, fenhong_shenfen, lilv_shenfen, club_id='xq' except PenaltyBonus.DoesNotExist: pass + club_rate = _read_club_fenhong_rate(club_id, lilv_shenfen) + if club_rate is not None: + return club_rate + return _read_global_fenhong_rate(lilv_shenfen)