""" Suggests which serial-number fields are probably relevant for a ticket, based on keywords in its line items (e.g. an item name containing "Laptop" suggests Laptop Serial Number + Laptop Asset Tag). This is a starting point staff can edit, not a hard schema - device types and their field sets vary by company and grow over time, so the mapping lives in a setting (DEVICE_FIELD_SUGGESTIONS), not code. If a ticket has two line items that both match "phone" (e.g. a termination processing two lines), the second gets numbered - "Phone IMEI (2)" - rather than colliding with the first. """ from __future__ import annotations from typing import List from app import config def parse_device_field_suggestions(raw: str) -> dict[str, list[str]]: """'keyword:Field One|Field Two,keyword2:Field Three' -> {keyword: [fields]}""" mapping: dict[str, list[str]] = {} for group in (raw or "").split(","): group = group.strip() if not group or ":" not in group: continue keyword, _, fields_str = group.partition(":") keyword = keyword.strip().lower() fields = [f.strip() for f in fields_str.split("|") if f.strip()] if keyword and fields: mapping[keyword] = fields return mapping def get_device_field_suggestions() -> dict[str, list[str]]: return parse_device_field_suggestions( config.get("DEVICE_FIELD_SUGGESTIONS", config.DEFAULT_DEVICE_FIELD_SUGGESTIONS) ) def suggest_serial_fields(line_items: List[dict]) -> List[str]: """ line_items: [{"sku": "OK401", "item_name": "Laptop - Dell Latitude..."}] Returns suggested field labels, in the order their matching keyword was found, numbered on repeat matches (e.g. two phone line items -> "Phone IMEI (1)", "Phone IMEI (2)", ...). Line items describing a shipping/return-label deliverable (e.g. "Shipping - Return Label Laptop") are skipped - they name a device type in passing but aren't an actual physical device to serialize, and would otherwise double-count against the real device line item. """ keyword_map = get_device_field_suggestions() suggestions: List[str] = [] match_counts: dict[str, int] = {} for item in line_items or []: item_name = item.get("item_name", "") or "" if item_name.strip().lower().startswith("shipping"): continue haystack = f"{item_name} {item.get('sku', '')}".lower() for keyword, fields in keyword_map.items(): if keyword in haystack: match_counts[keyword] = match_counts.get(keyword, 0) + 1 occurrence = match_counts[keyword] suffix = f" ({occurrence})" if occurrence > 1 else "" suggestions.extend(f"{field}{suffix}" for field in fields) return suggestions