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

95
api.php
View File

@@ -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();