# Document Management System (DMS)

The DMS centralises file storage and collaboration for all modules including Recruitment and Case Management. It exposes REST endpoints under `/api/documents` and related controllers.

When working on a module, run the tests for that module. Full or integration suites are only required when specifically requested. As modules are refactored, update or extend their tests accordingly.

## 1. File Storage & Connectivity

The service supports multiple storage drivers at once. Connectors are configured globally or per tenant in the `storage_connectors` table. Uploads can be saved to several destinations simultaneously.

- Local server directories.
- NAS or file servers.
- Cloud object stores (Amazon S3, Azure Blob, DigitalOcean Spaces etc.).
- Multi-destination uploads for redundancy.

Settings are managed from the admin screens and loaded by `StorageFactory` within `DocumentService`.

## 2. Document Organization & Management

Documents belong to folders using a hierarchical `document_folders` table and may be assigned to a `document_categories` entry. Each upload automatically extracts basic metadata (author, type) into `document_metadata`.

Additional metadata can be attached via `POST /api/documents/add-metadata/{id}` with a JSON body
like `{ "key": "department", "value": "Finance" }`. The metadata entry is stored
for the latest document version.

Version history is handled by `DocumentVersioning` and stored in `document_versions`. Standard CRUD endpoints allow creating, updating and deleting documents or folders.

## 3. Sharing & Collaboration

Permissions are recorded in the `document_permissions` table. Users can be granted view, edit or comment rights. Comments are stored in `document_comments` and activity is logged via `AuditLogger`.

Notifications fire whenever a document is shared or commented on so recipients stay informed.

## 4. Document Viewing and Preview

The controller exposes `/api/documents/{id}/preview` which generates a pre‑signed URL for the latest version. The preview page integrates PDF.js for zooming and navigation without downloads. To obtain the file directly, call `GET /api/documents/download/{id}` which streams the latest version. Use `/preview` for in-browser viewing and `/download` for an actual download.
When the previewed document is a ZIP archive, the first access extracts a list of
contained files and stores their names and MIME types in the `document_archive_entries`
table. Subsequent requests fetch the cached list so the archive is only downloaded
again when an individual file is streamed.

### Folder Management UI

`FolderManager.js` renders a tree view of folders using DaisyUI `tree` styles. Users can create, rename or delete folders through modal dialogs. The module talks to `DocumentFoldersController` for all CRUD operations. `DocumentsWidget` mounts the folder manager automatically so selecting a node filters the document table by that folder.

Each row in the documents table now includes a **Comments** button. Clicking this action opens a modal that displays all previous comments and provides a form for adding a new one. This lets users discuss a document without leaving the module.

## 5. Centralized Configuration

Super admins define global defaults while branch admins may override storage settings per tenant. The admin UI persists these options to `storage_connectors` so `DocumentService` can resolve them.

## Running DMS Tests

Prepare the environment with the helper script and then run the tests manually.
Choose the database by setting `DB_DRIVER` (e.g. `mariadb`, `pgsql`, `oci`, `mongo`):

```bash
DB_DRIVER=mariadb ./test_setup.sh
phpunit -c api/phpunit.xml
jest
```

Only execute the DMS tests when modifying this module unless a full run is requested.

## Document Expiry

Documents can include an optional `expiry_date` column. A scheduled job
`document_expiry.php` checks for records where the expiry date is near or has
passed. Owners receive reminder notifications and workflow events
(`document.expiringSoon`, `document.expired`) are emitted so other workflows can
react automatically.

The document upload modal now includes an **Expiry Date** field. The selected
date is sent to `/api/documents` and stored with the record. Documents can be
filtered by expiry range in `DocumentsWidget` using the new date inputs above the
table. A dashboard card labelled *Expiring Documents* opens the module
`Documents/Expiring.js` which queries `/api/documents?expiry_date<=YYYY-MM-DD`
to list items approaching expiry.
Documents may also be filtered by `category_id` or a specific tag using the
drop-downs exposed by `DocumentsWidget`.

