This commit is contained in:
256
alembic/versions/202605160002_common_work_order_catalog.py
Normal file
256
alembic/versions/202605160002_common_work_order_catalog.py
Normal file
@@ -0,0 +1,256 @@
|
||||
"""seed common work order catalog
|
||||
|
||||
Revision ID: 202605160002
|
||||
Revises: 202605160001
|
||||
Create Date: 2026-05-16 16:30:00.000000
|
||||
"""
|
||||
|
||||
from collections.abc import Sequence
|
||||
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
|
||||
revision: str = "202605160002"
|
||||
down_revision: str | None = "202605160001"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
SOURCE = "system_catalog_202605160002"
|
||||
|
||||
KOREAN = ["Hyundai", "Kia", "Genesis", "SsangYong", "KGM", "GM Korea", "Chevrolet Korea", "Renault Korea", "Samsung Motors"]
|
||||
PREMIUM_IMPORT = ["BMW", "Mercedes-Benz", "Lexus", "Toyota", "MINI"]
|
||||
ALL_IMPORT = KOREAN + PREMIUM_IMPORT
|
||||
|
||||
|
||||
def _meta(
|
||||
makes: list[str] | None = None,
|
||||
*,
|
||||
tiers: list[str] | None = None,
|
||||
keywords: list[str] | None = None,
|
||||
notes: str | None = None,
|
||||
) -> dict:
|
||||
data: dict[str, object] = {"source": SOURCE}
|
||||
if makes:
|
||||
data["applicable_makes"] = makes
|
||||
if tiers:
|
||||
data["quality_tiers"] = tiers
|
||||
if keywords:
|
||||
data["keywords"] = keywords
|
||||
if notes:
|
||||
data["notes"] = notes
|
||||
return data
|
||||
|
||||
|
||||
def _item(
|
||||
*,
|
||||
item_type: str,
|
||||
title: str,
|
||||
category: str,
|
||||
unit: str,
|
||||
default_quantity: int | float = 1,
|
||||
work_type: str | None = None,
|
||||
product_type: str | None = None,
|
||||
brand: str | None = None,
|
||||
sku: str | None = None,
|
||||
volume: int | float | None = None,
|
||||
viscosity: str | None = None,
|
||||
specification: str | None = None,
|
||||
description: str | None = None,
|
||||
metadata_json: dict | None = None,
|
||||
) -> dict:
|
||||
return {
|
||||
"service_center_id": None,
|
||||
"item_type": item_type,
|
||||
"title": title,
|
||||
"category": category,
|
||||
"description": description,
|
||||
"work_type": work_type,
|
||||
"product_type": product_type,
|
||||
"brand": brand,
|
||||
"sku": sku,
|
||||
"unit": unit,
|
||||
"default_quantity": default_quantity,
|
||||
"default_unit_price": 0,
|
||||
"volume": volume,
|
||||
"viscosity": viscosity,
|
||||
"specification": specification,
|
||||
"metadata_json": metadata_json or _meta(ALL_IMPORT),
|
||||
"is_active": True,
|
||||
}
|
||||
|
||||
|
||||
def _work(title: str, category: str, work_type: str = "maintenance", *, makes: list[str] | None = None, keywords: list[str] | None = None) -> dict:
|
||||
return _item(
|
||||
item_type="work",
|
||||
title=title,
|
||||
category=category,
|
||||
work_type=work_type,
|
||||
product_type=None,
|
||||
unit="job",
|
||||
metadata_json=_meta(makes or ALL_IMPORT, keywords=keywords),
|
||||
)
|
||||
|
||||
|
||||
def _product(
|
||||
title: str,
|
||||
category: str,
|
||||
product_type: str,
|
||||
*,
|
||||
unit: str = "pcs",
|
||||
quantity: int | float = 1,
|
||||
brand: str | None = None,
|
||||
sku: str | None = None,
|
||||
volume: int | float | None = None,
|
||||
viscosity: str | None = None,
|
||||
specification: str | None = None,
|
||||
makes: list[str] | None = None,
|
||||
keywords: list[str] | None = None,
|
||||
notes: str | None = None,
|
||||
) -> dict:
|
||||
return _item(
|
||||
item_type="product",
|
||||
title=title,
|
||||
category=category,
|
||||
work_type=None,
|
||||
product_type=product_type,
|
||||
brand=brand,
|
||||
sku=sku,
|
||||
unit=unit,
|
||||
default_quantity=quantity,
|
||||
volume=volume,
|
||||
viscosity=viscosity,
|
||||
specification=specification,
|
||||
metadata_json=_meta(makes or ALL_IMPORT, tiers=["OEM", "premium", "aftermarket"], keywords=keywords, notes=notes),
|
||||
)
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
catalog = sa.table(
|
||||
"work_order_catalog_items",
|
||||
sa.column("service_center_id", sa.Integer()),
|
||||
sa.column("item_type", sa.String()),
|
||||
sa.column("title", sa.String()),
|
||||
sa.column("category", sa.String()),
|
||||
sa.column("description", sa.Text()),
|
||||
sa.column("work_type", sa.String()),
|
||||
sa.column("product_type", sa.String()),
|
||||
sa.column("brand", sa.String()),
|
||||
sa.column("sku", sa.String()),
|
||||
sa.column("unit", sa.String()),
|
||||
sa.column("default_quantity", sa.Numeric()),
|
||||
sa.column("default_unit_price", sa.Numeric()),
|
||||
sa.column("volume", sa.Numeric()),
|
||||
sa.column("viscosity", sa.String()),
|
||||
sa.column("specification", sa.String()),
|
||||
sa.column("metadata_json", sa.JSON()),
|
||||
sa.column("is_active", sa.Boolean()),
|
||||
)
|
||||
|
||||
rows = [
|
||||
_work("Замена воздушного фильтра двигателя", "filters", keywords=["air filter", "engine air filter"]),
|
||||
_work("Замена салонного фильтра", "filters", keywords=["cabin filter", "air conditioner filter"]),
|
||||
_work("Замена топливного фильтра", "filters", keywords=["fuel filter"]),
|
||||
_work("Замена свечей зажигания", "ignition", keywords=["spark plug"]),
|
||||
_work("Замена свечей накаливания", "ignition", work_type="repair", keywords=["glow plug"]),
|
||||
_work("Замена передних тормозных колодок", "brakes", work_type="repair", keywords=["front pads"]),
|
||||
_work("Замена задних тормозных колодок", "brakes", work_type="repair", keywords=["rear pads"]),
|
||||
_work("Замена передних тормозных дисков", "brakes", work_type="repair", keywords=["front rotors"]),
|
||||
_work("Замена задних тормозных дисков", "brakes", work_type="repair", keywords=["rear rotors"]),
|
||||
_work("Замена тормозной жидкости", "brakes", keywords=["brake fluid", "bleeding"]),
|
||||
_work("Замена антифриза", "cooling", keywords=["coolant"]),
|
||||
_work("Замена масла АКПП", "transmission", keywords=["atf", "automatic transmission"]),
|
||||
_work("Замена масла CVT", "transmission", keywords=["cvt fluid"]),
|
||||
_work("Замена масла DCT", "transmission", keywords=["dct fluid", "dual clutch"]),
|
||||
_work("Замена масла редуктора", "drivetrain", keywords=["differential oil", "gear oil"]),
|
||||
_work("Замена масла раздаточной коробки", "drivetrain", keywords=["transfer case"]),
|
||||
_work("Диагностика подвески", "suspension", work_type="diagnostics", keywords=["chassis inspection"]),
|
||||
_work("Замена стойки стабилизатора", "suspension", work_type="repair", keywords=["stabilizer link"]),
|
||||
_work("Замена амортизатора", "suspension", work_type="repair", keywords=["shock absorber", "strut"]),
|
||||
_work("Замена рычага подвески", "suspension", work_type="repair", keywords=["control arm"]),
|
||||
_work("Замена ступичного подшипника", "suspension", work_type="repair", keywords=["wheel bearing"]),
|
||||
_work("Развал-схождение", "wheel_alignment", keywords=["alignment"]),
|
||||
_work("Замена приводного ремня", "engine", work_type="repair", keywords=["serpentine belt"]),
|
||||
_work("Замена ролика натяжителя ремня", "engine", work_type="repair", keywords=["belt tensioner"]),
|
||||
_work("Замена комплекта ремня ГРМ", "engine", work_type="repair", makes=KOREAN + ["Toyota", "Lexus"], keywords=["timing belt"]),
|
||||
_work("Замена комплекта цепи ГРМ", "engine", work_type="repair", keywords=["timing chain"]),
|
||||
_work("Обслуживание кондиционера", "climate", keywords=["ac service", "freon"]),
|
||||
_work("Заправка кондиционера", "climate", keywords=["ac recharge"]),
|
||||
_work("Замена аккумулятора", "electrical", work_type="repair", keywords=["battery"]),
|
||||
_work("Шиномонтаж и балансировка", "tires", keywords=["tire mounting", "balancing"]),
|
||||
_product("Масляный фильтр Hyundai/Kia/Genesis", "filters", "part", brand="Hyundai/Kia", sku="SYS-FILTER-OIL-HKG", makes=["Hyundai", "Kia", "Genesis"], keywords=["oil filter"]),
|
||||
_product("Масляный фильтр SsangYong/KGM", "filters", "part", brand="KGM", sku="SYS-FILTER-OIL-KGM", makes=["SsangYong", "KGM"], keywords=["oil filter"]),
|
||||
_product("Масляный фильтр GM Korea/Chevrolet", "filters", "part", brand="GM Korea", sku="SYS-FILTER-OIL-GMK", makes=["GM Korea", "Chevrolet Korea"], keywords=["oil filter"]),
|
||||
_product("Масляный фильтр Renault Korea/Samsung", "filters", "part", brand="Renault Korea", sku="SYS-FILTER-OIL-RKM", makes=["Renault Korea", "Samsung Motors"], keywords=["oil filter"]),
|
||||
_product("Масляный фильтр BMW/MINI", "filters", "part", brand="BMW/MINI", sku="SYS-FILTER-OIL-BMW-MINI", makes=["BMW", "MINI"], keywords=["oil filter"]),
|
||||
_product("Масляный фильтр Mercedes-Benz", "filters", "part", brand="Mercedes-Benz", sku="SYS-FILTER-OIL-MB", makes=["Mercedes-Benz"], keywords=["oil filter"]),
|
||||
_product("Масляный фильтр Lexus/Toyota", "filters", "part", brand="Toyota/Lexus", sku="SYS-FILTER-OIL-TY-LX", makes=["Toyota", "Lexus"], keywords=["oil filter"]),
|
||||
_product("Воздушный фильтр двигателя", "filters", "part", sku="SYS-FILTER-AIR", keywords=["air filter"]),
|
||||
_product("Салонный фильтр", "filters", "part", sku="SYS-FILTER-CABIN", keywords=["cabin filter"]),
|
||||
_product("Салонный фильтр угольный", "filters", "part", sku="SYS-FILTER-CABIN-CARBON", keywords=["cabin carbon filter"]),
|
||||
_product("Топливный фильтр бензиновый", "filters", "part", sku="SYS-FILTER-FUEL-GAS", keywords=["fuel filter"]),
|
||||
_product("Топливный фильтр дизельный", "filters", "part", sku="SYS-FILTER-FUEL-DIESEL", keywords=["diesel fuel filter"]),
|
||||
_product("Моторное масло 0W-20 API SP / ILSAC GF-6", "engine_oil", "fluid", unit="l", quantity=4, sku="SYS-OIL-0W20-SP", viscosity="0W-20", specification="API SP / ILSAC GF-6", makes=KOREAN + ["Toyota", "Lexus"], keywords=["engine oil"]),
|
||||
_product("Моторное масло 5W-30 API SP / ACEA A5/B5", "engine_oil", "fluid", unit="l", quantity=4, sku="SYS-OIL-5W30-A5B5", viscosity="5W-30", specification="API SP / ACEA A5/B5", makes=KOREAN, keywords=["engine oil"]),
|
||||
_product("Моторное масло 5W-40 ACEA A3/B4", "engine_oil", "fluid", unit="l", quantity=4, sku="SYS-OIL-5W40-A3B4", viscosity="5W-40", specification="ACEA A3/B4", keywords=["engine oil"]),
|
||||
_product("Моторное масло BMW Longlife-04 0W-30/5W-30", "engine_oil", "fluid", unit="l", quantity=5, brand="BMW", sku="SYS-OIL-BMW-LL04", viscosity="0W-30 / 5W-30", specification="BMW LL-04", makes=["BMW", "MINI"], keywords=["engine oil", "ll04"]),
|
||||
_product("Моторное масло Mercedes-Benz 229.52 5W-30", "engine_oil", "fluid", unit="l", quantity=5, brand="Mercedes-Benz", sku="SYS-OIL-MB-22952", viscosity="5W-30", specification="MB 229.52", makes=["Mercedes-Benz"], keywords=["engine oil"]),
|
||||
_product("Моторное масло Toyota/Lexus 0W-20", "engine_oil", "fluid", unit="l", quantity=4, brand="Toyota/Lexus", sku="SYS-OIL-TY-LX-0W20", viscosity="0W-20", specification="Toyota/Lexus 0W-20", makes=["Toyota", "Lexus"], keywords=["engine oil"]),
|
||||
_product("ATF Hyundai/Kia SP-IV", "transmission_fluid", "fluid", unit="l", quantity=6, brand="Hyundai/Kia", sku="SYS-ATF-SP4", specification="SP-IV", makes=["Hyundai", "Kia", "Genesis"], keywords=["atf"]),
|
||||
_product("ATF Hyundai/Kia SP-III", "transmission_fluid", "fluid", unit="l", quantity=6, brand="Hyundai/Kia", sku="SYS-ATF-SP3", specification="SP-III", makes=["Hyundai", "Kia"], keywords=["atf"]),
|
||||
_product("DCTF Hyundai/Kia", "transmission_fluid", "fluid", unit="l", quantity=2, brand="Hyundai/Kia", sku="SYS-DCTF-HKG", specification="DCTF", makes=["Hyundai", "Kia", "Genesis"], keywords=["dct fluid"]),
|
||||
_product("CVTF Hyundai/Kia", "transmission_fluid", "fluid", unit="l", quantity=6, brand="Hyundai/Kia", sku="SYS-CVTF-HKG", specification="CVTF", makes=["Hyundai", "Kia"], keywords=["cvt fluid"]),
|
||||
_product("ATF Dexron VI GM Korea", "transmission_fluid", "fluid", unit="l", quantity=6, brand="GM", sku="SYS-ATF-DEXRON6", specification="Dexron VI", makes=["GM Korea", "Chevrolet Korea"], keywords=["atf"]),
|
||||
_product("ATF/CVTF Renault Korea", "transmission_fluid", "fluid", unit="l", quantity=6, brand="Renault Korea", sku="SYS-ATF-CVT-RKM", specification="ATF/CVTF по VIN", makes=["Renault Korea", "Samsung Motors"], keywords=["atf", "cvt fluid"], notes="Подбирать точную спецификацию по VIN и типу КПП."),
|
||||
_product("ATF BMW ZF 8HP", "transmission_fluid", "fluid", unit="l", quantity=7, brand="ZF/BMW", sku="SYS-ATF-ZF8HP", specification="ZF Lifeguard 8 / BMW 8HP", makes=["BMW", "MINI"], keywords=["atf", "zf 8hp"]),
|
||||
_product("ATF Mercedes 7G-Tronic/9G-Tronic", "transmission_fluid", "fluid", unit="l", quantity=7, brand="Mercedes-Benz", sku="SYS-ATF-MB-7G-9G", specification="MB 236.x по VIN", makes=["Mercedes-Benz"], keywords=["atf"], notes="Подбирать точную спецификацию по VIN и коробке."),
|
||||
_product("ATF Toyota/Lexus WS", "transmission_fluid", "fluid", unit="l", quantity=6, brand="Toyota/Lexus", sku="SYS-ATF-TOYOTA-WS", specification="Toyota WS", makes=["Toyota", "Lexus"], keywords=["atf"]),
|
||||
_product("Масло редуктора 75W-90 GL-5", "gear_oil", "fluid", unit="l", quantity=1, sku="SYS-GEAR-75W90-GL5", viscosity="75W-90", specification="API GL-5", keywords=["gear oil", "differential"]),
|
||||
_product("Антифриз LLC/OAT", "coolant", "fluid", unit="l", quantity=4, sku="SYS-COOLANT-LLC-OAT", specification="LLC/OAT", keywords=["coolant"]),
|
||||
_product("Антифриз Hyundai/Kia Long Life Coolant", "coolant", "fluid", unit="l", quantity=4, brand="Hyundai/Kia", sku="SYS-COOLANT-HKG-LLC", specification="Long Life Coolant", makes=["Hyundai", "Kia", "Genesis"], keywords=["coolant"]),
|
||||
_product("Антифриз BMW/MINI G48/G11", "coolant", "fluid", unit="l", quantity=4, brand="BMW/MINI", sku="SYS-COOLANT-BMW-G48", specification="G48/G11", makes=["BMW", "MINI"], keywords=["coolant"]),
|
||||
_product("Антифриз Mercedes-Benz 325.x", "coolant", "fluid", unit="l", quantity=4, brand="Mercedes-Benz", sku="SYS-COOLANT-MB-325", specification="MB 325.x", makes=["Mercedes-Benz"], keywords=["coolant"]),
|
||||
_product("Тормозная жидкость DOT 4 LV", "brake_fluid", "fluid", unit="l", quantity=1, sku="SYS-BRAKE-DOT4-LV", specification="DOT 4 LV", keywords=["brake fluid"]),
|
||||
_product("Жидкость ГУР CHF 11S/202", "power_steering_fluid", "fluid", unit="l", quantity=1, sku="SYS-PSF-CHF", specification="CHF 11S/202", makes=["BMW", "Mercedes-Benz", "MINI"], keywords=["power steering fluid"]),
|
||||
_product("Передние тормозные колодки", "brakes", "part", sku="SYS-BRAKE-PADS-FRONT", keywords=["front brake pads"]),
|
||||
_product("Задние тормозные колодки", "brakes", "part", sku="SYS-BRAKE-PADS-REAR", keywords=["rear brake pads"]),
|
||||
_product("Передние тормозные диски", "brakes", "part", quantity=2, sku="SYS-BRAKE-ROTORS-FRONT", keywords=["front brake rotors"]),
|
||||
_product("Задние тормозные диски", "brakes", "part", quantity=2, sku="SYS-BRAKE-ROTORS-REAR", keywords=["rear brake rotors"]),
|
||||
_product("Датчик износа тормозных колодок BMW/MINI", "brakes", "part", brand="BMW/MINI", sku="SYS-BRAKE-SENSOR-BMW-MINI", makes=["BMW", "MINI"], keywords=["brake pad wear sensor"]),
|
||||
_product("Датчик износа тормозных колодок Mercedes-Benz", "brakes", "part", brand="Mercedes-Benz", sku="SYS-BRAKE-SENSOR-MB", makes=["Mercedes-Benz"], keywords=["brake pad wear sensor"]),
|
||||
_product("Свеча зажигания иридиевая", "ignition", "part", quantity=4, sku="SYS-SPARK-IRIDIUM", keywords=["spark plug"]),
|
||||
_product("Свеча зажигания платиновая", "ignition", "part", quantity=4, sku="SYS-SPARK-PLATINUM", keywords=["spark plug"]),
|
||||
_product("Свеча накаливания дизельная", "ignition", "part", quantity=4, sku="SYS-GLOW-PLUG", keywords=["glow plug"]),
|
||||
_product("Катушка зажигания", "ignition", "part", sku="SYS-IGNITION-COIL", keywords=["ignition coil"]),
|
||||
_product("Аккумулятор AGM 70Ah", "electrical", "part", sku="SYS-BATTERY-AGM-70", specification="AGM 70Ah", keywords=["battery"]),
|
||||
_product("Аккумулятор AGM 80Ah", "electrical", "part", sku="SYS-BATTERY-AGM-80", specification="AGM 80Ah", keywords=["battery"]),
|
||||
_product("Аккумулятор AGM 95Ah", "electrical", "part", sku="SYS-BATTERY-AGM-95", specification="AGM 95Ah", keywords=["battery"]),
|
||||
_product("Аккумулятор EFB 60Ah", "electrical", "part", sku="SYS-BATTERY-EFB-60", specification="EFB 60Ah", makes=KOREAN, keywords=["battery"]),
|
||||
_product("Аккумулятор EFB 70Ah", "electrical", "part", sku="SYS-BATTERY-EFB-70", specification="EFB 70Ah", makes=KOREAN, keywords=["battery"]),
|
||||
_product("Стойка стабилизатора передняя", "suspension", "part", sku="SYS-SUSP-LINK-FRONT", keywords=["stabilizer link"]),
|
||||
_product("Стойка стабилизатора задняя", "suspension", "part", sku="SYS-SUSP-LINK-REAR", keywords=["stabilizer link"]),
|
||||
_product("Амортизатор передний", "suspension", "part", quantity=2, sku="SYS-SHOCK-FRONT", keywords=["front shock", "strut"]),
|
||||
_product("Амортизатор задний", "suspension", "part", quantity=2, sku="SYS-SHOCK-REAR", keywords=["rear shock"]),
|
||||
_product("Рычаг передней подвески", "suspension", "part", sku="SYS-CONTROL-ARM-FRONT", keywords=["control arm"]),
|
||||
_product("Сайлентблок рычага", "suspension", "part", sku="SYS-BUSHING-CONTROL-ARM", keywords=["bushing"]),
|
||||
_product("Шаровая опора", "suspension", "part", sku="SYS-BALL-JOINT", keywords=["ball joint"]),
|
||||
_product("Ступичный подшипник", "suspension", "part", sku="SYS-WHEEL-BEARING", keywords=["wheel bearing"]),
|
||||
_product("Приводной ремень", "engine", "part", sku="SYS-SERPENTINE-BELT", keywords=["serpentine belt"]),
|
||||
_product("Ролик натяжителя приводного ремня", "engine", "part", sku="SYS-BELT-TENSIONER", keywords=["belt tensioner"]),
|
||||
_product("Комплект ремня ГРМ", "engine", "part", sku="SYS-TIMING-BELT-KIT", makes=KOREAN + ["Toyota", "Lexus"], keywords=["timing belt kit"]),
|
||||
_product("Комплект цепи ГРМ", "engine", "part", sku="SYS-TIMING-CHAIN-KIT", keywords=["timing chain kit"]),
|
||||
_product("Фреон R134a", "climate", "consumable", unit="g", quantity=500, sku="SYS-AC-R134A", specification="R134a", keywords=["freon", "refrigerant"]),
|
||||
_product("Фреон R1234yf", "climate", "consumable", unit="g", quantity=500, sku="SYS-AC-R1234YF", specification="R1234yf", keywords=["freon", "refrigerant"]),
|
||||
_product("Масло компрессора кондиционера PAG", "climate", "fluid", unit="ml", quantity=100, sku="SYS-AC-PAG-OIL", specification="PAG", keywords=["ac compressor oil"]),
|
||||
_product("Щетка стеклоочистителя 450 мм", "wipers", "part", sku="SYS-WIPER-450", specification="450 мм", keywords=["wiper blade"]),
|
||||
_product("Щетка стеклоочистителя 500 мм", "wipers", "part", sku="SYS-WIPER-500", specification="500 мм", keywords=["wiper blade"]),
|
||||
_product("Щетка стеклоочистителя 550 мм", "wipers", "part", sku="SYS-WIPER-550", specification="550 мм", keywords=["wiper blade"]),
|
||||
_product("Щетка стеклоочистителя 600 мм", "wipers", "part", sku="SYS-WIPER-600", specification="600 мм", keywords=["wiper blade"]),
|
||||
_product("Щетка стеклоочистителя 650 мм", "wipers", "part", sku="SYS-WIPER-650", specification="650 мм", keywords=["wiper blade"]),
|
||||
]
|
||||
|
||||
op.bulk_insert(catalog, rows)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.execute(sa.text("DELETE FROM work_order_catalog_items WHERE metadata_json ->> 'source' = :source").bindparams(source=SOURCE))
|
||||
@@ -222,7 +222,7 @@ function catalogOptions(workOrder, itemType) {
|
||||
const suggestions = itemType === "product" ? (catalog.vehicle_suggestions || []) : [];
|
||||
return [...catalogItems, ...suggestions].map((item) => {
|
||||
const key = registerCatalogOption(item);
|
||||
const meta = [item.category, item.specification || item.sku].filter(Boolean).join(" · ");
|
||||
const meta = [item.brand, item.category, item.specification || item.sku].filter(Boolean).join(" · ");
|
||||
return `<option value="${escapeHtml(key)}">${escapeHtml(item.title)}${meta ? ` · ${escapeHtml(meta)}` : ""}</option>`;
|
||||
}).join("");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user