- Ajout système complet de gestion des secteurs avec contours géographiques - Import des contours départementaux depuis GeoJSON - API REST pour la gestion des secteurs (/api/sectors) - Service de géolocalisation pour déterminer les secteurs - Migration base de données avec tables x_departements_contours et sectors_adresses - Interface Flutter pour visualisation et gestion des secteurs - Ajout thème sombre dans l'application - Corrections diverses et optimisations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
283 lines
13 KiB
PHP
Executable File
283 lines
13 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/ApiService.php';
|
|
require_once __DIR__ . '/LogService.php';
|
|
|
|
use PDO;
|
|
use ApiService;
|
|
use LogService;
|
|
|
|
class OperationDataService {
|
|
|
|
/**
|
|
* Prépare les données d'opération selon l'interface et le rôle utilisateur
|
|
*
|
|
* @param PDO $db Instance de la base de données
|
|
* @param int $entiteId ID de l'entité
|
|
* @param string $interface 'user' ou 'admin'
|
|
* @param int $userRole Rôle de l'utilisateur
|
|
* @param int $userId ID de l'utilisateur connecté
|
|
* @param int|null $specificOperationId ID d'opération spécifique (pour création d'opération)
|
|
* @return array Données formatées avec operations, sectors, users_sectors, passages
|
|
*/
|
|
public static function prepareOperationData(
|
|
PDO $db,
|
|
int $entiteId,
|
|
string $interface,
|
|
int $userRole,
|
|
int $userId,
|
|
?int $specificOperationId = null
|
|
): array {
|
|
|
|
$operationsData = [];
|
|
$sectorsData = [];
|
|
$passagesData = [];
|
|
$usersSectorsData = [];
|
|
|
|
// 1. Récupération des opérations selon les critères
|
|
$operationLimit = 0;
|
|
$activeOperationOnly = false;
|
|
|
|
if ($interface === 'user') {
|
|
// Interface utilisateur : seulement la dernière opération active
|
|
$operationLimit = 1;
|
|
$activeOperationOnly = true;
|
|
} elseif ($interface === 'admin' && $userRole == 2) {
|
|
// Interface admin avec rôle 2 : les 3 dernières opérations dont l'active
|
|
$operationLimit = 3;
|
|
} elseif ($interface === 'admin' && $userRole > 2) {
|
|
// Super admin : les 3 dernières opérations
|
|
$operationLimit = 3;
|
|
} else {
|
|
// Autres cas : pas d'opérations
|
|
$operationLimit = 0;
|
|
}
|
|
|
|
// Si une opération spécifique est demandée (création d'opération)
|
|
if ($specificOperationId) {
|
|
$operationQuery = "SELECT id, fk_entite, libelle, date_deb, date_fin, chk_active
|
|
FROM operations
|
|
WHERE fk_entite = ?
|
|
ORDER BY id DESC LIMIT 3";
|
|
|
|
$operationStmt = $db->prepare($operationQuery);
|
|
$operationStmt->execute([$entiteId]);
|
|
$operations = $operationStmt->fetchAll(PDO::FETCH_ASSOC);
|
|
$activeOperationId = $specificOperationId;
|
|
} elseif ($operationLimit > 0) {
|
|
$operationQuery = "SELECT id, fk_entite, libelle, date_deb, date_fin, chk_active
|
|
FROM operations
|
|
WHERE fk_entite = ?";
|
|
|
|
if ($activeOperationOnly) {
|
|
$operationQuery .= " AND chk_active = 1";
|
|
}
|
|
|
|
$operationQuery .= " ORDER BY id DESC LIMIT " . $operationLimit;
|
|
|
|
$operationStmt = $db->prepare($operationQuery);
|
|
$operationStmt->execute([$entiteId]);
|
|
$operations = $operationStmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// Récupérer l'ID de l'opération active (première opération retournée ou celle avec chk_active=1)
|
|
$activeOperationId = null;
|
|
if (!empty($operations)) {
|
|
foreach ($operations as $operation) {
|
|
if ($operation['chk_active'] == 1) {
|
|
$activeOperationId = (int)$operation['id'];
|
|
break;
|
|
}
|
|
}
|
|
// Si aucune opération active trouvée, prendre la première
|
|
if (!$activeOperationId) {
|
|
$activeOperationId = (int)$operations[0]['id'];
|
|
}
|
|
}
|
|
} else {
|
|
$operations = [];
|
|
$activeOperationId = null;
|
|
}
|
|
|
|
if (!empty($operations)) {
|
|
// Formater les données des opérations
|
|
foreach ($operations as $operation) {
|
|
$operationsData[] = [
|
|
'id' => $operation['id'],
|
|
'fk_entite' => $operation['fk_entite'],
|
|
'libelle' => $operation['libelle'],
|
|
'date_deb' => $operation['date_deb'],
|
|
'date_fin' => $operation['date_fin'],
|
|
'chk_active' => $operation['chk_active']
|
|
];
|
|
}
|
|
|
|
// 2. Récupérer les secteurs selon l'interface et le rôle
|
|
if ($activeOperationId) {
|
|
if ($interface === 'user') {
|
|
// Interface utilisateur : seulement les secteurs affectés à l'utilisateur
|
|
$sectorsStmt = $db->prepare(
|
|
'SELECT s.id, s.libelle, s.color, s.sector
|
|
FROM ope_sectors s
|
|
JOIN ope_users_sectors us ON s.id = us.fk_sector
|
|
WHERE us.fk_operation = ? AND us.fk_user = ? AND us.chk_active = 1 AND s.chk_active = 1'
|
|
);
|
|
$sectorsStmt->execute([$activeOperationId, $userId]);
|
|
} elseif ($interface === 'admin' && ($userRole == 2 || $userRole > 2)) {
|
|
// Interface admin : tous les secteurs distincts de l'opération
|
|
$sectorsStmt = $db->prepare(
|
|
'SELECT DISTINCT s.id, s.libelle, s.color, s.sector
|
|
FROM ope_sectors s
|
|
WHERE s.fk_operation = ? AND s.chk_active = 1'
|
|
);
|
|
$sectorsStmt->execute([$activeOperationId]);
|
|
} else {
|
|
$sectors = [];
|
|
}
|
|
|
|
// Récupération des secteurs si une requête a été préparée
|
|
if (isset($sectorsStmt)) {
|
|
$sectors = $sectorsStmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} else {
|
|
$sectors = [];
|
|
}
|
|
|
|
if (!empty($sectors)) {
|
|
$sectorsData = $sectors;
|
|
|
|
// 3. Récupérer les passages selon l'interface et le rôle
|
|
if ($interface === 'user' && !empty($sectors)) {
|
|
// Interface utilisateur : passages liés aux secteurs de l'utilisateur
|
|
$sectorIds = array_column($sectors, 'id');
|
|
$sectorIdsString = implode(',', $sectorIds);
|
|
|
|
if (!empty($sectorIdsString)) {
|
|
$passagesStmt = $db->prepare(
|
|
"SELECT id, fk_operation, fk_sector, fk_user, fk_type, fk_adresse, passed_at, numero, rue, rue_bis, ville, residence, fk_habitat, appt, niveau,
|
|
gps_lat, gps_lng, nom_recu, encrypted_name, remarque, encrypted_email, encrypted_phone, montant, fk_type_reglement, email_erreur, nb_passages,
|
|
chk_email_sent, docremis, date_repasser, chk_mobile, anomalie, created_at, updated_at, chk_active
|
|
FROM ope_pass
|
|
WHERE fk_operation = ? AND fk_sector IN ($sectorIdsString) AND chk_active = 1"
|
|
);
|
|
$passagesStmt->execute([$activeOperationId]);
|
|
}
|
|
} elseif ($interface === 'admin' && ($userRole == 2 || $userRole > 2)) {
|
|
// Interface admin : tous les passages de l'opération
|
|
$passagesStmt = $db->prepare(
|
|
"SELECT id, fk_operation, fk_sector, fk_user, fk_type, fk_adresse, passed_at, numero, rue, rue_bis, ville, residence, fk_habitat, appt, niveau,
|
|
gps_lat, gps_lng, nom_recu, encrypted_name, remarque, encrypted_email, encrypted_phone, montant, fk_type_reglement, email_erreur, nb_passages,
|
|
chk_email_sent, docremis, date_repasser, chk_mobile, anomalie, created_at, updated_at, chk_active
|
|
FROM ope_pass
|
|
WHERE fk_operation = ? AND chk_active = 1"
|
|
);
|
|
$passagesStmt->execute([$activeOperationId]);
|
|
} else {
|
|
$passages = [];
|
|
}
|
|
|
|
// Récupération des passages si une requête a été préparée
|
|
if (isset($passagesStmt)) {
|
|
$passages = $passagesStmt->fetchAll(PDO::FETCH_ASSOC);
|
|
} else {
|
|
$passages = [];
|
|
}
|
|
|
|
if (!empty($passages)) {
|
|
// Déchiffrer les données sensibles
|
|
foreach ($passages as &$passage) {
|
|
// Déchiffrement du nom
|
|
$passage['name'] = '';
|
|
if (!empty($passage['encrypted_name'])) {
|
|
$passage['name'] = ApiService::decryptData($passage['encrypted_name']);
|
|
}
|
|
unset($passage['encrypted_name']);
|
|
|
|
// Déchiffrement de l'email
|
|
$passage['email'] = '';
|
|
if (!empty($passage['encrypted_email'])) {
|
|
$decryptedEmail = ApiService::decryptSearchableData($passage['encrypted_email']);
|
|
if ($decryptedEmail) {
|
|
$passage['email'] = $decryptedEmail;
|
|
}
|
|
}
|
|
unset($passage['encrypted_email']);
|
|
|
|
// Déchiffrement du téléphone
|
|
$passage['phone'] = '';
|
|
if (!empty($passage['encrypted_phone'])) {
|
|
$passage['phone'] = ApiService::decryptData($passage['encrypted_phone']);
|
|
}
|
|
unset($passage['encrypted_phone']);
|
|
}
|
|
$passagesData = $passages;
|
|
}
|
|
|
|
// 4. Récupérer les utilisateurs des secteurs partagés
|
|
if (($interface === 'user' || ($interface === 'admin' && ($userRole == 2 || $userRole > 2))) && !empty($sectors)) {
|
|
$sectorIds = array_column($sectors, 'id');
|
|
$sectorIdsString = implode(',', $sectorIds);
|
|
|
|
if (!empty($sectorIdsString)) {
|
|
// Utiliser ope_users au lieu de users pour avoir les données historiques
|
|
$usersSectorsStmt = $db->prepare(
|
|
"SELECT DISTINCT ou.fk_user as id, ou.first_name, ou.encrypted_name, ou.sect_name, us.fk_sector
|
|
FROM ope_users ou
|
|
JOIN ope_users_sectors us ON ou.fk_user = us.fk_user AND ou.fk_operation = us.fk_operation
|
|
WHERE us.fk_sector IN ($sectorIdsString)
|
|
AND us.fk_operation = ?
|
|
AND us.chk_active = 1
|
|
AND ou.chk_active = 1
|
|
AND ou.fk_user != ?" // Exclure l'utilisateur connecté
|
|
);
|
|
$usersSectorsStmt->execute([$activeOperationId, $userId]);
|
|
$usersSectors = $usersSectorsStmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
if (!empty($usersSectors)) {
|
|
// Déchiffrer les noms des utilisateurs
|
|
foreach ($usersSectors as &$userSector) {
|
|
if (!empty($userSector['encrypted_name'])) {
|
|
$userSector['name'] = ApiService::decryptData($userSector['encrypted_name']);
|
|
unset($userSector['encrypted_name']);
|
|
}
|
|
}
|
|
$usersSectorsData = $usersSectors;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return [
|
|
'operations' => $operationsData,
|
|
'sectors' => $sectorsData,
|
|
'users_sectors' => $usersSectorsData,
|
|
'passages' => $passagesData
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Prépare la réponse complète pour la création d'opération
|
|
*
|
|
* @param PDO $db Instance de la base de données
|
|
* @param int $newOpeId ID de la nouvelle opération
|
|
* @param int $entiteId ID de l'entité
|
|
* @return array Réponse formatée avec status, message, operation_id et données
|
|
*/
|
|
public static function prepareOperationResponse(PDO $db, int $newOpeId, int $entiteId): array {
|
|
// Utiliser le rôle admin pour récupérer toutes les données
|
|
$operationData = self::prepareOperationData($db, $entiteId, 'admin', 2, 0, $newOpeId);
|
|
|
|
return [
|
|
'status' => 'success',
|
|
'message' => 'Opération créée avec succès',
|
|
'operation_id' => $newOpeId,
|
|
'operations' => $operationData['operations'],
|
|
'sectors' => $operationData['sectors'],
|
|
'users_sectors' => $operationData['users_sectors'],
|
|
'passages' => $operationData['passages']
|
|
];
|
|
}
|
|
}
|