Livraison d ela gestion des opérations v0.4.0
This commit is contained in:
803
api/src/Controllers/PassageController.php
Normal file
803
api/src/Controllers/PassageController.php
Normal file
@@ -0,0 +1,803 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
require_once __DIR__ . '/../Services/LogService.php';
|
||||
require_once __DIR__ . '/../Services/ApiService.php';
|
||||
|
||||
use PDO;
|
||||
use PDOException;
|
||||
use Database;
|
||||
use AppConfig;
|
||||
use Request;
|
||||
use Response;
|
||||
use Session;
|
||||
use LogService;
|
||||
use ApiService;
|
||||
use Exception;
|
||||
use DateTime;
|
||||
|
||||
class PassageController {
|
||||
private PDO $db;
|
||||
private AppConfig $appConfig;
|
||||
|
||||
public function __construct() {
|
||||
$this->db = Database::getInstance();
|
||||
$this->appConfig = AppConfig::getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère l'entité de l'utilisateur connecté
|
||||
*
|
||||
* @param int $userId ID de l'utilisateur
|
||||
* @return int|null ID de l'entité ou null si non trouvé
|
||||
*/
|
||||
private function getUserEntiteId(int $userId): ?int {
|
||||
try {
|
||||
$stmt = $this->db->prepare('SELECT fk_entite FROM users WHERE id = ?');
|
||||
$stmt->execute([$userId]);
|
||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
return $user ? (int)$user['fk_entite'] : null;
|
||||
} catch (Exception $e) {
|
||||
LogService::log('Erreur lors de la récupération de l\'entité utilisateur', [
|
||||
'level' => 'error',
|
||||
'error' => $e->getMessage(),
|
||||
'userId' => $userId
|
||||
]);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'utilisateur a accès à l'opération
|
||||
*
|
||||
* @param int $userId ID de l'utilisateur
|
||||
* @param int $operationId ID de l'opération
|
||||
* @return bool True si l'utilisateur a accès
|
||||
*/
|
||||
private function hasAccessToOperation(int $userId, int $operationId): bool {
|
||||
try {
|
||||
$entiteId = $this->getUserEntiteId($userId);
|
||||
if (!$entiteId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$stmt = $this->db->prepare('
|
||||
SELECT COUNT(*) as count
|
||||
FROM operations
|
||||
WHERE id = ? AND fk_entite = ? AND chk_active = 1
|
||||
');
|
||||
$stmt->execute([$operationId, $entiteId]);
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
return $result && $result['count'] > 0;
|
||||
} catch (Exception $e) {
|
||||
LogService::log('Erreur lors de la vérification d\'accès à l\'opération', [
|
||||
'level' => 'error',
|
||||
'error' => $e->getMessage(),
|
||||
'userId' => $userId,
|
||||
'operationId' => $operationId
|
||||
]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide les données d'un passage
|
||||
*
|
||||
* @param array $data Données à valider
|
||||
* @param int|null $passageId ID du passage (pour update)
|
||||
* @return array|null Erreurs de validation ou null
|
||||
*/
|
||||
private function validatePassageData(array $data, ?int $passageId = null): ?array {
|
||||
$errors = [];
|
||||
|
||||
// Validation de l'opération
|
||||
if (!isset($data['fk_operation']) || empty($data['fk_operation'])) {
|
||||
$errors[] = 'L\'ID de l\'opération est obligatoire';
|
||||
}
|
||||
|
||||
// Validation de l'utilisateur
|
||||
if (!isset($data['fk_user']) || empty($data['fk_user'])) {
|
||||
$errors[] = 'L\'ID de l\'utilisateur est obligatoire';
|
||||
}
|
||||
|
||||
// Validation de l'adresse
|
||||
if (!isset($data['numero']) || empty(trim($data['numero']))) {
|
||||
$errors[] = 'Le numéro de rue est obligatoire';
|
||||
}
|
||||
|
||||
if (!isset($data['rue']) || empty(trim($data['rue']))) {
|
||||
$errors[] = 'Le nom de rue est obligatoire';
|
||||
}
|
||||
|
||||
if (!isset($data['ville']) || empty(trim($data['ville']))) {
|
||||
$errors[] = 'La ville est obligatoire';
|
||||
}
|
||||
|
||||
// Validation du nom (chiffré)
|
||||
if (!isset($data['encrypted_name']) && !isset($data['name'])) {
|
||||
$errors[] = 'Le nom est obligatoire';
|
||||
}
|
||||
|
||||
// Validation du montant
|
||||
if (isset($data['montant'])) {
|
||||
$montant = (float)$data['montant'];
|
||||
if ($montant < 0) {
|
||||
$errors[] = 'Le montant ne peut pas être négatif';
|
||||
}
|
||||
if ($montant > 999999.99) {
|
||||
$errors[] = 'Le montant ne peut pas dépasser 999999.99';
|
||||
}
|
||||
}
|
||||
|
||||
// Validation de l'email si fourni
|
||||
if (isset($data['email']) && !empty($data['email'])) {
|
||||
if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
$errors[] = 'Format d\'email invalide';
|
||||
}
|
||||
}
|
||||
|
||||
// Validation des coordonnées GPS si fournies
|
||||
if (isset($data['gps_lat']) && !empty($data['gps_lat'])) {
|
||||
$lat = (float)$data['gps_lat'];
|
||||
if ($lat < -90 || $lat > 90) {
|
||||
$errors[] = 'Latitude invalide (doit être entre -90 et 90)';
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['gps_lng']) && !empty($data['gps_lng'])) {
|
||||
$lng = (float)$data['gps_lng'];
|
||||
if ($lng < -180 || $lng > 180) {
|
||||
$errors[] = 'Longitude invalide (doit être entre -180 et 180)';
|
||||
}
|
||||
}
|
||||
|
||||
return empty($errors) ? null : $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère tous les passages de l'entité de l'utilisateur
|
||||
*/
|
||||
public function getPassages(): void {
|
||||
try {
|
||||
$userId = Session::getUserId();
|
||||
if (!$userId) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Vous devez être connecté pour effectuer cette action'
|
||||
], 401);
|
||||
return;
|
||||
}
|
||||
|
||||
$entiteId = $this->getUserEntiteId($userId);
|
||||
if (!$entiteId) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Entité non trouvée pour cet utilisateur'
|
||||
], 404);
|
||||
return;
|
||||
}
|
||||
|
||||
// Paramètres de pagination
|
||||
$page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
|
||||
$limit = isset($_GET['limit']) ? min(100, max(1, (int)$_GET['limit'])) : 20;
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
// Filtres optionnels
|
||||
$operationId = isset($_GET['operation_id']) ? (int)$_GET['operation_id'] : null;
|
||||
$userId_filter = isset($_GET['user_id']) ? (int)$_GET['user_id'] : null;
|
||||
|
||||
// Construction de la requête
|
||||
$whereConditions = ['o.fk_entite = ?'];
|
||||
$params = [$entiteId];
|
||||
|
||||
if ($operationId) {
|
||||
$whereConditions[] = 'p.fk_operation = ?';
|
||||
$params[] = $operationId;
|
||||
}
|
||||
|
||||
if ($userId_filter) {
|
||||
$whereConditions[] = 'p.fk_user = ?';
|
||||
$params[] = $userId_filter;
|
||||
}
|
||||
|
||||
$whereClause = implode(' AND ', $whereConditions);
|
||||
|
||||
// Requête principale avec jointures
|
||||
$stmt = $this->db->prepare("
|
||||
SELECT
|
||||
p.id, p.fk_operation, p.fk_sector, p.fk_user, p.fk_adresse,
|
||||
p.passed_at, p.fk_type, p.numero, p.rue, p.rue_bis, p.ville,
|
||||
p.fk_habitat, p.appt, p.niveau, p.residence, p.gps_lat, p.gps_lng,
|
||||
p.encrypted_name, p.montant, p.fk_type_reglement, p.remarque,
|
||||
p.encrypted_email, p.encrypted_phone, p.nom_recu, p.date_recu,
|
||||
p.chk_email_sent, p.docremis, p.date_repasser, p.nb_passages,
|
||||
p.chk_mobile, p.anomalie, p.created_at, p.updated_at, p.chk_active,
|
||||
o.libelle as operation_libelle,
|
||||
u.encrypted_name as user_name, u.first_name as user_first_name
|
||||
FROM ope_pass p
|
||||
INNER JOIN operations o ON p.fk_operation = o.id
|
||||
INNER JOIN users u ON p.fk_user = u.id
|
||||
WHERE $whereClause AND p.chk_active = 1
|
||||
ORDER BY p.created_at DESC
|
||||
LIMIT ? OFFSET ?
|
||||
");
|
||||
|
||||
$params[] = $limit;
|
||||
$params[] = $offset;
|
||||
$stmt->execute($params);
|
||||
$passages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Déchiffrement des données sensibles
|
||||
foreach ($passages as &$passage) {
|
||||
$passage['name'] = ApiService::decryptData($passage['encrypted_name']);
|
||||
$passage['email'] = !empty($passage['encrypted_email']) ?
|
||||
ApiService::decryptSearchableData($passage['encrypted_email']) : '';
|
||||
$passage['phone'] = !empty($passage['encrypted_phone']) ?
|
||||
ApiService::decryptData($passage['encrypted_phone']) : '';
|
||||
$passage['user_name'] = ApiService::decryptData($passage['user_name']);
|
||||
|
||||
// Suppression des champs chiffrés
|
||||
unset($passage['encrypted_name'], $passage['encrypted_email'], $passage['encrypted_phone']);
|
||||
}
|
||||
|
||||
// Compter le total pour la pagination
|
||||
$countStmt = $this->db->prepare("
|
||||
SELECT COUNT(*) as total
|
||||
FROM ope_pass p
|
||||
INNER JOIN operations o ON p.fk_operation = o.id
|
||||
WHERE $whereClause AND p.chk_active = 1
|
||||
");
|
||||
$countStmt->execute(array_slice($params, 0, -2)); // Enlever limit et offset
|
||||
$totalResult = $countStmt->fetch(PDO::FETCH_ASSOC);
|
||||
$total = $totalResult['total'];
|
||||
|
||||
Response::json([
|
||||
'status' => 'success',
|
||||
'passages' => $passages,
|
||||
'pagination' => [
|
||||
'page' => $page,
|
||||
'limit' => $limit,
|
||||
'total' => $total,
|
||||
'pages' => ceil($total / $limit)
|
||||
]
|
||||
], 200);
|
||||
} catch (Exception $e) {
|
||||
LogService::log('Erreur lors de la récupération des passages', [
|
||||
'level' => 'error',
|
||||
'error' => $e->getMessage(),
|
||||
'userId' => $userId ?? null
|
||||
]);
|
||||
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Erreur lors de la récupération des passages'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère un passage spécifique par son ID
|
||||
*/
|
||||
public function getPassageById(string $id): void {
|
||||
try {
|
||||
$userId = Session::getUserId();
|
||||
if (!$userId) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Vous devez être connecté pour effectuer cette action'
|
||||
], 401);
|
||||
return;
|
||||
}
|
||||
|
||||
$entiteId = $this->getUserEntiteId($userId);
|
||||
if (!$entiteId) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Entité non trouvée pour cet utilisateur'
|
||||
], 404);
|
||||
return;
|
||||
}
|
||||
|
||||
$passageId = (int)$id;
|
||||
|
||||
$stmt = $this->db->prepare('
|
||||
SELECT
|
||||
p.*,
|
||||
o.libelle as operation_libelle,
|
||||
u.encrypted_name as user_name, u.first_name as user_first_name
|
||||
FROM ope_pass p
|
||||
INNER JOIN operations o ON p.fk_operation = o.id
|
||||
INNER JOIN users u ON p.fk_user = u.id
|
||||
WHERE p.id = ? AND o.fk_entite = ? AND p.chk_active = 1
|
||||
');
|
||||
|
||||
$stmt->execute([$passageId, $entiteId]);
|
||||
$passage = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$passage) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Passage non trouvé'
|
||||
], 404);
|
||||
return;
|
||||
}
|
||||
|
||||
// Déchiffrement des données sensibles
|
||||
$passage['name'] = ApiService::decryptData($passage['encrypted_name']);
|
||||
$passage['email'] = !empty($passage['encrypted_email']) ?
|
||||
ApiService::decryptSearchableData($passage['encrypted_email']) : '';
|
||||
$passage['phone'] = !empty($passage['encrypted_phone']) ?
|
||||
ApiService::decryptData($passage['encrypted_phone']) : '';
|
||||
$passage['user_name'] = ApiService::decryptData($passage['user_name']);
|
||||
|
||||
// Suppression des champs chiffrés
|
||||
unset($passage['encrypted_name'], $passage['encrypted_email'], $passage['encrypted_phone']);
|
||||
|
||||
Response::json([
|
||||
'status' => 'success',
|
||||
'passage' => $passage
|
||||
], 200);
|
||||
} catch (Exception $e) {
|
||||
LogService::log('Erreur lors de la récupération du passage', [
|
||||
'level' => 'error',
|
||||
'error' => $e->getMessage(),
|
||||
'passageId' => $id,
|
||||
'userId' => $userId ?? null
|
||||
]);
|
||||
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Erreur lors de la récupération du passage'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère tous les passages d'une opération spécifique
|
||||
*/
|
||||
public function getPassagesByOperation(string $operation_id): void {
|
||||
try {
|
||||
$userId = Session::getUserId();
|
||||
if (!$userId) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Vous devez être connecté pour effectuer cette action'
|
||||
], 401);
|
||||
return;
|
||||
}
|
||||
|
||||
$operationId = (int)$operation_id;
|
||||
|
||||
// Vérifier l'accès à l'opération
|
||||
if (!$this->hasAccessToOperation($userId, $operationId)) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Vous n\'avez pas accès à cette opération'
|
||||
], 403);
|
||||
return;
|
||||
}
|
||||
|
||||
// Paramètres de pagination
|
||||
$page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
|
||||
$limit = isset($_GET['limit']) ? min(100, max(1, (int)$_GET['limit'])) : 50;
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
$stmt = $this->db->prepare('
|
||||
SELECT
|
||||
p.id, p.fk_operation, p.fk_sector, p.fk_user, p.passed_at,
|
||||
p.numero, p.rue, p.rue_bis, p.ville, p.gps_lat, p.gps_lng,
|
||||
p.encrypted_name, p.montant, p.fk_type_reglement, p.remarque,
|
||||
p.encrypted_email, p.encrypted_phone, p.chk_email_sent,
|
||||
p.docremis, p.date_repasser, p.nb_passages, p.chk_mobile,
|
||||
p.anomalie, p.created_at, p.updated_at,
|
||||
u.encrypted_name as user_name, u.first_name as user_first_name
|
||||
FROM ope_pass p
|
||||
INNER JOIN users u ON p.fk_user = u.id
|
||||
WHERE p.fk_operation = ? AND p.chk_active = 1
|
||||
ORDER BY p.created_at DESC
|
||||
LIMIT ? OFFSET ?
|
||||
');
|
||||
|
||||
$stmt->execute([$operationId, $limit, $offset]);
|
||||
$passages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Déchiffrement des données sensibles
|
||||
foreach ($passages as &$passage) {
|
||||
$passage['name'] = ApiService::decryptData($passage['encrypted_name']);
|
||||
$passage['email'] = !empty($passage['encrypted_email']) ?
|
||||
ApiService::decryptSearchableData($passage['encrypted_email']) : '';
|
||||
$passage['phone'] = !empty($passage['encrypted_phone']) ?
|
||||
ApiService::decryptData($passage['encrypted_phone']) : '';
|
||||
$passage['user_name'] = ApiService::decryptData($passage['user_name']);
|
||||
|
||||
// Suppression des champs chiffrés
|
||||
unset($passage['encrypted_name'], $passage['encrypted_email'], $passage['encrypted_phone']);
|
||||
}
|
||||
|
||||
// Compter le total
|
||||
$countStmt = $this->db->prepare('
|
||||
SELECT COUNT(*) as total
|
||||
FROM ope_pass
|
||||
WHERE fk_operation = ? AND chk_active = 1
|
||||
');
|
||||
$countStmt->execute([$operationId]);
|
||||
$totalResult = $countStmt->fetch(PDO::FETCH_ASSOC);
|
||||
$total = $totalResult['total'];
|
||||
|
||||
Response::json([
|
||||
'status' => 'success',
|
||||
'passages' => $passages,
|
||||
'pagination' => [
|
||||
'page' => $page,
|
||||
'limit' => $limit,
|
||||
'total' => $total,
|
||||
'pages' => ceil($total / $limit)
|
||||
]
|
||||
], 200);
|
||||
} catch (Exception $e) {
|
||||
LogService::log('Erreur lors de la récupération des passages par opération', [
|
||||
'level' => 'error',
|
||||
'error' => $e->getMessage(),
|
||||
'operationId' => $operation_id,
|
||||
'userId' => $userId ?? null
|
||||
]);
|
||||
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Erreur lors de la récupération des passages'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un nouveau passage
|
||||
*/
|
||||
public function createPassage(): void {
|
||||
try {
|
||||
$userId = Session::getUserId();
|
||||
if (!$userId) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Vous devez être connecté pour effectuer cette action'
|
||||
], 401);
|
||||
return;
|
||||
}
|
||||
|
||||
$data = Request::getJson();
|
||||
|
||||
// Validation des données
|
||||
$errors = $this->validatePassageData($data);
|
||||
if ($errors) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Erreurs de validation',
|
||||
'errors' => $errors
|
||||
], 400);
|
||||
return;
|
||||
}
|
||||
|
||||
$operationId = (int)$data['fk_operation'];
|
||||
|
||||
// Vérifier l'accès à l'opération
|
||||
if (!$this->hasAccessToOperation($userId, $operationId)) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Vous n\'avez pas accès à cette opération'
|
||||
], 403);
|
||||
return;
|
||||
}
|
||||
|
||||
// Chiffrement des données sensibles
|
||||
$encryptedName = isset($data['name']) ? ApiService::encryptData($data['name']) : (isset($data['encrypted_name']) ? $data['encrypted_name'] : '');
|
||||
$encryptedEmail = isset($data['email']) && !empty($data['email']) ?
|
||||
ApiService::encryptSearchableData($data['email']) : '';
|
||||
$encryptedPhone = isset($data['phone']) && !empty($data['phone']) ?
|
||||
ApiService::encryptData($data['phone']) : '';
|
||||
|
||||
// Préparation des données pour l'insertion
|
||||
$insertData = [
|
||||
'fk_operation' => $operationId,
|
||||
'fk_sector' => isset($data['fk_sector']) ? (int)$data['fk_sector'] : 0,
|
||||
'fk_user' => (int)$data['fk_user'],
|
||||
'fk_adresse' => $data['fk_adresse'] ?? '',
|
||||
'passed_at' => isset($data['passed_at']) ? $data['passed_at'] : null,
|
||||
'fk_type' => isset($data['fk_type']) ? (int)$data['fk_type'] : 0,
|
||||
'numero' => trim($data['numero']),
|
||||
'rue' => trim($data['rue']),
|
||||
'rue_bis' => $data['rue_bis'] ?? '',
|
||||
'ville' => trim($data['ville']),
|
||||
'fk_habitat' => isset($data['fk_habitat']) ? (int)$data['fk_habitat'] : 1,
|
||||
'appt' => $data['appt'] ?? '',
|
||||
'niveau' => $data['niveau'] ?? '',
|
||||
'residence' => $data['residence'] ?? '',
|
||||
'gps_lat' => $data['gps_lat'] ?? '',
|
||||
'gps_lng' => $data['gps_lng'] ?? '',
|
||||
'encrypted_name' => $encryptedName,
|
||||
'montant' => isset($data['montant']) ? (float)$data['montant'] : 0.00,
|
||||
'fk_type_reglement' => isset($data['fk_type_reglement']) ? (int)$data['fk_type_reglement'] : 1,
|
||||
'remarque' => $data['remarque'] ?? '',
|
||||
'encrypted_email' => $encryptedEmail,
|
||||
'encrypted_phone' => $encryptedPhone,
|
||||
'nom_recu' => $data['nom_recu'] ?? null,
|
||||
'date_recu' => isset($data['date_recu']) ? $data['date_recu'] : null,
|
||||
'docremis' => isset($data['docremis']) ? (int)$data['docremis'] : 0,
|
||||
'date_repasser' => isset($data['date_repasser']) ? $data['date_repasser'] : null,
|
||||
'nb_passages' => isset($data['nb_passages']) ? (int)$data['nb_passages'] : 1,
|
||||
'chk_mobile' => isset($data['chk_mobile']) ? (int)$data['chk_mobile'] : 0,
|
||||
'anomalie' => isset($data['anomalie']) ? (int)$data['anomalie'] : 0,
|
||||
'fk_user_creat' => $userId
|
||||
];
|
||||
|
||||
// Construction de la requête d'insertion
|
||||
$fields = array_keys($insertData);
|
||||
$placeholders = array_fill(0, count($fields), '?');
|
||||
|
||||
$sql = 'INSERT INTO ope_pass (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $placeholders) . ')';
|
||||
|
||||
$stmt = $this->db->prepare($sql);
|
||||
$stmt->execute(array_values($insertData));
|
||||
|
||||
$passageId = $this->db->lastInsertId();
|
||||
|
||||
LogService::log('Création d\'un nouveau passage', [
|
||||
'level' => 'info',
|
||||
'userId' => $userId,
|
||||
'passageId' => $passageId,
|
||||
'operationId' => $operationId
|
||||
]);
|
||||
|
||||
Response::json([
|
||||
'status' => 'success',
|
||||
'message' => 'Passage créé avec succès',
|
||||
'passage_id' => $passageId
|
||||
], 201);
|
||||
} catch (Exception $e) {
|
||||
LogService::log('Erreur lors de la création du passage', [
|
||||
'level' => 'error',
|
||||
'error' => $e->getMessage(),
|
||||
'userId' => $userId ?? null
|
||||
]);
|
||||
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Erreur lors de la création du passage'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour un passage existant
|
||||
*/
|
||||
public function updatePassage(string $id): void {
|
||||
try {
|
||||
$userId = Session::getUserId();
|
||||
if (!$userId) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Vous devez être connecté pour effectuer cette action'
|
||||
], 401);
|
||||
return;
|
||||
}
|
||||
|
||||
$passageId = (int)$id;
|
||||
$data = Request::getJson();
|
||||
|
||||
// Vérifier que le passage existe et appartient à l'entité de l'utilisateur
|
||||
$entiteId = $this->getUserEntiteId($userId);
|
||||
if (!$entiteId) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Entité non trouvée pour cet utilisateur'
|
||||
], 404);
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $this->db->prepare('
|
||||
SELECT p.id, p.fk_operation
|
||||
FROM ope_pass p
|
||||
INNER JOIN operations o ON p.fk_operation = o.id
|
||||
WHERE p.id = ? AND o.fk_entite = ? AND p.chk_active = 1
|
||||
');
|
||||
$stmt->execute([$passageId, $entiteId]);
|
||||
$passage = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$passage) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Passage non trouvé'
|
||||
], 404);
|
||||
return;
|
||||
}
|
||||
|
||||
// Validation des données
|
||||
$errors = $this->validatePassageData($data, $passageId);
|
||||
if ($errors) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Erreurs de validation',
|
||||
'errors' => $errors
|
||||
], 400);
|
||||
return;
|
||||
}
|
||||
|
||||
// Construction de la requête de mise à jour dynamique
|
||||
$updateFields = [];
|
||||
$params = [];
|
||||
|
||||
// Champs pouvant être mis à jour
|
||||
$updatableFields = [
|
||||
'fk_sector',
|
||||
'fk_user',
|
||||
'fk_adresse',
|
||||
'passed_at',
|
||||
'fk_type',
|
||||
'numero',
|
||||
'rue',
|
||||
'rue_bis',
|
||||
'ville',
|
||||
'fk_habitat',
|
||||
'appt',
|
||||
'niveau',
|
||||
'residence',
|
||||
'gps_lat',
|
||||
'gps_lng',
|
||||
'montant',
|
||||
'fk_type_reglement',
|
||||
'remarque',
|
||||
'nom_recu',
|
||||
'date_recu',
|
||||
'docremis',
|
||||
'date_repasser',
|
||||
'nb_passages',
|
||||
'chk_mobile',
|
||||
'anomalie'
|
||||
];
|
||||
|
||||
foreach ($updatableFields as $field) {
|
||||
if (isset($data[$field])) {
|
||||
$updateFields[] = "$field = ?";
|
||||
$params[] = $data[$field];
|
||||
}
|
||||
}
|
||||
|
||||
// Gestion des champs chiffrés
|
||||
if (isset($data['name'])) {
|
||||
$updateFields[] = "encrypted_name = ?";
|
||||
$params[] = ApiService::encryptData($data['name']);
|
||||
}
|
||||
|
||||
if (isset($data['email'])) {
|
||||
$updateFields[] = "encrypted_email = ?";
|
||||
$params[] = !empty($data['email']) ? ApiService::encryptSearchableData($data['email']) : '';
|
||||
}
|
||||
|
||||
if (isset($data['phone'])) {
|
||||
$updateFields[] = "encrypted_phone = ?";
|
||||
$params[] = !empty($data['phone']) ? ApiService::encryptData($data['phone']) : '';
|
||||
}
|
||||
|
||||
if (empty($updateFields)) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Aucune donnée à mettre à jour'
|
||||
], 400);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ajout des champs de mise à jour
|
||||
$updateFields[] = "updated_at = NOW()";
|
||||
$updateFields[] = "fk_user_modif = ?";
|
||||
$params[] = $userId;
|
||||
$params[] = $passageId;
|
||||
|
||||
$sql = 'UPDATE ope_pass SET ' . implode(', ', $updateFields) . ' WHERE id = ?';
|
||||
$stmt = $this->db->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
|
||||
LogService::log('Mise à jour d\'un passage', [
|
||||
'level' => 'info',
|
||||
'userId' => $userId,
|
||||
'passageId' => $passageId
|
||||
]);
|
||||
|
||||
Response::json([
|
||||
'status' => 'success',
|
||||
'message' => 'Passage mis à jour avec succès'
|
||||
], 200);
|
||||
} catch (Exception $e) {
|
||||
LogService::log('Erreur lors de la mise à jour du passage', [
|
||||
'level' => 'error',
|
||||
'error' => $e->getMessage(),
|
||||
'passageId' => $id,
|
||||
'userId' => $userId ?? null
|
||||
]);
|
||||
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Erreur lors de la mise à jour du passage'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime (désactive) un passage
|
||||
*/
|
||||
public function deletePassage(string $id): void {
|
||||
try {
|
||||
$userId = Session::getUserId();
|
||||
if (!$userId) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Vous devez être connecté pour effectuer cette action'
|
||||
], 401);
|
||||
return;
|
||||
}
|
||||
|
||||
$passageId = (int)$id;
|
||||
|
||||
// Vérifier que le passage existe et appartient à l'entité de l'utilisateur
|
||||
$entiteId = $this->getUserEntiteId($userId);
|
||||
if (!$entiteId) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Entité non trouvée pour cet utilisateur'
|
||||
], 404);
|
||||
return;
|
||||
}
|
||||
|
||||
$stmt = $this->db->prepare('
|
||||
SELECT p.id
|
||||
FROM ope_pass p
|
||||
INNER JOIN operations o ON p.fk_operation = o.id
|
||||
WHERE p.id = ? AND o.fk_entite = ? AND p.chk_active = 1
|
||||
');
|
||||
$stmt->execute([$passageId, $entiteId]);
|
||||
$passage = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$passage) {
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Passage non trouvé'
|
||||
], 404);
|
||||
return;
|
||||
}
|
||||
|
||||
// Désactiver le passage (soft delete)
|
||||
$stmt = $this->db->prepare('
|
||||
UPDATE ope_pass
|
||||
SET chk_active = 0, updated_at = NOW(), fk_user_modif = ?
|
||||
WHERE id = ?
|
||||
');
|
||||
|
||||
$stmt->execute([$userId, $passageId]);
|
||||
|
||||
LogService::log('Suppression d\'un passage', [
|
||||
'level' => 'info',
|
||||
'userId' => $userId,
|
||||
'passageId' => $passageId
|
||||
]);
|
||||
|
||||
Response::json([
|
||||
'status' => 'success',
|
||||
'message' => 'Passage supprimé avec succès'
|
||||
], 200);
|
||||
} catch (Exception $e) {
|
||||
LogService::log('Erreur lors de la suppression du passage', [
|
||||
'level' => 'error',
|
||||
'error' => $e->getMessage(),
|
||||
'passageId' => $id,
|
||||
'userId' => $userId ?? null
|
||||
]);
|
||||
|
||||
Response::json([
|
||||
'status' => 'error',
|
||||
'message' => 'Erreur lors de la suppression du passage'
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user