mirror of
https://github.com/itflow-org/itflow
synced 2026-08-16 12:35:11 +00:00
Feature: Abiliry to assign Ticket Templates to Recurring Tickets
This commit is contained in:
16
admin/database_updates/2.5.4.php
Normal file
16
admin/database_updates/2.5.4.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ITFlow - Database update to version 2.5.4 (from 2.5.3)
|
||||||
|
* Included by admin/database_updates.php - do not access directly
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined('FROM_DB_UPDATER') || die("Direct file access is not allowed");
|
||||||
|
|
||||||
|
// Recurring tickets can now carry a ticket template. The template's subject
|
||||||
|
// and details are copied into the recurring ticket when it is picked, so the
|
||||||
|
// link exists for one reason only: to stamp the template's task list onto
|
||||||
|
// every ticket the schedule raises. 0 means no template, matching the other
|
||||||
|
// optional relations on this table.
|
||||||
|
mysqli_query($mysqli, "ALTER TABLE `recurring_tickets`
|
||||||
|
ADD COLUMN `recurring_ticket_ticket_template_id` int(11) NOT NULL DEFAULT 0 AFTER `recurring_ticket_asset_id`");
|
||||||
@@ -84,18 +84,59 @@ ob_start();
|
|||||||
|
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Template</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
|
||||||
|
</div>
|
||||||
|
<select class="form-control select2" id="ticket_template_select" name="ticket_template_id">
|
||||||
|
<option value="0">- No Template -</option>
|
||||||
|
<?php
|
||||||
|
$sql_ticket_templates = mysqli_query($mysqli, "
|
||||||
|
SELECT tt.ticket_template_id,
|
||||||
|
tt.ticket_template_name,
|
||||||
|
tt.ticket_template_subject,
|
||||||
|
tt.ticket_template_details,
|
||||||
|
COUNT(ttt.task_template_id) as task_count
|
||||||
|
FROM ticket_templates tt
|
||||||
|
LEFT JOIN task_templates ttt
|
||||||
|
ON tt.ticket_template_id = ttt.task_template_ticket_template_id
|
||||||
|
WHERE tt.ticket_template_archived_at IS NULL
|
||||||
|
GROUP BY tt.ticket_template_id
|
||||||
|
ORDER BY tt.ticket_template_name ASC
|
||||||
|
");
|
||||||
|
|
||||||
|
while ($row = mysqli_fetch_assoc($sql_ticket_templates)) {
|
||||||
|
$ticket_template_id_select = intval($row['ticket_template_id']);
|
||||||
|
$ticket_template_name_select = escapeHtml($row['ticket_template_name']);
|
||||||
|
$ticket_template_subject_select = escapeHtml($row['ticket_template_subject']);
|
||||||
|
$ticket_template_details_select = escapeHtml($row['ticket_template_details']);
|
||||||
|
$task_count = intval($row['task_count']);
|
||||||
|
?>
|
||||||
|
<option value="<?= $ticket_template_id_select ?>"
|
||||||
|
data-subject="<?= $ticket_template_subject_select ?>"
|
||||||
|
data-details="<?= $ticket_template_details_select ?>">
|
||||||
|
<?= $ticket_template_name_select ?> (<?= $task_count ?> tasks)
|
||||||
|
</option>
|
||||||
|
<?php } ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<small class="form-text text-muted">The template's tasks are added to every ticket this schedule raises.</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Subject <strong class="text-danger">*</strong></label>
|
<label>Subject <strong class="text-danger">*</strong></label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
|
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" class="form-control" name="subject" placeholder="Subject" maxlength="500" required>
|
<input type="text" class="form-control" id="subjectInput" name="subject" placeholder="Subject" maxlength="500" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<textarea class="form-control tinymceTicket" name="details"></textarea>
|
<textarea class="form-control tinymceTicket" id="detailsInput" name="details"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -343,6 +384,35 @@ ob_start();
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<!-- Ticket Templates -->
|
||||||
|
<script>
|
||||||
|
$(document).on('change', '#ticket_template_select', function () {
|
||||||
|
const $opt = $(this).find(':selected');
|
||||||
|
|
||||||
|
// Selecting "- No Template -" only unlinks the template - it must not wipe
|
||||||
|
// whatever subject/details the user has already written
|
||||||
|
if (!parseInt($opt.val(), 10)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const templateSubject = $opt.data('subject') || '';
|
||||||
|
const templateDetails = $opt.data('details') || '';
|
||||||
|
|
||||||
|
$('#subjectInput').val(templateSubject);
|
||||||
|
|
||||||
|
if (window.tinymce) {
|
||||||
|
const editor = tinymce.get('detailsInput');
|
||||||
|
if (editor) {
|
||||||
|
editor.setContent(templateDetails);
|
||||||
|
} else {
|
||||||
|
$('#detailsInput').val(templateDetails);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$('#detailsInput').val(templateDetails);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<!-- Recurring Ticket Client/Contact JS -->
|
<!-- Recurring Ticket Client/Contact JS -->
|
||||||
<link rel="stylesheet" href="/libs/jquery-ui/jquery-ui.min.css">
|
<link rel="stylesheet" href="/libs/jquery-ui/jquery-ui.min.css">
|
||||||
<script src="/libs/jquery-ui/jquery-ui.min.js"></script>
|
<script src="/libs/jquery-ui/jquery-ui.min.js"></script>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ $recurring_ticket_contact_id = intval($row['recurring_ticket_contact_id']);
|
|||||||
$recurring_ticket_asset_id = intval($row['recurring_ticket_asset_id']);
|
$recurring_ticket_asset_id = intval($row['recurring_ticket_asset_id']);
|
||||||
$recurring_ticket_category = intval($row['recurring_ticket_category']);
|
$recurring_ticket_category = intval($row['recurring_ticket_category']);
|
||||||
$recurring_ticket_billable = intval($row['recurring_ticket_billable']);
|
$recurring_ticket_billable = intval($row['recurring_ticket_billable']);
|
||||||
|
$recurring_ticket_ticket_template_id = intval($row['recurring_ticket_ticket_template_id']);
|
||||||
|
|
||||||
// Additional Assets Selected
|
// Additional Assets Selected
|
||||||
$additional_assets_array = array();
|
$additional_assets_array = array();
|
||||||
@@ -69,18 +70,60 @@ ob_start();
|
|||||||
|
|
||||||
<div class="tab-pane fade show active" id="pills-edit-details">
|
<div class="tab-pane fade show active" id="pills-edit-details">
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Template</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
|
||||||
|
</div>
|
||||||
|
<select class="form-control select2" id="ticket_template_select" name="ticket_template_id">
|
||||||
|
<option value="0">- No Template -</option>
|
||||||
|
<?php
|
||||||
|
$sql_ticket_templates = mysqli_query($mysqli, "
|
||||||
|
SELECT tt.ticket_template_id,
|
||||||
|
tt.ticket_template_name,
|
||||||
|
tt.ticket_template_subject,
|
||||||
|
tt.ticket_template_details,
|
||||||
|
COUNT(ttt.task_template_id) as task_count
|
||||||
|
FROM ticket_templates tt
|
||||||
|
LEFT JOIN task_templates ttt
|
||||||
|
ON tt.ticket_template_id = ttt.task_template_ticket_template_id
|
||||||
|
WHERE (tt.ticket_template_archived_at IS NULL OR tt.ticket_template_id = $recurring_ticket_ticket_template_id)
|
||||||
|
GROUP BY tt.ticket_template_id
|
||||||
|
ORDER BY tt.ticket_template_name ASC
|
||||||
|
");
|
||||||
|
|
||||||
|
while ($row = mysqli_fetch_assoc($sql_ticket_templates)) {
|
||||||
|
$ticket_template_id_select = intval($row['ticket_template_id']);
|
||||||
|
$ticket_template_name_select = escapeHtml($row['ticket_template_name']);
|
||||||
|
$ticket_template_subject_select = escapeHtml($row['ticket_template_subject']);
|
||||||
|
$ticket_template_details_select = escapeHtml($row['ticket_template_details']);
|
||||||
|
$task_count = intval($row['task_count']);
|
||||||
|
?>
|
||||||
|
<option value="<?= $ticket_template_id_select ?>"
|
||||||
|
data-subject="<?= $ticket_template_subject_select ?>"
|
||||||
|
data-details="<?= $ticket_template_details_select ?>"
|
||||||
|
<?php if ($recurring_ticket_ticket_template_id == $ticket_template_id_select) { echo "selected"; } ?>>
|
||||||
|
<?= $ticket_template_name_select ?> (<?= $task_count ?> tasks)
|
||||||
|
</option>
|
||||||
|
<?php } ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<small class="form-text text-muted">The template's tasks are added to every ticket this schedule raises. Changing it rewrites the subject and details below.</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Subject <strong class="text-danger">*</strong></label>
|
<label>Subject <strong class="text-danger">*</strong></label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
|
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" class="form-control" name="subject" placeholder="Subject" maxlength="500" value="<?= $recurring_ticket_subject ?>" required >
|
<input type="text" class="form-control" id="subjectInput" name="subject" placeholder="Subject" maxlength="500" value="<?= $recurring_ticket_subject ?>" required >
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<textarea class="form-control tinymce" name="details"><?= $recurring_ticket_details ?></textarea>
|
<textarea class="form-control tinymce" id="detailsInput" name="details"><?= $recurring_ticket_details ?></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -306,6 +349,35 @@ ob_start();
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<!-- Ticket Templates -->
|
||||||
|
<script>
|
||||||
|
$(document).on('change', '#ticket_template_select', function () {
|
||||||
|
const $opt = $(this).find(':selected');
|
||||||
|
|
||||||
|
// Selecting "- No Template -" only unlinks the template - it must not wipe
|
||||||
|
// whatever subject/details the user has already written
|
||||||
|
if (!parseInt($opt.val(), 10)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const templateSubject = $opt.data('subject') || '';
|
||||||
|
const templateDetails = $opt.data('details') || '';
|
||||||
|
|
||||||
|
$('#subjectInput').val(templateSubject);
|
||||||
|
|
||||||
|
if (window.tinymce) {
|
||||||
|
const editor = tinymce.get('detailsInput');
|
||||||
|
if (editor) {
|
||||||
|
editor.setContent(templateDetails);
|
||||||
|
} else {
|
||||||
|
$('#detailsInput').val(templateDetails);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$('#detailsInput').val(templateDetails);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once '../../../includes/modal_footer.php';
|
require_once '../../../includes/modal_footer.php';
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ if (isset($_POST['add_recurring_ticket'])) {
|
|||||||
|
|
||||||
$start_date = escapeSql($_POST['start_date']);
|
$start_date = escapeSql($_POST['start_date']);
|
||||||
|
|
||||||
mysqli_query($mysqli, "INSERT INTO recurring_tickets SET recurring_ticket_subject = '$subject', recurring_ticket_details = '$details', recurring_ticket_priority = '$priority', recurring_ticket_frequency = '$frequency', recurring_ticket_billable = $billable, recurring_ticket_start_date = '$start_date', recurring_ticket_next_run = '$start_date', recurring_ticket_assigned_to = $assigned_to, recurring_ticket_created_by = $session_user_id, recurring_ticket_client_id = $client_id, recurring_ticket_contact_id = $contact_id, recurring_ticket_asset_id = $asset_id, recurring_ticket_category = $category_id");
|
mysqli_query($mysqli, "INSERT INTO recurring_tickets SET recurring_ticket_subject = '$subject', recurring_ticket_details = '$details', recurring_ticket_priority = '$priority', recurring_ticket_frequency = '$frequency', recurring_ticket_billable = $billable, recurring_ticket_start_date = '$start_date', recurring_ticket_next_run = '$start_date', recurring_ticket_assigned_to = $assigned_to, recurring_ticket_created_by = $session_user_id, recurring_ticket_client_id = $client_id, recurring_ticket_contact_id = $contact_id, recurring_ticket_asset_id = $asset_id, recurring_ticket_category = $category_id, recurring_ticket_ticket_template_id = $ticket_template_id");
|
||||||
|
|
||||||
$recurring_ticket_id = mysqli_insert_id($mysqli);
|
$recurring_ticket_id = mysqli_insert_id($mysqli);
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ if (isset($_POST['edit_recurring_ticket'])) {
|
|||||||
|
|
||||||
enforceClientAccess();
|
enforceClientAccess();
|
||||||
|
|
||||||
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_subject = '$subject', recurring_ticket_details = '$details', recurring_ticket_priority = '$priority', recurring_ticket_frequency = '$frequency', recurring_ticket_billable = $billable, recurring_ticket_next_run = '$next_run_date', recurring_ticket_assigned_to = $assigned_to, recurring_ticket_asset_id = $asset_id, recurring_ticket_contact_id = $contact_id, recurring_ticket_category = $category_id WHERE recurring_ticket_id = $recurring_ticket_id");
|
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_subject = '$subject', recurring_ticket_details = '$details', recurring_ticket_priority = '$priority', recurring_ticket_frequency = '$frequency', recurring_ticket_billable = $billable, recurring_ticket_next_run = '$next_run_date', recurring_ticket_assigned_to = $assigned_to, recurring_ticket_asset_id = $asset_id, recurring_ticket_contact_id = $contact_id, recurring_ticket_category = $category_id, recurring_ticket_ticket_template_id = $ticket_template_id WHERE recurring_ticket_id = $recurring_ticket_id");
|
||||||
|
|
||||||
// Add Additional Assets
|
// Add Additional Assets
|
||||||
if (isset($_POST['additional_assets'])) {
|
if (isset($_POST['additional_assets'])) {
|
||||||
@@ -102,6 +102,7 @@ if (isset($_POST['bulk_force_recurring_tickets'])) {
|
|||||||
$client_id = intval($row['recurring_ticket_client_id']);
|
$client_id = intval($row['recurring_ticket_client_id']);
|
||||||
$asset_id = intval($row['recurring_ticket_asset_id']);
|
$asset_id = intval($row['recurring_ticket_asset_id']);
|
||||||
$category = intval($row['recurring_ticket_category']);
|
$category = intval($row['recurring_ticket_category']);
|
||||||
|
$ticket_template_id = intval($row['recurring_ticket_ticket_template_id']);
|
||||||
$url_key = randomString(32);
|
$url_key = randomString(32);
|
||||||
|
|
||||||
enforceClientAccess();
|
enforceClientAccess();
|
||||||
@@ -139,6 +140,9 @@ if (isset($_POST['bulk_force_recurring_tickets'])) {
|
|||||||
FROM recurring_ticket_assets
|
FROM recurring_ticket_assets
|
||||||
WHERE recurring_ticket_id = $recurring_ticket_id");
|
WHERE recurring_ticket_id = $recurring_ticket_id");
|
||||||
|
|
||||||
|
// Copy Tasks from the linked ticket template, if one is set
|
||||||
|
addTasksFromTicketTemplate($id, $ticket_template_id);
|
||||||
|
|
||||||
// Notifications
|
// Notifications
|
||||||
|
|
||||||
triggerCustomAction('ticket_create', $id);
|
triggerCustomAction('ticket_create', $id);
|
||||||
@@ -243,6 +247,7 @@ if (isset($_GET['force_recurring_ticket'])) {
|
|||||||
$client_id = intval($row['recurring_ticket_client_id']);
|
$client_id = intval($row['recurring_ticket_client_id']);
|
||||||
$asset_id = intval($row['recurring_ticket_asset_id']);
|
$asset_id = intval($row['recurring_ticket_asset_id']);
|
||||||
$category = intval($row['recurring_ticket_category']);
|
$category = intval($row['recurring_ticket_category']);
|
||||||
|
$ticket_template_id = intval($row['recurring_ticket_ticket_template_id']);
|
||||||
$url_key = randomString(32);
|
$url_key = randomString(32);
|
||||||
|
|
||||||
enforceClientAccess();
|
enforceClientAccess();
|
||||||
@@ -280,6 +285,9 @@ if (isset($_GET['force_recurring_ticket'])) {
|
|||||||
FROM recurring_ticket_assets
|
FROM recurring_ticket_assets
|
||||||
WHERE recurring_ticket_id = $recurring_ticket_id");
|
WHERE recurring_ticket_id = $recurring_ticket_id");
|
||||||
|
|
||||||
|
// Copy Tasks from the linked ticket template, if one is set
|
||||||
|
addTasksFromTicketTemplate($id, $ticket_template_id);
|
||||||
|
|
||||||
// Notifications
|
// Notifications
|
||||||
|
|
||||||
triggerCustomAction('ticket_create', $id);
|
triggerCustomAction('ticket_create', $id);
|
||||||
|
|||||||
@@ -10,3 +10,4 @@ $asset_id = intval($_POST['asset_id'] ?? 0);
|
|||||||
$contact_id = intval($_POST['contact_id'] ?? 0);
|
$contact_id = intval($_POST['contact_id'] ?? 0);
|
||||||
$assigned_to = intval($_POST['assigned_to'] ?? 0);
|
$assigned_to = intval($_POST['assigned_to'] ?? 0);
|
||||||
$category_id = intval($_POST['category_id'] ?? 0);
|
$category_id = intval($_POST['category_id'] ?? 0);
|
||||||
|
$ticket_template_id = intval($_POST['ticket_template_id'] ?? 0);
|
||||||
|
|||||||
@@ -80,20 +80,7 @@ if (isset($_POST['add_ticket'])) {
|
|||||||
applyTicketSla($ticket_id);
|
applyTicketSla($ticket_id);
|
||||||
|
|
||||||
// Add Tasks from Template if Template was selected
|
// Add Tasks from Template if Template was selected
|
||||||
if($ticket_template_id) {
|
addTasksFromTicketTemplate($ticket_id, $ticket_template_id);
|
||||||
// Get Associated Tasks from the ticket template
|
|
||||||
$sql_task_templates = mysqli_query($mysqli, "SELECT * FROM task_templates WHERE task_template_ticket_template_id = $ticket_template_id");
|
|
||||||
|
|
||||||
if (mysqli_num_rows($sql_task_templates) > 0) {
|
|
||||||
while ($row = mysqli_fetch_assoc($sql_task_templates)) {
|
|
||||||
$task_order = intval($row['task_template_order']);
|
|
||||||
$task_name = escapeSql($row['task_template_name']);
|
|
||||||
$task_completion_estimate = intval($row['task_template_completion_estimate']);
|
|
||||||
|
|
||||||
mysqli_query($mysqli,"INSERT INTO tasks SET task_name = '$task_name', task_order = $task_order, task_completion_estimate = $task_completion_estimate, task_ticket_id = $ticket_id");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Watchers
|
// Add Watchers
|
||||||
if (isset($_POST['watchers'])) {
|
if (isset($_POST['watchers'])) {
|
||||||
@@ -1705,10 +1692,6 @@ if (isset($_POST['bulk_add_asset_ticket'])) {
|
|||||||
$subject = escapeSql($row['ticket_template_subject']);
|
$subject = escapeSql($row['ticket_template_subject']);
|
||||||
}
|
}
|
||||||
$details = mysqli_escape_string($mysqli, $row['ticket_template_details']);
|
$details = mysqli_escape_string($mysqli, $row['ticket_template_details']);
|
||||||
|
|
||||||
// Get Associated Tasks from the ticket template
|
|
||||||
$sql_task_templates = mysqli_query($mysqli, "SELECT * FROM task_templates WHERE task_template_ticket_template_id = $ticket_template_id");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create ticket for each selected asset
|
// Create ticket for each selected asset
|
||||||
@@ -1770,16 +1753,7 @@ if (isset($_POST['bulk_add_asset_ticket'])) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add Tasks from Template if Template was selected
|
// Add Tasks from Template if Template was selected
|
||||||
if($ticket_template_id) {
|
addTasksFromTicketTemplate($ticket_id, $ticket_template_id);
|
||||||
if (mysqli_num_rows($sql_task_templates) > 0) {
|
|
||||||
while ($row = mysqli_fetch_assoc($sql_task_templates)) {
|
|
||||||
$task_order = intval($row['task_template_order']);
|
|
||||||
$task_name = escapeSql($row['task_template_name']);
|
|
||||||
|
|
||||||
mysqli_query($mysqli,"INSERT INTO tasks SET task_name = '$task_name', task_order = $task_order, task_ticket_id = $ticket_id");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom action/notif handler
|
// Custom action/notif handler
|
||||||
triggerCustomAction('ticket_create', $ticket_id);
|
triggerCustomAction('ticket_create', $ticket_id);
|
||||||
|
|||||||
@@ -317,6 +317,7 @@ if (mysqli_num_rows($sql_recurring_tickets) > 0) {
|
|||||||
$contact_id = intval($row['recurring_ticket_contact_id']);
|
$contact_id = intval($row['recurring_ticket_contact_id']);
|
||||||
$asset_id = intval($row['recurring_ticket_asset_id']);
|
$asset_id = intval($row['recurring_ticket_asset_id']);
|
||||||
$category = intval($row['recurring_ticket_category']);
|
$category = intval($row['recurring_ticket_category']);
|
||||||
|
$ticket_template_id = intval($row['recurring_ticket_ticket_template_id']);
|
||||||
|
|
||||||
$ticket_status = 1; // Default
|
$ticket_status = 1; // Default
|
||||||
if ($assigned_id > 0) {
|
if ($assigned_id > 0) {
|
||||||
@@ -351,6 +352,9 @@ if (mysqli_num_rows($sql_recurring_tickets) > 0) {
|
|||||||
FROM recurring_ticket_assets
|
FROM recurring_ticket_assets
|
||||||
WHERE recurring_ticket_id = $recurring_ticket_id");
|
WHERE recurring_ticket_id = $recurring_ticket_id");
|
||||||
|
|
||||||
|
// Copy Tasks from the linked ticket template, if one is set
|
||||||
|
addTasksFromTicketTemplate($id, $ticket_template_id);
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
logAudit("Ticket", "Create", "Cron created recurring scheduled $frequency ticket - $subject", $client_id, $id);
|
logAudit("Ticket", "Create", "Cron created recurring scheduled $frequency ticket - $subject", $client_id, $id);
|
||||||
|
|
||||||
|
|||||||
3
db.sql
3
db.sql
@@ -1937,6 +1937,7 @@ CREATE TABLE `recurring_tickets` (
|
|||||||
`recurring_ticket_client_id` int(11) NOT NULL DEFAULT 0,
|
`recurring_ticket_client_id` int(11) NOT NULL DEFAULT 0,
|
||||||
`recurring_ticket_contact_id` int(11) NOT NULL DEFAULT 0,
|
`recurring_ticket_contact_id` int(11) NOT NULL DEFAULT 0,
|
||||||
`recurring_ticket_asset_id` int(11) NOT NULL DEFAULT 0,
|
`recurring_ticket_asset_id` int(11) NOT NULL DEFAULT 0,
|
||||||
|
`recurring_ticket_ticket_template_id` int(11) NOT NULL DEFAULT 0,
|
||||||
PRIMARY KEY (`recurring_ticket_id`)
|
PRIMARY KEY (`recurring_ticket_id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
@@ -3066,4 +3067,4 @@ CREATE TABLE `vendors` (
|
|||||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
|
|
||||||
-- Dump completed on 2026-07-29 14:15:02
|
-- Dump completed on 2026-07-29 15:54:34
|
||||||
|
|||||||
@@ -71,6 +71,48 @@ function getTicketStatusName($ticket_status) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies a ticket template's tasks onto a ticket.
|
||||||
|
*
|
||||||
|
* Called anywhere a ticket is raised from a template - the ticket add modals,
|
||||||
|
* the bulk asset add, and every recurring ticket run (cron, force, bulk force).
|
||||||
|
* Tasks are a snapshot: editing the template later does not touch tickets that
|
||||||
|
* have already been raised from it.
|
||||||
|
*
|
||||||
|
* @param int $ticket_id The ticket to attach the tasks to.
|
||||||
|
* @param int $ticket_template_id The template to copy tasks from. 0 = no-op.
|
||||||
|
*
|
||||||
|
* @return int The number of tasks created.
|
||||||
|
*/
|
||||||
|
function addTasksFromTicketTemplate($ticket_id, $ticket_template_id) {
|
||||||
|
|
||||||
|
global $mysqli;
|
||||||
|
|
||||||
|
$ticket_id = intval($ticket_id);
|
||||||
|
$ticket_template_id = intval($ticket_template_id);
|
||||||
|
|
||||||
|
if (!$ticket_id || !$ticket_template_id) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql_task_templates = mysqli_query($mysqli, "SELECT * FROM task_templates WHERE task_template_ticket_template_id = $ticket_template_id ORDER BY task_template_order ASC");
|
||||||
|
|
||||||
|
$tasks_added = 0;
|
||||||
|
|
||||||
|
while ($row = mysqli_fetch_assoc($sql_task_templates)) {
|
||||||
|
$task_order = intval($row['task_template_order']);
|
||||||
|
$task_name = escapeSql($row['task_template_name']);
|
||||||
|
$task_completion_estimate = intval($row['task_template_completion_estimate']);
|
||||||
|
|
||||||
|
mysqli_query($mysqli, "INSERT INTO tasks SET task_name = '$task_name', task_order = $task_order, task_completion_estimate = $task_completion_estimate, task_ticket_id = $ticket_id");
|
||||||
|
|
||||||
|
$tasks_added++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tasks_added;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a specified field's value from a table based on the record's id.
|
* Retrieves a specified field's value from a table based on the record's id.
|
||||||
* It validates the table and field names, automatically determines the primary key (or uses the first column as fallback),
|
* It validates the table and field names, automatically determines the primary key (or uses the first column as fallback),
|
||||||
|
|||||||
Reference in New Issue
Block a user