feat: Laitteet-moduuli (inventaario) + sijaintien hallinta + login-fix

- Uusi "Laitteet" välilehti navigaatiossa (devices-moduuli)
  - Taulukko: Nimi, Hallintaosoite, Serial, Sijainti, Funktio, Tyyppi, Malli, Ping
  - Lisää/muokkaa/poista laitteita modaali-lomakkeella
  - Hakupalkki suodattaa kaikista kentistä
  - Ping-check täppä valmiina tulevaa toteutusta varten
- Sijainnit (Sites) -hallinta yrityksen asetuksissa
  - Lisää/muokkaa/poista sijainteja (toimipisteet, konesalit)
  - Sijainnit näkyvät laitelomakkeen dropdownissa
- Laitteet-moduuli lisätty moduulijärjestelmään (checkbox yritysasetuksissa)
- DB: sites + devices taulut, CRUD-funktiot
- Fix: Login-näkymä ei enää vilku refreshissä (piilotettu oletuksena)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 19:00:26 +02:00
parent a135aaaaef
commit 18d378be63
4 changed files with 546 additions and 3 deletions

106
db.php
View File

@@ -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 {