From 45c61efdc6d20a48f35b00a5ce1f03010801deca Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 16 Jul 2026 13:24:08 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E5=8F=91=E8=B4=A7=E7=BC=96=E5=8F=B7?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=8E=A5=E5=8F=A3number=5Fout=5Flast?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=97=A0=E6=A8=AA=E6=9D=A0=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E6=98=8E=E7=BB=86=E9=87=8D=E5=A4=8D=E7=BC=96?= =?UTF-8?q?=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit number_out_last原按"前缀-数字"(带横杠)查询,LIKE prefix-%对无横杠 编号(如FS01/FS00025)命中0行返回null,前端遂每次从头重编导致同一 草稿明细出现重复对外编号。改为: - LIKE去横杠(prefix%),用substring(...)~^[0-9]+$约束前缀后紧跟纯数字, 既命中FS00025又排除FSM00027等更长前缀 - 按尾部数字数值排序取最大,避免补零位数不一致时取错 - lstrip(prefix)改为re.sub取尾部数字,与前端提取逻辑一致 Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/wpmw/views.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/apps/wpmw/views.py b/apps/wpmw/views.py index f8582c9d..60c51b69 100644 --- a/apps/wpmw/views.py +++ b/apps/wpmw/views.py @@ -1,3 +1,4 @@ +import re from rest_framework.decorators import action from apps.utils.viewsets import CustomModelViewSet, CustomGenericViewSet from apps.utils.mixins import CustomListModelMixin, CustomRetrieveModelMixin, ComplexQueryMixin, BulkUpdateModelMixin @@ -101,18 +102,19 @@ class WprViewSet(BulkUpdateModelMixin, CustomListModelMixin, CustomRetrieveModel with_unsubmit = request.query_params.get("with_unsubmit", "yes") # wpr_qs_last = Wpr.objects.filter(number_out__startswith=prefix).order_by("number_out").last() # 使用原始sql + # 编号格式为"前缀+补零数字"(无分隔符,如 'FS01'/'FS00025',前端也按此规则拼接)。 + # 用 ^[0-9]+$ 约束前缀后必须紧跟纯数字,避免 'FS' 误命中 'FSM00027' 这类更长前缀; + # 并按尾部数字的数值(而非字符串)排序取最大,避免补零位数不一致时取错。 query = """ - SELECT id, number_out FROM wpmw_wpr + SELECT id, number_out FROM wpmw_wpr WHERE number_out LIKE %s - AND translate( - substring(number_out FROM LENGTH(%s) + 2), - '0123456789', - '' - ) = '' - order by number_out desc limit 1 + AND substring(number_out FROM LENGTH(%s) + 1) ~ '^[0-9]+$' + ORDER BY (substring(number_out FROM LENGTH(%s) + 1))::bigint DESC + LIMIT 1 """ params = ( - f"{prefix}-%", + f"{prefix}%", + prefix, prefix ) number_outs = [] @@ -127,25 +129,23 @@ class WprViewSet(BulkUpdateModelMixin, CustomListModelMixin, CustomRetrieveModel select mioitemw.id, mioitemw.number_out from inm_mioitemw mioitemw left join inm_mioitem mioitem on mioitem.id = mioitemw.mioitem_id left join inm_mio mio on mio.id = mioitem.mio_id where mio.submit_time is null and mioitemw.number_out LIKE %s - AND translate( - substring(mioitemw.number_out FROM LENGTH(%s) + 2), - '0123456789', - '' - ) = '' - order by mioitemw.number_out desc limit 1 + AND substring(mioitemw.number_out FROM LENGTH(%s) + 1) ~ '^[0-9]+$' + ORDER BY (substring(mioitemw.number_out FROM LENGTH(%s) + 1))::bigint DESC + LIMIT 1 """ mioitemw_last = query_one_dict(query2, params) if mioitemw_last: number_outs.append(mioitemw_last["number_out"]) if number_outs: - number_outs.sort() + # 按尾部数字的数值取最大(与前端一致:去掉非数字字符后作为流水号) + number_outs.sort(key=lambda n: int(re.sub(r"\D", "", n))) number_out_last = number_outs[-1] - number_int_last = number_out_last.lstrip(prefix).lstrip("0") + number_int_last = re.sub(r"\D", "", number_out_last) try: number_int_last = int(number_int_last) except ValueError: - raise ParseError(f"找到 {number_int_last}, 请检查前缀格式") - return Response({"number_out_last": number_out_last, "number_out_int_last": int(number_int_last)}) + raise ParseError(f"找到 {number_out_last}, 请检查前缀格式") + return Response({"number_out_last": number_out_last, "number_out_int_last": number_int_last}) else: return Response({"number_out_last": None})