feat: complete jobcard management workflows and UI
This commit is contained in:
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
namespace App\Domain\Credential;
|
||||
|
||||
require_once __DIR__ . '/TechnicalInformation.php';
|
||||
require_once __DIR__ . '/TechnicalInformationCommand.php';
|
||||
|
||||
use InvalidArgumentException;
|
||||
use PDO;
|
||||
@@ -33,17 +34,17 @@ final class TechnicalInformationRepository
|
||||
public function upsert(int $clientId, string $category, array $data, ?int $updatedBy = null): array
|
||||
{
|
||||
$this->assertIds($clientId, $updatedBy);
|
||||
$validation = $this->information->validate([...$data, 'category' => $category]);
|
||||
if (!$validation['valid']) {
|
||||
throw new InvalidArgumentException('Invalid technical information: ' . implode(' ', $validation['errors']));
|
||||
$normalizedCategory = strtolower(trim($category));
|
||||
if (in_array($normalizedCategory, TechnicalInformationCommand::categories(), true)) {
|
||||
$validation = (new TechnicalInformationCommand())->validate(['client_id' => $clientId, 'category' => $normalizedCategory, 'data' => $data]);
|
||||
if (!$validation['valid']) throw new InvalidArgumentException('Invalid technical information: ' . implode(' ', $validation['errors']));
|
||||
$jsonData = $validation['record']['data'];
|
||||
} else {
|
||||
$validation = $this->information->validate([...$data, 'category' => $category]);
|
||||
if (!$validation['valid']) throw new InvalidArgumentException('Invalid technical information: ' . implode(' ', $validation['errors']));
|
||||
$normalizedCategory = $validation['category'];
|
||||
$jsonData = ['label' => $validation['label'], 'username' => $validation['username'], 'notes' => $validation['notes']];
|
||||
}
|
||||
|
||||
$normalizedCategory = $validation['category'];
|
||||
$jsonData = [
|
||||
'label' => $validation['label'],
|
||||
'username' => $validation['username'],
|
||||
'notes' => $validation['notes'],
|
||||
];
|
||||
$json = json_encode($jsonData, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
$statement = $this->pdo->prepare(
|
||||
@@ -73,7 +74,11 @@ final class TechnicalInformationRepository
|
||||
if (!is_string($category)) {
|
||||
throw new InvalidArgumentException('Technical information category is required.');
|
||||
}
|
||||
unset($information['category']);
|
||||
if (isset($information['data']) && is_array($information['data'])) {
|
||||
$information = $information['data'];
|
||||
} else {
|
||||
unset($information['category']);
|
||||
}
|
||||
return $this->upsert($clientId, $category, $information, $updatedBy);
|
||||
}
|
||||
|
||||
@@ -128,6 +133,15 @@ final class TechnicalInformationRepository
|
||||
return $this->display($record);
|
||||
}
|
||||
|
||||
/** Delete by record id; adapters may use the same contract for logical commands. */
|
||||
public function delete(int $id): array
|
||||
{
|
||||
if ($id < 1) throw new InvalidArgumentException('Technical information id must be a positive integer.');
|
||||
$statement = $this->pdo->prepare('DELETE FROM technical_information WHERE id = :id');
|
||||
$statement->execute(['id' => $id]);
|
||||
return ['valid' => true, 'action' => 'delete', 'id' => $id, 'errors' => []];
|
||||
}
|
||||
|
||||
/** @param array<string,mixed> $row @return array<string,mixed> */
|
||||
private function hydrate(array $row): array
|
||||
{
|
||||
@@ -159,17 +173,19 @@ final class TechnicalInformationRepository
|
||||
return $record;
|
||||
}
|
||||
|
||||
/** @return array{label:string,username:string|null,notes:string|null} */
|
||||
/** @return array<string,mixed> */
|
||||
private function decodeData(mixed $json): array
|
||||
{
|
||||
if (!is_string($json) || $json === '') throw new PDOException('Technical information JSON is missing.');
|
||||
$decoded = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
|
||||
if (!is_array($decoded)) throw new PDOException('Technical information JSON must be an object.');
|
||||
return [
|
||||
'label' => is_string($decoded['label'] ?? null) ? $decoded['label'] : '',
|
||||
'username' => isset($decoded['username']) && is_string($decoded['username']) ? $decoded['username'] : null,
|
||||
'notes' => isset($decoded['notes']) && is_string($decoded['notes']) ? $decoded['notes'] : null,
|
||||
];
|
||||
$allowed = ['label', 'tenant', 'product', 'portal_url', 'hostname', 'ip_address', 'vlan', 'model', 'role', 'os', 'username', 'notes'];
|
||||
$data = [];
|
||||
foreach ($allowed as $field) {
|
||||
if (!array_key_exists($field, $decoded) || !is_scalar($decoded[$field])) continue;
|
||||
$data[$field] = $field === 'vlan' ? (int)$decoded[$field] : (string)$decoded[$field];
|
||||
}
|
||||
return $data + ['label' => '', 'username' => null, 'notes' => null];
|
||||
}
|
||||
|
||||
private function assertIds(int $clientId, ?int $updatedBy): void
|
||||
|
||||
Reference in New Issue
Block a user