250 lines
9.3 KiB
PHP
250 lines
9.3 KiB
PHP
<?php
|
||
session_start();
|
||
|
||
/* ========== VERİTABANI BAĞLANTISI ========== */
|
||
$host = 'localhost';
|
||
$db = 'store_db'; // veritabanı adını değiştir
|
||
$user = 'root'; // veritabanı kullanıcı adı
|
||
$pass = ''; // veritabanı şifre
|
||
$charset = 'utf8mb4';
|
||
|
||
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
|
||
try {
|
||
$pdo = new PDO($dsn, $user, $pass, [
|
||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
|
||
]);
|
||
} catch (PDOException $e) {
|
||
die("Veritabanına bağlanılamadı: " . $e->getMessage());
|
||
}
|
||
|
||
/* ========== TABLOLARIN OLUŞTURULMASI (İLK SEFERDE YAP) ========== */
|
||
$pdo->exec("
|
||
CREATE TABLE IF NOT EXISTS products (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
name VARCHAR(255) NOT NULL,
|
||
price DECIMAL(10,2) NOT NULL,
|
||
stock_quantity INT DEFAULT 0,
|
||
low_stock_threshold INT DEFAULT 5
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS sales (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS sale_items (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
sale_id INT NOT NULL,
|
||
product_id INT NOT NULL,
|
||
quantity INT NOT NULL,
|
||
total_price DECIMAL(10,2) NOT NULL,
|
||
profit_amount DECIMAL(10,2) NOT NULL,
|
||
FOREIGN KEY (sale_id) REFERENCES sales(id) ON DELETE CASCADE,
|
||
FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE
|
||
);
|
||
");
|
||
|
||
/* ========== İŞLEMLER (GET/POST) ========== */
|
||
// Ürün ekleme
|
||
if(isset($_POST['add_product'])){
|
||
$stmt = $pdo->prepare("INSERT INTO products (name, price, stock_quantity, low_stock_threshold) VALUES (?,?,?,?)");
|
||
$stmt->execute([$_POST['name'], $_POST['price'], $_POST['stock_quantity'], $_POST['low_stock_threshold']]);
|
||
$_SESSION['success'] = "Ürün eklendi.";
|
||
}
|
||
|
||
// Ürün silme
|
||
if(isset($_GET['delete_product'])){
|
||
$stmt = $pdo->prepare("DELETE FROM products WHERE id=?");
|
||
$stmt->execute([$_GET['delete_product']]);
|
||
$_SESSION['success'] = "Ürün silindi.";
|
||
}
|
||
|
||
// Satış ekleme
|
||
if(isset($_POST['add_sale'])){
|
||
$product_ids = $_POST['product_id'];
|
||
$quantities = $_POST['quantity'];
|
||
try {
|
||
$pdo->beginTransaction();
|
||
$pdo->exec("INSERT INTO sales (created_at) VALUES (NOW())");
|
||
$sale_id = $pdo->lastInsertId();
|
||
foreach($product_ids as $i => $pid){
|
||
$qty = intval($quantities[$i]);
|
||
if($qty <= 0) continue;
|
||
$product = $pdo->prepare("SELECT price, stock_quantity FROM products WHERE id=?");
|
||
$product->execute([$pid]);
|
||
$p = $product->fetch();
|
||
if(!$p || $p['stock_quantity'] < $qty) continue;
|
||
$total_price = $p['price'] * $qty;
|
||
$profit_amount = $total_price * 0.2;
|
||
$stmt = $pdo->prepare("INSERT INTO sale_items (sale_id, product_id, quantity, total_price, profit_amount) VALUES (?,?,?,?,?)");
|
||
$stmt->execute([$sale_id, $pid, $qty, $total_price, $profit_amount]);
|
||
$pdo->prepare("UPDATE products SET stock_quantity = stock_quantity - ? WHERE id=?")->execute([$qty, $pid]);
|
||
}
|
||
$pdo->commit();
|
||
$_SESSION['success'] = "Satış eklendi.";
|
||
} catch(PDOException $e){
|
||
$pdo->rollBack();
|
||
$_SESSION['error'] = "Satış eklenirken hata: ".$e->getMessage();
|
||
}
|
||
}
|
||
|
||
/* ========== VERİLERİN ÇEKİLMESİ ========== */
|
||
// Dashboard istatistikleri
|
||
$stats = [
|
||
'total_revenue' => $pdo->query("SELECT SUM(total_price) FROM sale_items")->fetchColumn() ?: 0,
|
||
'total_profit' => $pdo->query("SELECT SUM(profit_amount) FROM sale_items")->fetchColumn() ?: 0,
|
||
'product_count' => $pdo->query("SELECT COUNT(*) FROM products")->fetchColumn(),
|
||
'low_stock_count' => $pdo->query("SELECT COUNT(*) FROM products WHERE stock_quantity <= low_stock_threshold")->fetchColumn()
|
||
];
|
||
|
||
// Son 5 satış
|
||
$recent_sales = $pdo->query("
|
||
SELECT p.name AS product_name, si.quantity, si.total_price, s.created_at
|
||
FROM sale_items si
|
||
JOIN sales s ON si.sale_id = s.id
|
||
JOIN products p ON si.product_id = p.id
|
||
ORDER BY s.created_at DESC
|
||
LIMIT 5
|
||
")->fetchAll(PDO::FETCH_ASSOC);
|
||
|
||
// Ürün listesi
|
||
$products = $pdo->query("SELECT * FROM products ORDER BY name ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||
|
||
// Stoğu azalan ürünler
|
||
$low_stock_products = $pdo->query("SELECT * FROM products WHERE stock_quantity <= low_stock_threshold ORDER BY stock_quantity ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||
|
||
?>
|
||
|
||
<!DOCTYPE html>
|
||
<html lang="tr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Stok & Satış Takip</title>
|
||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet">
|
||
</head>
|
||
<body>
|
||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-4">
|
||
<div class="container-fluid">
|
||
<a class="navbar-brand" href="#">Elit Lastik</a>
|
||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||
<span class="navbar-toggler-icon"></span>
|
||
</button>
|
||
<div class="collapse navbar-collapse" id="navbarNav">
|
||
<ul class="navbar-nav ms-auto">
|
||
<li class="nav-item"><a class="nav-link" href="#">Dashboard</a></li>
|
||
<li class="nav-item"><a class="nav-link" href="#products">Ürünler</a></li>
|
||
<li class="nav-item"><a class="nav-link" href="#sales">Satışlar</a></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
<div class="container">
|
||
|
||
<?php if(isset($_SESSION['success'])) { echo "<div class='alert alert-success'>".$_SESSION['success']."</div>"; unset($_SESSION['success']); } ?>
|
||
<?php if(isset($_SESSION['error'])) { echo "<div class='alert alert-danger'>".$_SESSION['error']."</div>"; unset($_SESSION['error']); } ?>
|
||
|
||
<h1 class="mb-4">Dashboard</h1>
|
||
<div class="row mb-4">
|
||
<div class="col-md-3">
|
||
<div class="card text-white bg-primary mb-3">
|
||
<div class="card-body">
|
||
<h5 class="card-title">Toplam Gelir</h5>
|
||
<p class="card-text"><?php echo number_format($stats['total_revenue'],2); ?> TL</p>
|
||
</div></div></div>
|
||
<div class="col-md-3">
|
||
<div class="card text-white bg-success mb-3">
|
||
<div class="card-body">
|
||
<h5 class="card-title">Toplam Kâr</h5>
|
||
<p class="card-text"><?php echo number_format($stats['total_profit'],2); ?> TL</p>
|
||
</div></div></div>
|
||
<div class="col-md-3">
|
||
<div class="card text-white bg-info mb-3">
|
||
<div class="card-body">
|
||
<h5 class="card-title">Ürün Çeşidi</h5>
|
||
<p class="card-text"><?php echo $stats['product_count']; ?></p>
|
||
</div></div></div>
|
||
<div class="col-md-3">
|
||
<div class="card text-white bg-warning mb-3">
|
||
<div class="card-body">
|
||
<h5 class="card-title">Düşük Stok</h5>
|
||
<p class="card-text"><?php echo $stats['low_stock_count']; ?> Ürün</p>
|
||
</div></div></div>
|
||
</div>
|
||
|
||
<h2 id="products" class="mb-3">Ürünler</h2>
|
||
<form method="POST" class="mb-3">
|
||
<div class="row g-2">
|
||
<div class="col-md-3"><input type="text" name="name" class="form-control" placeholder="Ürün Adı" required></div>
|
||
<div class="col-md-2"><input type="number" step="0.01" name="price" class="form-control" placeholder="Fiyat" required></div>
|
||
<div class="col-md-2"><input type="number" name="stock_quantity" class="form-control" placeholder="Stok" required></div>
|
||
<div class="col-md-2"><input type="number" name="low_stock_threshold" class="form-control" placeholder="Düşük Stok" required></div>
|
||
<div class="col-md-3"><button type="submit" name="add_product" class="btn btn-success w-100">Ürün Ekle</button></div>
|
||
</div>
|
||
</form>
|
||
|
||
<table class="table table-striped table-hover mb-5">
|
||
<thead>
|
||
<tr><th>Ad</th><th>Fiyat</th><th>Stok</th><th>Düşük Stok</th><th>İşlemler</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach($products as $p): ?>
|
||
<tr>
|
||
<td><?php echo htmlspecialchars($p['name']); ?></td>
|
||
<td><?php echo number_format($p['price'],2); ?> TL</td>
|
||
<td><?php echo $p['stock_quantity']; ?></td>
|
||
<td><?php echo $p['low_stock_threshold']; ?></td>
|
||
<td><a href="?delete_product=<?php echo $p['id']; ?>" class="btn btn-danger btn-sm" onclick="return confirm('Silmek istediğine emin misin?')">Sil</a></td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h2 id="sales" class="mb-3">Satışlar</h2>
|
||
<form method="POST" class="mb-3">
|
||
<table class="table table-bordered">
|
||
<tr><th>Ürün</th><th>Adet</th></tr>
|
||
<?php foreach($products as $p): ?>
|
||
<tr>
|
||
<td><?php echo htmlspecialchars($p['name']); ?> (Stok: <?php echo $p['stock_quantity']; ?>)</td>
|
||
<td>
|
||
<input type="number" name="quantity[]" value="0" min="0" max="<?php echo $p['stock_quantity']; ?>" class="form-control">
|
||
<input type="hidden" name="product_id[]" value="<?php echo $p['id']; ?>">
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</table>
|
||
<button type="submit" name="add_sale" class="btn btn-success mb-5">Satışı Kaydet</button>
|
||
</form>
|
||
|
||
<h3 class="mb-3">Son 5 Satış</h3>
|
||
<table class="table table-striped table-hover mb-5">
|
||
<thead>
|
||
<tr><th>Ürün</th><th>Adet</th><th>Toplam</th><th>Tarih</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<?php foreach($recent_sales as $s): ?>
|
||
<tr>
|
||
<td><?php echo htmlspecialchars($s['product_name']); ?></td>
|
||
<td><?php echo $s['quantity']; ?></td>
|
||
<td><?php echo number_format($s['total_price'],2); ?> TL</td>
|
||
<td><?php echo date('d/m/Y H:i', strtotime($s['created_at'])); ?></td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h3>Düşük Stok Ürünler</h3>
|
||
<ul>
|
||
<?php foreach($low_stock_products as $lp): ?>
|
||
<li><?php echo htmlspecialchars($lp['name']); ?> - Stok: <?php echo $lp['stock_quantity']; ?></li>
|
||
<?php endforeach; ?>
|
||
</ul>
|
||
|
||
</div>
|
||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||
</body>
|
||
</html>
|