Files
Django/jituan/services/withdraw_config.py

268 lines
11 KiB
Python
Raw Permalink 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.
"""提现设置与运行时:按俱乐部读 club_lilubiao / club_tixian_quota / club_withdraw_config。"""
from datetime import date
from decimal import Decimal
from django.db import transaction
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.services.club_config import get_commission_rate
from jituan.services.club_context import resolve_club_id_from_request, resolve_club_scope
# 提现手续费率 → lilubiao config_type / CommissionRate Platform
LEIXING_RATE_KEY = {
1: '5', # 打手佣金
2: '6', # 管事分红
3: '8', # 组长分红
4: '9', # 考核官
5: '11', # 打手押金
6: '10', # 商家余额
}
# 提现身份 leixing → 平台日总限额配置 leixingclub_tixian_quota / TixianQuotaDefault UserType
WITHDRAW_TOTAL_QUOTA_LEIXING = {1: 4, 2: 5, 3: 6, 4: 7, 5: 8, 6: 9}
def _normalize_club_id(club_id):
return (club_id or '').strip() or CLUB_ID_DEFAULT
def _club_id(request):
return resolve_club_id_from_request(request)
def _get_quota(club_id, leixing, default=20.0):
club_id = _normalize_club_id(club_id)
row = ClubTixianQuota.query.filter(club_id=club_id, leixing=leixing).first()
if row is not None:
return float(row.daily_limit)
obj = TixianQuotaDefault.query.filter(UserType=leixing).first()
return float(obj.default_quota) if obj else default
def get_quota_decimal(club_id, leixing, default=20.0):
return Decimal(str(_get_quota(club_id, leixing, default)))
def _set_quota(club_id, leixing, quota):
row, created = ClubTixianQuota.query.get_or_create(
club_id=_normalize_club_id(club_id),
leixing=leixing,
defaults={'daily_limit': quota},
)
if not created:
row.daily_limit = quota
row.save(update_fields=['daily_limit', 'UpdateTime'])
def _set_lilv(club_id, config_type, rate):
ct = int(config_type)
row, created = ClubLilubiao.query.get_or_create(
club_id=_normalize_club_id(club_id),
config_type=ct,
defaults={'lilv': rate, 'remark': ''},
)
if not created:
row.lilv = rate
row.save(update_fields=['lilv', 'UpdateTime'])
def get_tixian_feilv(club_id, leixing):
"""读取提现手续费率(各俱乐部可不同)。"""
rate_key = LEIXING_RATE_KEY.get(leixing)
if not rate_key:
raise ValueError('无效的提现类型')
return get_commission_rate(_normalize_club_id(club_id), rate_key)
def get_withdraw_mode(club_id):
club_id = _normalize_club_id(club_id)
try:
return ClubWithdrawConfig.query.get(club_id=club_id).mode
except ClubWithdrawConfig.DoesNotExist:
return 2
def get_personal_daily_quota(club_id, leixing, profile):
"""打手/管事/组长个人每日限额:用户额外限额优先,否则读俱乐部配置。"""
if leixing == 1:
if profile.kaioi_ewai_xiane and profile.ewai_xiane > 0:
return Decimal(str(profile.ewai_xiane))
return get_quota_decimal(club_id, 1)
if leixing == 2:
if profile.kaioi_ewai_xiane and profile.ewai_xiane > 0:
return Decimal(str(profile.ewai_xiane))
return get_quota_decimal(club_id, 2)
if leixing == 3:
default = get_quota_decimal(club_id, 3, default=0.0)
if profile.kaioi_ewai_tixian and profile.ewai_tixian_xiane > 0:
return Decimal(str(profile.ewai_tixian_xiane))
return default
raise ValueError('无效的个人限额身份')
def get_platform_daily_limit(club_id, leixing):
quota_leixing = WITHDRAW_TOTAL_QUOTA_LEIXING.get(leixing)
if not quota_leixing:
return Decimal('0.00')
return get_quota_decimal(club_id, quota_leixing, default=0.0)
def get_platform_daily_total(club_id, leixing, today=None):
"""平台今日已提现总额(到账金额口径,按俱乐部)。"""
club_id = _normalize_club_id(club_id)
today = today or date.today()
rec = WithdrawalDailyStats.query.filter(
club_id=club_id, Date=today, WithdrawalType=leixing,
).first()
if rec:
return Decimal(str(rec.total_amount))
return Decimal('0.00')
def get_or_create_platform_daily_stat(club_id, leixing, today=None):
"""在 transaction.atomic 内获取并锁定平台日统计行。"""
club_id = _normalize_club_id(club_id)
today = today or date.today()
stat, _ = WithdrawalDailyStats.objects.select_for_update().get_or_create(
club_id=club_id,
Date=today,
WithdrawalType=leixing,
defaults={'total_amount': Decimal('0.00')},
)
return stat
def build_tixian_asset_rates(club_id):
club_id = _normalize_club_id(club_id)
return {
'dashou_rate': float(get_commission_rate(club_id, '5')),
'dashou_yajin_rate': float(get_commission_rate(club_id, '11')),
'shangjia_rate': float(get_commission_rate(club_id, '10')),
'guanshi_rate': float(get_commission_rate(club_id, '6')),
'zuzhang_rate': float(get_commission_rate(club_id, '8')),
'kaoheguan_rate': float(get_commission_rate(club_id, '9')),
}
def build_withdraw_settings_payload(request):
club_id = _club_id(request)
rate_map = {}
for leixing, code in [(1, '5'), (2, '6'), (3, '8'), (4, '9'), (5, '11'), (6, '10')]:
rate_map[leixing] = float(get_commission_rate(club_id, code))
order_rate_map = {}
for leixing, code in [(1, '1'), (3, '3'), (12, '12'), (13, '13')]:
order_rate_map[leixing] = float(get_commission_rate(club_id, code))
quota_map = {leixing: _get_quota(club_id, leixing) for leixing in [1, 2, 3]}
total_limit_map = {}
for withdraw_leixing, quota_leixing in [(1, 4), (2, 5), (3, 6), (4, 7), (5, 8), (6, 9)]:
total_limit_map[withdraw_leixing] = _get_quota(club_id, quota_leixing, default=0.0)
today = date.today()
today_totals = {i: 0.0 for i in range(1, 7)}
for rec in WithdrawalDailyStats.query.filter(club_id=club_id, Date=today):
if rec.WithdrawalType in today_totals:
today_totals[rec.WithdrawalType] = float(rec.total_amount)
return {
'club_id': club_id,
'scope': resolve_club_scope(request),
'withdraw_mode': get_withdraw_mode(club_id),
'rates': rate_map,
'order_rates': order_rate_map,
'quotas': quota_map,
'total_limits': total_limit_map,
'today_totals': today_totals,
}
def apply_withdraw_settings_update(request, permissions):
if resolve_club_scope(request) == DATA_SCOPE_ALL:
return Response({'code': 403, 'msg': '请在子公司视图下修改提现设置'})
club_id = _club_id(request)
rates = request.data.get('rates', {})
order_rates = request.data.get('order_rates', request.data.get('commission_rates', {}))
quotas = request.data.get('quotas', {})
total_limits = request.data.get('total_limits', {})
role_perms = {1: '5500a', 2: '5500b', 3: '5500c'}
rate_code_map = {1: '5', 2: '6', 3: '8', 4: '9', 5: '11', 6: '10'}
order_rate_code_map = {1: '1', 3: '3', 12: '12', 13: '13'}
total_code_map = {1: 4, 2: 5, 3: 6, 4: 7, 5: 8, 6: 9}
def _rate_key_present(data, role):
return (str(role) in data and data[str(role)] is not None) or \
(role in data and data[role] is not None)
with transaction.atomic():
for role in [1, 2, 3]:
perm_needed = role_perms[role]
if perm_needed not in permissions:
if _rate_key_present(rates, role) or \
(str(role) in quotas and quotas[str(role)] is not None) or \
(role in quotas and quotas.get(role) is not None) or \
(str(role) in total_limits and total_limits[str(role)] is not None) or \
(role in total_limits and total_limits.get(role) is not None):
return Response({'code': 403, 'msg': f'无权限修改{["","打手","管事","组长"][role]}相关设置(需要{perm_needed}'})
extra_role_names = {4: '考核官', 5: '打手押金', 6: '商家余额'}
for role in [4, 5, 6]:
if _rate_key_present(rates, role) and not any(p in permissions for p in ('5500a', '5500b', '5500c')):
return Response({'code': 403, 'msg': f'无权限修改{extra_role_names[role]}提现手续费率'})
if (str(role) in total_limits and total_limits[str(role)] is not None) or \
(role in total_limits and total_limits.get(role) is not None):
if not any(p in permissions for p in ('5500a', '5500b', '5500c')):
return Response({'code': 403, 'msg': f'无权限修改{extra_role_names[role]}总限额'})
for role in [1, 3, 12, 13]:
if _rate_key_present(order_rates, role) and not any(p in permissions for p in ('5500a', '5500b', '5500c')):
order_names = {
1: '平台订单打手分红', 3: '商家订单打手分红',
12: '押金管事分红', 13: '管事订单分红',
}
return Response({'code': 403, 'msg': f'无权限修改{order_names[role]}费率'})
for role in [1, 2, 3, 4, 5, 6]:
val = rates.get(str(role), rates.get(role))
if val is not None:
_set_lilv(club_id, rate_code_map[role], Decimal(str(val)))
for role in [1, 3, 12, 13]:
val = order_rates.get(str(role), order_rates.get(role))
if val is not None:
_set_lilv(club_id, order_rate_code_map[role], Decimal(str(val)))
for role in [1, 2, 3]:
if str(role) in quotas:
val = quotas[str(role)]
if val is not None:
_set_quota(club_id, role, Decimal(str(val)))
elif role in quotas and quotas.get(role) is not None:
_set_quota(club_id, role, Decimal(str(quotas[role])))
for role in [1, 2, 3, 4, 5, 6]:
val = total_limits.get(str(role), total_limits.get(role))
if val is not None:
_set_quota(club_id, total_code_map[role], Decimal(str(val)))
withdraw_mode = request.data.get('withdraw_mode')
if withdraw_mode is not None:
if not any(p in permissions for p in ('5500a', '5500b', '5500c')):
return Response({'code': 403, 'msg': '无权限修改提现模式'})
row, created = ClubWithdrawConfig.query.get_or_create(
club_id=club_id,
defaults={'mode': int(withdraw_mode)},
)
if not created:
row.mode = int(withdraw_mode)
row.save(update_fields=['mode', 'UpdateTime'])
return Response({'code': 0, 'msg': '设置修改成功'})