diff --git a/api.php b/api.php index 5bf5795..f05197e 100644 --- a/api.php +++ b/api.php @@ -1309,6 +1309,101 @@ switch ($action) { echo json_encode(['success' => true]); break; + // ---------- SIJAINNIT (SITES) ---------- + case 'sites': + requireAuth(); + $companyId = requireCompany(); + echo json_encode(dbLoadSites($companyId)); + break; + + case 'site_save': + requireAdmin(); + $companyId = requireCompany(); + if ($method !== 'POST') break; + $input = json_decode(file_get_contents('php://input'), true); + $site = [ + 'id' => $input['id'] ?? generateId(), + 'nimi' => trim($input['nimi'] ?? ''), + 'osoite' => trim($input['osoite'] ?? ''), + 'kaupunki' => trim($input['kaupunki'] ?? ''), + ]; + if (empty($site['nimi'])) { + http_response_code(400); + echo json_encode(['error' => 'Sijainnin nimi vaaditaan']); + break; + } + dbSaveSite($companyId, $site); + dbAddLog($companyId, currentUser(), 'site_save', $site['id'], $site['nimi'], (isset($input['id']) ? 'Muokkasi' : 'Lisäsi') . ' sijainnin'); + echo json_encode($site); + break; + + case 'site_delete': + requireAdmin(); + $companyId = requireCompany(); + if ($method !== 'POST') break; + $input = json_decode(file_get_contents('php://input'), true); + $id = $input['id'] ?? ''; + // Hae nimi logitusta varten + $sites = dbLoadSites($companyId); + $siteName = ''; + foreach ($sites as $s) { if ($s['id'] === $id) { $siteName = $s['nimi']; break; } } + dbDeleteSite($id); + dbAddLog($companyId, currentUser(), 'site_delete', $id, $siteName, 'Poisti sijainnin'); + echo json_encode(['success' => true]); + break; + + // ---------- LAITTEET (DEVICES) ---------- + case 'devices': + requireAuth(); + $companyId = requireCompany(); + echo json_encode(dbLoadDevices($companyId)); + break; + + case 'device_save': + requireAuth(); + $companyId = requireCompany(); + if ($method !== 'POST') break; + $input = json_decode(file_get_contents('php://input'), true); + $isNew = empty($input['id']); + $device = [ + 'id' => $input['id'] ?? generateId(), + 'nimi' => trim($input['nimi'] ?? ''), + 'hallintaosoite' => trim($input['hallintaosoite'] ?? ''), + 'serial' => trim($input['serial'] ?? ''), + 'site_id' => $input['site_id'] ?? null, + 'funktio' => trim($input['funktio'] ?? ''), + 'tyyppi' => trim($input['tyyppi'] ?? ''), + 'malli' => trim($input['malli'] ?? ''), + 'ping_check' => !empty($input['ping_check']), + 'lisatiedot' => trim($input['lisatiedot'] ?? ''), + 'luotu' => $isNew ? date('Y-m-d H:i:s') : ($input['luotu'] ?? date('Y-m-d H:i:s')), + 'muokattu' => $isNew ? null : date('Y-m-d H:i:s'), + 'muokkaaja' => $isNew ? '' : currentUser(), + ]; + if (empty($device['nimi'])) { + http_response_code(400); + echo json_encode(['error' => 'Laitteen nimi vaaditaan']); + break; + } + dbSaveDevice($companyId, $device); + dbAddLog($companyId, currentUser(), $isNew ? 'device_create' : 'device_update', $device['id'], $device['nimi'], ($isNew ? 'Lisäsi' : 'Muokkasi') . ' laitteen'); + echo json_encode($device); + break; + + case 'device_delete': + requireAuth(); + $companyId = requireCompany(); + if ($method !== 'POST') break; + $input = json_decode(file_get_contents('php://input'), true); + $id = $input['id'] ?? ''; + $devices = dbLoadDevices($companyId); + $deviceName = ''; + foreach ($devices as $d) { if ($d['id'] === $id) { $deviceName = $d['nimi']; break; } } + dbDeleteDevice($id); + dbAddLog($companyId, currentUser(), 'device_delete', $id, $deviceName, 'Poisti laitteen'); + echo json_encode(['success' => true]); + break; + // ---------- ARCHIVE ---------- case 'archived_customers': requireAuth(); diff --git a/db.php b/db.php index f394261..c22013a 100644 --- a/db.php +++ b/db.php @@ -350,6 +350,37 @@ function initDatabase(): void { INDEX idx_company (company_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", + "CREATE TABLE IF NOT EXISTS sites ( + id VARCHAR(20) PRIMARY KEY, + company_id VARCHAR(50) NOT NULL, + nimi VARCHAR(255) NOT NULL, + osoite VARCHAR(255) DEFAULT '', + kaupunki VARCHAR(100) DEFAULT '', + FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE, + INDEX idx_company (company_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", + + "CREATE TABLE IF NOT EXISTS devices ( + id VARCHAR(20) PRIMARY KEY, + company_id VARCHAR(50) NOT NULL, + nimi VARCHAR(255) NOT NULL, + hallintaosoite VARCHAR(255) DEFAULT '', + serial VARCHAR(255) DEFAULT '', + site_id VARCHAR(20) NULL, + funktio VARCHAR(255) DEFAULT '', + tyyppi VARCHAR(100) DEFAULT '', + malli VARCHAR(255) DEFAULT '', + ping_check BOOLEAN DEFAULT FALSE, + ping_status VARCHAR(20) DEFAULT '', + ping_checked_at DATETIME NULL, + lisatiedot TEXT, + luotu DATETIME, + muokattu DATETIME NULL, + muokkaaja VARCHAR(100) DEFAULT '', + FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE, + INDEX idx_company (company_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4", + "CREATE TABLE IF NOT EXISTS files ( id INT AUTO_INCREMENT PRIMARY KEY, company_id VARCHAR(50) NOT NULL, @@ -749,6 +780,81 @@ function dbDeleteCustomer(string $customerId): void { _dbExecute("DELETE FROM customers WHERE id = ?", [$customerId]); } +// ==================== SIJAINNIT (SITES) ==================== + +function dbLoadSites(string $companyId): array { + return _dbFetchAll("SELECT * FROM sites WHERE company_id = ? ORDER BY nimi", [$companyId]); +} + +function dbSaveSite(string $companyId, array $site): void { + _dbExecute(" + INSERT INTO sites (id, company_id, nimi, osoite, kaupunki) + VALUES (:id, :company_id, :nimi, :osoite, :kaupunki) + ON DUPLICATE KEY UPDATE + nimi = VALUES(nimi), osoite = VALUES(osoite), kaupunki = VALUES(kaupunki) + ", [ + 'id' => $site['id'], + 'company_id' => $companyId, + 'nimi' => $site['nimi'] ?? '', + 'osoite' => $site['osoite'] ?? '', + 'kaupunki' => $site['kaupunki'] ?? '', + ]); +} + +function dbDeleteSite(string $siteId): void { + // Nollaa viittaavien laitteiden site_id + _dbExecute("UPDATE devices SET site_id = NULL WHERE site_id = ?", [$siteId]); + _dbExecute("DELETE FROM sites WHERE id = ?", [$siteId]); +} + +// ==================== LAITTEET (DEVICES) ==================== + +function dbLoadDevices(string $companyId): array { + $devices = _dbFetchAll(" + SELECT d.*, s.nimi AS site_name + FROM devices d + LEFT JOIN sites s ON d.site_id = s.id + WHERE d.company_id = ? + ORDER BY d.nimi + ", [$companyId]); + foreach ($devices as &$d) { + $d['ping_check'] = (bool)$d['ping_check']; + unset($d['company_id']); + } + return $devices; +} + +function dbSaveDevice(string $companyId, array $device): void { + _dbExecute(" + INSERT INTO devices (id, company_id, nimi, hallintaosoite, serial, site_id, funktio, tyyppi, malli, ping_check, lisatiedot, luotu, muokattu, muokkaaja) + VALUES (:id, :company_id, :nimi, :hallintaosoite, :serial, :site_id, :funktio, :tyyppi, :malli, :ping_check, :lisatiedot, :luotu, :muokattu, :muokkaaja) + ON DUPLICATE KEY UPDATE + nimi = VALUES(nimi), hallintaosoite = VALUES(hallintaosoite), serial = VALUES(serial), + site_id = VALUES(site_id), funktio = VALUES(funktio), tyyppi = VALUES(tyyppi), + malli = VALUES(malli), ping_check = VALUES(ping_check), lisatiedot = VALUES(lisatiedot), + muokattu = VALUES(muokattu), muokkaaja = VALUES(muokkaaja) + ", [ + 'id' => $device['id'], + 'company_id' => $companyId, + 'nimi' => $device['nimi'] ?? '', + 'hallintaosoite' => $device['hallintaosoite'] ?? '', + 'serial' => $device['serial'] ?? '', + 'site_id' => !empty($device['site_id']) ? $device['site_id'] : null, + 'funktio' => $device['funktio'] ?? '', + 'tyyppi' => $device['tyyppi'] ?? '', + 'malli' => $device['malli'] ?? '', + 'ping_check' => $device['ping_check'] ?? false, + 'lisatiedot' => $device['lisatiedot'] ?? '', + 'luotu' => $device['luotu'] ?? date('Y-m-d H:i:s'), + 'muokattu' => $device['muokattu'] ?? null, + 'muokkaaja' => $device['muokkaaja'] ?? '', + ]); +} + +function dbDeleteDevice(string $deviceId): void { + _dbExecute("DELETE FROM devices WHERE id = ?", [$deviceId]); +} + // ==================== LIIDIT ==================== function dbLoadLeads(string $companyId): array { diff --git a/index.html b/index.html index 3841068..1a36055 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,7 @@ -
+ + +
+
+ +
+ + + + + + + + + + + + + + + +
Nimi ↕HallintaosoiteSerialSijaintiFunktioTyyppiMalliPingToiminnot
+ +
+
+ 0 laitetta +
+
+
+
@@ -620,6 +655,9 @@ + @@ -689,6 +727,37 @@
+ +
+
+

Sijainnit

+ +
+

Toimipisteet ja konesalit joihin laitteita voidaan sijoittaa.

+
+ +

Käyttäjäoikeudet

@@ -705,6 +774,66 @@
+ + +