From 3f90d2b0d09df9b35ba833bf72557d6a7a8d45fa Mon Sep 17 00:00:00 2001 From: johnnyq Date: Sun, 18 Oct 2026 00:01:43 -0400 Subject: [PATCH] Ticket templates stage 1: templates now set up the whole ticket - category, priority, billable, agent, due time and tags (migration 3.1.9 adds them, the ticket_template_tags table and tickets.ticket_template_id) - and fill [Client], [Contact], [Asset], [Site], [Agent], [Project], [Ticket], [Date], [Month], [Quarter] and [Year] in the subject, details and tasks when a ticket is raised, leaving other bracketed text for whoever picks it up; tickets remember the template they came from and each template shows how many tickets it raised, how many are open and when it was last used; the template picker fills New Ticket, the New Tickets windows on the assets and clients lists and recurring tickets, and project templates use each template's setup and agent; Admin > Ticket Templates rebuilt with search, Current/Archived, Copy, Archive/Restore and New ticket from it, and each template gets a page showing the ticket it starts, its tasks in drag-to-sort order with time estimates, what it sets up, its placeholders and the tickets, recurring tickets and project templates that use it; template handling moved into functions/ticket_template.php with ticketTemplateFinish, tagKeepIds and tagIdsFromValues split out of tagSetForRecord, and template task editing moved to admin/post; fixes editing a template task moving it to the top of the list, client bulk tickets skipping the template's tasks and time estimates, and the client bulk window not validating the agent, priority and category, and adds an option there to raise each client's ticket for its primary contact; changelog updated --- CHANGELOG.md | 26 +- admin/database_updates/3.1.9.php | 30 ++ .../ticket_template/ticket_template_add.php | 51 +-- .../ticket_template/ticket_template_edit.php | 76 ++-- .../ticket_template/ticket_template_form.php | 164 ++++++++ .../ticket_template_task_edit.php | 38 +- admin/post/ticket_template.php | 153 +++++-- admin/ticket_template.php | 387 ++++++++++++------ admin/ticket_templates.php | 232 +++++++---- agent/includes/inc_ticket_template_select.php | 101 ++--- agent/js/ticket_tasks_modal.js | 127 ++++-- agent/modals/asset/asset_bulk_add_ticket.php | 20 +- .../modals/client/client_bulk_add_ticket.php | 27 +- .../recurring_ticket/recurring_ticket_add.php | 17 +- .../recurring_ticket_edit.php | 13 +- agent/modals/ticket/ticket_add.php | 20 +- agent/post/client.php | 167 ++++---- agent/post/task.php | 21 - agent/post/ticket.php | 37 +- agent/tickets.php | 7 +- db.sql | 26 +- functions.php | 1 + functions/project.php | 54 +-- functions/tags.php | 53 ++- functions/ticket.php | 8 + functions/ticket_template.php | 375 +++++++++++++++++ 26 files changed, 1562 insertions(+), 669 deletions(-) create mode 100644 admin/database_updates/3.1.9.php create mode 100644 admin/modals/ticket_template/ticket_template_form.php create mode 100644 functions/ticket_template.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b014f33e..83e1e8c70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,9 @@ This file documents all notable changes made to ITFlow. ### Upgrading to 26.11 -Update from Maintenance > Update — Queue Update hands the job to cron, which updates the files and applies this release's database changes (2.7.9 to 3.1.8) in the same pass. Nothing else is required. +Update from Maintenance > Update — Queue Update hands the job to cron, which updates the files and applies this release's database changes (2.7.9 to 3.1.9) in the same pass. Nothing else is required. -This is a big release, with thirty-eight database steps in one go, so take a backup before you update. +This is a big release, with thirty-nine database steps in one go, so take a backup before you update. The update also clears out data that deletes in older versions left behind, all of it pointing at something that no longer exists: @@ -43,6 +43,8 @@ The built-in Accountant role gets full access to Financial, so it can delete an What the API makes from now on - tickets, replies, clients and the rest - is stamped in ITFlow's timezone, as the pages stamp what they make. What it made before keeps the server's time, which on a server set to UTC is hours off (see Bug Fixes). +Ticket templates keep their subject, details and tasks, and set nothing else on a ticket until you give them a category, priority, agent, due time or tags. Tickets raised before the update don't know which template they came from, so a template's use is counted from the update on. + If you are coming from 26.08 or earlier, the database update still has to be run from the command line one time, exactly as described under Upgrading to 26.09 below. ### Breaking Changes and Notes @@ -164,6 +166,9 @@ If you are coming from 26.08 or earlier, the database update still has to be run - Tickets: an agent is now emailed when a ticket is assigned to them from New Ticket or Edit, as they already were from the assignee pick and Bulk Action. It used to be an app notice only. Assigning a ticket to yourself sends nothing. - Client portal: the email inviting a contact to the portal no longer has their password in it. Tick Email them an invite to the portal - on New Contact as well as Edit - and they get a link to set their own password, good for 7 days, or with a Microsoft login a link to sign in. It used to email the password the agent typed, in plain text. A password you type is still set, for reading out over the phone; the link lets them choose another. - Email on the contacts and clients lists comes from one of your mailboxes in Admin > Mail, picked by name, and goes out in the email look. Archived contacts and contacts without an email address are left out, and each address gets it once. With no roles ticked on the clients list it goes to every contact that isn't archived. Nothing is sent while outgoing mail isn't set up. +- Ticket templates: [Client], [Contact], [Asset], [Site], [Agent], [Project], [Ticket], [Date], [Month], [Quarter] and [Year] in a template's subject, details and tasks are filled in when a ticket is raised from it - and in a recurring ticket's each time it raises one, template or not. A recurring ticket with [Month] in its subject used to raise it with [Month] in it. Anything else in square brackets stays as it is. +- Ticket templates: a project template's tickets are set up as their ticket templates say. They were always Medium, uncategorised and billed as the default. +- New Tickets on the assets list: with [Asset] in the subject, the asset's name isn't put in front of it as well. New Tickets on the assets and clients lists now email the agent they go to, once for all of them, as New Ticket does. - Emails to agents keep their subjects, so mail rules still match. The ones that changed: a client's reply from the portal is "ITFlow - Ticket updated - [TCK-12] Subject", with the dash the emailed reply always had; one recurring ticket assigned from Bulk Action is "ITFlow - Recurring ticket Subject assigned to you", as from the assignee pick; and a ticket raised on a schedule reaches the new-ticket address as "ITFlow - New Recurring Ticket - Client: Subject". - Client portal: primary and technical contacts' Tickets page now opens on everyone's tickets at their company, with Mine to see only their own. The separate All tickets page is gone, and links to it land on Tickets. A ticket shows the client where it stands - Received, In progress, Waiting on you, On hold, Resolved or Closed - rather than your ticket statuses. - Client portal: invoices and quotes now open in the portal, where they used to open their guest link in a new tab. The links in your emails work as before. A quote answered in the portal records the contact's name and any note they left. Pay invoices pays the invoices ticked as one card payment, and the Pay drop-down on each invoice is gone (see Client portal). @@ -479,10 +484,17 @@ If you are coming from 26.08 or earlier, the database update still has to be run - The project page shows warnings when something needs a look, and stat cards for tickets, tasks, time and due date. Tickets, Tasks and Activity are on tabs, alongside the scope, the details and the team with their hours. - Projects now have a start date, budget hours and a client contact. - A template can assign its tickets to the manager. You can also add a template's tickets to an existing project. - - Template ticket subjects can use [Client], [Project], [Month], [Quarter] and [Year]. + - Their tickets are set up as their ticket templates say, with [Client], [Project], [Month] and the like filled in (see Ticket templates). - You can add tickets by picking them or by number, and completed projects can be reopened. - Project templates in Admin keep their ticket templates in order, and can be duplicated, archived and restored. - Projects show on the ticket page, the client overview, the dashboard, the calendar and in search. +- **Ticket templates** (rebuilt) + - A template sets up the whole ticket, not just its subject, details and tasks: its category, priority, billing, the agent it goes to, when it is due (so many hours or days after it is raised) and its tags. Each is left alone unless the template sets it. + - Picking one on New Ticket fills in every field it sets, so you see the ticket before it is made and can change anything. The picker says what each template sets up and how many tasks it has. + - The New Tickets windows on the assets and clients lists now offer templates too, as recurring tickets do - and the clients list can raise each ticket for the client's primary contact. + - [Client], [Contact], [Asset], [Site], [Agent], [Project], [Ticket], [Date], [Month], [Quarter] and [Year] are filled in when the ticket is raised - in its subject, details and tasks. Anything else in square brackets, like [Employee Name], stays for whoever picks it up, and the template's page lists which are which. + - A ticket keeps which template it came from, and its history says so. Admin > Ticket Templates shows what each sets up, its tasks and their time, how many tickets it has raised and the recurring tickets and project templates that raise it. A template's page shows the ticket it starts with its placeholders marked, its tasks (added with their time, dragged into order) and its latest tickets, and New ticket from it opens New Ticket with it filled in. + - Templates can be copied, archived - not offered for new tickets, while the recurring tickets and project templates that use them keep them - restored and deleted. - **Assets** - The asset list has: - type icons, colored status pills and OS icons @@ -972,6 +984,8 @@ If you are coming from 26.08 or earlier, the database update still has to be run - Tickets: the email telling someone their email had become a ticket showed an apostrophe in its subject, or in their name, with a backslash in front of it. - Tickets: SLA alert emails were queued when outgoing mail was not set up. For a ticket raised or answered by email, the new ticket and client replied emails showed an apostrophe in the subject, the client's name or the reply with a backslash in front of it. - Admin > Mail: the test email was queued when outgoing mail was not set up, or when what was typed was not an email address, and greeted everyone as "Chap". +- Ticket templates: New Tickets on the clients list gave only the first client's ticket the template's tasks, dropped their times, and couldn't be given a template at all from the window. It took any priority, category or agent posted to it, and its "primary contact" never did anything. +- Ticket templates: changing one of a template's tasks moved it to the top of the list. - Email on the contacts list queued an email to a contact with no email address, which then failed in the mail queue. Email on the clients list included archived contacts. Both took any From address posted to them. - Emails: a saved card's confirmation, a new agent's sign in details and the email about a change to an agent's account were only sent when an SMTP host was filled in, so they were skipped when mail goes through Microsoft 365 or Google with no host. The saved card's email began "Were writing". - Contacts: an agent without Support saw a contact's Assets, Documents, Files and Services tabs, which led to pages they were refused. A document's or file's linked assets, licenses, services, domains and certificates were listed to them too. @@ -1414,6 +1428,12 @@ If you are coming from 26.08 or earlier, the database update still has to be run - Pulled out of the handlers so the previews can call them: `ticketMailCreated()` (from `agent/post/ticket.php`, now with `$how` and `$to`, which the email parser uses), `ticketMailReply($ticket_id, $reply_html, $by, $resolved, $attachments)` (the reply handler, bulk reply and the API), `ticketMailWatchersAdded()`, `ticketMailTaskApproval($approval_id, $by)`, `ticketMailClosedReply($ticket_id, $from_email)` and `ticketSlaAlert($ticket_id, $track, $breached, $due, $address)` in `functions/ticket.php` - `sendSlaAlert()` in `cron/ticket_sla.php` is gone - and `billingMailCardSaved()` in `functions/billing_email.php`. - `functions/portal.php`: `portalMailReady()`, `portalMailInvite($user_id, $by)` (used by `add_contact`, `edit_contact` - which take `send_email` - and the portal's `portalContactInvite()`), `portalMailPasswordReset($user_id)` and `portalMailAccountChange($email, $name, $change)` (`password`, `password_link`, `mfa_on`, `mfa_off`, `mfa_off_by_us`). `portalAccountEmail()` sends through `emailQueue()`. - `functions/share.php`: `shareMailHtml()` and `shareQueueMail()` are removed. `shareEmailLink()` returns a bool, and new `shareEmailCode($row, $code)` and `shareMailFrom()`. `shareMailReady()` goes by `emailReady()`. `calendarSendInvites()` sends through `emailQueue()`, and `calendarCanEmail()` is `emailReady()`. +- Ticket templates: + - Database 3.1.9: `ticket_templates` gains `ticket_template_category_id`, `ticket_template_priority` (NULL leaves it), `ticket_template_billable` (NULL leaves it), `ticket_template_assigned_to` and `ticket_template_due_hours`; new `ticket_template_tags` (ticket tags, cascading like `ticket_tags`); `tickets.ticket_template_id` with a key. + - New `functions/ticket_template.php`: `ticketTemplateRow()`, `ticketTemplateTasks()`, `ticketTemplateTagIds()`, `ticketTemplateFields($post, &$error)`, `ticketTemplateSave($id, $fields)`, `ticketTemplateSetTags()`, `ticketTemplateCopy()`, `ticketTemplateUsage($ids)`, `ticketTemplateDefaultsHtml()`, `ticketTemplatePickerData()`, `ticketTemplateDueText()`, `ticketTemplateDueAt()`, `ticketTemplateMinutesText()` and `ticketTemplatePlaceholdersIn()`; placeholders in `TICKET_PLACEHOLDERS`, `ticketPlaceholderValues($ticket_id)`, `ticketPlaceholderFill($text, $values, $html)` and `ticketPlaceholdersFill($ticket_id)`; and `ticketTemplateFinish($ticket_id, $template_id, $defaults, $tasks)`, which every path that raises from a template calls - `add_ticket`, `bulk_add_asset_ticket`, `bulk_add_client_ticket` (rewritten, with `use_primary_contact` now a switch in its window) and `projectApplyTemplate()`, which now takes each ticket template's settings. `recurringTicketRaise()` records the recurring ticket's template and calls `ticketPlaceholdersFill()`. `projectTemplateSubject()` is gone. + - `agent/includes/inc_ticket_template_select.php` writes each template's settings as `data-template-*` on its option and takes `$ticket_template_field`, `$ticket_template_apply_on_load` and `$ticket_template_hint`; `agent/js/ticket_tasks_modal.js` writes them into the form's fields marked `data-template-field` (`subject`, `details`, `priority`, `category`, `assigned`, `due`, `tags`, `billable`) and the task rows. `ticket_add.php` takes `ticket_template_id`, and `agent/tickets.php?new_from_template=` opens it. + - Admin: `admin/modals/ticket_template/ticket_template_form.php` is shared by the add and edit windows, which are ajax windows now; `copy_ticket_template`, `archive_ticket_template` and `restore_ticket_template` are new. `admin/post/ticket_template.php` no longer requires `agent/post/ticket.php` and `agent/post/task.php`, and `edit_ticket_template_task` moved there from `agent/post/task.php`. + - `functions/tags.php`: `tagIdsFromValues($entity, $values)` and `tagKeepIds($entity, $ids, $had)` are split out of `tagSetForRecord()`, and `tagFormFieldHtml()` takes the select's extra attributes. - Empty states: every list page sets `$empty_state` before including `includes/filter_footer.php`, and `includes/inc_empty_state.php` draws it with `emptyStateHtml()` (`functions/format.php`) when the list has nothing - `thing`, `icon`, `title`, `text`, `actions` (`label`, `modal` or `href`, `size`, `icon`; the first is the main one), `archived`, `view`, `filtered`, `views`, `match_title`, `match_text` and `clear_url`. `emptyStateFiltered($views)` reads the GET string for a search or filter, leaving out paging, sorting, `client_id`, `archived` and the page's views, and `emptyStateClearUrl($views)` is the page without them. `emptyStatePill($pills, $key, $default, $good)` builds a pill's own state from the page's pill array (`label`, `icon`, `title`, `alarm`), with a tick for `alarm` pills and the keys in `$good`. Files, notifications and racks call `emptyStateHtml()` in their own layout; files and notifications set `$empty_state_skip`. A page that sets nothing still gets one, worded from `$page_title`. The pages' own empty blocks (`.itflow-asset-empty` under a list) are gone. CSS: `.itflow-empty-state` with `-icon` (a grey round tile), `-title`, `-text` and `-actions`. - Removed unused helpers and files: - `credentialLink()`, `projectLink()`, `linkCounts()`, `assetContactAvatar()`, `clientOverviewPersonInitials()`, and `getMonthlyTax()` and `getQuarterlyTax()`, which looked a tax up by name diff --git a/admin/database_updates/3.1.9.php b/admin/database_updates/3.1.9.php new file mode 100644 index 000000000..e575ff67f --- /dev/null +++ b/admin/database_updates/3.1.9.php @@ -0,0 +1,30 @@ + @@ -13,53 +16,7 @@ ob_start();