Primer version funcional
This commit is contained in:
198
models/Expense.php
Executable file
198
models/Expense.php
Executable file
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
class Expense {
|
||||
public static function all($startDate = null, $endDate = null) {
|
||||
$db = Database::getInstance();
|
||||
|
||||
$sql = "SELECT e.*, u.username as created_by_name
|
||||
FROM expenses e
|
||||
LEFT JOIN users u ON e.created_by = u.id";
|
||||
|
||||
$params = [];
|
||||
|
||||
if ($startDate && $endDate) {
|
||||
$sql .= " WHERE expense_date BETWEEN ? AND ?";
|
||||
$params[] = $startDate;
|
||||
$params[] = $endDate;
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY expense_date DESC";
|
||||
|
||||
return $db->fetchAll($sql, $params);
|
||||
}
|
||||
|
||||
public static function findById($id) {
|
||||
$db = Database::getInstance();
|
||||
return $db->fetchOne(
|
||||
"SELECT * FROM expenses WHERE id = ?",
|
||||
[$id]
|
||||
);
|
||||
}
|
||||
|
||||
public static function create($data, $userId) {
|
||||
$db = Database::getInstance();
|
||||
|
||||
$db->execute(
|
||||
"INSERT INTO expenses (description, amount, expense_date, category, receipt_path, notes, created_by)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||
[
|
||||
$data['description'],
|
||||
$data['amount'],
|
||||
$data['expense_date'],
|
||||
$data['category'] ?? null,
|
||||
$data['receipt_path'] ?? null,
|
||||
$data['notes'] ?? null,
|
||||
$userId
|
||||
]
|
||||
);
|
||||
|
||||
return $db->lastInsertId();
|
||||
}
|
||||
|
||||
public static function update($id, $data) {
|
||||
$db = Database::getInstance();
|
||||
|
||||
$db->execute(
|
||||
"UPDATE expenses SET description = ?, amount = ?, expense_date = ?, category = ?, receipt_path = ?, notes = ? WHERE id = ?",
|
||||
[
|
||||
$data['description'],
|
||||
$data['amount'],
|
||||
$data['expense_date'],
|
||||
$data['category'] ?? null,
|
||||
$data['receipt_path'] ?? null,
|
||||
$data['notes'] ?? null,
|
||||
$id
|
||||
]
|
||||
);
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
public static function save($data, $userId, $receiptFile = null, $allocations = []) {
|
||||
$db = Database::getInstance();
|
||||
$isUpdate = isset($data['id']) && !empty($data['id']);
|
||||
$expenseId = $data['id'] ?? null;
|
||||
|
||||
// Handle receipt upload
|
||||
$receipt_path = $data['receipt_path'] ?? null; // Keep existing path if not new file
|
||||
if ($receiptFile && $receiptFile['error'] === UPLOAD_ERR_OK) {
|
||||
$uploadDir = __DIR__ . '/../uploads/expenses/';
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
$filename = uniqid('receipt_') . '_' . basename($receiptFile['name']);
|
||||
$targetPath = $uploadDir . $filename;
|
||||
if (move_uploaded_file($receiptFile['tmp_name'], $targetPath)) {
|
||||
$receipt_path = '/uploads/expenses/' . $filename;
|
||||
} else {
|
||||
// Handle upload error, maybe return false or throw exception
|
||||
error_log("Failed to move uploaded file: " . $receiptFile['tmp_name'] . " to " . $targetPath);
|
||||
return false;
|
||||
}
|
||||
} elseif ($isUpdate && empty($data['existing_receipt'])) {
|
||||
// If it's an update and no new file, and existing_receipt is empty, clear the path
|
||||
$receipt_path = null;
|
||||
}
|
||||
|
||||
$data['receipt_path'] = $receipt_path;
|
||||
|
||||
if ($isUpdate) {
|
||||
self::update($expenseId, $data);
|
||||
} else {
|
||||
$expenseId = self::create($data, $userId);
|
||||
}
|
||||
|
||||
// Save allocations
|
||||
if ($expenseId && !empty($allocations)) {
|
||||
self::saveAllocations($expenseId, $allocations);
|
||||
} else if ($expenseId && $isUpdate) {
|
||||
// If update and no allocations, clear existing ones
|
||||
$db->execute("DELETE FROM expense_concept_allocations WHERE expense_id = ?", [$expenseId]);
|
||||
}
|
||||
|
||||
return $expenseId;
|
||||
}
|
||||
|
||||
public static function saveAllocations($expenseId, $allocations) {
|
||||
$db = Database::getInstance();
|
||||
// Delete existing allocations for this expense
|
||||
$db->execute("DELETE FROM expense_concept_allocations WHERE expense_id = ?", [$expenseId]);
|
||||
|
||||
foreach ($allocations as $allocation) {
|
||||
$db->execute(
|
||||
"INSERT INTO expense_concept_allocations (expense_id, concept_id, amount)
|
||||
VALUES (?, ?, ?)",
|
||||
[$expenseId, $allocation['concept_id'], $allocation['amount']]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static function delete($id) {
|
||||
$db = Database::getInstance();
|
||||
// Optionally delete associated receipt file
|
||||
$expense = self::findById($id);
|
||||
if ($expense && $expense['receipt_path']) {
|
||||
$filePath = __DIR__ . '/..' . $expense['receipt_path'];
|
||||
if (file_exists($filePath)) {
|
||||
unlink($filePath);
|
||||
}
|
||||
}
|
||||
// Delete allocations first
|
||||
$db->execute("DELETE FROM expense_concept_allocations WHERE expense_id = ?", [$id]);
|
||||
return $db->execute(
|
||||
"DELETE FROM expenses WHERE id = ?",
|
||||
[$id]
|
||||
);
|
||||
}
|
||||
|
||||
public static function getTotalByDateRange($startDate, $endDate) {
|
||||
$db = Database::getInstance();
|
||||
$result = $db->fetchOne(
|
||||
"SELECT COALESCE(SUM(amount), 0) as total
|
||||
FROM expenses
|
||||
WHERE expense_date BETWEEN ? AND ?",
|
||||
[$startDate, $endDate]
|
||||
);
|
||||
return $result['total'] ?? 0;
|
||||
}
|
||||
|
||||
public static function getTotalByCategory($category, $startDate = null, $endDate = null) {
|
||||
$db = Database::getInstance();
|
||||
|
||||
$sql = "SELECT COALESCE(SUM(amount), 0) as total
|
||||
FROM expenses
|
||||
WHERE category = ?";
|
||||
$params = [$category];
|
||||
|
||||
if ($startDate && $endDate) {
|
||||
$sql .= " AND expense_date BETWEEN ? AND ?";
|
||||
$params[] = $startDate;
|
||||
$params[] = $endDate;
|
||||
}
|
||||
|
||||
$result = $db->fetchOne($sql, $params);
|
||||
return $result['total'] ?? 0;
|
||||
}
|
||||
|
||||
public static function getConcepts($expenseId) {
|
||||
$db = Database::getInstance();
|
||||
return $db->fetchAll(
|
||||
"SELECT ec.*, c.name as concept_name
|
||||
FROM expense_concept_allocations ec
|
||||
JOIN finance_collection_concepts c ON ec.concept_id = c.id
|
||||
WHERE ec.expense_id = ?",
|
||||
[$expenseId]
|
||||
);
|
||||
}
|
||||
|
||||
public static function getTotalByConcept($conceptId) {
|
||||
$db = Database::getInstance();
|
||||
$result = $db->fetchOne(
|
||||
"SELECT COALESCE(SUM(amount), 0) as total
|
||||
FROM expense_concept_allocations
|
||||
WHERE concept_id = ?",
|
||||
[$conceptId]
|
||||
);
|
||||
return $result['total'] ?? 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user