Jira aanpassingen

This commit is contained in:
2026-09-14 16:24:23 +02:00
parent 7a85f612b1
commit f992ca1ec9
4 changed files with 1004 additions and 569 deletions
+368 -264
View File
@@ -226,20 +226,111 @@ function jira_get_queue_filters(bool $onlyActive = true): array {
}
/**
* Haalt de standaard wachtrijfilter voorkeur van een gebruiker op
* Haalt alle gekoppelde wachtrijfilter codes voor een gebruiker op (meervoudig)
*/
function jira_get_user_queue_preference(int $userId): ?string {
function jira_get_user_queue_preferences(int $userId): array {
try {
$db = get_db_connection();
$stmt = $db->prepare("SELECT default_jira_filter_code FROM users WHERE id = ?");
$stmt = $db->prepare("SELECT default_jira_filter_codes, default_jira_filter_code FROM users WHERE id = ?");
$stmt->execute([$userId]);
$res = $stmt->fetchColumn();
return $res ? (string)$res : null;
$row = $stmt->fetch();
if (!$row) return [];
if (!empty($row['default_jira_filter_codes'])) {
$decoded = json_decode($row['default_jira_filter_codes'], true);
if (is_array($decoded)) {
return array_values(array_filter(array_map('strtoupper', array_map('trim', $decoded))));
}
$parts = explode(',', $row['default_jira_filter_codes']);
return array_values(array_filter(array_map('strtoupper', array_map('trim', $parts))));
}
if (!empty($row['default_jira_filter_code'])) {
return [strtoupper(trim($row['default_jira_filter_code']))];
}
return [];
} catch (Throwable $e) {
return null;
return [];
}
}
/**
* Haalt de eerste standaard wachtrijfilter voorkeur van een gebruiker op (backwards compatibility)
*/
function jira_get_user_queue_preference(int $userId): ?string {
$prefs = jira_get_user_queue_preferences($userId);
return !empty($prefs) ? $prefs[0] : null;
}
/**
* Haalt alle officiële statussen op uit de Atlassian Jira Cloud instantie
*/
function jira_fetch_statuses(string $domain, string $email, string $apiToken): array {
$cleanDomain = jira_normalize_domain($domain);
if (empty($cleanDomain) || empty($email) || empty($apiToken)) {
return [];
}
$cacheKey = "jira_statuses_" . md5($cleanDomain);
$cached = fociz_cache_get($cacheKey);
if (is_array($cached) && !empty($cached)) {
return $cached;
}
$authHeader = jira_get_auth_header($email, $apiToken);
$url = $cleanDomain . '/rest/api/3/status';
$response = fociz_http_request($url, [
'method' => 'GET',
'headers' => [
'Authorization' => $authHeader,
'Accept' => 'application/json',
],
'timeout' => 10,
]);
if ($response['status'] === 404 || $response['status'] === 405) {
$urlV2 = $cleanDomain . '/rest/api/2/status';
$response = fociz_http_request($urlV2, [
'method' => 'GET',
'headers' => [
'Authorization' => $authHeader,
'Accept' => 'application/json',
],
'timeout' => 10,
]);
}
$statuses = [];
if ($response['status'] === 200 && is_array($response['json'])) {
foreach ($response['json'] as $st) {
$catKey = strtolower($st['statusCategory']['key'] ?? 'indeterminate');
$catName = $st['statusCategory']['name'] ?? 'In uitvoering';
$statuses[] = [
'id' => (string)($st['id'] ?? ''),
'name' => $st['name'] ?? '',
'description' => $st['description'] ?? '',
'status_category' => $catKey, // 'new', 'indeterminate', 'done'
'category_name' => $catName,
'color' => $st['statusCategory']['colorName'] ?? '',
];
}
// Sorteer: To Do eerst, dan In Progress, dan Done
usort($statuses, function($a, $b) {
$order = ['new' => 1, 'indeterminate' => 2, 'done' => 3];
$oa = $order[$a['status_category']] ?? 2;
$ob = $order[$b['status_category']] ?? 2;
if ($oa !== $ob) return $oa - $ob;
return strcasecmp($a['name'], $b['name']);
});
fociz_cache_set($cacheKey, $statuses, 3600);
}
return $statuses;
}
/**
* Haalt issues op via een flexibele JQL query via Atlassian REST API
*/
@@ -464,7 +555,7 @@ function jira_fetch_issues(string $domain, string $email, string $apiToken, stri
/**
* Haalt alle actieve issues op die zijn toegewezen aan de ingelogde Jira gebruiker
*/
function jira_fetch_assigned_issues(string $domain, string $email, string $apiToken, int $maxResults = 50): array {
function jira_fetch_assigned_issues(string $domain, string $email, string $apiToken, int $maxResults = 100): array {
$jql = 'assignee = currentUser() ORDER BY updated DESC';
return jira_fetch_issues($domain, $email, $apiToken, $jql, $maxResults);
}
@@ -472,7 +563,7 @@ function jira_fetch_assigned_issues(string $domain, string $email, string $apiTo
/**
* Haalt openstaande team issues op die horen bij de projecten van de gebruiker
*/
function jira_fetch_team_issues(string $domain, string $email, string $apiToken, int $maxResults = 50): array {
function jira_fetch_team_issues(string $domain, string $email, string $apiToken, int $maxResults = 100): array {
$jql = 'assignee != currentUser() AND statusCategory != Done ORDER BY updated DESC';
return jira_fetch_issues($domain, $email, $apiToken, $jql, $maxResults);
}
@@ -486,18 +577,29 @@ function jira_get_dashboard_data(int $userId, bool $forceRefresh = false): array
$stmt->execute([$userId]);
$integration = $stmt->fetch();
// Ophalen van actieve wachtrijfilters en voorkeur van gebruiker
// Ophalen van actieve wachtrijfilters en voorkeuren van gebruiker
$queueFilters = jira_get_queue_filters(true);
$userQueuePref = jira_get_user_queue_preference($userId);
$userQueuePrefs = jira_get_user_queue_preferences($userId);
// Sandbox / Demo dataset indien niet gekoppeld of expliciet in demomodus
if (!$integration || !empty($integration['is_demo_mode'])) {
$demoStatuses = [
['id' => '1', 'name' => 'To Do', 'status_category' => 'new', 'category_name' => 'Nieuw'],
['id' => '2', 'name' => 'Nieuw', 'status_category' => 'new', 'category_name' => 'Nieuw'],
['id' => '3', 'name' => 'In behandeling', 'status_category' => 'indeterminate', 'category_name' => 'In uitvoering'],
['id' => '4', 'name' => 'Wachten op klant', 'status_category' => 'indeterminate', 'category_name' => 'In uitvoering'],
['id' => '5', 'name' => 'In Review', 'status_category' => 'indeterminate', 'category_name' => 'In uitvoering'],
['id' => '6', 'name' => 'Gereed', 'status_category' => 'done', 'category_name' => 'Gereed'],
['id' => '7', 'name' => 'Gesloten', 'status_category' => 'done', 'category_name' => 'Gereed'],
];
$assigned = [
[
'key' => 'SD-401',
'summary' => 'AFAS Profit SSO-koppeling geeft 401 fout bij token refresh',
'description' => "Gebruikers die via AFAS SSO inloggen krijgen periodiek een HTTP 401 foutcode bij de geautomatiseerde token verversing.\n\nHet endpoint `/oauth/token` reageert met `invalid_grant` zodra de refresh token ouder is dan 24 uur. Er dient een retry-mechanisme met fallback authenticatie ingebouwd te worden.",
'status' => 'In Progress',
'description' => "Gebruikers die via AFAS SSO inloggen krijgen periodiek een HTTP 401 foutcode bij de geautomatiseerde token verversing.\n\nHet endpoint `/oauth/token` reageert met `invalid_grant` zodra de refresh token ouder is dan 24 uur.",
'status' => 'In behandeling',
'status_category' => 'indeterminate',
'priority' => 'Highest',
'issue_type' => 'Bug',
@@ -512,12 +614,13 @@ function jira_get_dashboard_data(int $userId, bool $forceRefresh = false): array
'created' => date('Y-m-d H:i:s', strtotime('-1 day')),
'updated' => date('Y-m-d H:i:s', strtotime('-45 minutes')),
'url' => 'https://jira.atlassian.net/browse/SD-401',
'story_points' => 3,
'source' => 'SANDBOX',
],
[
'key' => 'SD-405',
'summary' => 'REST-endpoints voor medewerker synchronisatie beveiligen met rate limiting',
'description' => "De openbare REST-endpoints voor medewerkerssynchronisatie dienen conform security richtlijnen te worden voorzien van rate limiting (max 120 calls per minuut per IP).\n\nBij overschrijding moet een duidelijke HTTP 429 Retry-After header worden geretourneerd.",
'description' => "De openbare REST-endpoints voor medewerkerssynchronisatie dienen conform security richtlijnen te worden voorzien van rate limiting.",
'status' => 'To Do',
'status_category' => 'new',
'priority' => 'High',
@@ -533,14 +636,147 @@ function jira_get_dashboard_data(int $userId, bool $forceRefresh = false): array
'created' => date('Y-m-d H:i:s', strtotime('-2 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-2 hours')),
'url' => 'https://jira.atlassian.net/browse/SD-405',
'story_points' => 5,
'source' => 'SANDBOX',
],
[
'key' => 'IN-201',
'summary' => 'Exact Online REST API webhook connectie configureren',
'description' => "Configuratie van de webhook triggers voor realtime debiteuren synchronisatie tussen Fociz en Exact Online.",
'status' => 'In behandeling',
'status_category' => 'indeterminate',
'priority' => 'High',
'issue_type' => 'Story',
'project' => 'Interfaces',
'project_key' => 'IN',
'assignee_name' => 'Mijzelf',
'assignee_avatar' => '',
'reporter_name' => 'Financieel Beheer',
'reporter_avatar' => '',
'onderwerp_logging' => 'Koppelingen',
'due_date' => date('Y-m-d', strtotime('+2 days')),
'created' => date('Y-m-d H:i:s', strtotime('-3 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-30 minutes')),
'url' => 'https://jira.atlassian.net/browse/IN-201',
'story_points' => 8,
'source' => 'SANDBOX',
],
[
'key' => 'IN-205',
'summary' => 'OAuth 2.0 PKCE handshake voor mobiele koppeling afronden',
'description' => "Migreer de verouderde implicit flow naar de PKCE authorisatie flow voor alle mobiele apparaten.",
'status' => 'To Do',
'status_category' => 'new',
'priority' => 'Medium',
'issue_type' => 'Task',
'project' => 'Interfaces',
'project_key' => 'IN',
'assignee_name' => 'Mijzelf',
'assignee_avatar' => '',
'reporter_name' => 'Tech Lead',
'reporter_avatar' => '',
'onderwerp_logging' => 'SSO-koppeling',
'due_date' => date('Y-m-d', strtotime('+4 days')),
'created' => date('Y-m-d H:i:s', strtotime('-4 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-1 day')),
'url' => 'https://jira.atlassian.net/browse/IN-205',
'story_points' => 5,
'source' => 'SANDBOX',
],
[
'key' => 'AAN-102',
'summary' => 'Aanvraag nieuwe laptop en ergonomische thuiswerkplek beeldschermen',
'description' => "Nieuwe onboarding developer heeft MacBook Pro 16 inch en 2x 4K schermen nodig conform standaardpakket.",
'status' => 'Wachten op klant',
'status_category' => 'indeterminate',
'priority' => 'Medium',
'issue_type' => 'Task',
'project' => 'Aanvragen',
'project_key' => 'AAN',
'assignee_name' => 'Mijzelf',
'assignee_avatar' => '',
'reporter_name' => 'HR Onboarding',
'reporter_avatar' => '',
'onderwerp_logging' => 'Hardware',
'due_date' => date('Y-m-d', strtotime('+5 days')),
'created' => date('Y-m-d H:i:s', strtotime('-2 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-3 hours')),
'url' => 'https://jira.atlassian.net/browse/AAN-102',
'story_points' => 2,
'source' => 'SANDBOX',
],
[
'key' => 'AAN-108',
'summary' => 'Autorisatieverzoek rechten AFAS financieel beheer teamleider',
'description' => "Goedkeuring benodigd voor toekennen van geautoriseerde rollen in AFAS Profit.",
'status' => 'In behandeling',
'status_category' => 'indeterminate',
'priority' => 'High',
'issue_type' => 'Task',
'project' => 'Aanvragen',
'project_key' => 'AAN',
'assignee_name' => 'Mijzelf',
'assignee_avatar' => '',
'reporter_name' => 'Teamleider Financiën',
'reporter_avatar' => '',
'onderwerp_logging' => 'Rechten',
'due_date' => date('Y-m-d'),
'created' => date('Y-m-d H:i:s', strtotime('-1 day')),
'updated' => date('Y-m-d H:i:s', strtotime('-1 hour')),
'url' => 'https://jira.atlassian.net/browse/AAN-108',
'story_points' => 1,
'source' => 'SANDBOX',
],
[
'key' => 'GEN-301',
'summary' => 'Jaarlijkse ISO-27001 interne security review voorbereiden',
'description' => "Samenstellen van security checklists, access reviews en back-up logs voor auditcommissie.",
'status' => 'In behandeling',
'status_category' => 'indeterminate',
'priority' => 'High',
'issue_type' => 'Task',
'project' => 'General',
'project_key' => 'GEN',
'assignee_name' => 'Mijzelf',
'assignee_avatar' => '',
'reporter_name' => 'CISO',
'reporter_avatar' => '',
'onderwerp_logging' => 'Beveiliging',
'due_date' => date('Y-m-d', strtotime('+6 days')),
'created' => date('Y-m-d H:i:s', strtotime('-5 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-4 hours')),
'url' => 'https://jira.atlassian.net/browse/GEN-301',
'story_points' => 13,
'source' => 'SANDBOX',
],
[
'key' => 'GEN-305',
'summary' => 'Kantoorruimte vergadertafel opstelling aanpassen voor hybride team',
'description' => "Herinrichting van de videovergaderruimte met Yealink meetingbar.",
'status' => 'Gesloten',
'status_category' => 'done',
'priority' => 'Low',
'issue_type' => 'Task',
'project' => 'General',
'project_key' => 'GEN',
'assignee_name' => 'Mijzelf',
'assignee_avatar' => '',
'reporter_name' => 'Facility Management',
'reporter_avatar' => '',
'onderwerp_logging' => 'Facilitair',
'due_date' => date('Y-m-d', strtotime('-2 days')),
'created' => date('Y-m-d H:i:s', strtotime('-8 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-1 day')),
'url' => 'https://jira.atlassian.net/browse/GEN-305',
'story_points' => 1,
'source' => 'SANDBOX',
],
[
'key' => 'SD-380',
'summary' => 'Wachtwoord reset e-mail komt niet aan bij nieuwe medewerker',
'description' => "Een nieuwe medewerker ontvangt geen welkomstmail en wachtwoord reset via het selfservice portaal.\n\nControleer de SMTP-verbinding van de mailserver mail.fociz.nl en controleer of het mailadres in de spamfilter is beland.",
'status' => 'In Progress',
'status_category' => 'indeterminate',
'description' => "Controleer de SMTP-verbinding van de mailserver mail.fociz.nl en controleer of het mailadres in de spamfilter is beland.",
'status' => 'Gesloten',
'status_category' => 'done',
'priority' => 'High',
'issue_type' => 'Task',
'project' => 'Servicedesk',
@@ -550,136 +786,11 @@ function jira_get_dashboard_data(int $userId, bool $forceRefresh = false): array
'reporter_name' => 'HR Servicedesk',
'reporter_avatar' => '',
'onderwerp_logging' => 'EMPTY',
'due_date' => date('Y-m-d'),
'created' => date('Y-m-d H:i:s', strtotime('-3 hours')),
'updated' => date('Y-m-d H:i:s', strtotime('-1 hour')),
'url' => 'https://jira.atlassian.net/browse/SD-380',
'source' => 'SANDBOX',
],
[
'key' => 'SD-385',
'summary' => 'Rechten aanpassen voor rol Projectleider in urenregistratie',
'description' => "Projectleiders hebben momenteel alleen leesrechten op ingediende urenstaten. Graag de rol uitbreiden zodat zij declaraties direct kunnen goedkeuren of afkeuren.",
'status' => 'To Do',
'status_category' => 'new',
'priority' => 'Medium',
'issue_type' => 'Task',
'project' => 'Servicedesk',
'project_key' => 'SD',
'assignee_name' => 'Mijzelf',
'assignee_avatar' => '',
'reporter_name' => 'Marianne Willems',
'reporter_avatar' => '',
'onderwerp_logging' => 'Algemeen',
'due_date' => date('Y-m-d', strtotime('+5 days')),
'created' => date('Y-m-d H:i:s', strtotime('-3 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-1 day')),
'url' => 'https://jira.atlassian.net/browse/SD-385',
'source' => 'SANDBOX',
],
[
'key' => 'FOC-101',
'summary' => 'Tweestapsverificatie (2FA TOTP) flow implementeren',
'description' => "Ontwikkeling van een complete Google Authenticator / Microsoft Authenticator TOTP verificatie flow inclusief 8 cijferige noodcodes en QR-code weergave in het gebruikersprofiel.",
'status' => 'In Progress',
'status_category' => 'indeterminate',
'priority' => 'High',
'issue_type' => 'Story',
'project' => 'Fociz Platform',
'project_key' => 'FOC',
'assignee_name' => 'Mijzelf',
'assignee_avatar' => '',
'reporter_name' => 'Product Owner',
'reporter_avatar' => '',
'onderwerp_logging' => 'Beveiliging',
'due_date' => date('Y-m-d', strtotime('+2 days')),
'created' => date('Y-m-d H:i:s', strtotime('-4 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-2 hours')),
'url' => 'https://jira.atlassian.net/browse/FOC-101',
'source' => 'SANDBOX',
],
[
'key' => 'FOC-102',
'summary' => 'Interactief whiteboard canvas voor brainstormsessies',
'description' => "Gebruikers moeten live post-its kunnen slepen, kleuren en stemmen tijdens kwartaal brainstormsessies.",
'status' => 'To Do',
'status_category' => 'new',
'priority' => 'High',
'issue_type' => 'Feature',
'project' => 'Fociz Platform',
'project_key' => 'FOC',
'assignee_name' => 'Mijzelf',
'assignee_avatar' => '',
'reporter_name' => 'Scrum Master',
'reporter_avatar' => '',
'onderwerp_logging' => '',
'due_date' => date('Y-m-d', strtotime('+4 days')),
'created' => date('Y-m-d H:i:s', strtotime('-5 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-1 day')),
'url' => 'https://jira.atlassian.net/browse/FOC-102',
'source' => 'SANDBOX',
],
[
'key' => 'FOC-103',
'summary' => 'Koppeling met Microsoft Outlook Calendar & Teams Graph API',
'description' => "Synchronisatie van dagplanning blokken naar Microsoft 365 Exchange Online agenda met real-time conflictcontrole.",
'status' => 'In Review',
'status_category' => 'indeterminate',
'priority' => 'Medium',
'issue_type' => 'Task',
'project' => 'Integrations Hub',
'project_key' => 'INT',
'assignee_name' => 'Mijzelf',
'assignee_avatar' => '',
'reporter_name' => 'Architect',
'reporter_avatar' => '',
'onderwerp_logging' => 'SSO-koppeling',
'due_date' => date('Y-m-d'),
'created' => date('Y-m-d H:i:s', strtotime('-6 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-4 hours')),
'url' => 'https://jira.atlassian.net/browse/FOC-103',
'source' => 'SANDBOX',
],
[
'key' => 'FOC-108',
'summary' => 'CSS scrollbar glitch oplossen in Kanban lane op Firefox',
'description' => "Op Windows Firefox versies 128+ verspringt de horizontale scrollbalk bij het slepen van kaarten tussen kolommen.",
'status' => 'In Progress',
'status_category' => 'indeterminate',
'priority' => 'Highest',
'issue_type' => 'Bug',
'project' => 'UI/UX Redesign',
'project_key' => 'UI',
'assignee_name' => 'Mijzelf',
'assignee_avatar' => '',
'reporter_name' => 'QA Lead',
'reporter_avatar' => '',
'onderwerp_logging' => '',
'due_date' => date('Y-m-d', strtotime('+1 day')),
'created' => date('Y-m-d H:i:s', strtotime('-2 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-30 minutes')),
'url' => 'https://jira.atlassian.net/browse/FOC-108',
'source' => 'SANDBOX',
],
[
'key' => 'FOC-112',
'summary' => 'Avatar upload beveiliging en compressie optimalisatie',
'description' => "Server-side image re-encoding en EXIF stripping voor geüploade gebruikersavatars.",
'status' => 'Done',
'status_category' => 'done',
'priority' => 'Medium',
'issue_type' => 'Task',
'project' => 'Security',
'project_key' => 'SEC',
'assignee_name' => 'Mijzelf',
'assignee_avatar' => '',
'reporter_name' => 'SecOps',
'reporter_avatar' => '',
'onderwerp_logging' => '',
'due_date' => date('Y-m-d', strtotime('-1 day')),
'created' => date('Y-m-d H:i:s', strtotime('-7 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-5 hours')),
'url' => 'https://jira.atlassian.net/browse/FOC-112',
'created' => date('Y-m-d H:i:s', strtotime('-3 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-6 hours')),
'url' => 'https://jira.atlassian.net/browse/SD-380',
'story_points' => 2,
'source' => 'SANDBOX',
],
];
@@ -688,8 +799,8 @@ function jira_get_dashboard_data(int $userId, bool $forceRefresh = false): array
[
'key' => 'SD-408',
'summary' => 'UWV-koppeling polisadministratie import loopt vast op datumformaat',
'description' => "De XML batch import vanuit het UWV portaal faalt op records met afwijkende geboortedatumnotatie.\n\nDe parser dient flexibel zowel ISO-8601 (YYYY-MM-DD) als traditioneel formaat (DD-MM-YYYY) te accepteren.",
'status' => 'In Progress',
'description' => "De XML batch import vanuit het UWV portaal faalt op records met afwijkende geboortedatumnotatie.",
'status' => 'In behandeling',
'status_category' => 'indeterminate',
'priority' => 'High',
'issue_type' => 'Bug',
@@ -704,6 +815,7 @@ function jira_get_dashboard_data(int $userId, bool $forceRefresh = false): array
'created' => date('Y-m-d H:i:s', strtotime('-2 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-1 hour')),
'url' => 'https://jira.atlassian.net/browse/SD-408',
'story_points' => 5,
'source' => 'SANDBOX',
],
[
@@ -725,39 +837,19 @@ function jira_get_dashboard_data(int $userId, bool $forceRefresh = false): array
'created' => date('Y-m-d H:i:s', strtotime('-3 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-4 hours')),
'url' => 'https://jira.atlassian.net/browse/SD-412',
'story_points' => 3,
'source' => 'SANDBOX',
],
[
'key' => 'SD-416',
'summary' => 'Migratie van oude klantportaal database naar MariaDB 11 cluster',
'description' => "Voorbereiden en uitvoeren van de dataschemamigratie van het oude portaal naar de nieuwe MariaDB 11 clusteromgeving inclusief regressietests.",
'status' => 'To Do',
'status_category' => 'new',
'priority' => 'High',
'issue_type' => 'Story',
'project' => 'Servicedesk',
'project_key' => 'SD',
'assignee_name' => 'Bram Meijer',
'assignee_avatar' => '',
'reporter_name' => 'Lead Engineer',
'reporter_avatar' => '',
'onderwerp_logging' => 'Migratie',
'due_date' => date('Y-m-d', strtotime('+8 days')),
'created' => date('Y-m-d H:i:s', strtotime('-4 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-6 hours')),
'url' => 'https://jira.atlassian.net/browse/SD-416',
'source' => 'SANDBOX',
],
[
'key' => 'SD-420',
'key' => 'IN-210',
'summary' => 'Koppelingen API webhook notificaties afleveren met retry-mechanisme',
'description' => "Webhooks die naar externe partnersystemen worden verzonden moeten bij een tijdelijke 5xx fout automatisch 3x opnieuw worden aangeboden (exponential backoff).",
'status' => 'In Review',
'description' => "Webhooks die naar externe partnersystemen worden verzonden moeten bij een tijdelijke 5xx fout automatisch 3x opnieuw worden aangeboden.",
'status' => 'In behandeling',
'status_category' => 'indeterminate',
'priority' => 'Medium',
'issue_type' => 'Task',
'project' => 'Servicedesk',
'project_key' => 'SD',
'project' => 'Interfaces',
'project_key' => 'IN',
'assignee_name' => 'Sophie de Vries',
'assignee_avatar' => '',
'reporter_name' => 'Integratie Specialist',
@@ -766,112 +858,118 @@ function jira_get_dashboard_data(int $userId, bool $forceRefresh = false): array
'due_date' => date('Y-m-d', strtotime('+4 days')),
'created' => date('Y-m-d H:i:s', strtotime('-5 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-3 hours')),
'url' => 'https://jira.atlassian.net/browse/SD-420',
'url' => 'https://jira.atlassian.net/browse/IN-210',
'story_points' => 5,
'source' => 'SANDBOX',
],
[
'key' => 'SD-392',
'summary' => 'Outlook Agenda synchronisatie toont dubbele afspraken op mobiel',
'description' => "Bij enkele gebruikers met de iOS Outlook app worden terugkerende agenda-afspraken tweemaal weergegeven na het synchroniseren.",
'status' => 'In Progress',
'key' => 'IN-215',
'summary' => 'Specificatie documentatie voor externe partner API opvragen',
'description' => "Opvragen van de actuele OpenAPI v3 JSON specificatie bij leverancier.",
'status' => 'Wachten op klant',
'status_category' => 'indeterminate',
'priority' => 'Medium',
'issue_type' => 'Bug',
'project' => 'Servicedesk',
'project_key' => 'SD',
'assignee_name' => 'Lisa Bakker',
'assignee_avatar' => '',
'reporter_name' => 'Servicedesk Support',
'reporter_avatar' => '',
'onderwerp_logging' => 'Incident',
'due_date' => date('Y-m-d', strtotime('+3 days')),
'created' => date('Y-m-d H:i:s', strtotime('-3 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-2 hours')),
'url' => 'https://jira.atlassian.net/browse/SD-392',
'source' => 'SANDBOX',
],
[
'key' => 'SD-399',
'summary' => 'Vraag over exportmogelijkheden naar Excel rapportage',
'description' => "Klant informeert of het mogelijk is om een wekelijkse CSV / Excel export van de urenstaten automatisch per mail te ontvangen.",
'status' => 'To Do',
'status_category' => 'new',
'priority' => 'Low',
'issue_type' => 'Task',
'project' => 'Servicedesk',
'project_key' => 'SD',
'project' => 'Interfaces',
'project_key' => 'IN',
'assignee_name' => 'Sophie de Vries',
'assignee_avatar' => '',
'reporter_name' => 'Partner Manager',
'reporter_avatar' => '',
'onderwerp_logging' => 'Koppelingen',
'due_date' => date('Y-m-d', strtotime('+7 days')),
'created' => date('Y-m-d H:i:s', strtotime('-4 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-2 hours')),
'url' => 'https://jira.atlassian.net/browse/IN-215',
'story_points' => 1,
'source' => 'SANDBOX',
],
[
'key' => 'AAN-110',
'summary' => 'Aanvraag extra Microsoft 365 E5 licenties voor marketing team',
'description' => "Bestelling en activering van 5 aanvullende E5 licenties voor het datateam.",
'status' => 'To Do',
'status_category' => 'new',
'priority' => 'Medium',
'issue_type' => 'Task',
'project' => 'Aanvragen',
'project_key' => 'AAN',
'assignee_name' => 'Thomas Jansen',
'assignee_avatar' => '',
'reporter_name' => 'Financieel Directeur',
'reporter_name' => 'Marketing Director',
'reporter_avatar' => '',
'onderwerp_logging' => 'Vraag',
'due_date' => date('Y-m-d', strtotime('+10 days')),
'created' => date('Y-m-d H:i:s', strtotime('-5 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-1 day')),
'url' => 'https://jira.atlassian.net/browse/SD-399',
'source' => 'SANDBOX',
],
[
'key' => 'FOC-95',
'summary' => 'Sessie timeout notificatie verschijnt niet tijdig bij inactieve tab',
'description' => "Wanneer een gebruiker de browser 2 uur niet aanraakt, vervalt de PHP sessie zonder dat het login-dialoogvenster netjes openspringt.",
'status' => 'In Progress',
'status_category' => 'indeterminate',
'priority' => 'Highest',
'issue_type' => 'Bug',
'project' => 'Fociz Platform',
'project_key' => 'FOC',
'assignee_name' => 'Lisa Bakker',
'assignee_avatar' => '',
'reporter_name' => 'Product QA',
'reporter_avatar' => '',
'onderwerp_logging' => '',
'due_date' => date('Y-m-d', strtotime('+1 day')),
'created' => date('Y-m-d H:i:s', strtotime('-2 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-1 hour')),
'url' => 'https://jira.atlassian.net/browse/FOC-95',
'source' => 'SANDBOX',
],
[
'key' => 'FOC-98',
'summary' => 'Automatische e-mail triggers voor taakdeadlines en uitnodigingen',
'description' => "Cronjob instellen die 24 uur voor de deadline van een taak een herinneringsmail stuurt via SMTP.",
'status' => 'To Do',
'status_category' => 'new',
'priority' => 'High',
'issue_type' => 'Story',
'project' => 'Notifications',
'project_key' => 'NOTIF',
'assignee_name' => 'Daan van Dijk',
'assignee_avatar' => '',
'reporter_name' => 'Operations',
'reporter_avatar' => '',
'onderwerp_logging' => '',
'onderwerp_logging' => 'Licenties',
'due_date' => date('Y-m-d', strtotime('+3 days')),
'created' => date('Y-m-d H:i:s', strtotime('-3 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-2 days')),
'url' => 'https://jira.atlassian.net/browse/FOC-98',
'created' => date('Y-m-d H:i:s', strtotime('-2 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-1 day')),
'url' => 'https://jira.atlassian.net/browse/AAN-110',
'story_points' => 2,
'source' => 'SANDBOX',
],
[
'key' => 'FOC-110',
'summary' => 'Real-time websocket synchronisatie voor gelijktijdig bewerken van borden',
'description' => "Voorkom overschrijfconflicten wanneer meerdere collega's gelijktijdig kaarten verplaatsen op hetzelfde Kanban bord.",
'status' => 'To Do',
'status_category' => 'new',
'key' => 'AAN-115',
'summary' => 'Aanvraag tijdelijke VPN toegang externe auditor KPMG',
'description' => "Toegang configureren met verloopdatum 30 september en MFA verplichting.",
'status' => 'Gesloten',
'status_category' => 'done',
'priority' => 'High',
'issue_type' => 'Story',
'project' => 'Realtime Engine',
'project_key' => 'RT',
'issue_type' => 'Task',
'project' => 'Aanvragen',
'project_key' => 'AAN',
'assignee_name' => 'Bram Meijer',
'assignee_avatar' => '',
'reporter_name' => 'Architect',
'reporter_name' => 'Security Officer',
'reporter_avatar' => '',
'onderwerp_logging' => '',
'due_date' => date('Y-m-d', strtotime('+6 days')),
'onderwerp_logging' => 'Rechten',
'due_date' => date('Y-m-d', strtotime('-3 days')),
'created' => date('Y-m-d H:i:s', strtotime('-7 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-2 days')),
'url' => 'https://jira.atlassian.net/browse/AAN-115',
'story_points' => 2,
'source' => 'SANDBOX',
],
[
'key' => 'GEN-310',
'summary' => 'Organisatiebeleid hybride werken 2026 actualiseren',
'description' => "Aanpassing van reiskostenvergoeding en thuiswerkvergoeding conform nieuwe cao-afspraken.",
'status' => 'In behandeling',
'status_category' => 'indeterminate',
'priority' => 'Medium',
'issue_type' => 'Story',
'project' => 'General',
'project_key' => 'GEN',
'assignee_name' => 'Lisa Bakker',
'assignee_avatar' => '',
'reporter_name' => 'Directie',
'reporter_avatar' => '',
'onderwerp_logging' => 'Algemeen',
'due_date' => date('Y-m-d', strtotime('+10 days')),
'created' => date('Y-m-d H:i:s', strtotime('-6 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-1 day')),
'url' => 'https://jira.atlassian.net/browse/GEN-310',
'story_points' => 5,
'source' => 'SANDBOX',
],
[
'key' => 'GEN-315',
'summary' => 'Kwartaalplanning en doelstellingen inventarisatie Q4',
'description' => "Verzamel OKR's van alle teams voor de centrale kwartaalpresentatie.",
'status' => 'To Do',
'status_category' => 'new',
'priority' => 'High',
'issue_type' => 'Story',
'project' => 'General',
'project_key' => 'GEN',
'assignee_name' => 'Bram Meijer',
'assignee_avatar' => '',
'reporter_name' => 'Operations Lead',
'reporter_avatar' => '',
'onderwerp_logging' => 'Algemeen',
'due_date' => date('Y-m-d', strtotime('+8 days')),
'created' => date('Y-m-d H:i:s', strtotime('-4 days')),
'updated' => date('Y-m-d H:i:s', strtotime('-6 hours')),
'url' => 'https://jira.atlassian.net/browse/FOC-110',
'updated' => date('Y-m-d H:i:s', strtotime('-5 hours')),
'url' => 'https://jira.atlassian.net/browse/GEN-315',
'story_points' => 8,
'source' => 'SANDBOX',
],
];
@@ -887,6 +985,8 @@ function jira_get_dashboard_data(int $userId, bool $forceRefresh = false): array
'team_issues' => $team,
'queue_filters' => $queueFilters,
'default_queue_filter' => $userQueuePref,
'user_queue_filters' => $userQueuePrefs,
'available_statuses' => $demoStatuses,
];
}
@@ -921,10 +1021,12 @@ function jira_get_dashboard_data(int $userId, bool $forceRefresh = false): array
}
}
// Ophalen van toegewezen taken
$assignedRes = jira_fetch_assigned_issues($domain, $email, $apiToken, 50);
// Ophalen van teamtaken
$teamRes = jira_fetch_team_issues($domain, $email, $apiToken, 50);
// Ophalen van toegewezen taken (max 100)
$assignedRes = jira_fetch_assigned_issues($domain, $email, $apiToken, 100);
// Ophalen van teamtaken (max 100)
$teamRes = jira_fetch_team_issues($domain, $email, $apiToken, 100);
// Ophalen van Jira statussen
$availableStatuses = jira_fetch_statuses($domain, $email, $apiToken);
if (!$assignedRes['success'] && !$teamRes['success']) {
return [
@@ -950,6 +1052,8 @@ function jira_get_dashboard_data(int $userId, bool $forceRefresh = false): array
'team_issues' => $teamIssues,
'queue_filters' => $queueFilters,
'default_queue_filter' => $userQueuePref,
'user_queue_filters' => $userQueuePrefs,
'available_statuses' => $availableStatuses,
];
fociz_cache_set($cacheKey, $data, 60);