38808-vm/stock_items.php
2026-03-27 09:55:11 +00:00

313 lines
14 KiB
PHP

<?php
require_once __DIR__ . '/includes/header.php';
require_once __DIR__ . '/includes/pagination.php';
if (!canView('stock_items')) {
echo '<div class="alert alert-danger">عذراً، ليس لديك صلاحية الوصول لهذه الصفحة.</div>';
require_once __DIR__ . '/includes/footer.php';
exit;
}
$success = '';
$error = '';
// Handle Actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = $_POST['action'] ?? '';
$id = $_POST['id'] ?? 0;
$name = $_POST['name'] ?? '';
$sku = $_POST['sku'] ?? '';
$category_id = $_POST['category_id'] ?? null;
$min_quantity = $_POST['min_quantity'] ?? 0;
$unit = $_POST['unit'] ?? 'piece';
$description = $_POST['description'] ?? '';
if ($action === 'add' && canAdd('stock_items')) {
if ($name) {
$stmt = db()->prepare("INSERT INTO stock_items (name, sku, category_id, min_quantity, unit, description) VALUES (?, ?, ?, ?, ?, ?)");
if ($stmt->execute([$name, $sku, $category_id, $min_quantity, $unit, $description])) {
$success = 'تم إضافة الصنف بنجاح';
} else {
$error = 'حدث خطأ أثناء الإضافة';
}
}
} elseif ($action === 'edit' && canEdit('stock_items')) {
if ($name && $id) {
$stmt = db()->prepare("UPDATE stock_items SET name=?, sku=?, category_id=?, min_quantity=?, unit=?, description=? WHERE id=?");
if ($stmt->execute([$name, $sku, $category_id, $min_quantity, $unit, $description, $id])) {
$success = 'تم تحديث الصنف بنجاح';
} else {
$error = 'حدث خطأ أثناء التحديث';
}
}
} elseif ($action === 'delete' && canDelete('stock_items')) {
if ($id) {
$stmt = db()->prepare("DELETE FROM stock_items WHERE id=?");
if ($stmt->execute([$id])) {
$success = 'تم حذف الصنف بنجاح';
} else {
$error = 'لا يمكن حذف الصنف لوجود حركات مرتبطة به';
}
}
}
}
// Pagination & Search
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
if ($page < 1) $page = 1;
$limit = 10;
$offset = ($page - 1) * $limit;
$where = "WHERE 1=1";
$params = [];
if (isset($_GET['search']) && !empty($_GET['search'])) {
$where .= " AND (i.name LIKE ? OR i.sku LIKE ?)";
$search = "%" . $_GET['search'] . "%";
$params = array_merge($params, [$search, $search]);
}
if (isset($_GET['category_id']) && !empty($_GET['category_id'])) {
$where .= " AND i.category_id = ?";
$params[] = $_GET['category_id'];
}
// Count Total
$countQuery = "SELECT COUNT(*) FROM stock_items i $where";
$countStmt = db()->prepare($countQuery);
$countStmt->execute($params);
$totalFiltered = $countStmt->fetchColumn();
// Fetch Items with Category Name and Total Quantity
$query = "
SELECT i.*, c.name as category_name,
(SELECT SUM(quantity) FROM stock_quantities q WHERE q.item_id = i.id) as total_quantity
FROM stock_items i
LEFT JOIN stock_categories c ON i.category_id = c.id
$where
ORDER BY i.name ASC
LIMIT $limit OFFSET $offset
";
$stmt = db()->prepare($query);
$stmt->execute($params);
$items = $stmt->fetchAll();
// Fetch Categories for Dropdown
$categories = db()->query("SELECT * FROM stock_categories ORDER BY name ASC")->fetchAll();
?>
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">إدارة الأصناف</h1>
<?php if (canAdd('stock_items')): ?>
<button type="button" class="btn btn-primary" onclick="openItemModal('add')">
<i class="fas fa-plus"></i> إضافة صنف جديد
</button>
<?php endif; ?>
</div>
<?php if ($success): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<?= $success ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if ($error): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<?= $error ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<!-- Filter Bar -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-body p-3">
<form method="GET" class="row g-2 align-items-center">
<div class="col-md-5">
<div class="input-group">
<span class="input-group-text bg-white border-end-0"><i class="fas fa-search text-muted"></i></span>
<input type="text" name="search" class="form-control border-start-0" placeholder="بحث باسم الصنف أو الرمز (SKU)..." value="<?= htmlspecialchars($_GET['search'] ?? '') ?>">
</div>
</div>
<div class="col-md-4">
<select name="category_id" class="form-select" onchange="this.form.submit()">
<option value="">جميع التصنيفات</option>
<?php foreach ($categories as $cat): ?>
<option value="<?= $cat['id'] ?>" <?= (isset($_GET['category_id']) && $_GET['category_id'] == $cat['id']) ? 'selected' : '' ?>><?= $cat['name'] ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-3 text-end">
<button type="submit" class="btn btn-light w-100">تصفية</button>
</div>
</form>
</div>
</div>
<div class="card shadow-sm border-0">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead class="bg-light">
<tr>
<th class="ps-4">اسم الصنف</th>
<th>الرمز (SKU)</th>
<th>التصنيف</th>
<th>الكمية الحالية</th>
<th>الحد الأدنى</th>
<th>الوحدة</th>
<th class="text-center">الإجراءات</th>
</tr>
</thead>
<tbody>
<?php if (empty($items)): ?>
<tr>
<td colspan="7" class="text-center py-5 text-muted">
<i class="fas fa-boxes fa-3x mb-3 opacity-20"></i>
<p>لا يوجد أصناف مطابقة.</p>
</td>
</tr>
<?php endif; ?>
<?php foreach ($items as $item): ?>
<tr>
<td class="ps-4 fw-bold"><?= htmlspecialchars($item['name']) ?></td>
<td><?= htmlspecialchars($item['sku'] ?? '-') ?></td>
<td><span class="badge bg-secondary"><?= htmlspecialchars($item['category_name'] ?? 'عام') ?></span></td>
<td>
<?php
$qty = $item['total_quantity'] ?: 0;
$cls = ($qty <= $item['min_quantity']) ? 'text-danger fw-bold' : 'text-success';
?>
<span class="<?= $cls ?>"><?= number_format($qty, 2) ?></span>
</td>
<td><?= number_format($item['min_quantity']) ?></td>
<td><?= htmlspecialchars($item['unit']) ?></td>
<td class="text-center">
<?php if (canEdit('stock_items')): ?>
<button class="btn btn-sm btn-outline-primary" onclick='openItemModal("edit", <?= json_encode($item) ?>)'>
<i class="fas fa-edit"></i>
</button>
<?php endif; ?>
<?php if (canDelete('stock_items')): ?>
<button class="btn btn-sm btn-outline-danger" onclick="confirmDelete(<?= $item['id'] ?>)">
<i class="fas fa-trash"></i>
</button>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<!-- Pagination -->
<?php renderPagination($page, $totalFiltered, $limit); ?>
</div>
</div>
<!-- Item Modal -->
<div class="modal fade" id="itemModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-light">
<h5 class="modal-title" id="itemModalLabel">إضافة صنف</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="POST">
<div class="modal-body">
<input type="hidden" name="action" id="modalAction" value="add">
<input type="hidden" name="id" id="modalId" value="">
<div class="mb-3">
<label class="form-label">اسم الصنف <span class="text-danger">*</span></label>
<input type="text" name="name" id="modalName" class="form-control" required>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">الرمز (SKU)</label>
<input type="text" name="sku" id="modalSku" class="form-control">
</div>
<div class="col-md-6 mb-3">
<label class="form-label">التصنيف</label>
<select name="category_id" id="modalCategory" class="form-select">
<option value="">-- اختر --</option>
<?php foreach ($categories as $cat): ?>
<option value="<?= $cat['id'] ?>"><?= htmlspecialchars($cat['name']) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">الحد الأدنى للكمية</label>
<input type="number" name="min_quantity" id="modalMinQty" class="form-control" value="0">
</div>
<div class="col-md-6 mb-3">
<label class="form-label">الوحدة</label>
<input type="text" name="unit" id="modalUnit" class="form-control" value="قطعة">
</div>
</div>
<div class="mb-3">
<label class="form-label">الوصف</label>
<textarea name="description" id="modalDesc" class="form-control" rows="3"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">إلغاء</button>
<button type="submit" class="btn btn-primary">حفظ</button>
</div>
</form>
</div>
</div>
</div>
<script>
let itemModal;
document.addEventListener('DOMContentLoaded', function() {
var modalEl = document.getElementById('itemModal');
if (modalEl) {
itemModal = new bootstrap.Modal(modalEl);
}
});
function openItemModal(action, data = null) {
if (!itemModal) return;
document.getElementById('modalAction').value = action;
document.getElementById('itemModalLabel').textContent = action === 'add' ? 'إضافة صنف جديد' : 'تعديل الصنف';
if (action === 'edit' && data) {
document.getElementById('modalId').value = data.id;
document.getElementById('modalName').value = data.name;
document.getElementById('modalSku').value = data.sku || '';
document.getElementById('modalCategory').value = data.category_id || '';
document.getElementById('modalMinQty').value = data.min_quantity;
document.getElementById('modalUnit').value = data.unit;
document.getElementById('modalDesc').value = data.description || '';
} else {
document.getElementById('modalId').value = '';
document.getElementById('modalName').value = '';
document.getElementById('modalSku').value = '';
document.getElementById('modalCategory').value = '';
document.getElementById('modalMinQty').value = '0';
document.getElementById('modalUnit').value = 'قطعة';
document.getElementById('modalDesc').value = '';
}
itemModal.show();
}
function confirmDelete(id) {
if(confirm('هل أنت متأكد من حذف هذا الصنف؟')) {
const form = document.createElement('form');
form.method = 'POST';
form.innerHTML = `<input type="hidden" name="action" value="delete"><input type="hidden" name="id" value="${id}">`;
document.body.appendChild(form);
form.submit();
}
}
</script>
<?php require_once __DIR__ . '/includes/footer.php'; ?>