fetchAll( "SELECT h.id, h.number, h.status, h.consumption_only, h.owner_name FROM houses h ORDER BY CAST(h.number AS UNSIGNED)" ); $periods = ElectricityBill::getPeriods(); // OPTIMIZADO: Una sola query en lugar de 6 queries separadas $allPayments = $db->fetchAll( "SELECT house_id, period, amount, payment_date FROM electricity_payments WHERE year = ? ORDER BY FIELD(period, 'Ene-Feb', 'Mar-Abr', 'May-Jun', 'Jul-Ago', 'Sep-Oct', 'Nov-Dic')", [$year] ); // Organizar pagos por periodo $payments = []; foreach ($periods as $period) { $payments[$period] = []; } foreach ($allPayments as $p) { $payments[$p['period']][$p['house_id']] = $p; } return ['houses' => $houses, 'payments' => $payments, 'periods' => $periods]; } /** * Actualizar un solo pago */ public static function update($houseId, $year, $period, $amount, $userId, $notes = null) { $db = Database::getInstance(); $existing = $db->fetchOne( "SELECT id FROM electricity_payments WHERE house_id = ? AND year = ? AND period = ?", [$houseId, $year, $period] ); if ($amount == 0 && $existing) { $db->execute( "DELETE FROM electricity_payments WHERE id = ?", [$existing['id']] ); return ['success' => true, 'deleted' => true]; } if ($existing) { $db->execute( "UPDATE electricity_payments SET amount = ?, payment_date = NOW(), notes = ?, created_by = ? WHERE id = ?", [$amount, $notes, $userId, $existing['id']] ); } else { $db->execute( "INSERT INTO electricity_payments (house_id, year, period, amount, payment_date, notes, created_by) VALUES (?, ?, ?, ?, NOW(), ?, ?)", [$houseId, $year, $period, $amount, $notes, $userId] ); } return ['success' => true, 'deleted' => false]; } /** * Actualizar múltiples pagos en batch con transacción * OPTIMIZADO: Similar a Payment::updateBatch() */ public static function updateBatch($changes, $userId) { $db = Database::getInstance(); $pdo = $db->getPDO(); try { $pdo->beginTransaction(); $updateCount = 0; $deleteCount = 0; // Preparar statements una sola vez (reutilización) $insertStmt = $pdo->prepare( "INSERT INTO electricity_payments (house_id, year, period, amount, payment_date, created_by) VALUES (?, ?, ?, ?, NOW(), ?) ON DUPLICATE KEY UPDATE amount = VALUES(amount), payment_date = VALUES(payment_date), created_by = VALUES(created_by)" ); $deleteStmt = $pdo->prepare( "DELETE FROM electricity_payments WHERE house_id = ? AND year = ? AND period = ?" ); foreach ($changes as $change) { // Validar que tenemos los datos mínimos if (!isset($change['house_id'], $change['year'], $change['period'])) { continue; } $amount = isset($change['amount']) ? (float)$change['amount'] : 0; if ($amount == 0) { // Eliminar si el monto es 0 $deleteStmt->execute([ $change['house_id'], $change['year'], $change['period'] ]); $deleteCount++; } else { // Insertar o actualizar $insertStmt->execute([ $change['house_id'], $change['year'], $change['period'], $amount, $userId ]); $updateCount++; } } $pdo->commit(); return [ 'success' => true, 'count' => $updateCount + $deleteCount, 'updated' => $updateCount, 'deleted' => $deleteCount ]; } catch (Exception $e) { $pdo->rollback(); error_log("Error en ElectricityPayment::updateBatch: " . $e->getMessage()); return [ 'success' => false, 'error' => $e->getMessage() ]; } } /** * Obtener pagos de una casa específica */ public static function getByHouse($houseId, $year = null) { $db = Database::getInstance(); if ($year) { return $db->fetchAll( "SELECT * FROM electricity_payments WHERE house_id = ? AND year = ? ORDER BY FIELD(period, 'Ene-Feb', 'Mar-Abr', 'May-Jun', 'Jul-Ago', 'Sep-Oct', 'Nov-Dic')", [$houseId, $year] ); } return $db->fetchAll( "SELECT * FROM electricity_payments WHERE house_id = ? ORDER BY year DESC, FIELD(period, 'Ene-Feb', 'Mar-Abr', 'May-Jun', 'Jul-Ago', 'Sep-Oct', 'Nov-Dic') DESC", [$houseId] ); } /** * Obtener total de pagos de un año */ public static function getTotalByYear($year) { $db = Database::getInstance(); $result = $db->fetchOne( "SELECT COALESCE(SUM(amount), 0) as total FROM electricity_payments WHERE year = ?", [$year] ); return $result['total'] ?? 0; } }