Skip to main content

Access to ETNIC web services through Python

Project description

pyetnic

Bibliothèque Python d'accès aux services web SOAP d'ETNIC pour l'enseignement de promotion sociale (Wallonie-Bruxelles).

Fonctionnalités

Service Opérations
Formations Lister les formations organisables (catalogue), lister les formations organisées
Organisation Créer, lire, modifier, supprimer une organisation de formation
Document 1 Lire, modifier, approuver le document de population (inscriptions)
Document 2 Lire, modifier le document des périodes d'activités d'enseignement
Document 3 Lire, modifier le document des attributions d'enseignants

Installation

pip install pyetnic

Configuration

Générer un fichier .env de départ :

pyetnic init-config

Remplir les valeurs dans .env :

# Environnement : dev (services-web.tq.etnic.be) ou prod (services-web.etnic.be)
ENV=dev

# Identifiants pour le développement
DEV_USERNAME=
DEV_PASSWORD=

# Identifiants pour la production
PROD_USERNAME=
PROD_PASSWORD=

# Paramètres par défaut
DEFAULT_ETABID=       # identifiant établissement (int)
DEFAULT_IMPLID=       # identifiant implantation (int)
DEFAULT_SCHOOLYEAR=2024-2025

Les identifiants sont fournis par ETNIC pour accéder aux services web de votre établissement.


Utilisation

Formations

import pyetnic
from pyetnic.services.models import OrganisationId

# Formations organisables (catalogue de l'année)
result = pyetnic.lister_formations_organisables(annee_scolaire="2024-2025")
for formation in result:
    print(formation.numAdmFormation, formation.codeFormation, formation.libelleFormation)

# Formations déjà organisées (avec leurs organisations et statuts de documents)
result = pyetnic.lister_formations(annee_scolaire="2024-2025")
for formation in result:
    for org in formation.organisations:
        print(
            f"F{org.id.numAdmFormation}/org{org.id.numOrganisation}",
            org.dateDebutOrganisation, "→", org.dateFinOrganisation,
            org.statutDocumentOrganisation.statut if org.statutDocumentOrganisation else "—",
        )

Organisation

from datetime import date
import pyetnic

org_id = OrganisationId(
    anneeScolaire="2024-2025",
    etabId=3052,
    numAdmFormation=455,
    numOrganisation=1,
)

# Lire
org = pyetnic.lire_organisation(org_id)

# Créer (numOrganisation attribué par le serveur)
org = pyetnic.creer_organisation(
    annee_scolaire="2025-2026",
    etab_id=3052,
    impl_id=6050,
    num_adm_formation=455,
    date_debut=date(2025, 9, 15),
    date_fin=date(2026, 6, 26),
)

# Modifier
org.dateFinOrganisation = date(2026, 6, 20)
org = pyetnic.modifier_organisation(org)

# Supprimer
ok = pyetnic.supprimer_organisation(org_id)

Document 1 — Population

from pyetnic.services.models import Doc1PopulationListSave, Doc1PopulationLineSave

doc1 = pyetnic.lire_document_1(org_id)
# doc1 est None si le document n'est pas accessible (statut org insuffisant)

# Modifier
liste_save = Doc1PopulationListSave(population=[
    Doc1PopulationLineSave(coAnnEtude=1, nbEleveA=12, nbEleveTotHom=5, nbEleveTotFem=7),
])
doc1 = pyetnic.modifier_document_1(org_id, population_liste=liste_save)

# Approuver
doc1 = pyetnic.approuver_document_1(org_id)

Document 2 — Périodes d'activités

from pyetnic.services.models import Doc2ActiviteEnseignementListSave, Doc2ActiviteEnseignementLineSave

doc2 = pyetnic.lire_document_2(org_id)

liste_save = Doc2ActiviteEnseignementListSave(activiteEnseignement=[
    Doc2ActiviteEnseignementLineSave(coNumBranche=1, nbEleveC1=15, nbPeriodePrevueAn1=32.0),
])
doc2 = pyetnic.modifier_document_2(org_id, activite_enseignement_liste=liste_save)

Document 3 — Attributions d'enseignants

from pyetnic.services.models import (
    Doc3ActiviteListeSave, Doc3ActiviteDetailSave,
    Doc3EnseignantListSave, Doc3EnseignantDetailSave,
)

doc3 = pyetnic.lire_document_3(org_id)
# doc3 est None si Doc 1 et Doc 2 ne sont pas encore approuvés

liste_save = Doc3ActiviteListeSave(activite=[
    Doc3ActiviteDetailSave(
        coNumBranche=1,
        noAnneeEtude="1",
        enseignantListe=Doc3EnseignantListSave(enseignant=[
            Doc3EnseignantDetailSave(
                coNumAttribution=1,
                noMatEns="28901061314",
                teStatut="T",
                nbPeriodesAttribuees=52.0,
            )
        ]),
    ),
])
doc3 = pyetnic.modifier_document_3(org_id, liste_save)

Workflow métier

