-
Notifications
You must be signed in to change notification settings - Fork 17
Issue 110 No Notification When A Task Is Assigned
Assigning a task to a user or analyst produced no notification at all - no badge on the bell, nothing in the list. Unless that person happened to open the Tasks board and look, they were never told there was work waiting for them.
Reported in issue #110 by tjedelhauser, who also noted that tickets appeared to manage this and tasks did not - which is exactly the shape of the fault.
Fixed in 80618bdd, released as update #1259.
Assign a task to somebody. Sign in as that person, or look at their bell.
Nothing. No count, no row, no indication that anything had been given to them. Assign a ticket to the same person and the bell lights up immediately.
FreeITSM's notifications are not written by the screens that cause them. Every one of them is a side effect of an event, dispatched through WorkflowEngine::dispatch() - the single funnel that also drives workflows. includes/notifications_router.php listens on that funnel and answers two questions per event: who should be told, and what does it say.
That design is why this feature is normally small to extend. It is also why this bug was invisible: there was nothing to debug, because nothing was being sent.
Tasks dispatch exactly three events:
task.created
task.completed
task.deleted
There is no task.assigned. Not in the tasks service, not in the workflow engine's trigger list, not in the notification registry. The bell was not ignoring the event - the event did not exist.
task.created does notify the assignee, and it is off by default, deliberately, because a bell for every task created on a busy board is noise.
So the behaviour before this fix was oddly shaped:
| What you did | What happened |
|---|---|
| Created a task already assigned to somebody | They could be told - but only if they had gone and switched task.created on |
| Reassigned an existing task to somebody | Nobody could ever be told, under any setting |
The second row is the real fault, and the first is why it might have looked like a settings problem rather than a missing feature.
The only thing missing was the event itself. The rest of the chain was already waiting for it:
| Already in place | Doing what |
|---|---|
notificationsRecipientFor() |
Already read $payload['task']['assignee_id'] - it already knew a task's recipient is its assignee |
notificationsEntityFor() |
Already handled the task entity type |
entityLink() |
Already returned tasks/?task=N
|
system/preferences |
Already builds its switches from the type registry, so a new type brings its own switch |
The notification router needed no change at all. Adding the event was most of the work.
A task.assigned event, dispatched from TasksService, registered as a notification type defaulting to on (like ticket.assigned), and registered as a workflow trigger so it can drive an email too.
ticket.assigned fires only when a ticket is reassigned - never at creation. Copying that rule exactly would have left this half-fixed, because with tasks, creating one with somebody's name already on it is the ordinary way work gets handed out. A fix covering only later reassignment would have missed the commoner case, and would have looked broken to the first person who tested it the obvious way.
So task.assigned fires from createTask when a task is created with an assignee, and from updateTask when the assignee actually changes.
A new notification's risk is noise, so the quiet cases are as much a part of the fix as the loud one:
| Situation | Behaviour | Why |
|---|---|---|
| You assign a task to yourself | Silent | You know. This is the router's "never notify me about my own action" rule |
| You save the same task again, assignee unchanged | Silent | Editing a description must not re-announce the assignment |
| You clear the assignee | Silent | Removing somebody is not assigning to them, and there is nobody to tell |
| You change only the title | Silent | Not an assignment |
Self-assignment is filtered by the notification layer, not by the tasks service. That is deliberate: a workflow may legitimately want the event either way, and a second copy of the rule in the service is precisely how two copies drift apart.
typeEnabled() falls back to a type's default for any key a saved preference map does not contain. An analyst who set their notification preferences before today therefore gets task.assigned switched on, rather than silently missing a type that did not exist when they last looked.
| File | What changed |
|---|---|
includes/services/tasks.php |
assignedDispatch(), called from createTask and from updateTask when the assignee changes. Reads the row back after the write, so the payload carries what was actually stored. |
includes/services/notifications.php |
task.assigned registered, default on, entity task. |
workflow/includes/engine.php |
Registered as a trigger with its payload fields, so workflows can use it. |
lang/en, lang/de, lang/es common.php
|
The bell line and the Preferences switch label. |
includes/notifications_router.php |
Unchanged. It already knew how to find a task's recipient and how to describe it. |
entityLink() |
Already returned the right address, and assets/js/tasks.js already opens ?task=N into the detail panel. |
| The Preferences screen | Builds its switches from the registry, so the new switch appeared without being added. |
task.created staying off by default |
Right, and untouched. A bell for every task raised is the noise the default exists to prevent. |
The negative controls matter more than the positive one here, because the way a new notification goes wrong is by being chatty. Driven through the real endpoint against a running install:
| Action | Expected | Result |
|---|---|---|
| Create a task assigned to another analyst | Notify them | Notified |
| Reassign it to a second analyst | Notify the new one | Notified |
| Assign it to yourself | Nothing | Nothing |
| Save again, same assignee | No second notification | None |
| Clear the assignee | Nothing | Nothing |
| Change only the title | Nothing | Nothing |
Then from the recipient's side, which is the half that actually matters to the person who reported it: the badge count rose, the row was present, and its link read tasks/?task=88. Both new labels were confirmed to reach the browser - a missing translation would have degraded to a bare name rather than failing loudly - and the new switch appears, checked, on the Preferences page.
Finally a live run by a second person, which is what closed it: a task raised by one analyst and assigned to another, while that person sat in a different module doing something else. The bell chimed on its own, the notification arrived without a reload, and clicking it opened the task itself.
The chime is worth noting as evidence rather than decoration. It only sounds when the unread count rises against a baseline recorded earlier in that tab - so hearing it proves the count genuinely changed while the page was open, not merely that a row existed in the database somewhere.
Assign a task to somebody and they are told, whether you assign it as you create the task or hand it over later. The notification names who assigned it, and clicking it opens the task.
It is on unless you turn it off, under Preferences β Notifications, where it sits beside the ticket equivalent.
You are never notified about your own actions, so assigning work to yourself stays quiet.
If you would rather this drove an email as well as the bell, task.assigned is now available as a workflow trigger.
FreeITSM β an open-source IT Service Management platform Β· github.com/edmozley/freeitsm Β· MIT licence
- Installation
- β° Scheduled tasks (cron jobs)
- Architecture
- AI Providers
- Internationalisation (i18n)
- Timezones & Time Handling
- π Date & Time Formats
- Theming & Dark Mode
- β¨οΈ Command palette (βK)
- π Searching inside tickets
- π Attached documents
-
MobileβFriendly
- β³ π« Mobile: Tickets
- β³ π» Mobile: Assets
- β³ π Mobile: Calendar
- β³ π Mobile: Knowledge
- β³ π¦ Mobile: Service Status
- β³ πΌ Mobile: Watchtower
- β³ π§© Mobile: Problem Management
- β³ π Mobile: Change Management
- β³ πΏ Mobile: Software
- β³ β Mobile: Tasks
- β³ π§° Mobile: Techniques & Tricks
-
Security
- Layer 1 β which modules you can enter
- β³ π§© Module Access Control
- β³ π οΈ Module Access β Developer Guide
- Layer 2 β what you can administer
- β³ π Roles & Permissions
- β³ π οΈ Roles β Developer Guide
- β³ π€ Why capabilities are constants
- Layer 3 β the System module
- β³ π Admin Access Control
- Hardening
- β³ π Security review response 2026-08
- β³ π‘οΈ Security hardening 2026-08
- β³ π οΈ Security hardening 2026-08 β Developer Guide
- β³ π‘οΈ Round three β plain English
- β³ π οΈ Round three β Developer Guide
- Single Sign-On (SSO)
- ποΈ LDAP & Active Directory
- Browser Extension
- API Reference
-
π REST API β how it works
- β³ π« REST API: Tickets
- β³ π» REST API: Assets
- β³ π΄ REST API: Problems
- β³ π REST API: Changes
- β³ π REST API: Knowledge
- β³ β REST API: Tasks
- β³ ποΈ REST API: CMDB
- β³ π REST API: Contracts
- β³ ποΈ REST API: Calendar
- β³ πΏ REST API: Software
- β³ π¦ REST API: Service Status
- β³ βοΈ REST API: Morning Checks
- β³ π REST API: Forms
- β³ βοΈ REST API: Workflow
- β³ πΊοΈ REST API: Network Mapper
- β³ π§ Using the API docs page
- β³ π OpenAPI specification
- β³ β OpenAPI: kept correct
- β³ π οΈ Maintaining the catalogue
- Watchtower
-
Tickets
- β³ Mailbox Authentication
- β³ π€ Email send log
- β³ Basic IMAP mailboxes
- β³ Email rendering & images
- β³ SLA Management
- β³ WhatsApp channel
- β³ π¬ Web chat channel
- β³ π£ Slack channel
- β³ π Linking tickets
- β³ π Ticket notes: internal or shared
- β³ ποΈ Canned responses
- β³ βοΈ Limiting replies to particular senders
- β³ βοΈ Email signatures
- β³ π The public web address
- β³ π’ Ticket numbering
- β³ π Raising a ticket for someone else
- β³ π Merging tickets
- β³ β Splitting tickets
- β³ β Selecting several tickets
- β³ ποΈ The folder pane
- β³ π οΈ Snoozing tickets β Developer Guide
- β³ π₯ Collision detection
- β³ β±οΈ Time tracking
- β³ π Scheduled work in your own calendar
- Problem Management
- Tasks
- Assets
- Knowledge
- Change Management
- Calendar
- Morning Checks
- Reporting
- Software
- Forms
- Contracts
- Service Status
- π Notifications
- π¨ War Room
- Self-Service Portal
- LMS
- Process Mapper
- CMDB
- Network Mapper
- Workflows
- Issue trackers (Jira, Azure DevOps)
- System
-
Overview
- β³ π Progress tracker
- β³ Concepts & vocabulary
- β³ Email routing & mailboxes
- β³ Settings: global vs per-company
- β³ Users & self-service
- β³ Staff cross-company access
- β³ Worked examples
- β³ Pitfalls & gotchas
- β³ Scope: what it's for
- β³ π οΈ Developer Guide (make a module multi-company)
- β³ ποΈ Case study: CMDB (a linked graph)
- β³ π§ͺ Test harness (prove it's isolated)