diff --git a/dashboard.php b/dashboard.php index 4fdb627..78963ed 100755 --- a/dashboard.php +++ b/dashboard.php @@ -649,10 +649,14 @@ switch ($page) { 'balance' => 'Balance_General', 'expenses' => 'Gastos_por_Categoria', 'water-debtors' => 'Deudores_de_Agua', - 'concept-debtors' => 'Deudores_de_Conceptos' + 'concept-debtors' => 'Deudores_de_Conceptos', + 'concepts' => 'Conceptos_Especiales' ]; $reportName = $reportNames[$reportType] ?? ucfirst($reportType); + // Para conceptos, definir nombre personalizado del archivo PDF + $pdfFilename = $reportName . '_IBIZA_' . $year . '.pdf'; + // Incluir TCPDF require_once __DIR__ . '/vendor/autoload.php'; require_once __DIR__ . '/vendor/tecnickcom/tcpdf/tcpdf.php'; @@ -709,6 +713,42 @@ switch ($page) { $expensesByCategory = Report::getExpensesByCategory(); include __DIR__ . '/views/reports/pdf_expenses.php'; break; + case 'concepts': + // Requerimos los modelos necesarios + require_once __DIR__ . '/models/CollectionConcept.php'; + require_once __DIR__ . '/models/Expense.php'; + + $filterConceptId = $_GET['filter_concept'] ?? null; + $conceptsToExport = []; + + if ($filterConceptId) { + $concept = CollectionConcept::findById($filterConceptId); + if ($concept) { + $status = CollectionConcept::getCollectionStatus($filterConceptId); + $payments = CollectionConcept::getPaymentsByConcept($filterConceptId); + $conceptsToExport[] = [ + 'concept' => $concept, + 'status' => $status, + 'payments' => $payments + ]; + $conceptName = preg_replace('/[^a-zA-Z0-9_]/', '_', $concept['name']); + $pdfFilename = 'Concepto_' . $conceptName . '_IBIZA.pdf'; + } + } else { + $allConcepts = CollectionConcept::all(true); + foreach ($allConcepts as $c) { + $status = CollectionConcept::getCollectionStatus($c['id']); + $payments = CollectionConcept::getPaymentsByConcept($c['id']); + $conceptsToExport[] = [ + 'concept' => $c, + 'status' => $status, + 'payments' => $payments + ]; + } + } + + include __DIR__ . '/views/reports/pdf_concepts.php'; + break; case 'balance': default: // Requerimos el modelo Report @@ -719,7 +759,7 @@ switch ($page) { } $html = ob_get_clean(); $pdf->writeHTML($html, true, false, true, false, ''); - $pdf->Output($reportName . '_IBIZA_' . $year . '.pdf', 'D'); + $pdf->Output($pdfFilename, 'D'); exit; case 'export_csv_balance': @@ -771,6 +811,86 @@ switch ($page) { fclose($output); exit; + case 'export_csv_concepts': + Auth::requireAdmin(); + require_once __DIR__ . '/models/CollectionConcept.php'; + + $filterConceptId = $_GET['filter_concept'] ?? null; + $conceptsToExport = []; + + if ($filterConceptId) { + $concept = CollectionConcept::findById($filterConceptId); + if ($concept) { + $status = CollectionConcept::getCollectionStatus($filterConceptId); + $payments = CollectionConcept::getPaymentsByConcept($filterConceptId); + $conceptsToExport[] = [ + 'concept' => $concept, + 'status' => $status, + 'payments' => $payments + ]; + } + } else { + $allConcepts = CollectionConcept::all(true); + foreach ($allConcepts as $c) { + $status = CollectionConcept::getCollectionStatus($c['id']); + $payments = CollectionConcept::getPaymentsByConcept($c['id']); + $conceptsToExport[] = [ + 'concept' => $c, + 'status' => $status, + 'payments' => $payments + ]; + } + } + + header('Content-Type: text/csv'); + + if ($filterConceptId && !empty($conceptsToExport)) { + $conceptName = $conceptsToExport[0]['concept']['name']; + $conceptName = preg_replace('/[^a-zA-Z0-9_]/', '_', $conceptName); + $filename = 'Concepto_' . $conceptName . '_IBIZA'; + } else { + $filename = 'Conceptos_Especiales_IBIZA'; + } + + header('Content-Disposition: attachment; filename="' . $filename . '.csv"'); + fputs(fopen('php://output', 'w'), $bom = (chr(0xEF) . chr(0xBB) . chr(0xBF))); + + $output = fopen('php://output', 'w'); + + foreach ($conceptsToExport as $conceptData) { + $concept = $conceptData['concept']; + $status = $conceptData['status']; + $payments = $conceptData['payments']; + + fputcsv($output, ['Condominio IBIZA-Cto Sierra Morena 152 - Concepto: ' . htmlspecialchars($concept['name'])]); + fputcsv($output, ['Fecha: ' . date('d/m/Y', strtotime($concept['concept_date']))]); + if (!empty($concept['description'])) { + fputcsv($output, ['Descripción: ' . htmlspecialchars($concept['description'])]); + } + fputcsv($output, ['']); // Blank line + fputcsv($output, ['Monto por Casa:', $concept['amount_per_house']]); + fputcsv($output, ['Total Recaudado:', $status['total_collected']]); + fputcsv($output, ['Total Esperado:', $status['total_expected']]); + fputcsv($output, ['Balance:', $status['total_collected']]); + fputcsv($output, ['']); // Blank line + fputcsv($output, ['Casa', 'Propietario', 'Monto Pagado', 'Fecha de Pago']); + + foreach ($payments as $payment) { + fputcsv($output, [ + $payment['house_number'], + $payment['owner_name'] ?? '-', + $payment['amount'] > 0 ? $payment['amount'] : 0, + $payment['payment_date'] ? date('d/m/Y', strtotime($payment['payment_date'])) : '-' + ]); + } + + fputcsv($output, ['', '', 'Total:', $status['total_collected']]); + fputcsv($output, ['']); // Blank line para separar conceptos + } + + fclose($output); + exit; + default: // Si no es una acción de exportación conocida, continuar al default break; diff --git a/models/CollectionConcept.php b/models/CollectionConcept.php index 2c8e1cd..157eabf 100755 --- a/models/CollectionConcept.php +++ b/models/CollectionConcept.php @@ -185,7 +185,7 @@ class CollectionPayment { public static function initializePayments($conceptId, $userId) { require_once __DIR__ . '/House.php'; // Incluir House model - $houses = House::allActive(); // Obtener solo casas activas + $houses = House::getActive(); // Obtener solo casas activas $db = Database::getInstance(); $db->beginTransaction(); diff --git a/views/reports/index.php b/views/reports/index.php index 2f3b7ab..9752ce4 100755 --- a/views/reports/index.php +++ b/views/reports/index.php @@ -16,6 +16,9 @@ Deudores de Conceptos + + Conceptos Especiales + @@ -307,6 +310,216 @@ function exportConceptDebtorsPDF() { } + +
+
+
+
+ Filtros de Conceptos Especiales +
+ +
+
+ + + + +
+
+
+
+
+
+
+ + +
+
+
+
+ + + Limpiar Filtros + +
+
+
+
+
+
+ + $concept, + 'status' => $status, + 'payments' => $payments + ]; + } +} else { + $allConcepts = CollectionConcept::all(true); + foreach ($allConcepts as $c) { + $status = CollectionConcept::getCollectionStatus($c['id']); + $payments = CollectionConcept::getPaymentsByConcept($c['id']); + $conceptsToDisplay[] = [ + 'concept' => $c, + 'status' => $status, + 'payments' => $payments + ]; + } +} +?> + + + +
+
+
+ + () +
+
+
+
+
+
+
+
Monto por Casa
+
$
+
+
+
+
+
+
+
Recaudado
+
$
+
+
+
+
+
+
+
Esperado
+
$
+
+
+
+
+
+
+
Balance
+
+ $ +
+
+
+
+
+ +
Pagos por Casa
+ +
+ No hay pagos registrados para este concepto. +
+ +
+ + + + + + + + + + + 0 ? 'table-success' : 'table-light'; + ?> + + + + + + + + + + + + + + + +
CasaPropietarioMonto PagadoFecha de Pago
+ 0 ? '$' . number_format($payment['amount'], 2) : '-' ?> + + +
Total Recaudado:$
+
+ +
+
+ + + +
diff --git a/views/reports/pdf_concepts.php b/views/reports/pdf_concepts.php new file mode 100644 index 0000000..7fafce6 --- /dev/null +++ b/views/reports/pdf_concepts.php @@ -0,0 +1,82 @@ + + + $conceptData): + $concept = $conceptData['concept']; + $status = $conceptData['status']; + $payments = $conceptData['payments']; +?> +

+

Fecha:

+ +

Descripción:

+ + + + + + + + + + + + + + + +
Monto por Casa:$Recaudado:$
Esperado:$Balance:$
+ +

Pagos por Casa

+ + + + + + + + + + + 0 ? '#d4edda' : '#f8f9fa'; + ?> + + + + + + + + + + + + + + + +
CasaPropietarioMonto PagadoFecha de Pago
+ 0 ? '$' . number_format($payment['amount'], 2) : '-' ?> + + +
Total Recaudado:$
+ + +
+ +