Les documents suivent un workflow séquentiel imposé par ETNIC :

Créer organisation  →  statut "Encodé école"
        ↓
Inspection approuve →  statut "Approuvé"
        ↓
Doc 1 accessible (lecture/modification/approbation)
        ↓
Doc 2 accessible (lecture/modification)
        ↓
Doc 1 ET Doc 2 approuvés  →  Doc 3 accessible

Règles de blocage :

  • Doc 1 : inaccessible si l'organisation est "Encodé école"
  • Doc 3 : nécessite que Doc 1 ("Doc A") et Doc 2 soient approuvés (erreur ETNIC 20102)
  • Modification impossible si le document est dans un statut verrouillé

Modèles de données

Identifiant d'organisation

@dataclass
class OrganisationId:
    anneeScolaire: str      # ex. "2024-2025"
    etabId: int             # identifiant établissement
    numAdmFormation: int    # numéro administratif de la formation
    numOrganisation: int    # numéro d'organisation (attribué par le serveur à la création)
    implId: Optional[int]   # identifiant implantation (présent dans les réponses serveur)

Important : implId est retourné par le serveur dans ses réponses mais ne doit pas être envoyé dans les requêtes Lire/Modifier/Supprimer (contrat OrganisationReqIdCT). Seul CreerOrganisation accepte implId.

Vue d'une organisation

OrganisationApercu (retourné par lister_formations) contient les statuts des 4 documents :

Champ Description
statutDocumentOrganisation Statut de l'organisation elle-même
statutDocumentPopulationPeriodes Statut du Document 1
statutDocumentDroitsInscription Statut du Document droits d'inscription
statutDocumentAttributions Statut du Document 3

Organisation (retourné par lire_organisation) hérite de OrganisationApercu et ajoute les champs métier complets.


Gestion des erreurs

Toutes les fonctions de service retournent None (plutôt qu'une exception) si :

  • Le serveur répond avec success: False et response: None (accès refusé, document non existant, etc.)
  • Le document n'est pas accessible selon le workflow métier

Les erreurs réseau et SOAP sont encapsulées dans SoapError et propagées.

Codes d'erreur ETNIC courants :

Code Description
00009 Aucun enregistrement trouvé
20102 Doc 1 et Doc 2 doivent être approuvés pour accéder au Doc 3

Structure du projet

pyetnic/
├── __init__.py                  # Point d'entrée public
├── cli.py                       # CLI : commande init-config
├── config.py                    # Configuration (.env, endpoints SOAP)
├── soap_client.py               # SoapClientManager (zeep + WSSE)
├── services/
│   ├── __init__.py              # Instanciation des services, exports
│   ├── models.py                # Tous les dataclasses (communs, Doc1, Doc2, Doc3)
│   ├── formations_liste.py      # FormationsListeService
│   ├── organisation.py          # OrganisationService
│   ├── document1.py             # Document1Service
│   ├── document2.py             # Document2Service
│   └── document3.py             # Document3Service
└── resources/
    ├── *.wsdl                   # Contrats WSDL des services ETNIC
    └── xsd/                     # Schémas XSD associés

Tests

# Tous les tests (mock + intégration)
pytest tests/

# Mock uniquement (sans credentials)
pytest tests/ -k "mock"

Les tests d'intégration nécessitent un .env valide. Ils skipent automatiquement si les credentials sont absents ou si le document n'est pas accessible dans l'environnement courant.

Environnements ETNIC :

  • devservices-web.tq.etnic.be (test, SSL non vérifié)
  • prodservices-web.etnic.be (production, SSL vérifié)

Dépendances

Package Usage
zeep Client SOAP
python-dotenv Chargement .env
requests Transport HTTP
openpyxl Export Excel (futur)

Licence

MIT — voir LICENSE

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyetnic-0.0.6.tar.gz (33.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyetnic-0.0.6-py3-none-any.whl (41.0 kB view details)

Uploaded Python 3

File details

Details for the file pyetnic-0.0.6.tar.gz.

File metadata

  • Download URL: pyetnic-0.0.6.tar.gz
  • Upload date:
  • Size: 33.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for pyetnic-0.0.6.tar.gz
Algorithm Hash digest
SHA256 e5ae0c9e1fe5675dd73b306da068beaffc74368c9c3db228144bc4f393e34210
MD5 1713ca3729c82195892d6ecae8345aa7
BLAKE2b-256 95e838907db34fdd95422abfada14a60a0e781b9de4b5625bcb51dd35b1d6190

See more details on using hashes here.

File details

Details for the file pyetnic-0.0.6-py3-none-any.whl.

File metadata

  • Download URL: pyetnic-0.0.6-py3-none-any.whl
  • Upload date:
  • Size: 41.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for pyetnic-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 55b387ffd7189451f9270a31199f19e5f1bc9263a2897cb745945763454030ab
MD5 8e9c1268f61adb60f2a8cf8c55770e6e
BLAKE2b-256 687b647641c6f81e4a9c782a3bf124216810c8d67e2bb54b2930e61174185b61

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page