Email procedure (beta), WorkFlow update
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
"""
|
||||
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
|
||||
Reference in New Issue
Block a user