# Business rules — quantivia

Evidence date: 2026-10-05. Source: `git@bitbucket.org:overdrive/quantivia.git`, `master` at `c567977`.

Rules below are taken from code and from the in-app user guide. Each rule is marked **Documented** or **Inferred** when it is not a literal statement in a comment, message, or guide. No rule was added because it "should" exist.

`development` was not read. Rules that exist only on that branch are **Unknown**.

## Identity and access

### BR-001 — Quantivia requires an eGroupWare session

**Implemented.** `quantivia/index.php` and `quantivia/main.php` redirect to the eGroupWare index when `sessionid` is missing. `main.php` also redirects when `last_loginid` is missing. `common_functions.inc.php` returns HTTP 403 if `sessionid` is missing.

Provenance: Implemented behaviour.

### BR-002 — Site Admin is the eGroupWare `Admins` group, or user id `-1`

**Implemented.** `is_user_admin()` returns true for members of group `Admins` and for `$u_id == '-1'`. The comment says this allows worker processes to function. `get_uid()` returns `-1` when `$_SESSION['worker']` is set, before it looks up the username.

Provenance: Implemented behaviour. The `-1` bypass is **Inferred** to be a service account, from that comment.

### BR-003 — Project roles are eGroupWare groups plus one administrator column

**Implemented.**

| Check | True when |
|---|---|
| Project user | Member of group `P_{p_id}`, or member of `P_{p_id}_admin` |
| Project admin | Member of `P_{p_id}_admin`, or `projects.administrator` equals the user id |
| Progress admin | Member of `P_{p_id}_p_admin`, or member of `P_{p_id}_admin` |
| Programme user | Member of the eGroupWare group whose name equals the programme name |

Missing user id or project id returns false (except site admin, which only requires a user id).

Provenance: Implemented behaviour (`class.quantivia_so.inc.php`).

### BR-004 — Denied pages stop with HTTP 401

**Implemented.** `checkCurrentUserAutherization()` returns immediately when the matching role is allowed. Otherwise it prints one of:

- "Access Denied: User does not have site administration rights"
- "Access Denied: User does not have project administration rights"
- "Access Denied: User is not a member of this project."
- "Access Denied: This feature is locked for all user types."

Then it returns HTTP 401 and exits. Progress-admin allowance is tested first.

Provenance: Implemented behaviour (`common_pageSetup.php`).

### BR-005 — Menu visibility follows role

**Implemented.** Comments and conditions in `services/Menu.php`:

- Dashboard (and calendar, when extended features are on) for project admin or view user.
- Site admin menus include Project List, Users Admin, and Programme Admin.
- Tracking Admin and Theme Admin are project-admin items.
- Wizards are limited to project admins.
- Change management is limited to project admins. The change register is available to project admins and view users (comment in `Menu.php`).

Provenance: Implemented behaviour. The comment is **Documented** inside the menu file.

## Project lifecycle

### BR-006 — Three statuses, derived, not chosen from a free list

**Implemented.** `what_is_project_status()` returns:

| Status | Condition |
|---|---|
| `define` | Config `P{id}_budget_locked` is not set |
| `control` | Budget is locked and there is no open change instance |
| `change` | Budget is locked and an open change instance exists |

The function comment states the return is one of `define`, `control`, `change`.

Provenance: Implemented behaviour. **Documented** in the function comment.

### BR-007 — Structure edits lock in control; progress edits require control

**Implemented.** Menu disable messages:

- "A deliverable upload cannot be done while the project is in the 'Control' status."
- "A chain assignment upload cannot be done while the project is in the 'Control' status."
- "A schedule upload cannot be done while the project is in the 'Control' status."
- "A Resource update can not be done while the project is in the 'Control' status."
- "A progress upload can only be done while the project is in the 'Control' status."
- "Actual hours cannot be updated while the project is not in the 'Control' status."
- "A report cannot be published when the project is not in the 'Control' status."

`class.quantivia_bo.inc.php` returns false for schedule changes when status is `control`, and can return the string "Project locked, use change control".

Provenance: Implemented behaviour. The messages are **Documented** in code.

