commit 50f38a9e9aa13573c98d11c93b04d1b391afea56 Author: Albert Goral Date: Mon Mar 16 09:16:23 2026 +0100 init diff --git a/add_order.php b/add_order.php new file mode 100644 index 0000000..2cab010 --- /dev/null +++ b/add_order.php @@ -0,0 +1,126 @@ + 0) { + try { + $pdo->beginTransaction(); + + $sql = "INSERT INTO " . DB_PREFIX . "orders + (product_name, quantity, purchase_place, price_per_unit, delivery_date, notes, recipient, delivery_address, company, status) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'nowe')"; + $stmt = $pdo->prepare($sql); + $stmt->execute([$product_name, $quantity, $purchase_place, $price, $delivery_date, $notes, $recipient, $delivery_address, $company]); + + $order_id = $pdo->lastInsertId(); + + $hist_sql = "INSERT INTO " . DB_PREFIX . "order_history (order_id, user_id, action) VALUES (?, ?, ?)"; + $hist_stmt = $pdo->prepare($hist_sql); + $hist_stmt->execute([$order_id, $_SESSION['user_id'], 'Utworzono nowe zamówienie.']); + + $pdo->commit(); + + $message = "
Zamówienie dodane pomyślnie!
"; + } catch (PDOException $e) { + $pdo->rollBack(); + $message = "
Błąd: " . $e->getMessage() . "
"; + } + } else { + $message = "
Wypełnij nazwę produktu i ilość.
"; + } +} +?> + + + + + + Dodaj zamówienie - <?php echo APP_NAME; ?> + + + + +
+
+
+
Nowe zamówienie
+
+
+ +
+ +
+ + +
+ +
+ + +
+
+
+ + +
+
+ +
+ + +
+
+
+
+ + +
+ +
+
+ + +
+
+ + +
+
+ +
+ + +
+
+ + +
+ +
+ Powrót do listy + +
+
+
+
+
+ + diff --git a/admin.php b/admin.php new file mode 100644 index 0000000..d64f3f0 --- /dev/null +++ b/admin.php @@ -0,0 +1,359 @@ + 'Moje Przedsiębiorstwo IT', + 'company_1_details' => 'ul. Główna 1, 00-000 Warszawa | NIP: 0987654321', + 'company_2_name' => 'Spółka Celowa Sp. z o.o.', + 'company_2_details' => 'ul. Przykładowa 10, 00-000 Warszawa | NIP: 1234567890 | KRS: 0000123456' +]; + +foreach ($default_settings as $key => $val) { + // INSERT IGNORE dodaje wpis tylko wtedy, gdy taki klucz jeszcze nie istnieje w tabeli + $stmt = $pdo->prepare("INSERT IGNORE INTO " . DB_PREFIX . "settings (setting_key, setting_value) VALUES (?, ?)"); + $stmt->execute([$key, $val]); +} + +// --------------------------------------------------------- +// 1. WGRYWANIE LOGO +// --------------------------------------------------------- +if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_FILES['logo'])) { + if ($_FILES['logo']['error'] === 0) { + $upload_dir = 'uploads/'; + if (!is_dir($upload_dir)) mkdir($upload_dir, 0777, true); + + $file_ext = strtolower(pathinfo($_FILES['logo']['name'], PATHINFO_EXTENSION)); + if(in_array($file_ext, ['jpg', 'jpeg', 'png', 'gif', 'svg'])) { + $new_name = 'logo_' . time() . '.' . $file_ext; + $dest_path = $upload_dir . $new_name; + + if (move_uploaded_file($_FILES['logo']['tmp_name'], $dest_path)) { + $stmt = $pdo->prepare("REPLACE INTO " . DB_PREFIX . "settings (setting_key, setting_value) VALUES ('logo_path', ?)"); + $stmt->execute([$dest_path]); + $message = "
Pomyślnie zaktualizowano logo!
"; + } else { + $message = "
Błąd: Nie udało się zapisać pliku. Sprawdź uprawnienia folderu 'uploads'.
"; + } + } else { + $message = "
Błąd: Dozwolone są tylko pliki graficzne (JPG, PNG, GIF, SVG).
"; + } + } +} + +// --------------------------------------------------------- +// 1B. ZAPISYWANIE DANYCH FIRM +// --------------------------------------------------------- +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_company_settings') { + $settings_to_update = ['company_1_name', 'company_1_details', 'company_2_name', 'company_2_details']; + + try { + $pdo->beginTransaction(); + $update_stmt = $pdo->prepare("UPDATE " . DB_PREFIX . "settings SET setting_value = ? WHERE setting_key = ?"); + + foreach ($settings_to_update as $key) { + if (isset($_POST[$key])) { + $update_stmt->execute([trim($_POST[$key]), $key]); + } + } + $pdo->commit(); + $message = "
Ustawienia firmowe zostały zapisane!
"; + } catch (PDOException $e) { + $pdo->rollBack(); + $message = "
Błąd zapisu: " . $e->getMessage() . "
"; + } +} + +// --------------------------------------------------------- +// 2. DODAWANIE UŻYTKOWNIKA +// --------------------------------------------------------- +if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['add_user'])) { + $new_user = trim($_POST['new_username']); + $new_pass = $_POST['new_password']; + $new_role = $_POST['new_role']; + + if (!empty($new_user) && !empty($new_pass)) { + try { + $hashed_pass = password_hash($new_pass, PASSWORD_BCRYPT); + $stmt = $pdo->prepare("INSERT INTO " . DB_PREFIX . "users (username, password, role) VALUES (?, ?, ?)"); + $stmt->execute([$new_user, $hashed_pass, $new_role]); + $message = "
Dodano nowego użytkownika: $new_user
"; + } catch (PDOException $e) { + $message = "
Błąd: Użytkownik o takiej nazwie prawdopodobnie już istnieje.
"; + } + } +} + +// --------------------------------------------------------- +// 3. RESET HASŁA UŻYTKOWNIKA +// --------------------------------------------------------- +if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['reset_password'])) { + $user_id = (int)$_POST['user_id']; + $new_pass = $_POST['new_password']; + + if (!empty($new_pass)) { + $hashed_pass = password_hash($new_pass, PASSWORD_BCRYPT); + $stmt = $pdo->prepare("UPDATE " . DB_PREFIX . "users SET password = ? WHERE id = ?"); + $stmt->execute([$hashed_pass, $user_id]); + $message = "
Zmieniono hasło dla wybranego użytkownika.
"; + } +} + +// --------------------------------------------------------- +// 4. USUWANIE UŻYTKOWNIKA +// --------------------------------------------------------- +if (isset($_GET['delete'])) { + $id_to_delete = (int)$_GET['delete']; + if ($id_to_delete != $_SESSION['user_id']) { + $stmt = $pdo->prepare("DELETE FROM " . DB_PREFIX . "users WHERE id = ?"); + $stmt->execute([$id_to_delete]); + $message = "
Użytkownik został pomyślnie usunięty.
"; + } else { + $message = "
Odmowa: Nie możesz usunąć własnego konta administratora!
"; + } +} + +// --------------------------------------------------------- +// POBIERANIE DANYCH DO WIDOKU +// --------------------------------------------------------- +$users = $pdo->query("SELECT id, username, role FROM " . DB_PREFIX . "users")->fetchAll(); + +$settings = []; +try { + $settings = $pdo->query("SELECT setting_key, setting_value FROM " . DB_PREFIX . "settings")->fetchAll(PDO::FETCH_KEY_PAIR); +} catch(PDOException $e) { + // Zabezpieczenie na wypadek awarii tabeli settings +} + +$current_logo = $settings['logo_path'] ?? ''; +?> + + + + + + + Panel Administratora - <?php echo defined('APP_NAME') ? APP_NAME : 'System'; ?> + + + + + + + + +
+
+

Panel Zarządzania Systemem

+
+ + + +
+
+ +
+
+ Ustawienia Wizualne +
+
+
+
+ + + +
Brak wgranego logo
+ +
+
+ + +
+ +
+
+
+ +
+
+ Dane firm (Stopki wydruków) +
+
+
+ + +
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ + +
+
+
+ +
+
+ Dodaj pracownika +
+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+ +
+ +
+
+
+ Zarejestrowani pracownicy +
+
+
+ + + + + + + + + + + + + + + + + + + +
IDLoginUprawnieniaZarządzaj
+ + + + + + + + + Usuń + + + + + + +
+
+
+
+
+
+
+ + + + + diff --git a/ajax_action.php b/ajax_action.php new file mode 100644 index 0000000..c402abd --- /dev/null +++ b/ajax_action.php @@ -0,0 +1,66 @@ + false, 'error' => 'Brak danych'])); +} + +$id = (int)$data['id']; +$action = $data['action']; + +try { + if ($action === 'archive') { + $stmt = $pdo->prepare("UPDATE " . DB_PREFIX . "orders SET is_archived = 1 WHERE id = ?"); + $stmt->execute([$id]); + + $hist = $pdo->prepare("INSERT INTO " . DB_PREFIX . "order_history (order_id, user_id, action) VALUES (?, ?, ?)"); + $hist->execute([$id, $_SESSION['user_id'], 'Przeniesiono zamówienie do archiwum.']); + + echo json_encode(['success' => true]); + + } elseif ($action === 'duplicate') { + // Pobierz oryginał + $stmt = $pdo->prepare("SELECT * FROM " . DB_PREFIX . "orders WHERE id = ?"); + $stmt->execute([$id]); + $orig = $stmt->fetch(PDO::FETCH_ASSOC); + + if (!$orig) { + die(json_encode(['success' => false, 'error' => 'Nie znaleziono zamówienia'])); + } + + // Zapisz kopię (zawsze jako nowe, nie zarchiwizowane) + $insert = $pdo->prepare("INSERT INTO " . DB_PREFIX . "orders + (product_name, part_number, quantity, purchase_place, price_per_unit, delivery_date, notes, recipient, delivery_address, company, status, is_archived) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'nowe', 0)"); + + $insert->execute([ + $orig['product_name'] . ' (Kopia)', + $orig['part_number'], + $orig['quantity'], + $orig['purchase_place'], + $orig['price_per_unit'], + $orig['delivery_date'], + $orig['notes'], + $orig['recipient'], + $orig['delivery_address'], + $orig['company'] + ]); + + $new_id = $pdo->lastInsertId(); + + $hist = $pdo->prepare("INSERT INTO " . DB_PREFIX . "order_history (order_id, user_id, action) VALUES (?, ?, ?)"); + $hist->execute([$new_id, $_SESSION['user_id'], "Sklonowano na podstawie archiwalnego/starego zamówienia #$id."]); + + echo json_encode(['success' => true]); + } else { + echo json_encode(['success' => false, 'error' => 'Nieznana akcja']); + } +} catch (PDOException $e) { + echo json_encode(['success' => false, 'error' => $e->getMessage()]); +} +?> diff --git a/ajax_add_row.php b/ajax_add_row.php new file mode 100644 index 0000000..8737f5a --- /dev/null +++ b/ajax_add_row.php @@ -0,0 +1,39 @@ + false, 'error' => 'Nazwa produktu jest wymagana!'])); +} + +try { + $pdo->beginTransaction(); + + $stmt = $pdo->prepare("INSERT INTO " . DB_PREFIX . "orders (product_name, quantity, purchase_place, price_per_unit, status) VALUES (?, ?, ?, ?, 'nowe')"); + + $price = (float)str_replace(',', '.', $data['price_per_unit'] ?? 0); + $qty = (int)($data['quantity'] ?? 1); + + $stmt->execute([ + trim($data['product_name']), + $qty, + trim($data['purchase_place'] ?? ''), + $price + ]); + + $new_id = $pdo->lastInsertId(); + + $hist = $pdo->prepare("INSERT INTO " . DB_PREFIX . "order_history (order_id, user_id, action) VALUES (?, ?, ?)"); + $hist->execute([$new_id, $_SESSION['user_id'], "Utworzono zamówienie (szybkie dodawanie na liście)."]); + + $pdo->commit(); + echo json_encode(['success' => true]); +} catch (PDOException $e) { + $pdo->rollBack(); + echo json_encode(['success' => false, 'error' => $e->getMessage()]); +} +?> diff --git a/ajax_edit.php b/ajax_edit.php new file mode 100644 index 0000000..9acb70f --- /dev/null +++ b/ajax_edit.php @@ -0,0 +1,63 @@ + false, 'error' => 'Brak danych'])); +} + +$id = (int)$data['id']; +$field = $data['field']; +$value = trim($data['value']); + +// TUTAJ JEST MAGIA: dodano 'company' na końcu listy +$allowed_fields = ['product_name', 'quantity', 'purchase_place', 'price_per_unit', 'delivery_date', 'status', 'recipient', 'delivery_address', 'notes', 'company']; + +if (!in_array($field, $allowed_fields)) { + die(json_encode(['success' => false, 'error' => 'Niedozwolona kolumna'])); +} + +$field_labels = [ + 'product_name' => 'Produkt', + 'quantity' => 'Ilość', + 'purchase_place' => 'Miejsce zakupu', + 'price_per_unit' => 'Cena za sztukę', + 'delivery_date' => 'Data dostawy', + 'status' => 'Status', + 'recipient' => 'Odbiorca', + 'delivery_address' => 'Adres dostawy', + 'notes' => 'Notatki', + 'company' => 'Firma kupująca' +]; + +try { + $stmt = $pdo->prepare("SELECT $field FROM " . DB_PREFIX . "orders WHERE id = ?"); + $stmt->execute([$id]); + $old_val = $stmt->fetchColumn(); + + if ((string)$old_val !== (string)$value) { + if ($field === 'price_per_unit') { + $value = (float)str_replace(',', '.', $value); + } + + $update = $pdo->prepare("UPDATE " . DB_PREFIX . "orders SET $field = ? WHERE id = ?"); + $update->execute([$value, $id]); + + $label = $field_labels[$field] ?? $field; + $old_display = $old_val ?: '(brak)'; + $new_display = $value ?: '(brak)'; + $hist_msg = "Szybka edycja: $label zmieniono z [$old_display] ➔ [$new_display]"; + + $hist = $pdo->prepare("INSERT INTO " . DB_PREFIX . "order_history (order_id, user_id, action) VALUES (?, ?, ?)"); + $hist->execute([$id, $_SESSION['user_id'], $hist_msg]); + } + + echo json_encode(['success' => true]); +} catch (PDOException $e) { + echo json_encode(['success' => false, 'error' => $e->getMessage()]); +} +?> diff --git a/change_password.php b/change_password.php new file mode 100644 index 0000000..3304fa4 --- /dev/null +++ b/change_password.php @@ -0,0 +1,72 @@ +Nowe hasła nie są identyczne!'; + } else { + // Pobierz aktualne hasło z bazy + $stmt = $pdo->prepare("SELECT password FROM " . DB_PREFIX . "users WHERE id = ?"); + $stmt->execute([$_SESSION['user_id']]); + $user = $stmt->fetch(); + + if (password_verify($old_pass, $user['password'])) { + // Hasło poprawne - aktualizujemy + $new_hash = password_hash($new_pass, PASSWORD_BCRYPT); + $update = $pdo->prepare("UPDATE " . DB_PREFIX . "users SET password = ? WHERE id = ?"); + $update->execute([$new_hash, $_SESSION['user_id']]); + $message = '
Hasło zostało zmienione pomyślnie!
'; + } else { + $message = '
Obecne hasło jest nieprawidłowe.
'; + } + } +} +?> + + + + + + Zmiana hasła - <?php echo APP_NAME; ?> + + + +
+
+
+
Zmiana hasła
+
+
+ +
+
+ + +
+
+
+ + +
+
+ + +
+
+ Powrót + +
+
+
+
+
+ + diff --git a/edit_order.php b/edit_order.php new file mode 100644 index 0000000..c0d7772 --- /dev/null +++ b/edit_order.php @@ -0,0 +1,322 @@ +prepare("SELECT * FROM " . DB_PREFIX . "orders WHERE id = ?"); +$stmt->execute([$id]); +$order = $stmt->fetch(); + +if (!$order) { + die("Zamówienie nie istnieje."); +} + +// 1. OBSŁUGA ZMIANY STATUSU ARCHIWUM +if (isset($_POST['archive_action'])) { + $new_archive_status = $order['is_archived'] ? 0 : 1; + + $update_arch = $pdo->prepare("UPDATE " . DB_PREFIX . "orders SET is_archived = ? WHERE id = ?"); + $update_arch->execute([$new_archive_status, $id]); + + $action_msg = $new_archive_status ? "Przeniesiono do archiwum." : "Przywrócono z archiwum do aktualnych."; + $hist_arch = $pdo->prepare("INSERT INTO " . DB_PREFIX . "order_history (order_id, user_id, action) VALUES (?, ?, ?)"); + $hist_arch->execute([$id, $_SESSION['user_id'], $action_msg]); + + // Wracamy na listę, uwzględniając czy lądujemy w archiwum czy nie + $redirect_url = $new_archive_status ? "index.php?archive=1" : "index.php"; + header("Location: $redirect_url"); + exit(); +} + +// 2. OBSŁUGA DODAWANIA KOMENTARZA +if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['add_comment'])) { + $comment_text = trim($_POST['comment_text'] ?? ''); + + if (!empty($comment_text)) { + try { + $ins_comm = $pdo->prepare("INSERT INTO " . DB_PREFIX . "order_comments (order_id, user_id, comment_text) VALUES (?, ?, ?)"); + $ins_comm->execute([$id, $_SESSION['user_id'], $comment_text]); + + // Przeładowanie strony (PRG - Post/Redirect/Get), aby uniknąć ponownego wysłania przy odświeżaniu F5 + header("Location: edit_order.php?id=" . $id); + exit(); + } catch (PDOException $e) { + $message = "
Błąd zapisu komentarza: " . $e->getMessage() . "
"; + } + } +} + +// 3. OBSŁUGA STANDARDOWEJ EDYCJI +if ($_SERVER["REQUEST_METHOD"] == "POST" && !isset($_POST['archive_action']) && !isset($_POST['add_comment'])) { + $product_name = trim($_POST['product_name'] ?? ''); + $part_number = trim($_POST['part_number'] ?? ''); + $quantity = (int)$_POST['quantity']; + $purchase_place = trim($_POST['purchase_place'] ?? ''); + $status = $_POST['status']; + $price = (float)str_replace(',', '.', $_POST['price_per_unit'] ?? '0'); + $delivery_date = $_POST['delivery_date'] ?? null; + $notes = trim($_POST['notes'] ?? ''); + $recipient = trim($_POST['recipient'] ?? ''); + $delivery_address = trim($_POST['delivery_address'] ?? ''); + $company = trim($_POST['company'] ?? ''); + + $changes = []; + if (($order['company'] ?? '') !== $company) $changes[] = "Firma: [{$order['company']}] ➔ [$company]"; + if (($order['product_name'] ?? '') !== $product_name) $changes[] = "Produkt: [{$order['product_name']}] ➔ [$product_name]"; + if (($order['part_number'] ?? '') !== $part_number) $changes[] = "PN: [{$order['part_number']}] ➔ [$part_number]"; + if ((int)$order['quantity'] !== $quantity) $changes[] = "Ilość: [{$order['quantity']}] ➔ [$quantity]"; + if (($order['purchase_place'] ?? '') !== $purchase_place) $changes[] = "Sklep: [{$order['purchase_place']}] ➔ [$purchase_place]"; + if (($order['status'] ?? '') !== $status) $changes[] = "Status: [{$order['status']}] ➔ [$status]"; + if ((float)$order['price_per_unit'] !== $price) $changes[] = "Cena: [{$order['price_per_unit']}] ➔ [$price]"; + if (($order['delivery_date'] ?? '') !== $delivery_date) $changes[] = "Dostawa: [{$order['delivery_date']}] ➔ [$delivery_date]"; + if (($order['recipient'] ?? '') !== $recipient) $changes[] = "Odbiorca: [{$order['recipient']}] ➔ [$recipient]"; + if (($order['delivery_address'] ?? '') !== $delivery_address) $changes[] = "Adres: [{$order['delivery_address']}] ➔ [$delivery_address]"; + if (($order['notes'] ?? '') !== $notes) $changes[] = "Zaktualizowano notatki"; + + if (!empty($changes)) { + try { + $pdo->beginTransaction(); + + $update = $pdo->prepare("UPDATE " . DB_PREFIX . "orders SET + product_name=?, part_number=?, quantity=?, purchase_place=?, status=?, price_per_unit=?, delivery_date=?, notes=?, recipient=?, delivery_address=?, company=? + WHERE id=?"); + $update->execute([$product_name, $part_number, $quantity, $purchase_place, $status, $price, $delivery_date, $notes, $recipient, $delivery_address, $company, $id]); + + $action_text = "Zmieniono: " . implode(', ', $changes); + $hist = $pdo->prepare("INSERT INTO " . DB_PREFIX . "order_history (order_id, user_id, action) VALUES (?, ?, ?)"); + $hist->execute([$id, $_SESSION['user_id'], $action_text]); + + $pdo->commit(); + $message = "
Zmiany zostały zapisane!
"; + + $stmt->execute([$id]); + $order = $stmt->fetch(); + } catch (PDOException $e) { + $pdo->rollBack(); + $message = "
Błąd bazy: " . $e->getMessage() . "
"; + } + } +} + +// POBIERANIE HISTORII +$hist_sql = "SELECT h.action, h.created_at, u.username + FROM " . DB_PREFIX . "order_history h + LEFT JOIN " . DB_PREFIX . "users u ON h.user_id = u.id + WHERE h.order_id = ? + ORDER BY h.created_at DESC"; +$hist_stmt = $pdo->prepare($hist_sql); +$hist_stmt->execute([$id]); +$history = $hist_stmt->fetchAll(); + +// POBIERANIE KOMENTARZY +$comm_sql = "SELECT c.comment_text, c.created_at, u.username + FROM " . DB_PREFIX . "order_comments c + LEFT JOIN " . DB_PREFIX . "users u ON c.user_id = u.id + WHERE c.order_id = ? + ORDER BY c.created_at DESC"; +$comm_stmt = $pdo->prepare($comm_sql); +$comm_stmt->execute([$id]); +$comments = $comm_stmt->fetchAll(); +?> + + + + + + Karta Zamówienia - <?php echo APP_NAME; ?> + + + + + + + +
+
+ +
+
+
+
+ Edycja zamówienia # + + Archiwum + +
+ Powrót +
+
+ +
+ +
+ + +
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ +
+ + +
+
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+
+ + +
+
+ + +
+
+
+ +
+ + +
+ +
+ + +
+
+
+
+
+ +
+ +
+
+ Komentarze i ustalenia +
+
+
+
+ + +
+
+ +
+ +
Brak komentarzy. Bądź pierwszy!
+ + +
+
+
+ + +
+
+ +
+
+
+ + +
+
+
+ +
+
+ Historia zmian +
+
+
    + +
  • Brak zapisanej historii modyfikacji.
  • + + +
  • +
    + + +
    +
    + +
    +
  • + + +
+
+
+ +
+
+
+ + diff --git a/export_csv.php b/export_csv.php new file mode 100644 index 0000000..33c60b9 --- /dev/null +++ b/export_csv.php @@ -0,0 +1,54 @@ +prepare($sql); + $stmt->execute($ids); + $orders = $stmt->fetchAll(PDO::FETCH_ASSOC); + + // Ustawienia nagłówków dla przeglądarki, by wymusić pobieranie pliku + header('Content-Type: text/csv; charset=utf-8'); + header('Content-Disposition: attachment; filename=zamowienia_' . date('Ymd_Hi') . '.csv'); + + // Wymuszenie BOM (dzięki temu Excel od razu poprawnie przeczyta polskie znaki w UTF-8) + echo "\xEF\xBB\xBF"; + + $output = fopen('php://output', 'w'); + + // Zapisanie nagłówków kolumn (zwróć uwagę na średniki, które lubi polski Excel) + fputcsv($output, ['ID', 'Produkt', 'Part Number', 'Ilosc', 'Miejsce zakupu', 'Cena szt.', 'Data dostawy', 'Odbiorca', 'Adres dostawy', 'Status', 'Notatki'], ';'); + + // Zapisywanie danych + foreach ($orders as $o) { + fputcsv($output, [ + $o['id'], + $o['product_name'], + $o['part_number'], + $o['quantity'], + $o['purchase_place'], + number_format($o['price_per_unit'], 2, ',', ''), // Cena z przecinkiem dla Excela + $o['delivery_date'], + $o['recipient'], + $o['delivery_address'], + $o['status'], + $o['notes'] + ], ';'); + } + + fclose($output); + exit(); +} + +// Jeśli ktoś wszedł tu bezpośrednio lub nic nie zaznaczył, wracamy do indexu +header('Location: index.php'); +exit(); +?> diff --git a/import_csv.php b/import_csv.php new file mode 100644 index 0000000..eb91f22 --- /dev/null +++ b/import_csv.php @@ -0,0 +1,90 @@ +beginTransaction(); + $sql = "INSERT INTO " . DB_PREFIX . "orders + (product_name, quantity, purchase_place, price_per_unit, delivery_date, notes, status) + VALUES (?, ?, ?, ?, ?, ?, ?)"; + $stmt = $pdo->prepare($sql); + + $count = 0; + while (($row = fgetcsv($handle, 1000, ";")) !== FALSE) { + // $row[0] to LP - pomijamy zgodnie z wymaganiem + + // Obsługa polskich znaków (jeśli plik jest w Windows-1250) + foreach($row as $key => $value) { + $row[$key] = mb_convert_encoding($value, "UTF-8", "auto"); + } + + if (empty($row[1])) continue; // Pomiń jeśli brak nazwy produktu + + $stmt->execute([ + $row[1], // Produkt + (int)$row[2], // Ilość + $row[3], // Miejsce zakupu + (float)str_replace(',', '.', $row[4]), // Cena (zamiana przecinka na kropkę) + $row[5], // Data dostawy + $row[6], // Notatki + $row[7] ?? 'nowe' // Status + ]); + $count++; + } + $pdo->commit(); + $message = "
Zaimportowano $count zamówień z pliku CSV!
"; + } catch (Exception $e) { + $pdo->rollBack(); + $message = "
Błąd: " . $e->getMessage() . "
"; + } + fclose($handle); + } +} +?> + + + + + + Import CSV - <?php echo APP_NAME; ?> + + + +
+
+
+

Import z pliku CSV

+
+
+ + +
+ Ważne: W Excelu wybierz Zapisz jako -> CSV (rozdzielany średnikami). +
+ +
+
+ + +
+
+ Powrót + +
+
+
+
+
+ + diff --git a/import_excel.php b/import_excel.php new file mode 100644 index 0000000..1768b20 --- /dev/null +++ b/import_excel.php @@ -0,0 +1,95 @@ +getActiveSheet(); + $rows = $worksheet->toArray(); + + // Pomijamy nagłówek (pierwszy wiersz w Excelu) + unset($rows[0]); + + $pdo->beginTransaction(); + $sql = "INSERT INTO " . DB_PREFIX . "orders + (product_name, quantity, purchase_place, price_per_unit, delivery_date, notes, status) + VALUES (?, ?, ?, ?, ?, ?, ?)"; + $stmt = $pdo->prepare($sql); + + $count = 0; + foreach ($rows as $row) { + // Zgodnie z wymaganiem: pomijamy 1. kolumnę ($row[0]) + // Mapowanie kolumn Excela: + // $row[1] -> Produkt, $row[2] -> Ilość, $row[3] -> Miejsce, + // $row[4] -> Cena, $row[5] -> Data, $row[6] -> Notatki, $row[7] -> Status + + if (empty($row[1])) continue; // Pomiń puste wiersze + + $stmt->execute([ + $row[1], // Produkt + (int)$row[2], // Ilość + $row[3], // Miejsce zakupu + (float)$row[4], // Cena + $row[5], // Data dostawy (format YYYY-MM-DD) + $row[6], // Notatki + $row[7] ?? 'nowe' // Status + ]); + $count++; + } + $pdo->commit(); + $message = "
Pomyślnie zaimportowano $count zamówień!
"; + + } catch (Exception $e) { + if ($pdo->inTransaction()) $pdo->rollBack(); + $message = "
Błąd importu: " . $e->getMessage() . "
"; + } +} +?> + + + + + + Import Zamówień - <?php echo APP_NAME; ?> + + + +
+
+
+

Import z pliku Excel (.xlsx)

+
+
+ + +
+ Instrukcja:
+ 1. System pomija pierwszą kolumnę (LP).
+ 2. Kolejne kolumny to: Produkt, Ilość, Miejsce, Cena, Data (RRRR-MM-DD), Notatki, Status. +
+ +
+
+ + +
+
+ Powrót + +
+
+
+
+
+ + diff --git a/includes/auth.php b/includes/auth.php new file mode 100644 index 0000000..70c41bf --- /dev/null +++ b/includes/auth.php @@ -0,0 +1,18 @@ + diff --git a/includes/config.php b/includes/config.php new file mode 100644 index 0000000..89cffe4 --- /dev/null +++ b/includes/config.php @@ -0,0 +1,14 @@ + diff --git a/includes/db.php b/includes/db.php new file mode 100644 index 0000000..26eb652 --- /dev/null +++ b/includes/db.php @@ -0,0 +1,16 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, + ]; + + $pdo = new PDO($dsn, DB_USER, DB_PASS, $options); +} catch (\PDOException $e) { + throw new \PDOException($e->getMessage(), (int)$e->getCode()); +} +?> diff --git a/index.php b/index.php new file mode 100644 index 0000000..87d5cdf --- /dev/null +++ b/index.php @@ -0,0 +1,620 @@ + 'id', 'product_name' => 'product_name', 'quantity' => 'quantity', 'purchase_place' => 'purchase_place', 'price_per_unit' => 'price_per_unit', 'delivery_date' => 'delivery_date', 'status' => 'status']; +if (!array_key_exists($sort_col, $allowed_sort_cols)) $sort_col = 'id'; +if ($sort_dir !== 'asc' && $sort_dir !== 'desc') $sort_dir = 'desc'; + +function getSortLink($col_key, $label, $current_sort, $current_dir) { + global $status_filter, $date_from, $date_to, $search_query, $limit, $is_archived; + $new_dir = ($current_sort === $col_key && $current_dir === 'asc') ? 'desc' : 'asc'; + $icon = ($current_sort === $col_key) ? ($current_dir === 'asc' ? '' : '') : ''; + $text_class = ($current_sort === $col_key) ? 'text-warning' : 'text-white'; + + // Dodano parametr 'archive' do linków sortowania + $params = ['archive' => $is_archived, 'status' => $status_filter, 'date_from' => $date_from, 'date_to' => $date_to, 'q' => $search_query, 'limit' => $limit, 'sort' => $col_key, 'dir' => $new_dir]; + $url = '?' . http_build_query($params); + return "$label $icon"; +} + +// BAZOWY WARUNEK ARCHIWUM +$where = ["is_archived = ?"]; +$params = [$is_archived]; + +if ($status_filter) { $where[] = "status = ?"; $params[] = $status_filter; } +if ($date_from) { $where[] = "delivery_date >= ?"; $params[] = $date_from; } +if ($date_to) { $where[] = "delivery_date <= ?"; $params[] = $date_to; } +if ($search_query !== '') { + $where[] = "(product_name LIKE ? OR part_number LIKE ? OR purchase_place LIKE ? OR recipient LIKE ? OR delivery_address LIKE ? OR notes LIKE ? OR company LIKE ?)"; + $like_term = "%" . $search_query . "%"; + for ($i = 0; $i < 7; $i++) { $params[] = $like_term; } +} +$where_sql = implode(" AND ", $where); + +$count_stmt = $pdo->prepare("SELECT COUNT(*) FROM " . DB_PREFIX . "orders WHERE $where_sql"); +$count_stmt->execute($params); +$total_rows = $count_stmt->fetchColumn(); +$total_pages = ceil($total_rows / $limit); + +$sql = "SELECT * FROM " . DB_PREFIX . "orders WHERE $where_sql ORDER BY $sort_col $sort_dir LIMIT $limit OFFSET $offset"; +$stmt = $pdo->prepare($sql); +$stmt->execute($params); +$orders = $stmt->fetchAll(); + +$logo_path = $pdo->query("SELECT setting_value FROM " . DB_PREFIX . "settings WHERE setting_key = 'logo_path'")->fetchColumn() ?: 'assets/default_logo.png'; + +function getStatusClass($status) { + return match($status) { + 'nowe' => 'bg-info text-dark', + 'w trakcie realizacji' => 'bg-warning text-dark', + 'zrealizowane' => 'bg-success', + 'anulowane' => 'bg-danger', + default => 'bg-secondary', + }; +} +?> + + + + + + <?php echo $is_archived ? 'Archiwum' : 'Zamówienia IT'; ?> - <?php echo APP_NAME; ?> + + + + + + + + +
+
+

+ + Archiwum zamówień + + Lista zamówień + +

+ +
+ + Widok Aktualnych + + Widok Archiwum + + + + + + Import + Pełny formularz +
+
+ +
+
+
+ + + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Akcje
Brak wyników w tej sekcji.
# + + +
PN: + +
+ + kliknij...'; ?> + + + + dodaj datę'; ?> + + + + + + + + + +
+
+ + + + +
+
+
+
+ + + + +
+ +
+ + + 1): ?> +
    + +
  • + +
  • + +
