diff --git a/pos/services/catalog_service.py b/pos/services/catalog_service.py index 20311a5..0ea1057 100644 --- a/pos/services/catalog_service.py +++ b/pos/services/catalog_service.py @@ -15,6 +15,28 @@ import re from services.na_models import is_na_model +def _clean_model_name(name): + """Parse TecDoc model name to show only the primary name. + + '4 RUNNER V (_N28_)' → '4 RUNNER' + 'Corolla Hatchback (_E21_)' → 'COROLLA' + 'CAMRY Saloon (_V4_)' → 'CAMRY' + 'RAV 4 III (_A3_)' → 'RAV 4' + """ + s = name.strip() + # Remove generation codes in parentheses: (_N28_), (B1_), (_E21_), etc. + s = re.sub(r'\s*\([^)]*\)\s*', '', s) + # Remove Roman numeral generation suffixes: I, II, III, IV, V, VI, VII, VIII, IX, X + s = re.sub(r'\s+(?:VIII|VII|VI|IV|IX|III|II|V|X|I)(?:\s|$)', ' ', s) + # Remove body type suffixes + s = re.sub(r'\s+(?:Estate|Saloon|Hatchback|Van|Coupe|Coupé|Convertible|Wagon|Pickup|Cab|Sedan|SUV|MPV|Kombi|Kasten|Bus|Box|Platform|Chassis)\b', '', s, flags=re.IGNORECASE) + # Remove "Hatchback Van", "Box Body" compound types + s = re.sub(r'\s+(?:Hatchback|Box)\s+(?:Van|Body)\b', '', s, flags=re.IGNORECASE) + # Clean up extra spaces + s = re.sub(r'\s+', ' ', s).strip() + return s.upper() if s else name.upper() + + # ───────────────────────────────────────────────────────────────────────────── # VEHICLE HIERARCHY NAVIGATION # ───────────────────────────────────────────────────────────────────────────── @@ -87,12 +109,25 @@ def get_models(master_conn, brand_id, year_id=None, brand_name=None): rows = cur.fetchall() cur.close() - # Filter to North America models only - return [ - {'id_model': r[0], 'name_model': r[1]} - for r in rows - if is_na_model(brand_name, r[1]) - ] + # Filter to North America models only, add clean display name, deduplicate + filtered = [r for r in rows if is_na_model(brand_name, r[1])] + + # Group by clean name — keep all id_models but show one display name + seen = {} # display_name → first row + results = [] + for r in filtered: + display = _clean_model_name(r[1]) + if display not in seen: + seen[display] = True + results.append({ + 'id_model': r[0], + 'name_model': r[1], + 'display_name': display, + }) + + # Sort by display_name + results.sort(key=lambda x: x['display_name']) + return results def get_years(master_conn, model_id): diff --git a/pos/static/js/catalog.js b/pos/static/js/catalog.js index 9b42373..68f04dc 100644 --- a/pos/static/js/catalog.js +++ b/pos/static/js/catalog.js @@ -219,8 +219,8 @@ if (!data || !data.data || !data.data.length) { showEmpty('Sin modelos', 'No hay modelos con partes para ' + nav.brand.name); return; } navGrid.className = 'nav-grid'; navGrid.innerHTML = data.data.map(function (m) { - return '