Image Python 3.14-slim (même version qu'en dev local), utilisateur non-root, healthcheck sans dépendance externe, un seul worker Uvicorn (SQLite gère mal les écritures concurrentes multi-process). data/ monté en volume dans docker-compose.yml pour garder la base SQLite visible et sauvegardable directement dans le dossier du projet, comme en dev local. Non testé avec un vrai build : Docker indisponible dans cet environnement de dev, à vérifier avant un premier déploiement.
133 lines
5.2 KiB
Markdown
133 lines
5.2 KiB
Markdown
# Gestion de stock IT
|
|
|
|
Application web pour le département IT d'une clinique, permettant de gérer
|
|
le stock de matériel informatique (catégories / sous-catégories /
|
|
matériels), avec scan de codes-barres et alertes email de stock bas.
|
|
|
|
Pas de système d'authentification dans l'app : l'accès est censé être
|
|
restreint par un mécanisme externe (réseau interne, proxy, etc.).
|
|
|
|
## Stack
|
|
|
|
- **Python + FastAPI** : serveur web, un seul processus.
|
|
- **SQLite** : base de données fichier (`data/stock.db`), aucun serveur à installer.
|
|
- **Jinja2** : pages HTML rendues côté serveur, formulaires classiques (pas de JS de build).
|
|
- **SQLModel** : ORM (combine SQLAlchemy + validation Pydantic).
|
|
|
|
Tout vit dans ce dossier : pas de service externe requis pour développer
|
|
et tester en local (les emails d'alerte sont simulés dans la console tant
|
|
qu'aucun SMTP n'est configuré, voir plus bas).
|
|
|
|
## Démarrer en local
|
|
|
|
```bash
|
|
python3 -m venv .venv
|
|
source .venv/bin/activate # Windows : .venv\Scripts\activate
|
|
pip install -r requirements-dev.txt
|
|
cp .env.example .env # optionnel en local, voir ci-dessous
|
|
uvicorn app.main:app --reload
|
|
```
|
|
|
|
L'app est accessible sur http://127.0.0.1:8000. La base SQLite est créée
|
|
automatiquement au premier démarrage dans `data/stock.db`.
|
|
|
|
## Lancer avec Docker
|
|
|
|
```bash
|
|
cp .env.example .env # requis, voir Configuration des emails ci-dessous
|
|
docker compose up --build
|
|
```
|
|
|
|
L'app est accessible sur http://localhost:8000. `data/` est monté depuis
|
|
l'hôte : la base SQLite (`data/stock.db`) reste au même endroit qu'en dev
|
|
local sans Docker, visible et sauvegardable directement dans ce dossier.
|
|
|
|
Un seul worker Uvicorn dans le conteneur (voir commentaire dans le
|
|
`Dockerfile`) : SQLite gère mal les écritures concurrentes depuis
|
|
plusieurs process, et un seul worker est largement suffisant pour l'usage
|
|
interne visé.
|
|
|
|
Pour du développement actif, la boucle venv + `--reload` ci-dessus reste
|
|
plus rapide (pas de rebuild d'image à chaque changement) ; Docker sert
|
|
surtout à tester ou reproduire l'environnement de déploiement.
|
|
|
|
## Lancer les tests
|
|
|
|
```bash
|
|
source .venv/bin/activate
|
|
pytest
|
|
```
|
|
|
|
## Lancer le linter
|
|
|
|
```bash
|
|
source .venv/bin/activate
|
|
ruff check .
|
|
```
|
|
|
|
## Configuration des emails
|
|
|
|
Les emails de stock (alerte immédiate + résumé périodique) sont envoyés via
|
|
le relais SMTP interne de la clinique, configuré par variables
|
|
d'environnement (voir `.env.example`) :
|
|
|
|
```
|
|
SMTP_HOST=...
|
|
SMTP_PORT=25
|
|
SMTP_USER=...
|
|
SMTP_PASSWORD=...
|
|
SMTP_FROM=stock-it@clinique.local
|
|
```
|
|
|
|
Si `SMTP_HOST` n'est pas renseigné (cas du dev local), rien n'est réellement
|
|
envoyé : les emails sont affichés dans la console du serveur
|
|
(`--- [EMAIL SIMULÉ] ---`). Ça permet de développer et tester tout le flux
|
|
sans avoir de vrai serveur mail sous la main.
|
|
|
|
Deux emails distincts :
|
|
- **Alerte immédiate** : envoyée dès qu'un matériel passe sous son seuil
|
|
d'alerte (`Materiel.seuil_alerte`). Contient ce matériel, puis un résumé
|
|
de tous les articles actuellement en stock bas.
|
|
- **Résumé périodique** : stock bas en premier, puis le reste du stock
|
|
groupé par catégorie. L'horaire se configure **depuis l'interface**, sur
|
|
`/destinataires` (raccourcis courants + expression cron personnalisée) —
|
|
pas de fichier à éditer, le changement s'applique immédiatement sans
|
|
redémarrer le serveur. Défaut : tous les lundis à 9h. Le planificateur
|
|
(APScheduler) tourne dans le process de l'app, rien à configurer côté
|
|
système d'exploitation. Pour déclencher l'envoi manuellement (test, ou
|
|
pour le brancher sur un cron système / Planificateur de tâches Windows
|
|
à la place) : `python scripts/envoyer_resume_stock.py`.
|
|
|
|
Les destinataires (plusieurs possibles) se gèrent aussi sur `/destinataires`.
|
|
|
|
## Douchette code-barres
|
|
|
|
Aucune intégration logicielle particulière : une douchette USB (ou
|
|
Bluetooth) émule un clavier, elle "tape" le code puis Entrée. La page
|
|
`/scan` a un simple champ de texte auto-focus dans un formulaire ; Entrée
|
|
soumet automatiquement le formulaire.
|
|
|
|
## Structure du projet
|
|
|
|
```
|
|
app/
|
|
main.py point d'entrée FastAPI, démarrage du planificateur
|
|
config.py lecture des variables d'environnement
|
|
database.py connexion SQLite
|
|
models.py modèles SQLModel (Categorie en arborescence, Materiel, DestinataireAlerte)
|
|
categories_arbre.py parcours de l'arborescence de catégories
|
|
email_alerts.py alerte immédiate + résumé périodique de stock
|
|
scheduler.py planification (APScheduler) du résumé périodique
|
|
templates_engine.py instance Jinja2Templates partagée
|
|
routers/ une route FastAPI par ressource (categories, materiels, scan, destinataires)
|
|
templates/ pages HTML (Jinja2)
|
|
static/ CSS
|
|
scripts/
|
|
seed.py peuple la base avec des données de démo
|
|
envoyer_resume_stock.py déclenche manuellement l'email récapitulatif
|
|
tests/ tests pytest (client de test FastAPI + base SQLite en mémoire)
|
|
data/ base SQLite locale (ignorée par git)
|
|
Dockerfile image de l'app (Python 3.14-slim, utilisateur non-root, 1 worker Uvicorn)
|
|
docker-compose.yml lancement local avec data/ monté en volume
|
|
```
|