Finalización del módulo Luz Cámara: Corrección de errores JS, exportación profesional a PDF y reportes de deudores

This commit is contained in:
2026-02-14 16:07:25 -06:00
parent 5f90790c7a
commit 9850f1a85e
13 changed files with 2849 additions and 536 deletions

View File

@@ -19,6 +19,9 @@
<a href="/dashboard.php?page=reportes&type=concepts" class="btn btn-outline-info <?= ($_GET['type'] ?? '') == 'concepts' ? 'active' : '' ?>">
<i class="bi bi-collection"></i> Conceptos Especiales
</a>
<a href="/dashboard.php?page=reportes&type=electricity-debtors" class="btn btn-outline-warning <?= ($_GET['type'] ?? '') == 'electricity-debtors' ? 'active' : '' ?>">
<i class="bi bi-lightbulb-fill"></i> Deudores Luz
</a>
</div>
</div>
@@ -745,6 +748,233 @@ function exportConceptsCSV() {
}
</script>
</script>
<?php elseif ($reportType == 'electricity-debtors' && isset($electricityDebtors)): ?>
<?php
$hasFilters = !empty($electricityDebtors['filters']['year']) || !empty($electricityDebtors['filters']['periods']) || !empty($electricityDebtors['filters']['house_id']);
$filterText = [];
if (!empty($electricityDebtors['filters']['year'])) {
$filterText[] = "Año: " . $electricityDebtors['filters']['year'];
}
if (!empty($electricityDebtors['filters']['periods'])) {
$filterText[] = "Periodos: " . implode(', ', $electricityDebtors['filters']['periods']);
}
if (!empty($electricityDebtors['filters']['house_id'])) {
require_once __DIR__ . '/../../models/House.php';
$house = House::findById($electricityDebtors['filters']['house_id']);
$filterText[] = "Casa: " . ($house['number'] ?? 'N/A');
}
?>
<div class="card mb-4">
<div class="card-header">
<h5 class="card-title mb-0">
<i class="bi bi-funnel"></i> Filtros de Deudores de Luz
<?php if ($hasFilters): ?>
<span class="badge bg-warning text-dark ms-2"><?= implode(' | ', $filterText) ?></span>
<?php endif; ?>
</h5>
<button type="button" class="btn btn-sm btn-outline-secondary" data-bs-toggle="collapse" data-bs-target="#filtersCollapse">
<i class="bi bi-chevron-down"></i>
</button>
</div>
<div class="collapse <?php echo $hasFilters ? '' : 'show'; ?>" id="filtersCollapse">
<div class="card-body">
<form id="electricityDebtorsFilter">
<div class="row g-3">
<div class="col-md-3">
<label class="form-label">Año</label>
<select name="filter_year" class="form-select">
<option value="">Todos los años</option>
<?php for ($y = 2024; $y <= date('Y') + 1; $y++): ?>
<option value="<?= $y ?>" <?= ($_GET['filter_year'] ?? '') == $y ? 'selected' : '' ?>><?= $y ?></option>
<?php endfor; ?>
</select>
</div>
<div class="col-md-3">
<label class="form-label">Casa</label>
<select name="filter_house" class="form-select">
<option value="">Todas las casas</option>
<?php
require_once __DIR__ . '/../../models/House.php';
$allHouses = House::getAccessible();
foreach ($allHouses as $h): ?>
<option value="<?= $h['id'] ?>" <?= ($_GET['filter_house'] ?? '') == $h['id'] ? 'selected' : '' ?>><?= $h['number'] ?> - <?= htmlspecialchars($h['owner_name'] ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label">Periodos</label>
<div class="d-flex flex-wrap gap-2">
<?php
require_once __DIR__ . '/../../models/ElectricityBill.php';
$allPeriods = ElectricityBill::getPeriods();
$selectedPeriods = explode(',', $_GET['filter_periods'] ?? '');
foreach ($allPeriods as $p): ?>
<div class="form-check">
<input type="checkbox" name="filter_periods[]" value="<?= $p ?>"
class="form-check-input period-checkbox"
id="period_<?= str_replace(' ', '', $p) ?>"
<?= in_array($p, $selectedPeriods) ? 'checked' : '' ?>>
<label class="form-check-label" for="period_<?= str_replace(' ', '', $p) ?>"><?= $p ?></label>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-12">
<button type="submit" class="btn btn-primary">
<i class="bi bi-search"></i> Aplicar Filtros
</button>
<a href="/dashboard.php?page=reportes&type=electricity-debtors" class="btn btn-outline-secondary">
<i class="bi bi-x-circle"></i> Limpiar Filtros
</a>
</div>
</div>
</form>
</div>
</div>
</div>
<script>
document.getElementById('electricityDebtorsFilter').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
const params = new URLSearchParams();
if (formData.get('filter_year')) {
params.append('filter_year', formData.get('filter_year'));
}
if (formData.get('filter_house')) {
params.append('filter_house', formData.get('filter_house'));
}
const selectedPeriods = formData.getAll('filter_periods[]');
if (selectedPeriods.length > 0) {
params.append('filter_periods', selectedPeriods.join(','));
}
window.location.href = '/dashboard.php?page=reportes&type=electricity-debtors&' + params.toString();
});
</script>
<div class="row g-4 mb-4">
<div class="col-md-4">
<div class="card border-warning">
<div class="card-body">
<h6 class="text-muted">Total Adeudado (Luz)</h6>
<h3 class="text-warning">$<?= number_format($electricityDebtors['total_due'], 2) ?></h3>
<small class="text-muted">Total general de deudas</small>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card border-info">
<div class="card-body">
<h6 class="text-muted">Total Esperado</h6>
<h3 class="text-info">$<?= number_format($electricityDebtors['total_expected'], 2) ?></h3>
<small class="text-muted">Total configurado</small>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card border-success">
<div class="card-body">
<h6 class="text-muted">Total Pagado</h6>
<h3 class="text-success">$<?= number_format($electricityDebtors['total_paid'], 2) ?></h3>
<small class="text-muted">Total recaudado</small>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0"><i class="bi bi-exclamation-triangle"></i> Deudores de Luz - Cámara</h5>
<button onclick="exportElectricityDebtorsPDF()" class="btn btn-outline-warning btn-sm">
<i class="bi bi-file-earmark-pdf"></i> Exportar PDF
</button>
</div>
<div class="card-body">
<?php if (empty($electricityDebtors['debtors'])): ?>
<p class="text-muted">No hay deudores registrados</p>
<?php else: ?>
<div class="table-responsive">
<table class="table table-sm table-bordered">
<thead class="table-warning">
<tr>
<th>Casa</th>
<th>Propietario</th>
<th>Periodos Adeudados</th>
<th>Total Debe</th>
</tr>
</thead>
<tbody>
<?php foreach ($electricityDebtors['debtors'] as $debtor): ?>
<tr>
<td><strong><?= $debtor['house_number'] ?></strong></td>
<td><?= htmlspecialchars($debtor['owner_name'] ?? '-') ?></td>
<td>
<table class="table table-sm mb-0">
<?php foreach ($debtor['periods_due'] as $period): ?>
<tr>
<td><?= $period['year'] ?> - <?= $period['period'] ?></td>
<td class="text-end">$<?= number_format($period['due'], 2) ?></td>
</tr>
<?php endforeach; ?>
</table>
</td>
<td class="text-end fw-bold text-danger">$<?= number_format($debtor['total_due'], 2) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot class="table-dark">
<tr>
<th colspan="3" class="text-end">TOTAL GENERAL:</th>
<th class="text-end">$<?= number_format($electricityDebtors['total_due'], 2) ?></th>
</tr>
</tfoot>
</table>
</div>
<?php endif; ?>
</div>
</div>
<script>
function exportElectricityDebtorsPDF() {
const form = document.getElementById('electricityDebtorsFilter');
const params = new URLSearchParams();
params.append('action', 'export_pdf_report');
params.append('type', 'electricity-debtors');
if (form) {
const formData = new FormData(form);
if (formData.get('filter_year')) {
params.append('filter_year', formData.get('filter_year'));
}
if (formData.get('filter_house')) {
params.append('filter_house', formData.get('filter_house'));
}
const selectedPeriods = formData.getAll('filter_periods[]');
if (selectedPeriods.length > 0) {
params.append('filter_periods', selectedPeriods.join(','));
}
} else {
// Fallback si no hay formulario (por ejemplo si se ocultó), usar parámetros de URL actual
const currentParams = new URLSearchParams(window.location.search);
if (currentParams.get('filter_year')) params.append('filter_year', currentParams.get('filter_year'));
if (currentParams.get('filter_house')) params.append('filter_house', currentParams.get('filter_house'));
if (currentParams.get('filter_periods')) params.append('filter_periods', currentParams.get('filter_periods'));
}
window.open('/dashboard.php?page=reportes_actions&' + params.toString(), '_blank');
}
</script>
<?php else: ?>
<div class="card mb-4">
<div class="card-header d-flex justify-content-between align-items-center">

