5.9 KiB
name, description
| name | description |
|---|---|
| alis | Build the ALIS (Medtelligent) staff bulk-import .xls (13-column template) for Cascades of Tucson (communityId 622) and read the live staff roster via the read-only API. Triggers: alis, alisonline, medtelligent, alis staff import, add staff to alis, alis security roles. |
ALIS Skill (Medtelligent) — staff import builder + roster reference
ALIS is Medtelligent's assisted-living EHR. This skill exists to create/change staff
(and their logins) in bulk, which in ALIS is done by uploading an .xls in the web UI
(Staff -> Import) — there is no staff-write API. The skill:
- Reads the live staff roster via the ALIS API (read-only) to learn how staff are set up — the security-role and job-role vocabulary, and a job-role → security-role map.
- Builds a correctly-formatted import workbook from your CSV/JSON of new hires, inferring each person's Security Roles from that reference so new staff match existing ones. You upload it in ALIS and fine-tune there.
Running the CLI
PY="bash $CLAUDETOOLS_ROOT/.claude/scripts/py.sh"
ALIS="$PY C:/claudetools/.claude/skills/alis/scripts/alis.py"
# --- read (reference) ---
$ALIS auth-test # mint token, confirm scope
$ALIS communities # communityId(s) in scope (Cascades = 622)
$ALIS staff --status Hired --limit 20 # roster
$ALIS roles # live security + job role vocabulary
$ALIS role-map [--refresh] # jobRole -> securityRole(s), learned from Hired staff
# --- build (the deliverable) ---
$ALIS template --out new_staff.xls # blank, exactly-formatted template to hand-fill
$ALIS build-import --input hires.csv --out import.xls # NEW staff (create format)
$ALIS build-import --input hires.csv --out import.xls --gen-passwords # also mint logins
$ALIS build-import --input edits.csv --out upd.xls --format update # edit existing (ALIS ID)
$ALIS inspect import.xls # dump a workbook to verify before upload
Transport auto-selects httpx if installed, else stdlib urllib. Workbook I/O needs
xlwt (write .xls) + xlrd (read .xls); openpyxl for .xlsx.
Credentials
Never hardcoded. The user login (used to mint a JWT) loads from the SOPS vault:
bash "$CLAUDETOOLS_ROOT/.claude/scripts/vault.sh" \
get-field clients/cascades-tucson/alis-api-howard-user.sops.yaml credentials.username
Auth model (critical, verified live 2026-06-29): POST /user/tokens with
{username, password} returns a JWT (accessToken, ~1h) + refreshToken; send
Authorization: Bearer <accessToken>. The username must be tenant-qualified —
howard.enos@cascadestucson, not bare howard.enos (bare returns HTTP 400). Env overrides
for testing: ALIS_USERNAME, ALIS_PASSWORD, ALIS_BASE_URL, ALIS_COMMUNITY_ID.
The import template (what ALIS expects)
13 columns, exact order — Sheet1 header, then one row per staff. Sheet2 carries the dropdown lists. The builder reproduces both exactly.
| Column | Notes |
|---|---|
| First Name, Last Name | required |
| Staff Record Number | your HR id / match key |
| Security Roles | inferred from Job Role if blank (see role-map) |
| Staff Status | Applicant / Hired / Discharged / Rejected (default Hired) |
| Hire Date | date — format unconfirmed, builder passes your string through |
| Login Enabled | Yes / No (auto: Yes if Email+Password present, else No) |
| required if Login Enabled = Yes | |
| Password | credential — see below |
| Date of Birth, Gender | Gender: Female / Male |
| Job Role | free text; drives Security Role inference |
| Cell Phone |
Input headers are matched flexibly (Job Title→Job Role, Cell/Mobile→Cell Phone,
DOB→Date of Birth, Login→Login Enabled, etc.).
Passwords (handle with care)
- By default the builder does not invent passwords — supply them, or set
Login Enabled = No. --gen-passwordsmints a strong password for each Login-enabled row missing one and writes them to a plaintext sidecar*_passwords.csvnext to the .xls. That file is a credential set: distribute to staff, then delete it or vault it. Never commit it. The terminal output never prints passwords.
Two import formats — create vs update (confirmed from the real export)
ALIS has two layouts; the builder writes either via --format:
- create (default, new staff): columns include Password, no ALIS ID. Rows without an ALIS ID are created as new staff.
- update (existing staff): leads with ALIS ID (the staffId), no Password. Rows with
an ALIS ID update the matching staff member. (This is the format ALIS exports as
ALIS_Staff_Update_Import.xls.)
So the create-vs-update match key is ALIS ID — present = update, absent = create.
Dates are MM/DD/YYYY (confirmed). Security Roles are comma-separated and the builder
infers the full typical combination for a job role (e.g. Med Tech →
Caregiver (Cascades), Medication Tech), learned from current staff in role-map.json.
Still smart to test with ONE row first before a bulk run. Scope: this credential only sees Cascades of Tucson (communityId 622).
Scope reality
The ALIS API has only GET endpoints for staff — no create/update/delete. Do not try to "PUT a staff record"; it does not exist. The .xls upload is the supported write path. (The API does have writes for residents/prospects/billing, out of scope for this skill.)
Files
scripts/alis_client.py— API client (JWT auth via vault, staff/community reads, role-map).scripts/import_builder.py— template spec, input parsing, validation, role inference, password gen, .xls read/write.scripts/alis.py— CLI.references/api-reference.md— endpoints, auth, template, role vocabulary.references/role-map.json— cached job-role → security-role reference (refresh withrole-map --refresh).