Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions bin/lms-timetable-scheduler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/usr/bin/env php
<?php

/*
* LMS version 28.x
*
* (C) Copyright 2001-2025 LMS Developers
*
* Please, see the doc/AUTHORS for more information about authors!
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License Version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*
* $Id$
*/

$script_parameters = array(
'schedule-tickets' => 'c',
'debug' => 'd',
);

$script_help = <<<EOF
-c, --schedule-tickets create events for tickets with periodicity set;
-d, --debug print all possible output;
EOF;

require_once('script-options.php');

$debug = isset($options['debug']);

// Initialize Session, Auth and LMS classes
$SYSLOG = null;
$AUTH = null;
$LMS = new LMS($DB, $AUTH, $SYSLOG);
Localisation::setUiLanguage('pl');

$plugin_manager = LMSPluginManager::getInstance();
$LMS->setPluginManager($plugin_manager);

$rt_schedule_planing_forward_events = ConfigHelper::getConfig('rt.schedule_planing_forward_events', 3);
$tickets_to_plan = $LMS->GetQueueContents(
[
'periodicity' => -1,
'deleted' => 0,
'closed' => 0,
'short' => true,
]
);

function CalculateNextOccurrenceInFuture($start, $periodicity)
{
global $EVENT_PERIODICITY;
$timestamp = (new DateTime())->setTimestamp($start);
$interval = $EVENT_PERIODICITY[$periodicity]['map'];
$now = time();

do {
$timestamp->modify($interval);
} while ($timestamp->getTimestamp() <= $now);

return $timestamp->getTimestamp();
}

if (empty($tickets_to_plan)) {
die();
}

foreach ($tickets_to_plan as $idx => $t) {
$t = $LMS->GetTicketContents($t['id']);

for ($a = $t['openeventcount'] ?? 0; $a < $rt_schedule_planing_forward_events; $a++) {
$ticket_events = $LMS->GetEventsByTicketId($t['ticketid']);
$last_ticket_event = (is_array($ticket_events) && !empty($ticket_events)) ? end($ticket_events) : null;
$timestamp = $last_ticket_event['date'] ?? $t['createtime'];
$next_occurrence = CalculateNextOccurrenceInFuture($timestamp, $t['periodicity']);
$params = [
'date' => $next_occurrence,
'begintime' => $last_ticket_event['begintime'] ?? 0,
'endtime' => $last_ticket_event['endtime'] ?? 0,
'enddate' => $last_ticket_event['enddate'] ?? 0,
'title' => $t['messages'][0]['subject'] ?? null,
'description' => $t['messages'][0]['body'] ?? null,
'userlist' => array($t['owner']) ?? null,
'custid' => $t['customerid'] ?? null,
'address_id' => $t['address_id'] ?? null,
'ticketid' => $t['ticketid'],
'nodeid' => $t['nodeid'] ?? null,
'private' => 0,
'type' => EVENT_OTHER,
];
if ($debug) {
print_r($params) . PHP_EOL;
}
$LMS->EventAdd($params);
}
}
1 change: 1 addition & 0 deletions doc/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,7 @@ version 28-git (????-??-??):
- improvement: 'rt.from_header_email_is_customer_contact_check' configuration variable with default 'true'
value allows to disable checking if 'from' header e-mail address is customer contact during ticket message
reply form startup [chilan]
- enhancement: allow to set ticket as periodic and create new events by crontab script [interduo]

version 27.0 (2021-08-20):

