Add Outlook synchronization features: implement real-time sync check, save sync preferences, and reconcile tasks with Outlook events

This commit is contained in:
2026-09-09 15:31:12 +02:00
parent 1df22d97f9
commit 7a5d14f181
4 changed files with 589 additions and 48 deletions
+108
View File
@@ -252,6 +252,114 @@ try {
exit;
}
// 6. Realtime Outlook synchronisatie & controle op gewijzigde/gewiste items
if ($action === 'check_outlook_sync') {
$rawInput = file_get_contents('php://input');
$data = !empty($rawInput) ? (json_decode($rawInput, true) ?: []) : [];
if (empty($data)) {
$data = $_GET;
}
$planDate = !empty($data['plan_date']) ? trim($data['plan_date']) : $today;
$weekStart = !empty($data['week_start']) ? trim($data['week_start']) : date('Y-m-d', strtotime('monday this week', strtotime($planDate)));
$weekEnd = !empty($data['week_end']) ? trim($data['week_end']) : date('Y-m-d', strtotime('sunday this week', strtotime($planDate)));
$lastHash = !empty($data['last_hash']) ? trim($data['last_hash']) : '';
// Controleer of Outlook gekoppeld is
$stmtInt = $db->prepare("SELECT * FROM integrations WHERE user_id = ? AND provider = 'OUTLOOK' AND is_enabled = 1");
$stmtInt->execute([$user['id']]);
$integration = $stmtInt->fetch();
if (!$integration || empty($integration['access_token']) || !empty($integration['is_demo_mode'])) {
echo json_encode([
'success' => true,
'connected' => false,
'has_changes' => false,
'last_sync' => date('H:i:s'),
]);
exit;
}
// Haal live afspraken op voor de hele week
$weekLiveEvents = microsoft_fetch_events_range($user['id'], $weekStart, $weekEnd);
// Voer reconciliatie uit met de Fociz tasks tabel
$reconcileRes = microsoft_reconcile_tasks_with_outlook($user['id'], $weekStart, $weekEnd, $weekLiveEvents);
// Haal de geactualiseerde taken voor deze dag op
$stmtPlan = $db->prepare("SELECT id FROM daily_plans WHERE user_id = ? AND plan_date = ?");
$stmtPlan->execute([$user['id'], $planDate]);
$planId = $stmtPlan->fetchColumn();
$tasks = [];
if ($planId) {
$stmtTasks = $db->prepare("
SELECT id, title, priority, time_block_start, time_block_end, duration_minutes, is_completed, status, source, external_id
FROM tasks
WHERE user_id = ? AND (daily_plan_id = ? " . ($planDate === $today ? "OR daily_plan_id IS NULL" : "") . ")
ORDER BY is_completed ASC, priority ASC, time_block_start ASC, created_at DESC
");
$stmtTasks->execute([$user['id'], $planId]);
$tasks = $stmtTasks->fetchAll();
}
// Filter events voor de geselecteerde dag die geen gesynchroniseerde Fociz taak zijn
$syncedIds = [];
foreach ($tasks as $t) {
if (!empty($t['external_id'])) {
$syncedIds[$t['external_id']] = true;
}
}
$dayEvents = [];
foreach ($weekLiveEvents as $e) {
if (($e['date'] ?? '') === $planDate) {
if (!empty($e['id']) && isset($syncedIds[$e['id']])) {
continue;
}
$dayEvents[] = [
'id' => $e['id'],
'start' => $e['start'],
'end' => $e['end'],
'subject' => $e['subject'],
];
}
}
// Bereken status hash voor de dag
$hashData = [
'events' => $dayEvents,
'tasks' => array_map(function($t) {
return [
'id' => $t['id'],
'title' => $t['title'],
'time_block_start' => $t['time_block_start'],
'time_block_end' => $t['time_block_end'],
'is_completed' => $t['is_completed'],
];
}, $tasks)
];
$currentHash = md5(json_encode($hashData));
$hasChanges = ($reconcileRes['deleted'] > 0 || $reconcileRes['updated'] > 0);
if (!empty($lastHash) && $lastHash !== $currentHash) {
$hasChanges = true;
}
echo json_encode([
'success' => true,
'connected' => true,
'has_changes' => $hasChanges,
'hash' => $currentHash,
'deleted_count' => $reconcileRes['deleted'],
'updated_count' => $reconcileRes['updated'],
'events_count' => count($dayEvents),
'tasks_count' => count($tasks),
'last_sync' => date('H:i:s'),
]);
exit;
}
echo json_encode(['error' => 'Onbekende actie']);
} catch (Exception $e) {
http_response_code(500);