From 47c6e3b0241cb339dc91b5f71afd2c71cb6c58f1 Mon Sep 17 00:00:00 2001 From: XingQue Date: Wed, 1 Jul 2026 11:00:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=95=86=E5=AE=B6=E6=B4=BE=E5=8D=95?= =?UTF-8?q?=E9=87=91=E9=A2=9D=E9=99=90=E9=A2=9D=E6=94=B9=E4=B8=BA=E5=90=8E?= =?UTF-8?q?=E5=8F=B0=E5=8F=AF=E9=85=8D=E7=BD=AE=EF=BC=8C=E6=B4=BE=E5=8D=95?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=AF=BB=E5=8F=96XcxSysPeizhi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- dingdan/views.py | 14 +++---- ...020_xcx_sys_peizhi_shangjia_paifa_limit.py | 29 ++++++++++++++ peizhi/models.py | 6 +++ peizhi/views.py | 20 ++++++++-- peizhi/xcx_config_views.py | 23 +++++++++++ utils/shangjia_paifa_config.py | 39 +++++++++++++++++++ utils/xcx_sys_config.py | 16 ++++++++ 7 files changed, 134 insertions(+), 13 deletions(-) create mode 100644 peizhi/migrations/0020_xcx_sys_peizhi_shangjia_paifa_limit.py create mode 100644 utils/shangjia_paifa_config.py diff --git a/dingdan/views.py b/dingdan/views.py index dcb70d4..d3ab163 100644 --- a/dingdan/views.py +++ b/dingdan/views.py @@ -2556,15 +2556,11 @@ class ShangjiaPaifaView(APIView): logger.warning(f"参数缺失: {request.data}") return Response({'code': 400, 'msg': '缺少必填参数'}) - # ----- 4. 价格验证 ----- - try: - jiage = float(jiage_str) - if jiage < 10 or jiage > 10000: - return Response({'code': 400, 'msg': '价格需在10-10000元之间'}) - if '.' in str(jiage_str) and len(str(jiage_str).split('.')[1]) > 2: - return Response({'code': 400, 'msg': '最多支持两位小数'}) - except ValueError: - return Response({'code': 400, 'msg': '价格格式错误'}) + # ----- 4. 价格验证(限额读后台配置,非写死)----- + from utils.shangjia_paifa_config import validate_shangjia_paifa_jiage + price_ok, price_msg, jiage = validate_shangjia_paifa_jiage(jiage_str) + if not price_ok: + return Response({'code': 400, 'msg': price_msg}) # ----- 5. 商品类型 ----- try: diff --git a/peizhi/migrations/0020_xcx_sys_peizhi_shangjia_paifa_limit.py b/peizhi/migrations/0020_xcx_sys_peizhi_shangjia_paifa_limit.py new file mode 100644 index 0000000..5ec0016 --- /dev/null +++ b/peizhi/migrations/0020_xcx_sys_peizhi_shangjia_paifa_limit.py @@ -0,0 +1,29 @@ +from decimal import Decimal + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('peizhi', '0019_xcx_sys_peizhi_shangpin_mode'), + ] + + operations = [ + migrations.AddField( + model_name='xcxsyspeizhi', + name='shangjia_paifa_jiage_min', + field=models.DecimalField( + decimal_places=2, default=Decimal('10.00'), max_digits=10, + verbose_name='商家派单最低金额(元)', + ), + ), + migrations.AddField( + model_name='xcxsyspeizhi', + name='shangjia_paifa_jiage_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 252879b..cfc56c6 100644 --- a/peizhi/models.py +++ b/peizhi/models.py @@ -702,6 +702,12 @@ class XcxSysPeizhi(models.Model): verbose_name='点单商品展示模式', help_text='1=正常运营(shenhezhuangtai=1),2=审核专用(shenhezhuangtai=2)', ) + shangjia_paifa_jiage_min = models.DecimalField( + max_digits=10, decimal_places=2, default=10.00, verbose_name='商家派单最低金额(元)', + ) + shangjia_paifa_jiage_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 1bcdb0e..e2c15c9 100644 --- a/peizhi/views.py +++ b/peizhi/views.py @@ -1733,12 +1733,18 @@ class ShangjiaTianjiaMobanView(APIView): }, status=400) # 4. 价格格式验证 + from utils.shangjia_paifa_config import get_shangjia_paifa_jiage_limits + paifa_min, paifa_max = get_shangjia_paifa_jiage_limits() try: jiage_decimal = Decimal(str(jiage)) if jiage_decimal <= 0: return Response({'code': 400, 'msg': '价格必须大于0', 'data': {}}, status=400) - if jiage_decimal > 10000: - return Response({'code': 400, 'msg': '价格不能超过10000元', 'data': {}}, status=400) + if jiage_decimal < paifa_min or jiage_decimal > paifa_max: + return Response({ + 'code': 400, + 'msg': f'价格需在{paifa_min}-{paifa_max}元之间', + 'data': {}, + }, status=400) except (InvalidOperation, ValueError, TypeError): return Response({'code': 400, 'msg': '价格格式错误', 'data': {}}, status=400) @@ -1921,10 +1927,16 @@ class ShangjiaGengxinMobanView(APIView): # 修改价格 if new_jiage: + from utils.shangjia_paifa_config import get_shangjia_paifa_jiage_limits + paifa_min, paifa_max = get_shangjia_paifa_jiage_limits() try: jiage_decimal = Decimal(new_jiage) - if jiage_decimal <= 0 or jiage_decimal > 10000: - return Response({'code': 400, 'msg': '价格必须在0.1-10000元之间', 'data': {}}, status=400) + if jiage_decimal <= 0 or jiage_decimal < paifa_min or jiage_decimal > paifa_max: + return Response({ + 'code': 400, + 'msg': f'价格需在{paifa_min}-{paifa_max}元之间', + 'data': {}, + }, status=400) if jiage_decimal != moban.jiage: moban.jiage = jiage_decimal update_fields.append('jiage') diff --git a/peizhi/xcx_config_views.py b/peizhi/xcx_config_views.py index db12d07..2e86446 100644 --- a/peizhi/xcx_config_views.py +++ b/peizhi/xcx_config_views.py @@ -114,6 +114,12 @@ class XcxSysPeizhiQueryView(APIView): 'weixin_key_path': row.weixin_key_path if row else wx_cfg.WEIXIN_KEY_PATH, 'notify_base_url': row.notify_base_url if row else wx_cfg.NOTIFY_BASE_URL, 'shangpin_shenhe_mode': row.shangpin_shenhe_mode if row else wx_cfg.SHANGPIN_SHENHE_MODE, + 'shangjia_paifa_jiage_min': str( + row.shangjia_paifa_jiage_min if row else wx_cfg.SHANGJIA_PAIFA_JIAGE_MIN + ), + 'shangjia_paifa_jiage_max': str( + row.shangjia_paifa_jiage_max if row else wx_cfg.SHANGJIA_PAIFA_JIAGE_MAX + ), 'from_database': bool(row), } return Response({'code': 0, 'msg': 'success', 'data': data}) @@ -131,6 +137,7 @@ class XcxSysPeizhiUpdateView(APIView): 'weixin_template_max_per_minute', 'weixin_template_batch_size', 'weixin_broadcast_enabled', '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', }) def post(self, request): @@ -155,10 +162,26 @@ 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'): + from decimal import Decimal, InvalidOperation + try: + amount = Decimal(str(val)) + except (InvalidOperation, ValueError, TypeError): + continue + if amount <= 0: + continue + row.__setattr__(key, amount) else: row.__setattr__(key, str(val).strip()) row.save() clear_xcx_sys_peizhi_cache() + row = XcxSysPeizhi.objects.first() + if row and row.shangjia_paifa_jiage_min > row.shangjia_paifa_jiage_max: + row.shangjia_paifa_jiage_min, row.shangjia_paifa_jiage_max = ( + row.shangjia_paifa_jiage_max, row.shangjia_paifa_jiage_min, + ) + row.save(update_fields=['shangjia_paifa_jiage_min', 'shangjia_paifa_jiage_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 new file mode 100644 index 0000000..623997c --- /dev/null +++ b/utils/shangjia_paifa_config.py @@ -0,0 +1,39 @@ +"""商家派单金额限额 — 读 XcxSysPeizhi,后台可配""" +from decimal import Decimal, InvalidOperation + +from utils.xcx_sys_config import wx_cfg + +DEFAULT_MIN = Decimal('10') +DEFAULT_MAX = Decimal('10000') + + +def get_shangjia_paifa_jiage_limits(): + """返回 (min, max) Decimal""" + min_v = getattr(wx_cfg, 'SHANGJIA_PAIFA_JIAGE_MIN', None) or DEFAULT_MIN + max_v = getattr(wx_cfg, 'SHANGJIA_PAIFA_JIAGE_MAX', None) or DEFAULT_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): + """ + 校验派单金额 + @return (ok, msg, jiage_float|None) + """ + if jiage_str is None or str(jiage_str).strip() == '': + return False, '缺少价格', None + jiage_raw = str(jiage_str).strip() + try: + jiage = Decimal(jiage_raw) + except (InvalidOperation, ValueError, TypeError): + return False, '价格格式错误', None + if '.' in jiage_raw and len(jiage_raw.split('.')[1]) > 2: + return False, '最多支持两位小数', None + + min_v, max_v = get_shangjia_paifa_jiage_limits() + if jiage < min_v or jiage > max_v: + return False, f'价格需在{min_v}-{max_v}元之间', None + return True, '', float(jiage) diff --git a/utils/xcx_sys_config.py b/utils/xcx_sys_config.py index afac95d..5e1147a 100644 --- a/utils/xcx_sys_config.py +++ b/utils/xcx_sys_config.py @@ -3,6 +3,8 @@ """ import logging +from decimal import Decimal + from django.conf import settings from django.core.cache import cache @@ -126,6 +128,20 @@ class WxConfig: return int(row.shangpin_shenhe_mode) return 2 + @property + def SHANGJIA_PAIFA_JIAGE_MIN(self): + row = _load_row() + if row is not None and row.shangjia_paifa_jiage_min is not None: + return row.shangjia_paifa_jiage_min + return Decimal('10') + + @property + def SHANGJIA_PAIFA_JIAGE_MAX(self): + row = _load_row() + if row is not None and row.shangjia_paifa_jiage_max is not None: + return row.shangjia_paifa_jiage_max + return Decimal('10000') + wx_cfg = WxConfig()