Expand Down
1 change: 1 addition & 0 deletions doc/lms.mysql
Original file line number Diff line number Diff line change
Expand Up @@ -2244,6 +2244,7 @@ CREATE TABLE rttickets (
modtime int(16) NOT NULL DEFAULT 0,
source tinyint(4) NOT NULL DEFAULT '0',
priority tinyint(4) DEFAULT NULL,
periodicity smallint DEFAULT 0,
deleted tinyint(1) NOT NULL DEFAULT '0',
deltime int(16) NOT NULL DEFAULT 0,
deluserid int(11) DEFAULT NULL,
Expand Down
3 changes: 2 additions & 1 deletion doc/lms.pgsql
Original file line number Diff line number Diff line change
Expand Up @@ -2157,6 +2157,7 @@ CREATE TABLE rttickets (
modtime bigint NOT NULL DEFAULT 0,
source smallint DEFAULT 0 NOT NULL,
priority smallint DEFAULT NULL,
periodicity smallint DEFAULT 0,
deleted smallint DEFAULT 0 NOT NULL,
deltime bigint DEFAULT 0 NOT NULL,
deluserid integer DEFAULT NULL
Expand Down Expand Up @@ -4525,6 +4526,6 @@ INSERT INTO netdevicemodels (name, alternative_name, netdeviceproducerid) VALUES
('XR7', 'XR7 MINI PCI PCBA', 2),
('XR9', 'MINI PCI 600MW 900MHZ', 2);

INSERT INTO dbinfo (keytype, keyvalue) VALUES ('dbversion', '2025081300');
INSERT INTO dbinfo (keytype, keyvalue) VALUES ('dbversion', '2025073000');

COMMIT;
43 changes: 35 additions & 8 deletions lib/LMSManagers/LMSHelpdeskManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ public function GetQueueContents(array $params)
{
$userid = Auth::GetCurrentUser();
extract($params);
foreach (array('ids', 'state', 'priority', 'source', 'owner', 'catids', 'removed', 'netdevids', 'netnodeids', 'deadline',
foreach (array('ids', 'state', 'priority', 'periodicity', 'source', 'owner', 'catids', 'removed', 'netdevids', 'netnodeids', 'deadline',
'serviceids', 'typeids', 'unread', 'parentids', 'verifierids', 'rights', 'projectids', 'cid', 'subject', 'fromdate', 'todate', 'short', 'watching') as $var) {
if (!isset(${$var})) {
${$var} = null;
Expand Down Expand Up @@ -185,6 +185,9 @@ public function GetQueueContents(array $params)
case 'priority':
$sqlord = ' ORDER BY t.priority';
break;
case 'periodicity':
$sqlord = ' ORDER BY t.periodicity';
break;
case 'deadline':
$sqlord = ' ORDER BY t.deadline';
break;
Expand Down Expand Up @@ -223,6 +226,16 @@ public function GetQueueContents(array $params)
$priorityfilter = ' AND t.priority = '.$priority;
}

if (empty($periodicity)) {
$periodicityfilter = '';
} elseif (is_array($periodicity)) {
$periodicityfilter = ' AND t.periodicity IN (' . implode(',', $periodicity) . ')';
} elseif ($periodicity == -1) {
$periodicityfilter = ' AND t.periodicity IS NOT NULL';
} else {
$periodicityfilter = ' AND t.periodicity = ' . $periodicity;
}

if (empty($source) || intval($source) == -1) {
$sourcefilter = '';
} else {
Expand Down Expand Up @@ -485,6 +498,7 @@ public function GetQueueContents(array $params)
. $parentfilter
. $statefilter
. $priorityfilter
. $periodicityfilter
. $sourcefilter
. $ownerfilter
. $removedfilter
Expand All @@ -504,7 +518,7 @@ public function GetQueueContents(array $params)

if ($result = $this->db->GetAll(
'SELECT DISTINCT t.id, t.customerid, t.address_id, va.name AS vaname, va.city AS vacity, va.street, va.house, va.flat, c.address, c.city, vusers.name AS ownername,
t.subject, t.state, owner AS ownerid, t.requestor AS req, t.source, t.priority, rtqueues.name,'
t.subject, t.state, owner AS ownerid, t.requestor AS req, t.source, t.priority, t.periodicity, rtqueues.name,'
. $this->db->Concat('c.lastname', "' '", 'c.name') . ' AS customername,
t.requestor_phone, t.requestor_mail, t.deadline, t.requestor_userid, rq.name AS requestor_name,
t.createtime AS createtime, u.name AS creatorname, t.deleted, t.deltime, t.deluserid,
Expand Down Expand Up @@ -594,6 +608,7 @@ public function GetQueueContents(array $params)
. $parentfilter
. $statefilter
. $priorityfilter
. $periodicityfilter
. $sourcefilter
. $ownerfilter
. $removedfilter
Expand Down Expand Up @@ -651,6 +666,7 @@ public function GetQueueContents(array $params)
$result['owner'] = $owner;
$result['removed'] = $removed;
$result['priority'] = $priority;
$result['periodicity'] = $periodicity;
$result['source'] = $source;
$result['deadline'] = $deadline;
$result['service'] = $serviceids;
Expand Down Expand Up @@ -783,7 +799,7 @@ public function GetEventsByTicketId($id)
. 'LEFT JOIN vaddresses va ON va.id = events.address_id '
. 'LEFT JOIN vnodes as vn ON (nodeid = vn.id) '
. 'LEFT JOIN customerview c ON (events.customerid = c.id) '
. 'WHERE ticketid = ? ORDER BY events.id ASC', array($id));
. 'WHERE ticketid = ? ORDER BY events.date ASC', array($id));

if (is_array($events)) {
foreach ($events as $idx => $row) {
Expand Down Expand Up @@ -1150,9 +1166,9 @@ public function TicketAdd($ticket, $files = null)

$this->db->Execute(
'INSERT INTO rttickets (queueid, customerid, requestor, requestor_mail, requestor_phone,
requestor_userid, subject, state, owner, createtime, modtime, cause, creatorid, source, priority, address_id, nodeid,
requestor_userid, subject, state, owner, createtime, modtime, cause, creatorid, source, priority, periodicity, address_id, nodeid,
netnodeid, netdevid, verifierid, deadline, service, type, invprojectid, parentid, customcreatetime, customresolvetime)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
array(
$ticket['queue'],
empty($ticket['customerid']) ? null : $ticket['customerid'],
Expand All @@ -1169,6 +1185,7 @@ public function TicketAdd($ticket, $files = null)
$ticket['userid'] ?? Auth::GetCurrentUser(),
$ticket['source'] ?? 0,
isset($ticket['priority']) && strlen($ticket['priority']) ? $ticket['priority'] : null,
empty($ticket['periodicity']) ? null : $ticket['periodicity'],
!empty($ticket['address_id']) ? $ticket['address_id'] : null,
!empty($ticket['nodeid']) ? $ticket['nodeid'] : null,
!empty($ticket['netnodeid']) ? $ticket['netnodeid'] : null,
Expand Down Expand Up @@ -1296,7 +1313,7 @@ public function GetTicketContents($id, $short = false)

$ticket = $this->db->GetRow('SELECT t.id AS ticketid, t.queueid, rtqueues.name AS queuename, t.requestor, t.requestor_phone, t.requestor_mail,
t.requestor_userid, d.name AS requestor_username, t.state, t.owner, t.customerid, t.cause, t.creatorid, c.name AS creator,
t.source, t.priority, i.id AS invprojectid, i.name AS invproject_name, t.verifier_rtime, '
t.source, t.priority, t.periodicity, i.id AS invprojectid, i.name AS invproject_name, t.verifier_rtime, '
. $this->db->Concat('customers.lastname', "' '", 'customers.name') . ' AS customername,
o.name AS ownername, t.createtime, t.resolvetime,
t.customcreatetime,
Expand Down Expand Up @@ -1554,7 +1571,7 @@ protected function updateTicketParentID($ticketid, $parentid = null)

public function TicketChange($ticketid, array $props)
{
global $LMS, $RT_STATES, $RT_CAUSE, $RT_SOURCES, $RT_PRIORITIES, $SERVICETYPES, $RT_TYPES;
global $LMS, $RT_STATES, $RT_CAUSE, $RT_SOURCES, $RT_PRIORITIES, $SERVICETYPES, $RT_TYPES, $EVENT_PERIODICITY;

$allow_empty_categories = ConfigHelper::checkConfig('rt.allow_empty_categories', ConfigHelper::checkConfig('phpui.helpdesk_allow_empty_categories'));

Expand Down Expand Up @@ -1612,6 +1629,15 @@ public function TicketChange($ticketid, array $props)
$props['priority'] = $ticket['priority'];
}

if (array_key_exists('periodicity', $props) && $ticket['periodicity'] != $props['periodicity']) {
$a = isset($ticket['periodicity']) ? $EVENT_PERIODICITY[$ticket['periodicity']]['label'] : trans('none');
$b = isset($props['periodicity']) ? $EVENT_PERIODICITY[$props['periodicity']]['label'] : trans('none');
$notes[] = trans('Ticket\'s scheduling periodicity has been changed from $a to $b.', $a, $b);
$type = $type | RTMESSAGE_PERIODICITY_CHANGE;
} else {
$props['periodicity'] = $ticket['periodicity'];
}

if (isset($props['state']) && $ticket['state'] != $props['state']) {
$notes[] = trans('Ticket\'s state has been changed from $a to $b.', $RT_STATES[$ticket['state']]['label'], $RT_STATES[$props['state']]['label']);
$type = $type | RTMESSAGE_STATE_CHANGE;
Expand Down Expand Up @@ -1992,7 +2018,7 @@ public function TicketChange($ticketid, array $props)
$userid : $props['owner'];
$this->db->Execute(
'UPDATE rttickets SET queueid = ?, owner = ?, cause = ?, state = ?, modtime = ?, resolvetime=?, subject = ?,
customerid = ?, source = ?, priority = ?, address_id = ?, nodeid = ?, netnodeid = ?, netdevid = ?,
customerid = ?, source = ?, priority = ?, periodicity = ?, address_id = ?, nodeid = ?, netnodeid = ?, netdevid = ?,
verifierid = ?, verifier_rtime = ?, deadline = ?, service = ?, type = ?, invprojectid = ?,
requestor_userid = ?, requestor = ?, requestor_mail = ?, requestor_phone = ?, parentid = ?,
customcreatetime = ?, customresolvetime = ?
Expand All @@ -2008,6 +2034,7 @@ public function TicketChange($ticketid, array $props)
$props['customerid'],
$props['source'],
$props['priority'],
$props['periodicity'],
$props['address_id'],
$props['nodeid'],
$props['netnodeid'],
Expand Down
3 changes: 3 additions & 0 deletions lib/SYSLOG.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class SYSLOG
public const RES_TARIFF_PRICE_VARIANT = 68;
public const RES_TICKET_MESSAGE = 69;
public const RES_QUEUE = 70;
public const RES_PERIODICITY = 71;

public const OPER_ADD = 1;
public const OPER_DELETE = 2;
Expand Down Expand Up @@ -167,6 +168,7 @@ class SYSLOG
self::RES_TARIFFASSIGN => 'tariff assignment<!syslog>',
self::RES_EVENT => 'event<!syslog>',
self::RES_EVENTASSIGN => 'event assignment<!syslog>',
self::RES_PERIODICITY => 'scheduling periodicity<!syslog>',
self::RES_ADDRESS => 'address<!syslog>',
self::RES_TICKET => 'ticket<!syslog>',
self::RES_DOCATTACH => 'document attachment<!syslog>',
Expand Down Expand Up @@ -239,6 +241,7 @@ class SYSLOG
self::RES_TARIFFASSIGN => 'tariffassignmentid',
self::RES_EVENT => 'eventid',
self::RES_EVENTASSIGN => 'eventassignmentid',
self::RES_PERIODICITY => 'periodid',
self::RES_ADDRESS => 'address_id',
self::RES_TICKET => 'ticketid',
self::RES_DOCATTACH => 'documentattachmentid',
Expand Down
Loading