+ + + +
+ + + +
+ + + + + diff --git a/login.php b/login.php new file mode 100644 index 0000000..032495b --- /dev/null +++ b/login.php @@ -0,0 +1,115 @@ +query("SELECT setting_value FROM " . DB_PREFIX . "settings WHERE setting_key = 'logo_path'"); + if ($stmt) { + $logo_path = $stmt->fetchColumn(); + } +} catch (PDOException $e) { + // Ignorujemy błąd, jeśli tabela jeszcze nie istnieje itp. +} + +// 4. Obsługa logowania +if ($_SERVER["REQUEST_METHOD"] == "POST") { + $username = trim($_POST['username']); + $password = $_POST['password']; + + if (!empty($username) && !empty($password)) { + try { + // Pobieranie użytkownika z bazy (uwzględniając prefix) + $stmt = $pdo->prepare("SELECT * FROM " . DB_PREFIX . "users WHERE username = ?"); + $stmt->execute([$username]); + $user = $stmt->fetch(); + + if ($user) { + // Weryfikacja hasła + if (password_verify($password, $user['password'])) { + // Logowanie udane - zapis do sesji + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + $_SESSION['role'] = $user['role']; + + // Przekierowanie do index.php + header("Location: index.php"); + exit(); + } else { + $error = "Błędne hasło. Upewnij się, że hasło jest poprawne)."; + } + } else { + $error = "Użytkownik '$username' nie istnieje w bazie."; + } + } catch (PDOException $e) { + $error = "Błąd bazy danych: " . $e->getMessage(); + } + } else { + $error = "Proszę wypełnić oba pola."; + } +} +?> + + + + + + + Logowanie - <?php echo defined('APP_NAME') ? APP_NAME : 'System Zamówień'; ?> + + + + + +
+
+ + + +

💻 Logowanie

+ +

Wpisz dane, aby zarządzać zamówieniami

+
+ + +
+ + +
+
+ + +
+
+ + +
+ +
+ +
+

+ Aplikacja: goral.edu.pl/zeszyt
+ Serwer: OVH PHP 8.x +

+
+
+ + + diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..ba992bd --- /dev/null +++ b/logout.php @@ -0,0 +1,14 @@ + diff --git a/print.php b/print.php new file mode 100644 index 0000000..c8d002f --- /dev/null +++ b/print.php @@ -0,0 +1,112 @@ +prepare($sql); + $stmt->execute($ids); + $orders = $stmt->fetchAll(PDO::FETCH_ASSOC); + + // Obliczamy ile głównych kolumn wydrukować, żeby ustawić odpowiedni colspan dla sub-wiersza + $mainColsCount = 0; + $main_available = ['id', 'product', 'quantity', 'place', 'price', 'status']; + foreach($main_available as $mc) { if($hasCol($mc)) $mainColsCount++; } + if($mainColsCount == 0) $mainColsCount = 1; + +} else { + die("Błąd: Nie wybrano żadnych zamówień do druku."); +} +?> + + + + + Wydruk listy - <?php echo date('Y-m-d'); ?> + + + + +
+ + +
+ +

Zestawienie zamówień IT

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID Produkt (PN) Szt. Sklep Cena jedn. Status
# + +
PN: +
+ +
Odbiorca:
+ + + +
Adres:
+ + + +
Notatki:
+ +
+ + + + diff --git a/print_delivery.php b/print_delivery.php new file mode 100644 index 0000000..e5f8a70 --- /dev/null +++ b/print_delivery.php @@ -0,0 +1,150 @@ +prepare($sql); + $stmt->execute($ids); + $orders = $stmt->fetchAll(PDO::FETCH_ASSOC); + + $logo_db = $pdo->query("SELECT setting_value FROM " . DB_PREFIX . "settings WHERE setting_key = 'logo_path'")->fetchColumn(); + $logo_src = (file_exists('uploads/logo.png')) ? 'uploads/logo.png' : ($logo_db ?: ''); + + // --- KONFIGURACJA STOPEK (pobierana z bazy) --- + $settings_stmt = $pdo->query("SELECT setting_key, setting_value FROM " . DB_PREFIX . "settings WHERE setting_key IN ('company_1_name', 'company_1_details', 'company_2_name', 'company_2_details')"); + $settings = $settings_stmt->fetchAll(PDO::FETCH_KEY_PAIR); + + if ($company_footer === 'Spółka') { + $footer_company_name = $settings['company_2_name'] ?? "Spółka Celowa Sp. z o.o."; + $footer_company_details = $settings['company_2_details'] ?? "-"; + } else { + $footer_company_name = $settings['company_1_name'] ?? "Moje Przedsiębiorstwo IT"; + $footer_company_details = $settings['company_1_details'] ?? "-"; + } + +} else { + die("Błąd: Nie wybrano zamówień."); +} +?> + + + + + <?php echo htmlspecialchars($doc_type); ?> - <?php echo date('Y-m-d'); ?> + + + + +
+ + +
+ +
+
+ + Logo + +
+
+ +
+
Miejsce dostawy / Odbiorca:
+ + (Brak podanego adresu na dokumencie)"; ?> +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
LP ID Wydawany Towar (Produkt / PN) Ilość Notatki
# + +
PN: +
+ +
+
+
Wydający (Podpis i data)
+
+
+
+
Odbierający (Czytelny podpis i data)
+
+
+
+ + + + + diff --git a/uploads/logo.png b/uploads/logo.png new file mode 100644 index 0000000..5a0edf2 Binary files /dev/null and b/uploads/logo.png differ diff --git a/uploads/logo_1773509094.png b/uploads/logo_1773509094.png new file mode 100644 index 0000000..f1af883 Binary files /dev/null and b/uploads/logo_1773509094.png differ diff --git a/uploads/logo_1773574385.png b/uploads/logo_1773574385.png new file mode 100644 index 0000000..4e53a99 Binary files /dev/null and b/uploads/logo_1773574385.png differ diff --git a/uploads/logo_1773574724.png b/uploads/logo_1773574724.png new file mode 100644 index 0000000..f1af883 Binary files /dev/null and b/uploads/logo_1773574724.png differ