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.8.tar.gz (47.4 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.8-py3-none-any.whl (68.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pyetnic-0.0.8.tar.gz
  • Upload date:
  • Size: 47.4 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.8.tar.gz
Algorithm Hash digest
SHA256 a1a55a76221eecc809a175aa169bc42bf239d86f29ed9cc5088bf3f2e7149703
MD5 96355892c23233a5dce2dc61449714b8
BLAKE2b-256 7c4fc2698ff46f272e6b97412ec35db2af44686f6784c3ee67b4cd7624ed911d

See more details on using hashes here.

File details

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

File metadata

  • Download URL: pyetnic-0.0.8-py3-none-any.whl
  • Upload date:
  • Size: 68.8 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.8-py3-none-any.whl
Algorithm Hash digest
SHA256 26a52dbee086fbf87c9e9b51b00d378924766580958260cb8879133e48c07620
MD5 55efc603349aeeafb1be420d14d78010
BLAKE2b-256 8dcb71419fdf305a9d65f34e6e7f068a6302932d8b38ee1f69bffa6a776976a9

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