Agregar reporte de Conceptos Especiales con filtros y exportación PDF/CSV
This commit is contained in:
@@ -16,6 +16,9 @@
|
||||
<a href="/dashboard.php?page=reportes&type=concept-debtors" class="btn btn-outline-warning <?= ($_GET['type'] ?? '') == 'concept-debtors' ? 'active' : '' ?>">
|
||||
<i class="bi bi-cash-coin"></i> Deudores de Conceptos
|
||||
</a>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -307,6 +310,216 @@ function exportConceptDebtorsPDF() {
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php elseif ($reportType == 'concepts'): ?>
|
||||
<div class="card mb-4">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex align-items-center">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="bi bi-funnel"></i> Filtros de Conceptos Especiales
|
||||
</h5>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary ms-3" data-bs-toggle="collapse" data-bs-target="#conceptsFilterCollapse">
|
||||
<i class="bi bi-chevron-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<button onclick="exportConceptsPDF()" class="btn btn-outline-primary btn-sm">
|
||||
<i class="bi bi-file-earmark-pdf"></i> PDF
|
||||
</button>
|
||||
<?php if (Auth::isAdmin()): ?>
|
||||
<button onclick="exportConceptsCSV()" class="btn btn-outline-success btn-sm">
|
||||
<i class="bi bi-file-earmark-csv"></i> CSV
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse show" id="conceptsFilterCollapse">
|
||||
<div class="card-body">
|
||||
<form id="conceptsFilter">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-12">
|
||||
<label class="form-label">Concepto</label>
|
||||
<select name="filter_concept" class="form-select">
|
||||
<option value="">Todos los conceptos</option>
|
||||
<?php
|
||||
require_once __DIR__ . '/../../models/CollectionConcept.php';
|
||||
$allConcepts = CollectionConcept::all(true);
|
||||
foreach ($allConcepts as $c): ?>
|
||||
<option value="<?= $c['id'] ?>" <?= ($_GET['filter_concept'] ?? '') == $c['id'] ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($c['name']) ?> - <?= date('d/m/Y', strtotime($c['concept_date'])) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</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=concepts" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-x-circle"></i> Limpiar Filtros
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$filterConceptId = $_GET['filter_concept'] ?? null;
|
||||
$conceptsToDisplay = [];
|
||||
|
||||
if ($filterConceptId) {
|
||||
$concept = CollectionConcept::findById($filterConceptId);
|
||||
if ($concept) {
|
||||
$status = CollectionConcept::getCollectionStatus($filterConceptId);
|
||||
$payments = CollectionConcept::getPaymentsByConcept($filterConceptId);
|
||||
$conceptsToDisplay[] = [
|
||||
'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']);
|
||||
$conceptsToDisplay[] = [
|
||||
'concept' => $c,
|
||||
'status' => $status,
|
||||
'payments' => $payments
|
||||
];
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?php foreach ($conceptsToDisplay as $conceptData): ?>
|
||||
<?php $concept = $conceptData['concept']; $status = $conceptData['status']; $payments = $conceptData['payments']; ?>
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="bi bi-collection"></i> <?= htmlspecialchars($concept['name']) ?>
|
||||
<small class="text-muted">(<?= date('d/m/Y', strtotime($concept['concept_date'])) ?>)</small>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row g-4 mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="card border-primary">
|
||||
<div class="card-body text-center">
|
||||
<h6 class="text-muted">Monto por Casa</h6>
|
||||
<h5 class="text-primary">$<?= number_format($concept['amount_per_house'], 2) ?></h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card border-success">
|
||||
<div class="card-body text-center">
|
||||
<h6 class="text-muted">Recaudado</h6>
|
||||
<h5 class="text-success">$<?= number_format($status['total_collected'], 2) ?></h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card border-info">
|
||||
<div class="card-body text-center">
|
||||
<h6 class="text-muted">Esperado</h6>
|
||||
<h5 class="text-info">$<?= number_format($status['total_expected'], 2) ?></h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card <?= $status['balance'] >= 0 ? 'border-success' : 'border-danger' ?>">
|
||||
<div class="card-body text-center">
|
||||
<h6 class="text-muted">Balance</h6>
|
||||
<h5 class="<?= $status['balance'] >= 0 ? 'text-success' : 'text-danger' ?>">
|
||||
$<?= number_format($status['total_collected'], 2) ?>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 class="mb-3">Pagos por Casa</h6>
|
||||
<?php if (empty($payments)): ?>
|
||||
<div class="alert alert-info text-center">
|
||||
No hay pagos registrados para este concepto.
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered">
|
||||
<thead class="table-primary">
|
||||
<tr>
|
||||
<th>Casa</th>
|
||||
<th>Propietario</th>
|
||||
<th>Monto Pagado</th>
|
||||
<th>Fecha de Pago</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($payments as $payment):
|
||||
$rowClass = $payment['amount'] > 0 ? 'table-success' : 'table-light';
|
||||
?>
|
||||
<tr class="<?= $rowClass ?>">
|
||||
<td><strong><?= $payment['house_number'] ?></strong></td>
|
||||
<td><?= htmlspecialchars($payment['owner_name'] ?? '-') ?></td>
|
||||
<td class="text-end">
|
||||
<?= $payment['amount'] > 0 ? '$' . number_format($payment['amount'], 2) : '-' ?>
|
||||
</td>
|
||||
<td>
|
||||
<?= $payment['payment_date'] ? date('d/m/Y', strtotime($payment['payment_date'])) : '-' ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<tfoot class="table-dark">
|
||||
<tr>
|
||||
<th colspan="2" class="text-end">Total Recaudado:</th>
|
||||
<th class="text-end">$<?= number_format($status['total_collected'], 2) ?></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<script>
|
||||
document.getElementById('conceptsFilter').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(this);
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (formData.get('filter_concept')) {
|
||||
params.append('filter_concept', formData.get('filter_concept'));
|
||||
}
|
||||
|
||||
window.location.href = '/dashboard.php?page=reportes&type=concepts&' + params.toString();
|
||||
});
|
||||
|
||||
function exportConceptsPDF() {
|
||||
const conceptId = '<?= $filterConceptId ?? '' ?>';
|
||||
let url = '/dashboard.php?page=reportes_actions&action=export_pdf_report&type=concepts';
|
||||
if (conceptId) {
|
||||
url += '&filter_concept=' + conceptId;
|
||||
}
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
|
||||
function exportConceptsCSV() {
|
||||
const conceptId = '<?= $filterConceptId ?? '' ?>';
|
||||
let url = '/dashboard.php?page=reportes_actions&action=export_csv_concepts';
|
||||
if (conceptId) {
|
||||
url += '&filter_concept=' + conceptId;
|
||||
}
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php else: ?>
|
||||
|
||||
<div class="row g-4 mb-4">
|
||||
|
||||
82
views/reports/pdf_concepts.php
Normal file
82
views/reports/pdf_concepts.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<style>
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 9pt;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #000;
|
||||
padding: 4px;
|
||||
}
|
||||
th {
|
||||
background-color: #eee;
|
||||
}
|
||||
</style>
|
||||
|
||||
<?php
|
||||
$conceptCount = count($conceptsToExport);
|
||||
foreach ($conceptsToExport as $index => $conceptData):
|
||||
$concept = $conceptData['concept'];
|
||||
$status = $conceptData['status'];
|
||||
$payments = $conceptData['payments'];
|
||||
?>
|
||||
<h2><?= htmlspecialchars($concept['name']) ?></h2>
|
||||
<p><strong>Fecha:</strong> <?= date('d/m/Y', strtotime($concept['concept_date'])) ?></p>
|
||||
<?php if (!empty($concept['description'])): ?>
|
||||
<p><strong>Descripción:</strong> <?= htmlspecialchars($concept['description']) ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td style="background-color: #e3f2fd;"><strong>Monto por Casa:</strong></td>
|
||||
<td style="background-color: #e3f2fd; text-align: right; font-weight: bold;">$<?= number_format($concept['amount_per_house'], 2) ?></td>
|
||||
<td style="background-color: #d4edda;"><strong>Recaudado:</strong></td>
|
||||
<td style="background-color: #d4edda; text-align: right; font-weight: bold;">$<?= number_format($status['total_collected'], 2) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color: #e3f2fd;"><strong>Esperado:</strong></td>
|
||||
<td style="background-color: #e3f2fd; text-align: right; font-weight: bold;">$<?= number_format($status['total_expected'], 2) ?></td>
|
||||
<td style="background-color: #d4edda;"><strong>Balance:</strong></td>
|
||||
<td style="background-color: #d4edda; text-align: right; font-weight: bold;">$<?= number_format($status['total_collected'], 2) ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Pagos por Casa</h3>
|
||||
<table border="1" cellpadding="5">
|
||||
<thead style="background-color: #0d6efd; color: white;">
|
||||
<tr>
|
||||
<th>Casa</th>
|
||||
<th>Propietario</th>
|
||||
<th style="text-align: right;">Monto Pagado</th>
|
||||
<th>Fecha de Pago</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($payments as $payment):
|
||||
$bgColor = $payment['amount'] > 0 ? '#d4edda' : '#f8f9fa';
|
||||
?>
|
||||
<tr style="background-color: <?= $bgColor ?>;">
|
||||
<td><strong><?= $payment['house_number'] ?></strong></td>
|
||||
<td><?= htmlspecialchars($payment['owner_name'] ?? '-') ?></td>
|
||||
<td style="text-align: right;">
|
||||
<?= $payment['amount'] > 0 ? '$' . number_format($payment['amount'], 2) : '-' ?>
|
||||
</td>
|
||||
<td>
|
||||
<?= $payment['payment_date'] ? date('d/m/Y', strtotime($payment['payment_date'])) : '-' ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<tfoot style="background-color: #343a40; color: white; font-weight: bold;">
|
||||
<tr>
|
||||
<td colspan="2" style="text-align: right;">Total Recaudado:</td>
|
||||
<td style="text-align: right;">$<?= number_format($status['total_collected'], 2) ?></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<?php if ($index < $conceptCount - 1): ?>
|
||||
<div style="page-break-after: always;"></div>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
Reference in New Issue
Block a user