Primer version funcional
This commit is contained in:
399
models/Report.php
Executable file
399
models/Report.php
Executable file
@@ -0,0 +1,399 @@
|
||||
<?php
|
||||
|
||||
class Report {
|
||||
public static function getGeneralBalance($startDate = null, $endDate = null) {
|
||||
$db = Database::getInstance();
|
||||
|
||||
$whereClause = '';
|
||||
$params = [];
|
||||
|
||||
if ($startDate && $endDate) {
|
||||
$whereClause = " WHERE YEAR(cp.payment_date) BETWEEN ? AND ?";
|
||||
$params = [$startDate, $endDate];
|
||||
}
|
||||
|
||||
$accessibleHouseIds = Auth::getAccessibleHouseIds();
|
||||
|
||||
if (!empty($accessibleHouseIds) && !Auth::isAdmin()) {
|
||||
$placeholders = str_repeat('?,', count($accessibleHouseIds) - 1) . '?';
|
||||
|
||||
if ($whereClause) {
|
||||
$whereClause .= " AND cp.house_id IN ($placeholders)";
|
||||
} else {
|
||||
$whereClause = " WHERE cp.house_id IN ($placeholders)";
|
||||
}
|
||||
|
||||
$params = array_merge($params, $accessibleHouseIds);
|
||||
}
|
||||
|
||||
$totalConceptPayments = $db->fetchOne(
|
||||
"SELECT COALESCE(SUM(cp.amount), 0) as total
|
||||
FROM finance_collection_payments cp
|
||||
LEFT JOIN finance_collection_concepts c ON cp.concept_id = c.id
|
||||
$whereClause",
|
||||
$params
|
||||
);
|
||||
$totalConceptPayments = $totalConceptPayments['total'] ?? 0;
|
||||
|
||||
$totalExpenses = 0;
|
||||
$balance = $totalConceptPayments;
|
||||
|
||||
if (Auth::isAdmin() || Auth::isCapturist()) {
|
||||
$expenseParams = [];
|
||||
$expenseWhere = '';
|
||||
|
||||
if ($startDate && $endDate) {
|
||||
$expenseWhere = " WHERE YEAR(expense_date) BETWEEN ? AND ?";
|
||||
$expenseParams = [$startDate, $endDate];
|
||||
}
|
||||
|
||||
$totalExpenses = $db->fetchOne(
|
||||
"SELECT COALESCE(SUM(amount), 0) as total
|
||||
FROM expenses $expenseWhere",
|
||||
$expenseParams
|
||||
);
|
||||
$totalExpenses = $totalExpenses['total'] ?? 0;
|
||||
|
||||
$balance = $totalConceptPayments - $totalExpenses;
|
||||
}
|
||||
|
||||
return [
|
||||
'total_incomes' => $totalConceptPayments,
|
||||
'water_incomes' => 0,
|
||||
'concept_incomes' => $totalConceptPayments,
|
||||
'total_expenses' => $totalExpenses,
|
||||
'balance' => $balance
|
||||
];
|
||||
}
|
||||
|
||||
public static function getHouseStatement($houseId, $year = null) {
|
||||
$db = Database::getInstance();
|
||||
$house = House::findById($houseId);
|
||||
|
||||
$whereClause = $year ? " AND year = ?" : "";
|
||||
$params = $year ? [$houseId, $year] : [$houseId];
|
||||
|
||||
$waterPayments = $db->fetchAll(
|
||||
"SELECT 'Agua' as type, month, amount, payment_date, notes
|
||||
FROM payments
|
||||
WHERE house_id = ? $whereClause
|
||||
ORDER BY year DESC, FIELD(month, 'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre') DESC",
|
||||
$params
|
||||
);
|
||||
|
||||
$conceptPayments = $db->fetchAll(
|
||||
"SELECT 'Concepto' as type, c.name as description, cp.amount, cp.payment_date, cp.notes
|
||||
FROM finance_collection_payments cp
|
||||
JOIN finance_collection_concepts c ON cp.concept_id = c.id
|
||||
WHERE cp.house_id = ?" .
|
||||
($year ? " AND YEAR(cp.payment_date) = ?" : "") . "
|
||||
ORDER BY cp.payment_date DESC",
|
||||
$year ? [$houseId, $year] : [$houseId]
|
||||
);
|
||||
|
||||
return [
|
||||
'house' => $house,
|
||||
'water_payments' => $waterPayments,
|
||||
'concept_payments' => $conceptPayments
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPaymentsByYear($year) {
|
||||
$db = Database::getInstance();
|
||||
$months = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
|
||||
'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
|
||||
|
||||
$data = [];
|
||||
foreach ($months as $month) {
|
||||
$result = $db->fetchOne(
|
||||
"SELECT COALESCE(SUM(amount), 0) as total, COUNT(*) as count
|
||||
FROM payments
|
||||
WHERE year = ? AND month = ?",
|
||||
[$year, $month]
|
||||
);
|
||||
$data[$month] = [
|
||||
'total' => $result['total'] ?? 0,
|
||||
'count' => $result['count'] ?? 0
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public static function getExpensesByCategory($startDate = null, $endDate = null) {
|
||||
$db = Database::getInstance();
|
||||
|
||||
$sql = "SELECT category, COALESCE(SUM(amount), 0) as total
|
||||
FROM expenses";
|
||||
|
||||
$params = [];
|
||||
|
||||
if ($startDate && $endDate) {
|
||||
$sql .= " WHERE YEAR(expense_date) BETWEEN ? AND ?";
|
||||
$params = [$startDate, $endDate];
|
||||
}
|
||||
|
||||
$sql .= " GROUP BY category ORDER BY total DESC";
|
||||
|
||||
return $db->fetchAll($sql, $params);
|
||||
}
|
||||
|
||||
public static function getCollectionReport($conceptId) {
|
||||
$concept = CollectionConcept::findById($conceptId);
|
||||
$status = CollectionConcept::getCollectionStatus($conceptId);
|
||||
$payments = CollectionConcept::getPaymentsByConcept($conceptId);
|
||||
|
||||
return [
|
||||
'concept' => $concept,
|
||||
'status' => $status,
|
||||
'payments' => $payments
|
||||
];
|
||||
}
|
||||
|
||||
public static function getDashboardStats($year = null, $accessibleHouseIds = []) {
|
||||
$year = $year ?? date('Y');
|
||||
$db = Database::getInstance();
|
||||
|
||||
if (!empty($accessibleHouseIds) && !Auth::isAdmin()) {
|
||||
$placeholders = str_repeat('?,', count($accessibleHouseIds) - 1) . '?';
|
||||
|
||||
$totalHouses = count($accessibleHouseIds);
|
||||
|
||||
$activeHousesResult = $db->fetchOne(
|
||||
"SELECT COUNT(*) as count
|
||||
FROM houses
|
||||
WHERE id IN ($placeholders) AND status = 'activa'",
|
||||
$accessibleHouseIds
|
||||
);
|
||||
$activeHouses = $activeHousesResult['count'] ?? 0;
|
||||
|
||||
$conceptPayments = $db->fetchOne(
|
||||
"SELECT COALESCE(SUM(cp.amount), 0) as total
|
||||
FROM finance_collection_payments cp
|
||||
WHERE YEAR(cp.payment_date) = ? AND cp.house_id IN ($placeholders)",
|
||||
array_merge([$year], $accessibleHouseIds)
|
||||
);
|
||||
$conceptPayments = $conceptPayments['total'] ?? 0;
|
||||
|
||||
$totalExpenses = 0;
|
||||
$balance = $conceptPayments;
|
||||
} else {
|
||||
$totalHouses = House::countAll();
|
||||
$activeHouses = House::countActive();
|
||||
|
||||
$conceptPayments = $db->fetchOne(
|
||||
"SELECT COALESCE(SUM(cp.amount), 0) as total
|
||||
FROM finance_collection_payments cp
|
||||
WHERE YEAR(cp.payment_date) = ?",
|
||||
[$year]
|
||||
);
|
||||
$conceptPayments = $conceptPayments['total'] ?? 0;
|
||||
|
||||
$totalExpenses = $db->fetchOne(
|
||||
"SELECT COALESCE(SUM(amount), 0) as total
|
||||
FROM expenses
|
||||
WHERE YEAR(expense_date) = ?",
|
||||
[$year]
|
||||
);
|
||||
$totalExpenses = $totalExpenses['total'] ?? 0;
|
||||
|
||||
$balance = $conceptPayments - $totalExpenses;
|
||||
}
|
||||
|
||||
$totalConcepts = $db->fetchOne(
|
||||
"SELECT COUNT(*) as count
|
||||
FROM finance_collection_concepts
|
||||
WHERE is_active = 1"
|
||||
);
|
||||
$totalConcepts = $totalConcepts['count'] ?? 0;
|
||||
|
||||
return [
|
||||
'total_houses' => $totalHouses,
|
||||
'active_houses' => $activeHouses,
|
||||
'total_payments' => $conceptPayments,
|
||||
'total_expenses' => $totalExpenses,
|
||||
'balance' => $balance,
|
||||
'active_concepts' => $totalConcepts,
|
||||
'year' => $year
|
||||
];
|
||||
}
|
||||
|
||||
public static function getWaterDebtors($filters = []) {
|
||||
$db = Database::getInstance();
|
||||
$allMonths = ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio',
|
||||
'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'];
|
||||
|
||||
$year = $filters['year'] ?? null;
|
||||
$months = $filters['months'] ?? $allMonths;
|
||||
$houseId = $filters['house_id'] ?? null;
|
||||
$accessibleHouseIds = $filters['accessible_house_ids'] ?? [];
|
||||
|
||||
$whereHouse = '';
|
||||
$houseParams = [];
|
||||
|
||||
if ($houseId) {
|
||||
$whereHouse = "AND h.id = ?";
|
||||
$houseParams = [$houseId];
|
||||
}
|
||||
|
||||
$sql = "SELECT h.id, h.number, h.owner_name, h.status, h.consumption_only
|
||||
FROM houses h
|
||||
WHERE h.status = 'activa' $whereHouse";
|
||||
|
||||
if (!empty($accessibleHouseIds) && !Auth::isAdmin()) {
|
||||
$placeholders = str_repeat('?,', count($accessibleHouseIds) - 1) . '?';
|
||||
$sql .= " AND h.id IN ($placeholders)";
|
||||
$houseParams = array_merge($houseParams, $accessibleHouseIds);
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY CAST(h.number AS UNSIGNED)";
|
||||
|
||||
$houses = $db->fetchAll($sql, $houseParams);
|
||||
|
||||
if ($year) {
|
||||
$yearsToCheck = [$year];
|
||||
} else {
|
||||
$years = $db->fetchAll("SELECT DISTINCT year FROM payments ORDER BY year");
|
||||
$yearsToCheck = array_column($years, 'year');
|
||||
}
|
||||
|
||||
$debtors = [];
|
||||
$grandTotalExpected = 0;
|
||||
$grandTotalPaid = 0;
|
||||
|
||||
foreach ($houses as $house) {
|
||||
$totalExpected = 0;
|
||||
$totalPaid = 0;
|
||||
$monthDetails = [];
|
||||
|
||||
foreach ($yearsToCheck as $yr) {
|
||||
foreach ($months as $month) {
|
||||
$expected = Payment::getExpectedAmount($house, $yr, $month);
|
||||
$payment = $db->fetchOne(
|
||||
"SELECT amount FROM payments WHERE house_id = ? AND year = ? AND month = ?",
|
||||
[$house['id'], $yr, $month]
|
||||
);
|
||||
$paid = $payment['amount'] ?? 0;
|
||||
$due = $expected - $paid;
|
||||
|
||||
$totalExpected += $expected;
|
||||
$totalPaid += $paid;
|
||||
|
||||
if ($due > 0) {
|
||||
$monthDetails[] = [
|
||||
'year' => $yr,
|
||||
'month' => $month,
|
||||
'expected' => $expected,
|
||||
'paid' => $paid,
|
||||
'due' => $due
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$houseTotalDue = $totalExpected - $totalPaid;
|
||||
|
||||
if ($houseTotalDue > 0) {
|
||||
$debtors[] = [
|
||||
'house_id' => $house['id'],
|
||||
'house_number' => $house['number'],
|
||||
'owner_name' => $house['owner_name'],
|
||||
'months_due' => $monthDetails,
|
||||
'total_due' => $houseTotalDue
|
||||
];
|
||||
}
|
||||
|
||||
$grandTotalExpected += $totalExpected;
|
||||
$grandTotalPaid += $totalPaid;
|
||||
}
|
||||
|
||||
$grandTotalDue = $grandTotalExpected - $grandTotalPaid;
|
||||
|
||||
return [
|
||||
'debtors' => $debtors,
|
||||
'total_due' => $grandTotalDue,
|
||||
'total_expected' => $grandTotalExpected,
|
||||
'total_paid' => $grandTotalPaid,
|
||||
'filters' => $filters
|
||||
];
|
||||
}
|
||||
|
||||
public static function getConceptDebtors($accessibleHouseIds = []) {
|
||||
$db = Database::getInstance();
|
||||
$concepts = $db->fetchAll(
|
||||
"SELECT c.id, c.name, c.amount_per_house
|
||||
FROM finance_collection_concepts c
|
||||
WHERE c.is_active = 1
|
||||
ORDER BY c.created_at DESC"
|
||||
);
|
||||
|
||||
$debtors = [];
|
||||
$grandTotal = 0;
|
||||
|
||||
foreach ($concepts as $concept) {
|
||||
$sql = "SELECT h.id, h.number, h.owner_name, h.status
|
||||
FROM houses h
|
||||
WHERE h.status = 'activa'";
|
||||
|
||||
$params = [];
|
||||
|
||||
if (!empty($accessibleHouseIds) && !Auth::isAdmin()) {
|
||||
$placeholders = str_repeat('?,', count($accessibleHouseIds) - 1) . '?';
|
||||
$sql .= " AND h.id IN ($placeholders)";
|
||||
$params = $accessibleHouseIds;
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY CAST(h.number AS UNSIGNED)";
|
||||
|
||||
$houses = $db->fetchAll($sql, $params);
|
||||
|
||||
$houseDebtors = [];
|
||||
$totalCollected = 0;
|
||||
$totalExpected = $concept['amount_per_house'] * count($houses);
|
||||
|
||||
foreach ($houses as $house) {
|
||||
$payment = $db->fetchOne(
|
||||
"SELECT amount FROM finance_collection_payments
|
||||
WHERE concept_id = ? AND house_id = ?",
|
||||
[$concept['id'], $house['id']]
|
||||
);
|
||||
$paid = $payment['amount'] ?? 0;
|
||||
|
||||
if ($paid < $concept['amount_per_house']) {
|
||||
$due = $concept['amount_per_house'] - $paid;
|
||||
if ($due > 0) {
|
||||
$houseDebtors[] = [
|
||||
'house_id' => $house['id'],
|
||||
'house_number' => $house['number'],
|
||||
'owner_name' => $house['owner_name'],
|
||||
'expected' => $concept['amount_per_house'],
|
||||
'paid' => $paid,
|
||||
'due' => $due
|
||||
];
|
||||
}
|
||||
}
|
||||
$totalCollected += $paid;
|
||||
}
|
||||
|
||||
$conceptTotalDue = $totalExpected - $totalCollected;
|
||||
|
||||
if ($conceptTotalDue > 0) {
|
||||
$debtors[] = [
|
||||
'concept_id' => $concept['id'],
|
||||
'concept_name' => $concept['name'],
|
||||
'amount_per_house' => $concept['amount_per_house'],
|
||||
'total_expected' => $totalExpected,
|
||||
'total_collected' => $totalCollected,
|
||||
'total_due' => $conceptTotalDue,
|
||||
'house_debtors' => $houseDebtors
|
||||
];
|
||||
$grandTotal += $conceptTotalDue;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'debtors' => $debtors,
|
||||
'total_due' => $grandTotal
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user