While status is `define`, date writes are treated as the initial setup. While `change`, from/to values are recorded on the change. Provenance: Implemented behaviour (comments in the BO).

### BR-008 — Change instances are Open or Closed

**Implemented.** `read_change_instances()` maps `open_status` to the labels `Open` and `Closed`. Closed-by and closed-on fall back to `n/a`.

Provenance: Implemented behaviour.

### BR-009 — Graphs and most tabular reports need a published report

**Implemented.** Menu items for S-curves, bulls-eye, trend, FTE, Pareto, latency, standard reports, progress overview, and progress forecast show "No published reports exist." when the condition is true.

Resource S-curves and the two resource tabular reports pass `false` into that disable check, so they are not disabled by the "no published report" condition in this file.

Provenance: Implemented behaviour. **Inferred:** resource reports are intentionally available before the first publish. The code does not say why.

## Progress updates

### BR-010 — Progress package statuses

**Implemented.** `quantivia_bo::$view_statuses`:

| Code | Label |
|---|---|
| 0 | Invalid |
| 1 | Issued |
| 2 | Submitted |
| 3 | Reviewed |
| 4 | Archived |
| 5 | Rejected |
| 6 | Void |
| 7 | Proposed To Delete |
| 8 | Expired |
| 9 | Invalid |

Both 0 and 9 are labelled Invalid. Provenance: Implemented behaviour. Why two codes share the label is **Unknown / Requires Confirmation**.

Email subject lines include the status label. Provenance: Implemented behaviour (`class.quantivia_bo.inc.php`).

### BR-011 — Stale archive data is ignored on publish

**Documented** in active changelog `2.0.012`: "System ignores data in archives when publishing if actualy stale". The implementing function was not re-read line by line. Confidence: Medium.

## Calculation and configuration options

These are the option sets the BO exposes. Selection is stored per project. Exact persistence column names were not all traced.

| Rule | Allowed values | Provenance |
|---|---|---|
| BR-012 Timekeeping method | Structured, Detailed, None | Implemented (`$time_keeping`) |
| BR-013 Budget overflow | Remaining Budget, Current Budget | Implemented (`$budget_overflow`) |
| BR-014 Reporting method | RAMP (Ramp Method), STEP (Step Method) | Implemented (`$reporting_method`). User guide has an "Earning Methodology" topic (**Documented**) |
| BR-015 Reporting retention | Last 1, 3, 10, 25, 50, 100, or All (999) | Implemented (`$reporting_retention`) |
| BR-016 Forecasting method | Original Duration, Current Trend, Remaining Duration | Implemented (`$forecasting_method`) |
| BR-017 EAC method | Budget Rate; CPI; CPI and SPI compounded; CPI and SPI (80:20) | Implemented (`$eac_method`) |
| BR-018 S-curve / Gantt order | Alphabetical, or chronological by plan start, plan end, actual start, actual end, or ascending budget | Implemented (`$gantt_order`) |
| BR-019 Date display | `yyyy-mm-dd`, `dd-mm-yyyy`, `dd-mmm-yy`, `dd mmmm yyyy` | Implemented (`$date_display_options`) |
| BR-020 Pre-populate | No or Yes | Implemented (`$pre_populate_options`) |
| BR-021 Units of measure | Coded list (each, metres, kilometres, inches, feet, square metres, and further units in the same array). Base assumptions in the comment: length/area/volume in metres, mass in kg, time in days | Implemented. The base-unit sentence is **Documented** in the class comment |

### BR-022 — Actual Hours Structure only for Structured timekeeping

**Implemented.** If the project time method is not Structured, the menu item is disabled: "This menu option can only be used on projects with Structured time keeping."

### BR-023 — Reporting window defaults

**Implemented** in `quantivia_setings.php`: `report_period` is `4` and `time_report_period` is `4`. Comments say both are weeks, the second being the window for auto-allocating to open control points. Provenance: Implemented configuration. Whether every project can override the 4-week default is **Unknown / Requires Confirmation**.

### BR-024 — Calendar and quantity flags are per project

**Implemented.**

- Extended features: config `P{id}_extended_features`. Menu shows Calendar only when this is true.
- Quantity count: config `P{id}_qt_count`. Portfolio id `-1` returns false. Missing or non-positive values return false.

