36782-vm/admin/edit_product.php
2025-12-28 19:43:55 +00:00

429 lines
21 KiB
PHP

<?php
require_once __DIR__ . '/../includes/init.php';
require_role('admin');
$pdo = db();
// Handle image deletion
if (isset($_GET['delete_image']) && isset($_GET['id'])) {
$image_id_to_delete = $_GET['delete_image'];
$product_id_for_redirect = $_GET['id'];
$img_stmt = $pdo->prepare("SELECT file_path FROM product_images WHERE id = ? AND product_id = ?");
$img_stmt->execute([$image_id_to_delete, $product_id_for_redirect]);
$image_to_delete = $img_stmt->fetch(PDO::FETCH_ASSOC);
if ($image_to_delete) {
$file_path = __DIR__ . '/../uploads/products/' . $image_to_delete['file_path'];
if (file_exists($file_path)) {
unlink($file_path);
}
$delete_stmt = $pdo->prepare("DELETE FROM product_images WHERE id = ?");
$delete_stmt->execute([$image_id_to_delete]);
}
header('Location: edit_product.php?id=' . $product_id_for_redirect);
exit;
}
// Handle document deletion
if (isset($_GET['delete_document']) && isset($_GET['id'])) {
$doc_id_to_delete = $_GET['delete_document'];
$product_id_for_redirect = $_GET['id'];
$doc_stmt = $pdo->prepare("SELECT file_path FROM product_documents WHERE id = ? AND product_id = ?");
$doc_stmt->execute([$doc_id_to_delete, $product_id_for_redirect]);
$doc_to_delete = $doc_stmt->fetch(PDO::FETCH_ASSOC);
if ($doc_to_delete) {
$file_path = __DIR__ . '/../uploads/documents/' . $doc_to_delete['file_path'];
if (file_exists($file_path)) {
unlink($file_path);
}
$delete_stmt = $pdo->prepare("DELETE FROM product_documents WHERE id = ?");
$delete_stmt->execute([$doc_id_to_delete]);
}
header('Location: edit_product.php?id=' . $product_id_for_redirect);
exit;
}
$product = [
'id' => null,
'name' => '',
'description' => '',
'price_net' => '',
'price_gross' => '',
'supplier_id' => null,
'is_active' => 1,
'product_role' => 'membrana',
'unit' => 'szt',
'units_per_pallet' => null
];
$errors = [];
// Fetch suppliers
$stmt = $pdo->prepare("SELECT id, email FROM users WHERE role = 'supplier' AND is_active = 1 ORDER BY email");
$stmt->execute();
$suppliers = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Fetch all attribute keys
$keys_stmt = $pdo->query("SELECT * FROM attribute_keys ORDER BY name");
$attribute_keys = $keys_stmt->fetchAll(PDO::FETCH_ASSOC);
// Fetch product's current attributes and images
$product_attributes = [];
$product_images = [];
if (isset($_GET['id'])) {
$product_id = $_GET['id'];
$attr_stmt = $pdo->prepare("SELECT attribute_key_id, value FROM product_attributes WHERE product_id = ?");
$attr_stmt->execute([$product_id]);
$product_attributes_raw = $attr_stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($product_attributes_raw as $attr) {
$product_attributes[$attr['attribute_key_id']] = $attr['value'];
}
$img_stmt = $pdo->prepare("SELECT * FROM product_images WHERE product_id = ? ORDER BY is_primary DESC, id ASC");
$img_stmt->execute([$product_id]);
$product_images = $img_stmt->fetchAll(PDO::FETCH_ASSOC);
// Fetch all products for related products selection
$all_products_stmt = $pdo->query("SELECT id, name FROM products ORDER BY name");
$all_products = $all_products_stmt->fetchAll(PDO::FETCH_ASSOC);
// Fetch current related products
$related_products_stmt = $pdo->prepare("SELECT related_product_id FROM product_relations WHERE product_id = ?");
$related_products_stmt->execute([$product_id]);
$related_product_ids = $related_products_stmt->fetchAll(PDO::FETCH_COLUMN);
// Fetch product documents
$docs_stmt = $pdo->prepare("SELECT * FROM product_documents WHERE product_id = ?");
$docs_stmt->execute([$product_id]);
$product_documents = $docs_stmt->fetchAll(PDO::FETCH_ASSOC);
}
if (isset($_GET['id'])) {
$stmt = $pdo->prepare("SELECT * FROM products WHERE id = ?");
$stmt->execute([$_GET['id']]);
$product = $stmt->fetch();
if (!$product) {
die('Nie znaleziono produktu');
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = $_POST['name'] ?? '';
$description = $_POST['description'] ?? '';
$price_net = !empty($_POST['price_net']) ? (float)$_POST['price_net'] : null;
$price_gross = !empty($_POST['price_gross']) ? (float)$_POST['price_gross'] : null;
$unit = $_POST['unit'] ?? 'szt';
$units_per_pallet = !empty($_POST['units_per_pallet']) ? $_POST['units_per_pallet'] : null;
$supplier_id = !empty($_POST['supplier_id']) ? $_POST['supplier_id'] : null;
$attributes = $_POST['attributes'] ?? [];
$is_active = isset($_POST['is_active']) ? 1 : 0;
$product_role = $_POST['product_role'] ?? 'membrana';
$id = $_POST['id'] ?? null;
// Auto-calculate prices
if ($price_net !== null && $price_gross === null) {
$price_gross = round($price_net * 1.23, 2);
} elseif ($price_gross !== null && $price_net === null) {
$price_net = round($price_gross / 1.23, 2);
}
if ($supplier_id) {
$stmt = $pdo->prepare("SELECT COUNT(*) FROM users WHERE id = ? AND role = 'supplier' AND is_active = 1");
$stmt->execute([$supplier_id]);
if ($stmt->fetchColumn() == 0) {
$errors[] = 'Wybrany dostawca jest nieprawidłowy.';
}
}
if (empty($errors)) {
try {
$pdo->beginTransaction();
if ($id) { // Update
$stmt = $pdo->prepare("UPDATE products SET name=?, description=?, price_net=?, price_gross=?, unit=?, units_per_pallet=?, supplier_id=?, is_active=?, product_role=? WHERE id=?");
$stmt->execute([$name, $description, $price_net, $price_gross, $unit, $units_per_pallet, $supplier_id, $is_active, $product_role, $id]);
$product_id = $id;
} else { // Insert
$stmt = $pdo->prepare("INSERT INTO products (name, description, price_net, price_gross, unit, units_per_pallet, supplier_id, is_active, product_role) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$name, $description, $price_net, $price_gross, $unit, $units_per_pallet, $supplier_id, $is_active, $product_role]);
$product_id = $pdo->lastInsertId();
}
// Handle image uploads
if (isset($_FILES['images']) && !empty($_FILES['images']['name'][0])) {
$image_errors = [];
$allowed_types = ['image/jpeg', 'image/png'];
$upload_dir = __DIR__ . '/../uploads/products/';
if (!is_dir($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
foreach ($_FILES['images']['tmp_name'] as $key => $tmp_name) {
if ($_FILES['images']['error'][$key] === UPLOAD_ERR_OK) {
$file_type = mime_content_type($tmp_name);
if (in_array($file_type, $allowed_types)) {
$product_upload_dir = $upload_dir . $product_id . '/';
if (!is_dir($product_upload_dir)) {
mkdir($product_upload_dir, 0777, true);
}
$file_ext = pathinfo($_FILES['images']['name'][$key], PATHINFO_EXTENSION);
$file_name = uniqid('prod_' . $product_id . '_', true) . '.' . $file_ext;
$destination = $product_upload_dir . $file_name;
// GEMINI DEBUG
file_put_contents('/tmp/gemini_debug.log', "Destination: {$destination}\nFile Path for DB: {$product_id}/{$file_name}\n", FILE_APPEND);
if (move_uploaded_file($tmp_name, $destination)) {
$img_stmt = $pdo->prepare("INSERT INTO product_images (product_id, file_path) VALUES (?, ?)");
$img_stmt->execute([$product_id, $product_id . '/' . $file_name]);
} else {
$image_errors[] = "Nie udało się przenieść pliku: " . htmlspecialchars($_FILES['images']['name'][$key]);
}
} else {
$image_errors[] = "Niedozwolony typ pliku: " . htmlspecialchars($_FILES['images']['name'][$key]);
}
} elseif ($_FILES['images']['error'][$key] !== UPLOAD_ERR_NO_FILE) {
$image_errors[] = "Błąd podczas przesyłania pliku: " . htmlspecialchars($_FILES['images']['name'][$key]) . ": " . upload_error_message($_FILES['images']['error'][$key]);
}
}
// Store image errors in session to display after redirect if needed, or handle differently
if(!empty($image_errors)) {
// For simplicity, we add them to the main errors array.
$errors = array_merge($errors, $image_errors);
if ($pdo->inTransaction()) $pdo->rollBack();
// Stop further execution if image upload fails
goto end_of_post_handling;
}
}
// Handle document uploads
if (isset($_FILES['documents']) && !empty($_FILES['documents']['name'][0])) {
$doc_errors = [];
$allowed_doc_types = ['application/pdf'];
$doc_upload_dir = __DIR__ . '/../uploads/documents/' . $product_id . '/';
if (!is_dir($doc_upload_dir)) {
mkdir($doc_upload_dir, 0777, true);
}
foreach ($_FILES['documents']['tmp_name'] as $key => $tmp_name) {
if ($_FILES['documents']['error'][$key] === UPLOAD_ERR_OK) {
$file_type = mime_content_type($tmp_name);
if (in_array($file_type, $allowed_doc_types)) {
$original_file_name = basename($_FILES['documents']['name'][$key]);
$sanitized_file_name = sanitize_filename($original_file_name);
$destination = $doc_upload_dir . $sanitized_file_name;
if (move_uploaded_file($tmp_name, $destination)) {
$doc_stmt = $pdo->prepare("INSERT INTO product_documents (product_id, file_name, file_path) VALUES (?, ?, ?)");
$doc_stmt->execute([$product_id, $original_file_name, $product_id . '/' . $sanitized_file_name]);
} else {
$doc_errors[] = "Nie udało się przenieść pliku: " . htmlspecialchars($original_file_name);
}
} else {
$doc_errors[] = "Niedozwolony typ pliku: " . htmlspecialchars($original_file_name);
}
} elseif ($_FILES['documents']['error'][$key] !== UPLOAD_ERR_NO_FILE) {
$doc_errors[] = "Błąd podczas przesyłania pliku: " . htmlspecialchars($_FILES['documents']['name'][$key]) . ": " . upload_error_message($_FILES['documents']['error'][$key]);
}
}
if(!empty($doc_errors)) {
$errors = array_merge($errors, $doc_errors);
if ($pdo->inTransaction()) $pdo->rollBack();
goto end_of_post_handling;
}
}
$clear_stmt = $pdo->prepare("DELETE FROM product_attributes WHERE product_id = ?");
$clear_stmt->execute([$product_id]);
$attr_sql = "INSERT INTO product_attributes (product_id, attribute_key_id, value) VALUES (?, ?, ?)";
$attr_stmt = $pdo->prepare($attr_sql);
foreach ($attributes as $key_id => $value) {
if (!empty($value)) {
$attr_stmt->execute([$product_id, $key_id, $value]);
}
}
// Handle related products
$related_products = $_POST['related_products'] ?? [];
$clear_related_stmt = $pdo->prepare("DELETE FROM product_relations WHERE product_id = ?");
$clear_related_stmt->execute([$product_id]);
if (!empty($related_products)) {
$rel_sql = "INSERT INTO product_relations (product_id, related_product_id) VALUES (?, ?)";
$rel_stmt = $pdo->prepare($rel_sql);
foreach ($related_products as $related_id) {
$rel_stmt->execute([$product_id, $related_id]);
}
}
$pdo->commit();
header("Location: products.php");
exit;
} catch (Exception $e) {
if ($pdo->inTransaction()) $pdo->rollBack();
$errors[] = 'Błąd podczas zapisywania produktu: ' . $e->getMessage();
}
}
end_of_post_handling:
}
$page_title = $product['id'] ? 'Edytuj produkt' : 'Dodaj produkt';
?>
<?php require_once __DIR__ . '/../includes/html_head.php'; ?>
<body>
<?php include __DIR__ . '/menu.php'; ?>
<main class="container my-5">
<h1><?php echo $page_title; ?></h1>
<?php if (!empty($errors)): ?>
<div class="alert alert-danger">
<?php foreach ($errors as $error): ?><p><?php echo htmlspecialchars($error); ?></p><?php endforeach; ?>
</div>
<?php endif; ?>
<form action="edit_product.php<?php echo $product['id'] ? '?id='.$product['id'] : '' ?>" method="POST" enctype="multipart/form-data">
<input type="hidden" name="id" value="<?php echo htmlspecialchars($product['id'] ?? ''); ?>">
<div class="card card-body mb-4">
<div class="mb-3">
<label for="name" class="form-label">Nazwa produktu</label>
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($product['name'] ?? ''); ?>" required>
</div>
<div class="mb-3">
<label for="description" class="form-label">Opis</label>
<textarea class="form-control" id="description" name="description" rows="3"><?php echo htmlspecialchars($product['description'] ?? ''); ?></textarea>
</div>
<div class="mb-3">
<label for="price_net" class="form-label">Cena netto</label>
<input type="number" step="0.01" class="form-control" id="price_net" name="price_net" value="<?= htmlspecialchars($product['price_net'] ?? '') ?>">
</div>
<div class="mb-3">
<label for="price_gross" class="form-label">Cena brutto (z VAT 23%)</label>
<input type="number" step="0.01" class="form-control" id="price_gross" name="price_gross" value="<?= htmlspecialchars($product['price_gross'] ?? '') ?>">
</div>
<div class="mb-3">
<label for="unit" class="form-label">Jednostka miary</label>
<select name="unit" id="unit" class="form-select">
<option value="szt" <?= ($product['unit'] ?? 'szt') === 'szt' ? 'selected' : '' ?>><?= t('szt') ?></option>
<option value="mb" <?= ($product['unit'] ?? 'szt') === 'mb' ? 'selected' : '' ?>><?= t('mb') ?></option>
<option value="m2" <?= ($product['unit'] ?? 'szt') === 'm2' ? 'selected' : '' ?>><?= t('m2') ?></option>
<option value="rolka" <?= ($product['unit'] ?? 'szt') === 'rolka' ? 'selected' : '' ?>><?= t('rolka') ?></option>
</select>
</div>
<div class="mb-3">
<label for="units_per_pallet" class="form-label">Ilość sztuk na palecie</label>
<input type="number" min="1" class="form-control" id="units_per_pallet" name="units_per_pallet" value="<?= htmlspecialchars($product['units_per_pallet'] ?? '') ?>">
</div>
<div class="mb-3">
<label for="product_role" class="form-label">Typ produktu</label>
<select name="product_role" id="product_role" class="form-select">
<option value="membrana" <?php echo ($product['product_role'] ?? 'membrana') === 'membrana' ? 'selected' : ''; ?>>membrana</option>
<option value="akcesoria" <?php echo ($product['product_role'] ?? 'membrana') === 'akcesoria' ? 'selected' : ''; ?>>akcesoria</option>
</select>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="is_active" name="is_active" value="1" <?php echo !empty($product['is_active']) ? 'checked' : ''; ?>>
<label class="form-check-label" for="is_active">Aktywny</label>
</div>
</div>
<div class="card card-body mb-4">
<h5>Zdjęcia</h5>
<div class="mb-3">
<label for="images" class="form-label">Dodaj nowe zdjęcia</label>
<input type="file" class="form-control" id="images" name="images[]" multiple accept="image/png, image/jpeg">
</div>
<?php if (!empty($product_images)):
echo '<div class="row g-3">';
foreach($product_images as $image) {
echo '<div class="col-md-3 text-center">';
echo '<img src="../uploads/products/' . htmlspecialchars($image['file_path']) . '" class="img-thumbnail mb-2" style="max-height: 150px;">';
echo '<a href="edit_product.php?id=' . htmlspecialchars($product['id']) . '&delete_image=' . htmlspecialchars($image['id']) . '" class="btn btn-danger btn-sm" onclick="return confirm(\'Czy na pewno chcesz usunąć to zdjęcie?\');">Usuń</a>';
echo '</div>';
}
echo '</div>';
endif; ?>
</div>
<div class="card card-body mb-4">
<h5>Atrybuty</h5>
<div class="mb-3">
<label for="supplier_id" class="form-label">Dostawca</label>
<select name="supplier_id" id="supplier_id" class="form-select">
<option value="">-- Wybierz dostawcę --</option>
<?php foreach ($suppliers as $supplier): ?>
<option value="<?php echo htmlspecialchars($supplier['id']); ?>" <?php echo (isset($product['supplier_id']) && $product['supplier_id'] == $supplier['id']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($supplier['email']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<hr>
<h5>Specyfikacja techniczna</h5>
<?php foreach ($attribute_keys as $key): ?>
<div class="mb-3">
<label for="attribute_<?php echo htmlspecialchars($key['id']); ?>" class="form-label"><?php echo htmlspecialchars($key['name']); ?></label>
<input type="text" class="form-control" id="attribute_<?php echo htmlspecialchars($key['id']); ?>" name="attributes[<?php echo htmlspecialchars($key['id']); ?>]" value="<?php echo htmlspecialchars($product_attributes[$key['id']] ?? ''); ?>">
</div>
<?php endforeach; ?>
</div>
<div class="card card-body mb-4">
<h5>Produkty powiązane</h5>
<div class="mb-3">
<label for="related_products" class="form-label">Wybierz produkty powiązane</label>
<select multiple class="form-control" id="related_products" name="related_products[]" size="10">
<?php foreach ($all_products as $p): ?>
<?php if ($p['id'] != $product['id']): // Exclude self ?>
<option value="<?php echo htmlspecialchars($p['id']); ?>" <?php echo in_array($p['id'], $related_product_ids) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($p['name']); ?>
</option>
<?php endif; ?>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="card card-body mb-4">
<h5>Dokumenty produktu (PDF)</h5>
<div class="mb-3">
<label for="documents" class="form-label">Dodaj nowe dokumenty</label>
<input type="file" class="form-control" id="documents" name="documents[]" multiple accept="application/pdf">
</div>
<?php if (!empty($product_documents)):
echo '<ul class="list-group">';
foreach($product_documents as $doc) {
echo '<li class="list-group-item d-flex justify-content-between align-items-center">';
echo htmlspecialchars($doc['file_name']);
echo '<a href="edit_product.php?id=' . htmlspecialchars($product['id']) . '&delete_document=' . htmlspecialchars($doc['id']) . '" class="btn btn-danger btn-sm" onclick="return confirm(\'Czy na pewno chcesz usunąć ten dokument?\');">Usuń</a>';
echo '</li>';
}
echo '</ul>';
endif; ?>
</div>
<div class="mt-4">
<button type="submit" class="btn btn-primary">Zapisz</button>
<a href="products.php" class="btn btn-secondary">Anuluj</a>
</div>
</form>
</main>
<?php require_once __DIR__ . '/../includes/footer.php'; ?>
</body>
</html>