feat(material): add global floating helper to track latest specification codes with smart grouping

This commit is contained in:
DXC
2026-04-13 08:28:27 +08:00
parent e23e8c6a9e
commit c7ac092be4
5 changed files with 298 additions and 1 deletions

View File

@ -954,4 +954,71 @@ class MaterialBaseService:
except Exception as e:
traceback.print_exc()
raise e
raise e
@staticmethod
def get_latest_specs():
"""
获取所有规格型号的最大连号,按智能分组返回
返回格式: [{"group": "S", "latest": "S0115/S0115"}, {"group": "Opt4xxx", "latest": "Opt4018/Opt4018"}, ...]
"""
import re
# 1. 查询所有不为空的规格型号
specs = MaterialBase.query.filter(
MaterialBase.spec_model.isnot(None),
MaterialBase.spec_model != ''
).all()
# 2. 数据结构:{分组名: (原始规格, 数字部分)}
groups = {}
def parse_spec(spec_full):
"""
解析规格型号
返回: (prefix, num, group_name, original_spec)
"""
# 取斜杠前的部分作为基准
base_spec = spec_full.split('/')[0]
# 使用正则解析:字母前缀 + 数字
match = re.match(r'^([A-Za-z]+)(\d+)$', base_spec)
if not match:
return (base_spec, 0, base_spec, spec_full)
prefix, num_str = match.groups()
num = int(num_str)
# 智能分组逻辑
if prefix == 'Opt':
# Opt 按千位段分组
thousand = num // 1000
group = f"Opt{thousand}xxx"
else:
# 常规前缀按原值分组
group = prefix
return (prefix, num, group, spec_full)
# 3. 遍历并分组
for material in specs:
spec = material.spec_model
if not spec:
continue
prefix, num, group, original_spec = parse_spec(spec)
if group not in groups:
groups[group] = (original_spec, num)
else:
_, existing_num = groups[group]
if num > existing_num:
groups[group] = (original_spec, num)
# 4. 构建返回结果,按分组名排序
result = [
{"group": group, "latest": spec}
for group, (spec, _) in sorted(groups.items())
]
return result