|
|
@@ -23,6 +23,7 @@ from app.models.crm_models import (
|
|
|
SysOss,
|
|
|
)
|
|
|
from app.models.pl_models import PlInventory, PlPlan, PlPlanProduct
|
|
|
+from app.utils.pinyin_abbr import resolve_name_pinyin_abbr
|
|
|
from fastapi import HTTPException
|
|
|
|
|
|
|
|
|
@@ -522,6 +523,7 @@ def _product_row_to_dict(
|
|
|
"id": row.id,
|
|
|
"productNo": row.product_no,
|
|
|
"productName": row.product_name,
|
|
|
+ "namePinyinAbbr": getattr(row, "name_pinyin_abbr", None) or "",
|
|
|
"categoryId": row.category_id or "",
|
|
|
"categoryName": row.category_name or "",
|
|
|
"model": row.model or "",
|
|
|
@@ -578,11 +580,18 @@ def list_products(
|
|
|
if user_info:
|
|
|
q = apply_crm_create_by_scope(q, CrmProduct, user_info, db, tenant_no)
|
|
|
|
|
|
- # keyword 筛选
|
|
|
+ # keyword 筛选:名称 / 编号 / 拼音首字母
|
|
|
kw = (keyword or "").strip()
|
|
|
if kw:
|
|
|
like = f"%{kw}%"
|
|
|
- q = q.filter(or_(CrmProduct.product_name.like(like), CrmProduct.product_no.like(like)))
|
|
|
+ pinyin_like = f"%{kw.lower()}%"
|
|
|
+ q = q.filter(
|
|
|
+ or_(
|
|
|
+ CrmProduct.product_name.like(like),
|
|
|
+ CrmProduct.product_no.like(like),
|
|
|
+ func.lower(func.coalesce(CrmProduct.name_pinyin_abbr, "")).like(pinyin_like),
|
|
|
+ )
|
|
|
+ )
|
|
|
|
|
|
# category_id 筛选
|
|
|
if category_id:
|
|
|
@@ -751,10 +760,21 @@ def create_product(
|
|
|
if cat:
|
|
|
category_name = cat.category_name
|
|
|
|
|
|
+ # 拼音首字母:新增始终按提交值解析(空则由产品名称生成);兼容 snake / camel 键
|
|
|
+ submitted = kwargs.get("name_pinyin_abbr")
|
|
|
+ if submitted is None and "namePinyinAbbr" in kwargs:
|
|
|
+ submitted = kwargs.get("namePinyinAbbr")
|
|
|
+ name_pinyin_abbr = resolve_name_pinyin_abbr(
|
|
|
+ name=kwargs.get("product_name"),
|
|
|
+ submitted=submitted,
|
|
|
+ submitted_provided=True,
|
|
|
+ )
|
|
|
+
|
|
|
obj = CrmProduct(
|
|
|
id=generate_uuid(),
|
|
|
product_no=product_no,
|
|
|
product_name=kwargs.get("product_name"),
|
|
|
+ name_pinyin_abbr=name_pinyin_abbr,
|
|
|
category_id=category_id,
|
|
|
category_name=category_name or "",
|
|
|
model=kwargs.get("model"),
|
|
|
@@ -815,7 +835,7 @@ def update_product(
|
|
|
db, obj, user_info, obj.tenant_no, message="无权访问该产品"
|
|
|
)
|
|
|
|
|
|
- # 逐字段更新
|
|
|
+ # 逐字段更新(name_pinyin_abbr 单独处理,避免双重赋值)
|
|
|
for field in (
|
|
|
"product_no",
|
|
|
"product_name",
|
|
|
@@ -838,6 +858,23 @@ def update_product(
|
|
|
if field in kwargs and kwargs[field] is not None:
|
|
|
setattr(obj, field, kwargs[field])
|
|
|
|
|
|
+ # 拼音首字母:提交了则用提交值(空则重生);未提交则保留已有,已有空则按名称生成
|
|
|
+ name_keys = ("name_pinyin_abbr", "namePinyinAbbr")
|
|
|
+ submitted_provided = any(k in kwargs for k in name_keys)
|
|
|
+ submitted = kwargs.get("name_pinyin_abbr")
|
|
|
+ if submitted is None:
|
|
|
+ submitted = kwargs.get("namePinyinAbbr")
|
|
|
+ if "product_name" in kwargs and kwargs.get("product_name") is not None:
|
|
|
+ new_name = kwargs.get("product_name")
|
|
|
+ else:
|
|
|
+ new_name = obj.product_name
|
|
|
+ obj.name_pinyin_abbr = resolve_name_pinyin_abbr(
|
|
|
+ name=new_name,
|
|
|
+ submitted=submitted,
|
|
|
+ existing=obj.name_pinyin_abbr,
|
|
|
+ submitted_provided=submitted_provided,
|
|
|
+ )
|
|
|
+
|
|
|
if "barcode" in kwargs:
|
|
|
barcode = _normalize_text(kwargs.get("barcode"))
|
|
|
if barcode and barcode_exists(db, barcode, tenant_no=obj.tenant_no, exclude_id=product_id):
|
|
|
@@ -941,11 +978,18 @@ def list_product_options(
|
|
|
CrmProduct.status == "on",
|
|
|
)
|
|
|
# 下拉选项供合同/报价等选用,不做 create_by 过滤(产品管理分页列表仍保留数据权限)
|
|
|
- # keyword 仅按产品名称模糊匹配(不匹配编号,避免短数字如「32」误命中 SXWL00732x)
|
|
|
+ # keyword:产品名称 + 拼音首字母(不匹配编号,避免短数字如「32」误命中 SXWL00732x)
|
|
|
_ = user_info
|
|
|
kw = (keyword or "").strip()
|
|
|
if kw:
|
|
|
- q = q.filter(CrmProduct.product_name.like(f"%{kw}%"))
|
|
|
+ q = q.filter(
|
|
|
+ or_(
|
|
|
+ CrmProduct.product_name.like(f"%{kw}%"),
|
|
|
+ func.lower(func.coalesce(CrmProduct.name_pinyin_abbr, "")).like(
|
|
|
+ f"%{kw.lower()}%"
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ )
|
|
|
if category_id:
|
|
|
q = q.filter(CrmProduct.category_id == category_id)
|
|
|
q = q.order_by(CrmProduct.create_time.desc())
|