An iTop extension to manage Order Requests (German: BANF – Bedarfsanforderung) directly in iTop. Submit purchase requests, route them through approval, and hand over to procurement - all as a specialized ticket with line items.
OrderRequest, extends iTop Ticket)
OrderRequestType (per organization, status = active/inactive)approval_request_date, approved_by_id, approval_date, approval_commentprocurement_referenceOrderRequestLineItem)
line_number (1..n) per orderEA, PT, HUR, LIC, SET, MON, ANNtotal_price_estimated = quantity × unit_price_estimated (read-only)draftdraft, closed, or rejectedlnkOrderRequestLineItemToFunctionalCIestimated_total_cost on OrderRequest computed from line itemsorg_id, an incompatible request_type_id is clearedrequest_type_id is filtered to the same organization (and active types)OrderRequest / OrderRequestType)Ticket)
request_type_id → OrderRequestType (filtered to same org_id, status='active')technical_approver_id, approval_request_date, approved_by_id, approval_date, approval_commentbudget_approver_id, budget_approval_request_date, budget_approved_by_id, budget_approval_date, budget_approval_commentprocurement_referenceestimated_total_cost (decimal, computed)Incident / UserRequest / Problem / Changeline_items (OrderRequestLineItem)order_request_id (FK to OrderRequest)line_number (auto 1..n per order), name, vendor_sku, descriptionquantity (integer, >0), uom (enum: EA, PT, HUR, LIC, SET, MON, ANN)unit_price_estimated, total_price_estimated (RO, computed)functionalcis_list via link classOrderRequestLineItem and FunctionalCIorder_request_line_item_id, functionalci_id)org_id, code, name, status (active/inactive)default_approver_idrequires_budget_owner_approval (boolean)budget_approver_id (optional in general; required if requires_budget_owner_approval = yes)descriptionOrderRequest.status values (with UI styling and icons):
draft → new (fas fa-plus-circle)submitted → active (fas fa-paper-plane)in_review → active (fas fa-search)waiting_approval → waiting (fas fa-hourglass-half)waiting_budget_approval → waiting (fas fa-coins) - only used when the type requires budget approvalapproved → success (fas fa-check-circle)procurement → active (fas fa-shopping-cart)rejected → failure (fas fa-times-circle)closed → frozen (fas fa-flag-checkered)Transitions (user stimuli): submit → review → request approval → approve/reject → procure → close.
On approve the approver and date are recorded; request approval sets approval_request_date.
ev_submit → submittedev_review → in_reviewev_request_approval → sets approval_request_date, moves to waiting_approvalev_approve → sets technical approver & date, moves to approvedwaiting_approval: ev_request_budget_approval → sets approval_date and budget_approval_request_date, moves to waiting_budget_approvalwaiting_budget_approval:
ev_budget_approve → sets budget approver & date, moves to approvedev_budget_reject → sets rejector & date, moves to rejectedev_procure → procurement (prompts for procurement_reference)ev_close → closeddraft.draft, rejected, or closed (can be done from the line item’s detail page even if the LinkedSet widget is read-only).stateDiagram-v2
[*] --> draft
draft --> submitted : ev_submit
draft --> rejected : ev_reject
submitted --> in_review : ev_review
in_review --> waiting_approval : ev_request_approval
waiting_approval --> approved : ev_approve\n(no budget required)
waiting_approval --> waiting_budget_approval : ev_request_budget_approval\n(budget required)
waiting_approval --> rejected : ev_reject
waiting_budget_approval --> approved : ev_budget_approve
waiting_budget_approval --> rejected : ev_budget_reject
approved --> procurement : ev_procure
procurement --> closed : ev_close
rejected --> [*]
closed --> [*]
note right of waiting_approval
Path selection:
- If OrderRequestType.requires_budget_owner_approval = no → ev_approve
- If yes → ev_request_budget_approval → waiting_budget_approval
end note
OrderRequestType)
code, name, set status=activedefault_approver_id (auto-filled on requests)requires_budget_owner_approval = yes and assign budget_approver_idOrderRequest)
estimated_total_cost is computed automaticallyin_review → waiting_approvalev_approve) orev_request_budget_approval → waiting_budget_approval → ev_budget_approve / ev_budget_reject)procurement_reference and move to procurementfunctionalcis_listOnce the request leaves
draft, line items become read-only and not deletable. Once the request is inclosedorrejected, line items become deletable.
This extension exposes lightweight workflow policies via module settings. Defaults are installed from the XML, but any value in config-itop.php takes precedence.
| Key | Type | Default | Description |
|---|---|---|---|
policy_mode |
string (off, warn, enforce) |
warn |
Controls whether policies are disabled, only warn, or block actions. |
approval_restrict_to_assigned_approver |
bool | true |
If enabled, only the assigned approver may trigger Approve actions. |
approval_forbid_self_approval |
bool | true |
If enabled, the requester/caller cannot approve their own request. |
budget_auto_threshold |
int (≥ 0) | 0 |
If > 0, forces the budget approval flow when estimated_total_cost ≥ threshold. 0 disables auto-budget. |
Example in config-itop.php:
// config-itop.php
// ...
'module_settings' => array(
// ...
'br-orderrequest' => array(
'policy_mode' => 'warn', // off | warn | enforce
'approval_restrict_to_assigned_approver' => true,
'approval_forbid_self_approval' => true,
'budget_auto_threshold' => 0,
),
),
off – Policies are ignored.warn – Policies are evaluated and warnings are displayed, but users can proceed.enforce – Policies are blocking (transitions are denied and/or checks fail).ev_approve and ev_budget_approve. Only the user referenced in technical_approver_id or budget_approver_id (respectively) may approve.caller_id) cannot approve (ev_approve / ev_budget_approve).estimated_total_cost meets/exceeds the threshold, the UI hides/directly denies the straight Approve path and steers to Request budget approval instead.The extension was tested on iTop 3.2.2
See Manual Test Plan for end-to-end test steps.
Issues and PRs are welcome.
Please keep close to iTop conventions and include:
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See the LICENSE file or https://www.gnu.org/licenses/agpl-3.0.en.html.
© 2025 Björn Rudner