fix:发货编号获取接口number_out_last兼容无横杠格式避免明细重复编号

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) <noreply@anthropic.com>
This commit is contained in:
caoqianming 2026-07-16 13:24:08 +08:00
parent 4050d41370
commit 45c61efdc6
1 changed files with 18 additions and 18 deletions

View File

@ -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
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})