From b3d8b7e067ccda9ea4fd614f89d2e86e81851201 Mon Sep 17 00:00:00 2001 From: Jukka Lampikoski Date: Fri, 13 Mar 2026 19:35:45 +0200 Subject: [PATCH] Simplify timer: checkbox + delay days, execute at 10:00 Timer is now a simple checkbox + days field. When enabled, rule actions are scheduled for X days after ticket creation at 10:00 AM instead of applying immediately. Removed no_activity condition in favor of simple time-based scheduling stored on the ticket (delay_rule_id + delay_execute_at). Co-Authored-By: Claude Opus 4.6 --- api.php | 99 ++++++++++++++++++++++-------------------------------- index.html | 21 ++++++------ script.js | 19 ++++++----- 3 files changed, 61 insertions(+), 78 deletions(-) diff --git a/api.php b/api.php index 1937dc6..c90934d 100644 --- a/api.php +++ b/api.php @@ -3242,61 +3242,34 @@ switch ($action) { } unset($tc); - // Ajastinsääntöjen tarkistus (delay_days + no_activity) - $timedRules = array_filter(dbLoadTicketRules($comp['id']), function($r) { - return $r['enabled'] && $r['delay_days'] > 0 && $r['delay_condition'] === 'no_activity'; - }); - if (!empty($timedRules)) { - foreach ($tickets as &$tc) { - if (in_array($tc['status'], ['suljettu', 'ratkaistu'])) continue; - $lastActivity = $tc['updated'] ?? $tc['created']; - $inactiveDays = (strtotime($now) - strtotime($lastActivity)) / 86400; - foreach ($timedRules as $rule) { - if ($inactiveDays < $rule['delay_days']) continue; - // Tarkista ehdot (from/to/subject) - $match = true; - if (!empty($rule['from_contains'])) { - if (stripos(($tc['from_email'] ?? '') . ' ' . ($tc['from_name'] ?? ''), $rule['from_contains']) === false) $match = false; - } - if (!empty($rule['subject_contains'])) { - if (stripos($tc['subject'] ?? '', $rule['subject_contains']) === false) $match = false; - } - if (!empty($rule['to_contains'])) { - if (stripos($tc['to_email'] ?? '', $rule['to_contains']) === false) $match = false; - } - if (!$match) continue; - // Sovella toimenpiteet - $changed = false; - if (!empty($rule['set_priority']) && ($tc['priority'] ?? '') !== $rule['set_priority']) { - $tc['priority'] = $rule['set_priority']; - $changed = true; - } - if (!empty($rule['status_set']) && ($tc['status'] ?? '') !== $rule['status_set']) { - $tc['status'] = $rule['status_set']; - $changed = true; - } - if (!empty($rule['type_set']) && ($tc['type'] ?? '') !== $rule['type_set']) { - $tc['type'] = $rule['type_set']; - $changed = true; - } - if (!empty($rule['set_tags'])) { - $ruleTags = array_map('trim', explode(',', $rule['set_tags'])); - $existingTags = $tc['tags'] ?? []; - $merged = array_values(array_unique(array_merge($existingTags, $ruleTags))); - if ($merged !== $existingTags) { - $tc['tags'] = $merged; - $changed = true; - } - } - if ($changed) { - $tc['updated'] = $now; - dbSaveTicket($comp['id'], $tc); - } - break; // Vain yksi ajastinsääntö per tiketti + // Ajastettujen sääntöjen suoritus (delay_execute_at saavutettu) + foreach ($tickets as &$tc) { + if (empty($tc['delay_rule_id']) || empty($tc['delay_execute_at'])) continue; + if ($tc['delay_execute_at'] > $now) continue; + if (in_array($tc['status'], ['suljettu', 'ratkaistu'])) { + // Suljettu/ratkaistu ennen ajastinta → peruuta + unset($tc['delay_rule_id'], $tc['delay_execute_at']); + dbSaveTicket($comp['id'], $tc); + continue; + } + // Hae sääntö ja suorita toimenpiteet + $allRules = dbLoadTicketRules($comp['id']); + $rule = null; + foreach ($allRules as $r) { if ($r['id'] === $tc['delay_rule_id']) { $rule = $r; break; } } + if ($rule) { + if (!empty($rule['status_set'])) $tc['status'] = $rule['status_set']; + if (!empty($rule['type_set'])) $tc['type'] = $rule['type_set']; + if (!empty($rule['set_priority'])) $tc['priority'] = $rule['set_priority']; + if (!empty($rule['set_tags'])) { + $ruleTags = array_map('trim', explode(',', $rule['set_tags'])); + $tc['tags'] = array_values(array_unique(array_merge($tc['tags'] ?? [], $ruleTags))); } } - unset($tc); + unset($tc['delay_rule_id'], $tc['delay_execute_at']); + $tc['updated'] = $now; + dbSaveTicket($comp['id'], $tc); } + unset($tc); // Resolve mailbox names for this company $mailboxes = dbLoadMailboxes($comp['id']); @@ -3571,12 +3544,21 @@ switch ($action) { } } if ($match) { - if (!empty($rule['status_set'])) $ticket['status'] = $rule['status_set']; - if (!empty($rule['type_set'])) $ticket['type'] = $rule['type_set']; - if (!empty($rule['set_priority'])) $ticket['priority'] = $rule['set_priority']; - if (!empty($rule['set_tags'])) { - $ruleTags = array_map('trim', explode(',', $rule['set_tags'])); - $ticket['tags'] = array_values(array_unique(array_merge($ticket['tags'], $ruleTags))); + $delayDays = intval($rule['delay_days'] ?? 0); + if ($delayDays > 0) { + // Ajastettu sääntö: älä suorita heti, tallenna ajastus tikettiin + $executeAt = date('Y-m-d', strtotime("+{$delayDays} days")) . ' 10:00:00'; + $ticket['delay_rule_id'] = $rule['id']; + $ticket['delay_execute_at'] = $executeAt; + } else { + // Välitön sääntö: suorita heti + if (!empty($rule['status_set'])) $ticket['status'] = $rule['status_set']; + if (!empty($rule['type_set'])) $ticket['type'] = $rule['type_set']; + if (!empty($rule['set_priority'])) $ticket['priority'] = $rule['set_priority']; + if (!empty($rule['set_tags'])) { + $ruleTags = array_map('trim', explode(',', $rule['set_tags'])); + $ticket['tags'] = array_values(array_unique(array_merge($ticket['tags'], $ruleTags))); + } } if (!empty($rule['auto_close_days'])) { $days = intval($rule['auto_close_days']); @@ -4024,7 +4006,6 @@ switch ($action) { 'set_tags' => trim($input['set_tags'] ?? ''), 'auto_close_days' => intval($input['auto_close_days'] ?? 0), 'delay_days' => intval($input['delay_days'] ?? 0), - 'delay_condition' => trim($input['delay_condition'] ?? ''), 'enabled' => $input['enabled'] ?? true, ]; diff --git a/index.html b/index.html index e1930cb..09ae15e 100644 --- a/index.html +++ b/index.html @@ -1293,18 +1293,17 @@
- + +

