feat(pos): parsear nombres de modelos — solo nombre primario visible
Remueve codigos de generacion, numeros romanos, tipos de carroceria. Deduplica por display_name. Toyota: 236 → 73 modelos limpios. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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):
|
||||
|
||||
@@ -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 '<div class="nav-card" role="listitem" data-model-id="' + m.id_model + '" data-name="' + esc(m.name_model) + '">' +
|
||||
'<div class="nav-card__name">' + esc(m.name_model) + '</div>' +
|
||||
return '<div class="nav-card" role="listitem" data-model-id="' + m.id_model + '" data-name="' + esc(m.display_name || m.name_model) + '">' +
|
||||
'<div class="nav-card__name">' + esc(m.display_name || m.name_model) + '</div>' +
|
||||
'</div>';
|
||||
}).join('');
|
||||
|
||||
@@ -887,7 +887,7 @@
|
||||
if (!models) return;
|
||||
vsModel.innerHTML = '<option value="">Modelo...</option>';
|
||||
models.forEach(function (m) {
|
||||
vsModel.innerHTML += '<option value="' + m.id_model + '">' + esc(m.name_model) + '</option>';
|
||||
vsModel.innerHTML += '<option value="' + m.id_model + '">' + esc(m.display_name || m.name_model) + '</option>';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user