Agregar carga masiva de lecturas y corregir manejo de respuestas paginadas
- Implementar carga masiva de lecturas via Excel (backend y frontend) - Corregir cliente API para manejar respuestas con paginación - Eliminar referencias a device_id (columna inexistente) - Cambiar areaName por meterLocation en lecturas - Actualizar fetchProjects y fetchConcentrators para paginación - Agregar documentación del estado actual y cambios Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import { Request, Response } from 'express';
|
||||
import multer from 'multer';
|
||||
import { bulkUploadMeters, generateMeterTemplate } from '../services/bulk-upload.service';
|
||||
import {
|
||||
bulkUploadMeters,
|
||||
generateMeterTemplate,
|
||||
bulkUploadReadings,
|
||||
generateReadingTemplate,
|
||||
} from '../services/bulk-upload.service';
|
||||
|
||||
// Configure multer for memory storage
|
||||
const storage = multer.memoryStorage();
|
||||
@@ -11,13 +16,17 @@ export const upload = multer({
|
||||
fileSize: 10 * 1024 * 1024, // 10MB max
|
||||
},
|
||||
fileFilter: (_req, file, cb) => {
|
||||
// Accept Excel files only
|
||||
// Accept Excel files only - check both MIME type and extension
|
||||
const allowedMimes = [
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
|
||||
'application/vnd.ms-excel', // .xls
|
||||
'application/octet-stream', // Generic binary (some systems send this)
|
||||
];
|
||||
|
||||
if (allowedMimes.includes(file.mimetype)) {
|
||||
const allowedExtensions = ['.xlsx', '.xls'];
|
||||
const fileExtension = file.originalname.toLowerCase().slice(file.originalname.lastIndexOf('.'));
|
||||
|
||||
if (allowedMimes.includes(file.mimetype) || allowedExtensions.includes(fileExtension)) {
|
||||
cb(null, true);
|
||||
} else {
|
||||
cb(new Error('Solo se permiten archivos Excel (.xlsx, .xls)'));
|
||||
@@ -80,3 +89,59 @@ export async function downloadMeterTemplate(_req: Request, res: Response): Promi
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/bulk-upload/readings
|
||||
* Upload Excel file with readings data
|
||||
*/
|
||||
export async function uploadReadings(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
if (!req.file) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: 'No se proporcionó ningún archivo',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await bulkUploadReadings(req.file.buffer);
|
||||
|
||||
res.status(result.success ? 200 : 207).json({
|
||||
success: result.success,
|
||||
data: {
|
||||
totalRows: result.totalRows,
|
||||
inserted: result.inserted,
|
||||
failed: result.errors.length,
|
||||
errors: result.errors.slice(0, 50), // Limit errors in response
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
const error = err as Error;
|
||||
console.error('Error in readings bulk upload:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: error.message || 'Error procesando la carga masiva de lecturas',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/bulk-upload/readings/template
|
||||
* Download Excel template for readings
|
||||
*/
|
||||
export async function downloadReadingTemplate(_req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const buffer = generateReadingTemplate();
|
||||
|
||||
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
res.setHeader('Content-Disposition', 'attachment; filename=plantilla_lecturas.xlsx');
|
||||
res.send(buffer);
|
||||
} catch (err) {
|
||||
const error = err as Error;
|
||||
console.error('Error generating readings template:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Error generando la plantilla de lecturas',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import * as readingService from '../services/reading.service';
|
||||
export async function getAll(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const page = parseInt(req.query.page as string, 10) || 1;
|
||||
const pageSize = Math.min(parseInt(req.query.pageSize as string, 10) || 10, 100);
|
||||
const pageSize = Math.min(parseInt(req.query.pageSize as string, 10) || 50, 1000);
|
||||
|
||||
const filters: meterService.MeterFilters = {};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user