feat(audit) : extend audit logging to machines, constructeurs, model types, documents and conversions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matthieu
2026-02-12 14:51:26 +01:00
parent 2156df22c6
commit 02ff8b1a96
8 changed files with 1109 additions and 2 deletions

View File

@@ -4,10 +4,14 @@ declare(strict_types=1);
namespace App\Service;
use App\Entity\Profile;
use App\Enum\ModelCategory;
use App\Repository\ModelTypeRepository;
use DateTimeImmutable;
use Doctrine\DBAL\Connection;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Throwable;
final class ModelTypeCategoryConversionService
@@ -15,6 +19,8 @@ final class ModelTypeCategoryConversionService
public function __construct(
private readonly Connection $connection,
private readonly ModelTypeRepository $modelTypes,
private readonly RequestStack $requestStack,
private readonly Security $security,
) {}
/**
@@ -76,6 +82,11 @@ final class ModelTypeCategoryConversionService
$category = $modelType->getCategory();
$direction = ModelCategory::PIECE === $category ? 'piece_to_component' : 'component_to_piece';
$names = $check['names'];
$modelName = $modelType->getName();
$modelCode = $modelType->getCode();
$this->connection->beginTransaction();
try {
@@ -85,6 +96,8 @@ final class ModelTypeCategoryConversionService
$count = $this->convertComponentToPiece($modelTypeId);
}
$this->logConversionAudit($modelTypeId, $modelName, $modelCode, $direction, $count, $names);
$this->connection->commit();
return ['success' => true, 'convertedCount' => $count, 'error' => null];
@@ -415,4 +428,67 @@ final class ModelTypeCategoryConversionService
return $count;
}
/**
* @param list<string> $names
*/
private function logConversionAudit(
string $modelTypeId,
string $modelName,
string $modelCode,
string $direction,
int $convertedCount,
array $names,
): void {
$now = new DateTimeImmutable()->format('Y-m-d H:i:s');
$id = 'cl'.bin2hex(random_bytes(12));
$snapshot = [
'id' => $modelTypeId,
'name' => $modelName,
'code' => $modelCode,
];
$diff = [
'direction' => ['from' => null, 'to' => $direction],
'convertedCount' => ['from' => null, 'to' => $convertedCount],
'convertedNames' => ['from' => null, 'to' => $names],
];
$this->connection->executeStatement(
'INSERT INTO audit_logs (id, entitytype, entityid, action, diff, snapshot, actorprofileid, createdat)
VALUES (:id, :entityType, :entityId, :action, :diff, :snapshot, :actor, :now)',
[
'id' => $id,
'entityType' => 'model_type',
'entityId' => $modelTypeId,
'action' => 'convert',
'diff' => json_encode($diff),
'snapshot' => json_encode($snapshot),
'actor' => $this->resolveActorProfileId(),
'now' => $now,
],
);
}
private function resolveActorProfileId(): ?string
{
try {
$session = $this->requestStack->getSession();
if ($session instanceof SessionInterface) {
$profileId = $session->get('profileId');
if ($profileId) {
return (string) $profileId;
}
}
} catch (Throwable) {
}
$user = $this->security->getUser();
if ($user instanceof Profile) {
return $user->getId();
}
return null;
}
}