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 <noreply@anthropic.com>
This commit is contained in:
99
api.php
99
api.php
@@ -3242,61 +3242,34 @@ switch ($action) {
|
|||||||
}
|
}
|
||||||
unset($tc);
|
unset($tc);
|
||||||
|
|
||||||
// Ajastinsääntöjen tarkistus (delay_days + no_activity)
|
// Ajastettujen sääntöjen suoritus (delay_execute_at saavutettu)
|
||||||
$timedRules = array_filter(dbLoadTicketRules($comp['id']), function($r) {
|
foreach ($tickets as &$tc) {
|
||||||
return $r['enabled'] && $r['delay_days'] > 0 && $r['delay_condition'] === 'no_activity';
|
if (empty($tc['delay_rule_id']) || empty($tc['delay_execute_at'])) continue;
|
||||||
});
|
if ($tc['delay_execute_at'] > $now) continue;
|
||||||
if (!empty($timedRules)) {
|
if (in_array($tc['status'], ['suljettu', 'ratkaistu'])) {
|
||||||
foreach ($tickets as &$tc) {
|
// Suljettu/ratkaistu ennen ajastinta → peruuta
|
||||||
if (in_array($tc['status'], ['suljettu', 'ratkaistu'])) continue;
|
unset($tc['delay_rule_id'], $tc['delay_execute_at']);
|
||||||
$lastActivity = $tc['updated'] ?? $tc['created'];
|
dbSaveTicket($comp['id'], $tc);
|
||||||
$inactiveDays = (strtotime($now) - strtotime($lastActivity)) / 86400;
|
continue;
|
||||||
foreach ($timedRules as $rule) {
|
}
|
||||||
if ($inactiveDays < $rule['delay_days']) continue;
|
// Hae sääntö ja suorita toimenpiteet
|
||||||
// Tarkista ehdot (from/to/subject)
|
$allRules = dbLoadTicketRules($comp['id']);
|
||||||
$match = true;
|
$rule = null;
|
||||||
if (!empty($rule['from_contains'])) {
|
foreach ($allRules as $r) { if ($r['id'] === $tc['delay_rule_id']) { $rule = $r; break; } }
|
||||||
if (stripos(($tc['from_email'] ?? '') . ' ' . ($tc['from_name'] ?? ''), $rule['from_contains']) === false) $match = false;
|
if ($rule) {
|
||||||
}
|
if (!empty($rule['status_set'])) $tc['status'] = $rule['status_set'];
|
||||||
if (!empty($rule['subject_contains'])) {
|
if (!empty($rule['type_set'])) $tc['type'] = $rule['type_set'];
|
||||||
if (stripos($tc['subject'] ?? '', $rule['subject_contains']) === false) $match = false;
|
if (!empty($rule['set_priority'])) $tc['priority'] = $rule['set_priority'];
|
||||||
}
|
if (!empty($rule['set_tags'])) {
|
||||||
if (!empty($rule['to_contains'])) {
|
$ruleTags = array_map('trim', explode(',', $rule['set_tags']));
|
||||||
if (stripos($tc['to_email'] ?? '', $rule['to_contains']) === false) $match = false;
|
$tc['tags'] = array_values(array_unique(array_merge($tc['tags'] ?? [], $ruleTags)));
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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
|
// Resolve mailbox names for this company
|
||||||
$mailboxes = dbLoadMailboxes($comp['id']);
|
$mailboxes = dbLoadMailboxes($comp['id']);
|
||||||
@@ -3571,12 +3544,21 @@ switch ($action) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($match) {
|
if ($match) {
|
||||||
if (!empty($rule['status_set'])) $ticket['status'] = $rule['status_set'];
|
$delayDays = intval($rule['delay_days'] ?? 0);
|
||||||
if (!empty($rule['type_set'])) $ticket['type'] = $rule['type_set'];
|
if ($delayDays > 0) {
|
||||||
if (!empty($rule['set_priority'])) $ticket['priority'] = $rule['set_priority'];
|
// Ajastettu sääntö: älä suorita heti, tallenna ajastus tikettiin
|
||||||
if (!empty($rule['set_tags'])) {
|
$executeAt = date('Y-m-d', strtotime("+{$delayDays} days")) . ' 10:00:00';
|
||||||
$ruleTags = array_map('trim', explode(',', $rule['set_tags']));
|
$ticket['delay_rule_id'] = $rule['id'];
|
||||||
$ticket['tags'] = array_values(array_unique(array_merge($ticket['tags'], $ruleTags)));
|
$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'])) {
|
if (!empty($rule['auto_close_days'])) {
|
||||||
$days = intval($rule['auto_close_days']);
|
$days = intval($rule['auto_close_days']);
|
||||||
@@ -4024,7 +4006,6 @@ switch ($action) {
|
|||||||
'set_tags' => trim($input['set_tags'] ?? ''),
|
'set_tags' => trim($input['set_tags'] ?? ''),
|
||||||
'auto_close_days' => intval($input['auto_close_days'] ?? 0),
|
'auto_close_days' => intval($input['auto_close_days'] ?? 0),
|
||||||
'delay_days' => intval($input['delay_days'] ?? 0),
|
'delay_days' => intval($input['delay_days'] ?? 0),
|
||||||
'delay_condition' => trim($input['delay_condition'] ?? ''),
|
|
||||||
'enabled' => $input['enabled'] ?? true,
|
'enabled' => $input['enabled'] ?? true,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
21
index.html
21
index.html
@@ -1293,18 +1293,17 @@
|
|||||||
<input type="number" id="rule-form-autoclose" min="0" max="365" placeholder="esim. 7" style="max-width:120px;">
|
<input type="number" id="rule-form-autoclose" min="0" max="365" placeholder="esim. 7" style="max-width:120px;">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group full-width" style="margin-top:0.5rem;">
|
<div class="form-group full-width" style="margin-top:0.5rem;">
|
||||||
<label style="font-weight:600;color:#0f3460;">Ajastin (vapaaehtoinen)</label>
|
<label style="font-weight:600;color:#0f3460;">Ajastin</label>
|
||||||
|
<p style="color:#888;font-size:0.8rem;margin:2px 0 0;">Kun ajastin on päällä, toimenpiteet suoritetaan vasta X päivän päästä klo 10:00</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group" style="display:flex;align-items:center;gap:1rem;">
|
||||||
<label>Viive (päivää)</label>
|
<label style="display:flex;align-items:center;gap:0.4rem;cursor:pointer;">
|
||||||
<input type="number" id="rule-form-delay-days" min="0" max="365" placeholder="esim. 3" style="max-width:120px;">
|
<input type="checkbox" id="rule-form-delay-enabled"> Ajastin päällä
|
||||||
</div>
|
</label>
|
||||||
<div class="form-group">
|
<div style="display:flex;align-items:center;gap:0.4rem;">
|
||||||
<label>Ehto</label>
|
<input type="number" id="rule-form-delay-days" min="1" max="365" placeholder="2" style="max-width:80px;" disabled>
|
||||||
<select id="rule-form-delay-condition">
|
<span style="font-size:0.85rem;color:#666;">päivää</span>
|
||||||
<option value="">Ei ajastinta</option>
|
</div>
|
||||||
<option value="no_activity">Ei aktiviteettia</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="display:flex;gap:0.5rem;margin-top:1rem;">
|
<div style="display:flex;gap:0.5rem;margin-top:1rem;">
|
||||||
|
|||||||
19
script.js
19
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_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.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.auto_close_days) actions.push('Auto-close: ' + r.auto_close_days + 'pv');
|
||||||
if (r.delay_days && r.delay_condition) {
|
if (r.delay_days > 0) actions.push('⏱ Ajastin: ' + r.delay_days + 'pv (klo 10:00)');
|
||||||
const condLabel = r.delay_condition === 'no_activity' ? 'ei aktiviteettia' : r.delay_condition;
|
|
||||||
actions.push('⏱ Ajastin: ' + r.delay_days + 'pv (' + condLabel + ')');
|
|
||||||
}
|
|
||||||
return `<div style="display:flex;justify-content:space-between;align-items:center;padding:0.75rem 1rem;background:${r.enabled ? '#f8f9fb' : '#fafafa'};border:1px solid #e8ebf0;border-radius:8px;margin-bottom:0.5rem;opacity:${r.enabled ? '1' : '0.5'};">
|
return `<div style="display:flex;justify-content:space-between;align-items:center;padding:0.75rem 1rem;background:${r.enabled ? '#f8f9fb' : '#fafafa'};border:1px solid #e8ebf0;border-radius:8px;margin-bottom:0.5rem;opacity:${r.enabled ? '1' : '0.5'};">
|
||||||
<div>
|
<div>
|
||||||
<div style="font-weight:600;color:#0f3460;font-size:0.9rem;">${esc(r.name)}</div>
|
<div style="font-weight:600;color:#0f3460;font-size:0.9rem;">${esc(r.name)}</div>
|
||||||
@@ -2377,8 +2374,10 @@ function showRuleForm(rule) {
|
|||||||
document.getElementById('rule-form-priority').value = rule ? (rule.set_priority || '') : '';
|
document.getElementById('rule-form-priority').value = rule ? (rule.set_priority || '') : '';
|
||||||
document.getElementById('rule-form-tags').value = rule ? (rule.set_tags || '') : '';
|
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-autoclose').value = rule ? (rule.auto_close_days || '') : '';
|
||||||
document.getElementById('rule-form-delay-days').value = rule ? (rule.delay_days || '') : '';
|
const hasDelay = rule && rule.delay_days > 0;
|
||||||
document.getElementById('rule-form-delay-condition').value = rule ? (rule.delay_condition || '') : '';
|
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;
|
editingRuleId = rule ? rule.id : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2389,6 +2388,11 @@ function hideRuleForm() {
|
|||||||
|
|
||||||
document.getElementById('btn-add-rule').addEventListener('click', () => showRuleForm(null));
|
document.getElementById('btn-add-rule').addEventListener('click', () => showRuleForm(null));
|
||||||
document.getElementById('btn-cancel-rule').addEventListener('click', () => hideRuleForm());
|
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 () => {
|
document.getElementById('btn-save-rule').addEventListener('click', async () => {
|
||||||
const name = document.getElementById('rule-form-name').value.trim();
|
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_priority: document.getElementById('rule-form-priority').value,
|
||||||
set_tags: document.getElementById('rule-form-tags').value.trim(),
|
set_tags: document.getElementById('rule-form-tags').value.trim(),
|
||||||
auto_close_days: parseInt(document.getElementById('rule-form-autoclose').value) || 0,
|
auto_close_days: parseInt(document.getElementById('rule-form-autoclose').value) || 0,
|
||||||
delay_days: parseInt(document.getElementById('rule-form-delay-days').value) || 0,
|
delay_days: document.getElementById('rule-form-delay-enabled').checked ? (parseInt(document.getElementById('rule-form-delay-days').value) || 0) : 0,
|
||||||
delay_condition: document.getElementById('rule-form-delay-condition').value,
|
|
||||||
enabled: true,
|
enabled: true,
|
||||||
};
|
};
|
||||||
const existingId = document.getElementById('rule-form-id').value;
|
const existingId = document.getElementById('rule-form-id').value;
|
||||||
|
|||||||
Reference in New Issue
Block a user