aaa
This commit is contained in:
parent
3404f5328d
commit
75599b6a0f
365
index.php
365
index.php
@ -1,160 +1,249 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once 'db/config.php';
|
session_start();
|
||||||
|
|
||||||
$pdo = db();
|
/* ========== 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';
|
||||||
|
|
||||||
// İstatistikleri çek
|
$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 = [
|
$stats = [
|
||||||
'total_revenue' => 0,
|
'total_revenue' => $pdo->query("SELECT SUM(total_price) FROM sale_items")->fetchColumn() ?: 0,
|
||||||
'total_profit' => 0,
|
'total_profit' => $pdo->query("SELECT SUM(profit_amount) FROM sale_items")->fetchColumn() ?: 0,
|
||||||
'product_count' => 0,
|
'product_count' => $pdo->query("SELECT COUNT(*) FROM products")->fetchColumn(),
|
||||||
'low_stock_count' => 0
|
'low_stock_count' => $pdo->query("SELECT COUNT(*) FROM products WHERE stock_quantity <= low_stock_threshold")->fetchColumn()
|
||||||
];
|
];
|
||||||
|
|
||||||
try {
|
// Son 5 satış
|
||||||
// Toplam Gelir ve Kâr
|
$recent_sales = $pdo->query("
|
||||||
$stmt = $pdo->query("SELECT SUM(total_amount) as total_revenue, SUM(profit_amount) as total_profit FROM sales");
|
|
||||||
$sales_stats = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
||||||
if ($sales_stats) {
|
|
||||||
$stats['total_revenue'] = $sales_stats['total_revenue'] ?? 0;
|
|
||||||
$stats['total_profit'] = $sales_stats['total_profit'] ?? 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Toplam Ürün Sayısı
|
|
||||||
$stats['product_count'] = $pdo->query("SELECT count(*) FROM products")->fetchColumn();
|
|
||||||
|
|
||||||
// Düşük Stoktaki Ürün Sayısı
|
|
||||||
$stats['low_stock_count'] = $pdo->query("SELECT count(*) FROM products WHERE stock_quantity <= low_stock_threshold")->fetchColumn();
|
|
||||||
|
|
||||||
// Son Satışlar (Son 5)
|
|
||||||
$recent_sales_stmt = $pdo->query("
|
|
||||||
SELECT p.name AS product_name, si.quantity, si.total_price, s.created_at
|
SELECT p.name AS product_name, si.quantity, si.total_price, s.created_at
|
||||||
FROM sale_items si
|
FROM sale_items si
|
||||||
JOIN sales s ON si.sale_id = s.id
|
JOIN sales s ON si.sale_id = s.id
|
||||||
JOIN products p ON si.product_id = p.id
|
JOIN products p ON si.product_id = p.id
|
||||||
ORDER BY s.created_at DESC
|
ORDER BY s.created_at DESC
|
||||||
LIMIT 5
|
LIMIT 5
|
||||||
");
|
")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
$recent_sales = $recent_sales_stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
// Düşük Stoktaki Ürünler
|
// Ürün listesi
|
||||||
$low_stock_products_stmt = $pdo->query("SELECT id, name, stock_quantity, low_stock_threshold FROM products WHERE stock_quantity <= low_stock_threshold ORDER BY stock_quantity ASC");
|
$products = $pdo->query("SELECT * FROM products ORDER BY name ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
$low_stock_products = $low_stock_products_stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
// Stoğu azalan ürünler
|
||||||
$_SESSION['error'] = "Dashboard verileri çekilirken bir hata oluştu: " . $e->getMessage();
|
$low_stock_products = $pdo->query("SELECT * FROM products WHERE stock_quantity <= low_stock_threshold ORDER BY stock_quantity ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
}
|
|
||||||
|
|
||||||
require_once 'partials/header.php';
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<h1 class="mb-4">Ana Panel</h1>
|
<!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">
|
||||||
|
|
||||||
<!-- İstatistik Kartları -->
|
<?php if(isset($_SESSION['success'])) { echo "<div class='alert alert-success'>".$_SESSION['success']."</div>"; unset($_SESSION['success']); } ?>
|
||||||
<div class="row">
|
<?php if(isset($_SESSION['error'])) { echo "<div class='alert alert-danger'>".$_SESSION['error']."</div>"; unset($_SESSION['error']); } ?>
|
||||||
<?php
|
|
||||||
$cards = [
|
<h1 class="mb-4">Dashboard</h1>
|
||||||
['title' => 'Toplam Gelir', 'value' => number_format($stats['total_revenue'],2).' TL', 'color' => 'primary', 'icon' => 'bi-cash-coin'],
|
<div class="row mb-4">
|
||||||
['title' => 'Toplam Kâr', 'value' => number_format($stats['total_profit'],2).' TL', 'color' => 'success', 'icon' => 'bi-graph-up-arrow'],
|
<div class="col-md-3">
|
||||||
['title' => 'Toplam Ürün Çeşidi', 'value' => $stats['product_count'], 'color' => 'info', 'icon' => 'bi-box-seam'],
|
<div class="card text-white bg-primary mb-3">
|
||||||
['title' => 'Düşük Stok Uyarısı', 'value' => $stats['low_stock_count'].' Ürün', 'color' => 'warning', 'icon' => 'bi-exclamation-triangle-fill']
|
<div class="card-body">
|
||||||
];
|
<h5 class="card-title">Toplam Gelir</h5>
|
||||||
foreach($cards as $c): ?>
|
<p class="card-text"><?php echo number_format($stats['total_revenue'],2); ?> TL</p>
|
||||||
<div class="col-xl-3 col-md-6 mb-4">
|
</div></div></div>
|
||||||
<div class="card border-left-<?php echo $c['color']; ?> shadow h-100 py-2">
|
<div class="col-md-3">
|
||||||
<div class="card-body">
|
<div class="card text-white bg-success mb-3">
|
||||||
<div class="row no-gutters align-items-center">
|
<div class="card-body">
|
||||||
<div class="col mr-2">
|
<h5 class="card-title">Toplam Kâr</h5>
|
||||||
<div class="text-xs font-weight-bold text-<?php echo $c['color']; ?> text-uppercase mb-1"><?php echo $c['title']; ?></div>
|
<p class="card-text"><?php echo number_format($stats['total_profit'],2); ?> TL</p>
|
||||||
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo $c['value']; ?></div>
|
</div></div></div>
|
||||||
</div>
|
<div class="col-md-3">
|
||||||
<div class="col-auto">
|
<div class="card text-white bg-info mb-3">
|
||||||
<i class="bi <?php echo $c['icon']; ?> fs-2 text-gray-300"></i>
|
<div class="card-body">
|
||||||
</div>
|
<h5 class="card-title">Ürün Çeşidi</h5>
|
||||||
</div>
|
<p class="card-text"><?php echo $stats['product_count']; ?></p>
|
||||||
</div>
|
</div></div></div>
|
||||||
</div>
|
<div class="col-md-3">
|
||||||
</div>
|
<div class="card text-white bg-warning mb-3">
|
||||||
<?php endforeach; ?>
|
<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>
|
</div>
|
||||||
|
|
||||||
<!-- İçerik Alanı -->
|
<h2 id="products" class="mb-3">Ürünler</h2>
|
||||||
<div class="row">
|
<form method="POST" class="mb-3">
|
||||||
<!-- Son Satışlar -->
|
<div class="row g-2">
|
||||||
<div class="col-lg-7 mb-4">
|
<div class="col-md-3"><input type="text" name="name" class="form-control" placeholder="Ürün Adı" required></div>
|
||||||
<div class="card shadow">
|
<div class="col-md-2"><input type="number" step="0.01" name="price" class="form-control" placeholder="Fiyat" required></div>
|
||||||
<div class="card-header py-3">
|
<div class="col-md-2"><input type="number" name="stock_quantity" class="form-control" placeholder="Stok" required></div>
|
||||||
<h6 class="m-0 font-weight-bold text-primary">Son Satışlar</h6>
|
<div class="col-md-2"><input type="number" name="low_stock_threshold" class="form-control" placeholder="Düşük Stok" required></div>
|
||||||
</div>
|
<div class="col-md-3"><button type="submit" name="add_product" class="btn btn-success w-100">Ürün Ekle</button></div>
|
||||||
<div class="card-body">
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-sm table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Ürün</th>
|
|
||||||
<th>Adet</th>
|
|
||||||
<th>Tutar</th>
|
|
||||||
<th>Tarih</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php if (empty($recent_sales)): ?>
|
|
||||||
<tr><td colspan="4" class="text-center">Henüz satış yok.</td></tr>
|
|
||||||
<?php else: ?>
|
|
||||||
<?php foreach ($recent_sales as $sale): ?>
|
|
||||||
<tr>
|
|
||||||
<td><?php echo htmlspecialchars($sale['product_name']); ?></td>
|
|
||||||
<td><?php echo htmlspecialchars($sale['quantity']); ?></td>
|
|
||||||
<td><?php echo number_format($sale['total_price'], 2); ?> TL</td>
|
|
||||||
<td><?php echo date('d/m/Y', strtotime($sale['created_at'])); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<a href="sales.php" class="btn btn-primary btn-sm">Tüm Satışları Gör →</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Düşük Stoktaki Ürünler -->
|
|
||||||
<div class="col-lg-5 mb-4">
|
|
||||||
<div class="card shadow">
|
|
||||||
<div class="card-header py-3">
|
|
||||||
<h6 class="m-0 font-weight-bold text-warning">Stoğu Azalan Ürünler</h6>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table table-sm table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Ürün</th>
|
|
||||||
<th>Kalan Stok</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php if (empty($low_stock_products)): ?>
|
|
||||||
<tr><td colspan="2" class="text-center">Stoğu azalan ürün yok.</td></tr>
|
|
||||||
<?php else: ?>
|
|
||||||
<?php foreach ($low_stock_products as $product): ?>
|
|
||||||
<tr class="table-warning">
|
|
||||||
<td>
|
|
||||||
<a href="edit-product.php?id=<?php echo $product['id']; ?>">
|
|
||||||
<?php echo htmlspecialchars($product['name']); ?>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td><strong><?php echo htmlspecialchars($product['stock_quantity']); ?></strong> / <?php echo htmlspecialchars($product['low_stock_threshold']); ?></td>
|
|
||||||
</tr>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<a href="products.php" class="btn btn-primary btn-sm">Ürünleri Yönet →</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
<?php require_once 'partials/footer.php'; ?>
|
<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>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user