Department silos
Combodo's customers only
- name:
- Department silos
- description:
- Ticket segmentation between delivery organizations
- version:
- 1.0.5
- release:
- 2026-08-19
- itop-version-min:
- 3.2.0
With this extension, you can ensure that your IT department agents won't be able to see HR related UserRequest and Incidents Tickets and vice versa.
Usecase
Different departments in your company want to use iTop, but each
department wants their agents to be the only one to see the Tickets
related to their business.
Out of the box, iTop does not offer this possibility. This
extension enables this, by changing UserRequest and Incidents
Tickets.
Features
Multiple departments can handle in iTop console, the Tickets which must be managed by their department.
-
Users are not able to see Tickets for other departments than their own.
-
Compatible with Simple Ticket Management and full ITIL.
Revision History
| Release Date | Version | Comments |
|---|---|---|
| 2026-08-19 | 1.0.5 | * N°8277 - Handles case where service_id is moved
to Ticket class * N°8850 - Fix UR portal creation and Incident created with wrong owner organization * N°9140 - Set Event callback methods as public * N°9926 - Declare this extension as not removable (no uninstall option) |
| 2025-10-10 | 1.0.4 | * N°8454 - Conflict between Department
Silos and Global Demand * N°8498 - Migrate UserRequest/Incident OnInsert/OnUpdate into event within Silo * N°6799 - Install even without EN or FR dictionaries Cautious: it stops renaming service_org_id into org_id |
| 2023-07-17 | 1.0.3 | N°5807 - API: Remove SetupPage:log* for iTop 3.1 compatibility |
| 2022-11-18 | 1.0.2 | First published version |
Limitations
-
It's not possible to dispatch a wrongly routed Ticket to another Department, the requestor/caller must create himself another ticket under the right service
-
Callers can only create and see their Tickets through the User Portal.
-
Even agents users must use the User Portal to handle Ticket for themselves (except tickets for their own department)
If you use iTop 2.7.6 or older, there is an known issue with
Notification, which are not triggered unless their
filter is empty.
Requirements
-
Ticket management must be enabled.
-
The minimum required version for Approval Process Automation, if used, is 2.1.1.
Installation
Before
Otherwise, those Tickets won't be readable after installation!
Organization / org_id Ticket field1) If you have customized UserRequest and Incident presentation, mirror those changes:
-
Search & List: Replace
org_idbycustomer_id -
Details: Replace
org_idbycustomer_id(Ticket creation in console crashes iforg_idis displayed in the form)
2) If you have customized UserRequest and Incident methods OnInsert() / OnUpdate(), add this line of code to those functions:
- UserRequest / Incident :: OnInsert() / OnUpdate()
-
$this->Set('org_id', $this->Get('provider_id'));
3) With version 1.0.3, if you have added an
org_id field on ServiceSubcategory,
you should remove it as it will conflict with the one brought by
this extension, as it renames the service_org_id field
into org_id to make it treated by iTop as a silo
boundary.
With version 1.0.4, there is no rename of org_id
field, so no conflict. The rename was removed because as it was
generating a conflict with Global Demand extension.
In both versions Service Subcategories are visible only to users
having the service organization in their Allowed
organizations or having no Allowed
Organizations.
4) If you have customized the Ticket scopes in portal, make sure the Portal User can still see his own Tickets, and that the Portal Power User can see the Tickets he should.
Install
Use the Standard installation process for this extension.
DataModel changes
-
For class Ticket, it adds a computed
customer_idfield corresponding to the Organization of the Caller.-
French label of
org_idchanged from “Client” to “Organization” as it's no more the client on User request and Incident
-
-
For class UserRequest and Incident, it adds a computed
provider_idfield corresponding to the Organization of the Service. -
For class UserRequest and Incident, it forces the
org_idTicket field to be filled with theprovider_id-
During the Setup/MTP of the first installation of this extension
-
When the Ticket is created and each time it is updated.
-
-
For class Service Subcategory, rename
service_org_idintoorg_id→ so the silo applied (otherwise all service subcategories are visible by everyone) -
Change Ticket scopes in User Portal, to allow a simple Portal User with “Allowed organizations” limited to his own organization, to still see his own Tickets.
-
If you install this extension on an already in use iTop with Dashboards, Notifications, QueryPhrases, WebHook, API Rest or Excel reporting on UserRequest or Incident classes, be aware that you may have to rework them as the Ticket.org_id field no more contains the Customer but the Provider for the corresponding service.
UI changes
In the details of UserRequest & Incidents
-
“Organization” label is replaced by “Customer”.
-
“Customer” (
customer_id) field is not editable. It's always the Organization of the “Caller”. -
A new “Provider” (
provider_id) field not displayed in details and not editable. It contains the Provider of the Service -
“Organization” (
org_id) field is not displayed in the details, not editable and automatically fed with the “Provider” value.
In search banner of UserRequest & Incidents
-
“Organization” default search criteria was replaced by “Customer”
-
“Provider” can be used as a Search criteria,
In “Configure this List” for UserRequest & Incidents
-
“Provider” can be displayed,
-
“Organization” contains the same information as “Provider”
Search banner of Ticket
-
“Organization” is proposed by default but it does not correspond to the Customer anymore for User Request and Incident
-
The French label for
org_idwas changed from “Client” to “Organisation” to align to the English naming
Configuration
No configuration parameters
Usage
Setup
The purpose of this extension, is to separate User Request and
Incidents into silos, based on which organization is delivering the
Service.
Out of the box, User Request and Incidents are siloed by
customer.
To work as expected you must organize your data in a certain way:
-
Create separate organizations for each independent provider managing Tickets
-
Create separate organizations for each customer which must be visible to all providers agents
-
Decide under which organization you must put each object, so it is hidden/visible to the appropriate users
-
Give access to each user to the Organizations that they need to see and not more (User tab
Allowed Organizations)
Below 2 examples which are pretty common:
Single company
Goal: Ensure that the IT department agents won't be able to see HR related UserRequest and Incidents Tickets and vice versa.
In order to use this extension, you must modify the organizations and the owner organization of some objects.
-
Create a company organization and put all shared company objects under that organization:
-
Locations
-
Teams & Persons
-
Contracts
-
Public/shared CIs
-
-
Create the different Departments as separated iTop Organizations,
-
but leave their
Parentempty, Putting them under the main company would break the Silos, as iTop logic is to enable access to all sub-organizations of the UserAllowed organizations, and that behavior can not be changed. -
Defines catalog of Services within each of those organizations
-
Defines private CIs under the Department in charge of handling them in a silo. Such CIs cannot be seen in the console by people outside of the Department.
-
-
Create one or multiple contracts under the main company to buy the services provided by the various departments
-
Assuming you have IT and HR agents, ensure that they all have
Allowed organizationsset on their iTop user. They must be allowed on their contact organization (this is an iTop portal requirement) and on their department organization, as well as on all their customers organizations.
-
As a result, all employee must use the User Portal to request services to other departments than their own, but once in the console, they are limited to the Tickets which are linked to a Service that they are responsible for.
Service Provider
Goal: Have different providers delivering services to different customers, but seeing in the console, only the Tickets related to the services that they deliver.
For example, a company with multiple departments providing different services to other companies and each Department must only see the Tickets they are responsible for:
Check the steps described above for a “Single company” and adapt it
-
There is a Provider Company with 3 Departments needing to work in Silos
-
None of the Department will have the “Provider Company” as its parent (same reason as described above in “Single company” model)
-
Theirs customers can be the same or different
-
The customers Tickets must only be seen by the Department handling them
-
Here we have imagined that the “Loan Department” does not deliver any services to “Client #2”, which explains why its Users do not need to see “Client #2” organization
Each Department users, must have theirs customers in their “Allowed Organizations”, which can be an administrative burden, if there are a lot of agents and/or a lot of customers on-boarding. But if all customers can be visible to all company departments employee, then it's easier: Define a generic “My-Customers” organization as parent of every true customers organization and just put the “My-Customers” organization in the “allowed organizations” of all your departments employees and job done.
Change of behavior
There is no visual change to the User Portal, but scopes to let callers see their own tickets, as they are no more under the user organization. Ticket's organizations are not guaranteed to be in the user “Allowed organizations” anymore.
In the Console for User Request and Incident, the Customer can no more be selected, it is computed from the Caller.
Questions & Answers
Misrouted ticket
Q: I want that my IT department agents can reroute to a
HR department service, a misrouted Resquest?
A: It is possible to workaround this limitation
but requires a bit more customization:
1) Add a provider_id ExternalKey on class
Service,
2) Add some dictionary entries for this new field,
3) Move all Services under an organization which is visible by all
agents regardless of their department, and set them a
provider_id field to reflect the silo
department
4) Change on Incident and UserRequest classes the field
provider_id to refer that new provider_id
service field instead of the org_id
- itop-design | classes | class@UserRequest | fields
-
<field id="provider_id" xsi:type="AttributeExternalField" _delta="must_exists"> <extkey_attcode>service_id</extkey_attcode> <target_attcode _delta="redefine">provider_id</target_attcode> </field>
But this lead to another issue, any user allowed to modify the
Service of a given department, will be able to modify those of
other departments, as they would all be under organizations that
everyone must be able to see.
In iTop if you can modify a class, then you can modify all
objects of that class that you can see.
A CheckToWrite and CheckToDelete can prevent this, using a piece of PHP code, controlling that a user belongs to the appropriate department before modifying/deleting a given Service
Silos on Contracts
Q: I want to avoid that an IT department person can
modify customer contract where the provider is the HR
department.
A: This is possible but requires a bit more
customization:
1) Add a customer_id ExternalKey on class
Contract,
2) Replace org_id by customer_id everywhere in the presentation of
the CustomerContract and ProviderContract classes
3) Write some OnInsert and OnUpdate methods to copy in the
org_id either the customer_id or the
provider_id for ProviderContract and CustomerContract
respectively.
4) Add some dictionary entries so org_id is the
“Contract Owner” and customer_id is the
“Customer”
5) After Setup / MTP run 2 SQL queries on contract table (either within the extension or manually)
-
the first one to initialize
customer_idwith theorg_idon All Contracts
UPDATE `contract` SET `contract`.`customer_id` = `contract`.`org_id` WHERE `contract`.`customer_id` = 0
-
the second to change the “Contract owner” to be the “Provider” only for CustomerContract
UPDATE `contract` SET `contract`.`org_id` = `contract`.`provider_id` WHERE `contract`.`finalclass` = 'CustomerContract'
Department on Person
Q: I want to know the department of each Person, but if
I move the Person under his “HR Department”, IT users won't see
him. How can I do?
A: Add a department_id ExternalKey to
the Organization class, to specify the optional sub-organization of
the user
Q: I want to be sure I set the correct Allowed
Organizations to each User. How can I do?
A: The best would be to add a method on User to
automatically add the department_id and the
org_id to the allowed organizations of
the User, if it was possible 😦
The problem is that it is not possible to plug a method on User class for now…
-
That would avoid that a user is created without “allowed organizations” by mistake or without access to the Department they are working for
-
Adding “Allowed organizations” on Users with profile “Administrator” has no effect, as iTop ignores them, so it could be done for every users without side effect.
SLA and SLT
Q: Does it impacts my SLAs calculation?
A: Yes, for this you must modify one thing in 2
places.
:this->org_id must be replaced by :this->customer_id in:
-
The constant
RESPONSE_TICKET_SLT_QUERYin the Designer:
- RESPONSE_TICKET_SLT_QUERY
-
SELECT SLT AS slt JOIN lnkSLAToSLT AS l1 ON l1.slt_id=slt.id JOIN SLA AS sla ON l1.sla_id=sla.id JOIN lnkCustomerContractToService AS l2 ON l2.sla_id=sla.id JOIN CustomerContract AS sc ON l2.customercontract_id=sc.id WHERE slt.metric = :metric AND l2.service_id = :this->service_id /* We get the SLT applicable for the customer defined in the Ticket (:this->customer_id) */ AND sc.org_id = :this->customer_id AND slt.request_type = :request_type AND slt.priority = :this->priority
-
The coverage OQL in iTop Configuration file:
'combodo-sla-computation' => array ( 'coverage_oql' => 'SELECT CoverageWindow AS cw JOIN lnkCustomerContractToService AS l1 ON l1.coveragewindow_id = cw.id JOIN CustomerContract AS cc ON l1.customercontract_id = cc.id WHERE cc.org_id_id= :this->customer_id AND l1.service_id = :this->service_id', 'holidays_oql' => 'SELECT Holiday', ),






