Lisätty: - db.php: PDO-tietokantakerros (kaikki CRUD-funktiot) - migrate.php: JSON → MySQL migraatioskripti - db_config.php lisätty .gitignore:en (sisältää tunnukset) Muutettu: - api.php: kaikki JSON load/save → db*() funktiot - session.cookie_samesite: Strict → Lax (captcha-fix alias-domaineilla) - Poistettu kaikki JSON-tiedosto I/O (paitsi tiedostoupload + logot) Hyödyt: - Git deploy ei enää ylikirjoita dataa - Tiedostolukot ja transaktiot → ei korruptiota - Parempi suorituskyky isoilla tietomäärillä Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
201 lines
7.3 KiB
PHP
201 lines
7.3 KiB
PHP
<?php
|
|
/**
|
|
* Noxus Intra — JSON → MySQL migraatioskripti
|
|
*
|
|
* Aja kerran: php migrate.php
|
|
* Lukee kaikki data/*.json -tiedostot ja siirtää ne MySQL-tietokantaan.
|
|
*/
|
|
|
|
require_once __DIR__ . '/db.php';
|
|
|
|
echo "=== Noxus Intra: JSON → MySQL migraatio ===\n\n";
|
|
|
|
// 1. Luo taulut
|
|
echo "1. Luodaan tietokantarakenne...\n";
|
|
initDatabase();
|
|
echo " ✓ Taulut luotu\n\n";
|
|
|
|
$dataDir = __DIR__ . '/data';
|
|
|
|
// 2. Yritykset
|
|
echo "2. Siirretään yritykset...\n";
|
|
$companiesFile = $dataDir . '/companies.json';
|
|
$companies = file_exists($companiesFile) ? json_decode(file_get_contents($companiesFile), true) : [];
|
|
$companyCount = 0;
|
|
foreach ($companies as $c) {
|
|
dbSaveCompany($c);
|
|
$companyCount++;
|
|
echo " ✓ {$c['nimi']} (id: {$c['id']})\n";
|
|
}
|
|
echo " Yhteensä: $companyCount yritystä\n\n";
|
|
|
|
// 3. Käyttäjät
|
|
echo "3. Siirretään käyttäjät...\n";
|
|
$usersFile = $dataDir . '/users.json';
|
|
$users = file_exists($usersFile) ? json_decode(file_get_contents($usersFile), true) : [];
|
|
$userCount = 0;
|
|
foreach ($users as $u) {
|
|
dbSaveUser($u);
|
|
$userCount++;
|
|
echo " ✓ {$u['username']} ({$u['role']})\n";
|
|
}
|
|
echo " Yhteensä: $userCount käyttäjää\n\n";
|
|
|
|
// 4. Globaalit asetukset
|
|
echo "4. Siirretään globaalit asetukset...\n";
|
|
$configFile = $dataDir . '/config.json';
|
|
if (file_exists($configFile)) {
|
|
$config = json_decode(file_get_contents($configFile), true) ?: [];
|
|
dbSaveConfig($config);
|
|
echo " ✓ config.json siirretty\n";
|
|
}
|
|
echo "\n";
|
|
|
|
// 5. Salasanan palautustokenit
|
|
echo "5. Siirretään reset-tokenit...\n";
|
|
$tokensFile = $dataDir . '/reset_tokens.json';
|
|
if (file_exists($tokensFile)) {
|
|
$tokens = json_decode(file_get_contents($tokensFile), true) ?: [];
|
|
$db = getDb();
|
|
foreach ($tokens as $t) {
|
|
try {
|
|
$stmt = $db->prepare("INSERT IGNORE INTO reset_tokens (user_id, token, created_at) VALUES (?, ?, ?)");
|
|
$expires = $t['expires'] ?? time();
|
|
$created = date('Y-m-d H:i:s', $expires - 3600); // Arvio luontiajasta
|
|
$stmt->execute([$t['user_id'], $t['token'], $created]);
|
|
} catch (Exception $e) {
|
|
echo " ⚠ Token ohitettu: " . $e->getMessage() . "\n";
|
|
}
|
|
}
|
|
echo " ✓ " . count($tokens) . " tokenia\n";
|
|
}
|
|
echo "\n";
|
|
|
|
// 6. Yrityskohtainen data
|
|
echo "6. Siirretään yrityskohtainen data...\n";
|
|
$companiesDir = $dataDir . '/companies';
|
|
if (is_dir($companiesDir)) {
|
|
$dirs = array_filter(scandir($companiesDir), fn($d) => $d !== '.' && $d !== '..' && is_dir("$companiesDir/$d"));
|
|
|
|
foreach ($dirs as $companyId) {
|
|
$compDir = "$companiesDir/$companyId";
|
|
echo "\n === $companyId ===\n";
|
|
|
|
// Yrityksen config (postilaatikot, tikettisäännöt, api_key, cors_origins)
|
|
$compConfig = "$compDir/config.json";
|
|
if (file_exists($compConfig)) {
|
|
$cfg = json_decode(file_get_contents($compConfig), true) ?: [];
|
|
|
|
// Postilaatikot
|
|
$mailboxes = $cfg['mailboxes'] ?? [];
|
|
foreach ($mailboxes as $mb) {
|
|
dbSaveMailbox($companyId, $mb);
|
|
}
|
|
echo " ✓ " . count($mailboxes) . " postilaatikkoa\n";
|
|
|
|
// Tikettisäännöt
|
|
$rules = $cfg['ticket_rules'] ?? [];
|
|
foreach ($rules as $rule) {
|
|
dbSaveTicketRule($companyId, $rule);
|
|
}
|
|
echo " ✓ " . count($rules) . " tikettisääntöä\n";
|
|
|
|
// API-avain ja CORS
|
|
if (!empty($cfg['api_key'])) {
|
|
dbSetCompanyApiKey($companyId, $cfg['api_key']);
|
|
echo " ✓ API-avain\n";
|
|
}
|
|
if (!empty($cfg['cors_origins'])) {
|
|
dbSetCompanyCorsOrigins($companyId, $cfg['cors_origins']);
|
|
echo " ✓ CORS-asetukset\n";
|
|
}
|
|
}
|
|
|
|
// Asiakkaat
|
|
$custFile = "$compDir/customers.json";
|
|
if (file_exists($custFile)) {
|
|
$customers = json_decode(file_get_contents($custFile), true) ?: [];
|
|
foreach ($customers as $cust) {
|
|
// Migroi vanhat flat-kentät liittymiksi jos tarpeen
|
|
if (!isset($cust['liittymat'])) {
|
|
$cust['liittymat'] = [];
|
|
if (!empty($cust['asennusosoite'] ?? '') || !empty($cust['liittymanopeus'] ?? '')) {
|
|
$cust['liittymat'][] = [
|
|
'asennusosoite' => $cust['asennusosoite'] ?? '',
|
|
'postinumero' => $cust['postinumero'] ?? '',
|
|
'kaupunki' => $cust['kaupunki'] ?? '',
|
|
'liittymanopeus' => $cust['liittymanopeus'] ?? '',
|
|
'hinta' => $cust['hinta'] ?? 0,
|
|
'sopimuskausi' => $cust['sopimuskausi'] ?? '',
|
|
'alkupvm' => $cust['alkupvm'] ?? '',
|
|
];
|
|
}
|
|
}
|
|
dbSaveCustomer($companyId, $cust);
|
|
}
|
|
echo " ✓ " . count($customers) . " asiakasta\n";
|
|
}
|
|
|
|
// Liidit
|
|
$leadsFile = "$compDir/leads.json";
|
|
if (file_exists($leadsFile)) {
|
|
$leads = json_decode(file_get_contents($leadsFile), true) ?: [];
|
|
foreach ($leads as $lead) {
|
|
dbSaveLead($companyId, $lead);
|
|
}
|
|
echo " ✓ " . count($leads) . " liidiä\n";
|
|
}
|
|
|
|
// Tiketit
|
|
$ticketsFile = "$compDir/tickets.json";
|
|
if (file_exists($ticketsFile)) {
|
|
$tickets = json_decode(file_get_contents($ticketsFile), true) ?: [];
|
|
foreach ($tickets as $ticket) {
|
|
dbSaveTicket($companyId, $ticket);
|
|
}
|
|
echo " ✓ " . count($tickets) . " tikettiä\n";
|
|
}
|
|
|
|
// Arkisto
|
|
$archiveFile = "$compDir/archive.json";
|
|
if (file_exists($archiveFile)) {
|
|
$archives = json_decode(file_get_contents($archiveFile), true) ?: [];
|
|
foreach ($archives as $arc) {
|
|
if (!empty($arc['id'])) {
|
|
dbArchiveCustomer($companyId, $arc);
|
|
}
|
|
}
|
|
echo " ✓ " . count($archives) . " arkistoitua\n";
|
|
}
|
|
|
|
// Changelog
|
|
$logFile = "$compDir/changelog.json";
|
|
if (file_exists($logFile)) {
|
|
$logs = json_decode(file_get_contents($logFile), true) ?: [];
|
|
$db = getDb();
|
|
$stmt = $db->prepare("
|
|
INSERT IGNORE INTO changelog (id, company_id, timestamp, user, action, customer_id, customer_name, details)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
");
|
|
foreach ($logs as $log) {
|
|
$stmt->execute([
|
|
$log['id'] ?? bin2hex(random_bytes(8)),
|
|
$companyId,
|
|
$log['timestamp'] ?? date('Y-m-d H:i:s'),
|
|
$log['user'] ?? '',
|
|
$log['action'] ?? '',
|
|
$log['customer_id'] ?? '',
|
|
$log['customer_name'] ?? '',
|
|
$log['details'] ?? '',
|
|
]);
|
|
}
|
|
echo " ✓ " . count($logs) . " lokimerkintää\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
echo "\n=== Migraatio valmis! ===\n";
|
|
echo "\nSeuraavat vaiheet:\n";
|
|
echo "1. Testaa: php -r \"require 'db.php'; print_r(dbLoadCompanies());\"\n";
|
|
echo "2. Ota MySQL-pohjainen api.php käyttöön\n";
|