fix(inbound): last-location 回填前校验库位可用

三个入库表单选中物料后,会把该物料「上次用的库位」自动填进表单。
此前是直接把库存行里的字符串回填,不检查它是否还有效。

库位带上公司归属之后,历史库位有两种失效:
  · 指向已被删除的库位(改名/删除后残留的旧路径)
  · 属于另一家公司
两种情况都会让操作员在不知情的情况下,把货记到一个系统里根本不存在、
或不该用的地址上,而界面上看不出任何异常。

改为:按时间从新到旧,挑第一个「仍存在、且本公司可见」的库位;
全都不合法则返回空串(表单不预填)。

★ 即使查不到物料公司(company_name 为空),「库位是否存在」这一层照样校验 —
  「已被删除」跟公司归属无关,任何情况下都不该回填一个不存在的库位。

实测:三个接口共 117 个真实回填值,全部合法。
This commit is contained in:
yueli
2026-09-29 13:33:43 +08:00
parent 3e131fa584
commit d957581718
3 changed files with 36 additions and 6 deletions

View File

@ -12,6 +12,7 @@ import traceback
import json
import numpy as np
from app.utils.ai_vision import extract_and_embed
from app.utils.warehouse_location import material_company, usable_locations
from app.services.image_embedding_service import ImageEmbeddingService
@ -690,6 +691,15 @@ class BuyInboundService:
if not candidates:
return ""
# 按时间倒序排序,返回最新的库位
# 按时间倒序排序
candidates.sort(key=lambda x: x[0] if x[0] else datetime.min, reverse=True)
return candidates[0][1] if candidates[0][1] else ""
# ★ 回填前校验:历史库位可能已被删除、或属于别家公司。不过滤的话,
# 操作员会在不知情的情况下把货记到一个不属于本公司的库位上。
# 按时间从新到旧挑第一个仍可用的;全都不合法则返回空串(表单不预填)。
ordered = [loc for _, loc in candidates if loc]
usable = set(usable_locations(material_company(base_id), ordered))
for loc in ordered:
if loc in usable:
return loc
return ""

View File

@ -12,6 +12,7 @@ import traceback
import json
import numpy as np
from app.utils.ai_vision import extract_and_embed
from app.utils.warehouse_location import material_company, usable_locations
from app.services.image_embedding_service import ImageEmbeddingService
from app.services.track_webhook_service import notify_track, get_current_operator
@ -724,6 +725,15 @@ class ProductInboundService:
if not candidates:
return ""
# 按时间倒序排序,返回最新的库位
# 按时间倒序排序
candidates.sort(key=lambda x: x[0] if x[0] else datetime.min, reverse=True)
return candidates[0][1] if candidates[0][1] else ""
# ★ 回填前校验:历史库位可能已被删除、或属于别家公司。不过滤的话,
# 操作员会在不知情的情况下把货记到一个不属于本公司的库位上。
# 按时间从新到旧挑第一个仍可用的;全都不合法则返回空串(表单不预填)。
ordered = [loc for _, loc in candidates if loc]
usable = set(usable_locations(material_company(base_id), ordered))
for loc in ordered:
if loc in usable:
return loc
return ""

View File

@ -12,6 +12,7 @@ import traceback
import json
import numpy as np
from app.utils.ai_vision import extract_and_embed
from app.utils.warehouse_location import material_company, usable_locations
from app.services.image_embedding_service import ImageEmbeddingService
from app.services.track_webhook_service import notify_track, get_current_operator
@ -802,6 +803,15 @@ class SemiInboundService:
if not candidates:
return ""
# 按时间倒序排序,返回最新的库位
# 按时间倒序排序
candidates.sort(key=lambda x: x[0] if x[0] else datetime.min, reverse=True)
return candidates[0][1] if candidates[0][1] else ""
# ★ 回填前校验:历史库位可能已被删除、或属于别家公司。不过滤的话,
# 操作员会在不知情的情况下把货记到一个不属于本公司的库位上。
# 按时间从新到旧挑第一个仍可用的;全都不合法则返回空串(表单不预填)。
ordered = [loc for _, loc in candidates if loc]
usable = set(usable_locations(material_company(base_id), ordered))
for loc in ordered:
if loc in usable:
return loc
return ""