Initial Kaffeekasse SaaS restart
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use PDO;
|
||||
use RuntimeException;
|
||||
|
||||
final class RfidService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly PDO $pdo,
|
||||
private readonly AuditService $audit
|
||||
) {
|
||||
}
|
||||
|
||||
public function createDevice(int $tenantId, string $name, ?string $location, int $actorUserId): string
|
||||
{
|
||||
if (trim($name) === '') {
|
||||
throw new RuntimeException('Bitte einen Geraetenamen angeben.');
|
||||
}
|
||||
|
||||
$token = bin2hex(random_bytes(20));
|
||||
$statement = $this->pdo->prepare(
|
||||
'INSERT INTO rfid_devices (tenant_id, name, location_label, device_token, status)
|
||||
VALUES (:tenant_id, :name, :location_label, :device_token, "planned")'
|
||||
);
|
||||
$statement->execute([
|
||||
'tenant_id' => $tenantId,
|
||||
'name' => trim($name),
|
||||
'location_label' => $location,
|
||||
'device_token' => $token,
|
||||
]);
|
||||
$deviceId = (int) $this->pdo->lastInsertId();
|
||||
|
||||
$this->audit->log($tenantId, $actorUserId, 'rfid.device_created', 'rfid_device', $deviceId, 'success');
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
public function assignTag(int $tenantId, int $memberId, string $uid, ?string $label, int $actorUserId): void
|
||||
{
|
||||
if (trim($uid) === '') {
|
||||
throw new RuntimeException('Die Karten-UID darf nicht leer sein.');
|
||||
}
|
||||
|
||||
$statement = $this->pdo->prepare(
|
||||
'INSERT INTO rfid_tags (tenant_id, member_id, uid_hash, label, status)
|
||||
VALUES (:tenant_id, :member_id, :uid_hash, :label, "active")'
|
||||
);
|
||||
$statement->execute([
|
||||
'tenant_id' => $tenantId,
|
||||
'member_id' => $memberId,
|
||||
'uid_hash' => hash('sha256', trim($uid)),
|
||||
'label' => $label,
|
||||
]);
|
||||
|
||||
$this->audit->log($tenantId, $actorUserId, 'rfid.tag_assigned', 'rfid_tag', (int) $this->pdo->lastInsertId(), 'success');
|
||||
}
|
||||
|
||||
public function ingest(array $payload): void
|
||||
{
|
||||
$deviceToken = trim((string) ($payload['device_token'] ?? ''));
|
||||
$uid = trim((string) ($payload['uid'] ?? ''));
|
||||
$externalEventId = trim((string) ($payload['event_id'] ?? ''));
|
||||
|
||||
if ($deviceToken === '' || $uid === '') {
|
||||
throw new RuntimeException('device_token und uid sind Pflichtfelder.');
|
||||
}
|
||||
|
||||
$deviceStatement = $this->pdo->prepare(
|
||||
'SELECT d.id, d.tenant_id, d.status
|
||||
FROM rfid_devices d
|
||||
WHERE d.device_token = :device_token
|
||||
LIMIT 1'
|
||||
);
|
||||
$deviceStatement->execute(['device_token' => $deviceToken]);
|
||||
$device = $deviceStatement->fetch();
|
||||
|
||||
if (!$device) {
|
||||
throw new RuntimeException('Das RFID-Geraet ist unbekannt.');
|
||||
}
|
||||
|
||||
$status = 'received';
|
||||
$tagStatement = $this->pdo->prepare(
|
||||
'SELECT id FROM rfid_tags WHERE tenant_id = :tenant_id AND uid_hash = :uid_hash LIMIT 1'
|
||||
);
|
||||
$tagStatement->execute([
|
||||
'tenant_id' => $device['tenant_id'],
|
||||
'uid_hash' => hash('sha256', $uid),
|
||||
]);
|
||||
|
||||
if ($tagStatement->fetch()) {
|
||||
$status = 'linked';
|
||||
}
|
||||
|
||||
$statement = $this->pdo->prepare(
|
||||
'INSERT INTO rfid_events (
|
||||
tenant_id,
|
||||
device_id,
|
||||
external_event_id,
|
||||
uid_hash,
|
||||
payload_json,
|
||||
status,
|
||||
received_at
|
||||
) VALUES (
|
||||
:tenant_id,
|
||||
:device_id,
|
||||
:external_event_id,
|
||||
:uid_hash,
|
||||
:payload_json,
|
||||
:status,
|
||||
:received_at
|
||||
)'
|
||||
);
|
||||
$statement->execute([
|
||||
'tenant_id' => $device['tenant_id'],
|
||||
'device_id' => $device['id'],
|
||||
'external_event_id' => $externalEventId !== '' ? $externalEventId : null,
|
||||
'uid_hash' => hash('sha256', $uid),
|
||||
'payload_json' => json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
|
||||
'status' => $status,
|
||||
'received_at' => gmdate('Y-m-d H:i:s'),
|
||||
]);
|
||||
|
||||
$this->audit->log((int) $device['tenant_id'], null, 'rfid.event_received', 'rfid_event', (int) $this->pdo->lastInsertId(), 'success', [
|
||||
'status' => $status,
|
||||
'device_id' => (int) $device['id'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user