License type `E` sets `$_SESSION['Elicensed']`. License type `Q` sets `$_SESSION['Qlicensed']`. How those session flags relate to the per-project config attributes was not fully traced. **Unknown / Requires Confirmation** whether a license flag alone turns calendar on.

## Licensing

### BR-025 — Unlicensed installs stay in demonstration mode

**Implemented.**

- `licensed` starts false.
- If a license MAC matches a local MAC and `L_DOMAIN` equals `SERVER_NAME`, `licensed` becomes true.
- If no company is in the license constants, `L_COMPANY` is "Unregistered - Demonstration Only !".
- If `N_PROJECTS` is missing, the session project count is 0.
- `requireFullLicence()` returns HTTP 401 and "This system is in Demo mode, and can not use this function" when `licensed` is false.

Provenance: Implemented behaviour.

### BR-026 — Named hosts are treated as fully licensed

**Implemented.** For these `SERVER_NAME` values the code sets `N_PROJECTS` to 25, `L_COMPANY` to `Procon8`, and `licensed`, `Elicensed`, and `Qlicensed` to true, without a MAC match:

`demo.quantivia.com`, `colab.procon8.com`, `sdev.quantivia.com`, `sdev.procon8.co.za`, `sdev.procon8.com`, `quantivia.local.com`, `online.quantivia.com`, `online.quantivia`, `10.0.1.5`, `localhost`, `127.0.0.1`.

The comment calls this an exception for development environments. Several of the names are not obviously development hosts. Provenance: Implemented behaviour. Whether this list is still approved is **Unknown / Requires Confirmation**. It is not restated here as a desired business rule.

### BR-027 — Project count on the license

**Documented** in `who_is_who_in_the_zoo.php`: `$_SESSION['N_PROJECTS']` is the number of projects licensed. Enforcement of that cap (where a create would be refused) was not located in the sections read. **Unknown / Requires Confirmation** where the cap is applied.

## Time and files

### BR-028 — System time is UTC, with a 2038 ceiling

**Implemented.** `date_default_timezone_set("UTC")`. `$_SESSION['maxtime']` is `2147472000`. The comment says this must be midnight so tables still translate when seconds are not stored.

### BR-029 — File retention is on in the committed settings

**Implemented.** `file_retention` is true. `file_storage` is `C:\wamp64\www\html`. Temp files use that path when set, otherwise the system temp directory. Provenance: Implemented configuration for this snapshot. Whether production uses this path is **Unknown / Requires Confirmation**.

## Companion-app status lists

These lists live on the Quantivia BO even though the trackers have their own apps. Provenance: Implemented behaviour. Whether the tracker UIs use these exact maps was not confirmed.

| Domain | Values |
|---|---|
| Tickets | Open, Closed, Deleted, Pending, Verify (codes `-100` to `-104`) |
| Risks | Raised, Closed, Canceled, Acknowledged (codes `-100` to `-103`) |
| Risk severity | High (100), Moderate (50), Low (10), Unknown (-1) |

Risk setup description says the tracker follows QUAL 321-00022131. Provenance: **Documented** in `risk/setup/setup.inc.php`. The text of that quality document is not in the repository.

## Worker task types

**Implemented** in `worker.php`. **Inferred** labels are the code comments:

| Type | Comment in code |
|---|---|
| 0 | Maintenance (archive logs, service user views) |
| 1 | Deliverables import |
| 2 | Assignments import |
| 3 | Schedules import |
| 4 | Deliverable progress import |
| 5 | Time import |
| 6 | Publishing |
| 7 | Deliverables download |
| 8 | Assignments download |
| 9 | Schedules download |
| 10 | Progress download (activity or deliverable turnaround) |
| 11 | Time download — body empty |
| 12 | Complete download |
| 13 | Resources download |
| 14 | Resource upload |
| 15 | Resource actuals upload |

## Rules explicitly not inferred

- No pricing, contract, or customer-entitlement rule was found beyond the license constants.
- No data-retention period in days was found beyond the boolean `file_retention` and the "Last N" report retention options.
- No rule was found that says which template pack a client must use. Packs are selected through session template name and Theme Admin.