Kun ajastin on päällä, toimenpiteet suoritetaan vasta X päivän päästä klo 10:00

-
- - -
-
- - +
+ +
+ + päivää +
diff --git a/script.js b/script.js index 8c94ba8..6973bdf 100644 --- a/script.js +++ b/script.js @@ -2342,10 +2342,7 @@ function renderRules() { if (r.set_priority) actions.push('Prioriteetti → ' + (priorityLabels[r.set_priority] || r.set_priority)); if (r.set_tags) actions.push('Tagit: #' + r.set_tags.split(',').map(t => t.trim()).join(' #')); if (r.auto_close_days) actions.push('Auto-close: ' + r.auto_close_days + 'pv'); - if (r.delay_days && r.delay_condition) { - const condLabel = r.delay_condition === 'no_activity' ? 'ei aktiviteettia' : r.delay_condition; - actions.push('⏱ Ajastin: ' + r.delay_days + 'pv (' + condLabel + ')'); - } + if (r.delay_days > 0) actions.push('⏱ Ajastin: ' + r.delay_days + 'pv (klo 10:00)'); return `
${esc(r.name)}
@@ -2377,8 +2374,10 @@ function showRuleForm(rule) { document.getElementById('rule-form-priority').value = rule ? (rule.set_priority || '') : ''; document.getElementById('rule-form-tags').value = rule ? (rule.set_tags || '') : ''; document.getElementById('rule-form-autoclose').value = rule ? (rule.auto_close_days || '') : ''; - document.getElementById('rule-form-delay-days').value = rule ? (rule.delay_days || '') : ''; - document.getElementById('rule-form-delay-condition').value = rule ? (rule.delay_condition || '') : ''; + const hasDelay = rule && rule.delay_days > 0; + document.getElementById('rule-form-delay-enabled').checked = hasDelay; + document.getElementById('rule-form-delay-days').value = hasDelay ? rule.delay_days : ''; + document.getElementById('rule-form-delay-days').disabled = !hasDelay; editingRuleId = rule ? rule.id : null; } @@ -2389,6 +2388,11 @@ function hideRuleForm() { document.getElementById('btn-add-rule').addEventListener('click', () => showRuleForm(null)); document.getElementById('btn-cancel-rule').addEventListener('click', () => hideRuleForm()); +document.getElementById('rule-form-delay-enabled').addEventListener('change', function() { + const daysInput = document.getElementById('rule-form-delay-days'); + daysInput.disabled = !this.checked; + if (!this.checked) daysInput.value = ''; +}); document.getElementById('btn-save-rule').addEventListener('click', async () => { const name = document.getElementById('rule-form-name').value.trim(); @@ -2403,8 +2407,7 @@ document.getElementById('btn-save-rule').addEventListener('click', async () => { set_priority: document.getElementById('rule-form-priority').value, set_tags: document.getElementById('rule-form-tags').value.trim(), auto_close_days: parseInt(document.getElementById('rule-form-autoclose').value) || 0, - delay_days: parseInt(document.getElementById('rule-form-delay-days').value) || 0, - delay_condition: document.getElementById('rule-form-delay-condition').value, + delay_days: document.getElementById('rule-form-delay-enabled').checked ? (parseInt(document.getElementById('rule-form-delay-days').value) || 0) : 0, enabled: true, }; const existingId = document.getElementById('rule-form-id').value;