diff --git a/.gitignore b/.gitignore index f1ddee1..9491a2f 100644 --- a/.gitignore +++ b/.gitignore @@ -360,7 +360,4 @@ MigrationBackup/ .ionide/ # Fody - auto-generated XML schema -FodyWeavers.xsd -/project/public/submitLeaveRequest.php -/project/public/getPendingRequests.php -/project/public/validateRequest.php +FodyWeavers.xsd \ No newline at end of file diff --git a/project/public/getPendingRequests.php b/project/public/getPendingRequests.php new file mode 100644 index 0000000..54dac05 --- /dev/null +++ b/project/public/getPendingRequests.php @@ -0,0 +1,156 @@ +connect_error) { + error_log("Erreur connexion DB getPendingRequests: " . $conn->connect_error); + echo json_encode(["success" => false, "message" => "Erreur de connexion à la base de données"]); + exit(); +} + +$managerId = $_GET['manager_id'] ?? null; + +if ($managerId === null) { + echo json_encode(["success" => false, "message" => "ID manager manquant"]); + exit(); +} + +error_log("getPendingRequests - Manager ID: $managerId"); + +// Fonction pour calculer les jours ouvrés +function getWorkingDays($startDate, $endDate) { + $workingDays = 0; + $current = new DateTime($startDate); + $end = new DateTime($endDate); + + while ($current <= $end) { + $dayOfWeek = (int)$current->format('N'); + if ($dayOfWeek < 6) { + $workingDays++; + } + $current->modify('+1 day'); + } + return $workingDays; +} + +try { + // D'abord, récupérer le service du manager + $queryManagerService = "SELECT ServiceId FROM Users WHERE ID = ?"; + $stmtManager = $conn->prepare($queryManagerService); + $stmtManager->bind_param("i", $managerId); + $stmtManager->execute(); + $resultManager = $stmtManager->get_result(); + + if ($managerRow = $resultManager->fetch_assoc()) { + $serviceId = $managerRow['ServiceId']; + error_log("getPendingRequests - Service ID du manager: $serviceId"); + + // Récupérer les demandes en attente de l'équipe + $queryRequests = " + SELECT + dc.Id, + dc.DateDebut, + dc.DateFin, + dc.Statut, + dc.DateDemande, + dc.Commentaire, + dc.EmployeeId, + CONCAT(u.Prenom, ' ', u.Nom) as employee_name, + u.Email as employee_email, + tc.Nom as type + FROM DemandeConge dc + JOIN Users u ON dc.EmployeeId = u.ID + JOIN TypeConge tc ON dc.TypeCongeId = tc.Id + WHERE u.ServiceId = ? + AND dc.Statut = 'En attente' + AND u.ID != ? + ORDER BY dc.DateDemande ASC + "; + + $stmtRequests = $conn->prepare($queryRequests); + $stmtRequests->bind_param("ii", $serviceId, $managerId); + $stmtRequests->execute(); + $resultRequests = $stmtRequests->get_result(); + + $requests = []; + while ($row = $resultRequests->fetch_assoc()) { + $workingDays = getWorkingDays($row['DateDebut'], $row['DateFin']); + + $startDate = new DateTime($row['DateDebut']); + $endDate = new DateTime($row['DateFin']); + $submittedDate = new DateTime($row['DateDemande']); + + if ($row['DateDebut'] === $row['DateFin']) { + $dateDisplay = $startDate->format('d/m/Y'); + } else { + $dateDisplay = $startDate->format('d/m/Y') . ' - ' . $endDate->format('d/m/Y'); + } + + $requests[] = [ + 'id' => (int)$row['Id'], + 'employee_id' => (int)$row['EmployeeId'], + 'employee_name' => $row['employee_name'], + 'employee_email' => $row['employee_email'], + 'type' => $row['type'], + 'start_date' => $row['DateDebut'], + 'end_date' => $row['DateFin'], + 'date_display' => $dateDisplay, + 'days' => $workingDays, + 'status' => $row['Statut'], + 'reason' => $row['Commentaire'] ?: '', + 'submitted_at' => $row['DateDemande'], + 'submitted_display' => $submittedDate->format('d/m/Y') + ]; + } + + error_log("getPendingRequests - Demandes en attente trouvées: " . count($requests)); + + echo json_encode([ + "success" => true, + "message" => "Demandes en attente récupérées avec succès", + "requests" => $requests, + "service_id" => $serviceId + ]); + + $stmtRequests->close(); + } else { + error_log("getPendingRequests - Manager non trouvé: $managerId"); + echo json_encode([ + "success" => false, + "message" => "Manager non trouvé" + ]); + } + + $stmtManager->close(); + +} catch (Exception $e) { + error_log("Erreur getPendingRequests: " . $e->getMessage()); + echo json_encode([ + "success" => false, + "message" => "Erreur lors de la récupération des demandes: " . $e->getMessage() + ]); +} + +$conn->close(); +?> \ No newline at end of file diff --git a/project/public/submitLeaveRequest.php b/project/public/submitLeaveRequest.php new file mode 100644 index 0000000..bcb819c --- /dev/null +++ b/project/public/submitLeaveRequest.php @@ -0,0 +1,181 @@ +connect_error) { + error_log("Erreur connexion DB submitLeaveRequest: " . $conn->connect_error); + echo json_encode([ + "success" => false, + "message" => "Erreur de connexion DB : " . $conn->connect_error + ]); + exit(); +} + +// Lecture du JSON envoyé +$input = file_get_contents('php://input'); +error_log("submitLeaveRequest - Input reçu: " . $input); + +$data = json_decode($input, true); + +if (!isset( + $data['EmployeeId'], + $data['TypeConge'], + $data['DateDebut'], + $data['DateFin'], + $data['NumDays'] +)) { + error_log("submitLeaveRequest - Données manquantes: " . print_r($data, true)); + echo json_encode([ + "success" => false, + "message" => "Données manquantes pour la demande de congé." + ]); + exit(); +} + +// Récupération des champs +$employeeId = (int) $data['EmployeeId']; +$typeCongeNom= $data['TypeConge']; +$dateDebut = $data['DateDebut']; +$dateFin = $data['DateFin']; +$commentaire = $data['Commentaire'] ?? ''; +$numDays = (int) $data['NumDays']; + +error_log("submitLeaveRequest - Données parsées: EmployeeId=$employeeId, Type=$typeCongeNom, Début=$dateDebut, Fin=$dateFin"); + +$statut = 'En attente'; +$validateur = null; +$currentDate= date('Y-m-d H:i:s'); // date complète pour DateDemande + +// Mapping frontend → DB +switch ($typeCongeNom) { + case 'CP': $dbTypeCongeName = 'Congé payé'; break; + case 'RTT': $dbTypeCongeName = 'RTT'; break; + case 'ABS': $dbTypeCongeName = 'Congé maladie'; break; + default: + error_log("submitLeaveRequest - Type de congé inconnu: $typeCongeNom"); + echo json_encode([ + "success" => false, + "message" => "Type de congé inconnu." + ]); + $conn->close(); + exit(); +} + +error_log("submitLeaveRequest - Type DB mappé: $dbTypeCongeName"); + +// Récupération de l'ID du type de congé +$stmt = $conn->prepare("SELECT Id FROM TypeConge WHERE Nom = ?"); +if (!$stmt) { + error_log("submitLeaveRequest - Erreur préparation requête TypeConge: " . $conn->error); + echo json_encode([ + "success" => false, + "message" => "Erreur préparation requête TypeConge" + ]); + $conn->close(); + exit(); +} + +$stmt->bind_param("s", $dbTypeCongeName); +$stmt->execute(); +$res = $stmt->get_result(); +if ($row = $res->fetch_assoc()) { + $typeCongeId = (int) $row['Id']; + error_log("submitLeaveRequest - TypeCongeId trouvé: $typeCongeId"); +} else { + error_log("submitLeaveRequest - Type de congé non trouvé en DB: $dbTypeCongeName"); + echo json_encode([ + "success" => false, + "message" => "Type de congé non trouvé en DB : $dbTypeCongeName" + ]); + $stmt->close(); + $conn->close(); + exit(); +} +$stmt->close(); + +// Requête d'insertion dans DemandeConge +$query = " + INSERT INTO DemandeConge + (EmployeeId, DateDebut, DateFin, TypeCongeId, Statut, DateDemande, Commentaire, Validateur, NombreJours) + VALUES + (?, ?, ?, ?, ?, ?, ?, ?, ?) +"; + +error_log("submitLeaveRequest - Requête d'insertion: $query"); + +// Préparation de la requête +$stmt = $conn->prepare($query); +if (!$stmt) { + error_log("Erreur prepare insert : " . $conn->error); + echo json_encode([ + "success" => false, + "message" => "Erreur interne lors de la préparation de la requête." + ]); + $conn->close(); + exit(); +} + +// Pour la colonne Validateur, on passe '' si null +$validParam = $validateur ?? ''; + +error_log("submitLeaveRequest - Paramètres bind: $employeeId, $dateDebut, $dateFin, $typeCongeId, $statut, $currentDate, $commentaire, $validParam, $numDays"); + +// Bind des paramètres (types : i=integer, s=string, d=decimal) +$stmt->bind_param( + "ississssi", + $employeeId, // i + $dateDebut, // s + $dateFin, // s + $typeCongeId, // i + $statut, // s + $currentDate, // s - DateDemande + $commentaire, // s + $validParam, // s + $numDays // i - NombreJours +); + +// Exécution +if ($stmt->execute()) { + $insertId = $conn->insert_id; + error_log("submitLeaveRequest - Insertion réussie, ID: $insertId"); + echo json_encode([ + "success" => true, + "message" => "Demande de congé soumise avec succès.", + "request_id" => $insertId + ]); +} else { + error_log("Erreur execute insert : " . $stmt->error); + echo json_encode([ + "success" => false, + "message" => "Erreur lors de l'enregistrement : " . $stmt->error + ]); +} + +$stmt->close(); +$conn->close(); + +error_log("submitLeaveRequest - Script terminé"); + +?> diff --git a/project/public/validateRequest.php b/project/public/validateRequest.php new file mode 100644 index 0000000..5792465 --- /dev/null +++ b/project/public/validateRequest.php @@ -0,0 +1,197 @@ +connect_error) { + error_log("Erreur connexion DB validateRequest: " . $conn->connect_error); + echo json_encode(["success" => false, "message" => "Erreur de connexion à la base de données"]); + exit(); +} + +// Lecture du JSON envoyé +$input = file_get_contents('php://input'); +error_log("validateRequest - Input reçu: " . $input); + +$data = json_decode($input, true); + +if (!isset($data['request_id'], $data['action'], $data['validator_id'])) { + error_log("validateRequest - Données manquantes: " . print_r($data, true)); + echo json_encode([ + "success" => false, + "message" => "Données manquantes pour la validation" + ]); + exit(); +} + +$requestId = (int)$data['request_id']; +$action = $data['action']; // 'approve' ou 'reject' +$validatorId = (int)$data['validator_id']; +$comment = $data['comment'] ?? ''; + +error_log("validateRequest - Request ID: $requestId, Action: $action, Validator: $validatorId"); + +try { + $conn->begin_transaction(); + + // Vérifier que la demande existe et est en attente + $queryCheck = " + SELECT dc.Id, dc.EmployeeId, dc.TypeCongeId, dc.DateDebut, dc.DateFin, dc.NombreJours, + u.Nom, u.Prenom, tc.Nom as TypeNom + FROM DemandeConge dc + JOIN Users u ON dc.EmployeeId = u.ID + JOIN TypeConge tc ON dc.TypeCongeId = tc.Id + WHERE dc.Id = ? AND dc.Statut = 'En attente' + "; + + $stmtCheck = $conn->prepare($queryCheck); + $stmtCheck->bind_param("i", $requestId); + $stmtCheck->execute(); + $resultCheck = $stmtCheck->get_result(); + + if ($requestRow = $resultCheck->fetch_assoc()) { + $employeeId = $requestRow['EmployeeId']; + $typeCongeId = $requestRow['TypeCongeId']; + $nombreJours = $requestRow['NombreJours']; + $employeeName = $requestRow['Prenom'] . ' ' . $requestRow['Nom']; + $typeNom = $requestRow['TypeNom']; + + error_log("validateRequest - Demande trouvée: $employeeName, Type: $typeNom, Jours: $nombreJours"); + + // Déterminer le nouveau statut + $newStatus = ($action === 'approve') ? 'Validée' : 'Refusée'; + + // Mettre à jour la demande + $queryUpdate = " + UPDATE DemandeConge + SET Statut = ?, + ValidateurId = ?, + DateValidation = NOW(), + CommentaireValidation = ? + WHERE Id = ? + "; + + $stmtUpdate = $conn->prepare($queryUpdate); + $stmtUpdate->bind_param("sisi", $newStatus, $validatorId, $comment, $requestId); + + if ($stmtUpdate->execute()) { + error_log("validateRequest - Demande mise à jour avec succès"); + + // Si approuvée, déduire du solde (sauf pour congé maladie) + if ($action === 'approve' && $typeNom !== 'Congé maladie') { + // Déterminer l'année selon le type de congé + $currentDate = new DateTime(); + if ($typeNom === 'Congé payé') { + // Exercice CP: 01/06 au 31/05 + $year = ($currentDate->format('m') < 6) ? $currentDate->format('Y') - 1 : $currentDate->format('Y'); + } else { + // RTT: année civile + $year = $currentDate->format('Y'); + } + + error_log("validateRequest - Déduction solde: Type=$typeNom, Année=$year, Jours=$nombreJours"); + + // Déduire du solde + $queryDeduct = " + UPDATE CompteurConges + SET Solde = GREATEST(0, Solde - ?) + WHERE EmployeeId = ? AND TypeCongeId = ? AND Annee = ? + "; + + $stmtDeduct = $conn->prepare($queryDeduct); + $stmtDeduct->bind_param("diii", $nombreJours, $employeeId, $typeCongeId, $year); + + if ($stmtDeduct->execute()) { + error_log("validateRequest - Solde déduit avec succès"); + } else { + error_log("validateRequest - Erreur déduction solde: " . $stmtDeduct->error); + } + + $stmtDeduct->close(); + } + + // Créer une notification pour l'employé + $notificationTitle = ($action === 'approve') ? 'Demande approuvée' : 'Demande refusée'; + $notificationMessage = "Votre demande de $typeNom a été " . (($action === 'approve') ? 'approuvée' : 'refusée'); + if ($comment) { + $notificationMessage .= ". Commentaire: $comment"; + } + + $queryNotif = " + INSERT INTO Notifications (UserId, Titre, Message, Type, DemandeCongeId) + VALUES (?, ?, ?, ?, ?) + "; + + $notifType = ($action === 'approve') ? 'Success' : 'Error'; + $stmtNotif = $conn->prepare($queryNotif); + $stmtNotif->bind_param("isssi", $employeeId, $notificationTitle, $notificationMessage, $notifType, $requestId); + $stmtNotif->execute(); + $stmtNotif->close(); + + // Log dans l'historique + $actionText = ($action === 'approve') ? 'Validation congé' : 'Refus congé'; + $actionDetails = "$actionText $employeeName ($typeNom)"; + if ($comment) { + $actionDetails .= " - $comment"; + } + + $queryHistory = " + INSERT INTO HistoriqueActions (UserId, Action, Details, DemandeCongeId) + VALUES (?, ?, ?, ?) + "; + + $stmtHistory = $conn->prepare($queryHistory); + $stmtHistory->bind_param("issi", $validatorId, $actionText, $actionDetails, $requestId); + $stmtHistory->execute(); + $stmtHistory->close(); + + $conn->commit(); + + echo json_encode([ + "success" => true, + "message" => "Demande " . (($action === 'approve') ? 'approuvée' : 'refusée') . " avec succès", + "new_status" => $newStatus + ]); + + } else { + throw new Exception("Erreur lors de la mise à jour: " . $stmtUpdate->error); + } + + $stmtUpdate->close(); + } else { + throw new Exception("Demande non trouvée ou déjà traitée"); + } + + $stmtCheck->close(); + +} catch (Exception $e) { + $conn->rollback(); + error_log("Erreur validateRequest: " . $e->getMessage()); + echo json_encode([ + "success" => false, + "message" => "Erreur lors de la validation: " . $e->getMessage() + ]); +} + +$conn->close(); +?> \ No newline at end of file