124 lines
4.7 KiB
PHP
124 lines
4.7 KiB
PHP
<?php
|
|
require_once __DIR__ . '/db/config.php';
|
|
|
|
$message = '';
|
|
$error = '';
|
|
|
|
function find_or_create($pdo, $table, $name_column, $name_value, $extra_cols = []) {
|
|
if (empty($name_value)) return null;
|
|
|
|
$stmt = $pdo->prepare("SELECT id FROM `$table` WHERE `$name_column` = ?");
|
|
$stmt->execute([$name_value]);
|
|
$id = $stmt->fetchColumn();
|
|
|
|
if (!$id) {
|
|
$cols = '`' . $name_column . '`';
|
|
$vals = '?';
|
|
$exec_vals = [$name_value];
|
|
|
|
foreach ($extra_cols as $col => $val) {
|
|
$cols .= ', '`' . $col . '`';
|
|
$vals .= ', ?';
|
|
$exec_vals[] = $val;
|
|
}
|
|
|
|
$stmt = $pdo->prepare("INSERT INTO `$table` ($cols) VALUES ($vals)");
|
|
$stmt->execute($exec_vals);
|
|
$id = $pdo->lastInsertId();
|
|
}
|
|
return $id;
|
|
}
|
|
|
|
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_FILES['csv_file'])) {
|
|
$file = $_FILES['csv_file']['tmp_name'];
|
|
|
|
if (($handle = fopen($file, "r")) !== FALSE) {
|
|
$pdo = db();
|
|
$pdo->beginTransaction();
|
|
try {
|
|
// Skip header row
|
|
fgetcsv($handle, 1000, ",");
|
|
|
|
$imported_count = 0;
|
|
$sql = "INSERT INTO expenses (expense_date, title, amount, currency, expense_type, category_id, user_id, account_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
|
$stmt = $pdo->prepare($sql);
|
|
|
|
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
|
|
// CSV format: Date,Title,Category,Account,User,Type,Amount,Currency
|
|
$date = $data[0];
|
|
$title = $data[1];
|
|
$category_name = $data[2];
|
|
$account_name = $data[3];
|
|
$user_name = $data[4];
|
|
$expense_type = $data[5];
|
|
$amount = $data[6];
|
|
$currency = $data[7];
|
|
|
|
$category_id = find_or_create($pdo, 'categories', 'name', $category_name);
|
|
$user_id = find_or_create($pdo, 'users', 'name', $user_name, ['email' => strtolower(str_replace(' ', '.', $user_name)).'@example.com']);
|
|
$account_id = find_or_create($pdo, 'accounts', 'name', $account_name, ['user_id' => $user_id, 'currency' => $currency]);
|
|
|
|
$stmt->execute([$date, $title, $amount, $currency, $expense_type, $category_id, $user_id, $account_id]);
|
|
$imported_count++;
|
|
}
|
|
|
|
$pdo->commit();
|
|
$message = "Successfully imported $imported_count expenses!";
|
|
|
|
} catch (Exception $e) {
|
|
$pdo->rollBack();
|
|
$error = "Import failed: " . $e->getMessage();
|
|
}
|
|
fclose($handle);
|
|
} else {
|
|
$error = "Could not open the uploaded file.";
|
|
}
|
|
}
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Import Expenses</title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
|
<link rel="stylesheet" href="assets/css/custom.css">
|
|
</head>
|
|
<body>
|
|
<div class="container mt-5">
|
|
<header class="d-flex justify-content-between align-items-center mb-4">
|
|
<h1>Import Expenses from CSV</h1>
|
|
<a href="index.php" class="btn btn-secondary">Back to Dashboard</a>
|
|
</header>
|
|
|
|
<?php if ($message): ?>
|
|
<div class="alert alert-success"><?php echo htmlspecialchars($message); ?></div>
|
|
<?php endif; ?>
|
|
<?php if ($error): ?>
|
|
<div class="alert alert-danger"><?php echo htmlspecialchars($error); ?></div>
|
|
<?php endif; ?>
|
|
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">Upload CSV File</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<form action="import.php" method="POST" enctype="multipart/form-data">
|
|
<div class="mb-3">
|
|
<label for="csv_file" class="form-label">Select CSV file to upload</label>
|
|
<input class="form-control" type="file" id="csv_file" name="csv_file" accept=".csv" required>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary">Import</button>
|
|
</form>
|
|
</div>
|
|
<div class="card-footer text-muted">
|
|
<small>CSV format should be: <code>Date,Title,Category,Account,User,Type,Amount,Currency</code>. The header row will be skipped.</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
</body>
|
|
</html>
|