View File

@@ -0,0 +1,123 @@
<style>
table {
width: 100%;
border-collapse: collapse;
font-size: 8pt;
}
th,
td {
border: 1px solid #000;
padding: 4px;
text-align: center;
}
th {
background-color: #eee;
}
.print-title {
text-align: center;
font-size: 14pt;
margin-bottom: 10px;
}
.print-date {
text-align: right;
font-size: 8pt;
margin-bottom: 10px;
}
.text-danger {
color: red;
}
.text-warning {
color: orange;
}
</style>
<div class="print-title">Condominio IBIZA-Cto Sierra Morena 152 - Reporte de Deudores de Luz - Energía Cámara</div>
<div class="print-date">Fecha de generación:
<?= date('d/m/Y H:i')?>
</div>
<?php
$hasFilters = !empty($electricityDebtors['filters']['year']) || !empty($electricityDebtors['filters']['periods']) || !empty($electricityDebtors['filters']['house_id']);
$filterText = [];
if (!empty($electricityDebtors['filters']['year'])) {
$filterText[] = "Año: " . $electricityDebtors['filters']['year'];
}
if (!empty($electricityDebtors['filters']['periods'])) {
$filterText[] = "Periodos: " . implode(', ', $electricityDebtors['filters']['periods']);
}
if (!empty($electricityDebtors['filters']['house_id'])) {
require_once __DIR__ . '/../../models/House.php';
$house = House::findById($electricityDebtors['filters']['house_id']);
$filterText[] = "Casa: " . ($house['number'] ?? 'N/A');
}
if ($hasFilters):
?>
<div style="font-size: 9pt; margin-bottom: 10px;">
<strong>Filtros aplicados:</strong>
<?= implode(' | ', $filterText)?>
</div>
<?php
endif; ?>
<?php if (empty($electricityDebtors['debtors'])): ?>
<p>No hay deudores de luz registrados con los filtros actuales.</p>
<?php
else: ?>
<table>
<thead>
<tr style="background-color: #ffc107;">
<th>Casa</th>
<th>Propietario</th>
<th>Periodos Adeudados</th>
<th>Total Debe</th>
</tr>
</thead>
<tbody>
<?php foreach ($electricityDebtors['debtors'] as $debtor): ?>
<tr>
<td><strong>
<?= $debtor['house_number']?>
</strong></td>
<td>
<?= htmlspecialchars($debtor['owner_name'] ?? '-')?>
</td>
<td>
<table style="width:100%; border: none;">
<?php foreach ($debtor['periods_due'] as $period): ?>
<tr>
<td style="border: none; text-align: left;">
<?= $period['year']?> -
<?= $period['period']?>
</td>
<td style="border: none; text-align: right;">$
<?= number_format($period['due'], 2)?>
</td>
</tr>
<?php
endforeach; ?>
</table>
</td>
<td class="text-end fw-bold text-danger">$
<?= number_format($debtor['total_due'], 2)?>
</td>
</tr>
<?php
endforeach; ?>
</tbody>
<tfoot>
<tr style="background-color: #343a40; color: #fff;">
<th colspan="3" style="text-align: right;">TOTAL GENERAL:</th>
<th style="text-align: right;">$
<?= number_format($electricityDebtors['total_due'], 2)?>
</th>
</tr>
</tfoot>
</table>
<?php
endif; ?>