163 lines
5.7 KiB
PHP
163 lines
5.7 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
|
|
require_once __DIR__ . '/../config/config.php';
|
|
|
|
try {
|
|
if (getenv('APP_DEBUG') === 'true') { ini_set('display_errors', '1'); error_reporting(E_ALL); }
|
|
if (!class_exists('PDO')) { throw new Exception('PDO extension not loaded'); }
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
http_response_code(405);
|
|
echo json_encode(['ok'=>false, 'error'=>'Method not allowed']);
|
|
exit;
|
|
}
|
|
|
|
if (!isset($_POST['run'])) {
|
|
http_response_code(400);
|
|
echo json_encode(['ok'=>false, 'error'=>'Missing run']);
|
|
exit;
|
|
}
|
|
|
|
// Eingabe parsen
|
|
$run = json_decode($_POST['run'], true, 512, JSON_THROW_ON_ERROR);
|
|
|
|
// Optional: PDF speichern
|
|
$savedPdf = null;
|
|
if (isset($_FILES['pdf']) && $_FILES['pdf']['error'] === UPLOAD_ERR_OK) {
|
|
$ext = '.pdf';
|
|
$fname = sprintf(
|
|
'QA-%s-%s-%s-%s%s',
|
|
preg_replace('~[^a-zA-Z0-9_-]+~','_', $run['module'] ?? 'mod'),
|
|
preg_replace('~[^a-zA-Z0-9_-]+~','_', $run['module_version'] ?? 'v'),
|
|
preg_replace('~[^a-zA-Z0-9_-]+~','_', $run['pbx_version'] ?? 'pbx'),
|
|
date('Ymd_His'),
|
|
$ext
|
|
);
|
|
$destDir = rtrim($pdf_storage_dir ?? (__DIR__ . '/../storage/reports'), '/');
|
|
if (!is_dir($destDir)) { @mkdir($destDir, 0775, true); }
|
|
$dest = $destDir . '/' . $fname;
|
|
if (!@move_uploaded_file($_FILES['pdf']['tmp_name'], $dest)) {
|
|
$savedPdf = null; // PDF optional; DB-Export läuft trotzdem weiter
|
|
}
|
|
$savedPdf = $dest;
|
|
}
|
|
|
|
// DB verbinden
|
|
$dsn = "mysql:host={$db_host};port={$db_port};dbname={$db_name};charset=utf8mb4";
|
|
$pdo = new PDO($dsn, $db_user, $db_pass, [
|
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
|
|
]);
|
|
|
|
// Schema sicherstellen (idempotent)
|
|
$pdo->exec("
|
|
CREATE TABLE IF NOT EXISTS reports (
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
module VARCHAR(255),
|
|
module_version VARCHAR(100),
|
|
pbx_version VARCHAR(100),
|
|
olm_nummer VARCHAR(100),
|
|
tester VARCHAR(255),
|
|
docbee_url TEXT,
|
|
summary VARCHAR(255),
|
|
pdf_path TEXT
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
CREATE TABLE IF NOT EXISTS steps (
|
|
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
report_id BIGINT NOT NULL,
|
|
step_index INT,
|
|
step_id VARCHAR(50),
|
|
title TEXT,
|
|
expected TEXT,
|
|
status ENUM('pass','fail','skip','na','') DEFAULT '',
|
|
comment TEXT,
|
|
evidence TEXT,
|
|
group_title VARCHAR(255),
|
|
group_index INT,
|
|
CONSTRAINT fk_steps_report FOREIGN KEY (report_id) REFERENCES reports(id) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
");
|
|
|
|
// Summary berechnen
|
|
$total=0;$pass=0;$fail=0;$skip=0;
|
|
foreach (($run['steps'] ?? []) as $s) {
|
|
if (($s['kind'] ?? 'step') === 'step') {
|
|
$total++;
|
|
$st = $s['status'] ?? '';
|
|
if ($st==='pass') $pass++;
|
|
elseif ($st==='fail') $fail++;
|
|
elseif ($st==='skip') $skip++;
|
|
}
|
|
}
|
|
$summary = sprintf('%d/%d pass, %d fail, %d skip', $pass, $total, $fail, $skip);
|
|
|
|
// Report speichern
|
|
$stmt = $pdo->prepare("INSERT INTO reports
|
|
(module, module_version, pbx_version, olm_nummer, tester, docbee_url, summary, pdf_path)
|
|
VALUES (:module, :module_version, :pbx_version, :olm_nummer, :tester, :docbee_url, :summary, :pdf_path)");
|
|
$stmt->execute([
|
|
':module' => $run['module'] ?? null,
|
|
':module_version' => $run['module_version'] ?? null,
|
|
':pbx_version' => $run['pbx_version'] ?? null,
|
|
':olm_nummer' => $run['olm_nummer'] ?? null,
|
|
':tester' => $run['tester'] ?? null,
|
|
':docbee_url' => $run['docbee_url'] ?? null,
|
|
':summary' => $summary,
|
|
':pdf_path' => $savedPdf
|
|
]);
|
|
$reportId = (int)$pdo->lastInsertId();
|
|
|
|
// Steps speichern
|
|
$idx = 0; $gidx = -1; $currentGroup = null;
|
|
$ins = $pdo->prepare("INSERT INTO steps
|
|
(report_id, step_index, step_id, title, expected, status, comment, evidence, group_title, group_index)
|
|
VALUES (:report_id,:step_index,:step_id,:title,:expected,:status,:comment,:evidence,:group_title,:group_index)");
|
|
foreach (($run['steps'] ?? []) as $s) {
|
|
if (($s['kind'] ?? 'step') === 'group') {
|
|
$currentGroup = $s['title'] ?? null;
|
|
$gidx++;
|
|
continue;
|
|
}
|
|
$idx++;
|
|
// status normalisieren → ENUM-kompatibel
|
|
$rawStatus = strtolower(trim((string)($s['status'] ?? '')));
|
|
$map = [
|
|
'ok'=>'pass','passed'=>'pass','success'=>'pass','true'=>'pass','yes'=>'pass','✔'=>'pass','✓'=>'pass',
|
|
'ko'=>'fail','failed'=>'fail','error'=>'fail','✗'=>'fail','x'=>'fail',
|
|
'skipped'=>'skip',
|
|
'n/a'=>'na','not applicable'=>'na',
|
|
'block'=>'blocked','blocked'=>'blocked','⛔'=>'blocked'
|
|
];
|
|
$st = $map[$rawStatus] ?? (in_array($rawStatus, ['pass','fail','skip','na','blocked',''], true) ? $rawStatus : '');
|
|
// und beim Insert:
|
|
// ':status' => $st,
|
|
|
|
$st = $map[$rawStatus] ?? (in_array($rawStatus, ['pass','fail','skip','na',''], true) ? $rawStatus : '');
|
|
try {
|
|
$ins->execute([
|
|
':report_id' => $reportId,
|
|
':step_index' => $idx,
|
|
':step_id' => $s['id'] ?? null,
|
|
':title' => $s['title'] ?? null,
|
|
':expected' => $s['expected'] ?? null,
|
|
':status' => $st,
|
|
':comment' => $s['comment'] ?? null,
|
|
':evidence' => $s['evidence'] ?? null,
|
|
':group_title' => $currentGroup,
|
|
':group_index' => $gidx >= 0 ? $gidx : null,
|
|
]);
|
|
} catch (PDOException $e) {
|
|
if ($e->getCode() !== '01000') { throw $e; } // ENUM-Truncation-Warning ignorieren
|
|
}
|
|
}
|
|
|
|
echo json_encode(['ok'=>true, 'report_id'=>$reportId, 'pdf_path'=>$savedPdf, 'summary'=>$summary]);
|
|
} catch (Throwable $e) {
|
|
http_response_code(500);
|
|
echo json_encode(['ok'=>false, 'error'=>$e->getMessage()]);
|
|
}
|
|
|