Lightweight veterinary Laboratory Information System (LIS). The project is under active development.
Hans LIS provides a REST API to manage core entities in a veterinary laboratory workflow:
- Authentication and user management
- Pet owners and their animals (patients)
- Laboratory specimens, tests, and additional services
- Laboratory orders linking patients to tests/services
- Result entry and status tracking for performed tests
- TCP server and protocol handlers for laboratory instrument integration
- Authentication: JWT-based login, protected endpoints, user roles (admin, staff).
- CRUD operations for core entities (owners, patients, specimens, tests, services, orders, results).
- Orders: Create orders for a patient with selected tests and services;
/orders/{id}returns the full order state: specimens, test_runs, service_runs, results. - Specimen tracking: Auto-create runtime specimens (= barcode).
- Results: View and update test results (value, units, flags, status, verification); results are stored separately and linked to test_runs (1:N).
- TCP Server: LIS listens on multiple configurable ports (from YAML configs) and dispatches incoming messages to protocol handlers.
- ASTM Handler: ASTM message handler for query/result processing; accepts R- and Q-records; returns O-records with test lists.
- Audit logging: All CRUD operations are recorded in daily audit logs with user ID and timestamp.
- Instrument Emulator (debug tool): script for testing ASTM communication without a real analyzer (part of astmkit).
- Python 3.13+
- FastAPI
- PostgreSQL 16+
- SQLAlchemy 2.0 (async ORM)
- asyncpg (PostgreSQL driver)
- Alembic (migrations)
- Pydantic v2 (schemas and validation)
- python-jose + passlib (JWT authentication and password hashing)
- Uvicorn (ASGI server)
- Python-dotenv (environment variables)
- Vue 3 + Vite
- PrimeVue (UI components)
- Node.js 20+
- Docker
- Docker Compose
- Poetry 2.x (backend dependency management)
- Create
.envin the project root (used by Docker Compose):
POSTGRES_USER=hans
POSTGRES_PASSWORD=hans
POSTGRES_DB=hans
SECRET_KEY=your-secret-key
- Build and start containers:
docker compose up -d --build
- Apply migrations:
docker compose exec backend alembic upgrade head
- Seed admin user:
docker compose exec backend python3 -m hans.tools.seed_admin
- Login with username:
hans, password:hans:
http://localhost:8080/login
- Backend:
http://localhost:8000 - Frontend:
http://localhost:8080 - Admin UI:
http://localhost:8000/admin(CRUD management for all database entities)
- Docker uses
network_mode: hostfor the backend to expose dynamic instrument ports. This works only on Linux. For Docker Desktop (macOS/Windows), a different setup is required (no host networking).
- Postgres is exposed to the host on
5433(dbcontainer port5432). - Frontend is exposed on
8080. - Instrument interface ports come from YAML configs in
backend/src/hans/interfaces/configs(for example20100,20200). Becausebackendusesnetwork_mode: hostin Docker, these ports are listened on directly by the host with no Docker port mapping.
Configuration files live in backend/src/hans/interfaces/configs. Each config defines interface name, host, port, and test codes translation.
You can use astmkit to simulate input from instrument. It sends an ASTM frame over TCP to a target host and prints response frames.
astmkit inst input.astm --port 20100
Make sure the emulator port matches one of the configured interface ports (port in the YAML configs at backend/src/hans/interfaces/configs).
The dispatcher is a background TCP listener that loads YAML configs, opens instrument ports, and routes incoming messages to the appropriate protocol handlers.
Dispatcher starts automatically with the backend.
- Dispatcher status:
GET /settings/dispatcher/status - Dispatcher restart:
POST /settings/dispatcher/restart
- Audit logs:
live/audit/YYYY-MM-DD.log - Instrument traces:
live/instruments/<interface>/<YYYY-MM-DD>/
- Order-level comments for services
- PDF report generation
- Export (CSV / HL7)
- Automated testing
(In memory of Hans, a cat who was lost and never came back.)


