From edcb23582831413b4a6552d7fe79edac928e6315 Mon Sep 17 00:00:00 2001 From: XingQue Date: Wed, 22 Jul 2026 19:36:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=95=86=E5=AE=B6=E6=B4=BE=E5=8D=95=E6=8A=BC?= =?UTF-8?q?=E9=87=91=E8=A6=81=E6=B1=82=E6=94=B9=E4=B8=BA=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E5=8F=AF=E9=85=8D=E9=99=90=E9=A2=9D=EF=BC=8C=E5=8E=BB=E6=8E=89?= =?UTF-8?q?=E5=86=99=E6=AD=BB=E7=9A=84=200.1-50=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- dingdan/views.py | 29 +++++++------- ...024_xcx_sys_peizhi_shangjia_paifa_yajin.py | 34 +++++++++++++++++ peizhi/models.py | 7 ++++ peizhi/views.py | 38 ++++++++----------- peizhi/xcx_config_views.py | 18 ++++++++- utils/shangjia_paifa_config.py | 36 +++++++++++++++++- utils/xcx_sys_config.py | 14 +++++++ 7 files changed, 135 insertions(+), 41 deletions(-) create mode 100644 peizhi/migrations/0024_xcx_sys_peizhi_shangjia_paifa_yajin.py diff --git a/dingdan/views.py b/dingdan/views.py index b6572a2..e2aef07 100644 --- a/dingdan/views.py +++ b/dingdan/views.py @@ -2487,10 +2487,14 @@ class ShangpinLeixingView(APIView): data_list.append(item) + from utils.shangjia_paifa_config import get_shangjia_paifa_yajin_limits + yajin_min, yajin_max = get_shangjia_paifa_yajin_limits() return Response({ 'code': 200, 'msg': '获取成功', - 'data': data_list + 'data': data_list, + 'yajin_min': str(yajin_min), + 'yajin_max': str(yajin_max), }) except Exception as e: @@ -2613,21 +2617,14 @@ class ShangjiaPaifaView(APIView): # ----- 6. 押金 / 会员模式决定 ----- final_yongjin = None if commission_enabled and commission_value_str: - try: - cv = float(commission_value_str) - if cv > 0: - final_yaoqiu_type = 2 - final_yongjin = Decimal(str(cv)) - final_huiyuan_id = '' - logger.info(f"押金模式: 佣金={cv}") - else: - final_yaoqiu_type = shangpin_type.yaoqiuleixing or 1 - final_huiyuan_id = str(huiyuan_id) if huiyuan_id else '' - logger.warning("佣金为0,降级为会员模式") - except ValueError: - final_yaoqiu_type = shangpin_type.yaoqiuleixing or 1 - final_huiyuan_id = str(huiyuan_id) if huiyuan_id else '' - logger.warning("佣金格式错误,降级为会员模式") + from utils.shangjia_paifa_config import validate_shangjia_paifa_yajin + yajin_ok, yajin_msg, yajin_val = validate_shangjia_paifa_yajin(commission_value_str) + if not yajin_ok: + return Response({'code': 400, 'msg': yajin_msg}) + final_yaoqiu_type = 2 + final_yongjin = yajin_val + final_huiyuan_id = '' + logger.info(f"押金模式: 押金要求={yajin_val}") else: final_yaoqiu_type = shangpin_type.yaoqiuleixing or 1 final_huiyuan_id = str(huiyuan_id) if huiyuan_id else '' diff --git a/peizhi/migrations/0024_xcx_sys_peizhi_shangjia_paifa_yajin.py b/peizhi/migrations/0024_xcx_sys_peizhi_shangjia_paifa_yajin.py new file mode 100644 index 0000000..9984a7d --- /dev/null +++ b/peizhi/migrations/0024_xcx_sys_peizhi_shangjia_paifa_yajin.py @@ -0,0 +1,34 @@ +# Generated manually for shangjia paifa yajin limits +from decimal import Decimal + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('peizhi', '0023_user_wechat_mch_bind'), + ] + + operations = [ + migrations.AddField( + model_name='xcxsyspeizhi', + name='shangjia_paifa_yajin_min', + field=models.DecimalField( + decimal_places=2, + default=Decimal('0.10'), + max_digits=10, + verbose_name='派单押金要求最低(元)', + ), + ), + migrations.AddField( + model_name='xcxsyspeizhi', + name='shangjia_paifa_yajin_max', + field=models.DecimalField( + decimal_places=2, + default=Decimal('10000.00'), + max_digits=10, + verbose_name='派单押金要求最高(元)', + ), + ), + ] diff --git a/peizhi/models.py b/peizhi/models.py index 03b081e..6c972be 100644 --- a/peizhi/models.py +++ b/peizhi/models.py @@ -709,6 +709,13 @@ class XcxSysPeizhi(models.Model): shangjia_paifa_jiage_max = models.DecimalField( max_digits=10, decimal_places=2, default=10000.00, verbose_name='商家派单最高金额(元)', ) + # 商家派单「要求接单员押金」金额范围(yaoqiuleixing=2 / commission) + shangjia_paifa_yajin_min = models.DecimalField( + max_digits=10, decimal_places=2, default=0.10, verbose_name='派单押金要求最低(元)', + ) + shangjia_paifa_yajin_max = models.DecimalField( + max_digits=10, decimal_places=2, default=10000.00, verbose_name='派单押金要求最高(元)', + ) update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: diff --git a/peizhi/views.py b/peizhi/views.py index e2c15c9..260fc89 100644 --- a/peizhi/views.py +++ b/peizhi/views.py @@ -1752,20 +1752,16 @@ class ShangjiaTianjiaMobanView(APIView): if len(jieshao) > 100: return Response({'code': 400, 'msg': '订单介绍不能超过100字', 'data': {}}, status=400) - # 6. 佣金验证(若启用) + # 6. 押金要求验证(若启用,限额读后台配置) yongjin_qiangdan = False yongjin_jiage = None if commission_enabled: yongjin_qiangdan = True - if not commission_value: - return Response({'code': 400, 'msg': '开启佣金时,佣金金额不能为空', 'data': {}}, status=400) - try: - comm_decimal = Decimal(str(commission_value)) - if comm_decimal <= 0: - return Response({'code': 400, 'msg': '佣金必须大于0', 'data': {}}, status=400) - yongjin_jiage = comm_decimal - except (InvalidOperation, ValueError, TypeError): - return Response({'code': 400, 'msg': '佣金格式错误', 'data': {}}, status=400) + from utils.shangjia_paifa_config import validate_shangjia_paifa_yajin + yajin_ok, yajin_msg, yajin_val = validate_shangjia_paifa_yajin(commission_value) + if not yajin_ok: + return Response({'code': 400, 'msg': yajin_msg, 'data': {}}, status=400) + yongjin_jiage = yajin_val # 7. 标签ID清洗(前端可能传数字或字符串) cleaned_label_id = None @@ -1950,22 +1946,18 @@ class ShangjiaGengxinMobanView(APIView): moban.chenghao_id = new_label update_fields.append('chenghao_id') - # 修改佣金设置 + # 修改押金要求设置(限额读后台配置,不再写死50) if commission_enabled is not None: enabled = bool(commission_enabled) if enabled: - if not commission_value: - return Response({'code': 400, 'msg': '佣金价格不能为空', 'data': {}}, status=400) - try: - comm_decimal = Decimal(commission_value) - if comm_decimal < 0.1 or comm_decimal > 50: - return Response({'code': 400, 'msg': '佣金需在0.1-50元之间', 'data': {}}, status=400) - if moban.yongjin_qiangdan != True or moban.yongjin_jiage != comm_decimal: - moban.yongjin_qiangdan = True - moban.yongjin_jiage = comm_decimal - update_fields.extend(['yongjin_qiangdan', 'yongjin_jiage']) - except (InvalidOperation, ValueError, TypeError): - return Response({'code': 400, 'msg': '佣金格式错误', 'data': {}}, status=400) + from utils.shangjia_paifa_config import validate_shangjia_paifa_yajin + yajin_ok, yajin_msg, comm_decimal = validate_shangjia_paifa_yajin(commission_value) + if not yajin_ok: + return Response({'code': 400, 'msg': yajin_msg, 'data': {}}, status=400) + if moban.yongjin_qiangdan != True or moban.yongjin_jiage != comm_decimal: + moban.yongjin_qiangdan = True + moban.yongjin_jiage = comm_decimal + update_fields.extend(['yongjin_qiangdan', 'yongjin_jiage']) else: if moban.yongjin_qiangdan != False or moban.yongjin_jiage is not None: moban.yongjin_qiangdan = False diff --git a/peizhi/xcx_config_views.py b/peizhi/xcx_config_views.py index 2e86446..325c098 100644 --- a/peizhi/xcx_config_views.py +++ b/peizhi/xcx_config_views.py @@ -120,6 +120,12 @@ class XcxSysPeizhiQueryView(APIView): 'shangjia_paifa_jiage_max': str( row.shangjia_paifa_jiage_max if row else wx_cfg.SHANGJIA_PAIFA_JIAGE_MAX ), + 'shangjia_paifa_yajin_min': str( + row.shangjia_paifa_yajin_min if row else wx_cfg.SHANGJIA_PAIFA_YAJIN_MIN + ), + 'shangjia_paifa_yajin_max': str( + row.shangjia_paifa_yajin_max if row else wx_cfg.SHANGJIA_PAIFA_YAJIN_MAX + ), 'from_database': bool(row), } return Response({'code': 0, 'msg': 'success', 'data': data}) @@ -138,6 +144,7 @@ class XcxSysPeizhiUpdateView(APIView): 'weixin_broadcast_workers', 'weixin_mchid', 'weixin_shanghu_miyao', 'weixin_notify_url', 'weixin_cert_path', 'weixin_key_path', 'notify_base_url', 'shangpin_shenhe_mode', 'shangjia_paifa_jiage_min', 'shangjia_paifa_jiage_max', + 'shangjia_paifa_yajin_min', 'shangjia_paifa_yajin_max', }) def post(self, request): @@ -162,7 +169,10 @@ class XcxSysPeizhiUpdateView(APIView): if mode not in (1, 2): continue row.shangpin_shenhe_mode = mode - elif key in ('shangjia_paifa_jiage_min', 'shangjia_paifa_jiage_max'): + elif key in ( + 'shangjia_paifa_jiage_min', 'shangjia_paifa_jiage_max', + 'shangjia_paifa_yajin_min', 'shangjia_paifa_yajin_max', + ): from decimal import Decimal, InvalidOperation try: amount = Decimal(str(val)) @@ -182,6 +192,12 @@ class XcxSysPeizhiUpdateView(APIView): ) row.save(update_fields=['shangjia_paifa_jiage_min', 'shangjia_paifa_jiage_max']) clear_xcx_sys_peizhi_cache() + if row and row.shangjia_paifa_yajin_min > row.shangjia_paifa_yajin_max: + row.shangjia_paifa_yajin_min, row.shangjia_paifa_yajin_max = ( + row.shangjia_paifa_yajin_max, row.shangjia_paifa_yajin_min, + ) + row.save(update_fields=['shangjia_paifa_yajin_min', 'shangjia_paifa_yajin_max']) + clear_xcx_sys_peizhi_cache() return Response({'code': 0, 'msg': '配置已更新', 'data': None}) diff --git a/utils/shangjia_paifa_config.py b/utils/shangjia_paifa_config.py index 623997c..f6304a4 100644 --- a/utils/shangjia_paifa_config.py +++ b/utils/shangjia_paifa_config.py @@ -1,10 +1,12 @@ -"""商家派单金额限额 — 读 XcxSysPeizhi,后台可配""" +"""商家派单金额/押金要求限额 — 读 XcxSysPeizhi,后台可配""" from decimal import Decimal, InvalidOperation from utils.xcx_sys_config import wx_cfg DEFAULT_MIN = Decimal('10') DEFAULT_MAX = Decimal('10000') +DEFAULT_YAJIN_MIN = Decimal('0.10') +DEFAULT_YAJIN_MAX = Decimal('10000') def get_shangjia_paifa_jiage_limits(): @@ -18,6 +20,17 @@ def get_shangjia_paifa_jiage_limits(): return min_v, max_v +def get_shangjia_paifa_yajin_limits(): + """返回派单「要求接单员押金」金额 (min, max) Decimal""" + min_v = getattr(wx_cfg, 'SHANGJIA_PAIFA_YAJIN_MIN', None) or DEFAULT_YAJIN_MIN + max_v = getattr(wx_cfg, 'SHANGJIA_PAIFA_YAJIN_MAX', None) or DEFAULT_YAJIN_MAX + min_v = Decimal(str(min_v)) + max_v = Decimal(str(max_v)) + if min_v > max_v: + min_v, max_v = max_v, min_v + return min_v, max_v + + def validate_shangjia_paifa_jiage(jiage_str): """ 校验派单金额 @@ -37,3 +50,24 @@ def validate_shangjia_paifa_jiage(jiage_str): if jiage < min_v or jiage > max_v: return False, f'价格需在{min_v}-{max_v}元之间', None return True, '', float(jiage) + + +def validate_shangjia_paifa_yajin(yajin_str): + """ + 校验派单押金要求金额 + @return (ok, msg, yajin_decimal|None) + """ + if yajin_str is None or str(yajin_str).strip() == '': + return False, '押金金额不能为空', None + raw = str(yajin_str).strip() + try: + amount = Decimal(raw) + except (InvalidOperation, ValueError, TypeError): + return False, '押金格式错误', None + if '.' in raw and len(raw.split('.')[1]) > 2: + return False, '押金最多支持两位小数', None + + min_v, max_v = get_shangjia_paifa_yajin_limits() + if amount < min_v or amount > max_v: + return False, f'押金需在{min_v}-{max_v}元之间', None + return True, '', amount diff --git a/utils/xcx_sys_config.py b/utils/xcx_sys_config.py index 5e1147a..db5ddbd 100644 --- a/utils/xcx_sys_config.py +++ b/utils/xcx_sys_config.py @@ -142,6 +142,20 @@ class WxConfig: return row.shangjia_paifa_jiage_max return Decimal('10000') + @property + def SHANGJIA_PAIFA_YAJIN_MIN(self): + row = _load_row() + if row is not None and getattr(row, 'shangjia_paifa_yajin_min', None) is not None: + return row.shangjia_paifa_yajin_min + return Decimal('0.10') + + @property + def SHANGJIA_PAIFA_YAJIN_MAX(self): + row = _load_row() + if row is not None and getattr(row, 'shangjia_paifa_yajin_max', None) is not None: + return row.shangjia_paifa_yajin_max + return Decimal('10000') + wx_cfg = WxConfig()