# Employees plugin - directory database contract Read-only lookups against a **separate** employee/HR directory database. Powers: - Employee search (add people to a notification, browse the directory) - Single + batch SSO lookup - Recognition notifications (name + photo on the shopfloor / lobby displays) The plugin never writes to this database. Use a read-only account. ## Connection Credentials resolve **settings-first, then environment**, except the password which is env-only (never stored in the app database). | Field | Setting key (editable in the setup wizard) | Env var (fallback) | | -------- | ------------------------------------------ | ---------------------- | | Host | `employee_db_host` | `EMPLOYEE_DB_HOST` | | Database | `employee_db_name` | `EMPLOYEE_DB_NAME` | | User | `employee_db_user` | `EMPLOYEE_DB_USER` | | Password | (not stored) | `EMPLOYEE_DB_PASSWORD` | Set the password in `.env`; the setup wizard's Features step shows the exact line to paste. Engine is MySQL/MariaDB (pymysql). ## Required schema The plugin runs these queries verbatim, so a site's database must expose a table (or **view** - see below) named `employees` with these columns: | Column | Type | Notes | | ------------ | ------------------- | ------------------------------------------------- | | `SSO` | INT | Unique person id. Lookups require it to be numeric | | `First_Name` | VARCHAR | Displayed as the given name | | `Last_Name` | VARCHAR | Displayed as the surname; sort key | | `Team` | VARCHAR | Team / group label | | `Role` | VARCHAR | Job title / role | | `Picture` | VARCHAR | **Image filename** (see Photos) | Queries actually executed: ```sql -- search SELECT SSO, First_Name, Last_Name, Team, Role, Picture FROM employees WHERE First_Name LIKE %s OR Last_Name LIKE %s OR CAST(SSO AS CHAR) LIKE %s ORDER BY Last_Name, First_Name LIMIT %s; -- single / batch SELECT SSO, First_Name, Last_Name, Team, Role, Picture FROM employees WHERE SSO = %s; SELECT SSO, First_Name, Last_Name, Team, Role, Picture FROM employees WHERE SSO IN (...); ``` Rows are returned to the API **with these exact column names**. The frontend (EmployeeSearch, NotificationForm, EmployeeDetail, ShopfloorDashboard) reads `SSO`, `First_Name`, `Last_Name`, `Team`, `Role`, `Picture` as-is - do not rename them in the response. ## Photos `Picture` holds an **image filename** (e.g. `123456.jpg`), not a path or blob. The app renders it as `/static/employees/`, so the image files must live in the app's `static/employees/` directory. Leave `Picture` empty/NULL for people with no photo; the UI falls back to initials. ## Adapting a different site schema (recommended: a view) Sites whose HR/directory database uses different table or column names should **not** be forced to rename anything. Instead, create a read-only **view** named `employees` that maps local columns to the names above: ```sql CREATE VIEW employees AS SELECT person_id AS SSO, given_name AS First_Name, surname AS Last_Name, department AS Team, job_title AS Role, photo_filename AS Picture FROM hr_people WHERE active = 1; ``` Grant the app's read-only user `SELECT` on the view. No app code changes - point `employee_db_*` at that database and the plugin works. Notes: - `SSO` must be numeric (single/batch lookup validate `isdigit()`). - Column-name case follows your database's identifier casing; match the names above exactly on case-sensitive platforms. - If the directory is unreachable or the `employees` object is missing, lookups return a 500 and the rest of the app keeps working (the feature degrades, it does not crash the app).