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
|
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
|
# VEHICLE HIERARCHY NAVIGATION
|
||||||
# ─────────────────────────────────────────────────────────────────────────────
|
# ─────────────────────────────────────────────────────────────────────────────
|
||||||
@@ -87,12 +109,25 @@ def get_models(master_conn, brand_id, year_id=None, brand_name=None):
|
|||||||
rows = cur.fetchall()
|
rows = cur.fetchall()
|
||||||
cur.close()
|
cur.close()
|
||||||
|
|
||||||
# Filter to North America models only
|
# Filter to North America models only, add clean display name, deduplicate
|
||||||
return [
|
filtered = [r for r in rows if is_na_model(brand_name, r[1])]
|
||||||
{'id_model': r[0], 'name_model': r[1]}
|
|
||||||
for r in rows
|
# Group by clean name — keep all id_models but show one display name
|
||||||
if is_na_model(brand_name, r[1])
|
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):
|
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; }
|
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.className = 'nav-grid';
|
||||||
navGrid.innerHTML = data.data.map(function (m) {
|
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) + '">' +
|
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.name_model) + '</div>' +
|
'<div class="nav-card__name">' + esc(m.display_name || m.name_model) + '</div>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
}).join('');
|
}).join('');
|
||||||
|
|
||||||
@@ -887,7 +887,7 @@
|
|||||||
if (!models) return;
|
if (!models) return;
|
||||||
vsModel.innerHTML = '<option value="">Modelo...</option>';
|
vsModel.innerHTML = '<option value="">Modelo...</option>';
|
||||||
models.forEach(function (m) {
|
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