false, 'message' => 'ID non valido.']); exit; } $id = (int)$rawId; // Whether to create the next (recurring) deadline. Absent or '1' => create; '0' => complete only. $createNext = ($_POST['create_next'] ?? '1') !== '0'; // Whether to carry the attachment links over to the new deadline. Default ON ("default all activate"). $copyAttachments = ($_POST['copy_attachments'] ?? '1') !== '0'; $db = DBHandlerSelect::getInstance(); $pdo = $db->getConnection(); $stmt = $pdo->prepare("SELECT * FROM scad_deadlines WHERE id = ? AND status = 'active'"); $stmt->execute([$id]); $deadline = $stmt->fetch(PDO::FETCH_ASSOC); if (!$deadline) { echo json_encode(['success' => false, 'message' => 'Scadenza non trovata o giĆ  completata.']); exit; } $pdo->beginTransaction(); // Mark as completed $pdo->prepare("UPDATE scad_deadlines SET status = 'completed', completed_at = NOW(), completed_by = ? WHERE id = ?") ->execute([$currentUserId, $id]); // History $pdo->prepare("INSERT INTO scad_deadline_histories (deadline_id, user_id, action) VALUES (?, ?, 'completed')") ->execute([$id, $currentUserId]); $newId = null; $newDueDate = null; // If recurring AND the user asked for it, create the next deadline if ($deadline['recurrence_type'] !== 'once' && $createNext) { $dueDate = new DateTime($deadline['due_date']); $checkDate = $deadline['check_date'] ? new DateTime($deadline['check_date']) : null; $documentDate = $deadline['document_date'] ? new DateTime($deadline['document_date']) : null; switch ($deadline['recurrence_type']) { case 'monthly': $interval = new DateInterval('P1M'); break; case 'quarterly': $interval = new DateInterval('P3M'); break; case 'semiannual': $interval = new DateInterval('P6M'); break; case 'annual': $interval = new DateInterval('P1Y'); break; case 'biennial': $interval = new DateInterval('P2Y'); break; case 'triennial': $interval = new DateInterval('P3Y'); break; case 'quadriennial': $interval = new DateInterval('P4Y'); break; case 'quinquennial': $interval = new DateInterval('P5Y'); break; case 'decennial': $interval = new DateInterval('P10Y'); break; case 'quindecennial': $interval = new DateInterval('P15Y'); break; default: $interval = null; } if ($interval) { $dueDate->add($interval); if ($checkDate) $checkDate->add($interval); if ($documentDate) $documentDate->add($interval); $ins = $pdo->prepare(" INSERT INTO scad_deadlines (subject_id, topic, law_regulation, recurrence_type, due_date, check_date, document_date, notification_days, storage_location, notes, created_by, departments) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "); $ins->execute([ $deadline['subject_id'], $deadline['topic'], $deadline['law_regulation'], $deadline['recurrence_type'], $dueDate->format('Y-m-d'), $checkDate ? $checkDate->format('Y-m-d') : null, $documentDate ? $documentDate->format('Y-m-d') : null, $deadline['notification_days'], $deadline['storage_location'], $deadline['notes'], $deadline['created_by'], $deadline['departments'] ]); $newId = $pdo->lastInsertId(); $newDueDate = $dueDate; // Copy employee assignments $empStmt = $pdo->prepare("SELECT employee_id FROM scad_deadline_employee WHERE deadline_id = ?"); $empStmt->execute([$id]); $empIds = $empStmt->fetchAll(PDO::FETCH_COLUMN); if (!empty($empIds)) { $insertEmp = $pdo->prepare("INSERT INTO scad_deadline_employee (deadline_id, employee_id) VALUES (?, ?)"); foreach ($empIds as $empId) { $insertEmp->execute([$newId, $empId]); } } // Carry forward ALL attachment links from the source deadline (shared physical file, same stored_name). // Individual links can later be removed on the new deadline without deleting the file. if ($copyAttachments) { $attSel = $pdo->prepare(" SELECT original_name, stored_name, mime_type, size FROM scad_deadline_attachments WHERE deadline_id = ? "); $attSel->execute([$id]); $attRows = $attSel->fetchAll(PDO::FETCH_ASSOC); if ($attRows) { $attIns = $pdo->prepare(" INSERT INTO scad_deadline_attachments (deadline_id, original_name, stored_name, mime_type, size, uploaded_by) VALUES (?, ?, ?, ?, ?, ?) "); $attHist = $pdo->prepare("INSERT INTO scad_deadline_histories (deadline_id, user_id, action, notes) VALUES (?, ?, 'attachment_linked', ?)"); foreach ($attRows as $a) { $attIns->execute([$newId, $a['original_name'], $a['stored_name'], $a['mime_type'], $a['size'], $currentUserId]); $attHist->execute([$newId, $currentUserId, $a['original_name']]); } } } // History for new $pdo->prepare("INSERT INTO scad_deadline_histories (deadline_id, user_id, action, notes) VALUES (?, ?, 'created', ?)") ->execute([$newId, $currentUserId, 'Creata automaticamente dalla scadenza #' . $id]); } } $pdo->commit(); $msg = 'Scadenza completata con successo.'; if ($newId) { $msg .= ' Nuova scadenza creata con data ' . $newDueDate->format('d/m/Y') . '.'; } echo json_encode(['success' => true, 'message' => $msg, 'new_id' => $newId]); } catch (Exception $e) { if (isset($pdo) && $pdo->inTransaction()) { $pdo->rollBack(); } echo json_encode(['success' => false, 'message' => 'Errore: ' . $e->getMessage()]); }