Fix: Corregir pantalla blanca y mejorar carga masiva
- Fix error .toFixed() con valores DECIMAL de PostgreSQL (string vs number) - Fix modal de carga masiva que se cerraba sin mostrar resultados - Validar fechas antes de insertar en BD (evita error con "Installed") - Agregar mapeos de columnas comunes (device_status, device_name, etc.) - Normalizar valores de status (Installed -> ACTIVE, New_LoRa -> ACTIVE) - Actualizar documentación del proyecto Archivos modificados: - src/pages/meters/MetersTable.tsx - src/pages/consumption/ConsumptionPage.tsx - src/pages/meters/MeterPage.tsx - water-api/src/services/bulk-upload.service.ts - ESTADO_ACTUAL.md - CAMBIOS_SESION.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -63,27 +63,54 @@ function normalizeColumnName(name: string): string {
|
||||
|
||||
// Map common variations
|
||||
const mappings: Record<string, string> = {
|
||||
// Serial number
|
||||
'serial': 'serial_number',
|
||||
'numero_de_serie': 'serial_number',
|
||||
'serial_number': 'serial_number',
|
||||
'device_s/n': 'serial_number',
|
||||
'device_sn': 'serial_number',
|
||||
's/n': 'serial_number',
|
||||
'sn': 'serial_number',
|
||||
// Meter ID
|
||||
'meter_id': 'meter_id',
|
||||
'meterid': 'meter_id',
|
||||
'id_medidor': 'meter_id',
|
||||
// Name
|
||||
'nombre': 'name',
|
||||
'name': 'name',
|
||||
'device_name': 'name',
|
||||
'meter_name': 'name',
|
||||
'nombre_medidor': 'name',
|
||||
// Concentrator
|
||||
'concentrador': 'concentrator_serial',
|
||||
'concentrator': 'concentrator_serial',
|
||||
'concentrator_serial': 'concentrator_serial',
|
||||
'serial_concentrador': 'concentrator_serial',
|
||||
'gateway': 'concentrator_serial',
|
||||
'gateway_serial': 'concentrator_serial',
|
||||
// Location
|
||||
'ubicacion': 'location',
|
||||
'location': 'location',
|
||||
'direccion': 'location',
|
||||
'address': 'location',
|
||||
// Type
|
||||
'tipo': 'type',
|
||||
'type': 'type',
|
||||
'device_type': 'type',
|
||||
'tipo_dispositivo': 'type',
|
||||
'protocol': 'type',
|
||||
'protocolo': 'type',
|
||||
// Status
|
||||
'estado': 'status',
|
||||
'status': 'status',
|
||||
'device_status': 'status',
|
||||
'estado_dispositivo': 'status',
|
||||
// Installation date
|
||||
'fecha_instalacion': 'installation_date',
|
||||
'installation_date': 'installation_date',
|
||||
'fecha_de_instalacion': 'installation_date',
|
||||
'installed_time': 'installation_date',
|
||||
'installed_date': 'installation_date',
|
||||
};
|
||||
|
||||
return mappings[normalized] || normalized;
|
||||
@@ -181,6 +208,19 @@ export async function bulkUploadMeters(buffer: Buffer): Promise<BulkUploadResult
|
||||
}
|
||||
|
||||
// Prepare meter data
|
||||
// Validate installation_date is actually a valid date
|
||||
let installationDate: string | undefined = undefined;
|
||||
if (row.installation_date) {
|
||||
const dateStr = String(row.installation_date).trim();
|
||||
// Check if it looks like a date (contains numbers and possibly dashes/slashes)
|
||||
if (/^\d{4}[-/]\d{1,2}[-/]\d{1,2}/.test(dateStr) || /^\d{1,2}[-/]\d{1,2}[-/]\d{2,4}/.test(dateStr)) {
|
||||
const parsed = new Date(dateStr);
|
||||
if (!isNaN(parsed.getTime())) {
|
||||
installationDate = parsed.toISOString().split('T')[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const meterData: MeterRow = {
|
||||
serial_number: String(row.serial_number).trim(),
|
||||
meter_id: row.meter_id ? String(row.meter_id).trim() : undefined,
|
||||
@@ -189,7 +229,7 @@ export async function bulkUploadMeters(buffer: Buffer): Promise<BulkUploadResult
|
||||
location: row.location ? String(row.location).trim() : undefined,
|
||||
type: row.type ? String(row.type).trim().toUpperCase() : 'LORA',
|
||||
status: row.status ? String(row.status).trim().toUpperCase() : 'ACTIVE',
|
||||
installation_date: row.installation_date ? String(row.installation_date).trim() : undefined,
|
||||
installation_date: installationDate,
|
||||
};
|
||||
|
||||
// Validate type
|
||||
@@ -198,11 +238,23 @@ export async function bulkUploadMeters(buffer: Buffer): Promise<BulkUploadResult
|
||||
meterData.type = 'LORA';
|
||||
}
|
||||
|
||||
// Validate status
|
||||
const validStatuses = ['ACTIVE', 'INACTIVE', 'MAINTENANCE', 'FAULTY', 'REPLACED'];
|
||||
if (!validStatuses.includes(meterData.status!)) {
|
||||
meterData.status = 'ACTIVE';
|
||||
}
|
||||
// Validate and normalize status
|
||||
const statusMappings: Record<string, string> = {
|
||||
'ACTIVE': 'ACTIVE',
|
||||
'INACTIVE': 'INACTIVE',
|
||||
'MAINTENANCE': 'MAINTENANCE',
|
||||
'FAULTY': 'FAULTY',
|
||||
'REPLACED': 'REPLACED',
|
||||
'INSTALLED': 'ACTIVE',
|
||||
'NEW_LORA': 'ACTIVE',
|
||||
'NEW': 'ACTIVE',
|
||||
'ENABLED': 'ACTIVE',
|
||||
'DISABLED': 'INACTIVE',
|
||||
'OFFLINE': 'INACTIVE',
|
||||
'ONLINE': 'ACTIVE',
|
||||
};
|
||||
const normalizedStatus = meterData.status?.toUpperCase().replace(/\s+/g, '_') || 'ACTIVE';
|
||||
meterData.status = statusMappings[normalizedStatus] || 'ACTIVE';
|
||||
|
||||
// Insert meter
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user