<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://doc4-fr-mirror.openflyers.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Lhenry</id>
	<title>Documentation de la solution web de gestion OpenFlyers - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://doc4-fr-mirror.openflyers.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Lhenry"/>
	<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/Special:Contributions/Lhenry"/>
	<updated>2026-05-26T16:17:57Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.6</generator>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=API-OpenFlyers&amp;diff=13274</id>
		<title>API OpenFlyers</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=API-OpenFlyers&amp;diff=13274"/>
		<updated>2025-02-13T18:22:20Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: /* Script client : Authorization Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de décrire l'API OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
;Description de l'API&lt;br /&gt;
OpenFlyers possède une API basée sur [[Wikipedia-en:OAuth#OAuth_2.0|OAuth2]] qui permet à des serveurs extérieurs, dûment [[#Enregistrer-un-client|enregistrés]], de mettre en œuvre un processus d'[[Wikipedia-fr:Authentification_unique|authentification unique (SSO)]] et/ou de récupération des résultats des requêtes SQL de la [[Bibliothèque-des-rapports|bibliothèque des rapports]] ou des rapports personnalisés sous la forme de fichiers CSV.&lt;br /&gt;
&lt;br /&gt;
OAuth2 propose plusieurs mécanismes pour permettre l'authentification. Un mécanisme d'authentification détermine la séquence exacte des étapes impliquées dans le processus d'authentification d'OAuth2. OpenFlyers met à disposition deux mécanismes d'authentification :&lt;br /&gt;
*[[#Authorization Code|Authorization Code]] basé sur la méthode d'authentification par code d'autorisation et qui correspond au mécanisme associé à l'[[Wikipedia-fr:Authentification_unique|authentification unique (SSO)]],&lt;br /&gt;
*[[#Client Credentials|Client Credentials]] basé sur la méthode d'authentification avec les identifiants clients et qui est utilisé dans un contexte d'automatisme sans autorisation de l'utilisateur au préalable.&lt;br /&gt;
&lt;br /&gt;
Dans les chapitres qui suivent, le terme ''ressource'' fait référence à la définition OAuth2. Une ressource dans OAuth2 est un élément qui peut être :&lt;br /&gt;
*une ou des données comme des photos, des documents, des contacts ou des informations personnelles,&lt;br /&gt;
*un ou plusieurs services comme des transferts de fonds, la récupération de rapports ou l'ajout d'articles sur un blog,&lt;br /&gt;
*toute ressource nécessitant un accès restreint.&lt;br /&gt;
&lt;br /&gt;
OpenFlyers définit plusieurs [[#Utiliser-l'API|types de ressources]] :&lt;br /&gt;
*les [[#Récupérer-les-informations-de-l'utilisateur-connecté|informations de l'utilisateur connecté]],&lt;br /&gt;
*les [[#Récupérer les rapports génériques|rapports génériques]] ou [[#Récupérer les rapports personnalisés|personnalisés]] au format CSV.&lt;br /&gt;
&lt;br /&gt;
OAuth2 dispose de ''scopes''. Un scope est un privilège définit de manière explicite permettant l'accès à une ressource protégée. OpenFlyers met à disposition une [[#Liste des scopes disponibles|liste de scopes]] utilisables à travers l'API.&lt;br /&gt;
&lt;br /&gt;
Deux protocoles de sécurité sont présents dans l'API OpenFlyers :&lt;br /&gt;
*[[#Authentification-TLS-Mutuelle-(mTLS)|mTLS]] : il permet d'authentifier le client avec un certificat TLS, en plus d'authentifier le serveur avec un certificat. Ce protocole permet d'éviter les usurpations d'identité.&lt;br /&gt;
*[[#HTTP-Signature|HTTP-Signature]] : il permet de signer les en-têtes et le corps (lorsqu'il y en a un) des messages échangés afin d'en garantir leur intégrité.&lt;br /&gt;
&lt;br /&gt;
;Premiers pas - Client de démonstration&lt;br /&gt;
Un client de démonstration est disponible pour comprendre les mécanismes décrits ci-dessous.&lt;br /&gt;
&lt;br /&gt;
L'utilisation de ce client de démonstration est décrite dans la procédure [[#Utiliser-le-client|Utiliser le client]] de cette page.&lt;br /&gt;
&lt;br /&gt;
Le client de démonstration est lui-même accessible à cette adresse : https://openflyers.com/oauth2-demo/index.php&lt;br /&gt;
&lt;br /&gt;
Le code source du client de démonstration est mis à disposition par OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/oauth2-demo-src.zip&lt;br /&gt;
&lt;br /&gt;
L'utilisation du code source est décrite dans la procédure [[#Créer-un-client-à-partir-du-code-source|Créer un client à partir du code source]].&lt;br /&gt;
&lt;br /&gt;
=Définitions=&lt;br /&gt;
==Authentification TLS Mutuelle (mTLS)==&lt;br /&gt;
En général dans une communication TLS, seul le serveur a l'obligation de fournir un certificat. Il est également possible pour le client de fournir un certificat. Ce principe s'appelle l'authentification mutuelle et est mise en place avec Mutual TLS (ou [[Wikipedia-en:Mutual_authentication#mTLS|mTLS]]).&lt;br /&gt;
&lt;br /&gt;
OpenFlyers associe un certificat pour l'authentification mutuelle unique à chaque client OAuth2.&lt;br /&gt;
&lt;br /&gt;
;Envoyer un certificat client&lt;br /&gt;
Côté client, le code suivant peut être utilisé pour fournir à cURL le certificat et la clé correspondante ainsi que le certificat du CA d'OpenFlyers à utiliser pour la connexion :&lt;br /&gt;
&amp;lt;php&amp;gt;curl_setopt_array($request, [&lt;br /&gt;
    CURLOPT_SSLVERSION =&amp;gt; CURL_SSLVERSION_TLSv1_2,&lt;br /&gt;
    CURLOPT_CAINFO     =&amp;gt; $caCertificatePath,&lt;br /&gt;
    CURLOPT_SSLCERT    =&amp;gt; $certificatePath,&lt;br /&gt;
    CURLOPT_SSLKEY     =&amp;gt; $keyPath&lt;br /&gt;
]);&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''À noter''' : le certificat du CA d'OpenFlyers est nécessaire pour assurer la validité des certificats utilisés.&lt;br /&gt;
&lt;br /&gt;
==HTTP Signature==&lt;br /&gt;
HTTP Signature utilise le principe de la signature numérique pour garantir l'authenticité et l'intégrité du message HTTP.&lt;br /&gt;
&lt;br /&gt;
La signature est générée à l'aide d'une clé privée et vérifiée à l'aide de la clé publique correspondante ou d'un certificat contenant cette clé publique.&lt;br /&gt;
&lt;br /&gt;
HTTP Signature utilise deux en-têtes HTTP :&lt;br /&gt;
*Signature : contient la signature et ses métadonnées.&lt;br /&gt;
*Digest : contient le corps du message haché.&lt;br /&gt;
&lt;br /&gt;
===Digest===&lt;br /&gt;
Le ''digest'' est calculé comme ceci : &amp;lt;code&amp;gt;digest = base64encode(sha256(corps du message))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et l'en-tête est structuré de la manière suivante : &amp;lt;code&amp;gt;Digest: SHA-256=&amp;lt;digest&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un autre algorithme de hachage peut être utilisé, SHA-256 reste cependant le plus répendu.&lt;br /&gt;
&lt;br /&gt;
;Exemple en php&lt;br /&gt;
&amp;lt;php&amp;gt;$digestHeader = 'Digest: SHA-256=' . base64_encode(hash('sha256', $postData, true));&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Signature===&lt;br /&gt;
L'en-tête HTTP de signature est structuré de la manière suivante : &amp;lt;code&amp;gt;Signature: keyId=&amp;quot;&amp;lt;keyId&amp;gt;&amp;quot;,algorithm=&amp;quot;&amp;lt;algo&amp;gt;&amp;quot;,headers=&amp;quot;&amp;lt;signed_headers&amp;gt;&amp;quot;,signature=&amp;quot;&amp;lt;signature&amp;gt;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le champ ''keyId'' correspond à un identifiant permettant l'identification de la clé utilisée pour vérifier la signature. Pour l'API d'OpenFlyers, sa valeur correspond à l'empreinte SHA-1 du certificat au format PEM à utiliser pour vérifier la signature.&lt;br /&gt;
&lt;br /&gt;
L'algorithme ''algo'' correspond à celui utilisé pour générer la signature, exemple : &amp;lt;code&amp;gt;rsa-sha256&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
La valeur de ''signed_headers'' correspond à la liste des en-têtes inclus dans la signature séparés d'un espace. Exemple : &amp;lt;code&amp;gt;date digest (request-target)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour générer la signature, une chaîne de caractères appelée &amp;lt;code&amp;gt;signing string&amp;lt;/code&amp;gt; contenant les en-têtes au format &amp;lt;code&amp;gt;lowercase_header_name: value&amp;lt;/code&amp;gt; séparés par une nouvelle ligne au format LF (&amp;lt;code&amp;gt;\n&amp;lt;/code&amp;gt;) est d'abord générée. Exemple avec les en-têtes &amp;quot;date&amp;quot; et &amp;quot;(request-target)&amp;quot; :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;(request-target): post /some/uri\ndate: Tue, 07 Jun 2014 20:51:35 GMT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La signature est ensuite générée comme ceci : &amp;lt;code&amp;gt;base64encode(algo(signing string))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Exemple en php&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;function generateSignatureHeader(array $headersToSign, string $certificateFingerprint, string $privateKey): string&lt;br /&gt;
{&lt;br /&gt;
    // generating the signing string and header list&lt;br /&gt;
    $headers         = '';&lt;br /&gt;
    $signatureString = '';&lt;br /&gt;
    foreach ($headersToSign as $key =&amp;gt; $value) {&lt;br /&gt;
        $normalizedHeaderKey = trim(strtolower($key));&lt;br /&gt;
        $headers             .= $normalizedHeaderKey . ' ';&lt;br /&gt;
        $signatureString     .= $normalizedHeaderKey . ': ' . trim($value) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // trim extra whitespace&lt;br /&gt;
    $headers         = trim($headers);&lt;br /&gt;
    $signatureString = trim($signatureString);&lt;br /&gt;
&lt;br /&gt;
    // signing the signing string&lt;br /&gt;
    $signature = '';&lt;br /&gt;
    openssl_sign($signatureString, $signature, $privateKey, 'RSA-SHA256');&lt;br /&gt;
    $signature = base64_encode($signature);&lt;br /&gt;
&lt;br /&gt;
    // compiling the header line&lt;br /&gt;
    return &amp;quot;Signature: keyId=\&amp;quot;$certificateFingerprint\&amp;quot;,algorithm=\&amp;quot;rsa-sha256\&amp;quot;,headers=\&amp;quot;$headers\&amp;quot;,signature=\&amp;quot;$signature\&amp;quot;&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Les variables ''$certificateFingerprint'' et ''$privateKey'' correspondent respectivement à une empreinte SHA-1 de certificat et à une clé privée, tous deux au format PEM. &lt;br /&gt;
&lt;br /&gt;
La variable ''$headersToSign'' est un tableau formaté de la manière suivante : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;[&lt;br /&gt;
    $headerName =&amp;gt; $headerValue,&lt;br /&gt;
    ...&lt;br /&gt;
]&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''À noter''' : les en-têtes sont à signer côté client avec le certificat de signature signé par le CA d'OpenFlyers et dédié au client ainsi que la clé privée associée. Le certificat de signature dédié au client est téléchargeable depuis l'interface de gestion des clients OAuth2. Les en-têtes de la réponse du serveur quant à elles doivent être vérifiées avec le certificat de signature HTTP du serveur, téléchargeable aussi depuis l'interface de configuration des clients OAuth2.&lt;br /&gt;
&lt;br /&gt;
=Client OAuth2=&lt;br /&gt;
Une fois le client OAuth2 configuré sur OpenFlyers, il faut l'utiliser avec un client créé au préalable pour communiquer avec le serveur d'autorisation et l'API.&lt;br /&gt;
&lt;br /&gt;
Plusieurs [https://oauth.net/code/ bibliothèques] simplifiant la création d'un client sont disponibles.&lt;br /&gt;
&lt;br /&gt;
Des scripts client basiques écrits en php sont aussi fournis pour les mécanismes [[#Script-client-:-authorization-code|''authorization_code'']] et [[#Script-client-:-client-credentials|''client_credentials'']]&lt;br /&gt;
&lt;br /&gt;
==Authorization Code==&lt;br /&gt;
Ce flux OAuth2 se déroule en plusieurs étapes :&lt;br /&gt;
*Le client redirige le navigateur de l'utilisateur vers l'URL d'autorisation.&lt;br /&gt;
*Le navigateur de l'utilisateur est redirigé vers l'URL fournie durant la demande ou durant l'enregistrement du client.&lt;br /&gt;
*Le client récupère un code d'autorisation grâce à la redirection précédente, et échange ce code contre un jeton d'accès auprès du serveur d'autorisation.&lt;br /&gt;
*Le client peut utiliser ce code d'accès :&lt;br /&gt;
**Comme preuve d'authentification pour une solution SSO (Single Sign-On).&lt;br /&gt;
**Pour accéder à des données sur le serveur distant en utilisant l'API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    +-----------+                   +------+                +-----------+                  +-------------+                  +-----------+&lt;br /&gt;
    |Utilisateur|                   |Client|                |Navigateur |                  |   Serveur   |                  |  Serveur  |&lt;br /&gt;
    +-----+-----+                   +--+---+                +-----+-----+                  |Autorisation |                  | Ressources|&lt;br /&gt;
          |                            |                          |                        +------+------+                  +-----+-----+&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                   Demande|d'autorisation                 |                               |&lt;br /&gt;
          |                            +-------------------------&amp;gt;+------------------------------&amp;gt;|                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |Authentification + Formulaire d'autorisation              |                               |&lt;br /&gt;
          |&amp;lt;---------------------------+--------------------------+&amp;lt;------------------------------+                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |      Autorisation        |                               |                               |&lt;br /&gt;
          +----------------------------+-------------------------&amp;gt;+------------------------------&amp;gt;|                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                      Code|d'autorisation                 |                               |&lt;br /&gt;
          |                            |&amp;lt;-------------------------+&amp;lt;------------------------------+                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                Demande de|token                          |                               |&lt;br /&gt;
          |                            +--------------------------+------------------------------&amp;gt;|                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                 Access (+|Refresh) token                 |                               |&lt;br /&gt;
          |                            |&amp;lt;-------------------------+-------------------------------+                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |       Requête vers API        |                               |&lt;br /&gt;
          |                            +--------------------------+-------------------------------+------------------------------&amp;gt;|&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |                               |&amp;lt;------------------------------+&lt;br /&gt;
          |                            |                          |                               |  Vérification d'autorisation  |&lt;br /&gt;
          |                            |                          |                               +------------------------------&amp;gt;|&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |      Données/Réponse          |                               |&lt;br /&gt;
          |                            |&amp;lt;-------------------------+-------------------------------+-------------------------------+&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Générer les codes pour PKCE===&lt;br /&gt;
Pour faire fonctionner le client OAuth2, il faut générer deux codes pour l'extension PKCE :&lt;br /&gt;
*Un ''code_verifier'' échangé pendant la demande de jeton d'accès.&lt;br /&gt;
*Un ''code_challenge'' dérivé du ''code_verifier'' et échangé pendant la demande d'autorisation.&lt;br /&gt;
&lt;br /&gt;
;Générer le ''code_verifier''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;function generateCodeVerifier($length = 128): string&lt;br /&gt;
{&lt;br /&gt;
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~';&lt;br /&gt;
    $outputCode = '';&lt;br /&gt;
&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $length; $i++) {&lt;br /&gt;
        $index      = random_int(0, strlen($characters) - 1);&lt;br /&gt;
        $outputCode .= $characters[$index];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $outputCode;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cette fonction permet de générer un ''code_verifier'' avec une longueur donnée. Le ''code_verifier'' doit avoir une longueur entre 43 et 128 caractères.&lt;br /&gt;
&lt;br /&gt;
;Générer le ''code_challenge''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;function computeCodeChallenge(string $codeVerifier): string&lt;br /&gt;
{&lt;br /&gt;
    return strtr(rtrim(base64_encode(hash('sha256', $codeVerifier, true)), '='), '+/', '-_');&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cette fonction génère le ''code_challenge'' à partir du ''code_verifier'' fourni.&lt;br /&gt;
&lt;br /&gt;
===Demande d'autorisation===&lt;br /&gt;
Pour initier la demande d'autorisation, rediriger le navigateur de l'utilisateur vers l'URL : &amp;lt;code&amp;gt;GET https://openflyers.com/nom-de-plateforme/oauth/authorize.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Envoyer également les paramètres suivants :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|response_type||string||Le type de réponse envoyée par le serveur. Doit utiliser la valeur &amp;quot;code&amp;quot; (sans guillements) pour ce mécanisme.&lt;br /&gt;
|-&lt;br /&gt;
|redirect_uri||string||L'URI (ou l'URL) fourni pendant l'enregistrement du client et vers lequel l'utilisateur est redirigé après la demande d'autorisation.&lt;br /&gt;
|-&lt;br /&gt;
|scope||string||[[#Liste-des-scopes-disponibles|Liste des droits demandés par le client]], séparés par des espaces.&lt;br /&gt;
|-&lt;br /&gt;
|state||string||Chaîne de caractère aléatoire utilisée pour éviter les [https://fr.wikipedia.org/wiki/Cross-site_request_forgery attaques CSRF]. '''Fortement recommandé'''.&lt;br /&gt;
|-&lt;br /&gt;
|code_challenge||string||Code nécessaire pour le fonctionnement de l'extension [[#Générer-les-codes-pour-PKCE|PKCE]].&lt;br /&gt;
|-&lt;br /&gt;
|code_challenge_method||string||Méthode utilisée pour générer le ''code_challenge''. Ici, la valeur est &amp;quot;S256&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Demande de jeton d'accès===&lt;br /&gt;
Après avoir répondu à la demande, l'utilisateur est redirigé vers l'URI fourni pendant l'enregistrement du client. Si la demande est acceptée, un code temporaire : ''code'' est fourni, ainsi que le paramètre ''state'' fourni pendant la demande avec la même valeur. Si la demande est refusée, un code d'erreur est renvoyé.&lt;br /&gt;
;Si le paramètre ''state'' a une valeur différente de celle envoyée avec la demande, c'est peut-être une tentative d'attaque et il faut refuser la réponse.&lt;br /&gt;
&lt;br /&gt;
Echanger ce ''code'' contre un jeton d'accès via l'URL : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Les paramètres suivants sont également nécessaires :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|client_secret||string||La passphrase reçue pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|code||string||Le code temporaire reçu dans la réponse à la demande d'autorisation.&lt;br /&gt;
|-&lt;br /&gt;
|grant_type||string||Le mécanisme d'autorisation utilisé. Ici, sa valeur doit être ''authorization_code''&lt;br /&gt;
|-&lt;br /&gt;
|redirect_uri||string||L'URI (ou l'URL) de redirection fourni pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|code_verifier||string||Le ''code_verifier'' utilisé pour générer le ''code_challenge'' de la demande d'autorisation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Si la requête est correcte, un jeton d'accès (Access Token) ainsi qu'un jeton de rafraîchissement (Refresh Token) sont fournis en réponse dans un objet au format JSON.&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,&lt;br /&gt;
  &amp;quot;expires_in&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;access_token&amp;quot;: &amp;quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw&amp;quot;,&lt;br /&gt;
  &amp;quot;refresh_token&amp;quot;: &amp;quot;a59ef39fa9bab9b95cd554f921e7f3080a34c90f23d2b8031d692b5ff2d0993dcc392d9c7f9a43242337ef144c1a5fe1d0174413ade973e1b628ac0bbfc39b23973534&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Script client : Authorization Code===&lt;br /&gt;
Voici un exemple simple de client OAuth2 pour le mécanisme d'authentification par code d'autorisation (Authorization Code).&lt;br /&gt;
&lt;br /&gt;
Fichier de configuration ''config.authcode.json'' :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;authorize_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/authorize.php&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;/path/to/client/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;/path/to/client/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;/path/to/client/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;/path/to/client/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;/path/to/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;/path/to/server/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Où &amp;lt;code&amp;gt;/path/to/client/&amp;lt;/code&amp;gt; est le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
*Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/ssl/AuthCodeDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
*Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./ssl/AuthCodeDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ce fichier de configuration doit se situer au même niveau que le script PHP dans le système de fichiers.&lt;br /&gt;
&lt;br /&gt;
Script PHP :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&amp;lt;?php&lt;br /&gt;
$localTokenFile    = 'token.json';&lt;br /&gt;
// create token file if it does not exist&lt;br /&gt;
if (!file_exists($localTokenFile))&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
$config                 = json_decode(file_get_contents('config.authcode.json'), true);&lt;br /&gt;
$localToken             = json_decode(file_get_contents($localTokenFile), true);&lt;br /&gt;
$GLOBALS['config']      = $config;&lt;br /&gt;
&lt;br /&gt;
// Build the baseURL, accounting for protocol, port, name and endpoint. Used for redirection&lt;br /&gt;
$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';&lt;br /&gt;
$port     = ($protocol == 'https://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 443)&lt;br /&gt;
    || ($protocol == 'http://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 80) ? '' : ':' . $_SERVER['SERVER_PORT'];&lt;br /&gt;
&lt;br /&gt;
$baseURL            = $protocol . $_SERVER['SERVER_NAME'] . $port . $_SERVER['PHP_SELF'];&lt;br /&gt;
$errorLog           = 'error_log.log';&lt;br /&gt;
$responseLog        = 'response_log.log';&lt;br /&gt;
$GLOBALS['baseURL'] = $baseURL;&lt;br /&gt;
&lt;br /&gt;
//Session cookies are used to store information necessary for the authorization code flow&lt;br /&gt;
session_start();&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function is used to make api calls to the Authorization Server and the Resource Server&lt;br /&gt;
 *&lt;br /&gt;
 * @param       $url&lt;br /&gt;
 * @param       $post&lt;br /&gt;
 * @param array $headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return mixed&lt;br /&gt;
 */&lt;br /&gt;
function apiRequest($url, $post = null, $token = false, $auth = true, $refresh = false, $headers = array())&lt;br /&gt;
{&lt;br /&gt;
    $ch = curl_init($url);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HEADER, true);&lt;br /&gt;
&lt;br /&gt;
    $method = 'get';&lt;br /&gt;
&lt;br /&gt;
    if ($post) {&lt;br /&gt;
        $method   = 'post';&lt;br /&gt;
        $postData = http_build_query($post);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POST, true);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);&lt;br /&gt;
&lt;br /&gt;
        $headersToSign['Content-Type'] = 'application/x-www-form-urlencoded';&lt;br /&gt;
        $headersToSign['digest']       = 'SHA-256=' . base64_encode(hash('sha256', $postData, true));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $urlComponents = parse_url($url);&lt;br /&gt;
&lt;br /&gt;
    $headersToSign['(request-target)'] = $method . ' ' . $urlComponents['path'];&lt;br /&gt;
    $headersToSign['Host']             = $urlComponents['host'];&lt;br /&gt;
    $headersToSign['Date']             = gmdate('D, j M Y H:i:s T');&lt;br /&gt;
&lt;br /&gt;
    // generating the signature header&lt;br /&gt;
    $keyId                = openssl_x509_fingerprint(file_get_contents($GLOBALS['config']['sign_cert']));&lt;br /&gt;
    $privateKey           = file_get_contents($GLOBALS['config']['sign_key']);&lt;br /&gt;
    $headers['Signature'] = generateSignatureHeader($headersToSign, $keyId, $privateKey);&lt;br /&gt;
&lt;br /&gt;
    $headers['Accept']     = 'application/json';&lt;br /&gt;
    $headers['User-Agent'] = $GLOBALS['baseURL'];&lt;br /&gt;
    unset($headersToSign['(request-target)']);&lt;br /&gt;
    $headers               += $headersToSign;&lt;br /&gt;
&lt;br /&gt;
    if ($token) {&lt;br /&gt;
        $headers['Authorization'] = $token['token_type'] . ' ' . $token['access_token'];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // formatting the headers&lt;br /&gt;
    $httpFormattedHeaders = [];&lt;br /&gt;
    foreach ($headers as $key =&amp;gt; $value) {&lt;br /&gt;
        $httpFormattedHeaders[] = trim($key) . ': ' . trim($value);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HTTPHEADER, $httpFormattedHeaders);&lt;br /&gt;
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);&lt;br /&gt;
&lt;br /&gt;
    // for development environment only&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_VERBOSE, true);&lt;br /&gt;
&lt;br /&gt;
    // defining TLS client certificates for Mutual TLS&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_CAINFO, $GLOBALS['config']['auth_cacert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLCERT, $GLOBALS['config']['auth_cert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLKEY, $GLOBALS['config']['auth_key']);&lt;br /&gt;
&lt;br /&gt;
    $response = curl_exec($ch);&lt;br /&gt;
&lt;br /&gt;
    // logging errors and responses&lt;br /&gt;
    errorLog(true, $response, $ch);&lt;br /&gt;
&lt;br /&gt;
    curl_close($ch);&lt;br /&gt;
&lt;br /&gt;
    // in case an authentication request is executed&lt;br /&gt;
    if ($auth) {&lt;br /&gt;
        // required when a refresh token request is issued&lt;br /&gt;
        // because there is only one header in the response&lt;br /&gt;
        // while there are two for regular auth requests&lt;br /&gt;
        if (!$refresh) {&lt;br /&gt;
            list($firstResponseHeaders, $secondResponseHeaders, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 3);&lt;br /&gt;
            if (!$responseBody) {&lt;br /&gt;
                list($secondResponseHeaders, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 2);&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            list($secondResponseHeaders, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 2);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $responseHeadersDigest = '';&lt;br /&gt;
        $responseHeadersSignature = '';&lt;br /&gt;
        // extracting digest and signature from headers&lt;br /&gt;
        $responseHeadersArray = explode(&amp;quot;\r\n&amp;quot;, $secondResponseHeaders);&lt;br /&gt;
        $responseProtocol = array_shift($responseHeadersArray);&lt;br /&gt;
&lt;br /&gt;
        foreach ($responseHeadersArray as $value) {&lt;br /&gt;
            list($responseHeadersKeys, $responseHeadersValue) = explode(&amp;quot;: &amp;quot;, $value, 2);&lt;br /&gt;
            $responseHeaders[strtolower($responseHeadersKeys)] = $responseHeadersValue;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $responseDigestAlgo = '';&lt;br /&gt;
        $responseDigestKey = '';&lt;br /&gt;
        foreach ($responseHeaders as $key =&amp;gt; $value) {&lt;br /&gt;
            if ($key === &amp;quot;digest&amp;quot;) {&lt;br /&gt;
                $responseHeadersDigest = $value;&lt;br /&gt;
                // stripping SHA algorithm for later comparison&lt;br /&gt;
                list($responseDigestAlgo, $responseDigestKey) = explode(&amp;quot;=&amp;quot;, $responseHeadersDigest, 2);&lt;br /&gt;
            } else if ($key === &amp;quot;signature&amp;quot;)&lt;br /&gt;
                $responseHeadersSignature = $value;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // calculating response digest&lt;br /&gt;
        $responseDigest = base64_encode(hash(strtolower(str_replace(&amp;quot;-&amp;quot;, &amp;quot;&amp;quot;, $responseDigestAlgo)), $responseBody, true));&lt;br /&gt;
&lt;br /&gt;
        // checking digest validity&lt;br /&gt;
        if ($responseDigest !== $responseDigestKey) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Digests are not the same&amp;quot;);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // extracting variables from signature header&lt;br /&gt;
        $signatureArray = explode(&amp;quot;,&amp;quot;, $responseHeadersSignature);&lt;br /&gt;
        foreach ($signatureArray as $value) {&lt;br /&gt;
            list($signatureKey, $signatureValue) = explode(&amp;quot;=&amp;quot;, $value, 2);&lt;br /&gt;
            $signature[$signatureKey] = trim($signatureValue, '&amp;quot;');&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generating siging string&lt;br /&gt;
        $signingStringArray = explode(&amp;quot; &amp;quot;, $signature['headers']);&lt;br /&gt;
        $signingString = '';&lt;br /&gt;
        foreach ($signingStringArray as $value) {&lt;br /&gt;
            $signingString = $signingString . trim($value) . &amp;quot;: &amp;quot; . trim($responseHeaders[$value]) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // trimming last '\n' character&lt;br /&gt;
        $signingString = trim($signingString);&lt;br /&gt;
&lt;br /&gt;
        // decoding signature&lt;br /&gt;
        $decodedSignature = base64_decode($signature['signature']);&lt;br /&gt;
&lt;br /&gt;
        // verifying signature&lt;br /&gt;
        $signatureVerify = openssl_verify($signingString, $decodedSignature, openssl_get_publickey(file_get_contents($GLOBALS['config']['sign_cert_server'])), 'RSA-SHA256');&lt;br /&gt;
&lt;br /&gt;
        if (!$signatureVerify) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Signature is not correct&amp;quot;);&lt;br /&gt;
            while (($err = openssl_error_string()))&lt;br /&gt;
                errorLog(false, false, $err);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return json_decode($responseBody, true);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $response;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function logs curl responses and errors in text files&lt;br /&gt;
 *&lt;br /&gt;
 * @param mixed $response the response&lt;br /&gt;
 * @param mixed $request  the request handle, used to get errors&lt;br /&gt;
 */&lt;br /&gt;
function errorLog($curl, $response, $request = false)&lt;br /&gt;
{&lt;br /&gt;
    $timestamp = '[' . date('Y-m-d H:i:s') . ']:';&lt;br /&gt;
    global $errorLog;&lt;br /&gt;
    global $responseLog;&lt;br /&gt;
&lt;br /&gt;
    if ($response === false) {&lt;br /&gt;
        if ($curl)&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . curl_error($request) . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
        else&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . $request . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    } else {&lt;br /&gt;
        file_put_contents($responseLog, $timestamp . &amp;quot;\n&amp;quot; . $response . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function generates the full signature header line from a set of headers, a certificate and the linked private key&lt;br /&gt;
 *&lt;br /&gt;
 * @param array  $headersToSign the headers to sign, in the $key =&amp;gt; $value format&lt;br /&gt;
 * @param string $certificate   the certificate linked to the used private key&lt;br /&gt;
 * @param string $privateKey    the private key used to sign the headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the full signature header line&lt;br /&gt;
 */&lt;br /&gt;
function generateSignatureHeader(array $headersToSign, string $certificate, string $privateKey): string&lt;br /&gt;
{&lt;br /&gt;
    // generating the signing string and header list&lt;br /&gt;
    $headers         = '';&lt;br /&gt;
    $signatureString = '';&lt;br /&gt;
    foreach ($headersToSign as $key =&amp;gt; $value) {&lt;br /&gt;
        $normalizedHeaderKey = trim(strtolower($key));&lt;br /&gt;
        $headers             .= $normalizedHeaderKey . ' ';&lt;br /&gt;
        $signatureString     .= $normalizedHeaderKey . ': ' . trim($value) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    $headers         = trim($headers);&lt;br /&gt;
    $signatureString = trim($signatureString);&lt;br /&gt;
&lt;br /&gt;
    // signing the signing string&lt;br /&gt;
    $signature = '';&lt;br /&gt;
    openssl_sign($signatureString, $signature, openssl_get_privatekey($privateKey), 'RSA-SHA256');&lt;br /&gt;
    $signature = base64_encode($signature);&lt;br /&gt;
&lt;br /&gt;
    // compiling the header line&lt;br /&gt;
    return &amp;quot;keyId=\&amp;quot;$certificate\&amp;quot;,algorithm=\&amp;quot;rsa-sha256\&amp;quot;,headers=\&amp;quot;$headers\&amp;quot;,signature=\&amp;quot;$signature\&amp;quot;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function takes a code_verifier and outputs the corresponding code_challenge&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $codeVerifier the generated code_verifier&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the computed code_challenge&lt;br /&gt;
 */&lt;br /&gt;
function computeCodeChallenge(string $codeVerifier): string&lt;br /&gt;
{&lt;br /&gt;
    return strtr(rtrim(base64_encode(hash('sha256', $codeVerifier, true)), '='), '+/', '-_');&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function takes an optional string length and outputs a random code_verifier string&lt;br /&gt;
 *&lt;br /&gt;
 * @param int $length the length of the output code_verifier. Default = 128&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the code_verifier&lt;br /&gt;
 * @throws Exception&lt;br /&gt;
 */&lt;br /&gt;
function generateCodeVerifier($length = 128): string&lt;br /&gt;
{&lt;br /&gt;
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~';&lt;br /&gt;
    $outputCode = '';&lt;br /&gt;
&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $length; $i++) {&lt;br /&gt;
        $index      = random_int(0, strlen($characters) - 1);&lt;br /&gt;
        $outputCode .= $characters[$index];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $outputCode;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function calculates the entropy of a given string&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $string  the string for which to calculate the entropy&lt;br /&gt;
 * @param string $charset a string with all the usable characters. Default = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~&lt;br /&gt;
 *&lt;br /&gt;
 * @return float|int&lt;br /&gt;
 */&lt;br /&gt;
function computeEntropy(string $string, string $charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~')&lt;br /&gt;
{&lt;br /&gt;
    $chars = str_split($charset);&lt;br /&gt;
    $probs = [];&lt;br /&gt;
&lt;br /&gt;
    foreach ($chars as $char) {&lt;br /&gt;
        $probs[$char] = floatval(substr_count($string, $char)) / strlen($string);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $sum = 0.0;&lt;br /&gt;
    foreach ($probs as $prob) {&lt;br /&gt;
        $sum += $prob != 0 ? $prob * log($prob, 2) : 0.0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return -$sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function calculates the ideal (maximum) entropy for a string of a given length&lt;br /&gt;
 *&lt;br /&gt;
 * @param int $length length of the string. Default = 128&lt;br /&gt;
 *&lt;br /&gt;
 * @return float|int&lt;br /&gt;
 */&lt;br /&gt;
function idealEntropy(int $length = 128)&lt;br /&gt;
{&lt;br /&gt;
    $prob = 1.0 / $length;&lt;br /&gt;
&lt;br /&gt;
    return -1.0 * $length * $prob * log($prob, 2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function is used to initiate the authentication code flow.&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $clientID     the client's ID&lt;br /&gt;
 * @param string $redirectURL  the URL where to redirect after auth&lt;br /&gt;
 * @param string $authorizeURL the target URL to request authorization&lt;br /&gt;
 *&lt;br /&gt;
 * @throws Exception&lt;br /&gt;
 */&lt;br /&gt;
function login(string $clientID, string $redirectURL, string $authorizeURL): void&lt;br /&gt;
{&lt;br /&gt;
    global $localTokenFile;&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
    // This unguessable string is used to prevent csrf attacks&lt;br /&gt;
    $_SESSION['state'] = bin2hex(random_bytes(16));&lt;br /&gt;
&lt;br /&gt;
    // Generate code_verifier and code_challenge for PKCE    &lt;br /&gt;
    $_SESSION['code_verifier']  = generateCodeVerifier();&lt;br /&gt;
    $_SESSION['code_challenge'] = computeCodeChallenge($_SESSION['code_verifier']);&lt;br /&gt;
&lt;br /&gt;
    // required parameters for the redirection, redirect_uri is where the browser should be redirected&lt;br /&gt;
    // when the user grants (or denies) access, scope are the authorizations (rights) requested&lt;br /&gt;
    $params = [&lt;br /&gt;
        'response_type'         =&amp;gt; 'code',&lt;br /&gt;
        'client_id'             =&amp;gt; $clientID,&lt;br /&gt;
        'redirect_uri'          =&amp;gt; $redirectURL,&lt;br /&gt;
        'scope'                 =&amp;gt; 'default.login',&lt;br /&gt;
        'state'                 =&amp;gt; $_SESSION['state'],&lt;br /&gt;
        'code_challenge'        =&amp;gt; $_SESSION['code_challenge'],&lt;br /&gt;
        'code_challenge_method' =&amp;gt; 'S256'&lt;br /&gt;
    ];&lt;br /&gt;
&lt;br /&gt;
    // redirecting the browser to the AS authorization endpoint to obtain the authorization code&lt;br /&gt;
    header('Location: ' . $authorizeURL . '?' . http_build_query($params));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function deletes the access token from the session&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $baseURL&lt;br /&gt;
 */&lt;br /&gt;
function logout(string $baseURL): void&lt;br /&gt;
{&lt;br /&gt;
    global $localTokenFile;&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
    header('Location: ' . $baseURL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedIn(): void&lt;br /&gt;
{&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Logged In&amp;lt;/h3&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;view_repos&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;view&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'view_repos\').submit(); return false;&amp;quot;&amp;gt;View Repos&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;logout&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;logout&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'logout\').submit(); return false;&amp;quot;&amp;gt;Log Out&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedOut(): void&lt;br /&gt;
{&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Not logged in&amp;lt;/h3&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;login&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;login&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'login\').submit(); return false;&amp;quot;&amp;gt;Log In&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// display client &amp;quot;home&amp;quot; page&lt;br /&gt;
if (!isset($_POST['action'])) {&lt;br /&gt;
    if (!empty($localToken['access_token'])) {&lt;br /&gt;
        displayMenuLoggedIn();&lt;br /&gt;
    } else {&lt;br /&gt;
        displayMenuLoggedOut();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if (isset($_POST['action'])) {&lt;br /&gt;
    // Building query array for resource dumping&lt;br /&gt;
    $repoQueryParameters = [&lt;br /&gt;
        'resource_type' =&amp;gt; 'user_information',&lt;br /&gt;
        'client_id' =&amp;gt; $config['client_id']&lt;br /&gt;
    ];&lt;br /&gt;
    switch ($_POST['action']) {&lt;br /&gt;
        case 'login':&lt;br /&gt;
            login($config['client_id'], $baseURL, $config['authorize_uri']);&lt;br /&gt;
            break;&lt;br /&gt;
        case 'logout':&lt;br /&gt;
            logout($baseURL);&lt;br /&gt;
            break;&lt;br /&gt;
        case 'view':&lt;br /&gt;
            // call to the resource server to retreive user information&lt;br /&gt;
            $resources = apiRequest(&lt;br /&gt;
                $config['resource_uri'],&lt;br /&gt;
                $repoQueryParameters,&lt;br /&gt;
                $localToken,&lt;br /&gt;
                false&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            // Separating headers from body&lt;br /&gt;
            list($resourceHeader, $resourceBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $resources, 2);&lt;br /&gt;
&lt;br /&gt;
            $resourceHeaders = explode(&amp;quot;\r\n&amp;quot;, $resourceHeader);&lt;br /&gt;
            $firstHeaderLine = array_shift($resourceHeaders);&lt;br /&gt;
&lt;br /&gt;
            // Displaying user information&lt;br /&gt;
            echo '&amp;lt;pre&amp;gt;';&lt;br /&gt;
            echo $resourceBody;&lt;br /&gt;
            echo '&amp;lt;/pre&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
            // Automatic refreshing token once access token is expired&lt;br /&gt;
            if (strpos($firstHeaderLine, &amp;quot;401&amp;quot;)) {&lt;br /&gt;
                $errorBody = json_decode($resourceBody, true);&lt;br /&gt;
                if ($errorBody['error'] == 'access_denied' &amp;amp;&amp;amp; isset($errorBody['hint'])) {&lt;br /&gt;
                    if ($errorBody['hint'] == 'Access token could not be verified') {&lt;br /&gt;
                        $token = apiRequest(&lt;br /&gt;
                            $config['token_uri'],&lt;br /&gt;
                            [&lt;br /&gt;
                                'grant_type'    =&amp;gt; 'refresh_token',&lt;br /&gt;
                                'refresh_token' =&amp;gt; $localToken['refresh_token'],&lt;br /&gt;
                                'client_id'     =&amp;gt; $config['client_id'],&lt;br /&gt;
                                'client_secret' =&amp;gt; empty($config['client_secret']) ? null : $config['client_secret']&lt;br /&gt;
                            ],&lt;br /&gt;
                            false,&lt;br /&gt;
                            true,&lt;br /&gt;
                            true&lt;br /&gt;
                        );&lt;br /&gt;
&lt;br /&gt;
                        // We store the access token in the session so the user is &amp;quot;connected&amp;quot;&lt;br /&gt;
                        // Only if the request has been successfully executed&lt;br /&gt;
                        if (isset($token['access_token'])) {&lt;br /&gt;
                            file_put_contents($localTokenFile, json_encode($token, true));&lt;br /&gt;
&lt;br /&gt;
                            // Redirecting the user's browser to the &amp;quot;home&amp;quot; page&lt;br /&gt;
                            header('Location: ' . $baseURL);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Once the browser has been redirected to the AS to ask for the user's authorization, assuming it has been granted,&lt;br /&gt;
// the browser will get back here with a &amp;quot;code&amp;quot; parameter in the query string&lt;br /&gt;
if (isset($_GET['code'])) {&lt;br /&gt;
    // The AS MUST redirect the browser here with the exact same state parameter we sent it before, so we check if it is indeed the same&lt;br /&gt;
    // to detect if the oauth flow has been tampered with&lt;br /&gt;
    if (!isset($_GET['state']) || $_SESSION['state'] != $_GET['state']) {&lt;br /&gt;
        header('Location: ' . $baseURL . '?error=invalid_state');&lt;br /&gt;
        die();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // We communicate directly with the AS to exchange the code received against an access token.&lt;br /&gt;
    // The id/secret pair is send to authenticate the client, the redirect_uri is sent to verify the code's validity&lt;br /&gt;
    $token = apiRequest(&lt;br /&gt;
        $config['token_uri'],&lt;br /&gt;
        [&lt;br /&gt;
            'grant_type'    =&amp;gt; 'authorization_code',&lt;br /&gt;
            'client_id'     =&amp;gt; $config['client_id'],&lt;br /&gt;
            'client_secret' =&amp;gt; empty($config['client_secret']) ? null : $config['client_secret'],&lt;br /&gt;
            'redirect_uri'  =&amp;gt; $baseURL,&lt;br /&gt;
            'code'          =&amp;gt; $_GET['code'],&lt;br /&gt;
            'code_verifier' =&amp;gt; $_SESSION['code_verifier']&lt;br /&gt;
        ]&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    // We store the access token in the session so the user is &amp;quot;connected&amp;quot;&lt;br /&gt;
    // Only if the request has been successfully executed&lt;br /&gt;
    if (isset($token['access_token'])) {&lt;br /&gt;
        file_put_contents($localTokenFile, json_encode($token, true));&lt;br /&gt;
&lt;br /&gt;
        // Redirecting the user's browser to the &amp;quot;home&amp;quot; page&lt;br /&gt;
        header('Location: ' . $baseURL);&lt;br /&gt;
    } else {&lt;br /&gt;
        echo $token;&lt;br /&gt;
    }&lt;br /&gt;
    die();&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Ce script a été conçu pour montrer le fonctionnement du mécanisme afin de tester l'implémentation d'un serveur et n'a pas été testé extensivement. Il est conseillé d'utiliser une solution adaptée à un environnement de production.&lt;br /&gt;
&lt;br /&gt;
==Client Credentials==&lt;br /&gt;
Ce mécanisme d'autorisation est adapté pour l'automatisation. Il fonctionne de la manière suivante :&lt;br /&gt;
*Le client effectue la demande de jeton d'accès au serveur d'autorisation en fournissant ses identifiants.&lt;br /&gt;
*Le serveur authentifie le client avec les identifiants fournis et renvoie un jeton d'accès.&lt;br /&gt;
*Le client utilise ce jeton d'accès pour accéder à des données via l'API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    +------+                       +-------------+                  +-----------+&lt;br /&gt;
    |Client|                       |   Serveur   |                  |  Serveur  |&lt;br /&gt;
    +--+---+                       |Autorisation |                  | Ressources|&lt;br /&gt;
       |                           +------+------+                  +-----+-----+&lt;br /&gt;
       |        Authentification          |                               |&lt;br /&gt;
       |         + Demande token          |                               |&lt;br /&gt;
       +---------------------------------&amp;gt;|                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |          Access token            |                               |&lt;br /&gt;
       |&amp;lt;---------------------------------+                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                      Requête vers|API                            |&lt;br /&gt;
       +----------------------------------+------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |&amp;lt;------------------------------+&lt;br /&gt;
       |                                  |  Vérification d'autorisation  |&lt;br /&gt;
       |                                  +------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                         Données /|Réponse                        |&lt;br /&gt;
       |&amp;lt;---------------------------------+-------------------------------+&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Demande de jeton d'accès===&lt;br /&gt;
Pour obtenir un jeton d'accès, il faut effectuer la requête suivante : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Les paramètres suivants sont nécessaires :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|client_secret||string||La passphrase reçue pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|grant_type||string||Le mécanisme d'autorisation utilisé. Ici, la valeur doit être ''client_credentials''.&lt;br /&gt;
|-&lt;br /&gt;
|scope||string||[[#Liste-des-scopes-disponibles|Liste des droits demandés par le client]], séparé par des espaces.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
;Ce mécanisme a la particularité de ne pas nécessiter d'URI de redirection, il n'est donc pas utile d'en renseigner un lors de l'enregistrement d'un client.&lt;br /&gt;
&lt;br /&gt;
Si la requête est correcte, un jeton d'accès (Access Token) est fourni en réponse dans un objet au format JSON.&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,&lt;br /&gt;
  &amp;quot;expires_in&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;access_token&amp;quot;: &amp;quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Script client : Client Credentials===&lt;br /&gt;
Voici un exemple simple d'un client OAuth2 pour le mécanisme d'authentification par les identifiants client (Client Credentials).&lt;br /&gt;
&lt;br /&gt;
Fichier de configuration ''config.clientcred.json'' :&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;/path/to/client/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;/path/to/client/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;/path/to/client/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;/path/to/client/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;/path/to/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;/path/to/server/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
Où &amp;lt;code&amp;gt;/path/to/client/&amp;lt;/code&amp;gt; est le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
*Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/ssl/ClientCredDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
*Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./ssl/ClientCredDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ce fichier de configuration doit se situer au même niveau que le script PHP dans le système de fichiers.&lt;br /&gt;
&lt;br /&gt;
Script php :&lt;br /&gt;
&amp;lt;php&amp;gt;&amp;lt;?php&lt;br /&gt;
$localTokenFile    = 'token.json';&lt;br /&gt;
// create token file if it does not exist&lt;br /&gt;
if (!file_exists($localTokenFile))&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
$config                 = json_decode(file_get_contents('config.clientcred.json'), true);&lt;br /&gt;
$localToken             = json_decode(file_get_contents($localTokenFile), true);&lt;br /&gt;
$GLOBALS['config']      = $config;&lt;br /&gt;
&lt;br /&gt;
// Build the baseURL, accounting for protocol, port, name and endpoint. Used for redirection&lt;br /&gt;
$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';&lt;br /&gt;
$port     = ($protocol == 'https://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 443)&lt;br /&gt;
    || ($protocol == 'http://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 80) ? '' : ':' . $_SERVER['SERVER_PORT'];&lt;br /&gt;
&lt;br /&gt;
$baseURL            = $protocol . $_SERVER['SERVER_NAME'] . $port . $_SERVER['PHP_SELF'];&lt;br /&gt;
$errorLog           = 'error_log.log';&lt;br /&gt;
$responseLog        = 'response_log.log';&lt;br /&gt;
$GLOBALS['baseURL'] = $baseURL;&lt;br /&gt;
&lt;br /&gt;
$replacementListItems = [&lt;br /&gt;
    1 =&amp;gt; &amp;quot;year&amp;quot;,&lt;br /&gt;
    2 =&amp;gt; &amp;quot;validityTypeId&amp;quot;,&lt;br /&gt;
    3 =&amp;gt; &amp;quot;icao&amp;quot;,&lt;br /&gt;
    4 =&amp;gt; &amp;quot;profileId&amp;quot;,&lt;br /&gt;
    7 =&amp;gt; &amp;quot;accountingId&amp;quot;,&lt;br /&gt;
    8 =&amp;gt; &amp;quot;paymentType&amp;quot;,&lt;br /&gt;
    9 =&amp;gt; &amp;quot;startDate&amp;quot;,&lt;br /&gt;
    10 =&amp;gt; &amp;quot;endDate&amp;quot;,&lt;br /&gt;
    11 =&amp;gt; &amp;quot;occupiedSeat&amp;quot;,&lt;br /&gt;
    12 =&amp;gt; &amp;quot;date&amp;quot;,&lt;br /&gt;
    13 =&amp;gt; &amp;quot;activityTypeId&amp;quot;,&lt;br /&gt;
    14 =&amp;gt; &amp;quot;age&amp;quot;,&lt;br /&gt;
    15 =&amp;gt; &amp;quot;resourceId&amp;quot;,&lt;br /&gt;
    16 =&amp;gt; &amp;quot;personId&amp;quot;,&lt;br /&gt;
    17 =&amp;gt; &amp;quot;accountId&amp;quot;,&lt;br /&gt;
    20 =&amp;gt; &amp;quot;rightPlacePersonId&amp;quot;,&lt;br /&gt;
    21 =&amp;gt; &amp;quot;month&amp;quot;,&lt;br /&gt;
    22 =&amp;gt; &amp;quot;numberMonth&amp;quot;,&lt;br /&gt;
    23 =&amp;gt; &amp;quot;oneValidityTypeId&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
&lt;br /&gt;
//Session cookies are used to store information necessary for the authorization code flow&lt;br /&gt;
session_start();&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function is used to make api calls to the RS&lt;br /&gt;
 *&lt;br /&gt;
 * @param       $url&lt;br /&gt;
 * @param       $post&lt;br /&gt;
 * @param array $headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return mixed&lt;br /&gt;
 */&lt;br /&gt;
function apiRequest($url, $post = null, $token = false, $auth = true, $headers = array())&lt;br /&gt;
{&lt;br /&gt;
    $ch = curl_init($url);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HEADER, true);&lt;br /&gt;
&lt;br /&gt;
    $method = 'get';&lt;br /&gt;
&lt;br /&gt;
    if ($post) {&lt;br /&gt;
        $method   = 'post';&lt;br /&gt;
        $postData = http_build_query($post);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POST, true);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);&lt;br /&gt;
&lt;br /&gt;
        $headersToSign['Content-Type'] = 'application/x-www-form-urlencoded';&lt;br /&gt;
        $headersToSign['digest']       = 'SHA-256=' . base64_encode(hash('sha256', $postData, true));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $urlComponents = parse_url($url);&lt;br /&gt;
&lt;br /&gt;
    $headersToSign['(request-target)'] = $method . ' ' . $urlComponents['path'];&lt;br /&gt;
    $headersToSign['Host']             = $urlComponents['host'];&lt;br /&gt;
    $headersToSign['Date']             = gmdate('D, j M Y H:i:s T');&lt;br /&gt;
&lt;br /&gt;
    // generating the signature header&lt;br /&gt;
    $keyId                = openssl_x509_fingerprint(file_get_contents($GLOBALS['config']['sign_cert']));&lt;br /&gt;
    $privateKey           = file_get_contents($GLOBALS['config']['sign_key']);&lt;br /&gt;
    $headers['Signature'] = generateSignatureHeader($headersToSign, $keyId, $privateKey);&lt;br /&gt;
&lt;br /&gt;
    $headers['Accept']     = 'application/json';&lt;br /&gt;
    $headers['User-Agent'] = $GLOBALS['baseURL'];&lt;br /&gt;
    unset($headersToSign['(request-target)']);&lt;br /&gt;
    $headers               += $headersToSign;&lt;br /&gt;
&lt;br /&gt;
    if ($token) {&lt;br /&gt;
        $headers['Authorization'] = $token['token_type'] . ' ' . $token['access_token'];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // formatting the headers&lt;br /&gt;
    $httpFormattedHeaders = [];&lt;br /&gt;
    foreach ($headers as $key =&amp;gt; $value) {&lt;br /&gt;
        $httpFormattedHeaders[] = trim($key) . ': ' . trim($value);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HTTPHEADER, $httpFormattedHeaders);&lt;br /&gt;
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);&lt;br /&gt;
&lt;br /&gt;
    // for development environment only&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_VERBOSE, true);&lt;br /&gt;
&lt;br /&gt;
    // defining TLS client certificates for Mutual TLS&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_CAINFO, $GLOBALS['config']['auth_cacert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLCERT, $GLOBALS['config']['auth_cert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLKEY, $GLOBALS['config']['auth_key']);&lt;br /&gt;
&lt;br /&gt;
    $response = curl_exec($ch);&lt;br /&gt;
&lt;br /&gt;
    // logging errors and responses&lt;br /&gt;
    errorLog(true, $response, $ch);&lt;br /&gt;
&lt;br /&gt;
    curl_close($ch);&lt;br /&gt;
&lt;br /&gt;
    // in case an authentication request is executed&lt;br /&gt;
    if ($auth) {&lt;br /&gt;
        list($responseHeader, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 2);&lt;br /&gt;
&lt;br /&gt;
        $responseHeadersDigest = '';&lt;br /&gt;
        $responseHeadersSignature = '';&lt;br /&gt;
        // extracting digest and signature from headers&lt;br /&gt;
        $responseHeadersArray = explode(&amp;quot;\r\n&amp;quot;, $responseHeader);&lt;br /&gt;
        $responseProtocol = array_shift($responseHeadersArray);&lt;br /&gt;
&lt;br /&gt;
        foreach ($responseHeadersArray as $value) {&lt;br /&gt;
            list($responseHeadersKeys, $responseHeadersValue) = explode(&amp;quot;: &amp;quot;, $value, 2);&lt;br /&gt;
            $responseHeaders[strtolower($responseHeadersKeys)] = $responseHeadersValue;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $responseDigestAlgo = '';&lt;br /&gt;
        $responseDigestKey = '';&lt;br /&gt;
        foreach ($responseHeaders as $key =&amp;gt; $value) {&lt;br /&gt;
            if ($key === &amp;quot;digest&amp;quot;) {&lt;br /&gt;
                $responseHeadersDigest = $value;&lt;br /&gt;
                // stripping SHA algorithm for later comparison&lt;br /&gt;
                list($responseDigestAlgo, $responseDigestKey) = explode(&amp;quot;=&amp;quot;, $responseHeadersDigest, 2);&lt;br /&gt;
            } else if ($key === &amp;quot;signature&amp;quot;)&lt;br /&gt;
                $responseHeadersSignature = $value;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // calculating response digest&lt;br /&gt;
        $responseDigest = base64_encode(hash(strtolower(str_replace(&amp;quot;-&amp;quot;, &amp;quot;&amp;quot;, $responseDigestAlgo)), $responseBody, true));&lt;br /&gt;
&lt;br /&gt;
        // checking digest validity&lt;br /&gt;
        if ($responseDigest !== $responseDigestKey) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Digests are not the same&amp;quot;);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // extracting variables from signature header&lt;br /&gt;
        $signatureArray = explode(&amp;quot;,&amp;quot;, $responseHeadersSignature);&lt;br /&gt;
        foreach ($signatureArray as $value) {&lt;br /&gt;
            list($signatureKey, $signatureValue) = explode(&amp;quot;=&amp;quot;, $value, 2);&lt;br /&gt;
            $signature[$signatureKey] = trim($signatureValue, '&amp;quot;');&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generating siging string&lt;br /&gt;
        $signingStringArray = explode(&amp;quot; &amp;quot;, $signature['headers']);&lt;br /&gt;
        $signingString = '';&lt;br /&gt;
        foreach ($signingStringArray as $value) {&lt;br /&gt;
            $signingString = $signingString . trim($value) . &amp;quot;: &amp;quot; . trim($responseHeaders[$value]) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // trimming last '\n' character&lt;br /&gt;
        $signingString = trim($signingString);&lt;br /&gt;
&lt;br /&gt;
        // decoding signature&lt;br /&gt;
        $decodedSignature = base64_decode($signature['signature']);&lt;br /&gt;
&lt;br /&gt;
        // verifying signature&lt;br /&gt;
        $signatureVerify = openssl_verify($signingString, $decodedSignature, openssl_get_publickey(file_get_contents($GLOBALS['config']['sign_cert_server'])), 'RSA-SHA256');&lt;br /&gt;
&lt;br /&gt;
        if (!$signatureVerify) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Signature is not correct&amp;quot;);&lt;br /&gt;
            while (($err = openssl_error_string()))&lt;br /&gt;
                errorLog(false, false, $err);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return json_decode($responseBody, true);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $response;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function logs curl responses and errors in text files&lt;br /&gt;
 *&lt;br /&gt;
 * @param mixed $response the response&lt;br /&gt;
 * @param mixed $request  the request handle, used to get errors&lt;br /&gt;
 */&lt;br /&gt;
function errorLog($curl, $response, $request = false)&lt;br /&gt;
{&lt;br /&gt;
    $timestamp = '[' . date('Y-m-d H:i:s') . ']:';&lt;br /&gt;
    global $errorLog;&lt;br /&gt;
    global $responseLog;&lt;br /&gt;
&lt;br /&gt;
    if ($response === false) {&lt;br /&gt;
        if ($curl)&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . curl_error($request) . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
        else&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . $request . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    } else {&lt;br /&gt;
        file_put_contents($responseLog, $timestamp . &amp;quot;\n&amp;quot; . $response . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function generates the full signature header line from a set of headers, a certificate and the linked private key&lt;br /&gt;
 *&lt;br /&gt;
 * @param array  $headersToSign the headers to sign, in the $key =&amp;gt; $value format&lt;br /&gt;
 * @param string $certificate   the certificate linked to the used private key&lt;br /&gt;
 * @param string $privateKey    the private key used to sign the headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the full signature header line&lt;br /&gt;
 */&lt;br /&gt;
function generateSignatureHeader(array $headersToSign, string $certificate, string $privateKey): string&lt;br /&gt;
{&lt;br /&gt;
    // generating the signing string and header list&lt;br /&gt;
    $headers         = '';&lt;br /&gt;
    $signatureString = '';&lt;br /&gt;
    foreach ($headersToSign as $key =&amp;gt; $value) {&lt;br /&gt;
        $normalizedHeaderKey = trim(strtolower($key));&lt;br /&gt;
        $headers             .= $normalizedHeaderKey . ' ';&lt;br /&gt;
        $signatureString     .= $normalizedHeaderKey . ': ' . trim($value) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    $headers         = trim($headers);&lt;br /&gt;
    $signatureString = trim($signatureString);&lt;br /&gt;
&lt;br /&gt;
    // signing the signing string&lt;br /&gt;
    $signature = '';&lt;br /&gt;
    openssl_sign($signatureString, $signature, openssl_get_privatekey($privateKey), 'RSA-SHA256');&lt;br /&gt;
    $signature = base64_encode($signature);&lt;br /&gt;
&lt;br /&gt;
    // compiling the header line&lt;br /&gt;
    return &amp;quot;keyId=\&amp;quot;$certificate\&amp;quot;,algorithm=\&amp;quot;rsa-sha256\&amp;quot;,headers=\&amp;quot;$headers\&amp;quot;,signature=\&amp;quot;$signature\&amp;quot;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function deletes the access token from the session&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $baseURL&lt;br /&gt;
 */&lt;br /&gt;
function logout(string $baseURL): void&lt;br /&gt;
{&lt;br /&gt;
    global $localTokenFile;&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
    header('Location: ' . $baseURL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedIn(): void&lt;br /&gt;
{&lt;br /&gt;
    global $replacementListItems;&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Logged In&amp;lt;/h3&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;view_repos&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;label for=&amp;quot;report_id&amp;quot;&amp;gt;Report ID: &amp;lt;/label&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;number&amp;quot; id=&amp;quot;report_id&amp;quot; name=&amp;quot;report_id&amp;quot;&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;';&lt;br /&gt;
    foreach ($replacementListItems as $value) {&lt;br /&gt;
        echo '&amp;lt;label for=&amp;quot;' . $value . '&amp;quot;&amp;gt;' . $value . ': &amp;lt;/label&amp;gt;';&lt;br /&gt;
        echo '&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;' . $value . '&amp;quot; name=&amp;quot;' . $value . '&amp;quot;&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;';&lt;br /&gt;
    }&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;view&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'view_repos\').submit(); return false;&amp;quot;&amp;gt;View Repos&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;logout&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;logout&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'logout\').submit(); return false;&amp;quot;&amp;gt;Log Out&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedOut(): void&lt;br /&gt;
{&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Not logged in&amp;lt;/h3&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;login&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;login&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'login\').submit(); return false;&amp;quot;&amp;gt;Log In&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// display client &amp;quot;home&amp;quot; page&lt;br /&gt;
if (!isset($_POST['action'])) {&lt;br /&gt;
    if (!empty($localToken['access_token'])) {&lt;br /&gt;
        displayMenuLoggedIn();&lt;br /&gt;
    } else {&lt;br /&gt;
        displayMenuLoggedOut();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if (isset($_POST['action'])) {&lt;br /&gt;
    $replacementList = [];&lt;br /&gt;
    // Building replacement list&lt;br /&gt;
    foreach ($replacementListItems as $key =&amp;gt; $value) {&lt;br /&gt;
        $replacementList[$value] = (isset($_POST[$value]) &amp;amp;&amp;amp; strlen($_POST[$value]) &amp;gt; 0) ? $_POST[$value] : null;&lt;br /&gt;
    }&lt;br /&gt;
    // Building query array&lt;br /&gt;
    $repoQueryParameters = [&lt;br /&gt;
        'resource_type' =&amp;gt; 'generic_report',&lt;br /&gt;
        'client_id' =&amp;gt; $config['client_id'],&lt;br /&gt;
        'report_id' =&amp;gt; (isset($_POST['report_id']) &amp;amp;&amp;amp; strlen($_POST['report_id']) &amp;gt; 0) ? $_POST['report_id'] : null,&lt;br /&gt;
        'replacementList' =&amp;gt; $replacementList&lt;br /&gt;
    ];&lt;br /&gt;
    switch ($_POST['action']) {&lt;br /&gt;
        case 'login':&lt;br /&gt;
            $token = apiRequest(&lt;br /&gt;
                $config['token_uri'],&lt;br /&gt;
                [&lt;br /&gt;
                    'grant_type'    =&amp;gt; 'client_credentials',&lt;br /&gt;
                    'client_id'     =&amp;gt; $config['client_id'],&lt;br /&gt;
                    'client_secret' =&amp;gt; empty($config['client_secret']) ? null : $config['client_secret'],&lt;br /&gt;
                    'scope'         =&amp;gt; 'genericreports.readonly reports.readonly'&lt;br /&gt;
                ]&lt;br /&gt;
            );&lt;br /&gt;
            // We store the access token in the session so the user is &amp;quot;connected&amp;quot;&lt;br /&gt;
            // Only if the request has been successfully executed&lt;br /&gt;
            if (isset($token['access_token'])) {&lt;br /&gt;
                file_put_contents($localTokenFile, json_encode($token, true));&lt;br /&gt;
&lt;br /&gt;
                // Redirecting the user's browser to the &amp;quot;home&amp;quot; page&lt;br /&gt;
                header('Location: ' . $baseURL);&lt;br /&gt;
            } else {&lt;br /&gt;
                echo $token;&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
        case 'logout':&lt;br /&gt;
            logout($baseURL);&lt;br /&gt;
            break;&lt;br /&gt;
        case 'view':&lt;br /&gt;
            // call to the resource server&lt;br /&gt;
            $resources = apiRequest(&lt;br /&gt;
                $config['resource_uri'],&lt;br /&gt;
                $repoQueryParameters,&lt;br /&gt;
                $localToken,&lt;br /&gt;
                false&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            // Separating headers from body&lt;br /&gt;
            list($resourceHeader, $resourceBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $resources, 2);&lt;br /&gt;
&lt;br /&gt;
            $resourceHeaders = explode(&amp;quot;\r\n&amp;quot;, $resourceHeader);&lt;br /&gt;
            $firstHeaderLine = array_shift($resourceHeaders);&lt;br /&gt;
&lt;br /&gt;
            // Building form for download CSV button&lt;br /&gt;
            echo '&amp;lt;form method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
            foreach ($_POST as $key =&amp;gt; $value) {&lt;br /&gt;
                if ($key == &amp;quot;action&amp;quot;) {&lt;br /&gt;
                    $value = &amp;quot;download&amp;quot;;&lt;br /&gt;
                }&lt;br /&gt;
                echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;' . $key . '&amp;quot; name=&amp;quot;' . $key . '&amp;quot; value=&amp;quot;' . $value . '&amp;quot;&amp;gt;';&lt;br /&gt;
            }&lt;br /&gt;
            if (isset($_POST['report_id']) &amp;amp;&amp;amp; strlen($_POST['report_id']) &amp;gt; 0 &amp;amp;&amp;amp; !isset(json_decode($resourceBody, true)['error'])) {&lt;br /&gt;
                echo '&amp;lt;button&amp;gt;Download as CSV&amp;lt;/button&amp;gt;';&lt;br /&gt;
            }&lt;br /&gt;
            echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
            // Displaying requested content&lt;br /&gt;
            echo '&amp;lt;pre&amp;gt;';&lt;br /&gt;
            echo (strpos($firstHeaderLine, &amp;quot;200&amp;quot;)) ? json_decode($resourceBody) : $resourceBody;&lt;br /&gt;
            echo '&amp;lt;/pre&amp;gt;';&lt;br /&gt;
            break;&lt;br /&gt;
        case 'download':&lt;br /&gt;
            // call to the resource server&lt;br /&gt;
            $resources = apiRequest(&lt;br /&gt;
                $config['resource_uri'],&lt;br /&gt;
                $repoQueryParameters,&lt;br /&gt;
                $localToken,&lt;br /&gt;
                false&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            // Separating headers from body&lt;br /&gt;
            list($resourceHeader, $resourceBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $resources, 2);&lt;br /&gt;
            $resourceHeaders = explode(&amp;quot;\r\n&amp;quot;, $resourceHeader);&lt;br /&gt;
            array_shift($resourceHeaders);&lt;br /&gt;
&lt;br /&gt;
            // Dumping headers to insert them in current page&lt;br /&gt;
            foreach ($resourceHeaders as $key =&amp;gt; $value) {&lt;br /&gt;
                header($value);&lt;br /&gt;
            }&lt;br /&gt;
            echo json_decode($resourceBody);&lt;br /&gt;
            break;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Ce script a été conçu pour montrer le fonctionnement du mécanisme et tester l'implémentation d'un serveur, il n'a pas été testé extensivement. Il est conseillé d'utiliser une solution adaptée à un environnement de production.&lt;br /&gt;
&lt;br /&gt;
==Refresh Token==&lt;br /&gt;
Refresh Token (ou jeton de rafraîchissement en français) est un mécanisme d'autorisation particulier. Il ne peut fonctionner en tant que tel, il fonctionne de pair avec [[#Authorization-Code|Authorization Code]]. Lorsqu'un jeton d'accès arrive est arrivé en fin de vie, si le client y est autorisé, il peut faire une demande de renouvellement de son jeton d'accès auprès du serveur d'autorisation en présentant son jeton de rafraîchissement. Le serveur d'autorisation vérifie la validité et génère un autre jeton d'accès qu'il transmet au client, sans que l'utilisateur final n'aît à se connecter de nouveau.&lt;br /&gt;
&lt;br /&gt;
Le principe de fonctionnement du rafraîchissement d'un jeton est le suivant :&lt;br /&gt;
* Le jeton d'accès du client est arrivé à péremption. Le client effectue une demande de renouvellement en transmettant son Refresh Token au serveur d'autorisation.&lt;br /&gt;
* Le serveur d'autorisation vérifie la validité des informations, &amp;quot;consomme&amp;quot; le jeton de rafraîchissement et génère une nouvelle paire de jetons&lt;br /&gt;
* Le client reçoit sa nouvelle paire et utilise le nouveau jeton d'accès pour accéder aux ressources&lt;br /&gt;
&lt;br /&gt;
    +------+                       +-------------+                  +-----------+&lt;br /&gt;
    |Client|                       |   Serveur   |                  |  Serveur  |&lt;br /&gt;
    +--+---+                       |Autorisation |                  | Ressources|&lt;br /&gt;
       |                           +------+------+                  +-----+-----+&lt;br /&gt;
       |        Authentification          |                               |&lt;br /&gt;
       |         + Refresh Token          |                               |&lt;br /&gt;
       +---------------------------------&amp;gt;|                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |    Access (+ Refresh) token      |                               |&lt;br /&gt;
       |&amp;lt;---------------------------------+                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                      Requête vers|API                            |&lt;br /&gt;
       +----------------------------------+------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |&amp;lt;------------------------------+&lt;br /&gt;
       |                                  |  Vérification d'autorisation  |&lt;br /&gt;
       |                                  +------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                         Données /|Réponse                        |&lt;br /&gt;
       |&amp;lt;---------------------------------+-------------------------------+&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
&lt;br /&gt;
===Demande de renouvellement d'un jeton===&lt;br /&gt;
Pour obtenir un renouvellement de jeton d'accès, il faut effectuer la requête suivante : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Les paramètres suivants sont nécessaires :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant ''client_id'' reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|client_secret||string||La passphrase ''client_secret'' reçue pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|grant_type||string||Le mécanisme d'autorisation utilisé. Ici, la valeur doit être &amp;quot;refresh_token&amp;quot; (sans guillements).&lt;br /&gt;
|-&lt;br /&gt;
|scope||string||('''OPTIONNEL''') Liste des droits demandés par le client, séparés par des espaces.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Si la requête est correcte, un jeton d'accès ''access_token'' est fourni en réponse dans un objet au format JSON.&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,&lt;br /&gt;
  &amp;quot;expires_in&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;access_token&amp;quot;: &amp;quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw&amp;quot;,&lt;br /&gt;
  &amp;quot;refresh_token&amp;quot;: &amp;quot;a59ef39fa9bab9b95cd554f921e7f3080a34c90f23d2b8031d692b5ff2d0993dcc392d9c7f9a43242337ef144c1a5fe1d0174413ade973e1b628ac0bbfc39b23973534&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Liste des scopes disponibles==&lt;br /&gt;
Un scope sur OAuth2 correspond à un droit d'accès sur une ressource particulière. Chaque scope est unique et indique de manière explicite le privilège qu'il donne. Il n'y a aucune restriction d'utilisation des scopes par rapport aux mécanismes. Chaque scope peut être utilisé avec n'importe quel mécanisme. Il n'y a que des recommandations vis à vis de leur utilisation. OpenFlyers définit une liste de scopes dédiée aux ressources accessibles par les clients. Ces scopes sont les suivants :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Description&lt;br /&gt;
|-&lt;br /&gt;
|default.login||Comportement par défaut lorsqu'aucun scope n'est précisé ou qu'un scope est invalide. Ce scope est recommandé pour '''Authorization Code'''.&lt;br /&gt;
|-&lt;br /&gt;
|genericreports.readonly||Accéder aux rapports génériques autorisés pour le client en lecture seule. Ce scope est recommandé pour '''Client Credentials'''.&lt;br /&gt;
|-&lt;br /&gt;
|reports.readonly||Accéder aux rapports personnalisés autorisés pour le client en lecture seule. Ce scope est recommandé pour '''Client Credentials'''.&lt;br /&gt;
|}&lt;br /&gt;
==Prolonger la durée de vie de la session du client de démonstration==&lt;br /&gt;
La session du client de démonstration est initiée avec la méthode PHP [https://www.php.net/manual/en/function.session-start.php session_start]. Cette session peut être interrompue soit en cliquant sur le bouton de déconnexion, soit en fermant le navigateur (car les cookies associés à cette session se détruisent par défaut lorsque le navigateur est fermé).&lt;br /&gt;
&lt;br /&gt;
Pour permettre à la session de rester active même après la fermeture du navigateur, il faut utiliser la méthode PHP [https://www.php.net/manual/en/function.session-set-cookie-params.php session_set_cookie_params]. Cette méthode donne la possibilité de définir une durée de vie pour les différents cookies associés à la session.&lt;br /&gt;
&amp;lt;php&amp;gt;// Set the parameters for the session cookie in a PHP session in order to configure its lifetime in 30 days&lt;br /&gt;
$oauth2DemoSessionLifeTime = time() + (86400 * 30);&lt;br /&gt;
session_set_cookie_params($oauth2DemoSessionLifeTime);&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NB: Cette approche n'est pas particulièrement sécurisée et peut présenter des risques de sécurité pour OpenFlyers. Par conséquent, elle doit être utilisée avec précaution.&lt;br /&gt;
&lt;br /&gt;
==Révocation de token==&lt;br /&gt;
Pour initier la demande de révocation, rediriger le navigateur de l'utilisateur vers l'URL : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/revoke.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Envoyer également le paramètre suivant:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|access_token||string||Le jeton d'accès (Chaîne de caractère unique permettant de prouver qu'un client OAuth a le droit d'accéder à une ressource.)&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;php&amp;gt; apiRequest(&lt;br /&gt;
                $config['revoke_uri'],&lt;br /&gt;
                ['access_token' =&amp;gt; $_SESSION['auth_token']['access_token']],&lt;br /&gt;
                null,&lt;br /&gt;
                false&lt;br /&gt;
            );&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La demande de révocation se fait quand l'utilisateur clique sur le bouton '''Se déconnecter''' pour l'un des deux Clients '''Authorization Code''' et '''Client Credentials'''.&lt;br /&gt;
&lt;br /&gt;
Si les jetons sont révoqués, l'utilisateur ne peut pas accéder à la plateforme OpenFlyers, il doit se reconnecter.&lt;br /&gt;
&lt;br /&gt;
==Utiliser l'API==&lt;br /&gt;
Une fois un jeton d'accès obtenu, les données sont accessibles par une requête POST exécutée vers l'URL : &amp;lt;code&amp;gt;https://openflyers.com/nom-de-plateforme/oauth/resources.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée. La requête POST doit respecter une structure particulière. Cette structure diffère en fonction du type de ressource souhaité et chaque ressource ne peut être accédée qu'[[#Liste-des-scopes-disponibles|avec le scope qui lui est associé]]. Le jeton d'accès doit être renseigné dans l'en-tête HTTP ''Authorization'' en y indiquant la valeur complète du jeton d'accès reçu précédé du type de jeton reçu  : &amp;lt;code&amp;gt;Authorization: &amp;lt;token_type&amp;gt; &amp;lt;access_token&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Récupérer les informations de l'utilisateur connecté===&lt;br /&gt;
Ce type de ressource est nommé '''user_information'''. Cette ressource n'est accessible qu'avec le scope '''default.login'''. Cette ressource permet la récupération des informations de l'utilisateur connecté, en d'autre termes, l'utilisateur connecté lors de l'étape d'autorisation et correspondant à celui ayant émis la demande de jeton d'accès. À l'heure actuelle, seul l'identifiant de l'utilisateur connecté est retourné. La requête POST est construite de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|resource_type||string||Le type de ressource demandé, ici, ce champ correspond à '''user_information'''.&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Un exemple de requête complète au format JSON :&lt;br /&gt;
&amp;lt;javascript&amp;gt;POST /nom-de-plateforme/oauth/resources.php HTTP/1.1&lt;br /&gt;
Content-Type: application/x-www-form-urlencoded&lt;br /&gt;
Host: openflyers.com&lt;br /&gt;
Date: Wed, 04 Aug 2021 13:57:51 GMT&lt;br /&gt;
Accept: application/json&lt;br /&gt;
User-Agent: curl/7.64.1&lt;br /&gt;
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU&lt;br /&gt;
Signature: keyId=&amp;quot;58c450d937953829c8cca3613001f865a918da07&amp;quot;,&lt;br /&gt;
           algorithm=&amp;quot;rsa-sha256&amp;quot;,&lt;br /&gt;
           headers=&amp;quot;host content-type digest&amp;quot;,&lt;br /&gt;
           signature=&amp;quot;UsTjCPLsXzmo1b8FrA18SdLgaPamCpqR7tDHBhaiBnro6RbOkoD7=&amp;quot;&lt;br /&gt;
Digest: SHA-256=Bi6/9qfJXEWme2/9o7VQMyvf+MED523bWdtdi91opwk=&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;resource_type&amp;quot;:&amp;quot;user_information&amp;quot;,&lt;br /&gt;
    &amp;quot;client_id&amp;quot;:&amp;quot;d2615fe2020ec476&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La réponse est retournée dans un conteneur JSON.&lt;br /&gt;
&lt;br /&gt;
===Récupérer les rapports génériques===&lt;br /&gt;
Ce type de ressource est nommé '''generic_report'''. Cette ressource n'est accessible qu'avec le scope '''genericreports.readonly'''. Cette ressource permet la récupération des rapports génériques au format CSV autorisés pour le profil de l'utilisateur associé au client OAuth2 enregistré. La requête POST est construite de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|resource_type||string||Le type de ressource demandé, ici, ce champ correspond à '''generic_report'''.&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|report_id||int||Identifiant du rapport souhaité.&lt;br /&gt;
|-&lt;br /&gt;
|replacementList||array||Tableau correspondant aux différents paramètres modifiables pour générer le rapport souhaité.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Un exemple de requête complète au format JSON :&lt;br /&gt;
&amp;lt;javascript&amp;gt;POST /nom-de-plateforme/oauth/resources.php HTTP/1.1&lt;br /&gt;
Content-Type: application/x-www-form-urlencoded&lt;br /&gt;
Host: openflyers.com&lt;br /&gt;
Date: Wed, 04 Aug 2021 13:57:51 GMT&lt;br /&gt;
Accept: application/json&lt;br /&gt;
User-Agent: curl/7.64.1&lt;br /&gt;
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU&lt;br /&gt;
Signature: keyId=&amp;quot;58c450d937953829c8cca3613001f865a918da07&amp;quot;,&lt;br /&gt;
           algorithm=&amp;quot;rsa-sha256&amp;quot;,&lt;br /&gt;
           headers=&amp;quot;host content-type digest&amp;quot;,&lt;br /&gt;
           signature=&amp;quot;UsTjCPLsXzmo1b8FrA18SdLgaPamCpqR7tDHBhaiBnro6RbOkoD7=&amp;quot;&lt;br /&gt;
Digest: SHA-256=Bi6/9qfJXEWme2/9o7VQMyvf+MED523bWdtdi91opwk=&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;resource_type&amp;quot;:&amp;quot;generic_report&amp;quot;,&lt;br /&gt;
    &amp;quot;client_id&amp;quot;:&amp;quot;d2615fe2020ec476&amp;quot;,&lt;br /&gt;
    &amp;quot;report_id&amp;quot;:135,&lt;br /&gt;
    &amp;quot;replacementList&amp;quot;:{&lt;br /&gt;
        &amp;quot;year&amp;quot;:2018&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La réponse est un fichier CSV retourné dans un conteneur JSON.&lt;br /&gt;
&lt;br /&gt;
===Récupérer les rapports personnalisés===&lt;br /&gt;
Ce type de ressource est nommé '''report'''. Cette ressource n'est accessible qu'avec le scope '''reports.readonly'''. Cette ressource permet la récupération des rapports personnalisés au format CSV autorisés pour le profil de l'utilisateur associé au client OAuth2 enregistré. La requête POST est construite de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|resource_type||string||Le type de ressource demandé, ici, ce champ correspond à '''report'''.&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|report_id||int||Identifiant du rapport souhaité.&lt;br /&gt;
|-&lt;br /&gt;
|replacementList||array||Tableau correspondant aux différents paramètres modifiables pour générer le rapport souhaité.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Un exemple de requête complète au format JSON :&lt;br /&gt;
&amp;lt;javascript&amp;gt;POST /nom-de-plateforme/oauth/resources.php HTTP/1.1&lt;br /&gt;
Content-Type: application/x-www-form-urlencoded&lt;br /&gt;
Host: openflyers.com&lt;br /&gt;
Date: Wed, 04 Aug 2021 13:57:51 GMT&lt;br /&gt;
Accept: application/json&lt;br /&gt;
User-Agent: curl/7.64.1&lt;br /&gt;
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU&lt;br /&gt;
Signature: keyId=&amp;quot;58c450d937953829c8cca3613001f865a918da07&amp;quot;,&lt;br /&gt;
           algorithm=&amp;quot;rsa-sha256&amp;quot;,&lt;br /&gt;
           headers=&amp;quot;host content-type digest&amp;quot;,&lt;br /&gt;
           signature=&amp;quot;UsTjCPLsXzmo1b8FrA18SdLgaPamCpqR7tDHBhaiBnro6RbOkoD7=&amp;quot;&lt;br /&gt;
Digest: SHA-256=Bi6/9qfJXEWme2/9o7VQMyvf+MED523bWdtdi91opwk=&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;resource_type&amp;quot;:&amp;quot;report&amp;quot;,&lt;br /&gt;
    &amp;quot;client_id&amp;quot;:&amp;quot;d2615fe2020ec476&amp;quot;,&lt;br /&gt;
    &amp;quot;report_id&amp;quot;:1,&lt;br /&gt;
    &amp;quot;replacementList&amp;quot;:{&lt;br /&gt;
        &amp;quot;year&amp;quot;:2020&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La réponse est un fichier CSV retourné dans un conteneur JSON.&lt;br /&gt;
&lt;br /&gt;
=Procédures=&lt;br /&gt;
==Créer un client à partir du code source==&lt;br /&gt;
;Prérequis&lt;br /&gt;
Un client de démonstration est disponible pour le logiciel OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/index.php&lt;br /&gt;
&lt;br /&gt;
;Télécharger Le code source du client de démonstration :&lt;br /&gt;
&lt;br /&gt;
Le code source est mis à disposition par OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/oauth2-demo-src.zip &lt;br /&gt;
&lt;br /&gt;
Le code source est structuré de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 src demo folder.png|800px]]&lt;br /&gt;
&lt;br /&gt;
* Le dossier '''css''' contient tout le matériel nécessaire à la stylisation de la page web.&lt;br /&gt;
* Le dossier '''img''' contient les images affichées sur la page web.&lt;br /&gt;
* Le dossier '''ssl''' est le dossier contenant tous les certificats et les clé privées associées à chaque client. Il doit respecter une structure particulière décrite ci-dessous.&lt;br /&gt;
* Le fichier '''ClientDemo.php''' contient la classe '''ClientDemo'''. Cette classe contient toutes les méthodes nécessaires au fonctionnement du client de démonstration OAuth2.&lt;br /&gt;
* Le fichier '''index.php''' est le fichier à appeler depuis le navigateur. Ce fichier correspond au fichier qui gère les appels à la classe '''ClientDemo''' et exécute les méthodes dans l'ordre.&lt;br /&gt;
&lt;br /&gt;
Le dossier '''ssl''' doit respecter la structure suivante :&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 demo tree.png]]&lt;br /&gt;
&lt;br /&gt;
;[[#Générer des certificats|Générer les certificats]] :&lt;br /&gt;
Après la génération des certificats, les clés privées 'auth.key' et 'sign.key' remplacent celles présentes dans les dossiers 'ssl/AuthCodeDemo' et 'ssl/ClientCredDemo'.&lt;br /&gt;
&lt;br /&gt;
;[[#Enregistrer un client|Enregistrer les clients]] :&lt;br /&gt;
&lt;br /&gt;
*Deux clients doivent être créés :&lt;br /&gt;
**Le premier pour le mécanisme d'autorisation '''Authorization Code''',&lt;br /&gt;
**Le second pour le mécanisme d'autorisation '''Client Credentials'''.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 demo manage.png|800px]]&lt;br /&gt;
&lt;br /&gt;
*Télécharger le certificat du CA OpenFlyers en cliquant sur le bouton '''Télécharger le certificat CA''' de la page de gestion. Télécharger aussi le certificat de signature du serveur en cliquant sur le bouton '''Télécharger le certificat de signature du serveur''' de la page de gestion. Placer les deux certificats téléchargés à la racine du dossier '''ssl'''.&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Authorization Code''' et les placer dans le répertoire '''ssl/AuthCodeDemo'''. &lt;br /&gt;
*Modifier le fichier '''ssl/AuthCodeDemo/config.authcode.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;authorize_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/authorize.php&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;path_to_client/ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;path_to_client/ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Remplacer les &amp;lt;code&amp;gt;XXXXXXXXXXXXXXXX&amp;lt;/code&amp;gt; des champs &amp;lt;code&amp;gt;client_id&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;client_secret&amp;lt;/code&amp;gt; par les valeurs obtenues lors de [[#Enregistrer-un-client|l'enregistrement du client]].&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;mastructure&amp;lt;/code&amp;gt; par le nom de la structure sur laquelle la démo est testée.&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;path_to_client/&amp;lt;/code&amp;gt; par le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
**Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
**Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Client Credentials''' et les placer dans le répertoire '''ssl/ClientCredDemo'''.&lt;br /&gt;
*Modifier le fichier '''ssl/ClientCredDemo/config.clientcred.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;path_to_client/ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;path_to_client/ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Remplacer les &amp;lt;code&amp;gt;XXXXXXXXXXXXXXXX&amp;lt;/code&amp;gt; des champs &amp;lt;code&amp;gt;client_id&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;client_secret&amp;lt;/code&amp;gt; par les valeurs obtenues lors de [[#Enregistrer-un-client|l'enregistrement du client]].&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;mastructure&amp;lt;/code&amp;gt; par le nom de la structure sur laquelle la démo est testée.&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;path_to_client/&amp;lt;/code&amp;gt; par le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
**Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
**Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Suivre la [[#Utiliser le client|procédure d'utilisation du client de démonstration]] pour faire fonctionner le client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NB''': Le certificat de signature du serveur est unique à chaque plateforme et serveur. Ainsi, si le serveur ou la plateforme est modifié, le certificat doit être renouvelé.&lt;br /&gt;
&lt;br /&gt;
==Enregistrer un client==&lt;br /&gt;
Pour utiliser l'API OAuth2, il faut enregistrer un client OAuth2 auprès d'OpenFlyers. Pour ceci, suivre les étapes suivantes :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Pour le mécanisme d'authentification Client Credentials&lt;br /&gt;
*Créer un [[Gestion-des-profils#Ajouter-un-profil|nouveau profil]]. Ce profil doit permettre de gérer les droits du client OAuth2. Choisir un nom explicite, par exemple &amp;quot;Client OAuth rapports&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*Sélectionner les droits à assigner à ce profil. Ces droits limitent les données auxquelles le client OAuth2 a accès.&lt;br /&gt;
**Sélectionner les droits relatifs à l'enregistrement de clients OAuth2 dans l'onglet '''Admin''' (colonne '''Associé aux clients OAuth2''').&lt;br /&gt;
**Sélectionner les rapports accessibles par le profil précédemment créé.&lt;br /&gt;
&lt;br /&gt;
*Créer un nouvel utilisateur à partir du panneau de gestion. Cet utilisateur est virtuel et représente le serveur sur lequel fonctionne le client OAuth2.&lt;br /&gt;
**''Des identifiant et nom explicites sont recommandés (exemple : &amp;quot;serv1_oauth_client&amp;quot;)''&lt;br /&gt;
**'''Attention''' : tout utilisateur désactivé et associé à un client OAuth2 rend le client inactif, il faut donc changer l'utilisateur associé au client pour réactiver le client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Pour le mécanisme d'authentification Authorization Code&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Utilisateurs &amp;gt; Profils'''&lt;br /&gt;
*Dans l'onglet '''Généralités''', cocher la case relative à la colonne '''Connexion depuis l'extérieur (OAuth2)''' pour le profil souhaité.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Créer un nouveau client OAuth2&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Transferts &amp;gt; Exports &amp;gt; API OAuth2'''&lt;br /&gt;
[[File:Oauth2 manage.png|800px]]&lt;br /&gt;
*Cliquer sur le bouton Ajouter '''+''' ou '''Ajouter un client'''&lt;br /&gt;
[[File:Oauth2 client creation.png|800px]]&lt;br /&gt;
*Choisir un nom pour le client.&lt;br /&gt;
*Sélectionner le mécanisme d'autorisation utilisé par le client :&lt;br /&gt;
**'''Authorization Code''': permet d'utiliser OAuth2 comme solution SSO ou accéder à des données utilisateurs. Cette méthode peut être couplée avec le mécanisme de mémorisation de connexion (''Refresh Token'').&lt;br /&gt;
**'''Client Credentials''': permet d'utiliser OAuth2 dans un contexte d'automatisme.&lt;br /&gt;
*Saisir l'URI de redirection vers le client pour le mécanisme ''Authorization Code''.&lt;br /&gt;
*Sélectionner l'utilisateur virtuel créé précédemment pour le mécanisme ''Client Credentials''.&lt;br /&gt;
*[[#Générer-des-certificats|Générer deux CSR]] afin d'obtenir deux certificats signés et les saisir :&lt;br /&gt;
**'''Certificate Signing Request pour le certificat d'authentification''' est utilisé pour l'authentification mutuelle avec mTLS (auth_cert.csr.pem).&lt;br /&gt;
**'''Certificate Signing Request pour le certificat de signature''' est utilisé pour la signature des en-têtes HTTP (sign_cert.csr.pem).&lt;br /&gt;
&lt;br /&gt;
[[File:PublicKeysCopyScreen.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Cliquer sur '''Enregistrer'''.&lt;br /&gt;
&lt;br /&gt;
NB: La validité des certificats générés s'étend sur une période de '''3 années'''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Sauvegarder le couple ID/passphrase&lt;br /&gt;
Un couple ID/passphrase (client_id/client_secret) est généré. Ces deux clées ne sont communiquées qu'une seule fois. Elle doivent être stockées en toute sécurité et gardées confidentielles,&lt;br /&gt;
et Mettre ces identifiants dans le fichier '''config.clientcred.json'''.&lt;br /&gt;
[[File:Oauth2 client created.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:ConfigCredJsonScreen.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Télécharger les certificats crt&lt;br /&gt;
Les certificats signés sont téléchargeables depuis l'interface de gestion des clients OAuth2, les certificats sont disponibles dans les onglets '''Certificat d'authentification''' et '''Certificat de signature''' et les mettre dans le dossier '''/ssl''' du client OAuth2.&lt;br /&gt;
[[File:Oauth2 client certificates.png]]&lt;br /&gt;
&lt;br /&gt;
;Téléchargez les certificats du serveur.&lt;br /&gt;
*Les certificats du CA d'OpenFlyers et de signature HTTP du serveur sont nécessaires. Ils sont téléchargeables depuis l'interface de configuration des clients OAuth2.&lt;br /&gt;
[[File:DownloadServerCertifScreen.png|900px]]&lt;br /&gt;
*Dans certains cas d'utilisation, il peut être nécessaire d'ajouter le certificat du CA d'OpenFlyers au Trust Store du système. Si cette étape n'est pas réalisée, les certificats peuvent être considérés comme invalides et peuvent ne pas être utilisables.&lt;br /&gt;
*Pour ajouter le certificat CA au Trust Store du système, suivre les étapes suivantes:&lt;br /&gt;
**Sous Linux, copier le certificat CA d'OpenFlyers dans le dossier &amp;lt;code&amp;gt;/usr/local/share/ca-certificates&amp;lt;/code&amp;gt; et exécuter la commande &amp;lt;code&amp;gt;sudo update-ca-certificates&amp;lt;/code&amp;gt;&lt;br /&gt;
**Sous Windows,&lt;br /&gt;
***Double-cliquer sur le certificat CA d'OpenFlyers téléchargé depuis l'interface d'enregistrement des clients OAuth2&lt;br /&gt;
***Cliquer sur '''Installer un certificat...'''&lt;br /&gt;
***Choisir l'emplacement de stockage (utilisateur ou ordinateur) et cliquer sur '''Suivant''' puis '''Suivant''' et enfin '''Terminer'''&lt;br /&gt;
&lt;br /&gt;
==Générer des certificats==&lt;br /&gt;
L'API OAuth2 implémente [https://tools.ietf.org/html/draft-cavage-http-signatures-10 HTTP Signature] et l'[[Wikipedia-en:Mutual_authentication#mTLS|authentification TLS mutuelle]]. Ces mécanismes utilisent chacun une paire certificat/clé privée différente.&lt;br /&gt;
&lt;br /&gt;
Pour obtenir ces certificats, il faut d'abord générer des Certificate Signing Request (CSR).&lt;br /&gt;
&lt;br /&gt;
La procédure est la suivante :&lt;br /&gt;
*[[OpenSSL#Installer-OpenSSL-dans-un-environnement-Windows|Télécharger OpenSSL pour Windows]] ou [[OpenSSL#Utiliser-Openssl-d'Apache-sous-WAMP|utiliser Openssl d'Apache sous WAMP]].&lt;br /&gt;
*Utiliser les deux fichiers de configuration ''sign_cert.conf'' et ''auth_cert.conf'' ci-dessous et les remplir.&lt;br /&gt;
&lt;br /&gt;
;Fichier de configuration OpenSSL - sign_cert.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;[req]&lt;br /&gt;
default_bits       = 4096                     # taille par défaut des nouvelles clés, peut être surchargé dans la commande&lt;br /&gt;
encrypt_key        = no                       # chiffrer la clé générée&lt;br /&gt;
distinguished_name = req_distinguished_name   # pointe vers la catégorie spécifiée pour le Distinguished Name&lt;br /&gt;
x509_extensions    = v3_req                   # pointe vers la catégorie spécifiée pour les extensions x509&lt;br /&gt;
prompt             = no&lt;br /&gt;
&lt;br /&gt;
[req_distinguished_name]&lt;br /&gt;
C                  =                          # code à deux chiffres du pays (ex: FR)&lt;br /&gt;
ST                 =                          # région/état (ex: Gironde)&lt;br /&gt;
L                  =                          # ville (ex: Bordeaux)&lt;br /&gt;
O                  =                          # organisation (ex: OpenFlyers)&lt;br /&gt;
OU                 =                          # unité organisationelle (ex: IT)&lt;br /&gt;
CN                 =                          # nom de domaine (ex: openflyers.com)&lt;br /&gt;
&lt;br /&gt;
[v3_req]&lt;br /&gt;
keyUsage           = digitalSignature         # pour quelles opérations la clé peut-elle être utilisée&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Fichier de configuration OpenSSL - auth_cert.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;[req]&lt;br /&gt;
default_bits       = 4096                     # taille par défaut des nouvelles clés, peut être surchargé dans la commande&lt;br /&gt;
encrypt_key        = no                       # chiffrer la clé générée&lt;br /&gt;
distinguished_name = req_distinguished_name   # pointe vers la catégorie spécifiée pour le Distinguished Name&lt;br /&gt;
x509_extensions    = v3_req                   # pointe vers la catégorie spécifiée pour les extensions x509&lt;br /&gt;
prompt             = no&lt;br /&gt;
&lt;br /&gt;
[req_distinguished_name]&lt;br /&gt;
C                  =                          # code à deux chiffres du pays (ex: FR)&lt;br /&gt;
ST                 =                          # région/état (ex: Gironde)&lt;br /&gt;
L                  =                          # ville (ex: Bordeaux)&lt;br /&gt;
O                  =                          # organisation (ex: OpenFlyers)&lt;br /&gt;
OU                 =                          # unité organisationelle (ex: IT)&lt;br /&gt;
CN                 =                          # nom de domaine (ex: openflyers.com)&lt;br /&gt;
&lt;br /&gt;
[v3_req]&lt;br /&gt;
extendedKeyUsage   = clientAuth               # pour quelles opérations la clé peut-elle être utilisée&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Exécuter les commandes suivantes :&lt;br /&gt;
*&amp;lt;bash&amp;gt;openssl req -sha256 -newkey rsa -keyout sign.key -out sign_cert.csr.pem -outform PEM -config sign_cert.conf&amp;lt;/bash&amp;gt;&lt;br /&gt;
*&amp;lt;bash&amp;gt;openssl req -sha256 -newkey rsa -keyout auth.key -out auth_cert.csr.pem -outform PEM -config auth_cert.conf&amp;lt;/bash&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces commandes prennent chacune en entrée le fichier de configuration et génèrent une clé privée et un Certificate Signing Request. &lt;br /&gt;
&lt;br /&gt;
Une fois ces CSR obtenus :&lt;br /&gt;
*Les renseigner dans les champs prévus à cet effet lors de la [[#Enregistrer-un-client|création d'un client]] et télécharger les certificats signés depuis l'interface une fois le client créé.&lt;br /&gt;
*Garder la clé privée confidentielle. Une fuite poserait un risque de sécurité. Elle va de paire avec le certificat distribué par l'autorité de certification OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
==Mettre en place une connexion à l'API OpenFlyers sur un serveur mutualisé==&lt;br /&gt;
;Note&lt;br /&gt;
La procédure ci-après est destinée à une mise en place lorsqu'il n'y a pas d'accès SSH en ligne de commande mais uniquement un accès FTP. Dans ce cas, la création des clés privées et publics est effectuée &amp;quot;en local&amp;quot;. Dans la procédure suivante elle est effectuée depuis un PC sous '''Windows'''.&lt;br /&gt;
&lt;br /&gt;
;Prérequis&lt;br /&gt;
*Posséder les accès FTP :&lt;br /&gt;
**Hôte : XXXXXXXXXXXXXXXXXX&lt;br /&gt;
**Login : XXXXXXXX&lt;br /&gt;
**Mot de passe :  XXXXXXXX&lt;br /&gt;
**Port : XX (par exemple 21)&lt;br /&gt;
*Télécharger Le code source du client de démonstration à disposition par OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/oauth2-demo-src.zip &lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
*[[#Générer des certificats|Générer les certificats]] en local.&lt;br /&gt;
*Remplacer les clés privées 'auth.key' et 'sign.key' présentes dans les dossiers 'ssl/AuthCodeDemo' et 'ssl/ClientCredDemo' par les clés générées.&lt;br /&gt;
*[[#Enregistrer un client|Enregistrer les deux clients]] :&lt;br /&gt;
**Le premier pour le mécanisme d'autorisation '''Authorization Code'''.&lt;br /&gt;
**Le second pour le mécanisme d'autorisation '''Client Credentials'''.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 demo manage.png|800px]]&lt;br /&gt;
&lt;br /&gt;
*Télécharger le certificat du CA OpenFlyers en cliquant sur le bouton '''Télécharger le certificat CA''' de la page de gestion. &lt;br /&gt;
*Télécharger aussi le certificat de signature du serveur en cliquant sur le bouton '''Télécharger le certificat de signature du serveur''' de la page de gestion.&lt;br /&gt;
*Placer les deux certificats téléchargés à la racine du dossier '''ssl'''.&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Authorization Code''' et les placer dans le répertoire '''ssl/AuthCodeDemo'''. &lt;br /&gt;
*Modifier le fichier '''ssl/AuthCodeDemo/config.authcode.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;authorize_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/authorize.php&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;./ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;./ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Client Credentials''' et les placer dans le répertoire '''ssl/ClientCredDemo'''.&lt;br /&gt;
*Modifier le fichier '''ssl/ClientCredDemo/config.clientcred.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;./ssl/ClientCredDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;./ssl/ClientCredDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;./ssl/ClientCredDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;./ssl/ClientCredDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;./ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;./ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Remplacer les &amp;lt;code&amp;gt;XXXXXXXXXXXXXXXX&amp;lt;/code&amp;gt; des champs &amp;lt;code&amp;gt;client_id&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;client_secret&amp;lt;/code&amp;gt; par les valeurs obtenues lors de [[#Enregistrer-un-client|l'enregistrement du client]].&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;mastructure&amp;lt;/code&amp;gt; par le nom de la structure sur laquelle la démo est testée.&lt;br /&gt;
&lt;br /&gt;
*Transférer le fichier &amp;quot;oauth-demo&amp;quot; vers le serveur mutualisé :&lt;br /&gt;
**Télécharger [http://filezilla-project.org/download.php?type=client FileZilla].&lt;br /&gt;
**Lancer FileZilla.&lt;br /&gt;
**Entrer l'URl du serveur mutualisé dans le champ '''Hôte'''.&lt;br /&gt;
**Entrer le login dans le champ '''Nom d'utilisateur'''.&lt;br /&gt;
**Entrer le mot de passe dans le champ '''Mot de passe'''.&lt;br /&gt;
**Entrer le port dans le champ '''Port'''.&lt;br /&gt;
**Cliquer sur le bouton Connexion.&lt;br /&gt;
**Accéder à l'emplacement du répertoire &amp;quot;oauth-demo&amp;quot; en local à gauche dans l'onglet &amp;quot;Site local&amp;quot;.&lt;br /&gt;
**Choisir l'emplacement où placer le répértoire oauth-demo dans l'anglet '''Site distant''' à droite.&lt;br /&gt;
**Glisser et déposer le oauth-demo à l'emplacement choisi.&lt;br /&gt;
[[File:Transfer OauthDemo To Shared Server.png|800px]]&lt;br /&gt;
*Accéder au client OAuth-demo depuis le serveur mutualisé en utilisant l'URL du domaine du serveur : url_de_domaine_de_serveur/oauth-demo/index.php&lt;br /&gt;
*Modifier la valeur '''URI de redirection vers le client''' du client '''AuthCodeDemo''' précédemment créé en remplaçant l'ancienne URL par la nouvelle.&lt;br /&gt;
&lt;br /&gt;
*Suivre la [[#Utiliser le client|procédure d'utilisation du client de démonstration]] pour faire fonctionner le client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NB''': Le certificat de signature du serveur est unique à chaque plateforme et serveur. Ainsi, si le serveur ou la plateforme est modifié, le certificat doit être renouvelé.&lt;br /&gt;
&lt;br /&gt;
==Récupérer les données d'un utilisateur==&lt;br /&gt;
*Cliquer sur le bouton '''Récupérer les informations utilisateur''', l'identifiant de l'utilisateur s'affiche.&lt;br /&gt;
*Utiliser l'identifiant récupérer afin de récupérer toute information associée à cet utilisateur en [[Gestion-des-rapports#Ajouter-un-rapport|créant de nouveaux rapports personnalisés]]&lt;br /&gt;
&lt;br /&gt;
==Utiliser le client==&lt;br /&gt;
;Prérequis&lt;br /&gt;
Un client de démonstration est disponible pour le logiciel OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/index.php&lt;br /&gt;
&lt;br /&gt;
Le client de démonstration se présente de la manière suivante.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2-client-demo.png]]&lt;br /&gt;
&lt;br /&gt;
La démonstration est composée de deux colonnes. La première, nommée '''Authorization Code''' correspond [[#Authorization Code|au mécanisme d'autorisation du même nom]]. Elle dispose d'un bouton permettant de se connecter ainsi que d'une section indiquant les informations relatives à l'état de la connexion. La seconde colonne, nommée '''Client Credentials''' correspond elle aussi [[#Client Credentials|au mécanisme d'autorisation du même nom]]. Comme pour la première colonne, les éléments qui y sont présentés sont identiques. La différence étant que le bouton de connexion n'a pas le même effet étant donné que ces deux mécanismes sont différents. Chaque mécanisme est indépendant et il est possible de se connecter à un des deux mécanismes sans se connecter à l'autre ou se connecter aux deux en même temps.&lt;br /&gt;
&lt;br /&gt;
;Le mécanisme '''Authorization Code'''&lt;br /&gt;
*Cliquer sur le bouton '''Se connecter''' (ce qui redirige le navigateur vers la page de connexion du logiciel OpenFlyers).&lt;br /&gt;
*Renseigner les identifiants de l'administrateur pour s'y connecter.&lt;br /&gt;
*Nom d'utilisateur : '''admini'''.&lt;br /&gt;
*Mot de passe : '''azerty'''.&lt;br /&gt;
&lt;br /&gt;
Une fois les informations saisies, la page suivante est affichée.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth authorize demo.png]]&lt;br /&gt;
&lt;br /&gt;
*Cliquer sur le bouton '''Autoriser l'application''' pour autoriser la connexion (ce qui se redirige le navigateur vers la page du client de démonstration OAuth2).&lt;br /&gt;
&lt;br /&gt;
La première colonne doit afficher l'état de connexion '''Connecté''' ainsi qu'un nouveau bouton '''Récupèrer les informations utilisateurs''' qui permet de récupérer les informations de l'utilisateur connecté.&lt;br /&gt;
&lt;br /&gt;
;Le mécanisme '''Client Credentials'''&lt;br /&gt;
*Cliquer sur le bouton de connexion '''Se connecter''': contrairement à celui du mécanisme '''Authorization Code''', ne redirige pas le navigateur vers la page de connexion du logiciel OpenFlyers. Le bouton de connexion utilise les identifiants du client, ici le couple clé privée/clé publique, pour initier la connexion avec le serveur d'autorisation et obtenir un jeton d'accès.&lt;br /&gt;
&lt;br /&gt;
Une fois la connexion établie, la seconde colonne doit afficher l'état de connexion '''Connecté''' ainsi qu'un menu déroulant '''Rapport à récupèrer''' et un nouveau bouton '''Récupèrer le rapport''' qui permet de récupérer les rapports génériques et personnalisés.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le client, une fois connecté sur les deux mécanismes, se présente de la manière suivante.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 connected demo.png]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
==500 Internal Server Error en récupérant le rapport==&lt;br /&gt;
La démo utilise les valeurs par défaut pour extraire les rapports. Une erreur 500 indique une &amp;quot;Erreur de syntaxe ou violation d'accès&amp;quot; lors de l'exécution de la requête du rapport. Cela se produit parce que le rapport n'a pas de valeurs par défaut associées, étant donné qu'il n'a jamais été visualisé dans l'interface web. Pour résoudre ce problème, il vous suffit de visualiser le rapport et de cocher la case &amp;quot;Mémoriser ce choix&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Erreur &amp;quot;File not found.&amp;quot;==&lt;br /&gt;
Cette erreur se produit lorsque l'URI utilisé n'existe pas sur le serveur OpenFlyers. Vérifier les URIs mis en place dans les fichiers de configuration et essayer de nouveau.&lt;br /&gt;
&lt;br /&gt;
==int_rsa_verify : longueur de signature incorrecte==&lt;br /&gt;
Ce problème pourrait survenir si les fichiers ca.cert et sign_cert_server.cert ne proviennent pas du même serveur que celui du client oauth2.&lt;br /&gt;
La solution est :&lt;br /&gt;
&lt;br /&gt;
*D'essayer depuis le début l'étape de [[#Générer-des-certificats|génération]] et de [[#Enregistrer-un-client|configuration des certificats]] avec jsut la modification du client existant.&lt;br /&gt;
&lt;br /&gt;
;Si cela ne fonctionne pas:&lt;br /&gt;
&lt;br /&gt;
*Essayez de créer [[#Enregistrer-un-client|un nouveau client]] et refaites la configuration des certificats.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=API-OpenFlyers&amp;diff=13273</id>
		<title>API OpenFlyers</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=API-OpenFlyers&amp;diff=13273"/>
		<updated>2025-02-13T18:21:32Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: /* Générer les codes pour PKCE */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de décrire l'API OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
;Description de l'API&lt;br /&gt;
OpenFlyers possède une API basée sur [[Wikipedia-en:OAuth#OAuth_2.0|OAuth2]] qui permet à des serveurs extérieurs, dûment [[#Enregistrer-un-client|enregistrés]], de mettre en œuvre un processus d'[[Wikipedia-fr:Authentification_unique|authentification unique (SSO)]] et/ou de récupération des résultats des requêtes SQL de la [[Bibliothèque-des-rapports|bibliothèque des rapports]] ou des rapports personnalisés sous la forme de fichiers CSV.&lt;br /&gt;
&lt;br /&gt;
OAuth2 propose plusieurs mécanismes pour permettre l'authentification. Un mécanisme d'authentification détermine la séquence exacte des étapes impliquées dans le processus d'authentification d'OAuth2. OpenFlyers met à disposition deux mécanismes d'authentification :&lt;br /&gt;
*[[#Authorization Code|Authorization Code]] basé sur la méthode d'authentification par code d'autorisation et qui correspond au mécanisme associé à l'[[Wikipedia-fr:Authentification_unique|authentification unique (SSO)]],&lt;br /&gt;
*[[#Client Credentials|Client Credentials]] basé sur la méthode d'authentification avec les identifiants clients et qui est utilisé dans un contexte d'automatisme sans autorisation de l'utilisateur au préalable.&lt;br /&gt;
&lt;br /&gt;
Dans les chapitres qui suivent, le terme ''ressource'' fait référence à la définition OAuth2. Une ressource dans OAuth2 est un élément qui peut être :&lt;br /&gt;
*une ou des données comme des photos, des documents, des contacts ou des informations personnelles,&lt;br /&gt;
*un ou plusieurs services comme des transferts de fonds, la récupération de rapports ou l'ajout d'articles sur un blog,&lt;br /&gt;
*toute ressource nécessitant un accès restreint.&lt;br /&gt;
&lt;br /&gt;
OpenFlyers définit plusieurs [[#Utiliser-l'API|types de ressources]] :&lt;br /&gt;
*les [[#Récupérer-les-informations-de-l'utilisateur-connecté|informations de l'utilisateur connecté]],&lt;br /&gt;
*les [[#Récupérer les rapports génériques|rapports génériques]] ou [[#Récupérer les rapports personnalisés|personnalisés]] au format CSV.&lt;br /&gt;
&lt;br /&gt;
OAuth2 dispose de ''scopes''. Un scope est un privilège définit de manière explicite permettant l'accès à une ressource protégée. OpenFlyers met à disposition une [[#Liste des scopes disponibles|liste de scopes]] utilisables à travers l'API.&lt;br /&gt;
&lt;br /&gt;
Deux protocoles de sécurité sont présents dans l'API OpenFlyers :&lt;br /&gt;
*[[#Authentification-TLS-Mutuelle-(mTLS)|mTLS]] : il permet d'authentifier le client avec un certificat TLS, en plus d'authentifier le serveur avec un certificat. Ce protocole permet d'éviter les usurpations d'identité.&lt;br /&gt;
*[[#HTTP-Signature|HTTP-Signature]] : il permet de signer les en-têtes et le corps (lorsqu'il y en a un) des messages échangés afin d'en garantir leur intégrité.&lt;br /&gt;
&lt;br /&gt;
;Premiers pas - Client de démonstration&lt;br /&gt;
Un client de démonstration est disponible pour comprendre les mécanismes décrits ci-dessous.&lt;br /&gt;
&lt;br /&gt;
L'utilisation de ce client de démonstration est décrite dans la procédure [[#Utiliser-le-client|Utiliser le client]] de cette page.&lt;br /&gt;
&lt;br /&gt;
Le client de démonstration est lui-même accessible à cette adresse : https://openflyers.com/oauth2-demo/index.php&lt;br /&gt;
&lt;br /&gt;
Le code source du client de démonstration est mis à disposition par OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/oauth2-demo-src.zip&lt;br /&gt;
&lt;br /&gt;
L'utilisation du code source est décrite dans la procédure [[#Créer-un-client-à-partir-du-code-source|Créer un client à partir du code source]].&lt;br /&gt;
&lt;br /&gt;
=Définitions=&lt;br /&gt;
==Authentification TLS Mutuelle (mTLS)==&lt;br /&gt;
En général dans une communication TLS, seul le serveur a l'obligation de fournir un certificat. Il est également possible pour le client de fournir un certificat. Ce principe s'appelle l'authentification mutuelle et est mise en place avec Mutual TLS (ou [[Wikipedia-en:Mutual_authentication#mTLS|mTLS]]).&lt;br /&gt;
&lt;br /&gt;
OpenFlyers associe un certificat pour l'authentification mutuelle unique à chaque client OAuth2.&lt;br /&gt;
&lt;br /&gt;
;Envoyer un certificat client&lt;br /&gt;
Côté client, le code suivant peut être utilisé pour fournir à cURL le certificat et la clé correspondante ainsi que le certificat du CA d'OpenFlyers à utiliser pour la connexion :&lt;br /&gt;
&amp;lt;php&amp;gt;curl_setopt_array($request, [&lt;br /&gt;
    CURLOPT_SSLVERSION =&amp;gt; CURL_SSLVERSION_TLSv1_2,&lt;br /&gt;
    CURLOPT_CAINFO     =&amp;gt; $caCertificatePath,&lt;br /&gt;
    CURLOPT_SSLCERT    =&amp;gt; $certificatePath,&lt;br /&gt;
    CURLOPT_SSLKEY     =&amp;gt; $keyPath&lt;br /&gt;
]);&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''À noter''' : le certificat du CA d'OpenFlyers est nécessaire pour assurer la validité des certificats utilisés.&lt;br /&gt;
&lt;br /&gt;
==HTTP Signature==&lt;br /&gt;
HTTP Signature utilise le principe de la signature numérique pour garantir l'authenticité et l'intégrité du message HTTP.&lt;br /&gt;
&lt;br /&gt;
La signature est générée à l'aide d'une clé privée et vérifiée à l'aide de la clé publique correspondante ou d'un certificat contenant cette clé publique.&lt;br /&gt;
&lt;br /&gt;
HTTP Signature utilise deux en-têtes HTTP :&lt;br /&gt;
*Signature : contient la signature et ses métadonnées.&lt;br /&gt;
*Digest : contient le corps du message haché.&lt;br /&gt;
&lt;br /&gt;
===Digest===&lt;br /&gt;
Le ''digest'' est calculé comme ceci : &amp;lt;code&amp;gt;digest = base64encode(sha256(corps du message))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et l'en-tête est structuré de la manière suivante : &amp;lt;code&amp;gt;Digest: SHA-256=&amp;lt;digest&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un autre algorithme de hachage peut être utilisé, SHA-256 reste cependant le plus répendu.&lt;br /&gt;
&lt;br /&gt;
;Exemple en php&lt;br /&gt;
&amp;lt;php&amp;gt;$digestHeader = 'Digest: SHA-256=' . base64_encode(hash('sha256', $postData, true));&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Signature===&lt;br /&gt;
L'en-tête HTTP de signature est structuré de la manière suivante : &amp;lt;code&amp;gt;Signature: keyId=&amp;quot;&amp;lt;keyId&amp;gt;&amp;quot;,algorithm=&amp;quot;&amp;lt;algo&amp;gt;&amp;quot;,headers=&amp;quot;&amp;lt;signed_headers&amp;gt;&amp;quot;,signature=&amp;quot;&amp;lt;signature&amp;gt;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le champ ''keyId'' correspond à un identifiant permettant l'identification de la clé utilisée pour vérifier la signature. Pour l'API d'OpenFlyers, sa valeur correspond à l'empreinte SHA-1 du certificat au format PEM à utiliser pour vérifier la signature.&lt;br /&gt;
&lt;br /&gt;
L'algorithme ''algo'' correspond à celui utilisé pour générer la signature, exemple : &amp;lt;code&amp;gt;rsa-sha256&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
La valeur de ''signed_headers'' correspond à la liste des en-têtes inclus dans la signature séparés d'un espace. Exemple : &amp;lt;code&amp;gt;date digest (request-target)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour générer la signature, une chaîne de caractères appelée &amp;lt;code&amp;gt;signing string&amp;lt;/code&amp;gt; contenant les en-têtes au format &amp;lt;code&amp;gt;lowercase_header_name: value&amp;lt;/code&amp;gt; séparés par une nouvelle ligne au format LF (&amp;lt;code&amp;gt;\n&amp;lt;/code&amp;gt;) est d'abord générée. Exemple avec les en-têtes &amp;quot;date&amp;quot; et &amp;quot;(request-target)&amp;quot; :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;(request-target): post /some/uri\ndate: Tue, 07 Jun 2014 20:51:35 GMT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La signature est ensuite générée comme ceci : &amp;lt;code&amp;gt;base64encode(algo(signing string))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Exemple en php&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;function generateSignatureHeader(array $headersToSign, string $certificateFingerprint, string $privateKey): string&lt;br /&gt;
{&lt;br /&gt;
    // generating the signing string and header list&lt;br /&gt;
    $headers         = '';&lt;br /&gt;
    $signatureString = '';&lt;br /&gt;
    foreach ($headersToSign as $key =&amp;gt; $value) {&lt;br /&gt;
        $normalizedHeaderKey = trim(strtolower($key));&lt;br /&gt;
        $headers             .= $normalizedHeaderKey . ' ';&lt;br /&gt;
        $signatureString     .= $normalizedHeaderKey . ': ' . trim($value) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // trim extra whitespace&lt;br /&gt;
    $headers         = trim($headers);&lt;br /&gt;
    $signatureString = trim($signatureString);&lt;br /&gt;
&lt;br /&gt;
    // signing the signing string&lt;br /&gt;
    $signature = '';&lt;br /&gt;
    openssl_sign($signatureString, $signature, $privateKey, 'RSA-SHA256');&lt;br /&gt;
    $signature = base64_encode($signature);&lt;br /&gt;
&lt;br /&gt;
    // compiling the header line&lt;br /&gt;
    return &amp;quot;Signature: keyId=\&amp;quot;$certificateFingerprint\&amp;quot;,algorithm=\&amp;quot;rsa-sha256\&amp;quot;,headers=\&amp;quot;$headers\&amp;quot;,signature=\&amp;quot;$signature\&amp;quot;&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Les variables ''$certificateFingerprint'' et ''$privateKey'' correspondent respectivement à une empreinte SHA-1 de certificat et à une clé privée, tous deux au format PEM. &lt;br /&gt;
&lt;br /&gt;
La variable ''$headersToSign'' est un tableau formaté de la manière suivante : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;[&lt;br /&gt;
    $headerName =&amp;gt; $headerValue,&lt;br /&gt;
    ...&lt;br /&gt;
]&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''À noter''' : les en-têtes sont à signer côté client avec le certificat de signature signé par le CA d'OpenFlyers et dédié au client ainsi que la clé privée associée. Le certificat de signature dédié au client est téléchargeable depuis l'interface de gestion des clients OAuth2. Les en-têtes de la réponse du serveur quant à elles doivent être vérifiées avec le certificat de signature HTTP du serveur, téléchargeable aussi depuis l'interface de configuration des clients OAuth2.&lt;br /&gt;
&lt;br /&gt;
=Client OAuth2=&lt;br /&gt;
Une fois le client OAuth2 configuré sur OpenFlyers, il faut l'utiliser avec un client créé au préalable pour communiquer avec le serveur d'autorisation et l'API.&lt;br /&gt;
&lt;br /&gt;
Plusieurs [https://oauth.net/code/ bibliothèques] simplifiant la création d'un client sont disponibles.&lt;br /&gt;
&lt;br /&gt;
Des scripts client basiques écrits en php sont aussi fournis pour les mécanismes [[#Script-client-:-authorization-code|''authorization_code'']] et [[#Script-client-:-client-credentials|''client_credentials'']]&lt;br /&gt;
&lt;br /&gt;
==Authorization Code==&lt;br /&gt;
Ce flux OAuth2 se déroule en plusieurs étapes :&lt;br /&gt;
*Le client redirige le navigateur de l'utilisateur vers l'URL d'autorisation.&lt;br /&gt;
*Le navigateur de l'utilisateur est redirigé vers l'URL fournie durant la demande ou durant l'enregistrement du client.&lt;br /&gt;
*Le client récupère un code d'autorisation grâce à la redirection précédente, et échange ce code contre un jeton d'accès auprès du serveur d'autorisation.&lt;br /&gt;
*Le client peut utiliser ce code d'accès :&lt;br /&gt;
**Comme preuve d'authentification pour une solution SSO (Single Sign-On).&lt;br /&gt;
**Pour accéder à des données sur le serveur distant en utilisant l'API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    +-----------+                   +------+                +-----------+                  +-------------+                  +-----------+&lt;br /&gt;
    |Utilisateur|                   |Client|                |Navigateur |                  |   Serveur   |                  |  Serveur  |&lt;br /&gt;
    +-----+-----+                   +--+---+                +-----+-----+                  |Autorisation |                  | Ressources|&lt;br /&gt;
          |                            |                          |                        +------+------+                  +-----+-----+&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                   Demande|d'autorisation                 |                               |&lt;br /&gt;
          |                            +-------------------------&amp;gt;+------------------------------&amp;gt;|                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |Authentification + Formulaire d'autorisation              |                               |&lt;br /&gt;
          |&amp;lt;---------------------------+--------------------------+&amp;lt;------------------------------+                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |      Autorisation        |                               |                               |&lt;br /&gt;
          +----------------------------+-------------------------&amp;gt;+------------------------------&amp;gt;|                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                      Code|d'autorisation                 |                               |&lt;br /&gt;
          |                            |&amp;lt;-------------------------+&amp;lt;------------------------------+                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                Demande de|token                          |                               |&lt;br /&gt;
          |                            +--------------------------+------------------------------&amp;gt;|                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                 Access (+|Refresh) token                 |                               |&lt;br /&gt;
          |                            |&amp;lt;-------------------------+-------------------------------+                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |       Requête vers API        |                               |&lt;br /&gt;
          |                            +--------------------------+-------------------------------+------------------------------&amp;gt;|&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |                               |&amp;lt;------------------------------+&lt;br /&gt;
          |                            |                          |                               |  Vérification d'autorisation  |&lt;br /&gt;
          |                            |                          |                               +------------------------------&amp;gt;|&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |      Données/Réponse          |                               |&lt;br /&gt;
          |                            |&amp;lt;-------------------------+-------------------------------+-------------------------------+&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Générer les codes pour PKCE===&lt;br /&gt;
Pour faire fonctionner le client OAuth2, il faut générer deux codes pour l'extension PKCE :&lt;br /&gt;
*Un ''code_verifier'' échangé pendant la demande de jeton d'accès.&lt;br /&gt;
*Un ''code_challenge'' dérivé du ''code_verifier'' et échangé pendant la demande d'autorisation.&lt;br /&gt;
&lt;br /&gt;
;Générer le ''code_verifier''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;function generateCodeVerifier($length = 128): string&lt;br /&gt;
{&lt;br /&gt;
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~';&lt;br /&gt;
    $outputCode = '';&lt;br /&gt;
&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $length; $i++) {&lt;br /&gt;
        $index      = random_int(0, strlen($characters) - 1);&lt;br /&gt;
        $outputCode .= $characters[$index];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $outputCode;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cette fonction permet de générer un ''code_verifier'' avec une longueur donnée. Le ''code_verifier'' doit avoir une longueur entre 43 et 128 caractères.&lt;br /&gt;
&lt;br /&gt;
;Générer le ''code_challenge''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;function computeCodeChallenge(string $codeVerifier): string&lt;br /&gt;
{&lt;br /&gt;
    return strtr(rtrim(base64_encode(hash('sha256', $codeVerifier, true)), '='), '+/', '-_');&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cette fonction génère le ''code_challenge'' à partir du ''code_verifier'' fourni.&lt;br /&gt;
&lt;br /&gt;
===Demande d'autorisation===&lt;br /&gt;
Pour initier la demande d'autorisation, rediriger le navigateur de l'utilisateur vers l'URL : &amp;lt;code&amp;gt;GET https://openflyers.com/nom-de-plateforme/oauth/authorize.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Envoyer également les paramètres suivants :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|response_type||string||Le type de réponse envoyée par le serveur. Doit utiliser la valeur &amp;quot;code&amp;quot; (sans guillements) pour ce mécanisme.&lt;br /&gt;
|-&lt;br /&gt;
|redirect_uri||string||L'URI (ou l'URL) fourni pendant l'enregistrement du client et vers lequel l'utilisateur est redirigé après la demande d'autorisation.&lt;br /&gt;
|-&lt;br /&gt;
|scope||string||[[#Liste-des-scopes-disponibles|Liste des droits demandés par le client]], séparés par des espaces.&lt;br /&gt;
|-&lt;br /&gt;
|state||string||Chaîne de caractère aléatoire utilisée pour éviter les [https://fr.wikipedia.org/wiki/Cross-site_request_forgery attaques CSRF]. '''Fortement recommandé'''.&lt;br /&gt;
|-&lt;br /&gt;
|code_challenge||string||Code nécessaire pour le fonctionnement de l'extension [[#Générer-les-codes-pour-PKCE|PKCE]].&lt;br /&gt;
|-&lt;br /&gt;
|code_challenge_method||string||Méthode utilisée pour générer le ''code_challenge''. Ici, la valeur est &amp;quot;S256&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Demande de jeton d'accès===&lt;br /&gt;
Après avoir répondu à la demande, l'utilisateur est redirigé vers l'URI fourni pendant l'enregistrement du client. Si la demande est acceptée, un code temporaire : ''code'' est fourni, ainsi que le paramètre ''state'' fourni pendant la demande avec la même valeur. Si la demande est refusée, un code d'erreur est renvoyé.&lt;br /&gt;
;Si le paramètre ''state'' a une valeur différente de celle envoyée avec la demande, c'est peut-être une tentative d'attaque et il faut refuser la réponse.&lt;br /&gt;
&lt;br /&gt;
Echanger ce ''code'' contre un jeton d'accès via l'URL : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Les paramètres suivants sont également nécessaires :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|client_secret||string||La passphrase reçue pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|code||string||Le code temporaire reçu dans la réponse à la demande d'autorisation.&lt;br /&gt;
|-&lt;br /&gt;
|grant_type||string||Le mécanisme d'autorisation utilisé. Ici, sa valeur doit être ''authorization_code''&lt;br /&gt;
|-&lt;br /&gt;
|redirect_uri||string||L'URI (ou l'URL) de redirection fourni pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|code_verifier||string||Le ''code_verifier'' utilisé pour générer le ''code_challenge'' de la demande d'autorisation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Si la requête est correcte, un jeton d'accès (Access Token) ainsi qu'un jeton de rafraîchissement (Refresh Token) sont fournis en réponse dans un objet au format JSON.&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,&lt;br /&gt;
  &amp;quot;expires_in&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;access_token&amp;quot;: &amp;quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw&amp;quot;,&lt;br /&gt;
  &amp;quot;refresh_token&amp;quot;: &amp;quot;a59ef39fa9bab9b95cd554f921e7f3080a34c90f23d2b8031d692b5ff2d0993dcc392d9c7f9a43242337ef144c1a5fe1d0174413ade973e1b628ac0bbfc39b23973534&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Script client : Authorization Code===&lt;br /&gt;
Voici un exemple simple de client OAuth2 pour le mécanisme d'authentification par code d'autorisation (Authorization Code).&lt;br /&gt;
&lt;br /&gt;
Fichier de configuration ''config.authcode.json'' :&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;authorize_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/authorize.php&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;/path/to/client/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;/path/to/client/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;/path/to/client/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;/path/to/client/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;/path/to/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;/path/to/server/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
Où &amp;lt;code&amp;gt;/path/to/client/&amp;lt;/code&amp;gt; est le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
*Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/ssl/AuthCodeDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
*Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./ssl/AuthCodeDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ce fichier de configuration doit se situer au même niveau que le script PHP dans le système de fichiers.&lt;br /&gt;
&lt;br /&gt;
Script PHP :&lt;br /&gt;
&amp;lt;php&amp;gt;&amp;lt;?php&lt;br /&gt;
$localTokenFile    = 'token.json';&lt;br /&gt;
// create token file if it does not exist&lt;br /&gt;
if (!file_exists($localTokenFile))&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
$config                 = json_decode(file_get_contents('config.authcode.json'), true);&lt;br /&gt;
$localToken             = json_decode(file_get_contents($localTokenFile), true);&lt;br /&gt;
$GLOBALS['config']      = $config;&lt;br /&gt;
&lt;br /&gt;
// Build the baseURL, accounting for protocol, port, name and endpoint. Used for redirection&lt;br /&gt;
$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';&lt;br /&gt;
$port     = ($protocol == 'https://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 443)&lt;br /&gt;
    || ($protocol == 'http://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 80) ? '' : ':' . $_SERVER['SERVER_PORT'];&lt;br /&gt;
&lt;br /&gt;
$baseURL            = $protocol . $_SERVER['SERVER_NAME'] . $port . $_SERVER['PHP_SELF'];&lt;br /&gt;
$errorLog           = 'error_log.log';&lt;br /&gt;
$responseLog        = 'response_log.log';&lt;br /&gt;
$GLOBALS['baseURL'] = $baseURL;&lt;br /&gt;
&lt;br /&gt;
//Session cookies are used to store information necessary for the authorization code flow&lt;br /&gt;
session_start();&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function is used to make api calls to the Authorization Server and the Resource Server&lt;br /&gt;
 *&lt;br /&gt;
 * @param       $url&lt;br /&gt;
 * @param       $post&lt;br /&gt;
 * @param array $headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return mixed&lt;br /&gt;
 */&lt;br /&gt;
function apiRequest($url, $post = null, $token = false, $auth = true, $refresh = false, $headers = array())&lt;br /&gt;
{&lt;br /&gt;
    $ch = curl_init($url);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HEADER, true);&lt;br /&gt;
&lt;br /&gt;
    $method = 'get';&lt;br /&gt;
&lt;br /&gt;
    if ($post) {&lt;br /&gt;
        $method   = 'post';&lt;br /&gt;
        $postData = http_build_query($post);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POST, true);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);&lt;br /&gt;
&lt;br /&gt;
        $headersToSign['Content-Type'] = 'application/x-www-form-urlencoded';&lt;br /&gt;
        $headersToSign['digest']       = 'SHA-256=' . base64_encode(hash('sha256', $postData, true));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $urlComponents = parse_url($url);&lt;br /&gt;
&lt;br /&gt;
    $headersToSign['(request-target)'] = $method . ' ' . $urlComponents['path'];&lt;br /&gt;
    $headersToSign['Host']             = $urlComponents['host'];&lt;br /&gt;
    $headersToSign['Date']             = gmdate('D, j M Y H:i:s T');&lt;br /&gt;
&lt;br /&gt;
    // generating the signature header&lt;br /&gt;
    $keyId                = openssl_x509_fingerprint(file_get_contents($GLOBALS['config']['sign_cert']));&lt;br /&gt;
    $privateKey           = file_get_contents($GLOBALS['config']['sign_key']);&lt;br /&gt;
    $headers['Signature'] = generateSignatureHeader($headersToSign, $keyId, $privateKey);&lt;br /&gt;
&lt;br /&gt;
    $headers['Accept']     = 'application/json';&lt;br /&gt;
    $headers['User-Agent'] = $GLOBALS['baseURL'];&lt;br /&gt;
    unset($headersToSign['(request-target)']);&lt;br /&gt;
    $headers               += $headersToSign;&lt;br /&gt;
&lt;br /&gt;
    if ($token) {&lt;br /&gt;
        $headers['Authorization'] = $token['token_type'] . ' ' . $token['access_token'];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // formatting the headers&lt;br /&gt;
    $httpFormattedHeaders = [];&lt;br /&gt;
    foreach ($headers as $key =&amp;gt; $value) {&lt;br /&gt;
        $httpFormattedHeaders[] = trim($key) . ': ' . trim($value);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HTTPHEADER, $httpFormattedHeaders);&lt;br /&gt;
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);&lt;br /&gt;
&lt;br /&gt;
    // for development environment only&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_VERBOSE, true);&lt;br /&gt;
&lt;br /&gt;
    // defining TLS client certificates for Mutual TLS&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_CAINFO, $GLOBALS['config']['auth_cacert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLCERT, $GLOBALS['config']['auth_cert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLKEY, $GLOBALS['config']['auth_key']);&lt;br /&gt;
&lt;br /&gt;
    $response = curl_exec($ch);&lt;br /&gt;
&lt;br /&gt;
    // logging errors and responses&lt;br /&gt;
    errorLog(true, $response, $ch);&lt;br /&gt;
&lt;br /&gt;
    curl_close($ch);&lt;br /&gt;
&lt;br /&gt;
    // in case an authentication request is executed&lt;br /&gt;
    if ($auth) {&lt;br /&gt;
        // required when a refresh token request is issued&lt;br /&gt;
        // because there is only one header in the response&lt;br /&gt;
        // while there are two for regular auth requests&lt;br /&gt;
        if (!$refresh) {&lt;br /&gt;
            list($firstResponseHeaders, $secondResponseHeaders, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 3);&lt;br /&gt;
            if (!$responseBody) {&lt;br /&gt;
                list($secondResponseHeaders, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 2);&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            list($secondResponseHeaders, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 2);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $responseHeadersDigest = '';&lt;br /&gt;
        $responseHeadersSignature = '';&lt;br /&gt;
        // extracting digest and signature from headers&lt;br /&gt;
        $responseHeadersArray = explode(&amp;quot;\r\n&amp;quot;, $secondResponseHeaders);&lt;br /&gt;
        $responseProtocol = array_shift($responseHeadersArray);&lt;br /&gt;
&lt;br /&gt;
        foreach ($responseHeadersArray as $value) {&lt;br /&gt;
            list($responseHeadersKeys, $responseHeadersValue) = explode(&amp;quot;: &amp;quot;, $value, 2);&lt;br /&gt;
            $responseHeaders[strtolower($responseHeadersKeys)] = $responseHeadersValue;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $responseDigestAlgo = '';&lt;br /&gt;
        $responseDigestKey = '';&lt;br /&gt;
        foreach ($responseHeaders as $key =&amp;gt; $value) {&lt;br /&gt;
            if ($key === &amp;quot;digest&amp;quot;) {&lt;br /&gt;
                $responseHeadersDigest = $value;&lt;br /&gt;
                // stripping SHA algorithm for later comparison&lt;br /&gt;
                list($responseDigestAlgo, $responseDigestKey) = explode(&amp;quot;=&amp;quot;, $responseHeadersDigest, 2);&lt;br /&gt;
            } else if ($key === &amp;quot;signature&amp;quot;)&lt;br /&gt;
                $responseHeadersSignature = $value;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // calculating response digest&lt;br /&gt;
        $responseDigest = base64_encode(hash(strtolower(str_replace(&amp;quot;-&amp;quot;, &amp;quot;&amp;quot;, $responseDigestAlgo)), $responseBody, true));&lt;br /&gt;
&lt;br /&gt;
        // checking digest validity&lt;br /&gt;
        if ($responseDigest !== $responseDigestKey) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Digests are not the same&amp;quot;);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // extracting variables from signature header&lt;br /&gt;
        $signatureArray = explode(&amp;quot;,&amp;quot;, $responseHeadersSignature);&lt;br /&gt;
        foreach ($signatureArray as $value) {&lt;br /&gt;
            list($signatureKey, $signatureValue) = explode(&amp;quot;=&amp;quot;, $value, 2);&lt;br /&gt;
            $signature[$signatureKey] = trim($signatureValue, '&amp;quot;');&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generating siging string&lt;br /&gt;
        $signingStringArray = explode(&amp;quot; &amp;quot;, $signature['headers']);&lt;br /&gt;
        $signingString = '';&lt;br /&gt;
        foreach ($signingStringArray as $value) {&lt;br /&gt;
            $signingString = $signingString . trim($value) . &amp;quot;: &amp;quot; . trim($responseHeaders[$value]) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // trimming last '\n' character&lt;br /&gt;
        $signingString = trim($signingString);&lt;br /&gt;
&lt;br /&gt;
        // decoding signature&lt;br /&gt;
        $decodedSignature = base64_decode($signature['signature']);&lt;br /&gt;
&lt;br /&gt;
        // verifying signature&lt;br /&gt;
        $signatureVerify = openssl_verify($signingString, $decodedSignature, openssl_get_publickey(file_get_contents($GLOBALS['config']['sign_cert_server'])), 'RSA-SHA256');&lt;br /&gt;
&lt;br /&gt;
        if (!$signatureVerify) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Signature is not correct&amp;quot;);&lt;br /&gt;
            while (($err = openssl_error_string()))&lt;br /&gt;
                errorLog(false, false, $err);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return json_decode($responseBody, true);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $response;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function logs curl responses and errors in text files&lt;br /&gt;
 *&lt;br /&gt;
 * @param mixed $response the response&lt;br /&gt;
 * @param mixed $request  the request handle, used to get errors&lt;br /&gt;
 */&lt;br /&gt;
function errorLog($curl, $response, $request = false)&lt;br /&gt;
{&lt;br /&gt;
    $timestamp = '[' . date('Y-m-d H:i:s') . ']:';&lt;br /&gt;
    global $errorLog;&lt;br /&gt;
    global $responseLog;&lt;br /&gt;
&lt;br /&gt;
    if ($response === false) {&lt;br /&gt;
        if ($curl)&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . curl_error($request) . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
        else&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . $request . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    } else {&lt;br /&gt;
        file_put_contents($responseLog, $timestamp . &amp;quot;\n&amp;quot; . $response . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function generates the full signature header line from a set of headers, a certificate and the linked private key&lt;br /&gt;
 *&lt;br /&gt;
 * @param array  $headersToSign the headers to sign, in the $key =&amp;gt; $value format&lt;br /&gt;
 * @param string $certificate   the certificate linked to the used private key&lt;br /&gt;
 * @param string $privateKey    the private key used to sign the headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the full signature header line&lt;br /&gt;
 */&lt;br /&gt;
function generateSignatureHeader(array $headersToSign, string $certificate, string $privateKey): string&lt;br /&gt;
{&lt;br /&gt;
    // generating the signing string and header list&lt;br /&gt;
    $headers         = '';&lt;br /&gt;
    $signatureString = '';&lt;br /&gt;
    foreach ($headersToSign as $key =&amp;gt; $value) {&lt;br /&gt;
        $normalizedHeaderKey = trim(strtolower($key));&lt;br /&gt;
        $headers             .= $normalizedHeaderKey . ' ';&lt;br /&gt;
        $signatureString     .= $normalizedHeaderKey . ': ' . trim($value) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    $headers         = trim($headers);&lt;br /&gt;
    $signatureString = trim($signatureString);&lt;br /&gt;
&lt;br /&gt;
    // signing the signing string&lt;br /&gt;
    $signature = '';&lt;br /&gt;
    openssl_sign($signatureString, $signature, openssl_get_privatekey($privateKey), 'RSA-SHA256');&lt;br /&gt;
    $signature = base64_encode($signature);&lt;br /&gt;
&lt;br /&gt;
    // compiling the header line&lt;br /&gt;
    return &amp;quot;keyId=\&amp;quot;$certificate\&amp;quot;,algorithm=\&amp;quot;rsa-sha256\&amp;quot;,headers=\&amp;quot;$headers\&amp;quot;,signature=\&amp;quot;$signature\&amp;quot;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function takes a code_verifier and outputs the corresponding code_challenge&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $codeVerifier the generated code_verifier&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the computed code_challenge&lt;br /&gt;
 */&lt;br /&gt;
function computeCodeChallenge(string $codeVerifier): string&lt;br /&gt;
{&lt;br /&gt;
    return strtr(rtrim(base64_encode(hash('sha256', $codeVerifier, true)), '='), '+/', '-_');&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function takes an optional string length and outputs a random code_verifier string&lt;br /&gt;
 *&lt;br /&gt;
 * @param int $length the length of the output code_verifier. Default = 128&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the code_verifier&lt;br /&gt;
 * @throws Exception&lt;br /&gt;
 */&lt;br /&gt;
function generateCodeVerifier($length = 128): string&lt;br /&gt;
{&lt;br /&gt;
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~';&lt;br /&gt;
    $outputCode = '';&lt;br /&gt;
&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $length; $i++) {&lt;br /&gt;
        $index      = random_int(0, strlen($characters) - 1);&lt;br /&gt;
        $outputCode .= $characters[$index];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $outputCode;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function calculates the entropy of a given string&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $string  the string for which to calculate the entropy&lt;br /&gt;
 * @param string $charset a string with all the usable characters. Default = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~&lt;br /&gt;
 *&lt;br /&gt;
 * @return float|int&lt;br /&gt;
 */&lt;br /&gt;
function computeEntropy(string $string, string $charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~')&lt;br /&gt;
{&lt;br /&gt;
    $chars = str_split($charset);&lt;br /&gt;
    $probs = [];&lt;br /&gt;
&lt;br /&gt;
    foreach ($chars as $char) {&lt;br /&gt;
        $probs[$char] = floatval(substr_count($string, $char)) / strlen($string);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $sum = 0.0;&lt;br /&gt;
    foreach ($probs as $prob) {&lt;br /&gt;
        $sum += $prob != 0 ? $prob * log($prob, 2) : 0.0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return -$sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function calculates the ideal (maximum) entropy for a string of a given length&lt;br /&gt;
 *&lt;br /&gt;
 * @param int $length length of the string. Default = 128&lt;br /&gt;
 *&lt;br /&gt;
 * @return float|int&lt;br /&gt;
 */&lt;br /&gt;
function idealEntropy(int $length = 128)&lt;br /&gt;
{&lt;br /&gt;
    $prob = 1.0 / $length;&lt;br /&gt;
&lt;br /&gt;
    return -1.0 * $length * $prob * log($prob, 2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function is used to initiate the authentication code flow.&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $clientID     the client's ID&lt;br /&gt;
 * @param string $redirectURL  the URL where to redirect after auth&lt;br /&gt;
 * @param string $authorizeURL the target URL to request authorization&lt;br /&gt;
 *&lt;br /&gt;
 * @throws Exception&lt;br /&gt;
 */&lt;br /&gt;
function login(string $clientID, string $redirectURL, string $authorizeURL): void&lt;br /&gt;
{&lt;br /&gt;
    global $localTokenFile;&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
    // This unguessable string is used to prevent csrf attacks&lt;br /&gt;
    $_SESSION['state'] = bin2hex(random_bytes(16));&lt;br /&gt;
&lt;br /&gt;
    // Generate code_verifier and code_challenge for PKCE    &lt;br /&gt;
    $_SESSION['code_verifier']  = generateCodeVerifier();&lt;br /&gt;
    $_SESSION['code_challenge'] = computeCodeChallenge($_SESSION['code_verifier']);&lt;br /&gt;
&lt;br /&gt;
    // required parameters for the redirection, redirect_uri is where the browser should be redirected&lt;br /&gt;
    // when the user grants (or denies) access, scope are the authorizations (rights) requested&lt;br /&gt;
    $params = [&lt;br /&gt;
        'response_type'         =&amp;gt; 'code',&lt;br /&gt;
        'client_id'             =&amp;gt; $clientID,&lt;br /&gt;
        'redirect_uri'          =&amp;gt; $redirectURL,&lt;br /&gt;
        'scope'                 =&amp;gt; 'default.login',&lt;br /&gt;
        'state'                 =&amp;gt; $_SESSION['state'],&lt;br /&gt;
        'code_challenge'        =&amp;gt; $_SESSION['code_challenge'],&lt;br /&gt;
        'code_challenge_method' =&amp;gt; 'S256'&lt;br /&gt;
    ];&lt;br /&gt;
&lt;br /&gt;
    // redirecting the browser to the AS authorization endpoint to obtain the authorization code&lt;br /&gt;
    header('Location: ' . $authorizeURL . '?' . http_build_query($params));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function deletes the access token from the session&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $baseURL&lt;br /&gt;
 */&lt;br /&gt;
function logout(string $baseURL): void&lt;br /&gt;
{&lt;br /&gt;
    global $localTokenFile;&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
    header('Location: ' . $baseURL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedIn(): void&lt;br /&gt;
{&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Logged In&amp;lt;/h3&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;view_repos&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;view&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'view_repos\').submit(); return false;&amp;quot;&amp;gt;View Repos&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;logout&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;logout&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'logout\').submit(); return false;&amp;quot;&amp;gt;Log Out&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedOut(): void&lt;br /&gt;
{&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Not logged in&amp;lt;/h3&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;login&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;login&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'login\').submit(); return false;&amp;quot;&amp;gt;Log In&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// display client &amp;quot;home&amp;quot; page&lt;br /&gt;
if (!isset($_POST['action'])) {&lt;br /&gt;
    if (!empty($localToken['access_token'])) {&lt;br /&gt;
        displayMenuLoggedIn();&lt;br /&gt;
    } else {&lt;br /&gt;
        displayMenuLoggedOut();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if (isset($_POST['action'])) {&lt;br /&gt;
    // Building query array for resource dumping&lt;br /&gt;
    $repoQueryParameters = [&lt;br /&gt;
        'resource_type' =&amp;gt; 'user_information',&lt;br /&gt;
        'client_id' =&amp;gt; $config['client_id']&lt;br /&gt;
    ];&lt;br /&gt;
    switch ($_POST['action']) {&lt;br /&gt;
        case 'login':&lt;br /&gt;
            login($config['client_id'], $baseURL, $config['authorize_uri']);&lt;br /&gt;
            break;&lt;br /&gt;
        case 'logout':&lt;br /&gt;
            logout($baseURL);&lt;br /&gt;
            break;&lt;br /&gt;
        case 'view':&lt;br /&gt;
            // call to the resource server to retreive user information&lt;br /&gt;
            $resources = apiRequest(&lt;br /&gt;
                $config['resource_uri'],&lt;br /&gt;
                $repoQueryParameters,&lt;br /&gt;
                $localToken,&lt;br /&gt;
                false&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            // Separating headers from body&lt;br /&gt;
            list($resourceHeader, $resourceBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $resources, 2);&lt;br /&gt;
&lt;br /&gt;
            $resourceHeaders = explode(&amp;quot;\r\n&amp;quot;, $resourceHeader);&lt;br /&gt;
            $firstHeaderLine = array_shift($resourceHeaders);&lt;br /&gt;
&lt;br /&gt;
            // Displaying user information&lt;br /&gt;
            echo '&amp;lt;pre&amp;gt;';&lt;br /&gt;
            echo $resourceBody;&lt;br /&gt;
            echo '&amp;lt;/pre&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
            // Automatic refreshing token once access token is expired&lt;br /&gt;
            if (strpos($firstHeaderLine, &amp;quot;401&amp;quot;)) {&lt;br /&gt;
                $errorBody = json_decode($resourceBody, true);&lt;br /&gt;
                if ($errorBody['error'] == 'access_denied' &amp;amp;&amp;amp; isset($errorBody['hint'])) {&lt;br /&gt;
                    if ($errorBody['hint'] == 'Access token could not be verified') {&lt;br /&gt;
                        $token = apiRequest(&lt;br /&gt;
                            $config['token_uri'],&lt;br /&gt;
                            [&lt;br /&gt;
                                'grant_type'    =&amp;gt; 'refresh_token',&lt;br /&gt;
                                'refresh_token' =&amp;gt; $localToken['refresh_token'],&lt;br /&gt;
                                'client_id'     =&amp;gt; $config['client_id'],&lt;br /&gt;
                                'client_secret' =&amp;gt; empty($config['client_secret']) ? null : $config['client_secret']&lt;br /&gt;
                            ],&lt;br /&gt;
                            false,&lt;br /&gt;
                            true,&lt;br /&gt;
                            true&lt;br /&gt;
                        );&lt;br /&gt;
&lt;br /&gt;
                        // We store the access token in the session so the user is &amp;quot;connected&amp;quot;&lt;br /&gt;
                        // Only if the request has been successfully executed&lt;br /&gt;
                        if (isset($token['access_token'])) {&lt;br /&gt;
                            file_put_contents($localTokenFile, json_encode($token, true));&lt;br /&gt;
&lt;br /&gt;
                            // Redirecting the user's browser to the &amp;quot;home&amp;quot; page&lt;br /&gt;
                            header('Location: ' . $baseURL);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Once the browser has been redirected to the AS to ask for the user's authorization, assuming it has been granted,&lt;br /&gt;
// the browser will get back here with a &amp;quot;code&amp;quot; parameter in the query string&lt;br /&gt;
if (isset($_GET['code'])) {&lt;br /&gt;
    // The AS MUST redirect the browser here with the exact same state parameter we sent it before, so we check if it is indeed the same&lt;br /&gt;
    // to detect if the oauth flow has been tampered with&lt;br /&gt;
    if (!isset($_GET['state']) || $_SESSION['state'] != $_GET['state']) {&lt;br /&gt;
        header('Location: ' . $baseURL . '?error=invalid_state');&lt;br /&gt;
        die();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // We communicate directly with the AS to exchange the code received against an access token.&lt;br /&gt;
    // The id/secret pair is send to authenticate the client, the redirect_uri is sent to verify the code's validity&lt;br /&gt;
    $token = apiRequest(&lt;br /&gt;
        $config['token_uri'],&lt;br /&gt;
        [&lt;br /&gt;
            'grant_type'    =&amp;gt; 'authorization_code',&lt;br /&gt;
            'client_id'     =&amp;gt; $config['client_id'],&lt;br /&gt;
            'client_secret' =&amp;gt; empty($config['client_secret']) ? null : $config['client_secret'],&lt;br /&gt;
            'redirect_uri'  =&amp;gt; $baseURL,&lt;br /&gt;
            'code'          =&amp;gt; $_GET['code'],&lt;br /&gt;
            'code_verifier' =&amp;gt; $_SESSION['code_verifier']&lt;br /&gt;
        ]&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    // We store the access token in the session so the user is &amp;quot;connected&amp;quot;&lt;br /&gt;
    // Only if the request has been successfully executed&lt;br /&gt;
    if (isset($token['access_token'])) {&lt;br /&gt;
        file_put_contents($localTokenFile, json_encode($token, true));&lt;br /&gt;
&lt;br /&gt;
        // Redirecting the user's browser to the &amp;quot;home&amp;quot; page&lt;br /&gt;
        header('Location: ' . $baseURL);&lt;br /&gt;
    } else {&lt;br /&gt;
        echo $token;&lt;br /&gt;
    }&lt;br /&gt;
    die();&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Ce script a été conçu pour montrer le fonctionnement du mécanisme afin de tester l'implémentation d'un serveur et n'a pas été testé extensivement. Il est conseillé d'utiliser une solution adaptée à un environnement de production.&lt;br /&gt;
&lt;br /&gt;
==Client Credentials==&lt;br /&gt;
Ce mécanisme d'autorisation est adapté pour l'automatisation. Il fonctionne de la manière suivante :&lt;br /&gt;
*Le client effectue la demande de jeton d'accès au serveur d'autorisation en fournissant ses identifiants.&lt;br /&gt;
*Le serveur authentifie le client avec les identifiants fournis et renvoie un jeton d'accès.&lt;br /&gt;
*Le client utilise ce jeton d'accès pour accéder à des données via l'API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    +------+                       +-------------+                  +-----------+&lt;br /&gt;
    |Client|                       |   Serveur   |                  |  Serveur  |&lt;br /&gt;
    +--+---+                       |Autorisation |                  | Ressources|&lt;br /&gt;
       |                           +------+------+                  +-----+-----+&lt;br /&gt;
       |        Authentification          |                               |&lt;br /&gt;
       |         + Demande token          |                               |&lt;br /&gt;
       +---------------------------------&amp;gt;|                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |          Access token            |                               |&lt;br /&gt;
       |&amp;lt;---------------------------------+                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                      Requête vers|API                            |&lt;br /&gt;
       +----------------------------------+------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |&amp;lt;------------------------------+&lt;br /&gt;
       |                                  |  Vérification d'autorisation  |&lt;br /&gt;
       |                                  +------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                         Données /|Réponse                        |&lt;br /&gt;
       |&amp;lt;---------------------------------+-------------------------------+&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Demande de jeton d'accès===&lt;br /&gt;
Pour obtenir un jeton d'accès, il faut effectuer la requête suivante : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Les paramètres suivants sont nécessaires :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|client_secret||string||La passphrase reçue pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|grant_type||string||Le mécanisme d'autorisation utilisé. Ici, la valeur doit être ''client_credentials''.&lt;br /&gt;
|-&lt;br /&gt;
|scope||string||[[#Liste-des-scopes-disponibles|Liste des droits demandés par le client]], séparé par des espaces.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
;Ce mécanisme a la particularité de ne pas nécessiter d'URI de redirection, il n'est donc pas utile d'en renseigner un lors de l'enregistrement d'un client.&lt;br /&gt;
&lt;br /&gt;
Si la requête est correcte, un jeton d'accès (Access Token) est fourni en réponse dans un objet au format JSON.&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,&lt;br /&gt;
  &amp;quot;expires_in&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;access_token&amp;quot;: &amp;quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Script client : Client Credentials===&lt;br /&gt;
Voici un exemple simple d'un client OAuth2 pour le mécanisme d'authentification par les identifiants client (Client Credentials).&lt;br /&gt;
&lt;br /&gt;
Fichier de configuration ''config.clientcred.json'' :&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;/path/to/client/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;/path/to/client/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;/path/to/client/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;/path/to/client/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;/path/to/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;/path/to/server/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
Où &amp;lt;code&amp;gt;/path/to/client/&amp;lt;/code&amp;gt; est le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
*Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/ssl/ClientCredDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
*Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./ssl/ClientCredDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ce fichier de configuration doit se situer au même niveau que le script PHP dans le système de fichiers.&lt;br /&gt;
&lt;br /&gt;
Script php :&lt;br /&gt;
&amp;lt;php&amp;gt;&amp;lt;?php&lt;br /&gt;
$localTokenFile    = 'token.json';&lt;br /&gt;
// create token file if it does not exist&lt;br /&gt;
if (!file_exists($localTokenFile))&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
$config                 = json_decode(file_get_contents('config.clientcred.json'), true);&lt;br /&gt;
$localToken             = json_decode(file_get_contents($localTokenFile), true);&lt;br /&gt;
$GLOBALS['config']      = $config;&lt;br /&gt;
&lt;br /&gt;
// Build the baseURL, accounting for protocol, port, name and endpoint. Used for redirection&lt;br /&gt;
$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';&lt;br /&gt;
$port     = ($protocol == 'https://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 443)&lt;br /&gt;
    || ($protocol == 'http://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 80) ? '' : ':' . $_SERVER['SERVER_PORT'];&lt;br /&gt;
&lt;br /&gt;
$baseURL            = $protocol . $_SERVER['SERVER_NAME'] . $port . $_SERVER['PHP_SELF'];&lt;br /&gt;
$errorLog           = 'error_log.log';&lt;br /&gt;
$responseLog        = 'response_log.log';&lt;br /&gt;
$GLOBALS['baseURL'] = $baseURL;&lt;br /&gt;
&lt;br /&gt;
$replacementListItems = [&lt;br /&gt;
    1 =&amp;gt; &amp;quot;year&amp;quot;,&lt;br /&gt;
    2 =&amp;gt; &amp;quot;validityTypeId&amp;quot;,&lt;br /&gt;
    3 =&amp;gt; &amp;quot;icao&amp;quot;,&lt;br /&gt;
    4 =&amp;gt; &amp;quot;profileId&amp;quot;,&lt;br /&gt;
    7 =&amp;gt; &amp;quot;accountingId&amp;quot;,&lt;br /&gt;
    8 =&amp;gt; &amp;quot;paymentType&amp;quot;,&lt;br /&gt;
    9 =&amp;gt; &amp;quot;startDate&amp;quot;,&lt;br /&gt;
    10 =&amp;gt; &amp;quot;endDate&amp;quot;,&lt;br /&gt;
    11 =&amp;gt; &amp;quot;occupiedSeat&amp;quot;,&lt;br /&gt;
    12 =&amp;gt; &amp;quot;date&amp;quot;,&lt;br /&gt;
    13 =&amp;gt; &amp;quot;activityTypeId&amp;quot;,&lt;br /&gt;
    14 =&amp;gt; &amp;quot;age&amp;quot;,&lt;br /&gt;
    15 =&amp;gt; &amp;quot;resourceId&amp;quot;,&lt;br /&gt;
    16 =&amp;gt; &amp;quot;personId&amp;quot;,&lt;br /&gt;
    17 =&amp;gt; &amp;quot;accountId&amp;quot;,&lt;br /&gt;
    20 =&amp;gt; &amp;quot;rightPlacePersonId&amp;quot;,&lt;br /&gt;
    21 =&amp;gt; &amp;quot;month&amp;quot;,&lt;br /&gt;
    22 =&amp;gt; &amp;quot;numberMonth&amp;quot;,&lt;br /&gt;
    23 =&amp;gt; &amp;quot;oneValidityTypeId&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
&lt;br /&gt;
//Session cookies are used to store information necessary for the authorization code flow&lt;br /&gt;
session_start();&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function is used to make api calls to the RS&lt;br /&gt;
 *&lt;br /&gt;
 * @param       $url&lt;br /&gt;
 * @param       $post&lt;br /&gt;
 * @param array $headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return mixed&lt;br /&gt;
 */&lt;br /&gt;
function apiRequest($url, $post = null, $token = false, $auth = true, $headers = array())&lt;br /&gt;
{&lt;br /&gt;
    $ch = curl_init($url);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HEADER, true);&lt;br /&gt;
&lt;br /&gt;
    $method = 'get';&lt;br /&gt;
&lt;br /&gt;
    if ($post) {&lt;br /&gt;
        $method   = 'post';&lt;br /&gt;
        $postData = http_build_query($post);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POST, true);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);&lt;br /&gt;
&lt;br /&gt;
        $headersToSign['Content-Type'] = 'application/x-www-form-urlencoded';&lt;br /&gt;
        $headersToSign['digest']       = 'SHA-256=' . base64_encode(hash('sha256', $postData, true));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $urlComponents = parse_url($url);&lt;br /&gt;
&lt;br /&gt;
    $headersToSign['(request-target)'] = $method . ' ' . $urlComponents['path'];&lt;br /&gt;
    $headersToSign['Host']             = $urlComponents['host'];&lt;br /&gt;
    $headersToSign['Date']             = gmdate('D, j M Y H:i:s T');&lt;br /&gt;
&lt;br /&gt;
    // generating the signature header&lt;br /&gt;
    $keyId                = openssl_x509_fingerprint(file_get_contents($GLOBALS['config']['sign_cert']));&lt;br /&gt;
    $privateKey           = file_get_contents($GLOBALS['config']['sign_key']);&lt;br /&gt;
    $headers['Signature'] = generateSignatureHeader($headersToSign, $keyId, $privateKey);&lt;br /&gt;
&lt;br /&gt;
    $headers['Accept']     = 'application/json';&lt;br /&gt;
    $headers['User-Agent'] = $GLOBALS['baseURL'];&lt;br /&gt;
    unset($headersToSign['(request-target)']);&lt;br /&gt;
    $headers               += $headersToSign;&lt;br /&gt;
&lt;br /&gt;
    if ($token) {&lt;br /&gt;
        $headers['Authorization'] = $token['token_type'] . ' ' . $token['access_token'];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // formatting the headers&lt;br /&gt;
    $httpFormattedHeaders = [];&lt;br /&gt;
    foreach ($headers as $key =&amp;gt; $value) {&lt;br /&gt;
        $httpFormattedHeaders[] = trim($key) . ': ' . trim($value);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HTTPHEADER, $httpFormattedHeaders);&lt;br /&gt;
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);&lt;br /&gt;
&lt;br /&gt;
    // for development environment only&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_VERBOSE, true);&lt;br /&gt;
&lt;br /&gt;
    // defining TLS client certificates for Mutual TLS&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_CAINFO, $GLOBALS['config']['auth_cacert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLCERT, $GLOBALS['config']['auth_cert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLKEY, $GLOBALS['config']['auth_key']);&lt;br /&gt;
&lt;br /&gt;
    $response = curl_exec($ch);&lt;br /&gt;
&lt;br /&gt;
    // logging errors and responses&lt;br /&gt;
    errorLog(true, $response, $ch);&lt;br /&gt;
&lt;br /&gt;
    curl_close($ch);&lt;br /&gt;
&lt;br /&gt;
    // in case an authentication request is executed&lt;br /&gt;
    if ($auth) {&lt;br /&gt;
        list($responseHeader, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 2);&lt;br /&gt;
&lt;br /&gt;
        $responseHeadersDigest = '';&lt;br /&gt;
        $responseHeadersSignature = '';&lt;br /&gt;
        // extracting digest and signature from headers&lt;br /&gt;
        $responseHeadersArray = explode(&amp;quot;\r\n&amp;quot;, $responseHeader);&lt;br /&gt;
        $responseProtocol = array_shift($responseHeadersArray);&lt;br /&gt;
&lt;br /&gt;
        foreach ($responseHeadersArray as $value) {&lt;br /&gt;
            list($responseHeadersKeys, $responseHeadersValue) = explode(&amp;quot;: &amp;quot;, $value, 2);&lt;br /&gt;
            $responseHeaders[strtolower($responseHeadersKeys)] = $responseHeadersValue;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $responseDigestAlgo = '';&lt;br /&gt;
        $responseDigestKey = '';&lt;br /&gt;
        foreach ($responseHeaders as $key =&amp;gt; $value) {&lt;br /&gt;
            if ($key === &amp;quot;digest&amp;quot;) {&lt;br /&gt;
                $responseHeadersDigest = $value;&lt;br /&gt;
                // stripping SHA algorithm for later comparison&lt;br /&gt;
                list($responseDigestAlgo, $responseDigestKey) = explode(&amp;quot;=&amp;quot;, $responseHeadersDigest, 2);&lt;br /&gt;
            } else if ($key === &amp;quot;signature&amp;quot;)&lt;br /&gt;
                $responseHeadersSignature = $value;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // calculating response digest&lt;br /&gt;
        $responseDigest = base64_encode(hash(strtolower(str_replace(&amp;quot;-&amp;quot;, &amp;quot;&amp;quot;, $responseDigestAlgo)), $responseBody, true));&lt;br /&gt;
&lt;br /&gt;
        // checking digest validity&lt;br /&gt;
        if ($responseDigest !== $responseDigestKey) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Digests are not the same&amp;quot;);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // extracting variables from signature header&lt;br /&gt;
        $signatureArray = explode(&amp;quot;,&amp;quot;, $responseHeadersSignature);&lt;br /&gt;
        foreach ($signatureArray as $value) {&lt;br /&gt;
            list($signatureKey, $signatureValue) = explode(&amp;quot;=&amp;quot;, $value, 2);&lt;br /&gt;
            $signature[$signatureKey] = trim($signatureValue, '&amp;quot;');&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generating siging string&lt;br /&gt;
        $signingStringArray = explode(&amp;quot; &amp;quot;, $signature['headers']);&lt;br /&gt;
        $signingString = '';&lt;br /&gt;
        foreach ($signingStringArray as $value) {&lt;br /&gt;
            $signingString = $signingString . trim($value) . &amp;quot;: &amp;quot; . trim($responseHeaders[$value]) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // trimming last '\n' character&lt;br /&gt;
        $signingString = trim($signingString);&lt;br /&gt;
&lt;br /&gt;
        // decoding signature&lt;br /&gt;
        $decodedSignature = base64_decode($signature['signature']);&lt;br /&gt;
&lt;br /&gt;
        // verifying signature&lt;br /&gt;
        $signatureVerify = openssl_verify($signingString, $decodedSignature, openssl_get_publickey(file_get_contents($GLOBALS['config']['sign_cert_server'])), 'RSA-SHA256');&lt;br /&gt;
&lt;br /&gt;
        if (!$signatureVerify) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Signature is not correct&amp;quot;);&lt;br /&gt;
            while (($err = openssl_error_string()))&lt;br /&gt;
                errorLog(false, false, $err);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return json_decode($responseBody, true);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $response;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function logs curl responses and errors in text files&lt;br /&gt;
 *&lt;br /&gt;
 * @param mixed $response the response&lt;br /&gt;
 * @param mixed $request  the request handle, used to get errors&lt;br /&gt;
 */&lt;br /&gt;
function errorLog($curl, $response, $request = false)&lt;br /&gt;
{&lt;br /&gt;
    $timestamp = '[' . date('Y-m-d H:i:s') . ']:';&lt;br /&gt;
    global $errorLog;&lt;br /&gt;
    global $responseLog;&lt;br /&gt;
&lt;br /&gt;
    if ($response === false) {&lt;br /&gt;
        if ($curl)&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . curl_error($request) . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
        else&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . $request . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    } else {&lt;br /&gt;
        file_put_contents($responseLog, $timestamp . &amp;quot;\n&amp;quot; . $response . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function generates the full signature header line from a set of headers, a certificate and the linked private key&lt;br /&gt;
 *&lt;br /&gt;
 * @param array  $headersToSign the headers to sign, in the $key =&amp;gt; $value format&lt;br /&gt;
 * @param string $certificate   the certificate linked to the used private key&lt;br /&gt;
 * @param string $privateKey    the private key used to sign the headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the full signature header line&lt;br /&gt;
 */&lt;br /&gt;
function generateSignatureHeader(array $headersToSign, string $certificate, string $privateKey): string&lt;br /&gt;
{&lt;br /&gt;
    // generating the signing string and header list&lt;br /&gt;
    $headers         = '';&lt;br /&gt;
    $signatureString = '';&lt;br /&gt;
    foreach ($headersToSign as $key =&amp;gt; $value) {&lt;br /&gt;
        $normalizedHeaderKey = trim(strtolower($key));&lt;br /&gt;
        $headers             .= $normalizedHeaderKey . ' ';&lt;br /&gt;
        $signatureString     .= $normalizedHeaderKey . ': ' . trim($value) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    $headers         = trim($headers);&lt;br /&gt;
    $signatureString = trim($signatureString);&lt;br /&gt;
&lt;br /&gt;
    // signing the signing string&lt;br /&gt;
    $signature = '';&lt;br /&gt;
    openssl_sign($signatureString, $signature, openssl_get_privatekey($privateKey), 'RSA-SHA256');&lt;br /&gt;
    $signature = base64_encode($signature);&lt;br /&gt;
&lt;br /&gt;
    // compiling the header line&lt;br /&gt;
    return &amp;quot;keyId=\&amp;quot;$certificate\&amp;quot;,algorithm=\&amp;quot;rsa-sha256\&amp;quot;,headers=\&amp;quot;$headers\&amp;quot;,signature=\&amp;quot;$signature\&amp;quot;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function deletes the access token from the session&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $baseURL&lt;br /&gt;
 */&lt;br /&gt;
function logout(string $baseURL): void&lt;br /&gt;
{&lt;br /&gt;
    global $localTokenFile;&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
    header('Location: ' . $baseURL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedIn(): void&lt;br /&gt;
{&lt;br /&gt;
    global $replacementListItems;&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Logged In&amp;lt;/h3&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;view_repos&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;label for=&amp;quot;report_id&amp;quot;&amp;gt;Report ID: &amp;lt;/label&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;number&amp;quot; id=&amp;quot;report_id&amp;quot; name=&amp;quot;report_id&amp;quot;&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;';&lt;br /&gt;
    foreach ($replacementListItems as $value) {&lt;br /&gt;
        echo '&amp;lt;label for=&amp;quot;' . $value . '&amp;quot;&amp;gt;' . $value . ': &amp;lt;/label&amp;gt;';&lt;br /&gt;
        echo '&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;' . $value . '&amp;quot; name=&amp;quot;' . $value . '&amp;quot;&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;';&lt;br /&gt;
    }&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;view&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'view_repos\').submit(); return false;&amp;quot;&amp;gt;View Repos&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;logout&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;logout&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'logout\').submit(); return false;&amp;quot;&amp;gt;Log Out&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedOut(): void&lt;br /&gt;
{&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Not logged in&amp;lt;/h3&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;login&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;login&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'login\').submit(); return false;&amp;quot;&amp;gt;Log In&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// display client &amp;quot;home&amp;quot; page&lt;br /&gt;
if (!isset($_POST['action'])) {&lt;br /&gt;
    if (!empty($localToken['access_token'])) {&lt;br /&gt;
        displayMenuLoggedIn();&lt;br /&gt;
    } else {&lt;br /&gt;
        displayMenuLoggedOut();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if (isset($_POST['action'])) {&lt;br /&gt;
    $replacementList = [];&lt;br /&gt;
    // Building replacement list&lt;br /&gt;
    foreach ($replacementListItems as $key =&amp;gt; $value) {&lt;br /&gt;
        $replacementList[$value] = (isset($_POST[$value]) &amp;amp;&amp;amp; strlen($_POST[$value]) &amp;gt; 0) ? $_POST[$value] : null;&lt;br /&gt;
    }&lt;br /&gt;
    // Building query array&lt;br /&gt;
    $repoQueryParameters = [&lt;br /&gt;
        'resource_type' =&amp;gt; 'generic_report',&lt;br /&gt;
        'client_id' =&amp;gt; $config['client_id'],&lt;br /&gt;
        'report_id' =&amp;gt; (isset($_POST['report_id']) &amp;amp;&amp;amp; strlen($_POST['report_id']) &amp;gt; 0) ? $_POST['report_id'] : null,&lt;br /&gt;
        'replacementList' =&amp;gt; $replacementList&lt;br /&gt;
    ];&lt;br /&gt;
    switch ($_POST['action']) {&lt;br /&gt;
        case 'login':&lt;br /&gt;
            $token = apiRequest(&lt;br /&gt;
                $config['token_uri'],&lt;br /&gt;
                [&lt;br /&gt;
                    'grant_type'    =&amp;gt; 'client_credentials',&lt;br /&gt;
                    'client_id'     =&amp;gt; $config['client_id'],&lt;br /&gt;
                    'client_secret' =&amp;gt; empty($config['client_secret']) ? null : $config['client_secret'],&lt;br /&gt;
                    'scope'         =&amp;gt; 'genericreports.readonly reports.readonly'&lt;br /&gt;
                ]&lt;br /&gt;
            );&lt;br /&gt;
            // We store the access token in the session so the user is &amp;quot;connected&amp;quot;&lt;br /&gt;
            // Only if the request has been successfully executed&lt;br /&gt;
            if (isset($token['access_token'])) {&lt;br /&gt;
                file_put_contents($localTokenFile, json_encode($token, true));&lt;br /&gt;
&lt;br /&gt;
                // Redirecting the user's browser to the &amp;quot;home&amp;quot; page&lt;br /&gt;
                header('Location: ' . $baseURL);&lt;br /&gt;
            } else {&lt;br /&gt;
                echo $token;&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
        case 'logout':&lt;br /&gt;
            logout($baseURL);&lt;br /&gt;
            break;&lt;br /&gt;
        case 'view':&lt;br /&gt;
            // call to the resource server&lt;br /&gt;
            $resources = apiRequest(&lt;br /&gt;
                $config['resource_uri'],&lt;br /&gt;
                $repoQueryParameters,&lt;br /&gt;
                $localToken,&lt;br /&gt;
                false&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            // Separating headers from body&lt;br /&gt;
            list($resourceHeader, $resourceBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $resources, 2);&lt;br /&gt;
&lt;br /&gt;
            $resourceHeaders = explode(&amp;quot;\r\n&amp;quot;, $resourceHeader);&lt;br /&gt;
            $firstHeaderLine = array_shift($resourceHeaders);&lt;br /&gt;
&lt;br /&gt;
            // Building form for download CSV button&lt;br /&gt;
            echo '&amp;lt;form method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
            foreach ($_POST as $key =&amp;gt; $value) {&lt;br /&gt;
                if ($key == &amp;quot;action&amp;quot;) {&lt;br /&gt;
                    $value = &amp;quot;download&amp;quot;;&lt;br /&gt;
                }&lt;br /&gt;
                echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;' . $key . '&amp;quot; name=&amp;quot;' . $key . '&amp;quot; value=&amp;quot;' . $value . '&amp;quot;&amp;gt;';&lt;br /&gt;
            }&lt;br /&gt;
            if (isset($_POST['report_id']) &amp;amp;&amp;amp; strlen($_POST['report_id']) &amp;gt; 0 &amp;amp;&amp;amp; !isset(json_decode($resourceBody, true)['error'])) {&lt;br /&gt;
                echo '&amp;lt;button&amp;gt;Download as CSV&amp;lt;/button&amp;gt;';&lt;br /&gt;
            }&lt;br /&gt;
            echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
            // Displaying requested content&lt;br /&gt;
            echo '&amp;lt;pre&amp;gt;';&lt;br /&gt;
            echo (strpos($firstHeaderLine, &amp;quot;200&amp;quot;)) ? json_decode($resourceBody) : $resourceBody;&lt;br /&gt;
            echo '&amp;lt;/pre&amp;gt;';&lt;br /&gt;
            break;&lt;br /&gt;
        case 'download':&lt;br /&gt;
            // call to the resource server&lt;br /&gt;
            $resources = apiRequest(&lt;br /&gt;
                $config['resource_uri'],&lt;br /&gt;
                $repoQueryParameters,&lt;br /&gt;
                $localToken,&lt;br /&gt;
                false&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            // Separating headers from body&lt;br /&gt;
            list($resourceHeader, $resourceBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $resources, 2);&lt;br /&gt;
            $resourceHeaders = explode(&amp;quot;\r\n&amp;quot;, $resourceHeader);&lt;br /&gt;
            array_shift($resourceHeaders);&lt;br /&gt;
&lt;br /&gt;
            // Dumping headers to insert them in current page&lt;br /&gt;
            foreach ($resourceHeaders as $key =&amp;gt; $value) {&lt;br /&gt;
                header($value);&lt;br /&gt;
            }&lt;br /&gt;
            echo json_decode($resourceBody);&lt;br /&gt;
            break;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Ce script a été conçu pour montrer le fonctionnement du mécanisme et tester l'implémentation d'un serveur, il n'a pas été testé extensivement. Il est conseillé d'utiliser une solution adaptée à un environnement de production.&lt;br /&gt;
&lt;br /&gt;
==Refresh Token==&lt;br /&gt;
Refresh Token (ou jeton de rafraîchissement en français) est un mécanisme d'autorisation particulier. Il ne peut fonctionner en tant que tel, il fonctionne de pair avec [[#Authorization-Code|Authorization Code]]. Lorsqu'un jeton d'accès arrive est arrivé en fin de vie, si le client y est autorisé, il peut faire une demande de renouvellement de son jeton d'accès auprès du serveur d'autorisation en présentant son jeton de rafraîchissement. Le serveur d'autorisation vérifie la validité et génère un autre jeton d'accès qu'il transmet au client, sans que l'utilisateur final n'aît à se connecter de nouveau.&lt;br /&gt;
&lt;br /&gt;
Le principe de fonctionnement du rafraîchissement d'un jeton est le suivant :&lt;br /&gt;
* Le jeton d'accès du client est arrivé à péremption. Le client effectue une demande de renouvellement en transmettant son Refresh Token au serveur d'autorisation.&lt;br /&gt;
* Le serveur d'autorisation vérifie la validité des informations, &amp;quot;consomme&amp;quot; le jeton de rafraîchissement et génère une nouvelle paire de jetons&lt;br /&gt;
* Le client reçoit sa nouvelle paire et utilise le nouveau jeton d'accès pour accéder aux ressources&lt;br /&gt;
&lt;br /&gt;
    +------+                       +-------------+                  +-----------+&lt;br /&gt;
    |Client|                       |   Serveur   |                  |  Serveur  |&lt;br /&gt;
    +--+---+                       |Autorisation |                  | Ressources|&lt;br /&gt;
       |                           +------+------+                  +-----+-----+&lt;br /&gt;
       |        Authentification          |                               |&lt;br /&gt;
       |         + Refresh Token          |                               |&lt;br /&gt;
       +---------------------------------&amp;gt;|                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |    Access (+ Refresh) token      |                               |&lt;br /&gt;
       |&amp;lt;---------------------------------+                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                      Requête vers|API                            |&lt;br /&gt;
       +----------------------------------+------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |&amp;lt;------------------------------+&lt;br /&gt;
       |                                  |  Vérification d'autorisation  |&lt;br /&gt;
       |                                  +------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                         Données /|Réponse                        |&lt;br /&gt;
       |&amp;lt;---------------------------------+-------------------------------+&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
&lt;br /&gt;
===Demande de renouvellement d'un jeton===&lt;br /&gt;
Pour obtenir un renouvellement de jeton d'accès, il faut effectuer la requête suivante : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Les paramètres suivants sont nécessaires :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant ''client_id'' reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|client_secret||string||La passphrase ''client_secret'' reçue pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|grant_type||string||Le mécanisme d'autorisation utilisé. Ici, la valeur doit être &amp;quot;refresh_token&amp;quot; (sans guillements).&lt;br /&gt;
|-&lt;br /&gt;
|scope||string||('''OPTIONNEL''') Liste des droits demandés par le client, séparés par des espaces.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Si la requête est correcte, un jeton d'accès ''access_token'' est fourni en réponse dans un objet au format JSON.&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,&lt;br /&gt;
  &amp;quot;expires_in&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;access_token&amp;quot;: &amp;quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw&amp;quot;,&lt;br /&gt;
  &amp;quot;refresh_token&amp;quot;: &amp;quot;a59ef39fa9bab9b95cd554f921e7f3080a34c90f23d2b8031d692b5ff2d0993dcc392d9c7f9a43242337ef144c1a5fe1d0174413ade973e1b628ac0bbfc39b23973534&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Liste des scopes disponibles==&lt;br /&gt;
Un scope sur OAuth2 correspond à un droit d'accès sur une ressource particulière. Chaque scope est unique et indique de manière explicite le privilège qu'il donne. Il n'y a aucune restriction d'utilisation des scopes par rapport aux mécanismes. Chaque scope peut être utilisé avec n'importe quel mécanisme. Il n'y a que des recommandations vis à vis de leur utilisation. OpenFlyers définit une liste de scopes dédiée aux ressources accessibles par les clients. Ces scopes sont les suivants :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Description&lt;br /&gt;
|-&lt;br /&gt;
|default.login||Comportement par défaut lorsqu'aucun scope n'est précisé ou qu'un scope est invalide. Ce scope est recommandé pour '''Authorization Code'''.&lt;br /&gt;
|-&lt;br /&gt;
|genericreports.readonly||Accéder aux rapports génériques autorisés pour le client en lecture seule. Ce scope est recommandé pour '''Client Credentials'''.&lt;br /&gt;
|-&lt;br /&gt;
|reports.readonly||Accéder aux rapports personnalisés autorisés pour le client en lecture seule. Ce scope est recommandé pour '''Client Credentials'''.&lt;br /&gt;
|}&lt;br /&gt;
==Prolonger la durée de vie de la session du client de démonstration==&lt;br /&gt;
La session du client de démonstration est initiée avec la méthode PHP [https://www.php.net/manual/en/function.session-start.php session_start]. Cette session peut être interrompue soit en cliquant sur le bouton de déconnexion, soit en fermant le navigateur (car les cookies associés à cette session se détruisent par défaut lorsque le navigateur est fermé).&lt;br /&gt;
&lt;br /&gt;
Pour permettre à la session de rester active même après la fermeture du navigateur, il faut utiliser la méthode PHP [https://www.php.net/manual/en/function.session-set-cookie-params.php session_set_cookie_params]. Cette méthode donne la possibilité de définir une durée de vie pour les différents cookies associés à la session.&lt;br /&gt;
&amp;lt;php&amp;gt;// Set the parameters for the session cookie in a PHP session in order to configure its lifetime in 30 days&lt;br /&gt;
$oauth2DemoSessionLifeTime = time() + (86400 * 30);&lt;br /&gt;
session_set_cookie_params($oauth2DemoSessionLifeTime);&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NB: Cette approche n'est pas particulièrement sécurisée et peut présenter des risques de sécurité pour OpenFlyers. Par conséquent, elle doit être utilisée avec précaution.&lt;br /&gt;
&lt;br /&gt;
==Révocation de token==&lt;br /&gt;
Pour initier la demande de révocation, rediriger le navigateur de l'utilisateur vers l'URL : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/revoke.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Envoyer également le paramètre suivant:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|access_token||string||Le jeton d'accès (Chaîne de caractère unique permettant de prouver qu'un client OAuth a le droit d'accéder à une ressource.)&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;php&amp;gt; apiRequest(&lt;br /&gt;
                $config['revoke_uri'],&lt;br /&gt;
                ['access_token' =&amp;gt; $_SESSION['auth_token']['access_token']],&lt;br /&gt;
                null,&lt;br /&gt;
                false&lt;br /&gt;
            );&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La demande de révocation se fait quand l'utilisateur clique sur le bouton '''Se déconnecter''' pour l'un des deux Clients '''Authorization Code''' et '''Client Credentials'''.&lt;br /&gt;
&lt;br /&gt;
Si les jetons sont révoqués, l'utilisateur ne peut pas accéder à la plateforme OpenFlyers, il doit se reconnecter.&lt;br /&gt;
&lt;br /&gt;
==Utiliser l'API==&lt;br /&gt;
Une fois un jeton d'accès obtenu, les données sont accessibles par une requête POST exécutée vers l'URL : &amp;lt;code&amp;gt;https://openflyers.com/nom-de-plateforme/oauth/resources.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée. La requête POST doit respecter une structure particulière. Cette structure diffère en fonction du type de ressource souhaité et chaque ressource ne peut être accédée qu'[[#Liste-des-scopes-disponibles|avec le scope qui lui est associé]]. Le jeton d'accès doit être renseigné dans l'en-tête HTTP ''Authorization'' en y indiquant la valeur complète du jeton d'accès reçu précédé du type de jeton reçu  : &amp;lt;code&amp;gt;Authorization: &amp;lt;token_type&amp;gt; &amp;lt;access_token&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Récupérer les informations de l'utilisateur connecté===&lt;br /&gt;
Ce type de ressource est nommé '''user_information'''. Cette ressource n'est accessible qu'avec le scope '''default.login'''. Cette ressource permet la récupération des informations de l'utilisateur connecté, en d'autre termes, l'utilisateur connecté lors de l'étape d'autorisation et correspondant à celui ayant émis la demande de jeton d'accès. À l'heure actuelle, seul l'identifiant de l'utilisateur connecté est retourné. La requête POST est construite de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|resource_type||string||Le type de ressource demandé, ici, ce champ correspond à '''user_information'''.&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Un exemple de requête complète au format JSON :&lt;br /&gt;
&amp;lt;javascript&amp;gt;POST /nom-de-plateforme/oauth/resources.php HTTP/1.1&lt;br /&gt;
Content-Type: application/x-www-form-urlencoded&lt;br /&gt;
Host: openflyers.com&lt;br /&gt;
Date: Wed, 04 Aug 2021 13:57:51 GMT&lt;br /&gt;
Accept: application/json&lt;br /&gt;
User-Agent: curl/7.64.1&lt;br /&gt;
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU&lt;br /&gt;
Signature: keyId=&amp;quot;58c450d937953829c8cca3613001f865a918da07&amp;quot;,&lt;br /&gt;
           algorithm=&amp;quot;rsa-sha256&amp;quot;,&lt;br /&gt;
           headers=&amp;quot;host content-type digest&amp;quot;,&lt;br /&gt;
           signature=&amp;quot;UsTjCPLsXzmo1b8FrA18SdLgaPamCpqR7tDHBhaiBnro6RbOkoD7=&amp;quot;&lt;br /&gt;
Digest: SHA-256=Bi6/9qfJXEWme2/9o7VQMyvf+MED523bWdtdi91opwk=&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;resource_type&amp;quot;:&amp;quot;user_information&amp;quot;,&lt;br /&gt;
    &amp;quot;client_id&amp;quot;:&amp;quot;d2615fe2020ec476&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La réponse est retournée dans un conteneur JSON.&lt;br /&gt;
&lt;br /&gt;
===Récupérer les rapports génériques===&lt;br /&gt;
Ce type de ressource est nommé '''generic_report'''. Cette ressource n'est accessible qu'avec le scope '''genericreports.readonly'''. Cette ressource permet la récupération des rapports génériques au format CSV autorisés pour le profil de l'utilisateur associé au client OAuth2 enregistré. La requête POST est construite de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|resource_type||string||Le type de ressource demandé, ici, ce champ correspond à '''generic_report'''.&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|report_id||int||Identifiant du rapport souhaité.&lt;br /&gt;
|-&lt;br /&gt;
|replacementList||array||Tableau correspondant aux différents paramètres modifiables pour générer le rapport souhaité.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Un exemple de requête complète au format JSON :&lt;br /&gt;
&amp;lt;javascript&amp;gt;POST /nom-de-plateforme/oauth/resources.php HTTP/1.1&lt;br /&gt;
Content-Type: application/x-www-form-urlencoded&lt;br /&gt;
Host: openflyers.com&lt;br /&gt;
Date: Wed, 04 Aug 2021 13:57:51 GMT&lt;br /&gt;
Accept: application/json&lt;br /&gt;
User-Agent: curl/7.64.1&lt;br /&gt;
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU&lt;br /&gt;
Signature: keyId=&amp;quot;58c450d937953829c8cca3613001f865a918da07&amp;quot;,&lt;br /&gt;
           algorithm=&amp;quot;rsa-sha256&amp;quot;,&lt;br /&gt;
           headers=&amp;quot;host content-type digest&amp;quot;,&lt;br /&gt;
           signature=&amp;quot;UsTjCPLsXzmo1b8FrA18SdLgaPamCpqR7tDHBhaiBnro6RbOkoD7=&amp;quot;&lt;br /&gt;
Digest: SHA-256=Bi6/9qfJXEWme2/9o7VQMyvf+MED523bWdtdi91opwk=&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;resource_type&amp;quot;:&amp;quot;generic_report&amp;quot;,&lt;br /&gt;
    &amp;quot;client_id&amp;quot;:&amp;quot;d2615fe2020ec476&amp;quot;,&lt;br /&gt;
    &amp;quot;report_id&amp;quot;:135,&lt;br /&gt;
    &amp;quot;replacementList&amp;quot;:{&lt;br /&gt;
        &amp;quot;year&amp;quot;:2018&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La réponse est un fichier CSV retourné dans un conteneur JSON.&lt;br /&gt;
&lt;br /&gt;
===Récupérer les rapports personnalisés===&lt;br /&gt;
Ce type de ressource est nommé '''report'''. Cette ressource n'est accessible qu'avec le scope '''reports.readonly'''. Cette ressource permet la récupération des rapports personnalisés au format CSV autorisés pour le profil de l'utilisateur associé au client OAuth2 enregistré. La requête POST est construite de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|resource_type||string||Le type de ressource demandé, ici, ce champ correspond à '''report'''.&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|report_id||int||Identifiant du rapport souhaité.&lt;br /&gt;
|-&lt;br /&gt;
|replacementList||array||Tableau correspondant aux différents paramètres modifiables pour générer le rapport souhaité.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Un exemple de requête complète au format JSON :&lt;br /&gt;
&amp;lt;javascript&amp;gt;POST /nom-de-plateforme/oauth/resources.php HTTP/1.1&lt;br /&gt;
Content-Type: application/x-www-form-urlencoded&lt;br /&gt;
Host: openflyers.com&lt;br /&gt;
Date: Wed, 04 Aug 2021 13:57:51 GMT&lt;br /&gt;
Accept: application/json&lt;br /&gt;
User-Agent: curl/7.64.1&lt;br /&gt;
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU&lt;br /&gt;
Signature: keyId=&amp;quot;58c450d937953829c8cca3613001f865a918da07&amp;quot;,&lt;br /&gt;
           algorithm=&amp;quot;rsa-sha256&amp;quot;,&lt;br /&gt;
           headers=&amp;quot;host content-type digest&amp;quot;,&lt;br /&gt;
           signature=&amp;quot;UsTjCPLsXzmo1b8FrA18SdLgaPamCpqR7tDHBhaiBnro6RbOkoD7=&amp;quot;&lt;br /&gt;
Digest: SHA-256=Bi6/9qfJXEWme2/9o7VQMyvf+MED523bWdtdi91opwk=&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;resource_type&amp;quot;:&amp;quot;report&amp;quot;,&lt;br /&gt;
    &amp;quot;client_id&amp;quot;:&amp;quot;d2615fe2020ec476&amp;quot;,&lt;br /&gt;
    &amp;quot;report_id&amp;quot;:1,&lt;br /&gt;
    &amp;quot;replacementList&amp;quot;:{&lt;br /&gt;
        &amp;quot;year&amp;quot;:2020&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La réponse est un fichier CSV retourné dans un conteneur JSON.&lt;br /&gt;
&lt;br /&gt;
=Procédures=&lt;br /&gt;
==Créer un client à partir du code source==&lt;br /&gt;
;Prérequis&lt;br /&gt;
Un client de démonstration est disponible pour le logiciel OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/index.php&lt;br /&gt;
&lt;br /&gt;
;Télécharger Le code source du client de démonstration :&lt;br /&gt;
&lt;br /&gt;
Le code source est mis à disposition par OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/oauth2-demo-src.zip &lt;br /&gt;
&lt;br /&gt;
Le code source est structuré de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 src demo folder.png|800px]]&lt;br /&gt;
&lt;br /&gt;
* Le dossier '''css''' contient tout le matériel nécessaire à la stylisation de la page web.&lt;br /&gt;
* Le dossier '''img''' contient les images affichées sur la page web.&lt;br /&gt;
* Le dossier '''ssl''' est le dossier contenant tous les certificats et les clé privées associées à chaque client. Il doit respecter une structure particulière décrite ci-dessous.&lt;br /&gt;
* Le fichier '''ClientDemo.php''' contient la classe '''ClientDemo'''. Cette classe contient toutes les méthodes nécessaires au fonctionnement du client de démonstration OAuth2.&lt;br /&gt;
* Le fichier '''index.php''' est le fichier à appeler depuis le navigateur. Ce fichier correspond au fichier qui gère les appels à la classe '''ClientDemo''' et exécute les méthodes dans l'ordre.&lt;br /&gt;
&lt;br /&gt;
Le dossier '''ssl''' doit respecter la structure suivante :&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 demo tree.png]]&lt;br /&gt;
&lt;br /&gt;
;[[#Générer des certificats|Générer les certificats]] :&lt;br /&gt;
Après la génération des certificats, les clés privées 'auth.key' et 'sign.key' remplacent celles présentes dans les dossiers 'ssl/AuthCodeDemo' et 'ssl/ClientCredDemo'.&lt;br /&gt;
&lt;br /&gt;
;[[#Enregistrer un client|Enregistrer les clients]] :&lt;br /&gt;
&lt;br /&gt;
*Deux clients doivent être créés :&lt;br /&gt;
**Le premier pour le mécanisme d'autorisation '''Authorization Code''',&lt;br /&gt;
**Le second pour le mécanisme d'autorisation '''Client Credentials'''.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 demo manage.png|800px]]&lt;br /&gt;
&lt;br /&gt;
*Télécharger le certificat du CA OpenFlyers en cliquant sur le bouton '''Télécharger le certificat CA''' de la page de gestion. Télécharger aussi le certificat de signature du serveur en cliquant sur le bouton '''Télécharger le certificat de signature du serveur''' de la page de gestion. Placer les deux certificats téléchargés à la racine du dossier '''ssl'''.&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Authorization Code''' et les placer dans le répertoire '''ssl/AuthCodeDemo'''. &lt;br /&gt;
*Modifier le fichier '''ssl/AuthCodeDemo/config.authcode.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;authorize_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/authorize.php&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;path_to_client/ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;path_to_client/ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Remplacer les &amp;lt;code&amp;gt;XXXXXXXXXXXXXXXX&amp;lt;/code&amp;gt; des champs &amp;lt;code&amp;gt;client_id&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;client_secret&amp;lt;/code&amp;gt; par les valeurs obtenues lors de [[#Enregistrer-un-client|l'enregistrement du client]].&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;mastructure&amp;lt;/code&amp;gt; par le nom de la structure sur laquelle la démo est testée.&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;path_to_client/&amp;lt;/code&amp;gt; par le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
**Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
**Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Client Credentials''' et les placer dans le répertoire '''ssl/ClientCredDemo'''.&lt;br /&gt;
*Modifier le fichier '''ssl/ClientCredDemo/config.clientcred.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;path_to_client/ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;path_to_client/ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Remplacer les &amp;lt;code&amp;gt;XXXXXXXXXXXXXXXX&amp;lt;/code&amp;gt; des champs &amp;lt;code&amp;gt;client_id&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;client_secret&amp;lt;/code&amp;gt; par les valeurs obtenues lors de [[#Enregistrer-un-client|l'enregistrement du client]].&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;mastructure&amp;lt;/code&amp;gt; par le nom de la structure sur laquelle la démo est testée.&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;path_to_client/&amp;lt;/code&amp;gt; par le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
**Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
**Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Suivre la [[#Utiliser le client|procédure d'utilisation du client de démonstration]] pour faire fonctionner le client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NB''': Le certificat de signature du serveur est unique à chaque plateforme et serveur. Ainsi, si le serveur ou la plateforme est modifié, le certificat doit être renouvelé.&lt;br /&gt;
&lt;br /&gt;
==Enregistrer un client==&lt;br /&gt;
Pour utiliser l'API OAuth2, il faut enregistrer un client OAuth2 auprès d'OpenFlyers. Pour ceci, suivre les étapes suivantes :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Pour le mécanisme d'authentification Client Credentials&lt;br /&gt;
*Créer un [[Gestion-des-profils#Ajouter-un-profil|nouveau profil]]. Ce profil doit permettre de gérer les droits du client OAuth2. Choisir un nom explicite, par exemple &amp;quot;Client OAuth rapports&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*Sélectionner les droits à assigner à ce profil. Ces droits limitent les données auxquelles le client OAuth2 a accès.&lt;br /&gt;
**Sélectionner les droits relatifs à l'enregistrement de clients OAuth2 dans l'onglet '''Admin''' (colonne '''Associé aux clients OAuth2''').&lt;br /&gt;
**Sélectionner les rapports accessibles par le profil précédemment créé.&lt;br /&gt;
&lt;br /&gt;
*Créer un nouvel utilisateur à partir du panneau de gestion. Cet utilisateur est virtuel et représente le serveur sur lequel fonctionne le client OAuth2.&lt;br /&gt;
**''Des identifiant et nom explicites sont recommandés (exemple : &amp;quot;serv1_oauth_client&amp;quot;)''&lt;br /&gt;
**'''Attention''' : tout utilisateur désactivé et associé à un client OAuth2 rend le client inactif, il faut donc changer l'utilisateur associé au client pour réactiver le client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Pour le mécanisme d'authentification Authorization Code&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Utilisateurs &amp;gt; Profils'''&lt;br /&gt;
*Dans l'onglet '''Généralités''', cocher la case relative à la colonne '''Connexion depuis l'extérieur (OAuth2)''' pour le profil souhaité.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Créer un nouveau client OAuth2&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Transferts &amp;gt; Exports &amp;gt; API OAuth2'''&lt;br /&gt;
[[File:Oauth2 manage.png|800px]]&lt;br /&gt;
*Cliquer sur le bouton Ajouter '''+''' ou '''Ajouter un client'''&lt;br /&gt;
[[File:Oauth2 client creation.png|800px]]&lt;br /&gt;
*Choisir un nom pour le client.&lt;br /&gt;
*Sélectionner le mécanisme d'autorisation utilisé par le client :&lt;br /&gt;
**'''Authorization Code''': permet d'utiliser OAuth2 comme solution SSO ou accéder à des données utilisateurs. Cette méthode peut être couplée avec le mécanisme de mémorisation de connexion (''Refresh Token'').&lt;br /&gt;
**'''Client Credentials''': permet d'utiliser OAuth2 dans un contexte d'automatisme.&lt;br /&gt;
*Saisir l'URI de redirection vers le client pour le mécanisme ''Authorization Code''.&lt;br /&gt;
*Sélectionner l'utilisateur virtuel créé précédemment pour le mécanisme ''Client Credentials''.&lt;br /&gt;
*[[#Générer-des-certificats|Générer deux CSR]] afin d'obtenir deux certificats signés et les saisir :&lt;br /&gt;
**'''Certificate Signing Request pour le certificat d'authentification''' est utilisé pour l'authentification mutuelle avec mTLS (auth_cert.csr.pem).&lt;br /&gt;
**'''Certificate Signing Request pour le certificat de signature''' est utilisé pour la signature des en-têtes HTTP (sign_cert.csr.pem).&lt;br /&gt;
&lt;br /&gt;
[[File:PublicKeysCopyScreen.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Cliquer sur '''Enregistrer'''.&lt;br /&gt;
&lt;br /&gt;
NB: La validité des certificats générés s'étend sur une période de '''3 années'''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Sauvegarder le couple ID/passphrase&lt;br /&gt;
Un couple ID/passphrase (client_id/client_secret) est généré. Ces deux clées ne sont communiquées qu'une seule fois. Elle doivent être stockées en toute sécurité et gardées confidentielles,&lt;br /&gt;
et Mettre ces identifiants dans le fichier '''config.clientcred.json'''.&lt;br /&gt;
[[File:Oauth2 client created.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:ConfigCredJsonScreen.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Télécharger les certificats crt&lt;br /&gt;
Les certificats signés sont téléchargeables depuis l'interface de gestion des clients OAuth2, les certificats sont disponibles dans les onglets '''Certificat d'authentification''' et '''Certificat de signature''' et les mettre dans le dossier '''/ssl''' du client OAuth2.&lt;br /&gt;
[[File:Oauth2 client certificates.png]]&lt;br /&gt;
&lt;br /&gt;
;Téléchargez les certificats du serveur.&lt;br /&gt;
*Les certificats du CA d'OpenFlyers et de signature HTTP du serveur sont nécessaires. Ils sont téléchargeables depuis l'interface de configuration des clients OAuth2.&lt;br /&gt;
[[File:DownloadServerCertifScreen.png|900px]]&lt;br /&gt;
*Dans certains cas d'utilisation, il peut être nécessaire d'ajouter le certificat du CA d'OpenFlyers au Trust Store du système. Si cette étape n'est pas réalisée, les certificats peuvent être considérés comme invalides et peuvent ne pas être utilisables.&lt;br /&gt;
*Pour ajouter le certificat CA au Trust Store du système, suivre les étapes suivantes:&lt;br /&gt;
**Sous Linux, copier le certificat CA d'OpenFlyers dans le dossier &amp;lt;code&amp;gt;/usr/local/share/ca-certificates&amp;lt;/code&amp;gt; et exécuter la commande &amp;lt;code&amp;gt;sudo update-ca-certificates&amp;lt;/code&amp;gt;&lt;br /&gt;
**Sous Windows,&lt;br /&gt;
***Double-cliquer sur le certificat CA d'OpenFlyers téléchargé depuis l'interface d'enregistrement des clients OAuth2&lt;br /&gt;
***Cliquer sur '''Installer un certificat...'''&lt;br /&gt;
***Choisir l'emplacement de stockage (utilisateur ou ordinateur) et cliquer sur '''Suivant''' puis '''Suivant''' et enfin '''Terminer'''&lt;br /&gt;
&lt;br /&gt;
==Générer des certificats==&lt;br /&gt;
L'API OAuth2 implémente [https://tools.ietf.org/html/draft-cavage-http-signatures-10 HTTP Signature] et l'[[Wikipedia-en:Mutual_authentication#mTLS|authentification TLS mutuelle]]. Ces mécanismes utilisent chacun une paire certificat/clé privée différente.&lt;br /&gt;
&lt;br /&gt;
Pour obtenir ces certificats, il faut d'abord générer des Certificate Signing Request (CSR).&lt;br /&gt;
&lt;br /&gt;
La procédure est la suivante :&lt;br /&gt;
*[[OpenSSL#Installer-OpenSSL-dans-un-environnement-Windows|Télécharger OpenSSL pour Windows]] ou [[OpenSSL#Utiliser-Openssl-d'Apache-sous-WAMP|utiliser Openssl d'Apache sous WAMP]].&lt;br /&gt;
*Utiliser les deux fichiers de configuration ''sign_cert.conf'' et ''auth_cert.conf'' ci-dessous et les remplir.&lt;br /&gt;
&lt;br /&gt;
;Fichier de configuration OpenSSL - sign_cert.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;[req]&lt;br /&gt;
default_bits       = 4096                     # taille par défaut des nouvelles clés, peut être surchargé dans la commande&lt;br /&gt;
encrypt_key        = no                       # chiffrer la clé générée&lt;br /&gt;
distinguished_name = req_distinguished_name   # pointe vers la catégorie spécifiée pour le Distinguished Name&lt;br /&gt;
x509_extensions    = v3_req                   # pointe vers la catégorie spécifiée pour les extensions x509&lt;br /&gt;
prompt             = no&lt;br /&gt;
&lt;br /&gt;
[req_distinguished_name]&lt;br /&gt;
C                  =                          # code à deux chiffres du pays (ex: FR)&lt;br /&gt;
ST                 =                          # région/état (ex: Gironde)&lt;br /&gt;
L                  =                          # ville (ex: Bordeaux)&lt;br /&gt;
O                  =                          # organisation (ex: OpenFlyers)&lt;br /&gt;
OU                 =                          # unité organisationelle (ex: IT)&lt;br /&gt;
CN                 =                          # nom de domaine (ex: openflyers.com)&lt;br /&gt;
&lt;br /&gt;
[v3_req]&lt;br /&gt;
keyUsage           = digitalSignature         # pour quelles opérations la clé peut-elle être utilisée&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Fichier de configuration OpenSSL - auth_cert.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;[req]&lt;br /&gt;
default_bits       = 4096                     # taille par défaut des nouvelles clés, peut être surchargé dans la commande&lt;br /&gt;
encrypt_key        = no                       # chiffrer la clé générée&lt;br /&gt;
distinguished_name = req_distinguished_name   # pointe vers la catégorie spécifiée pour le Distinguished Name&lt;br /&gt;
x509_extensions    = v3_req                   # pointe vers la catégorie spécifiée pour les extensions x509&lt;br /&gt;
prompt             = no&lt;br /&gt;
&lt;br /&gt;
[req_distinguished_name]&lt;br /&gt;
C                  =                          # code à deux chiffres du pays (ex: FR)&lt;br /&gt;
ST                 =                          # région/état (ex: Gironde)&lt;br /&gt;
L                  =                          # ville (ex: Bordeaux)&lt;br /&gt;
O                  =                          # organisation (ex: OpenFlyers)&lt;br /&gt;
OU                 =                          # unité organisationelle (ex: IT)&lt;br /&gt;
CN                 =                          # nom de domaine (ex: openflyers.com)&lt;br /&gt;
&lt;br /&gt;
[v3_req]&lt;br /&gt;
extendedKeyUsage   = clientAuth               # pour quelles opérations la clé peut-elle être utilisée&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Exécuter les commandes suivantes :&lt;br /&gt;
*&amp;lt;bash&amp;gt;openssl req -sha256 -newkey rsa -keyout sign.key -out sign_cert.csr.pem -outform PEM -config sign_cert.conf&amp;lt;/bash&amp;gt;&lt;br /&gt;
*&amp;lt;bash&amp;gt;openssl req -sha256 -newkey rsa -keyout auth.key -out auth_cert.csr.pem -outform PEM -config auth_cert.conf&amp;lt;/bash&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces commandes prennent chacune en entrée le fichier de configuration et génèrent une clé privée et un Certificate Signing Request. &lt;br /&gt;
&lt;br /&gt;
Une fois ces CSR obtenus :&lt;br /&gt;
*Les renseigner dans les champs prévus à cet effet lors de la [[#Enregistrer-un-client|création d'un client]] et télécharger les certificats signés depuis l'interface une fois le client créé.&lt;br /&gt;
*Garder la clé privée confidentielle. Une fuite poserait un risque de sécurité. Elle va de paire avec le certificat distribué par l'autorité de certification OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
==Mettre en place une connexion à l'API OpenFlyers sur un serveur mutualisé==&lt;br /&gt;
;Note&lt;br /&gt;
La procédure ci-après est destinée à une mise en place lorsqu'il n'y a pas d'accès SSH en ligne de commande mais uniquement un accès FTP. Dans ce cas, la création des clés privées et publics est effectuée &amp;quot;en local&amp;quot;. Dans la procédure suivante elle est effectuée depuis un PC sous '''Windows'''.&lt;br /&gt;
&lt;br /&gt;
;Prérequis&lt;br /&gt;
*Posséder les accès FTP :&lt;br /&gt;
**Hôte : XXXXXXXXXXXXXXXXXX&lt;br /&gt;
**Login : XXXXXXXX&lt;br /&gt;
**Mot de passe :  XXXXXXXX&lt;br /&gt;
**Port : XX (par exemple 21)&lt;br /&gt;
*Télécharger Le code source du client de démonstration à disposition par OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/oauth2-demo-src.zip &lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
*[[#Générer des certificats|Générer les certificats]] en local.&lt;br /&gt;
*Remplacer les clés privées 'auth.key' et 'sign.key' présentes dans les dossiers 'ssl/AuthCodeDemo' et 'ssl/ClientCredDemo' par les clés générées.&lt;br /&gt;
*[[#Enregistrer un client|Enregistrer les deux clients]] :&lt;br /&gt;
**Le premier pour le mécanisme d'autorisation '''Authorization Code'''.&lt;br /&gt;
**Le second pour le mécanisme d'autorisation '''Client Credentials'''.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 demo manage.png|800px]]&lt;br /&gt;
&lt;br /&gt;
*Télécharger le certificat du CA OpenFlyers en cliquant sur le bouton '''Télécharger le certificat CA''' de la page de gestion. &lt;br /&gt;
*Télécharger aussi le certificat de signature du serveur en cliquant sur le bouton '''Télécharger le certificat de signature du serveur''' de la page de gestion.&lt;br /&gt;
*Placer les deux certificats téléchargés à la racine du dossier '''ssl'''.&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Authorization Code''' et les placer dans le répertoire '''ssl/AuthCodeDemo'''. &lt;br /&gt;
*Modifier le fichier '''ssl/AuthCodeDemo/config.authcode.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;authorize_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/authorize.php&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;./ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;./ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Client Credentials''' et les placer dans le répertoire '''ssl/ClientCredDemo'''.&lt;br /&gt;
*Modifier le fichier '''ssl/ClientCredDemo/config.clientcred.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;./ssl/ClientCredDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;./ssl/ClientCredDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;./ssl/ClientCredDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;./ssl/ClientCredDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;./ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;./ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Remplacer les &amp;lt;code&amp;gt;XXXXXXXXXXXXXXXX&amp;lt;/code&amp;gt; des champs &amp;lt;code&amp;gt;client_id&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;client_secret&amp;lt;/code&amp;gt; par les valeurs obtenues lors de [[#Enregistrer-un-client|l'enregistrement du client]].&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;mastructure&amp;lt;/code&amp;gt; par le nom de la structure sur laquelle la démo est testée.&lt;br /&gt;
&lt;br /&gt;
*Transférer le fichier &amp;quot;oauth-demo&amp;quot; vers le serveur mutualisé :&lt;br /&gt;
**Télécharger [http://filezilla-project.org/download.php?type=client FileZilla].&lt;br /&gt;
**Lancer FileZilla.&lt;br /&gt;
**Entrer l'URl du serveur mutualisé dans le champ '''Hôte'''.&lt;br /&gt;
**Entrer le login dans le champ '''Nom d'utilisateur'''.&lt;br /&gt;
**Entrer le mot de passe dans le champ '''Mot de passe'''.&lt;br /&gt;
**Entrer le port dans le champ '''Port'''.&lt;br /&gt;
**Cliquer sur le bouton Connexion.&lt;br /&gt;
**Accéder à l'emplacement du répertoire &amp;quot;oauth-demo&amp;quot; en local à gauche dans l'onglet &amp;quot;Site local&amp;quot;.&lt;br /&gt;
**Choisir l'emplacement où placer le répértoire oauth-demo dans l'anglet '''Site distant''' à droite.&lt;br /&gt;
**Glisser et déposer le oauth-demo à l'emplacement choisi.&lt;br /&gt;
[[File:Transfer OauthDemo To Shared Server.png|800px]]&lt;br /&gt;
*Accéder au client OAuth-demo depuis le serveur mutualisé en utilisant l'URL du domaine du serveur : url_de_domaine_de_serveur/oauth-demo/index.php&lt;br /&gt;
*Modifier la valeur '''URI de redirection vers le client''' du client '''AuthCodeDemo''' précédemment créé en remplaçant l'ancienne URL par la nouvelle.&lt;br /&gt;
&lt;br /&gt;
*Suivre la [[#Utiliser le client|procédure d'utilisation du client de démonstration]] pour faire fonctionner le client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NB''': Le certificat de signature du serveur est unique à chaque plateforme et serveur. Ainsi, si le serveur ou la plateforme est modifié, le certificat doit être renouvelé.&lt;br /&gt;
&lt;br /&gt;
==Récupérer les données d'un utilisateur==&lt;br /&gt;
*Cliquer sur le bouton '''Récupérer les informations utilisateur''', l'identifiant de l'utilisateur s'affiche.&lt;br /&gt;
*Utiliser l'identifiant récupérer afin de récupérer toute information associée à cet utilisateur en [[Gestion-des-rapports#Ajouter-un-rapport|créant de nouveaux rapports personnalisés]]&lt;br /&gt;
&lt;br /&gt;
==Utiliser le client==&lt;br /&gt;
;Prérequis&lt;br /&gt;
Un client de démonstration est disponible pour le logiciel OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/index.php&lt;br /&gt;
&lt;br /&gt;
Le client de démonstration se présente de la manière suivante.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2-client-demo.png]]&lt;br /&gt;
&lt;br /&gt;
La démonstration est composée de deux colonnes. La première, nommée '''Authorization Code''' correspond [[#Authorization Code|au mécanisme d'autorisation du même nom]]. Elle dispose d'un bouton permettant de se connecter ainsi que d'une section indiquant les informations relatives à l'état de la connexion. La seconde colonne, nommée '''Client Credentials''' correspond elle aussi [[#Client Credentials|au mécanisme d'autorisation du même nom]]. Comme pour la première colonne, les éléments qui y sont présentés sont identiques. La différence étant que le bouton de connexion n'a pas le même effet étant donné que ces deux mécanismes sont différents. Chaque mécanisme est indépendant et il est possible de se connecter à un des deux mécanismes sans se connecter à l'autre ou se connecter aux deux en même temps.&lt;br /&gt;
&lt;br /&gt;
;Le mécanisme '''Authorization Code'''&lt;br /&gt;
*Cliquer sur le bouton '''Se connecter''' (ce qui redirige le navigateur vers la page de connexion du logiciel OpenFlyers).&lt;br /&gt;
*Renseigner les identifiants de l'administrateur pour s'y connecter.&lt;br /&gt;
*Nom d'utilisateur : '''admini'''.&lt;br /&gt;
*Mot de passe : '''azerty'''.&lt;br /&gt;
&lt;br /&gt;
Une fois les informations saisies, la page suivante est affichée.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth authorize demo.png]]&lt;br /&gt;
&lt;br /&gt;
*Cliquer sur le bouton '''Autoriser l'application''' pour autoriser la connexion (ce qui se redirige le navigateur vers la page du client de démonstration OAuth2).&lt;br /&gt;
&lt;br /&gt;
La première colonne doit afficher l'état de connexion '''Connecté''' ainsi qu'un nouveau bouton '''Récupèrer les informations utilisateurs''' qui permet de récupérer les informations de l'utilisateur connecté.&lt;br /&gt;
&lt;br /&gt;
;Le mécanisme '''Client Credentials'''&lt;br /&gt;
*Cliquer sur le bouton de connexion '''Se connecter''': contrairement à celui du mécanisme '''Authorization Code''', ne redirige pas le navigateur vers la page de connexion du logiciel OpenFlyers. Le bouton de connexion utilise les identifiants du client, ici le couple clé privée/clé publique, pour initier la connexion avec le serveur d'autorisation et obtenir un jeton d'accès.&lt;br /&gt;
&lt;br /&gt;
Une fois la connexion établie, la seconde colonne doit afficher l'état de connexion '''Connecté''' ainsi qu'un menu déroulant '''Rapport à récupèrer''' et un nouveau bouton '''Récupèrer le rapport''' qui permet de récupérer les rapports génériques et personnalisés.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le client, une fois connecté sur les deux mécanismes, se présente de la manière suivante.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 connected demo.png]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
==500 Internal Server Error en récupérant le rapport==&lt;br /&gt;
La démo utilise les valeurs par défaut pour extraire les rapports. Une erreur 500 indique une &amp;quot;Erreur de syntaxe ou violation d'accès&amp;quot; lors de l'exécution de la requête du rapport. Cela se produit parce que le rapport n'a pas de valeurs par défaut associées, étant donné qu'il n'a jamais été visualisé dans l'interface web. Pour résoudre ce problème, il vous suffit de visualiser le rapport et de cocher la case &amp;quot;Mémoriser ce choix&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Erreur &amp;quot;File not found.&amp;quot;==&lt;br /&gt;
Cette erreur se produit lorsque l'URI utilisé n'existe pas sur le serveur OpenFlyers. Vérifier les URIs mis en place dans les fichiers de configuration et essayer de nouveau.&lt;br /&gt;
&lt;br /&gt;
==int_rsa_verify : longueur de signature incorrecte==&lt;br /&gt;
Ce problème pourrait survenir si les fichiers ca.cert et sign_cert_server.cert ne proviennent pas du même serveur que celui du client oauth2.&lt;br /&gt;
La solution est :&lt;br /&gt;
&lt;br /&gt;
*D'essayer depuis le début l'étape de [[#Générer-des-certificats|génération]] et de [[#Enregistrer-un-client|configuration des certificats]] avec jsut la modification du client existant.&lt;br /&gt;
&lt;br /&gt;
;Si cela ne fonctionne pas:&lt;br /&gt;
&lt;br /&gt;
*Essayez de créer [[#Enregistrer-un-client|un nouveau client]] et refaites la configuration des certificats.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=API-OpenFlyers&amp;diff=13272</id>
		<title>API OpenFlyers</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=API-OpenFlyers&amp;diff=13272"/>
		<updated>2025-02-13T18:20:28Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: /* Signature */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de décrire l'API OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
;Description de l'API&lt;br /&gt;
OpenFlyers possède une API basée sur [[Wikipedia-en:OAuth#OAuth_2.0|OAuth2]] qui permet à des serveurs extérieurs, dûment [[#Enregistrer-un-client|enregistrés]], de mettre en œuvre un processus d'[[Wikipedia-fr:Authentification_unique|authentification unique (SSO)]] et/ou de récupération des résultats des requêtes SQL de la [[Bibliothèque-des-rapports|bibliothèque des rapports]] ou des rapports personnalisés sous la forme de fichiers CSV.&lt;br /&gt;
&lt;br /&gt;
OAuth2 propose plusieurs mécanismes pour permettre l'authentification. Un mécanisme d'authentification détermine la séquence exacte des étapes impliquées dans le processus d'authentification d'OAuth2. OpenFlyers met à disposition deux mécanismes d'authentification :&lt;br /&gt;
*[[#Authorization Code|Authorization Code]] basé sur la méthode d'authentification par code d'autorisation et qui correspond au mécanisme associé à l'[[Wikipedia-fr:Authentification_unique|authentification unique (SSO)]],&lt;br /&gt;
*[[#Client Credentials|Client Credentials]] basé sur la méthode d'authentification avec les identifiants clients et qui est utilisé dans un contexte d'automatisme sans autorisation de l'utilisateur au préalable.&lt;br /&gt;
&lt;br /&gt;
Dans les chapitres qui suivent, le terme ''ressource'' fait référence à la définition OAuth2. Une ressource dans OAuth2 est un élément qui peut être :&lt;br /&gt;
*une ou des données comme des photos, des documents, des contacts ou des informations personnelles,&lt;br /&gt;
*un ou plusieurs services comme des transferts de fonds, la récupération de rapports ou l'ajout d'articles sur un blog,&lt;br /&gt;
*toute ressource nécessitant un accès restreint.&lt;br /&gt;
&lt;br /&gt;
OpenFlyers définit plusieurs [[#Utiliser-l'API|types de ressources]] :&lt;br /&gt;
*les [[#Récupérer-les-informations-de-l'utilisateur-connecté|informations de l'utilisateur connecté]],&lt;br /&gt;
*les [[#Récupérer les rapports génériques|rapports génériques]] ou [[#Récupérer les rapports personnalisés|personnalisés]] au format CSV.&lt;br /&gt;
&lt;br /&gt;
OAuth2 dispose de ''scopes''. Un scope est un privilège définit de manière explicite permettant l'accès à une ressource protégée. OpenFlyers met à disposition une [[#Liste des scopes disponibles|liste de scopes]] utilisables à travers l'API.&lt;br /&gt;
&lt;br /&gt;
Deux protocoles de sécurité sont présents dans l'API OpenFlyers :&lt;br /&gt;
*[[#Authentification-TLS-Mutuelle-(mTLS)|mTLS]] : il permet d'authentifier le client avec un certificat TLS, en plus d'authentifier le serveur avec un certificat. Ce protocole permet d'éviter les usurpations d'identité.&lt;br /&gt;
*[[#HTTP-Signature|HTTP-Signature]] : il permet de signer les en-têtes et le corps (lorsqu'il y en a un) des messages échangés afin d'en garantir leur intégrité.&lt;br /&gt;
&lt;br /&gt;
;Premiers pas - Client de démonstration&lt;br /&gt;
Un client de démonstration est disponible pour comprendre les mécanismes décrits ci-dessous.&lt;br /&gt;
&lt;br /&gt;
L'utilisation de ce client de démonstration est décrite dans la procédure [[#Utiliser-le-client|Utiliser le client]] de cette page.&lt;br /&gt;
&lt;br /&gt;
Le client de démonstration est lui-même accessible à cette adresse : https://openflyers.com/oauth2-demo/index.php&lt;br /&gt;
&lt;br /&gt;
Le code source du client de démonstration est mis à disposition par OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/oauth2-demo-src.zip&lt;br /&gt;
&lt;br /&gt;
L'utilisation du code source est décrite dans la procédure [[#Créer-un-client-à-partir-du-code-source|Créer un client à partir du code source]].&lt;br /&gt;
&lt;br /&gt;
=Définitions=&lt;br /&gt;
==Authentification TLS Mutuelle (mTLS)==&lt;br /&gt;
En général dans une communication TLS, seul le serveur a l'obligation de fournir un certificat. Il est également possible pour le client de fournir un certificat. Ce principe s'appelle l'authentification mutuelle et est mise en place avec Mutual TLS (ou [[Wikipedia-en:Mutual_authentication#mTLS|mTLS]]).&lt;br /&gt;
&lt;br /&gt;
OpenFlyers associe un certificat pour l'authentification mutuelle unique à chaque client OAuth2.&lt;br /&gt;
&lt;br /&gt;
;Envoyer un certificat client&lt;br /&gt;
Côté client, le code suivant peut être utilisé pour fournir à cURL le certificat et la clé correspondante ainsi que le certificat du CA d'OpenFlyers à utiliser pour la connexion :&lt;br /&gt;
&amp;lt;php&amp;gt;curl_setopt_array($request, [&lt;br /&gt;
    CURLOPT_SSLVERSION =&amp;gt; CURL_SSLVERSION_TLSv1_2,&lt;br /&gt;
    CURLOPT_CAINFO     =&amp;gt; $caCertificatePath,&lt;br /&gt;
    CURLOPT_SSLCERT    =&amp;gt; $certificatePath,&lt;br /&gt;
    CURLOPT_SSLKEY     =&amp;gt; $keyPath&lt;br /&gt;
]);&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''À noter''' : le certificat du CA d'OpenFlyers est nécessaire pour assurer la validité des certificats utilisés.&lt;br /&gt;
&lt;br /&gt;
==HTTP Signature==&lt;br /&gt;
HTTP Signature utilise le principe de la signature numérique pour garantir l'authenticité et l'intégrité du message HTTP.&lt;br /&gt;
&lt;br /&gt;
La signature est générée à l'aide d'une clé privée et vérifiée à l'aide de la clé publique correspondante ou d'un certificat contenant cette clé publique.&lt;br /&gt;
&lt;br /&gt;
HTTP Signature utilise deux en-têtes HTTP :&lt;br /&gt;
*Signature : contient la signature et ses métadonnées.&lt;br /&gt;
*Digest : contient le corps du message haché.&lt;br /&gt;
&lt;br /&gt;
===Digest===&lt;br /&gt;
Le ''digest'' est calculé comme ceci : &amp;lt;code&amp;gt;digest = base64encode(sha256(corps du message))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et l'en-tête est structuré de la manière suivante : &amp;lt;code&amp;gt;Digest: SHA-256=&amp;lt;digest&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un autre algorithme de hachage peut être utilisé, SHA-256 reste cependant le plus répendu.&lt;br /&gt;
&lt;br /&gt;
;Exemple en php&lt;br /&gt;
&amp;lt;php&amp;gt;$digestHeader = 'Digest: SHA-256=' . base64_encode(hash('sha256', $postData, true));&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Signature===&lt;br /&gt;
L'en-tête HTTP de signature est structuré de la manière suivante : &amp;lt;code&amp;gt;Signature: keyId=&amp;quot;&amp;lt;keyId&amp;gt;&amp;quot;,algorithm=&amp;quot;&amp;lt;algo&amp;gt;&amp;quot;,headers=&amp;quot;&amp;lt;signed_headers&amp;gt;&amp;quot;,signature=&amp;quot;&amp;lt;signature&amp;gt;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le champ ''keyId'' correspond à un identifiant permettant l'identification de la clé utilisée pour vérifier la signature. Pour l'API d'OpenFlyers, sa valeur correspond à l'empreinte SHA-1 du certificat au format PEM à utiliser pour vérifier la signature.&lt;br /&gt;
&lt;br /&gt;
L'algorithme ''algo'' correspond à celui utilisé pour générer la signature, exemple : &amp;lt;code&amp;gt;rsa-sha256&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
La valeur de ''signed_headers'' correspond à la liste des en-têtes inclus dans la signature séparés d'un espace. Exemple : &amp;lt;code&amp;gt;date digest (request-target)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour générer la signature, une chaîne de caractères appelée &amp;lt;code&amp;gt;signing string&amp;lt;/code&amp;gt; contenant les en-têtes au format &amp;lt;code&amp;gt;lowercase_header_name: value&amp;lt;/code&amp;gt; séparés par une nouvelle ligne au format LF (&amp;lt;code&amp;gt;\n&amp;lt;/code&amp;gt;) est d'abord générée. Exemple avec les en-têtes &amp;quot;date&amp;quot; et &amp;quot;(request-target)&amp;quot; :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;(request-target): post /some/uri\ndate: Tue, 07 Jun 2014 20:51:35 GMT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La signature est ensuite générée comme ceci : &amp;lt;code&amp;gt;base64encode(algo(signing string))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Exemple en php&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;function generateSignatureHeader(array $headersToSign, string $certificateFingerprint, string $privateKey): string&lt;br /&gt;
{&lt;br /&gt;
    // generating the signing string and header list&lt;br /&gt;
    $headers         = '';&lt;br /&gt;
    $signatureString = '';&lt;br /&gt;
    foreach ($headersToSign as $key =&amp;gt; $value) {&lt;br /&gt;
        $normalizedHeaderKey = trim(strtolower($key));&lt;br /&gt;
        $headers             .= $normalizedHeaderKey . ' ';&lt;br /&gt;
        $signatureString     .= $normalizedHeaderKey . ': ' . trim($value) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // trim extra whitespace&lt;br /&gt;
    $headers         = trim($headers);&lt;br /&gt;
    $signatureString = trim($signatureString);&lt;br /&gt;
&lt;br /&gt;
    // signing the signing string&lt;br /&gt;
    $signature = '';&lt;br /&gt;
    openssl_sign($signatureString, $signature, $privateKey, 'RSA-SHA256');&lt;br /&gt;
    $signature = base64_encode($signature);&lt;br /&gt;
&lt;br /&gt;
    // compiling the header line&lt;br /&gt;
    return &amp;quot;Signature: keyId=\&amp;quot;$certificateFingerprint\&amp;quot;,algorithm=\&amp;quot;rsa-sha256\&amp;quot;,headers=\&amp;quot;$headers\&amp;quot;,signature=\&amp;quot;$signature\&amp;quot;&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Les variables ''$certificateFingerprint'' et ''$privateKey'' correspondent respectivement à une empreinte SHA-1 de certificat et à une clé privée, tous deux au format PEM. &lt;br /&gt;
&lt;br /&gt;
La variable ''$headersToSign'' est un tableau formaté de la manière suivante : &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;[&lt;br /&gt;
    $headerName =&amp;gt; $headerValue,&lt;br /&gt;
    ...&lt;br /&gt;
]&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''À noter''' : les en-têtes sont à signer côté client avec le certificat de signature signé par le CA d'OpenFlyers et dédié au client ainsi que la clé privée associée. Le certificat de signature dédié au client est téléchargeable depuis l'interface de gestion des clients OAuth2. Les en-têtes de la réponse du serveur quant à elles doivent être vérifiées avec le certificat de signature HTTP du serveur, téléchargeable aussi depuis l'interface de configuration des clients OAuth2.&lt;br /&gt;
&lt;br /&gt;
=Client OAuth2=&lt;br /&gt;
Une fois le client OAuth2 configuré sur OpenFlyers, il faut l'utiliser avec un client créé au préalable pour communiquer avec le serveur d'autorisation et l'API.&lt;br /&gt;
&lt;br /&gt;
Plusieurs [https://oauth.net/code/ bibliothèques] simplifiant la création d'un client sont disponibles.&lt;br /&gt;
&lt;br /&gt;
Des scripts client basiques écrits en php sont aussi fournis pour les mécanismes [[#Script-client-:-authorization-code|''authorization_code'']] et [[#Script-client-:-client-credentials|''client_credentials'']]&lt;br /&gt;
&lt;br /&gt;
==Authorization Code==&lt;br /&gt;
Ce flux OAuth2 se déroule en plusieurs étapes :&lt;br /&gt;
*Le client redirige le navigateur de l'utilisateur vers l'URL d'autorisation.&lt;br /&gt;
*Le navigateur de l'utilisateur est redirigé vers l'URL fournie durant la demande ou durant l'enregistrement du client.&lt;br /&gt;
*Le client récupère un code d'autorisation grâce à la redirection précédente, et échange ce code contre un jeton d'accès auprès du serveur d'autorisation.&lt;br /&gt;
*Le client peut utiliser ce code d'accès :&lt;br /&gt;
**Comme preuve d'authentification pour une solution SSO (Single Sign-On).&lt;br /&gt;
**Pour accéder à des données sur le serveur distant en utilisant l'API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    +-----------+                   +------+                +-----------+                  +-------------+                  +-----------+&lt;br /&gt;
    |Utilisateur|                   |Client|                |Navigateur |                  |   Serveur   |                  |  Serveur  |&lt;br /&gt;
    +-----+-----+                   +--+---+                +-----+-----+                  |Autorisation |                  | Ressources|&lt;br /&gt;
          |                            |                          |                        +------+------+                  +-----+-----+&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                   Demande|d'autorisation                 |                               |&lt;br /&gt;
          |                            +-------------------------&amp;gt;+------------------------------&amp;gt;|                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |Authentification + Formulaire d'autorisation              |                               |&lt;br /&gt;
          |&amp;lt;---------------------------+--------------------------+&amp;lt;------------------------------+                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |      Autorisation        |                               |                               |&lt;br /&gt;
          +----------------------------+-------------------------&amp;gt;+------------------------------&amp;gt;|                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                      Code|d'autorisation                 |                               |&lt;br /&gt;
          |                            |&amp;lt;-------------------------+&amp;lt;------------------------------+                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                Demande de|token                          |                               |&lt;br /&gt;
          |                            +--------------------------+------------------------------&amp;gt;|                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                 Access (+|Refresh) token                 |                               |&lt;br /&gt;
          |                            |&amp;lt;-------------------------+-------------------------------+                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |       Requête vers API        |                               |&lt;br /&gt;
          |                            +--------------------------+-------------------------------+------------------------------&amp;gt;|&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |                               |&amp;lt;------------------------------+&lt;br /&gt;
          |                            |                          |                               |  Vérification d'autorisation  |&lt;br /&gt;
          |                            |                          |                               +------------------------------&amp;gt;|&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |      Données/Réponse          |                               |&lt;br /&gt;
          |                            |&amp;lt;-------------------------+-------------------------------+-------------------------------+&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Générer les codes pour PKCE===&lt;br /&gt;
Pour faire fonctionner le client OAuth2, il faut générer deux codes pour l'extension PKCE :&lt;br /&gt;
*Un ''code_verifier'' échangé pendant la demande de jeton d'accès.&lt;br /&gt;
*Un ''code_challenge'' dérivé du ''code_verifier'' et échangé pendant la demande d'autorisation.&lt;br /&gt;
&lt;br /&gt;
;Générer le ''code_verifier''&lt;br /&gt;
&amp;lt;php&amp;gt;function generateCodeVerifier($length = 128): string&lt;br /&gt;
{&lt;br /&gt;
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~';&lt;br /&gt;
    $outputCode = '';&lt;br /&gt;
&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $length; $i++) {&lt;br /&gt;
        $index      = random_int(0, strlen($characters) - 1);&lt;br /&gt;
        $outputCode .= $characters[$index];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $outputCode;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cette fonction permet de générer un ''code_verifier'' avec une longueur donnée. Le ''code_verifier'' doit avoir une longueur entre 43 et 128 caractères.&lt;br /&gt;
&lt;br /&gt;
;Générer le ''code_challenge''&lt;br /&gt;
&amp;lt;php&amp;gt;function computeCodeChallenge(string $codeVerifier): string&lt;br /&gt;
{&lt;br /&gt;
    return strtr(rtrim(base64_encode(hash('sha256', $codeVerifier, true)), '='), '+/', '-_');&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cette fonction génère le ''code_challenge'' à partir du ''code_verifier'' fourni.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Demande d'autorisation===&lt;br /&gt;
Pour initier la demande d'autorisation, rediriger le navigateur de l'utilisateur vers l'URL : &amp;lt;code&amp;gt;GET https://openflyers.com/nom-de-plateforme/oauth/authorize.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Envoyer également les paramètres suivants :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|response_type||string||Le type de réponse envoyée par le serveur. Doit utiliser la valeur &amp;quot;code&amp;quot; (sans guillements) pour ce mécanisme.&lt;br /&gt;
|-&lt;br /&gt;
|redirect_uri||string||L'URI (ou l'URL) fourni pendant l'enregistrement du client et vers lequel l'utilisateur est redirigé après la demande d'autorisation.&lt;br /&gt;
|-&lt;br /&gt;
|scope||string||[[#Liste-des-scopes-disponibles|Liste des droits demandés par le client]], séparés par des espaces.&lt;br /&gt;
|-&lt;br /&gt;
|state||string||Chaîne de caractère aléatoire utilisée pour éviter les [https://fr.wikipedia.org/wiki/Cross-site_request_forgery attaques CSRF]. '''Fortement recommandé'''.&lt;br /&gt;
|-&lt;br /&gt;
|code_challenge||string||Code nécessaire pour le fonctionnement de l'extension [[#Générer-les-codes-pour-PKCE|PKCE]].&lt;br /&gt;
|-&lt;br /&gt;
|code_challenge_method||string||Méthode utilisée pour générer le ''code_challenge''. Ici, la valeur est &amp;quot;S256&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Demande de jeton d'accès===&lt;br /&gt;
Après avoir répondu à la demande, l'utilisateur est redirigé vers l'URI fourni pendant l'enregistrement du client. Si la demande est acceptée, un code temporaire : ''code'' est fourni, ainsi que le paramètre ''state'' fourni pendant la demande avec la même valeur. Si la demande est refusée, un code d'erreur est renvoyé.&lt;br /&gt;
;Si le paramètre ''state'' a une valeur différente de celle envoyée avec la demande, c'est peut-être une tentative d'attaque et il faut refuser la réponse.&lt;br /&gt;
&lt;br /&gt;
Echanger ce ''code'' contre un jeton d'accès via l'URL : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Les paramètres suivants sont également nécessaires :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|client_secret||string||La passphrase reçue pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|code||string||Le code temporaire reçu dans la réponse à la demande d'autorisation.&lt;br /&gt;
|-&lt;br /&gt;
|grant_type||string||Le mécanisme d'autorisation utilisé. Ici, sa valeur doit être ''authorization_code''&lt;br /&gt;
|-&lt;br /&gt;
|redirect_uri||string||L'URI (ou l'URL) de redirection fourni pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|code_verifier||string||Le ''code_verifier'' utilisé pour générer le ''code_challenge'' de la demande d'autorisation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Si la requête est correcte, un jeton d'accès (Access Token) ainsi qu'un jeton de rafraîchissement (Refresh Token) sont fournis en réponse dans un objet au format JSON.&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,&lt;br /&gt;
  &amp;quot;expires_in&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;access_token&amp;quot;: &amp;quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw&amp;quot;,&lt;br /&gt;
  &amp;quot;refresh_token&amp;quot;: &amp;quot;a59ef39fa9bab9b95cd554f921e7f3080a34c90f23d2b8031d692b5ff2d0993dcc392d9c7f9a43242337ef144c1a5fe1d0174413ade973e1b628ac0bbfc39b23973534&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Script client : Authorization Code===&lt;br /&gt;
Voici un exemple simple de client OAuth2 pour le mécanisme d'authentification par code d'autorisation (Authorization Code).&lt;br /&gt;
&lt;br /&gt;
Fichier de configuration ''config.authcode.json'' :&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;authorize_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/authorize.php&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;/path/to/client/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;/path/to/client/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;/path/to/client/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;/path/to/client/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;/path/to/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;/path/to/server/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
Où &amp;lt;code&amp;gt;/path/to/client/&amp;lt;/code&amp;gt; est le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
*Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/ssl/AuthCodeDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
*Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./ssl/AuthCodeDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ce fichier de configuration doit se situer au même niveau que le script PHP dans le système de fichiers.&lt;br /&gt;
&lt;br /&gt;
Script PHP :&lt;br /&gt;
&amp;lt;php&amp;gt;&amp;lt;?php&lt;br /&gt;
$localTokenFile    = 'token.json';&lt;br /&gt;
// create token file if it does not exist&lt;br /&gt;
if (!file_exists($localTokenFile))&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
$config                 = json_decode(file_get_contents('config.authcode.json'), true);&lt;br /&gt;
$localToken             = json_decode(file_get_contents($localTokenFile), true);&lt;br /&gt;
$GLOBALS['config']      = $config;&lt;br /&gt;
&lt;br /&gt;
// Build the baseURL, accounting for protocol, port, name and endpoint. Used for redirection&lt;br /&gt;
$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';&lt;br /&gt;
$port     = ($protocol == 'https://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 443)&lt;br /&gt;
    || ($protocol == 'http://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 80) ? '' : ':' . $_SERVER['SERVER_PORT'];&lt;br /&gt;
&lt;br /&gt;
$baseURL            = $protocol . $_SERVER['SERVER_NAME'] . $port . $_SERVER['PHP_SELF'];&lt;br /&gt;
$errorLog           = 'error_log.log';&lt;br /&gt;
$responseLog        = 'response_log.log';&lt;br /&gt;
$GLOBALS['baseURL'] = $baseURL;&lt;br /&gt;
&lt;br /&gt;
//Session cookies are used to store information necessary for the authorization code flow&lt;br /&gt;
session_start();&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function is used to make api calls to the Authorization Server and the Resource Server&lt;br /&gt;
 *&lt;br /&gt;
 * @param       $url&lt;br /&gt;
 * @param       $post&lt;br /&gt;
 * @param array $headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return mixed&lt;br /&gt;
 */&lt;br /&gt;
function apiRequest($url, $post = null, $token = false, $auth = true, $refresh = false, $headers = array())&lt;br /&gt;
{&lt;br /&gt;
    $ch = curl_init($url);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HEADER, true);&lt;br /&gt;
&lt;br /&gt;
    $method = 'get';&lt;br /&gt;
&lt;br /&gt;
    if ($post) {&lt;br /&gt;
        $method   = 'post';&lt;br /&gt;
        $postData = http_build_query($post);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POST, true);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);&lt;br /&gt;
&lt;br /&gt;
        $headersToSign['Content-Type'] = 'application/x-www-form-urlencoded';&lt;br /&gt;
        $headersToSign['digest']       = 'SHA-256=' . base64_encode(hash('sha256', $postData, true));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $urlComponents = parse_url($url);&lt;br /&gt;
&lt;br /&gt;
    $headersToSign['(request-target)'] = $method . ' ' . $urlComponents['path'];&lt;br /&gt;
    $headersToSign['Host']             = $urlComponents['host'];&lt;br /&gt;
    $headersToSign['Date']             = gmdate('D, j M Y H:i:s T');&lt;br /&gt;
&lt;br /&gt;
    // generating the signature header&lt;br /&gt;
    $keyId                = openssl_x509_fingerprint(file_get_contents($GLOBALS['config']['sign_cert']));&lt;br /&gt;
    $privateKey           = file_get_contents($GLOBALS['config']['sign_key']);&lt;br /&gt;
    $headers['Signature'] = generateSignatureHeader($headersToSign, $keyId, $privateKey);&lt;br /&gt;
&lt;br /&gt;
    $headers['Accept']     = 'application/json';&lt;br /&gt;
    $headers['User-Agent'] = $GLOBALS['baseURL'];&lt;br /&gt;
    unset($headersToSign['(request-target)']);&lt;br /&gt;
    $headers               += $headersToSign;&lt;br /&gt;
&lt;br /&gt;
    if ($token) {&lt;br /&gt;
        $headers['Authorization'] = $token['token_type'] . ' ' . $token['access_token'];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // formatting the headers&lt;br /&gt;
    $httpFormattedHeaders = [];&lt;br /&gt;
    foreach ($headers as $key =&amp;gt; $value) {&lt;br /&gt;
        $httpFormattedHeaders[] = trim($key) . ': ' . trim($value);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HTTPHEADER, $httpFormattedHeaders);&lt;br /&gt;
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);&lt;br /&gt;
&lt;br /&gt;
    // for development environment only&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_VERBOSE, true);&lt;br /&gt;
&lt;br /&gt;
    // defining TLS client certificates for Mutual TLS&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_CAINFO, $GLOBALS['config']['auth_cacert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLCERT, $GLOBALS['config']['auth_cert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLKEY, $GLOBALS['config']['auth_key']);&lt;br /&gt;
&lt;br /&gt;
    $response = curl_exec($ch);&lt;br /&gt;
&lt;br /&gt;
    // logging errors and responses&lt;br /&gt;
    errorLog(true, $response, $ch);&lt;br /&gt;
&lt;br /&gt;
    curl_close($ch);&lt;br /&gt;
&lt;br /&gt;
    // in case an authentication request is executed&lt;br /&gt;
    if ($auth) {&lt;br /&gt;
        // required when a refresh token request is issued&lt;br /&gt;
        // because there is only one header in the response&lt;br /&gt;
        // while there are two for regular auth requests&lt;br /&gt;
        if (!$refresh) {&lt;br /&gt;
            list($firstResponseHeaders, $secondResponseHeaders, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 3);&lt;br /&gt;
            if (!$responseBody) {&lt;br /&gt;
                list($secondResponseHeaders, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 2);&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            list($secondResponseHeaders, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 2);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $responseHeadersDigest = '';&lt;br /&gt;
        $responseHeadersSignature = '';&lt;br /&gt;
        // extracting digest and signature from headers&lt;br /&gt;
        $responseHeadersArray = explode(&amp;quot;\r\n&amp;quot;, $secondResponseHeaders);&lt;br /&gt;
        $responseProtocol = array_shift($responseHeadersArray);&lt;br /&gt;
&lt;br /&gt;
        foreach ($responseHeadersArray as $value) {&lt;br /&gt;
            list($responseHeadersKeys, $responseHeadersValue) = explode(&amp;quot;: &amp;quot;, $value, 2);&lt;br /&gt;
            $responseHeaders[strtolower($responseHeadersKeys)] = $responseHeadersValue;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $responseDigestAlgo = '';&lt;br /&gt;
        $responseDigestKey = '';&lt;br /&gt;
        foreach ($responseHeaders as $key =&amp;gt; $value) {&lt;br /&gt;
            if ($key === &amp;quot;digest&amp;quot;) {&lt;br /&gt;
                $responseHeadersDigest = $value;&lt;br /&gt;
                // stripping SHA algorithm for later comparison&lt;br /&gt;
                list($responseDigestAlgo, $responseDigestKey) = explode(&amp;quot;=&amp;quot;, $responseHeadersDigest, 2);&lt;br /&gt;
            } else if ($key === &amp;quot;signature&amp;quot;)&lt;br /&gt;
                $responseHeadersSignature = $value;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // calculating response digest&lt;br /&gt;
        $responseDigest = base64_encode(hash(strtolower(str_replace(&amp;quot;-&amp;quot;, &amp;quot;&amp;quot;, $responseDigestAlgo)), $responseBody, true));&lt;br /&gt;
&lt;br /&gt;
        // checking digest validity&lt;br /&gt;
        if ($responseDigest !== $responseDigestKey) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Digests are not the same&amp;quot;);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // extracting variables from signature header&lt;br /&gt;
        $signatureArray = explode(&amp;quot;,&amp;quot;, $responseHeadersSignature);&lt;br /&gt;
        foreach ($signatureArray as $value) {&lt;br /&gt;
            list($signatureKey, $signatureValue) = explode(&amp;quot;=&amp;quot;, $value, 2);&lt;br /&gt;
            $signature[$signatureKey] = trim($signatureValue, '&amp;quot;');&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generating siging string&lt;br /&gt;
        $signingStringArray = explode(&amp;quot; &amp;quot;, $signature['headers']);&lt;br /&gt;
        $signingString = '';&lt;br /&gt;
        foreach ($signingStringArray as $value) {&lt;br /&gt;
            $signingString = $signingString . trim($value) . &amp;quot;: &amp;quot; . trim($responseHeaders[$value]) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // trimming last '\n' character&lt;br /&gt;
        $signingString = trim($signingString);&lt;br /&gt;
&lt;br /&gt;
        // decoding signature&lt;br /&gt;
        $decodedSignature = base64_decode($signature['signature']);&lt;br /&gt;
&lt;br /&gt;
        // verifying signature&lt;br /&gt;
        $signatureVerify = openssl_verify($signingString, $decodedSignature, openssl_get_publickey(file_get_contents($GLOBALS['config']['sign_cert_server'])), 'RSA-SHA256');&lt;br /&gt;
&lt;br /&gt;
        if (!$signatureVerify) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Signature is not correct&amp;quot;);&lt;br /&gt;
            while (($err = openssl_error_string()))&lt;br /&gt;
                errorLog(false, false, $err);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return json_decode($responseBody, true);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $response;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function logs curl responses and errors in text files&lt;br /&gt;
 *&lt;br /&gt;
 * @param mixed $response the response&lt;br /&gt;
 * @param mixed $request  the request handle, used to get errors&lt;br /&gt;
 */&lt;br /&gt;
function errorLog($curl, $response, $request = false)&lt;br /&gt;
{&lt;br /&gt;
    $timestamp = '[' . date('Y-m-d H:i:s') . ']:';&lt;br /&gt;
    global $errorLog;&lt;br /&gt;
    global $responseLog;&lt;br /&gt;
&lt;br /&gt;
    if ($response === false) {&lt;br /&gt;
        if ($curl)&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . curl_error($request) . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
        else&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . $request . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    } else {&lt;br /&gt;
        file_put_contents($responseLog, $timestamp . &amp;quot;\n&amp;quot; . $response . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function generates the full signature header line from a set of headers, a certificate and the linked private key&lt;br /&gt;
 *&lt;br /&gt;
 * @param array  $headersToSign the headers to sign, in the $key =&amp;gt; $value format&lt;br /&gt;
 * @param string $certificate   the certificate linked to the used private key&lt;br /&gt;
 * @param string $privateKey    the private key used to sign the headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the full signature header line&lt;br /&gt;
 */&lt;br /&gt;
function generateSignatureHeader(array $headersToSign, string $certificate, string $privateKey): string&lt;br /&gt;
{&lt;br /&gt;
    // generating the signing string and header list&lt;br /&gt;
    $headers         = '';&lt;br /&gt;
    $signatureString = '';&lt;br /&gt;
    foreach ($headersToSign as $key =&amp;gt; $value) {&lt;br /&gt;
        $normalizedHeaderKey = trim(strtolower($key));&lt;br /&gt;
        $headers             .= $normalizedHeaderKey . ' ';&lt;br /&gt;
        $signatureString     .= $normalizedHeaderKey . ': ' . trim($value) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    $headers         = trim($headers);&lt;br /&gt;
    $signatureString = trim($signatureString);&lt;br /&gt;
&lt;br /&gt;
    // signing the signing string&lt;br /&gt;
    $signature = '';&lt;br /&gt;
    openssl_sign($signatureString, $signature, openssl_get_privatekey($privateKey), 'RSA-SHA256');&lt;br /&gt;
    $signature = base64_encode($signature);&lt;br /&gt;
&lt;br /&gt;
    // compiling the header line&lt;br /&gt;
    return &amp;quot;keyId=\&amp;quot;$certificate\&amp;quot;,algorithm=\&amp;quot;rsa-sha256\&amp;quot;,headers=\&amp;quot;$headers\&amp;quot;,signature=\&amp;quot;$signature\&amp;quot;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function takes a code_verifier and outputs the corresponding code_challenge&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $codeVerifier the generated code_verifier&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the computed code_challenge&lt;br /&gt;
 */&lt;br /&gt;
function computeCodeChallenge(string $codeVerifier): string&lt;br /&gt;
{&lt;br /&gt;
    return strtr(rtrim(base64_encode(hash('sha256', $codeVerifier, true)), '='), '+/', '-_');&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function takes an optional string length and outputs a random code_verifier string&lt;br /&gt;
 *&lt;br /&gt;
 * @param int $length the length of the output code_verifier. Default = 128&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the code_verifier&lt;br /&gt;
 * @throws Exception&lt;br /&gt;
 */&lt;br /&gt;
function generateCodeVerifier($length = 128): string&lt;br /&gt;
{&lt;br /&gt;
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~';&lt;br /&gt;
    $outputCode = '';&lt;br /&gt;
&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $length; $i++) {&lt;br /&gt;
        $index      = random_int(0, strlen($characters) - 1);&lt;br /&gt;
        $outputCode .= $characters[$index];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $outputCode;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function calculates the entropy of a given string&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $string  the string for which to calculate the entropy&lt;br /&gt;
 * @param string $charset a string with all the usable characters. Default = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~&lt;br /&gt;
 *&lt;br /&gt;
 * @return float|int&lt;br /&gt;
 */&lt;br /&gt;
function computeEntropy(string $string, string $charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~')&lt;br /&gt;
{&lt;br /&gt;
    $chars = str_split($charset);&lt;br /&gt;
    $probs = [];&lt;br /&gt;
&lt;br /&gt;
    foreach ($chars as $char) {&lt;br /&gt;
        $probs[$char] = floatval(substr_count($string, $char)) / strlen($string);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $sum = 0.0;&lt;br /&gt;
    foreach ($probs as $prob) {&lt;br /&gt;
        $sum += $prob != 0 ? $prob * log($prob, 2) : 0.0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return -$sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function calculates the ideal (maximum) entropy for a string of a given length&lt;br /&gt;
 *&lt;br /&gt;
 * @param int $length length of the string. Default = 128&lt;br /&gt;
 *&lt;br /&gt;
 * @return float|int&lt;br /&gt;
 */&lt;br /&gt;
function idealEntropy(int $length = 128)&lt;br /&gt;
{&lt;br /&gt;
    $prob = 1.0 / $length;&lt;br /&gt;
&lt;br /&gt;
    return -1.0 * $length * $prob * log($prob, 2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function is used to initiate the authentication code flow.&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $clientID     the client's ID&lt;br /&gt;
 * @param string $redirectURL  the URL where to redirect after auth&lt;br /&gt;
 * @param string $authorizeURL the target URL to request authorization&lt;br /&gt;
 *&lt;br /&gt;
 * @throws Exception&lt;br /&gt;
 */&lt;br /&gt;
function login(string $clientID, string $redirectURL, string $authorizeURL): void&lt;br /&gt;
{&lt;br /&gt;
    global $localTokenFile;&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
    // This unguessable string is used to prevent csrf attacks&lt;br /&gt;
    $_SESSION['state'] = bin2hex(random_bytes(16));&lt;br /&gt;
&lt;br /&gt;
    // Generate code_verifier and code_challenge for PKCE    &lt;br /&gt;
    $_SESSION['code_verifier']  = generateCodeVerifier();&lt;br /&gt;
    $_SESSION['code_challenge'] = computeCodeChallenge($_SESSION['code_verifier']);&lt;br /&gt;
&lt;br /&gt;
    // required parameters for the redirection, redirect_uri is where the browser should be redirected&lt;br /&gt;
    // when the user grants (or denies) access, scope are the authorizations (rights) requested&lt;br /&gt;
    $params = [&lt;br /&gt;
        'response_type'         =&amp;gt; 'code',&lt;br /&gt;
        'client_id'             =&amp;gt; $clientID,&lt;br /&gt;
        'redirect_uri'          =&amp;gt; $redirectURL,&lt;br /&gt;
        'scope'                 =&amp;gt; 'default.login',&lt;br /&gt;
        'state'                 =&amp;gt; $_SESSION['state'],&lt;br /&gt;
        'code_challenge'        =&amp;gt; $_SESSION['code_challenge'],&lt;br /&gt;
        'code_challenge_method' =&amp;gt; 'S256'&lt;br /&gt;
    ];&lt;br /&gt;
&lt;br /&gt;
    // redirecting the browser to the AS authorization endpoint to obtain the authorization code&lt;br /&gt;
    header('Location: ' . $authorizeURL . '?' . http_build_query($params));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function deletes the access token from the session&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $baseURL&lt;br /&gt;
 */&lt;br /&gt;
function logout(string $baseURL): void&lt;br /&gt;
{&lt;br /&gt;
    global $localTokenFile;&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
    header('Location: ' . $baseURL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedIn(): void&lt;br /&gt;
{&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Logged In&amp;lt;/h3&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;view_repos&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;view&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'view_repos\').submit(); return false;&amp;quot;&amp;gt;View Repos&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;logout&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;logout&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'logout\').submit(); return false;&amp;quot;&amp;gt;Log Out&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedOut(): void&lt;br /&gt;
{&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Not logged in&amp;lt;/h3&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;login&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;login&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'login\').submit(); return false;&amp;quot;&amp;gt;Log In&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// display client &amp;quot;home&amp;quot; page&lt;br /&gt;
if (!isset($_POST['action'])) {&lt;br /&gt;
    if (!empty($localToken['access_token'])) {&lt;br /&gt;
        displayMenuLoggedIn();&lt;br /&gt;
    } else {&lt;br /&gt;
        displayMenuLoggedOut();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if (isset($_POST['action'])) {&lt;br /&gt;
    // Building query array for resource dumping&lt;br /&gt;
    $repoQueryParameters = [&lt;br /&gt;
        'resource_type' =&amp;gt; 'user_information',&lt;br /&gt;
        'client_id' =&amp;gt; $config['client_id']&lt;br /&gt;
    ];&lt;br /&gt;
    switch ($_POST['action']) {&lt;br /&gt;
        case 'login':&lt;br /&gt;
            login($config['client_id'], $baseURL, $config['authorize_uri']);&lt;br /&gt;
            break;&lt;br /&gt;
        case 'logout':&lt;br /&gt;
            logout($baseURL);&lt;br /&gt;
            break;&lt;br /&gt;
        case 'view':&lt;br /&gt;
            // call to the resource server to retreive user information&lt;br /&gt;
            $resources = apiRequest(&lt;br /&gt;
                $config['resource_uri'],&lt;br /&gt;
                $repoQueryParameters,&lt;br /&gt;
                $localToken,&lt;br /&gt;
                false&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            // Separating headers from body&lt;br /&gt;
            list($resourceHeader, $resourceBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $resources, 2);&lt;br /&gt;
&lt;br /&gt;
            $resourceHeaders = explode(&amp;quot;\r\n&amp;quot;, $resourceHeader);&lt;br /&gt;
            $firstHeaderLine = array_shift($resourceHeaders);&lt;br /&gt;
&lt;br /&gt;
            // Displaying user information&lt;br /&gt;
            echo '&amp;lt;pre&amp;gt;';&lt;br /&gt;
            echo $resourceBody;&lt;br /&gt;
            echo '&amp;lt;/pre&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
            // Automatic refreshing token once access token is expired&lt;br /&gt;
            if (strpos($firstHeaderLine, &amp;quot;401&amp;quot;)) {&lt;br /&gt;
                $errorBody = json_decode($resourceBody, true);&lt;br /&gt;
                if ($errorBody['error'] == 'access_denied' &amp;amp;&amp;amp; isset($errorBody['hint'])) {&lt;br /&gt;
                    if ($errorBody['hint'] == 'Access token could not be verified') {&lt;br /&gt;
                        $token = apiRequest(&lt;br /&gt;
                            $config['token_uri'],&lt;br /&gt;
                            [&lt;br /&gt;
                                'grant_type'    =&amp;gt; 'refresh_token',&lt;br /&gt;
                                'refresh_token' =&amp;gt; $localToken['refresh_token'],&lt;br /&gt;
                                'client_id'     =&amp;gt; $config['client_id'],&lt;br /&gt;
                                'client_secret' =&amp;gt; empty($config['client_secret']) ? null : $config['client_secret']&lt;br /&gt;
                            ],&lt;br /&gt;
                            false,&lt;br /&gt;
                            true,&lt;br /&gt;
                            true&lt;br /&gt;
                        );&lt;br /&gt;
&lt;br /&gt;
                        // We store the access token in the session so the user is &amp;quot;connected&amp;quot;&lt;br /&gt;
                        // Only if the request has been successfully executed&lt;br /&gt;
                        if (isset($token['access_token'])) {&lt;br /&gt;
                            file_put_contents($localTokenFile, json_encode($token, true));&lt;br /&gt;
&lt;br /&gt;
                            // Redirecting the user's browser to the &amp;quot;home&amp;quot; page&lt;br /&gt;
                            header('Location: ' . $baseURL);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Once the browser has been redirected to the AS to ask for the user's authorization, assuming it has been granted,&lt;br /&gt;
// the browser will get back here with a &amp;quot;code&amp;quot; parameter in the query string&lt;br /&gt;
if (isset($_GET['code'])) {&lt;br /&gt;
    // The AS MUST redirect the browser here with the exact same state parameter we sent it before, so we check if it is indeed the same&lt;br /&gt;
    // to detect if the oauth flow has been tampered with&lt;br /&gt;
    if (!isset($_GET['state']) || $_SESSION['state'] != $_GET['state']) {&lt;br /&gt;
        header('Location: ' . $baseURL . '?error=invalid_state');&lt;br /&gt;
        die();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // We communicate directly with the AS to exchange the code received against an access token.&lt;br /&gt;
    // The id/secret pair is send to authenticate the client, the redirect_uri is sent to verify the code's validity&lt;br /&gt;
    $token = apiRequest(&lt;br /&gt;
        $config['token_uri'],&lt;br /&gt;
        [&lt;br /&gt;
            'grant_type'    =&amp;gt; 'authorization_code',&lt;br /&gt;
            'client_id'     =&amp;gt; $config['client_id'],&lt;br /&gt;
            'client_secret' =&amp;gt; empty($config['client_secret']) ? null : $config['client_secret'],&lt;br /&gt;
            'redirect_uri'  =&amp;gt; $baseURL,&lt;br /&gt;
            'code'          =&amp;gt; $_GET['code'],&lt;br /&gt;
            'code_verifier' =&amp;gt; $_SESSION['code_verifier']&lt;br /&gt;
        ]&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    // We store the access token in the session so the user is &amp;quot;connected&amp;quot;&lt;br /&gt;
    // Only if the request has been successfully executed&lt;br /&gt;
    if (isset($token['access_token'])) {&lt;br /&gt;
        file_put_contents($localTokenFile, json_encode($token, true));&lt;br /&gt;
&lt;br /&gt;
        // Redirecting the user's browser to the &amp;quot;home&amp;quot; page&lt;br /&gt;
        header('Location: ' . $baseURL);&lt;br /&gt;
    } else {&lt;br /&gt;
        echo $token;&lt;br /&gt;
    }&lt;br /&gt;
    die();&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Ce script a été conçu pour montrer le fonctionnement du mécanisme afin de tester l'implémentation d'un serveur et n'a pas été testé extensivement. Il est conseillé d'utiliser une solution adaptée à un environnement de production.&lt;br /&gt;
&lt;br /&gt;
==Client Credentials==&lt;br /&gt;
Ce mécanisme d'autorisation est adapté pour l'automatisation. Il fonctionne de la manière suivante :&lt;br /&gt;
*Le client effectue la demande de jeton d'accès au serveur d'autorisation en fournissant ses identifiants.&lt;br /&gt;
*Le serveur authentifie le client avec les identifiants fournis et renvoie un jeton d'accès.&lt;br /&gt;
*Le client utilise ce jeton d'accès pour accéder à des données via l'API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    +------+                       +-------------+                  +-----------+&lt;br /&gt;
    |Client|                       |   Serveur   |                  |  Serveur  |&lt;br /&gt;
    +--+---+                       |Autorisation |                  | Ressources|&lt;br /&gt;
       |                           +------+------+                  +-----+-----+&lt;br /&gt;
       |        Authentification          |                               |&lt;br /&gt;
       |         + Demande token          |                               |&lt;br /&gt;
       +---------------------------------&amp;gt;|                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |          Access token            |                               |&lt;br /&gt;
       |&amp;lt;---------------------------------+                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                      Requête vers|API                            |&lt;br /&gt;
       +----------------------------------+------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |&amp;lt;------------------------------+&lt;br /&gt;
       |                                  |  Vérification d'autorisation  |&lt;br /&gt;
       |                                  +------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                         Données /|Réponse                        |&lt;br /&gt;
       |&amp;lt;---------------------------------+-------------------------------+&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Demande de jeton d'accès===&lt;br /&gt;
Pour obtenir un jeton d'accès, il faut effectuer la requête suivante : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Les paramètres suivants sont nécessaires :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|client_secret||string||La passphrase reçue pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|grant_type||string||Le mécanisme d'autorisation utilisé. Ici, la valeur doit être ''client_credentials''.&lt;br /&gt;
|-&lt;br /&gt;
|scope||string||[[#Liste-des-scopes-disponibles|Liste des droits demandés par le client]], séparé par des espaces.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
;Ce mécanisme a la particularité de ne pas nécessiter d'URI de redirection, il n'est donc pas utile d'en renseigner un lors de l'enregistrement d'un client.&lt;br /&gt;
&lt;br /&gt;
Si la requête est correcte, un jeton d'accès (Access Token) est fourni en réponse dans un objet au format JSON.&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,&lt;br /&gt;
  &amp;quot;expires_in&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;access_token&amp;quot;: &amp;quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Script client : Client Credentials===&lt;br /&gt;
Voici un exemple simple d'un client OAuth2 pour le mécanisme d'authentification par les identifiants client (Client Credentials).&lt;br /&gt;
&lt;br /&gt;
Fichier de configuration ''config.clientcred.json'' :&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;/path/to/client/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;/path/to/client/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;/path/to/client/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;/path/to/client/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;/path/to/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;/path/to/server/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
Où &amp;lt;code&amp;gt;/path/to/client/&amp;lt;/code&amp;gt; est le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
*Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/ssl/ClientCredDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
*Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./ssl/ClientCredDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ce fichier de configuration doit se situer au même niveau que le script PHP dans le système de fichiers.&lt;br /&gt;
&lt;br /&gt;
Script php :&lt;br /&gt;
&amp;lt;php&amp;gt;&amp;lt;?php&lt;br /&gt;
$localTokenFile    = 'token.json';&lt;br /&gt;
// create token file if it does not exist&lt;br /&gt;
if (!file_exists($localTokenFile))&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
$config                 = json_decode(file_get_contents('config.clientcred.json'), true);&lt;br /&gt;
$localToken             = json_decode(file_get_contents($localTokenFile), true);&lt;br /&gt;
$GLOBALS['config']      = $config;&lt;br /&gt;
&lt;br /&gt;
// Build the baseURL, accounting for protocol, port, name and endpoint. Used for redirection&lt;br /&gt;
$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';&lt;br /&gt;
$port     = ($protocol == 'https://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 443)&lt;br /&gt;
    || ($protocol == 'http://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 80) ? '' : ':' . $_SERVER['SERVER_PORT'];&lt;br /&gt;
&lt;br /&gt;
$baseURL            = $protocol . $_SERVER['SERVER_NAME'] . $port . $_SERVER['PHP_SELF'];&lt;br /&gt;
$errorLog           = 'error_log.log';&lt;br /&gt;
$responseLog        = 'response_log.log';&lt;br /&gt;
$GLOBALS['baseURL'] = $baseURL;&lt;br /&gt;
&lt;br /&gt;
$replacementListItems = [&lt;br /&gt;
    1 =&amp;gt; &amp;quot;year&amp;quot;,&lt;br /&gt;
    2 =&amp;gt; &amp;quot;validityTypeId&amp;quot;,&lt;br /&gt;
    3 =&amp;gt; &amp;quot;icao&amp;quot;,&lt;br /&gt;
    4 =&amp;gt; &amp;quot;profileId&amp;quot;,&lt;br /&gt;
    7 =&amp;gt; &amp;quot;accountingId&amp;quot;,&lt;br /&gt;
    8 =&amp;gt; &amp;quot;paymentType&amp;quot;,&lt;br /&gt;
    9 =&amp;gt; &amp;quot;startDate&amp;quot;,&lt;br /&gt;
    10 =&amp;gt; &amp;quot;endDate&amp;quot;,&lt;br /&gt;
    11 =&amp;gt; &amp;quot;occupiedSeat&amp;quot;,&lt;br /&gt;
    12 =&amp;gt; &amp;quot;date&amp;quot;,&lt;br /&gt;
    13 =&amp;gt; &amp;quot;activityTypeId&amp;quot;,&lt;br /&gt;
    14 =&amp;gt; &amp;quot;age&amp;quot;,&lt;br /&gt;
    15 =&amp;gt; &amp;quot;resourceId&amp;quot;,&lt;br /&gt;
    16 =&amp;gt; &amp;quot;personId&amp;quot;,&lt;br /&gt;
    17 =&amp;gt; &amp;quot;accountId&amp;quot;,&lt;br /&gt;
    20 =&amp;gt; &amp;quot;rightPlacePersonId&amp;quot;,&lt;br /&gt;
    21 =&amp;gt; &amp;quot;month&amp;quot;,&lt;br /&gt;
    22 =&amp;gt; &amp;quot;numberMonth&amp;quot;,&lt;br /&gt;
    23 =&amp;gt; &amp;quot;oneValidityTypeId&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
&lt;br /&gt;
//Session cookies are used to store information necessary for the authorization code flow&lt;br /&gt;
session_start();&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function is used to make api calls to the RS&lt;br /&gt;
 *&lt;br /&gt;
 * @param       $url&lt;br /&gt;
 * @param       $post&lt;br /&gt;
 * @param array $headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return mixed&lt;br /&gt;
 */&lt;br /&gt;
function apiRequest($url, $post = null, $token = false, $auth = true, $headers = array())&lt;br /&gt;
{&lt;br /&gt;
    $ch = curl_init($url);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HEADER, true);&lt;br /&gt;
&lt;br /&gt;
    $method = 'get';&lt;br /&gt;
&lt;br /&gt;
    if ($post) {&lt;br /&gt;
        $method   = 'post';&lt;br /&gt;
        $postData = http_build_query($post);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POST, true);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);&lt;br /&gt;
&lt;br /&gt;
        $headersToSign['Content-Type'] = 'application/x-www-form-urlencoded';&lt;br /&gt;
        $headersToSign['digest']       = 'SHA-256=' . base64_encode(hash('sha256', $postData, true));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $urlComponents = parse_url($url);&lt;br /&gt;
&lt;br /&gt;
    $headersToSign['(request-target)'] = $method . ' ' . $urlComponents['path'];&lt;br /&gt;
    $headersToSign['Host']             = $urlComponents['host'];&lt;br /&gt;
    $headersToSign['Date']             = gmdate('D, j M Y H:i:s T');&lt;br /&gt;
&lt;br /&gt;
    // generating the signature header&lt;br /&gt;
    $keyId                = openssl_x509_fingerprint(file_get_contents($GLOBALS['config']['sign_cert']));&lt;br /&gt;
    $privateKey           = file_get_contents($GLOBALS['config']['sign_key']);&lt;br /&gt;
    $headers['Signature'] = generateSignatureHeader($headersToSign, $keyId, $privateKey);&lt;br /&gt;
&lt;br /&gt;
    $headers['Accept']     = 'application/json';&lt;br /&gt;
    $headers['User-Agent'] = $GLOBALS['baseURL'];&lt;br /&gt;
    unset($headersToSign['(request-target)']);&lt;br /&gt;
    $headers               += $headersToSign;&lt;br /&gt;
&lt;br /&gt;
    if ($token) {&lt;br /&gt;
        $headers['Authorization'] = $token['token_type'] . ' ' . $token['access_token'];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // formatting the headers&lt;br /&gt;
    $httpFormattedHeaders = [];&lt;br /&gt;
    foreach ($headers as $key =&amp;gt; $value) {&lt;br /&gt;
        $httpFormattedHeaders[] = trim($key) . ': ' . trim($value);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HTTPHEADER, $httpFormattedHeaders);&lt;br /&gt;
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);&lt;br /&gt;
&lt;br /&gt;
    // for development environment only&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_VERBOSE, true);&lt;br /&gt;
&lt;br /&gt;
    // defining TLS client certificates for Mutual TLS&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_CAINFO, $GLOBALS['config']['auth_cacert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLCERT, $GLOBALS['config']['auth_cert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLKEY, $GLOBALS['config']['auth_key']);&lt;br /&gt;
&lt;br /&gt;
    $response = curl_exec($ch);&lt;br /&gt;
&lt;br /&gt;
    // logging errors and responses&lt;br /&gt;
    errorLog(true, $response, $ch);&lt;br /&gt;
&lt;br /&gt;
    curl_close($ch);&lt;br /&gt;
&lt;br /&gt;
    // in case an authentication request is executed&lt;br /&gt;
    if ($auth) {&lt;br /&gt;
        list($responseHeader, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 2);&lt;br /&gt;
&lt;br /&gt;
        $responseHeadersDigest = '';&lt;br /&gt;
        $responseHeadersSignature = '';&lt;br /&gt;
        // extracting digest and signature from headers&lt;br /&gt;
        $responseHeadersArray = explode(&amp;quot;\r\n&amp;quot;, $responseHeader);&lt;br /&gt;
        $responseProtocol = array_shift($responseHeadersArray);&lt;br /&gt;
&lt;br /&gt;
        foreach ($responseHeadersArray as $value) {&lt;br /&gt;
            list($responseHeadersKeys, $responseHeadersValue) = explode(&amp;quot;: &amp;quot;, $value, 2);&lt;br /&gt;
            $responseHeaders[strtolower($responseHeadersKeys)] = $responseHeadersValue;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $responseDigestAlgo = '';&lt;br /&gt;
        $responseDigestKey = '';&lt;br /&gt;
        foreach ($responseHeaders as $key =&amp;gt; $value) {&lt;br /&gt;
            if ($key === &amp;quot;digest&amp;quot;) {&lt;br /&gt;
                $responseHeadersDigest = $value;&lt;br /&gt;
                // stripping SHA algorithm for later comparison&lt;br /&gt;
                list($responseDigestAlgo, $responseDigestKey) = explode(&amp;quot;=&amp;quot;, $responseHeadersDigest, 2);&lt;br /&gt;
            } else if ($key === &amp;quot;signature&amp;quot;)&lt;br /&gt;
                $responseHeadersSignature = $value;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // calculating response digest&lt;br /&gt;
        $responseDigest = base64_encode(hash(strtolower(str_replace(&amp;quot;-&amp;quot;, &amp;quot;&amp;quot;, $responseDigestAlgo)), $responseBody, true));&lt;br /&gt;
&lt;br /&gt;
        // checking digest validity&lt;br /&gt;
        if ($responseDigest !== $responseDigestKey) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Digests are not the same&amp;quot;);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // extracting variables from signature header&lt;br /&gt;
        $signatureArray = explode(&amp;quot;,&amp;quot;, $responseHeadersSignature);&lt;br /&gt;
        foreach ($signatureArray as $value) {&lt;br /&gt;
            list($signatureKey, $signatureValue) = explode(&amp;quot;=&amp;quot;, $value, 2);&lt;br /&gt;
            $signature[$signatureKey] = trim($signatureValue, '&amp;quot;');&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generating siging string&lt;br /&gt;
        $signingStringArray = explode(&amp;quot; &amp;quot;, $signature['headers']);&lt;br /&gt;
        $signingString = '';&lt;br /&gt;
        foreach ($signingStringArray as $value) {&lt;br /&gt;
            $signingString = $signingString . trim($value) . &amp;quot;: &amp;quot; . trim($responseHeaders[$value]) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // trimming last '\n' character&lt;br /&gt;
        $signingString = trim($signingString);&lt;br /&gt;
&lt;br /&gt;
        // decoding signature&lt;br /&gt;
        $decodedSignature = base64_decode($signature['signature']);&lt;br /&gt;
&lt;br /&gt;
        // verifying signature&lt;br /&gt;
        $signatureVerify = openssl_verify($signingString, $decodedSignature, openssl_get_publickey(file_get_contents($GLOBALS['config']['sign_cert_server'])), 'RSA-SHA256');&lt;br /&gt;
&lt;br /&gt;
        if (!$signatureVerify) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Signature is not correct&amp;quot;);&lt;br /&gt;
            while (($err = openssl_error_string()))&lt;br /&gt;
                errorLog(false, false, $err);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return json_decode($responseBody, true);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $response;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function logs curl responses and errors in text files&lt;br /&gt;
 *&lt;br /&gt;
 * @param mixed $response the response&lt;br /&gt;
 * @param mixed $request  the request handle, used to get errors&lt;br /&gt;
 */&lt;br /&gt;
function errorLog($curl, $response, $request = false)&lt;br /&gt;
{&lt;br /&gt;
    $timestamp = '[' . date('Y-m-d H:i:s') . ']:';&lt;br /&gt;
    global $errorLog;&lt;br /&gt;
    global $responseLog;&lt;br /&gt;
&lt;br /&gt;
    if ($response === false) {&lt;br /&gt;
        if ($curl)&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . curl_error($request) . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
        else&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . $request . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    } else {&lt;br /&gt;
        file_put_contents($responseLog, $timestamp . &amp;quot;\n&amp;quot; . $response . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function generates the full signature header line from a set of headers, a certificate and the linked private key&lt;br /&gt;
 *&lt;br /&gt;
 * @param array  $headersToSign the headers to sign, in the $key =&amp;gt; $value format&lt;br /&gt;
 * @param string $certificate   the certificate linked to the used private key&lt;br /&gt;
 * @param string $privateKey    the private key used to sign the headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the full signature header line&lt;br /&gt;
 */&lt;br /&gt;
function generateSignatureHeader(array $headersToSign, string $certificate, string $privateKey): string&lt;br /&gt;
{&lt;br /&gt;
    // generating the signing string and header list&lt;br /&gt;
    $headers         = '';&lt;br /&gt;
    $signatureString = '';&lt;br /&gt;
    foreach ($headersToSign as $key =&amp;gt; $value) {&lt;br /&gt;
        $normalizedHeaderKey = trim(strtolower($key));&lt;br /&gt;
        $headers             .= $normalizedHeaderKey . ' ';&lt;br /&gt;
        $signatureString     .= $normalizedHeaderKey . ': ' . trim($value) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    $headers         = trim($headers);&lt;br /&gt;
    $signatureString = trim($signatureString);&lt;br /&gt;
&lt;br /&gt;
    // signing the signing string&lt;br /&gt;
    $signature = '';&lt;br /&gt;
    openssl_sign($signatureString, $signature, openssl_get_privatekey($privateKey), 'RSA-SHA256');&lt;br /&gt;
    $signature = base64_encode($signature);&lt;br /&gt;
&lt;br /&gt;
    // compiling the header line&lt;br /&gt;
    return &amp;quot;keyId=\&amp;quot;$certificate\&amp;quot;,algorithm=\&amp;quot;rsa-sha256\&amp;quot;,headers=\&amp;quot;$headers\&amp;quot;,signature=\&amp;quot;$signature\&amp;quot;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function deletes the access token from the session&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $baseURL&lt;br /&gt;
 */&lt;br /&gt;
function logout(string $baseURL): void&lt;br /&gt;
{&lt;br /&gt;
    global $localTokenFile;&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
    header('Location: ' . $baseURL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedIn(): void&lt;br /&gt;
{&lt;br /&gt;
    global $replacementListItems;&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Logged In&amp;lt;/h3&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;view_repos&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;label for=&amp;quot;report_id&amp;quot;&amp;gt;Report ID: &amp;lt;/label&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;number&amp;quot; id=&amp;quot;report_id&amp;quot; name=&amp;quot;report_id&amp;quot;&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;';&lt;br /&gt;
    foreach ($replacementListItems as $value) {&lt;br /&gt;
        echo '&amp;lt;label for=&amp;quot;' . $value . '&amp;quot;&amp;gt;' . $value . ': &amp;lt;/label&amp;gt;';&lt;br /&gt;
        echo '&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;' . $value . '&amp;quot; name=&amp;quot;' . $value . '&amp;quot;&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;';&lt;br /&gt;
    }&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;view&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'view_repos\').submit(); return false;&amp;quot;&amp;gt;View Repos&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;logout&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;logout&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'logout\').submit(); return false;&amp;quot;&amp;gt;Log Out&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedOut(): void&lt;br /&gt;
{&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Not logged in&amp;lt;/h3&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;login&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;login&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'login\').submit(); return false;&amp;quot;&amp;gt;Log In&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// display client &amp;quot;home&amp;quot; page&lt;br /&gt;
if (!isset($_POST['action'])) {&lt;br /&gt;
    if (!empty($localToken['access_token'])) {&lt;br /&gt;
        displayMenuLoggedIn();&lt;br /&gt;
    } else {&lt;br /&gt;
        displayMenuLoggedOut();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if (isset($_POST['action'])) {&lt;br /&gt;
    $replacementList = [];&lt;br /&gt;
    // Building replacement list&lt;br /&gt;
    foreach ($replacementListItems as $key =&amp;gt; $value) {&lt;br /&gt;
        $replacementList[$value] = (isset($_POST[$value]) &amp;amp;&amp;amp; strlen($_POST[$value]) &amp;gt; 0) ? $_POST[$value] : null;&lt;br /&gt;
    }&lt;br /&gt;
    // Building query array&lt;br /&gt;
    $repoQueryParameters = [&lt;br /&gt;
        'resource_type' =&amp;gt; 'generic_report',&lt;br /&gt;
        'client_id' =&amp;gt; $config['client_id'],&lt;br /&gt;
        'report_id' =&amp;gt; (isset($_POST['report_id']) &amp;amp;&amp;amp; strlen($_POST['report_id']) &amp;gt; 0) ? $_POST['report_id'] : null,&lt;br /&gt;
        'replacementList' =&amp;gt; $replacementList&lt;br /&gt;
    ];&lt;br /&gt;
    switch ($_POST['action']) {&lt;br /&gt;
        case 'login':&lt;br /&gt;
            $token = apiRequest(&lt;br /&gt;
                $config['token_uri'],&lt;br /&gt;
                [&lt;br /&gt;
                    'grant_type'    =&amp;gt; 'client_credentials',&lt;br /&gt;
                    'client_id'     =&amp;gt; $config['client_id'],&lt;br /&gt;
                    'client_secret' =&amp;gt; empty($config['client_secret']) ? null : $config['client_secret'],&lt;br /&gt;
                    'scope'         =&amp;gt; 'genericreports.readonly reports.readonly'&lt;br /&gt;
                ]&lt;br /&gt;
            );&lt;br /&gt;
            // We store the access token in the session so the user is &amp;quot;connected&amp;quot;&lt;br /&gt;
            // Only if the request has been successfully executed&lt;br /&gt;
            if (isset($token['access_token'])) {&lt;br /&gt;
                file_put_contents($localTokenFile, json_encode($token, true));&lt;br /&gt;
&lt;br /&gt;
                // Redirecting the user's browser to the &amp;quot;home&amp;quot; page&lt;br /&gt;
                header('Location: ' . $baseURL);&lt;br /&gt;
            } else {&lt;br /&gt;
                echo $token;&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
        case 'logout':&lt;br /&gt;
            logout($baseURL);&lt;br /&gt;
            break;&lt;br /&gt;
        case 'view':&lt;br /&gt;
            // call to the resource server&lt;br /&gt;
            $resources = apiRequest(&lt;br /&gt;
                $config['resource_uri'],&lt;br /&gt;
                $repoQueryParameters,&lt;br /&gt;
                $localToken,&lt;br /&gt;
                false&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            // Separating headers from body&lt;br /&gt;
            list($resourceHeader, $resourceBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $resources, 2);&lt;br /&gt;
&lt;br /&gt;
            $resourceHeaders = explode(&amp;quot;\r\n&amp;quot;, $resourceHeader);&lt;br /&gt;
            $firstHeaderLine = array_shift($resourceHeaders);&lt;br /&gt;
&lt;br /&gt;
            // Building form for download CSV button&lt;br /&gt;
            echo '&amp;lt;form method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
            foreach ($_POST as $key =&amp;gt; $value) {&lt;br /&gt;
                if ($key == &amp;quot;action&amp;quot;) {&lt;br /&gt;
                    $value = &amp;quot;download&amp;quot;;&lt;br /&gt;
                }&lt;br /&gt;
                echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;' . $key . '&amp;quot; name=&amp;quot;' . $key . '&amp;quot; value=&amp;quot;' . $value . '&amp;quot;&amp;gt;';&lt;br /&gt;
            }&lt;br /&gt;
            if (isset($_POST['report_id']) &amp;amp;&amp;amp; strlen($_POST['report_id']) &amp;gt; 0 &amp;amp;&amp;amp; !isset(json_decode($resourceBody, true)['error'])) {&lt;br /&gt;
                echo '&amp;lt;button&amp;gt;Download as CSV&amp;lt;/button&amp;gt;';&lt;br /&gt;
            }&lt;br /&gt;
            echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
            // Displaying requested content&lt;br /&gt;
            echo '&amp;lt;pre&amp;gt;';&lt;br /&gt;
            echo (strpos($firstHeaderLine, &amp;quot;200&amp;quot;)) ? json_decode($resourceBody) : $resourceBody;&lt;br /&gt;
            echo '&amp;lt;/pre&amp;gt;';&lt;br /&gt;
            break;&lt;br /&gt;
        case 'download':&lt;br /&gt;
            // call to the resource server&lt;br /&gt;
            $resources = apiRequest(&lt;br /&gt;
                $config['resource_uri'],&lt;br /&gt;
                $repoQueryParameters,&lt;br /&gt;
                $localToken,&lt;br /&gt;
                false&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            // Separating headers from body&lt;br /&gt;
            list($resourceHeader, $resourceBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $resources, 2);&lt;br /&gt;
            $resourceHeaders = explode(&amp;quot;\r\n&amp;quot;, $resourceHeader);&lt;br /&gt;
            array_shift($resourceHeaders);&lt;br /&gt;
&lt;br /&gt;
            // Dumping headers to insert them in current page&lt;br /&gt;
            foreach ($resourceHeaders as $key =&amp;gt; $value) {&lt;br /&gt;
                header($value);&lt;br /&gt;
            }&lt;br /&gt;
            echo json_decode($resourceBody);&lt;br /&gt;
            break;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Ce script a été conçu pour montrer le fonctionnement du mécanisme et tester l'implémentation d'un serveur, il n'a pas été testé extensivement. Il est conseillé d'utiliser une solution adaptée à un environnement de production.&lt;br /&gt;
&lt;br /&gt;
==Refresh Token==&lt;br /&gt;
Refresh Token (ou jeton de rafraîchissement en français) est un mécanisme d'autorisation particulier. Il ne peut fonctionner en tant que tel, il fonctionne de pair avec [[#Authorization-Code|Authorization Code]]. Lorsqu'un jeton d'accès arrive est arrivé en fin de vie, si le client y est autorisé, il peut faire une demande de renouvellement de son jeton d'accès auprès du serveur d'autorisation en présentant son jeton de rafraîchissement. Le serveur d'autorisation vérifie la validité et génère un autre jeton d'accès qu'il transmet au client, sans que l'utilisateur final n'aît à se connecter de nouveau.&lt;br /&gt;
&lt;br /&gt;
Le principe de fonctionnement du rafraîchissement d'un jeton est le suivant :&lt;br /&gt;
* Le jeton d'accès du client est arrivé à péremption. Le client effectue une demande de renouvellement en transmettant son Refresh Token au serveur d'autorisation.&lt;br /&gt;
* Le serveur d'autorisation vérifie la validité des informations, &amp;quot;consomme&amp;quot; le jeton de rafraîchissement et génère une nouvelle paire de jetons&lt;br /&gt;
* Le client reçoit sa nouvelle paire et utilise le nouveau jeton d'accès pour accéder aux ressources&lt;br /&gt;
&lt;br /&gt;
    +------+                       +-------------+                  +-----------+&lt;br /&gt;
    |Client|                       |   Serveur   |                  |  Serveur  |&lt;br /&gt;
    +--+---+                       |Autorisation |                  | Ressources|&lt;br /&gt;
       |                           +------+------+                  +-----+-----+&lt;br /&gt;
       |        Authentification          |                               |&lt;br /&gt;
       |         + Refresh Token          |                               |&lt;br /&gt;
       +---------------------------------&amp;gt;|                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |    Access (+ Refresh) token      |                               |&lt;br /&gt;
       |&amp;lt;---------------------------------+                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                      Requête vers|API                            |&lt;br /&gt;
       +----------------------------------+------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |&amp;lt;------------------------------+&lt;br /&gt;
       |                                  |  Vérification d'autorisation  |&lt;br /&gt;
       |                                  +------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                         Données /|Réponse                        |&lt;br /&gt;
       |&amp;lt;---------------------------------+-------------------------------+&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
&lt;br /&gt;
===Demande de renouvellement d'un jeton===&lt;br /&gt;
Pour obtenir un renouvellement de jeton d'accès, il faut effectuer la requête suivante : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Les paramètres suivants sont nécessaires :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant ''client_id'' reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|client_secret||string||La passphrase ''client_secret'' reçue pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|grant_type||string||Le mécanisme d'autorisation utilisé. Ici, la valeur doit être &amp;quot;refresh_token&amp;quot; (sans guillements).&lt;br /&gt;
|-&lt;br /&gt;
|scope||string||('''OPTIONNEL''') Liste des droits demandés par le client, séparés par des espaces.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Si la requête est correcte, un jeton d'accès ''access_token'' est fourni en réponse dans un objet au format JSON.&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,&lt;br /&gt;
  &amp;quot;expires_in&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;access_token&amp;quot;: &amp;quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw&amp;quot;,&lt;br /&gt;
  &amp;quot;refresh_token&amp;quot;: &amp;quot;a59ef39fa9bab9b95cd554f921e7f3080a34c90f23d2b8031d692b5ff2d0993dcc392d9c7f9a43242337ef144c1a5fe1d0174413ade973e1b628ac0bbfc39b23973534&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Liste des scopes disponibles==&lt;br /&gt;
Un scope sur OAuth2 correspond à un droit d'accès sur une ressource particulière. Chaque scope est unique et indique de manière explicite le privilège qu'il donne. Il n'y a aucune restriction d'utilisation des scopes par rapport aux mécanismes. Chaque scope peut être utilisé avec n'importe quel mécanisme. Il n'y a que des recommandations vis à vis de leur utilisation. OpenFlyers définit une liste de scopes dédiée aux ressources accessibles par les clients. Ces scopes sont les suivants :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Description&lt;br /&gt;
|-&lt;br /&gt;
|default.login||Comportement par défaut lorsqu'aucun scope n'est précisé ou qu'un scope est invalide. Ce scope est recommandé pour '''Authorization Code'''.&lt;br /&gt;
|-&lt;br /&gt;
|genericreports.readonly||Accéder aux rapports génériques autorisés pour le client en lecture seule. Ce scope est recommandé pour '''Client Credentials'''.&lt;br /&gt;
|-&lt;br /&gt;
|reports.readonly||Accéder aux rapports personnalisés autorisés pour le client en lecture seule. Ce scope est recommandé pour '''Client Credentials'''.&lt;br /&gt;
|}&lt;br /&gt;
==Prolonger la durée de vie de la session du client de démonstration==&lt;br /&gt;
La session du client de démonstration est initiée avec la méthode PHP [https://www.php.net/manual/en/function.session-start.php session_start]. Cette session peut être interrompue soit en cliquant sur le bouton de déconnexion, soit en fermant le navigateur (car les cookies associés à cette session se détruisent par défaut lorsque le navigateur est fermé).&lt;br /&gt;
&lt;br /&gt;
Pour permettre à la session de rester active même après la fermeture du navigateur, il faut utiliser la méthode PHP [https://www.php.net/manual/en/function.session-set-cookie-params.php session_set_cookie_params]. Cette méthode donne la possibilité de définir une durée de vie pour les différents cookies associés à la session.&lt;br /&gt;
&amp;lt;php&amp;gt;// Set the parameters for the session cookie in a PHP session in order to configure its lifetime in 30 days&lt;br /&gt;
$oauth2DemoSessionLifeTime = time() + (86400 * 30);&lt;br /&gt;
session_set_cookie_params($oauth2DemoSessionLifeTime);&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NB: Cette approche n'est pas particulièrement sécurisée et peut présenter des risques de sécurité pour OpenFlyers. Par conséquent, elle doit être utilisée avec précaution.&lt;br /&gt;
&lt;br /&gt;
==Révocation de token==&lt;br /&gt;
Pour initier la demande de révocation, rediriger le navigateur de l'utilisateur vers l'URL : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/revoke.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Envoyer également le paramètre suivant:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|access_token||string||Le jeton d'accès (Chaîne de caractère unique permettant de prouver qu'un client OAuth a le droit d'accéder à une ressource.)&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;php&amp;gt; apiRequest(&lt;br /&gt;
                $config['revoke_uri'],&lt;br /&gt;
                ['access_token' =&amp;gt; $_SESSION['auth_token']['access_token']],&lt;br /&gt;
                null,&lt;br /&gt;
                false&lt;br /&gt;
            );&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La demande de révocation se fait quand l'utilisateur clique sur le bouton '''Se déconnecter''' pour l'un des deux Clients '''Authorization Code''' et '''Client Credentials'''.&lt;br /&gt;
&lt;br /&gt;
Si les jetons sont révoqués, l'utilisateur ne peut pas accéder à la plateforme OpenFlyers, il doit se reconnecter.&lt;br /&gt;
&lt;br /&gt;
==Utiliser l'API==&lt;br /&gt;
Une fois un jeton d'accès obtenu, les données sont accessibles par une requête POST exécutée vers l'URL : &amp;lt;code&amp;gt;https://openflyers.com/nom-de-plateforme/oauth/resources.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée. La requête POST doit respecter une structure particulière. Cette structure diffère en fonction du type de ressource souhaité et chaque ressource ne peut être accédée qu'[[#Liste-des-scopes-disponibles|avec le scope qui lui est associé]]. Le jeton d'accès doit être renseigné dans l'en-tête HTTP ''Authorization'' en y indiquant la valeur complète du jeton d'accès reçu précédé du type de jeton reçu  : &amp;lt;code&amp;gt;Authorization: &amp;lt;token_type&amp;gt; &amp;lt;access_token&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Récupérer les informations de l'utilisateur connecté===&lt;br /&gt;
Ce type de ressource est nommé '''user_information'''. Cette ressource n'est accessible qu'avec le scope '''default.login'''. Cette ressource permet la récupération des informations de l'utilisateur connecté, en d'autre termes, l'utilisateur connecté lors de l'étape d'autorisation et correspondant à celui ayant émis la demande de jeton d'accès. À l'heure actuelle, seul l'identifiant de l'utilisateur connecté est retourné. La requête POST est construite de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|resource_type||string||Le type de ressource demandé, ici, ce champ correspond à '''user_information'''.&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Un exemple de requête complète au format JSON :&lt;br /&gt;
&amp;lt;javascript&amp;gt;POST /nom-de-plateforme/oauth/resources.php HTTP/1.1&lt;br /&gt;
Content-Type: application/x-www-form-urlencoded&lt;br /&gt;
Host: openflyers.com&lt;br /&gt;
Date: Wed, 04 Aug 2021 13:57:51 GMT&lt;br /&gt;
Accept: application/json&lt;br /&gt;
User-Agent: curl/7.64.1&lt;br /&gt;
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU&lt;br /&gt;
Signature: keyId=&amp;quot;58c450d937953829c8cca3613001f865a918da07&amp;quot;,&lt;br /&gt;
           algorithm=&amp;quot;rsa-sha256&amp;quot;,&lt;br /&gt;
           headers=&amp;quot;host content-type digest&amp;quot;,&lt;br /&gt;
           signature=&amp;quot;UsTjCPLsXzmo1b8FrA18SdLgaPamCpqR7tDHBhaiBnro6RbOkoD7=&amp;quot;&lt;br /&gt;
Digest: SHA-256=Bi6/9qfJXEWme2/9o7VQMyvf+MED523bWdtdi91opwk=&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;resource_type&amp;quot;:&amp;quot;user_information&amp;quot;,&lt;br /&gt;
    &amp;quot;client_id&amp;quot;:&amp;quot;d2615fe2020ec476&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La réponse est retournée dans un conteneur JSON.&lt;br /&gt;
&lt;br /&gt;
===Récupérer les rapports génériques===&lt;br /&gt;
Ce type de ressource est nommé '''generic_report'''. Cette ressource n'est accessible qu'avec le scope '''genericreports.readonly'''. Cette ressource permet la récupération des rapports génériques au format CSV autorisés pour le profil de l'utilisateur associé au client OAuth2 enregistré. La requête POST est construite de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|resource_type||string||Le type de ressource demandé, ici, ce champ correspond à '''generic_report'''.&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|report_id||int||Identifiant du rapport souhaité.&lt;br /&gt;
|-&lt;br /&gt;
|replacementList||array||Tableau correspondant aux différents paramètres modifiables pour générer le rapport souhaité.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Un exemple de requête complète au format JSON :&lt;br /&gt;
&amp;lt;javascript&amp;gt;POST /nom-de-plateforme/oauth/resources.php HTTP/1.1&lt;br /&gt;
Content-Type: application/x-www-form-urlencoded&lt;br /&gt;
Host: openflyers.com&lt;br /&gt;
Date: Wed, 04 Aug 2021 13:57:51 GMT&lt;br /&gt;
Accept: application/json&lt;br /&gt;
User-Agent: curl/7.64.1&lt;br /&gt;
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU&lt;br /&gt;
Signature: keyId=&amp;quot;58c450d937953829c8cca3613001f865a918da07&amp;quot;,&lt;br /&gt;
           algorithm=&amp;quot;rsa-sha256&amp;quot;,&lt;br /&gt;
           headers=&amp;quot;host content-type digest&amp;quot;,&lt;br /&gt;
           signature=&amp;quot;UsTjCPLsXzmo1b8FrA18SdLgaPamCpqR7tDHBhaiBnro6RbOkoD7=&amp;quot;&lt;br /&gt;
Digest: SHA-256=Bi6/9qfJXEWme2/9o7VQMyvf+MED523bWdtdi91opwk=&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;resource_type&amp;quot;:&amp;quot;generic_report&amp;quot;,&lt;br /&gt;
    &amp;quot;client_id&amp;quot;:&amp;quot;d2615fe2020ec476&amp;quot;,&lt;br /&gt;
    &amp;quot;report_id&amp;quot;:135,&lt;br /&gt;
    &amp;quot;replacementList&amp;quot;:{&lt;br /&gt;
        &amp;quot;year&amp;quot;:2018&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La réponse est un fichier CSV retourné dans un conteneur JSON.&lt;br /&gt;
&lt;br /&gt;
===Récupérer les rapports personnalisés===&lt;br /&gt;
Ce type de ressource est nommé '''report'''. Cette ressource n'est accessible qu'avec le scope '''reports.readonly'''. Cette ressource permet la récupération des rapports personnalisés au format CSV autorisés pour le profil de l'utilisateur associé au client OAuth2 enregistré. La requête POST est construite de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|resource_type||string||Le type de ressource demandé, ici, ce champ correspond à '''report'''.&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|report_id||int||Identifiant du rapport souhaité.&lt;br /&gt;
|-&lt;br /&gt;
|replacementList||array||Tableau correspondant aux différents paramètres modifiables pour générer le rapport souhaité.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Un exemple de requête complète au format JSON :&lt;br /&gt;
&amp;lt;javascript&amp;gt;POST /nom-de-plateforme/oauth/resources.php HTTP/1.1&lt;br /&gt;
Content-Type: application/x-www-form-urlencoded&lt;br /&gt;
Host: openflyers.com&lt;br /&gt;
Date: Wed, 04 Aug 2021 13:57:51 GMT&lt;br /&gt;
Accept: application/json&lt;br /&gt;
User-Agent: curl/7.64.1&lt;br /&gt;
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU&lt;br /&gt;
Signature: keyId=&amp;quot;58c450d937953829c8cca3613001f865a918da07&amp;quot;,&lt;br /&gt;
           algorithm=&amp;quot;rsa-sha256&amp;quot;,&lt;br /&gt;
           headers=&amp;quot;host content-type digest&amp;quot;,&lt;br /&gt;
           signature=&amp;quot;UsTjCPLsXzmo1b8FrA18SdLgaPamCpqR7tDHBhaiBnro6RbOkoD7=&amp;quot;&lt;br /&gt;
Digest: SHA-256=Bi6/9qfJXEWme2/9o7VQMyvf+MED523bWdtdi91opwk=&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;resource_type&amp;quot;:&amp;quot;report&amp;quot;,&lt;br /&gt;
    &amp;quot;client_id&amp;quot;:&amp;quot;d2615fe2020ec476&amp;quot;,&lt;br /&gt;
    &amp;quot;report_id&amp;quot;:1,&lt;br /&gt;
    &amp;quot;replacementList&amp;quot;:{&lt;br /&gt;
        &amp;quot;year&amp;quot;:2020&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La réponse est un fichier CSV retourné dans un conteneur JSON.&lt;br /&gt;
&lt;br /&gt;
=Procédures=&lt;br /&gt;
==Créer un client à partir du code source==&lt;br /&gt;
;Prérequis&lt;br /&gt;
Un client de démonstration est disponible pour le logiciel OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/index.php&lt;br /&gt;
&lt;br /&gt;
;Télécharger Le code source du client de démonstration :&lt;br /&gt;
&lt;br /&gt;
Le code source est mis à disposition par OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/oauth2-demo-src.zip &lt;br /&gt;
&lt;br /&gt;
Le code source est structuré de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 src demo folder.png|800px]]&lt;br /&gt;
&lt;br /&gt;
* Le dossier '''css''' contient tout le matériel nécessaire à la stylisation de la page web.&lt;br /&gt;
* Le dossier '''img''' contient les images affichées sur la page web.&lt;br /&gt;
* Le dossier '''ssl''' est le dossier contenant tous les certificats et les clé privées associées à chaque client. Il doit respecter une structure particulière décrite ci-dessous.&lt;br /&gt;
* Le fichier '''ClientDemo.php''' contient la classe '''ClientDemo'''. Cette classe contient toutes les méthodes nécessaires au fonctionnement du client de démonstration OAuth2.&lt;br /&gt;
* Le fichier '''index.php''' est le fichier à appeler depuis le navigateur. Ce fichier correspond au fichier qui gère les appels à la classe '''ClientDemo''' et exécute les méthodes dans l'ordre.&lt;br /&gt;
&lt;br /&gt;
Le dossier '''ssl''' doit respecter la structure suivante :&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 demo tree.png]]&lt;br /&gt;
&lt;br /&gt;
;[[#Générer des certificats|Générer les certificats]] :&lt;br /&gt;
Après la génération des certificats, les clés privées 'auth.key' et 'sign.key' remplacent celles présentes dans les dossiers 'ssl/AuthCodeDemo' et 'ssl/ClientCredDemo'.&lt;br /&gt;
&lt;br /&gt;
;[[#Enregistrer un client|Enregistrer les clients]] :&lt;br /&gt;
&lt;br /&gt;
*Deux clients doivent être créés :&lt;br /&gt;
**Le premier pour le mécanisme d'autorisation '''Authorization Code''',&lt;br /&gt;
**Le second pour le mécanisme d'autorisation '''Client Credentials'''.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 demo manage.png|800px]]&lt;br /&gt;
&lt;br /&gt;
*Télécharger le certificat du CA OpenFlyers en cliquant sur le bouton '''Télécharger le certificat CA''' de la page de gestion. Télécharger aussi le certificat de signature du serveur en cliquant sur le bouton '''Télécharger le certificat de signature du serveur''' de la page de gestion. Placer les deux certificats téléchargés à la racine du dossier '''ssl'''.&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Authorization Code''' et les placer dans le répertoire '''ssl/AuthCodeDemo'''. &lt;br /&gt;
*Modifier le fichier '''ssl/AuthCodeDemo/config.authcode.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;authorize_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/authorize.php&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;path_to_client/ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;path_to_client/ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Remplacer les &amp;lt;code&amp;gt;XXXXXXXXXXXXXXXX&amp;lt;/code&amp;gt; des champs &amp;lt;code&amp;gt;client_id&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;client_secret&amp;lt;/code&amp;gt; par les valeurs obtenues lors de [[#Enregistrer-un-client|l'enregistrement du client]].&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;mastructure&amp;lt;/code&amp;gt; par le nom de la structure sur laquelle la démo est testée.&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;path_to_client/&amp;lt;/code&amp;gt; par le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
**Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
**Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Client Credentials''' et les placer dans le répertoire '''ssl/ClientCredDemo'''.&lt;br /&gt;
*Modifier le fichier '''ssl/ClientCredDemo/config.clientcred.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;path_to_client/ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;path_to_client/ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Remplacer les &amp;lt;code&amp;gt;XXXXXXXXXXXXXXXX&amp;lt;/code&amp;gt; des champs &amp;lt;code&amp;gt;client_id&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;client_secret&amp;lt;/code&amp;gt; par les valeurs obtenues lors de [[#Enregistrer-un-client|l'enregistrement du client]].&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;mastructure&amp;lt;/code&amp;gt; par le nom de la structure sur laquelle la démo est testée.&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;path_to_client/&amp;lt;/code&amp;gt; par le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
**Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
**Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Suivre la [[#Utiliser le client|procédure d'utilisation du client de démonstration]] pour faire fonctionner le client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NB''': Le certificat de signature du serveur est unique à chaque plateforme et serveur. Ainsi, si le serveur ou la plateforme est modifié, le certificat doit être renouvelé.&lt;br /&gt;
&lt;br /&gt;
==Enregistrer un client==&lt;br /&gt;
Pour utiliser l'API OAuth2, il faut enregistrer un client OAuth2 auprès d'OpenFlyers. Pour ceci, suivre les étapes suivantes :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Pour le mécanisme d'authentification Client Credentials&lt;br /&gt;
*Créer un [[Gestion-des-profils#Ajouter-un-profil|nouveau profil]]. Ce profil doit permettre de gérer les droits du client OAuth2. Choisir un nom explicite, par exemple &amp;quot;Client OAuth rapports&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*Sélectionner les droits à assigner à ce profil. Ces droits limitent les données auxquelles le client OAuth2 a accès.&lt;br /&gt;
**Sélectionner les droits relatifs à l'enregistrement de clients OAuth2 dans l'onglet '''Admin''' (colonne '''Associé aux clients OAuth2''').&lt;br /&gt;
**Sélectionner les rapports accessibles par le profil précédemment créé.&lt;br /&gt;
&lt;br /&gt;
*Créer un nouvel utilisateur à partir du panneau de gestion. Cet utilisateur est virtuel et représente le serveur sur lequel fonctionne le client OAuth2.&lt;br /&gt;
**''Des identifiant et nom explicites sont recommandés (exemple : &amp;quot;serv1_oauth_client&amp;quot;)''&lt;br /&gt;
**'''Attention''' : tout utilisateur désactivé et associé à un client OAuth2 rend le client inactif, il faut donc changer l'utilisateur associé au client pour réactiver le client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Pour le mécanisme d'authentification Authorization Code&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Utilisateurs &amp;gt; Profils'''&lt;br /&gt;
*Dans l'onglet '''Généralités''', cocher la case relative à la colonne '''Connexion depuis l'extérieur (OAuth2)''' pour le profil souhaité.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Créer un nouveau client OAuth2&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Transferts &amp;gt; Exports &amp;gt; API OAuth2'''&lt;br /&gt;
[[File:Oauth2 manage.png|800px]]&lt;br /&gt;
*Cliquer sur le bouton Ajouter '''+''' ou '''Ajouter un client'''&lt;br /&gt;
[[File:Oauth2 client creation.png|800px]]&lt;br /&gt;
*Choisir un nom pour le client.&lt;br /&gt;
*Sélectionner le mécanisme d'autorisation utilisé par le client :&lt;br /&gt;
**'''Authorization Code''': permet d'utiliser OAuth2 comme solution SSO ou accéder à des données utilisateurs. Cette méthode peut être couplée avec le mécanisme de mémorisation de connexion (''Refresh Token'').&lt;br /&gt;
**'''Client Credentials''': permet d'utiliser OAuth2 dans un contexte d'automatisme.&lt;br /&gt;
*Saisir l'URI de redirection vers le client pour le mécanisme ''Authorization Code''.&lt;br /&gt;
*Sélectionner l'utilisateur virtuel créé précédemment pour le mécanisme ''Client Credentials''.&lt;br /&gt;
*[[#Générer-des-certificats|Générer deux CSR]] afin d'obtenir deux certificats signés et les saisir :&lt;br /&gt;
**'''Certificate Signing Request pour le certificat d'authentification''' est utilisé pour l'authentification mutuelle avec mTLS (auth_cert.csr.pem).&lt;br /&gt;
**'''Certificate Signing Request pour le certificat de signature''' est utilisé pour la signature des en-têtes HTTP (sign_cert.csr.pem).&lt;br /&gt;
&lt;br /&gt;
[[File:PublicKeysCopyScreen.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Cliquer sur '''Enregistrer'''.&lt;br /&gt;
&lt;br /&gt;
NB: La validité des certificats générés s'étend sur une période de '''3 années'''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Sauvegarder le couple ID/passphrase&lt;br /&gt;
Un couple ID/passphrase (client_id/client_secret) est généré. Ces deux clées ne sont communiquées qu'une seule fois. Elle doivent être stockées en toute sécurité et gardées confidentielles,&lt;br /&gt;
et Mettre ces identifiants dans le fichier '''config.clientcred.json'''.&lt;br /&gt;
[[File:Oauth2 client created.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:ConfigCredJsonScreen.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Télécharger les certificats crt&lt;br /&gt;
Les certificats signés sont téléchargeables depuis l'interface de gestion des clients OAuth2, les certificats sont disponibles dans les onglets '''Certificat d'authentification''' et '''Certificat de signature''' et les mettre dans le dossier '''/ssl''' du client OAuth2.&lt;br /&gt;
[[File:Oauth2 client certificates.png]]&lt;br /&gt;
&lt;br /&gt;
;Téléchargez les certificats du serveur.&lt;br /&gt;
*Les certificats du CA d'OpenFlyers et de signature HTTP du serveur sont nécessaires. Ils sont téléchargeables depuis l'interface de configuration des clients OAuth2.&lt;br /&gt;
[[File:DownloadServerCertifScreen.png|900px]]&lt;br /&gt;
*Dans certains cas d'utilisation, il peut être nécessaire d'ajouter le certificat du CA d'OpenFlyers au Trust Store du système. Si cette étape n'est pas réalisée, les certificats peuvent être considérés comme invalides et peuvent ne pas être utilisables.&lt;br /&gt;
*Pour ajouter le certificat CA au Trust Store du système, suivre les étapes suivantes:&lt;br /&gt;
**Sous Linux, copier le certificat CA d'OpenFlyers dans le dossier &amp;lt;code&amp;gt;/usr/local/share/ca-certificates&amp;lt;/code&amp;gt; et exécuter la commande &amp;lt;code&amp;gt;sudo update-ca-certificates&amp;lt;/code&amp;gt;&lt;br /&gt;
**Sous Windows,&lt;br /&gt;
***Double-cliquer sur le certificat CA d'OpenFlyers téléchargé depuis l'interface d'enregistrement des clients OAuth2&lt;br /&gt;
***Cliquer sur '''Installer un certificat...'''&lt;br /&gt;
***Choisir l'emplacement de stockage (utilisateur ou ordinateur) et cliquer sur '''Suivant''' puis '''Suivant''' et enfin '''Terminer'''&lt;br /&gt;
&lt;br /&gt;
==Générer des certificats==&lt;br /&gt;
L'API OAuth2 implémente [https://tools.ietf.org/html/draft-cavage-http-signatures-10 HTTP Signature] et l'[[Wikipedia-en:Mutual_authentication#mTLS|authentification TLS mutuelle]]. Ces mécanismes utilisent chacun une paire certificat/clé privée différente.&lt;br /&gt;
&lt;br /&gt;
Pour obtenir ces certificats, il faut d'abord générer des Certificate Signing Request (CSR).&lt;br /&gt;
&lt;br /&gt;
La procédure est la suivante :&lt;br /&gt;
*[[OpenSSL#Installer-OpenSSL-dans-un-environnement-Windows|Télécharger OpenSSL pour Windows]] ou [[OpenSSL#Utiliser-Openssl-d'Apache-sous-WAMP|utiliser Openssl d'Apache sous WAMP]].&lt;br /&gt;
*Utiliser les deux fichiers de configuration ''sign_cert.conf'' et ''auth_cert.conf'' ci-dessous et les remplir.&lt;br /&gt;
&lt;br /&gt;
;Fichier de configuration OpenSSL - sign_cert.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;[req]&lt;br /&gt;
default_bits       = 4096                     # taille par défaut des nouvelles clés, peut être surchargé dans la commande&lt;br /&gt;
encrypt_key        = no                       # chiffrer la clé générée&lt;br /&gt;
distinguished_name = req_distinguished_name   # pointe vers la catégorie spécifiée pour le Distinguished Name&lt;br /&gt;
x509_extensions    = v3_req                   # pointe vers la catégorie spécifiée pour les extensions x509&lt;br /&gt;
prompt             = no&lt;br /&gt;
&lt;br /&gt;
[req_distinguished_name]&lt;br /&gt;
C                  =                          # code à deux chiffres du pays (ex: FR)&lt;br /&gt;
ST                 =                          # région/état (ex: Gironde)&lt;br /&gt;
L                  =                          # ville (ex: Bordeaux)&lt;br /&gt;
O                  =                          # organisation (ex: OpenFlyers)&lt;br /&gt;
OU                 =                          # unité organisationelle (ex: IT)&lt;br /&gt;
CN                 =                          # nom de domaine (ex: openflyers.com)&lt;br /&gt;
&lt;br /&gt;
[v3_req]&lt;br /&gt;
keyUsage           = digitalSignature         # pour quelles opérations la clé peut-elle être utilisée&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Fichier de configuration OpenSSL - auth_cert.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;[req]&lt;br /&gt;
default_bits       = 4096                     # taille par défaut des nouvelles clés, peut être surchargé dans la commande&lt;br /&gt;
encrypt_key        = no                       # chiffrer la clé générée&lt;br /&gt;
distinguished_name = req_distinguished_name   # pointe vers la catégorie spécifiée pour le Distinguished Name&lt;br /&gt;
x509_extensions    = v3_req                   # pointe vers la catégorie spécifiée pour les extensions x509&lt;br /&gt;
prompt             = no&lt;br /&gt;
&lt;br /&gt;
[req_distinguished_name]&lt;br /&gt;
C                  =                          # code à deux chiffres du pays (ex: FR)&lt;br /&gt;
ST                 =                          # région/état (ex: Gironde)&lt;br /&gt;
L                  =                          # ville (ex: Bordeaux)&lt;br /&gt;
O                  =                          # organisation (ex: OpenFlyers)&lt;br /&gt;
OU                 =                          # unité organisationelle (ex: IT)&lt;br /&gt;
CN                 =                          # nom de domaine (ex: openflyers.com)&lt;br /&gt;
&lt;br /&gt;
[v3_req]&lt;br /&gt;
extendedKeyUsage   = clientAuth               # pour quelles opérations la clé peut-elle être utilisée&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Exécuter les commandes suivantes :&lt;br /&gt;
*&amp;lt;bash&amp;gt;openssl req -sha256 -newkey rsa -keyout sign.key -out sign_cert.csr.pem -outform PEM -config sign_cert.conf&amp;lt;/bash&amp;gt;&lt;br /&gt;
*&amp;lt;bash&amp;gt;openssl req -sha256 -newkey rsa -keyout auth.key -out auth_cert.csr.pem -outform PEM -config auth_cert.conf&amp;lt;/bash&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces commandes prennent chacune en entrée le fichier de configuration et génèrent une clé privée et un Certificate Signing Request. &lt;br /&gt;
&lt;br /&gt;
Une fois ces CSR obtenus :&lt;br /&gt;
*Les renseigner dans les champs prévus à cet effet lors de la [[#Enregistrer-un-client|création d'un client]] et télécharger les certificats signés depuis l'interface une fois le client créé.&lt;br /&gt;
*Garder la clé privée confidentielle. Une fuite poserait un risque de sécurité. Elle va de paire avec le certificat distribué par l'autorité de certification OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
==Mettre en place une connexion à l'API OpenFlyers sur un serveur mutualisé==&lt;br /&gt;
;Note&lt;br /&gt;
La procédure ci-après est destinée à une mise en place lorsqu'il n'y a pas d'accès SSH en ligne de commande mais uniquement un accès FTP. Dans ce cas, la création des clés privées et publics est effectuée &amp;quot;en local&amp;quot;. Dans la procédure suivante elle est effectuée depuis un PC sous '''Windows'''.&lt;br /&gt;
&lt;br /&gt;
;Prérequis&lt;br /&gt;
*Posséder les accès FTP :&lt;br /&gt;
**Hôte : XXXXXXXXXXXXXXXXXX&lt;br /&gt;
**Login : XXXXXXXX&lt;br /&gt;
**Mot de passe :  XXXXXXXX&lt;br /&gt;
**Port : XX (par exemple 21)&lt;br /&gt;
*Télécharger Le code source du client de démonstration à disposition par OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/oauth2-demo-src.zip &lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
*[[#Générer des certificats|Générer les certificats]] en local.&lt;br /&gt;
*Remplacer les clés privées 'auth.key' et 'sign.key' présentes dans les dossiers 'ssl/AuthCodeDemo' et 'ssl/ClientCredDemo' par les clés générées.&lt;br /&gt;
*[[#Enregistrer un client|Enregistrer les deux clients]] :&lt;br /&gt;
**Le premier pour le mécanisme d'autorisation '''Authorization Code'''.&lt;br /&gt;
**Le second pour le mécanisme d'autorisation '''Client Credentials'''.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 demo manage.png|800px]]&lt;br /&gt;
&lt;br /&gt;
*Télécharger le certificat du CA OpenFlyers en cliquant sur le bouton '''Télécharger le certificat CA''' de la page de gestion. &lt;br /&gt;
*Télécharger aussi le certificat de signature du serveur en cliquant sur le bouton '''Télécharger le certificat de signature du serveur''' de la page de gestion.&lt;br /&gt;
*Placer les deux certificats téléchargés à la racine du dossier '''ssl'''.&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Authorization Code''' et les placer dans le répertoire '''ssl/AuthCodeDemo'''. &lt;br /&gt;
*Modifier le fichier '''ssl/AuthCodeDemo/config.authcode.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;authorize_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/authorize.php&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;./ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;./ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Client Credentials''' et les placer dans le répertoire '''ssl/ClientCredDemo'''.&lt;br /&gt;
*Modifier le fichier '''ssl/ClientCredDemo/config.clientcred.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;./ssl/ClientCredDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;./ssl/ClientCredDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;./ssl/ClientCredDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;./ssl/ClientCredDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;./ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;./ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Remplacer les &amp;lt;code&amp;gt;XXXXXXXXXXXXXXXX&amp;lt;/code&amp;gt; des champs &amp;lt;code&amp;gt;client_id&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;client_secret&amp;lt;/code&amp;gt; par les valeurs obtenues lors de [[#Enregistrer-un-client|l'enregistrement du client]].&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;mastructure&amp;lt;/code&amp;gt; par le nom de la structure sur laquelle la démo est testée.&lt;br /&gt;
&lt;br /&gt;
*Transférer le fichier &amp;quot;oauth-demo&amp;quot; vers le serveur mutualisé :&lt;br /&gt;
**Télécharger [http://filezilla-project.org/download.php?type=client FileZilla].&lt;br /&gt;
**Lancer FileZilla.&lt;br /&gt;
**Entrer l'URl du serveur mutualisé dans le champ '''Hôte'''.&lt;br /&gt;
**Entrer le login dans le champ '''Nom d'utilisateur'''.&lt;br /&gt;
**Entrer le mot de passe dans le champ '''Mot de passe'''.&lt;br /&gt;
**Entrer le port dans le champ '''Port'''.&lt;br /&gt;
**Cliquer sur le bouton Connexion.&lt;br /&gt;
**Accéder à l'emplacement du répertoire &amp;quot;oauth-demo&amp;quot; en local à gauche dans l'onglet &amp;quot;Site local&amp;quot;.&lt;br /&gt;
**Choisir l'emplacement où placer le répértoire oauth-demo dans l'anglet '''Site distant''' à droite.&lt;br /&gt;
**Glisser et déposer le oauth-demo à l'emplacement choisi.&lt;br /&gt;
[[File:Transfer OauthDemo To Shared Server.png|800px]]&lt;br /&gt;
*Accéder au client OAuth-demo depuis le serveur mutualisé en utilisant l'URL du domaine du serveur : url_de_domaine_de_serveur/oauth-demo/index.php&lt;br /&gt;
*Modifier la valeur '''URI de redirection vers le client''' du client '''AuthCodeDemo''' précédemment créé en remplaçant l'ancienne URL par la nouvelle.&lt;br /&gt;
&lt;br /&gt;
*Suivre la [[#Utiliser le client|procédure d'utilisation du client de démonstration]] pour faire fonctionner le client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NB''': Le certificat de signature du serveur est unique à chaque plateforme et serveur. Ainsi, si le serveur ou la plateforme est modifié, le certificat doit être renouvelé.&lt;br /&gt;
&lt;br /&gt;
==Récupérer les données d'un utilisateur==&lt;br /&gt;
*Cliquer sur le bouton '''Récupérer les informations utilisateur''', l'identifiant de l'utilisateur s'affiche.&lt;br /&gt;
*Utiliser l'identifiant récupérer afin de récupérer toute information associée à cet utilisateur en [[Gestion-des-rapports#Ajouter-un-rapport|créant de nouveaux rapports personnalisés]]&lt;br /&gt;
&lt;br /&gt;
==Utiliser le client==&lt;br /&gt;
;Prérequis&lt;br /&gt;
Un client de démonstration est disponible pour le logiciel OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/index.php&lt;br /&gt;
&lt;br /&gt;
Le client de démonstration se présente de la manière suivante.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2-client-demo.png]]&lt;br /&gt;
&lt;br /&gt;
La démonstration est composée de deux colonnes. La première, nommée '''Authorization Code''' correspond [[#Authorization Code|au mécanisme d'autorisation du même nom]]. Elle dispose d'un bouton permettant de se connecter ainsi que d'une section indiquant les informations relatives à l'état de la connexion. La seconde colonne, nommée '''Client Credentials''' correspond elle aussi [[#Client Credentials|au mécanisme d'autorisation du même nom]]. Comme pour la première colonne, les éléments qui y sont présentés sont identiques. La différence étant que le bouton de connexion n'a pas le même effet étant donné que ces deux mécanismes sont différents. Chaque mécanisme est indépendant et il est possible de se connecter à un des deux mécanismes sans se connecter à l'autre ou se connecter aux deux en même temps.&lt;br /&gt;
&lt;br /&gt;
;Le mécanisme '''Authorization Code'''&lt;br /&gt;
*Cliquer sur le bouton '''Se connecter''' (ce qui redirige le navigateur vers la page de connexion du logiciel OpenFlyers).&lt;br /&gt;
*Renseigner les identifiants de l'administrateur pour s'y connecter.&lt;br /&gt;
*Nom d'utilisateur : '''admini'''.&lt;br /&gt;
*Mot de passe : '''azerty'''.&lt;br /&gt;
&lt;br /&gt;
Une fois les informations saisies, la page suivante est affichée.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth authorize demo.png]]&lt;br /&gt;
&lt;br /&gt;
*Cliquer sur le bouton '''Autoriser l'application''' pour autoriser la connexion (ce qui se redirige le navigateur vers la page du client de démonstration OAuth2).&lt;br /&gt;
&lt;br /&gt;
La première colonne doit afficher l'état de connexion '''Connecté''' ainsi qu'un nouveau bouton '''Récupèrer les informations utilisateurs''' qui permet de récupérer les informations de l'utilisateur connecté.&lt;br /&gt;
&lt;br /&gt;
;Le mécanisme '''Client Credentials'''&lt;br /&gt;
*Cliquer sur le bouton de connexion '''Se connecter''': contrairement à celui du mécanisme '''Authorization Code''', ne redirige pas le navigateur vers la page de connexion du logiciel OpenFlyers. Le bouton de connexion utilise les identifiants du client, ici le couple clé privée/clé publique, pour initier la connexion avec le serveur d'autorisation et obtenir un jeton d'accès.&lt;br /&gt;
&lt;br /&gt;
Une fois la connexion établie, la seconde colonne doit afficher l'état de connexion '''Connecté''' ainsi qu'un menu déroulant '''Rapport à récupèrer''' et un nouveau bouton '''Récupèrer le rapport''' qui permet de récupérer les rapports génériques et personnalisés.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le client, une fois connecté sur les deux mécanismes, se présente de la manière suivante.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 connected demo.png]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
==500 Internal Server Error en récupérant le rapport==&lt;br /&gt;
La démo utilise les valeurs par défaut pour extraire les rapports. Une erreur 500 indique une &amp;quot;Erreur de syntaxe ou violation d'accès&amp;quot; lors de l'exécution de la requête du rapport. Cela se produit parce que le rapport n'a pas de valeurs par défaut associées, étant donné qu'il n'a jamais été visualisé dans l'interface web. Pour résoudre ce problème, il vous suffit de visualiser le rapport et de cocher la case &amp;quot;Mémoriser ce choix&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Erreur &amp;quot;File not found.&amp;quot;==&lt;br /&gt;
Cette erreur se produit lorsque l'URI utilisé n'existe pas sur le serveur OpenFlyers. Vérifier les URIs mis en place dans les fichiers de configuration et essayer de nouveau.&lt;br /&gt;
&lt;br /&gt;
==int_rsa_verify : longueur de signature incorrecte==&lt;br /&gt;
Ce problème pourrait survenir si les fichiers ca.cert et sign_cert_server.cert ne proviennent pas du même serveur que celui du client oauth2.&lt;br /&gt;
La solution est :&lt;br /&gt;
&lt;br /&gt;
*D'essayer depuis le début l'étape de [[#Générer-des-certificats|génération]] et de [[#Enregistrer-un-client|configuration des certificats]] avec jsut la modification du client existant.&lt;br /&gt;
&lt;br /&gt;
;Si cela ne fonctionne pas:&lt;br /&gt;
&lt;br /&gt;
*Essayez de créer [[#Enregistrer-un-client|un nouveau client]] et refaites la configuration des certificats.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Validit%C3%A9s&amp;diff=12911</id>
		<title>Validités</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Validit%C3%A9s&amp;diff=12911"/>
		<updated>2024-10-02T17:28:03Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter l'utilisation des validités dans la [[Accueil|version 4 d'OpenFlyers]].&lt;br /&gt;
&lt;br /&gt;
Il existe également une page qui traite du [[paramétrage des validités]].&lt;br /&gt;
&lt;br /&gt;
==Définitions==&lt;br /&gt;
Le terme '''validité''' est utilisé par OpenFlyers pour désigner tout ce qui peut constituer une attestation, autorisation, brevet, certificat, diplôme, échelon, expérience acquise, grade, licence, permis, qualification, etc.&lt;br /&gt;
&lt;br /&gt;
Les '''types de validités''' permettent de [[#Paramètres-de-configuration|définir des validités]] qui seront attribuées aux utilisateurs.&lt;br /&gt;
&lt;br /&gt;
La détention par un utilisateur de validités requises peut être vérifié :&lt;br /&gt;
*A la connexion de l'utilisateur&lt;br /&gt;
*Lors d'une réservation faite pour un utilisateur par lui-même ou un autre utilisateur. OpenFlyers vérifie les validités de l'utilisateur concerné par la réservation.&lt;br /&gt;
*Lors d'une saisie d'activité (par exemple lors de la saisie d'un vol pour l'aéronautique).&lt;br /&gt;
&lt;br /&gt;
===Documents-validités===&lt;br /&gt;
Document associé à la validité d'un utilisateur et qui permet de démontrer la réelle détention de la validité par un utilisateur. Pour qu'un document soit associable à une validité, le type de validité doit avoir le paramètre [[Paramétrage-des-validités#Associer-un-document|Associer un document]].&lt;br /&gt;
&lt;br /&gt;
Pour un tel type de validité, la [[Paramétrage-des-validités#Certification|certification]] est en général activée pour permettre la validation du document par un gestionnaire.&lt;br /&gt;
&lt;br /&gt;
===Validité à expérience===&lt;br /&gt;
Un type de validité est une validité à expérience lorsque le champ de paramétrage du type de validité [[#Formule-d'expérience|formule d'expérience]] contient une formule. Dans ce cas, la validité n'est pas attribuable à un utilisateur. C'est l'expérience de l'utilisateur, c'est à dire son activité passée vérifiée par la formule d'expérience, qui définit si l'utilisateur détient cette validité.&lt;br /&gt;
&lt;br /&gt;
===Validité à vendre===&lt;br /&gt;
Une validité à vendre est une validité qui est couplée à un [[Gestion-des-produits-et-des-ventes#Configuration-d'un-produit-Validité|produit en vente]].&lt;br /&gt;
&lt;br /&gt;
===Validité complète===&lt;br /&gt;
&lt;br /&gt;
Une validité est complète lorsque tous les points suivants sont réunis :&lt;br /&gt;
&lt;br /&gt;
* Si la date d'expiration est requise, elle doit être renseignée.&lt;br /&gt;
* Si le code identifiant est requis, il doit être renseigné.&lt;br /&gt;
* Si la date d'obtention est requise, elle doit être renseignée.&lt;br /&gt;
* Si un document peut être associé, les pages obligatoires (s'il y en a) doivent être téléversées.&lt;br /&gt;
&lt;br /&gt;
===Validité contrat===&lt;br /&gt;
Une validité contrat est un validité qui a été déclarée comme contrat. Un contrat est une validité avec un document défini, le but est de permettre de mettre en ligne un document que les utilisateurs doivent signer.&lt;br /&gt;
&lt;br /&gt;
Un utilisateur qui n'a pas signé ses contrats ne peux pas se connecter. Il a la possibilité de signer ses contrats lors de ses tentatives de connexion.&lt;br /&gt;
&lt;br /&gt;
Un contrat signé est stocké en base de données avec le nom  et l'adresse IP du signataire ainsi que la date et l'heure de signature.&lt;br /&gt;
&lt;br /&gt;
Suivre [[Paramétrage-des-validités#Paramétrer-une-validité-comme-contrat|cette procédure]] pour mettre en place des contrats.&lt;br /&gt;
&lt;br /&gt;
Voir également la procédure de [[Connexion#Signer-des-validités-contrats|signature des validités-contrats]].&lt;br /&gt;
&lt;br /&gt;
=Alertes sur les validités=&lt;br /&gt;
==Alerte à la connexion==&lt;br /&gt;
Les validités contrôlées à la connexion sont uniquement :&lt;br /&gt;
*celles possédées par l'utilisateur qui se connecte et qui sont soumises à échéance&lt;br /&gt;
*les validités à expérience récente.&lt;br /&gt;
&lt;br /&gt;
Ainsi, les validités sans échéance ne sont pas contrôlées.&lt;br /&gt;
&lt;br /&gt;
OpenFlyers affiche un message d'alerte pour les validités dont la date d'échéance est expirée ou va expirer dans un délai inférieur à la période d'alerte définie dans la fiche utilisateur. L'utilisateur a la possibilité de cliquer sur la case à cocher &amp;quot;Ne plus le rappeler&amp;quot; afin de ne plus avoir de message de rappel. Dans ce cas, lors des connexions ultérieures, il n'aura plus de message de rappel. Il peut cependant réactiver cette alerte en la réactivant dans la colonne &amp;quot;Alertes&amp;quot; de la ligne correspondante dans '''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Validités'''. Cette réactivation est automatique lors d'une modification de la validité.&lt;br /&gt;
&lt;br /&gt;
==Alertes lors d'une réservation ou une saisie d'activité==&lt;br /&gt;
Les [[Gestion-des-activités#Alertes|alertes suivantes sont générées lors de la saisie d'une activité]] ou d'une réservation.&lt;br /&gt;
&lt;br /&gt;
Les validités périmées apparaissent systématiquement lors de la saisie d'une réservation ou d'une activité comme à la connexion. Leur affichage ne dépend pas du type de ressource. C'est juste un rappel.&lt;br /&gt;
&lt;br /&gt;
Ce rappel est notamment utile lorsqu'une personne effectue une réservation ou une saisie de vol pour le compte d'un tiers. Cela lui permet d'être informé et d'informer ce tiers de sa situation.&lt;br /&gt;
&lt;br /&gt;
==Alertes sur la page listant les validités d'un utilisateur==&lt;br /&gt;
*Alerte de cellule vide alors qu'elle devrait être remplie : la cellule affiche une bordure et un panneau rouges.&lt;br /&gt;
*[[#Alertes-d'expiration|Alertes d'expiration]]&lt;br /&gt;
&lt;br /&gt;
==[[Envoi-des-emails#Email-de-rappel-d'échéance-de-validité|Email de rappel d'échéance de validité]]==&lt;br /&gt;
&lt;br /&gt;
=Certifier des validités=&lt;br /&gt;
La certification permet à une structure d'attester qu'une validité saisie dans OpenFlyers a été vérifiée.&lt;br /&gt;
&lt;br /&gt;
Lorsqu'un document est associé à une validité, cela permet d'indiquer que le document a été vérifié et que les données saisies correspondantes à la validité sont conformes au document téléversé. Cela permet également d'indiquer que le document est valide.&lt;br /&gt;
&lt;br /&gt;
Un document-validité, une fois certifié, n'est plus modifiable, ni par l'utilisateur à qui correspond la validité ni par un gestionnaire de la structure. Cela permet de garantir la pérennité et l'inviolabilité de la certification.&lt;br /&gt;
&lt;br /&gt;
Un document-validité peut être certifié de 2 façons :&lt;br /&gt;
*Soit manuellement par un gestionnaire disposant des droits de certification du document&lt;br /&gt;
*Soit par un robot dans le cas où le robot dispose d'un modèle du type de document à certifier.&lt;br /&gt;
&lt;br /&gt;
Voir le [[Paramétrage-des-validités#Certification|paramétrage de la certification d'un type de validité]] pour définir les validités qui peuvent être certifiées et la colonne [[Gestion-des-profils#Types-de-validités-que-l'utilisateur-peut-gérer-et-certifier|Types de validités que l'utilisateur peut gérer et certifier]] dans la gestion des profils pour définir ceux qui peuvent certifier.&lt;br /&gt;
&lt;br /&gt;
==Certification manuelle==&lt;br /&gt;
;Pré-requis&lt;br /&gt;
Pour pouvoir certifier une validité, un utilisateur doit disposer du [[Gestion-des-profils#Types-de-validités-que-l'utilisateur-peut-gérer-et-certifier|droit de certifier la validité concernée]]&lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
Pour certifier manuellement une validité, il faut soit :&lt;br /&gt;
*Passer par l'interface de gestion des [[#Validités-en-attente-de-certification|validités en attente de certification]] :&lt;br /&gt;
**Vérifier les informations des validités en attente, corriger si besoin&lt;br /&gt;
**Quand une validités est conforme, cliquer sur certifier&lt;br /&gt;
*Passer par le menu de gestion individuelle des validités des utilisateurs :&lt;br /&gt;
**Aller sur la page de gestion des validités des utilisateurs dans '''Gestion &amp;gt; Utilisateurs &amp;gt; Actifs'''&lt;br /&gt;
**Chercher l'utilisateur dont la validité est à certifier puis dans la colonne action cliquer sur l'icône &amp;quot;Editer les validités de l'utilisateur&amp;quot;&lt;br /&gt;
**Sur la page qui s'ouvre, contrôler les informations de la validité puis cliquer sur le bouton dans la colonne &amp;quot;Certifier&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Certification automatique==&lt;br /&gt;
===Certification automatique à partir du numéro de licence délivré par la [https://www.ffa-aero.fr Fédération Française Aéronautique]===&lt;br /&gt;
Cette certification est active lorsque le type de validité est paramétré avec le [[Paramétrage-des-validités#Certification|type de certification '''Par API FFA''']].&lt;br /&gt;
&lt;br /&gt;
;Certification automatique&lt;br /&gt;
Lorsque la validité est nécessaire, à la connexion, lors de la réservation en solo ou lors d'une saisie d'activité en solo, si la validité n'est pas déjà certifiée ou si elle est périmée, le robot OpenFlyers interroge l'API SMILE FFA pour vérifier la validité de la licence.&lt;br /&gt;
&lt;br /&gt;
;Réactualisation manuelle&lt;br /&gt;
Il est possible de forcer la réactualisation de la certification en appuyant sur l'icône de mise à jour qui apparaît dans la colonne '''Actions''' de la liste des validités, cela permet d'appeler le robot OpenFlyers qui interroge l'API SMILE FFA pour vérifier la validité de la licence.&lt;br /&gt;
&lt;br /&gt;
Le bouton n'est actif que si l'une des conditions suivantes est rencontrée :&lt;br /&gt;
*La date d'échéance de la validité est dépassée&lt;br /&gt;
*La date courante est supérieure ou égale au 1er octobre et l'année de la date d'échéance est l'année en cours&lt;br /&gt;
&lt;br /&gt;
;Interrogation de l'API SMILE FFA par le robot OpenFlyers&lt;br /&gt;
*Si la date actuelle est comprise entre le 1er octobre et le 31 décembre, le robot interroge l'API SMILE FFA pour l'année suivante (N+1).&lt;br /&gt;
*Si la licence est valide pour l'année suivante, le robot certifie automatiquement la validité en mettant à jour la date d'échéance de la validité au 31/12 de l'année suivante.&lt;br /&gt;
*Si la licence n'est pas valide pour l'année suivante ou si la date actuelle est antérieure au 1er octobre, le robot OpenFlyers interroge à nouveau l'API SMILE FFA pour l'année en cours afin de  vérifier la validité de la licence:&lt;br /&gt;
**Si la licence est valide, le robot certifie automatiquement la validité en mettant à jour la date d'échéance de la validité au 31/12 de l'année renvoyée par l'API FFA&lt;br /&gt;
**Si la licence n'est pas valide, le robot certifie automatiquement la validité en mettant à jour la date d'échéance de la validité au 31/12 de l'année précédente à l'année courante.&lt;br /&gt;
&lt;br /&gt;
Un document peut-être associé à la validité. Il n'est pas pris en compte pour la certification.&lt;br /&gt;
&lt;br /&gt;
===Certification automatique de l'attestation délivrée par la [https://www.ffa-aero.fr Fédération Française Aéronautique]===&lt;br /&gt;
Cette certification est active lorsque le type de validité est paramétré avec le [[Paramétrage-des-validités#Certification|type de certification '''Possible par robot (FFA)''']].&lt;br /&gt;
&lt;br /&gt;
Le robot d'OpenFlyers est capable d'analyser les fichiers PDF correspondant aux attestations de licence délivrées par la [https://www.ffa-aero.fr Fédération Française Aéronautique (FFA)]. Chaque pilote licencié à la FFA peut récupérer ce document sur le site web [http://projet.ff-aero.fr/SMILE_II/ SMILE]. Le robot extrait du document :&lt;br /&gt;
*Le numéro de licence de l'utilisateur&lt;br /&gt;
*Les noms et prénom de l'utilisateur&lt;br /&gt;
*La date de naissance de l'utilisateur&lt;br /&gt;
*La date de début de validité la licence FFA&lt;br /&gt;
*La date de fin de validité de la licence FFA&lt;br /&gt;
*La présence de l'assurance &amp;quot;Individuelle Accident de base&amp;quot; avec l'attribut &amp;quot;Oui&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Ces informations lui permettent de valider que le document est conforme et correspond à l'utilisateur pour qui le document a été téléversé. Il se base sur le nom et la date de naissance.&lt;br /&gt;
&lt;br /&gt;
Lorsque la correspondance est établie, il met à jour la validité avec les données suivantes :&lt;br /&gt;
*Le numéro de licence&lt;br /&gt;
*La date de début de validité&lt;br /&gt;
*La date de fin de validité&lt;br /&gt;
&lt;br /&gt;
Quand un document est sélectionné les champs mis à jour disparaissent dans le formulaire de saisie, car les données seront extraite du document.&lt;br /&gt;
&lt;br /&gt;
===Licence de pilote privé (PPL)===&lt;br /&gt;
''(en développement)''&lt;br /&gt;
 &lt;br /&gt;
La certification de ce type de validité n'est en fonction que lorsque la [[Paramétrage-des-validités#Certification|certification]] de ce type de validité est activé avec le choix '''Possible par OCR'''.&lt;br /&gt;
&lt;br /&gt;
Un deuxième robot d'OpenFlyers permet d'analyser les fichiers PDF ou JPEG qui correspondent aux Licences de Pilote Privé (PPL). &lt;br /&gt;
&lt;br /&gt;
Les champs détéctés par le robot sont : &lt;br /&gt;
*Les noms et prénoms&lt;br /&gt;
*Le numéro de la licence&lt;br /&gt;
*L'intitulé de la licence&lt;br /&gt;
*La date de validité de la licence&lt;br /&gt;
&lt;br /&gt;
Déroulement de la procédure : &lt;br /&gt;
*Quand un document est téléversé, la détéction commence automatiquement.&lt;br /&gt;
*A l'issue du traitment, quatre champs remplis des données résultantes du traitement par le robot apparaîssent. Des boutons de confirmations apparaîssent aussi en dessous de chaque champ :&lt;br /&gt;
*A ce stade, l'utilisateur est amené à '''effectuer certaines actions''' avant de pouvoir valider le formulaire de saisie. '''Il doit vérifier si les résultats sont correctes puis les confirmer ou les corriger''' sinon : &lt;br /&gt;
**Si l'utilisateur corrige le champ, le bouton de confirmation est remplacé par le message &amp;quot;Vous avez corrigé ce champ&amp;quot;.&lt;br /&gt;
**Si l'utilisateur remet le résultat initial dans le champ, le bouton de confirmation réapparaît sous le champ à la place du message.&lt;br /&gt;
**Si l'utilisateur est en train de modifier un champ, des points de suspension sont affichés en dessou du champ réspectif.&lt;br /&gt;
Les champs sont toujours modifiables. C'est-à-dire, l'utilisateur peut corriger un champ même après l'appui sur le bouton de confirmation.&lt;br /&gt;
&lt;br /&gt;
Dans tous les cas, la validation du formulaire n'est possible que si l'utilisateur a '''corrigé''' ou '''validé''' tous les champs.&lt;br /&gt;
&lt;br /&gt;
=Consulter et gérer ses validités ou celles d'un tiers=&lt;br /&gt;
&lt;br /&gt;
L'interface de gestion des validités est accessible :&lt;br /&gt;
*côté planning : '''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Validités'''&lt;br /&gt;
*côté Gestion :&lt;br /&gt;
*'''Gestion &amp;gt; Utilisateurs &amp;gt; Validités'''&lt;br /&gt;
*'''Gestion &amp;gt; Utilisateurs &amp;gt; Actifs''' et cliquer sur l’icône représentant une check-list dans la colonne '''Actions'''.&lt;br /&gt;
&lt;br /&gt;
Conditions pour consulter et gérer ses validités :&lt;br /&gt;
*Pour consulter ses validités un utilisateur doit posséder le droit [[Gestion-des-profils#Voir-ses-validités|Voir ses validités]].&lt;br /&gt;
*Un utilisateur peut gérer pour lui-même les validités qui sont définies dans le droit [[Gestion des profils#Type-de-validité-que-l'utilisateur-peut-gérer-pour-lui-même|Type de validité que l'utilisateur peut gérer pour lui-même]]. &lt;br /&gt;
*Pour qu'un utilisateur soit autorisé à ajouter une nouvelle validité, il doit détenir le droit [[Gestion-des-profils#Ajout-et-gestion-de-ses-validités|Ajout et gestion de ses validités]].&lt;br /&gt;
*Pour qu'un utilisateur soit autorisé à renouveler une validité détenue ou à mettre à jour le '''Code identifiant''', la '''Date d'obtention''', la '''Limite de validité''' (d'une validité non achetable) ou à supprimer une validité, il doit détenir le droit [[Gestion-des-profils#Ajout-et-gestion-de-ses-validités|Ajout et gestion de ses validités]] ou le droit [[Gestion-des-profils#Gestion-de-ses-validités-détenues|Gestion de ses validités détenues]].&lt;br /&gt;
*Pour qu'un utilisateur soit autorisé à acheter ou renouveler une validité-produit, il doit détenir le droit [[Gestion des profils#Achat-ventes-libres|Achat ventes libres]] et le produit associé à la validité doit être en vente libre.&lt;br /&gt;
&lt;br /&gt;
Conditions pour consulter et gérer les validités d'un tiers :&lt;br /&gt;
*Un utilisateur peut consulter et gérer les validités qui sont définies dans le droit [[Gestion des profils#Type-de-validité-que-l'utilisateur-peut-gérer-pour-lui-même|Types de validités que l'utilisateur peut gérer et certifier]]. &lt;br /&gt;
*Pour qu'un utilisateur soit autorisé à ajouter une validité à vendre à un autre utilisateur, il doit détenir le droit [[Gestion-des-profils#Acheter-pour-les-tiers|Acheter pour les tiers]]&lt;br /&gt;
&lt;br /&gt;
Il est possible d'afficher uniquement les validités nécessaires en sélectionnant un filtre :&lt;br /&gt;
&lt;br /&gt;
[[File:selecteur-validités.png]]&lt;br /&gt;
&lt;br /&gt;
Il est donc possible d'afficher uniquement :&lt;br /&gt;
*les validités qui peuvent être certifiées&lt;br /&gt;
*les validités effectives ([[#Prise-en-compte-d'une-validité|prises en compte]])&lt;br /&gt;
&lt;br /&gt;
Si les validités de tous les utilisateurs sont affichées, il est possible d'afficher uniquement les validités d'un certain type grâce au sélecteur présent en haut à droite de la page. Si tous les types de validités sont affichés, alors il est uniquement possible d'afficher les validités qui peuvent être certifiées.&lt;br /&gt;
&lt;br /&gt;
Pour renouveler une validité détenue, il faut éditer la validité en appuyant sur l'icône crayon qui apparaît dans la colonne '''Actions'''. Une fois sur le formulaire d'édition de la validité concernée un bouton '''Renouveler la validité''' est affiché. Cliquer dessus puis valider.&lt;br /&gt;
&lt;br /&gt;
Lorsqu'un type de validité est configuré pour y [[Paramétrage-des-validités#Associer-un-document|associer un document]], l'utilisateur peut [[#Téléverser-un-fichier|téléverser un fichier]]. Une fois le fichier téléversé, il est téléchargeable.&lt;br /&gt;
&lt;br /&gt;
Dans le tableau de la liste des validités, l'utilisateur concerné, peut voir qui et quand ont été certifiées ses validités. Il retrouve aussi les [[#Validité-contrat|validités-contrats]] qu'il a [[Connexion#Signer-des-validités-contrats|signé à la connexion]].&lt;br /&gt;
&lt;br /&gt;
Si l'utilisateur peut gérer les validités de tiers, une liste déroulante '''Utilisateur''' apparaît au-dessus du tableau. Si la valeur '''Tous''' est sélectionné seules les validités à certifier sont affichées. De plus, une colonne ''Nom du titulaire'' est ajoutée et la colonne ''Alerte ?'' ainsi que le champ ''délai de prévenance'' sont cachés. Si on sélectionne un utilisateur autre que soi-même la colonne ''Alerte ?'' et le champ ''délai de prévenance'' sont cachés.&lt;br /&gt;
&lt;br /&gt;
Remarques :&lt;br /&gt;
*Les validités arrivées à échéance apparaissent sur fond orange.&lt;br /&gt;
*Lorsqu'une validité n'est pas certifiée la cellule '''Etat de certification''' apparaît sur fond orange.&lt;br /&gt;
*La mise à jour de la date d'échéance d'une validité réactive automatiquement la cellule de la colonne [[#Alertes-d'expiration|Alertes ?]] si celle-ci n'est pas modifié lors de la saisie dans le formulaire.&lt;br /&gt;
*Une validité-produit déjà détenue ne peut pas être supprimée.&lt;br /&gt;
&lt;br /&gt;
==Alertes d'expiration==&lt;br /&gt;
Il existe deux types d'alertes liées à l'expiration d'un validité :&lt;br /&gt;
*Lorsque la date limite d'une validité est bientôt atteinte, une '''alerte avant échéance''' apparaît. Celle-ci s'affiche sous la forme d'une cellule à bordure orange et contenant un panneau orange. &lt;br /&gt;
*Lorsque la date limite d'une validité est dépassée, une '''alerte de validité expirée''' apparaît. Celle-ci s'affiche sous la forme d'une cellule à bordure et contenant un panneau rouges.&lt;br /&gt;
&lt;br /&gt;
La case '''Alerte ?''' dans le formulaire de gestion d'une validité permet à un utilisateur d'activer ou désactiver les '''rappels à la connexion''' des validités arrivant à expiration ou ayant expiré.&lt;br /&gt;
&lt;br /&gt;
Le délai de rappel des validités arrivant à expiration est visible dans le champ '''Délai de prévenance en semaines avant chaque échéance''' sous le tableau listant les validités d'un utilisateur. L'utilisateur connecté peut modifier son propre délai. Dans ce cas, ce champ affiche un menu déroulant dans lequel l'utilisateur connecté peut changer le délai. Par ailleurs, pour chaque activité, la case '''Alerte''' doit être cochée.&lt;br /&gt;
&lt;br /&gt;
==Ajouter une validité à un utilisateur==&lt;br /&gt;
*[[#Consulter-et-gérer-ses-validités-ou-celles-d'un-tiers|Accéder à l'interface de gestion des validités]]&lt;br /&gt;
*Sélectionner la validité à ajouter et valider.&lt;br /&gt;
*Saisir les données dans le formulaire et valider&lt;br /&gt;
&lt;br /&gt;
Si la validité est une [[#Validité-à-vendre|validité à vendre]], l'utilisateur sera automatiquement débité du montant correspondant. Les écritures comptables générées correspondantes sont validées. L'objectif est d'empêcher la réversibilité de cette opération par un utilisateur qui aurait souscrit à une validité. Cela permet de garantir la traçabilité des engagements.&lt;br /&gt;
&lt;br /&gt;
Il est néanmoins possible de [[#Supprimer_la_validité_d'un_utilisateur|supprimer une validité]] à vendre indument attribuée.&lt;br /&gt;
&lt;br /&gt;
Il est également possible de débrayer la vente an cliquant sur le toggle-switch '''Débrayer la vente''' afin que le compte ne soit pas débité. Cela nécessite d'avoir le [[Gestion-des-profils#Débrayage-des-ventes-de-validités|droit de débrayage]].&lt;br /&gt;
&lt;br /&gt;
===Téléverser un fichier===&lt;br /&gt;
Lorsqu'un type de validité est configuré pour y [[Paramétrage-des-validités#Associer-un-document|associer un document]], le téléversement des fichiers se fait comme suit :&lt;br /&gt;
*L'utilisateur téléverse le fichier&lt;br /&gt;
Ensuite :&lt;br /&gt;
*S'il s'agit d'un fichier image, il est stocké en base de données.&lt;br /&gt;
*S'il s'agit d'un PDF contenant du texte, le PDF est stocké en base de données.&lt;br /&gt;
*S'il s'agit d'un PDF qui contient une seule image, celle-ci est extraite du PDF et est stockée en base de données.&lt;br /&gt;
*S'il s'agit d'un PDF qui contient plusieurs images, seule la première image est extraite du PDF et stockée en base de données.&lt;br /&gt;
*Si le fichier est vide (ne contient ni texte ni image), une alerte utilisateur [[Alertes-utilisateur#Le-contenu-du-fichier-est-vide.-Le-fichier-n'as-pas-pu-être-téléchargé|indiquant que le contenu du fichier est vide]] est affichée à l'écran. Le fichier ne peut pas être téléversé.&lt;br /&gt;
Dans un cas particulier où l'image encapsulée dans le PDF se compose de plusieurs masques transparents, OpenFlyers convertit l'ensemble de la page du PDF en une image jpeg. Dans le cas où plusieurs images sont encapsulées dans le fichier sur plusieurs pages, seule la première page est extraite.&lt;br /&gt;
&lt;br /&gt;
Les fichiers téléversés sont stockés directement en base de données sous réserve d'être conforme aux règles de téléversement ci-dessous :&lt;br /&gt;
*Formats des fichiers autorisés : GIF, JPEG, PNG et PDF. Si le fichier téléversé n'est pas dans l'un de ces formats, [[Alertes-utilisateur#Ce-n'est-pas-un-fichier-de-type-:-gif,-jpeg,-png,-pdf|un message d'alerte correspondant]] s'affiche à l'écran.&lt;br /&gt;
*Poids maximal autorisé au moment du téléversement : 10 Mo.&lt;br /&gt;
*Poids maximal autorisé pour le stockage : 500 ko. Si le fichier téléversé dépasse les 500 Ko, il est redimensionné dans le cas où c'est une image. Si le fichier est toujours trop gros, alors il est refusé et le [[Alertes-utilisateur#La-taille-maximale-d'un-fichier-est-500ko|message d'alerte correspondant]] s'affiche.&lt;br /&gt;
&lt;br /&gt;
Récapitulatif :&lt;br /&gt;
&lt;br /&gt;
[[File:traitement-apres-televersement.png|800px]]&lt;br /&gt;
&lt;br /&gt;
==Modifier la validité d'un utilisateur==&lt;br /&gt;
*[[#Consulter-et-gérer-ses-validités-ou-celles-d'un-tiers|Accéder à l'interface de gestion des validités]]&lt;br /&gt;
*Les modifications s'effectuent via le formulaire d'édition d'une validité accessible depuis l'icône crayon dans la colonne '''Actions''' du tableau.&lt;br /&gt;
&lt;br /&gt;
''Note :''&lt;br /&gt;
*Avant de faire un enregistrement en base de données, OpenFlyers vérifie s'il y a des modifications par rapport au dernier enregistrement actif de la même validité pour le même utilisateur.&lt;br /&gt;
*Les cellules non renseignées sont en rouges. Lors de l'édition via le formulaire, les champs associés sont également en surbrillance rouge.&lt;br /&gt;
&lt;br /&gt;
Dans le cas d'une [[#Validité-à-vendre|validité à vendre]], la limite de validité n'est pas modifiable. Afin de l'augmenter, il faut passer par un renouvellement. Il est également possible de la modifier manuellement (à condition de disposer du [[Gestion-des-profils#Débrayage-des-ventes-de-validités|droit de débrayage]]) en cliquant sur l'interrupteur '''Débrayer la vente'''.&lt;br /&gt;
&lt;br /&gt;
==Supprimer la validité d'un utilisateur==&lt;br /&gt;
*[[#Consulter-et-gérer-ses-validités-ou-celles-d'un-tiers|Accéder à l'interface de gestion des validités]]&lt;br /&gt;
*Les suppressions s'effectuent directement sur la ligne de la validité concernée en cliquant sur l'icône poubelle de la validité associée.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Dans le cas où la ligne de la validité concernée ne dispose pas de l'icône poubelle&lt;br /&gt;
Cela veut dire que [[Gestion des produits et des ventes#Configuration_du_produit_Validité_&amp;quot;Cotisation&amp;quot;|la validité est à vendre]]. Il faut effectuer la procédure suivante :&lt;br /&gt;
*Si l'utilisateur a été indument débité, il faut [[Utilisation de la comptabilité#Annuler_l'effet_d'une_écriture_comptable|annuler l'effet d'une écriture comptable]] correspond au montant facturé qui n'aurait pas du l'être&lt;br /&gt;
Supprimer la vente de validité de façon temporaire :&lt;br /&gt;
*'''Admin &amp;gt; Ventes &amp;gt; Produits &amp;gt; Validités à vendre'''&lt;br /&gt;
*Repérer la ligne qui lie le type de validité concerné avec un produit&lt;br /&gt;
*Copier la '''Formule de calcul de la date d'expiration''' de la ligne concernée et la coller dans un fichier texte temporaire pour la récupérer ultérieurement&lt;br /&gt;
*Noter le nom du produit associé&lt;br /&gt;
*Supprimer la ligne&lt;br /&gt;
*Supprimer la validité de l'utilisateur concerné (cf. début de la présente procédure)&lt;br /&gt;
Remettre en place la vente du type de validité :&lt;br /&gt;
*'''Admin &amp;gt; Ventes &amp;gt; Produits &amp;gt; Validités à vendre'''&lt;br /&gt;
Sur la dernière ligne :&lt;br /&gt;
*Champ '''Validité''' : sélectionner le nom du type de validité concerné&lt;br /&gt;
*Champ '''Produit''' : sélectionner le nom du produit associé&lt;br /&gt;
*Champ '''Formule de calcul de la date d'expiration''' : recoller la formule de calcul&lt;br /&gt;
*Cliquer le bouton '''Ajouter'''.&lt;br /&gt;
&lt;br /&gt;
=Contrôle des validités=&lt;br /&gt;
==Contrôle des validités à la connexion==&lt;br /&gt;
Dès que l'utilisateur est identifié, un contrôle de ses validités est effectué. Les validités contrôlées sont uniquement celles que possède l'utilisateur et qui sont soumises à échéance ou les validités à expérience récente. &lt;br /&gt;
&lt;br /&gt;
Le paramétrage du contrôle des validités s'effectue au travers de 2 champs :&lt;br /&gt;
*le champ '''[[Paramétrage-des-validités#Alerte-à-la-connexion|Alerte à la connexion]]''' qui définit le comportement que l'application OpenFlyers doit adopter à la connexion&lt;br /&gt;
*le champ '''[[Paramétrage-des-validités#Soumise-à-échéance|Soumise à échéance]]''' qui doit être attribué. S'il n'y a pas d'échéance, alors il n'y a pas de contrôle de validité de l'échéance à la connexion&lt;br /&gt;
&lt;br /&gt;
==Contrôle des validités lors de la saisie d'une réservation==&lt;br /&gt;
Lors d'une réservation, OpenFlyers contrôle les validités détenues par la personne occupant la 1ère place dans la ressource '''et seulement s'il n'y a qu'une seule personne pour cette réservation'''. OpenFlyers vérifie également pour cette personne si des validités ne vont pas expirés avant la date de fin de la réservation. Les validités détenues doivent correspondre aux validités demandées pour le type de ressource correspondant à la ressource réservée et aux validités demandées pour les types d'activités sélectionnés.&lt;br /&gt;
&lt;br /&gt;
Il y a 3 comportement possibles :&lt;br /&gt;
*Pas de contrôle des validités.&lt;br /&gt;
*Une [[Présentation-générale-des-alertes#Alerte-orange|alerte non bloquante]] dans le cas où il manque une ou plusieurs validités.&lt;br /&gt;
*Une [[Présentation-générale-des-alertes#Alerte-rouge|alerte bloquante]] dans le cas où il manque une ou plusieurs validités.&lt;br /&gt;
&lt;br /&gt;
Le comportement est le même pour toutes les validités.&lt;br /&gt;
&lt;br /&gt;
==Contrôle des validités lors de la saisie d'une activité==&lt;br /&gt;
Lors de la saisie d'une activité, OpenFlyers effectue 2 contrôles :&lt;br /&gt;
#'''S'il n'y a qu'une seule personne pour cette activité''', le logiciel vérifie la présence des validités requises pour la ressource utilisée et les types d'activités sélectionnés. Il y a 2 comportements possibles pour chaque validité manquante :&lt;br /&gt;
#*Une [[Présentation-générale-des-alertes#Alerte-orange|alerte non bloquante]].&lt;br /&gt;
#*Une [[Présentation-générale-des-alertes#Alerte-rouge|alerte bloquante]].&lt;br /&gt;
#:Il y a un [[Paramétrage-des-validités#Paramétrer-le-contrôle-des-validités-pour-la-saisie-des-activités|paramétrage général]] qui définit si toute validité manquante doit entrainer un blocage. Si ce n'est pas le cas, alors cela dépend du paramétrage associé à chaque type de validité grâce à la case à cocher [[Paramétrage-des-validités#Validité-bloquante-pour-la-saisie-des-activités-(si-requise)|Validité bloquante pour la saisie des activités (si requise)]].&lt;br /&gt;
#OpenFlyers affiche une alerte pour les validités périmées [[#Contrôle_des_validités_à_la_connexion|comme à la connexion]].&lt;br /&gt;
&lt;br /&gt;
=Débrayer la vente d'une validité=&lt;br /&gt;
Débrayer la vente d'une validité consiste à modifier la date limite d'une validité sans déclencher de vente afin que l'utilisateur concerné ne soit pas débité.&lt;br /&gt;
&lt;br /&gt;
;Prérequis :&lt;br /&gt;
Pour pouvoir débrayer la vente d'une validité, le gestionnaire doit disposer du droit [[Gestion-des-profils#Débrayage-des-ventes-de-validités|débrayage des ventes de validités]].&lt;br /&gt;
&lt;br /&gt;
;Procédure pour attribuer une nouvelle validité sans la vendre :&lt;br /&gt;
*'''Gestion &amp;gt; Utilisateurs &amp;gt; Utilisateurs &amp;gt; Validités'''&lt;br /&gt;
*Sélectionner en haut à gauche, dans la liste des utilisateurs, l'utilisateur concerné&lt;br /&gt;
*Sélectionner en haut à droite, dans la liste des validités, la validité à attribuer&lt;br /&gt;
Si la validité est une validité à vendre, alors apparait à côté de la liste, un interrupteur&lt;br /&gt;
*Cliquer sur cet interrupteur '''Débrayer la vente'''&lt;br /&gt;
Le bouton '''Acheter''' se transforme en '''Ajouter'''&lt;br /&gt;
*Cliquer sur le bouton '''Ajouter'''&lt;br /&gt;
*Compléter le formulaire, notamment la '''Limite de validité'''&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
&lt;br /&gt;
;Procédure pour modifier la limite validité d'une validité déjà attribuée sans la vendre :&lt;br /&gt;
*'''Gestion &amp;gt; Utilisateurs &amp;gt; Utilisateurs &amp;gt; Validités'''&lt;br /&gt;
*Sélectionner en haut à gauche, dans la liste des utilisateurs, l'utilisateur concerné&lt;br /&gt;
Les validités attribuées à l'utilisateur apparaissent&lt;br /&gt;
*A droite de la ligne de la validité à modifier, cliquer sur le pictogramme avec le symbole de l'euro barré et un crayon&lt;br /&gt;
Le formulaire d'édition de la validité apparait&lt;br /&gt;
*Modifier le champ '''Limite de validité'''&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
&lt;br /&gt;
=Historique des validités=&lt;br /&gt;
Une validité possède un historique contenant tous les états par lesquels elle est passée.&lt;br /&gt;
Chaque changement effectué sur une validité entraîne automatiquement une entrée dans l'historique.&lt;br /&gt;
&lt;br /&gt;
L'historique d'une validité est conservé même si la validité est supprimée, il sera consultable si une nouvelle validité du même type est créée pour le même utilisateur.&lt;br /&gt;
&lt;br /&gt;
Il est possible de consulter les anciens fichiers contenus par la validité mêmes s'ils ont été remplacés.&lt;br /&gt;
&lt;br /&gt;
Les fichiers validités téléversés sont comparés. S'ils sont identiques, alors seul l'ancien fichier est conservé. Cela permet de limiter l'augmentation de la taille de la base de données.&lt;br /&gt;
&lt;br /&gt;
==Afficher l'historique des validités==&lt;br /&gt;
Pour afficher l'historique des validité :&lt;br /&gt;
*Aller sur l'[[#Consulter-et-gérer-ses-validités-ou-celles-d'un-tiers|interface de gestion des validités d'un utilisateur]].&lt;br /&gt;
*Cliquer sur le nom de la validité dans la colonne de gauche du tableau pour ouvrir la page d'historique.&lt;br /&gt;
L'historique s'affiche chronologiquement, du changement le plus récent au plus ancien.&lt;br /&gt;
&lt;br /&gt;
=Lister les détenteurs d'un type de validité=&lt;br /&gt;
*Aller sur '''Admin &amp;gt; Utilisateurs &amp;gt; Types de validités'''&lt;br /&gt;
*Cliquer sur l'icône symbolisant une liste dans la colonne '''Liste''' de la ligne correspondante à la validité concernée.&lt;br /&gt;
&lt;br /&gt;
Le tableau liste les personnes ayant la validité correspondante.&lt;br /&gt;
&lt;br /&gt;
Lorsque la validité est soumise à échéance, la liste fait ressortir en rouge sur fond gris les dates d'échéances périmées.&lt;br /&gt;
&lt;br /&gt;
Lorsque la validité est une validité à expérience, la liste contient uniquement les utilisateurs remplissant les critères de la formule d'expérience.&lt;br /&gt;
&lt;br /&gt;
=Prise en compte d'une validité=&lt;br /&gt;
&lt;br /&gt;
Une validité prend effet lorsque tous les points suivants sont réunis :&lt;br /&gt;
&lt;br /&gt;
* La validité doit être [[#Validité-complète|complète]].&lt;br /&gt;
* Si une date d'expiration est présente, elle ne doit pas être dépassée.&lt;br /&gt;
* Si la [[#Certifier-des-validités|certification]] est possible, la validité doit être certifiée.&lt;br /&gt;
&lt;br /&gt;
=Validités en attente de certification=&lt;br /&gt;
&lt;br /&gt;
*[[#Consulter-et-gérer-ses-validités-ou-celles-d'un-tiers|Accéder à l'interface de gestion des validités]]&lt;br /&gt;
*Par défaut le filtre ''Utilisateur'' est sélectionné sur ''Tous'' ce qui permet de visualiser toutes les validités que l'utilisateur peut certifier.&lt;br /&gt;
&lt;br /&gt;
Il est possible de consulter et modifier les renseignements rentrés par les utilisateurs, dans le cas où les informations sont valides, l'utilisateur peut certifier la validité.&lt;br /&gt;
&lt;br /&gt;
Une fois certifiée, la validité reste encore visible 24h, ainsi il est encore possible de corriger la validité si une erreur apparaît.&lt;br /&gt;
&lt;br /&gt;
Cette page est accessible en suivant le lien contenu dans [[Envoi-des-emails#E-mail-de-demande-de-certification-de-validité|l'e-mail de notification]] envoyé automatiquement aux utilisateurs disposant du [[Gestion-des-profils#Types-de-validités-que-l'utilisateur-peut-gérer-et-certifier|droit de certifier la validité concernée]].&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Trucs-et-astuces&amp;diff=12910</id>
		<title>Trucs et astuces</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Trucs-et-astuces&amp;diff=12910"/>
		<updated>2024-10-02T17:28:03Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter des trucs et astuces généraux et indépendants de l'utilisation d'[[Accueil|OpenFlyers]] .&lt;br /&gt;
&lt;br /&gt;
=Administration réseau=&lt;br /&gt;
==Trouver l'adresse IP du routeur==&lt;br /&gt;
Pour connaître l'adresse IP d'une passerelle (box ou routeur).&lt;br /&gt;
===Trouver l'adresse IP du routeur freebox à distance===&lt;br /&gt;
*Aller sur le site de [http://www.free.fr free].&lt;br /&gt;
*Cliquer sur '''Mon compte'''&lt;br /&gt;
*Saisir l'identifiant et le mot de passe du compte pour lequel on souhaite connaitre l'adresse IP&lt;br /&gt;
*Aller sur '''Ma Freebox &amp;gt; Afficher mon adresse IP'''&lt;br /&gt;
*L'adresse IP est indiquée dans le champ '''Votre adresse IP :'''&lt;br /&gt;
Cette adresse IP dite &amp;quot;fixe&amp;quot; est présente avec le message '''Ceci est votre adresse IP, pour les abonnés dégroupés ainsi que les abonnés IPADSL ayant demandé une IP Fixe'''&lt;br /&gt;
&lt;br /&gt;
===Trouver l'adresse IP du routeur sous Windows===&lt;br /&gt;
*[[#Ouvrir_une_console_sous_Windows|Ouvrir une console]]&lt;br /&gt;
*Taper ''ipconfig /all'' pour afficher la structure de la connexion au réseau.&lt;br /&gt;
*L'adresse du routeur est indiquée à la ligne '''passerelle par défaut''' de la '''carte Ethernet''' du PC pour une connexion par câble RJ45 ou sous la '''carte WLAN''' pour une connexion sans fil (par exemple wifi).&lt;br /&gt;
&lt;br /&gt;
===Trouver l'adresse IP du routeur par l'interface graphique de Windows 7===&lt;br /&gt;
*Cliquer sur le bouton '''Démarrer'''&lt;br /&gt;
*cliquer sur '''Panneau de configuration'''&lt;br /&gt;
*Cliquer sur '''Réseau et Internet'''&lt;br /&gt;
*Cliquer sur '''Centre de réseau et partage'''&lt;br /&gt;
*Cliquer sur '''Afficher l'intégralité du réseau''' dan&lt;br /&gt;
*Survoler l’icône Passerelle : l'adresse IP du matériel apparait dans le popup&lt;br /&gt;
&lt;br /&gt;
[[File:Reseau_W7.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Sous Linux===&lt;br /&gt;
*Ouvrir une console&lt;br /&gt;
*Taper « netstat -r -n » &lt;br /&gt;
*L'adresse IP est dans la colonne Passerelle (Gateway en Anglais)&lt;br /&gt;
&lt;br /&gt;
[[File:Reseau_Linux.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Monitoring d'une freebox==&lt;br /&gt;
*http://mafreebox.freebox.fr/pub/fbx_info.txt&lt;br /&gt;
&lt;br /&gt;
=Connexion à un routeur=&lt;br /&gt;
==Connexion à distance à une livebox==&lt;br /&gt;
Prérequis :&lt;br /&gt;
*la livebox doit avoir été configurée pour permettre une contrôle à distance&lt;br /&gt;
*Il faut connaitre l'adresse IP externe de la livebox, soit parce qu'elle est fixe, soit parce qu'un service Dynamic DNS a été mis en place&lt;br /&gt;
&lt;br /&gt;
*Dans un navigateur saisir l'URL pour accéder à la livebox. Cette URL doit être écrite avec &amp;quot;https://&amp;quot; suivie de l'adresse IP externe de la livebox suivie de &amp;quot;:10000&amp;quot; qui correspond au port par défaut proposée par la livebox lors de la mise en place d'une connexion à distance. Cela donne une URL sous la forme : https://X.X.X.X:10000&lt;br /&gt;
*Dans le champ '''identifiant''', saisir l'identifiant créé pour la connexion à distance&lt;br /&gt;
*Dans le champ '''mot de passe''', saisir le mot de passe créé pour la connexion à distance&lt;br /&gt;
*Cliquer sur le bouton '''s'identifier'''&lt;br /&gt;
&lt;br /&gt;
=Console=&lt;br /&gt;
Une console est une fenêtre en ligne de commande.&lt;br /&gt;
==Copier/Coller dans une console==&lt;br /&gt;
====Copier/Coller dans une console sous Windows====&lt;br /&gt;
Vous pouvez faire un copier/coller en utilisant le bouton droit de la souris dans la fenêtre de l'invite de commandes puis en choisissant '''sélectionner''' et ensuite en appuyant sur le bouton gauche et en le laissant appuyer tout en sélectionnant la zone souhaitée)&lt;br /&gt;
&lt;br /&gt;
====Copier/Coller dans une console sous Mac====&lt;br /&gt;
Pour faire un copier/coller de ces informations et nous les communiquer, il suffit d'utiliser commande-C dans le terminal.&lt;br /&gt;
&lt;br /&gt;
==Ouvrir une console==&lt;br /&gt;
===Ouvrir une console sous Mac===&lt;br /&gt;
Sous OSX (mac) il faut lancer un Terminal. Pour cela 2 solutions :&lt;br /&gt;
*Taper &amp;quot;terminal&amp;quot; dans spotlight&lt;br /&gt;
ou&lt;br /&gt;
*lancer l'application qui est dans Applications &amp;gt; Utilitaires.&lt;br /&gt;
&lt;br /&gt;
===Ouvrir une console sous Windows 7===&lt;br /&gt;
*Cliquer sur le bouton '''Démarrer'''&lt;br /&gt;
*Dans le champs '''Rechercher''' taper ''cmd'' puis sélectionner le fichier '''cmd.exe'''.&lt;br /&gt;
*Taper sur la touche &amp;quot;Entrer&amp;quot; pour ouvrir la console DOS.&lt;br /&gt;
&lt;br /&gt;
===Ouvrir une console sous Windows 8===&lt;br /&gt;
*Aller avec le pointeur de la souris dans le coin inférieur gauche de l'écran&lt;br /&gt;
*Le petit rectangle '''Accueil''' doit s'afficher : cliquer sur le bouton droit de la souris&lt;br /&gt;
*Un menu contextuel doit s'afficher : cliquer sur l'item '''Exécuter'''&lt;br /&gt;
*Une fenêtre '''Exécuter''' doit s'ouvrir. Taper ''cmd'' dans le champ '''Ouvrir''' et valider avec la touche &amp;quot;Entrer&amp;quot; pour ouvrir la console DOS.&lt;br /&gt;
&lt;br /&gt;
=Editer un fichier texte=&lt;br /&gt;
Nous recommandons l'utilisation de l'outil [[Wikipedia-en:Notepad%2B%2B|Notepad++]] pour visualiser ou modifier un fichier texte depuis un ordinateur sous système d'exploitation Windows.&lt;br /&gt;
&lt;br /&gt;
=Effectuer une copie d'écran=&lt;br /&gt;
Nous recommandons l'utilisation de l'outil [[Wikipedia-en:Greenshot|Greenshot]] pour effectuer une copie d'écran depuis un ordinateur sous système d'exploitation Windows.&lt;br /&gt;
&lt;br /&gt;
Une fois le logiciel installé et lancé, il suffit d'appuyer sur la touche &amp;quot;Imp. écr&amp;quot; du clavier pour lancer la copie d'écran. Greenshot vous permettra alors de sélectionner la zone à copier puis vous proposera de sauvegarder le fichier.&lt;br /&gt;
&lt;br /&gt;
Lorsque la copie d'écran doit être envoyée par e-mail ou ajouter dans un rapport de bug, il est indispensable de la communiquer sous son format d'origine c'est à dire au format png ou jpg. Surtout, ne mettez pas vos copies d'écran dans un document texte : cela rend son exploitation difficile.&lt;br /&gt;
&lt;br /&gt;
=Modifier le comportement de la souris=&lt;br /&gt;
Voici les procédures pour modifier le comportement de la souris, et notamment le &amp;quot;clic molette&amp;quot; dont nous recommandons l'usage dans la [[Documentation utilisateur#Clic_droit_et_clic_molette|version 3]] d'OpenFlyers :&lt;br /&gt;
*Sur Windows : http://windows.microsoft.com/fr-fr/windows/change-mouse-settings#1TC=windows-7&lt;br /&gt;
*Sur Mac OS : http://support.apple.com/fr-fr/HT2490&lt;br /&gt;
&lt;br /&gt;
=[[Navigateurs]]=&lt;br /&gt;
&lt;br /&gt;
=Tableurs=&lt;br /&gt;
Les procédures suivantes décrites pour LibreOffice sont normalement identiques sous OpenOffice et existent également sous Word ou Excel mais avec des commandes différentes.&lt;br /&gt;
&lt;br /&gt;
==Afficher uniquement un certain type de lignes sous LibreOffice==&lt;br /&gt;
Cas pratique : lors de l'import des à nouveaux, lorsqu'il existe plusieurs types de comptes par utilisateur, il peut être intéressant de n'afficher que les lignes d'un seul type de compte à la fois&lt;br /&gt;
&lt;br /&gt;
Dans LibreOffice, une fois que le document à traiter est ouvert :&lt;br /&gt;
*'''Données &amp;gt; AutoFiltre'''&lt;br /&gt;
Cela fait apparaitre à droite de chaque cellule de la première colonne une flèche&lt;br /&gt;
*Cliquer sur la flèche correspondante à la cellule dont on souhaite restreindre les types de données visibles (exemple : cellule &amp;quot;account_type_name&amp;quot; pour ne faire apparaitre qu'un seul type de compte)&lt;br /&gt;
*Sélectionner/désélectionner les types de données à faire apparaitre/disparaitre&lt;br /&gt;
&lt;br /&gt;
==Afficher un total d'heures sous LibreOffice==&lt;br /&gt;
Cas pratique : lorsqu'on effectue une somme de plusieurs heures, si cette somme dépasse 24h l'affichage par défaut est incohérent.&lt;br /&gt;
&lt;br /&gt;
Dans LibreOffice :&lt;br /&gt;
*Survoler la cellule qui contient le total des heures&lt;br /&gt;
*Clic droit&lt;br /&gt;
*Dans le menu contextuel '''Formater des cellules'''&lt;br /&gt;
*Onglet '''Nombres'''&lt;br /&gt;
*Dans le tableau '''Catégorie''', sélectionner '''Heure'''&lt;br /&gt;
*Dans le tableau '''Format''', sélectionner celui dont le format dans la cellule description correspond à [HH]:MM:SS au lieu de celui qui se met par défaut (HH:MM:SS).&lt;br /&gt;
*Cliquer sur le bouton '''OK'''.&lt;br /&gt;
&lt;br /&gt;
==Changer le format d'affichage des dates dans une colonne sous Excel 2016==&lt;br /&gt;
*Positionner le pointeur de la souris sur la lettre de la colonne concernée&lt;br /&gt;
*Effectuer un clic droit pour faire apparaitre le menu contextuel&lt;br /&gt;
*Sélectionner '''Format de cellule''' pour faire apparaitre une boite de dialogue intitulée '''Format de cellule'''&lt;br /&gt;
*Laisser sélectionné le premier onglet '''Nombre'''&lt;br /&gt;
*Dans le champ '''Catégorie''', sélectionner &amp;quot;Date&amp;quot;&lt;br /&gt;
*Dans le champ '''Type''', sélectionner le format souhaité si existant (penser à utiliser l'ascenseur du champ pour faire défiler l'intégralité des formats proposés)&lt;br /&gt;
*Si le format souhaité est inexistant :&lt;br /&gt;
**Dans le champ '''Catégorie''', sélectionner '''Personnalisée'''&lt;br /&gt;
**Dans le champ '''Type''', renseigner le format souhaiter.&lt;br /&gt;
Pour construire le format souhaité, il suffit en général de s'inspirer des formats existants. Exemple de format pour les dates tel que demandé pour l'import des utilisateurs dans OpenFlyers : &amp;quot;aaaa-mm-jj&amp;quot;&lt;br /&gt;
*Cliquer sur le bouton '''OK'''&lt;br /&gt;
&lt;br /&gt;
==Changer le format d'affichage des dates dans une colonne sous LibreOffice==&lt;br /&gt;
*Positionner le pointeur de la souris sur la lettre de la colonne concernée&lt;br /&gt;
*Effectuer un clic droit pour faire apparaitre le menu contextuel&lt;br /&gt;
*Sélectionner '''Formater les cellules...''' pour faire apparaitre une boite de dialogue intitulée '''Formatage des cellules'''&lt;br /&gt;
*Laisser sélectionné le premier onglet '''Nombres'''&lt;br /&gt;
*Dans le champ '''Catégorie''', sélectionner &amp;quot;Date&amp;quot;&lt;br /&gt;
*Dans le champ '''Format''', sélectionner le format souhaité si existant (penser à utiliser l'ascenseur du champ pour faire défiler l'intégralité des formats proposés)&lt;br /&gt;
*Si le format souhaité est inexistant, dans le champ '''Description de format''', renseigner le format souhaité&lt;br /&gt;
Pour construire le format souhaité, il suffit en général de s'inspirer des formats existants. Exemple de format pour les dates tel que demandé pour l'import des utilisateurs dans OpenFlyers : &amp;quot;YYYY-MM-DD&amp;quot;&lt;br /&gt;
*Cliquer sur le bouton '''OK'''&lt;br /&gt;
&lt;br /&gt;
==Exporter au format csv pour OpenFlyers sous LibreOffice==&lt;br /&gt;
Dans OpenFlyers, l'encodage de caractère par défaut utilisé est l'UTF-8 et la séparation entre les champs est le point-virgule. Voici comment effectuer un export de fichier .csv respectant ces éléments :&lt;br /&gt;
*Sélectionner '''Fichier &amp;gt; Enregistrer sous...'''&lt;br /&gt;
*Choisir le répertoire et le nom de fichier&lt;br /&gt;
*Dans le champ '''Type''' sélectionner '''Texte CSV (.csv) (*.csv)'''&lt;br /&gt;
*Cocher '''Éditer les paramètres du filtre'''&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
Dans la fenêtre '''Export de fichiers texte''' :&lt;br /&gt;
*Dans le champ '''Jeu de caractères''' taper la lettre &amp;quot;U&amp;quot; puis sélectionner '''Unicode (UTF-8)'''&lt;br /&gt;
*Appuyer sur la touche TAB pour éditer le champ suivant, cela permet non seulement de mettre le focus dans le champ mais également de sélectionner tout le contenu de la cellule&lt;br /&gt;
*Dans le champ '''Séparateur de champ''', taper &amp;quot;;&amp;quot;&lt;br /&gt;
*Appuyer sur la touche TAB&lt;br /&gt;
*Taper sur la touche &amp;quot;Supprimer&amp;quot; du clavier de sorte à vider le contenu du champ '''Séparateur de texte'''&lt;br /&gt;
*Cliquer sur le bouton '''OK'''&lt;br /&gt;
&lt;br /&gt;
==Importer un fichier csv sous LibreOffice avec des dates et/ou des heures==&lt;br /&gt;
Lors de l'import d'un fichier csv dans LibreOffice, il faut vider le champ '''Séparateur de chaîne de caractères''' pour que lors de l'import effectif du fichier les colonnes contenant des dates et/ou des heures soient reconnues comme telles.&lt;br /&gt;
&lt;br /&gt;
[[File:Paramétrer_la_prise_en_compte_des_dates_dans_les_fichiers_csv_avec_libreoffice.png]]&lt;br /&gt;
&lt;br /&gt;
Les colonnes correctement reconnues ont le texte aligné à droite.&lt;br /&gt;
&lt;br /&gt;
Par défaut, les heures (=durées) se retrouvent formatées sous la forme ''HH:MM:SS''.&lt;br /&gt;
&lt;br /&gt;
[[File:Résultat import avec date et heure dans libreoffice.png]]&lt;br /&gt;
&lt;br /&gt;
=Télécharger une pièce jointe avec Gmail=&lt;br /&gt;
*Aller sur son compte Gmail depuis un navigateur : https://mail.google.com&lt;br /&gt;
*Cliquer sur l'email reçu contenant la ou les pièce(s) jointe(s) à télécharger&lt;br /&gt;
Les pièces jointes sont en bas de la page avec un titre au-dessus qui indique le nombre de pièces jointes : '''X pièces jointes'''&lt;br /&gt;
*Survoler avec le pointeur de la souris la pièce jointe souhaitée&lt;br /&gt;
3 boutons apparaissent&lt;br /&gt;
*Cliquer sur le bouton le plus à gauche symbolisé par une flèche vers le bas et intitulé '''Télécharger'''&lt;br /&gt;
Si le navigateur ouvre une fenêtre contextuelle demandant '''Que doit-on faire avec ce fichier ?''' :&lt;br /&gt;
*Sélectionner '''Enregistrer le fichier'''&lt;br /&gt;
*Cliquer sur bouton '''OK'''&lt;br /&gt;
[[File:Pièce jointe gmail.jpg|900px]]&lt;br /&gt;
&lt;br /&gt;
Le fichier est enregistré dans le répertoire de sauvegarde paramétré par défaut ou utilisé la fois précédente.&lt;br /&gt;
&lt;br /&gt;
Dans Firefox, il peut être retrouvé en cliquant en haut à droite du navigateur sur le pictogramme symbolisant une flèche vers le bas.&lt;br /&gt;
&lt;br /&gt;
Dans Chrome, il peut être retrouvé en cliquant sur le bouton représentant le fichier téléchargé qui doit apparaitre en bas de la fenêtre.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Technologies-de-g%C3%A9olocalisation-a%C3%A9ronautique&amp;diff=12909</id>
		<title>Technologies de géolocalisation aéronautique</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Technologies-de-g%C3%A9olocalisation-a%C3%A9ronautique&amp;diff=12909"/>
		<updated>2024-10-02T17:28:02Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter :&lt;br /&gt;
*les différentes solutions technologiques de géolocalisation pour l'aéronautique en terme :&lt;br /&gt;
**de transmission de données&lt;br /&gt;
**d'installation à bord d'un aéronef&lt;br /&gt;
*les avantages et inconvénients de chaque type de solution&lt;br /&gt;
*les ordres de grandeur des coûts d'achat (hors main d’œuvre pour l'installation) et d'exploitation&lt;br /&gt;
&lt;br /&gt;
=Principe de la géolocalisation=&lt;br /&gt;
*Un appareil mobile (dans notre cas un aéronef) est équipé d'un récepteur de position par satellite (GPS, GLONASS, GALILEO, ...) lui permettant de connaitre sa position géographique en 3 dimensions&lt;br /&gt;
*D'un dispositif de transmission permettant d'envoyer cette position à une station au sol &lt;br /&gt;
*Cette station au sol renvoie les données de géolocalisation à un serveur accessible depuis le réseau internet permettant son exploitation par des solutions logicielles notamment sur des applications de cartographie permettant d'afficher la position de l'aéronef.&lt;br /&gt;
[[File:Aircraft-position-generic-transmission-scheme.png|center]]&lt;br /&gt;
&lt;br /&gt;
=Réception de la position par GNS=&lt;br /&gt;
Deux réseaux de système de navigation global sont opérationnels&lt;br /&gt;
*GPS: gérè par les États Unis&lt;br /&gt;
*GLONASS: gèré par les Force Spatiales de la Fédération Russe&lt;br /&gt;
&lt;br /&gt;
La constellation GALILEO lancée par un consortium Européen est prévu d'être disponible en 2016&lt;br /&gt;
&lt;br /&gt;
La réception à bord d'un aéronef se fait par le biais d'une antenne incluse dans un équipement ou extérieure à cet équipement et reliée à un boitier incluant l’électronique de décodage et de calcul de position.&lt;br /&gt;
[[File:Aircraft-GPS-various-receptions-scheme.png|center]]&lt;br /&gt;
&lt;br /&gt;
Les combinaisons possibles sont les suivantes :&lt;br /&gt;
*Équipement aéronautique certifié, fixé à l’intérieur de l'aéronef et relié à une antenne extérieur&lt;br /&gt;
Il est préférable d'avoir une antenne GPS extérieure à l'aéronef afin de garantir une meilleure réception des signaux satellites.&lt;br /&gt;
*Antenne extérieure à l'aéronef certifiée et reliée à un équipement non certifié installé dans l'aéronef grâce à un support prévu à cet effet&lt;br /&gt;
*Boitier de réception connecté à une tablette ou à un smartphone par liaison sans fil (Bluetooth, wifi, ...)&lt;br /&gt;
*Boitier autonome incluant l'antenne&lt;br /&gt;
&lt;br /&gt;
=Modes de transmission de données adaptés à l'aéronautique=&lt;br /&gt;
==Transmission ACARS==&lt;br /&gt;
[[File:Aircraft-position-acars-transmission-scheme.png|center]]&lt;br /&gt;
&lt;br /&gt;
Le mode de communication [[Wikipedia-en:Aircraft_Communications_Addressing_and_Reporting_System|ACARS]] date de la fin des années 70. Il utilise plusieurs modes de transmission : VHF, HF ou Satellite. C'est un module dénommé Management Unit (MU) ou Communication Management Unit (CMU) qui détermine le meilleur mode de transmission selon la situation de l'aéronef. Les autres équipements électroniques de l'aéronef peuvent se connecter sur le MU/CMU pour échanger des données avec l'extérieur de l'aéronef. Ce mode de communication permet d'échanger tout type de données et non pas uniquement la position de l'aéronef. De plus, c'est un mode de communication bidirectionnel : l'aéronef peut aussi bien émettre que recevoir des données. Il est communément déployé sur les avions de lignes.&lt;br /&gt;
&lt;br /&gt;
Les successeurs de cette technologie au travers du projet [[Wikipedia-en:Future_Air_Navigation_System|FANS]] et de l'[[Wikipedia-en:Aeronautical_Telecommunications_Network|ATN]] constituent sans doute le futur de la transmission d'information depuis et vers un aéronef car ils permettent d'envisager des échanges basés sur le protocole [[Wikipedia-en:Internet protocol suite|TCP/IP]].&lt;br /&gt;
&lt;br /&gt;
===Avantages de la transmission ACARS===&lt;br /&gt;
Ce mode de transmission permet d'adapter le mode réel de transmission en fonction du réseau disponible et ainsi d'augmenter les chances d'avoir une couverture de disponible.&lt;br /&gt;
&lt;br /&gt;
===Inconvénients de la transmission ACARS===&lt;br /&gt;
 Il nécessite l'implémentation d'un composant coûteux, volumineux (prévu pour être dans un ou plusieurs racks de soute avionique) et lourd (de l'ordre de 5kg).&lt;br /&gt;
&lt;br /&gt;
===Coût de la transmission ACARS===&lt;br /&gt;
*Installation : non chiffré.&lt;br /&gt;
*Transmission : 5 € à 50 € par Heure de vol.&lt;br /&gt;
&lt;br /&gt;
==Transmission ADS-B==&lt;br /&gt;
[[File:Aircraft-position-ads-b-transmission-scheme.png|center]]&lt;br /&gt;
&lt;br /&gt;
L'[[Wikipedia-en:Automatic_dependent_surveillance-broadcast|ADS-B]] (Automatic Dependent Surveillance - Broadcast) est une technologie en cours de déploiement en Europe. A l'origine, l'ADS était uniquement utilisée dans certains espaces aériens ou l'implémentation de radars sols étaient impossible comme en Atlantique Nord dans les espaces aériens océaniques de Gander et Shanwick.&lt;br /&gt;
&lt;br /&gt;
Il s'agit d'un protocole d'émission radio envoyé par les aéronefs pour indiquer leur position aux contrôleurs aérien. On parle alors d'ADS-B out. D'un point de vu cockpit, l'ADS-B est totalement transparent pour le pilote. Il peut simplement le désactiver au travers d'une interface spécifique mais normalement l'émission doit être permanente.&lt;br /&gt;
&lt;br /&gt;
Ultérieurement, l'ADS-B devrait servir à une nouvelle génération de TCAS pour l'ATSAW (Airborne Traffic Situational AWareness). On parlera alors d'ADS-B in.&lt;br /&gt;
&lt;br /&gt;
La législation européenne devrait rendre son installation et son usage obligatoire sur les aéronefs de plus de 5,7T à partir de 2017 pour les anciens aéronefs et 2015 pour les nouveaux aéronefs.&lt;br /&gt;
&lt;br /&gt;
Certaines activités particulières, comme les activités militaires, peuvent être exclues de l'obligation d'emport.&lt;br /&gt;
&lt;br /&gt;
Le signal n'étant pas crypté, il peut être récupéré par n'importe quelle antenne de réception. Il faut donc juste un réseau d'antenne ADS-B permettant de recevoir les émissions des aéronefs. Ce réseau peut être un réseau tiers ouvert. Il est possible de construire son propre réseau. Une antenne de réception ADS-B peut recevoir les émissions des aéronefs dans un rayon de 200Nm.&lt;br /&gt;
&lt;br /&gt;
===Avantages de la transmission ADS-B===&lt;br /&gt;
L'avantage de cette solution réside dans son obligation : si l'aéronef doit règlementairement être équipé d'un transpondeur ADS-B alors il n'y pas besoin d'ajouter d'autre équipement pour transmettre la position.&lt;br /&gt;
&lt;br /&gt;
===Inconvénients de la transmission ADS-B===&lt;br /&gt;
Les inconvénients sont les suivants :&lt;br /&gt;
*S'il n'a pas d'obligation d'installation de dispositif ADS-B, l'exploitant peut, pour des raisons de confidentialité, interdire son usage.&lt;br /&gt;
*Il n'existe pas, à notre connaissance, de serveur officiel ouvert permettant de récupérer la position d'un aéronef. Il faut donc :&lt;br /&gt;
**soit construire son propre réseau d'antennes.&lt;br /&gt;
**soit utiliser des réseaux &amp;quot;libres&amp;quot; privés.&lt;br /&gt;
&lt;br /&gt;
===Coûts de la transmission ADS-B===&lt;br /&gt;
*Installation dans l'aéronef : 0 € si on considère que l'installation d'un transpondeur ADS-B répond à une obligation réglementaire. Sinon il faut compter 3000 € pour le transpondeur ADS-B.&lt;br /&gt;
*Transmission : 0 €.&lt;br /&gt;
*Installation au sol : 1 € par Heure de vol pour l'usage d'un réseau de réception de position ADS-B.&lt;br /&gt;
&lt;br /&gt;
==Transmission GSM==&lt;br /&gt;
[[File:Aircraft-position-gsm-transmission-scheme.png|center]]&lt;br /&gt;
La position peut être envoyée grâce au réseau GSM utilisé par les téléphones portables. L'équipement qui envoie la position doit être doté d'un modem [[Wikipedia-fr:General Packet Radio Service|GPRS]] incluant une carte SIM. Il nécessite un abonnement data appelé &amp;quot;[[Wikipedia-fr:Machine_to_machine|M2M]]&amp;quot; auprès d'un opérateur de téléphonie. En général l'équipement peut fonctionner avec le réseau GSM partout dans le monde en fonction de l'abonnement (prise en compte ou non du [[Wikipedia-fr:Roaming|roaming]]). Par contre la transmission en temps réel des données est soumise à l'existence d'une couverture GSM au niveau de la région survolée et à la réglementation applicable en matière d'utilisation des appareils GSM (cf. [[#Inconvénients_de_la_transmission_GSM|Inconvénients de la transmission GSM]]). Dans le cadre de l'aéronautique, le GSM est une solution peu onéreuse dans le cas de la transmission des [[Wikipedia-en:OOOI#OOOI_events|OOOI]] ou si la trajectoire n'a besoin d'être transmise qu'à l'issue du vol.&lt;br /&gt;
&lt;br /&gt;
===Avantages de la transmission GSM===&lt;br /&gt;
*La transmission GSM passe sans problème à travers le fuselage d'un aéronef. Cela permet d'envisager une installation d'un boitier indépendant de l'aéronef et donc ne nécessitant pas de certification ou encore même l'utilisation d'une tablette dotée d'une carte SIM ou d'un smartphone.&lt;br /&gt;
&lt;br /&gt;
===Inconvénients de la transmission GSM===&lt;br /&gt;
*Interdiction d'utilisation du GSM en l'air du fait de la réglementation locale ou de l'exploitant.&lt;br /&gt;
*Perte de transmission :&lt;br /&gt;
**Ne fonctionne pas au delà de 3000ft à 5000ft sol dans la plupart des pays car les antennes de réception GSM sont dirigées vers le sol. Les pertes de transmission sont systématiques au delà de 5000ft, très fréquentes au delà de 3000ft.&lt;br /&gt;
**Les vitesses de déplacement élevées peuvent rendre difficile l'appariement entre une antenne de réception et le module émetteur : l'émetteur saute alors d'antenne en antenne sans avoir le temps d'envoyer les données.&lt;br /&gt;
**La région survolée peut ne pas être équipée d'antenne GSM. C'est notamment le cas dans certaines régions boisées et non peuplées ou au-dessus de la mer. Ainsi les pertes de transmission dépassent fréquemment les 5 minutes sur les zones non habitées.&lt;br /&gt;
&lt;br /&gt;
===Coût de la transmission GSM===&lt;br /&gt;
*Installation :&lt;br /&gt;
**Matériel non certifié :&lt;br /&gt;
***Solution smartphone : 0 € si on considère que le smartphone est déjà acheté&lt;br /&gt;
***Solution tablette : coût de la tablette (environ 1000 €)&lt;br /&gt;
***Solution boitier : l'AeroBox proposée par OpenFlyers est à 990 €. Il existe des boitiers offrant moins de fonctionnalités que l'AeroBox pour 100 à 200 €.&lt;br /&gt;
*:Il est possible de connecter une antenne GPS externe à certaines tablettes ou à du matériel non certifié. L'idéal étant que l'antenne soit à l'extérieur de l'aéronef. Dans ce cas, l'antenne doit être certifiée et le coût de l'installation varie entre 1.000 € et 10.000 € selon la nature de l'installation et du boitier auquel elle est reliée.&lt;br /&gt;
**Matériel intégralement certifié : 10.000 € à 100.000 €&lt;br /&gt;
*Transmission : 0,1 € à 1 €. Le prix dépend de la couverture géographique souhaitée et de la quantité de données à transmettre, c'est à dire de la fréquence d'envoi de la position.&lt;br /&gt;
&lt;br /&gt;
==Transmission Satellite==&lt;br /&gt;
[[File:Aircraft-position-satellite-transmission-scheme.png|center]]&lt;br /&gt;
Les transmissions satellite depuis des aéronefs repose en général sur la constellation satellite Iridium. La couverture est mondiale.&lt;br /&gt;
&lt;br /&gt;
Il existe 2 types de matériel embarqué :&lt;br /&gt;
*le matériel indépendant de l'aéronef : il s'agit de boitiers autonomes qui reçoivent également les signaux GPS et transmettent l'émission par satellite. Cela peut également être une tablette reliée à un modem satellite.&lt;br /&gt;
*le matériel monté dans l'aéronef : les antennes sont alors situées à l'extérieur de l'aéronef et qu'il n'y a par conséquent pas de problème réception et de transmission des signaux sauf dans le cas des hélicoptères où la transmission satellite peut poser problème.&lt;br /&gt;
&lt;br /&gt;
===Avantages de la transmission Satellite===&lt;br /&gt;
*Couverture mondiale&lt;br /&gt;
&lt;br /&gt;
===Inconvénients de la transmission Satellite===&lt;br /&gt;
*Coût&lt;br /&gt;
&lt;br /&gt;
===Coût de la transmission Satellite===&lt;br /&gt;
*Installation :&lt;br /&gt;
**Matériel non certifié :&lt;br /&gt;
***Solution boitier : environ 2.000 €&lt;br /&gt;
***Solution tablette : coût de la tablette (environ 1.000 €) + coût du modem satellite (environ 300 €).&lt;br /&gt;
**Matériel certifié :&lt;br /&gt;
***Module de tracking simplement fixé sur le fuselage de l'aéronef : environ 1.000 €&lt;br /&gt;
***Il est possible de connecter une antenne GPS externe à certaines tablettes ou à du matériel non certifié. L'idéal étant que l'antenne soit à l'extérieur de l'aéronef. Dans ce cas, l'antenne doit être certifiée et le coût de l'installation est de l'ordre de 8.000 €.&lt;br /&gt;
***Il existe également des solutions conçues pour le montage de tablette utilisée comme EFB classe 2 et permettant une connexion sur le bus ARINC. Nous n'avons pas étudié le chiffrage.&lt;br /&gt;
***Matériel intégralement certifié : 15.000 € à 60.000 €&lt;br /&gt;
*Transmission : 5 € à 50 € par Heure de vol. Le prix dépend de la fréquence de rafraichissement de la position, du volume d'heures de vol et également du volume des données dans le cas où en plus de la position d'autres données sont échangées. Dans le cadre d'une activité saisonnière l'abonnement peut être réduit sur les seuls mois utiles.&lt;br /&gt;
&lt;br /&gt;
=Interface Homme Machine (IHM)=&lt;br /&gt;
Désormais les Interface Homme Machine de type [[Wikipedia-en:Electronic_flight_bag|Electronic Flight Bag (EFB)]] reposent sur un écran tactile.&lt;br /&gt;
&lt;br /&gt;
Elle permet à l'équipage d'obtenir des informations en temps réel durant le vol et également d'envoyer des informations vers un opérateur sol.&lt;br /&gt;
&lt;br /&gt;
Il existe 2 types de solution :&lt;br /&gt;
*le matériel non certifié. Désormais seules les tablettes, type iPad, Android ou encore Windows 8RT sont réellement présents sur le marché. Les avantages des tablettes sont indéniables :&lt;br /&gt;
**Ils apportent une grande valeur ajoutée en terme de fonctionnalités grâce à une multitude d'applications dédiées à l'aéronautique.&lt;br /&gt;
**Leur installation est facilitée par le biais de supports dédiés&lt;br /&gt;
**Mises à jour simplifiées des applications embarquées&lt;br /&gt;
*le matériel certifié. Il existe notamment les EFB classe 3. Cependant le prix et la lourdeur d'une certification en font des appareils qui paraissent obsolètes par rapport aux tablettes. Ainsi, nombre de compagnies aériennes renoncent à s'équiper en EFB classe 3 onéreux, voir même font démonter leurs EFBs pour rétrofiter leur flotte avec des supports pour iPad certifiés EFB classe 1 ou 2. C'est ainsi que [http://news.delta.com/index.php?s=43&amp;amp;item=2118 Delta a annoncé le 30 septembre 2013] l'équipement en [[Wikipedia-en:Microsoft Surface 2|tablette Surface 2]] pour ses 11.000 pilotes.&lt;br /&gt;
&lt;br /&gt;
=Certification=&lt;br /&gt;
Dès qu'un équipement est fixé à l'aéronef, il doit être homologué. (Boitier, antenne, ...) C'est la &amp;quot;fixité&amp;quot; du produit ou des parties du produit qui définit s'il doit bénéficier d'un agrément de matériel autorisé sur un aéronef [http://www.easa.europa.eu/certification/ETSO-authorisations.php ETSO (European Technical Standard Order)]&lt;br /&gt;
&lt;br /&gt;
L'équivalent américain de l'ETSO est le TSO mais il n'est pas valide pour une installation conforme à l'EASA. Une demande doit être faite, le procédé est toutefois allégé&lt;br /&gt;
&lt;br /&gt;
Chaque modification sur un aéronef doit être approuvée par un Supplementary Type Certificat STC &lt;br /&gt;
La plupart ne sont pas génériques pour ce type de matériel, à chaque type d'installation il en faut un.&lt;br /&gt;
&lt;br /&gt;
La liste des ETSO et des STC est mise à jour mensuellement sur le site de l'EASA.&lt;br /&gt;
&lt;br /&gt;
==Ensembles autonomes==&lt;br /&gt;
Les ensembles autonomes sont posés dans l'aéronef. Dans ce cas les antennes sont soient internes au produit soit externes mais toujours à l'intérieur de l'aéronef. Le produit nécessite alors une alimentation et doit donc disposer d'une batterie pour assurer son autonomie. Le produit n'est pas certifié aéronautique. 2 exemples de produits :&lt;br /&gt;
*L'AeroBox que fournit la société OpenFlyers : il s'agit d'un boitier totalement autonome avec une batterie interne et des antennes GPS et GSM internes.&lt;br /&gt;
*l'iPad d'Apple : il s'agit d'une tablette qui dispose de sa propre antenne GPS et de sa propre antenne GSM. L'iPad peut également être relié à une antenne GPS externe pour améliorer la réception.&lt;br /&gt;
Il existe d'autres produits proposant des récepteurs GPS et des émetteurs Iridium par exemple.&lt;br /&gt;
&lt;br /&gt;
Il est possible de relier le produit au circuit électrique de l'avion via une prise électrique. Une prise allume-cigare peut être utilisée mais une prise dédiée protégée par fusible est recommandée. Dans ce cas il faudra que la câblage soit approuvé par un STC.&lt;br /&gt;
&lt;br /&gt;
==Ensembles partiellement fixés sur l'aéronef==&lt;br /&gt;
Dans ce cas, seules les interfaces doivent être approuvées, (câblage, alimentation, antennes, ...). L’équipement est considéré comme dé-connectable sans outillage [http://fsims.faa.gov/PICDetail.aspx?docId=8900.1,Vol.4,Ch15,Sec1 FSIMS 8200-1]&lt;br /&gt;
&lt;br /&gt;
C'est typiquement le cas de la transformation d'un iPad en EFB classe 2 relié à un bus ARINC.&lt;br /&gt;
[[File:HMI-non-certified-external-satellite-transmission-scheme.png|center]]&lt;br /&gt;
&lt;br /&gt;
==Ensembles totalement certifiés==&lt;br /&gt;
Il existe 2 types de produits correspondant à cette classification :&lt;br /&gt;
*les &amp;quot;boites noires&amp;quot; qui ne disposent pas d'IHM. Dans ce cas le produit peut être installé n'importe où dans l'aéronef, notamment dans la soute électronique lorsqu'il y en a une. &lt;br /&gt;
*les produits avec une IHM accessible pour le pilote. Le produit peut être alors complètement intégré dans le poste de pilotage ou une partie peut être déportée ailleurs dans l'aéronef.&lt;br /&gt;
&lt;br /&gt;
===Ensembles totalement certifiés sans IHM===&lt;br /&gt;
====Ensemble totalement certifié fixé dans l'aéronef====&lt;br /&gt;
[[File:Autonomous-external-attached-satellite-transmission-scheme.png|center]]&lt;br /&gt;
&lt;br /&gt;
===Ensembles totalement certifiés avec IHM===&lt;br /&gt;
[[File:HMI-all-certified-external-satellite-transmission-scheme.png|center]]&lt;br /&gt;
&lt;br /&gt;
=CS-STAN=&lt;br /&gt;
Dans le cadre du CS-STAN (CS-SC106b), un boitier enregistreur ne nécessite pas de certification particulière pour les ELA2 (European Light Aircraft) car :&lt;br /&gt;
*Il ne contient pas de batterie (pas de risque de feu de batterie)&lt;br /&gt;
&lt;br /&gt;
Pour plus de précisions, voir le chapitre '''Standard Change CS-SC106b''' pages 119 et120 du document EASA [https://www.easa.europa.eu/en/downloads/136407/en CS-STAN / Issue 4] concernant ''INSTALLATION OF FLIGHT TIME RECORDERS''.&lt;br /&gt;
&lt;br /&gt;
Si le boitier transmet des données pendant le vol, alors il faut un certificat EMI.&lt;br /&gt;
&lt;br /&gt;
Si le boitier contient une batterie, alors il faut qu'il respecte la CS STAN.47.&lt;br /&gt;
&lt;br /&gt;
=Synthèse des coûts des solutions matérielles=&lt;br /&gt;
{| class=&amp;quot;wikitable centre&amp;quot;&lt;br /&gt;
!Schéma de principe!!Type de solution matérielle!!IHM!!Transmission!!Coût d'installation!!Coût mensuel des transmissions&amp;lt;br /&amp;gt;par Heure de Vol&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Aircraft-position-acars-transmission-scheme.png|center|200px]]||certifié||-||ACARS||non chiffré|| 5 € à 50 €&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Aircraft-position-ads-b-transmission-scheme.png|center|200px]]||certifié||-||ADS-B||0 € si requis&amp;lt;br /&amp;gt;Sinon 3.000 € pour le transpondeur|| 1 €&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Autonomous-internal-gsm-transmission-scheme.png|center|200px]]||autonome&lt;br /&gt;
|rowspan=&amp;quot;3&amp;quot;|-&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot;|GSM||0 à 1.000 €&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot;| 0,1 € à 1 €&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Autonomous-internal-gsm-transmission-linked-to-external-attached-gns-antenna-scheme.png|center|200px]]||branché sur antenne GPS extérieure certifiée, amovible et non certifié||~1.000 €&lt;br /&gt;
|-&lt;br /&gt;
|X||certifié intégral, fixé extérieurement sur l'aéronef||non étudié&lt;br /&gt;
|-&lt;br /&gt;
|[[File:HMI-autonomous-internal-gsm-transmission-scheme.png|center|200px]]||autonome&lt;br /&gt;
|rowspan=&amp;quot;3&amp;quot;|OUI||~1.000 €&lt;br /&gt;
|-&lt;br /&gt;
|[[File:HMI-non-certified-internal-gsm-transmission-linked-to-external-attached-gns-antenna-scheme.png|center|200px]]||branché sur antenne GPS extérieure certifiée, amovible et non certifié||~8.000 €&lt;br /&gt;
|-&lt;br /&gt;
|X||certifié intégral||non étudié&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Autonomous-internal-satellite-transmission-scheme.png|center|200px]]||autonome&lt;br /&gt;
|rowspan=&amp;quot;2&amp;quot;|-&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot;|Satellite||~2.000 €&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot;|5 € à 50 €&lt;br /&gt;
|-&lt;br /&gt;
|[[File:Autonomous-external-attached-satellite-transmission-scheme.png|center|200px]]||certifié intégral, fixé extérieurement sur l'aéronef||non chiffré&lt;br /&gt;
|-&lt;br /&gt;
|[[File:IHM-autonomous-internal-satellite-transmission-scheme.png|center|200px]]||autonome&lt;br /&gt;
|rowspan=&amp;quot;4&amp;quot;|OUI||~1.300 €&lt;br /&gt;
|-&lt;br /&gt;
|[[File:HMI-non-certified-internal-satellite-transmission-linked-to-external-attached-gns-antenna-scheme.png|center|200px]]||branché sur antenne GPS extérieure certifiée, amovible et non certifié||~8.000 €&lt;br /&gt;
|-&lt;br /&gt;
|[[File:HMI-non-certified-external-satellite-transmission-scheme.png|center|200px]]||branché sur bus ARINC, certifié, tablette amovible et certifiée EFB classe 2||non chiffré&lt;br /&gt;
|-&lt;br /&gt;
|[[File:HMI-all-certified-external-satellite-transmission-scheme.png|center|200px]]||certifié intégral||15.000 à 60.000 €&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Tableurs&amp;diff=12908</id>
		<title>Tableurs</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Tableurs&amp;diff=12908"/>
		<updated>2024-10-02T17:28:02Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
Les abonnements Business + et supérieur, ou les plateformes disposant de l'option (voir le catalogue [https://openflyers.com/fr/tarifs tarifaire]), peuvent disposer d'un accès à des feuilles de calcul regroupées par classeurs.&lt;br /&gt;
&lt;br /&gt;
Cette page présente le fonctionnement de ces classeurs accessibles depuis la plateforme.&lt;br /&gt;
&lt;br /&gt;
Un exemple de classeur pour le [[suivi de maintenance]] est disponible depuis la plateforme de démonstration [https://openflyers.com/demo-aero-club demo-aero-club].&lt;br /&gt;
&lt;br /&gt;
=Configuration du droit=&lt;br /&gt;
Avant d'ouvrir les classeurs, le droit doit être correctement attribué sur la plateforme.&lt;br /&gt;
&lt;br /&gt;
Pour cela, il faut :&lt;br /&gt;
*Aller dans le menu '''Amin &amp;gt; Utilisateurs &amp;gt; Profils'''&lt;br /&gt;
*Cliquer sur l'onglet '''[[Gestion-des-profils#Généralités-admin|Généralités admin]]'''&lt;br /&gt;
*Cocher le droit '''[[Gestion-des-profils#Accès-aux-tableurs|Accès aux tableurs]]''' pour les profils désirés.&lt;br /&gt;
&lt;br /&gt;
[[File:Tableurs_configuration_profils.png|1200px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois la configuration effectuée, un nouveau sous-menu [[#Ouvrir-un-classeur|permettant d'accéder aux classeurs]] apparaît dans le menu '''Tableurs''' pour les profils précédemment sélectionnés, pour chaque classeur disponible.&lt;br /&gt;
&lt;br /&gt;
[[File:Bouton_tableur_suivi_nav.png]]&lt;br /&gt;
&lt;br /&gt;
=Ouvrir un classeur=&lt;br /&gt;
Les profils [[#Configuration du droit|ayant le droit requis]] peuvent accéder aux classeurs.&lt;br /&gt;
&lt;br /&gt;
Elles sont accessibles depuis le menu '''Tableurs''', où un sous-menu est proposé pour chaque classeur disponible.&lt;br /&gt;
&lt;br /&gt;
Un clique sur l'item du menu ouvre un nouvel onglet dans le navigateur qui contient le classeur dans l'interface ''Google Sheets''.&lt;br /&gt;
&lt;br /&gt;
[[File:Bouton_tableur_suivi_nav.png]]&lt;br /&gt;
&lt;br /&gt;
=Classeurs disponibles=&lt;br /&gt;
Voici une liste des différents classeurs proposés par OpenFlyers :&lt;br /&gt;
*[[Suivi de maintenance#Classeur de suivi de maintenance|Classeur de suivi de maintenance]] : le classeur, mis à jour en temps réel lors de la saisie et la suppression d'un vol, permet de suivre les potentiels, butées et autres informations des aéronefs paramétrés dans la plateforme.&lt;br /&gt;
&lt;br /&gt;
Il est possible de demander le développement de classeurs personnalisées.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Suivi-de-maintenance&amp;diff=12907</id>
		<title>Suivi de maintenance</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Suivi-de-maintenance&amp;diff=12907"/>
		<updated>2024-10-02T17:28:01Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter le module de suivi de [[Maintenance aéronautique|maintenance]].&lt;br /&gt;
&lt;br /&gt;
Ce module est accessible depuis le menu '''Gestion &amp;gt; Ressources &amp;gt; Maintenance''' et dispose de plusieurs interfaces :&lt;br /&gt;
*Une page '''[[#Vue-d'ensemble|Vue d'ensemble]]''' récapitulant les informations des aéronefs et les prochaines butées des actions&lt;br /&gt;
*Une page '''[[#Programme|Programme]]''' permettant de définir pour chaque ressource les caractéristiques nécessaire pour le suivi : les éléments, visites, potentiels, etc.&lt;br /&gt;
*Une page '''[[#Suivi|Suivi]]''' permettant de saisir pour chaque ressource les actions effectuées&lt;br /&gt;
&lt;br /&gt;
Cette page présente également le [[#Module-de-suivi-du-potentiel-restant|module de suivi du potentiel restant]]&lt;br /&gt;
&lt;br /&gt;
Lors de l'initialisation du module, il est recommandé de commencer par renseigner tout le programme de maintenance en commençant par les visites les plus importantes pour terminer par les visites les moins importantes.&lt;br /&gt;
&lt;br /&gt;
=Décalage du programme de maintenance=&lt;br /&gt;
Par défaut, le module de suivi de maintenance est prévu pour que '''toutes''' les interventions d'un aéronef soient renseignées dans [[#Suivi|le suivi de la ressource]] et ce, depuis sa mise en circulation.&lt;br /&gt;
&lt;br /&gt;
Si des interventions ont déjà été effectuées sur l'aéronef quand le module est paramétré pour la première fois, ou si les interventions précédentes sont inconnues, il est possible de '''décaler le programme de maintenance'''. De cette manière, on évite de devoir saisir les anciennes actions effectuées.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour décaler un programme de maintenance, un paramétrage supplémentaire est nécessaire afin d'optimiser les calculs des butées :&lt;br /&gt;
#Aller dans le [[#Programme|paramétrage du programme de la ressource]]&lt;br /&gt;
#Renseigner les bonnes valeurs dans la colonne '''Premier travaux de référence (horaire et calendaire)'''&lt;br /&gt;
&lt;br /&gt;
Si le programme de maintenance doit démarrer à un certain instant '''t''', les premiers travaux de référence de chaque action correspondent aux '''heures''' et à la '''date''' auxquels l'action a été effectuée pour la dernière fois quand l'aéronef avait '''t''' heures de vol. Pour les visites, on prend en compte le fait qu'elles [[Maintenance-aéronautique#Remarques|s'incluent]].&lt;br /&gt;
&lt;br /&gt;
Par exemple, un aéronef a déjà 2054h de vol et on veut faire démarrer le programme de maintenance à ce moment :&lt;br /&gt;
#La dernière '''Visite 50h''' a été effectuée à 2050h&lt;br /&gt;
#La dernière '''Visite 100h''' a été effectuée à 2000h (inclue dans la '''Visite 2000h''')&lt;br /&gt;
#La dernière '''Visite 500h''' a été effectuée à 2000h (inclue dans la '''Visite 2000h''')&lt;br /&gt;
#La dernière révision du '''Moteur''' était à 2000h&lt;br /&gt;
#etc.&lt;br /&gt;
&lt;br /&gt;
Ces valeurs de référence ne prennent pas en compte les marges de tolérance, donc le retard ou l'avance sur l'action. La valeur peut donc être approximative. En reprenant l'exemple précédent :&lt;br /&gt;
*Par exemple, la dernière '''Visite 50h''' a été effectuée à 2067h.&lt;br /&gt;
*Cette visite aurait dû être effectuée à 2050h, de plus la prochaine est prévue pour 2100h (on additionne les heures lors de la dernière visite plus sa périodicité)&lt;br /&gt;
*En mettant 2067h, la prochaine visite serait calculée à 2117h, donc la bonne valeur à renseigner est '''2050h'''. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Attention, pour la saisie de '''toutes''' les visites horaires et calendaires, '''les butées calculées et affichées''' démarrent '''toutes''' de la plus petite visite (habituellement la '''Visite 50h''' et la '''Visite 1 an''') :&lt;br /&gt;
*Ainsi, les prochaines butées des visites horaires sont, par exemple, calculées à partir de la '''Visite 50h''' de référence&lt;br /&gt;
*Les prochaines butées des visites calendaires sont, par exemple, souvent calculées à partir de la '''Visite 1 an''' de référence&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois ces valeurs de référence entrées, [[#Suivi|le suivi de la ressource]] peut être complété en indiquant toutes les interventions '''après''' ces valeurs de référence. Par exemple, si la valeur de référence de la '''Visite 50h''' est 2050h, le suivi ne doit pas contenir de valeur pour la '''Visite 50h''' à 2050h. Seulement les '''Visites 50h''' suivantes seront renseignées.  Le principe est le même pour les autres visites et toute autre action.&lt;br /&gt;
&lt;br /&gt;
=Programme=&lt;br /&gt;
Pour accéder au programme de chaque ressource :&lt;br /&gt;
*'''Gestion &amp;gt; Ressources &amp;gt; Maintenance'''&lt;br /&gt;
*Cliquer sur le bouton '''Programme''' de la ressource concernée&lt;br /&gt;
&lt;br /&gt;
Sur cette interface, il est possible d'accéder au programme d'une autre ressource depuis la liste déroulante '''Ressource'''.&lt;br /&gt;
&lt;br /&gt;
Lorsque le programme est vide, en-dessous du tableau, apparait une ligne '''Créer le programme par duplication à partir de''' qui permet de dupliquer le programme de maintenance d'une autre ressource pour la ressource en cours. Dans ce cas, seules les données des colonnes '''Type''', '''Description''', '''Périodicité horaire (heures)''', '''Tolérance horaire''', '''Périodicité calendaire (mois)''', '''Tolérance calendaire''' sont dupliquées.&lt;br /&gt;
&lt;br /&gt;
La page programme d'une ressource contient les caractéristiques nécessaires pour son suivi : éléments, visites, potentiels, etc et sont affichés selon un [[#Ordre-d'affichage-des-composants-du-programme|ordre de priorité]]. Ainsi, chaque ligne du tableau correspond à un élément de la ressource qui est suivi.&lt;br /&gt;
&lt;br /&gt;
Tous les éléments devant être suivis doivent être renseignés et paramétrés. Le paramétrage est nécessaire au bon fonctionnement du [[#Suivi|suivi]]. &lt;br /&gt;
&lt;br /&gt;
Une fois le paramétrage effectué, la page affiche les résultats des calculs obtenus d'après les informations contenues dans [[#Suivi|le suivi]].&lt;br /&gt;
&lt;br /&gt;
Lors du paramétrage des composants, [[#Ajouter-ou-modifier-un-composant|plusieurs champs sont à renseigner]].&lt;br /&gt;
&lt;br /&gt;
==Ajouter ou modifier un composant==&lt;br /&gt;
Pour ajouter un composant, il faut cliquer sur le bouton '''Ajouter''' présent en-dessous du tableau.&lt;br /&gt;
&lt;br /&gt;
Pour modifier un composant, il faut cliquer sur le pictogramme crayon présent dans la colonne '''Actions''' de la ligne concernée.&lt;br /&gt;
&lt;br /&gt;
Dans le formulaire il faut saisir les champs :&lt;br /&gt;
*'''[[#Types-de-composants|Type de composant]]''' : un élément de l'appareil (moteur, hélice, etc), une visite (50H, 100H, etc) ou autre (CEN, Pesée, etc)&lt;br /&gt;
*'''Description''' : le nom et les informations détaillées sur le composant. Par exemple la référence du moteur&lt;br /&gt;
*'''Périodicité horaire (heures)''' : si le composant a une périodicité horaire il faut remplir cette colonne&lt;br /&gt;
*'''Tolérance horaire''' : la tolérance d'un composant permet de calculer [[Maintenance-aéronautique#Schémas-:-calcul-d'échéances|la fenêtre de la butée optimale]]. Pour les composants avec une périodicité horaires, la tolérance doit être en heures.&lt;br /&gt;
*'''Périodicité calendaire (mois)''' : si le composant a une périodicité calendaire il faut remplir cette colonne&lt;br /&gt;
*'''Tolérance calendaire''' : la tolérance d'un composant permet de calculer [[Maintenance-aéronautique#Schémas-:-calcul-d'échéances|la fenêtre de la butée optimale]]. Pour les composants avec une périodicité calendaire, la tolérance doit être en mois.&lt;br /&gt;
*'''Premiers travaux de référence''' : il s'agit de la date ou des heures cellules des travaux de l'action à utiliser comme référence pour le calcul des valeurs dans [[#Suivi|le suivi]]. Cette colonne permet de [[#Décalage-du-programme-de-maintenance|décaler le programme de maintenance de l'aéronef]]. &lt;br /&gt;
**'''horaire''' : A remplir pour un composant avec périodicité horaire. La valeur doit correspondre aux heures cellules quand l'action a été effectuée pour la dernière fois.&lt;br /&gt;
***Si le programme de maintenance n'est pas décalé, ne rien remplir&lt;br /&gt;
**'''calendaire''' : Le principe est identique aux premier travaux de référence ayant une périodicité horaire, la date des derniers travaux doit être indiquée. &lt;br /&gt;
***&amp;lt;s&amp;gt;Si le programme de maintenance n'est pas décalé, la '''date de mise en circulation''' de l'aéronef doit être renseignée.&amp;lt;/s&amp;gt;&lt;br /&gt;
*'''Cette visite correspond à la révision générale'''&lt;br /&gt;
&lt;br /&gt;
'''Attention :''' tout composant doit être défini avec soit une périodicité horaire soit une périodicité calendaire. Dans le cas où un composant n'a pas de périodicité, il faut créer une périodicité fictive, par exemple en indiquant une butée calendaire de 120 mois.&lt;br /&gt;
&lt;br /&gt;
==Détail du programme==&lt;br /&gt;
Les premières colonnes du programme sont définis lors de l'[[#Ajouter-ou-modifier-un-composant|ajout d'un composant]] :&lt;br /&gt;
*'''Type'''&lt;br /&gt;
*'''Description'''&lt;br /&gt;
*'''Périodicité horaire (heures)'''&lt;br /&gt;
*'''Tolérance horaire'''&lt;br /&gt;
*'''Périodicité calendaire (mois)'''&lt;br /&gt;
*'''Tolérance calendaire'''&lt;br /&gt;
*'''Premiers travaux de référence horaire'''&lt;br /&gt;
*'''Premiers travaux de référence calendaire'''&lt;br /&gt;
&lt;br /&gt;
Les colonnes suivantes et calculs intermédiaires non visibles sont déterminées à partir des premières colonnes et des informations contenues dans le [[#Suivi|suivi]] :&lt;br /&gt;
*'''Heures cellule début travaux''' : récupère sur la dernière entrée du composant dans le suivi la valeur de la colonne '''Heures cellule début travaux'''. Si le composant n'a pas d'entrée dans le suivi, récupère la valeur de la colonne '''Premiers travaux de référence horaire''' du composant&lt;br /&gt;
*'''Date fin travaux''' : récupère sur la dernière entrée du composant dans le suivi la valeur de la colonne '''Date fin travaux'''. Si le composant n'a pas d'entrée dans le suivi, récupère la valeur de la colonne '''Premiers travaux de référence calendaire''' du composant&lt;br /&gt;
*'''Temps réalisé (heures)''' : résultat de la différence entre la colonne '''Heures totales''' de la ressource et la colonne '''Heures cellule début travaux''' du composant&lt;br /&gt;
*'''Potentiel restant (heures)''' : résultat de la différence entre la colonne '''Butée horaire sans marge''' du composant et la colonne '''Heures totales''' de la ressource&lt;br /&gt;
*'''Butée horaire sans marge''' : récupère sur la dernière entrée du composant dans le suivi la valeur de la colonne '''Butée horaire sans marge'''. Résultat de la valeur la plus petite entre celle que l'on vient de récupérer et la colonne '''Heures cellule début travaux''' du composant à laquelle on ajoute la valeur de la colonne '''Périodicité horaire''' du composant&lt;br /&gt;
*'''Butée horaire avec marge''' : résultat de la colonne '''Butée horaire sans marge''' du composant à laquelle on ajoute la valeur de la colonne '''Tolérance horaire''' du composant&lt;br /&gt;
*'''Temps réalisé (mois)''' : résultat de la différence entre la date du jour et de la colonne '''Date fin travaux''' du composant&lt;br /&gt;
*'''Potentiel restant (mois)''' : résultat de la différence entre la colonne '''Butée calendaire sans marge''' du composant et la date du jour&lt;br /&gt;
*'''Butée calendaire sans marge''' : récupère sur la dernière entrée du composant dans le suivi la valeur de la colonne '''Butée calendaire sans marge'''. Résultat de la valeur la plus petite entre celle que l'on vient de récupérer et la colonne '''Date fin travaux''' du composant à laquelle on ajoute la valeur de la colonne '''Périodicité calendaire''' du composant&lt;br /&gt;
*'''Butée calendaire avec marge''' : résultat de la colonne '''Butée calendaire sans marge''' du composant à laquelle on ajoute la valeur de la colonne '''Tolérance calendaire''' du composant&lt;br /&gt;
*'''Heures début travaux effective''' (calcul intermédiaire) :&lt;br /&gt;
**Si le composant est une visite : récupère sur la dernière visite enregistrée [[Maintenance-aéronautique#Remarques|compatible avec le composant]] dans le suivi la valeur de la colonne '''Heures cellule début travaux'''. Si aucune entrée n'est compatible dans le suivi, récupère la valeur de la colonne '''Premiers travaux de référence horaire''' du composant&lt;br /&gt;
**Si le composant n'est pas une visite : récupère sur la dernière entrée du composant dans le suivi la valeur de la colonne '''Heures cellule début travaux'''. Si le composant n'a pas d'entrée dans le suivi, récupère la valeur de la colonne '''Premiers travaux de référence horaire''' du composant&lt;br /&gt;
*'''Butée horaire originale théorique''' (calcul intermédiaire) :&lt;br /&gt;
**Si le composant est une visite : récupère sur la dernière visite enregistrée [[Maintenance-aéronautique#Remarques|compatible avec le composant]] dans le suivi la valeur de la colonne '''Butée horaire sans marge'''. Si aucune entrée n'est compatible dans le suivi, récupère la valeur de la colonne '''Premiers travaux de référence horaire''' du composant&lt;br /&gt;
**Si le composant n'est pas une visite : récupère sur la dernière entrée du composant dans le suivi la valeur de la colonne '''Heures cellule début travaux'''. Si le composant n'a pas d'entrée dans le suivi, récupère la valeur de la colonne '''Premiers travaux de référence horaire''' du composant&lt;br /&gt;
*'''Butée horaire originale intelligente''' (calcul intermédiaire) : Si ces valeurs sont présentes, récupère la valeur la plus petite entre la colonne '''Heures début travaux effective''' du composant et la colonne '''Butée horaire originale théorique''' du composant. Sinon récupère la valeur de la colonne '''Heures cellule début travaux''' du composant&lt;br /&gt;
*'''Butée horaire intelligente sans marge''' (calcul intermédiaire) : résultat de la valeur de la colonne '''Butée horaire originale intelligente''' du composant à laquelle on ajoute la valeur de la colonne '''Périodicité horaire''' du composant&lt;br /&gt;
*'''Butée horaire intelligente avec marge''' (calcul intermédiaire) : résultat de la valeur de la colonne '''Butée horaire intelligente sans marge''' du composant à laquelle on ajoute la valeur de la colonne '''Tolérance horaire''' du composant&lt;br /&gt;
*'''Date fin travaux effective''' (calcul intermédiaire) :&lt;br /&gt;
**Si le composant est une visite : récupère sur la dernière visite enregistrée [[Maintenance-aéronautique#Remarques|compatible avec le composant]] dans le suivi la valeur de la colonne '''Date fin travaux'''. Si aucune entrée n'est compatible dans le suivi, récupère la valeur de la colonne '''Premiers travaux de référence calendaire''' du composant&lt;br /&gt;
**Si le composant n'est pas une visite : récupère sur la dernière entrée du composant dans le suivi la valeur de la colonne '''Date fin travaux'''. Si le composant n'a pas d'entrée dans le suivi, récupère la valeur de la colonne '''Premiers travaux de référence calendaire''' du composant&lt;br /&gt;
*'''Butée calendaire originale théorique''' (calcul intermédiaire) :&lt;br /&gt;
**Si le composant est une visite : récupère sur la dernière visite enregistrée [[Maintenance-aéronautique#Remarques|compatible avec le composant]] dans le suivi la valeur de la colonne '''Butée calendaire sans marge'''. Si aucune entrée n'est compatible dans le suivi, récupère la valeur de la colonne '''Premiers travaux de référence calendaire''' du composant&lt;br /&gt;
**Si le composant n'est pas une visite : récupère sur la dernière entrée du composant dans le suivi la valeur de la colonne '''Butée calendaire sans marge'''. Si le composant n'a pas d'entrée dans le suivi, récupère la valeur de la colonne '''Premiers travaux de référence calendaire''' du composant&lt;br /&gt;
*'''Butée calendaire originale intelligente''' (calcul intermédiaire) : Si ces valeurs sont présentes, récupère la valeur la plus petite entre la colonne '''Date fin travaux effective''' du composant et la colonne '''Butée calendaire originale théorique''' du composant. Sinon récupère la valeur de la colonne '''Date fin travaux''' du composant&lt;br /&gt;
*'''Butée calendaire intelligente sans marge''' (calcul intermédiaire) : résultat de la valeur de la colonne '''Butée calendaire originale intelligente''' du composant à laquelle on ajoute la valeur de la colonne '''Périodicité calendaire''' du composant&lt;br /&gt;
*'''Butée calendaire intelligente avec marge''' (calcul intermédiaire) : résultat de la valeur de la colonne '''Butée calendaire intelligente sans marge''' du composant à laquelle on ajoute la valeur de la colonne '''Tolérance calendaire''' du composant&lt;br /&gt;
*'''Groupe de chevauchement''' (calcul intermédiaire) : n'est calculé que si le composant est une visite.&lt;br /&gt;
*#Récupère dans le programme tous les composants qui sont de type visite et qui chevauche le composant pour lequel on détermine son groupe de chevauchement. Dans le cas d'un composant avec une périodicité horaire, pour déterminer que le composant chevauche un autre composant il doit avoir la valeur de la colonne '''Butée horaire intelligente sans marge''' qui est inférieure ou égale à la valeur de la colonne '''Butée horaire intelligente avec marge''' de l'autre composant et il doit avoir la valeur de la colonne '''Butée horaire intelligente avec marge''' qui est supérieure ou égale à la valeur de la colonne '''Butée horaire intelligente sans marge''' de l'autre composant. Il est également récupéré les visites en retard qui ont la valeur de la colonne '''Butée horaire intelligente avec marge''' qui est inférieure ou égale à la valeur de la colonne '''Butée horaire intelligente sans marge''' de l'autre composant. Dans le cas d'un composant avec une périodicité calendaire le principe est le même mais avec les colonnes '''Butée calendaire intelligente sans et avec marge'''&lt;br /&gt;
*#A partir des composant récupérés, le composant reçoit comme identifiant de groupe de chevauchement l'identifiant du composant qui a la plus petite périodicité horaire ou calendaire. Si le composant n'est chevauché par aucun autre composant ou si c'est lui qui a la plus petite périodicité dans le groupe alors c'est son identifiant qui est utilisé comme identifiant de groupe de chevauchement.&lt;br /&gt;
*'''Cette visite correspond à la révision générale''' (saisi par l'utilisateur mais non visible sur le programme)&lt;br /&gt;
&lt;br /&gt;
==Forcer le rafraichissement des calculs==&lt;br /&gt;
S'il est nécessaire de forcer le recalcule de l'ensemble des butées (calcul intermédiaire), alors il faut saisir une activitéee fictive pour la ressource concernée et ensuite supprimer cette activité.&lt;br /&gt;
&lt;br /&gt;
==Ordre d'affichage des composants du programme==&lt;br /&gt;
L'ordre d'affichage des composants du programme est le suivant :&lt;br /&gt;
#les visites&lt;br /&gt;
#les éléments&lt;br /&gt;
#les inspections&lt;br /&gt;
#les documents&lt;br /&gt;
*Les éléments et les attestations sont triés, dans chaque type, par ordre alphabétique&lt;br /&gt;
*Les visites sont triées ainsi :&lt;br /&gt;
*#Celles avec une périodicité horaire, de la plus petite à la plus grande&lt;br /&gt;
*#Celles avec une périodicité calendaire, par ordre alphabétique&lt;br /&gt;
&lt;br /&gt;
=Suivi=&lt;br /&gt;
Le suivi de chaque ressource est accessible depuis le menu '''Gestion &amp;gt; Resource &amp;gt; Maintenance'''. Dans le tableau, cliquer sur le bouton '''Suivi''' de la resource souhaitée. La page suivi d'une ressource contient toutes les actions effectuées sur l'aéronef. Suite à chaque [[#Ajouter-une-action-effectuée|saisie]], les prochaines butées des actions sont estimées et affichées. &lt;br /&gt;
&lt;br /&gt;
Les actions sont triées par ordre chronologique.&lt;br /&gt;
&lt;br /&gt;
==Ajouter une action effectuée==&lt;br /&gt;
Pour ajouter une action, il faut cliquer sur le bouton '''Ajouter''' présent en dessous du tableau. Pour modifier une action, il faut cliquer sur le pictogramme crayon présent dans la colonne ''Actions''.&lt;br /&gt;
&lt;br /&gt;
Dans le formulaire il faut saisir les champs :&lt;br /&gt;
*'''[[#Types-de-composants|Type de composant]]''' : il s'agit d'une liste déroulante contenant les composant définis dans le [[#Programme|programme]] de la ressource. Il faut sélectionner le composant concerné&lt;br /&gt;
*'''Heures cellule début travaux''' : les heures cellule de la ressource au début de l'action effectuée. Le champ est obligatoire si le composant a une périodicité horaire&lt;br /&gt;
*'''Date fin travaux''' : la date lorsque l'action a été effectuée. Le champ est obligatoire si le composant a une périodicité calendaire&lt;br /&gt;
&lt;br /&gt;
'''Attention :'''&lt;br /&gt;
*Si [[#Décalage-du-programme-de-maintenance|le programme de maintenance est décalé]], le suivi doit contenir les actions '''suivant ce décalage'''. Par exemple si les '''Travaux de référence''' du '''Moteur''' sont de '''2000h''' (le suivi du moteur démarre à 2000h), le suivi ne doit pas contenir l'entrée du '''Moteur''' avec '''2000h''', il contiendra les interventions suivantes du moteur.&lt;br /&gt;
&lt;br /&gt;
==Détail du suivi==&lt;br /&gt;
Les premiers champs du suivi sont définis lors de l'[[#Ajouter-une-action-effectuée|ajout d'une action]] :&lt;br /&gt;
*'''Action'''&lt;br /&gt;
*'''Heures cellule début travaux'''&lt;br /&gt;
*'''Date fin travaux'''&lt;br /&gt;
&lt;br /&gt;
Les champs suivants et calculs intermédiaires non visibles sont déterminées à partir des premières colonnes et des informations contenues dans le [[#Programme|programme]] :&lt;br /&gt;
*'''Est une visite''' : défini à partir du type du composant&lt;br /&gt;
*'''Type d'action''' : horaire (1), calendaire (2), les deux (0). Défini en fonction de si le composant a une périodicité horaire, calendaire ou les deux.&lt;br /&gt;
*'''Tolérance horaire''' : défini à partir du champ correspondant dans le composant&lt;br /&gt;
*'''Tolérance calendaire''' : défini à partir du champ correspondant dans le composant&lt;br /&gt;
*'''Périodicité horaire de l'action''' : si l'action est une visite, la valeur est défini à partir du champ correspondant dans la visite de référence sinon elle est défini à partir du champ correspondant dans le composant&lt;br /&gt;
*'''Périodicité calendaire de l'action''' : si l'action est une visite, la valeur est défini à partir du champ correspondant dans la visite de référence sinon elle est défini à partir du champ correspondant dans le composant&lt;br /&gt;
*'''Périodicité horaire du composant''' : défini à partir du champ correspondant dans le composant&lt;br /&gt;
*'''Périodicité calendaire du composant''' : défini à partir du champ correspondant dans le composant&lt;br /&gt;
*'''Butée horaire de référence''' : défini à partir du champ '''Premiers travaux de référence horaire''' dans le composant. Si l'action est une visite il lui est ajouté la valeur du champ '''Périodicité horaire'''&lt;br /&gt;
*'''Butée calendaire de référence''' : défini à partir du champ '''Premiers travaux de référence calendaire''' dans le composant. Si l'action est une visite il lui est ajouté la valeur du champ '''Périodicité calendaire'''&lt;br /&gt;
*'''Ligne précédente action horaire liée''' / '''Ligne précédente action calendaire liée''' :&lt;br /&gt;
**les lignes sont triées par ordre croissant selon le champ '''Heures cellule début travaux''' puis par ordre chronologique selon le champ '''Date fin travaux'''&lt;br /&gt;
**si c'est une visite le moteur recherche parmi les visites l'entrée précédente la plus proche, sinon il recherche parmi les entrées qui concernent le même composant&lt;br /&gt;
**si une entrée a été trouvée elle est est défini comme ligne précédente sinon c'est la visite de référence qui est utilisée&lt;br /&gt;
*'''Ligne prochaine action horaire liée''' / '''Ligne prochaine action calendaire liée''' :&lt;br /&gt;
**les lignes sont triées par ordre croissant selon le champ '''Heures cellule début travaux''' puis par ordre chronologique selon le champ '''Date fin travaux'''&lt;br /&gt;
**si c'est une visite le moteur recherche parmi les visites l'entrée suivante la plus proche, sinon il recherche parmi les entrées qui concernent le même composant&lt;br /&gt;
**si une entrée a été trouvée elle est est défini comme ligne précédente sinon aucune valeur ne lui est défini&lt;br /&gt;
*'''Butée horaire sans marge''' :&lt;br /&gt;
**s'il s'agit d'une visite ou que la ligne précédente ne correspond pas à la visite de référence&lt;br /&gt;
***si la ligne précédente correspond à la visite de référence, le champ '''Butée horaire sans marge''' de la visite de référence est utilisé&lt;br /&gt;
***sinon, le champ '''Prochaine butée horaire sans marge''' de la ligne précédente est utilisé&lt;br /&gt;
**sinon, le champ '''Butée horaire de référence''' de l'action est utilisé&lt;br /&gt;
*'''Butée horaire avec marge''' : résultat du champ '''Butée horaire sans marge''' de l'action à qui on ajoute la valeur du champ '''Tolérance horaire''' de l'action&lt;br /&gt;
*'''Prochaine butée horaire sans marge''' : résultat de la valeur la plus petite entre celle du champ '''Heures cellule début travaux''' et du champ '''Butée horaire sans marge''' à qui on ajoute la valeur du champ '''Périodicité horaire''' de l'action&lt;br /&gt;
*'''Prochaine butée horaire avec marge''' : résultat du champ '''Prochaine butée horaire sans marge''' de l'action à qui on ajoute une '''Tolérance horaire''' qu'il faut déterminer. Si l'action n'a pas de prochaine ligne alors si c'est une visite on utilise le champ '''Tolérance horaire''' de la visite de référence sinon on utilise le champ '''Tolérance horaire''' de l'action. Si l'action a une prochaine ligne de défini alors c'est le champ '''Tolérance horaire''' de celle-ci qui est utilisé&lt;br /&gt;
*'''Butée calendaire sans marge''' :&lt;br /&gt;
**s'il s'agit d'une visite ou que la ligne précédente ne correspond pas à la visite de référence&lt;br /&gt;
***si la ligne précédente correspond à la visite de référence, le champ '''Butée calendaire sans marge''' de la visite de référence est utilisé&lt;br /&gt;
***sinon, le champ '''Prochaine butée calendaire sans marge''' de la ligne précédente est utilisé&lt;br /&gt;
**sinon, le champ '''Butée calendaire de référence''' de l'action est utilisé&lt;br /&gt;
*'''Butée calendaire avec marge''' : résultat du champ '''Butée calendaire sans marge''' de l'action à qui on ajoute la valeur du champ '''Tolérance calendaire''' de l'action&lt;br /&gt;
*'''Prochaine butée calendaire sans marge''' : résultat de la valeur la plus petite entre celle du champ '''Date fin travaux''' et du champ '''Butée calendaire sans marge''' à qui on ajoute la valeur du champ '''Périodicité calendaire''' de l'action&lt;br /&gt;
*'''Prochaine butée calendaire avec marge''' : résultat du champ '''Prochaine butée calendaire sans marge''' de l'action à qui on ajoute une '''Tolérance calendaire''' qu'il faut déterminer. Si l'action n'a pas de prochaine ligne alors si c'est une visite on utilise le champ '''Tolérance calendaire''' de la visite de référence sinon on utilise le champ '''Tolérance calendaire''' de l'action. Si l'action a une prochaine ligne de défini alors c'est le champ '''Tolérance calendaire''' de celle-ci qui est utilisé&lt;br /&gt;
&lt;br /&gt;
Une première ligne '''Première visite de référence''' apparait dès lors qu'un composant est ajouté au programme de maintenance. Les cellules suivantes sont initialisées :&lt;br /&gt;
*'''Butée horaire sans marge''' : correspond au champ '''Premiers travaux de référence horaire''' du composant ajouté&lt;br /&gt;
*'''Butée horaire avec marge''' : correspond à la somme des champs ''''''Premiers travaux de référence horaire''' et '''Tolérance horaire''' du composant ajouté&lt;br /&gt;
*'''Butée calendaire sans marge''' : correspond au champ '''Premiers travaux de référence calendaire''' du composant ajouté uniquement si le champ '''Périodicité calendaire''' du composant ajouté est renseigné&lt;br /&gt;
*'''Butée calendaire avec marge''' : correspond à la somme des champs '''Premiers travaux de référence calendaire''' et '''Tolérance calendaire''' du composant ajouté. Si le champ '''Périodicité calendaire''' est laissé vide, alors la date indiquée est le 01/01/1970.&lt;br /&gt;
Si par la suite d'autres composants sont ajoutés, cette première ligne '''Première visite de référence''' se met à jour dès lors que le composant ajouté est d'une périodicité plus faible que les composants déjà présents. En effet, c'est le composant à la périodicité la plus faible qui donne le rythme des actions de maintenance. C'est donc lui qui donne la référence sur la prochaine action. Cf. le chapitre [[#Décalage-du-programme-de-maintenance|Décalage du programme de maintenance]].&lt;br /&gt;
&lt;br /&gt;
===Calcul des fenêtres d'action de maintenance : 50h bien positionnée ou trop anticipée===&lt;br /&gt;
[[File:50h bien positionnée.jpg|800px]]&lt;br /&gt;
&lt;br /&gt;
[[File:50h trop anticipée.jpg|800px]]&lt;br /&gt;
&lt;br /&gt;
===Programme sans/avec butée calendaire===&lt;br /&gt;
Programme sans visite calendaire :&lt;br /&gt;
&lt;br /&gt;
[[File:Programme sans VP calendaire.jpg|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Affichage du suivi sans butée calendaire :&lt;br /&gt;
&lt;br /&gt;
[[File:Suivi sans butée calendaire.jpg|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Programme avec butée calendaire :&lt;br /&gt;
&lt;br /&gt;
[[File:Programme avec VP calendaire.jpg|800px]]&lt;br /&gt;
&lt;br /&gt;
Affichage du suivi avec butée calendaire :&lt;br /&gt;
&lt;br /&gt;
[[File:Suivi avec butée calendaire.jpg|800px]]&lt;br /&gt;
&lt;br /&gt;
=Vue d'ensemble=&lt;br /&gt;
La vue d'ensemble est accessible depuis le menu '''Gestion &amp;gt; Ressources &amp;gt; Maintenance'''. Cette page synthétise les informations les plus importantes pour le suivi de maintenance des différentes ressources:&lt;br /&gt;
*'''Heures totales''' : heures totales de la ressource. Cette colonne est automatiquement mise à jour lors de la saisie ou la suppression d'une activité&lt;br /&gt;
*'''Heures depuis RG (Cellule)''' : Cette valeur correspond aux heures totales de la ressource depuis sa Révision Générale (RG). La RG est [[#Programme|paramétrée pour correspondre à une visite]] de la ressource, par exemple la visite 2000h.&lt;br /&gt;
*'''Heures depuis RG (Moteur)''' : La valeur correspond aux heures totales du moteur depuis sa révision, soit depuis ses [[#Programme|'''Heures début travaux''']].&lt;br /&gt;
*'''Heures depuis RG (Hélice)''' : Le principe est le même que pour le moteur, la valeur correspond aux heures totales depuis la révision de l'hélice.&lt;br /&gt;
*'''Potentiel''' : Le '''Potentiel''' est divisé en deux sous colonnes. Une contenant le potentiel restant en heures, une contenant le potentiel restant en mois. Les potentiels affichés sont ceux de la colonne '''Prochaine action'''. Si la prochaine action est une visite alors le potentiel restant affichée se base sur le [[Maintenance-aéronautique#Calcul-de-l'échéance-d'une-visite|calcul de l'échéance d'une visite]]. Il est possible que le potentiel restant de la visite visible dans le [[#Programme|programme]] soit inférieur au potentiel calculé. Dans ce cas on vérifie si une [[Maintenance-aéronautique#Remarques|visite compatible]] avec une périodicité supérieure a été réalisé depuis la dernière révision de la prochaine visite affichée. Si c'est le cas alors on affiche le potentiel calculé. Sinon on affiche la potentiel restant de la prochaine visite.&lt;br /&gt;
*'''Prochaine action''' : La '''Prochaine action''', divisée en deux colonnes est un complément de la colonne '''Potentiel'''. Elle contient le nom des deux prochaines actions de la ressource arrivant à échéance, une en heures et une en mois. L'affichage de la '''Prochaine action''' est optimisé quand le [[#Suivi|suivi]] de la ressource est complet. La prochaine action est le composant avec la plus petite butée horaire ou calendaire. Lorsque la prochaine action est une visite on regarde si des visites se chevauchent. Si c'est le cas alors c'est la visite avec la plus grande périodicité qui sera affichée.&lt;br /&gt;
**Le caractère '''*''' est affiché sur les prochaines actions qui incluent un chevauchement de visite&lt;br /&gt;
&lt;br /&gt;
Le potentiel affiché change de couleur selon sa valeur :&lt;br /&gt;
*Au dessus de 10 heures : &amp;lt;span style=&amp;quot;color: green;&amp;quot;&amp;gt;'''vert'''&amp;lt;/span&amp;gt;&lt;br /&gt;
*Entre 10 heures (inclus) et 5 heures (non inclus) : &amp;lt;span style=&amp;quot;color: orange;&amp;quot;&amp;gt;'''orange'''&amp;lt;/span&amp;gt;&lt;br /&gt;
*En dessous de 5 heures (inclus) : &amp;lt;span style=&amp;quot;color: red;&amp;quot;&amp;gt;'''rouge'''&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Actualisation journalière de la vue d'ensemble==&lt;br /&gt;
&lt;br /&gt;
Chaque nuit à 06h00 UTC la [[#Vue-d'ensemble|vue d'ensemble]] est actualisée afin de mettre à jour les [[#Détail-de-la-vue-d'ensemble|calculs intermédiaires]] se basant sur la date du jour.&lt;br /&gt;
&lt;br /&gt;
==Détail de la vue d'ensemble==&lt;br /&gt;
&lt;br /&gt;
Les champs suivants et calculs intermédiaires non visibles sont déterminés à partir des informations contenues dans le [[#Programme|programme]] et dans le [[#Suivi|suivi]] :&lt;br /&gt;
*'''Cellule - Heures totales''' : heures totales de l'aéronef mises à jour à chaque modification du temps de vol - création, édition ou suppression d'un vol&lt;br /&gt;
*'''Cellule - Heures depuis RG''' : résultat de la différence entre le champ '''Cellule - Heures totales''' et le champ '''Heures cellule début travaux''' de la visite qui correspond à la révision générale&lt;br /&gt;
*'''Moteur - Heures depuis RG''' : résultat de la différence entre le champ '''Cellule - Heures totales''' et le champ '''Temps réalisé (heures) ''' de l'élément moteur.&lt;br /&gt;
Pour que cette case contienne une valeur, il faut qu'un composant de type ''72 - Moteur'' soit renseigné dans le programme de l'aéronef et qu'une entrée soit saisie dans le suivi de l'aéronef lié à ce composant&lt;br /&gt;
*'''Hélice - Heures depuis RG''' : résultat de la différence entre le champ '''Cellule - Heures totales''' et le champ '''Temps réalisé (heures) ''' de l'élément hélice.&lt;br /&gt;
Pour que cette case contienne une valeur, il faut qu'un composant de type ''61 - Hélice'' soit renseigné dans le programme de l'aéronef et qu'une entrée soit saisie dans le suivi de l'aéronef lié à ce composant&lt;br /&gt;
&lt;br /&gt;
*'''Prochaine visite horaire''' : recherche la visite avec la plus petite périodicité horaire. A partir du champ '''Groupe de chevauchement''', recherche parmi les visites qui sont dans ce groupe la visite avec la plus grande périodicité horaire. Cette visite sera la '''prochaine visite horaire'''.&lt;br /&gt;
*'''Butée horaire visite''' : recherche parmi le suivi de la ressource, la visite avec la valeur la plus grande pour le champ '''Prochaine butée horaire sans marge'''. Si une visite est trouvée, récupère la valeur de ce champ. Sinon récupère la valeur de ce champ dans le programme sur la visite défini comme étant la '''prochaine visite horaire'''.&lt;br /&gt;
*'''Potentiel prochaine visite horaire''' :&lt;br /&gt;
*#Calcule la différence entre le champ '''Butée horaire visite''' et le champ '''Cellule - Heures totales''' et la compare avec le potentiel restant de la prochaine visite horaire&lt;br /&gt;
*#Si ce dernier est plus petit, vérifie si une visite compatible avec une périodicité supérieure a été réalisé depuis la dernière révision de la prochaine visite horaire&lt;br /&gt;
*#Si c'est le cas alors on affiche le résultat de la différence entre le champ '''Butée horaire visite''' et le champ '''Cellule - Heures totales'''. Sinon on affiche la potentiel restant de la prochaine visite horaire&lt;br /&gt;
*'''Prochaine action horaire''' : recherche le composant qui a la '''Butée horaire sans marge''' la plus petite&lt;br /&gt;
*'''Butée horaire action''' : récupère sur le composant correspond à la '''Prochaine action horaire''', le champ '''Butée horaire sans marge'''&lt;br /&gt;
*'''Potentiel prochaine action horaire''' : résultat de la différence entre le champ '''Butée horaire action''' et le champ '''Cellule - Heures totales'''&lt;br /&gt;
&lt;br /&gt;
*'''Potentiel - Heures''' qui correspond au champ '''Potentiel prochaine action horaire prioritaire''' :&lt;br /&gt;
**si les champs '''Potentiel prochaine visite horaire''' et '''Potentiel prochaine action horaire''' sont définis, le champ avec la plus petite valeur sera celui utilisé pour définir le champ '''Potentiel prochaine action horaire prioritaire'''&lt;br /&gt;
**si un seul des deux champs est défini ce sera celui utilisé pour définir le champ '''Potentiel prochaine action horaire prioritaire'''&lt;br /&gt;
*'''Prochaine action horaire prioritaire''' : si c'est le champ '''Potentiel prochaine visite horaire''' qui a été retenu, la prochaine action sera donc celle correspondant au champ '''Prochaine visite horaire''' sinon ce sera celle du champ '''Prochaine action horaire'''&lt;br /&gt;
&lt;br /&gt;
*'''Prochaine visite calendaire''' : recherche la visite avec la plus petite périodicité calendaire. A partir du champ '''Groupe de chevauchement''', recherche parmi les visites qui sont dans ce groupe la visite avec la plus grande périodicité calendaire. Cette visite sera la '''prochaine visite calendaire'''.&lt;br /&gt;
*'''Butée calendaire visite''' : recherche parmi le suivi de la ressource, la visite avec la valeur la plus grande pour le champ '''Prochaine butée calendaire sans marge'''. Si une visite est trouvée, récupère la valeur de ce champ. Sinon récupère la valeur de ce champ dans le programme sur la visite défini comme étant la '''prochaine visite horaire'''.&lt;br /&gt;
*'''Potentiel prochaine visite calendaire ''' : résultat en mois de la différence entre le champ '''Butée calendaire visite''' et la date du jour&lt;br /&gt;
&lt;br /&gt;
*'''Prochaine action calendaire''' : recherche le composant qui a la '''Butée calendaire sans marge''' la plus petite&lt;br /&gt;
*'''Butée calendaire action''' : récupère sur le composant correspond à la '''Prochaine action calendaire''', le champ '''Butée calendaire sans marge'''&lt;br /&gt;
*'''Potentiel prochaine action calendaire ''' : résultat en mois de la différence entre le champ '''Butée calendaire action''' et la date du jour&lt;br /&gt;
&lt;br /&gt;
*'''Potentiel - Mois''' qui correspond au champ '''Potentiel prochaine action calendaire prioritaire''' :&lt;br /&gt;
**si les champs '''Potentiel prochaine visite calendaire''' et '''Potentiel prochaine action calendaire''' sont définis, le champ avec la plus petite valeur sera celui utilisé pour définir le champ '''Potentiel prochaine action calendaire prioritaire'''&lt;br /&gt;
**si un seul des deux champs est défini ce sera celui utilisé pour définir le champ '''Potentiel prochaine action calendaire prioritaire'''&lt;br /&gt;
*'''Prochaine action calendaire prioritaire''' : si c'est le champ '''Potentiel prochaine visite calendaire''' qui a été retenu, la prochaine action sera donc celle correspondant au champ '''Prochaine visite calendaire''' sinon ce sera celle du champ '''Prochaine action calendaire'''&lt;br /&gt;
&lt;br /&gt;
=Module de suivi du potentiel restant=&lt;br /&gt;
==Unité de mesure des heures==&lt;br /&gt;
L'unité de mesure des compteurs d'un aéronef correspond au [[Gestion des ressources#Ajouter_un_type_de_ressource|paramétrage du type de ressource]] correspondant.&lt;br /&gt;
&lt;br /&gt;
Par contre, l'unité de mesure des totaux d'heures correspond au [[Configuration#Gestion-des-vols|paramétrage de l'unité de temps de la plateforme]]. Cela permet d'avoir la tenue des carnets de route des aéronefs dans une seule unité quelque soit l'aéronef. De même pour les calculs des butées pour le suivi de navigabilité cela permet d'avoir une seule unité.&lt;br /&gt;
&lt;br /&gt;
==Activer le module de gestion des potentiels==&lt;br /&gt;
*'''Admin &amp;gt; Structure &amp;gt; Paramétrage &amp;gt; Activités'''&lt;br /&gt;
*Activer l'interrupteur '''Gestion des potentiels''' s'il n'est pas déjà activé&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
&lt;br /&gt;
===Initialisation de la gestion des potentiels===&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Ressources &amp;gt; Actives'''&lt;br /&gt;
*Cliquer sur l'icône Édition (le crayon)	&lt;br /&gt;
**Dans la partie inférieure '''Données pour la gestion des vols''' on initialise les valeurs :&lt;br /&gt;
**'''Date de début de comptabilisation des heures'''&lt;br /&gt;
**'''Total des heures à la date de début'''&lt;br /&gt;
Il faut indiquer dans ces 2 champs le nombre d'heures de la ressource et à quelle date il y avait ce nombre d'heures. Ainsi, OpenFlyers calculera le nombre d'heures de vols effectuées par l'aéronef à compter de cette date de début et en partant du total renseigné pour cette date. Seules les heures de vols dont la date sera postérieure à cette date de début seront prises en compte pour ce calcul.&lt;br /&gt;
&lt;br /&gt;
'''Attention :''' pour un calcul exact du potentiel restant, tous les vols postérieurs à la '''date de début de comptabilisation des heures''' doivent être saisis dans OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
===Affichage du potentiel estimé restant dans les créneaux de réservation===&lt;br /&gt;
Cela se fait en activant le champ additionnel spécifique [[Champs-métiers#bookingEstimatedFlightTime|bookingEstimatedFlightTime]].&lt;br /&gt;
&lt;br /&gt;
===Initialisation de la gestion des alertes===&lt;br /&gt;
*Aller sur '''Gestion &amp;gt; Ressources &amp;gt; Navigabilité'''&lt;br /&gt;
*Cliquer sur l'icône Édition (le crayon) :&lt;br /&gt;
**Régler les 3 seuils d'alerte pour les potentiels (exemple 10 h, 0 h et -5 h)&lt;br /&gt;
**Régler les 3 seuils d'alerte pour les dates calendaire (exemple 15 jours, 8 jours et 0 jours)&lt;br /&gt;
&lt;br /&gt;
==Butées de maintenance==&lt;br /&gt;
*Aller sur '''Gestion &amp;gt; Ressources &amp;gt; Navigabilité'''&lt;br /&gt;
&amp;lt;center&amp;gt;[[Image:Maintenance_table_fr.jpg|Tableau de bord maintenance]]&amp;lt;/center&amp;gt;&lt;br /&gt;
*Cliquer sur l'icône Modifier (le crayon) :&lt;br /&gt;
&amp;lt;center&amp;gt;[[Image:Maintenance_detail_fr.jpg|Maintenance]]&amp;lt;/center&amp;gt;&lt;br /&gt;
:Prochaine butée calendaire : c'est la date qui servira de référence pour les alertes calendaires (ex : renouvèlement CDN). En attendant le module de gestion de la maintenance, le mécanicien gère lui-même la butée en mettant la butée selon son programme d'entretien&lt;br /&gt;
:Prochaine butée horaire : c'est le compte horaire de référence. Le programme soustrait de cette valeur le nombre d'heure de référence indiqué dans la page Aéronef et le temps de vols saisi par les pilotes pour définir le potentiel restant&lt;br /&gt;
:Seuil des alertes : Il y a 3 niveaux d'alerte horaire et calendaire à mettre selon les souhaits du mécanicien. L'alerte visualisée sur le cahier de réservation sera la première des échéances atteintes&lt;br /&gt;
Le programme calcule à chaque vol le total des heures de vol depuis la date d'initialisation (HdV) et affiche le potentiel restant (Pot) à gauche du cahier journalier et affiche sous chaque réservation le potentiel estimé (durée indiquée par l'utilisateur lors de la réservation ou 50% de la durée de la réservation en absence d'information)&lt;br /&gt;
	&amp;lt;SQL&amp;gt;Potentiel = Prochaine butée horaire - (Total des heures à la date de début + HdV)&amp;lt;/SQL&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Le programme surveille ces 2 butées :&lt;br /&gt;
** Alerte visuelle si la date du jour approche les seuils de date calendaire.&lt;br /&gt;
** Alerte visuelle si on approche les seuils de fin de potentiel.&lt;br /&gt;
&lt;br /&gt;
Le survol de la souris sur le voyant indique si c'est la date ou le potentiel (ou les deux) qui a déclenché l'alerte&lt;br /&gt;
&lt;br /&gt;
* Il est conseillé de mettre à jour les valeurs d'initialisation une fois par an&lt;br /&gt;
&lt;br /&gt;
==Gestion des points fixes==&lt;br /&gt;
On appelle un point fixe le fait de faire tourner le moteur d'un aéronef pour en contrôler les paramètres sans que cela soit suivi d'un vol. Il s'agit d'une action prévue pour certaines opérations de maintenance.&lt;br /&gt;
&lt;br /&gt;
Pour les aéronefs équipés d'horamètres, le point fixe &amp;quot;fait tourner l'horamètre&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
OpenFlyers préconise de ne pas saisir les points fixes en tant que vol car il n'y a pas de vol réalisé. Cela évite de d'impacter inutilement le potentiel de l'aéronef qui est normalement déterminé uniquement par les heures de vols.&lt;br /&gt;
 &lt;br /&gt;
Aussi, à l'issu d'un point fixe, la seule action à effectuer dans OpenFlyers consiste à mettre à jour le compteur :&lt;br /&gt;
*'''Gestion &amp;gt; Ressources &amp;gt; Actives'''&lt;br /&gt;
*Cliquer sur l’icône &amp;quot;Crayon&amp;quot; dans la colonne '''Actions''' de la ligne de l'aéronef concerné&lt;br /&gt;
*Mettre à jour le champ '''Dernier compteur enregistré'''&lt;br /&gt;
*Valider&lt;br /&gt;
&lt;br /&gt;
Ainsi, lors de la prochaine saisie d'heure de vol, le compteur départ correspondra au compteur mis à jour. Cela n'empêchera pas l'utilisateur de voir s'afficher ensuite une alerte mais il pourra vérifier sur le carnet de route ou sur tout autre document mis en place par la structure que cet écart est justifié. De la même façon, lors de la [[#Valider-une-activité|validation des activités]], l'écart de compteur ressortira et sera justifiable.&lt;br /&gt;
&lt;br /&gt;
==Modification des butées suite à un vol validé mal saisi==&lt;br /&gt;
Si un vol a été validé et que l'on se rencontre à posteriori qu'il a été mal saisi, il faut alors intervenir pour corriger les erreurs de calcul de potentiel restant qui en résultent. Pour cela, il y a plusieurs possibilités :&lt;br /&gt;
*Si le vol saisi initialement a une durée inférieure au vol réellement effectué : il faut saisir un vol complémentaire dont la durée correspond au temps de vol manquant.&lt;br /&gt;
*Si le vol saisi initialement a une durée supérieure au vol réellement effectué : il faut reprendre la procédure d'[[#Initialisation-de-la-gestion-des-potentiels|initialisation de la gestion des potentiels]] pour enlever au temps cellule initial le temps de vol décompté en trop de sorte à avoir un potentiel restant qui soit juste.&lt;br /&gt;
&lt;br /&gt;
Du fait de l'[[Comptabilité#Inaltérabilité-des-données|inaltérabilité des données]], il n'est pas possible de modifier une écriture validée.&lt;br /&gt;
&lt;br /&gt;
Il ne faut pas oublier de [[Utilisation-de-la-comptabilité#Annuler-l'effet-d'une-écriture-comptable|corriger comptablement l'effet des écritures]].&lt;br /&gt;
&lt;br /&gt;
=Types de composants=&lt;br /&gt;
Les types de composants sont répertoriés dans un catalogue tenu à jour par OpenFlyers. Chaque type de composant est caractérisé par son étiquette et sa catégorie. Il existe 4 catégories définies ci-dessous :&lt;br /&gt;
&lt;br /&gt;
==Documents==&lt;br /&gt;
Il s'agit des documents nécessaires pour la gestion et la traçabilité des activités de maintenance. Ils incluent les manuels de maintenance, les bulletins de service, les certificats de conformité, les rapports d'inspection, etc.&lt;br /&gt;
&lt;br /&gt;
'''Exemples''' : Manuels de maintenance de l'aéronef (AMM), Certificat d'Examens de Navigation (CEN), Assurance, Fiche de pesée, etc.&lt;br /&gt;
&lt;br /&gt;
==Éléments==&lt;br /&gt;
Il s'agit des composants physiques individuels ou des parties spécifiques de l'aéronef, comme les pièces de rechange, les sous-ensembles, ou les équipements spécifiques.&lt;br /&gt;
&lt;br /&gt;
'''Exemples''' : Un moteur, un hélice, un train d'atterrissage, des instruments de cockpit, etc.&lt;br /&gt;
&lt;br /&gt;
==Inspections==&lt;br /&gt;
Il s'agit des activités spécifiques de vérification et de contrôle des composants ou des systèmes de l'aéronef pour s'assurer qu'ils sont en bon état de fonctionnement et conformes aux normes de sécurité.&lt;br /&gt;
&lt;br /&gt;
'''Exemples''' : Inspection de pré-vol, inspection de corrosion, contrôle non destructif (CND), etc.&lt;br /&gt;
&lt;br /&gt;
==Visites==&lt;br /&gt;
Il s'agit des visites planifiées pour la maintenance, qui peuvent inclure des vérifications générales, des réparations ou des remplacements de composants.&lt;br /&gt;
&lt;br /&gt;
'''Exemples''' : (50H, 100H, 600 H / 2 ANS, etc)&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Rapporter-un-bug&amp;diff=12906</id>
		<title>Rapporter un bug</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Rapporter-un-bug&amp;diff=12906"/>
		<updated>2024-10-02T17:28:01Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:BTS home.jpg|thumb]]&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
L'outil de gestion de tickets client d'OpenFlyers utilise le logiciel OpenProject disponible à l'adresse https://project.openflyers.com.&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir voir et créer un ticket, il est nécessaire de créer un compte. '''Ce compte est indépendant de votre accès à la plateforme OpenFlyers au gestionnaire client d'OpenFlyers'''.&lt;br /&gt;
&lt;br /&gt;
Nous sommes conscients que l'utilisation de cet outil nécessite un peu plus de temps pour rapporter une anomalie que l'envoi d'un email. Mais pour l'équipe de développement OpenFlyers, c'est un véritable gain de temps qui permet ainsi d'être plus efficace et donc de limiter les coûts.&lt;br /&gt;
&lt;br /&gt;
=Créer son compte=&lt;br /&gt;
*Se rendre sur le gestionnaire de ticket à l'adresse https://project.openflyers.com.&lt;br /&gt;
*En haut à droite, cliquer sur '''Connexion''', puis '''Créer un compte'''.&lt;br /&gt;
*Remplir le formulaire d'inscription. Le mot de passe doit contenir au moins 10 caractères.&lt;br /&gt;
&lt;br /&gt;
[[File:Inscription-BTS.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Un email de confirmation est envoyé par le BTS.&lt;br /&gt;
*Aller sur la messagerie pour retrouver cet e-mail et cliquer sur le lien permettant d'activer le compte.&lt;br /&gt;
L'envoi de l'e-mail est instantané mais il est possible de devoir attendre plusieurs minutes avant qu'il n'apparaisse dans la messagerie du fait d'un traitement par le serveur de messagerie recevant l'email. Si l'email n'est pas reçu, vérifier qu'il n'a pas été mis de côté (voir supprimé) par un outil anti-spam attaché à la messagerie. Enfin, si l'e-mail n'est pas retrouvé, il faut envoyer un e-mail au support OpenFlyers de demande d'activation manuelle du compte en nous précisant l'identifiant que choisi pour sa création.&lt;br /&gt;
*Cliquer sur le lien contenu dans le message pour activer votre compte.&lt;br /&gt;
*Se connecter.&lt;br /&gt;
&lt;br /&gt;
=Comment rapporter un bug=&lt;br /&gt;
*[[#Se-connecter|Se connecter]]&lt;br /&gt;
*Sur la page d'accueil, dans la case &amp;quot;Projets&amp;quot;, cliquer sur '''OpenFlyers'''.&lt;br /&gt;
*Dans le menu de gauche, cliquer sur '''Lots de travaux''' (ou '''Work Packages''' en anglais).&lt;br /&gt;
*Avant de rapporter un bug, prenez le temps d'effectuer les actions suivantes :&lt;br /&gt;
**Vérifier que le bug n'est pas déjà rapporté.&lt;br /&gt;
**Renseigner les items dès le début pour éviter l'envoi dans une rubrique non adaptée.&lt;br /&gt;
*Cliquer sur le bouton vert '''Créer'''&lt;br /&gt;
Un formulaire s'affiche avec comme titre '''New PROBLEME'''&lt;br /&gt;
*Remplir les champs '''titre''', '''description''' et '''Order Id'''&lt;br /&gt;
:*Dans le champ '''titre''' :&lt;br /&gt;
::*Indiquer entre parenthèses sur quelle plateforme OpenFlyers le problème est rencontré suivi d'un titre synthétisant le problème (exemple : ''(ac-nasa) Impossible de se connecter'')&lt;br /&gt;
:*Dans le champ '''description''' :&lt;br /&gt;
::*Préciser l'identifiant de l'utilisateur concerné&lt;br /&gt;
::*La description doit être la plus complète possible pour que les développeurs puissent reproduire le problème.&lt;br /&gt;
::*La nature &amp;quot;réelle&amp;quot; (non affichage, alerte, etc.) du problème et sa manifestation. &lt;br /&gt;
::*Quelles sont les actions qui conduisent au bug sous la forme de fils d'Ariane (exemple : '''Admin &amp;gt; Utilisateurs &amp;gt; Utilisateurs''' puis icône '''Modifier la fiche utilisateur''')&lt;br /&gt;
::*Joindre une copie d'écran est parfois plus explicite que de longs discours. Ne pas en abuser, on ne cherche pas à documenter un bug pour le contourner mais à fournir des explications au développeur pour qu'il puisse le traiter.&lt;br /&gt;
:*Dans le champ '''Order Id''' :&lt;br /&gt;
::*Mettre la valeur 0&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer'''.&lt;br /&gt;
&lt;br /&gt;
Remarques :&lt;br /&gt;
*En cours de traitement, utiliser les notes pour ajouter des informations, éviter les échanges par email parallèles.&lt;br /&gt;
*Lorsque le bug est résolu vous recevrez un email d'information :&lt;br /&gt;
:*Merci de bien vouloir confirmer que le bug est résolu en '''fermant votre rapport de bug'''.&lt;br /&gt;
:*Si vous constatez que la solution ne correspond pas à votre description (totale ou partielle), relancez le sujet en le changeant d'état.&lt;br /&gt;
:*Par contre si vous détectez une nouvelle anomalie rédigez un nouveau rapport de bug.&lt;br /&gt;
:La fermeture du Bug doit être effectuée par celui qui l'a émis.&lt;br /&gt;
:En l'absence d'action de votre part dans un temps raisonnable le développeur ou un administrateur le fermera.&lt;br /&gt;
&lt;br /&gt;
==Faire une copie d'écran==&lt;br /&gt;
Il est souvent utile de joindre une copie d'écran montrant le problème. Cela permet de montrer visuellement le problème et peut nous faire gagner un temps précieux à comprendre la description du problème.&lt;br /&gt;
&lt;br /&gt;
Le site de [http://www.commentcamarche.net www.commentcamarche.net] présente une explication sur [http://www.commentcamarche.net/faq/398-capture-d-ecran-copie-d-ecran comment réaliser des captures d'écran].&lt;br /&gt;
&lt;br /&gt;
Sous Windows, la combinaison de touches Alt + PrintScreen donne le meilleur résultat dans la plupart des cas : la fenêtre active est capturée et placée dans le presse papier. Il faut l'enregistrer avec un nom de fichier type jpg. Pour cela il existe une multitude de [http://www.commentcamarche.net/download/graphisme-9 logiciels de traitement d'images]. Ceci dépend des utilisations que vous souhaitez en faire :&lt;br /&gt;
*le plus simple est l'utilitaire Paint inclut dans Windows mais il n'est pas très pratique&lt;br /&gt;
*[http://www.gimp.org/ Gimp] est très complet mais lourd pour juste faire des copies d'écran&lt;br /&gt;
&lt;br /&gt;
[http://www.faststone.org/ FastStone] est pratique si vous devez capturer une page qui est plus grande que l'écran ou une portion de l'écran et il permet de sauver la capture au format que l'on souhaite.&lt;br /&gt;
&lt;br /&gt;
=Description des états et de l'avancement de la résolution=&lt;br /&gt;
==Etats==&lt;br /&gt;
{| {{prettytable}}&lt;br /&gt;
!Intitulé de l'état!!Description!!Qui devrait mettre cet état&lt;br /&gt;
|-&lt;br /&gt;
|nouveau||nouveau bug, c'est l'état initial||le rédacteur du bug&lt;br /&gt;
|-&lt;br /&gt;
|commentaire||le bug nécessite plus d'informations, le rédacteur du bug devrait y préter attention||un gestionnaire ou un développeur&lt;br /&gt;
|-&lt;br /&gt;
|accepté||le bug a été lu mais n'est ni confirmé ni assigné||un gestionnaire ou le développeur dont dépend le bug&lt;br /&gt;
|-&lt;br /&gt;
|confirmé||le bug est confirmé et reproductible||un gestionnaire ou un développeur&lt;br /&gt;
|-&lt;br /&gt;
|assigné||le bug est assigné à un développeur||un gestionnaire ou un développeur qui le prend en charge&lt;br /&gt;
|-&lt;br /&gt;
|résolu||le bug devrait être résolu, en attente de la confirmation de sa résolution par le rédacteur du bug||le développeur qui a corrigé le bug&lt;br /&gt;
|-&lt;br /&gt;
|fermé||le bug est fermé||le rédacteur initial du bug ou un gestionnaire ayant confirmé le bug&lt;br /&gt;
|}&lt;br /&gt;
==Résolutions==&lt;br /&gt;
{| {{prettytable}}&lt;br /&gt;
!Intitulé de la résolution!!Description&lt;br /&gt;
|-&lt;br /&gt;
|ouvert||bug ouvert en attente&lt;br /&gt;
|-&lt;br /&gt;
|résolu||bug résolu d'après le développeur responsable&lt;br /&gt;
|-&lt;br /&gt;
|réouvert||bug considéré comme toujours existant après correction&lt;br /&gt;
|-&lt;br /&gt;
|impossible à reproduire||le bug rapporté n'arrive pas à être reproduit&lt;br /&gt;
|-&lt;br /&gt;
|impossible à corriger||il n'y a pas de possibilité de corriger le bug&lt;br /&gt;
|-&lt;br /&gt;
|doublon||le bug a déjà fait l'objet d'un rapport dans le BTS&lt;br /&gt;
|-&lt;br /&gt;
|pas un bug||Ce n'est pas considéré comme un bug&lt;br /&gt;
|-&lt;br /&gt;
|suspendu||Le bug est mis de côté&lt;br /&gt;
|-&lt;br /&gt;
|ne sera pas résolu||Le bug est reconnu mais ne sera pas résolu&lt;br /&gt;
|}&lt;br /&gt;
=Comment fermer un rapport ?=&lt;br /&gt;
Une fois qu'un rapport est positionné sur &amp;quot;résolu&amp;quot;, voici comment procéder pour le fermer :&lt;br /&gt;
*Cliquer sur le bouton &amp;quot;Rouvrir&amp;quot;&lt;br /&gt;
*Mettre l'état du bug sur &amp;quot;fermer&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=Se connecter=&lt;br /&gt;
*Aller sur https://project.openflyers.com&lt;br /&gt;
*Cliquer en haut à droite sur le bouton '''Connexion'''&lt;br /&gt;
*Renseigner l'adresse l'email de connexion dans le champ '''Nom d'utilisateur'''&lt;br /&gt;
*Renseigner le champ '''Mot de passe'''&lt;br /&gt;
*Cliquer sur le bouton '''Connexion'''&lt;br /&gt;
&lt;br /&gt;
=Traitement des bugs dans le BTS (pour les développeurs et gestionnaires)=&lt;br /&gt;
*Lorsqu'un bug est résolu il faut faire attention à le marquer comme tel dans la '''version en cours''' de modif (=donc normalement la future version publiée)&lt;br /&gt;
*La fermeture du Bug doit être effectuée par celui qui l'a reporté.&lt;br /&gt;
*En l'absence d'action de sa part dans un temps raisonnable un gestionnaire le fermera.&lt;br /&gt;
'''Suivez vos bugs'''&lt;br /&gt;
&lt;br /&gt;
=Interopérabilité=&lt;br /&gt;
==JavaScript==&lt;br /&gt;
Les interactions dynamiques d'OpenFlyers nécessitent que JavaScript soit actif. Voici une page du support AdSense de Google qui présente [https://www.google.com/adsense/support/bin/answer.py?hl=fr&amp;amp;answer=12654 les différentes méthodes d'activation de JavaScript] en fonction du navigateur.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Pr%C3%A9sentation-d%27OpenFlyers-4&amp;diff=12905</id>
		<title>Présentation d'OpenFlyers 4</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Pr%C3%A9sentation-d%27OpenFlyers-4&amp;diff=12905"/>
		<updated>2024-10-02T17:28:00Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
=Migrer vers OpenFlyers 4=&lt;br /&gt;
==Les nouveautés de la version 4==&lt;br /&gt;
OpenFlyers repense son interface avec la version 4 afin d'offrir un confort d'utilisation pour les utilisateurs disposant d'écran à forte résolution ou d'écrans tactiles.&lt;br /&gt;
&lt;br /&gt;
Ainsi, la version 4 est prévue être accessible via trois interfaces graphiques différentes :&lt;br /&gt;
*L'[[#Appli-OpenFlyers|appli téléchargeable]] (actuellement en développement).&lt;br /&gt;
*L'[[#Interface-dynamique|interface dynamique]] (en version alpha)&lt;br /&gt;
*L'[[#Interface-légère|interface légère]] qui correspond à l'interface historique d'OpenFlyers qui a fait son succès et qui a été rafraichie pour l'occasion afin de garder un caractère moderne tout en maintenant sa légèreté qui lui permet d'être facilement utilisable dans des lieux où le débit du réseau est limité.&lt;br /&gt;
&lt;br /&gt;
Outre ses nouvelles interfaces, OpenFlyers 4 offre de nombreuses nouvelles fonctionnalités et continue de s'enrichir au fil des semaines en fonction des demandes de ses clients. Notamment le stockage des validités permet aux organismes ATO ou DTO de dématérialiser l'archivage des documents associés à certaines validités des utilisateurs tout en étant conforme à la réglementation.&lt;br /&gt;
&lt;br /&gt;
De nombreuses nouvelles fonctionnalités sont disponibles. Il est possible de retrouver la liste complète dans l'historique des versions :&lt;br /&gt;
&lt;br /&gt;
https://openflyers.com/fr/doc/of4/Historique-des-versions&lt;br /&gt;
&lt;br /&gt;
==Tester la version 4 avant de migrer==&lt;br /&gt;
Il est possible pour les clients sous version 3.6 de [[Compte-client-OpenFlyers-et-modèle-commercial#Plateforme-supplémentaire-de-test|créer automatiquement une recopie de leur base de données sur une plateforme OF4]] pour pouvoir la découvrir et la tester avant de passer en production dessus.&lt;br /&gt;
&lt;br /&gt;
Pour les autres clients, il suffit d'aller sur une plateforme de démonstration :&lt;br /&gt;
https://openflyers.com/fr/etudes-cas&lt;br /&gt;
&lt;br /&gt;
==Demander à migrer vers la version 4==&lt;br /&gt;
Les clients disposant d'une plateforme OpenFlyers sous une ancienne version et souhaitant migrer vers la version 4 peuvent le faire très simplement en effectuant les actions suivantes :&lt;br /&gt;
*Uniquement pour les clients First-Price : créer et payer la facture de 100 € HT de demande de migration dans l'espace client https://client.openflyers.com&lt;br /&gt;
*Pour tous les clients : envoyer un email à OpenFlyers en tant que responsable OpenFlyers de sa structure et demandant la migration.&lt;br /&gt;
&lt;br /&gt;
Dans l'email, il faut préciser s'il faut activer l'interface dynamique qui est, pour le moment, en version &amp;quot;alpha&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
En général, la migration est effectuée la semaine suivant la demande sauf le vendredi et de préférence le lundi.&lt;br /&gt;
&lt;br /&gt;
'''Attention''' : la migration est irréversible et les rapports personnalisés ne sont pas mis à jour. D'ailleurs l'accès à ces derniers est supprimé sauf demande express pour les conserver. Il est recommandé de ne le faire que si la structure dispose d'un informaticien qui s'engage à les maintenir.&lt;br /&gt;
&lt;br /&gt;
=Les interfaces de la version 4=&lt;br /&gt;
==Appli OpenFlyers==&lt;br /&gt;
Une appli OpenFlyers est en cours de finalisation. Elle sera téléchargeable dans un premier temps sous Android puis ensuite sous iOS.&lt;br /&gt;
&lt;br /&gt;
==Interface légère==&lt;br /&gt;
L'interface légère correspond à l'interface historique d'OpenFlyers. Elle contient non seulement l'ensemble des fonctionnalités qui étaient présentes sur l'ancienne version 3 mais également les nouvelles fonctionnalités qui font leur apparition progressivement sur la version 4 en fonction des demandes des clients. Cette interface a le mérite de pouvoir être facilement accessible lorsque la connexion internet souffre d'un débit limité.&lt;br /&gt;
&lt;br /&gt;
=Refonte complète du design et de l'ergonomie=&lt;br /&gt;
&lt;br /&gt;
==Fil d'Ariane==&lt;br /&gt;
Le [[Wikipedia-fr:Fil_d'Ariane_(ergonomie)|fil d'Ariane]] est présent uniquement sur l'[[#Interface-légère|interface légère]]. En effet, il est construit d'après l'[[Wikipedia-fr:Arborescence|arborescence]] de la plateforme, celle-ci correspondant aux différents niveaux des menus et sous-menus.&lt;br /&gt;
&lt;br /&gt;
L'[[#Interface-dynamique|interface dynamique]] ne contient pas de fil d'Ariane car le [[Menu-de-l'interface-dynamique|menu]] est potentiellement ré-organisable par l'utilisateur.&lt;br /&gt;
&lt;br /&gt;
==Interface graphique==&lt;br /&gt;
&lt;br /&gt;
===Emails===&lt;br /&gt;
&lt;br /&gt;
====Aspect====&lt;br /&gt;
[[File:Mailing.png]]&lt;br /&gt;
====Types d'emails====&lt;br /&gt;
*[[Envoi-des-emails|E-mails automatiques]]&lt;br /&gt;
*[[Mailing|Mailing]]&lt;br /&gt;
&lt;br /&gt;
===Interface multi-supports===&lt;br /&gt;
====Adaptation aux différentes résolutions d'écrans====&lt;br /&gt;
L'interface graphique d'OpenFlyers4 a été conçue pour '''s'adapter''' à l'écran de l'utilisateur. Que l'écran soit large (PC) ou étroit (tablette en mode portrait et bientôt sur smarphone), les éléments se redisposent de manière à offrir lecture et interactions optimisées.&lt;br /&gt;
&lt;br /&gt;
====Optimisation pour l'utilisation tactile====&lt;br /&gt;
Les interactions sont aisément réalisables sur écrans tactiles :&lt;br /&gt;
*De nombreuses actions s'effectuent par '''balayage''' ou '''glisser-déposer'''.&lt;br /&gt;
*La '''taille''' des éléments est suffisamment grande pour les manipulations tactiles.&lt;br /&gt;
&lt;br /&gt;
===[[Ergonomie#Gestes|Gestes]]===&lt;br /&gt;
&lt;br /&gt;
==[[Menu de navigation]]==&lt;br /&gt;
&lt;br /&gt;
==Planning de réservation==&lt;br /&gt;
&lt;br /&gt;
[[File:OF4-planning-doigt.png]]&lt;br /&gt;
&lt;br /&gt;
====[[Aspect du planning de réservation|Palette d'outils associée au planning]]====&lt;br /&gt;
L'interaction entre les lignes du planning et la palette d'outils permet une gestion dynamique des réservations.&lt;br /&gt;
&lt;br /&gt;
====[[Aspect du planning de réservation#Iconographie|Pictogrammes et code-couleurs]]====&lt;br /&gt;
De nombreux éléments visuels pour accéder rapidement à l'information et aux interactions.&lt;br /&gt;
&lt;br /&gt;
====Visualisation immédiate des ressources====&lt;br /&gt;
Chaque [[Glossaire|ressource]] est identifiée par un pictogramme dédié, quel que soit l'emplacement où elle se trouve : [[Aspect du planning de réservation#Palette_d'outils|palette d'outils]], [[Aspect du planning de réservation#Lignes_du_planning|lignes du planning]], [[Aspect du planning de réservation#Composition_d'une_réservation|réservation]].&lt;br /&gt;
&lt;br /&gt;
====[[Aspect du planning de réservation#Réservations_de_l'utilisateur_connecté|Réservations de l'utilisateur connecté]]====&lt;br /&gt;
Pour distinguer immédiatement ses propres réservations.&lt;br /&gt;
&lt;br /&gt;
====[[Utilisation du planning de réservation#Redimensionnement|Redimensionnement de la réservation]]====&lt;br /&gt;
Le redimensionnement s'effectue directement sur les lignes du planning, par glisser-déposer.&lt;br /&gt;
&lt;br /&gt;
====[[Utilisation du planning de réservation#Réservation_incomplète|Réservations incomplètes]]====&lt;br /&gt;
Les réservations, même incomplètes, sont matérialisées sur le planning et affectées à un utilisateur.&lt;br /&gt;
&lt;br /&gt;
===Publicité===&lt;br /&gt;
La publicité permet à OpenFlyers de proposer des [https://openflyers.com/fr/tarifs tarifs d'abonnements] modiques à ses clients. &lt;br /&gt;
&lt;br /&gt;
Elle s'affiche sous forme de bannières sur le [[Aspect du planning de réservation|planning de réservation]], la page de [[connexion]] et les [[#Emails|emails]], selon la formule d'abonnement choisie.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Formule d'abonnement!!Publicité sur le planning!!Publicité sur la page de connexion et les emails&lt;br /&gt;
|-&lt;br /&gt;
|[[#Solo|Solo]]||Oui||Oui&lt;br /&gt;
|-&lt;br /&gt;
|[[#First Price|First Price]]||Oui||Oui&lt;br /&gt;
|-&lt;br /&gt;
|[[#Business|Business]]||Non||Oui&lt;br /&gt;
|-&lt;br /&gt;
|[[#Business+|Business+]]||Non||Non&lt;br /&gt;
|-&lt;br /&gt;
|[[#Première|Première]]||Non||Non&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==[[Tableaux|Tableaux]]==&lt;br /&gt;
[[File:Table4-1-generic.png]]&lt;br /&gt;
&lt;br /&gt;
====[[Aspect des tableaux#Adaptation_à_la_taille_de_l'écran|Adaptation à la taille de l'écran]]====&lt;br /&gt;
Les dimensions du tableau s'adaptent à celles de l'écran de l'utilisateur. Il est ensuite possible de faire coulisser le contenu dans l'espace disponible. Ainsi, le contenu reste facilement accessible, quel que soit le support.&lt;br /&gt;
&lt;br /&gt;
====[[Utilisation des tableaux#Édition_des_données|Éditions des données]]====&lt;br /&gt;
Mise à jour instantanée, sans rechargement de page.&lt;br /&gt;
&lt;br /&gt;
====[[Utilisation des tableaux#Ordonnancement|Ordonnancement]]====&lt;br /&gt;
Il est possible de changer l'ordre des lignes du tableau par glisser-déposer.&lt;br /&gt;
&lt;br /&gt;
====[[Utilisation des tableaux#Ajout/suppression-de-ligne|Ajouter et supprimer des lignes]]====&lt;br /&gt;
L'utilisateur peut ajouter ou supprimer des lignes rapidement.&lt;br /&gt;
&lt;br /&gt;
====[[Aspect des tableaux#Tableau_à_onglets|Tableaux à onglets]]====&lt;br /&gt;
Certains tableaux comportent plusieurs sections. Celles-ci sont accessibles par onglets.&lt;br /&gt;
&lt;br /&gt;
====[[Aspect des tableaux#Tableaux_à_pages|Tableaux à pages]]====&lt;br /&gt;
Certains tableau comportent des tableaux imbriqués. Ceux-ci sont accéssibles depuis le premier tableau grâce à un système de pagination.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Utilisation-des-r%C3%A9servations-internes-sur-l%27interface-web&amp;diff=12904</id>
		<title>Utilisation des réservations internes sur l'interface web</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Utilisation-des-r%C3%A9servations-internes-sur-l%27interface-web&amp;diff=12904"/>
		<updated>2024-10-02T17:27:59Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter le planning et le formulaire de réservation de l'[[Présentation-d'OpenFlyers-4#Interface-légère|interface légère]] de la [[Accueil|version 4 d'OpenFlyers]].&lt;br /&gt;
&lt;br /&gt;
=Aspect du planning de réservation=&lt;br /&gt;
==Activité ouverte==&lt;br /&gt;
Lorsqu'une activité et en cours :&lt;br /&gt;
*Le créneau horaire correspondant est coloré en bleu vif.&lt;br /&gt;
*Dans la zone de titre de ligne, un pictogramme animé apparaît, coloré du même bleu. Pour l'aéronautique, ce pictogramme représente un avion qui décolle.&lt;br /&gt;
&lt;br /&gt;
[[File:planning-int-leg-activite-1.png]]&lt;br /&gt;
&lt;br /&gt;
==Affichage des activités sur les réservations==&lt;br /&gt;
Cette fonctionnalité permet d'afficher les types d'activités associés à une réservation directement sur l'affichage de la réservation dans le planning sans avoir besoin de la survoler.&lt;br /&gt;
&lt;br /&gt;
Cet affichage est en place lorsque l'utilisateur connecté dispose du droit [[Gestion-des-profils#Voir-les-activités-sur-les-réservations|Voir les activités sur les réservations]].&lt;br /&gt;
&lt;br /&gt;
==Affichage des images des pilotes sur le menu contextuel==&lt;br /&gt;
Cette fonctionnalité permet d'afficher les images des personnes associées à une réservation sur le menu contextuel lorsqu'on survole ou effectue un clic droit sur une réservation dans le planning.&lt;br /&gt;
&lt;br /&gt;
Cet affichage est en place lorsque l'utilisateur connecté dispose du droit [[Gestion-des-profils#Voir-les-images-des-pilotes-sur-le-menu-contextuel|Voir les images des pilotes sur le menu contextuel]].&lt;br /&gt;
&lt;br /&gt;
[[File:images-des-pilots-sur-la-réservation.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==Créneaux horaires==&lt;br /&gt;
Lorsqu'une réservation ne comporte pas de nom, les intitulés des activités apparaissent sur le créneau de la réservation.&lt;br /&gt;
&lt;br /&gt;
==Places disponibles==&lt;br /&gt;
Lorsqu'une ou plusieurs places sont indiquées comme disponibles pour une réservation, alors un pictogramme représentant un siège apparaît dans le créneau correspond à cette réservation. &lt;br /&gt;
&lt;br /&gt;
Le nombre de places disponibles y est précisé : +1, +2, ou +3.&lt;br /&gt;
&lt;br /&gt;
[[File:places-disponibles.png|400px]]&lt;br /&gt;
&lt;br /&gt;
==Planning par type d'activité==&lt;br /&gt;
Lorsqu'un type d'activité est sélectionné, seuls les créneaux horaires réservés avec le type d'activité sélectionné sont affichés. En revanche, les autres plages horaires réservées sont affichées sur fond gris hachuré.&lt;br /&gt;
&lt;br /&gt;
[[File:planning_By_Activity_Type.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Positionner automatiquement les activités d’un programme de formation==&lt;br /&gt;
Si la plateforme dispose du droit [[Gestion-des-profils#Réservation-de-programmes|réservation de programmes]] et des programmes de formation définis, lorsqu'on survole un créneau horaire dans le planning, un menu contextuel s'affiche, proposant les actions suivantes :&lt;br /&gt;
*'''Ajouter une réservation...''': Cette option permet de réaliser une réservation simple en affichant le [[#Formulaire-de-réservation|formulaire de réservation]].&lt;br /&gt;
*'''Ajouter un programme...''': En choisissant cette option, un pop-up s'affiche, permettant de sélectionner un programme de formation à ajouter au planning pour un utilisateur/client spécifique. En cliquant sur &amp;quot;Ajouter&amp;quot;, des créneaux de réservation sont automatiquement générés si des ressources compatibles avec le type d'activité sont disponibles. Dans le cas contraire, ces créneaux sont placés dans une nouvelle ligne appelée &amp;quot;Activité non placée&amp;quot;. Cette ligne est positionnée au début du planning, juste après la barre des heures, et reste fixe en haut de la page lorsque l'on fait défiler la page.&lt;br /&gt;
&lt;br /&gt;
En survolant l'un des créneaux créés, tous les créneaux des réservations et des activités non placées du même programme s'affichent avec un effet de mise en surbrillance jaune. Pour supprimer tous les créneaux créés, il suffit de survoler l'un des créneaux de réservation et de cliquer sur l'action '''Annuler la réservation et les réservations liées'''.&lt;br /&gt;
&lt;br /&gt;
Pour positionner une activité non placée, il est possible de soit la [[#Glisser-déposer-des-réservations|glisser-déposer]]  à l'emplacement souhaité dans le planning, soit de cliquer sur le créneau pour afficher le [[#Formulaire-de-réservation|formulaire de réservation]].&lt;br /&gt;
&lt;br /&gt;
=Ergonomie sur écran tactile=&lt;br /&gt;
==Appui court==&lt;br /&gt;
L'appui court au-dessus d'une réservation affiche le menu contextuel.&lt;br /&gt;
&lt;br /&gt;
==Appui suivi d'un déplacement==&lt;br /&gt;
L'appui sui d'un déplacement peu de temps après l'appui fait déplacer tout le planning.&lt;br /&gt;
&lt;br /&gt;
==Appui long==&lt;br /&gt;
L'appui long au-dessus d'une réservation sans bouger le doigt permet de [[#Glisser-déposer-des-réservations|glisser-déposer]] un créneau de réservation.&lt;br /&gt;
&lt;br /&gt;
==Double-clic==&lt;br /&gt;
Double-clic au-dessus d'une réservation permet d'afficher le formulaire de réservation.&lt;br /&gt;
&lt;br /&gt;
=Glisser-déposer des réservations=&lt;br /&gt;
La fonction de glisser-déposer est active pour tout utilisateur qui dispose du droit de réservation pour lui-même. Dans ce cas, il ne peut effectuer cette opération que pour les réservations qui le concerne.&lt;br /&gt;
&lt;br /&gt;
;Écran non tactile&lt;br /&gt;
*Survoler la réservation qui a besoin d'être déplacée&lt;br /&gt;
Le pointeur de la souris se transforme en &amp;quot;4 flèches&amp;quot;.&lt;br /&gt;
*Appuyer sur le bouton gauche de la souris pour sélectionner la réservation&lt;br /&gt;
*Déplacer la souris tout en maintenant le bouton gauche appuyé afin de déplacer le créneau de réservation sur le nouvel horaire et/ou la nouvelle ressource souhaités&lt;br /&gt;
*Relâcher le bouton gauche afin que la réservation soit mise à jour&lt;br /&gt;
Un pictogramme (roue qui tourne) apparaît en haut à gauche du rectangle de la réservation pour symboliser la mise à jour en base de données.&lt;br /&gt;
&lt;br /&gt;
Lorsque cette mise à jour est effective, le pictogramme est remplacé pendant quelques secondes par une « check » verte.&lt;br /&gt;
&lt;br /&gt;
;Écran tactile&lt;br /&gt;
*Maintenir un appui prolongé avec le doigt sur une réservation qui a besoin d'être déplacée&lt;br /&gt;
Un pictogramme &amp;quot;4 flèches&amp;quot; s'affiche en haut à gauche du rectangle symbolisant la réservation&lt;br /&gt;
*Déplacer son doigt afin de déplacer le créneau de réservation sur le nouvel horaire et/ou la nouvelle ressource souhaités&lt;br /&gt;
*Relâcher le doigt afin que la réservation se mette à jour&lt;br /&gt;
Un pictogramme (roue qui tourne) apparaît en haut à gauche du rectangle de la réservation pour symboliser la mise à jour en base de données.&lt;br /&gt;
&lt;br /&gt;
Lorsque cette mise à jour est effective, le pictogramme est remplacé pendant quelques secondes par une « check » verte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Un utilisateur disposant du droit d'effectuer des réservations pour des tiers peut procéder de la même façon pour toutes les réservations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lors du déplacement d'une réservation :&lt;br /&gt;
*si une alerte bloquante est générée elle est affichée et empêche le déplacement de la réservation&lt;br /&gt;
*si une alerte non bloquante est générée, elle n'est affichée que si le paramètre [[Configuration#Afficher-les-alertes-non-bloquantes-lors-des-glisser-déposer|Afficher les alertes non bloquantes lors des glisser-déposer]] est activé.&lt;br /&gt;
&lt;br /&gt;
=Formulaire de réservation=&lt;br /&gt;
[[File:Formulaire_reservation_ancienne_interface.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Type d'activité par défaut==&lt;br /&gt;
&lt;br /&gt;
Il est possible de cocher automatiquement un type d'activité sur le formulaire de réservation :&lt;br /&gt;
* Pour définir le type par défaut lors d'une nouvelle réservation ou lorsqu'on sélectionne une personne en première place, [[Configuration#Type-d'activité-par-défaut|suivre cette procédure de paramétrage]]&lt;br /&gt;
* Pour définir le type par défaut lorsqu'on sélectionne une personne en seconde place, [[Configuration#Type-d'activité-par-défaut-pour-la-seconde-place-(ancienne-interface)|suivre cette procédure de paramétrage]]&lt;br /&gt;
&lt;br /&gt;
=Préparer un vol=&lt;br /&gt;
OpenFlyers est couplé avec [[Airmate]] pour aider les pilotes à préparer leur vol. Ainsi, depuis OpenFlyers il est possible de :&lt;br /&gt;
*coupler une réservation avec une préparation de vol Airmate en survolant la réservation concernée pour faire apparaitre le menu contextuel, puis de sélectionner l'item de menu '''Préparer le vol...'''&lt;br /&gt;
*créer un nouveau vol dans Airmate en cliquant sur l'item de menu '''Préparation vol &amp;gt; Préparer un vol'''&lt;br /&gt;
Voir la page [[Airmate]] pour les détails concernant l'inscription à Airmate et la synchronisation réservation/vol.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Param%C3%A9trage-des-validit%C3%A9s&amp;diff=12903</id>
		<title>Paramétrage des validités</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Param%C3%A9trage-des-validit%C3%A9s&amp;diff=12903"/>
		<updated>2024-10-02T17:27:59Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter le paramétrage des [[Validités#Définitions|validités]] sur la [[Accueil|version 4 d'OpenFlyers]].&lt;br /&gt;
&lt;br /&gt;
Il existe également une page qui traite de l'[[Validités|utilisation des validités]].&lt;br /&gt;
&lt;br /&gt;
=Ajouter un type de validités=&lt;br /&gt;
*'''Admin &amp;gt; Utilisateurs &amp;gt; Types de validités'''&lt;br /&gt;
*Cliquer sur le bouton '''Ajouter un type de validité'''&lt;br /&gt;
*Remplir les champs [[#Paramètres_de_configuration|en fonction du comportement attendu]].&lt;br /&gt;
*Cliquer sur le bouton '''Valider'''&lt;br /&gt;
La validité s'insère dans le tableau qui est trié par ordre alphabétique&lt;br /&gt;
&lt;br /&gt;
==Paramètres de configuration==&lt;br /&gt;
&lt;br /&gt;
===Nom===&lt;br /&gt;
Nom choisi pour désigner une validité&lt;br /&gt;
&lt;br /&gt;
===Soumise à échéance===&lt;br /&gt;
Indique si la validité doit contenir une date d'échéance ou non&lt;br /&gt;
&lt;br /&gt;
===Gestion du code identifiant===&lt;br /&gt;
Indique si un champ &amp;quot;code identifiant&amp;quot; est éditable pour y renseigner un code associé à la validité de l'utilisateur. Exemples : numéro de membre, numéro de licence, numéro de qualification, identifiant, etc.&lt;br /&gt;
&lt;br /&gt;
===Gestion de la date d'obtention===&lt;br /&gt;
Indique si un champ &amp;quot;date d'obtention&amp;quot; doit être associé à la validité.&lt;br /&gt;
Exemples : date de délivrance d'un permis, date d'obtention d'un brevet, 1ère date d'inscription&lt;br /&gt;
&lt;br /&gt;
===Associer un document===&lt;br /&gt;
Indique s'il est possible d'associer un document à une validité. Un document est constitué d'une ou plusieurs pages. Chaque page a un nom et peut être indépendamment obligatoire ou non. Lorsque le paramètre &amp;quot;associer un document&amp;quot; est activé pour un type de validité, les utilisateurs peuvent [[Validités#Téléverser-un-fichier|téléverser un fichier]] pour chaque page afin de l'associer à la validité correspondante dans l'[[Validités#Consulter-et-gérer-ses-validités-ou-celles-d'un-tiers|interface des validités]].&lt;br /&gt;
&lt;br /&gt;
===Validité bloquante pour la saisie (si requise)===&lt;br /&gt;
Indique le comportement pour ce type de validité que doit adopter OpenFlyers lors d'une tentative de saisie d'activité ou de réservation dont une validité requise est périmée ou absente. Si la validité est configurée comme bloquante, alors la saisie sera bloquée et impossible.&lt;br /&gt;
&lt;br /&gt;
C'est utile en mode ouverture/fermeture d'activité où il est alors possible lors de l'ouverture de l'activité d'interdite un utilisateur de saisir son activité s'il manque un certain nombre de validités.&lt;br /&gt;
&lt;br /&gt;
===Validité bloquante pour le contrôle d'accès (lorsque requise par un type de ressource)===&lt;br /&gt;
Cette colonne est visible uniquement dans le cas où un contrôle d'accès spécifique est interfacé avec OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
Elle permet de définir si une validité doit bloquer une autorisation d'accès gérée par un système de contrôle d'accès.&lt;br /&gt;
&lt;br /&gt;
Le comportement du blocage est le suivant :&lt;br /&gt;
*OpenFlyers liste les validités qui ne sont pas détenues par un utilisateur et qui sont des [[#Paramétrer-pour-chaque-type-de-ressource-les-validités-requises|validités qui sont requises pour un type de ressource]].&lt;br /&gt;
*Si dans cette liste, il existe des validités qui sont marquées bloquantes pour le contrôle d'accès alors l'accès n'est pas autorisé.&lt;br /&gt;
&lt;br /&gt;
===Alerte à la connexion===&lt;br /&gt;
Définit le comportement souhaité pour [[Connexion#Alertes-à-la-connexion|les contrôles des validités à la connexion]]. 4 types de comportements sont possibles lorsqu'une validité à échéance est périmée ou que l'expérience requise par la validité n'est pas suffisante :&lt;br /&gt;
*'''Pas de gestion''' : La validité n'est pas contrôlée à la connexion&lt;br /&gt;
*'''Alerte à la connexion''' : Affichage d'une [[Présentation générale des alertes#Description|alerte non bloquante]].&lt;br /&gt;
*'''[[Connexion#Restriction_d'accès|Accès restreint au profil X]]''' (où X peut désigner tout profil définit pour la plateforme) : Affichage d'une [[Présentation générale des alertes#Description|alerte non bloquante]] et qui induit des restrictions sur les droits de l'utilisateur.&lt;br /&gt;
*'''Pas d'accès''' : Affichage d'une [[Présentation générale des alertes#Description|alerte bloquante]].&lt;br /&gt;
'''Attention :''' une validité est considérée comme obsolète si les critères suivants sont remplis :&lt;br /&gt;
*Elle est détenue par l'utilisateur&lt;br /&gt;
*Sa date d'échéance est renseignée&lt;br /&gt;
*Sa date d'échéance est passée&lt;br /&gt;
Ainsi, si un utilisateur ne dispose pas de la validité, il ne sera pas alerté ou bloqué à la connexion. De la même façon, un utilisateur qui dispose d'une validité sans que la date d'échéance ne soit renseignée ne sera également pas impacté.&lt;br /&gt;
&lt;br /&gt;
A noter également qu'un utilisateur qui dispose d'un profil ayant le droit de [[Gestion-des-profils#Surpasser-les-restrictions-sur-les-validités-expirées|surpasser les restrictions sur les validités expirées]] ne sera pas bloqué à la connexion si la restriction en place est '''Pas d'accès'''. Il aura une alerte surpassable.&lt;br /&gt;
&lt;br /&gt;
===Formule d'expérience===&lt;br /&gt;
Lorsque ce champ est renseigné avec une formule, alors le type de validité devient une [[Validités#Validité-à-expérience|validité à expérience]]. Dans ce cas, la validité ne peut plus être attribuée à un utilisateur. Elle sert à vérifier que l'utilisateur remplit des critères variables au cours du temps. Elle est compatible avec tous les [[Validités#Contrôle-des-validités|cas de contrôle de validité]].&lt;br /&gt;
&lt;br /&gt;
Exemples de validités à formule d'expérience :&lt;br /&gt;
*avoir plus de 3 atterrissages dans les 90 derniers jours&lt;br /&gt;
*ne pas dépasser plus de 90h dans les 30 derniers jours&lt;br /&gt;
cf. [[Formules de calcul#Expérience_récente|les formules de calcul d'expérience récente]].&lt;br /&gt;
&lt;br /&gt;
Note : une validité à expérience ne peut, par conception, être attribuée à un utilisateur puisqu'il s'agit d'un test. Il existe une protection qui empêche de transformer un type de validité, attribué à au moins un utilisateur, en validité à expérience. Cette protection affiche le message d'erreur '''Vous ne pouvez ajouter de formule d'expérience car des utilisateurs sont encore liés à cette validité'''. Il est important de noter que même si le type de validité est supprimé de tous les utilisateurs, cette suppression n'est pas forcément complète en base de données et qu'il reste donc en mémoire le fait que ce type de validité a été associé à des utilisateurs. Dans ce cas, il n'est pas possible de transformer le type de validité en validité à expérience.&lt;br /&gt;
&lt;br /&gt;
===Alerte échéance par email : 1er rappel===&lt;br /&gt;
Ce champ ne peut être renseigné que pour les [[#Soumise-à-échéance|validités soumises à échéance]]. Il indique la période d'échéance pour déclencher le [[Envoi-des-emails#Email-de-rappel-d'échéance-de-validité|premier rappel par email]].&lt;br /&gt;
&lt;br /&gt;
Les validités sans date d'échéance ne déclenchent pas l'[[Envoi-des-emails#Email-de-rappel-d'échéance-de-validité|envoi du rappel]].&lt;br /&gt;
&lt;br /&gt;
Les emails de rappels ne sont pas envoyés aux utilisateurs désactivés.&lt;br /&gt;
&lt;br /&gt;
===Fréquence===&lt;br /&gt;
&lt;br /&gt;
Ce champ ne peut être renseigné que pour les [[#Soumise-à-échéance|validités soumises à échéance]] et lorsque le champ [[#Alerte-échéance-par-email-:-1er-rappel|1er rappel]] a été renseigné.&lt;br /&gt;
&lt;br /&gt;
Il détermine la fréquence de rappel, après le [[#Alerte-échéance-par-email-:-1er-rappel|1er rappel]], pour l'[[Envoi-des-emails#Email-de-rappel-d'échéance-de-validité|envoi de l'email d'alerte]].&lt;br /&gt;
&lt;br /&gt;
S'il est sur ''aucun'' et que le champ [[#Alerte-échéance-par-email-:-1er-rappel|1er rappel]] a été renseigné, alors 1 seul envoi d'email est effectué à la date du 1er rappel.&lt;br /&gt;
&lt;br /&gt;
Les validités sans date d'échéance ne déclenchent pas l'[[Envoi-des-emails#Email-de-rappel-d'échéance-de-validité|envoi du rappel]].&lt;br /&gt;
&lt;br /&gt;
===Certification===&lt;br /&gt;
La cellule '''Certification''' a 5 choix possibles :&lt;br /&gt;
*'''Désactivée''' : la certification n'est pas active sur ce type de validité&lt;br /&gt;
*'''Requise''' : la certification est active. La validité ne sera considérée comme valide que si elle est [[Validités#Certification-manuelle|certifiée manuellement]]. Si un document peut être associé, la présence des pages obligatoires est requise.&lt;br /&gt;
*'''Par API FFA''' : la certification est active et réalisable exclusivement par le biais du  [[Validités#Certification-automatique-à-partir-du-numéro-de-licence-délivré-par-la-Fédération-Française-Aéronautique|robot OpenFlyers en interrogeant l'API FFA]], ce qui signifie que la [[Validités#Certification-manuelle|certification manuelle]] n'est pas possible. De plus, les utilisateurs ne peuvent ni attribuer ni modifier la date d'échéance de la validité.&lt;br /&gt;
*'''Possible par robot (FFA)''' : la certification est active, un document est obligatoire qui doit correspondre au fichier PDF original de l'attestation de licence Fédérale délivrée par la FFA. Alors le robot [[Validités#Certification-automatique-de-l'attestation-délivrée-par-la-Fédération-Française-Aéronautique|certifie automatiquement]] le document associé à la validité.&lt;br /&gt;
*&amp;lt;s&amp;gt;'''Possible par OCR''' : La certification est active, un document doit être obligatoirement associé à la validité. Ensuite, [[Validités#Licence-de-pilote-privé-(PPL)|une certification automatique par OCR]] peut être effectuée.&amp;lt;/s&amp;gt; ''(en développement)''&lt;br /&gt;
*'''Requise avec auto-remplissage (SEP)'''&lt;br /&gt;
Lorsque la certification est '''requise''', les personnes en charge de ce type de validités sont notifiées par e-mail lorsque une validité doit être certifiée ou re-certifier. Cela arrive dans l'un des cas suivant :&lt;br /&gt;
*La validité a été créée et est [[Validités#Validité-complète|complète]].&lt;br /&gt;
*La validité a été [[Validités#Validité-complète|complétée]].&lt;br /&gt;
*La validité était [[Validités#Validité-complète|complète]] et [[Validités#Certifier-des-validités|certifiée]], mais une page obligatoire a été modifiée.&lt;br /&gt;
&lt;br /&gt;
Lorsque la certification est '''possible par robot''', les personnes en charge de ce type de validités sont notifiées par e-mail uniquement lorsque le robot n'est pas parvenu à certifier automatiquement le fichier téléversé.&lt;br /&gt;
&lt;br /&gt;
Pour l'utilisation des validités avec certification, voir le chapitre [[Validités#Certifier-des-validités|certifier des validités]].&lt;br /&gt;
&lt;br /&gt;
===Contrat===&lt;br /&gt;
Permet de définir si la validité est un contrat.&lt;br /&gt;
&lt;br /&gt;
Un gestionnaire ne peut attribuer l'état &amp;quot;contrat&amp;quot; à une validité que si cette dernière n'est pas déjà attribuée à un utilisateur.&lt;br /&gt;
&lt;br /&gt;
L'affectation de l'état de &amp;quot;contrat&amp;quot; à une validité est irréversible, sauf si aucun utilisateur n'a signé cette validité-contrat. Le but est d'empêcher de générer une rupture d'intégrité en base de données ou de perdre des signatures qui seraient dues à une erreur de manipulation.&lt;br /&gt;
&lt;br /&gt;
Voir la procédure [[#Paramétrer-une-validité-comme-contrat|Paramétrer une validité comme contrat]].&lt;br /&gt;
&lt;br /&gt;
===Fichier du contrat===&lt;br /&gt;
&lt;br /&gt;
Permet de mettre en ligne un fichier PDF, ce fichier doit contenir le texte du contrat afin que les utilisateurs puissent le consulter.&lt;br /&gt;
&lt;br /&gt;
Un fichier de contrat ne doit pas dépasser '''500ko'''.&lt;br /&gt;
&lt;br /&gt;
Un contrat n'est proposé à la signature que lorsqu'il contient un fichier. &lt;br /&gt;
&lt;br /&gt;
Cependant lorsqu'un contrat est complet (fichier mis en ligne), tous les utilisateurs qui appartiennent à un profil n'étant pas dispensé de ce contrat devront le signer à leur connexion. La connexion n'est pas possible tant qu'il reste des contrats non signés.&lt;br /&gt;
&lt;br /&gt;
===Profils autorisés à gérer pour eux-mêmes===&lt;br /&gt;
Permet de sélectionner les profils autorisés à gérer pour eux-mêmes la validité.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Le droit sur la &amp;quot;Gestion des profils&amp;quot; est nécessaire pour modifier les valeurs de cette colonne.&lt;br /&gt;
&lt;br /&gt;
===Profils autorisés à gérer/certifier pour les autres===&lt;br /&gt;
&lt;br /&gt;
Permet de sélectionner les profils autorisés à gérer et certifier la validité pour les autres utilisateurs.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Le droit sur la &amp;quot;Gestion des profils&amp;quot; est nécessaire pour modifier les valeurs de cette colonne.&lt;br /&gt;
===Profils dispensés de signature===&lt;br /&gt;
Dans le cas d'une validité de type contrat, permet de sélectionner les profils dispensés de signature.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Le droit sur la &amp;quot;Gestion des profils&amp;quot; est nécessaire pour modifier les valeurs de cette colonne.&lt;br /&gt;
&lt;br /&gt;
=Paramétrer le [[Validités#Contrôle-des-validités|contrôle des validités]]=&lt;br /&gt;
&lt;br /&gt;
==Paramétrer le contrôle des validités pour les activités ou les réservations==&lt;br /&gt;
Lors de la saisie d'une activité ou d'une réservation, le contrôle des validités s'effectue en fonction du type de ressource sélectionné et des types d'activités sélectionnés.&lt;br /&gt;
&lt;br /&gt;
===Prendre en compte les validités requises pour un type d'activité donné===&lt;br /&gt;
*'''Admin &amp;gt; Structure &amp;gt; Paramétrage'''.&lt;br /&gt;
*Dans le formulaire aller sur la section '''[[Configuration#Gestion-des-activités|Gestion des activités]]''' ou sur la section '''[[Configuration#Gestion-du-planning|Gestion du planning]]''' selon si vous souhaitez configurer le contrôles des validités pour les activités ou pour les réservations&lt;br /&gt;
*Champ '''Prendre en compte les validités requises pour un type d'activité donné''', il faut choisir le comportement général parmi les choix suivants :&lt;br /&gt;
**'''En mode &amp;quot;Restreint&amp;quot;''' : cela fait apparaitre des alertes bloquantes lorsqu'il y a une absence de validités requises pour un type d'activité donné&lt;br /&gt;
**'''En mode &amp;quot;Avertissement&amp;quot;''' : cela fait apparaitre des alertes bloquantes ou non-bloquantes lorsqu'il y a une absence de validité requises pour un type d'activité donné. Le choix de l'alerte bloquante ou non est déterminé par OpenFlyers en fonction du [[#Validité-bloquante-pour-la-saisie-(si-requise)|paramétrage du type de validité]].&lt;br /&gt;
**'''Désactivé'''&lt;br /&gt;
*Puis vous pouvez [[#Paramétrer-pour-chaque-type-d'activité-les-validités-requises|paramétrer pour chaque type d'activité les validités requises]]&lt;br /&gt;
&lt;br /&gt;
====Paramétrer pour chaque type d'activité les validités requises====&lt;br /&gt;
Les validités requises lors de la saisie d'une activité dépendent des types d'activités sélectionnés pour cette activité. Le paramétrage des validités requises pour chaque type d'activité s'effectue ainsi :&lt;br /&gt;
*'''Admin &amp;gt; Activités &amp;gt; Types d'activités'''&lt;br /&gt;
*Dans le tableau '''Types de validités requises (si seul à bord) pour un type d'activité donné''', cocher les validités requises pour chaque type d'activité&lt;br /&gt;
&lt;br /&gt;
===Prendre en compte les validités requises pour un type de ressource donné===&lt;br /&gt;
*'''Admin &amp;gt; Structure &amp;gt; Paramétrage'''&lt;br /&gt;
*Dans le formulaire aller sur la section '''[[Configuration#Gestion-des-activités|Gestion des activités]]''' ou sur la section '''[[Configuration#Gestion-du-planning|Gestion du planning]]''' selon si vous souhaitez configurer le contrôles des validités pour les activités ou pour les réservations&lt;br /&gt;
*Champ '''Prendre en compte les validités requises pour un type de ressource donné''', il faut choisir le comportement général parmi les choix suivants :&lt;br /&gt;
**'''En mode &amp;quot;Restreint&amp;quot;''' : cela fait apparaitre des alertes bloquantes lorsqu'il y a une absence de [[#Validités-requises-pour-la-saisie-des-activités|validités requises]] pour une ressource donnée&lt;br /&gt;
**'''En mode &amp;quot;Avertissement&amp;quot;''' : cela fait apparaitre des alertes bloquantes ou non-bloquantes lorsqu'il y a une absence de validité requises pour une ressource donnée. Le choix de l'alerte bloquante ou non est déterminé par OpenFlyers en fonction du [[#Validité-bloquante-pour-la-saisie-(si-requise)|paramétrage du type de validité]].&lt;br /&gt;
**'''Désactivé'''&lt;br /&gt;
*Puis vous pouvez [[#Paramétrer-pour-chaque-type-de-ressource-les-validités-requises|paramétrer pour chaque type de ressource les validités requises]]&lt;br /&gt;
&lt;br /&gt;
====Paramétrer pour chaque type de ressource les validités requises====&lt;br /&gt;
Ce paramétrage permet de définir les validités requises en fonction des types de ressources à la fois pour la [[Validités#Contrôle-des-validités-lors-de-la-saisie-d'une-réservation|réservation]] et la [[Validités#Contrôle-des-validités-lors-de-la-saisie-d'un-vol|saisie des activités]].&lt;br /&gt;
&lt;br /&gt;
*'''Admin &amp;gt; Types de ressources &amp;gt; Actifs'''&lt;br /&gt;
*Dans le tableau qui liste les types de ressources, cliquer sur l'icône dans la colonne '''Action''' symbolisant une check-list [[File:Checklist.png]] et intitulée '''Validité'''.&lt;br /&gt;
&lt;br /&gt;
On se retrouve avec un tableau qui permet de déterminer les validités requises d'une ressource donnée.&lt;br /&gt;
&lt;br /&gt;
Les validités peuvent se suppléer les unes les autres. C'est la règle &amp;quot;ou&amp;quot; présente entre chaque validité d'une même ligne.&lt;br /&gt;
&lt;br /&gt;
Si on souhaite que les validités s'ajoutent et soient toutes nécessaires, alors il faut les disposer sur des lignes différentes qui sont séparées par la règle &amp;quot;et&amp;quot; présente en début de ligne.&lt;br /&gt;
&lt;br /&gt;
Exemples types :&lt;br /&gt;
*Si on souhaite qu'une validité A soit requise, il faut cliquer sur la check verte de cette validité sur la 1ère ligne. Une deuxième ligne apparait alors avec aucune validité de sélectionnée.&lt;br /&gt;
&lt;br /&gt;
*Si on souhaite qu'une validité A et qu'une validité B soient toutes les 2 requises, il faut cliquer sur la check verte de la validité A de la 1ère ligne puis sur la check verte de la validité B de la 2ème ligne qui est apparue. Une 3ème ligne apparait alors également avec aucune validité de sélectionnée.&lt;br /&gt;
&lt;br /&gt;
*Si on souhaite qu’indifféremment les validités A ou B soient requises, il cliquer sur les check vertes de chacune des validités de la 1ère ligne.&lt;br /&gt;
&lt;br /&gt;
Exemple pratique : On souhaite qu'un utilisateur dispose d'un brevet PPL ou d'un brevet BB et qu'il dispose également d'une visite médicale de classe 1 ou de classe 2. Pour cela, on va cliquer :&lt;br /&gt;
*sur les validités &amp;quot;PPL&amp;quot; et &amp;quot;BB&amp;quot; de la 1ère ligne.&lt;br /&gt;
*sur les validités &amp;quot;Visite médicale classe 1&amp;quot; et &amp;quot;Visite médicale classe 2&amp;quot; de la 2ème ligne.&lt;br /&gt;
&lt;br /&gt;
''Conseil OpenFlyers'' :&lt;br /&gt;
*En mode restreint, ne pas oublier d’attribuer les validités aux membres pour qu'ils ne soient pas bloqués. Il est recommandé de rester en mode avertissement durant plusieurs semaines avant d'activer les restrictions.&lt;br /&gt;
&lt;br /&gt;
=Paramétrer des [[Envoi-des-emails#E-mail-de-rappel-d'échéance-de-validité|rappels par e-mail]] des validités à échéance=&lt;br /&gt;
&lt;br /&gt;
Ce paramétrage n'est possible que pour les validités [[#Soumise-à-échéance|soumises à échéance]] :&lt;br /&gt;
*'''Admin &amp;gt; Utilisateurs &amp;gt; Types de validités'''&lt;br /&gt;
*Pour chaque validité soumise à échéance :&lt;br /&gt;
**Cliquer sur le bouton de modification (pictogramme &amp;quot;crayon&amp;quot;)&lt;br /&gt;
**Champ [[#Alerte-échéance-par-email-:-1er-rappel|Alerte échéance par email : 1er rappel]] : Sélectionner une période d'échéance&lt;br /&gt;
**Champ [[#Fréquence|Fréquence]] : Sélectionner une fréquence de rappel ou &amp;quot;Aucun&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''/!\ Les validités sans date d'échéance ne déclenchent pas l'[[Envoi-des-emails#Email-de-rappel-d'échéance-de-validité|envoi du rappel]].'''&lt;br /&gt;
&lt;br /&gt;
Exemple de paramétrage de rappel qu'au premier mois d'échéance :&lt;br /&gt;
* [[#Alerte-échéance-par-email-:-1er-rappel|Alerte échéance par email : 1er rappel]] : 1 mois&lt;br /&gt;
* [[#Fréquence|Fréquence]] : Aucun&lt;br /&gt;
&lt;br /&gt;
Exemple de paramétrage de rappel journalier au bout d'un mois d'échéance :&lt;br /&gt;
* [[#Alerte-échéance-par-email-:-1er-rappel|Alerte échéance par email : 1er rappel]] : 1 mois&lt;br /&gt;
* [[#Fréquence|Fréquence]] : Tous les jours&lt;br /&gt;
&lt;br /&gt;
Exemple de paramétrage de rappel hebdomadaire au bout de deux mois d'échéance :&lt;br /&gt;
* [[#Alerte-échéance-par-email-:-1er-rappel|Alerte échéance par email : 1er rappel]] : 2 mois&lt;br /&gt;
* [[#Fréquence|Fréquence]] : Tous les 7 jours&lt;br /&gt;
&lt;br /&gt;
=Paramétrer le surpassement des restrictions sur les validités=&lt;br /&gt;
''A l'inverse de ce qui est présenté dans ce chapitre, il est également possible de [[Gestion-des-profils#Créer-un-profil-empêchant-tout-surpassement|créer un profil restreint empêchant tout surpassement]].''&lt;br /&gt;
&lt;br /&gt;
Comme indiqué dans le chapitre [[Validités#Contrôle-des-validités|Contrôle des validités]], que se soit à la connexion, lors d'une réservation ou lors d'une saisie d'activité, il est possible de mettre en place des restrictions qui bloqueront les utilisateurs n'ayant pas les validités requises.&lt;br /&gt;
&lt;br /&gt;
Cependant, dans certains cas, il peut être nécessaire de permettre à certaines populations d'utilisateurs de pouvoir surpasser ces restrictions.&lt;br /&gt;
&lt;br /&gt;
Le paramétrage du surpassement dépend de plusieurs choses :&lt;br /&gt;
*Est-ce que l'utilisateur peut surpasser lui-même ou est-ce que l'action que ne peut pas effectuer l'utilisateur peut être effectuée par une tierce personne&lt;br /&gt;
*Est-ce que la population d'utilisateurs concernés est définie par un profil ou non&lt;br /&gt;
*Est-ce que le surpassement est pour toute validité ou est-ce qu'il ne s'applique qu'à certaines validités&lt;br /&gt;
&lt;br /&gt;
Voici quelques exemples de paramétrages possibles :&lt;br /&gt;
&lt;br /&gt;
*Permettre aux instructeurs de pouvoir effectuer une réservation même s'ils n'ont pas l'expérience récente suffisante :&lt;br /&gt;
*:Comme les instructeurs disposent d'une validité permettant de connaitre leur statut d'instructeur, la méthode appropriée pour permettre aux instructeurs de surpasser l'absence d'expérience récente est la suivante :&lt;br /&gt;
**Aller dans '''Admin &amp;gt; Types de ressources &amp;gt; Actifs'''&lt;br /&gt;
**Cliquer sur le bouton symbolisant une liste de validités pour le type de ressource concerné&lt;br /&gt;
**Sur la ligne où la validité à expérience concernée est cochée, cocher également le type de validité correspondant aux instructeur (exemple : &amp;quot;Flight Instructor (FI)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*Permettre à des utilisateurs n'ayant pas l'expérience récente en interne mais disposant de l'expérience récente suffisante grâce à leur activité externe de pouvoir surpasser la restriction, aussi bien en réservation qu'en saisie de vol, pour une validité à expérience récente donnée :&lt;br /&gt;
**[[#Ajouter-un-type-de-validités|Ajouter un nouveau type de validité]] à échéance intitulé ''expérience extérieure''&lt;br /&gt;
**Modifier la formule de la validité à expérience concernée pour y inclure la prise en compte de la validité ''expérience extérieure''. Cf. la formule de calcul [[Formules-de-calcul#Expérience-récente-en-heures-ou-la-détention-d'une-validité-spécifique|Expérience récente en heures ou la détention d'une validité spécifique]]&lt;br /&gt;
&lt;br /&gt;
=Paramétrer une validité comme [[Validités#Validité-contrat|contrat]]=&lt;br /&gt;
*'''Admin &amp;gt; Utilisateurs &amp;gt; Types de validités'''.&lt;br /&gt;
*Cliquer sur le bouton '''Ajouter un type de validité'''.&lt;br /&gt;
*Choisir un nom pour le contrat.&lt;br /&gt;
*Cocher '''Contrat'''.&lt;br /&gt;
*Insérer le fichier contenant le corps du contrat dans '''Fichier du contrat'''.&lt;br /&gt;
*Si la validité-contrat ne doit pas être requise pour certains profils, cocher [[Gestion-des-profils#Contrats-non-requis|les profils exemptés]].&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
&lt;br /&gt;
Une fois ceci fait, tous les utilisateurs ou uniquement les utilisateurs n'appartenant aux profils exemptés devront [[Connexion#Signer-des-contrats|signer le contrat]] à leur connexion.&lt;br /&gt;
&lt;br /&gt;
=Supprimer ou désactiver un type de validité=&lt;br /&gt;
&lt;br /&gt;
*'''Admin &amp;gt; Utilisateurs &amp;gt; Types de validités'''&lt;br /&gt;
*L'icône symbolisant une poubelle permet de supprimer ou désactiver un type de validité.&lt;br /&gt;
&lt;br /&gt;
Si cette validité a été attribuée à au moins un utilisateur, un message d'avertissement avec la liste des utilisateurs apparaît proposant deux options :&lt;br /&gt;
&lt;br /&gt;
*La suppression : Permet de supprimer complètement le type de validité et les validités correspondantes détenues par les utilisateurs&lt;br /&gt;
*La désactivation : &lt;br /&gt;
**Permet de rendre obsolète un type de validité, notamment une validité contrat dont la signature ne sera désormais plus requise à la connexion tout en conservant l’historique des personnes ayant détenu cette validité ou ayant signé la « validité contrat ».&lt;br /&gt;
**Pour afficher les validités désactivées, cliquer sur le bouton de switch '''Afficher les items désactivés''' disponible au-dessus et en-dessous du tableau.&lt;br /&gt;
**Les types de validités désactivés s'affichent et se réactivent selon les [[Tableaux#Entrée-désactivée|caractéristiques des entrées désactivées des tableaux]].&lt;br /&gt;
&lt;br /&gt;
Si une validité du type qu'il faut supprimer est rattachée à un type de ressource ou à un produit alors une alerte bloquante, avec la liste des éléments rattachés, empêche la suppression de cette validité. Il faut d'abord retirer la validité aux éléments concernés.&lt;br /&gt;
&lt;br /&gt;
=Supprimer un type de validité déclaré comme contrat=&lt;br /&gt;
*'''Admin &amp;gt; Utilisateurs &amp;gt; Types de validités'''&lt;br /&gt;
*L'icône symbolisant une poubelle permet de supprimer un contrat s'il n'a été signé par personne, sinon la page qui permet de consulter les utilisateurs l'ayant signé s'ouvre. Contrairement aux types de validités classiques, l'interface ne propose pas de bouton de suppression forcée &lt;br /&gt;
&lt;br /&gt;
Il est impossible de supprimer un contrat une fois qu'il a été signé par aux moins 2 personnes. Cela permet de conserver la signature des documents par les utilisateurs.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Panier-de-r%C3%A9servation&amp;diff=12902</id>
		<title>Panier de réservation</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Panier-de-r%C3%A9servation&amp;diff=12902"/>
		<updated>2024-10-02T17:27:59Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter le panier de réservation de l'[[Présentation-d'OpenFlyers-4#Interface-dynamique|interface dynamique]] de la [[Accueil|version 4 d'OpenFlyers]]. D'autres pages de la documentation traitent de l'[[aspect du planning de réservation]] et de l'[[utilisation du planning de réservation]].&lt;br /&gt;
&lt;br /&gt;
=Fonctionnement=&lt;br /&gt;
Les réservations créées sur le planning et sujettes à une tarification, sont ajoutées au panier. Cela va engendrer la génération [[Écritures-comptables|d'écritures comptables non validées]] pour chacune des réservations.&lt;br /&gt;
&lt;br /&gt;
Le bouton &amp;quot;Payer&amp;quot; permet de valider les réservations présentes dans le panier. Cela a pour effet de :&lt;br /&gt;
* Si l'utilisateur connecté dispose du droit de [[Gestion-des-profils#Gestion-des-comptes|gestion des comptes]] ou que le solde de l'utilisateur suffisant, le compte est débité directement en validant les écritures générées&lt;br /&gt;
* Sinon une fenêtre pop-up s'ouvre pour alimenter le compte du montant manquant via un [[Paiement en ligne]] par carte bancaire. Après paiement, les écritures générées sont validées.&lt;br /&gt;
'''Attention : Certains navigateurs peuvent bloquer les fenêtres pop-up et ainsi empêcher d'effectuer le paiement. Dans ce cas, il faut ajouter une exception pour autoriser votre plateforme OF à ouvrir des fenêtres pop-up.'''&lt;br /&gt;
&lt;br /&gt;
Lorsqu'une réservation validée est modifiée :&lt;br /&gt;
* Des [[Écritures-comptables|écritures comptables]] de contre-partie sont générées pour annuler le paiement précédemment effectué&lt;br /&gt;
* De nouvelles [[Écritures-comptables|écritures comptables non validées]] sont régénérées&lt;br /&gt;
Cela a pour conséquence :&lt;br /&gt;
* D'ajouter la réservation modifiée au panier&lt;br /&gt;
* De refaire un paiement pour valider à nouveau la réservation&lt;br /&gt;
&lt;br /&gt;
Les réservations qui n'ont pas été payées au bout de 15 minutes sont supprimées automatiquement du panier et du planning.&lt;br /&gt;
&lt;br /&gt;
=Tester le paiement à la réservation=&lt;br /&gt;
La plateforme de démonstration http://demo-paiement-reservation.openflyers.fr/ permet de découvrir le paiement à la réservation.&lt;br /&gt;
&lt;br /&gt;
Pour se faire :&lt;br /&gt;
*Aller sur la plateforme [http://demo-paiement-reservation.openflyers.fr/ demo-paiement-reservation].&lt;br /&gt;
*Se connecter avec :&lt;br /&gt;
**identifiant : mbonsaint&lt;br /&gt;
**mot de passe : azerty&lt;br /&gt;
'''Attention :''' certains navigateurs peuvent bloquer les fenêtres pop-up et ainsi empêcher d'effectuer le paiement. Dans ce cas, il faut ajouter une exception pour [[FAQ-utilisateur#Comment-autoriser-les-fenêtres-pop-up|autoriser la plateforme à ouvrir des fenêtres pop-up]]. &lt;br /&gt;
&lt;br /&gt;
Avant de procéder à de quelconques tests de paiement, éditer la [[Fiche personnelle]] pour y mettre une adresse e-mail existante. Une carte bancaire factrice sera utilisée lors des tests.&lt;br /&gt;
&lt;br /&gt;
* [[Utilisation-du-planning-de-réservation#Créer-une-réservation|Créer une réservation]] pour soi-même&lt;br /&gt;
* Aller sur le panier situé en haut à droite du planning&lt;br /&gt;
[[File:Panier_reservation.png]]&lt;br /&gt;
* Cliquer sur le bouton '''Payer'''&lt;br /&gt;
* Choisir comme moyen de paiement &amp;quot;CB&amp;quot; ou &amp;quot;Visa&amp;quot; et cliquer sur le bouton '''Effectuer un paiement'''&lt;br /&gt;
[[File:Interface_choix_paiement.png]]&lt;br /&gt;
* Saisir les informations de la carte bancaire et cliquer sur le bouton '''Valider'''. Pour les tests, utiliser '''1111222233334444''' comme '''numéro de carte''', les valeurs de la '''date de fin''' et le '''cryptogramme''' importent peu&lt;br /&gt;
[[File:Interface_saisie_carte_paiement.png]]&lt;br /&gt;
* Une fois sur le bon de commande, cliquer sur le bouton '''Retour commerce'''. Ce bon de commande sera aussi envoyé par email&lt;br /&gt;
[[File:Bon_commande_reservation.png]]&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Normes-et-r%C3%A9glementations&amp;diff=12901</id>
		<title>Normes et réglementations</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Normes-et-r%C3%A9glementations&amp;diff=12901"/>
		<updated>2024-10-02T17:27:58Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
=Présentation=&lt;br /&gt;
L'objet de cette page est de regrouper les différentes normes et réglementations qu'OpenFlyers respecte ou met en oeuvre.&lt;br /&gt;
&lt;br /&gt;
=Cookies=&lt;br /&gt;
La [https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=celex%3A32009L0136 directive 2009/136/CE] impose le consentement de l'utilisateur au stockage de données dans son équipement, c'est à dire le stockage des cookies dans les navigateurs.&lt;br /&gt;
&lt;br /&gt;
Dans le cas d'OpenFlyers, les cookies utilisés sont des &amp;quot;cookies de session&amp;quot;. Ils sont indispensables car ils permettent d'assurer la continuité de la connexion de chaque utilisateur après son identification initiale et ainsi lui permettent de naviguer sans avoir à ressaisir le couple identifiant/mot de passe à chaque page.&lt;br /&gt;
&lt;br /&gt;
Depuis le 2 mai 2019, afin d'être conforme à cette réglementation, un article &amp;quot;Cookies&amp;quot; est inclus dans les conditions générales v. 11 et supérieures. Il permet d'informer l'utilisateur sur la nécessité de ce stockage.&lt;br /&gt;
&lt;br /&gt;
Depuis le 18 juin 2019, sur les plateformes OpenFlyers sous version 4, la SARL OpenFlyers impose aux utilisateurs d'accepter les [https://openflyers.com/fr/entreprise/conditions-generales conditions générales d'OpenFlyers] grâce à la fonction [[Validités#Validité-contrat|validité-contrat]].&lt;br /&gt;
&lt;br /&gt;
=Conservation des documents=&lt;br /&gt;
'''Documents comptables :'''&lt;br /&gt;
&lt;br /&gt;
Depuis le 4 janvier 2003. Les documents comptables et les pièces justificatives doivent être conservé pendant dix ans.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type de document!!Durée de conservation!!Texte de loi&lt;br /&gt;
|-&lt;br /&gt;
|Livre et registre comptable||10 ans à partir de la clôture de l'exercice comptable||[https://www.legifrance.gouv.fr/affichCodeArticle.do?idArticle=LEGIARTI000006219327&amp;amp;cidTexte=LEGITEXT000005634379&amp;amp;dateTexte=20030104 article L123-22] du code de commerce&lt;br /&gt;
|-&lt;br /&gt;
|Pièce justificative (facture client et fournisseur)||10 ans à partir de la clôture de l'exercice comptable||[https://www.legifrance.gouv.fr/affichCodeArticle.do?idArticle=LEGIARTI000006219327&amp;amp;cidTexte=LEGITEXT000005634379&amp;amp;dateTexte=20030104 article L123-22] du code de commerce&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Documents fiscaux :'''&lt;br /&gt;
&lt;br /&gt;
Depuis le 29 décembre 2016, selon [https://www.legifrance.gouv.fr/affichCodeArticle.do?idArticle=LEGIARTI000033815239&amp;amp;cidTexte=LEGITEXT000006069583&amp;amp;dateTexte=20170331 l'article L102 B] du livre des procédures fiscales, les livres, registres, documents ou pièces sur lesquels peuvent s'exercer les droits de communication, d'enquête et de contrôle de l'administration doivent être conservés pendant un délai de 6 ans à partir de la dernière opération mentionnée sur les livres ou registres ou de la date à laquelle les documents ou pièces ont été établis.&lt;br /&gt;
&lt;br /&gt;
Cette article s'applique pour les documents concernant les différents impôts et les cotisations.&lt;br /&gt;
&lt;br /&gt;
=Factures dématérialisées=&lt;br /&gt;
==[https://www.ssi.gouv.fr/entreprise/reglementation/confiance-numerique/le-reglement-eidas/ eIDAS]==&lt;br /&gt;
Le règlement eIDAS s'applique à l'identification électronique, aux services de confiance et aux documents électroniques. Il vise à mettre en place un cadre d'interopérabilité des différents systèmes présents au sein des États membres afin de développer un marché numérique de confiance. Des exigences relatives à la reconnaissance mutuelle des moyens d'identification électroniques et des signatures électroniques sont formulées dans le cadre des échanges entre organismes publics et usagers. Les échanges internes aux administrations n'y sont pas inclus.&lt;br /&gt;
&lt;br /&gt;
L'adoption de ce règlement fait suite à un relatif constat d'échec de la directive 1999/93/CE sur la signature électronique. Le règlement eIDAS a pour objectif de mettre en place un socle commun d'interopérabilité afin de développer les échanges transfrontaliers. Contrairement à la directive 1999/93/CE, ce règlement est appliqué directement aux États membres de l'Union Européenne sans transposition dans leur droit national.&lt;br /&gt;
&lt;br /&gt;
Le règlement eIDAS définit le [https://www.ssi.gouv.fr/administration/reglementation/confiance-numerique/le-referentiel-general-de-securite-rgs/ Référentiel Général de Sécurité] (RGS) qui correspond au cadre règlementaire permettant d’instaurer la confiance dans les échanges au sein de l’administration et avec les citoyens. Le RGS, a pour objet le renforcement de la confiance des usagers dans les services électroniques mis à disposition par les autorités administratives et s’impose ainsi à elles comme un cadre contraignant tout en étant adaptable et adapté aux enjeux et besoins de tout type d’autorité administrative.&lt;br /&gt;
&lt;br /&gt;
La version initiale du RGS (v.1.0) a été rendue officielle par arrêté du Premier ministre en date du 6 mai 2010. Une version 2.0 a été publiée par arrêté du Premier ministre du 13 juin 2014. Ses mesures de transitions ont été étendues par arrêté du Premier ministre du 10 juin 2015. Elle est applicable depuis le 1er juillet 2014. La version 2.0 du RGS constitue un référentiel de transition entre une première version liée à la mise en œuvre de l’administration électronique et une troisième version qui se fondera sur la réglementation européenne en cours d’évolution.&lt;br /&gt;
&lt;br /&gt;
Le Référentiel général de sécurité s’impose spécifiquement aux systèmes d’information mis en œuvre par les autorités administratives dans leurs relations entre elles et dans leurs relations avec les usagers.&lt;br /&gt;
&lt;br /&gt;
==Fiscalité française==&lt;br /&gt;
La France reconnaît la signature électronique standard comme ayant une valeur juridique limitée et qui a pour vocation de simplifier des processus internes. Seules les signatures électroniques avancées et qualifiées ont une valeur juridique complète. La signature qualifiée, par rapport à la signature avancée, est l'équivalent de la signature manuscrite.&lt;br /&gt;
&lt;br /&gt;
L'[https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000042910281/ article 289 VII du CGI] (Code général des impôts) indique qu'il existe trois solutions pour la transmission de factures électroniques :&lt;br /&gt;
* Soit en mettant en place des contrôles établissant une piste d'audit fiable (1°),&lt;br /&gt;
* Soit en recourant à la procédure de signature électronique avancée avec un certificat qualifié (2°),&lt;br /&gt;
* Soit en utilisant l'échange de données informatisées répondant aux normes prévues par le CGI (3°).&lt;br /&gt;
&lt;br /&gt;
Le [https://bofip.impots.gouv.fr/bofip/8865-PGP.html/identifiant%3DBOI-TVA-DECLA-30-20-30-20-20180207 BOI-TVA-DECLA-30-20-30-20] indique au point '''70''' que dans une très petite entreprise, une comparaison manuelle des factures avec les documents commerciaux (devis, bons de commande, bons de livraison, justificatifs de paiement) peut constituer un contrôle suffisant mis en place par l'assujetti. Ainsi, chacun des éléments suivants doit être conservé et traçé : le devis qui devient le bon de commande, par la suite validé, le bon de livraison (avec l'impact des retours éventuels) et enfin la facturation (également avec l'impact des avoirs éventuels). Les contrôles établissant la piste d'audit doivent permettre de s'assurer que le passage de l'un à l'autre des documents précité est traçable dans les deux sens.&lt;br /&gt;
&lt;br /&gt;
Le point '''80''' indique que, conformément à l'[https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000026892933/2013-01-01 article L. 13 D du livre des procédures fiscales (LPF)] et à l'[https://www.legifrance.gouv.fr/codes/article_lc/LEGIARTI000026949916/2013-01-01 article L. 80 F du LPF], si les contrôles sont effectués sous forme dématérialisée, les contribuables sont tenus de les présenter à l'administration sous cette forme.&lt;br /&gt;
&lt;br /&gt;
Le point '''130''' indique que la piste d'audit doit permettre :&lt;br /&gt;
&lt;br /&gt;
* de reconstituer, dans un ordre chronologique la totalité du processus de facturation, depuis son origine (par exemple, le bon de commande) jusqu'au document facture c'est-à-dire de reconstituer le processus documenté (bons de commande, bons de livraisons, extraits de compte...) d'une opération et de relier les différents documents de ce processus ;&lt;br /&gt;
* de garantir que la facture émise ou reçue reflète l'opération qui a eu lieu, en permettant d'établir un lien entre la facture et la livraison de biens ou la prestation de services qui la fonde ;&lt;br /&gt;
* de justifier toute opération par une pièce d’origine à partir de laquelle il doit être possible de remonter par un cheminement ininterrompu à la facture et réciproquement.&lt;br /&gt;
&lt;br /&gt;
Concernant [https://www.pwcavocats.com/fr/ealertes/ealertes-france/2017/novembre/signature-electronique-eidas-admise-en-france.html la facture électronique sécurisée au moyen d’une signature électronique], il convient de distinguer deux situations :&lt;br /&gt;
&lt;br /&gt;
* Seule la signature électronique avancée fondée sur un certificat qualifié et créée par un dispositif sécurisé de création de signature, c’est-à-dire la signature électronique qualifiée telle que définie ci-dessus, garantissent de façon autonome l'authenticité de l'origine et l'intégrité du contenu des factures. Ce dispositif prévu par l’article 289 VII 2° du CGI exonère de l’obligation de démonstration et de documentation de la piste d’audit fiable. Les prestataires de services de confiance qualifiés selon le RGS au niveau 2 étoiles (RGS**) ou 3 étoiles (RGS***), pourront bénéficier de modalités de qualification facilitées au titre du règlement eIDAS et ainsi de bénéficier d’une telle qualification au sens du règlement eIDAS.&lt;br /&gt;
* A l’inverse, les entreprises émettrices de factures assorties d'autres signatures électroniques (par exemple : signature avancée au sens de l'article 2, point 2, de la Directive 1999/93/CE du 13 décembre 1999 du Parlement européen signature simple ou conforme au RGS 1 étoile (RGS*)) doivent, aux fins de garantir l'authenticité de l'origine et l'intégrité du contenu des factures électroniques, mettre en place des contrôles établissant une piste d’audit fiable.&lt;br /&gt;
&lt;br /&gt;
[[File:Acroba bandeau signature invalide.png]]&lt;br /&gt;
&lt;br /&gt;
Il est donc possible d'utiliser la signature électronique standard, c'est-à-dire que la signature n'a pas pour objectif de certifier que l'auteur de la signature est bien le signataire lui-même. En contre-partie, des pistes d'audit fiables doivent être établies. Cela signifie que dans un lecteur de fichiers PDF comme Adobe Acrobat Reader par exemple, un bandeau indiquant &amp;quot;Validité de la certification du document INCONNUE. Impossible d'en authentifier l'auteur.&amp;quot; n'indique pas que la signature est fausse mais que le logiciel n'est pas en capacité d'assurer l'authenticité de la signature.&lt;br /&gt;
&lt;br /&gt;
==Norme PDF/A==&lt;br /&gt;
Le PDF/A est une version normalisée [https://fr.wikipedia.org/wiki/ISO ISO] du format [[PDF]] spécialisée pour l'archivage et la conservation à long terme des documents numériques. Le PDF/A diffère du format standard en interdisant les fonctionnalités inadaptées à l'archivage à long terme comme le chiffrement par exemple. Les visionneuses de fichiers PDF/A comprennent des directives de gestion des couleurs, la prise en charge des polices intégrées et une interface utilisateur pour la lecture des annotations intégrées.&lt;br /&gt;
&lt;br /&gt;
Le PDF/A est une version particulière du format propriétaire PDF mis au point par [https://fr.wikipedia.org/wiki/Adobe_Systems Adobe Systems]. Le principal avantage du PDF/A est la fidélité vis à vis des documents originaux : les polices, les images, les objets graphiques et la mise en forme du fichier source sont préservés.&lt;br /&gt;
&lt;br /&gt;
PDF est une norme pour l'encodage de documents sous une forme &amp;quot;telle qu'inprimée&amp;quot; qui est portable entre les systèmes. La pertinence d'un fichier PDF pour la conservation des archives dépend des options choisies lors de la création du PDF comme l'incorporation de polices nécessaires pour produire ou afficher le document, l'utilisation du chiffrement ou la conservation des informations supplémentaires du document original au-delà de ce qui est nécessaire pour l'impression.&lt;br /&gt;
&lt;br /&gt;
La norme PDF/A est à l'origine une activité conjointe entre deux associations américaines : l'Association pour les fournisseurs de technologies d'impression, d'édition et de conversion et l'Association pour la gestion de l'information et de l'image dans le but d'élaborer une norme internationale pour l'archivage de documents au format PDF. L'objectif étant de répondre au besoin croissant d'archiver électroniquement des documents de manière à garantir la conservation de leur contenu.&lt;br /&gt;
&lt;br /&gt;
OpenFlyers utilise la version 2 de la norme publiée en juin 2011 traite de certaines des nouvelles fonctionnalités ajoutées avec les version 1.5, 1.6 et 1.7 de PDF. Les fichiers PDF/A-1 ne sont pas nécessairement conformes à la norme PDF/A-2 et inversement.&lt;br /&gt;
&lt;br /&gt;
La version 2 de la norme PDF/A est basée sur PDF 1.7 plutôt que PDF 1.4 et offre de nouvelles fonctionnalités :&lt;br /&gt;
* compression de données pour les images au format [https://fr.wikipedia.org/wiki/JPEG_2000 JPEG 2000]&lt;br /&gt;
* prise en charge des effets de transparence et des calques&lt;br /&gt;
* incorportation de polices de caractères [https://fr.wikipedia.org/wiki/OpenType OpenType]&lt;br /&gt;
* dispositions relatives aux signatures numériques conformément aux signatures électroniques avancées dans PDF (PDF Advanced Electronic Signatures, norme PAdES)&lt;br /&gt;
* l'option d'intégration de fichiers à la norme PDF/A pour faciliter l'archivage d'ensembles de documents avec un seul fichier.&lt;br /&gt;
&lt;br /&gt;
La version 2 définit trois niveaux de conformité :&lt;br /&gt;
* PDF/A-2a : Conformité de niveau A (niveau avec accessibilité pour mal-voyant ou aveugle). Elle représente la forme complète de la norme ISO.&lt;br /&gt;
* PDF/A-2b : Conformité de niveau B (niveau de base). Elle représente une forme allégée de la norme ISO. Cette version préserve la lisibilité du document et sa bonne présentation à l'affichage et à l'impression.&lt;br /&gt;
* PDF/A-2u : Conformité de niveau U. Elle représente la conformité de niveau B (PDF/A-2b) avec l'exigence supplémentaire que tout le texte du document ait un mappage [https://fr.wikipedia.org/wiki/Unicode Unicode].&lt;br /&gt;
&lt;br /&gt;
=Inaltérabilité des données et traçabilité des encaissements=&lt;br /&gt;
Conformément :&lt;br /&gt;
*Au [https://www.legifrance.gouv.fr/affichCodeArticle.do;jsessionid=0CC8197762CAEDE98ECD25A8E19BD9EE.tplgfr36s_2?idArticle=LEGIARTI000034309494&amp;amp;cidTexte=LEGITEXT000006069577&amp;amp;categorieLien=id&amp;amp;dateTexte=20180101 3° bis du I de l'article 286 du Code Général des Impôts de la réglementation française]&lt;br /&gt;
&lt;br /&gt;
OpenFlyers v.4 et supérieur respectent cette réglementation. Ainsi :&lt;br /&gt;
*Les [[Comptabilité#Inaltérabilité-des-données|écritures comptables validées ne sont pas modifiables]]&lt;br /&gt;
*La traçabilité est garantie par l'[[Envoi-des-emails#E-mail-de-reçu|envoi automatique d'un email de reçu de paiement]] contenant une pièce jointe au format PDF avec un sceau chainé&lt;br /&gt;
*Sur les interfaces affichant les extraits de compte, un test est effectué pour chaque écriture comptable validée afin de vérifier que sa chaine n'a pas été falsifiée. Si le test est concluant un pictogramme symbolisant un cadenas apparait à droite de l'écriture comptable concernée. Si une rupture du chainage est identifié, le symbole du cadenas apparaît grisé avec une croix rouge.&lt;br /&gt;
&lt;br /&gt;
Les clients concernés par l'obligation d'utiliser un logiciel conforme à la réglementation peuvent retrouver une attestation à compléter et à produire à l'administration fiscale en cas de contrôle. Cette attestation est disponible dans [[Compte-client-OpenFlyers-et-modèle-commercial#Accéder-à-son-compte-client-OpenFlyers|l'espace client]] menu '''Fiche contact &amp;gt; Attestation art. 286 du CGI'''.&lt;br /&gt;
&lt;br /&gt;
=Protocole TLS 1.2=&lt;br /&gt;
Conformément :&lt;br /&gt;
*A la recommandation R3 du [https://www.ssi.gouv.fr/uploads/2016/09/guide_tls_v1.1.pdf guide TLS v1.1] du 19 août 2016 de l'[https://www.ssi.gouv.fr/ Agence Nationale de la Sécurité des Systèmes d'Information (ANSSI)] : &amp;quot;Utiliser uniquement TLS 1.2&amp;quot;&lt;br /&gt;
*Aux versions 3.1 et 3.2 de la [https://fr.pcisecuritystandards.org/minisite/env2/ norme de sécurité de l’industrie des cartes de paiement PCI-DSS] qui imposent l'abandon de SSL 3.0 et TLS 1.0 à la date du 10 avril 2018&lt;br /&gt;
Depuis le 1er mars 2018, sur l'ensemble de ses serveurs, OpenFlyers met uniquement en œuvre le protocole TLS 1.2 pour les échanges sécurisés via le port HTTPS.&lt;br /&gt;
&lt;br /&gt;
Sur OpenFlyers v.4 et supérieur, les accès au logiciel se font exclusivement par le port HTTPS.&lt;br /&gt;
&lt;br /&gt;
L'[[API-OpenFlyers#Script-client-:-Authorization-Code|exemple de script PHP]] concernant le contrôle d'identification par OpenFlyers pour un logiciel tiers est à jour de cette version de protocole.&lt;br /&gt;
&lt;br /&gt;
=Obligation de fournir le fichier des écritures comptables=&lt;br /&gt;
Selon [https://www.legifrance.gouv.fr/affichCodeArticle.do?cidTexte=LEGITEXT000006069583&amp;amp;idArticle=LEGIARTI000006315024&amp;amp;dateTexte=&amp;amp;categorieLien=cid l'article L47 A-1] du livre des procédures fiscales, depuis le 1 janvier 2014, il est nécessaire pour les contribuables tenant leur comptabilité au moyen de systèmes informatisés de pouvoir fournir le Fichier des Écritures Comptables (FEC) dématérialisé.&lt;br /&gt;
&lt;br /&gt;
Sont concernées, toutes les entreprises soumises à une obligation de présentation de documents comptables, qui tiennent leur comptabilité de façon informatisée et qui font l'objet d'une vérification de comptabilité. Ceci concerne donc :&lt;br /&gt;
*Les entreprises relevant de l’impôt sur les sociétés&lt;br /&gt;
*Les entreprises relevant de l’impôt sur le revenu dans la catégorie des BIC, des BNC ou des BA&lt;br /&gt;
&lt;br /&gt;
En cas de contrôle les, un FEC doit être fourni pour chacun des trois derniers exercices clôturés.&lt;br /&gt;
&lt;br /&gt;
=Obligation d'informer les utilisateurs=&lt;br /&gt;
Brochure mentionnée au paragraphe 1er de l'article 106 de la directive 2015/2366 du Parlement européen et du Conseil du 25 novembre 2015 :&lt;br /&gt;
&lt;br /&gt;
https://ec.europa.eu/info/sites/default/files/business_economy_euro/banking_and_finance/documents/leaflet-your-rights-payments-eu_fr.pdf&lt;br /&gt;
&lt;br /&gt;
=Prestation de Service d’Information sur les Comptes (PSIC)=&lt;br /&gt;
La S.A.R.L. OpenFlyers peut mettre à disposition un service d’import des informations de compte bancaire. Pour ce faire, elle peut faire appel à un sous-traitant dont le nom est indiqué dans ce chapitre.&lt;br /&gt;
&lt;br /&gt;
=[[Règlement Général sur la Protection des Données|Règlement général sur la protection des données (RGPD)]]=&lt;br /&gt;
[https://openflyers.com/fr/entreprise/conditions-generales Les conditions générales d'OpenFlyers v. 2] sont conformes au règlement en incluant les [[Règlement-Général-sur-la-Protection-des-Données#Conditions-générales|mentions obligatoires]]. Pour rappel :&lt;br /&gt;
*Les données appartiennent aux clients d'OpenFlyers (et non pas aux utilisateurs finaux et encore moins à OpenFlyers)&lt;br /&gt;
*Cela ne veut pas dire que l'utilisateur ou le client peuvent demander de rectifier ou supprimer des données. En effet, d'autres règlements imposent la [[#Conservation-des-documents|conservation des données]] et il doit être possible de produire les logs de connexion des utilisateurs ou des actions effectuées sur une durée raisonnable.&lt;br /&gt;
*C'est aux structures clientes d'OpenFlyers de mettre en place, au travers du paramétrage, les droits qui permettent de garantir aux utilisateurs les accès de consultation de leurs données personnelles.&lt;br /&gt;
*Nous recommandons aux structures clientes de préciser dans leurs propres conditions générales ou dans leur règlement intérieur l'acceptation par l'utilisateur final de la nécessité de stockage, par la structure, des données qui concernent les utilisateurs.&lt;br /&gt;
&lt;br /&gt;
Depuis le 27 mars 2019 (cf. actualité [https://openflyers.com/fr/actualites/certification-des-validites-et-validites-contrats Certification des validités et validités contrats]), OpenFlyers v.4 contient une fonction qui permet aux structures clientes de créer des [[Validités#Validité-contrat|validités-contrats]] que doivent signer les utilisateurs à la connexion. Cette fonction a vocation à permettre l'acceptation, par les utilisateurs finaux, des conditions générales ou du règlement intérieur d'une structure.&lt;br /&gt;
&lt;br /&gt;
Depuis le 18 juin 2019, sur les plateformes OpenFlyers sous version 4, la SARL OpenFlyers impose aux utilisateurs d'accepter les [https://openflyers.com/fr/entreprise/conditions-generales conditions générales d'OpenFlyers] grâce à cette fonction [[Validités#Validité-contrat|validité-contrat]].&lt;br /&gt;
&lt;br /&gt;
Depuis le 12 avril 2021, sur les plateformes OpenFlyers sous version 4, la fonctionnalité liées aux [[Données]] permet :&lt;br /&gt;
*de supprimer les données obsolètes&lt;br /&gt;
*de générer le registre de traitement des données personnelles prévu par le RGPD&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Navigateurs&amp;diff=12900</id>
		<title>Navigateurs</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Navigateurs&amp;diff=12900"/>
		<updated>2024-10-02T17:27:57Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de regrouper les procédures concernant les navigateurs&lt;br /&gt;
&lt;br /&gt;
=Autoriser les cookies=&lt;br /&gt;
==Autoriser les cookies sous Firefox==&lt;br /&gt;
*'''Outils &amp;gt; Options'''&lt;br /&gt;
*Onglet '''vie privée'''&lt;br /&gt;
*Cocher '''Accepter les cookies'''&lt;br /&gt;
*Bouton '''OK'''&lt;br /&gt;
&lt;br /&gt;
==Autoriser les cookies sous Internet Explorer==&lt;br /&gt;
*'''Outils &amp;gt; Options internet'''&lt;br /&gt;
*Onglet '''Confidentialité'''&lt;br /&gt;
*Positionner le niveau de sécurité au maximum à '''Moyenne'''&lt;br /&gt;
*Bouton '''OK'''&lt;br /&gt;
&lt;br /&gt;
==Autoriser les cookies sous iPhone / Safari==&lt;br /&gt;
*'''Réglages &amp;gt; Safari'''&lt;br /&gt;
*Régler '''Accepter les cookies'''&lt;br /&gt;
[[File:Accepter-cookies-iPhone-Safari.png]]&lt;br /&gt;
&lt;br /&gt;
=Autoriser les fenêtres pop-up=&lt;br /&gt;
==Autoriser les fenêtres pop-up sur Firefox==&lt;br /&gt;
* Lorsque Firefox bloque une fenêtre pop-up, un bandeau apparaît en haut de page &lt;br /&gt;
[[File:Message_blocage_popup.png]]&lt;br /&gt;
* Pour autoriser la fenêtre, cliquer sur le bouton '''Options''' du bandeau&lt;br /&gt;
* Un menu déroulant apparait, cliquer sur '''Autoriser les popups pour &amp;quot;url de la plateforme&amp;quot;'''&lt;br /&gt;
[[File:Debloquer_popup.png]]&lt;br /&gt;
* La fenêtre pop-up va s'afficher. La fois d'après, la fenêtre pop-up s'affichera directement et vous n'aurez donc pas à suivre cette procédure&lt;br /&gt;
&lt;br /&gt;
==Autoriser les fenêtres pop-up sur Internet Explorer==&lt;br /&gt;
* Lorsque Internet Explorer bloque une fenêtre pop-up, une notification apparaît en bas de la page&lt;br /&gt;
[[File:Message_blocage_popup_ie.png]]&lt;br /&gt;
* Pour autoriser la fenêtre, cliquer sur '''Options de ce site'''&lt;br /&gt;
* Un menu déroulant apparait, cliquer sur '''Toujours autoriser'''&lt;br /&gt;
[[File:Debloquer_popup_ie.png]]&lt;br /&gt;
* La fenêtre pop-up va s'afficher. La fois d'après, la fenêtre pop-up s'affichera directement et vous n'aurez donc pas à suivre cette procédure&lt;br /&gt;
&lt;br /&gt;
==Autoriser les fenêtres pop-up sur Opera==&lt;br /&gt;
* Lorsque Opera bloque une fenêtre pop-up, une notification apparaît en haut à droite de la page&lt;br /&gt;
[[File:Message_blocage_popup_opera.png]]&lt;br /&gt;
* Pour autoriser la fenêtre, cliquer sur la notification&lt;br /&gt;
* Un menu déroulant apparait, cliquer sur '''Toujours autoriser les pop-ups de &amp;quot;url de la plateforme&amp;quot;'''&lt;br /&gt;
[[File:Debloquer_popup_opera.png]]&lt;br /&gt;
* La fenêtre pop-up va s'afficher. La fois d'après, la fenêtre pop-up s'affichera directement et vous n'aurez donc pas à suivre cette procédure&lt;br /&gt;
&lt;br /&gt;
==Autoriser les fenêtres pop-up sur Safari==&lt;br /&gt;
* Cliquer sur l'icône de créneau en haut à droite &lt;br /&gt;
* Un menu déroulant apparait, cliquer sur '''Bloquer les fenêtres surgissantes''' pour enlever le symbole de coche&lt;br /&gt;
[[File:Debloquer_popup_safari.png]]&lt;br /&gt;
&lt;br /&gt;
=Créer un favori=&lt;br /&gt;
Un favori, ou signet, permet d'avoir un lien d'enregistré dans le navigateur vers la plateforme OpenFlyers et ainsi d'éviter de devoir chercher la plateforme OpenFlyers dans un moteur de recherche.&lt;br /&gt;
&lt;br /&gt;
==Créer un favori avec Firefox==&lt;br /&gt;
*Positionner la souris sur l'onglet de la page à mettre en favori&lt;br /&gt;
*Cliquer avec le bouton gauche en laissant appuyer&lt;br /&gt;
*Déplacer l'onglet vers la barre personnelle à l'endroit où on souhaite mettre le lien&lt;br /&gt;
*Relâcher le bouton gauche de la souris&lt;br /&gt;
Il est possible de supprimer l'affichage du nom de la page, pour ne garder que l'icône, en effectuant les actions suivantes :&lt;br /&gt;
*Survoler l'icône pour laquelle on souhaite supprimer l'affichage du nom de la page à sa droite&lt;br /&gt;
*Cliquer sur le bouton droit de la souris&lt;br /&gt;
*Cliquer sur le menu '''Propriétés'''&lt;br /&gt;
*Dans la fenêtre contextuelle :&lt;br /&gt;
**Supprimer le contenu dans le champ '''Nom'''&lt;br /&gt;
**Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
&lt;br /&gt;
=Créer une icône sur la page d'accueil d'un smartphone ou d'une tablette=&lt;br /&gt;
==Créer une icône sur la page d'accueil d'un smartphone ou d'une tablette Apple==&lt;br /&gt;
*Afficher la page d'accueil OpenFlyers dans le navigateur Safari&lt;br /&gt;
*Taper sur le bouton '''Partager''' (carré avec une flèche qui sort vers le haut)&lt;br /&gt;
*Taper sur le bouton '''Sur l'écran d'accueil'''&lt;br /&gt;
*Modifier éventuellement le nom dans la première ligne&lt;br /&gt;
*Taper sur le bouton '''Ajouter'''&lt;br /&gt;
&lt;br /&gt;
=Désactiver AdBlock sur Chrome=&lt;br /&gt;
AdBlock peut empêcher l'affichage des zones d'informations (flux de la structure, météo, aerobuzz, aerovfr).&lt;br /&gt;
&lt;br /&gt;
Pour empêcher la disparition de ces zones d'informations, il faut désactiver AdBlock pour le site openflyers.com. Voici la procédure :&lt;br /&gt;
*Se connecter à sa plateforme OpenFlyers&lt;br /&gt;
[[File:AdBlockMenuContextuel.jpg|200px]]&lt;br /&gt;
*Cliquer sur le bouton AdBlock symbolisant une main &amp;quot;stop&amp;quot; sur fond rouge en haut à droite du navigateur&lt;br /&gt;
*Cliquer sur '''Ne pas activer sur les pages de ce site'''&lt;br /&gt;
[[File:AdBlockChoixExclusion.jpg|300px]]&lt;br /&gt;
*Cliquer sur le bouton de confirmation '''Exclure'''&lt;br /&gt;
[[File:AdBlockRecapitulatif.jpg|300px]]&lt;br /&gt;
*Cliquer sur le bouton '''Terminée'''&lt;br /&gt;
&lt;br /&gt;
=Empêcher la mémorisation des saisies dans les formulaires=&lt;br /&gt;
Sur Chrome :&lt;br /&gt;
*Icône menu &amp;gt; '''Paramètres'''&lt;br /&gt;
*'''Afficher les paramètres avancés'''&lt;br /&gt;
*Chapitre '''Mots de passe et formulaires''' : décocher '''Activer la saisie automatique pour remplir les formulaires Web en un simple clic'''&lt;br /&gt;
&lt;br /&gt;
Sur Firefox :&lt;br /&gt;
*'''Outils &amp;gt; Options'''&lt;br /&gt;
*'''Vie privée'''&lt;br /&gt;
*Chapitre '''Historique''', décocher '''Conserver l’historique des recherches et des formulaires'''&lt;br /&gt;
&lt;br /&gt;
=Imprimer avec un navigateur=&lt;br /&gt;
==Imprimer avec Chrome==&lt;br /&gt;
*Cliquer sur le bouton en haut à droite de la barre de navigation symbolisant un menu (trois traits horizontaux)&lt;br /&gt;
*'''Imprimer...'''&lt;br /&gt;
&lt;br /&gt;
==Imprimer avec Firefox==&lt;br /&gt;
*'''Fichier &amp;gt; Imprimer...'''&lt;br /&gt;
Alternative si le menu n'est pas disponible :&lt;br /&gt;
*Cliquer sur le bouton en haut à droite de la barre de navigation symbolisant un menu (trois traits horizontaux)&lt;br /&gt;
*Cliquer sur le bouton symbolisant une imprimante&lt;br /&gt;
&lt;br /&gt;
=Supprimer une saisie automatique=&lt;br /&gt;
Si le navigateur est paramétré pour enregistrer les champs dans un formulaire, il peut être nécessaire de pouvoir supprimer une entrée. C'est par exemple le cas lorsque l'on saisit par erreur son mot de passe dans le champ identifiant et qu'il se retrouve ainsi mémorisé en clair.&lt;br /&gt;
&lt;br /&gt;
Dans le cas d'un ordinateur en accès public, il est déconseillé de paramétrer les navigateurs pour permettre cet enregistrement automatique. Voir [[#Empêcher-la-mémorisation-des-saisies-dans-les-formulaires|Empêcher la mémorisation des saisies dans les formulaires]].&lt;br /&gt;
&lt;br /&gt;
Pour supprimer cette entrée il faut :&lt;br /&gt;
*Saisir le début du texte jusqu'à ce que l'entrée à supprimer apparaisse dans la liste des propositions en auto-complétion.&lt;br /&gt;
*Positionner le curseur de la souris sur l'entrée à supprimer.&lt;br /&gt;
*Appuyer sur la touche ''Suppr'' du clavier.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Kiosque-PC&amp;diff=12898</id>
		<title>Kiosque PC</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Kiosque-PC&amp;diff=12898"/>
		<updated>2024-10-02T17:27:56Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
Le but de cette page est de référencer et de proposer des solutions de configuration pour les ordinateurs en accès public.&lt;br /&gt;
&lt;br /&gt;
Les objectifs d'un mode kiosque sont multiples et peuvent recouvrir les besoins suivants :&lt;br /&gt;
*Empêcher l'utilisateur de fermer le navigateur&lt;br /&gt;
*Empêcher l'utilisateur de changer les pages affichées&lt;br /&gt;
*Empêcher l'utilisateur de surfer sur d'autres sites que ceux autorisés&lt;br /&gt;
*Empêcher l'utilisateur de basculer sur d'autres programmes que le navigateur souhaité&lt;br /&gt;
*Empêcher l'utilisateur de lancer d'autres programmes&lt;br /&gt;
*Empêcher l'utilisateur d'accéder au &amp;quot;Bureau&amp;quot;.&lt;br /&gt;
*Empêcher l'utilisateur de pouvoir éteindre l'ordinateur&lt;br /&gt;
*Permettre à l'utilisateur d'allumer l'ordinateur dans le cas où ce dernier a eu par exemple une coupure d'alimentation mais empêcher ce dernier d'accéder au BIOS.&lt;br /&gt;
&lt;br /&gt;
Un prérequis pour la mise en place d'un ordinateur en mode kiosque consiste à ne proposer que les interfaces nécessaires à l'utilisateur :&lt;br /&gt;
*Souris&lt;br /&gt;
*Clavier&lt;br /&gt;
*Écran&lt;br /&gt;
Les autres éléments attachés à l'unité centrale ne doivent pas être accessibles (ports, lecteurs)&lt;br /&gt;
&lt;br /&gt;
Pour un PC sous Windows, les opérations suivantes permettent de mettre en place un PC kiosque avec le navigateur souhaité :&lt;br /&gt;
*[[#Lancer_un_programme_au_démarrage_de_Windows|Lancer automatiquement un programme au démarrage de Windows]]&lt;br /&gt;
*[[#Configurer_un_navigateur_en_mode_kiosque|Modifier l'icône du raccourci pour que le navigateur soit lancé en mode kiosque]] (à effectuer avec l'icône du navigateur placée dans le répertoire de démarrage&lt;br /&gt;
*[[#Bloquer-Alt+F4-avec-Deskman|Paramétrer deskman pour qu'il désactive le raccourci [Alt+F4]]] &lt;br /&gt;
Il pourra être utile d'utiliser également [[#deskman|Deskman]] pour mettre en place des restrictions d'accès sur certains site internet ou de bloquer l'exécution de programmes ou des fonctionnalités liées à Windows.&lt;br /&gt;
&lt;br /&gt;
=Créer un compte utilisateur Kiosque=&lt;br /&gt;
Il est possible de créer un compte utilisateur &amp;quot;kiosque&amp;quot; permettant de ne pas avoir de [[Connexion#Automatique|déconnexion automatique]] et permettant également d'avoir un retour automatique sur la page du planning du jour au bout de 5 minutes d'inactivité. Pour cela il faut effectuer les actions suivantes :&lt;br /&gt;
*Créer un profil &amp;quot;kiosque&amp;quot; de type public c'est à dire avec un picto associé noir [[File:Profile-management3.0.x_Userinfo_kiosk.gif]] (voir le chapitre des [[Gestion-des-profils#Icônes-symbolisant-les-droits-des-profils|Icônes symbolisant les droits des profils]]).&lt;br /&gt;
*Créer un compte kiosque/kiosque par exemple disposant de ce profil.&lt;br /&gt;
*[[#Définir_la_page_par_défaut_à_l'ouverture_du_navigateur|Mettre en place une page par défaut]] sur le navigateur du PC en accès public permettant une connexion automatique avec le compte kiosque.&lt;br /&gt;
&lt;br /&gt;
=Définir la page par défaut à l'ouverture du navigateur=&lt;br /&gt;
En l'absence d'un mode kiosque pour un PC, il est toujours possible de mettre OpenFlyers en page par défaut du navigateur.&lt;br /&gt;
&lt;br /&gt;
Pour pousser la personnalisation, il est possible de mettre dans l'adresse l'identifiant et le mot de passe de l'utilisateur sans droit ([[#Créer_un_compte_utilisateur_&amp;quot;visiteur&amp;quot;|type kiosque]]) afin de garder la page de cahier journalier affichée en permanence et dès le lancement du navigateur. Pour cela, il faut mettre en lien par défaut du navigateur le lien suivant :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;https://&amp;lt;/nowiki&amp;gt;openflyers.com/'''plateforme'''/?login='''identifiant'''&amp;amp;password='''motdepasse'''&lt;br /&gt;
&lt;br /&gt;
En remplaçant :&lt;br /&gt;
*'''plateforme''' par le nom de la plateforme de sorte à obtenir l'URL de la plateforme à la place de &amp;lt;nowiki&amp;gt;https://&amp;lt;/nowiki&amp;gt;openflyers.com/'''plateforme'''/&lt;br /&gt;
*'''identifiant''' par l'identifiant de l'utilisateur ayant un [[#Créer_un_compte_utilisateur_&amp;quot;visiteur&amp;quot;|profil kiosque]] et '''motdepasse''' par son mot de passe&lt;br /&gt;
&lt;br /&gt;
Attention, ceci ne fonctionne que pour les comptes qui n'ont uniquement un profil type &amp;quot;kiosque&amp;quot;, c'est à dire sans aucun droit.&lt;br /&gt;
&lt;br /&gt;
==Page par défaut dans Firefox==&lt;br /&gt;
*Aller dans '''Outils &amp;gt; Options'''&lt;br /&gt;
*Dans l'onglet '''Général''', renseigner le champ '''Page d'accueil''' avec l'URL souhaitée.&lt;br /&gt;
*Cliquer sur le bouton '''Fermer'''&lt;br /&gt;
&lt;br /&gt;
==Page par défaut dans Internet Explorer==&lt;br /&gt;
*Aller dans '''Outils &amp;gt; Options internet'''&lt;br /&gt;
**Dans l'onglet '''Général''', renseigner le champ '''page de démarrage''' avec l'adresse du site.&lt;br /&gt;
*Sélectionner le radio-bouton '''Démarrer avec la page d'accueil'''&lt;br /&gt;
*Cliquer sur le bouton '''OK'''&lt;br /&gt;
&lt;br /&gt;
=Solutions Mac=&lt;br /&gt;
==[http://www.icab.de/ iCab]==&lt;br /&gt;
iCab possède un mode kiosque contenant des fonctionnalités &amp;quot;Outils&amp;quot;, &amp;quot;Mode public&amp;quot;, une protection par mot de passe, et dans lequel ni le Dock de Mac Os X, ni la barre de menu n'apparaissent.&lt;br /&gt;
&lt;br /&gt;
Il faut mettre dans les ouvertures au démarrage un script en applescript, qui démarre automatiquement iCab en ouverture de session, en mode kiosque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;bash&amp;gt;tell application &amp;quot;iCab&amp;quot;&lt;br /&gt;
     Activate&lt;br /&gt;
     enter kiosk mode with password &amp;quot;password&amp;quot; &lt;br /&gt;
        -- ''le mot de passe qui permettra de sortir du mode kiosque avec le raccourci [Commande-k]''&lt;br /&gt;
     OpenURL &amp;quot;http://monsite.org/?login=monidentifiant&amp;amp;password=monmotdepasse&amp;quot; toWindow -1 &lt;br /&gt;
        -- ''ouvre la page en question dans iCab et au premier plan, en introduisant identifiant et MdP de l'utilisateur invité''&lt;br /&gt;
end tell&amp;lt;/bash&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut supprimer toutes les barres d'affichage : Adresse, Barre d'état, Signets, Liens standards, dans les Préférences du mode Kiosque PC, et mettre la page d'OF en page d'accueil du navigateur.&lt;br /&gt;
&lt;br /&gt;
Il est néanmoins nécessaire dans le mode kiosque de garder la barre de navigation, pour relancer le navigateur lors des pertes de connexion.&lt;br /&gt;
&lt;br /&gt;
Comme il est possible de n'autoriser la connexion qu'à un ou plusieurs sites nommément désignés par un système de filtres, il est possible de de bloquer le navigateur sur OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
Le mode kiosque doit être lancé depuis une session d'un utilisateur sans mot de passe (permet les ouvertures et extinctions automatiques la nuit), utilisateur qui n'a aucun droit de gestion sur l'ordinateur et qui travaille sur un Finder restreint.&lt;br /&gt;
&lt;br /&gt;
Une version Free existe, une version Pro sans limitations est disponible pour 15 €.&lt;br /&gt;
&lt;br /&gt;
==wKiosque PC Browser==&lt;br /&gt;
Il existe également [http://www.app4mac.com/wkioskbrowser.html wKiosque PC Browser], créé spécifiquement pour cet usage, mais payant ($69 pour un seul poste, la version d'essai quitte après une heure ). Il a des paramétrages très complets et en particulier relance la connexion lors du boot jusqu'à la connexion au site.&lt;br /&gt;
=Solutions Windows=&lt;br /&gt;
==Configurer un navigateur en mode kiosque==&lt;br /&gt;
===Configurer Firefox en mode kiosque===&lt;br /&gt;
Il existe des thèmes et extensions permettant de transformer Firefox en kiosque.&lt;br /&gt;
Par exemple R-kiosk.&lt;br /&gt;
&lt;br /&gt;
===Configurer Chrome en mode kiosque===&lt;br /&gt;
*Créer un raccourci de Chrome&lt;br /&gt;
*Survoler avec le pointeur de la souris l'icône du raccourci&lt;br /&gt;
*Sélectionner '''Propriétés'''&lt;br /&gt;
*Dans l'onglet '''Raccourci''', champ '''Cible''', rajouter à la fin de la ligne : ''--kiosk http://openflyers.com/plateforme/'' en remplaçant ''plateforme'' par le nom de votre plateforme OpenFlyers&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;quot;C:\Program Files (x86)\Google\Chrome\Application\chrome.exe&amp;quot; --kiosk http://openflyers.com/plateforme/&amp;lt;/pre&amp;gt;&lt;br /&gt;
*Cliquer sur le bouton '''OK'''&lt;br /&gt;
Une fois Chrome lancé, pour le fermer, il faut utiliser la combinaison de touches [Alt+F4]&lt;br /&gt;
&lt;br /&gt;
===Configurer Internet Explorer en mode kiosque===&lt;br /&gt;
*Créer un raccourci d'Internet Explorer&lt;br /&gt;
*Survoler avec le pointeur de la souris l'icône du raccourci&lt;br /&gt;
*Sélectionner '''Propriétés'''&lt;br /&gt;
*Dans l'onglet '''Raccourci''', champ '''Cible''', rajouter à la fin de la ligne : ''-k http://openflyers.com/plateforme/'' en remplaçant ''plateforme'' par le nom de votre plateforme OpenFlyers&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;quot;&amp;quot;C:\Program Files (x86)\Internet Explorer\iexplore.exe&amp;quot; -k http://openflyers.com/plateforme/&amp;lt;/pre&amp;gt;&lt;br /&gt;
*Cliquer sur le bouton '''OK'''&lt;br /&gt;
Une fois Internet Explorer lancé, pour le fermer, il faut utiliser la combinaison de touches [Alt+F4]&lt;br /&gt;
&lt;br /&gt;
==Lancer un programme au démarrage de Windows==&lt;br /&gt;
===Lancer un programme au démarrage de Windows XP===&lt;br /&gt;
Mettre un raccourci vers le navigateur dans le menu '''Démarrer &amp;gt; Programmes &amp;gt; Démarrage'''&lt;br /&gt;
&lt;br /&gt;
===Lancer un programme au démarrage de Windows 8===&lt;br /&gt;
*Ouvrir la fenêtre '''Exécuter''' par la combinaison de touches [Win+R]&lt;br /&gt;
*Saisir ''shell:startup''&lt;br /&gt;
*Dans ce répertoire démarrage, mettre un raccourci vers le navigateur&lt;br /&gt;
&lt;br /&gt;
==Sécuriser Windows==&lt;br /&gt;
===[http://www.anfibia-soft.com/products/deskman/index.html deskman]===&lt;br /&gt;
Deskman permet de contrôler l'accessibilité des fonctionnalités de Windows. Il est disponible pour Windows XP, Vista 7 et 8 en 32 et 64 bits. Il est disponible pour essai gratuitement et son prix est de 35 € pour un poste.&lt;br /&gt;
&lt;br /&gt;
====Installation de Deskman====&lt;br /&gt;
'''Attention''' : ce programme permet de limiter totalement l'accès à un ordinateur notamment en empêchant l'exécution de programmes. S'il est mal configuré, il peut devenir [[#Impossible_de_saisir_le_mot_de_passe_dans_deskman|impossible d'en retrouver le contrôle]].&lt;br /&gt;
*[http://www.anfibia-soft.com/products/deskman/index.html#getdeskman Télécharger deskman] en cliquant sur le bouton '''Donwnload Deskman'''.&lt;br /&gt;
*Exécuter ''deskmansetup.exe'', accepter les conditions générales et lancer Deskman.&lt;br /&gt;
*Cliquer sur l'icône '''Settings'''&lt;br /&gt;
*Dans l'onglet '''Basic''', formulaire '''Deskman Authentication'', renseigner dans '''Main password''' et '''Confirm password''', le mot de passe permettant d'accéder à deskman.&lt;br /&gt;
*Noter le raccourci par défaut permettant d'afficher affiché dans le formulaire '''Open Deskman''', champ '''Primary Hotkey''' : [CTRL + MAJ + F12]&lt;br /&gt;
*Cliquer sur le bouton '''Save'''.&lt;br /&gt;
&lt;br /&gt;
====Activer le contrôle avec Deskman====&lt;br /&gt;
Il faut avoir [[#Installation_de_Deskman|installé]] Deskman et mis en place un mot de passe d'accès&lt;br /&gt;
*Lancer Deskman&lt;br /&gt;
*Cliquer sur l'icône '''Secure'''&lt;br /&gt;
&lt;br /&gt;
====Bloquer Alt+F4 avec Deskman====&lt;br /&gt;
Il faut avoir [[#Installation_de_Deskman|installé]] Deskman&lt;br /&gt;
*Lancer Deskman&lt;br /&gt;
*Dans l'onglet '''Keys''', cocher '''Key Options &amp;gt; Program Closing Disable Alt-F4'''&lt;br /&gt;
*[[#Activer_le_contrôle_avec_Deskman|Activer le contrôle avec Deskman]]&lt;br /&gt;
&lt;br /&gt;
====deskman troubleshooting====&lt;br /&gt;
=====Impossible de saisir le mot de passe dans deskman=====&lt;br /&gt;
Lors de nos essais sur un PC portable avec écran tactile sous Windows 8, il nous a été impossible de saisir le mot de passe permettant de reprendre l'accès car la plupart des touches du clavier étaient reconnues commes des raccourcis pour lancer des programmes au lieu d'afficher le caractère correspondant dans le champ de saisie du mot de passe.&lt;br /&gt;
&lt;br /&gt;
Procédure pour retrouver le contrôle total et les paramètres d'origine :&lt;br /&gt;
&lt;br /&gt;
*Eteindre l'ordinateur&lt;br /&gt;
*Déconnecter le disque dur contenant Windows&lt;br /&gt;
*Déconnecter le disque dur et le connecter depuis un autre ordinateur&lt;br /&gt;
*Renommer les fichiers exécutables correspondants au programme deskman présents dans &amp;quot;Program Files (x86)\anfibia deskman&amp;quot; en rajoutant par exemple un caractère pour en empêcher l'exécution au démarrage.&lt;br /&gt;
*Reconnecter le disque dur le PC d'origine&lt;br /&gt;
*Lancer Windows : vous retrouver l'accès à l'ordinateur&lt;br /&gt;
*Remettre les noms de fichiers initiaux de deskman&lt;br /&gt;
*Désinstaller deskman&lt;br /&gt;
*Ré-installer deskman&lt;br /&gt;
*Activer deskman sans rien restreindre : cela permet de rétablir l'intégralité des accès à Windows notamment au répertoire racine &amp;quot;Ce PC&amp;quot; qui peut ne pas être réapparu.&lt;br /&gt;
*Désactiver deskman&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Introduction&amp;diff=12897</id>
		<title>Introduction</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Introduction&amp;diff=12897"/>
		<updated>2024-10-02T17:27:56Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
OpenFlyers est un logiciel de gestion d'activité qui permet de suivre l'ensemble des phases liées aux activités d'une structure qui propose des services à destination de personnes (sociétés de location, organismes de formation, sociétés de services, etc.). Ces personnes sont appelées dans OpenFlyers les &amp;quot;utilisateurs&amp;quot;. Il peut s'agir de clients, de membres, d'adhérents, de salariés, etc. Elles ont la possibilité d'interagir avec le logiciel OpenFlyers qui sert d'outil de partage de l'information :&lt;br /&gt;
*planning&lt;br /&gt;
*suivi de l'activité&lt;br /&gt;
*comptes utilisateurs&lt;br /&gt;
&lt;br /&gt;
OpenFlyers a été conçu pour répondre à un [[Bien débuter avec OpenFlyers#Workflow|workflow]] défini et qui correspond aux enchainements généralement constatés des actions au sein des structures proposant des services.&lt;br /&gt;
&lt;br /&gt;
=La gestion des réservations avec OpenFlyers=&lt;br /&gt;
OpenFlyers comporte un outil de plannification. Il s'agit d'un planning qui permet de visualiser les réservations de ressources matérielles et humaines. Typiquement, il peut s'agir du triptyque : véhicule, formateur, élève.&lt;br /&gt;
&lt;br /&gt;
[[File:OF-intro-planning.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
Selon les droits attribués aux profils des utilisateurs, ces derniers ont la possibilité d'accéder en mode consultation ou en mode édition.&lt;br /&gt;
&lt;br /&gt;
Lorsque les utilisateurs ont le droit d'effectuer des réservations, il leur suffit de cliquer sur une case correspondant à un quart d'heure du planning pour effectuer leur réservation. Un formulaire de réservation s'affiche alors afin de leur permettre de compléter les informations nécessaires à la réservation :&lt;br /&gt;
&lt;br /&gt;
[[File:OF-intro-reserver.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
=La gestion d'activité avec OpenFlyers=&lt;br /&gt;
==Génération du chiffre d'affaire et gestion des encaissements clients==&lt;br /&gt;
L'une des fonctionnalités d'OpenFlyers est de gérer les comptes comptables des utilisateurs.&lt;br /&gt;
&lt;br /&gt;
Le processus chronologique est le suivant :&lt;br /&gt;
===saisie de l'activité===&lt;br /&gt;
Il s'agit typiquement de la saisie des heures de vols.&lt;br /&gt;
&lt;br /&gt;
Cette saisie peut se faire directement par l'utilisateur final ou être centralisée au sein d'un service dédié (secrétariat par exemple). &lt;br /&gt;
&lt;br /&gt;
Cependant, nous recommandons fortement de déléguer la saisie à l'utilisateur final. Cela présente 2 avantages :&lt;br /&gt;
*Renforcement de la qualité de l'action de contrôle effectuée en aval par un service centralisé (secrétariat par exemple). En effet, il a été constaté que lorsque la personne qui saisit l'activité est également la personne qui contrôle la saisie, ce contrôle est effectué avec moins d'assiduité pour des raisons qui relèvent des [[Wikipedia-fr:Facteurs_humains|facteurs humains]] : une personne aura tendance à se faire confiance et à moins remettre en cause sa propre action. De ce fait, elle détectera moins facilement ses propres erreurs de saisie. C'est la raison pour laquelle il est judicieux de faire effectuer ce contrôle par une autre personne.&lt;br /&gt;
*Délégation à l'utilisateur (qui peut être le client) et ainsi une diminution des tâches récurrentes pour la structure.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour les heures de vols, cette saisie se fait grâce au menu '''Vols &amp;gt; Saisir un vol''' ou grâce à '''Saisir un vol''' qui apparait dans le menu contextuel en survolant une réservation. L'utilisateur remplit ainsi un formulaire de saisie qui peut être personnalisé selon les règles et la politique de la structure :&lt;br /&gt;
&lt;br /&gt;
[[File:FOF-intro-saisie-activite.jpg|1050px]]&lt;br /&gt;
&lt;br /&gt;
Dès qu'un vol est saisi &amp;quot;fermé&amp;quot; une facture pro-format, un devis ou un bon de commande est généré et les écritures comptables qui en découlent sont automatiquement générées. Ces écritures ne sont pas définitives et peuvent être modifiées en modifiant la saisie du vol. C'est l'équivalent du ''Brouillard'' existant dans les logiciels de comptabilité. Elles apparaissent en vert italique sur les relevés de comptes, les carnets de routes, carnets de vols et sur les listes des vols. La personne qui a saisit le vol peut le reprendre et les personnes disposant des droits de gestion peuvent modifier cette saisie.&lt;br /&gt;
&lt;br /&gt;
Si des anomalies sont détectées lors de la saisie, alors des alertes sont affichées à l'utilisateur demandant à l'utilisateur de compléter/corriger sa saisie. Cela peut également être le cas pour des champs dont la saisie est indispensable et qui n'auraient pas été remplis.&lt;br /&gt;
&lt;br /&gt;
'''Conseil OpenFlyers :'''&lt;br /&gt;
*Dans le cas où les vols sont saisis directement par les pilotes, nous recommandons de demander aux pilotes de saisir d'abord leur vol dans OpenFlyers et ensuite de recopier ce qui est saisit dans OpenFlyers sur le carnet de route. Ainsi, on est sûr que les 2 informations coïncideront et que les calculs faits par l'application OpenFlyers seront en conformité avec les calculs qui seraient fait au vu du carnet de route qui est le seul document officiel.&lt;br /&gt;
&lt;br /&gt;
====Modes de saisie ouverture+fermeture ou fermeture seule====&lt;br /&gt;
Il existe dans OpenFlyers deux modes de gestion de l'activité :&lt;br /&gt;
*mode ouverture+fermeture = on ouvre une activité avant de la débuter et on la referme après l'avoir terminée&lt;br /&gt;
*mode fermeture seule = on ferme uniquement l'activité une fois qu'elle est terminée&lt;br /&gt;
&lt;br /&gt;
Si on choisit la &amp;lt;i&amp;gt;fermeture des vols seulement&amp;lt;/i&amp;gt; le pilote devra remplir à l'issue de son vol un formulaire qui fait office de carnet de route de l'aéronef ; il y renseigne le même type d'informations, entre autres les index de départ et d'arrivée, ce qui permettra à Openflyers de calculer le coût du vol.&lt;br /&gt;
&lt;br /&gt;
Si on choisit &amp;lt;i&amp;gt;ouverture et fermeture des vols&amp;lt;/i&amp;gt; on doit lors de la prise de l'aéronef renseigner un formulaire où l'on précise la durée estimée, la destination ainsi que d'autres informations.&lt;br /&gt;
L'ouverture du vol présente 3 avantages :&lt;br /&gt;
*Alerter le pilote avant son départ en cas de validités expirées, de solde de compte insuffisant&lt;br /&gt;
*Permettre d'avoir un &amp;quot;mini-plan de vol&amp;quot; en connaissant où à prévu d'aller le pilote, pour combien de temps et avec combien de personnes&lt;br /&gt;
*Permettre aux autres utilisateurs de savoir si une ressource est réellement disponible même lorsqu'elle n'a pas été réservée au préalable&lt;br /&gt;
En effet, lorsqu'un vol est ouvert, un créneau bleu apparait sur le planning de réservation et le fond du rectangle de l'aéronef correspondant apparait également sur fond bleu&lt;br /&gt;
&lt;br /&gt;
L'ouverture du vol permet enfin de gérer l'armoire à clef OpenFlyers et ainsi de libérer ou non la clef en fonction des nombreux critères (solde du compte, qualification à jour...)&lt;br /&gt;
&lt;br /&gt;
===Saisie des encaissements===&lt;br /&gt;
Les encaissements peuvent être saisis à tout moment et de façon indépendante de l'activité.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tout comme pour l'activité, la saisie peut être autorisée aux utilisateurs finaux ou restreinte à certaines personnes en charge de la gestion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cette saisie s'effectue côté planning, par le biais du menu '''Comptes &amp;gt; Approvisionner'''.&lt;br /&gt;
&lt;br /&gt;
[[File:OF-intro-encaissement.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
Toutes les écritures saisies sont modifiables comme pour les vols sauf dans le cas d'un paiement par l'intermédiaire d'un Terminal de Paiement Électronique virtuel (paiement en ligne). En effet, dans ce dernier cas, la validation par la banque du numéro de carte bancaire vaut acceptation par celle-ci et confirmation du montant débité sur le compte attaché à la carte bancaire. Il n'y a donc pas nécessité de valider à posteriori cette écriture comptable. C'est même tout son intérêt : elle permet d'automatiser le processus d'encaissement.&lt;br /&gt;
&lt;br /&gt;
===[[Gestion-des-activités#Valider-une-activité|Validation de la saisie de l'activité]]===&lt;br /&gt;
&lt;br /&gt;
===Validation de la saisie des encaissements===&lt;br /&gt;
La validation de la saisie encaissements n'a pas lieu dans le cas d'un paiement par carte bancaire sur un Terminal de Paiement Électronique virtuel (paiement en ligne).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dans les autres cas, la validation s'effectue dans '''Comptes &amp;gt; Pointer &amp;gt; xxx''' où il faut remplacer xxx par le type de paiement dont on souhaite valider les écritures.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Conseils OpenFlyers :'''&lt;br /&gt;
*Le pointage des encaissements doit se faire au vu de ces derniers : on pointe les chèques en contrôlant les chèques.&lt;br /&gt;
*Une fois le pointage effectué dans OpenFlyers et après appuie sur la touche '''Editer le bordereau de remise''', la personne en charge du pointage voit apparaitre le bordereau de remise. Il est important qu'à ce moment là, le bordereau soit imprimé 2 fois : une fois pour la remise en banque et une fois pour archivage.&lt;br /&gt;
&lt;br /&gt;
==Consultation des écritures==&lt;br /&gt;
Un utilisateur peut retrouver l'ensemble des écritures qui concernent son compte depuis le côté Planning en cliquant sur la zone en haut et à droite du planning où apparait le solde de son compte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il retrouve alors l'ensemble des écritures qui impactent son compte :&lt;br /&gt;
*les factures&lt;br /&gt;
*les paiements qu'il a effectué&lt;br /&gt;
Ces écritures sont :&lt;br /&gt;
*soit en vert italique pour indiquer qu'elles peuvent être modifiées : il a alors la possibilité de les modifier lui-même (sous réserve qu'il dispose des droits) à l'aide de la fonction '''modifier''' qui correspond à l'icône symbolisant un '''crayon''' présente dans la colonne '''action''' à droite de son relevé de comptes.&lt;br /&gt;
*soit en noir pour indiquer qu'elles sont définitives&lt;br /&gt;
&lt;br /&gt;
=Le suivi et l'enregistrement de trajectoire avec OpenFlyers et Charterware=&lt;br /&gt;
OpenFlyers se couple à la solution Charterware pour l'enregistrement automatique des vols et la récupération des trajectoires.&lt;br /&gt;
&lt;br /&gt;
Voir https://openflyers.com/fr/fonctionnalites/recuperation-automatique-des-vols-avec-charterware&lt;br /&gt;
&lt;br /&gt;
=[[Bien débuter avec OpenFlyers|Bien débuter avec OpenFlyers]]=&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Interfa%C3%A7age-OpenFlyers-et-armoire-%C3%A0-cl%C3%A9s&amp;diff=12896</id>
		<title>Interfaçage OpenFlyers et armoire à clés</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Interfa%C3%A7age-OpenFlyers-et-armoire-%C3%A0-cl%C3%A9s&amp;diff=12896"/>
		<updated>2024-10-02T17:27:55Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
=Présentation=&lt;br /&gt;
L'objet de cette page est de décrire le protocole d'interfaçage avec toute solution d'armoire à clés tiers. Pour les armoires à clés commercialisées par OpenFlyers, il faut se référer à la [[Contrôle des accès|documentation sur le contrôle d'accès]].&lt;br /&gt;
&lt;br /&gt;
Le protocole repose sur le principe que l'interfaçage est réalisé par un logiciel de contrôle de l'armoire à clé sur un PC ou une solution embarquée et qui dispose d'un accès à internet lui permettant de communiquer avec OpenFlyers. La communication est synchrone.&lt;br /&gt;
&lt;br /&gt;
=Interface utilisateur OpenFlyers=&lt;br /&gt;
L'utilisateur ouvre un vol dans OpenFlyers :&lt;br /&gt;
&lt;br /&gt;
[[File:Menu-contextuel-ouverture-de-vol.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Il se retrouve sur le formulaire de saisie du vol en mode Départ en vol:&lt;br /&gt;
&lt;br /&gt;
[[File:Formulaire-ouverture-de-vol.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lorsqu'il clique sur le bouton de validation, 3 cas peuvent se présenter :&lt;br /&gt;
*Une alerte ou plusieurs alertes rouges (bloquantes), s'affichent : l'utilisateur n'a pas la possibilité de surpasser ses alertes, il ne peut alors récupérer la clé :&lt;br /&gt;
&lt;br /&gt;
[[File:Alertes-bloquantes-en-ouverture-vol.png]]&lt;br /&gt;
&lt;br /&gt;
*Une alerte ou plusieurs alertes oranges (non-bloquantes), s'affichent : l'utilisateur a la possibilité de surpasser ses alertes, et ainsi de récupérer la clé :&lt;br /&gt;
&lt;br /&gt;
[[File:Alertes-non-bloquantes-en-ouverture-vol.png]]&lt;br /&gt;
&lt;br /&gt;
*Aucune alerte ne s'affiche, l'utilisateur se retrouve alors directement sur la page lui indiquant :&lt;br /&gt;
&lt;br /&gt;
[[File:Message_autorisation_libération_clé.png]]&lt;br /&gt;
&lt;br /&gt;
Une fois qu'il a cliqué sur '''LIBÉRER LA CLÉ''', il dispose de X secondes. Cette durée est paramétrable par OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
*Lorsqu'il rentre de vol, l'utilisateur n'a plus qu'a retourner sur le formulaire de saisie de vol et à fermer son vol. La clé doit etre remise en place sur l'armoire pour fermer le vol.&lt;br /&gt;
&lt;br /&gt;
=Interface administrateur OpenFlyers=&lt;br /&gt;
==Activation et configuration de la gestion des armoires à clé==&lt;br /&gt;
*'''Admin &amp;gt; Structure &amp;gt; Structure &amp;gt; Paramétrage'''&lt;br /&gt;
*Dans la section du formulaire '''Contrôle d'accès''', sélectionner '''Activé(e)''' pour les champs '''Contrôle d'accès''' et '''Gestion armoire à clés'''.&lt;br /&gt;
[[File:Config_parametres_OF_controle_acces 1.jpg]]&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer''' &lt;br /&gt;
*Un nouveau champ s'affich&lt;br /&gt;
*Sélectionner le '''Logiciel de contrôle de l'armoire à clés''' selon votre armoire à clés&lt;br /&gt;
[[File:Config_parametres_OF_controle_acces 4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Les Logiciels OpenKey et PyOpenKey sont des protocoles propriétaires d'OF, pour les configurer voir  [[Interfaçage-OpenFlyers-et-armoire-à-clés#Interface-administrateur-OpenFlyers | Interfaçage armoire à clés OF]]&lt;br /&gt;
&lt;br /&gt;
==Attribution des clés aux ressources/aéronefs==&lt;br /&gt;
''Dans le cas où c'est le logiciel OpenFlyers qui gère les clés.''&lt;br /&gt;
*'''Admin &amp;gt; Types de ressources &amp;gt; Actives'''&lt;br /&gt;
[[File:Liste_des_aéronefs.png]]&lt;br /&gt;
&lt;br /&gt;
Pour chaque aéronef concerné, il suffit d'attribuer un numéro et un nom de clé dans les champs correspondants. La validation de la saisie se fait automatiquement en cliquant hors du champ de saisie.&lt;br /&gt;
&lt;br /&gt;
=Protocole de dialogue XML-RPC entre OpenFlyers et le logiciel de gestion de l'armoire à clé=&lt;br /&gt;
Le dialogue avec le serveur XML-RPC d'OpenFlyers doit s'effectuer en '''HTTPS'''. Les commandes accessibles sont listées par un appel à ActionOnDemand.php&lt;br /&gt;
https://openflyers.com/yourURL/actionOnDemand.php&lt;br /&gt;
&lt;br /&gt;
==Demande de libération d'une clé==&lt;br /&gt;
&lt;br /&gt;
===Cas avec gestion des clés par OpenFlyers===&lt;br /&gt;
&lt;br /&gt;
*Lorsque qu'une clé doit être libérée, le navigateur envoie un message au logiciel de contrôle de l'armoire à clé par le protocole HTTPS sous la forme suivante :&lt;br /&gt;
https://127.0.0.1:4080/?sessid=e5f01p2oqh2vb36arisr8k5j87&amp;amp;amp;timeOut=10000&amp;amp;amp;key=1&amp;amp;amp;resource=2&amp;amp;amp;person=12;action='releaseKey'&lt;br /&gt;
&lt;br /&gt;
:*L'adresse IP (ici 127.0.0.1) et le port (ici 4080) sont fonction de la [[#Activation_et_configuration_de_la_gestion_des_armoires_à_clé|configuration de l'armoire à clé dans OpenFlyers]].&lt;br /&gt;
:*sessid contient le numéro de session en cours&lt;br /&gt;
:*timeout correspond au temps d'attente pour la prise d'une clé en millisecondes&lt;br /&gt;
:*key contient le numéro de la clé concernée&lt;br /&gt;
:*resource contient le numéro de la ressource concernée&lt;br /&gt;
:*person contient le numéro de l'utilisateur qui fait la demande&lt;br /&gt;
:*action est un mot clé désignant l'objet de la commande&lt;br /&gt;
:**release_key: ordre de libérer la clé&lt;br /&gt;
:**open_door: ordre d'ouvrir la porte&lt;br /&gt;
:**init_tags: ordre de lire les tags des clés&lt;br /&gt;
*Le logiciel de contrôle de l'armoire à clé doit alors envoyer une demande d'ordre au serveur OpenFlyers à l'adresse suivante https://openflyers.com/structure/ où il faut remplacer openflyers.com/structure par l'adresse de la plateforme OpenFlyers concernée, avec comme commande XML_RPC '''checkCommand (&amp;quot;e5f01p2oqh2vb36arisr8k5j87&amp;quot;,int(key))'''.&lt;br /&gt;
&lt;br /&gt;
*Le serveur OpenFlyers vérifie alors l'action demandée :&lt;br /&gt;
Pour release_key, il est vérifié :&lt;br /&gt;
#Que la clé est au bon format et existe. Lorsque la clé est validée, on passe à l'étape suivante sinon on retourne 0&lt;br /&gt;
#Que l'utilisateur faisant la demande est bien celui qui est connecté. Lorsque c'est le cas, on passe à l'étape suivante sinon on retourne 0&lt;br /&gt;
#Ensuite si l'utilisateur qui a passé la demande :&lt;br /&gt;
#*A le droit '''Gestion des clés''' (administrateur) alors on libère la clé sans condition (cela permet de libérer la clé sans contrôle) et on retourne 1&lt;br /&gt;
#*N'a pas le droit '''Gestion des clés''' (pilote) alors on vérifie s'il existe un vol ouvert qui remplit la double condition :&lt;br /&gt;
#**Vol attribué à l'utilisateur&lt;br /&gt;
#**Aéronef du vol associé à la demande de libération de la clé&lt;br /&gt;
#**Lorsque la double condition est remplie, on retourne 1 sinon 0&lt;br /&gt;
&lt;br /&gt;
*Le serveur retourne ensuite la réponse :&lt;br /&gt;
**1 dans le cas d'autorisation de libération de clé &lt;br /&gt;
**0 dans le cas contraire&lt;br /&gt;
&lt;br /&gt;
====Exemple de script en Python d'utilisation de la commande checkCommand avec gestion des clés====&lt;br /&gt;
&amp;lt;python&amp;gt;# load library&lt;br /&gt;
from twisted.web.xmlrpc import Proxy&lt;br /&gt;
from twisted.internet import reactor, ssl&lt;br /&gt;
 &lt;br /&gt;
def printValue(value):&lt;br /&gt;
    print repr(value)&lt;br /&gt;
    reactor.stop()&lt;br /&gt;
 &lt;br /&gt;
def printError(error):&lt;br /&gt;
    print 'error', error&lt;br /&gt;
    reactor.stop()&lt;br /&gt;
 &lt;br /&gt;
# URL of the XML-RPC server&lt;br /&gt;
proxy = Proxy('https://yourURL.xx/actionOnDemand.php')&lt;br /&gt;
 &lt;br /&gt;
# init array to send&lt;br /&gt;
sessid = &amp;quot;&amp;quot;&lt;br /&gt;
key_num = 1&lt;br /&gt;
 &lt;br /&gt;
# send to the XML-RPC server&lt;br /&gt;
proxy.callRemote('checkCommand', sessid, key_num).addCallbacks(printValue, printError)&lt;br /&gt;
reactor.run()&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce test peut être complété (pour obtenir une réponse &amp;quot;1&amp;quot;) en simulant une armoire à clé à l'aide d'un script PHP de la façon suivante :&lt;br /&gt;
*Installer un serveur local (par exemple [https://www.wampserver.com/ wampserver] sous Windows) de façon à avoir le port 127.0.0.1 qui lui est attribué&lt;br /&gt;
*Configurer la plateforme OpenFlyers de manière à gérer l'armoire à clé avec les éléments suivants :&lt;br /&gt;
**'''IP du PC contenant le logiciel de contrôle''' : 127.0.0.1&lt;br /&gt;
**'''Port du PC contenant le logiciel de contrôle''' : 80&lt;br /&gt;
*Configurer la plateforme OpenFlyers de manière à gérer les clés&lt;br /&gt;
*A la racine du répertoire www, mettre le script index.php suivant (on suppose que ce script est appelé par défaut lorsqu'on utilise l'URL https://127.0.0.1 ) :&lt;br /&gt;
&amp;lt;php&amp;gt;&amp;lt;?php &lt;br /&gt;
file_put_contents('test.txt', 'TEST', FILE_APPEND );&lt;br /&gt;
file_put_contents('test.txt', print_r($_REQUEST, true), FILE_APPEND );&lt;br /&gt;
?&amp;gt;&amp;lt;/php&amp;gt;&lt;br /&gt;
*Toujours à la racine du répertoire www, créer un fichier test.txt&lt;br /&gt;
Le script PHP écrira dans le fichier test.txt les variables transmises lors de la demande d'ouverture de l'armoire à clé :&lt;br /&gt;
&amp;lt;pre&amp;gt;TESTArray&lt;br /&gt;
(&lt;br /&gt;
    [sessid] =&amp;gt; j2eo92215nbef09borb74jftm1&lt;br /&gt;
    [key] =&amp;gt; 1&lt;br /&gt;
    [resource] =&amp;gt; 1&lt;br /&gt;
    [person] =&amp;gt; 1&lt;br /&gt;
)&amp;lt;/pre&amp;gt;&lt;br /&gt;
*Il suffit alors de recopier la valeur de '''sessid''' et de '''key''' dans le script python de ce début de paragraphe et de le tester : il devrait renvoyer 1.&lt;br /&gt;
&lt;br /&gt;
===Cas sans gestion des clés par OpenFlyers===&lt;br /&gt;
&lt;br /&gt;
*Lorsque qu'une demande de vérification doit être réalisée, le navigateur envoie un message au logiciel de contrôle de l'armoire à clé par le protocole HTTPS sous la forme suivante :&lt;br /&gt;
https://127.0.0.1:4080/?sessid=e5f01p2oqh2vb36arisr8k5j87&amp;amp;amp;resource=2&amp;amp;amp;person=12&lt;br /&gt;
&lt;br /&gt;
:*L'adresse IP (ici 127.0.0.1) et le port (ici 4080) sont fonction de la [[#Activation_et_configuration_de_la_gestion_des_armoires_à_clé|configuration de l'armoire à clé dans OpenFlyers]].&lt;br /&gt;
:*sessid contient le numéro de session en cours&lt;br /&gt;
:*resource contient le numéro de la ressource concernée&lt;br /&gt;
:*person contient le numéro de l'utilisateur qui fait la demande&lt;br /&gt;
*Le logiciel de contrôle de l'armoire à clé doit alors envoyer une demande d'ordre au serveur OpenFlyers à l'adresse suivante https://openflyers.com/structure/actionOnDemand.php où il faut remplacer openflyers.com/structure par l'adresse de la plateforme OpenFlyers concernée, avec comme commande XML_RPC '''checkCommand (&amp;quot;e5f01p2oqh2vb36arisr8k5j87&amp;quot;)'''.&lt;br /&gt;
&lt;br /&gt;
*Le serveur OpenFlyers vérifie alors :&lt;br /&gt;
#Que l'utilisateur faisant la demande est bien celui qui est connecté. Lorsque c'est le cas, on passe à l'étape suivante sinon on retourne 0&lt;br /&gt;
#On vérifie s'il existe un vol ouvert qui remplit la double condition :&lt;br /&gt;
#*Vol attribué à l'utilisateur&lt;br /&gt;
#*Aéronef du vol associé à la demande de libération de la clé&lt;br /&gt;
#*Lorsque la double condition est remplie, on retourne 1 sinon 0&lt;br /&gt;
&lt;br /&gt;
*Le serveur retourne ensuite la réponse :&lt;br /&gt;
**1 dans le cas d'autorisation&lt;br /&gt;
**0 dans le cas contraire&lt;br /&gt;
&lt;br /&gt;
====Exemple de script en Python d'utilisation de la commande checkCommand sans gestion des clés====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;# load library&lt;br /&gt;
from twisted.web.xmlrpc import Proxy&lt;br /&gt;
from twisted.internet import reactor, ssl&lt;br /&gt;
 &lt;br /&gt;
def printValue(value):&lt;br /&gt;
    print repr(value)&lt;br /&gt;
    reactor.stop()&lt;br /&gt;
 &lt;br /&gt;
def printError(error):&lt;br /&gt;
    print 'error', error&lt;br /&gt;
    reactor.stop()&lt;br /&gt;
 &lt;br /&gt;
# URL of the XML-RPC server&lt;br /&gt;
proxy = Proxy('https://yourURL.xx/actionOnDemand.php')&lt;br /&gt;
 &lt;br /&gt;
# init array to send&lt;br /&gt;
sessid = &amp;quot;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
# send to the XML-RPC server&lt;br /&gt;
proxy.callRemote('checkCommand', sessid).addCallbacks(printValue, printError)&lt;br /&gt;
reactor.run()&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ce test peut être complété (pour obtenir une réponse &amp;quot;1&amp;quot;) en simulant une armoire à clé à l'aide d'un script PHP de la façon suivante :&lt;br /&gt;
*Installer un serveur local (par exemple [https://www.wampserver.com/ wampserver] sous Windows) de façon à avoir le port 127.0.0.1 qui lui est attribué&lt;br /&gt;
*Configurer la plateforme OpenFlyers de manière à gérer l'armoire à clé avec les éléments suivants :&lt;br /&gt;
**'''IP du PC contenant le logiciel de contrôle''' : 127.0.0.1&lt;br /&gt;
**'''Port du PC contenant le logiciel de contrôle''' : 80&lt;br /&gt;
*Configurer la plateforme OpenFlyers de manière à ne pas gérer les clés&lt;br /&gt;
*A la racine du répertoire www, mettre le script index.php suivant (on suppose que ce script est appelé par défaut lorsqu'on utilise l'URL https://127.0.0.1 ) :&lt;br /&gt;
&amp;lt;php&amp;gt;&amp;lt;?php &lt;br /&gt;
file_put_contents('test.txt', 'TEST', FILE_APPEND );&lt;br /&gt;
file_put_contents('test.txt', print_r($_REQUEST, true), FILE_APPEND );&lt;br /&gt;
?&amp;gt;&amp;lt;/php&amp;gt;&lt;br /&gt;
*Toujours à la racine du répertoire www, créer un fichier test.txt&lt;br /&gt;
Le script PHP écrira dans le fichier test.txt les variables transmises lors de la demande d'ouverture de l'armoire à clé :&lt;br /&gt;
&amp;lt;pre&amp;gt;TESTArray&lt;br /&gt;
(&lt;br /&gt;
    [sessid] =&amp;gt; j2eo92215nbef09borb74jftm1&lt;br /&gt;
    [resource] =&amp;gt; 1&lt;br /&gt;
    [person] =&amp;gt; 1&lt;br /&gt;
)&amp;lt;/pre&amp;gt;&lt;br /&gt;
*Il suffit alors de recopier la valeur de '''sessid''' dans le script python de ce début de paragraphe et de le tester : il devrait renvoyer 1.&lt;br /&gt;
&lt;br /&gt;
==Modification de l'état d'une clé==&lt;br /&gt;
''Applicable dans le cas où le protocole PyOpenKeys2 gère les clés.''&lt;br /&gt;
*Le logiciel de contrôle de l'armoire à clés doit envoyer un ordre '''notify([1,0,1,1,1,1,0,0], &amp;quot;passphrase&amp;quot;)''' avec comme paramètre un tableau chronologique des clés ayant pour valeur leur état &lt;br /&gt;
''Applicable dans le cas où le protocole PyOpenKeys3 gère les clés.''&lt;br /&gt;
*Le logiciel de contrôle de l'armoire à clés doit envoyer un ordre '''notify2([[1,1],[2,0],[3,1],[4,1],[5,1],[6,1],[7,0],[8,0]], &amp;quot;passphrase&amp;quot;)''' avec comme paramètre un tableau de tableau avec le numéro de la clé suivi de son état&lt;br /&gt;
**1 = interrupteur de présence de clé fermé = clé absente de l'armoire&lt;br /&gt;
**0 = interrupteur de présence de clé ouvert = clé présente dans l'armoire&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
===Exemple de script en Python pour la commande notify===&lt;br /&gt;
Nécessite les librairies Twisted et OpenSSL&lt;br /&gt;
&lt;br /&gt;
&amp;lt;python&amp;gt;# load library&lt;br /&gt;
from twisted.web.xmlrpc import Proxy&lt;br /&gt;
from twisted.internet import reactor, ssl&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
def printValue(value):&lt;br /&gt;
    print repr(value)&lt;br /&gt;
    reactor.stop()&lt;br /&gt;
&lt;br /&gt;
def printError(error):&lt;br /&gt;
    print 'error', error&lt;br /&gt;
    reactor.stop()&lt;br /&gt;
&lt;br /&gt;
# URL of the XML-RPC server&lt;br /&gt;
proxy = Proxy('https://yourURL.xx/actionOnDemand.php')&lt;br /&gt;
&lt;br /&gt;
# init passphrase&lt;br /&gt;
passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'&lt;br /&gt;
&lt;br /&gt;
# Initiate number of key&lt;br /&gt;
KEY_NUMBER = 16&lt;br /&gt;
&lt;br /&gt;
# init array to send&lt;br /&gt;
state = random.randint(0,1)&lt;br /&gt;
&lt;br /&gt;
if KEY_NUMBER &amp;gt; 8:&lt;br /&gt;
    # Test notify2&lt;br /&gt;
    status = [[d+1,0] for d in range(KEY_NUMBER)]&lt;br /&gt;
    for i in range(KEY_NUMBER):&lt;br /&gt;
        status[i] = [i+1,state]&lt;br /&gt;
        # Alternate 0 and 1 for test&lt;br /&gt;
        state = 0 if state == 1 else 1&lt;br /&gt;
else:&lt;br /&gt;
    # Test notify&lt;br /&gt;
    for i in range(KEY_NUMBER):&lt;br /&gt;
        status.append(state)&lt;br /&gt;
        # Alternate 0 and 1 for test&lt;br /&gt;
        state = 0 if state == 1 else 1&lt;br /&gt;
&lt;br /&gt;
# send to the XML-RPC server&lt;br /&gt;
print &amp;quot;Status sequence : %s&amp;quot; % status&lt;br /&gt;
if KEY_NUMBER&amp;lt;9:&lt;br /&gt;
    proxy.callRemote('notify', status, passphrase).addCallbacks(printValue, printError)&lt;br /&gt;
else:&lt;br /&gt;
    proxy.callRemote('notify2', status, passphrase).addCallbacks(printValue, printError)&lt;br /&gt;
reactor.run()&lt;br /&gt;
&amp;lt;/python&amp;gt;&lt;br /&gt;
''Nota : to test change the number of key : up to 8 the software use '''notify()''', beyond it uses '''notify2()'''&lt;br /&gt;
&lt;br /&gt;
Cela retournera 0 en cas d'anomalie ou si la passphase transmise n'est pas correcte, 1 si la table des clés a été correctement mise à jour.&lt;br /&gt;
&lt;br /&gt;
==Fermeture automatique d'un vol==&lt;br /&gt;
&lt;br /&gt;
Le logiciel de contrôle de l'armoire à clé doit envoyer un ordre '''closeFlight(&amp;quot;passphrase&amp;quot;, &amp;quot;id de ressource&amp;quot;)''' avec comme paramètre un passphrase et l'id qui va entraîner la fermeture du vol effectué sur cette ressource si un vol avait été ouvert et que la &amp;quot;Fermeture automatique des&lt;br /&gt;
vols au retour de la clé&amp;quot; soit activée. La commande retournera comme réponse une structure JSON pour déterminer si la fermeture du vol s'est bien réalisée ou non et qu'il n'y a pas eu d'erreur.&lt;br /&gt;
&lt;br /&gt;
Réponse quand la vérification du passphrase est incorrecte, ce qui a entraîné la non-fermeture du vol :&lt;br /&gt;
&amp;lt;javascript&amp;gt;{[&lt;br /&gt;
    ack : 0&lt;br /&gt;
]}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Réponse quand la vérification du passphrase est correcte et que la demande de fermeture du vol s'est bien réalisée :&lt;br /&gt;
&amp;lt;javascript&amp;gt;{[&lt;br /&gt;
    ack : 1&lt;br /&gt;
]}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Réponse quand la vérification du passphrase est correcte et que la demande de fermeture du vol ne s'est pas bien réalisée suite à une erreur :&lt;br /&gt;
&amp;lt;javascript&amp;gt;{[&lt;br /&gt;
    ack : 1,&lt;br /&gt;
    error : 'Message d\'erreur ...'&lt;br /&gt;
]}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Script d'exemple pour closeFlight===&lt;br /&gt;
&amp;lt;python&amp;gt;# load library&lt;br /&gt;
from twisted.web.xmlrpc import Proxy&lt;br /&gt;
from twisted.internet import reactor, ssl&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
def printValue(value):&lt;br /&gt;
    print repr(value)&lt;br /&gt;
    reactor.stop()&lt;br /&gt;
&lt;br /&gt;
def printError(error):&lt;br /&gt;
    print 'error', error&lt;br /&gt;
    reactor.stop()&lt;br /&gt;
&lt;br /&gt;
# URL of the XML-RPC server&lt;br /&gt;
proxy = Proxy('https://yourURL.xx/actionOnDemand.php')&lt;br /&gt;
&lt;br /&gt;
# Id of resource which needs a flight closing&lt;br /&gt;
resource_id = 1&lt;br /&gt;
&lt;br /&gt;
# init passphrase&lt;br /&gt;
passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'&lt;br /&gt;
&lt;br /&gt;
# send to the XML-RPC server&lt;br /&gt;
proxy.callRemote('closeFlight', resource_id, passphrase).addCallbacks(printValue, printError)&lt;br /&gt;
reactor.run()&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Exemple de script en Python de logiciel de contrôle d'une armoire==&lt;br /&gt;
&amp;lt;python&amp;gt;#!/usr/bin/python&lt;br /&gt;
import xmlrpclib, time, dummy_proto, hashlib&lt;br /&gt;
from twisted.internet import reactor, task, threads, ssl&lt;br /&gt;
from twisted.application import internet, service&lt;br /&gt;
from twisted.internet.protocol import Protocol, ClientCreator, ReconnectingClientFactory&lt;br /&gt;
from twisted.web import resource, server&lt;br /&gt;
&lt;br /&gt;
# Port from which the OF client contact OpenKeys service&lt;br /&gt;
SERVICE_PORT=4080 &lt;br /&gt;
# IP address of the OpenKeys service&lt;br /&gt;
SERVICE_HOST=&amp;quot;192.168.0.200&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# IP address of the key cabinet&lt;br /&gt;
KEYS_ADDR='192.168.0.201'&lt;br /&gt;
# Port from which OpenKeys service contacts the key cabinet&lt;br /&gt;
KEYS_PORT=6002&lt;br /&gt;
#Time to release the key&lt;br /&gt;
KEY_RELEASE_DURATION=15&lt;br /&gt;
&lt;br /&gt;
# sha224 passwords&lt;br /&gt;
PASSWORDS=('847bed9bc354e7e47bc5350a3b3aaf6124f5748224a3c7ad79586c3c')&lt;br /&gt;
&lt;br /&gt;
# init passphrase&lt;br /&gt;
passphrase = 'SDjklsdiuQSIPO23879ZERK2098ZL2908DFZLK'&lt;br /&gt;
&lt;br /&gt;
OF_XMLRPC_URL=&amp;quot;https://openflyers.com/structure/actionOnDemand.php&amp;quot;&lt;br /&gt;
&lt;br /&gt;
DEBUG=False&lt;br /&gt;
&lt;br /&gt;
class dummyProtocol(Protocol):&lt;br /&gt;
	def __init__(self, rpc_server):&lt;br /&gt;
		self.rpc_server=rpc_server&lt;br /&gt;
		self.lc = None&lt;br /&gt;
&lt;br /&gt;
	def connectionMade(self):&lt;br /&gt;
		if not self.lc:&lt;br /&gt;
			# update status every 10 minutes&lt;br /&gt;
			self.lc = task.LoopingCall(self.updateStatus)&lt;br /&gt;
			self.lc.start(600)&lt;br /&gt;
&lt;br /&gt;
	def dataReceived(self, data):&lt;br /&gt;
		msg=dummy_proto.dummy_message.newFromData(data)&lt;br /&gt;
		if DEBUG: msg.display()&lt;br /&gt;
		try:&lt;br /&gt;
			if type(msg)==dummyproto.dummy_ONOFF_Control_Response:&lt;br /&gt;
				response = self.rpc_server.notify(msg.getKeysStatus(),passphrase)&lt;br /&gt;
		except Exception, err:&lt;br /&gt;
			if DEBUG: print &amp;quot;error: &amp;quot;, err&lt;br /&gt;
			pass # ignore&lt;br /&gt;
&lt;br /&gt;
	def updateStatus(self):&lt;br /&gt;
		msg = dummy_proto.dummy_State_Request()&lt;br /&gt;
		self.transport.write(msg.build_message())&lt;br /&gt;
	&lt;br /&gt;
	def send(self, dummy_data):&lt;br /&gt;
		self.transport.write(dummy_data.build_message())&lt;br /&gt;
&lt;br /&gt;
class dummyClientFactory(ReconnectingClientFactory):&lt;br /&gt;
	def __init__(self, rpc_server):&lt;br /&gt;
		self.rpc_server = rpc_server&lt;br /&gt;
&lt;br /&gt;
	def buildProtocol(self, addr):&lt;br /&gt;
		self.resetDelay()&lt;br /&gt;
		self.protocol = dummyProtocol(self.rpc_server)&lt;br /&gt;
		return self.protocol&lt;br /&gt;
&lt;br /&gt;
	def clientConnectionLost(self, connector, reason):&lt;br /&gt;
		ReconnectingClientFactory.clientConnectionLost(self, connector, reason)&lt;br /&gt;
		connector.connect()&lt;br /&gt;
&lt;br /&gt;
	def clientConnectionFailed(self, connector, reason):&lt;br /&gt;
		if DEBUG: print 'Connection failed. Reason:', reason&lt;br /&gt;
		ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)&lt;br /&gt;
&lt;br /&gt;
	# blocking method ! must be run in a new thread&lt;br /&gt;
	def release_key(self, key_num, timeOur):&lt;br /&gt;
		m = dummy_proto.dummy_ONOFF_Control()&lt;br /&gt;
		m.setON(key_num)&lt;br /&gt;
		self.protocol.send(m)&lt;br /&gt;
		time.sleep(timeOut)&lt;br /&gt;
		m.setOFF(key_num)&lt;br /&gt;
		self.protocol.send(m)&lt;br /&gt;
		return key_num&lt;br /&gt;
&lt;br /&gt;
class WebResource(resource.Resource):&lt;br /&gt;
	def __init__(self, rpc_server, dummy_client_factory):&lt;br /&gt;
		self.rpc_server = rpc_server&lt;br /&gt;
		self.dummy_client_factory = dummy_client_factory&lt;br /&gt;
		resource.Resource.__init__(self)&lt;br /&gt;
		self.keys_webcontrol_state = [0,0,0,0,0,0,0,0,0,0]&lt;br /&gt;
		&lt;br /&gt;
	def getChild(self, name, request):&lt;br /&gt;
		return self&lt;br /&gt;
&lt;br /&gt;
	def render(self, request):&lt;br /&gt;
		reponse = 0 # NOK par defaut&lt;br /&gt;
		key_num = 0&lt;br /&gt;
		try:&lt;br /&gt;
			sessid = request.args.get('sessid', [&amp;quot;&amp;quot;])[0]&lt;br /&gt;
			password = request.args.get('password', [&amp;quot;&amp;quot;])[0]&lt;br /&gt;
			key_num = int(request.args.get('key', [&amp;quot;0&amp;quot;])[0])&lt;br /&gt;
			response = 0&lt;br /&gt;
			if password:&lt;br /&gt;
                                if hashlib.sha224(password).hexdigest() in PASSWORDS:&lt;br /&gt;
                                        timeOut   = KEY_RELEASE_DURATION&lt;br /&gt;
                                        response_XMLRPC = 1&lt;br /&gt;
                        else:&lt;br /&gt;
                                timeOut   = int(request.args.get('timeout', [&amp;quot;0&amp;quot;])[0])&lt;br /&gt;
                                response = self.rpc_server.checkCommand(sessid, key_num)&lt;br /&gt;
		except Exception, err:&lt;br /&gt;
			if DEBUG: print &amp;quot;error: &amp;quot;, err&lt;br /&gt;
			return &amp;quot;NOK:bad request&amp;quot;&lt;br /&gt;
		&lt;br /&gt;
		if response == 1:&lt;br /&gt;
			# Don't try to release a key that is being released&lt;br /&gt;
			if self.keys_webcontrol_state[key_num-1]: return &amp;quot;OK:already released&amp;quot;&lt;br /&gt;
			self.keys_webcontrol_state[key_num-1] = 1&lt;br /&gt;
			d = threads.deferToThread(self.dummy_client_factory.release_key, key_num, timeOut)&lt;br /&gt;
			d.addCallback(self.unset_webcontrol_state)&lt;br /&gt;
			return &amp;quot;OK:releasing key...&amp;quot;&lt;br /&gt;
		else:&lt;br /&gt;
			return &amp;quot;NOK:permission refused&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	def unset_webcontrol_state(self, key_num):&lt;br /&gt;
		self.keys_webcontrol_state[key_num-1] = 0&lt;br /&gt;
&lt;br /&gt;
class OpenKeysService(service.Service):&lt;br /&gt;
	def __init__(self):&lt;br /&gt;
		rpc_server=xmlrpclib.Server(OF_XMLRPC_URL);&lt;br /&gt;
		self.dummy_client_factory = dummyClientFactory(rpc_server)&lt;br /&gt;
		self.web_resource = WebResource(rpc_server, self.dummy_client_factory)&lt;br /&gt;
		&lt;br /&gt;
	def getdummyClientFactory(self):&lt;br /&gt;
		return self.dummy_client_factory&lt;br /&gt;
&lt;br /&gt;
	def getWebResource(self):&lt;br /&gt;
		return self.web_resource&lt;br /&gt;
&lt;br /&gt;
application = service.Application('openkeys')&lt;br /&gt;
f = OpenKeysService()&lt;br /&gt;
serviceCollection = service.IServiceCollection(application)&lt;br /&gt;
internet.TCPClient(KEYS_ADDR, KEYS_PORT, f.getdummyClientFactory()&lt;br /&gt;
				   ).setServiceParent(serviceCollection)&lt;br /&gt;
internet.TCPServer(SERVICE_PORT, server.Site(f.getWebResource())&lt;br /&gt;
				   ).setServiceParent(serviceCollection)&amp;lt;/python&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Maquette de script actionOnDemand.php côté serveur recevant les appels du logiciel de contrôle de l'armoire==&lt;br /&gt;
Ce script nécessite la bibliothèque PEAR [http://pear.php.net/package/XML_RPC2 XML_RPC2].&lt;br /&gt;
&lt;br /&gt;
Pour les tests, il suffit de modifier la valeur de la variable $weDontWant.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;php&amp;gt;&amp;lt;?php&lt;br /&gt;
include 'XML/RPC2/Server.php';&lt;br /&gt;
&lt;br /&gt;
class OpenKeysGateway {&lt;br /&gt;
    /**&lt;br /&gt;
     * Update the status of the keys&lt;br /&gt;
     *&lt;br /&gt;
     * @param array $status Status of keys&lt;br /&gt;
     * @return integer 1 if ok, 0 else&lt;br /&gt;
     */&lt;br /&gt;
    public static function notify($status) {&lt;br /&gt;
        $logmsg = &amp;quot;&amp;quot;;&lt;br /&gt;
        foreach ($status as $key_num_from_zero =&amp;gt; $key_pres) {&lt;br /&gt;
            if (!is_numeric($key_pres) || intval($key_pres)!=$key_pres || $key_pres &amp;lt; 0 || $key_pres &amp;gt; 1) continue;&lt;br /&gt;
            if (!is_numeric($key_num_from_zero) || intval($key_num_from_zero)!=$key_num_from_zero &lt;br /&gt;
                || $key_num_from_zero &amp;lt; 0 || $key_num_from_zero &amp;gt; 9) continue;&lt;br /&gt;
            $logmsg .= &amp;quot;&amp;quot;.($key_num_from_zero+1).&amp;quot;:&amp;quot;.$key_pres.&amp;quot;,&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
        file_put_contents('test.txt', &amp;quot;key notify :&amp;quot;.$logmsg, FILE_APPEND );&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Check if user is able to release the key 'key_num'&lt;br /&gt;
     *&lt;br /&gt;
     * @param string $sessid PHPSESSID of a connected user&lt;br /&gt;
     * @param integer $key_num number of the key to release&lt;br /&gt;
     * @return integer 0:NOK, 1:OK&lt;br /&gt;
     */&lt;br /&gt;
    public static function checkCommand($sessid, $key_num) {&lt;br /&gt;
        /* sanitize input */&lt;br /&gt;
        if (!is_numeric($key_num) || intval($key_num)!=$key_num || $key_num &amp;lt; 1 || $key_num &amp;gt; 10) {&lt;br /&gt;
            return 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $weDontWant = 1;&lt;br /&gt;
&lt;br /&gt;
        if ($weDontWant) {&lt;br /&gt;
            file_put_contents('test.txt', &amp;quot;$key_num has no associated airborne aircraft&amp;quot;, FILE_APPEND );&lt;br /&gt;
            return 0;&lt;br /&gt;
        }&lt;br /&gt;
        else {&lt;br /&gt;
            file_put_contents('test.txt', &amp;quot;granted key: &amp;quot;.$key_num.&amp;quot;:permission granted&amp;quot;, FILE_APPEND );&lt;br /&gt;
            return 1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
$options = array(&lt;br /&gt;
    'autoDocument' =&amp;gt; true,&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
// dirty hack to get things work !&lt;br /&gt;
$GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents('php://input');&lt;br /&gt;
&lt;br /&gt;
$server = XML_RPC2_Server::create('OpenKeysGateway', $options);&lt;br /&gt;
$server-&amp;gt;handleCall();&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&amp;lt;/php&amp;gt;&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Interfa%C3%A7age-OpenFlyers-et-Charterware&amp;diff=12895</id>
		<title>Interfaçage OpenFlyers et Charterware</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Interfa%C3%A7age-OpenFlyers-et-Charterware&amp;diff=12895"/>
		<updated>2024-10-02T17:27:55Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
[[File:Boitier charterware.png]]&lt;br /&gt;
&lt;br /&gt;
L'objet de cette page est de présenter :&lt;br /&gt;
*Le produit Charterware&lt;br /&gt;
*La configuration de l'interfaçage OpenFlyers avec Charterware&lt;br /&gt;
*Son utilisation dans OpenFlyers&lt;br /&gt;
&lt;br /&gt;
[https://www.charterware.de/index-en.html Charterware] est une société allemande qui commercialise un boitier qui s'installe dans un aéronef en le posant sur le tableau de bord et en le reliant par un câble à l'alimentation électrique de l'avion. Ce boitier enregistre les heures blocs :&lt;br /&gt;
*Début du roulage&lt;br /&gt;
*Décollage&lt;br /&gt;
*Atterrissage&lt;br /&gt;
*Fin du roulage&lt;br /&gt;
Ainsi que les facteurs de charges excessifs lors de l'atterrissage.&lt;br /&gt;
&lt;br /&gt;
Le boitier transmet ces informations au serveur Charterware après le bloc arrivé et après que les pilotes aient badgé avec leur carte prévue à cet effet après avoir coupé le contact de l'aéronef. Ensuite, OpenFlyers récupère ces données (voir le chapitre ci-dessous [[#Données-récupérés-via-Charterware|données récupérées via Charterware]]).&lt;br /&gt;
&lt;br /&gt;
Il est également possible de récupérer les traces de vols.&lt;br /&gt;
&lt;br /&gt;
Pour la certification, voir le chapitre [[Technologies-de-géolocalisation-aéronautique#CS-STAN|CS-STAN]]. De plus Charterware dispose également d'un Minor Change Approval pour certains types d'aéronefs.&lt;br /&gt;
&lt;br /&gt;
La tarification Charterware est disponible ici : https://www.charterware.de/price.html .&lt;br /&gt;
&lt;br /&gt;
En 2019, les tarifs donnés par Charterware sont :&lt;br /&gt;
*Boitier + kit d'installation : 900 + 90 = 990 € HT soit 1178,10 € TTC avec 19% de TVA allemande&lt;br /&gt;
*Tag pour permettre à un 1 pilote de badger : 4,90 € HT soit 5,83 € TTC avec 19% de TVA allemande&lt;br /&gt;
*Abonnement pour une structure associative sans les traces de vol : 19 € HT/mois soit 22,80 € TTC/mois avec 20% de TVA française&lt;br /&gt;
*Abonnement pour une structure associative avec les traces de vol : 28 € HT/mois soit 33,60 € TTC/mois avec 20% de TVA française&lt;br /&gt;
*Abonnement pour une structure professionnelle : 49 € HT/mois&lt;br /&gt;
C'est la TVA française qui s'applique sur la location car le service est rendu en France.&lt;br /&gt;
&lt;br /&gt;
Pour l'installation, il faut prévoir environ 300 € HT par aéronef selon l'atelier de maintenance. Le prix sera surement plus cher pour un seul appareil et moins cher pour une flotte importante car l'atelier devra passer du temps à lire le guide d'installation une fois et ensuite il pourra amortir ce temps sur les autres appareils.&lt;br /&gt;
&lt;br /&gt;
Côté OpenFlyers, l’interconnexion avec Charterware est facturé 120 € HT/ressource/an pour les abonnements First-Price et Business. L'interconnexion est incluse dans les abonnements Business+ et Première.&lt;br /&gt;
&lt;br /&gt;
OpenFlyers a sélectionné cette solution car elle est fiable et pérenne dans le temps. Nos concurrents nous ont suivi ;-)&lt;br /&gt;
&lt;br /&gt;
==Chronologie de la mise en place==&lt;br /&gt;
La mise en place de Charterware et la synchronisation avec OpenFlyers suit la chronologie suivante :&lt;br /&gt;
*Achat des boitiers et souscription à l’abonnement de transmission des données chez Charterware.&lt;br /&gt;
*Installation des boitiers par l'atelier de maintenance ou l'atelier radio de la structure&lt;br /&gt;
*Interfaçage par OpenFlyers de la liaison entre la plateforme OpenFlyers et Charterware. Cela nécessite pour OpenFlyers de disposer des informations de connexion et les numéros d'aéronefs communiqués par Charterware.&lt;br /&gt;
Une fois que la configuration est faite par OpenFlyers, il reste à la structure à saisir les numéros de badges des utilisateurs : [[Gestion-des-utilisateurs#Saisir-le-numéro-d'utilisateur-Charterware|Saisir le numéro d'utilisateur Charterware]]&lt;br /&gt;
&lt;br /&gt;
'''Points d'attention''' :&lt;br /&gt;
*L'interfaçage n'est pas mis en place sur les dépôts de test OpenFlyers.&lt;br /&gt;
*Si les aéronefs disposaient de la saisie des compteurs dans OpenFlyers, ces champs deviennent obsolètes et doivent être désactivés.&lt;br /&gt;
&lt;br /&gt;
=Données récupérées via Charterware=&lt;br /&gt;
En récupérant les vols via Charterware les informations suivantes sont récupérées ou calculées.&lt;br /&gt;
*Aéronef utilisé (donnée planecode)&lt;br /&gt;
*Horodatage du début du vol (donnée offblock)&lt;br /&gt;
*Durée du vol (par calcul de la différence entre les données offblock et onblock)&lt;br /&gt;
*Temps en l'air (par calcul de la différence entre les données landing et takeoff)&lt;br /&gt;
*Personnes à bord (données pilot1 et pilot2)&lt;br /&gt;
*Lieu de départ (donnée flightfrom)&lt;br /&gt;
*Lieu d'arrivé (donnée flightto)&lt;br /&gt;
*Nombre d’atterrissage (donnée nooflandings)&lt;br /&gt;
*Rapport d'atterrissage dur&lt;br /&gt;
&lt;br /&gt;
=Paramétrage des arrondis=&lt;br /&gt;
Charterware transmet à OpenFlyers des dates à la seconde. OpenFlyers fonctionne avec des dates à la minute. Il est donc nécessaire de définir des formules d'arrondis dans le [[Configuration#Gestion-de-Charterware|paramétrage de Charterware]] de la plateforme.&lt;br /&gt;
&lt;br /&gt;
Les variables suivantes sont utilisables dans les formules :&lt;br /&gt;
*CHARTERWARE_ONBLOCK_DATE : Datetime de départ bloc&lt;br /&gt;
*CHARTERWARE_TAKEOFF_DATE : Datetime de décollage &lt;br /&gt;
*CHARTERWARE_LANDING_DATE : Datetime d’atterrissage&lt;br /&gt;
*CHARTERWARE_OFFBLOCK_DATE : Datetime de bloc arrivée&lt;br /&gt;
Ces variables sont directement transmises par Charterware.&lt;br /&gt;
&lt;br /&gt;
Les fonctions suivantes peuvent être utilisées dans les formules :&lt;br /&gt;
*[[Formules-de-calcul#formatDate('patron',-'date')|formatDate]] : Permet de formater une date&lt;br /&gt;
*[[Formules-de-calcul#roundCeil(X,Y)|roundCeil]] : Arrondi à la minute supérieure la date transmise en paramètre&lt;br /&gt;
*[[Formules-de-calcul#roundFloor(X,Y)|roundFloor]] : Arrondi à la minute inférieure la date transmise en paramètre&lt;br /&gt;
*[[Formules-de-calcul#strtotime(string)|strtotime]] : Transforme une date en timestamp&lt;br /&gt;
=Procédure=&lt;br /&gt;
==Interfacer OpenFlyers avec Charterware==&lt;br /&gt;
&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Structure &amp;gt; Paramétrage &amp;gt; Activités'''&lt;br /&gt;
**Activer l'interrupteur '''Charterware''' situé dans la 4ème colonne&lt;br /&gt;
**Renseigner les champs suivants :&lt;br /&gt;
*** '''Nom de la plateforme dans Charterware''': Saisir le nom de votre plateforme Charterware.&lt;br /&gt;
*** '''Formule date de début du vol Charterware''': Entrer la formule pour calculer la date de début du vol.&lt;br /&gt;
*** '''Formule durée du vol Charterware''': Entrer la formule pour calculer la durée du vol.&lt;br /&gt;
*** '''Formule temps en l'air Charterware''': Entrer la formule pour calculer le temps en l'air.&lt;br /&gt;
*** '''Règle d'arrondi horaire Charterware''': Sélectionner la règle d'arrondi horaire (par exemple, Arrondi au plus proche).&lt;br /&gt;
*** '''Type d'activité par défaut avec zéro ou un pilote dans Charterware''': Choisir le type d'activité par défaut pour un pilote unique ou aucun pilote.&lt;br /&gt;
*** '''Type d'activité par défaut avec deux pilotes dans Charterware''': Choisir le type d'activité par défaut pour deux pilotes.&lt;br /&gt;
*** '''E-mail''': Entrer l'adresse e-mail associée à votre compte Charterware.&lt;br /&gt;
*** '''Mot de passe''': Entrer le mot de passe associé à votre compte Charterware.&lt;br /&gt;
**Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
*[[Gestion-des-ressources#Saisir-le-numéro-de-ressource-pour-l'API-de-geolocalisation|Configurer le numéro de l'API de géolocalisation pour les ressources]].&lt;br /&gt;
&lt;br /&gt;
=Récupération des vols Charterware=&lt;br /&gt;
Chaque minute le robot OpenFlyers interroge le serveur Charterware pour savoir si de nouveaux vols ont été enregistrés par Charterware. Si c'est le cas, alors il sont sauvegardés dans OpenFlyers et supprimés des vols en attente de récupération côté Charterware.&lt;br /&gt;
&lt;br /&gt;
Charterware utilise un système d'identifiant pour retrouver les pilotes et les aéronefs il est donc nécessaire de créer les champs métiers nécessaires et de les renseigner dans l'interface d'OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
*Si l'identifiant d'un utilisateur Charterware ne peut être retrouvé dans OpenFlyers alors le robot se comporte comme si les pilotes n'avaient pas été transmis par Charterware. &lt;br /&gt;
*Si l'identifiant d'un aéronef Charterware ne peut être retrouvé dans OpenFlyers alors le robot n'enregistrera pas le vol.&lt;br /&gt;
&lt;br /&gt;
Afin de retrouver un maximum d'informations le robot tente de retrouver une réservation avec la même ressource correspondant au vol communiqué par charterware :&lt;br /&gt;
*Il cherche s'il existe une réservation dont les horaires comprennent l'heure médiane du vol charterware. Si c'est le cas, il se base sur les informations de cette réservation.&lt;br /&gt;
*S'il n'y a aucune réservation, il cherche une réservation avec la même ressource dont les horaires sont compris entre le début et la fin du vol remonté par Charterware.&lt;br /&gt;
**S'il y a plusieurs réservations, alors il n'en prend aucune.&lt;br /&gt;
**S'il y a une seule réservation :&lt;br /&gt;
***Si Charterware a transmis les identifiants pilotes alors le robot vérifie si ceux-ci correspondent à ceux de la réservation. Si c'est le cas il prend en compte les informations de la réservation.&lt;br /&gt;
***Si Charterware n'a pas transmis les identifiants pilotes, les informations de la réservation sont prises en compte.&lt;br /&gt;
&lt;br /&gt;
Une fois qu'une réservation est identifiée comme correspondre au vol remonté par Charterware, les informations de la réservation sont prises en compte par le robot.&lt;br /&gt;
&lt;br /&gt;
;Exemple :&lt;br /&gt;
Pour un vol exemple qui commence à 16h05 et se termine à 17h00, l'heure médiane serait 16h32 et 30 secondes. La réservation correspondante pour ce vol serait celle qui inclut cette heure médiane.&lt;br /&gt;
&lt;br /&gt;
Les données suivantes sont alors récupérées :&lt;br /&gt;
==Statut des pilotes==&lt;br /&gt;
Pour chaque pilote :&lt;br /&gt;
*Si un vol récupéré dans Charterware peut être associé à une réservation =&amp;gt; Les statuts des pilotes sont celles définies dans la réservation.&lt;br /&gt;
*Si le vol ne peut être associé : &lt;br /&gt;
**S'il n'y a qu'un statut autorisé pour la place du pilote et pour l'avion =&amp;gt; Le statut du pilote est ce statut.&lt;br /&gt;
**Si le pilote est sur la première place =&amp;gt; Le statut du pilote est le statut &amp;quot;pilote&amp;quot; si il n'existe pas le premier statut.&lt;br /&gt;
**Si le pilote est sur la seconde place =&amp;gt; Le statut du pilote est le statut &amp;quot;Instructeur&amp;quot; si il n'existe pas le second statut.&lt;br /&gt;
&lt;br /&gt;
==Place des pilotes==&lt;br /&gt;
*Si un vol récupéré dans Charterware peut être associé à une réservation =&amp;gt; Les places des pilotes sont celles définies dans la réservation.&lt;br /&gt;
*Si le vol ne peut être associé : &lt;br /&gt;
**S'il y a un seul pilote =&amp;gt; Sa place est celle par défaut (0, Gauche).&lt;br /&gt;
**S'il y a deux pilotes et que un seul à l'autorisation pour être sur la place de droite =&amp;gt; Le pilote ayant l'autorisation est à la place de droite et l'autre à la place de gauche.&lt;br /&gt;
**Si les deux pilotes ont les autorisations pour être sur la place de droite =&amp;gt; Le pilote 1 est sur la place de gauche le pilote 2 est sur la place de droite.&lt;br /&gt;
&lt;br /&gt;
==Type d'activité==&lt;br /&gt;
*Si un vol récupéré dans Charterware peut être associé à une réservation =&amp;gt; Les types d'activités sont celles définies dans la réservation.&lt;br /&gt;
*Si le vol ne peut être associé : &lt;br /&gt;
**S'il y a deux pilotes et que le type d'activité par défaut pour deux pilotes est défini =&amp;gt; Le type d'activité est celle définie par défaut.&lt;br /&gt;
**S'il y a zero ou un pilote et que le type d'activité par défaut pour zero ou un pilote est défini =&amp;gt; Le type d'activité est celle définie par défaut.&lt;br /&gt;
**Si les types d'activité par défaut ne sont pas définies =&amp;gt; Le type d'activité est le premier type d'activité trouvé.&lt;br /&gt;
&lt;br /&gt;
=Récupération des traces de vols=&lt;br /&gt;
Charterware propose en option à son abonnement d'enregistrer les traces de vols. Cf. la [[#Présentation|présentation]].&lt;br /&gt;
&lt;br /&gt;
Les traces de vols sont constituées de points enregistrés à une fréquence variable qui dépend de la trajectoire ou de la vitesse de l'aéronef :&lt;br /&gt;
*1 point tous les 3 secondes pour le roulage&lt;br /&gt;
*1 point toutes les 25 secondes en vol en ligne droite&lt;br /&gt;
*1 point toutes les secondes en montée et en descente&lt;br /&gt;
*1 point tous les 10 degrés d'angle en virage&lt;br /&gt;
&lt;br /&gt;
Les traces de vols sont téléchargeables depuis les interfaces [[Carnet-de-route#Traces-de-vols|Activités &amp;gt; Carnet de route]] et '''Activités &amp;gt; Carnet de vol'''. Pour visualiser les traces de vol il faut soit être sur le vol en tant que pilote ou instructeur ou bien avoir le droit [[Gestion-des-profils#Visualiser-les-traces-de-vol|Visualiser les traces de vol]].&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
==Activité vol non créée automatiquement dans OpenFlyers==&lt;br /&gt;
Procédure à suivre dans le cas où un vol a été effectué sur un appareil équipé d'un boitier Charterware et que l'activité vol correspondante n'apparait pas dans OpenFlyers.&lt;br /&gt;
*Allumer le boitier Charterware de l'aéronef concerné pour lancer une nouvelle tentative de transmission des données. Contrôler l'affichage du boitier pour voir s'il s'éteint de lui-même au bout de 2 minutes. Ce n'est que lorsqu'il s'éteint avec aucun texte d'affiché que la transmission s'est effectuée. Dans le cas contraire, cela veut dire qu'il y a un problème de transmission entre le boitier et le serveur Charterware. Il est probable que ce problème de transmission soit un problème de réseau. Dans ce cas là, il faut retenter le processus lorsque la transmission réseau est meilleure.&lt;br /&gt;
Une fois que le boitier s'est éteint de lui-même, dans les 10 minutes qui suivent, la synchronisation entre le serveur Charterware et celui d'OpenFlyers se fait.&lt;br /&gt;
*Vérifier à nouveau si le vol apparait dans OpenFlyers &lt;br /&gt;
**Si le vol est présent, la procédure est terminée&lt;br /&gt;
**Si le vol est toujours manquant effectuer les actions suivantes&lt;br /&gt;
*Se connecter à l'interface Charterware et voir si le vol apparait&lt;br /&gt;
**Si le vol apparait, faire une copie d'écran de l'interface et la transmettre à OpenFlyers pour qu'il puisse investiguer sur la non création automatique de l'activité vol dans la plateforme OpenFlyers&lt;br /&gt;
**Si le vol n'apparait pas, contacter Charterware pour investigation&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Interfa%C3%A7age-A%C3%A9rogligli&amp;diff=12894</id>
		<title>Interfaçage Aérogligli</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Interfa%C3%A7age-A%C3%A9rogligli&amp;diff=12894"/>
		<updated>2024-10-02T17:27:55Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter les fonctionnalités proposées par [https://openflyers.com/fr/actualites/aerogligli-arrive-sur-openflyers l'interfaçage] avec [https://www.aerogligli.fr/ Aerogligli].&lt;br /&gt;
&lt;br /&gt;
=Questionnaire=&lt;br /&gt;
[[File:Aérogligli_qcm.png]][[File:Aérogligli_qcm_correction.png]]&lt;br /&gt;
&lt;br /&gt;
Dans le tableau de bord de la plateforme, le questionnaire du jour d'Aérogligli apparaît.&lt;br /&gt;
&lt;br /&gt;
Après avoir choisi une réponse et avoir cliqué sur le bouton '''Correction''', un pictogramme indiquant une réussite ou une erreur apparaîtra.&lt;br /&gt;
&lt;br /&gt;
Un nouveau bouton '''En savoir plus''' apparaît. Un clic dessus redirige vers une page d'explications d'Aérogligli.&lt;br /&gt;
&lt;br /&gt;
=Statistiques de l'élève=&lt;br /&gt;
[[File:Aérogligli_résultats.png]]&lt;br /&gt;
&lt;br /&gt;
Un composant statistiques est aussi disponible dans le tableau de bord.&lt;br /&gt;
&lt;br /&gt;
Ce composant ne fonctionne que si le champ '''Numéro d'utilisateur Aérogligli''' de la fiche personnelle de l'utilisateur est rempli. Si ce n'est pas le cas, le composant affichera un message invitant à renseigner ce numéro.&lt;br /&gt;
&lt;br /&gt;
Une fois le champ renseigné, le bloc statistiques affiche deux éléments selon le profil Aérogligli ''PPL(A) ou BIA'':&lt;br /&gt;
*le pourcentage de réussite des QCM&lt;br /&gt;
*le pourcentage de cours lus de l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Il est possible de changer de profil Aérogligli en cliquant sur le crayon d'édition à côté de son intitulé. Le changer actualisera les statistiques pour afficher celles correspondantes au profil sélectionné.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Installation-armoire-%C3%A0-cl%C3%A9s&amp;diff=12893</id>
		<title>Installation armoire à clés</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Installation-armoire-%C3%A0-cl%C3%A9s&amp;diff=12893"/>
		<updated>2024-10-02T17:27:54Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de décrire la procédure d'installation d'une [[Contrôle des accès#Armoires_à_clés_Deister_commercialiées_par_OpenFlyers|armoire à clés Deister ProxSafe Smart vendue par OpenFlyers]] et équipée du mini-serveur OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
=Préparation du réseau avant réception de l'armoire=&lt;br /&gt;
''La procédure décrite dans ce paragraphe peut être effectuée avant la réception de l'armoire. A défaut, de préparation anticipée, elle doit être effectuée '''avant''' tout branchement de l'armoire à clés sauf dans le cas d'une Livebox d'orange où il est nécessaire d'effectuer d'abord le branchement du matériel pour pouvoir ensuite effectuer la configuration du routeur. Dans ce cas, il faut d'abord suivre la procédure [[#Connexion_de_l'armoire|connexion de l'armoire et ensuite revenir sur ce paragraphe]]''&lt;br /&gt;
&lt;br /&gt;
L'utilisation de l'armoire à clés Deister, nécessite 1 raccordement électrique 220v avec les 3 câbles (phase, neutre et terre) ainsi que 2 connexions RJ45 au réseau local via un routeur, en général une &amp;quot;box&amp;quot; :&lt;br /&gt;
*une pour le mini-serveur OpenFlyers&lt;br /&gt;
*une pour l'armoire à clés.&lt;br /&gt;
&lt;br /&gt;
Le réseau doit être configuré en DHCP ce qui signifie que toute connexion au réseau est automatiquement reconnue et qu'une adresse IP est automatiquement affectée à cette connexion. Par défaut, les &amp;quot;box&amp;quot; des fournisseurs d'accès sont configurées selon ce mode là.&lt;br /&gt;
&lt;br /&gt;
Cependant pour que le serveur OpenKey et l'armoire à clé puissent communiquer entre-eux et avec le logiciel OpenFlyers, les adresses IP attribuées par le routeur doivent être fixes. Pour forcer le routeur à attribuer toujours la même adresse IP à un équipement il faut le configurer en créant l'association d'une [[Wikipedia-fr:Adresse_IP|adresse IP]] à l'[[Wikipedia-fr:Adresse_MAC|adresse MAC]] du matériel.&lt;br /&gt;
&lt;br /&gt;
Les adresses IP et MAC à configurer vous sont communiquées dans un e-mail qu'OpenFlyers envoie après la commande de l'armoire à clés et qui sont également indiquées le bordereau de livraison.&lt;br /&gt;
&lt;br /&gt;
Ce paramétrage se fait soit directement dans l'interface de gestion du routeur ou par l'intermédiaire de l'interface de gestion de la &amp;quot;box&amp;quot; de votre fournisseur d'accès et dépend du matériel que vous disposez.&lt;br /&gt;
==Configuration du routeur==&lt;br /&gt;
Le routeur d'un fournisseur d'accès internet correspond à la &amp;quot;box&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Configuration d'un Routeur NETGEAR Numericable===&lt;br /&gt;
''Cette documentation a été rédigée à partir d'un routeur NETGEAR CBVG834G''&lt;br /&gt;
*Aller sur la page d'administration du routeur. Elle est par défaut sous la forme http://192.168.0.1&lt;br /&gt;
*Saisir l'identifiant et le mot de passe&lt;br /&gt;
''Rédiger la redirection des ports''&lt;br /&gt;
*Aller '''Paramètres avancés &amp;gt; IP LAN'''&lt;br /&gt;
*Dans le 2ème formulaire, saisir dans les lignes '''Adresse MAC''' et '''Adresse IP''' les couples (adresse IP, adresse MAC) communiqués dans le bordereau de livraison et cliquer à après la saisie de chaque couple sur le bouton '''Ajouter''' de sorte à obtenir le tableau suivant :&lt;br /&gt;
''Copie d'écran à insérer''&lt;br /&gt;
*Débrancher 5 secondes le routeur puis le rebrancher.&lt;br /&gt;
&lt;br /&gt;
===Configuration d'une Box BBox===&lt;br /&gt;
Il faut au préalable connecter l'armoire afin que la BBox lui affecte par défaut une adresse IP.&lt;br /&gt;
*Connecter vous sur votre BBox en tapant son IP 192.168.1.254 et mettre le mot de passe &lt;br /&gt;
* Déployer le menu '''Service de la box''' et sélectionner DHCP&lt;br /&gt;
&lt;br /&gt;
[[File:BBox_acces_DHCP.jpg]]&lt;br /&gt;
* Allez dans la rubrique '''Attribution adresse IP Statique'''&lt;br /&gt;
* Cliquer sur ajouter un équipement&lt;br /&gt;
Sélectionner l'adresse MAC de l'équipement et le nommer pour plus de clarté&lt;br /&gt;
&lt;br /&gt;
[[File:BBox_config_adresse_IP_fixe.jpg]]&lt;br /&gt;
* Refaire l'opération pour le Raspberry Pi&lt;br /&gt;
&lt;br /&gt;
[[File:BBox_adresse_IP_fixe.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Configuration d'une Box SFR===&lt;br /&gt;
Il faut au préalable connecter l'armoire et le module Raspberry Pi par câbles RJ45 et l'alimenter afin que la Box SFR lui affecte par défaut une adresse IP.&lt;br /&gt;
*Connecter vous sur votre Box SFR en tapant son IP 192.168.1.1 &lt;br /&gt;
*Cliquer sur Réseau V4/Général&lt;br /&gt;
*Mettre l'identifiant et mot de passe &lt;br /&gt;
*Vous visualiser les Postes connectés, il doit y en avoir deux supplémentaires à votre configuration habituelle&lt;br /&gt;
*Notez les adresses MAC des deux équipements (celles ci vous ont été communiquées dans le bon de livraison)&lt;br /&gt;
*Aller dans Réseau V4/DHCP&lt;br /&gt;
*Dans la section Adresses statiques &lt;br /&gt;
**Associez l'adresse 192.168.1.200 à l'adresse MAC du Raspberry Pi et cliquez sur le bouton + à droite&lt;br /&gt;
**Associez l'adresse 192.168.1.201 à l'adresse MAC de l'armoire Deister et cliquez sur le bouton + à droite&lt;br /&gt;
&lt;br /&gt;
[[File:Keypanel2012-redirection-de-ports-SFR.PNG|center]]&lt;br /&gt;
&lt;br /&gt;
*Déconnecter l'alimentation de l'armoire et la réalimenter après 10 secondes d'attente pour visualiser les nouvelles affectations d'IP statiques&lt;br /&gt;
&lt;br /&gt;
===Configuration d'une Freebox v4===&lt;br /&gt;
*Aller sur [https://subscribe.free.fr/login/ l'espace client]&lt;br /&gt;
*Saisir l'identifiant et le mot de passe&lt;br /&gt;
*Aller '''Ma Freebox &amp;gt; Configurer mon routeur Freebox'''&lt;br /&gt;
*Dans '''Configuration &amp;gt; Configuration du routeur''', vérifier que l''''Adresse IP Freebox''' est 192.168.0.254&lt;br /&gt;
*Cliquer sur '''Redirections / Baux DHCP''' pour faire dérouler le contenu&lt;br /&gt;
*Dans le paragraphe '''Redirections de ports''', à côté de l’icône symbolisant un &amp;quot;plus&amp;quot; :&lt;br /&gt;
**Dans le champ de la colonne '''PORT EXTERNE''' saisir ''8000''&lt;br /&gt;
**Dans les champs de la colonne '''IP DE DESTINATION''' saisir ''192.168.0.200''&lt;br /&gt;
**Dans le champ de la colonne '''PORT INTERNE''' saisir ''8000''&lt;br /&gt;
**Cliquer sur l'icône symbolisant un &amp;quot;plus&amp;quot; de sorte à ce que la ligne vienne s'ajouter en-dessous&lt;br /&gt;
*Répéter cette opération de sorte à obtenir le tableau suivant :&lt;br /&gt;
&lt;br /&gt;
[[File:Keypanel2012-redirection-de-ports-freebox.png|center]]&lt;br /&gt;
&lt;br /&gt;
*Dans le paragraphe '''Baux DHCP permanents''', saisir sur la ligne avec l'icône symbolisant un &amp;quot;plus&amp;quot; les couples (adresse IP, adresse MAC) communiqués dans le bordereau de livraison de sorte à obtenir le tableau suivant :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Keypanel2012-Baux-DHCP-permanents-freebox.png|center]]&lt;br /&gt;
&lt;br /&gt;
*En bas du formulaire, cliquer sur le bouton '''Sauvegarder les paramètres'''&lt;br /&gt;
*Débrancher 5 secondes la freebox puis la rebrancher.&lt;br /&gt;
*Une fois l'armoire à clés livrée, passer à l'étape de [[Installation armoire à clés#Connexion_de_l'armoire|connexion de l'armoire]].&lt;br /&gt;
&lt;br /&gt;
===Configuration d'une Freebox v6===&lt;br /&gt;
A effectuer avec l'armoire connectée au réseau local de la Freebox&lt;br /&gt;
*Dans un navigateur d'un appareil connecté au réseau local de la Freebox concernée : http://mafreebox.freebox.fr&lt;br /&gt;
*Saisir le mot de passe de connexion à la Freebox&lt;br /&gt;
*Double-cliquer sur le bouton '''Paramètres de la Freebox'''&lt;br /&gt;
*Cliquer sur l'onglet en haut '''Mode avancé'''&lt;br /&gt;
*Double-cliquer le bouton '''DHCP'''&lt;br /&gt;
*Cliquer sur l'onglet '''Baux actifs'''&lt;br /&gt;
*Identifier dans la liste l'armoire à clés&lt;br /&gt;
*Faire un clic droit et cliquer sur le bouton contextuel '''Ajouter un bail statique'''&lt;br /&gt;
*Compléter l'adresse IP statique avec l'adresse IP communiqué dans le bordereau de livraison&lt;br /&gt;
*Indiquer éventuellement un commentaire pour permettre de repérer plus facilement l'élément dans la liste&lt;br /&gt;
*Cliquer le bouton '''Valider'''&lt;br /&gt;
*Vérifier dans '''Baux statiques''' qu'apparait bien le nouvel élément&lt;br /&gt;
&lt;br /&gt;
===Configuration d'une Livebox Orange===&lt;br /&gt;
Pour se connecter à l'interface d'une Livebox Orange, il faut :&lt;br /&gt;
*[[Trucs-et-astuces#Trouver-l'adresse-IP-du-routeur|Trouver l'adresse IP du routeur]].&lt;br /&gt;
*Taper cette adresse dans la barre d'adresse du navigateur.&lt;br /&gt;
*Saisir le couple identifiant mot de passe du routeur. C'est par défaut (admin, admin). ''Il est recommandé de modifier ce mot passe.''&lt;br /&gt;
Ensuite, la procédure dépend du [http://assistance.orange.fr/livebox-tous-les-modeles-524.php modèle de Livebox]. Nous mettons ci-dessous les procédures en fonction des demandes et des difficultés rencontrées par les administrateurs.&lt;br /&gt;
&lt;br /&gt;
''Attention, pour configurer correctement le routeur, il faut mettre les couples (adresses IP, adresses MAC) au niveau de la configuration des adresses IP statiques et non pas au niveau du filtrage du réseau Wifi (WAN).''&lt;br /&gt;
&lt;br /&gt;
====Livebox 2 de Sagem====&lt;br /&gt;
La procédure ci-dessous permet d'associer les couples (adresse IP, adresse MAC) uniquement lorsque l'armoire à clé est connectée.&lt;br /&gt;
* '''Configuration'''&lt;br /&gt;
* Menu de gauche '''Réseaux &amp;amp; Services &amp;gt; Équipements &amp;gt; Visualiser'''&lt;br /&gt;
* Deux nouvelles icônes doivent apparaitre&lt;br /&gt;
* Cliquer dessus chaque icône, vérifier à quel matériel l'adresse MAC correspond (inscrit sur le bordereau de livraison de l'armoire à clés) et renommer chaque icône en &amp;quot;Armoire à clés&amp;quot; et &amp;quot;Daemon RPi&amp;quot; pour une identification plus aisée.&lt;br /&gt;
Attention : orange rajoute ses propres noms qui ne simplifient pas la reconnaissance du matériel.&lt;br /&gt;
*Retourner dans l'onglet '''Configuration'''&lt;br /&gt;
*Menu de gauche '''Réseaux &amp;amp; Services &amp;gt; Livebox &amp;gt; Paramètres avancés'''&lt;br /&gt;
*Onglet '''DHCP'''&lt;br /&gt;
*Section '''Adresse IP statique'''&lt;br /&gt;
*Cliquer sur '''Ajouter'''&lt;br /&gt;
[[File:LiveBox.JPG]]&lt;br /&gt;
*Sélectionner dans le menu déroulant '''Armoire à clés'''&lt;br /&gt;
*Saisir l'adresse &amp;quot;192.168.1.201&amp;quot;&lt;br /&gt;
*Cliquer sur '''Ajouter'''&lt;br /&gt;
*Sélectionner dans le menu déroulant '''Daemon RPi'''&lt;br /&gt;
*Saisir l'adresse &amp;quot;192.168.1.200&amp;quot;&lt;br /&gt;
*Cliquer sur le bouton '''Sauver'''&lt;br /&gt;
*Réinitialiser la Livebox&lt;br /&gt;
Il ne faut pas se fier à l'interface livebox pour la reconnaissance de l'armoire à clés car il semblerait qu'il existe un défaut d'affichage de l'état de connexion de l'armoire à clés dans cette interface. A la place il faut [[Gestion armoire à clés#Vérifier_les_connexions_réseaux_de_l'armoire_et_du_mini-serveur|vérifier la bonne attribution des couples (adresse IP, adresse MAC) en ligne de commande]].&lt;br /&gt;
&lt;br /&gt;
=Fixation de l'armoire DEISTER ProxSafe Smart II=&lt;br /&gt;
L'armoire a un encombrement murale de 630 mm x 300 mm et une profondeur de 200 mm&lt;br /&gt;
&lt;br /&gt;
L'arrière du coffret comporte un capteur de détection d'arrachement, veillez à ce que la zone d'appui soit affleurante aux fixations du coffret&lt;br /&gt;
&lt;br /&gt;
La face arrière du coffret est espacé de 20 mm des fixations murales. Ceci permet le cheminement des câbles (alimentation + 2 Ethernet)&lt;br /&gt;
&lt;br /&gt;
Pour accéder aux fixations de l'armoire il faut ouvrir la porte de service. Prendre la clé dans la pochette rouge fournie avec l'armoire, ouvrir la porte de façade en tournant la clé dans le sens horaire. Ouvrir la porte de service en tournant la clé dans le sens anti-horaire&lt;br /&gt;
&lt;br /&gt;
Sa fixation murale dépend du type de mur sur lequel vous l'installez&lt;br /&gt;
&lt;br /&gt;
==Fixation de l'armoire sur un mur robuste==&lt;br /&gt;
Elle peut dans ce cas être fixée que par les 2 orifices traversants avec 2 vis&lt;br /&gt;
&lt;br /&gt;
[[File:DEISTER_ _Support_fixation_ _dos_armoire.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[Media:DEISTER_fixation_SMART U II.pdf]]&lt;br /&gt;
&lt;br /&gt;
*Entraxe 406 mm, &lt;br /&gt;
*Diamètre 10 mm, &lt;br /&gt;
*Profondeur 20 mm&lt;br /&gt;
Les fixations dépendent de la nature du support, nous conseillons :&lt;br /&gt;
* Dans du bois : 2 tire-fonds de 8 x 70&lt;br /&gt;
* Dans du béton : 2 chevilles à expansion M8 x 55 + 2 vis M8 x 60&lt;br /&gt;
* Dans de la brique alvéolaire : 2 chevilles à scellement chimique M8 + rondelles et écrous (ou bien voir ci dessous)&lt;br /&gt;
&lt;br /&gt;
Ces fixations sont aussi suffisantes si l'armoire est supportée sur un meuble ou une étagère&lt;br /&gt;
&lt;br /&gt;
==Fixation de l'armoire sur un mur de résistance modérée==&lt;br /&gt;
Le support de fixation fournit permet de répartir les efforts. Il est vivement recommandé pour une pose similaire à celle d'une fixation d'une télévision à écran plat murale&lt;br /&gt;
&lt;br /&gt;
[[File:DEISTER_ _Support_fixation.jpg]]&lt;br /&gt;
&lt;br /&gt;
Il présente les avantages suivants :&lt;br /&gt;
*Il permet de faire l'installation seul (pas besoin d'être à deux)&lt;br /&gt;
*Il permet un réglage de horizontalité pour une mise niveaux plus aisée &lt;br /&gt;
*Il réduit le risque de chute (l'armoire pèse 20kg) et de l'endommager en la faisant tomber lors de son installation.&lt;br /&gt;
Ce support ne reprend que les efforts verticaux, il ne dispense pas des 2 fixations centrales qui pourront alors être de résistance moindre. Le support comporte 8 orifices de fixations de diamètre 8 mm, le nombre de fixations sera adaptée au type de support&lt;br /&gt;
*Placo, chevilles à grande expansion (type &amp;quot;Molly&amp;quot;) M6 x 65 ou DuoPower de Fisher + vis 7 x 60&lt;br /&gt;
*Brique plâtrière, carreau de plâtre, parpaing, béton cellulaire : cheville plastique de 10 x 50 + vis 6 ou 8 de longueur 60 mm&lt;br /&gt;
&lt;br /&gt;
Ne pas négliger les fixations, les sollicitations dans un club peuvent être sévères&lt;br /&gt;
&lt;br /&gt;
=Connexions de l'armoire DEISTER ProxSafe Smart II=&lt;br /&gt;
&lt;br /&gt;
Ne brancher la batterie qu'au moment de la [[#Finalisation|finalisation]], c'est à dire une fois que l'armoire est correctement installée et configurée à la plateforme OpenFlyers. En effet, il peut être nécessaire de faire plusieurs reboots de l'armoire en débranchant/rebranchant l'armoire du secteur. De ce fait, si la batterie est branchée, le reboot ne pourrait se faire  en débranchant l'alimentation.&lt;br /&gt;
&lt;br /&gt;
Les câbles suivants doivent être passés avant la fixation définitive au mur :&lt;br /&gt;
*Câble d'alimentation 220v&lt;br /&gt;
*Câble Ethernet entre le routeur et l'armoire&lt;br /&gt;
*Câble Ethernet entre le routeur et le mini-serveur OpenFlyers&lt;br /&gt;
Fixer l'armoire au mur par 4 chevilles et vis en ayant au préalable retiré l’adhésif de maintien de l’interrupteur qui sert à détecter une tentative de vandalisme&lt;br /&gt;
*Identifier le serveur OpenKey situé derrière le verrou de porte &lt;br /&gt;
*Vérifier que la carte microSDHC est correctement enfichée dans le logement du serveur OpenKey situé derrière la carte électronique.&lt;br /&gt;
*Brancher un câble Ethernet sur le serveur OpenKey&lt;br /&gt;
*Identifier la prise RJ45 de l'armoire et y brancher un câble Ethernet :&lt;br /&gt;
*Brancher le câble d'alimentation 220V en y joignant le câble de l'armoire correspondant à la &amp;quot;terre&amp;quot; (câble jaune et vert) :&lt;br /&gt;
*Bien vérifier que la terre soit raccorder sur le connecteur et que votre installation dispose d'un disjoncteur différentielle approprié&lt;br /&gt;
[[File:Connexion_Alim_SmartII.jpg]]&lt;br /&gt;
*Brancher l'alimentation sur le secteur.&lt;br /&gt;
**1 voyant vert, sur l'alimentation signal que l'alimentation est correctement connectée&lt;br /&gt;
**1 voyant rouge, sur le module serveur Openkey signal que la carte est fonctionnelle, un voyant vert cligne lorsque des signaux sont échangé sur le réseaux&lt;br /&gt;
**5 voyants leds, situés sur la carte mère de l'armoire doivent s'éclairer&lt;br /&gt;
**2 leds sur chaque connecteur RJ45, indique que la connexion au réseau est fonctionnelle : orange fixe et clignement vert&lt;br /&gt;
*Refermer la porte de service puis la porte de façade&lt;br /&gt;
*A l'initialisation de l'armoire les voyants en haut de la face  avant signale les phases de démarrage&lt;br /&gt;
** Jaune clignotant durant l'initialisation de la carte mère de l'armoire&lt;br /&gt;
** Jaune fixe en fin d'initialisation&lt;br /&gt;
** Si la configuration du programme est faite le voyant Jaune s'eteint, le voyant rouge s'allumera pour test puis le voyant vert fixe signale la fin de l'initialisation du serveur OpenKey&lt;br /&gt;
&lt;br /&gt;
=Configuration OpenFlyers=&lt;br /&gt;
&lt;br /&gt;
==Navigateur==&lt;br /&gt;
&lt;br /&gt;
*Dialogue avec l'armoire en HTTPS : seul le navigateur Chrome de Google permet la connexion avec l'armoire à clés. Ce navigateur est compatible avec le certificat de sécurité autosigné installé sur le(s) PC permettant l'accès à l'armoire.&lt;br /&gt;
*Le ou les PC de la structure doivent être paramétrés pour que ce soit ce navigateur qui soit utilisé.&lt;br /&gt;
&lt;br /&gt;
=== Installation du certificat de sécurité sur PC Windows ===&lt;br /&gt;
En cas de changement de PC le certificat de sécurité doit être installé&lt;br /&gt;
&lt;br /&gt;
Avant le changement du PC récupérer la clé public sur une clé USB. Par défaut elle est situé dans le répertoire :&lt;br /&gt;
'''C:\Users\OpenFlyers\PyOpenKey\SSL\opkServer.crt'''&lt;br /&gt;
&lt;br /&gt;
Ce certificat est au format texte codé en base 64&lt;br /&gt;
&lt;br /&gt;
En tant qu'administrateur créer les répertoires devant recevoir le certificat&lt;br /&gt;
*Ouvrir l'explorateur et le répertoire Utilisateur&lt;br /&gt;
*Clic droit puis dans le menu popup sélectionné '''Nouveau &amp;gt; Dossier'''&lt;br /&gt;
*Nommer le '''OpenFlyers'''&lt;br /&gt;
*Ce déplacer dans ce nouveau répertoire&lt;br /&gt;
*Clic droit puis dans le menu popup sélectionné '''Nouveau &amp;gt; Dossier'''&lt;br /&gt;
*Nommer le '''PyOpenKey'''&lt;br /&gt;
*Ce déplacer dans ce nouveau répertoire&lt;br /&gt;
*Clic droit puis dans le menu popup sélectionné '''Nouveau &amp;gt; Dossier'''&lt;br /&gt;
*Nommer le '''SSL'''&lt;br /&gt;
*Copier le certificat '''opkServer.crt''' situé sur votre clé USB dans ce répertoire&lt;br /&gt;
&lt;br /&gt;
L'activation du certificat doit être faite dans chaque environnement utilisant OpenFlyers &lt;br /&gt;
&lt;br /&gt;
L'installation sur le nouveau PC s'effectue en ligne de commande&lt;br /&gt;
&lt;br /&gt;
Ouvrir l'interface de ligne de commande de Windows &lt;br /&gt;
* Exécuté la commande '''cmd''' dans la zone de recherche de la barre de tache de Windows&lt;br /&gt;
* Cliquer sur '''Invite de commande''', ceci affiche la fenêtre noir Windows de ligne de commande&lt;br /&gt;
* Exécuter la commande '''certutil -addstore -f -user root &amp;quot;C:\Users\OpenFlyers\PyOpenKey\SSL\opkServer.crt&amp;quot;'''&lt;br /&gt;
&lt;br /&gt;
==Paramétrage OpenFlyers==&lt;br /&gt;
&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Structure &amp;gt; Structure &amp;gt; Paramétrage'''&lt;br /&gt;
*Dans la section '''Contrôle d'accès''', cliquer sur l'option '''Activé(e)''' des rubriques '''Contrôle d'accès''' et '''Gestion armoire à clés'''. &lt;br /&gt;
[[File:Config_parametres_OF_controle_acces 1.jpg]]&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
*De nouveaux champs sont alors visibles :&lt;br /&gt;
**cliquer sur l'option '''Activé(e)''' de la rubrique '''Gestion des clés'&lt;br /&gt;
** sélectionner le Logiciel de contrôle de l'armoire à clés. Pour OpenFlyers version 4.2 en https : PyOpenKey4&lt;br /&gt;
[[File:Config_parametres_OF_controle_acces 2.jpg]]&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
*De nouveaux champs sont alors visibles :&lt;br /&gt;
**Champ '''Nombre de clés''' : indiquer le nombre de clés que l'armoire peut accueillir (8, 16 ou 32)&lt;br /&gt;
*Dans la rubrique '''IP du PC contenant le logiciel de contrôle''' indiquer l'adresse IP du mini-serveur OpenFlyers, par défaut '''192.168.0.200''' ou '''192.168.1.200'''&lt;br /&gt;
*Dans la rubrique '''Port du PC contenant le logiciel de contrôle''' indiquer le port '''4080''' (ou autre si spécifié sur le bordereau de livraison)&lt;br /&gt;
**Champ '''Vérifier la présence de la clé lors de la fermeture du vol''', valeur conseillée : '''Activé(e)'''&lt;br /&gt;
**Choisissez la durée de '''Temporisation''' pour prendre la clé. Cette durée est uniquement valide pour la prise de clé en mode locale, elle dépend de la distance entre votre PC et l'armoire. 10 à 20 secondes sont des valeurs usuelles. Pour la durée de déclenchement par le logiciel celle ci est paramétrable dans le programme du mini serveur. Demander au support OF pour modification&lt;br /&gt;
**Champ '''Fermeture automatique des vols au retour de la clé''', valeur conseillée : '''Désactivé(e)'''&lt;br /&gt;
**Champ '''Phrase mot de passe''', saisissez la même phrase que celle paramétrée lors de la configuration de l'armoire&lt;br /&gt;
[[File:Config_parametres_OF_controle_acces 3.jpg]]&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Utilisateurs &amp;gt; Profils''' et vérifier que le profil sous lequel vous êtes connecté possède le droit '''Gestion des clés''' dans l'onglet '''Généralité admin'''&lt;br /&gt;
&lt;br /&gt;
=Première connexion=&lt;br /&gt;
==Brancher l'alimentation de l'armoire à clés==&lt;br /&gt;
*Le voyant vert de l'armoire doit s'allumer après quelques minutes&lt;br /&gt;
*Le voyant orange reste allumé durant la phase de connexion au serveur OpenFlyers et la vérification de la concordande de la position des clés dans l'armoire&lt;br /&gt;
*A la fin de l'initialisation, si toutes les clés sont bien positionnées, le voyant orange s’éteint&lt;br /&gt;
&lt;br /&gt;
Si le voyant orange ne s'éteint pas, [[Gestion armoire à clés#Remettre_les_clés_à_leur_bonne_position|vérifier si le problème ne vient pas de la position d'une ou plusieurs clés]].&lt;br /&gt;
&lt;br /&gt;
== Vérifier la communication avec le serveur PyOpenKey ==&lt;br /&gt;
Ce chapitre concerne les utilisateurs d'OpenFlyers 4.2 et au delà qui demande une connexion au serveur PyOpenKey en https&lt;br /&gt;
&lt;br /&gt;
Vérifier si le certificat est correctement reconnu sur votre PC&lt;br /&gt;
&lt;br /&gt;
*Ouvrer le Navigateur Google Chrome&lt;br /&gt;
*Dans le champ url indiquer l'adresse du WevServer de PyOpenKey, port 8000 '''https;//192.168.1.200:8000''' (cette adresse est a adapter en fonction de votre configuration réseau)&lt;br /&gt;
*Si c'est une première connexion, une fenêtre Windows s'ouvre vous demandant la confirmation de l'utilisation du certificat&lt;br /&gt;
*Si la fenêtre Windows indique que la connexion n'est pas sécurisé c'est que le certificat n'est pas correctement installé. Ne pas valider une exception de sécurité &lt;br /&gt;
*Si le certificat est reconnu alors la page du [[Gestion-armoire-à-clés#Connexion-à-l'interface-Web-de-secours|Webserver]] doit s'ouvrir&lt;br /&gt;
&lt;br /&gt;
=Appariement des clés aux ressources=&lt;br /&gt;
*Pour attribuer les clés aux ressources dans OpenFlyers il faut aller dans la page '''Gestion &amp;gt; Ressources &amp;gt; Actives'''&lt;br /&gt;
*Sélectionner un numéro de clé pour chaque ressource.&lt;br /&gt;
[[File:Page_Ressource.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Sur les versions au-delà d'OpenFlyers 4.2, si aucune action ne s'exécute ceci être dû à la non reconnaissance du certificat&lt;br /&gt;
 &lt;br /&gt;
Voir [[Installation-armoire-à-clés#Vérifier-la-communication-avec-le-serveur-PyOpenKey |Vérifier la communication avec le serveur PyOpenKey]].&lt;br /&gt;
&lt;br /&gt;
Sur les versions antérieures d'OpenFlyers 4.2, si l'action ne s'exécute pas ceci peut être dû au blocage par le navigateur des scripts javascript car l'appel est en http sur une page https.&lt;br /&gt;
&lt;br /&gt;
Sous Google Chrome apparait un icône en haut à droite&lt;br /&gt;
[[File:Page_Allow_mixed_content_Chrome.png|center]]&lt;br /&gt;
Avec le message&lt;br /&gt;
&amp;lt;bash&amp;gt;This page is trying to load scripts from unauthenticated sources&amp;lt;/bash&amp;gt;&lt;br /&gt;
Avec un lien pour autoriser la page&lt;br /&gt;
&amp;lt;bash&amp;gt;Load unsafe script&amp;lt;/bash&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Enregistrer la position souhaitée des clés=&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Ressources &amp;gt; Actives'''&lt;br /&gt;
*Cliquer sur l'un des icônes symbolisant une clé dans la colonne '''Armoire à clé &amp;gt; Statut''' afin de pouvoir déverrouiller la porte.&lt;br /&gt;
*Mettre '''toutes les clés''' au tableau dans l'ordre souhaité y compris les clés qui avaient été retirées lors de la [[#Première_connexion|première connexion]]. Il ne faut pas tenir compte des lumières rouges autour des clés.&lt;br /&gt;
*Cliquer sur l'icône '''Activer les tags des clés'''&lt;br /&gt;
Les identifiants de chaque clé doivent apparaître après rafraîchissement de la page :&lt;br /&gt;
&lt;br /&gt;
[[File:Ressources_activees.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
Si ce n'est pas le cas, rafraichir manuellement la page en allant dans '''Gestion &amp;gt; Ressources &amp;gt; Actives'''.&lt;br /&gt;
&lt;br /&gt;
Débranchez de nouveau l'armoire pour refaire l'initialisation&lt;br /&gt;
&lt;br /&gt;
=Prise de clé à l'ouverture d'un vol=&lt;br /&gt;
Pour un contrôle de la prise de clé par un utilisateur il faut que le logiciel soit paramétré avec l'option '''Ouverture et fermeture des activités.'''  Aller dans '''Admin &amp;gt; Structure &amp;gt; Structure &amp;gt; Paramétrage''' et dans la rubrique '''Gestion des activités''' activer l'option '''Ouverture et fermeture des activités'''&lt;br /&gt;
.&lt;br /&gt;
[[File:Gestion_des_vols.JPG]]&lt;br /&gt;
&lt;br /&gt;
Pour une prise de clé il faut cliquer droit sur une réservation et choisir l'option Saisir un vol&lt;br /&gt;
La page de saisie d'un vol s'ouvre avec l'option Départ en vol&lt;br /&gt;
Renseigner les champs et cliquer sur Valider&lt;br /&gt;
Une page de prise de clé s'ouvrira &lt;br /&gt;
&lt;br /&gt;
[[File:Prise_de_cle.JPG]]&lt;br /&gt;
&lt;br /&gt;
Cliquer sur le bouton Libérer la clé pour l'aéronef F-XXXX &lt;br /&gt;
La porte doit se déverrouiller (voyant orange) et la clé être libérer durant la temporisation prévue (clé entourée d'un halo lumineux rouge)&lt;br /&gt;
Refermer la porte sinon un buzzer intermittent retenti&lt;br /&gt;
&lt;br /&gt;
Déconnectez-vous de OpenFlyers pour l'utilisateur suivant&lt;br /&gt;
&lt;br /&gt;
=Retour de vol=&lt;br /&gt;
&lt;br /&gt;
Pour remettre la clé, se connecter sur OpenFlyers &lt;br /&gt;
Cliquer sur l'icône Ouvrir la porte en haut à gauche de la page du cahier de réservation&lt;br /&gt;
&lt;br /&gt;
[[File:Ouvrir_porte.JPG]]&lt;br /&gt;
&lt;br /&gt;
La porte sera déverrouillé durant la durée de la temporisation&lt;br /&gt;
*Remettre la clé à son emplacement&lt;br /&gt;
*Si la clé est incorrectement placée, l'armoire déverrouille la clé (halo rouge de la clé reposée) et signale l'emplacement correct en allumant le halo rouge de l'emplacement prévu. &lt;br /&gt;
*Sur le planning l'avion en vol est indiquer par une couleur bleu. Survoler ce vol avec la souris&lt;br /&gt;
*Un menu apparait avec l'option '''Fermer le vol'''&lt;br /&gt;
*Cliquer et enregistré le vol &lt;br /&gt;
&lt;br /&gt;
'''Note:''' Ne pas aller directement sur le menu '''Planning &amp;gt; Activités &amp;gt; Saisir une activité''' pour fermer le vol. Dans ce cas il ne pourra être établi de corrélation entre l'affichage du planning et le vol que vous fermez. Le vol restera ouvert (en bleu sur le planning) et l'avion sera bloqué pour repartir en vol. Néanmoins si un pilote faire l'erreur alors il faut, dans le menu surgissant, cliquer sur '''Annuler'''&lt;br /&gt;
&lt;br /&gt;
=Finalisation=&lt;br /&gt;
*Ouvrir la porte de service&lt;br /&gt;
*Brancher le connecteur de la batterie de sauvegarde (Déconnecté pour le transport)&lt;br /&gt;
&lt;br /&gt;
[[File:Connexion_Batterie_SmartII.jpg]]&lt;br /&gt;
*Refermer la porte de service&lt;br /&gt;
&lt;br /&gt;
L'ouverture de la porte de service enclenche une alarme qui est mise en mémoire dans OpenFlyers. Pour supprimer l'alarme il faut aller sur l'interface [[Gestion armoire à clés#Connexion_interface_Web_de_secours|Web admin]] et cliquer sur '''RESET'''&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Gestion-des-types-d%27activit%C3%A9s&amp;diff=12892</id>
		<title>Gestion des types d'activités</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Gestion-des-types-d%27activit%C3%A9s&amp;diff=12892"/>
		<updated>2024-10-02T17:27:54Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter la '''gestion des types d'activités''' sur la [[Accueil|version 4 d'OpenFlyers]].&lt;br /&gt;
&lt;br /&gt;
Le droit [[Gestion-des-profils#Gestion-du-paramétrage|Gestion du paramétrage]] est nécessaire pour accéder à cette fonctionnalité.&lt;br /&gt;
&lt;br /&gt;
=Affecter une couleur à un type d'activité=&lt;br /&gt;
Préambule : pour voir ces couleurs, il faut que dans la configuration soit paramétré le code couleur par type d'activité pour voir ces couleurs.&lt;br /&gt;
&lt;br /&gt;
*Aller sur la page '''Admin &amp;gt; Types d'activités &amp;gt; Types d'activités &amp;gt; Actifs'''&lt;br /&gt;
*Aller sur la ligne concernée et cliquer dans la colonne '''Couleur''' où apparait l'icône modifier.&lt;br /&gt;
*Sélectionner une couleur.&lt;br /&gt;
*La validation se fait automatiquement.&lt;br /&gt;
&lt;br /&gt;
=Ajouter un type d'activité=&lt;br /&gt;
*Aller sur la page '''Admin &amp;gt; Types d'activités &amp;gt; Types d'activités &amp;gt; Actifs'''&lt;br /&gt;
*Cliquer sur chaque cellule contenant le symbole '''+''' pour&lt;br /&gt;
**Saisir le nom du type d'activité&lt;br /&gt;
**[[#Affecter-une-couleur-à-un-type-d'activité|Affecter une couleur]]&lt;br /&gt;
**La colonne '''Formation''' permet de définir le type d'activité comme étant un type d'activité formation ce qui permet de [[Gestion-des-activités#Saisir-un-suivi-de-formation|saisir un suivi de formation]] pour chaque activité ayant ce type.&lt;br /&gt;
*Cliquer sur l'icône [[File:MRO302-addButton.png]]&lt;br /&gt;
&lt;br /&gt;
=Modifier un type d'activité=&lt;br /&gt;
*Aller sur la page '''Admin &amp;gt; Types d'activités &amp;gt; Types d'activités &amp;gt; Actifs'''&lt;br /&gt;
*Cliquer sur le champ dont le contenu est à modifier de l'activité concernée et qui correspond à l'une des colonnes suivantes :&lt;br /&gt;
**'''Nom''' : nom de l'activité&lt;br /&gt;
**'''[[#Affecter-une-couleur-à-un-type-d'activité|Couleur]]'''&lt;br /&gt;
**'''Formation''' : permet de définir le type d'activité comme étant un type d'activité formation ce qui permet de [[Gestion-des-activités#Saisir-un-suivi-de-formation|saisir un suivi de formation]] pour chaque activité ayant ce type.&lt;br /&gt;
Une fois la modification effectuée, il faut cliquer en dehors du tableau pour que la modification soit enregistrée en base de données.&lt;br /&gt;
&lt;br /&gt;
=Typer formation un type d'activité=&lt;br /&gt;
Permet de définir un type d'activité comme étant un type d'activité formation ce qui permet de [[Gestion-des-activités#Saisir-un-suivi-de-formation|saisir un suivi de formation]] pour chaque activité ayant ce type.&lt;br /&gt;
&lt;br /&gt;
*Aller sur la page '''Admin &amp;gt; Types d'activités &amp;gt; Types d'activités &amp;gt; Actifs'''&lt;br /&gt;
*Cliquer sur la cellule de la colonne '''Formation''' de la ligne du type d'activité concerné&lt;br /&gt;
*Cocher la case à cocher&lt;br /&gt;
Une fois la modification effectuée, il faut cliquer en dehors du tableau pour que la modification soit enregistrée en base de données.&lt;br /&gt;
Attendre que la page se rafraichisse et qu'un 1 apparaisse&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Gestion-des-profils&amp;diff=12891</id>
		<title>Gestion des profils</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Gestion-des-profils&amp;diff=12891"/>
		<updated>2024-10-02T17:27:53Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter la '''gestion des profils''' sur la [[Accueil|version 4 d'OpenFlyers]].&lt;br /&gt;
&lt;br /&gt;
[[File:Profile-management4.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les profils attribués par défaut à un utilisateur créé automatiquement sont définis dans '''Admin &amp;gt; Utilisateurs &amp;gt; Paramètres par défaut'''.&lt;br /&gt;
&lt;br /&gt;
=Définition=&lt;br /&gt;
*Un '''profil''' correspond à un ensemble de '''droits''' qui définissent les actions que peut effectuer un [[Glossaire|utilisateur]] dans l'application OpenFlyers.&lt;br /&gt;
*Un utilisateur peut disposer de '''plusieurs profils'''. L'attribution des profils aux utilisateurs se fait par l'intermédiaire du  [[Gestion des utilisateurs|tableau de gestion des utilisateurs]].&lt;br /&gt;
&lt;br /&gt;
''Exemple de profils : administrateur, pilote, formateur, technicien, mécanicien, trésorier, secrétaire.''&lt;br /&gt;
&lt;br /&gt;
=Icônes symbolisant les droits des profils=&lt;br /&gt;
Dans la page '''Admin &amp;gt; Utilisateurs &amp;gt; Profils''', il faut distinguer deux éléments pour comprendre le principe des icônes. Il y a les droits d'un côté et les profils de l'autre.&lt;br /&gt;
&lt;br /&gt;
Les droits constituent les entêtes du tableau. Chaque entête de colonne correspond à un droit.&lt;br /&gt;
L’icône [[File:Profile-management3.0.x_Userinfo_connected.gif]] a été attribuée à l'ensemble de ces droits sauf deux :&lt;br /&gt;
*[[#Profil-non-sélectionnable-par-l'utilisateur|Profil non sélectionnable par l'utilisateur]] de l'onglet '''Généralités''' à laquelle l'icône [[File:Profile-management3.0.x_ConnectedNoFilling.png]] à été attribuée&lt;br /&gt;
*[[#Voir-les-noms-sur-les-réservations|Voir les noms sur les réservations]] de l'onglet '''Réservations''' à laquelle l'icône [[File:Profile-management3.0.x_Userinfo_kiosk.gif]] à été attribuée&lt;br /&gt;
&lt;br /&gt;
Les profils correspondent à chaque ligne du tableau. L'icône d'un profil est variable et dépend des droits qui lui sont attribués.&lt;br /&gt;
#L'icône d'un profil sera [[File:Profile-management3.0.x_ConnectedNoFilling.png]] si le droit [[#Profil-non-sélectionnable-par-l'utilisateur|Profil non sélectionnable par l'utilisateur]] ci-dessus est coché&lt;br /&gt;
#L'icône d'un profil sera [[File:Profile-management3.0.x_Userinfo_kiosk.gif]] si aucun droit n'est attribué au profil à l'exception du droit [[#Voir-les-noms-sur-les-réservations|Voir les noms sur les réservations]] ci-dessus qui peut être coché ou non&lt;br /&gt;
#Dans tous les autres cas, l'icône d'un profil sera [[File:Profile-management3.0.x_Userinfo_connected.gif]]&lt;br /&gt;
&lt;br /&gt;
==Définition des icônes représentant des droits==&lt;br /&gt;
:[[File:Profile-management3.0.x_Userinfo_connected.gif]] : Droit qui définit un profil de base.&lt;br /&gt;
:[[File:Profile-management3.0.x_ConnectedNoFilling.png]] : Droit qui rend un profil non sélectionnable par un utilisateur lors de sa connexion.&lt;br /&gt;
:[[File:Profile-management3.0.x_Userinfo_kiosk.gif]] : Droit qui rend un profil de type &amp;quot;kiosque&amp;quot; (voir [[Kiosque PC]]) permettant de consulter le planning uniquement. Si au moins un droit de base est activé, le profil devient un profil de base.&lt;br /&gt;
&lt;br /&gt;
==Définition des icônes attribuées aux profils==&lt;br /&gt;
:[[File:Profile-management3.0.x_Userinfo_connected.gif]] : Profil de base&lt;br /&gt;
:[[File:Profile-management3.0.x_ConnectedNoFilling.png]] : Profil non sélectionnable par un utilisateur lors de sa connexion.&lt;br /&gt;
:[[File:Profile-management3.0.x_Userinfo_kiosk.gif]] : Profil de type &amp;quot;kiosque&amp;quot; (voir [[Kiosque PC]]) permettant de consulter le planning uniquement. Toute modification ou saisie par un utilisateur nécessitera une identification par le biais d'une fenêtre &amp;quot;pop-up&amp;quot; demandant à l'utilisateur son propre identifiant et mot de passe.&lt;br /&gt;
&lt;br /&gt;
=Niveau d'accréditation des droits et des profils=&lt;br /&gt;
Les niveaux d'accréditation vont de 0 à 6 :&lt;br /&gt;
*0 représente le niveau le plus bas&lt;br /&gt;
*6 représente le niveau le plus élevé&lt;br /&gt;
&lt;br /&gt;
Chaque droit dispose d'un niveau d'accréditation qui lui est propre : plus le droit permet de faire des actions pouvant avoir des conséquences sur les données, plus le niveau d'accréditation est élevé.&lt;br /&gt;
&lt;br /&gt;
Chaque profil dispose également d'un niveau d'accréditation. Le niveau d'accréditation d'un profil correspond au niveau d'accréditation le plus élevé des droits détenus par le profil.&lt;br /&gt;
&lt;br /&gt;
La page '''Admin &amp;gt; Utilisateurs &amp;gt; Profils''' indique les niveaux d'accréditation à la fois des droits et des profils :&lt;br /&gt;
*Les droits sont indiqués dans les entêtes de chaque colonne. Le niveau d'accréditation du droit est indiqué en dessous du nom du droit dans un cercle.&lt;br /&gt;
*Les profils sont indiqués à chaque ligne du tableau. le niveau d'accréditation du profil est indiqué en dessous du nom du profil dans un cercle.&lt;br /&gt;
Le niveau d'accréditation 6 est affiché en inverse vidéo par rapport aux autres niveaux pour le distinguer.&lt;br /&gt;
&lt;br /&gt;
Un gestionnaire disposant le droit de gérer des utilisateurs ne peut attribuer un profil à un utilisateur qui soit plus élevé que le profil le plus élevé qu'il détient lui-même.&lt;br /&gt;
&lt;br /&gt;
Lorsqu'une plateforme dispose de plus de 3 utilisateurs avec le niveau 6, [[Alertes-de-configuration#La-plateforme-a-plus-de-3-utilisateurs-actifs-avec-un-profil-de-niveau-6.-Les-utilisateurs-concernés-sont-:-XXX|une alerte de configuration est affichée]].&lt;br /&gt;
&lt;br /&gt;
Lorsqu'un droit de niveau 6 est accordé à un profil, une alerte est générée si cela entraîne plus de 3 utilisateurs de niveau 6.&lt;br /&gt;
&lt;br /&gt;
=Profils=&lt;br /&gt;
La gestion des profils s'effectue depuis le menu '''Admin &amp;gt; Utilisateurs &amp;gt; Profils'''.&lt;br /&gt;
&lt;br /&gt;
Le nombre d'onglets disponible dépend du paramétrage de la plateforme OpenFlyers. Par exemple, si la gestion des activités est activée, alors l'onglet ''Activités'' est disponible.&lt;br /&gt;
&lt;br /&gt;
==Généralités==&lt;br /&gt;
&lt;br /&gt;
===Profil non sélectionnable par l'utilisateur===&lt;br /&gt;
&lt;br /&gt;
Lors de la connexion et lorsqu'un utilisateur doit faire le choix entre un profil pour se connecter, les [[Bien-débuter-avec-OpenFlyers#Attribuer-les-profils-aux-utilisateurs|profils non sélectionnables]] ne seront pas proposés parmi la liste. Ce droit ne peut pas être attribué à un profil ayant des droits de gestion.&lt;br /&gt;
&lt;br /&gt;
===Pas de déconnexion automatique===&lt;br /&gt;
Ce droit permet d'éviter la [[Connexion#Automatique|déconnexion automatique de la session]] au bout de 10 minutes et étend la connexion à 2 heures.&lt;br /&gt;
&lt;br /&gt;
===Accès visiteur===&lt;br /&gt;
L'accès visiteur permet de [[Kiosque-PC#Créer-un-compte-utilisateur-Visiteur|créer un compte visiteur]] donnant un accès limité destiné à pouvoir être utilisé par n'importe quelle personne.&lt;br /&gt;
&lt;br /&gt;
Cet accès permet également de créer un lien vers OpenFlyers avec une connexion automatique en passant les identifiants via l'URL.&lt;br /&gt;
&lt;br /&gt;
Si un visiteur [[#Réservation|peut réserver]] - dépend du paramétrage - alors, lors de la création d'une réservation, [[Utilisation-du-planning-de-réservation#Créer-automatiquement-un-utilisateur-en-créant-une-réservation|le système va générer automatiquement un compte utilisateur]] à partir des informations que le visiteur aura saisi. Le visiteur sera connecté automatiquement sur ce nouveau compte.&lt;br /&gt;
&lt;br /&gt;
===Mise à jour de sa date de naissance, de son sexe et de sa nationalité===&lt;br /&gt;
&lt;br /&gt;
Permet à un utilisateur de modifier [[Fiche-personnelle#Mettre-à-jour-sa-date-de-naissance,-sa-nationalité-ou-son-sexe|sa date de naissance, sa nationalité et/ou son sexe dans sa fiche personnelle]].&lt;br /&gt;
&lt;br /&gt;
===Voir ses validités===&lt;br /&gt;
&lt;br /&gt;
Permet d'[[Validités#Consulter-et-gérer-ses-validités-ou-celles-d'un-tiers|accéder à ses validités depuis le planning]].&lt;br /&gt;
&lt;br /&gt;
===Ajout et gestion de ses validités===&lt;br /&gt;
&lt;br /&gt;
Permet à un [[Validités#Consulter-et-gérer-ses-validités-ou-celles-d'un-tiers|utilisateur de rajouter/supprimer/mettre à jour ses validités]] qui sont dans la liste [[#Type-de-validité-que-l'utilisateur-peut-gérer|Type de validité que l'utilisateur peut gérer]] et pour la mise à jour, sous réserve que le type de validité dispose d'informations qui peuvent être mises à jour.&lt;br /&gt;
&lt;br /&gt;
===Gestion de ses validités détenues===&lt;br /&gt;
&lt;br /&gt;
Permet à un [[Validités#Consulter-et-gérer-ses-validités-ou-celles-d'un-tiers|utilisateur de mettre à jour/supprimer uniquement les validités]] qui lui sont déjà attribuées et qui sont dans la liste [[#Type-de-validité-que-l'utilisateur-peut-gérer|Type de validité que l'utilisateur peut gérer]] et pour la mise à jour, sous réserve que le type de validité dispose d'informations qui peuvent être mises à jour.&lt;br /&gt;
&lt;br /&gt;
===Surpasser les restrictions sur les validités===&lt;br /&gt;
Permet à un utilisateur de surpasser les [[Connexion#Restriction_d'accès|restrictions d'accès]] dues à des validités expirées, incomplétes ou non certifiées qui sont [[Validités#Contrôle-des-validités-à-la-connexion|appliquées à la connexion]].&lt;br /&gt;
&lt;br /&gt;
Voir le chapitre [[Paramétrage-des-validités#Alerte-à-la-connexion|Alerte à la connexion]] pour le paramétrage des restrictions sur les validités.&lt;br /&gt;
&lt;br /&gt;
===Editer sa photo===&lt;br /&gt;
&lt;br /&gt;
Permet à un utilisateur [[Fiche-personnelle#Editer-sa-photo|d'importer ou de supprimer sa photo dans sa fiche personnelle]].&lt;br /&gt;
&lt;br /&gt;
==Réservation==&lt;br /&gt;
&lt;br /&gt;
===Planning personnel===&lt;br /&gt;
&lt;br /&gt;
Permet de visualiser son propre planning.&lt;br /&gt;
&lt;br /&gt;
===Planning individuel visible pour les autres===&lt;br /&gt;
&lt;br /&gt;
Permet de rendre disponible son planning aux autres utilisateurs.&lt;br /&gt;
&lt;br /&gt;
===Personnaliser ses ressources visibles===&lt;br /&gt;
&lt;br /&gt;
Permet de personnaliser la [[Fiche-personnelle#Paramétrer-les-ressources-et-les-utilisateurs-visibles-sur-le-planning|liste des ressources et utilisateurs visibles dans le planning depuis sa fiche utilisateur]].&lt;br /&gt;
&lt;br /&gt;
===Gérer ses disponibilités===&lt;br /&gt;
&lt;br /&gt;
Permet la gestion de [[Gestion-des-disponibilités#Gérer-la-disponibilité-des-intervenants|ses propres disponibilités]].&lt;br /&gt;
&lt;br /&gt;
===Gestion des disponibilités des tiers===&lt;br /&gt;
&lt;br /&gt;
Permet de gérer la [[Gestion-des-disponibilités#Gérer-la-disponibilité-des-intervenants|disponibilité des utilisateurs]].&lt;br /&gt;
&lt;br /&gt;
===Etre sur une nouvelle réservation===&lt;br /&gt;
Permet lors d'une nouvelle réservation, que l'utilisateur disposant du profil concerné soit autorisée à être sur une des places. &lt;br /&gt;
&lt;br /&gt;
Permet entre autre à un utilisateur tiers, de pouvoir effectuer de nouvelles réservations pour un utilisateur disposant du profil concerné et n'ayant pas de droit [[#Réservation-solo|Réservation solo]], [[#Réservation-pour-des-tiers|Réservation pour des tiers]] ou [[#Réservation-avec-un-instructeur|Réservation avec un instructeur]].&lt;br /&gt;
&lt;br /&gt;
===Réservation solo===&lt;br /&gt;
&lt;br /&gt;
Autorise un utilisateur de réserver une ressource avec lui-même en première place.&lt;br /&gt;
&lt;br /&gt;
===Réservation pour des tiers===&lt;br /&gt;
&lt;br /&gt;
Autorise la réservation d'une ressource pour un autre utilisateur (en solo et/ou double selon les droits du profil de cet utilisateur tiers).&lt;br /&gt;
&lt;br /&gt;
===Réservation avec un instructeur===&lt;br /&gt;
&lt;br /&gt;
Autorise la réservation d'une ressource avec une personne en seconde place.&lt;br /&gt;
&lt;br /&gt;
===Réservation de programmes===&lt;br /&gt;
Autorise [[Planning-(interface-légère)#Positionner-automatiquement-les-activités-d’un-programme-de-formation|le positionnement automatique des activités d’un programme de formation dans le planning]].&lt;br /&gt;
&lt;br /&gt;
===Gestion des disponibilités des ressources===&lt;br /&gt;
&lt;br /&gt;
Sur l'ancienne interface, permet de gérer la disponibilité des ressources et de les immobiliser (pour entretien, maintenance, réparation, arrêt d'activité, ...). &lt;br /&gt;
&lt;br /&gt;
Cela se fait comme pour une réservation, une case &amp;quot;immobiliser la ressource&amp;quot; est alors disponible. Sur la frise de réservation, il sera indiqué &amp;quot;Mise en maintenance&amp;quot; pour la période demandée.&lt;br /&gt;
&lt;br /&gt;
===Surpasser l'indisponibilité des instructeurs=== &lt;br /&gt;
&lt;br /&gt;
Autorise la réservation d'une ressource avec un instructeur même si celui-ci n'est pas enregistré comme disponible durant la plage horaire de la réservation (Un message d'alerte prévient quand même. Fonction utile pour les instructeurs et le secrétariat).&lt;br /&gt;
&lt;br /&gt;
===Surpasser l'indisponibilité des ressources===&lt;br /&gt;
&lt;br /&gt;
Autorise la réservation d'une ressource même si celle-ci n'est pas enregistrée comme disponible durant la plage horaire de la réservation (Un message d'alerte prévient quand même).&lt;br /&gt;
&lt;br /&gt;
===Surpasser l'interdiction d'effectuer une réservation dans moins de X temps===&lt;br /&gt;
&lt;br /&gt;
Autorise la réservation en annulant l'interdiction &amp;quot;d'effectuer une réservation débutant dans moins de&amp;quot; .&lt;br /&gt;
&lt;br /&gt;
===Surpasser la limite de durée minimum===&lt;br /&gt;
&lt;br /&gt;
Autorise la réservation en annulant la restriction sur la durée minimum d'une réservation.&lt;br /&gt;
&lt;br /&gt;
===Surpasser la limite de durée maximum===&lt;br /&gt;
&lt;br /&gt;
Autorise la réservation en annulant la restriction sur la durée maximum d'une réservation.&lt;br /&gt;
&lt;br /&gt;
===Surpasser la limite de temps===&lt;br /&gt;
&lt;br /&gt;
Autorise la réservation en annulant la restriction sur la limitation dans le temps des réservations.&lt;br /&gt;
&lt;br /&gt;
===Surpasser la limite de nombre===&lt;br /&gt;
&lt;br /&gt;
Autorise la réservation en annulant la restriction sur le nombre maximum de réservation.&lt;br /&gt;
&lt;br /&gt;
===Surpasser la réservation par type===&lt;br /&gt;
&lt;br /&gt;
En cas de chevauchement, cela permet de déplacer la réservation sur une autre ressource de type différent.&lt;br /&gt;
&lt;br /&gt;
===Alertable par e-mail pour toute réservation===&lt;br /&gt;
&lt;br /&gt;
Permet la [[Fiche-personnelle#Recevoir-un-e-mail-pour-les-réservations-ayant-pour-activité|notification par e-mail pour toute réservation]].&lt;br /&gt;
&lt;br /&gt;
===Créer ou modifier une réservation avec une date de début dépassée===&lt;br /&gt;
&lt;br /&gt;
Autorise à créer ou modifier une réservation dont la date de début est dépassée.&lt;br /&gt;
&lt;br /&gt;
===Supprimer une réservation avec une date de début dépassée===&lt;br /&gt;
&lt;br /&gt;
Autorise à supprimer une réservation dont la date de début est dépassée.&lt;br /&gt;
&lt;br /&gt;
===Voir les noms sur les réservations===&lt;br /&gt;
Permet de visualiser les noms des utilisateurs associés à la réservation.&lt;br /&gt;
&lt;br /&gt;
===Voir les activités sur les réservations===&lt;br /&gt;
Permet de [[Planning-(interface-légère)#Affichage-des-activités-sur-les-réservations|visualiser les types d'activités associés à chaque réservation]].&lt;br /&gt;
&lt;br /&gt;
===Voir les images des pilotes sur le menu contextuel===&lt;br /&gt;
Permet de [[Planning-(interface-légère)#Affichage-des-images-des-pilotes-sur-le-menu-contextuel|visualiser images des pilotes associés à chaque réservation sur le menu contextuel]] lorsqu'on survole ou effectue un clic droit sur la réservation.&lt;br /&gt;
&lt;br /&gt;
===Surpasser les formules de saisie===&lt;br /&gt;
Permet de surpasser les règles de saisie sur les réservations.&lt;br /&gt;
&lt;br /&gt;
===Champs additionnels visualisables dans les pop-ups de réservation===&lt;br /&gt;
&lt;br /&gt;
Permet de visualiser le contenu des champs additionnels dans la pop-up de réservation.&lt;br /&gt;
&lt;br /&gt;
==Activités==&lt;br /&gt;
&lt;br /&gt;
===Etre sur une nouvelle ouverture d'activité===&lt;br /&gt;
Permet lors d'une nouvelle ouverture d'activité, que la personne disposant du profil concerné soit autorisée à être sur une des places.&lt;br /&gt;
&lt;br /&gt;
Permet entre autre à une personne tierce, de pouvoir effectuer de nouvelles ouvertures d'activité pour une personne disposant du profil concerné et n'ayant pas le droit [[#Saisie-d'activité-pour-soi-même|Saisie d'activité pour soi-même]] ou [[#Saisie-d'activité-pour-un-tiers|Saisie d'activité pour un tiers]].&lt;br /&gt;
&lt;br /&gt;
===Etre sur une nouvelle fermeture d'activité===&lt;br /&gt;
Permet lors d'une nouvelle fermeture d'activité, que la personne disposant du profil concerné soit autorisée à être sur une des places.&lt;br /&gt;
&lt;br /&gt;
Permet entre autre à une personne tierce, de pouvoir effectuer de nouvelles fermetures d'activité pour une personne disposant du profil concerné et n'ayant pas le droit [[#Saisie-d'activité-pour-soi-même|Saisie d'activité pour soi-même]] ou [[#Saisie-d'activité-pour-un-tiers|Saisie d'activité pour un tiers]].&lt;br /&gt;
&lt;br /&gt;
===Saisie d'activité pour soi-même===&lt;br /&gt;
Autorise la saisie des vols et permet aussi à l'utilisateur de voir son carnet de vols.&lt;br /&gt;
&lt;br /&gt;
Permet également de supprimer ses propres vols depuis son carnet de vol et depuis le [[Carnet-de-route#Modifier-et-supprimer|carnet de route]].&lt;br /&gt;
&lt;br /&gt;
===Saisie d'activité pour un tiers===&lt;br /&gt;
Autorise la saisie des vols pour des tiers et permet de voir les carnets de vols des utilisateurs.&lt;br /&gt;
&lt;br /&gt;
Permet également de supprimer les vols des tiers depuis le carnet de vol d'un utilisateur et depuis le [[Carnet-de-route#Modifier-et-supprimer|carnet de route]].&lt;br /&gt;
&lt;br /&gt;
===Vérifier la saisie des activités et les modifier===&lt;br /&gt;
&lt;br /&gt;
Permet de voir les carnets de vols des utilisateurs et de pointer les vols (vérification qui entérine un vol et qui rend ainsi sa modification ou suppression impossible), permet ainsi de voir les &amp;quot;vols oubliés&amp;quot; aussi (trous dans les horamètres).&lt;br /&gt;
&lt;br /&gt;
===Visualisation du carnet de route===&lt;br /&gt;
&lt;br /&gt;
Accorde (ou pas) le droit de visualiser le carnet de route de chaque ressource aéronef.&lt;br /&gt;
&lt;br /&gt;
===Visualisation de son carnet de vol===&lt;br /&gt;
&lt;br /&gt;
Autorise l'utilisateur à voir son carnet de vol.&lt;br /&gt;
&lt;br /&gt;
===Visualiser les traces de vol===&lt;br /&gt;
&lt;br /&gt;
Permet de [[Interfaçage-OpenFlyers-et-Charterware#Récupération-des-traces-de-vols|visualiser les traces d'un vol]].&lt;br /&gt;
&lt;br /&gt;
===Attribution de place===&lt;br /&gt;
&lt;br /&gt;
Permet d'attribuer les places auxquelles sont autorisées les utilisateurs de ce profil. Cela impacte sur les listes des utilisateurs qui se nttrouve à la saisie d'une réservation ou d'une activité.&lt;br /&gt;
&lt;br /&gt;
Ces listes sont accessibles depuis '''Planning &amp;gt; Planning &amp;gt; Réserver''' et '''Planning &amp;gt; Activités &amp;gt; Saisir une activité'''.&lt;br /&gt;
&lt;br /&gt;
La page '''Admin &amp;gt; Type de ressource &amp;gt; Places''' permet de gérer les places d'un type de ressource. Elle permet également de définir qui a le droit d'être sur telle place en cas de restriction de profil.&lt;br /&gt;
&lt;br /&gt;
===Alerté par e-mail pour le renouvellement des validités de tous les utilisateurs===&lt;br /&gt;
&lt;br /&gt;
Ce droit permet de suivre le renouvellement des validités par les utilisateurs en étant alerté par un [[Envoi-des-emails#E-mail-d'information-des-actions-des-utilisateurs-sur-des-validités|e-maild'information des actions des utilisateurs sur des validités]] à chaque fois qu'un utilisateur renouvelle une validité sélectionnée dans la liste de la cellule '''Alerté par e-mail pour le renouvellement des types de validités'''. Attention : la mise en place de ce droit peut provoquer la réception de nombreux e-mails.&lt;br /&gt;
&lt;br /&gt;
==Formations==&lt;br /&gt;
===Voir les suivis de formations===&lt;br /&gt;
Autorise l'utilisateur à [[Gestion-des-activités#Consulter-le-suivi-de-formation|voir les suivis de formations]] de tous les utilisateurs.&lt;br /&gt;
&lt;br /&gt;
===Gestion des formations===&lt;br /&gt;
Ce droit permet la [[Gestion-des-formations|gestion des formations]].&lt;br /&gt;
&lt;br /&gt;
==Comptes==&lt;br /&gt;
&lt;br /&gt;
===Gestion des comptes===&lt;br /&gt;
Couplé à d'autres droits, permet de créer et modifier les intitulés des comptes (boutiques, espèces, etc.) ainsi que d'accéder à la comptabilité.&lt;br /&gt;
&lt;br /&gt;
Permet lors de la [[Gestion-de-la-comptabilité-côté-utilisateur#Extrait-de-compte|visualisation des écritures]] d'un compte :&lt;br /&gt;
*de pouvoir consulter les écritures des comptes affectés&lt;br /&gt;
*[[Gestion-de-la-comptabilité-côté-utilisateur#Consulter-une-facture-client-ou-un-reçu-d'encaissement|de pouvoir consulter une facture client ou un reçu]]&lt;br /&gt;
*de pouvoir [[Utilisation-de-la-comptabilité#Contrepasser-une-écriture|contrepasser les écritures]]&lt;br /&gt;
*de pouvoir [[Utilisation-de-la-comptabilité#Lettrer-des-écritures-comptables|lettrer les écritures]]&lt;br /&gt;
&lt;br /&gt;
Permet [[Utilisation-de-la-comptabilité#Importer-un-relevé-bancaire|d'importer des relevés bancaires]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ce droit inclut les droits '''Gestion des types d'encaissements''' et '''Voir les comptes'''.&lt;br /&gt;
&lt;br /&gt;
===Voir les comptes===&lt;br /&gt;
[[Gestion-de-la-comptabilité-côté-utilisateur#Consulter-son-compte-ou-celui-d'un-tiers|Permet de voir tous les comptes]], de [[Gestion-de-la-comptabilité-côté-utilisateur#Extrait-de-compte|visualiser la liste des mouvements]] et de [[Gestion-de-la-comptabilité-côté-utilisateur#Consulter-une-facture-client-ou-un-reçu-d'encaissement|consulter les factures clients et les reçus]].&lt;br /&gt;
&lt;br /&gt;
Couplé au droit [[#Saisir-les-encaissements-pour-les-tiers|Saisir les encaissements pour les tiers]], il permet de saisir un encaissement sur tous comptes. Ce droit inclut les privilèges du droit [[#Voir-les-comptes-utilisateurs|Voir les comptes utilisateurs]].&lt;br /&gt;
&lt;br /&gt;
===Voir les comptes utilisateurs===&lt;br /&gt;
[[Gestion-de-la-comptabilité-côté-utilisateur#Consulter-son-compte-ou-celui-d'un-tiers|Permet de voir tous les comptes utilisateurs]] et de [[Gestion-de-la-comptabilité-côté-utilisateur#Consulter-une-facture-client-ou-un-reçu-d'encaissement|consulter les factures clients et les reçus]].&lt;br /&gt;
&lt;br /&gt;
Couplé au droit [[#Saisir-les-encaissements-pour-les-tiers|Saisir les encaissements pour les tiers]], il permet de saisir un encaissement sur les comptes utilisateurs.&lt;br /&gt;
&lt;br /&gt;
===Gestion des comptabilités===&lt;br /&gt;
&lt;br /&gt;
permet la gestion des comptabilités&lt;br /&gt;
&lt;br /&gt;
===Gestion des types d'encaissements===&lt;br /&gt;
&lt;br /&gt;
permet la gestion des types d'encaissements.&lt;br /&gt;
&lt;br /&gt;
===Encaisser ses paiements===&lt;br /&gt;
&lt;br /&gt;
Permet à l'utilisateur de [[FAQ-comptabilité#Comment-autoriser-un-profil-utilisateur-à-saisir-des-encaissements-pour-lui-même-?|saisir ses propres paiements]], de les modifier ou de les supprimer tant qu'ils n'ont pas été validés. L'utilisateur ne peut pas saisir les types d'encaissements qui sont ''Accessible uniquement aux personnes autorisées à saisir pour les tiers''.&lt;br /&gt;
&lt;br /&gt;
===Saisir les encaissements pour les tiers===&lt;br /&gt;
&lt;br /&gt;
Permet à l'utilisateur de saisir, modifier ou supprimer, tant qu'ils n'ont pas été validés, les encaissements d'autres utilisateurs ainsi que les encaissements devant être affectés sur des [[Configuration de la comptabilité#Créer_un_compte_comptable|comptes comptables clients autorisés à recevoir de l'argent]].&lt;br /&gt;
&lt;br /&gt;
===Modifier la date d'un encaissement, d'un flux ou d'un transfert===&lt;br /&gt;
&lt;br /&gt;
autorise la modification de la date d'un encaissement, d'un flux ou d'un transfert s'il peut être modifié&lt;br /&gt;
&lt;br /&gt;
===Valider les encaissements===&lt;br /&gt;
&lt;br /&gt;
pointage des paiements saisis par les pilotes par exemple (Modification ultérieure de cette saisie impossible, en cas de problème il faudra alors faire l'opération inverse). Permet également la suppression d'encaissement.&lt;br /&gt;
&lt;br /&gt;
===Recevoir de l'argent===&lt;br /&gt;
&lt;br /&gt;
Permet à un utilisateur d'être sur la liste des paiements remis. Voir la [[Configuration-de-la-comptabilité#Types-d'encaissements|configuration de la ventilation des types d'encaissements]].&lt;br /&gt;
&lt;br /&gt;
===Transfert de son compte===&lt;br /&gt;
Permet le transfert de compte à compte depuis la page '''Planning &amp;gt; Comptes &amp;gt; Actions &amp;gt; Transférer'''.&lt;br /&gt;
&lt;br /&gt;
Les transferts effectués avec ce seul droit (sans le droit [[#Transfert-de-son-compte-sans-validation|Transfert de son compte sans validation]]) depuis cette page sont validés automatiquement.&lt;br /&gt;
&lt;br /&gt;
===Transfert de son compte sans validation===&lt;br /&gt;
Permet lors d'un transfert de compte à compte, que les flux générés ne soient pas automatiquement validés. Ce droit n'a d'effet que si le droit [[#Transfert-de-son-compte|Transfert de son compte]] est affecté au profil.&lt;br /&gt;
&lt;br /&gt;
'''Conseil OpenFlyers :''' Ce droit a été créé à la demande de clients OpenFlyers. Néanmoins, nous en déconseillons son usage. En effet, avec ce droit, un utilisateur qui &amp;quot;donne&amp;quot; de l'argent à un autre utilisateur peut ensuite reprendre sa donation. Or comme le dit l'expression : &amp;quot;[https://fr.wiktionary.org/wiki/donner_c%E2%80%99est_donner,_reprendre_c%E2%80%99est_voler Donner c'est donner, reprendre c'est voler]&amp;quot;. L'attribution du seul droit [[#Transfert-de-son-compte|Transfert de son compte]] permet un comportement conforme aux fonctionnalités présentes sur les applications bancaires, à savoir que lorsqu'on effectue un virement ce virement est définitif. Si un utilisateur se trompe dans son virement, alors il faut qu'il demande soit à la personne à qui il a donné de lui rendre le trop-perçu, soit à un gestionnaire de la structure pour qu'elle saisisse une écriture corrective. L'intérêt de procéder ainsi est qu'on conserve visuellement et directement sur les comptes la trace des opérations effectuées.&lt;br /&gt;
&lt;br /&gt;
===Saisir tout flux===&lt;br /&gt;
Permet de :&lt;br /&gt;
*[[Utilisation-de-la-comptabilité#Saisir-un-flux|saisir des flux]] depuis '''Gestion &amp;gt; Comptes &amp;gt; Flux &amp;gt; Saisir'''&lt;br /&gt;
*de modifier/supprimer des flux non validés&lt;br /&gt;
*de consulter la liste des flux depuis '''Gestion &amp;gt; Comptes &amp;gt; Flux &amp;gt; Valider'''&lt;br /&gt;
*de [[Gestion-de-la-comptabilité-côté-utilisateur#Extrait-de-compte|visualiser la liste des mouvements]]&lt;br /&gt;
*d'[[Utilisation-de-la-comptabilité#Importer-un-relevé-bancaire|importer des relevés bancaires]]&lt;br /&gt;
&lt;br /&gt;
===Valider tout flux===&lt;br /&gt;
Permet de valider les flux de la page '''Gestion &amp;gt; Comptes &amp;gt; Flux &amp;gt; Valider'''.&lt;br /&gt;
&lt;br /&gt;
Ce droit n'a effet que si le droit [[#Saisir-tout-flux|Saisir tout flux]] est affecté au profil.&lt;br /&gt;
&lt;br /&gt;
===Paramétrage de la facturation===&lt;br /&gt;
Permet de gérer les règles de [[Facturation-des-clients#Facturation-des-activités|facturation des activités]] et de [[Facturation-des-clients#Facturation-périodique|facturation périodique]].&lt;br /&gt;
&lt;br /&gt;
===Saisie des valeurs de facturation===&lt;br /&gt;
&lt;br /&gt;
Permet de gérer les variables et leurs valeurs destinés aux règles de facturation&lt;br /&gt;
&lt;br /&gt;
===Compte sur lequel un utilisateur peut agir===&lt;br /&gt;
&lt;br /&gt;
Permet de définir sur quel compte utilisateur un encaissement ou un transfert peut être réalisé par la personne connectée. Attention : ce droit est pour l'utilisateur connecté et non pas pour l'utilisateur concerné par l'encaissement ou le transfert.&lt;br /&gt;
&lt;br /&gt;
===Surpasser la limitation du solde du compte===&lt;br /&gt;
&lt;br /&gt;
Permet à un utilisateur disposant de ce droit dans l'un de ses profils de ne pas avoir de [[Connexion#Restriction_d'accès|restriction d'accès]], de saisie de réservation ou de saisie de vol lorsque [[Configuration de la comptabilité#Restriction_d'accès_en_cas_de_solde_insuffisant|une restriction sur les soldes]] est en place. Il aura juste une alerte à la connexion. Ce droit ne permet pas à l'utilisateur concerné X de pouvoir surpasser les restrictions d'un autre utilisateur Y en effectuant par exemple une réservation en son nom alors que Y n'a ni le droit de surpasser ni le solde suffisant.&lt;br /&gt;
&lt;br /&gt;
===Surpasser le seuil de [[Gestion-de-la-comptabilité-côté-utilisateur#Transférer-de-l'argent|transfert de compte]]===&lt;br /&gt;
&lt;br /&gt;
Permet à un utilisateur disposant de ce droit dans l'un de ses profils de ne pas être bloqué lorsque une [[Configuration-de-la-comptabilité#Paramétrage-général-des-comptabilités|restriction sur les soldes]] est en place et qu'il ne dispose pas d'un solde suffisant.&lt;br /&gt;
&lt;br /&gt;
==Ventes==&lt;br /&gt;
&lt;br /&gt;
===Gestion globale des ventes===&lt;br /&gt;
&lt;br /&gt;
Permet de gérer les produits, la facturation des produits, les stocks et [[Paramétrage-des-validités#Validité-à-vendre|validités à vendre]]. Permet également de modifier/supprimer des achats de produit.&lt;br /&gt;
&lt;br /&gt;
===Achat ventes libres===&lt;br /&gt;
&lt;br /&gt;
Autorise à acheter tous les produits qui sont en vente libre. Permet également de modifier/supprimer des achats de produit.&lt;br /&gt;
&lt;br /&gt;
===Acheter pour les tiers===&lt;br /&gt;
Autorise à effectuer/modifier/supprimer des achats de produit pour un tiers.&lt;br /&gt;
*Couplé au droit [[#Gestion-des-utilisateurs|Gestion des utilisateurs]], il permet de gérer les [[Paramétrage-des-validités#Validité-à-vendre|validités à vendre]] d'un tiers.&lt;br /&gt;
*Couplé au droit [[Gestion-des-profils#Vente-de-produit-sans-tarif|Vente de produit sans tarif]], il permet de vendre des [[Gestion-des-produits-et-des-ventes#Configuration-d'un-produit-non-stocké-sans-tarif-défini|produits sans tarif]].&lt;br /&gt;
&lt;br /&gt;
===Vente de produit sans tarif===&lt;br /&gt;
Autorise à rendre disponible et à acheter des produits sans tarif. Nécessite le droit [[#Acheter-pour-les-tiers|Acheter pour les tiers]].&lt;br /&gt;
&lt;br /&gt;
===Débrayage des ventes de validités===&lt;br /&gt;
&lt;br /&gt;
Autorise à ajouter et modifier la date d'expiration d'une [[Validités#Validité-à-vendre|validité à vendre]] sans débiter le compte.&lt;br /&gt;
&lt;br /&gt;
==Achats==&lt;br /&gt;
&lt;br /&gt;
===Gestion des achats===&lt;br /&gt;
Permet la gestion des factures fournisseurs, à en créer, modifier et supprimer.&lt;br /&gt;
&lt;br /&gt;
==Admin==&lt;br /&gt;
===Gestion du paramétrage===&lt;br /&gt;
Ce droit est nécessaire pour accéder aux pages permettant de [[Paramétrage|paramétrer la plateforme]] et fait apparaitre le menu '''Structure''' avec les items :&lt;br /&gt;
*[[Données#Accéder-au-tableau-de-conservation-des-données|'''Admin &amp;gt; Structure &amp;gt; Données &amp;gt; Conservation des données''']]&lt;br /&gt;
*'''Admin &amp;gt; Structure &amp;gt; Structure &amp;gt; Canaux de communications'''&lt;br /&gt;
*[[Configuration#Admin &amp;gt; Structure &amp;gt; Structure &amp;gt; Paramétrage|'''Admin &amp;gt; Structure &amp;gt; Structure &amp;gt; Paramétrage''']]&lt;br /&gt;
*[[Configuration#Admin-&amp;gt;-Structure-&amp;gt;-Structure-&amp;gt;-Coordonnées|'''Admin &amp;gt; Structure &amp;gt; Structure &amp;gt; Coordonnées''']]&lt;br /&gt;
*'''Admin &amp;gt; Structure &amp;gt; Variables &amp;gt; Définition'''&lt;br /&gt;
*'''Admin &amp;gt; Structure &amp;gt; Variables &amp;gt; Actualisation'''&lt;br /&gt;
*[[Configuration#Structure-&amp;gt;-Champs-métiers|'''Admin &amp;gt; Structure &amp;gt; Variables &amp;gt; Champs métiers''']]&lt;br /&gt;
*[[Configuration#Structure-&amp;gt;-Export-SQL|'''Admin &amp;gt; Structure &amp;gt; Export SQL &amp;gt; Complet''']]&lt;br /&gt;
*[[Utilisation-de-la-comptabilité#Importer-son-modèle-de-facture|'''Admin &amp;gt; Structure &amp;gt; Imports &amp;gt; Templates ODT''']]&lt;br /&gt;
&lt;br /&gt;
Ce droit fait également apparaitre des items utiles au paramétrage mais présents dans d'autres menus :&lt;br /&gt;
*Couplé au droit [[#Gestion-des-utilisateurs|Gestion des utilisateurs]], dans le menu '''Admin &amp;gt; Utilisateurs''' :&lt;br /&gt;
**[[Champs-métiers|'''Admin &amp;gt; Utilisateurs &amp;gt; Champs métiers''']]&lt;br /&gt;
**'''Admin &amp;gt; Utilisateurs &amp;gt; Statuts'''&lt;br /&gt;
*[[Gestion-des-types-d'activités|'''Admin &amp;gt; Types d'activités &amp;gt; Actifs''']]&lt;br /&gt;
*[[Champs-métiers|'''Admin &amp;gt; Types d'activités &amp;gt; Champs métiers''']]&lt;br /&gt;
*[[Champs-métiers|'''Ventes &amp;gt; Champs métiers &amp;gt; Champs métiers''']]&lt;br /&gt;
&lt;br /&gt;
===Gestion des valeurs===&lt;br /&gt;
&lt;br /&gt;
===Gestion des profils===&lt;br /&gt;
permet de créer et modifier les profils. Attention, laisser cette autorisation à au moins un profil !&lt;br /&gt;
&lt;br /&gt;
===Gestion des utilisateurs===&lt;br /&gt;
&lt;br /&gt;
Permet de modifier les caractéristiques, infos et photos des utilisateurs, les désactiver et gérer leurs validités qui ne correspondent pas à des [[Paramétrage-des-validités#Validité-à-vendre|validités à vendre]]. Couplé au droit [[#Acheter-pour-les-tiers|Acheter pour les tiers]], il permet de gérer les [[Paramétrage-des-validités#Validité-à-vendre|validités qui sont à vendre]].&lt;br /&gt;
&lt;br /&gt;
===Gestion des ressources===&lt;br /&gt;
Permet la gestion complète des types de ressources et des ressources (créer/supprimer/modifier/associer des validités). Autorise également la gestion de navigabilité des ressources aéronefs et la gestion des statuts.&lt;br /&gt;
&lt;br /&gt;
Permet d'accéder à [[Gestion-des-documents|la liste des documents]] qui sont associés aux ressources et leur gestion (Ajouter, modifier, supprimer). Permet aussi de gérer la liste des catégories de ces documents.&lt;br /&gt;
&lt;br /&gt;
===Gestion des rapports===&lt;br /&gt;
Fait apparaître le menu '''[[Gestion-des-rapports|Gestion &amp;gt; Rapports]]''' avec les items :&lt;br /&gt;
* '''Gestion &amp;gt; Rapports &amp;gt; Rapports personnalisés &amp;gt; Champs métiers'''&lt;br /&gt;
* '''[[Gestion-des-rapports#Configurer-les-rapports-visibles-pour-les-utilisateurs|Gestion &amp;gt; Rapports &amp;gt; Rapports personnalisés &amp;gt; Créer/Modifier]]'''&lt;br /&gt;
* '''[[Gestion-des-rapports#Configurer-les-rapports-visibles-pour-les-utilisateurs|Gestion &amp;gt; Rapports &amp;gt; Rapports personnalisés &amp;gt; Visualiser]]'''&lt;br /&gt;
* '''Gestion &amp;gt; Rapports &amp;gt; Rapports spécifiques &amp;gt; Activités et coûts'''&lt;br /&gt;
* '''[[Gestion-des-rapports#Configurer-les-rapports-visibles-pour-les-utilisateurs|Gestion &amp;gt; Rapports &amp;gt; Bibliothèque]]'''&lt;br /&gt;
&lt;br /&gt;
Fait apparaître la [[Gestion-des-rapports#Case-à-cocher-Mémoriser-ce-choix|case à cocher '''Mémoriser ce choix''']].&lt;br /&gt;
&lt;br /&gt;
===Voir tous les rapports===&lt;br /&gt;
Fait apparaître le menu '''Rapports''' avec les items :&lt;br /&gt;
* '''[[Gestion-des-rapports#Configurer-les-rapports-visibles-pour-les-utilisateurs|Rapports personnalisés &amp;gt; Visualiser]]'''&lt;br /&gt;
* '''Rapports spécifiques &amp;gt; Vols et coûts'''&lt;br /&gt;
&lt;br /&gt;
Cela permet de consulter l'intégralité des rapports, y compris les favoris.&lt;br /&gt;
&lt;br /&gt;
Fait apparaître la [[Gestion-des-rapports#Case-à-cocher-Mémoriser-ce-choix|case à cocher '''Mémoriser ce choix''']].&lt;br /&gt;
&lt;br /&gt;
===Gestion des logs===&lt;br /&gt;
Fait apparaître le menu '''Admin &amp;gt; Logs''' avec les items :&lt;br /&gt;
*'''Admin &amp;gt; Logs &amp;gt; Actions effectuées'''&lt;br /&gt;
*'''Admin &amp;gt; Logs &amp;gt; Adresses IP bloquées'''&lt;br /&gt;
*'''Admin &amp;gt; Logs &amp;gt; Historique d'une réservation'''&lt;br /&gt;
*'''Admin &amp;gt; Logs &amp;gt; Identifiants bloqués'''&lt;br /&gt;
*'''Admin &amp;gt; Logs &amp;gt; Requête utilisateur en attente'''&lt;br /&gt;
&lt;br /&gt;
===Envoyer et suivre les e-mails===&lt;br /&gt;
Permet d'accéder à la page [[Mailing|Mailing]] et de [[Suivi-des-emails|suivre les emails]].&lt;br /&gt;
&lt;br /&gt;
===Accès aux tableurs===&lt;br /&gt;
Permet d'accéder aux fichiers [[Tableurs|tableurs]] depuis le menu.&lt;br /&gt;
&lt;br /&gt;
===Gestion des communications===&lt;br /&gt;
Permet de gérer les flux d'informations et leurs canaux.&lt;br /&gt;
&lt;br /&gt;
=Profils Plus=&lt;br /&gt;
*'''Admin &amp;gt; Utilisateurs &amp;gt; Profils plus'''&lt;br /&gt;
&lt;br /&gt;
==Ajouter un profil depuis Profils plus==&lt;br /&gt;
*Cliquer sur une cellule contenant le caractère '''+'''&lt;br /&gt;
*remplissez la cellule puis appuyer sur la touche &amp;quot;Entrée&amp;quot;&lt;br /&gt;
*pour valider cliquer sur la disquette à gauche dans la colonne &amp;quot;Actions&amp;quot;&lt;br /&gt;
*le nouveau profil est placé à la fin du tableau&lt;br /&gt;
&lt;br /&gt;
==Modifier un profil depuis Profils plus==&lt;br /&gt;
*Cliquer sur une cellule du profil à modifier&lt;br /&gt;
*remplissez la cellule puis appuyer sur la touche &amp;quot;Entrée&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Colonnes du tableau Profils Plus==&lt;br /&gt;
===Nom (du profil)===&lt;br /&gt;
Nom du profil&lt;br /&gt;
&lt;br /&gt;
===Type de compte requis===&lt;br /&gt;
Permet de définir les comptes utilisateurs appartenant aux types sélectionnés qui seront créés pour les nouveaux utilisateurs ou ajoutés aux utilisateurs existants à qui on attribuera ce profil&lt;br /&gt;
&lt;br /&gt;
===Champ métier visible par le profil sur le formulaire utilisateur ou sur le planning===&lt;br /&gt;
Permet d'afficher ou de cacher les [[Champs-métiers|champs métiers]] des formulaires présents dans :&lt;br /&gt;
*'''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
*'''Gestion &amp;gt; Utilisateurs &amp;gt; Utilisateurs &amp;gt; Actifs'''&lt;br /&gt;
*'''Planning &amp;gt; Planning &amp;gt; Réserver'''&lt;br /&gt;
&lt;br /&gt;
===Type de validité que l'utilisateur peut gérer pour lui-même===&lt;br /&gt;
Permet de sélectionner les types de validités qu'un utilisateur de ce profil peut [[Validités#Consulter-et-gérer-ses-validités-ou-celles-d'un-tiers|ajouter/acheter/mettre/supprimer]] (ex: Licence fédérale, Visite Médicale, Autres licences) pour lui-même. Les validités d'un utilisateur sont accessibles depuis '''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Validités'''.&lt;br /&gt;
&lt;br /&gt;
[[Paramétrage-des-validités#Ajouter-un-type-de-validités|Lors de l'ajout d'un type de validité, celui-ci est automatiquement affecté aux profils]].&lt;br /&gt;
&lt;br /&gt;
===Types de validités que l'utilisateur peut gérer et certifier===&lt;br /&gt;
Permet de sélectionner les types de validités qu'un utilisateur de ce profil peut gérer et certifier.&lt;br /&gt;
&lt;br /&gt;
Tous les utilisateurs détenant un profil pouvant certifier un type de validité coché recevront un [[Envoi-des-emails#E-mail-de-demande-de-certification-de-validité|e-mail]] lorsqu'une validité d'un des types choisis sera ajoutée par un utilisateur et [[Validités#Validités-en-attente-de-certification|en attente de certification]].&lt;br /&gt;
&lt;br /&gt;
===Contrats non requis===&lt;br /&gt;
Voir la définition de [[Paramétrage-des-validités#Validité-contrat|validité-contrat]].&lt;br /&gt;
&lt;br /&gt;
Permet de [[Gestion-des-profils#Modifier-un-profil-depuis-Profils-plus|définir]] les [[Paramétrage-des-validités#Validité-contrat|validités-contrats]] qui ne sont pas requises pour certains profils.&lt;br /&gt;
&lt;br /&gt;
Les utilisateurs ne disposant que de profils exemptés, ne se verront pas demandés la signature des validités-contrats à la connexion. Tous les autres utilisateurs doivent signer chacun des contrats s'ils disposent d'au moins un profil non-exempté ou si la validité-contrat est requise pour tous les profils.&lt;br /&gt;
&lt;br /&gt;
La signature des validités-contrats, se fait juste après l'identification à la connexion. Le formulaire apparait tant qu'il reste au moins un contrat non-signé. L'utilisateur ne peut passer outre ce processus.&lt;br /&gt;
&lt;br /&gt;
===Attribution de place===&lt;br /&gt;
Permet d'attribuer les places auxquelles sont autorisées les utilisateurs de ce profil. Cela impacte sur les listes des utilisateurs que l'on trouve à la saisie d'une réservation ou d'un vol.&lt;br /&gt;
&lt;br /&gt;
Ces listes sont accessibles depuis '''Planning &amp;gt; Planning &amp;gt; Réserver''' et '''Planning &amp;gt; Activités &amp;gt; Saisir une activités'''.&lt;br /&gt;
&lt;br /&gt;
La page '''Admin &amp;gt; Type de ressource &amp;gt; Places''' permet de gérer les places d'un type de ressource. Elle permet également de définir qui a le droit d'être sur telle place en cas de restriction de profil.&lt;br /&gt;
&lt;br /&gt;
===Profils visibles===&lt;br /&gt;
Dans les pages '''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle''', '''Gestion &amp;gt; Utilisateurs &amp;gt; Actifs''' et '''Admin &amp;gt; Utilisateurs &amp;gt; Paramètres par défaut''', on peut sélectionner les utilisateurs auxquels on souhaite voir leur planning.&lt;br /&gt;
&lt;br /&gt;
La liste des utilisateurs affichés sont ceux possédant un profil ayant les droits [[#Planning-personnel|Planning personnel]] et [[#Planning-individuel-visible-pour-les-autres|Planning individuel visible pour les autres]]. La colonne '''Profils visibles''' permet de restreindre la liste de ces utilisateurs pour ne la limiter qu'aux utilisateurs possédant les profils sélectionnés.&lt;br /&gt;
&lt;br /&gt;
'''Attention :''' Il faut attribuer à un profil au moins une place de 1ère rang (numéro de place 0).&lt;br /&gt;
&lt;br /&gt;
===Types de ressources visibles===&lt;br /&gt;
Dans les pages '''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle''', '''Gestion &amp;gt; Utilisateurs &amp;gt; Actifs''' et '''Admin &amp;gt; Utilisateurs &amp;gt; Paramètres par défaut''', on peut sélectionner les ressources dont on souhaite voir le [[Utilisation-du-planning-de-réservation|planning]] ou les rendre disponibles dans les formulaires de saisie de réservation et d'activité.&lt;br /&gt;
&lt;br /&gt;
La colonne '''Types de ressources visibles''' permet de restreindre la liste de ces ressources pour ne la limiter qu'aux ressources appartenant aux types de ressources sélectionnés.&lt;br /&gt;
&lt;br /&gt;
===Comptabilités visibles===&lt;br /&gt;
Permet de sélectionner les comptabilités qui sont visibles pour un profil. De plus, les types de compte et les comptes n'étant pas d'une comptabilité sélectionnée ne seront pas visibles.&lt;br /&gt;
&lt;br /&gt;
===Alerté par e-mail pour le renouvellement des validités de tous les utilisateurs===&lt;br /&gt;
Ce droit permet de suivre le renouvellement des validités par les utilisateurs en étant alerté par e-mail à chaque fois qu'un utilisateur renouvelle une validité sélectionnée dans la liste de la cellule '''Alerté par e-mail pour le renouvellement des validités de tous les utilisateurs'''. Attention : la mise en place de ce droit peut provoquer la réception de nombreux e-mails.&lt;br /&gt;
&lt;br /&gt;
=Utilisation=&lt;br /&gt;
==[[Connexion#Choix_du_profil|Choix du profil à la connexion]]==&lt;br /&gt;
&lt;br /&gt;
==Ajouter un profil==&lt;br /&gt;
&lt;br /&gt;
Depuis l'interface dynamique :&lt;br /&gt;
*Cliquer sur l'icône de menu correspondant à la gestion des profils&lt;br /&gt;
*[[Tableaux#Ajout-de-ligne|Ajouter une ligne]]&lt;br /&gt;
*[[Tableaux#Édition-des-données|Compléter les cellules]]&lt;br /&gt;
*L'ajout est [[Tableaux#Enregistrement-d'une-ligne|enregistré]] si les cellules suivantes sont correctement remplies :&lt;br /&gt;
**'''Nom du profil''' : la cellule doit être remplie et le nom ne pas avoir déjà été utilisé comme nom de profil.&lt;br /&gt;
&lt;br /&gt;
Depuis l'interface légère :&lt;br /&gt;
*Aller sur '''Admin &amp;gt; Utilisateurs &amp;gt; Profils'''&lt;br /&gt;
*En-dessous du tableau listant les profils, cliquer sur le bouton '''AJOUTER UN PROFIL'''&lt;br /&gt;
*Renseigner les droits pour chaque onglet&lt;br /&gt;
*Aller sur '''Admin &amp;gt; Utilisateurs &amp;gt; Profils plus'''&lt;br /&gt;
*Renseigner les colonnes pour la ligne du profil nouvellement créé&lt;br /&gt;
&lt;br /&gt;
===Ajouter un profil qui surpasse la restriction en cas de solde insuffisant===&lt;br /&gt;
*Procéder à l'[[Tableaux#Ajout_de_ligne|ajout de ligne dans un tableau]].&lt;br /&gt;
*Saisir par exemple comme nom '''Non restreignable'''.&lt;br /&gt;
*Toujours dans '''Admin &amp;gt; Utilisateurs &amp;gt; Profils''', onglet '''Généralités''', cocher pour ce profil le droit [[Gestion des profils#Généralités|Profil non sélectionnable par l'utilisateur]].&lt;br /&gt;
*Dans l'onglet '''Gestion des comptes''', sélectionner le droit [[#Surpasser-la-limitation-du-solde-du-compte|Surpasser la limitation du solde du compte]] pour le profil concerné&lt;br /&gt;
Il suffit ensuite de rajouter ce profil aux utilisateurs concernés.&lt;br /&gt;
&lt;br /&gt;
=Créer un profil empêchant tout surpassement=&lt;br /&gt;
Il peut être nécessaire d'empêcher un utilisateur de pouvoir réserver ou saisir une activité même en recourant à l'aide d'un tiers qui disposerait de droits permettant de surpasser des restrictions, que cela soit sur des comptes ou sur des validités.&lt;br /&gt;
&lt;br /&gt;
Cela peut être le cas, par exemple, pour la détention d'une validité ''Cotisation'' périmée ou lorsque le solde du compte utilisateur est insuffisant (cf. [[Configuration-de-la-comptabilité#Restriction-d'accès-en-cas-de-solde-insuffisant|Restriction d'accès en cas de solde insuffisant]]).&lt;br /&gt;
&lt;br /&gt;
Pour mettre en place une telle restriction, il faut :&lt;br /&gt;
*[[Gestion-des-profils#Ajouter-un-profil|Ajouter un profil]] en lui attribuant l'ensemble des droits (ne pas oublier la page '''Admin &amp;gt; Utilisateurs &amp;gt; Profils plus'''&lt;br /&gt;
*[[Gestion-des-profils#Modifier-un-profil|Modifier le profil]] nouvellement créé&lt;br /&gt;
**Si l'utilisateur ne doit pas pouvoir ouvrir un vol : dans l'onglet [[Gestion-des-profils#Activités|Activités]], décocher le droit [[Gestion-des-profils#Etre-sur-une-nouvelle-ouverture-d'activité|Etre sur une nouvelle ouverture d'activité]]&lt;br /&gt;
**Si l'utilisateur ne doit pas pouvoir être sur une réservation : dans l'onglet [[Gestion-des-profils#Réservation|Réservation]], décocher les droits [[Gestion-des-profils#Etre-sur-une-nouvelle-réservation|Etre sur une nouvelle réservation]], [[Gestion-des-profils#Réservation-solo|Réservation solo]] et [[Gestion-des-profils#Réservation-avec-un-instructeur|Réservation avec un instructeur]]&lt;br /&gt;
&lt;br /&gt;
==Droits particuliers==&lt;br /&gt;
*'''GÉNÉRALITÉS / Profil non sélectionnable par l'utilisateur :''' ce droit n'est applicable que si les [[Gestion des utilisateurs|utilisateurs disposant du profil concerné]] possèdent au moins un autre [[Connexion#Sélection_du_profil|profil sélectionnable à la connexion]].&lt;br /&gt;
*'''GÉNÉRALITÉS ADMIN / Gestion des profils :''' au moins un profil doit posséder ce droit.&lt;br /&gt;
&lt;br /&gt;
==Modifier un profil==&lt;br /&gt;
La modification des profils s'effectue selon les règles d'[[Utilisation des tableaux#Édition_des_données#|édition des données d'un tableau]].&lt;br /&gt;
&lt;br /&gt;
==Supprimer un profil==&lt;br /&gt;
*La suppression d'un profil est possible uniquement si les [[Gestion des utilisateurs|utilisateurs disposant de ce profil]] possèdent aussi au moins un autre profil.&lt;br /&gt;
*Procéder à la[[Tableaux#Suppression_de_ligne|suppression de ligne dans un tableau]].&lt;br /&gt;
&lt;br /&gt;
==Valeurs par défaut lors de la création d'un profil==&lt;br /&gt;
Lors de la création d'un profil, on affecte automatiquement par défaut :&lt;br /&gt;
* Tous les '''Profils visibles'''&lt;br /&gt;
* Tous les '''Types de ressources visibles'''&lt;br /&gt;
* Toutes les '''Comptabilités visibles'''&lt;br /&gt;
* Les '''Attribution de place''' correspondants à la première place de chaque type de ressource&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Gestion-des-produits-et-des-ventes&amp;diff=12890</id>
		<title>Gestion des produits et des ventes</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Gestion-des-produits-et-des-ventes&amp;diff=12890"/>
		<updated>2024-10-02T17:27:53Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
=Présentation=&lt;br /&gt;
Cette page décrit la '''gestion des produits et des ventes'''.&lt;br /&gt;
&lt;br /&gt;
Pour facturer des produits, il faut que [[Configuration-de-la-comptabilité#Paramétrage-général-de-la-gestion-des-comptes|la gestion des comptes soit activée]].&lt;br /&gt;
&lt;br /&gt;
Les écritures comptables générées par le moteur de facturation dépendent de la [[Gestion-des-écritures-comptables#Fusion-des-écritures-comptables|fusion des écritures]].&lt;br /&gt;
&lt;br /&gt;
Pour accéder à la gestion des produits (menu '''Admin &amp;gt; Ventes &amp;gt; Produits &amp;gt; Produits'''), il faut de l'un des droits suivants : [[Gestion-des-profils#Gestion-globale-des-ventes|gestion globale des ventes]], [[Gestion-des-profils#Gestion-des-comptes|gestion des comptes]].&lt;br /&gt;
&lt;br /&gt;
==[[Facturation-des-clients#Fonctionnement-et-nommage-des-variables-associées-aux-formules-de-facturation|Fonctionnement et nommage des variables associées aux formules de facturation]]==&lt;br /&gt;
&lt;br /&gt;
=Configuration=&lt;br /&gt;
* Les produits non stockés sans tarif ne sont disponibles à l'achat qu'avec le droit [[Gestion-des-profils#Vente-de-produit-sans-tarif|Vente de produit sans tarif]].&lt;br /&gt;
*Les produits en vente libre peuvent être achetés par les utilisateurs disposant du droit [[Gestion-des-profils#Achat-ventes-libres|Achat ventes libres]] ou être vendus par les utilisateurs avec le droit [[Gestion-des-profils#Acheter-pour-les-tiers|Acheter pour les tiers]].&lt;br /&gt;
*Les produits qui ne sont pas en vente libre ne peuvent être vendues qu'avec le droit [[Gestion-des-profils#Acheter-pour-les-tiers|Acheter pour les tiers]].&lt;br /&gt;
&lt;br /&gt;
Pour définir un produit comme étant en '''Vente libre''', il faut aller dans '''Admin &amp;gt; Ventes &amp;gt; Produits &amp;gt; Produits''' et cocher la marque correspondante dans la colonne '''Vente libre''' de la ligne du produit concerné.&lt;br /&gt;
&lt;br /&gt;
Voir les [[Formules de calcul#Tarification|formules de tarification]].&lt;br /&gt;
&lt;br /&gt;
Les paragraphes ci-dessous présentes plusieurs exemples de configuration de produit.&lt;br /&gt;
&lt;br /&gt;
==Mettre en place une règle de facturation générale pour les produits==&lt;br /&gt;
Nous recommandons fortement de mettre en place cette règle qui simplifie grandement par la suite l'ajout de nouveaux produits à vendre. Cette règle à vocation à s'appliquer tout le temps. Ensuite, on peut rajouter des [[Facturation des clients#Cascade_d'écritures_comptables|règles en cascade]] qui viendront modifier le comportement de cette première règle de tarification en modifiant par exemple le compte produit concerné.&lt;br /&gt;
&lt;br /&gt;
*'''Admin &amp;gt; Ventes &amp;gt; Facturation &amp;gt; Produits'''&lt;br /&gt;
*Cliquer sur le bouton '''AJOUTER UNE LIGNE DE FACTURATION'''&lt;br /&gt;
*Dans le champ '''Nom''', insérer ''Facturation générale des produits''&lt;br /&gt;
*Dans le champ '''Formule''', insérer ''%UNIT_PRICE_VALUE * %PRODUCT_QUANTITY''. Cette formule multiplie le tarif unitaire du produit défini dans '''Admin &amp;gt; Ventes &amp;gt; Produits &amp;gt; Produits''' avec la quantité commandée.&lt;br /&gt;
*Dans le champ '''Nom de variable associé à la formule''', insérer ''tarifGeneral''.&lt;br /&gt;
*Dans le champ '''Type de compte à débiter''' sélectionner ''Compte utilisateur''.&lt;br /&gt;
*Modifier le cas échéant, le champ '''Compte utilisateur à débiter'''.&lt;br /&gt;
*Dans le champ '''Type de compte à créditer''', sélectionner ''Compte Produit''.&lt;br /&gt;
*Dans le champ '''Compte Produit à créditer''', sélectionner ''Boutique''.&lt;br /&gt;
*Dans les champs '''produits internes''' et '''produits externes''', sélectionner '''tous'''.&lt;br /&gt;
*Cliquer sur le bouton '''Valider'''.&lt;br /&gt;
&lt;br /&gt;
==Rediriger vers un autre compte produit le produit d'une vente==&lt;br /&gt;
Avec la [[#Mettre-en-place-une-règle-de-facturation-générale-pour-les-produits|règle de facturation générale]] déjà en place, le produit de toute vente va dans le compte de produit ''boutique''. Si on souhaite une ventilation différente, il faut rediriger le produit de la vente ainsi :&lt;br /&gt;
&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Ventes &amp;gt; Facturation &amp;gt; Produits'''.&lt;br /&gt;
* Cliquer sur '''AJOUTER UNE LIGNE DE FACTURATION'''&lt;br /&gt;
* Remplir le formulaire :&lt;br /&gt;
** '''Nom''' : ''produit X''&lt;br /&gt;
** '''Formule''' : ''@tarifGeneral''&lt;br /&gt;
** '''Produits internes/Produits externes''' : Cocher le ou les noms du ou des produits concernés par cette redirection.&lt;br /&gt;
** '''Type de compte à créditer''' : Au choix. Normalement cela doit être un compte produit.&lt;br /&gt;
** '''Type de compte à débiter''' : ''Compte produit''&lt;br /&gt;
** '''Compte à produit à débiter''' : ''Boutique''&lt;br /&gt;
** Valider le formulaire&lt;br /&gt;
Ainsi la 1ère règle générale créditera le compte produit &amp;quot;Boutique&amp;quot; et la règle ci-dessus débitera du même montant ce compte produit &amp;quot;Boutique&amp;quot; pour créditer à la place un autre compte produit au choix.&lt;br /&gt;
&lt;br /&gt;
==Configuration d'un produit non-stocké avec tarif==&lt;br /&gt;
*Aller sur '''Admin &amp;gt; Ventes &amp;gt; Produits &amp;gt; Produits'''&lt;br /&gt;
Tout en bas du tableau, sur la dernière ligne vide, créer un produit :&lt;br /&gt;
*'''Nom''' : Carte&lt;br /&gt;
*'''Unité''' : ''Sans unité''&lt;br /&gt;
*Cocher '''Vente libre''' si vous souhaitez que les utilisateurs ayant le droit '''[[Gestion-des-profils#Achat-ventes-libres|Achat ventes libres]]''' puissent acheter ce produit là.&lt;br /&gt;
*'''Type de vente''' : ''Produit non stocké''&lt;br /&gt;
*'''Tarif associé''' : ''Nouveau tarif...''&lt;br /&gt;
*'''Historique des montants''' : laisser ''Nouveau couple...''&lt;br /&gt;
*'''Date d'entrée en vigueur du tarif''' : laisser la date proposée par défaut qui correspond à la date du début d'exercice comptable. En effet, chaque nouveau tarif doit avoir un prix qui couvre depuis le début de l'exercice en cours afin de ne pas avoir d'absence de tarif applicable.&lt;br /&gt;
*'''Montant du tarif''' : renseigner le montant applicable&lt;br /&gt;
*Cliquer sur le bouton '''Ajouter'''&lt;br /&gt;
&lt;br /&gt;
Avec la [[#Mettre-en-place-une-règle-de-facturation-générale-pour-les-produits|règle de facturation générale]] déjà en place, le produit de la vente d'une carte ira dans le compte de produit ''boutique''. Si on souhaite une ventilation différente, il faut [[#Rediriger-vers-un-autre-compte-produit-le-produit-d'une-vente|rediriger le produit de la vente]].&lt;br /&gt;
&lt;br /&gt;
==Configuration d'un produit non-stocké sans tarif défini==&lt;br /&gt;
Tout en bas du tableau, sur la dernière ligne vide, créer un produit :&lt;br /&gt;
*'''Nom''' : Carte&lt;br /&gt;
*'''Unité''' : ''Sans unité''&lt;br /&gt;
*Cocher '''Vente libre''' si vous souhaitez que les utilisateurs ayant le droit '''[[Gestion-des-profils#Achat-ventes-libres|Achat ventes libres]]''' puissent acheter ce produit là.&lt;br /&gt;
*'''Type de vente''' : ''Produit non stocké''&lt;br /&gt;
*'''Tarif associé''' : ''Aucun''&lt;br /&gt;
*Cliquer sur le bouton '''Ajouter'''&lt;br /&gt;
&lt;br /&gt;
Avec la [[#Mettre-en-place-une-règle-de-facturation-générale-pour-les-produits|règle de facturation générale]] déjà en place, le produit de la vente d'une carte ira dans le compte de produit ''boutique''. Si on souhaite une ventilation différente, il faut [[#Rediriger-vers-un-autre-compte-produit-le-produit-d'une-vente|rediriger le produit de la vente]].&lt;br /&gt;
&lt;br /&gt;
==[[Validités#Débrayer-la-vente-d'une-validité|Mettre à jour la date d'échéance d'une validité à vendre]]==&lt;br /&gt;
&lt;br /&gt;
==Mise en place de la TVA dans la facturation des produits==&lt;br /&gt;
Si vous gérez la TVA, alors il faut rajouter une ligne pour créer les mouvements liés à la TVA. On suppose qu'il existe déjà une [[#Mettre-en-place-une-règle-de-facturation-générale-pour-les-produits|ligne de facturation générale]].&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Ventes &amp;gt; Facturation &amp;gt; Produits'''.&lt;br /&gt;
*Cliquer sur le bouton '''AJOUTER UNE LIGNE DE FACTURATION'''&lt;br /&gt;
*Dans le champ '''Nom''', renseigner ''Taux TVA standard''&lt;br /&gt;
*Dans le champ formule, renseigner ''@standardPrice * $tvaFranceNormale / 100'' en supposant que la variable associée à la TVA se nomme ''$tvaFranceNormale''.&lt;br /&gt;
*Laisser le champ '''Produit''' sélectionné pour '''Tous'''.&lt;br /&gt;
*Dans le champ '''Type de compte à débiter''', sélectionner ''Compte utilisateur''.&lt;br /&gt;
*Modifier le cas échéant, le champ '''Compte utilisateur à débiter'''.&lt;br /&gt;
*Dans le champ '''Type de compte à créditer''', sélectionner ''Compte TVA''.&lt;br /&gt;
*Dans le champ '''Compte TVA à créditer''', sélectionner ''TVA collectée''.&lt;br /&gt;
*Cliquer sur le bouton '''Valider'''.&lt;br /&gt;
Remarque : dans le cas où l'on part d'un prix TTC, alors pour retrouver la TVA il faut appliquer la formule suivante :&lt;br /&gt;
''@standardPriceTTC * $tvaFranceNormale / (100 + $tvaFranceNormale)''&lt;br /&gt;
&lt;br /&gt;
=[[Utilisation-de-la-comptabilité#Mettre-à-jour-les-tarifs|Gestion des tarifs]]=&lt;br /&gt;
&lt;br /&gt;
=Utilisation=&lt;br /&gt;
&lt;br /&gt;
==Achat de produit non stocké==&lt;br /&gt;
Depuis la page du planning, se rendre sur la page '''Planning &amp;gt; Comptes &amp;gt; Actions &amp;gt; Acheter'''. Pour avoir une vue des produits sans tarif, s'assurer de posséder le droit [[Gestion-des-profils#Vente-de-produit-sans-tarif|Vente de produit sans tarif]].&lt;br /&gt;
&lt;br /&gt;
Pour l'achat d'un seul produit, se placer la ligne de celui-ci :&lt;br /&gt;
* '''Compte utilisateur''' : Champ vide par défaut et affiché si l'utilisateur à le droit [[Gestion-des-profils#Acheter-pour-les-tiers|Acheter pour les tiers]]. Entrer le début du nom, prénom ou identifiant d'un utilisateur pour voir apparaitre une liste proposant les choix possibles correspondants.&lt;br /&gt;
* '''Quantité''' : Saisir la valeur désirée&lt;br /&gt;
* '''Prix unitaire''' : Dans le cas d'un produit sans tarif, saisir la valeur désirée&lt;br /&gt;
* Cliquer sur l'icône qui représente un caddy avec un plus intitulée '''Ajouter au panier'''&lt;br /&gt;
&lt;br /&gt;
Pour l'achat de plusieurs produits :&lt;br /&gt;
* '''Compte utilisateur''' : Champ vide par défaut et affiché si l'utilisateur à le droit [[Gestion-des-profils#Acheter-pour-les-tiers|Acheter pour les tiers]]. Entrer le début du nom, prénom ou identifiant d'un utilisateur pour voir apparaitre une liste proposant les choix possibles correspondants. &lt;br /&gt;
* Pour chacun des produits :&lt;br /&gt;
** '''Quantité''' : Saisir la valeur désirée&lt;br /&gt;
** '''Prix unitaire''' : Dans le cas d'un produit sans tarif, saisir la valeur désirée&lt;br /&gt;
* Cliquer sur le bouton '''Tout ajouter au panier'''&lt;br /&gt;
&lt;br /&gt;
Après un achat, on est redirigé vers le panier. On peut retirer des produits du panier. On peut également en rajouter d'autres en cliquant sur le bouton '''Voir les produits en vente'''.&lt;br /&gt;
&lt;br /&gt;
Avec un utilisateur gestionnaire possédant le droit [[Gestion-des-profils#Acheter-pour-les-tiers|Acheter pour les tiers]] il est possible de vendre des produits depuis la page '''Gestion &amp;gt; Ventes &amp;gt; Vendre'''.&lt;br /&gt;
&lt;br /&gt;
Le droit [[Gestion-des-profils#Acheter-pour-les-tiers|Acheter pour les tiers]] n'inclut pas le droit de vendre des produits sans tarif, le droit [[Gestion-des-profils#Vente-de-produit-sans-tarif|Vente de produit sans tarif]] doit être activé activé, l'inverse est aussi vrai.&lt;br /&gt;
&lt;br /&gt;
==Achat de validité==&lt;br /&gt;
Les utilisateurs auront le droit d'&amp;quot;Acheter&amp;quot; leur cotisation si leur profil a le droit de '''Mises à jour des dates de péremption de ses validités'''. Sinon seul les profils avec '''Mise à jour de ses validités''' pourront le faire.&lt;br /&gt;
&lt;br /&gt;
[[File:Users_Profil_fr.jpg]]&lt;br /&gt;
&lt;br /&gt;
Dans '''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Validités''', au premier accès, il faut acheter la validité &amp;quot;Cotisation&amp;quot; :&lt;br /&gt;
* En bas du tableau, sélectionner dans la liste déroulante &amp;quot;Cotisation&amp;quot;. le bouton sur la gauche doit indiquer '''Acheter'''. Si le bouton est désactivé (grisé), c'est que le produit lié à la validité n'a pas l'option '''Ventes libre''' de coché.&lt;br /&gt;
* Cliquer sur '''Acheter'''. La validité doit apparaitre dans le tableau et la date limite de validité doit être au 31/12/2012&lt;br /&gt;
&lt;br /&gt;
[[File:Donnés_validité_fr.jpg]]&lt;br /&gt;
&lt;br /&gt;
Si la validité &amp;quot;Cotisation&amp;quot; existe déjà dans le tableau, il faut la renouveler (par exemple, la date actuelle est le 31/12/2011). Dans ce cas, dans la colonne Limite de validité, cliquer sur l'icône &amp;quot;Flèche circulaire&amp;quot; et la date de la validité doit passer au 31/12/2012&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L'action de renouvellement/achat de validité est irréversible. Par contre, on peut [[#Annuler_l'achat_d'une_validité|annuler comptablement l'achat d'une validité et modifier la validité pour l'utilisateur concerné]].&lt;br /&gt;
&lt;br /&gt;
==Annuler l'achat d'une validité==&lt;br /&gt;
L'achat d'une validité est irréversible pour un utilisateur : dès qu'il a choisi d'acheter une validité, cette opération est comptablement validée et l'utilisateur n'a pas la possibiltié de revenir en arrière. Cela permet de garantir que l'utilisateur ne va pas s'attribuer des privilèges liés à son achat de validité, effectuer ce qu'il souhaite et ensuite annuler cet achat.&lt;br /&gt;
&lt;br /&gt;
Si un gestionnaire souhaite annuler un tel achat, il faut alors effectuer 2 opérations :&lt;br /&gt;
*[[Utilisation-de-la-comptabilité#Annuler-l'effet-d'une-écriture-comptable|Annuler l'effet comptable]] de la vente de la validité en saisissant un flux opposé.&lt;br /&gt;
*[[Validités#Débrayer-la-vente-d'une-validité|Débrayer la vente de la validité]] afin de modifier la date d'échéance pour l'utilisateur concerné.&lt;br /&gt;
&lt;br /&gt;
==Annuler la vente d'un produit==&lt;br /&gt;
Si la vente du produit n'a pas été validée, alors il faut cliquer sur l'icône crayon correspondant à une ligne comptable de la vente du produit pour se retrouver dans le panier correspondant à cette vente. Ensuite, il faut éditer le panier soit en supprimant la ligne correspondant au produit soit vider complètement le panier.&lt;br /&gt;
&lt;br /&gt;
Si la vente du produit a été validée, alors il n'est plus possible de supprimer les écritures comptables correspondantes et il faut [[#Annuler-l'effet-d'une-écriture-comptable|annuler l'effet comptable]].&lt;br /&gt;
&lt;br /&gt;
==Validation d'un panier par un utilisateur==&lt;br /&gt;
*Pour finaliser les achats et les valider, cliquer sur le bouton '''Valider tous les achats'''.&lt;br /&gt;
Lors de la validation de plusieurs produits, ceux-ci sont [[Facturation-des-clients#Regrouper-les-ventes-par-client|regroupés en une seule facture]].&lt;br /&gt;
&lt;br /&gt;
Cette opération peut être effectuée plus tard en modifiant une entrée comptable générée par la vente du produit concerné. Dans ce cas, les produits restent dans le panier. On doit considérer qu'ils ne sont pas réellement vendus tant qu'ils ne sont pas validés.&lt;br /&gt;
&lt;br /&gt;
Cependant un gestionnaire a la possibilité de [[#Validation_des_produits_en_attente_dans_les_paniers_par_un_gestionnaire|valider massivement les produits présents dans les paniers]] et ainsi de valider à posteriori les achats. Ce mode de fonctionnement peut être utile dans un [[Bien débuter avec OpenFlyers#Workflow|workflow]] où seul un gestionnaire/responsable dispose du droit d'effectuer les achats et ne souhaitent pas valider à chaque achat pour ne pas perdre de temps mais reporter cette opération en fin de journée ou en fin de semaine par exemple.&lt;br /&gt;
&lt;br /&gt;
==Validation des produits en attente dans les paniers par un gestionnaire==&lt;br /&gt;
*Un gestionnaire peut valider tout ou partie des produits mis dans les paniers de chaque utilisateur :&lt;br /&gt;
*'''Gestion &amp;gt; Ventes &amp;gt; Valider les ventes'''&lt;br /&gt;
*Choisir la période de ventes souhaitée dans les champs '''A partir du''' et '''Jusqu'au'''&lt;br /&gt;
*Choisir l'utilisateur concerné dans le champ '''Compte utilisateur''' ou laisser ''Tous'' pour faire apparaitre les ventes de tous les utilisateurs&lt;br /&gt;
*Cliquer sur le bouton '''Valider'''&lt;br /&gt;
Un tableau liste les produits mis dans des paniers et en attente de validation&lt;br /&gt;
*Pointer les produits à valider&lt;br /&gt;
*Cliquer sur le bouton '''Pointer les entrées sélectionnées (cette action est irréversible)'''&lt;br /&gt;
&lt;br /&gt;
Lors de la validation, les ventes sont [[Facturation-des-clients#Regrouper-les-ventes-par-client|regroupées en une seule facture par client]].&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Gestion-de-la-comptabilit%C3%A9-c%C3%B4t%C3%A9-utilisateur&amp;diff=12889</id>
		<title>Gestion de la comptabilité côté utilisateur</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Gestion-de-la-comptabilit%C3%A9-c%C3%B4t%C3%A9-utilisateur&amp;diff=12889"/>
		<updated>2024-10-02T17:27:53Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter la '''gestion de la comptabilité côté utilisateur''' dans la [[Accueil|version 4 d'OpenFlyers]].&lt;br /&gt;
&lt;br /&gt;
=Alertes générées lors de [[Utilisation de la comptabilité#Saisie_d'écritures_comptables|saisie d'écritures comptables]]=&lt;br /&gt;
&lt;br /&gt;
==Les comptes n'ont pas la même comptabilité==&lt;br /&gt;
&lt;br /&gt;
Cette alerte apparait lors d'une [[Comptabilité#Comptabilités_multiples|comptabilité multiple]] : Le compte débité et le compte crédité doivent être issues de la même comptabilité.&lt;br /&gt;
&lt;br /&gt;
=Consulter son compte ou celui d'un tiers=&lt;br /&gt;
Pour consulter son propre compte :&lt;br /&gt;
*'''Planning &amp;gt; Comptes &amp;gt; Extrait de compte... &amp;gt; &amp;quot;le nom de son compte&amp;quot;''' ou depuis le raccourci présent en en-tête de chaque page (juste en dessous du menu).&lt;br /&gt;
&lt;br /&gt;
Pour consulter le compte d'un tiers, il faut disposer de [[Gestion des profils#Comptes|l'un de ces droits]] : [[Gestion-des-profils#Gestion-des-comptes|'''Gestion des comptes''']], [[Gestion-des-profils#Voir-les-comptes|'''Voir les comptes''']] ou [[Gestion-des-profils#Voir-les-comptes-utilisateurs|'''Voir les comptes utilisateurs''']].&lt;br /&gt;
*'''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Utilisateurs''' et cliquer sur la loupe du compte que l'on souhaite consulter.&lt;br /&gt;
&lt;br /&gt;
=Consulter une [[Écritures comptables#Facture-client|facture client]] ou un reçu d'encaissement=&lt;br /&gt;
&lt;br /&gt;
Pour consulter une facture client ou un reçu d'encaissement, il faut :&lt;br /&gt;
*Aller sur [[#Consulter-son-compte-ou-celui-d'un-tiers|le compte concerné]]&lt;br /&gt;
*Cibler l'écriture recherchée&lt;br /&gt;
*Colonne [[#Colonne-Numéro-de-pointage,-facture-ou-reçu|'''Numéro de pointage, facture ou reçu''']], cliquer sur l'icône correspondante de la facture ou du reçu&lt;br /&gt;
&lt;br /&gt;
=Créditer son compte utilisateur=&lt;br /&gt;
Un utilisateur, qui dispose du droit [[Gestion-des-profils#Encaisser-ses-paiements|Encaisser ses paiements]] ou du droit [[Gestion-des-profils#Saisir-les-encaissements-pour-les-tiers|Saisir les encaissements pour les tiers]], peut le créditer :&lt;br /&gt;
*Soit par '''Planning &amp;gt; Comptes &amp;gt; Actions &amp;gt; Approvisionner'''&lt;br /&gt;
*Soit par '''Gestion &amp;gt; Comptes &amp;gt; Encaissements &amp;gt; Saisir''' s'il dispose de droits de gestion&lt;br /&gt;
*Soit en affichant un extrait de son compte utilisateur et cliquer sur le bouton '''Approvisionner''' situé en bas à droite de l'affichage de son compte à droite de la ligne du solde de compte.&lt;br /&gt;
Si l'utilisateur arrive sur le formulaire de saisie d'encaissement depuis un extrait de compte utilisateur, alors le compte à créditer par défaut porte le nom de l'utilisateur du compte depuis où la personne a cliqué.&lt;br /&gt;
*Si l'utilisateur dispose du droit [[Gestion-des-profils#Saisir-les-encaissements-pour-les-tiers|Saisir les encaissements pour les tiers]], choisir dans le champ '''Encaissement de l'utilisateur''' le nom de l'utilisateur concerné&lt;br /&gt;
*Si l'utilisateur dispose de plusieurs comptes sur lesquels il peut effectuer son encaissement (défini par le droit [[Gestion-des-profils#Compte-sur-lequel-un-utilisateur-peut-agir|Compte sur lequel un utilisateur peut agir]]), choisir dans le champ '''Compte à créditer''' le nom du compte concerné&lt;br /&gt;
*Dans le champ '''Type de règlement''', sélectionner le type de règlement&lt;br /&gt;
*Si vous effectuez un paiement avec une remise à une personne physique, vous devez préciser le nom de cette personne dans le champ '''Personne qui reçoit'''&lt;br /&gt;
*Dans le champ, montant indiquer le montant de votre paiement.&lt;br /&gt;
*Cliquer sur le bouton '''Valider'''&lt;br /&gt;
Dans le cas où le type de paiement est un paiement par carte bancaire en ligne mis en place par votre structure, alors êtes redirigé sur le terminal de paiement électronique de la banque de votre structure. Il vous faut alors saisir les informations de votre carte bancaire. Il est possible que le terminal de paiement électronique supporte le &amp;quot;[[Wikipedia-fr:3-D_Secure|3-D Secure]]&amp;quot; qui implique un contrôle renforcé. Dans ce cas, c'est votre propre banque qui vous demandera des informations complémentaires pour confirmer que c'est bien vous qui êtes à l'origine de la demande de paiement par carte bancaire.&lt;br /&gt;
&lt;br /&gt;
Une fois le paiement validé, [[Envoi-des-emails#E-mail-de-reçu|un email vous sera automatiquement envoyé par OpenFlyers avec en pièce-jointe votre reçu au format PDF]].&lt;br /&gt;
&lt;br /&gt;
=Extrait de compte=&lt;br /&gt;
'''OpenFlyers''' offre la possibilité à un utilisateur de consulter des extraits de compte : C'est un rapport permettant de visualiser le détail des écritures comptables effectuées sur une période (une année complète ou un mois d'une année) d'un compte ou de tous les comptes d'une comptabilité donnée. Si la gestion des budgets est activée, il est possible de filtrer l'affichage des écritures selon les budgets.&lt;br /&gt;
&lt;br /&gt;
L'extrait de compte est accessible :&lt;br /&gt;
*Depuis l'interface légère :&lt;br /&gt;
**Le bandeau des soldes de chaque compte sous le menu&lt;br /&gt;
** '''Planning &amp;gt; Comptes &amp;gt; Extrait de compte...''' puis sélectionner un compte&lt;br /&gt;
** '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Utilisateurs''' puis cliquer sur l'icône '''Extrait de compte''' du compte&lt;br /&gt;
** '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Ressources''' puis cliquer sur l'icône '''Extrait de compte''' du compte&lt;br /&gt;
** '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; ... ''', sélectionner une catégorie de compte puis cliquer sur l'icône '''Extrait de compte''' du compte&lt;br /&gt;
** '''Gestion &amp;gt; Comptes &amp;gt; Flux &amp;gt; Mouvements''', pour visualiser cette page il faut posséder le droit [[Gestion-des-profils#Gestion-des-comptes|Gestion des comptes]], [[Gestion-des-profils#Voir-les-comptes|Voir les comptes]] ou [[Gestion-des-profils#Saisir-tout-flux|Saisir tout flux]]&lt;br /&gt;
* Depuis la nouvelle interface :&lt;br /&gt;
** Le bandeau des soldes de chaque compte sous la barre supérieure&lt;br /&gt;
&lt;br /&gt;
Dès qu'il y a plus de 50 écritures à afficher pour un extrait de compte, la liste des écritures est paginée pour afficher 50 écritures par page.&lt;br /&gt;
&lt;br /&gt;
Lorsqu'une écriture est validée, les montants au débit et au crédit sont affichés en noir gras.&lt;br /&gt;
&lt;br /&gt;
Lorsqu'une écriture est non validée, les montants au débit et au crédit sont affichés en vert gras. En fonction du [[Gestion des profils|profil et de ses droits]], dans la colonne '''Actions''', des icônes peuvent apparaitre pour modifier ou supprimer une écriture non validée selon [[Gestion des écritures comptables#Types_d'écritures_comptable_générées_par_OpenFlyers|le type d'écriture comptable qui est générée]].&lt;br /&gt;
&lt;br /&gt;
En bas du tableau, en fonction du [[Gestion des profils|profil et des droits]] de l'utilisateur, les boutons suivants peuvent être présents :&lt;br /&gt;
*'''Saisir un encaissement''' : accès au formulaire de [[#Créditer-son-compte-utilisateur|saisie d'encaissement]]. Ce lien apparaît uniquement dans les extraits de comptes-utilisateurs.&lt;br /&gt;
*'''Saisir un flux''' : accès au formulaire de [[Utilisation-de-la-comptabilité#Saisir-un-flux|saisie d'un flux]].&lt;br /&gt;
&lt;br /&gt;
==Colonne Numéro de pointage, facture ou reçu==&lt;br /&gt;
*Lorsque l'écriture est liée à une [[Écritures comptables#Facture-fournisseur|facture fournisseur]], la colonne affiche le numéro de pointage.&lt;br /&gt;
*Lorsque l'écriture est liée à une [[Écritures comptables#Facture-client|facture client]] :&lt;br /&gt;
**Si l'utilisateur dispose de [[Gestion des profils#Comptes|l'un de ces droits]] : [[Gestion-des-profils#Gestion-des-comptes|'''Gestion des comptes''']], [[Gestion-des-profils#Voir-les-comptes|'''Voir les comptes''']] ou [[Gestion-des-profils#Voir-les-comptes-utilisateurs|'''Voir les comptes utilisateurs''']] ou que la facture à afficher '''lui est destinée''' :&lt;br /&gt;
***Pour une écriture non-validée, la colonne affiche les icônes [[File:IconHTML.png]] qui amènent aux factures pro-format associées.&lt;br /&gt;
***Pour une écriture validée, la colonne affiche les icônes [[File:IconPDF.png]] qui amène aux factures PDF associées.&lt;br /&gt;
**Dans le cas contraire, ce sont les numéros des factures qui sont affichés à la place des icônes.&lt;br /&gt;
&lt;br /&gt;
La colonne affiche &amp;quot;--&amp;quot; lorsqu'il s'agit d'une écriture :&lt;br /&gt;
* D'[[Écritures comptables#Encaissement-(d'un-client)|encaissement client]].&lt;br /&gt;
* De [[Écritures comptables#Les-4-grands-types-d'écritures|flux]].&lt;br /&gt;
* De [[Écritures comptables#Facture-client|facture client]] n'ayant pas de facture associée.&lt;br /&gt;
&lt;br /&gt;
=Imprimer un extrait de compte=&lt;br /&gt;
*Afficher l'extrait de compte souhaité&lt;br /&gt;
*[[Navigateurs#Imprimer-avec-un-navigateur|Imprimer avec la commande du navigateur]]&lt;br /&gt;
&lt;br /&gt;
=Transférer de l'argent=&lt;br /&gt;
Selon les droits accordés aux utilisateurs par la structure, il peut être possible d'effectuer un transfert d'argent depuis son compte vers le compte d'un autre utilisateur en suivant la procédure suivante :&lt;br /&gt;
*'''Planning &amp;gt; Comptes &amp;gt; Actions &amp;gt; Transférer'''&lt;br /&gt;
*Dans le champ '''Compte à créditer''' choisir le nom de la personne concernée&lt;br /&gt;
*Dans le champ '''Montant''', saisir le montant que l'on souhaite transférer&lt;br /&gt;
*Remplir éventuellement le champ '''Commentaires'''&lt;br /&gt;
*Cliquer sur le bouton '''Valider''' : '''Attention''' cette opération est irrévocable et une fois que vous aurez validé, il ne sera pas possible de supprimer le virement. Si vous souhaitez faire annuler l'opération il faudra contacter la personne recevant l'argent pour qu'elle fasse à son tour un transfert sur votre compte.&lt;br /&gt;
&lt;br /&gt;
Si le message d'alerte '''Le solde du compte après opération serait inférieur au minimum autorisé (X) pour un transfert''' apparait alors cela signifie qu'une [[Configuration-de-la-comptabilité#Paramétrage-général-des-comptabilités|restriction sur les soldes]] est en place et que vous ne disposez pas d'un solde suffisant.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Gestion-armoire-%C3%A0-cl%C3%A9s&amp;diff=12888</id>
		<title>Gestion armoire à clés</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Gestion-armoire-%C3%A0-cl%C3%A9s&amp;diff=12888"/>
		<updated>2024-10-02T17:27:52Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de décrire le logiciel de gestion d'armoire à clés POK.&lt;br /&gt;
&lt;br /&gt;
=Alertes=&lt;br /&gt;
==Alertes de paramétrage==&lt;br /&gt;
===[[Alertes-de-configuration#Une-armoire-à-clés-est-paramétrée-cependant-la-dernière-synchronisation-remonte-à-X|Une armoire à clés est paramétrée cependant la dernière synchronisation remonte à X]]===&lt;br /&gt;
==Alertes lors de la saisie d'une activité==&lt;br /&gt;
Les [[Gestion-des-activités#Alertes|alertes suivantes sont générées lors de la saisie d'une activité]].&lt;br /&gt;
===Alerte générée lors du contrôle sur la présence de la clé===&lt;br /&gt;
Un contrôle sur la présence de la clé associée à un aéronef est effectué lorsque l'utilisateur :&lt;br /&gt;
*Saisit une nouvelle activité, en ouverture ou fermeture&lt;br /&gt;
ou&lt;br /&gt;
*Ferme une activité qui est saisie ouverte&lt;br /&gt;
et que l'[[Installation-armoire-à-clés#Paramétrage-OpenFlyers|armoire à clés est paramétrée]] avec '''Vérifier la présence de la clé lors de la fermeture du vol'''&lt;br /&gt;
&lt;br /&gt;
Alors, si la clé n'est pas à sa position sur l'armoire, une alerte rouge apparait indiquant : '''La clé de l'aéronef n'est pas au tableau'''.&lt;br /&gt;
&lt;br /&gt;
NB : Le contrôle n'est pas effectué si on essaie de modifier un vol déjà saisi et clôturé.&lt;br /&gt;
&lt;br /&gt;
=Débloquer une clé en secours manuellement=&lt;br /&gt;
*Couper l'alimentation électrique et débrancher la batterie de secours&lt;br /&gt;
*[[#Ouvrir-la-porte-avant-vitrée-en-secours|Ouvrir la porte avant vitrée en secours]]&lt;br /&gt;
*Agir sur le crochet verrouillant la clé à récupérer&lt;br /&gt;
&lt;br /&gt;
=Interface web de secours=&lt;br /&gt;
L'armoire à clés fournie par OpenFlyers dispose d'une interface web accessible en intranet gérée par le mini-serveur OpenFlyers embarqué dans l'armoire à clés. Cette interface permet de contrôler l'armoire en cas de problème d'accès internet.&lt;br /&gt;
==Connexion à l'interface Web de secours==&lt;br /&gt;
*Dans le navigateur mettre l'URL du mini-serveur OpenFlyers. Cette adresse peut changer selon les configurations. Voici les 2 cas les plus courants :&lt;br /&gt;
**http://192.168.0.200:8000&lt;br /&gt;
**http://192.168.1.200:8000&lt;br /&gt;
*Une page permettant de libérer les clés indépendamment d'une connexion avec le serveur s'affiche :&lt;br /&gt;
&lt;br /&gt;
[[File:Interface_administrateur_POK4.png|600px]]&lt;br /&gt;
&lt;br /&gt;
*Saisir le mot de passe administrateur indiqué sur le bordereau de livraison&lt;br /&gt;
&lt;br /&gt;
==Libérer une clé via l'interface intranet de secours==&lt;br /&gt;
Pour libérer une clé lors d'une coupure internet, il y a 2 solutions :&lt;br /&gt;
*Soit en tant qu'administrateur :&lt;br /&gt;
**[[#Connexion_à_l'interface_Web_de_secours|Se connecter à l'interface web de secours]]&lt;br /&gt;
**Sélectionner le numéro et cliquer sur le bouton '''Libérer la clé'''&lt;br /&gt;
*Soit en tant qu'utilisateur final :&lt;br /&gt;
**S'identifier sur l'interface utilisateur hors ligne&lt;br /&gt;
**Demander la clé à libérer&lt;br /&gt;
Le système vérifie alors que l'utilisateur dispose bien des droits&lt;br /&gt;
&lt;br /&gt;
[[File:Interface_utilisateur_hors_ligne_POK4.png|600px]]&lt;br /&gt;
&lt;br /&gt;
==Réinitialiser une alarme de défaut==&lt;br /&gt;
*[[#Connexion_à_l'interface_Web_de_secours|Se connecter à l'interface web de secours]]&lt;br /&gt;
*Cliquer sur le bouton '''RESET''' pour supprimer l'alarme de défaut&lt;br /&gt;
&lt;br /&gt;
=Libérer une clé sans ouvrir une activité=&lt;br /&gt;
Il est possible de libérer une clé d'une ressource depuis OpenFlyers sans avoir à ouvrir une activité. Cette possibilité n'est normalement accessible qu'à des utilisateurs disposant de droits de gestion.&lt;br /&gt;
*Aller au menu '''Gestion &amp;gt; Ressources &amp;gt; Actives'''&lt;br /&gt;
*Dans la colonne '''statut''' cliquer sur le pictogramme symbolisant une clé pour la ressource concernée.&lt;br /&gt;
&lt;br /&gt;
=Ouvrir la porte avant vitrée en secours=&lt;br /&gt;
*Ouvrir la porte arrière avec la clé&lt;br /&gt;
*Glisser sa main contre le panneau latéral jusqu'à toucher le crochet qui sert à verrouiller mécaniquement la porte.&lt;br /&gt;
*Manipuler le crochet pour ouvrir la porte&lt;br /&gt;
&lt;br /&gt;
=Remettre les clés à leur bonne position=&lt;br /&gt;
Le paramétrage des clés dans OpenFlyers permet de choisir la position que doit avoir chaque clé. Lorsqu'une clé est mal positionnée dans l'armoire elle est entourée d'un cercle rouge et elle est déverrouillée :&lt;br /&gt;
&lt;br /&gt;
[[File:Clé_rouge.JPG|center]]&lt;br /&gt;
&lt;br /&gt;
De plus, la porte de l'armoire est également déverrouillée. Dans ce cas, il faut effectuer la procédure suivante :&lt;br /&gt;
*Ouvrir la porte&lt;br /&gt;
*Enlever toutes les clés qui sont détectées comme mal positionnées&lt;br /&gt;
*Effectuer une réinitialisation de l'armoire en débranchant l'alimentation puis en la reconnectant après 5 secondes&lt;br /&gt;
Si à la fin de cette nouvelle réinitialisation, il y a d'autres clés qui sont détectées comme mal positionnées, il faut répéter cette opération d'enlèvement/réinitialisation jusqu'à ce qu'il n'y ait ne plus de clé détectée comme mal positionnée. Au pire, toutes les clés seront enlevées de l'armoire.&lt;br /&gt;
&lt;br /&gt;
Une fois qu'il n'y a plus de clé détectée comme mal positionnée, on doit se retrouver avec une ou plusieurs clés hors de l'armoire : ces clés seront remises à leur emplacement ultérieurement dans la procédure [[#Enregistrer_la_position_souhaitée_des_clés|d'enregistrement de la position souhaitée des clés]] après avoir effectué la procédure [[#Appariement_des_clés_aux_ressources|d’appariement des clés aux ressources]].&lt;br /&gt;
&lt;br /&gt;
=Séquence d'initialisation des leds=&lt;br /&gt;
''La séquence d'initialisation suivante correspond au logiciel de gestion de l'armoire POK v.4.''&lt;br /&gt;
&lt;br /&gt;
Lors de l'initialisation de l'armoire par le programme, une séquence de fonctionnement des leds de l'armoire est mise en place :&lt;br /&gt;
# La led jaune clignote : l'armoire démarre.&lt;br /&gt;
# La led jaune reste allumée : L'armoire a démarré et attend la connexion du programme.&lt;br /&gt;
# La led jaune s’éteint et la led rouge s'allume : Le programme vient de se connecter à l'armoire et se met à jour auprès d'elle.&lt;br /&gt;
# La led rouge reste allumée et la led jaune se rallume : Le programme fini l'initialisation&lt;br /&gt;
# Les leds rouge et jaune s'éteignent et la led verte s'allume : Le programme a fini l'initialisation et attend les ordres.&lt;br /&gt;
&lt;br /&gt;
=Trouver l'adresse MAC du deamon=&lt;br /&gt;
==Trouver l'adresse MAC du deamon avec une freebox==&lt;br /&gt;
Prérequis :&lt;br /&gt;
*Il ne faut pas que le deamon soit connecté à la freebox par câble RJ45&lt;br /&gt;
*Il ne faut pas qu'un baud permanent soit déjà attribué à cette adresse MAC sur la freebox. En effet, si un baud est déjà attribué, la procédure suivante fera apparaitre l'adresse MAC du deamon même s'il n'est pas connecté.&lt;br /&gt;
&lt;br /&gt;
Procédure :&lt;br /&gt;
*Afficher la [[Trucs-et-astuces#Monitoring-d'une-freebox|page de monitoring d'une freebox]]&lt;br /&gt;
*Repérer le paragraphe '''Réseau''' et le sous-paragraphe '''Attributions dhcp'''&lt;br /&gt;
*Brancher le deamon par câble RJ45 à la freebox en veillant à ce qu'il soit sous tension&lt;br /&gt;
*Rafraichir la [[Trucs-et-astuces#Monitoring-d'une-freebox|page de monitoring d'une freebox]]&lt;br /&gt;
*Comparer le paragraphe '''Réseau''' et le sous-paragraphe '''Attributions dhcp''' avec l'onglet précédent : la nouvelle ligne qui apparait correspond à l'adresse IP et à l'adresse MAC du deamon&lt;br /&gt;
&lt;br /&gt;
=Vérifier les connexions réseaux de l'armoire et du mini-serveur=&lt;br /&gt;
*[[Trucs-et-astuces#Ouvrir-une-console|Ouvrir une console]]&lt;br /&gt;
*Taper la commande suivante en remplaçant :&lt;br /&gt;
**x par 0 ou 1 selon la configuration du réseau&lt;br /&gt;
**y par :&lt;br /&gt;
***200 pour vérifier le branchement du mini-serveur&lt;br /&gt;
***201 pour vérifier la branchement de l'armoire à clés&lt;br /&gt;
&amp;lt;bash&amp;gt;ping 192.168.x.y&amp;lt;/bash&amp;gt;&lt;br /&gt;
Le résultat doit être sous la forme suivante :&lt;br /&gt;
&amp;lt;bash&amp;gt;ping 192.168.x.y (192.168.x.y) 56(84) bytes of data.&lt;br /&gt;
64 bytes from 192.168.x.y: icmp_req=1 ttl=64 time=0.241 ms&lt;br /&gt;
64 bytes from 192.168.x.y: icmp_req=2 ttl=64 time=0.143 ms&lt;br /&gt;
64 bytes from 192.168.x.y: icmp_req=3 ttl=64 time=0.144 ms&lt;br /&gt;
64 bytes from 192.168.x.y: icmp_req=4 ttl=64 time=0.145 ms&amp;lt;/bash&amp;gt;&lt;br /&gt;
Si la réponse est &amp;quot;Unreachable&amp;quot; ou &amp;quot;Impossible de joindre l'hôte de destination&amp;quot; :&lt;br /&gt;
&amp;lt;bash&amp;gt;ping 192.168.x.y (192.168.x.y) 56(84) bytes of data.&lt;br /&gt;
From 192.168.x.y icmp_seq=1 Destination Host Unreachable&amp;lt;/bash&amp;gt;&lt;br /&gt;
&amp;lt;bash&amp;gt;Envoi d'une requête 'Ping'  192.168.x.y avec 32 octets de données :&lt;br /&gt;
Réponse de 192.168.x.y : Impossible de joindre l'hôte de destination.&amp;lt;/bash&amp;gt;&lt;br /&gt;
alors les adresses ne sont pas correctement affectées ou un câble est défectueux.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Fiche-personnelle&amp;diff=12887</id>
		<title>Fiche personnelle</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Fiche-personnelle&amp;diff=12887"/>
		<updated>2024-10-02T17:27:52Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Fiche_personnelle.png|right|thumb|200px|Fiche personnelle]]&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter la '''fiche personnelle''' dans la [[Accueil|version 4 d'OpenFlyers]].&lt;br /&gt;
&lt;br /&gt;
=Accès=&lt;br /&gt;
Depuis le [[Planning-(interface-légère)|planning de l'interface légère]] :&lt;br /&gt;
*'''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
&lt;br /&gt;
=Affichage du menu contextuel=&lt;br /&gt;
Le menu contextuel et un menu déroulant qui apparait lors du survol d'une réservation ou d'un vol ouvert. Ce menu contextuel peut apparaitre :&lt;br /&gt;
*soit automatiquement&lt;br /&gt;
*soit par un clic droit de la souris&lt;br /&gt;
Ce paramétrage est personnalisable pour chaque utilisateur :&lt;br /&gt;
*'''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
*Cocher ou décocher '''N'afficher la description des réservations qu'avec le bouton droit de la souris''' selon le comportement souhaité&lt;br /&gt;
*Cliquer sur le bouton '''Sauver''' tout en bas du formulaire&lt;br /&gt;
&lt;br /&gt;
=Afficher les éphémérides=&lt;br /&gt;
Permet sur le [[Planning-(interface-légère)|planning de l'interface légère]] :&lt;br /&gt;
* D'afficher la boîte des éphémérides&lt;br /&gt;
* Faire une distinction de couleur sur les créneaux horaires liés aux éphémérides&lt;br /&gt;
&lt;br /&gt;
[[File:Ephemeride_ancienne_interface.png|800px]]&lt;br /&gt;
&lt;br /&gt;
Ce paramétrage est personnalisable pour chaque utilisateur :&lt;br /&gt;
*'''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
*Cocher ou décocher '''Afficher les éphémérides''' selon le comportement souhaité&lt;br /&gt;
*Cliquer sur le bouton '''Sauver''' tout en bas du formulaire&lt;br /&gt;
&lt;br /&gt;
=Choisir l'unité de temps=&lt;br /&gt;
Chaque utilisateur peut choisir l'unité de temps qui sert à afficher les heures.&lt;br /&gt;
*'''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
*Choisir dans le champ '''Unité de temps''' parmi :&lt;br /&gt;
**heures minutes&lt;br /&gt;
**heures centièmes&lt;br /&gt;
**heures dixièmes&lt;br /&gt;
*Appuyer sur le bouton '''Sauver'''.&lt;br /&gt;
&lt;br /&gt;
==[[Champs métiers]]==&lt;br /&gt;
En plus des champs habituels, des [[Champs-métiers|champs métiers]] spécifiques à la structure peuvent apparaître dans la fiche personnelle. &lt;br /&gt;
&lt;br /&gt;
Ils sont affichés [[Gestion-des-profils#Généralités|si les droits sont attribués par l'administrateur]] et permettent d'activer des fonctionnalités supplémentaires, par exemple, [[Interfaçage-Aérogligli|l'interfaçage avec Aérogligli]].&lt;br /&gt;
&lt;br /&gt;
=Changer sa langue=&lt;br /&gt;
*Aller dans '''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
*Dans la colonne '''Accès et interface''', changer la '''langue'''&lt;br /&gt;
*Cliquer sur '''Enregistrer'''&lt;br /&gt;
&lt;br /&gt;
=Changer son mot de passe=&lt;br /&gt;
&lt;br /&gt;
==Alertes en changeant son mot de passe==&lt;br /&gt;
&lt;br /&gt;
===Vous devez saisir l'ancien mot de passe et deux fois le nouveau===&lt;br /&gt;
&lt;br /&gt;
Lors du changement du mot de passe, cette alerte s'affiche si :&lt;br /&gt;
*L'un des champs du formulaire n'a pas été saisi.&lt;br /&gt;
&lt;br /&gt;
===Vous devez saisir deux fois le même nouveau mot de passe===&lt;br /&gt;
&lt;br /&gt;
Lors du changement du mot de passe, cette alerte s'affiche si :&lt;br /&gt;
*L'un des champs du formulaire n'a pas été saisi et que l'ancien mot de passe n'est pas demandé.&lt;br /&gt;
*Le nouveau mot de passe et sa confirmation ne sont pas identiques.&lt;br /&gt;
&lt;br /&gt;
==Niveau de sécurité du mot de passe==&lt;br /&gt;
&lt;br /&gt;
Lors du changement du mot de passe, une barre montre le niveau de sécurité du mot de passe. Cette barre a 4 niveaux : '''faible''', '''moyen''', '''fort''' et '''excellent'''. Pour évaluer le niveau de sécurité du mot de passe nous regardons son nombre de caractères, s'il y a des lettres minuscules et majuscules, s'il y a des chiffres et s'il y a des caractères de ponctuation.&lt;br /&gt;
&lt;br /&gt;
Plus précisément voici ce que requiert chaque niveau :&lt;br /&gt;
*Faible : le mot de passe doit avoir au moins 1 caractère&lt;br /&gt;
*Moyen : le mot de passe doit avoir au moins 8 caractères et doit être composé de 2 types de caractères (par exemple des lettres minuscules et des lettres majuscules)&lt;br /&gt;
*Fort : le mot de passe doit avoir au moins 8 caractères et doit être composé de 3 types de caractères (par exemple des lettres minuscules, des lettres majuscules et des chiffres)&lt;br /&gt;
*Excellent : le mot de passe doit avoir au moins 14 caractères et doit être composé de 3 types de caractères (par exemple des lettres minuscules, des lettres majuscules et des chiffres)&lt;br /&gt;
&lt;br /&gt;
=Communication=&lt;br /&gt;
==E-mail==&lt;br /&gt;
Il est possible de renseigner plusieurs adresses e-mails dans ce champ en séparant chaque adresse e-mail d'une virgule.&lt;br /&gt;
'''Attention : il ne faut jamais mettre d'espace : ni dans l'adresse e-mail elle même, ni avant ou après les virgules de séparation des adresses e-mails'''&lt;br /&gt;
&lt;br /&gt;
Exemple valide :&lt;br /&gt;
&amp;lt;pre&amp;gt;jesuisuntest@test.fr,jesuisuntest@test.com&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Exemples non valides :&lt;br /&gt;
&amp;lt;pre&amp;gt;jesuisuntest@test.fr , jesuisuntest@test.com&lt;br /&gt;
jesuisuntest@test.fr ,jesuisuntest@test.com&lt;br /&gt;
jesuisuntest@test.fr, jesuisuntest@test.com&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Gérer l'abonnement à la liste de diffusion==&lt;br /&gt;
Lorsque une liste de diffusion mailman gérée par OpenFlyers est activée pour la plateforme OpenFlyers, l'utilisateur peut de lui-même gérer son abonnement à la liste de diffusion :&lt;br /&gt;
*'''Données &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
Formulaire '''Liste de diffusion : nomdelastructure-ml@openflyers.info'''&lt;br /&gt;
*Cocher/décocher le bouton '''Abonné(e)'''&lt;br /&gt;
*Cliquer sur le bouton '''Sauver'''&lt;br /&gt;
&lt;br /&gt;
=Editer sa photo=&lt;br /&gt;
*'''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
*L'import ou la suppression d'une photo requiert le droit [[Gestion-des-profils#Editer-sa-photo|Editer sa photo]]. Ce droit n'est pas nécessaire pour rendre sa photo visible pour tous.&lt;br /&gt;
*Lors de l'import, si la photo de profil a une taille supérieure à 600 pixels (de largeur ou de hauteur), elle est automatiquement redimensionner à cette taille. Son poids ne doit pas être supérieur à 100Ko.&lt;br /&gt;
&lt;br /&gt;
=Mettre à jour sa date de naissance, sa nationalité ou son sexe=&lt;br /&gt;
Le droit [[Gestion-des-profils#Mise-à-jour-de-sa-date-de-naissance,-de-son-sexe-et-de-sa-nationalité|Mise à jour de sa date de naissance, de son sexe et de sa nationalité]] est requis pour mettre à jour sa date de naissance, sa nationalité ou son sexe.&lt;br /&gt;
&lt;br /&gt;
=Notifications=&lt;br /&gt;
==Etre informé des actualités OpenFlyers par e-mail==&lt;br /&gt;
*'''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
*L'utilisateur peut cocher ou décocher cette case afin d'être prévenu ou non par e-mail des nouveautés OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
==Notification des réservations par e-mail==&lt;br /&gt;
*'''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
*L'utilisateur peut cocher ou décocher cette case afin d'être prévenu ou non par [[#E-mail_de_notification_de_réservation|e-mail des réservations créées ou modifiées]] le concernant.&lt;br /&gt;
&lt;br /&gt;
==Rappel des réservations de 2 jours d'avance par e-mail==&lt;br /&gt;
*'''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
*L'utilisateur peut cocher ou décocher cette case afin de recevoir ou non par e-mail un rappel de réservation.&lt;br /&gt;
&lt;br /&gt;
Les rappels sont envoyés entre 0h et 6h au fuseau Europe/Paris pour les réservations débutant entre 2 et 3 jours après.&lt;br /&gt;
&lt;br /&gt;
Les [[Envoi-des-emails#Présentation|rappels ne sont effectifs que sur les plateformes en production]].&lt;br /&gt;
&lt;br /&gt;
==Rappel des réservations de la veille ou de la journée par e-mail==&lt;br /&gt;
*'''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
*L'utilisateur peut cocher ou décocher cette case afin de recevoir ou non l'e-mail de rappel de la structure concernant une réservation passée (réservation de la veille ou de la journée). L'e-mail contient un message paramétré par la structure.&lt;br /&gt;
&lt;br /&gt;
Les rappels sont envoyés entre 0h et 6h au fuseau Europe/Paris pour les réservations de la veille.&lt;br /&gt;
&lt;br /&gt;
Les [[Envoi-des-emails#Présentation|rappels ne sont effectifs que sur les plateformes en production]].&lt;br /&gt;
&lt;br /&gt;
==Notification des réservations annulées==&lt;br /&gt;
*'''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
*L'utilisateur peut cocher ou décocher cette case afin d'être prévenu ou non par [[#E-mail_d'annulation_de_réservation|e-mail des réservations annulées]] le concernant.&lt;br /&gt;
&lt;br /&gt;
==Recevoir un e-mail pour les réservations ayant pour activité==&lt;br /&gt;
*'''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
Lorsque l'utilisateur dispose d'un profil avec le droit [[Gestion-des-profils#Alertable-par-e-mail-pour-toute-réservation|Alertable par e-mail pour toute réservation]], apparait une liste de case à cocher avec pour label '''Recevoir un e-mail pour les réservations ayant pour activité'''.&lt;br /&gt;
*L'utilisateur peut cocher ou décocher ces cases afin d'être prévenu ou non [[Envoi-des-emails|par e-mail]] lorsqu'une réservation avec l'une de ces [[Gestion-des-activités|activités]] est créée ou modifiée par n'importe quel utilisateur.&lt;br /&gt;
&lt;br /&gt;
==Recevoir un e-mail pour chaque facture==&lt;br /&gt;
Cette option permet d'activer ou de désactiver l'[[Envoi-des-emails#E-mail-de-facture|envoi automatique de chaque facture]] appartenant à l'utilisateur.&lt;br /&gt;
&lt;br /&gt;
L'apparition de cette option dépend de la [[Configuration#Envoyer-un-email-pour-chaque-facture|configuration de la plateforme]] dont [[Facturation-des-clients#Envoi-automatique-de-chaque-facture-client|le comportement est décrit ici]].&lt;br /&gt;
&lt;br /&gt;
=Paramétrer les ressources et les utilisateurs visibles sur le planning=&lt;br /&gt;
Depuis la fiche personnelle, il est possible de choisir [[Aspect-du-planning-de-réservation#Généralités|quelles ressources matérielles et humaines sont visibles sur le planning]] avec le droit [[Gestion-des-profils#Personnaliser-ses-ressources-visibles|Personnaliser ses ressources visibles]].&lt;br /&gt;
&lt;br /&gt;
*'''Planning &amp;gt; Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
*Dans la catégorie '''Options d'affichage''' :&lt;br /&gt;
*Cocher ou décocher les '''Ressources visibles''' ou '''Utilisateurs visibles''' à afficher.&lt;br /&gt;
&lt;br /&gt;
=Synchronisation des réservations=&lt;br /&gt;
==Mettre en place un planning partagé avec Google agenda==&lt;br /&gt;
;Présentation&lt;br /&gt;
L'objectif de cette procédure est de permettre la création d'un planning partagé contenant l'ensemble des réservations d'une plateforme OpenFlyers afin qu'elles soient visibles depuis un agenda Google lui-même partagé entre plusieurs personnes&lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
*Créer un compte utilisateur ayant un profil disposant du droit [[Gestion-des-profils#Alertable-par-e-mail-pour-toute-réservation|Alertable par e-mail pour toute réservation]]&lt;br /&gt;
Depuis la fiche personnelle de l'utilisateur créé :&lt;br /&gt;
*Suivre la procédure [[#Synchroniser-les-réservations-dans-OpenFlyers-avec-un-agenda-Google|Synchroniser les réservations dans OpenFlyers avec un agenda Google]] &lt;br /&gt;
*Dans '''Recevoir un e-mail pour les réservations ayant pour activité''', cocher les activités pour lesquelles la synchronisation avec le planning partagé Google agenda doit s'effectuer&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
&lt;br /&gt;
==Synchroniser les réservations dans OpenFlyers avec un agenda Google==&lt;br /&gt;
;Présentation&lt;br /&gt;
L'objectif est de synchroniser ses réservations personnelles présentes sur une plateforme OpenFlyers avec un compte Google agenda&lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
*'''Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
Sous le titre '''Synchronisation des réservations''' et le sous titre '''avec Google agenda'''&lt;br /&gt;
*Cliquer sur le bouton '''Se connecter avec Google'''&lt;br /&gt;
*Si plusieurs comptes Google sont enregistrés dans le navigateur, une page s'affiche demandant avec quel compte Google il faut se synchroniser. Sélectionner le compte concerné&lt;br /&gt;
*Une fois le compte Google sélectionné, le nom du compte en question s'affiche en dessous du sous titre '''avec Google agenda'''&lt;br /&gt;
Lorsque l'utilisateur a lié son compte Google agenda, une liste d'agendas apparaît lui permettant de choisir dans quel agenda les événements doivent être créés.&lt;br /&gt;
*'''Données &amp;gt; Personnelles &amp;gt; Affichage et fiche personnelle'''&lt;br /&gt;
Sous le titre '''Synchronisation des réservations''' et le sous titre '''Calendrier'''&lt;br /&gt;
*Choisir un des agendas de la liste&lt;br /&gt;
*Cliquer sur '''Enregistrer'''&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=FAQ-armoire-%C3%A0-cl%C3%A9s&amp;diff=12886</id>
		<title>FAQ armoire à clés</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=FAQ-armoire-%C3%A0-cl%C3%A9s&amp;diff=12886"/>
		<updated>2024-10-02T17:27:52Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
=Changement de fournisseur d'accès impliquant un changement de routeur=&lt;br /&gt;
Dans le cas d'un changement de routeur entrainant un changement de la structure du réseau (par exemple réseau en 192.168.0.x devenant 192.168.1.x), afin d'éviter d'avoir à reconfigurer tout le réseau et en particulier l'armoire à clés, le plus simple est de modifier la structure par défaut du réseau mis en place par le nouveau routeur afin de conserver l'ancienne structuration (par exemple 192.168.0.x).&lt;br /&gt;
&lt;br /&gt;
Dans le cas où il n'est pas possible de modifier la structuration du réseau dans le paramétrage du routeur et qu'il est nécessaire de modifier les adresses IP internes à l'armoire à clés, il faut contacter OpenFlyers pour une prise de rendez-vous afin de permettre une intervention à distance pour effectuer ces modifications.&lt;br /&gt;
&lt;br /&gt;
=Check-list Armoire à clé INOP=&lt;br /&gt;
En cas de dysfonctionnement de l'armoire effectuer les vérification suivantes:&lt;br /&gt;
#Vérifier les branchements des câbles RJ45 coté routeur&lt;br /&gt;
#Couper son alimentation (retrait de la prise ou disjoncteur). &lt;br /&gt;
#Ouvrir la porte de service&lt;br /&gt;
#Vérifier les branchements des câbles RJ45 coté armoire&lt;br /&gt;
#Déconnecter la batterie de sauvegarde. Troisième connecteur vert en bas de la carte électronique Deister en partant de la gauche (2 pins) [[File:Connecteur_Batterie.JPG]]&lt;br /&gt;
#Après 15 secondes d'attente reconnecter l'alimentation électrique (pas la batterie de secours)&lt;br /&gt;
#Observer la présence de la diode orange clignotante sur la façade avant du tableau de clés&lt;br /&gt;
#Observer les diodes sur la carte électronique du daemon Openflyers, porte arrière ouverte &lt;br /&gt;
#Une diode rouge doit immédiatement s'allumer suivi du clignotement des diodes oranges. Voir signification des [http://www.framboise314.fr/les-leds-du-raspberry-pi/ diodes du Raspberry Pi]&lt;br /&gt;
#La diode Orange de façade doit devenir fixe&lt;br /&gt;
#Après 2 à 3 minutes la diode de façade orange doit s’éteindre et la diode vertes doit s'allumer fixe&lt;br /&gt;
#Vérifier vos [[Installation armoire à clés#Paramétrage OpenFlyers|paramètres dans OpenFlyers]]&lt;br /&gt;
#:Si la séquence d'allumage des diodes décrite ci-dessus n'est pas conforme, contacter OpenFlyers en décrivant les points défaillants&lt;br /&gt;
#:Si la séquence d'allumage des diodes est opérationnelle poursuivre les investigations ci-après&lt;br /&gt;
#Vérifier s'il est possible de contrôler l'armoire à clés avec l'interface web de secours qui ne nécessite pas de connexion internet mais juste que le réseau local fonctionne. Voir le chapitre [[Gestion-armoire-à-clés#Interface-web-de-secours|Interface-web-de-secours]].&lt;br /&gt;
&lt;br /&gt;
=Access denied=&lt;br /&gt;
Ce message peut apparaitre lorsque le contrôle d'accès est partiellement désactivé :&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Structure &amp;gt; Contrôle d'accès'''&lt;br /&gt;
Vérifier que :&lt;br /&gt;
*'''Contrôle d'accès''' est activé&lt;br /&gt;
*'''Gestion armoire à clés''' est activé&lt;br /&gt;
Si ce n'est pas le cas, activer les 2 paramètres&lt;br /&gt;
&lt;br /&gt;
=Connection is denied=&lt;br /&gt;
Lors de la demande d'ouverture d'une porte ou de libération d'une clé depuis l'interface OpenFlyers, un popup apparait au bout de quelques secondes avec le message '''Connection is denied'''.&lt;br /&gt;
&lt;br /&gt;
Ce message indique que le mini-serveur OpenFlyers présent dans l'armoire n'arrive pas à établir la connexion avec le serveur OpenFlyers hébergeant la plateforme de la structure.&lt;br /&gt;
&lt;br /&gt;
Vérifier que la connexion internet est valide (ce qui est normalement le cas, si on arrive à afficher le contenu de la plateforme OpenFlyers sur un ordinateur du même réseau.&lt;br /&gt;
&lt;br /&gt;
Si l'armoire et le mini-serveur sont en IP statique, vérifier que l'adresse IP du routeur est identique à celle communiquée à OpenFlyers lors de la mise en place du paramétrage.&lt;br /&gt;
&lt;br /&gt;
A défaut, contacter l'équipe OpenFlyers pour vérification de la configuration du mini-serveur et de la plateforme OpenFlyers de la structure.&lt;br /&gt;
&lt;br /&gt;
=Connection Issue with Raspberry Server=&lt;br /&gt;
&lt;br /&gt;
Lors de la demande d'ouverture d'une porte ou de libération d'une clé depuis l'interface OpenFlyers, un popup apparaît au bout de quelques secondes avec le message '''Connection issue with Raspberry server'''.&lt;br /&gt;
&lt;br /&gt;
Ce message indique qu'une erreur retournée par le mini-serveur ou à une réponse inattendue.&lt;br /&gt;
&lt;br /&gt;
=Impossible de dialoguer avec l'armoire depuis un nouveau PC=&lt;br /&gt;
Le problème doit venir du fait que le nouveau PC utilise le protocole HTTPS au lieu du protocole HTTP qui est le seul supporté pour se connecter à l'armoire à clés pour les armoires dont le firmware n'a pas été mis à jour.&lt;br /&gt;
&lt;br /&gt;
Il faut [[Installation-armoire-à-clés#Navigateur|configurer les navigateurs pour qu'ils acceptent le mix HTTP/HTTPS]].&lt;br /&gt;
&lt;br /&gt;
=Latence entre la demande d'ouverture de la porte et l'ouverture effective=&lt;br /&gt;
S'il y a un délai de plusieurs secondes (5, 10, ou 20 secondes) entre le moment où un utilisateur demande à récupérer une clé le le moment où la porte de l'armoire s'ouvre effectivement, alors il faut fortement soupçonner un problème de configuration des DNS.&lt;br /&gt;
&lt;br /&gt;
=Le voyant jaune reste allumé=&lt;br /&gt;
* Débrancher/rebrancher l'armoire&lt;br /&gt;
Le voyant devrait ensuite clignoter pendant moins d'une minute, puis rester fixe et s'éteindre pour que le voyant rouge s'allume.&lt;br /&gt;
&lt;br /&gt;
Si le problème persiste :&lt;br /&gt;
* Pinger le programme&lt;br /&gt;
** Si le programme ne répond pas au ping, alors le problème est du côté du daemon&lt;br /&gt;
** Si le programme répond, poursuivre&lt;br /&gt;
* Pinger l'armoire&lt;br /&gt;
** Si l'armoire ne répond pas au ping, alors le problème est du côté de l'armoire&lt;br /&gt;
** Si l'armoire répond, poursuivre&lt;br /&gt;
A ce niveau là, on peut suspecter un problème de liaison entre le daemon et l'armoire.&lt;br /&gt;
* Contacter OpenFlyers pour lancer une investigation.&lt;br /&gt;
&lt;br /&gt;
=Le voyant rouge reste allumé=&lt;br /&gt;
* Débrancher/rebrancher l'armoire&lt;br /&gt;
Le voyant devrait ensuite clignoter pendant moins d'une minute, puis rester fixe et s'éteindre pour que le voyant rouge s'allume.&lt;br /&gt;
&lt;br /&gt;
Après une courte période le voyant jaune devrait s'allumer lui aussi.&lt;br /&gt;
&lt;br /&gt;
Si le problème persiste :&lt;br /&gt;
* Pinger le programme&lt;br /&gt;
** Si le programme ne répond pas au ping, alors le problème est du côté du daemon&lt;br /&gt;
** Si le programme répond, poursuivre&lt;br /&gt;
* Pinger l'armoire&lt;br /&gt;
** Si l'armoire ne répond pas au ping, alors le problème est du côté de l'armoire&lt;br /&gt;
** Si l'armoire répond, poursuivre&lt;br /&gt;
A ce niveau là, on peut suspecter un problème de liaison entre le daemon et l'armoire.&lt;br /&gt;
* Contacter OpenFlyers pour lancer une investigation.&lt;br /&gt;
&lt;br /&gt;
=Les voyants jaune et rouge restent allumés=&lt;br /&gt;
* Débrancher/rebrancher l'armoire&lt;br /&gt;
Le voyant devrait ensuite clignoter pendant moins d'une minute, puis rester fixe et s'éteindre pour que le voyant rouge s'allume.&lt;br /&gt;
&lt;br /&gt;
Après une courte période le voyant jaune devrait s'allumer lui aussi.&lt;br /&gt;
&lt;br /&gt;
Après cela les deux voyants devraient s'éteindre pour que le voyant vert s'allume.&lt;br /&gt;
&lt;br /&gt;
Si le problème persiste :&lt;br /&gt;
* Pinger le programme&lt;br /&gt;
** Si le programme ne répond pas au ping, alors le problème est du côté du daemon&lt;br /&gt;
** Si le programme répond, poursuivre&lt;br /&gt;
* Pinger l'armoire&lt;br /&gt;
** Si l'armoire ne répond pas au ping, alors le problème est du côté de l'armoire&lt;br /&gt;
** Si l'armoire répond, poursuivre&lt;br /&gt;
A ce niveau là, on peut suspecter un problème de liaison entre le daemon et l'armoire.&lt;br /&gt;
* Contacter OpenFlyers pour lancer une investigation.&lt;br /&gt;
&lt;br /&gt;
=Modifier le mot de passe de communication interne à OpenFlyers=&lt;br /&gt;
OpenFlyers utilise une pass-phrase pour contrôler l'origine des commandes de type &amp;quot;push&amp;quot; de l'armoire à clés. Ce mot de passe ne doit pas être modifié dans l'interface OpenFlyers sinon le dialogue entre l'armoire à clés et la plateforme OpenFlyers ne sera plus possible.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Ergonomie&amp;diff=12885</id>
		<title>Ergonomie</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Ergonomie&amp;diff=12885"/>
		<updated>2024-10-02T17:27:51Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter l''''ergonomie''' de la [[Accueil|version 4 d'OpenFlyers]].&lt;br /&gt;
&lt;br /&gt;
=Éléments communs aux deux interfaces=&lt;br /&gt;
&lt;br /&gt;
==Comptes==&lt;br /&gt;
Les '''comptes''' sont situées à droite sous le menu principal.&lt;br /&gt;
&lt;br /&gt;
Un compte s'affiche :&lt;br /&gt;
*Sur fond '''rouge''' lorsqu'il est déficitaire.&lt;br /&gt;
*Sur fond '''vert''' lorsqu'il est bénéficiaire.&lt;br /&gt;
&lt;br /&gt;
[[File:comptes-utilisateurs.png]]&lt;br /&gt;
&lt;br /&gt;
==Fuseau horaire==&lt;br /&gt;
Il s'affiche au survol de l'[[#Utilisateur-connecté|utilisateur connecté]].&lt;br /&gt;
&lt;br /&gt;
[[File:fuseau-horaire.png]]&lt;br /&gt;
&lt;br /&gt;
==Utilisateur connecté==&lt;br /&gt;
Située sous le menu de navigation à droite, la zone de l'utilisateur connecté comprend :&lt;br /&gt;
*Un pictogramme par défaut ou la photo de l'utilisateur si celui-ci l'a [[Fiche-personnelle#Editer-sa-photo|importée dans sa fiche personnelle]].&lt;br /&gt;
*Le nom de famille, le prénom ainsi que l'identifiant.&lt;br /&gt;
&lt;br /&gt;
[[File:utilisateur-connecte-default.png]]&lt;br /&gt;
[[File:utilisateur-connecte-photo.png]]&lt;br /&gt;
&lt;br /&gt;
==Pied de page==&lt;br /&gt;
Il affiche :&lt;br /&gt;
*l'email de la structure lorsque celui-ci est saisi dans les [[Configuration#Adresse-de-la-structure|paramètres de la structure]].&lt;br /&gt;
&lt;br /&gt;
[[File:footer-structure-email.png]]&lt;br /&gt;
&lt;br /&gt;
=Interface dynamique=&lt;br /&gt;
Ce paragraphe présente les interactions de l'utilisateurs spécifiques à la '''interface dynamique'''.&lt;br /&gt;
&lt;br /&gt;
==Gestes==&lt;br /&gt;
Ce paragraphe présente les '''gestes''' permettant de manipuler OpenFlyers 4.&lt;br /&gt;
&lt;br /&gt;
===Balayage===&lt;br /&gt;
Le '''balayage''' existe uniquement sur écran tactile. Il consiste à effleurer rapidement l'écran selon l'axe horizontal ou l'axe vertical.&lt;br /&gt;
&lt;br /&gt;
Utilisation :&lt;br /&gt;
*Sur le menu de navigation ouvert : affiche la page à la gauche ou à la droite de la page actuelle selon le sens du balayage.&lt;br /&gt;
&lt;br /&gt;
Vidéo : https://www.youtube.com/watch?v=qNACMM6vv7s#t=0m32s&lt;br /&gt;
&lt;br /&gt;
===Clic court===&lt;br /&gt;
Le '''clic court''' consiste à presser brièvement le bouton gauche de la souris ou à appuyer avec un doigt brièvement sur l'écran tactile. &lt;br /&gt;
&lt;br /&gt;
Utilisation :&lt;br /&gt;
Le clic court étant le clic standard, seules sont détaillées ici les utilisations notables dans d'OpenFlyers 4.&lt;br /&gt;
*Sur une réservation existante : édition de la réservation&lt;br /&gt;
&lt;br /&gt;
Vidéo : https://www.youtube.com/watch?v=tzM6hyOIpnc&amp;amp;t=1m06s&lt;br /&gt;
&lt;br /&gt;
===Clic long===&lt;br /&gt;
Le '''clic long''' consiste à presser le bouton gauche de la souris ou à appuyer avec un doigt 0,3 secondes sur l'écran tactile.&lt;br /&gt;
&lt;br /&gt;
Utilisation :&lt;br /&gt;
*Sur un créneau des lignes du planning : crée une réservation.&lt;br /&gt;
&lt;br /&gt;
Vidéo : https://www.youtube.com/watch?v=tzM6hyOIpnc&amp;amp;t=2m18s&lt;br /&gt;
&lt;br /&gt;
===Glisser-déposer===&lt;br /&gt;
Le '''glisser-déposer''' consiste avec une souris à presser le bouton gauche de la souris sur un élément déplaçable, effectuer un déplacement avec la souris, et enfin relâcher le bouton gauche lorsque le déplacement est terminé.&lt;br /&gt;
&lt;br /&gt;
Le '''glisser-déposer''' consiste avec un écran tactile à maintenir le doigt appuyé sur un élément déplaçable, effectuer un déplacement, et enfin enlever son doigt de l'écran lorsque le déplacement est terminé.&lt;br /&gt;
&lt;br /&gt;
Utilisation :&lt;br /&gt;
*Sur un pictogramme du menu : déplace le pictogramme.&lt;br /&gt;
*Au milieu d'une réservation auparavant éditée avec un [[#Clic_court|clic court]] : déplace la réservation.&lt;br /&gt;
*Sur une zone de redimensionnement d'une réservation auparavant éditée avec un [[#Clic_court|clic court]] : redimensionne la réservation.&lt;br /&gt;
*Sur le bouton de déplacement d'une ligne de tableau : modifie la position de la ligne.&lt;br /&gt;
&lt;br /&gt;
Vidéo : https://www.youtube.com/watch?v=YylSewaTm4c&amp;amp;t=3m45s&lt;br /&gt;
&lt;br /&gt;
=Interface légère=&lt;br /&gt;
Ce paragraphe présente les interactions de l'utilisateurs spécifiques à l'''interface légère'''.&lt;br /&gt;
&lt;br /&gt;
==Navigation par onglet==&lt;br /&gt;
Afin d'avoir à disposition les différentes pages dont vous avez besoin pour effectuer une action, il est possible d'afficher chacune d'entre elles dans un [[Wikipedia-fr:Onglet_%28informatique%29|onglet]] du navigateur.&lt;br /&gt;
Lorsque vous effectuez un clic gauche sur un lien situé dans une page donnée pour accéder à une autre page, la page initiale est remplacée par la page de destination. Ce qui rend fastidieux la réalisation des tâches nécessitant un accès répétitif à certaines pages.&lt;br /&gt;
&lt;br /&gt;
==Clic droit et clic molette==&lt;br /&gt;
[https://www.youtube.com/watch?v=kUvWhUXyC5Q&amp;amp;ab_channel=OpenFlyers Vidéo tutorielle présentant l'ouverture dans un nouvel onglet]&lt;br /&gt;
&lt;br /&gt;
Afin de gagner en efficacité et en confort d'utilisation, pensez à utiliser les autres boutons de la souris qui vous permettent d'ouvrir une page dans un '''nouvel onglet'''. Pour cela il existe deux méthodes lorsqu'on survole un lien dans un navigateur Internet pour ouvrir la page de destination dans un nouvel onglet :&lt;br /&gt;
*'''Le clic droit :''' il permet d'afficher un menu contextuel qui contient une action nommée « Ouvrir le lien dans un nouveau onglet ».&lt;br /&gt;
*'''Le clic molette :''' il est encore plus efficace que le clic droit, car il correspond directement à l'action « Ouvrir le lien dans un nouveau onglet ».&lt;br /&gt;
&lt;br /&gt;
Normalement le clic molette est configuré pour cette action. Dans le cas contraire, il faut [[Trucs et astuces#Modifier_le_comportement_la_souris|en modifier le comportement]].&lt;br /&gt;
&lt;br /&gt;
[[File:OF3.5-clics-1.png]]&lt;br /&gt;
&lt;br /&gt;
L'exemple suivant explique comment modifier successivement les validités de plusieurs utilisateurs :&lt;br /&gt;
*Dans un premier onglet, ouvrir le tableau présentant la liste des utilisateurs.&lt;br /&gt;
[[File:OF3.5-clics-2.png]]&lt;br /&gt;
*Effectuer un '''clic droit''' ou '''clic molette''' sur le pictogramme des validités pour déplier un second onglet.&lt;br /&gt;
[[File:OF3.5-clics-3.png]]&lt;br /&gt;
*Effectuer et enregistrer les modifications dans le second onglet, présentant les validités d'un utilisateur.&lt;br /&gt;
[[File:OF3.5-clics-4.jpg]]&lt;br /&gt;
*Replier le second onglet en cliquant sur la croix ou en pressant '''CTRL + W'''.&lt;br /&gt;
[[File:OF3.5-clics-5.png]]&lt;br /&gt;
*Retour au premier onglet, présentant la liste des utilisateurs. Répéter les opérations du 2 au 4 pour les autres utilisateurs concernés.&lt;br /&gt;
&lt;br /&gt;
Il est possible de naviguer rapidement d'un onglet à l'autre sans utiliser la souris en utilisant simplement les raccourcis clavier : '''CTRL + TAB''' pour avancer d'un onglet ou '''CTRL + SHIFT + TAB''' pour reculer d'un onglet.&lt;br /&gt;
&lt;br /&gt;
[[File:OF3.5-clics-6.png]]&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Documents&amp;diff=12884</id>
		<title>Documents</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Documents&amp;diff=12884"/>
		<updated>2024-10-02T17:27:51Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter les fonctionnalités utilisateurs permettant d'accéder aux documents stockés sur une plateforme OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
Les gestionnaires peuvent consulter la page de [[gestion des documents]].&lt;br /&gt;
&lt;br /&gt;
=Utilisation=&lt;br /&gt;
L'utilisateur peut accéder aux documents rattachés à chaque ressource depuis le planning (interface légère). Il faut survoler la ressource avec la souris et choisir parmi les documents disponibles en cliquant sur le document souhaité.&lt;br /&gt;
[[File:doc-planning.png|400px|center]]&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Cr%C3%A9er-une-plateforme-OpenFlyers-pour-sa-structure&amp;diff=12883</id>
		<title>Créer une plateforme OpenFlyers pour sa structure</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Cr%C3%A9er-une-plateforme-OpenFlyers-pour-sa-structure&amp;diff=12883"/>
		<updated>2024-10-02T17:27:50Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Le processus de création de plateforme est complètement automatisé.&lt;br /&gt;
&lt;br /&gt;
Il en est de même pour la prise d'abonnement, sauf dans le cas d'un paiement pas chèque ou par virement qui nécessitent un traitement manuel. Aussi, il est nécessaire d'informer la SARL OpenFlyers par email lors d'un virement afin qu'il soit pris en compte.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Création de [[Compte-client-OpenFlyers-et-modèle-commercial|compte client]] et de plateforme=&lt;br /&gt;
Cette procédure est gratuite et vous pouvez rester en [[Compte-client-OpenFlyers-et-modèle-commercial#Plateforme-en-test|test]] aussi longtemps que vous le souhaitez.&lt;br /&gt;
&lt;br /&gt;
La création d'une plateforme OpenFlyers se fait depuis le site vitrine [https://openflyers.com/ openflyers.com].&lt;br /&gt;
&lt;br /&gt;
Il faut ensuite cliquer en haut à droite sur le bouton '''s'inscrire'''.&lt;br /&gt;
&lt;br /&gt;
La page de création de compte doit alors apparaitre :&lt;br /&gt;
&lt;br /&gt;
[[File:création_de_compte_français.png|center|thumb|Formulaire de création de compte et de plateforme|upright=3]]&lt;br /&gt;
&lt;br /&gt;
Si certains champs sont invalides, différents messages d'alertes sont affichées (voir plus bas).&lt;br /&gt;
&lt;br /&gt;
Lors de la création de votre plateforme, une recopie de la plateforme de démonstration est effectuée vers la nouvelle plateforme créée et également, vers une [[#Plateforme-supplémentaire-de-test|seconde plateforme de test]]. Si dans le champ '''Activité principale''', a été sélectionné '''Propriétaire(s) privé(s) d'aéronef''' alors une recopie de la plateforme de démonstration pour abonnement '''SOLO''' est effectuée.&lt;br /&gt;
&lt;br /&gt;
Une fois que le formulaire est renseigné, la page suivante s'affiche :&lt;br /&gt;
&lt;br /&gt;
[[File:e-mail_confirmation_flouté.png|center|thumb|message d'envoi d'e-mail|upright=3]]&lt;br /&gt;
&lt;br /&gt;
Elle invite à consulter la boite de messagerie associée à l'adresse e-mail qui a été communiquée pour confirmer la création de votre compte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
''Messages d'alertes possibles au dessus du formulaire si des champs sont manquants ou invalides :''&lt;br /&gt;
*Lorsqu'un des champs est vide le message '''Champ vide : ''[champ]'' ''' apparaît &lt;br /&gt;
*Lorsque le champ '''Nom de la structure''' est invalide : '''Ce nom de structure contient un ou plusieurs mots interdits'''&lt;br /&gt;
*Lorsque le champ '''Nom de domaine de la plateforme''' contient des caractères interdits : '''Le nom de domaine doit seulement comporter des lettres en minuscule et/ou des chiffres/tirets et ne commencer que par une lettre'''&lt;br /&gt;
*Lorsque le champ '''Nom de domaine de la plateforme''' est déjà utilisé : '''Ce domaine est déjà utilisé ou plusieurs mots-clés interdits'''&lt;br /&gt;
*Lorsque le champ '''Email''' ne contient pas une bonne adresse : '''Email invalide'''&lt;br /&gt;
&lt;br /&gt;
=E-mail de demande de confirmation de création de plateforme=&lt;br /&gt;
Le message envoyé a pour objet &amp;quot;plateforme de test OpenFlyers&amp;quot;, et se présente comme suit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Bonjour,&lt;br /&gt;
&lt;br /&gt;
Ceci est un e-mail généré automatiquement par nos serveurs.&lt;br /&gt;
&lt;br /&gt;
Nous avons le plaisir de vous confirmer la création de compte client sur http://client.openflyers.com/.&lt;br /&gt;
&lt;br /&gt;
Veuillez trouver ci-dessous les identifiants vous permettant de vous y connecter :&lt;br /&gt;
Identifiant : demo-fr&lt;br /&gt;
Mot de passe : XXXXXX&lt;br /&gt;
&lt;br /&gt;
Merci de confirmer la création de votre plateforme openflyers.com/demo-fr, en cliquant sur ce lien :&lt;br /&gt;
https://client.openflyers.com/confirmSubscription.php?ofName=demo-fr&amp;amp;ofRelease=3&amp;amp;key=15a151bf1561e&lt;br /&gt;
&lt;br /&gt;
Pour tout question, n'hésitez pas à contacter notre service commercial qui est à votre disposition du lundi au vendredi de 9h à 12h et de 13h à 17h : 05.35.54.58.18 ou bien selon l'un des moyens proposés ici :&lt;br /&gt;
https://openflyers.com/support&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cliquer sur le lien contenu dans cet e-mail pour activer la création.&lt;br /&gt;
&lt;br /&gt;
L'écran suivant s'ouvre et confirme que la plateforme est en cours de création :&lt;br /&gt;
&lt;br /&gt;
[[File:Création_de_compte_en_cours_français.png|center|thumb|Ecran de confirmation de plateforme|upright=3]]&lt;br /&gt;
&lt;br /&gt;
Un second e-mail est envoyé avec pour objet &amp;quot;plateforme de test OpenFlyers&amp;quot; qui confirme la création de la plateforme :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Votre plateforme a été créée et est accessible à cette adresse :&lt;br /&gt;
http://openflyers.com/demo-fr/&lt;br /&gt;
&lt;br /&gt;
Veuillez attendre 5 minutes avant d'accéder à votre plateforme, le temps que l'installation soit totalement terminée.&lt;br /&gt;
&lt;br /&gt;
Votre plateforme est la recopie d'une plateforme de démonstration. Par défaut les identifiants sont :&lt;br /&gt;
Identifiant : admini&lt;br /&gt;
Mot de passe : azerty&lt;br /&gt;
&lt;br /&gt;
Vous trouverez de plus amples explications sur cette plateforme de démonstration à cette adresse :&lt;br /&gt;
https://openflyers.com/fr/doc/of4/Découvrir-OpenFlyers&lt;br /&gt;
&lt;br /&gt;
Attention : votre plateforme est en phase de test et par conséquent les réservations et les factures sont susceptibles d'être effacées à tout moment.&lt;br /&gt;
&lt;br /&gt;
N'hésitez pas à contacter notre service commercial qui se fera un plaisir de vous assister et de répondre à vos questions du lundi au vendredi de 9h à 12h et de 13h à 17h : 05.35.54.58.18&lt;br /&gt;
&lt;br /&gt;
Si vous souhaitez passer en production et ainsi utiliser notre solution avec des réservations et des factures réelles, souscrivez à l'un des abonnements proposés en vous connectant sur notre espace client :&lt;br /&gt;
https://client.openflyers.com&lt;br /&gt;
&lt;br /&gt;
Vous trouverez de plus amples explications à cette adresse :&lt;br /&gt;
https://openflyers.com/fr/doc/of4/Créer-une-plateforme-OpenFlyers-pour-sa-structure#Prise-d'abonnement&lt;br /&gt;
&lt;br /&gt;
Vous pouvez aussi nous contacter selon l'un des moyens proposés à cette adresse :&lt;br /&gt;
https://openflyers.com/support&lt;br /&gt;
&lt;br /&gt;
L'équipe OpenFlyers&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Prise d'abonnement=&lt;br /&gt;
Pour passer en production et ainsi lancer le paramétrage (hors abonnement Solo) de la plateforme par l'équipe OpenFlyers, il faut [[Compte-client-OpenFlyers-et-modèle-commercial#Renouveler-l'abonnement-OpenFlyers|lancer la facturation]] depuis l'espace client OpenFlyers : https://client.openflyers.com&lt;br /&gt;
&lt;br /&gt;
Cf. [[Compte-client-OpenFlyers-et-modèle-commercial#Accéder-à-l'espace-client-OpenFlyers|Accéder à l'espace client OpenFlyers]].&lt;br /&gt;
&lt;br /&gt;
'''Attention :''' le [[Bien-débuter-avec-OpenFlyers#Forfait-paramétrage|forfait paramétrage]] est obligatoire dans la 1ère prise d'abonnement. Il est d'ailleurs inclus dans les abonnements Business et Business+.&lt;br /&gt;
&lt;br /&gt;
A noter également que le passage en production impacte la base de données lors de la mise en œuvre du paramétrage par OpenFlyers : toutes les données déjà saisies sont susceptibles d'être écrasées pour repartir sur une base de données vierge.&lt;br /&gt;
&lt;br /&gt;
Si les données de la plateforme de test doivent être conservées, alors il faut créer une nouvelle plateforme et passer en production sur cette dernière.&lt;br /&gt;
&lt;br /&gt;
=[[Formations OpenFlyers|Formations OpenFlyers]]=&lt;br /&gt;
&lt;br /&gt;
=[[Compte-client-OpenFlyers-et-modèle-commercial#Plateforme-supplémentaire-de-test-(bac-à-sable)|Plateforme supplémentaire de test (bac à sable)]]=&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Conseils-sp%C3%A9cifiques-pour-la-comptabilit%C3%A9&amp;diff=12882</id>
		<title>Conseils spécifiques pour la comptabilité</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Conseils-sp%C3%A9cifiques-pour-la-comptabilit%C3%A9&amp;diff=12882"/>
		<updated>2024-10-02T17:27:50Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter nos conseils sur la [[Comptabilité|comptabilité]]&lt;br /&gt;
&lt;br /&gt;
Les associations à but non lucratif sont tenues de tenir une comptabilité conformément au [https://www.anc.gouv.fr/files/live/sites/anc/files/contributed/ANC/1_Normes_fran%c3%a7aises/Reglements/2018/Reglt_2018_06/Reglt_2018_06_Asso_version_commentaires-fev-2021.pdf RÈGLEMENT N° 2018-06 du 5 décembre 2018 Relatif aux comptes annuels des personnes morales de droit privé à but non lucratif Version intégrant l’article 1er du règlement ANC n° 2019-04 et le règlement ANC n° 2020-08].&lt;br /&gt;
&lt;br /&gt;
=Baptêmes dans un aéro-club=&lt;br /&gt;
Dans un aéro-club, les baptêmes ne doivent pas dépasser pas 8% de l'activité (cf. [http://www.legifrance.gouv.fr/affichCodeArticle.do;?cidTexte=LEGITEXT000006074234&amp;amp;idArticle=LEGIARTI000006844019&amp;amp;dateTexte=20140707&amp;amp;categorieLien=id#LEGIARTI000006844019 Article D510-7 du code de l'aviation civile]). Aussi, nous déconseillons de mettre en place les tarifs des baptêmes qui engendrent plus d'erreurs de saisies qu'autre chose. Par contre, dans le cas d'une société commerciale et notamment si la saisie des vols est entre les mains d'un nombre réduit de personnes, alors la facturation des baptêmes peut être mise en place. Voici donc comment nous conseillons de gérer les baptêmes dans OpenFlyers pour un aéro-club.&lt;br /&gt;
&lt;br /&gt;
==[[Configuration de la comptabilité#Gestion_des_baptêmes|Paramétrage préconisé pour gérer les baptêmes de l'air d'un aéro-club]]==&lt;br /&gt;
&lt;br /&gt;
==[[Utilisation de la comptabilité#Gestion_des_baptêmes|Utilisation pratique du paramétrage préconisé des baptêmes de l'air d'un aéro-club]]==&lt;br /&gt;
&lt;br /&gt;
==Bons baptêmes payés et non effectués==&lt;br /&gt;
Quelque soit le statut commercial de la structure aéronautique (association ou société), voici comment nous conseillons de gérer les bons baptêmes :&lt;br /&gt;
*Enregistrer dans OpenFlyers uniquement l'encaissement du bon sans saisir de vente (et donc ne pas créer de produit pour cela)&lt;br /&gt;
*Lorsque le baptême est effectué, saisir le vol : cela génère la facture selon le paramétrage&lt;br /&gt;
Lors de la clôture de l'exercice, il suffit de contrôler le compte &amp;quot;client baptême&amp;quot; et de le comparer avec les dates de remise des bons baptêmes. C'est alors que doit être décidé si un bon ne sera jamais utilisé. Auquel cas, une écriture spécifique est à prévoir comptablement.&lt;br /&gt;
&lt;br /&gt;
==Contrôle du quota d'heures baptêmes==&lt;br /&gt;
Pour vérifier que l'activité baptême de l'aéro-club ne dépasse pas les 8% des heures de vols, il faut utiliser les rapports pour contrôler le pourcentage d'heures de vols baptêmes par rapport au total des heures de vols.&lt;br /&gt;
&lt;br /&gt;
=Cautions=&lt;br /&gt;
Le principe de la caution est de demander, lors de l'inscription en général, un montant de X € à l'utilisateur qui est mis en réserve et remboursé lorsqu'il quitte la structure.&lt;br /&gt;
&lt;br /&gt;
Cette somme doit être encaissée normalement sur son compte utilisateur.&lt;br /&gt;
&lt;br /&gt;
Par contre, elle doit également générer une &amp;quot;facture&amp;quot; qui va débiter son compte utilisateur du montant de la caution et créditer un [[Comptabilité#Comptes_d'emprunts_et_de_dettes_assimilées|compte d'emprunts de dettes assimilées]] pour &amp;quot;stocker&amp;quot; la caution. Ce compte de caution est en général en 165000.&lt;br /&gt;
&lt;br /&gt;
Il est possible de mettre en place la vente d'un produit &amp;quot;Caution&amp;quot; qui génère automatiquement l'écriture entre le compte utilisateur et le compte de caution.&lt;br /&gt;
&lt;br /&gt;
=Comptes à terme, Livret A=&lt;br /&gt;
Il faut créer autant de compte comptable qu'il y a de comptes bancaires. L'extrait de chaque compte en comptabilité doit être le reflet exact du relevé de compte fourni par la banque.&lt;br /&gt;
&lt;br /&gt;
Les intérêts générés par chaque compte doivent faire l'objet d'une écriture comptable séparée.&lt;br /&gt;
&lt;br /&gt;
Les comptes bancaires doivent avoir pour racine 512 dans le plan comptable à la française.&lt;br /&gt;
&lt;br /&gt;
=Cotisation des adhérents dans une association=&lt;br /&gt;
Le produit de la cotisation des adhérents à l'association doivent aller au crédit du compte de produit 756100 ''Cotisation sans contrepartie'' ou 756200 ''Cotisation avec contrepartie''.&lt;br /&gt;
&lt;br /&gt;
Est considérée comme une cotisation sans contrepartie si la cotisation donne juste le droit de participer à l'assemblée générale de l'association.&lt;br /&gt;
&lt;br /&gt;
Cf. Art. 142-1 du [https://www.anc.gouv.fr/files/live/sites/anc/files/contributed/ANC/1_Normes_fran%c3%a7aises/Reglements/2018/Reglt_2018_06/Reglt_2018_06_Asso_version_commentaires-fev-2021.pdf RÈGLEMENT N° 2018-06 du 5 décembre 2018 Relatif aux comptes annuels des personnes morales de droit privé à but non lucratif]&lt;br /&gt;
&lt;br /&gt;
=Cotisations fédérales des adhérents dans une association=&lt;br /&gt;
La gestion des cotisations fédérales des adhérents dans OpenFlyers dépend de plusieurs facteurs.&lt;br /&gt;
*Si les cotisations fédérales sont souscrites par les adhérents directement auprès des fédérations concernées et qu'il n'y a pas de mouvement financier au travers de l'association, alors il n'y a pas à mettre en place comptablement de gestion. Par contre, il peut être nécessaire de [[Paramétrage des validités|gérer les types de validités]] correspondantes dans OpenFlyers notamment lorsque les cotisations fédérales inclues des assurances pour la pratique de l'activité. Dans ce cas là, il faut également voir avec l'équipe OpenFlyers s'il n'existe pas un système automatique de mise à jour dans OpenFlyers depuis le système de gestion des fédérations concernées.&lt;br /&gt;
*Si les cotisations fédérales sont souscrites par les adhérents auprès de l'association et que par conséquent l'association leur facture comptablement ces cotisations, alors il faut mettre en place dans OpenFlyers la [[Gestion des produits et des ventes#Configuration_du_produit_Validité|vente de produits validités]] correspondante.&lt;br /&gt;
*:Dans ce cas là, il y a également la question de la gestion des &amp;quot;factures fournisseurs&amp;quot; des fédérations. 2 cas possibles :&lt;br /&gt;
*#Si OpenFlyers n'est utilisé que pour gérer la &amp;quot;facturation client&amp;quot;, c'est à dire le chiffre d'affaire, alors la saisie des factures fédérales doit se faire dans le logiciel de gestion comptable.&lt;br /&gt;
*#Si OpenFlyers est utilisé pour gérer l'intégralité de la comptabilité courante de la structure, alors il faudra [[Gestion des achats#Saisie_d'une_facture_fournisseur|saisir les factures des fédérations en tant que facture fournisseur]]. Comptablement les choses sont hermétiques entre :&lt;br /&gt;
*#*d'un côté, la vente d'une cotisation d'une fédération à un adhérent qui va impacter son [[Comptabilité#Comptes_clients|compte client]] et un [[Comptabilité#Comptes_de_produits|compte produit]].&lt;br /&gt;
*#*de l'autre côté, l'achat de la même cotisation auprès de la fédération pour cet adhérent qui va impacter le [[Comptabilité#Comptes_fournisseurs|compte fournisseur]] de la fédération et un [[Comptabilité#Comptes_de_charges|compte de charge]].&lt;br /&gt;
*:A noter que pour ce qui concerne la saisie de la facture fournisseur de la fédération, il y a 2 méthodes expliquées dans le chapitre [[Écritures-comptables#Achat-direct|achat direct]].&lt;br /&gt;
Dans certaines structures, la prise de cotisation après une certaine date dans l'année, permet de bénéficier de la cotisation jusqu'au 31 décembre de l'année suivante. Cela se gère au travers de la formule de calcul de la date d'expiration dans '''Ventes &amp;gt; Validités à vendre'''. Cf. [[Formules-de-calcul#Exemples-de-formules-de-calcul-de-la-date-d'expiration|les exemples de formules de calcul de la date d'expiration]].&lt;br /&gt;
&lt;br /&gt;
=Cotisations/abonnements année N+1=&lt;br /&gt;
Certaines cotisations ou abonnements peuvent être facturées sur l'année précédente de leur date d'effet. Comptablement, ces factures clients doivent apparaitre sur l'exercice où elles ont été établies. Cependant, il est souvent nécessaire de séparer leur produit des cotisations ou abonnements de l'année N afin de pouvoir les sortir du chiffre d'affaire de l'année N.&lt;br /&gt;
&lt;br /&gt;
Voici comment gérer cela dans OpenFlyers :&lt;br /&gt;
*Nous supposons qu'il existe déjà un compte produit ''Cotisation'' dont le compte d'export est par exemple ''706100''.&lt;br /&gt;
*Il faut créer un 2ème compte produit intitulé ''Cotisation N+1'' dont le compte d'export sera par exemple ''706110''.&lt;br /&gt;
*Dans '''Ventes &amp;gt; Facturation des produits''', il faut créer une nouvelle ligne de facturation qui va transférer le crédit au profit du compte produit &amp;quot;Cotisation&amp;quot; vers le comptes produit &amp;quot;Cotisation N+1&amp;quot;. De plus, ce transfert ne devra s'applique que lorsqu'on est dans la période de renouvellement anticipé. Voici un exemple de règle de facturation lorsque la cotisation peut être pris de façon anticipée à partir du mois d'octobre :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Champ!!Ligne Cotisation N+1&lt;br /&gt;
|-&lt;br /&gt;
|'''Nom'''||Cotisation N+1&lt;br /&gt;
|-&lt;br /&gt;
|'''Quantité/Taux'''||&lt;br /&gt;
|-&lt;br /&gt;
|'''Prix unitaire hors-taxe / TVA'''||&lt;br /&gt;
|-&lt;br /&gt;
|'''Formule'''||(formatDate('MM',%NOW_DATE)&amp;gt;9)?@tarifGeneral:0&lt;br /&gt;
|-&lt;br /&gt;
|'''Nom de variable associé à la formule'''||tarifGeneral&lt;br /&gt;
|-&lt;br /&gt;
|'''Produit'''||''Cocher uniquement les produits concernés. Normalement, il s'agit de la même liste de produit que pour la règle &amp;quot;parente&amp;quot; Cotisation.&lt;br /&gt;
|-&lt;br /&gt;
|'''Type de compte à débiter'''||Compte produit&lt;br /&gt;
|-&lt;br /&gt;
|'''Compte à débiter'''||Cotisation&lt;br /&gt;
|-&lt;br /&gt;
|'''Type de compte à créditer'''||Compte produit&lt;br /&gt;
|-&lt;br /&gt;
|'''Compte produit à créditer'''||Cotisation N+1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Si la structure applique une remise sur cotisation sur certains critères, comme par exemple l'âge, il faut que la règle appliquant la remise s'applique avant la règle ci-dessus de ventilation. De plus, il faut que la règle de remise stocke son calcul dans une [[Facturation des clients#Facturation-des-clients#Fonctionnement-des-variables-associées-aux-formules-de-facturation|variable associée à la formule]] comme par exemple @remise pour que la remise soit prise en compte pour la ventilation N+1. Voici un exemple de construction de ces règles en cascade :&lt;br /&gt;
[[File:Tarification_cotisation_N+1.png]]&lt;br /&gt;
&lt;br /&gt;
*En fin d'année, avant la clôture de la comptabilité, il faudra effectuer une [[Écritures comptables#Écritures_de_transfert_des_produits_et_charges_constatées_d'avance|opération comptable pour transférer le solde du compte produit N+1 dans un compte de ''produit constaté d’avance'']]&lt;br /&gt;
*Puis, après l'ouverture de la comptabilité, il faudra [[Écritures comptables#Écritures_de_réaffectation_des_produits/charges_constatées_d'avances|transférer le même montant du compte ''produit constaté d’avance'' vers le compte produit de l'année N]].&lt;br /&gt;
&lt;br /&gt;
=Dons=&lt;br /&gt;
Ce chapitre décrit les opérations comptables pour un don de la structure en faveur d'un tiers. Pour les dons reçus par la structure, il faut voir le chapitre [[#Subventions|Subventions]].&lt;br /&gt;
&lt;br /&gt;
Enregistrement d'un don effectué par la structure en faveur d'un tiers :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Compte!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Tiers percevant le don (401...)||||1000 €&lt;br /&gt;
|-&lt;br /&gt;
|Divers (pourboires, dons courants...) (6238)||1000 €||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Le compte de charge ''Divers (pourboires, dons courants...) (6238)'' peut être remplacé par le compte de charge exceptionnelle ''Dons, libéralités (6713)''.&lt;br /&gt;
&lt;br /&gt;
Lorsque le don est décaissé par la structure :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Compte!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Banque (512)||||1000 €&lt;br /&gt;
|-&lt;br /&gt;
|Tiers percevant le don (401...)||1000 €||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Droit d'entrée=&lt;br /&gt;
Le droit d’entrée versé par un membre d'une association doit poursuivre un des trois objectifs suivants et cela doit être défini dans les statuts :&lt;br /&gt;
*financer l’entité, il est alors assimilé à un dépôt restituable.  Le produit est affecté sur le compte de bilan 1032 ''Fonds statutaires''&lt;br /&gt;
*renforcer les fonds propres de l’entité. Le produit est affecté sur le compte de bilan 1022 ''Fonds statutaires''&lt;br /&gt;
*être constitutif d’un produit. Le produit est affecté sur un compte de produit.&lt;br /&gt;
&lt;br /&gt;
Cf. Art. 142-2 du [https://www.anc.gouv.fr/files/live/sites/anc/files/contributed/ANC/1_Normes_fran%c3%a7aises/Reglements/2018/Reglt_2018_06/Reglt_2018_06_Asso_version_commentaires-fev-2021.pdf RÈGLEMENT N° 2018-06 du 5 décembre 2018 Relatif aux comptes annuels des personnes morales de droit privé à but non lucratif]&lt;br /&gt;
&lt;br /&gt;
=Encaissements &amp;quot;test&amp;quot; (type PayPal)=&lt;br /&gt;
Certains organismes, pour vérifier la véracité des informations déclarées, effectuent un virement test de quelques centimes sur le compte bancaire qu'on leur communique. C'est le cas, par exemple, de PayPal lors de l'ouverture d'un compte chez eux.&lt;br /&gt;
&lt;br /&gt;
Le virement peut être enregistré comptablement de la façon suivante :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Compte!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Banque (512)||0,15 €||&lt;br /&gt;
|-&lt;br /&gt;
|Produits divers de gestion courante (758...)||||0,15 €&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Facturation automatique à des organismes avec ou sans quotas=&lt;br /&gt;
Certains utilisateurs finaux peuvent appartenir à des organismes (Entreprises, Comités d'entreprises, établissements publics etc.) qui prennent en charge soit une partie soit la totalité du coût d'une activité avec ou sans des limitations (quotas en heures d'activité ou en montant).&lt;br /&gt;
&lt;br /&gt;
Il est possible de mettre en place sur une plateforme OpenFlyers un paramétrage comptable spécifique qui déclenchera la facturation automatiquement auprès de l'organisme devant être réellement facturé. Cela présente comme avantages :&lt;br /&gt;
*De ne pas avoir à passer systématiquement et manuellement des écritures de transfert de facturation entre comptes clients.&lt;br /&gt;
*D'avoir directement sur le compte client de l'organisme concerné l'ensemble des débits à sa charge et ainsi de pouvoir déterminer le montant du paiement global qu'il doit effectuer.&lt;br /&gt;
&lt;br /&gt;
La mise en place du paramétrage comptable repose sur 2 éléments :&lt;br /&gt;
*un suivi (le cas échéant) des quotas d'heures d'activités/montants au travers de la mise en place d'une comptabilité en heures/euros séparée de la comptabilité générale. Ce mécanisme est identique dans son principe à celui mis en place pour la [[#Packs_d'heures_d'activités|gestion des packs d'heures]]. Simplement, le &amp;quot;rechargement&amp;quot; du compte &amp;quot;quota&amp;quot; de l'utilisateur concerné ne se fait pas lors de la vente d'un pack mais lors du renouvellement d'une cotisation.&lt;br /&gt;
*une cascade d'écritures comptables permettant de débiter l'organisme en lieu et place de l'utilisateur&lt;br /&gt;
&lt;br /&gt;
Les utilisateurs dépendant d'un organisme X doivent être identifiés dans OpenFlyers grâce à un profil spécifique et [[Gestion-des-profils#Profil-non-sélectionnable-par-l'utilisateur|non sélectionnable par l'utilisateur]].&lt;br /&gt;
&lt;br /&gt;
A l'usage, les choses se déroulent concrètement dans l'ordre suivant :&lt;br /&gt;
#L'utilisateur saisit son activité dans OpenFlyers =&amp;gt; automatiquement la ventilation des écritures se fait. Si l'utilisateur dispose d'un quota positif d'heures/d'argent, voir même d'un quota illimité, alors c'est le compte de son organisme de rattachement qui est débité au lieu de son compte. Il est également possible de &amp;quot;mixer&amp;quot;. C'est à dire que si l'organisme de rattachement ne prend en charge qu'une partie du coût, OpenFlyers calculera automatiquement qui paie quoi et débitera chaque compte en conséquence.&lt;br /&gt;
#Le gestionnaire de la structure envoie la liasse de factures ou un relevé d'activités général mensuellement/trimestriellement à l'organisme considéré. Ces éléments sont disponibles dans OpenFlyers.&lt;br /&gt;
#Le gestionnaire de la structure reçoit le paiement de l'organisme qu'il saisit directement dans OpenFlyers comme un encaissement normal qui va créditer le compte client de l'organisme considéré.&lt;br /&gt;
&lt;br /&gt;
Ainsi, le gestionnaire n'a que 2 actions à faire :&lt;br /&gt;
#Générer le relevé d'activités ou la liasse de factures et l'envoyer par e-mail&lt;br /&gt;
#Saisir l'encaissement de l'organisme payeur&lt;br /&gt;
&lt;br /&gt;
=Forfaits découverte=&lt;br /&gt;
Les forfaits découverte consistent à vendre à un prix réduit plusieurs produits lors d'une première inscription ou pré-inscription dans une structure. Typiquement, dans le cas d'une structure aéronautique, les forfaits découvertes regroupent en général :&lt;br /&gt;
*La cotisation&lt;br /&gt;
*L'assurance/Licence Fédérale&lt;br /&gt;
*Un certain nombre d'heures d'instruction&lt;br /&gt;
&lt;br /&gt;
''Pour les associations à but non lucratifs qui bénéficient d'exemption fiscale, OpenFlyers recommande, avant leur mise en place, de se rapprocher du fisc afin de vérifier la comptabilité de cette offre qui pourrait être considérée comme une remise commerciale et entrainer la requalification fiscale de l'association.''&lt;br /&gt;
&lt;br /&gt;
Pour la gestion comptable du forfait découverte dans OpenFlyers, le plus simple consiste à vendre normalement chaque produit &amp;quot;physique&amp;quot; :&lt;br /&gt;
*Cotisation&lt;br /&gt;
*Assurance/Licence Fédérale&lt;br /&gt;
A enregistrer l'encaissement (par exemple Forfait découverte vendu 500 €) et ensuite à calculer la remise auquel à droit l'utilisateur en regardant son solde de compte et en le comparant avec le nombre d'heures auquel il a droit. En effet, bien souvent, la remise va être différente en fonction du montant payé pour la cotisation qui lui-même peut varier en fonction de l'âge ou de la date de prise de cotisation.&lt;br /&gt;
&lt;br /&gt;
Exemple de calcul pour un forfait découverte à 500 € qui donne droit à :&lt;br /&gt;
*1 cotisation normalement facturée 120 €&lt;br /&gt;
*1 licence fédérale normalement facturée 80 €&lt;br /&gt;
*3 heures de vols normalement facturés 120 €/h&lt;br /&gt;
Après l'enregistrement de la cotisation, de la licence et l'encaissement des 500 €, le solde du compte pilote est de 500-120-80 = 300 €.&lt;br /&gt;
&lt;br /&gt;
La personne en charge de la saisie, calcule :&lt;br /&gt;
*le montant normalement facturé pour les 3 heures de vols : 3 x 120 € = 360 €&lt;br /&gt;
*Détermine la remise à enregistrer en comptabilité au vu du solde du compte : 360 € - 300 € = 60 €&lt;br /&gt;
&lt;br /&gt;
Elle doit enregistrer ensuite un flux comptable qui va créditer le compte pilote de 60 € et débiter un compte de charge &amp;quot;remise inscription&amp;quot; de 60 €.&lt;br /&gt;
&lt;br /&gt;
Ainsi le solde du compte pilote est de 360 € à l'issue de ces saisies. Lorsque les 3 heures de vols seront effectuées, il sera bien à 0 €.&lt;br /&gt;
&lt;br /&gt;
L'intérêt de cette méthode est :&lt;br /&gt;
*d'enregistrer une fois pour toute la remise et ensuite de ne plus avoir à s'en soucier&lt;br /&gt;
*de permettre que les heures de vols réellement effectuées ne correspondent pas exactement au nombre attribué par le Forfait découverte et permette ainsi un dépassement qui rentrera le montant normalement facturé des heures de vols.&lt;br /&gt;
&lt;br /&gt;
=Packs d'heures d'activités=&lt;br /&gt;
OpenFlyers propose un système de comptabilités multiples dans son [[Configuration de la comptabilité#Paramétrage_général_des_comptabilités|paramétrage général des comptabilités]]. Ce système permet de mettre en place plusieurs comptabilités à la fois. Ainsi, on peut avoir une comptabilité en euros et une comptabilités en heures. La comptabilité en heures, permet de gérer des crédits d'heures d'activités qui sont mis en ventes sous la forme de packs d'heures d'activités.&lt;br /&gt;
&lt;br /&gt;
'''Attention''' : ce système de packs d'heures d'activités n'est pas adapté aux produits de type [[#Forfaits-découverte|Forfaits découverte]]. En effet, le paramétrage de packs d'heures d'activités induisent la création de comptabilités supplémentaires, en heures de vols, pour générer les crédits d'heures des utilisateurs. De ce fait cela rajoute des comptes, en heures, pour tous les utilisateurs et cela alourdit donc visuellement l'interface. Or, les forfaits découverte sont destinés à 1 seule utilisation maximum par utilisateur. Il n'est donc pas souhaitable de polluer visuellement l'interface pour un usage non récurrent. Alors qu'à l'inverse, dans le cas des packs d'heures, la vue de ces comptes agit comme un moyen de communication et d'appropriation du concept de packs d'heures auprès des utilisateurs.&lt;br /&gt;
&lt;br /&gt;
==Fonctionnement d'un exemple de configuration de vente de packs d'heures==&lt;br /&gt;
L'exemple est basé sur une structure qui propose 2 packs d'heures d'activités :&lt;br /&gt;
*un pack de 5 heures à 450 €&lt;br /&gt;
*un pack de 10 heures à 850 €&lt;br /&gt;
Le tarif d'une heure d'activité hors pack est à 100 €.&lt;br /&gt;
&lt;br /&gt;
===Achat d'un pack d'heures par un utilisateur===&lt;br /&gt;
un utilisateur achète un pack de 10 heures 850 euros :&lt;br /&gt;
*Son compte utilisateur en euro est débité de 850 euros : le solde de son compte est débiteur de 850 €.&lt;br /&gt;
*Son compte en heures est crédité de 10 heures.&lt;br /&gt;
Ensuite l'utilisateur paie son pack 850 € ce qui a pour effet de ramener le solde de son compte en euros à 0 €.&lt;br /&gt;
&lt;br /&gt;
===Saisie d'une activité pour un utilisateur bénéficiant d'heures créditées===&lt;br /&gt;
Lors de la saisie d'une activité de 1 heure, le compte en heures de l'utilisateur est débité de 1 heure. Le compte en euros de l'utilisateur n'est pas impacté : les heures ont été payées en amont lors de l'achat du pack.&lt;br /&gt;
&lt;br /&gt;
===Remboursement d'heures===&lt;br /&gt;
A titre commercial, une structure peut accepter de rembourser un utilisateur n'ayant pas épuisé ses heures. Dans ce cas, plusieurs méthodes commerciales sont possibles dont :&lt;br /&gt;
#Considérer le crédit d'heures restant au tarif de l'heure du pack (par exemple 85 €/h pour un pack de 10 heures à 850 €) : cela revient à faire un prorata du prix du pack&lt;br /&gt;
#Considérer que dans ce cas précis, les heures utilisées sont refacturables à leur tarif hors pack. Dans ce cas, il faut consulter l'histoire du compte pour trouver le dernier pack acheté (pack de 5h ou de 10h), en déduire le nombre d'heures utilisées sur ce pack en faisant la différence avec le crédit d'heures restant, calculer le coût des heures utilisées hors pack et rembourser de la différence du prix du pack.&lt;br /&gt;
Dans les 2 cas, il faut saisir 2 flux :&lt;br /&gt;
*Un flux qui va débiter le compte en heures de l'utilisateur et créditer le compte de bilan correspondant &amp;quot;Encours ...&amp;quot; du nombre d'heures choisi&lt;br /&gt;
*Un flux qui va créditer le compte en euros de l'utilisateur et débiter le compte de produit comptabilisant normalement la vente des packs d'heures correspondant. Le montant est le montant calculé comme indiqué ci-dessus en 1 ou en 2.&lt;br /&gt;
&lt;br /&gt;
===Solder un compte en heure présentant un très faible reliquat===&lt;br /&gt;
Il peut arriver qu'un compte en heures présente un reliquat très faible et qui apparait avec un solde à 0 mais sans l'icône poubelle permettant de désactiver ce compte. De plus, si on tente de saisir un flux pour solder ce reliquat, le flux n'est pas enregistré. De ce fait, on peut penser qu'il est impossible de supprimer ce compte.&lt;br /&gt;
&lt;br /&gt;
Pour sortir de l'impasse, voici la procédure :&lt;br /&gt;
*Saisir un flux entre le compte à supprimer et son compte de contre-partie naturel. En général, le compte de contre-partie naturel est un compte de bilan qui s'intitule &amp;quot;Encours...&amp;quot;. Pour en être sûr, il suffit de remonter dans l'historique des opérations du compte pour noter le compte de contre-partie qui était impacté.&lt;br /&gt;
*Sur la ligne du compte à supprimer cliquer sur l'icône représentant une balance pour que le montant du reliquat apparaisse en débit ou en crédit. Il doit être de la forme ''0,0123''.&lt;br /&gt;
*Rajouter une unité au montant du reliquat. Ainsi, ''0,0123'' devient ''1,0123''.&lt;br /&gt;
*Sur la 2ème ligne contrant le compte de contre-partie, cliquer sur l'icône balance avec une flèche pour équilibrer le flux.&lt;br /&gt;
*Indiquer la bonne date comptable&lt;br /&gt;
*Valider&lt;br /&gt;
Le flux est bien saisi et le compte à supprimer présente désormais un solde exact de 1 ou -1.&lt;br /&gt;
*Saisir un nouveau flux entre le compte à supprimer et son compte de contre-partie naturel en ramenant tout simplement le solde de son compte à 0.&lt;br /&gt;
La 2ème écriture s'enregistre correctement et le solde du compte est exactement de 0. Il est donc possible de supprimer le compte après avoir validé les flux.&lt;br /&gt;
&lt;br /&gt;
==Initialisation du solde d'heures lors de la mise en place des packs==&lt;br /&gt;
Lors de la mise en place du système des packs sur une structure aéronautique déjà en activités, des packs peuvent avoir déjà été vendues et des heures effectuées. Dans ce cas, il faut juste saisir un flux entre le compte d'heures de l'utilisateur et le compte de bilan représentant l'encours des heures. Ce flux va créditer le compte d'heures de l'utilisateur de la valeur du nombre d'heures auxquelles il a encore droit.&lt;br /&gt;
&lt;br /&gt;
Exemple de saisie d'un flux :&lt;br /&gt;
&lt;br /&gt;
[[Image:Exemple-saisie-flux-pour-initialisation-solde-heures.png]]&lt;br /&gt;
&lt;br /&gt;
==Transférer des crédits d'heures d'un utilisateur sur un autre de ses comptes==&lt;br /&gt;
Généralement, chaque compte utilisateur dispose de sa propre comptabilité. Ainsi, le compte principal, en euros, est rattaché à la comptabilité en euros. De la même façon, si l'utilisateur dispose d'un compte &amp;quot;Crédit heures A&amp;quot; et d'un autre compte &amp;quot;Crédit heures B&amp;quot; alors le premier compte va être rattaché à une comptabilité A et le deuxième compte à une comptabilité B. Pour dire les choses autrement : on ne mélange pas les torchons avec les serviettes.&lt;br /&gt;
&lt;br /&gt;
Néanmoins, si commercialement, il est nécessaire de transférer le solde du compte &amp;quot;Crédit heures A&amp;quot; vers le compte &amp;quot;Crédit heures B&amp;quot;, alors il faut saisir 2 flux comptables :&lt;br /&gt;
*Un premier flux qui va [[Utilisation-de-la-comptabilité#Solder-un-compte|solder le compte]] &amp;quot;Crédit heures A&amp;quot; en débit le compte correspondant et en créditant le compte permettant de mesurer l'encourt total des heures en crédit et que l'on intitule généralement &amp;quot;Encours Heures A&amp;quot;. Pour trouver son intitulé exact, il suffit d'aller dans les comptes de bilan où ce compte doit être référencé.&lt;br /&gt;
*Un deuxième flux qui va effectuer l'opération en sens inverse : créditer le compte &amp;quot;Crédit heures B&amp;quot; et débiter le compte &amp;quot;Encours Heures B&amp;quot;.&lt;br /&gt;
Il est possible lors de la saisie de ce 2ème flux, d'appliquer un coefficient correctif au montant à créditer si les valeurs des heures entre A et B ne correspondent pas.&lt;br /&gt;
&lt;br /&gt;
Nous recommandons de mettre un intitulé qui permet d'expliquer la raison d'être de chaque flux.&lt;br /&gt;
&lt;br /&gt;
S'il y a beaucoup de comptes utilisateurs concernés, la multiplication des saisies de flux, peut s'avérer rapidement fastidieuse. Afin de limiter le temps consacré à cette saisie, nous recommandons alors d'effectuer 1 seule saisie de flux qui solde l'ensemble des comptes utilisateurs, en soldant tous les comptes utilisateurs concernés dans un seul flux qui contiendra en dernière ligne la contre-partie totale.&lt;br /&gt;
&lt;br /&gt;
[[Image:Saisir_un_flux_solde_multiple_de_comptes_heures.png]]&lt;br /&gt;
&lt;br /&gt;
Pour trouver facilement les comptes utilisateurs concernés, nous recommandons d'afficher dans un onglet du navigateur la liste des comptes de tous les utilisateurs et dans un autre onglet d'afficher l'interface de saisie de flux.&lt;br /&gt;
&lt;br /&gt;
De la même façon, pour le deuxième flux, nous recommandons de garder un onglet ouvert qui affiche le détail des montants soldés, en éditant l'écriture comptable précédente, et dans un autre onglet de saisir le deuxième flux.&lt;br /&gt;
&lt;br /&gt;
=Participation des adhérents à une auto-assurance=&lt;br /&gt;
Le versement par un membre d'une association à une caisse d'auto-assurance doit aller au crédit du compte de bilan 151 ''Provisions pour risques''.&lt;br /&gt;
&lt;br /&gt;
=Prêt des adhérents à l'association avec remboursement en numéraire=&lt;br /&gt;
Il s'agit d'argent prêté des membres à l'association, par exemple pour participer au financement de l'achat d'un nouvel aéronef.&lt;br /&gt;
&lt;br /&gt;
Il est considéré dans l'exemple ci-après que l'argent est prêté sans intérêt. Il s'agit d'un prêt de 5 000 € remboursé en 5 mensualités de 1 000 €.&lt;br /&gt;
&lt;br /&gt;
;Enregistrement comptable du prêt&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Compte!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Compte de l'adhérent X (411xxx)||5 000 €||&lt;br /&gt;
|-&lt;br /&gt;
|Emprunt X (164xxx - compte de bilan)||||5 000 €&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
;Enregistrement comptable du remboursement d'une échéance&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Compte!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Compte de l'adhérent X (411xxx)||||1 000 €&lt;br /&gt;
|-&lt;br /&gt;
|Emprunt X (164xxx - compte de bilan)||1000 €||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Prêt des adhérents à l'association avec remboursement en remise sur le tarif des heures de vols=&lt;br /&gt;
Il s'agit d'argent prêté des membres à l'association, par exemple pour participer au financement de l'achat d'un nouvel aéronef.&lt;br /&gt;
&lt;br /&gt;
Dans l'exemple ci-après, le membre prête 1 000 € se sera remboursé par une remise de 20 € sur l'heure de vol à concurrence de 50 heures.&lt;br /&gt;
&lt;br /&gt;
;Enregistrement comptable du prêt&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Compte!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Compte de l'adhérent X (411xxx)||5 000 €||&lt;br /&gt;
|-&lt;br /&gt;
|Emprunt X (164xxx - compte de bilan)||||5 000 €&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
;Enregistrement comptable du remboursement d'une échéance&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Compte!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Compte de l'adhérent X (411xxx)||||20 € * temps de vol en heure&lt;br /&gt;
|-&lt;br /&gt;
|Emprunt X (164xxx - compte de bilan)||20 € * temps de vol en heure||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Il est possible d'automatiser dans OpenFlyers le remboursement des 20 € par heure de vol en mettant en place un mécanisme similaire aux [[#Packs-d'heures-d'activités|packs d'heures d'activités]].&lt;br /&gt;
&lt;br /&gt;
=Rapprochement des encaissements=&lt;br /&gt;
Lors de la saisie d'un [[Écritures-comptables#Encaissement-(d'un-client)|encaissement client]], un flux comptable est généré. Il crédite le compte du client et débite un [[Comptabilité#Comptes-de-trésorerie|compte de trésorerie]].&lt;br /&gt;
&lt;br /&gt;
Dans le paramétrage type d'OpenFlyers, le compte de trésorerie débité est un compte d'attente intitulé ''Compte remise X'' où X correspond au type d'encaissement (carte bancaire, virement, chèques).&lt;br /&gt;
&lt;br /&gt;
Cela permet ensuite lors de l'import d'un relevé bancaire, de rapprocher automatiquement les écritures en générant des flux qui crédite le compte de banque et crédite le ''Compte remise X''.&lt;br /&gt;
&lt;br /&gt;
Si après import du relevé bancaire, tout est juste alors le ''Compte remise X'' a un solde à 0.&lt;br /&gt;
&lt;br /&gt;
S'il n'est pas à 0, alors grâce au lettrage, il est possible en regardant le détail du compte de lister les écritures non lettrées qui sont à l'origine de l'écart et ainsi de trouver plus rapidement la justification de l'écart.&lt;br /&gt;
&lt;br /&gt;
Exemple basé sur le paramétrage ci-dessous avec un chèque de 250 € remis par le pilote M. Romain GARY.&lt;br /&gt;
&lt;br /&gt;
La saisie du chèque de 250 € par M. Romain GARY génère le flux suivant :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Compte!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Compte remise chèque (512102)||2500 €||&lt;br /&gt;
|-&lt;br /&gt;
|Compte M. GARY (411rgary)||||250 €&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
L'import du relevé bancaire génère le flux suivant :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Compte!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Compte courant (512100)||2500 €||&lt;br /&gt;
|-&lt;br /&gt;
|Compte remise chèque (512102)||||250 €&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Les extraits de compte résultants sont les suivants :&lt;br /&gt;
&lt;br /&gt;
Compte M. GARY :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Intitulé écriture!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Chèque X||||250 €&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAUX'''||'''0 €'''||'''250 €'''&lt;br /&gt;
|-&lt;br /&gt;
|'''SOLDE'''||||'''250 €'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Compte remise chèque :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Intitulé écriture!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Chèque X||250 €||&lt;br /&gt;
|-&lt;br /&gt;
|Remise en banque chèque||||250 €&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAUX'''||'''250 €'''||'''250 €'''&lt;br /&gt;
|-&lt;br /&gt;
|'''SOLDE'''||||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Compte courant :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Intitulé écriture!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Remise en banque chèque||250 €||&lt;br /&gt;
|-&lt;br /&gt;
|'''TOTAUX'''||'''250 €'''||'''0 €'''&lt;br /&gt;
|-&lt;br /&gt;
|'''SOLDE'''||'''250 €'''||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
'''Paramétrage'''&lt;br /&gt;
&lt;br /&gt;
Pour que ce mécanisme fonctionne, il faut :&lt;br /&gt;
&lt;br /&gt;
*Avoir des comptes de trésorerie &amp;quot;Compte remise X&amp;quot; définis ainsi dans '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Trésorerie''' :&lt;br /&gt;
[[File:Comptes_remise_trésorerie.jpg]]&lt;br /&gt;
&lt;br /&gt;
*Avoir une [[Configuration-de-la-comptabilité#Ventilation-des-types-d'encaissements|ventilation des types d'encaissements]] définie ainsi dans '''Admin &amp;gt; Comptes &amp;gt; Encaissements &amp;gt; Ventilation''' :&lt;br /&gt;
[[File:Paramétrage_ventilation_encaissements.jpg]]&lt;br /&gt;
&lt;br /&gt;
*Avoir des [[Configuration-de-la-comptabilité#Règles-d'imputations-automatiques|règles d'imputation]] définies ainsi dans '''Gestion &amp;gt; Comptes &amp;gt; Relevé bancaire &amp;gt; Règles d'imputation''' :&lt;br /&gt;
[[File:Règles_imputation_ventilation_encaissements.jpg]]&lt;br /&gt;
&lt;br /&gt;
Attention : les mots clés définis dans les règles d'imputation varient en fonction de la banque de la structure.&lt;br /&gt;
&lt;br /&gt;
=Refacturation=&lt;br /&gt;
Il peut arriver qu'une structure soit facturée à la place de l'utilisateur final. Dans ce cas, la structure peut décider de refacturer à la personne concernée. C'est souvent le cas, par exemple, pour les factures de taxes d'atterrissages qui sont envoyée à la structure en tant que propriétaire de l'aéronef et qu'ensuite la structure refacture l'utilisateur concerné.&lt;br /&gt;
&lt;br /&gt;
Comptablement, il faut saisir les 2 écritures séparément :&lt;br /&gt;
*Saisir la facture fournisseur de la taxe d'atterrissage soit [[Gestion des achats#Saisie_d'une_facture_fournisseur|dans OpenFlyers]], soit dans le logiciel comptable utilisé pour les charges.&lt;br /&gt;
*[[Gestion des produits et des ventes#Achat_de_produit_non_stocké|Saisir l'achat d'une taxe d'atterrissages pour l'utilisateur concerné]].&lt;br /&gt;
&lt;br /&gt;
=Rembourser une facture avancée par un utilisateur=&lt;br /&gt;
Pour rembourser une facture payée par un utilisateur (exemple : un pilote qui paie une facture d'essence alors que la location de l'aéronef inclut déjà l'essence), il suffit de [[Utilisation-de-la-comptabilité#Saisir-un-flux|saisir un flux]] qui va créditer le compte de l'utilisateur et débiter le compte du fournisseur correspondant à la facture.&lt;br /&gt;
&lt;br /&gt;
Dans le cas où les [[Gestion-des-achats|factures fournisseurs]] sont saisies dans OpenFlyers, il suffit alors de saisir cette facture normalement et le compte du fournisseur se retrouvera à 0.&lt;br /&gt;
&lt;br /&gt;
Dans le cas où les factures fournisseurs ne sont pas saisies dans OpenFlyers, il faut laisser le compte fournisseur débiteur. La facture correspondante sera saisie dans le logiciel de comptabilité en créditeur le même compte fournisseur qui se retrouvera donc à 0.&lt;br /&gt;
&lt;br /&gt;
=Salaires=&lt;br /&gt;
Les salaires doivent être [[Gestion-des-achats#Saisie-d'une-facture-fournisseur|saisis comme des factures fournisseurs]] :&lt;br /&gt;
*Pour le salaire net versé au salarié : mettre comme fournisseur le salarié et comme compte de charge ''Rémunérations brutes'' (compte d'export 641100)&lt;br /&gt;
*Pour l'URSSAF : mettre comme fournisseur l'URSSAF (compte d'export 431000) et comme compte de charge ''Cotisations à l'URSSAF'' (compte d'export 645100)&lt;br /&gt;
&lt;br /&gt;
=Subventions=&lt;br /&gt;
Une structure peut recevoir 2 types de subventions :&lt;br /&gt;
*[[#Enregistrement_des_subventions_destinées_à_la_structure|Des subventions destinées directement à la structure]]&lt;br /&gt;
*[[#Ventilation_des_subventions_destinées_aux_utilisateurs|Des subventions destinées à des utilisateurs de la structure et qui doivent donc être ventilées]]&lt;br /&gt;
&lt;br /&gt;
==Enregistrement des subventions destinées à la structure==&lt;br /&gt;
Il existe plusieurs situations :&lt;br /&gt;
*Subventions d'exploitation accordées sans condition&lt;br /&gt;
*Subventions d'exploitation accordées avec condition résolutoire&lt;br /&gt;
*Subventions d'exploitation accordées avec condition suspensives&lt;br /&gt;
*Subventions d’investissement&lt;br /&gt;
&lt;br /&gt;
Nous ne documentons ici que le cas de la subvention d'exploitation accordée sans condition. Pour ces autres cas, nous recommandons d'effectuer une recherche sur internet pour trouver les éléments décrivant l'enregistrement comptable correspondant.&lt;br /&gt;
&lt;br /&gt;
*Enregistrement de la subvention à percevoir :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Compte!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Tiers qui subventionne (411...)||1000 €||&lt;br /&gt;
|-&lt;br /&gt;
|Subventions d'exploitation (74....)||||1000 €&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Si le tiers est une collectivité, alors la racine est 441...&lt;br /&gt;
&lt;br /&gt;
Si la subvention est destinée à financer un investissement, alors il faut passer par des écritures qui impactent les comptes de bilan.&lt;br /&gt;
&lt;br /&gt;
*Lorsque la subvention est encaissée par la structure :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Compte!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Banque (512...)||1000 €||&lt;br /&gt;
|-&lt;br /&gt;
|Tiers qui subventionne (411...)||||1000 €&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Si on souhaite simplifier la saisie, on peut enregistrer directement et uniquement l'encaissement de la subvention :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Compte!!Débit!!Crédit&lt;br /&gt;
|-&lt;br /&gt;
|Banque (512...)||1000 €||&lt;br /&gt;
|-&lt;br /&gt;
|Subventions d’exploitation (74....)||||1000 €&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Ventilation des subventions destinées aux utilisateurs==&lt;br /&gt;
Il peut arriver que la structure reçoive de l'argent d'un organisme et que cet argent doive ensuite être ventilé entre plusieurs clients. C'est le cas notamment pour les bourses attribuées par les fédérations qui doivent être redistribuées sur les comptes des utilisateurs concernés.&lt;br /&gt;
&lt;br /&gt;
Les opérations comptables à effectuer pour cela sont les suivantes :&lt;br /&gt;
*[[Utilisation-de-la-comptabilité#Saisir-un-flux|Saisir un flux]] correspondant à un [[Écritures comptables#Transfert_de_charge|transfert de charges]].&lt;br /&gt;
*[[Utilisation-de-la-comptabilité#Saisir-un-flux|Saisir un autre flux]] débitant le &amp;quot;compte de Transfert de charge (791)&amp;quot;  et créditant les comptes des utilisateurs concernés.&lt;br /&gt;
Si on sait au moment de l'encaissement du paiement quels sont les utilisateurs concernés, alors on peut saisir directement un flux qui débite le compte de trésorerie et crédite les comptes des utilisateurs concernés.&lt;br /&gt;
&lt;br /&gt;
===Anticiper l'attribution des subventions pour ne pas bloquer les utilisateurs===&lt;br /&gt;
Dans le cas où il existe des restrictions sur les droits pour les utilisateurs n'ayant pas le solde suffisant sur leur compte, il peut être pénalisant pour les utilisateurs attendant des subventions de se retrouver restreints dans leur droit à cause d'un solde insuffisant alors que la subvention est certaine.&lt;br /&gt;
&lt;br /&gt;
Afin, de ne pas restreindre les pilotes concernés, il faut :&lt;br /&gt;
*Créer un [[Comptabilité#Comptes_de_tiers|compte de tiers]], par exemple &amp;quot;Subvention à recevoir (441)&amp;quot;.&lt;br /&gt;
*Saisir un flux créditant le compte de l'utilisateur et débitant le compte &amp;quot;Subvention à recevoir&amp;quot;.&lt;br /&gt;
Ainsi :&lt;br /&gt;
*Le compte du pilote est crédité de la future subvention et il n'est donc pas restreint du fait d'un solde insuffisant dans l'attente d'une subvention.&lt;br /&gt;
*Il est possible de contrôler les sommes distribuées et non perçues au travers du compte &amp;quot;Subvention à recevoir&amp;quot;.&lt;br /&gt;
*Lorsque la subvention sera réellement perçue, il suffira de saisir un flux de transfert entre ce compte et le compte recevant la subvention afin de le ramener à 0.&lt;br /&gt;
&lt;br /&gt;
=Les taxes=&lt;br /&gt;
==Gérer les taxes d'atterrissage==&lt;br /&gt;
Les taxes d'atterrissages sont facturées à la structure aéronautique qui souvent les débitent sur le compte de ses clients. Voici plusieurs méthodes pour gérer ces opérations dans OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
#Pour les aérodromes dont la facturation est très récurrente et systématiquement effectuée à la structure (par exemple s'il s'agit de la base ou d'un aérodrome voisin), il peut être intéressant de rendre la facturation systématique en la couplant avec la saisie du vol. Pour ce faire, il faut créer la variable tarif correspondante, lui associer une valeur et ensuite créer une règle de facturation d'activité avec une formule qui contiendra un test sur l'aérodrome de départ ou d'arrivée :&lt;br /&gt;
#:''(%AIRFIELD_DEPARTURE=='LFBD')? $tarifTaxeLFBD : 0''&lt;br /&gt;
#Pour les aérodromes dont les taxes sont récurrentes mais pour lesquelles le pilote est susceptible de les payer directement et qui ne sont donc pas systématiquement facturées à la structure, il est recommander de créer un type de vente et de &amp;quot;revendre&amp;quot; la taxe à l'utilisateur concerné.&lt;br /&gt;
#Sinon, pour le cas plus fréquent (taxes différentes et peu fréquentes), il est recommandé de revendre la taxe en tant que produit &amp;quot;Taxe&amp;quot; dont le tarif est libre.&lt;br /&gt;
&lt;br /&gt;
=Ventilation des factures essences=&lt;br /&gt;
Afin de déterminer le coût de revient d'une ressource, il est nécessaire de pouvoir ventiler les différents postes de charge par ressource. C'est notamment le cas pour le poste &amp;quot;essence&amp;quot; qui dans le cas de l'aéronautique représente une part importante des charges.&lt;br /&gt;
&lt;br /&gt;
Dans le cas d'une structure aéronautique, en général, l'approvisionnement se fait principalement auprès d'une seul fournisseur d'essence localisé sur son aérodrome ou sur un aérodrome voisin.&lt;br /&gt;
&lt;br /&gt;
Il existe alors 2 types de situations :&lt;br /&gt;
#la structure dispose de &amp;quot;clés&amp;quot; ou de badges par aéronef et ainsi le fournisseur d'essence est capable de générer des factures avec le détail des montants facturés par aéronef&lt;br /&gt;
#le fournisseur d'essence ne fournit qu'une facture globale &lt;br /&gt;
&lt;br /&gt;
Dans la 1ère situation, il est judicieux de saisir les factures fournisseurs en éclatant la facture globale en autant de sous-factures qu'il y a de ressources concernées. Cela permet d'avoir directement une ventilation des charges par ressource. C'est également le cas qu'on retrouve dans le cas où les factures sont individualisées à chaque avitaillement : on est capable d'associer telle facture à telle ressource.&lt;br /&gt;
&lt;br /&gt;
Dans la 2ème situation, il n'est pas possible à priori de ventiler la facture d'essence par ressource. Dans ce cas là, on recommande de regrouper toutes les factures d'essence dans un même compte de charge. Ensuite, grâce à la consultation du total des volumes d'essences saisis dans les rapports, on est capable d'en déduire la part du coût global qui revient à chaque ressource. On recommande de ne pas faire de post-ventilation comptable mais de gérer cela directement dans une feuille de calcul qui est normalement utilisée pour déterminer le coût de revient des ressources.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Configuration-de-la-comptabilit%C3%A9&amp;diff=12881</id>
		<title>Configuration de la comptabilité</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Configuration-de-la-comptabilit%C3%A9&amp;diff=12881"/>
		<updated>2024-10-02T17:27:49Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
=Présentation=&lt;br /&gt;
L'objet de cette page est de décrire la configuration de la [[Comptabilité|comptabilité]] dans la [[Accueil|version 4 d'OpenFlyers]].&lt;br /&gt;
&lt;br /&gt;
=[[Bien débuter avec OpenFlyers#Mettre_en_place_la_gestion_d'activité_sur_OpenFlyers|Mise en place de la comptabilité dans OpenFlyers]]=&lt;br /&gt;
&lt;br /&gt;
=Paramétrage général de la gestion des comptes=&lt;br /&gt;
*Aller dans '''[[Configuration#Gestion-des-comptes-(Admin-&amp;gt;-Structure-&amp;gt;-Paramétrage-&amp;gt;-Comptes)|Admin &amp;gt; Structure &amp;gt; Paramétrage &amp;gt; Comptes]]'''.&lt;br /&gt;
&lt;br /&gt;
*Activer le toggle switch '''Comptes''' et cliquer sur '''Enregistrer''' pour activer la gestion des comptes.&lt;br /&gt;
*Champ '''Gestion TVA''' : activer le toggle switch si la structure est soumise à la TVA, sinon le laisser désactivé. Lorsque le toggle switch est désactivé, le champ '''Mention spécifique pour l'absence de TVA''' est saisissable.&lt;br /&gt;
*Champ '''Mention spécifique pour l'absence de TVA''' :&lt;br /&gt;
*:Exemple de valeurs possibles pour le champ :&lt;br /&gt;
**&amp;quot;TVA non applicable : article 293B du CGI&amp;quot; pour une association loi 1901, exonérée de TVA car ne dépassant pas un certain chiffre d'affaire&lt;br /&gt;
**&amp;quot;Association loi 1901, exonérées de TVA :  B.O.I. N° 208 du 18/12/2006 [BOI 4H-5-06]&amp;quot; pour une association exonérée de TVA du fait de son caractère non lucratif&lt;br /&gt;
**&amp;quot;TVA non applicable : article 202B du CGI&amp;quot; pour un organisme de formation professionnelle continue déclaré ayant opté pour l'exonération de TVA&lt;br /&gt;
**&amp;quot;Organisme de formation professionnelle continue déclaré ayant opté pour l'exonération de TVA : article 202B du CGI&amp;quot; pour les organismes de formation ayant opté pour l'exonération de TVA&lt;br /&gt;
**&amp;quot;TVA provisoirement non applicable en Guyane, Article 294-1 du CGI&amp;quot; pour une structure commerciale en Guyane.&lt;br /&gt;
**&amp;quot;TVA non applicable sur vols internationaux : Article 262-II-8° du CGI&amp;quot; pour une structure commerciale effectuant des vols internationaux&lt;br /&gt;
*Champ '''Titre spécifique pour les factures validées''' :&lt;br /&gt;
*:Exemple de valeurs possibles pour le champ :&lt;br /&gt;
**&amp;quot;Facture&amp;quot;&lt;br /&gt;
**&amp;quot;Note de participation aux frais&amp;quot;&lt;br /&gt;
*Champ '''Titre spécifique pour les factures non validées''' :&lt;br /&gt;
*:Exemple de valeurs possibles pour le champ :&lt;br /&gt;
**&amp;quot;Facture PROFORMA&amp;quot;&lt;br /&gt;
**&amp;quot;Note de participation aux frais PROFORMA&amp;quot;&lt;br /&gt;
**&amp;quot;Devis&amp;quot;&lt;br /&gt;
**&amp;quot;Bon de commande&amp;quot;&lt;br /&gt;
*Champ '''Titre spécifique pour les reçus validées''' :&lt;br /&gt;
*:Exemple de valeurs possibles pour le champ :&lt;br /&gt;
**&amp;quot;Reçu&amp;quot;&lt;br /&gt;
*Champ '''Titre spécifique pour les reçus non validés''' :&lt;br /&gt;
*:Exemple de valeurs possibles pour le champ :&lt;br /&gt;
**&amp;quot;Reçu PROFORMA&amp;quot;&lt;br /&gt;
*Champ '''Nombre maximal de jours antérieur pour lettrer''' : définit le nombre de jours avant la date d'une écriture pour lequel le lettrage automatique peut s'appliquer avec une autre écriture d'un même compte lors de l'[[Utilisation-de-la-comptabilité#Importer-un-relevé-bancaire|import d'un relevé bancaire]]&lt;br /&gt;
*Champ '''Nombre maximal de jours postérieur pour lettrer''' : définit le nombre de jours après la date d'une écriture pour lequel le lettrage automatique peut s'appliquer avec une autre écriture d'un même compte lors de l'[[Utilisation-de-la-comptabilité#Importer-un-relevé-bancaire|import d'un relevé bancaire]]&lt;br /&gt;
*Champ '''Mentions sur les conditions de paiement''' : remplace le champ [[Modèle de facture ODT#Variables|[payment_notice_tag]]] dans le template de la facture PDF.&lt;br /&gt;
*:Exemple de texte possible :&lt;br /&gt;
&amp;lt;pre&amp;gt;Règlement à réception&lt;br /&gt;
&lt;br /&gt;
En cas de retard de paiement, il sera appliqué des pénalités correspondant au taux légal en vigueur par mois de retard.&lt;br /&gt;
&lt;br /&gt;
En outre, une indemnité forfaitaire pour frais de recouvrement de 40 € sera due.&lt;br /&gt;
&lt;br /&gt;
Pas d'escompte en cas de paiement anticipé.&amp;lt;/pre&amp;gt;&lt;br /&gt;
*'''Mentions pieds de page''' : remplace le champ [[Modèle de facture ODT#Variables|[footer_tag]]] dans le template de la facture PDF. Exemple de texte possible :&lt;br /&gt;
&amp;lt;pre&amp;gt;SARL DUPONT au capital de 22 000 €, SIREN 123 456 789 RCS Paris, FR01234567890&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Paramétrage général des comptabilités=&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Comptes &amp;gt; Comptabilités &amp;gt; Comptabilités'''.&lt;br /&gt;
&lt;br /&gt;
Les différentes colonnes permettent de paramétrer une comptabilité :&lt;br /&gt;
*'''Nom''' : Nom de la comptabilité&lt;br /&gt;
*'''Unité''' : L'unité employé&lt;br /&gt;
*'''Symbole''' : Le symbole de l'unité&lt;br /&gt;
*'''Format''' : Le format d'affichage à utiliser pour les montants&lt;br /&gt;
*'''Nombre de chiffre après la virgule''' : Détermine à combien de chiffre après la virgule vont être arrondi les montants calculés au sein de la comptabilité. L'arrondissement s'effectue aussi sur les variable-formules.&lt;br /&gt;
*'''Comptes pour apurement d'un compte utilisateur'''&lt;br /&gt;
**'''Solde de compte positif''' : compte de produit défini pour recevoir le crédit lors de l'apurement d'un compte utilisateur ayant un solde positif lors de sa désactivation. Le compte défini par défaut est le compte [[Wikipedia-fr::Plan_comptable_général_(France)#75._Autres_produits_de_gestion_courante|758-Produits divers de gestion courante]].&lt;br /&gt;
**'''Solde de compte négatif''' : compte de charge défini pour recevoir le débit lors de l'apurement d'un compte utilisateur ayant un solde négatif lors de sa désactivation. Le compte défini par défaut est le compte [[Wikipedia-fr::Plan_comptable_général_(France)#65._Autres_charges_de_gestion_courante|654-Perte sur créances irrécouvrable]].&lt;br /&gt;
:Si le compte utilisateur à mettre à 0 est un compte en heure alors le compte de contre-partie est en général un compte de bilan intitulé &amp;quot;Encours xxx&amp;quot; appartement à la même comptabilité que le compte utilisateur concerné.&lt;br /&gt;
* '''Solde minimum requis''' et '''Si solde utilisateur inférieur au minimum''' : Permettent d'alerter et de restreindre l'accès à un profil déterminé ou de bloquer l'accès lorsque l'un des soldes des comptes d'un utilisateur est inférieur au minimum requis.&lt;br /&gt;
*'''Seuil minimum requis après transfert''' : Permet de bloquer [[Gestion-de-la-comptabilité-côté-utilisateur#Transférer-de-l'argent|un transfert]] si après opération, le solde du compte de l'utilisateur serait inférieur au seuil minimum requis. Si le seuil n'est pas défini alors il n'y a pas de vérification sur le solde. Le droit [[Gestion-des-profils#Surpasser-le-seuil-de-transfert-de-compte|Surpasser le seuil de transfert de compte]] permet de outrepasser cette limitation.&lt;br /&gt;
* '''Seuil de compte pour l'envoi d'e-mail d'alerte''' : Permet l'envoi d'un [[Envoi-des-emails#E-mail-de-rappel-de-solde|email d'alerte]], [[Envoi-des-emails#Présentation|uniquement sur les plateformes en production]], lorsque l'utilisateur a un solde de compte inférieur au seuil. L'email est envoyé à tous les utilisateurs concernés dès lors qu'une adresse email est enregistrée dans leur fiche utilisateur. Il est possible de suivre la bonne réception des alertes par email dans le module [[Suivi-des-emails|Suivi des emails]] (catégorie ''Alerte de solde'').&lt;br /&gt;
* '''Fréquence de rappel pour l'envoi d'e-mail d'alerte''' : Détermine la fréquence de rappel pour l'envoi de l'[[Envoi-des-emails#E-mail-de-rappel-de-solde|email d'alerte]] (Jamais, tous les jours, tous les 3 jours).&lt;br /&gt;
* '''Contenu de l'e-mail d'alerte''' : Le contenu à insérer dans le message d'[[Envoi-des-emails#E-mail-de-rappel-de-solde|email d'alerte]].&lt;br /&gt;
* '''Ajouté en copie d'e-mail''' : Permet d'ajouter les utilisateurs des profils cochés en copie de l'[[Envoi-des-emails#E-mail-de-rappel-de-solde|email d'alerte]] envoyé à chaque utilisateur concerné&lt;br /&gt;
&lt;br /&gt;
Voir le chapitre [[Formules-de-calcul#Exemples-de-patrons-d'emails-de-rappel-de-solde|Exemples de patrons d'emails de rappel de solde]].&lt;br /&gt;
&lt;br /&gt;
Nous recommandons fortement de mettre le paramètre %ACCOUNT_BALANCE € dans le patron d'emails. Cela permet d'avoir une traçabilité du montant calculé par OpenFlyers au moment de l'envoi de l'e-mail et ainsi d'éviter tout problème de discussion ultérieur.&lt;br /&gt;
&lt;br /&gt;
==Restriction d'accès en cas de solde insuffisant==&lt;br /&gt;
Il est possible de définir des règles de restriction et/ou alerte pour chaque comptabilité. Pour cela, il faut :&lt;br /&gt;
*[[Gestion des profils|Créer un profil]] spécifique qui peut s'intituler ''Accès restreint''. Lors de la restriction, seuls les droits présents à la fois sur ce profil et sur celui de l'utilisateur restreint, resteront valides. Il faut donc bien définir les droits qui doivent rester présent pour le profil restreint.&lt;br /&gt;
*Dans le [[#Paramétrage_général_des_comptabilités|paramétrage général des comptabilités]], paramétrer les colonnes '''Si solde utilisateur inférieur au minimum''' et '''Solde minimum requis''' pour permettent d'alerter et de [[Connexion#Restriction-d'accès|restreindre l'accès à un profil déterminé]] ou de bloquer l'accès lorsque l'un des soldes des comptes d'un utilisateur est inférieur au minimum requis.&lt;br /&gt;
&lt;br /&gt;
Le fait de [[Connexion#Restriction_d'accès|restreindre le profil d'un utilisateur]], permet de l'empêcher de pouvoir effectuer certaines actions comme réserver ou débuter une activité si l'un de ses soldes est insuffisant.&lt;br /&gt;
&lt;br /&gt;
Ce contrôle sur le solde du compte et les droits qui en résultent s'effectue :&lt;br /&gt;
*A la connexion de l'utilisateur pour en déduire le type d'accès auquel il a droit&lt;br /&gt;
*Lors d'une action de réservation ou de saisie de vol effectuée par n'importe quel utilisateur. Dans ce cas, OpenFlyers contrôle le solde non pas de la personne effectuant l'action mais celui pour qui l'action est effectuée. Cela permet d'empêcher à un utilisateur de contourner une restriction en demandant à un autre utilisateur disposant de droits étendus de faire par exemple une réservation à son nom.&lt;br /&gt;
&lt;br /&gt;
Il est possible d'attribuer à des profils le droit &amp;quot;[[Gestion-des-profils#Surpasser-la-limitation-du-solde-du-compte|Surpasser la limitation du solde du compte]]&amp;quot; qui seraient ainsi mise en place.&lt;br /&gt;
&lt;br /&gt;
'''Attention :''' lorsqu'un utilisateur dispose d'un profil avec le droit &amp;quot;[[Gestion-des-profils#Surpasser-la-limitation-du-solde-du-compte|Surpasser la limitation du solde du compte]]&amp;quot;, alors même s'il se connecte avec un autre profil, il n'aura pas de restriction en cas de solde insuffisant.&lt;br /&gt;
&lt;br /&gt;
Il est possible d'empêcher les utilisateurs standards d'effectuer des réservations en cas de solde insuffisant en enlevant les droits [[Gestion-des-profils#Réservation-solo|&amp;quot;Réservation solo&amp;quot;]] et [[Gestion-des-profils#Réservation-pour-des-tiers|&amp;quot;Réservation pour des tiers&amp;quot;]] au profil ''Accès restreint'' tout en permettant à des tiers de pouvoir effectuer des réservations pour eux en laissant le droit [[Gestion-des-profils#Etre-sur-une-nouvelle-réservation|&amp;quot;Etre sur une nouvelle réservation&amp;quot;]] au profil ''Accès restreint''.&lt;br /&gt;
&lt;br /&gt;
Conseil OpenFlyers : il est possible d'utiliser l'alerte sur une comptabilité pour mettre en place l'envoi automatique d'un e-mail lorsque le crédit d'heures de vol devient inférieur à une certaine valeur. Exemple : &amp;quot;Votre crédit d'heures de vol est inférieur à 1h, n'hésitez-pas à le recharger en achetant un pack de 10 heures&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=Compte comptable=&lt;br /&gt;
==Créer un compte comptable==&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; X''' où X dépend de la [[Comptabilité#Présentation-des-comptes-dans-OpenFlyers|catégorie de comptes]] à créer.&lt;br /&gt;
*En bas du tableau :&lt;br /&gt;
**Remplir le champ de la colonne '''Nom''' avec le nom souhaité pour désigner le compte à créer. Certains caractères ne sont pas recommandés dans le nom [[OF-doc-en::Accounting-export-template-CsvWithPointDecimal#Introduction|car ils sont supprimées dans les fichiers d'exports]]&lt;br /&gt;
***'''Attention''' : Certains caractères ne sont pas recommandés dans le nom [[OF-doc-en::Accounting-export-template-CsvWithPointDecimal#Introduction|car ils sont supprimées dans les fichiers d'exports au format CSV]]&lt;br /&gt;
**Remplir le champ de la colonne '''Compte d'export''' avec le numéro de compte d'export comptable souhaité. Cette information peut être saisie ou mise à jour à tout moment jusqu'à avant l'export vers un logiciel de comptabilité.&lt;br /&gt;
**Dans le cas où il s'agit d'un compte client, il faut sélectionner la case à cocher de la colonne '''Reçoit les paiements des clients extérieurs''' si l'on souhaite pouvoir saisir des encaissements directement sur ce compte&lt;br /&gt;
**Cliquer sur le bouton '''Ajouter'''&lt;br /&gt;
&lt;br /&gt;
==Créer un compte pour les ressources==&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Ressources'''&lt;br /&gt;
*Cliquer sur l'icône [[File:Icone_creation_compte.png]]&lt;br /&gt;
&lt;br /&gt;
Les ressources affichées sont :&lt;br /&gt;
* celles utilisables pour la '''Saisie d'activité'''&lt;br /&gt;
* celles non utilisables pour la '''Saisie d'activité''' mais ayant au moins un compte actif : cela permet de continuer à pouvoir consulter l'historique du compte de la ressource alors que la ressource n'est plus utilisée.&lt;br /&gt;
&lt;br /&gt;
==Comptes d'export==&lt;br /&gt;
A chaque [[#Compte_comptable|compte comptable]] est associé un compte d'export qui lui est propre.&lt;br /&gt;
*Ce numéro de compte d'export est utilisé exclusivement pour les [[Utilisation de la comptabilité#Les_exports_comptables|exports comptables]] et les rapports comptables&lt;br /&gt;
*Tous les comptes d'export doivent être définis avant de pouvoir réaliser un export comptable.&lt;br /&gt;
*Cette attribution de compte d'export peut être effectuée et modifiée à n'importe quel moment.&lt;br /&gt;
*Ce compte d'export est éditable directement au niveau du compte.&lt;br /&gt;
*De plus, pour les comptes utilisateurs et les comptes ressources, il est possible et fortement recommandé de définir des règles de numérotation automatique qui permettent de créer automatiquement les numéros de compte d'export lors de la création de nouveaux utilisateurs ou de nouvelles ressources.&lt;br /&gt;
*'''Attention''' : Certains caractères ne sont pas recommandés dans le nom [[OF-doc-en::Accounting-export-template-CsvWithPointDecimal#Introduction|car ils sont supprimées dans les fichiers d'exports au format CSV]]&lt;br /&gt;
''Dans le cadre du paramétrage effectué par OpenFlyers, nous livrons la plateforme avec les comptes d'export attribués selon le modèle couramment utilisé pour tous les comptes créés par nos soins.''&lt;br /&gt;
===Attribuer les comptes d'export utilisateurs ou ressources===&lt;br /&gt;
Pour attribuer les comptes d'export aux comptes utilisateurs ou aux comptes ressources, il existe 2 possibilités :&lt;br /&gt;
*soit par [[#Attribuer_manuellement_les_comptes_d'export_utilisateurs_ou_ressources|édition du compte d'export de chaque compte individuellement]]&lt;br /&gt;
*soit par [[#Mettre_en_place_un_patron_de_génération_automatique_de_compte_d'export_utilisateurs_ou_ressources|mise en place d'une formule permettant de générer automatiquement les valeurs]]&lt;br /&gt;
Il est recommandé de mettre en place une formule pour chaque type de compte utilisateur/ressource. Cela permet, lors de l'ajout de nouveaux utilisateurs/ressources, d'être sûr d'avoir une règle qui va être respectée et de permettre une génération automatique du compte d'export.&lt;br /&gt;
&lt;br /&gt;
====Attribuer manuellement les comptes d'export utilisateurs ou ressources====&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Utilisateurs''' ou '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Ressources'''&lt;br /&gt;
*Retrouver le compte souhaité&lt;br /&gt;
*Cliquer sur l'icône &amp;quot;crayon&amp;quot; pour modifier : un formulaire apparait permettant de modifier/saisir le Code comptable pour l'exportation&lt;br /&gt;
&lt;br /&gt;
====Mettre en place un patron de génération automatique de compte d'export utilisateurs ou ressources====&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Comptes &amp;gt; Utilisateurs &amp;gt; Types actifs''' ou '''Admin &amp;gt; Comptes &amp;gt; Ressources &amp;gt; Types actifs''' selon le cas.&lt;br /&gt;
*Cliquer sur l'icône symbolisant un crayon de la ligne du type de compte pour lequel vous souhaitez mettre en place/éditer le patron de code comptable.&lt;br /&gt;
*Renseigner le champ '''Patron de code comptable pour l'exportation''' (cf. [[Formules de calcul#Compte_d'export|les exemples]]).&lt;br /&gt;
*Cliquer sur le bouton '''Valider'''.&lt;br /&gt;
Il faut ensuite appliquer le patron :&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Comptes &amp;gt; Utilisateurs &amp;gt; Gérer les comptes d'export''' ou dans '''Admin &amp;gt; Comptes &amp;gt; Ressources &amp;gt; Gérer les comptes d'export''' selon le cas.&lt;br /&gt;
*Dans le champ '''Appliquer la mise à jour sur les types de comptes''' sélectionner le type de compte concerné. Le champ '''Formule à appliquer''' doit automatiquement se remplir avec le patron précédemment créé&lt;br /&gt;
*Si vous souhaitez que le patron s'applique à tous les comptes, sélectionner '''Tous les comptes'''. Sinon, sélectionner '''Uniquement les comptes sans numéro d'export'''.&lt;br /&gt;
*Cliquer sur le bouton '''Appliquer'''.&lt;br /&gt;
&lt;br /&gt;
===Attribuer les comptes d'export pour un compte ni utilisateur ni ressource===&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Tous'''&lt;br /&gt;
*Modifier le champ Compte d'export, la validation est automatique lors de la sortie du champ&lt;br /&gt;
&lt;br /&gt;
=Agréger des comptes bancaires=&lt;br /&gt;
;Présentation&lt;br /&gt;
Cette action préliminaire est nécessaire pour permettre soit d'activer l'import quotidien automatique des relevés bancaires soit pour [[Utilisation-de-la-comptabilité#Importer-par-API|importer par API]] les relevés bancaires.&lt;br /&gt;
&lt;br /&gt;
;Prérequis&lt;br /&gt;
*Disposer du droit [[Gestion-des-profils#Gestion-des-comptabilités|Gestion des comptabilités]] ou du droit [[Gestion-des-profils#Gestion-des-comptes|Gestion des comptes]]&lt;br /&gt;
&lt;br /&gt;
;Chapitres liés&lt;br /&gt;
*[[Envoi-des-emails#E-mail-de-rappel-de-renouvellement-d'agrégation-bancaire|E-mail de rappel de renouvellement d'agrégation bancaire]]&lt;br /&gt;
*[[Utilisation-de-la-comptabilité#Importer-par-API|Importer par API un relevé bancaire]]&lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
Aller dans '''Admin &amp;gt; Comptes &amp;gt; Banque &amp;gt; Agréger''', Un tableau s'affiche avec les informations suivantes :&lt;br /&gt;
*Colonne '''Actions sur la banque''' :&lt;br /&gt;
**Bouton '''supprimer''' à gauche du tableau permet de supprimer l'agrégation d'une banque et tous les comptes associés.&lt;br /&gt;
**Bouton '''Renouveler''' permet d'effectuer le renouvellement de l'authentification forte. Il est à faire tous les 90 jours pour que l'agrégation soit maintenue.&lt;br /&gt;
*'''Banque''' : banque du compte contenant les transactions à importer.&lt;br /&gt;
*'''Compte Bancaire''' : compte bancaire contenant les extraits de compte à importer.&lt;br /&gt;
*'''Date de la dernière authentification''': dernière authentification forte réalisée auprès de la banque à laquelle appartient le compte en question.&lt;br /&gt;
*'''Date limite d'agrégation''': date d'échéance d'aggrégation (Date de la dernière authentification + 90 jours), s'affiche en rouge à partir d'un mois avant l'échéance.&lt;br /&gt;
*'''[[Comptabilité#Comptes-de-trésorerie|Compte de trésorerie]]''' : compte de trésorerie couplé au compte bancaire. C'est sur ce compte que s'enregistre les écritures comptables correspondantes aux extraits de comptes importés du compte bancaire.&lt;br /&gt;
*'''Date de début d'import''' : seuls les extraits de compte ayant une date postérieure ou égale à la date de début d'import indiquée sont pris en compte pour l'import dans OpenFlyers.&lt;br /&gt;
*'''Synchroniser 1 fois par jour ''': Lorsque la case est cochée, alors le robot OpenFlyers importe automatiquement une fois par jour l'extrait de compte du compte bancaire concerné dans le compte de trésorerie couplé.&lt;br /&gt;
&lt;br /&gt;
Pour créer une nouvelle agrégation il faut cliquer sur le bouton '''Ajouter''' situé à droite en bas et en haut du tableau. Il faut ensuite remplir le formulaire et appuyer sur le bouton '''Ajouter'''.&lt;br /&gt;
&lt;br /&gt;
Pour modifier un couplage entre un compte bancaire et un compte de trésorerie, il faut cliquer sur le bouton '''Modifier''' situé dans la colonne Actions de l'agrégation que l'on souhaite éditer. Il faut ensuite remplir le formulaire et appuyer sur le bouton '''Modifier'''.&lt;br /&gt;
&lt;br /&gt;
Pour supprimer un couplage entre un compte bancaire et un compte de trésorerie, il faut cliquer sur le bouton '''Supprimer''' situé dans la colonne Actions de l'agrégation que l'on souhaite supprimer. Il faut ensuite confirmer la suppression en appuyant sur le bouton '''OK'''.&lt;br /&gt;
&lt;br /&gt;
Pour supprimer l'agrégation d'une banque, il faut cliquer sur le bouton '''Supprimer''' situé dans la colonne de gauche à la ligne de la concernée. Il faut ensuite confirmer la suppression en appuyant sur le bouton '''OK'''.&lt;br /&gt;
&lt;br /&gt;
Le formulaire d'ajout/modification d'une agrégation/d'un couplage contient les champs suivants :&lt;br /&gt;
*'''Compte de trésorerie''' : menu déroulant permettant de choisir le compte de trésorerie. Seuls les comptes qui ne sont pas déjà couplés ainsi que le compte qu'on édite, dans le cas d'une modification peuvent être sélectionnés.&lt;br /&gt;
*'''Date de début d'import''': calendrier permettant de choisir la date de début d'import à associer au compte de trésorerie sélectionné dans le champ précèdent.&lt;br /&gt;
*'''Synchroniser 1 fois par jour''': un interrupteur permet d'activer la synchronisation automatique afin d'importer le relevé bancaire tous les jours.&lt;br /&gt;
*'''Banque''' : menu déroulant permettant de sélectionner la banque à agréger. Une fois la banque sélectionnée, la page défile et il y a deux situations :&lt;br /&gt;
**Si la banque sélectionnée n'est pas déjà agrégée, le processus d'agrégation est le suivant :&lt;br /&gt;
***'''Agréger la banque''' : permet de lancer le processus d'agrégation.&lt;br /&gt;
***En cliquant sur le bouton l'utilisateur est redirigé vers une page d'authentification de la banque sélectionnée.&lt;br /&gt;
***Une fois l'utilisateur authentifié, tous les comptes disponibles de la banque sont agrégées, l'utilisateur se redirige vers la même interface avec :&lt;br /&gt;
****Les champs '''Compte de trésorerie''' et '''Banque''' seront en lecture seule.&lt;br /&gt;
****Une liste déroulante permet de choisir le compte à coupler. Cette liste contient les comptes agrégés de la banque. Seuls les comptes qui ne sont pas couplés à un compte de trésorerie peuvent être sélectionnés.&lt;br /&gt;
**Si la banque est déjà agrégée, le nom de la banque apparait dans la liste suivi de l'information '''(agrégation existante)''', le processus de l'agrégation est le suivant :&lt;br /&gt;
***'''Compte bancaire''': une liste déroulante permet de choisir l'un des comptes. Seuls les comptes qui ne sont pas déjà couplés à un compte de trésorerie et le compte couplé que l'on édite en cas de modification peuvent être sélectionnés.&lt;br /&gt;
*le bouton '''Ajouter''' ou '''Modifier''' pour enregistrer l'agrégation.&lt;br /&gt;
&lt;br /&gt;
Un email de rappel de renouvellement de l'agrégation est envoyé à intervalle régulier pour avertir les gestionnaires de la nécessité de renouveler l'agrégation. Voir les chapitres [[Envoi-des-emails#E-mail-de-rappel-de-renouvellement-d'agrégation-bancaire|E-mail de rappel de renouvellement d'agrégation bancaire]] et [[#Renouveler-l'agrégation-des-comptes-bancaires|Renouveler l'agrégation des comptes bancaires]].&lt;br /&gt;
&lt;br /&gt;
=Renouveler l'agrégation des comptes bancaires=&lt;br /&gt;
;Présentation&lt;br /&gt;
Le renouvellement de l'agrégation des comptes bancaires doit être effectués tous les 3 mois. Il s'agit d'une obligation légale européenne. Si le renouvellement de l'agrégation n'est pas effectué au bout de 3 mois, alors il n'est plus possible de synchroniser manuellement ou automatiquement les comptes bancaires avec l'API de la banque.&lt;br /&gt;
&lt;br /&gt;
Il est important de noter qu'il ne faut pas supprimer une agrégation existante pour la renouveler. En effet, si un utilisateur effectue cette action, alors les références de la nouvelle agrégation ne correspondront plus avec celles de l'ancienne et l'import des écritures bancaires va créer des doublons avec les anciens imports.&lt;br /&gt;
&lt;br /&gt;
;Prérequis&lt;br /&gt;
*Disposer du droit [[Gestion-des-profils#Gestion-des-comptabilités|Gestion des comptabilités]] ou du droit [[Gestion-des-profils#Gestion-des-comptes|Gestion des comptes]]&lt;br /&gt;
*Avoir un ou plusieurs [[#Agréger-des-comptes-bancaires|comptes bancaires agrégés]]&lt;br /&gt;
&lt;br /&gt;
;Chapitres liés&lt;br /&gt;
*[[#Agréger-des-comptes-bancaires|Agréger des comptes bancaires]]&lt;br /&gt;
*[[Envoi-des-emails#E-mail-de-rappel-de-renouvellement-d'agrégation-bancaire|E-mail de rappel de renouvellement d'agrégation bancaire]]&lt;br /&gt;
*[[Utilisation-de-la-comptabilité#Importer-par-API|Importer par API un relevé bancaire]]&lt;br /&gt;
*[[Alertes-de-configuration#Utiliser-correctement-la-fonctionnalité-'Importer-les-relevés-bancaires-par-API'-en-prolongant-l'agrégation-des-banques-au-delà-de-90-jours-après-la-dernière-date-d'authentification|Alerte de configuration pour renouveler l'aggrégation bancaire]]&lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
Aller dans '''Admin &amp;gt; Comptes &amp;gt; Banque &amp;gt; Agréger'''&lt;br /&gt;
Un tableau s'affiche. Il doit contenir la liste des banques agrégées. Pour renouveler l'agrégation de l'une d'elle, il faut :&lt;br /&gt;
*Cliquer sur le pictogramme '''Renouveler''', symbolisant un triangle avec une flèche qui tourne autour, à gauche de la ligne de la banque concernée&lt;br /&gt;
L'interface de la banque apparait pour effectuer l'action de renouvellement de l'agrégation. Suivre les consignes et renseigner les informations demandées par la banque. Une fois le renouvellement de l'agrégation achevé, apparait à nouveau la page OpenFlyers du tableau des agrégations.&lt;br /&gt;
*Vérifier que la date d'agrégation correspond à la date du jour&lt;br /&gt;
&lt;br /&gt;
=Règles d'imputations automatiques=&lt;br /&gt;
Pour accéder à cette fonctionnalité il faut disposer des droits de [[Gestion-des-profils#Gestion-des-comptes|Gestion des comptes]] ou [[Gestion-des-profils#Saisir-tout-flux|Saisir tout flux]].&lt;br /&gt;
&lt;br /&gt;
Prérequis :&lt;br /&gt;
*L'accès à cette fonctionnalité nécessite [[Utilisation-de-la-comptabilité#Créer-un-compte|la création d'au moins un compte]] client ou fournisseur.&lt;br /&gt;
&lt;br /&gt;
Cela permet de créer ou modifier les règles d'imputation automatique utilisés lors de l'[[Utilisation-de-la-comptabilité#Importer-un-relevé-bancaire|importation de relevés bancaires]].&lt;br /&gt;
&lt;br /&gt;
Depuis l'[[Présentation-d'OpenFlyers-4#Interface-légère|interface légère]] :&lt;br /&gt;
*'''Gestion &amp;gt; Comptes &amp;gt; relevé bancaire &amp;gt; Règles d'imputation'''&lt;br /&gt;
Un tableau est alors affiché : &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Ordonner!!Titre!!Montant sur le relevé bancaire!!Mot clé à rechercher!!Nom du compte imputé dans la comptabilité&lt;br /&gt;
|-&lt;br /&gt;
|0||Compte d'attente fournisseur||Débit (montant négatif)||--||Fournisseur - compte d'attente&lt;br /&gt;
|-&lt;br /&gt;
|1||Compte d'attente client||Crédit (montant positif)||--||Client - compte d'attente&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Pour créer une nouvelle règle il faut cliquer sur le bouton '''Ajouter une règle d'imputation''' situé en bas du tableau. Il faut ensuite remplir le formulaire et appuyer sur le bouton '''Enregistrer'''. Le champ &amp;quot;Titre&amp;quot; doit être obligatoirement rempli.&lt;br /&gt;
&lt;br /&gt;
Pour modifier une nouvelle règle il faut cliquer sur le bouton '''Modifier''' situé dans la colonne '''Actions''' de la règle d'imputation que l'on souhaite éditer. Il faut ensuite remplir le formulaire et appuyer sur le bouton '''Enregistrer'''. Le champ &amp;quot;Titre&amp;quot; doit être obligatoirement rempli.&lt;br /&gt;
&lt;br /&gt;
Pour les règles d'imputation &amp;quot;Compte d'attente fournisseur&amp;quot; et &amp;quot;Compte d'attente client&amp;quot; seul les champs &amp;quot;Placer avant&amp;quot; et &amp;quot;Nom de compte&amp;quot; sont modifiable.&lt;br /&gt;
&lt;br /&gt;
Présentation des colonnes :&lt;br /&gt;
*La colonne 'Ordonner' : Ordre dans lequel s'applique les règles d'imputation;&lt;br /&gt;
*La colonne 'Titre' : Titre des règles d'imputation;&lt;br /&gt;
*La colonne 'Montant sur le relevé bancaire' : L'utilisateur à le choix entre &amp;quot;Crédit&amp;quot; ou &amp;quot;Débit&amp;quot;,&lt;br /&gt;
*La colonne 'Mot clé à rechercher' : Champs texte;&lt;br /&gt;
*La colonne 'Nom du compte imputé dans la comptabilité' : L'utilisateur à le choix entre les comptes déjà existant,&lt;br /&gt;
&lt;br /&gt;
Fonctionnement :&lt;br /&gt;
*Lors de l'[[Utilisation-de-la-comptabilité#Importer-un-relevé-bancaire|import d'un relevé bancaire]], le robot OpenFlyers va pour chaque ligne du relevé bancaire, parcourir les règles d'imputation dans l'ordre dans lequel elles sont définies.&lt;br /&gt;
*Si le montant de la ligne du relevé est du même signe que celui défini dans la règle (champ '''Montant sur le relevé bancaire''') et si l'intitulé contient le mot clé ou l'[[Wikipedia-fr:Expression_régulière|expression régulière]] définie dans le champ '''Mot clé à rechercher''', alors la règle s'applique. Dans ce cas, le robot, génère un flux qui va débiter/créditer le compte de trésorerie définie dans l'interface d'import des relevés bancaires et va mettre la contre-partie dans le compte défini dans la règle (champ '''Nom du compte imputé dans la comptabilité''').&lt;br /&gt;
*Si la règle ne correspond pas, le robot passe à la règle suivante jusqu'à trouver une règle qui s'applique.&lt;br /&gt;
&lt;br /&gt;
Deux règles (''Compte d'attente fournisseur'' et ''Compte d'attente client'') sont créées par défaut. Elles ne peuvent être supprimées et leur ordre ne peut être modifiées. Elles sont positionnées en dernier. Ainsi, elles permettent de garantir que pour toute ligne du relevé bancaire, une règle va correspondre et que la ligne va donc bien être enregistrée dans OpenFlyers. Ces règles sont prévues pour s'appliquer sur des comptes par défaut (comptes d'attentes) afin de permettre un traitement manuel ultérieur par le gestionnaire. Seul le paramètre '''Nom du compte imputé dans la comptabilité''' est modifiable.&lt;br /&gt;
&lt;br /&gt;
[[File:Exemple_regle_imputation.PNG|center|800px]]&lt;br /&gt;
&lt;br /&gt;
=Types d'encaissements=&lt;br /&gt;
OpenFlyers permet de définir librement autant de types d'encaissements que l'on souhaite. Cela permet de créer, outre les types d'encaissements courants tels que les paiements par espèce, carte bancaire, chèque ou virement de définir des types de paiements plus spécifiques comme les chèques vacances, les bons de comités d'entreprises, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Aller dans le menu '''Admin &amp;gt; Comptes &amp;gt; Encaissements &amp;gt; Types''' afin d'afficher l'interface tableau de bord (vue synthétique), cette interface permet de visualiser les types d'encaissement créés précédemment. Il est possible d'y effectuer des modifications, notamment pour les actions suivants:&lt;br /&gt;
&lt;br /&gt;
*Supprimer un type d'encaissement existant en cliquant sur le pictogramme symbolisant une poubelle à droite de la ligne du type d'encaissement à supprimer.&lt;br /&gt;
*Modifier un type d'encaissement existant en cliquant sur le pictogramme symbolisant un crayon sur la ligne correspondante au type d'encaissement à modifier.&lt;br /&gt;
*Créer un nouveau type d'encaissement en cliquant sur le bouton '''Ajouter'''.&lt;br /&gt;
&lt;br /&gt;
L'ajout ou la modification d'un type d'encaissement redirige vers un formulaire contenant les champs suivants:&lt;br /&gt;
*'''Type d'encaissement''':&lt;br /&gt;
**'''Nom''' : Champ de saisie de texte permet de définir le nom du type d'encaissement (il est interdit de créer deux types d'encaissement avec le même nom).&lt;br /&gt;
**'''Intitulé du champ de saisie (vide si pas de champ)''' : champ de saisie de texte permet de définir l'intitulé&lt;br /&gt;
**'''Accessible uniquement aux personnes autorisées à saisir pour les tiers'''&lt;br /&gt;
*'''Ventilation''':&lt;br /&gt;
**'''Compte de trésorerie affecté''' : champ de sélection permet de définir sur quel compte de trésorerie les paiements doivent être affectés au débit en contre partie du crédit sur le compte de l'utilisateur concerné.&lt;br /&gt;
**'''Remise à une personne''' : toggle switch permet de rendra actif le champ '''Personne qui reçoit''' lors de [[Utilisation-de-la-comptabilité#Saisir-un-encaissement|la saisie d'un encaissement]] (La liste des utilisateurs apparaissant dans le menu déroulant de ce champ contient les utilisateurs disposant d'un profil ayant le droit [[Gestion-des-profils#Recevoir-de-l'argent|Recevoir de l'argent]]).&lt;br /&gt;
*'''Montant minimum''' : &lt;br /&gt;
**'''Aucune limite''' : si le toggle switch est activé donc il n'y a aucune limite minimum pour le montant lors de [[Utilisation-de-la-comptabilité#Saisir-un-encaissement|la saisie d'un encaissement]].&lt;br /&gt;
**Sinon, Champ de saisie de texte s'affiche pour définir le montant minimum autorisée pour le type d'encaissement lors de [[Utilisation-de-la-comptabilité#Saisir-un-encaissement|la saisie d'un encaissement]].&lt;br /&gt;
*'''Montant maximum''' :&lt;br /&gt;
**'''Aucune limite''' : si le toggle switch est activé donc il n'y a aucune limite maximum pour le montant lors de [[Utilisation-de-la-comptabilité#Saisir-un-encaissement|la saisie d'un encaissement]].&lt;br /&gt;
**Sinon, Champ de saisie de texte s'affiche pour définir le montant maximum autorisée pour le type d'encaissement lors de [[Utilisation-de-la-comptabilité#Saisir-un-encaissement|la saisie d'un encaissement]].&lt;br /&gt;
&lt;br /&gt;
=Spécificités métiers=&lt;br /&gt;
==[[Conseils spécifiques pour la comptabilité#Baptêmes_dans_un_aéro-club|Gestion des baptêmes]]==&lt;br /&gt;
#Créer un type d'activité &amp;quot;baptême&amp;quot;&lt;br /&gt;
#Créer un compte client &amp;quot;Clients extérieurs&amp;quot;&lt;br /&gt;
#Créer une règle de tarification concernant le type de vol &amp;quot;baptême&amp;quot; qui va débiter le compte &amp;quot;Clients extérieurs&amp;quot; et créditer le compte du pilote qui effectue le baptême à hauteur du montant du prix du vol en solo&lt;br /&gt;
Ainsi :&lt;br /&gt;
*le pilote qui effectue le baptême ne sera pas facturé&lt;br /&gt;
*le compte client &amp;quot;Clients extérieurs&amp;quot; sera débité du montant du prix du vol &amp;quot;solo&amp;quot;&lt;br /&gt;
*le compte produit &amp;quot;heures de vol&amp;quot; sera crédité normalement&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Classeur-de-suivi-de-maintenance&amp;diff=12880</id>
		<title>Classeur de suivi de maintenance</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Classeur-de-suivi-de-maintenance&amp;diff=12880"/>
		<updated>2024-10-02T17:27:49Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Classeur de suivi de maintenance=&lt;br /&gt;
Voir la vidéo [https://www.youtube.com/watch?v=iJJitD7j8Ro Classeur de suivi de maintenance].&lt;br /&gt;
&lt;br /&gt;
Parmi les [[Tableurs|classeurs]] existants, OpenFlyers propose un classeur de suivi de maintenance.&lt;br /&gt;
&lt;br /&gt;
Ce document, contenant les caractéristiques des aéronefs comme les potentiels restants et les butées des actions, est mis à jour en temps réel lors de la saisie ou de la suppression d'un vol sur OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
==Présentation du classeur==&lt;br /&gt;
Le classeur est constitué de plusieurs onglets :&lt;br /&gt;
*Un onglet appelé [[#Onglet &amp;quot;Vue d'ensemble&amp;quot;|'''Vue d'ensemble''']], récapitulant les informations des aéronefs et les prochaines butées des actions.&lt;br /&gt;
*Un onglet [[#Onglets des ressources|'''par ressource''']], contenant les informations détaillées telles que les heures cellules de chaque action, les potentiels et butées associées.&lt;br /&gt;
*Un onglet [[#Onglets de l'historique d'une ressource|'''d'historique et de saisie des actions par ressource''']] permettant de suivre les échéances pour chaque action.&lt;br /&gt;
&lt;br /&gt;
[[File:Tableur_suivi_navigabilité_onglets.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Les modifications apportées [[#Règles de modification du document|doivent respecter des règles]], notamment sur les formats de durées et dates, puis sur les droits de modifications de certaines cellules bien précises.&lt;br /&gt;
&lt;br /&gt;
==Onglet &amp;quot;Vue d'ensemble&amp;quot;==&lt;br /&gt;
===Présentation de l'onglet général===&lt;br /&gt;
[[File:tableur_suivi_navigabilité_vue_d_ensemble.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
La vue d'ensemble est automatiquement mise à jour. Les heures cellules totales des aéronefs sont modifiées dès qu'un vol est saisi ou supprimé sur OpenFlyers, ce qui provoque la mise à jour en cascade de toutes les valeurs calculées et affichées.&lt;br /&gt;
&lt;br /&gt;
Sur cet onglet, les cellules correspondant aux '''Heures cellules depuis RG''', '''Heures moteur depuis RG''', '''Heures hélice depuis RG''', '''Potentiel''' (en heures et mois) et à la '''Prochaine action''' (en heures et mois) sont mises à jour automatiquement.&lt;br /&gt;
&lt;br /&gt;
La colonne '''Heures totales''' est mise à jour automatiquement dès qu'un vol est saisi ou supprimé sur la plateforme.&lt;br /&gt;
&lt;br /&gt;
===Lire l'onglet général===&lt;br /&gt;
[[File:tableur_suivi_navigabilité_vue_d_ensemble_ex.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Étant donné que cet onglet est géré de manière automatique, il n'y a aucune modification à effectuer. &lt;br /&gt;
&lt;br /&gt;
L'onglet synthétise les informations les plus importantes pour le suivi de maintenance des différentes ressources:&lt;br /&gt;
*'''Heures totales''' : C'est cette cellule qui est mise à jour automatiquement par le logiciel OpenFlyers, lors de la saisie ou suppression d'un vol.&lt;br /&gt;
*'''Heures depuis RG (Cellule)''' : Cette valeur correspond aux heures totales de la ressource depuis sa Révision Générale (RG). La RG est paramétrée pour [[#Onglets des ressources|correspondre à une visite]] de la ressource, par exemple la visite 2000h.&lt;br /&gt;
*'''Heures depuis RG (Moteur)''' : La valeur correspond aux heures totales du moteur depuis sa révision, soit depuis ses [[#Onglets des ressources|'''Heures début travaux''']].&lt;br /&gt;
*'''Heures depuis RG (Hélice)''' : Le principe est le même que pour le moteur, la valeur correspond aux heures totales depuis la révision de l'hélice.&lt;br /&gt;
*'''Potentiel''' : Le '''Potentiel''' est divisé en deux sous colonnes. Une contenant le potentiel restant en heures, une contenant le potentiel restant en mois. Les potentiels affichés sont ceux de la colonne '''Prochaine action'''.&lt;br /&gt;
*'''Prochaine action''' : La '''Prochaine action''', divisée en deux colonnes est un complément de la colonne '''Potentiel'''. Elle contient le nom des deux prochaines actions de la ressource arrivant à échéance, une en heures et une en mois. L'affichage de la '''Prochaine action''' est optimisé quand [[#Onglets de l'historique d'une ressource|l'onglet d'historique est complet]].&lt;br /&gt;
&lt;br /&gt;
Le potentiel affiché change de couleur selon sa valeur :&lt;br /&gt;
*Au dessus de 10 heures : &amp;lt;span style=&amp;quot;color: green;&amp;quot;&amp;gt;'''vert'''&amp;lt;/span&amp;gt;&lt;br /&gt;
*Entre 10 heures (inclus) et 5 heures (non inclus) : &amp;lt;span style=&amp;quot;color: orange;&amp;quot;&amp;gt;'''orange'''&amp;lt;/span&amp;gt;&lt;br /&gt;
*En dessous de 5 heures (inclus) : &amp;lt;span style=&amp;quot;color: red;&amp;quot;&amp;gt;'''rouge'''&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Onglets des ressources==&lt;br /&gt;
[[File:tableur_suivi_navigabilité_ressource.png|800px]]&lt;br /&gt;
&lt;br /&gt;
Chaque ressource suivie dans le classeur est accessible dans son propre onglet qui est paramétrable. Ainsi, pour chaque aéronef dans la vue d'ensemble, un onglet est présent avec le même nom.&lt;br /&gt;
&lt;br /&gt;
La page d'un aéronef contient ses caractéristiques nécessaires pour le suivi : les éléments, visites, potentiels, etc. Ainsi, chaque ligne du tableau correspond à un élément de la ressource qui est suivi.&lt;br /&gt;
&lt;br /&gt;
Tous les éléments devant être suivis doivent être renseignés et correctement paramétrés dans cet onglet. Le paramétrage est nécessaire au bon fonctionnement de [[#Onglets de l'historique d'une ressource|l'onglet d'historique]].&lt;br /&gt;
&lt;br /&gt;
Une fois le paramétrage correctement effectué, l'onglet complètera automatiquement les informations des actions, en allant chercher les bonnes informations [[#Onglets de l'historique d'une ressource|dans l'onglet de l'historique]].&lt;br /&gt;
&lt;br /&gt;
Lors du paramétrage des actions, [[#Ajouter ou supprimer une action|plusieurs champs sont à renseigner]].&lt;br /&gt;
===Ajouter ou supprimer une action===&lt;br /&gt;
[[File:tableur_suivi_navigabilité_ressource_ex_paramétrage.png]]&lt;br /&gt;
&lt;br /&gt;
Pour gérer les différentes actions, il est nécessaire d'éditer ces colonnes:&lt;br /&gt;
*Le '''Type'''&lt;br /&gt;
**Pour les visites, la valeur doit être '''Visite'''&lt;br /&gt;
**Pour un élément (moteur, hélice, etc), entrer '''Elément'''&lt;br /&gt;
**Pour les autres actions, entrer la valeur de votre choix.&lt;br /&gt;
*'''Description''' : Le nom et les informations détaillées sur l'action. Par exemple '''Visite 50 heures''', '''Moteur [ref]''', etc&lt;br /&gt;
*'''Durée potentielle''' : Si l'élément a une durée potentielle en heure, il faut remplir cette colonne.&lt;br /&gt;
*'''Potentiel calendaire en mois''' : Si l'élément a un potentiel calculé en mois, c'est cette colonne qu'il faut renseigner.&lt;br /&gt;
*'''Premiers travaux de référence''' : Il s'agit de la date ou des heures cellules des travaux de l'action à utiliser comme référence pour le calcul des valeurs dans [[#Onglets de l'historique d'une ressource|dans l'onglet de l'historique]]. Cette colonne permet de [[#Décalage du programme de maintenance|décaler le programme de maintenance de l'aéronef ('''explications sur l'utilisation du décalage''')]].&lt;br /&gt;
**'''Horaire''' : A remplir pour une action avec périodicité horaire. La valeur doit correspondre aux heures cellules  quand l'action a été effectuée pour la dernière fois.&lt;br /&gt;
***Si le programme de maintenance n'est pas décalé ('''toutes''' les interventions de l'aéronef seront saisies), ne rien remplir&lt;br /&gt;
**'''Calendaire''' : Le principe est identique aux premier travaux de référence ayant une périodicité horaire, la '''date''' des derniers travaux doit être indiquée.&lt;br /&gt;
***Si le programme de maintenance n'est pas décalé ('''toutes''' les interventions de l'aéronef seront saisies), la '''date de mise en circulation''' de l'aéronef doit être renseignée.&lt;br /&gt;
*'''Marge''' : La '''marge''' d'une action permet de calculer [[Maintenance-aéronautique#Schémas-:-calcul-d'échéances|la fenêtre de la butée optimale]]. Pour les actions horaires, la marge doit être en heures. Pour les actions calendaires, elle doit être en mois.&lt;br /&gt;
&lt;br /&gt;
Lors de l'ajout d'un nouvel élément donc d'une nouvelle ligne, il suffit de prendre une ligne vide disponible en bas du tableau et remplir les différentes colonnes citées.&lt;br /&gt;
&lt;br /&gt;
Pour la suppression d'un élément, il suffit simplement de vider les colonnes de paramétrage de l'élément.&lt;br /&gt;
&lt;br /&gt;
'''Attention''' : Après chaque modification d'une action, il faut [[#Modifications des actions d'une ressource et impact sur l'historique|vérifier la cohérence de l'historique]].&lt;br /&gt;
&lt;br /&gt;
===Lire les données d'une action===&lt;br /&gt;
[[File:tableur_suivi_navigabilité_ressource_ex_lecture.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois les actions paramétrées, les données se mettent à jour automatiquement en fonction des informations contenues dans [[#Onglets de l'historique d'une ressource|l'historique]].&lt;br /&gt;
Par exemple, la ligne d'une '''Visite 50h''' affichera les données de la dernière '''Visite 50h''' effectuée dans [[#Onglets de l'historique d'une ressource|l'historique]], '''sans prendre en compte le fait que [[#Maintenance-aéronautique#Remarques|les visites s'incluent]]'''.&lt;br /&gt;
&lt;br /&gt;
*'''Heures cellules début travaux''' : Le nombre d'heures de la ressource lorsque que l'action a été effectuée.&lt;br /&gt;
*'''Date fin travaux''' : Le principe est identique à '''Heures cellules début travaux'''. Cette colonne a pour but de contenir la date lorsque la dernière opération est terminée.&lt;br /&gt;
*'''Temps réalisé''' : Il s'agit du temps écoulé depuis les '''Heures cellules début travaux''' d'un élément. Si les potentiels de l'élément sont en durées, le '''Temps réalisé''' est en heures. Si ils sont en mois, la valeur est aussi en mois.&lt;br /&gt;
*'''Potentiel restant''' : Le potentiel restant est calculé selon les données précédentes, en heures ou en mois. Il s'agit d'une soustraction entre '''Durée potentielle''' et '''Temps réalisé''' pour les données en heures. Pour les données en mois une soustraction entre la date actuelle et la '''Butée en temps''' est effectuée.&lt;br /&gt;
*'''Butée horaire''' : Cette colonne est affichée uniquement si la '''Durée potentielle''' en heures d'un élément est renseignée. Le temps affiché est la quantité totale d'heures cellules de la ressource avant l'échéance de l'élément en prenant en compte la '''Marge horaire''' de l'action afin de construire un intervalle optimal.&lt;br /&gt;
*'''Butée en temps''' : Le principe est identique à la '''Butée horaire'''. La colonne est calculée uniquement si le '''Potentiel calendaire en mois''' est renseigné. La valeur affichée est la date d'échéance de l'élément en prenant en compte la '''Marge calendaire''' de l'action.&lt;br /&gt;
&lt;br /&gt;
==Onglets de l'historique d'une ressource==&lt;br /&gt;
[[File:Tableur_suivi_navigabilité_historique.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
En plus d'un tableau de suivi détaillé, chaque ressource dispose d'un onglet d'historique des actions, nommé '''RESSOURCE - Historique des actions'''.&lt;br /&gt;
&lt;br /&gt;
Dans cet onglet, toutes les actions effectuées sur l'aéronef doivent être saisies. Dès qu'une visite, révision ou autre action est faite, elle doit être ajoutée dans l'onglet afin de mettre à jour [[#Onglets des ressources|l'onglet de suivi détaillé de la ressource]].&lt;br /&gt;
&lt;br /&gt;
Une fois les valeurs saisies [[#Lire les informations de l'action ajoutée|les prochaines butées des actions]] sont estimées et affichées.&lt;br /&gt;
&lt;br /&gt;
===Ajouter une action effectuée===&lt;br /&gt;
[[File:Tableur_suivi_navigabilité_historique_ex_paramétrage.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour ajouter une nouvelle action qui vient d'être effectuée (par exemple, on vient de faire la '''Visite 100h'''), il faut renseigner ces trois champs dans une nouvelle ligne :&lt;br /&gt;
*'''Action''' : il s'agit d'une liste déroulante contenant les '''descriptions''' des actions définies dans [[#Onglets des ressources|l'onglet de suivi détaillé de la ressource]]. Il faut sélectionner l'action à ajouter.&lt;br /&gt;
*'''Heures cellules début travaux''' : Les heures cellules lors de la ressource lorsque l'action a été effectuée, le champ est obligatoire si l'action est horaire.&lt;br /&gt;
*'''Date fin travaux''' : La date lorsque l'action a été effectuée, le champ est obligatoire si l'action est calendaire&lt;br /&gt;
&lt;br /&gt;
'''Attention :'''&lt;br /&gt;
*Les actions doivent être saisies [[#Chronologie de l'historique des actions|dans l'ordre chronologique dans lequel est ont été effectuée]].&lt;br /&gt;
*Si [[#Décalage-du-programme-de-maintenance|le programme de maintenance est décalé]], l'historique doit contenir les actions '''suivant ce décalage'''. Par exemple si les '''Travaux de référence''' du '''Moteur''' sont de '''2000h''' (le suivi du moteur démarre à 2000h), l'historique ne doit pas contenir l'entrée du '''Moteur''' avec '''2000h''', il contiendra les intervetion sur le moteur suivantes.&lt;br /&gt;
&lt;br /&gt;
===Lire les informations de l'action ajoutée===&lt;br /&gt;
[[File:Tableur_suivi_navigabilité_historique_ex_lecture.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois [[#Ajouter une action effectuée|l'action ajoutée]], les données de l'action sont automatiquement calculées :&lt;br /&gt;
*'''Butée horaire théorique''' : Cette colonne, vide si l'action est calendaire, contiendra la '''fourchette de la butée de l'action saisie'''. Autrement dit, pour optimiser le programme de maintenance de l'aéronef, il est préférable que l'action (ses '''Heures cellules début travaux''') soit dans cet intervalle.&lt;br /&gt;
*'''Butée calendaire théorique''' : Le principe est le même que la '''Butée horaire théorique''' mais pour les actions calendaires. Il s'agit d'un intervalle de date optimal pour effectuer l'action : il est préférable que la '''Date fin travaux''' appartienne à cet intervalle.&lt;br /&gt;
*'''Prochaine butée horaire''' : Il s'agit de la fenêtre optimale de la butée pour la '''prochaine action'''&lt;br /&gt;
**Dans le cas d'une visite horaire, une visite se fait toutes les 50 heures. Donc la '''Prochaine butée horaire''' est calculée 50 heures en avance.&lt;br /&gt;
*'''Prochaine butée calendaire''' : Le principe est le même que la '''Butée horaire théorique''' mais pour les actions calendaires. Il s'agit d'un intervalle de date optimal pour effectuer l'action.&lt;br /&gt;
**Pour les visites calendaires (1 an, 2 ans, etc), la fenêtre est calculée avec un an d'avance, puisqu'une visite calendaire est effectuée tous les ans.&lt;br /&gt;
&lt;br /&gt;
==Règles de modification du document==&lt;br /&gt;
&lt;br /&gt;
===Chronologie de l'historique des actions===&lt;br /&gt;
Dans [[#Onglets-de-l'historique-d'une-ressource|l'onglet d'historique des actions]] d'une ressource, il est conseillé de saisir les actions dans leur ordre chronologique afin d'avoir un affichage et un enchaînement des valeurs calculées plus clair.&lt;br /&gt;
&lt;br /&gt;
===Format des dates===&lt;br /&gt;
Le classeur est au format Royaume-Unis, ainsi :&lt;br /&gt;
*Les durée utilisent le format '''Heures:Minutes:Secondes.Millisecondes'''&lt;br /&gt;
&lt;br /&gt;
===Modifications des actions d'une ressource et impact sur l'historique===&lt;br /&gt;
Pour une ressource, son [[#Onglets-de-l'historique-d'une-ressource|onglet d'historique des actions]] est lié au [[#Ajouter-ou-supprimer-une-action|paramétrage des actions dans l'onglet de la ressource]].&lt;br /&gt;
&lt;br /&gt;
Si le paramétrage d'une action est modifié, toutes les entrées correspondant à cette même action dans l'historique seront modifiées. Par exempe si on modifie le paramétrage de la '''Visite 50H''', toutes les '''Visites 50H''' rentrées dans l'historique seront mises à jour.&lt;br /&gt;
&lt;br /&gt;
Lorsque la '''[[#Ajouter-ou-supprimer-une-action|description]]''' d'une action est modifiée, il faut vérifier celles affichées dans [[#Onglets-de-l'historique-d'une-ressource|l'historique d'historique des actions]]. Si la description d'une action ne correspond plus entre ces deux onglets, le lien et les calculs ne peuvent pas être faits correctement.&lt;br /&gt;
&lt;br /&gt;
===Modifications des cellules===&lt;br /&gt;
Une partie des cellules sont calculées automatiquement, il n'est pas nécessaire de les modifier.&lt;br /&gt;
&lt;br /&gt;
Les colonnes comportant des cellules modifiables ont une annotation :&lt;br /&gt;
*'''&amp;quot;À renseigner&amp;quot;''' lorsque les informations peuvent être modifiées autant de fois que désiré&lt;br /&gt;
*'''&amp;quot;À paramétrer&amp;quot;''' lorsqu'une valeur '''définitive''' est attendue&lt;br /&gt;
&lt;br /&gt;
Ainsi, dans la [[#Onglet &amp;quot;Vue d'ensemble&amp;quot;|vue d'ensemble]], aucune colonne n'est à modifier.&lt;br /&gt;
&lt;br /&gt;
Dans [[#Onglets des ressources|les onglets des ressource]], les colonnes '''Description''', '''Durée potentielle''', '''Potentiel calendaire en mois''', '''Premier travaux de référence''' et '''Marge''' doivent être paramétrées de manière définitive pour chaque élément.&lt;br /&gt;
&lt;br /&gt;
Dans l'onglet [[#Onglets de l'historique d'une ressource|'''d'historique et de saisie des actions''']], les colonnes '''Heures cellules début travaux''' et/ou '''Date fin travaux''' doivent être renseignées et peuvent être modifiées par la suite.&lt;br /&gt;
&lt;br /&gt;
==Décalage du programme de maintenance==&lt;br /&gt;
Par défaut, le classeur de suivi de maintenance est prévu pour que '''toutes''' les interventions d'un aéronef soient renseignées dans [[#Onglets-de-l'historique-d'une-ressource|l'onglet d'historique de la ressource]] et ce, depuis sa mise en circulation.&lt;br /&gt;
&lt;br /&gt;
Si des interventions ont déjà été effectuées sur l'aéronef quand le classeur est paramétré pour la première fois, ou si les interventions précédentes sont inconnues, il est possible de '''décaler le programme de maintenance'''. De cette manière, on évite de devoir saisir les anciennes actions effectuées.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour décaler un programme de maintenance, un paramétrage supplémentaire est nécessaire afin d'optimiser les calculs des butées :&lt;br /&gt;
#[[Tableurs#Ouvrir-un-classeur|Se rendre sur le classeur]]&lt;br /&gt;
#Aller dans l'onglet de [[#Onglets des ressources|paramétrage du programme de maintenance de la ressource]]&lt;br /&gt;
#Renseigner les bonnes valeurs dans la colonne '''Premier travaux de référence (horaire et calendaire)'''&lt;br /&gt;
&lt;br /&gt;
Si le programme de maintenance doit démarrer à un certain instant '''t''', les premiers travaux de référence de chaque action correspondent aux '''heures''' et à la '''date''' auxquels l'action a été effectuée pour la dernière fois quand l'aéronef avait '''t''' heures de vol. Pour les visites, on prend en compte le fait qu'elles [[Maintenance-aéronautique#Remarques|s'incluent]].&lt;br /&gt;
&lt;br /&gt;
Par exemple, un aéronef a déjà 2054h de vol et on veut faire démarrer le programme de maintenance à ce moment :&lt;br /&gt;
#La dernière '''Visite 50h''' a été effectuée à 2050h&lt;br /&gt;
#La dernière '''Visite 100h''' a été effectuée à 2000h (inclue dans la '''Visite 2000h''')&lt;br /&gt;
#La dernière '''Visite 500h''' a été effectuée à 2000h (inclue dans la '''Visite 2000h''')&lt;br /&gt;
#La dernière révision du '''Moteur''' était à 2000h&lt;br /&gt;
#etc.&lt;br /&gt;
&lt;br /&gt;
Ces valeurs de référence ne prennent pas en compte les marges de tolérance, donc le retard ou l'avance sur l'action. La valeur peut donc être approximative. En reprenant l'exemple précédent :&lt;br /&gt;
*Par exemple, la dernière '''Visite 50h''' a été effectuée à 2067h.&lt;br /&gt;
*Cette visite aurait dû être effectuée à 2050h, de plus la prochaine est prévue pour 2100h (on additionne les heures lors de la dernière visite plus sa périodicité)&lt;br /&gt;
*En mettant 2067h, la prochaine visite serait calculée à 2117h, donc la bonne valeur à renseigner est '''2050h'''. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Attention, pour la saisie de '''toutes''' les visites horaires et calendaires, '''les butées calculées et affichées''' démarrent '''toutes''' de la plus petite visite (habituellement la '''Visite 50h''' et la '''Visite 1 an''') :&lt;br /&gt;
*Ainsi, les prochaines butées des visites horaires sont, par exemple, calculées à partir de la '''Visite 50h''' de référence&lt;br /&gt;
*Les prochaines butées des visites calendaires sont, par exemple, souvent calculées à partir de la '''Visite 1 an''' de référence&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois ces valeurs de référence entrées, [[#Onglets-de-l'historique-d'une-ressource|l'onglet d'historique de la ressource]] peut être complété en indiquant toutes les interventions '''après''' ces valeurs de référence. Par exemple, si la valeur de référence de la '''Visite 50h''' est 2050h, l'historique ne doit pas contenir de valeur pour la '''Visite 50h''' à 2050h. Seulement les '''Visites 50h''' suivantes seront renseignées.  Le principe est le même pour les autres visites et toute autre action.&lt;br /&gt;
&lt;br /&gt;
==Utilisation du classeur==&lt;br /&gt;
===Paramétrer une action dans le programme de maintenance===&lt;br /&gt;
Pour rajouter une action dans le programme de maintenance d'un aéronef, il faut :&lt;br /&gt;
&lt;br /&gt;
#Se rendre sur [[#Onglets-des-ressources|l'onglet du programme de maintenance]]&lt;br /&gt;
#Saisir l'action dans une ligne vide&lt;br /&gt;
#*'''Type''' :&lt;br /&gt;
#**'''Élément''', à choisir pour un moteur ou une hélice&lt;br /&gt;
#**'''Visite''', à choisir pour une visite horaire ou calendaire (Visite 50h, Visite 5 ans, etc)&lt;br /&gt;
#**Si l'action ne correspond pas aux types au-dessus, il est possible de mettre un type personnalisé complètement arbitraire&lt;br /&gt;
#*'''Description''' : l'intitulé de l'action ou une très courte description&lt;br /&gt;
#Selon le type de périodicité de l'action&lt;br /&gt;
#*Saisir la '''Durée potentielle''' en heure, ou&lt;br /&gt;
#*saisir le '''Potentiel calendaire en mois'''&lt;br /&gt;
#Si le suivi de l'action doit-être décalé, [[#Décaler le programme de maintenance|saisir des travaux de référence]]&lt;br /&gt;
#Selon le type de périodicité de l'action&lt;br /&gt;
#*Saisir la '''Marge horaire''' , ou&lt;br /&gt;
#*saisir la '''Marge calendaire'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:tableur_suivi_maintenance_creation_action.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois ces colonnes remplies, l'action est désormais ajoutée au programme de maintenance. Elle sera suivi et prise en compte dans l'historique.&lt;br /&gt;
&lt;br /&gt;
===Saisir une action venant d'être effectuée===&lt;br /&gt;
[[#Onglets-des-ressources|L'onglet du programme de maintenance]] d'un aéronef contient ses actions suivies.&lt;br /&gt;
&lt;br /&gt;
Si une action vient d'être effectuée sur l'aéronef, il faut la saisir dans [[#Onglets de l'historique d'une ressource|l'onglet d'historique de la ressource]].&lt;br /&gt;
&lt;br /&gt;
Par exemple, si une '''Visite 100h''' a été effectuée, elle doit être renseignée :&lt;br /&gt;
#Se rendre sur [[#Onglets-des-ressources|l'onglet d'historique de la ressource]]&lt;br /&gt;
#Saisir l'action dans une ligne vide, '''à la suite des actions précédentes, dans l'ordre chronologique'''&lt;br /&gt;
#*Colonne '''Action''' : Un clic affiche toutes les actions paramétrées dans [[#Onglets-des-ressources|l'onglet du programme de maintenance]]. Sélectionner la bonne action.&lt;br /&gt;
#Selon le type de périodicité de l'action&lt;br /&gt;
#*Saisir les '''Heures cellules début travaux''' au début de l'intervention , ou&lt;br /&gt;
#*saisir la '''Data fin travaux''' à la fin de l'intervention&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:tableur_suivi_maintenance_saisie_action.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Une fois ces colonnes remplies, l'intervention est prise en compte dans les calculs du suivi de maintenance.&lt;br /&gt;
&lt;br /&gt;
===Décaler le programme de maintenance===&lt;br /&gt;
Habituellement, '''toutes les actions effectuées sur un avion depuis sa mise en circulation '''doivent être saisies dans [[#Onglets de l'historique d'une ressource|l'onglet d'historique]]'''.&lt;br /&gt;
Si on ne connaît pas l'historique de l'entretien entier d'une ressource, il est nécessaire de décaler le programme de maintenance pour ne pas prendre en compte les actions précédentes qui sont inconnues.&lt;br /&gt;
&lt;br /&gt;
Dans ce cas, il est nécessaire de choisir, pour chaque action (moteur, hélice, visite 50h et autres), des '''travaux de référence''' qui ont deux rôles :&lt;br /&gt;
*Décaler l'enchaînement et la saisie des futures actions saisies, en ignorant les visites précédentes inconnues&lt;br /&gt;
*Calculer la toute première prochaine butée&lt;br /&gt;
&lt;br /&gt;
Pour ce faire, il faut :&lt;br /&gt;
#Se rendre sur [[#Onglets-des-ressources|l'onglet du programme de maintenance]]&lt;br /&gt;
#Renseigner les '''Premiers travaux de référence''' :&lt;br /&gt;
#*'''Horaire''', à saisir s'il s'agit d'une action horaire, mettre le nombre d'heures de vol qu'avait l'aéronef lors de l'action&lt;br /&gt;
#*'''Horaire''', à saisir s'il s'agit d'une action calendaire, mettre la date lorsque l'action a été effectuée&lt;br /&gt;
&lt;br /&gt;
Remarques :&lt;br /&gt;
*Les premiers travaux de référence prennent en compte le fait que les [[Maintenance-aéronautique#Remarques|visites s'incluent]] : si on a fait une 100 heures, on considère qu'on a aussi fait une 50 heures&lt;br /&gt;
*L'[[#Onglets de l'historique d'une ressource|historique]] ne contient pas les actions correspondant aux travaux de référence, mais contient uniquement les actions '''suivantes''', donc l'action de référence est exclue&lt;br /&gt;
*Cependant dans l'[[#Onglets de l'historique d'une ressource|historique]], les calculs des '''visites''' sont continus et se suivent. Toutes les visites '''suivant''' la première occurence de la plus petite doivent être saisies. La première occurrence de la petite visite est exclue.&lt;br /&gt;
&lt;br /&gt;
Désormais, les calculs dans le programme de maintenance prennent en compte les décalages paramétrés.&lt;br /&gt;
&lt;br /&gt;
====Exemple de décalage====&lt;br /&gt;
[[File:tableur_suivi_maintenance_décalage_programme_maintenance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Par exemple, on vient d'acquérir un aéronef qui a 12250 heures de vol. On ne connaît pas l'historique entier des interventions. &lt;br /&gt;
&lt;br /&gt;
Cependant :&lt;br /&gt;
*La révision du moteur la plus ancienne qu'on connaît a été effectuée à 12000 heures&lt;br /&gt;
*La visite 50 heures la plus ancienne qu'on connaît a été effectuée à 12250 heures&lt;br /&gt;
*La visite 100 heures la plus ancienne qu'on connaît a été effectuée à 12200 heures&lt;br /&gt;
*etc...&lt;br /&gt;
&lt;br /&gt;
On a donc comme '''travaux de référence''' à renseigner dans le classeur :&lt;br /&gt;
*12000 heures pour le moteur&lt;br /&gt;
*12250 heures pour la visite 50 heures&lt;br /&gt;
*12200 heures pour la visite 100 heures&lt;br /&gt;
*etc...&lt;br /&gt;
&lt;br /&gt;
Les toutes premières butées calculées seront donc :&lt;br /&gt;
*14000 heures pour le moteur, en supposant que son potentiel est de 2000 heures&lt;br /&gt;
*12300 heures pour la visite 50 heures&lt;br /&gt;
*12300 heures pour la visite 100 heures&lt;br /&gt;
*etc...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:tableur_suivi_maintenance_décalage_historique.png|500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On suppose que l'avion a maintenant 12400 heures de vol. Il y a eu des interventions depuis et on aurait un historique des actions proche de celui-ci :&lt;br /&gt;
#Les travaux de référence du moteur correspondent à 12000 heures. L'historique ne doit pas contenir l'entrée '''Moteur à 12000 heures'''. Depuis, il n'y a pas eu de révision, donc il n'y a aucune ligne sur le moteur.&lt;br /&gt;
#La première visite 50 heures connue a été effectuée à 12250 heures. Tout comme le moteur, dans l'historique, il ne faut pas la saisir. La valeur de référence est détectée et utilisée en point de départ.&lt;br /&gt;
#Cependant, '''toutes les visites suivantes''', y compris les autres visites de référence (ici la 100 heures de référence à 12200 heures qui est surlignée), '''doivent être saisies'''&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Champs-m%C3%A9tiers&amp;diff=12879</id>
		<title>Champs métiers</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Champs-m%C3%A9tiers&amp;diff=12879"/>
		<updated>2024-10-02T17:27:48Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter les '''champs métiers''' de la [[Accueil|version 4 d'OpenFlyers]].&lt;br /&gt;
&lt;br /&gt;
Le droit [[Gestion-des-profils#Gestion-du-paramétrage|Gestion du paramétrage]] est nécessaire pour accéder à cette page.&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
Les champs métiers ont pour vocation de remplacer les champs définis en dur dans les différents modules du logiciel OpenFlyers :&lt;br /&gt;
*Imports et synchronisations&lt;br /&gt;
*Gestion des ressources&lt;br /&gt;
*Gestion des utilisateurs&lt;br /&gt;
*Saisie des réservations&lt;br /&gt;
*Saisie des activités (saisie des vols par exemple)&lt;br /&gt;
*Edition des rapports&lt;br /&gt;
*Rapport des mouvements comptables (ou flux) d'un compte et factures&lt;br /&gt;
&lt;br /&gt;
On retrouve ces modules dans la colonne '''Catégorie''' :&lt;br /&gt;
*Comptabilité : Cela rajoute une colonne dans les rapports et les factures&lt;br /&gt;
*Import : Cela rajoute un champ dans le module d'import&lt;br /&gt;
*Rapport : Cela rajoute un champ dans le formulaire d'édition des rapports&lt;br /&gt;
*Ressource : Cela rajoute un champ dans le formulaire de gestion de ressource&lt;br /&gt;
*Réservation : Cela rajoute un champ dans le formulaire de réservation&lt;br /&gt;
*Utilisateur : Cela rajoute une champ dans les fiches utilisateurs&lt;br /&gt;
*Activité : Cela rajoute un champ dans le formulaire de saisie des réservations ectèrnes&lt;br /&gt;
*Réservation extérieure: Cela rajoutera un champ dans le formulaire de saisie des vols&lt;br /&gt;
&lt;br /&gt;
Ils permettent ainsi une plus grande flexibilité dans la configuration d'OpenFlyers en permettant de créer librement des champs et en permettant de définir qui peut y avoir accès, qui peut en voir le contenu et quelles règles de saisies peuvent être imposées pour chaque champ.&lt;br /&gt;
&lt;br /&gt;
[[#Champs-spécifiques|Certains champs additionnels restent néanmoins liés à des comportements spécifiques du logiciel.]] Leur absence entraine alors une régression des fonctionnalités propres à OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
L'accès à la gestion des champs additionnels se fait depuis '''Admin &amp;gt; Configuration &amp;gt; Champ(s) additionnel(s)''' :&lt;br /&gt;
[[File:Extrafield4.png]]&lt;br /&gt;
&lt;br /&gt;
Pour chaque champ, il est possible de définir le [[#Type-de-valeur|type de valeur]]. En fonction du type sélectionné, le champ prendra une forme différente (zone de saisie libre, &amp;quot;combo&amp;quot;, etc.)&lt;br /&gt;
&lt;br /&gt;
=Champs spécifiques=&lt;br /&gt;
&lt;br /&gt;
==activityComment==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''activityComment''' remplace le champ en dur qui permettait de laisser un commentaire sur l'activité.&lt;br /&gt;
&lt;br /&gt;
==airborneTime==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''airborneTime''' permet de spécifier pour chaque vol le temps passé en l'air cela est utilisé pour [[Interfaçage-OpenFlyers-et-Charterware|l'interfaçage Charterware]].&lt;br /&gt;
&lt;br /&gt;
==aerogligliPilotId==&lt;br /&gt;
Le champ métier '''aerogligliPilotId''' permet de coupler les utilisateurs avec [[Interfaçage-Aérogligli|Aérogligli]]. Ce champ est de type '''Chaîne textuelle''' et appartient à la catégorie '''Utilisateur'''.&lt;br /&gt;
&lt;br /&gt;
Ainsi, lorsqu'il est activé, chaque utilisateur verra apparaître dans sa [[Fiche personnelle]] un champ '''Numéro d'utilisateur Aérogligli'''.&lt;br /&gt;
Une fois le numéro d'utilisateur aérogligli renseigné, l'utilisateur verra ses [[Interfaçage-Aérogligli|statistiques Aérogligli]] apparaître dans le tableau de bord.&lt;br /&gt;
&lt;br /&gt;
==billingAddress==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''billingAddress''' est utilisé dans la facturation pour modifier l'adresse de l'utilisateur facturé par l'adresse d'un autre utilisateur.&lt;br /&gt;
&lt;br /&gt;
Pour autoriser cette fonctionnalité, [[Champs-métiers#Introduction|créer le champ métier]] avec :&lt;br /&gt;
* '''Nom''' : billingAddress&lt;br /&gt;
* '''Intitulé''' : Adresse de facturation&lt;br /&gt;
* '''Type de valeur''' : dbObject::Person&lt;br /&gt;
* '''Catégorie''' : Utilisateur&lt;br /&gt;
&lt;br /&gt;
Ensuite, procéder à la liaison des utilisateurs :&lt;br /&gt;
* Aller '''Gestion &amp;gt; Utilisateurs &amp;gt; Utilisateurs &amp;gt; Actifs'''&lt;br /&gt;
* Aller sur la ligne d'un utilisateur et cliquer sur l'icône &amp;quot;Crayon&amp;quot;&lt;br /&gt;
* Dans le champ '''Adresse de facturation''', sélectionner un utilisateur dont son adresse sera utilisée pour la facturation&lt;br /&gt;
* Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
&lt;br /&gt;
==bookingArrivalLocation==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''bookingArrivalLocation''' de catégorie '''Réservation''' remplace le champ en dur qui permettait de choisir le lieu d'arrivée.&lt;br /&gt;
&lt;br /&gt;
==bookingComment==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''bookingComment''' remplace le champ en dur qui permettait de laisser un commentaire sur la réservation.&lt;br /&gt;
&lt;br /&gt;
==bookingDepartureLocation==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''bookingDepartureLocation''' de catégorie '''Réservation''' remplace le champ en dur qui permettait de choisir le lieu de départ.&lt;br /&gt;
&lt;br /&gt;
==bookingEstimatedFlightTime==&lt;br /&gt;
Le champ métier '''bookingEstimatedFlightTime''' remplace le champ en dur qui permettait de connaitre la durée du temps de vol prévu. S'il est présent, alors OpenFlyers le renseigne automatiquement lorsqu'il est laissé vide en prenant la moitié de la durée de la réservation.&lt;br /&gt;
&lt;br /&gt;
Ce champ métier permet aussi le calcul du temps prévisionnel qui va s'afficher au niveau du planning, en dessous de chaque réservation.&lt;br /&gt;
&lt;br /&gt;
Il est également possible d'obliger les utilisateurs à renseigner la valeur du champ en cochant la check-box de la colonne '''Remplissage obligatoire'''.&lt;br /&gt;
&lt;br /&gt;
Pour que la valeur contenue dans ce champ soit utilisée pour remplir par défaut le champ '''Durée du vol''' lors de la saisie d'un vol associé à une réservation, il faut :&lt;br /&gt;
*Dans la cellule de la colonne '''Catégorie liée''', sélectionner '''Vol'''&lt;br /&gt;
*Dans la cellule de la colonne '''Champ à lier''', sélectionner '''Temps de vol'''&lt;br /&gt;
&lt;br /&gt;
==bookingFreeSeats==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''bookingFreeSeats''' remplace le champ en dur '''Places à disposition''' qui permettait de saisir le nombre de places à disposition.&lt;br /&gt;
&lt;br /&gt;
Valeur par défaut : '''0'''&lt;br /&gt;
&lt;br /&gt;
==charterwareUserId==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''charterwareUserId''' permet de spécifier pour chaque utilisateur son identifiant Charterware cela est utilisé pour [[Interfaçage-OpenFlyers-et-Charterware|l'interfaçage Charterware]]&lt;br /&gt;
&lt;br /&gt;
==charterwareResourceId==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''charterwareResourceId''' permet de spécifier pour chaque ressource son identifiant Charterware cela est utilisé pour [[Interfaçage-OpenFlyers-et-Charterware|l'interfaçage Charterware]]&lt;br /&gt;
&lt;br /&gt;
==city==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''city''' de catégorie '''Ayant comme activité''' permet de définir la ville de [[Utilisation-du-planning-de-réservation#Créer-automatiquement-un-utilisateur-en-créant-une-réservation|de l'utilisateur lors de la création automatique à la réservation]].&lt;br /&gt;
&lt;br /&gt;
==email==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''email''' de catégorie '''Ayant comme activité''' permet de définir l'email [[Utilisation-du-planning-de-réservation#Créer-automatiquement-un-utilisateur-en-créant-une-réservation|de l'utilisateur lors de la création automatique à la réservation]].&lt;br /&gt;
&lt;br /&gt;
==endDate==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''endDate''' de catégorie '''Réservation''' permet de définir la date de fin des [[Utilisation-du-planning-de-réservation|réservations sur la nouvelle interface]].&lt;br /&gt;
&lt;br /&gt;
==firstName==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''firstName''' de catégorie '''Ayant comme activité''' permet de définir le nom de [[Utilisation-du-planning-de-réservation#Créer-automatiquement-un-utilisateur-en-créant-une-réservation|de l'utilisateur lors de la création automatique à la réservation]].&lt;br /&gt;
&lt;br /&gt;
==hardLandingReport==&lt;br /&gt;
Le champ métier '''hardLandingReport''' (Rapport d'atterrissage dur) de catégorie '''Vol''' permet de stocker le rapport d'atterrissage dur récupéré de l'[[Interfaçage-OpenFlyers-et-Charterware|interfaçage avec Charterware]].&lt;br /&gt;
&lt;br /&gt;
==keyAuthorization==&lt;br /&gt;
Le champ métier '''keyAuthorization''' de catégorie '''Utilisateur''' est utilisé notamment pour certains [[Contrôle-des-accès|contrôles d'accès]] afin de mettre à jour la clé d'accès de chaque utilisateur.&lt;br /&gt;
&lt;br /&gt;
===Mettre à jour les clés d'autorisations des utilisateurs===&lt;br /&gt;
Les actions suivantes permettent de mettre à jour les clés de tous les utilisateurs :&lt;br /&gt;
*Créer, modifier, supprimer un type de validité&lt;br /&gt;
*Modifier les types de validités requises d'un type de ressource&lt;br /&gt;
&lt;br /&gt;
Les actions suivantes permettent de mettre à jour la clé d'un seul utilisateur :&lt;br /&gt;
*Ajouter, modifier, supprimer une validité d'un utilisateur&lt;br /&gt;
*Créer, modifier, supprimer un vol&lt;br /&gt;
&lt;br /&gt;
==keyPanelUserId==&lt;br /&gt;
Le champ métier '''keyPanelUserId''' de catégorie '''Utilisateur''' est utilisé notamment pour certains [[Contrôle-des-accès|contrôles d'accès]] afin d'indiquer le numéro de badge attribué à chaque utilisateur.&lt;br /&gt;
&lt;br /&gt;
Ce champ doit être renseigné pour chaque utilisateur qui dispose d'un badge.&lt;br /&gt;
&lt;br /&gt;
==landingDate==&lt;br /&gt;
Le champ métier '''landingDate''' de catégorie '''Vol''' permet de stocker la date d'atterissage récupérée de l'[[Interfaçage-OpenFlyers-et-Charterware|interfaçage avec Charterware]].&lt;br /&gt;
&lt;br /&gt;
==lastName==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''lastName''' de catégorie '''Ayant comme activité''' permet de définir le nom de [[Utilisation-du-planning-de-réservation#Créer-automatiquement-un-utilisateur-en-créant-une-réservation|de l'utilisateur lors de la création automatique à la réservation]].&lt;br /&gt;
&lt;br /&gt;
==offBlockDate==&lt;br /&gt;
Le champ métier '''offBlockDate''' permet de spécifier pour chaque vol une heure off block cela est utilisé pour [[Interfaçage-OpenFlyers-et-Charterware|l'interfaçage Charterware]]&lt;br /&gt;
&lt;br /&gt;
==onBlockDate==&lt;br /&gt;
Le champ métier '''onBlockDate''' permet de spécifier pour chaque vol une heure on block cela est utilisé pour [[Interfaçage-OpenFlyers-et-Charterware|l'interfaçage Charterware]]&lt;br /&gt;
&lt;br /&gt;
==phone==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''phone''' de catégorie '''Ayant comme activité''' permet de définir le téléphone de [[Utilisation-du-planning-de-réservation#Créer-automatiquement-un-utilisateur-en-créant-une-réservation|de l'utilisateur lors de la création automatique à la réservation]].&lt;br /&gt;
&lt;br /&gt;
==spreadsheetResourceCell==&lt;br /&gt;
Le champ métier '''spreadsheetResourceCell''' remplace le champ en dur qui permettait de définir, [[Tableurs|pour une feuille de calcul]], la cellule liée à la ressource.&lt;br /&gt;
&lt;br /&gt;
==startDate==&lt;br /&gt;
&lt;br /&gt;
Le champ métier '''startDate''' de catégorie '''Réservation''' permet de définir la date de début des [[Utilisation-du-planning-de-réservation|réservations sur la nouvelle interface]].&lt;br /&gt;
&lt;br /&gt;
==takeoffDate==&lt;br /&gt;
Le champ métier '''takeoffDate''' de catégorie '''Vol''' permet de stocker la date de décollage récupérée de l'[[Interfaçage-OpenFlyers-et-Charterware|interfaçage avec Charterware]].&lt;br /&gt;
&lt;br /&gt;
=Type de valeur=&lt;br /&gt;
&lt;br /&gt;
Les types de valeurs proposées sont :&lt;br /&gt;
*'''currency''' pour les nombres décimaux positifs (utilisé principalement pour du monétaire)&lt;br /&gt;
*'''date''' pour les dates&lt;br /&gt;
*'''datetime''' pour les dates avec les heures&lt;br /&gt;
*'''decimal''' pour les nombres décimaux&lt;br /&gt;
*'''integer''' pour les entiers&lt;br /&gt;
*'''formula''' pour les formules&lt;br /&gt;
*'''mois''' pour les mois. Seul le module [[Gestion-des-rapports|Edition des rapports]] peut exploiter ce type de valeur.&lt;br /&gt;
*'''multiline_string''' pour les chaînes textuelles multi-ligne&lt;br /&gt;
*'''sexacentimal''' pour les [[Formules-de-calcul#Définition-Unité-sexacentimal|Sexacentimal]]&lt;br /&gt;
*'''time''' pour les heures&lt;br /&gt;
*'''unique_integer''' pour les entiers dont les valeurs doivent être uniques&lt;br /&gt;
*'''unique_string''' pour les chaînes textuelles dont les valeurs doivent être uniques&lt;br /&gt;
*'''string''' pour les chaînes textuelles&lt;br /&gt;
*'''year''' pour les années&lt;br /&gt;
*[[#dbObject::XXX|'''dbObject::XXX''']] pour un élément de la base de données&lt;br /&gt;
*[[#dbObjectMulti::XXX|'''dbObjectMulti::XXX''']] pour plusieurs éléments de la base de données. Seul le module [[Gestion-des-rapports|Edition des rapports]] peut exploiter ce type de valeur.&lt;br /&gt;
&lt;br /&gt;
==dbObject::[[#Liste-des-valeurs-possibles-pour-dbObject-et-dbObjectMulti|XXX]]==&lt;br /&gt;
&lt;br /&gt;
Chaque type '''dbOject''' représentent [[#Liste-des-valeurs-possibles-pour-dbObject-et-dbObjectMulti|une table de la base de donnée]] et retournent les entrées de la table sous forme d'une liste déroulante. Exemple : '''dbObject::Account''' retourne la liste des comptes. Chaque liste déroulante a pour première entrée la valeur ''Pas de filtre''. Il n'est possible de ne sélectionner qu'un élément.&lt;br /&gt;
&lt;br /&gt;
Cas particulier pour le type '''dbObject::Person''', il est possible de filtrer la liste des personnes avec l'identifiant d'un profil. Le logiciel va proposer pour chaque profil un type '''dbObject::Person''', par exemple : '''dbObject::Person::1024''' et qui sera affiché dans le logiciel sous cette forme : '''dbObject::Person (Instructeur)'''.&lt;br /&gt;
&lt;br /&gt;
==dbObjectMulti::[[#Liste-des-valeurs-possibles-pour-dbObject-et-dbObjectMulti|XXX]]==&lt;br /&gt;
&lt;br /&gt;
Chaque type '''dbObjectMulti''' représentent [[#Liste-des-valeurs-possibles-pour-dbObject-et-dbObjectMulti|une table de la base de donnée]] et retournent les entrées de la table sous forme d'une liste de cases à cocher. Exemple : '''dbObjectMulti::Profile''' retourne la liste des profils. Il est possible de sélectionner plusieurs éléments.&lt;br /&gt;
&lt;br /&gt;
==Liste des valeurs possibles pour [[#dbObject::XXX|dbObject]] et [[#dbObjectMulti::XXX|dbObjectMulti]]==&lt;br /&gt;
*Account&lt;br /&gt;
*AccountEntry&lt;br /&gt;
*Accounting&lt;br /&gt;
*AccountType&lt;br /&gt;
*ActivityType&lt;br /&gt;
*BalanceDate&lt;br /&gt;
*Booking&lt;br /&gt;
*Budget&lt;br /&gt;
*BudgetGroup&lt;br /&gt;
*BusinessField&lt;br /&gt;
*Structure&lt;br /&gt;
*Criteria&lt;br /&gt;
*ExceptionnalInstDate&lt;br /&gt;
*Flight&lt;br /&gt;
*FlightHoursPricing&lt;br /&gt;
*Location&lt;br /&gt;
*Logger&lt;br /&gt;
*Nationality&lt;br /&gt;
*Parameter&lt;br /&gt;
*PaymentDistribution&lt;br /&gt;
*PaymentType&lt;br /&gt;
*Person&lt;br /&gt;
*Profile&lt;br /&gt;
*Product&lt;br /&gt;
*RegularPresenceInstDate&lt;br /&gt;
*Resource&lt;br /&gt;
*ResourceType&lt;br /&gt;
*SalePricing&lt;br /&gt;
*Status&lt;br /&gt;
*Stock&lt;br /&gt;
*StockLevel&lt;br /&gt;
*StockType&lt;br /&gt;
*StockVariation&lt;br /&gt;
*SupplierBill&lt;br /&gt;
*SupplierBillType&lt;br /&gt;
*ValidityType&lt;br /&gt;
*Variable&lt;br /&gt;
*WebFeed&lt;br /&gt;
*WebFeedChannel&lt;br /&gt;
&lt;br /&gt;
=Utilisations=&lt;br /&gt;
==Ajouter un champ métier==&lt;br /&gt;
* Aller Dans '''Structure › Variables › Champs métiers'''&lt;br /&gt;
* Renseigner les champs suivants :&lt;br /&gt;
** '''Nom du champ''' : un identifiant unique pour le champ.&lt;br /&gt;
** '''Intitulé''' : le nom qui apparaîtra dans l'interface utilisateur.&lt;br /&gt;
** '''Catégorie''' : représente le module auquel le champ métier peut être amputé.&lt;br /&gt;
** '''Type de valeur''' : [[#Type-de-valeur|le type de données]] autorisé.&lt;br /&gt;
** '''Formule''' : Si le champ nécessite une valeur calculée, saisir la formule correspondante.&lt;br /&gt;
** '''Remplissage obligatoire''' : Cocher cette case si le champ doit être complété par l'utilisateur.&lt;br /&gt;
** '''Catégorie liée''' : la catégorie à lier au champ métier.&lt;br /&gt;
** '''Champ à lier''' : Ce champ s'affiche automatiquement lorsqu'une catégorie est sélectionnée. Il correspond au champ métier ou original de la catégorie associée, où la valeur saisie par le client externe est enregistrée.&lt;br /&gt;
** '''Valeur par défaut''' : Définir une valeur par défaut si applicable.&lt;br /&gt;
* Cliquer sur le bouton '''Ajouter'''&lt;br /&gt;
&lt;br /&gt;
==Créer une colonne supplémentaire dans les factures des heures de vols==&lt;br /&gt;
Il est possible de créer des colonnes supplémentaires dans les factures des heures de vols grâce aux champs métiers.&lt;br /&gt;
*Dans '''Admin &amp;gt; Structure &amp;gt; Variables &amp;gt; Champs métiers''' :&lt;br /&gt;
**Créer un nouveau champ métier de catégorie '''Entrée comptable'''&lt;br /&gt;
*Dans '''Admin &amp;gt; Ventes &amp;gt; Facturation &amp;gt; Activités''' :&lt;br /&gt;
**Modifier une règle de tarification ou en créer une nouvelle (s'il faut créer une règle de tarification spécifique pour obtenir l'information à insérer dans le champ additionnel) et renseigner le champ '''Champ additionnel à lier''' avec le nom du champ métier précédemment créé.&lt;br /&gt;
**'''Valider'''.&lt;br /&gt;
Ainsi, une nouvelle colonne du nom du champ métier créé sera systématiquement rajoutée dans la facture et contiendra la valeur issue de la règle de tarification qui lui est liée.&lt;br /&gt;
&lt;br /&gt;
==Ordonner les champs métiers==&lt;br /&gt;
&lt;br /&gt;
Pour ordonner les champs métiers il faut utiliser les flèches haut/bas dans la colonne '''Ordonner'''.&lt;br /&gt;
&lt;br /&gt;
A cause de [[Champs-métiers#Champs-spécifiques|champs cachés]], il se peut que vous ne voyez pas de changement lorsque vous cliquez sur une flèche car le changement s'est fait avec l'un de ces champs. Il faut donc recommencer l'opération.&lt;br /&gt;
&lt;br /&gt;
==Récupérer la valeur d'un champ métier dans les règles de tarification des activités==&lt;br /&gt;
Il est possible de récupérer la valeur d'un champ métier dans les règles de tarification des activités. Cela permet de modifier par exemple un tarif en fonction de la valeur indiquée dans le champ métier ou d'indiquer une quantité qui influe sur le prix.&lt;br /&gt;
&lt;br /&gt;
Pour cela il faut utiliser la variable [[Formules-de-calcul#.EXTRAFIELDxx|%EXTRAFIELDxx]].&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Airmate&amp;diff=12877</id>
		<title>Airmate</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Airmate&amp;diff=12877"/>
		<updated>2024-10-02T17:27:48Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de regrouper les informations concernant l'outil de préparation des vols [https://airmate.aero Airmate] couplé à OpenFlyers via les items de menu/boutons de préparation de vol. Voir :&lt;br /&gt;
*Pour l'interface légère : [[Planning-(interface-légère)#Préparer-un-vol|Planning (interface légère)]]&lt;br /&gt;
*Pour l'interface dynamique : [[Utilisation-du-planning-de-réservation#Préparer-un-vol|Utilisation du planning de réservation]]&lt;br /&gt;
&lt;br /&gt;
=Se connecter=&lt;br /&gt;
Lorsque l'utilisateur est redirigé sur Airmate sans être précédemment logué, une page de connexion s'affiche. Il faut renseigner l'identifiant Airmate qui a été créé la première fois :&lt;br /&gt;
[[File:Identification airmate.png]]&lt;br /&gt;
&lt;br /&gt;
=S'inscrire=&lt;br /&gt;
Après avoir cliquer, pour la première fois, sur l'un des liens '''Préparer un vol''' depuis OpenFlyers, l'utilisateur est redirigé sur le site d'airmate où s'affiche un formulaire lui permettant de s'inscrire à partir des informations pré-complétées communiquées par OpenFlyers, à savoir :&lt;br /&gt;
*l'adresse email de l'utilisateur enregistré dans OpenFlyers&lt;br /&gt;
*Le code OACI de la structure aéronautique de l'utilisateur&lt;br /&gt;
&lt;br /&gt;
L'utilisateur doit renseigner un identifiant, un mot de passe, accepter les conditions d'utilisation et valider le formulaire :&lt;br /&gt;
&lt;br /&gt;
[[File:Interface airmate creation de compte.png]]&lt;br /&gt;
&lt;br /&gt;
Il reçoit un email qui lui permet d'avoir un rappel de son identifiant Airmate.&lt;br /&gt;
&lt;br /&gt;
Ensuite, il doit [[#Se-connecter|se connecter]].&lt;br /&gt;
&lt;br /&gt;
=Synchronisation réservations OpenFlyers / préparation de vols Airmate=&lt;br /&gt;
Lorsque l'utilisateur clique sur l'item de menu '''Préparer un vol...''' depuis le menu contextuel qui apparait au survol d'une réservation, il est redirigé sur le site d'Airmate avec une transmission des éléments suivants de la réservation :&lt;br /&gt;
*Aérodrome de départ&lt;br /&gt;
*Aérodrome d'arrivée&lt;br /&gt;
*Date et heure de départ&lt;br /&gt;
&lt;br /&gt;
Ensuite, les éléments du vol sont mémorisés chez Airmate et l'utilisateur peut donc facilement les retrouver pour les compléter ou les modifier juste en survolant la réservation associée dans OpenFlyers et en cliquant sur l'item de menu '''Préparer un vol...'''.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=API-OpenFlyers&amp;diff=12876</id>
		<title>API OpenFlyers</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=API-OpenFlyers&amp;diff=12876"/>
		<updated>2024-10-02T17:27:47Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de décrire l'API OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
;Description de l'API&lt;br /&gt;
OpenFlyers possède une API basée sur [[Wikipedia-en:OAuth#OAuth_2.0|OAuth2]] qui permet à des serveurs extérieurs, dûment [[#Enregistrer-un-client|enregistrés]], de mettre en œuvre un processus d'[[Wikipedia-fr:Authentification_unique|authentification unique (SSO)]] et/ou de récupération des résultats des requêtes SQL de la [[Bibliothèque-des-rapports|bibliothèque des rapports]] ou des rapports personnalisés sous la forme de fichiers CSV.&lt;br /&gt;
&lt;br /&gt;
OAuth2 propose plusieurs mécanismes pour permettre l'authentification. Un mécanisme d'authentification détermine la séquence exacte des étapes impliquées dans le processus d'authentification d'OAuth2. OpenFlyers met à disposition deux mécanismes d'authentification :&lt;br /&gt;
*[[#Authorization Code|Authorization Code]] basé sur la méthode d'authentification par code d'autorisation et qui correspond au mécanisme associé à l'[[Wikipedia-fr:Authentification_unique|authentification unique (SSO)]],&lt;br /&gt;
*[[#Client Credentials|Client Credentials]] basé sur la méthode d'authentification avec les identifiants clients et qui est utilisé dans un contexte d'automatisme sans autorisation de l'utilisateur au préalable.&lt;br /&gt;
&lt;br /&gt;
Dans les chapitres qui suivent, le terme ''ressource'' fait référence à la définition OAuth2. Une ressource dans OAuth2 est un élément qui peut être :&lt;br /&gt;
*une ou des données comme des photos, des documents, des contacts ou des informations personnelles,&lt;br /&gt;
*un ou plusieurs services comme des transferts de fonds, la récupération de rapports ou l'ajout d'articles sur un blog,&lt;br /&gt;
*toute ressource nécessitant un accès restreint.&lt;br /&gt;
&lt;br /&gt;
OpenFlyers définit plusieurs [[#Utiliser-l'API|types de ressources]] :&lt;br /&gt;
*les [[#Récupérer-les-informations-de-l'utilisateur-connecté|informations de l'utilisateur connecté]],&lt;br /&gt;
*les [[#Récupérer les rapports génériques|rapports génériques]] ou [[#Récupérer les rapports personnalisés|personnalisés]] au format CSV.&lt;br /&gt;
&lt;br /&gt;
OAuth2 dispose de ''scopes''. Un scope est un privilège définit de manière explicite permettant l'accès à une ressource protégée. OpenFlyers met à disposition une [[#Liste des scopes disponibles|liste de scopes]] utilisables à travers l'API.&lt;br /&gt;
&lt;br /&gt;
Deux protocoles de sécurité sont présents dans l'API OpenFlyers :&lt;br /&gt;
*[[#Authentification-TLS-Mutuelle-(mTLS)|mTLS]] : il permet d'authentifier le client avec un certificat TLS, en plus d'authentifier le serveur avec un certificat. Ce protocole permet d'éviter les usurpations d'identité.&lt;br /&gt;
*[[#HTTP-Signature|HTTP-Signature]] : il permet de signer les en-têtes et le corps (lorsqu'il y en a un) des messages échangés afin d'en garantir leur intégrité.&lt;br /&gt;
&lt;br /&gt;
;Premiers pas - Client de démonstration&lt;br /&gt;
Un client de démonstration est disponible pour comprendre les mécanismes décrits ci-dessous.&lt;br /&gt;
&lt;br /&gt;
L'utilisation de ce client de démonstration est décrite dans la procédure [[#Utiliser-le-client|Utiliser le client]] de cette page.&lt;br /&gt;
&lt;br /&gt;
Le client de démonstration est lui-même accessible à cette adresse : https://openflyers.com/oauth2-demo/index.php&lt;br /&gt;
&lt;br /&gt;
Le code source du client de démonstration est mis à disposition par OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/oauth2-demo-src.zip&lt;br /&gt;
&lt;br /&gt;
L'utilisation du code source est décrite dans la procédure [[#Créer-un-client-à-partir-du-code-source|Créer un client à partir du code source]].&lt;br /&gt;
&lt;br /&gt;
=Définitions=&lt;br /&gt;
==Authentification TLS Mutuelle (mTLS)==&lt;br /&gt;
En général dans une communication TLS, seul le serveur a l'obligation de fournir un certificat. Il est également possible pour le client de fournir un certificat. Ce principe s'appelle l'authentification mutuelle et est mise en place avec Mutual TLS (ou [[Wikipedia-en:Mutual_authentication#mTLS|mTLS]]).&lt;br /&gt;
&lt;br /&gt;
OpenFlyers associe un certificat pour l'authentification mutuelle unique à chaque client OAuth2.&lt;br /&gt;
&lt;br /&gt;
;Envoyer un certificat client&lt;br /&gt;
Côté client, le code suivant peut être utilisé pour fournir à cURL le certificat et la clé correspondante ainsi que le certificat du CA d'OpenFlyers à utiliser pour la connexion :&lt;br /&gt;
&amp;lt;php&amp;gt;curl_setopt_array($request, [&lt;br /&gt;
    CURLOPT_SSLVERSION =&amp;gt; CURL_SSLVERSION_TLSv1_2,&lt;br /&gt;
    CURLOPT_CAINFO     =&amp;gt; $caCertificatePath,&lt;br /&gt;
    CURLOPT_SSLCERT    =&amp;gt; $certificatePath,&lt;br /&gt;
    CURLOPT_SSLKEY     =&amp;gt; $keyPath&lt;br /&gt;
]);&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''À noter''' : le certificat du CA d'OpenFlyers est nécessaire pour assurer la validité des certificats utilisés.&lt;br /&gt;
&lt;br /&gt;
==HTTP Signature==&lt;br /&gt;
HTTP Signature utilise le principe de la signature numérique pour garantir l'authenticité et l'intégrité du message HTTP.&lt;br /&gt;
&lt;br /&gt;
La signature est générée à l'aide d'une clé privée et vérifiée à l'aide de la clé publique correspondante ou d'un certificat contenant cette clé publique.&lt;br /&gt;
&lt;br /&gt;
HTTP Signature utilise deux en-têtes HTTP :&lt;br /&gt;
*Signature : contient la signature et ses métadonnées.&lt;br /&gt;
*Digest : contient le corps du message haché.&lt;br /&gt;
&lt;br /&gt;
===Digest===&lt;br /&gt;
Le ''digest'' est calculé comme ceci : &amp;lt;code&amp;gt;digest = base64encode(sha256(corps du message))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Et l'en-tête est structuré de la manière suivante : &amp;lt;code&amp;gt;Digest: SHA-256=&amp;lt;digest&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un autre algorithme de hachage peut être utilisé, SHA-256 reste cependant le plus répendu.&lt;br /&gt;
&lt;br /&gt;
;Exemple en php&lt;br /&gt;
&amp;lt;php&amp;gt;$digestHeader = 'Digest: SHA-256=' . base64_encode(hash('sha256', $postData, true));&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Signature===&lt;br /&gt;
L'en-tête HTTP de signature est structuré de la manière suivante : &amp;lt;code&amp;gt;Signature: keyId=&amp;quot;&amp;lt;keyId&amp;gt;&amp;quot;,algorithm=&amp;quot;&amp;lt;algo&amp;gt;&amp;quot;,headers=&amp;quot;&amp;lt;signed_headers&amp;gt;&amp;quot;,signature=&amp;quot;&amp;lt;signature&amp;gt;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le champ ''keyId'' correspond à un identifiant permettant l'identification de la clé utilisée pour vérifier la signature. Pour l'API d'OpenFlyers, sa valeur correspond à l'empreinte SHA-1 du certificat au format PEM à utiliser pour vérifier la signature.&lt;br /&gt;
&lt;br /&gt;
L'algorithme ''algo'' correspond à celui utilisé pour générer la signature, exemple : &amp;lt;code&amp;gt;rsa-sha256&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
La valeur de ''signed_headers'' correspond à la liste des en-têtes inclus dans la signature séparés d'un espace. Exemple : &amp;lt;code&amp;gt;date digest (request-target)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour générer la signature, une chaîne de caractères appelée &amp;lt;code&amp;gt;signing string&amp;lt;/code&amp;gt; contenant les en-têtes au format &amp;lt;code&amp;gt;lowercase_header_name: value&amp;lt;/code&amp;gt; séparés par une nouvelle ligne au format LF (&amp;lt;code&amp;gt;\n&amp;lt;/code&amp;gt;) est d'abord générée. Exemple avec les en-têtes &amp;quot;date&amp;quot; et &amp;quot;(request-target)&amp;quot; :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;(request-target): post /some/uri\ndate: Tue, 07 Jun 2014 20:51:35 GMT&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La signature est ensuite générée comme ceci : &amp;lt;code&amp;gt;base64encode(algo(signing string))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Exemple en php&lt;br /&gt;
&amp;lt;php&amp;gt;function generateSignatureHeader(array $headersToSign, string $certificateFingerprint, string $privateKey): string&lt;br /&gt;
{&lt;br /&gt;
    // generating the signing string and header list&lt;br /&gt;
    $headers         = '';&lt;br /&gt;
    $signatureString = '';&lt;br /&gt;
    foreach ($headersToSign as $key =&amp;gt; $value) {&lt;br /&gt;
        $normalizedHeaderKey = trim(strtolower($key));&lt;br /&gt;
        $headers             .= $normalizedHeaderKey . ' ';&lt;br /&gt;
        $signatureString     .= $normalizedHeaderKey . ': ' . trim($value) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // trim extra whitespace&lt;br /&gt;
    $headers         = trim($headers);&lt;br /&gt;
    $signatureString = trim($signatureString);&lt;br /&gt;
&lt;br /&gt;
    // signing the signing string&lt;br /&gt;
    $signature = '';&lt;br /&gt;
    openssl_sign($signatureString, $signature, $privateKey, 'RSA-SHA256');&lt;br /&gt;
    $signature = base64_encode($signature);&lt;br /&gt;
&lt;br /&gt;
    // compiling the header line&lt;br /&gt;
    return &amp;quot;Signature: keyId=\&amp;quot;$certificateFingerprint\&amp;quot;,algorithm=\&amp;quot;rsa-sha256\&amp;quot;,headers=\&amp;quot;$headers\&amp;quot;,signature=\&amp;quot;$signature\&amp;quot;&amp;quot;;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
Les variables ''$certificateFingerprint'' et ''$privateKey'' correspondent respectivement à une empreinte SHA-1 de certificat et à une clé privée, tous deux au format PEM. &lt;br /&gt;
&lt;br /&gt;
La variable ''$headersToSign'' est un tableau formaté de la manière suivante : &lt;br /&gt;
&amp;lt;php&amp;gt;[&lt;br /&gt;
    $headerName =&amp;gt; $headerValue,&lt;br /&gt;
    ...&lt;br /&gt;
]&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''À noter''' : les en-têtes sont à signer côté client avec le certificat de signature signé par le CA d'OpenFlyers et dédié au client ainsi que la clé privée associée. Le certificat de signature dédié au client est téléchargeable depuis l'interface de gestion des clients OAuth2. Les en-têtes de la réponse du serveur quant à elles doivent être vérifiées avec le certificat de signature HTTP du serveur, téléchargeable aussi depuis l'interface de configuration des clients OAuth2.&lt;br /&gt;
&lt;br /&gt;
=Client OAuth2=&lt;br /&gt;
Une fois le client OAuth2 configuré sur OpenFlyers, il faut l'utiliser avec un client créé au préalable pour communiquer avec le serveur d'autorisation et l'API.&lt;br /&gt;
&lt;br /&gt;
Plusieurs [https://oauth.net/code/ bibliothèques] simplifiant la création d'un client sont disponibles.&lt;br /&gt;
&lt;br /&gt;
Des scripts client basiques écrits en php sont aussi fournis pour les mécanismes [[#Script-client-:-authorization-code|''authorization_code'']] et [[#Script-client-:-client-credentials|''client_credentials'']]&lt;br /&gt;
&lt;br /&gt;
==Authorization Code==&lt;br /&gt;
Ce flux OAuth2 se déroule en plusieurs étapes :&lt;br /&gt;
*Le client redirige le navigateur de l'utilisateur vers l'URL d'autorisation.&lt;br /&gt;
*Le navigateur de l'utilisateur est redirigé vers l'URL fourni durant la demande ou durant l'enregistrement du client.&lt;br /&gt;
*Le client récupère un code d'autorisation grâce à la redirection précédente, et échange ce code contre un jeton d'accès auprès du serveur d'autorisation.&lt;br /&gt;
*Le client peut utiliser ce code d'accès :&lt;br /&gt;
**Comme preuve d'authentification pour une solution SSO (Single Sign-On).&lt;br /&gt;
**Pour accéder à des données sur le serveur distant en utilisant l'API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    +-----------+                   +------+                +-----------+                  +-------------+                  +-----------+&lt;br /&gt;
    |Utilisateur|                   |Client|                |Navigateur |                  |   Serveur   |                  |  Serveur  |&lt;br /&gt;
    +-----+-----+                   +--+---+                +-----+-----+                  |Autorisation |                  | Ressources|&lt;br /&gt;
          |                            |                          |                        +------+------+                  +-----+-----+&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                   Demande|d'autorisation                 |                               |&lt;br /&gt;
          |                            +-------------------------&amp;gt;+------------------------------&amp;gt;|                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |Authentification + Formulaire d'autorisation              |                               |&lt;br /&gt;
          |&amp;lt;---------------------------+--------------------------+&amp;lt;------------------------------+                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |      Autorisation        |                               |                               |&lt;br /&gt;
          +----------------------------+-------------------------&amp;gt;+------------------------------&amp;gt;|                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                      Code|d'autorisation                 |                               |&lt;br /&gt;
          |                            |&amp;lt;-------------------------+&amp;lt;------------------------------+                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                Demande de|token                          |                               |&lt;br /&gt;
          |                            +--------------------------+------------------------------&amp;gt;|                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                 Access (+|Refresh) token                 |                               |&lt;br /&gt;
          |                            |&amp;lt;-------------------------+-------------------------------+                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |       Requête vers API        |                               |&lt;br /&gt;
          |                            +--------------------------+-------------------------------+------------------------------&amp;gt;|&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |                               |&amp;lt;------------------------------+&lt;br /&gt;
          |                            |                          |                               |  Vérification d'autorisation  |&lt;br /&gt;
          |                            |                          |                               +------------------------------&amp;gt;|&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
          |                            |                          |      Données/Réponse          |                               |&lt;br /&gt;
          |                            |&amp;lt;-------------------------+-------------------------------+-------------------------------+&lt;br /&gt;
          |                            |                          |                               |                               |&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Générer les codes pour PKCE===&lt;br /&gt;
Pour faire fonctionner le client OAuth2, il faut générer deux codes pour l'extension PKCE :&lt;br /&gt;
*Un ''code_verifier'' échangé pendant la demande de jeton d'accès.&lt;br /&gt;
*Un ''code_challenge'' dérivé du ''code_verifier'' et échangé pendant la demande d'autorisation.&lt;br /&gt;
&lt;br /&gt;
;Générer le ''code_verifier''&lt;br /&gt;
&amp;lt;php&amp;gt;function generateCodeVerifier($length = 128): string&lt;br /&gt;
{&lt;br /&gt;
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~';&lt;br /&gt;
    $outputCode = '';&lt;br /&gt;
&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $length; $i++) {&lt;br /&gt;
        $index      = random_int(0, strlen($characters) - 1);&lt;br /&gt;
        $outputCode .= $characters[$index];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $outputCode;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cette fonction permet de générer un ''code_verifier'' avec une longueur donnée. Le ''code_verifier'' doit avoir une longueur entre 43 et 128 caractères.&lt;br /&gt;
&lt;br /&gt;
;Générer le ''code_challenge''&lt;br /&gt;
&amp;lt;php&amp;gt;function computeCodeChallenge(string $codeVerifier): string&lt;br /&gt;
{&lt;br /&gt;
    return strtr(rtrim(base64_encode(hash('sha256', $codeVerifier, true)), '='), '+/', '-_');&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Cette fonction génère le ''code_challenge'' à partir du ''code_verifier'' fourni.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Demande d'autorisation===&lt;br /&gt;
Pour initier la demande d'autorisation, rediriger le navigateur de l'utilisateur vers l'URL : &amp;lt;code&amp;gt;GET https://openflyers.com/nom-de-plateforme/oauth/authorize.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Envoyer également les paramètres suivants :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|response_type||string||Le type de réponse envoyée par le serveur. Doit utiliser la valeur &amp;quot;code&amp;quot; (sans guillements) pour ce mécanisme.&lt;br /&gt;
|-&lt;br /&gt;
|redirect_uri||string||L'URI (ou l'URL) fourni pendant l'enregistrement du client et vers lequel l'utilisateur est redirigé après la demande d'autorisation.&lt;br /&gt;
|-&lt;br /&gt;
|scope||string||[[#Liste-des-scopes-disponibles|Liste des droits demandés par le client]], séparés par des espaces.&lt;br /&gt;
|-&lt;br /&gt;
|state||string||Chaîne de caractère aléatoire utilisée pour éviter les [https://fr.wikipedia.org/wiki/Cross-site_request_forgery attaques CSRF]. '''Fortement recommandé'''.&lt;br /&gt;
|-&lt;br /&gt;
|code_challenge||string||Code nécessaire pour le fonctionnement de l'extension [[#Générer-les-codes-pour-PKCE|PKCE]].&lt;br /&gt;
|-&lt;br /&gt;
|code_challenge_method||string||Méthode utilisée pour générer le ''code_challenge''. Ici, la valeur est &amp;quot;S256&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Demande de jeton d'accès===&lt;br /&gt;
Après avoir répondu à la demande, l'utilisateur est redirigé vers l'URI fourni pendant l'enregistrement du client. Si la demande est acceptée, un code temporaire : ''code'' est fourni, ainsi que le paramètre ''state'' fourni pendant la demande avec la même valeur. Si la demande est refusée, un code d'erreur est renvoyé.&lt;br /&gt;
;Si le paramètre ''state'' a une valeur différente de celle envoyée avec la demande, c'est peut-être une tentative d'attaque et il faut refuser la réponse.&lt;br /&gt;
&lt;br /&gt;
Echanger ce ''code'' contre un jeton d'accès via l'URL : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Les paramètres suivants sont également nécessaires :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|client_secret||string||La passphrase reçue pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|code||string||Le code temporaire reçu dans la réponse à la demande d'autorisation.&lt;br /&gt;
|-&lt;br /&gt;
|grant_type||string||Le mécanisme d'autorisation utilisé. Ici, sa valeur doit être ''authorization_code''&lt;br /&gt;
|-&lt;br /&gt;
|redirect_uri||string||L'URI (ou l'URL) de redirection fourni pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|code_verifier||string||Le ''code_verifier'' utilisé pour générer le ''code_challenge'' de la demande d'autorisation.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Si la requête est correcte, un jeton d'accès (Access Token) ainsi qu'un jeton de rafraîchissement (Refresh Token) sont fournis en réponse dans un objet au format JSON.&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,&lt;br /&gt;
  &amp;quot;expires_in&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;access_token&amp;quot;: &amp;quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw&amp;quot;,&lt;br /&gt;
  &amp;quot;refresh_token&amp;quot;: &amp;quot;a59ef39fa9bab9b95cd554f921e7f3080a34c90f23d2b8031d692b5ff2d0993dcc392d9c7f9a43242337ef144c1a5fe1d0174413ade973e1b628ac0bbfc39b23973534&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Script client : Authorization Code===&lt;br /&gt;
Voici un exemple simple de client OAuth2 pour le mécanisme d'authentification par code d'autorisation (Authorization Code).&lt;br /&gt;
&lt;br /&gt;
Fichier de configuration ''config.authcode.json'' :&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;authorize_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/authorize.php&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;/path/to/client/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;/path/to/client/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;/path/to/client/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;/path/to/client/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;/path/to/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;/path/to/server/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
Où &amp;lt;code&amp;gt;/path/to/client/&amp;lt;/code&amp;gt; est le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
*Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/ssl/AuthCodeDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
*Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./ssl/AuthCodeDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ce fichier de configuration doit se situer au même niveau que le script PHP dans le système de fichiers.&lt;br /&gt;
&lt;br /&gt;
Script PHP :&lt;br /&gt;
&amp;lt;php&amp;gt;&amp;lt;?php&lt;br /&gt;
$localTokenFile    = 'token.json';&lt;br /&gt;
// create token file if it does not exist&lt;br /&gt;
if (!file_exists($localTokenFile))&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
$config                 = json_decode(file_get_contents('config.authcode.json'), true);&lt;br /&gt;
$localToken             = json_decode(file_get_contents($localTokenFile), true);&lt;br /&gt;
$GLOBALS['config']      = $config;&lt;br /&gt;
&lt;br /&gt;
// Build the baseURL, accounting for protocol, port, name and endpoint. Used for redirection&lt;br /&gt;
$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';&lt;br /&gt;
$port     = ($protocol == 'https://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 443)&lt;br /&gt;
    || ($protocol == 'http://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 80) ? '' : ':' . $_SERVER['SERVER_PORT'];&lt;br /&gt;
&lt;br /&gt;
$baseURL            = $protocol . $_SERVER['SERVER_NAME'] . $port . $_SERVER['PHP_SELF'];&lt;br /&gt;
$errorLog           = 'error_log.log';&lt;br /&gt;
$responseLog        = 'response_log.log';&lt;br /&gt;
$GLOBALS['baseURL'] = $baseURL;&lt;br /&gt;
&lt;br /&gt;
//Session cookies are used to store information necessary for the authorization code flow&lt;br /&gt;
session_start();&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function is used to make api calls to the Authorization Server and the Resource Server&lt;br /&gt;
 *&lt;br /&gt;
 * @param       $url&lt;br /&gt;
 * @param       $post&lt;br /&gt;
 * @param array $headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return mixed&lt;br /&gt;
 */&lt;br /&gt;
function apiRequest($url, $post = null, $token = false, $auth = true, $refresh = false, $headers = array())&lt;br /&gt;
{&lt;br /&gt;
    $ch = curl_init($url);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HEADER, true);&lt;br /&gt;
&lt;br /&gt;
    $method = 'get';&lt;br /&gt;
&lt;br /&gt;
    if ($post) {&lt;br /&gt;
        $method   = 'post';&lt;br /&gt;
        $postData = http_build_query($post);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POST, true);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);&lt;br /&gt;
&lt;br /&gt;
        $headersToSign['Content-Type'] = 'application/x-www-form-urlencoded';&lt;br /&gt;
        $headersToSign['digest']       = 'SHA-256=' . base64_encode(hash('sha256', $postData, true));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $urlComponents = parse_url($url);&lt;br /&gt;
&lt;br /&gt;
    $headersToSign['(request-target)'] = $method . ' ' . $urlComponents['path'];&lt;br /&gt;
    $headersToSign['Host']             = $urlComponents['host'];&lt;br /&gt;
    $headersToSign['Date']             = gmdate('D, j M Y H:i:s T');&lt;br /&gt;
&lt;br /&gt;
    // generating the signature header&lt;br /&gt;
    $keyId                = openssl_x509_fingerprint(file_get_contents($GLOBALS['config']['sign_cert']));&lt;br /&gt;
    $privateKey           = file_get_contents($GLOBALS['config']['sign_key']);&lt;br /&gt;
    $headers['Signature'] = generateSignatureHeader($headersToSign, $keyId, $privateKey);&lt;br /&gt;
&lt;br /&gt;
    $headers['Accept']     = 'application/json';&lt;br /&gt;
    $headers['User-Agent'] = $GLOBALS['baseURL'];&lt;br /&gt;
    unset($headersToSign['(request-target)']);&lt;br /&gt;
    $headers               += $headersToSign;&lt;br /&gt;
&lt;br /&gt;
    if ($token) {&lt;br /&gt;
        $headers['Authorization'] = $token['token_type'] . ' ' . $token['access_token'];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // formatting the headers&lt;br /&gt;
    $httpFormattedHeaders = [];&lt;br /&gt;
    foreach ($headers as $key =&amp;gt; $value) {&lt;br /&gt;
        $httpFormattedHeaders[] = trim($key) . ': ' . trim($value);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HTTPHEADER, $httpFormattedHeaders);&lt;br /&gt;
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);&lt;br /&gt;
&lt;br /&gt;
    // for development environment only&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_VERBOSE, true);&lt;br /&gt;
&lt;br /&gt;
    // defining TLS client certificates for Mutual TLS&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_CAINFO, $GLOBALS['config']['auth_cacert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLCERT, $GLOBALS['config']['auth_cert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLKEY, $GLOBALS['config']['auth_key']);&lt;br /&gt;
&lt;br /&gt;
    $response = curl_exec($ch);&lt;br /&gt;
&lt;br /&gt;
    // logging errors and responses&lt;br /&gt;
    errorLog(true, $response, $ch);&lt;br /&gt;
&lt;br /&gt;
    curl_close($ch);&lt;br /&gt;
&lt;br /&gt;
    // in case an authentication request is executed&lt;br /&gt;
    if ($auth) {&lt;br /&gt;
        // required when a refresh token request is issued&lt;br /&gt;
        // because there is only one header in the response&lt;br /&gt;
        // while there are two for regular auth requests&lt;br /&gt;
        if (!$refresh) {&lt;br /&gt;
            list($firstResponseHeaders, $secondResponseHeaders, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 3);&lt;br /&gt;
            if (!$responseBody) {&lt;br /&gt;
                list($secondResponseHeaders, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 2);&lt;br /&gt;
            }&lt;br /&gt;
        } else {&lt;br /&gt;
            list($secondResponseHeaders, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 2);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $responseHeadersDigest = '';&lt;br /&gt;
        $responseHeadersSignature = '';&lt;br /&gt;
        // extracting digest and signature from headers&lt;br /&gt;
        $responseHeadersArray = explode(&amp;quot;\r\n&amp;quot;, $secondResponseHeaders);&lt;br /&gt;
        $responseProtocol = array_shift($responseHeadersArray);&lt;br /&gt;
&lt;br /&gt;
        foreach ($responseHeadersArray as $value) {&lt;br /&gt;
            list($responseHeadersKeys, $responseHeadersValue) = explode(&amp;quot;: &amp;quot;, $value, 2);&lt;br /&gt;
            $responseHeaders[strtolower($responseHeadersKeys)] = $responseHeadersValue;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $responseDigestAlgo = '';&lt;br /&gt;
        $responseDigestKey = '';&lt;br /&gt;
        foreach ($responseHeaders as $key =&amp;gt; $value) {&lt;br /&gt;
            if ($key === &amp;quot;digest&amp;quot;) {&lt;br /&gt;
                $responseHeadersDigest = $value;&lt;br /&gt;
                // stripping SHA algorithm for later comparison&lt;br /&gt;
                list($responseDigestAlgo, $responseDigestKey) = explode(&amp;quot;=&amp;quot;, $responseHeadersDigest, 2);&lt;br /&gt;
            } else if ($key === &amp;quot;signature&amp;quot;)&lt;br /&gt;
                $responseHeadersSignature = $value;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // calculating response digest&lt;br /&gt;
        $responseDigest = base64_encode(hash(strtolower(str_replace(&amp;quot;-&amp;quot;, &amp;quot;&amp;quot;, $responseDigestAlgo)), $responseBody, true));&lt;br /&gt;
&lt;br /&gt;
        // checking digest validity&lt;br /&gt;
        if ($responseDigest !== $responseDigestKey) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Digests are not the same&amp;quot;);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // extracting variables from signature header&lt;br /&gt;
        $signatureArray = explode(&amp;quot;,&amp;quot;, $responseHeadersSignature);&lt;br /&gt;
        foreach ($signatureArray as $value) {&lt;br /&gt;
            list($signatureKey, $signatureValue) = explode(&amp;quot;=&amp;quot;, $value, 2);&lt;br /&gt;
            $signature[$signatureKey] = trim($signatureValue, '&amp;quot;');&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generating siging string&lt;br /&gt;
        $signingStringArray = explode(&amp;quot; &amp;quot;, $signature['headers']);&lt;br /&gt;
        $signingString = '';&lt;br /&gt;
        foreach ($signingStringArray as $value) {&lt;br /&gt;
            $signingString = $signingString . trim($value) . &amp;quot;: &amp;quot; . trim($responseHeaders[$value]) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // trimming last '\n' character&lt;br /&gt;
        $signingString = trim($signingString);&lt;br /&gt;
&lt;br /&gt;
        // decoding signature&lt;br /&gt;
        $decodedSignature = base64_decode($signature['signature']);&lt;br /&gt;
&lt;br /&gt;
        // verifying signature&lt;br /&gt;
        $signatureVerify = openssl_verify($signingString, $decodedSignature, openssl_get_publickey(file_get_contents($GLOBALS['config']['sign_cert_server'])), 'RSA-SHA256');&lt;br /&gt;
&lt;br /&gt;
        if (!$signatureVerify) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Signature is not correct&amp;quot;);&lt;br /&gt;
            while (($err = openssl_error_string()))&lt;br /&gt;
                errorLog(false, false, $err);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return json_decode($responseBody, true);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $response;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function logs curl responses and errors in text files&lt;br /&gt;
 *&lt;br /&gt;
 * @param mixed $response the response&lt;br /&gt;
 * @param mixed $request  the request handle, used to get errors&lt;br /&gt;
 */&lt;br /&gt;
function errorLog($curl, $response, $request = false)&lt;br /&gt;
{&lt;br /&gt;
    $timestamp = '[' . date('Y-m-d H:i:s') . ']:';&lt;br /&gt;
    global $errorLog;&lt;br /&gt;
    global $responseLog;&lt;br /&gt;
&lt;br /&gt;
    if ($response === false) {&lt;br /&gt;
        if ($curl)&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . curl_error($request) . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
        else&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . $request . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    } else {&lt;br /&gt;
        file_put_contents($responseLog, $timestamp . &amp;quot;\n&amp;quot; . $response . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function generates the full signature header line from a set of headers, a certificate and the linked private key&lt;br /&gt;
 *&lt;br /&gt;
 * @param array  $headersToSign the headers to sign, in the $key =&amp;gt; $value format&lt;br /&gt;
 * @param string $certificate   the certificate linked to the used private key&lt;br /&gt;
 * @param string $privateKey    the private key used to sign the headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the full signature header line&lt;br /&gt;
 */&lt;br /&gt;
function generateSignatureHeader(array $headersToSign, string $certificate, string $privateKey): string&lt;br /&gt;
{&lt;br /&gt;
    // generating the signing string and header list&lt;br /&gt;
    $headers         = '';&lt;br /&gt;
    $signatureString = '';&lt;br /&gt;
    foreach ($headersToSign as $key =&amp;gt; $value) {&lt;br /&gt;
        $normalizedHeaderKey = trim(strtolower($key));&lt;br /&gt;
        $headers             .= $normalizedHeaderKey . ' ';&lt;br /&gt;
        $signatureString     .= $normalizedHeaderKey . ': ' . trim($value) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    $headers         = trim($headers);&lt;br /&gt;
    $signatureString = trim($signatureString);&lt;br /&gt;
&lt;br /&gt;
    // signing the signing string&lt;br /&gt;
    $signature = '';&lt;br /&gt;
    openssl_sign($signatureString, $signature, openssl_get_privatekey($privateKey), 'RSA-SHA256');&lt;br /&gt;
    $signature = base64_encode($signature);&lt;br /&gt;
&lt;br /&gt;
    // compiling the header line&lt;br /&gt;
    return &amp;quot;keyId=\&amp;quot;$certificate\&amp;quot;,algorithm=\&amp;quot;rsa-sha256\&amp;quot;,headers=\&amp;quot;$headers\&amp;quot;,signature=\&amp;quot;$signature\&amp;quot;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function takes a code_verifier and outputs the corresponding code_challenge&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $codeVerifier the generated code_verifier&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the computed code_challenge&lt;br /&gt;
 */&lt;br /&gt;
function computeCodeChallenge(string $codeVerifier): string&lt;br /&gt;
{&lt;br /&gt;
    return strtr(rtrim(base64_encode(hash('sha256', $codeVerifier, true)), '='), '+/', '-_');&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function takes an optional string length and outputs a random code_verifier string&lt;br /&gt;
 *&lt;br /&gt;
 * @param int $length the length of the output code_verifier. Default = 128&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the code_verifier&lt;br /&gt;
 * @throws Exception&lt;br /&gt;
 */&lt;br /&gt;
function generateCodeVerifier($length = 128): string&lt;br /&gt;
{&lt;br /&gt;
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~';&lt;br /&gt;
    $outputCode = '';&lt;br /&gt;
&lt;br /&gt;
    for ($i = 0; $i &amp;lt; $length; $i++) {&lt;br /&gt;
        $index      = random_int(0, strlen($characters) - 1);&lt;br /&gt;
        $outputCode .= $characters[$index];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $outputCode;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function calculates the entropy of a given string&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $string  the string for which to calculate the entropy&lt;br /&gt;
 * @param string $charset a string with all the usable characters. Default = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~&lt;br /&gt;
 *&lt;br /&gt;
 * @return float|int&lt;br /&gt;
 */&lt;br /&gt;
function computeEntropy(string $string, string $charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-._~')&lt;br /&gt;
{&lt;br /&gt;
    $chars = str_split($charset);&lt;br /&gt;
    $probs = [];&lt;br /&gt;
&lt;br /&gt;
    foreach ($chars as $char) {&lt;br /&gt;
        $probs[$char] = floatval(substr_count($string, $char)) / strlen($string);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $sum = 0.0;&lt;br /&gt;
    foreach ($probs as $prob) {&lt;br /&gt;
        $sum += $prob != 0 ? $prob * log($prob, 2) : 0.0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return -$sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function calculates the ideal (maximum) entropy for a string of a given length&lt;br /&gt;
 *&lt;br /&gt;
 * @param int $length length of the string. Default = 128&lt;br /&gt;
 *&lt;br /&gt;
 * @return float|int&lt;br /&gt;
 */&lt;br /&gt;
function idealEntropy(int $length = 128)&lt;br /&gt;
{&lt;br /&gt;
    $prob = 1.0 / $length;&lt;br /&gt;
&lt;br /&gt;
    return -1.0 * $length * $prob * log($prob, 2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function is used to initiate the authentication code flow.&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $clientID     the client's ID&lt;br /&gt;
 * @param string $redirectURL  the URL where to redirect after auth&lt;br /&gt;
 * @param string $authorizeURL the target URL to request authorization&lt;br /&gt;
 *&lt;br /&gt;
 * @throws Exception&lt;br /&gt;
 */&lt;br /&gt;
function login(string $clientID, string $redirectURL, string $authorizeURL): void&lt;br /&gt;
{&lt;br /&gt;
    global $localTokenFile;&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
    // This unguessable string is used to prevent csrf attacks&lt;br /&gt;
    $_SESSION['state'] = bin2hex(random_bytes(16));&lt;br /&gt;
&lt;br /&gt;
    // Generate code_verifier and code_challenge for PKCE    &lt;br /&gt;
    $_SESSION['code_verifier']  = generateCodeVerifier();&lt;br /&gt;
    $_SESSION['code_challenge'] = computeCodeChallenge($_SESSION['code_verifier']);&lt;br /&gt;
&lt;br /&gt;
    // required parameters for the redirection, redirect_uri is where the browser should be redirected&lt;br /&gt;
    // when the user grants (or denies) access, scope are the authorizations (rights) requested&lt;br /&gt;
    $params = [&lt;br /&gt;
        'response_type'         =&amp;gt; 'code',&lt;br /&gt;
        'client_id'             =&amp;gt; $clientID,&lt;br /&gt;
        'redirect_uri'          =&amp;gt; $redirectURL,&lt;br /&gt;
        'scope'                 =&amp;gt; 'default.login',&lt;br /&gt;
        'state'                 =&amp;gt; $_SESSION['state'],&lt;br /&gt;
        'code_challenge'        =&amp;gt; $_SESSION['code_challenge'],&lt;br /&gt;
        'code_challenge_method' =&amp;gt; 'S256'&lt;br /&gt;
    ];&lt;br /&gt;
&lt;br /&gt;
    // redirecting the browser to the AS authorization endpoint to obtain the authorization code&lt;br /&gt;
    header('Location: ' . $authorizeURL . '?' . http_build_query($params));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function deletes the access token from the session&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $baseURL&lt;br /&gt;
 */&lt;br /&gt;
function logout(string $baseURL): void&lt;br /&gt;
{&lt;br /&gt;
    global $localTokenFile;&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
    header('Location: ' . $baseURL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedIn(): void&lt;br /&gt;
{&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Logged In&amp;lt;/h3&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;view_repos&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;view&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'view_repos\').submit(); return false;&amp;quot;&amp;gt;View Repos&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;logout&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;logout&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'logout\').submit(); return false;&amp;quot;&amp;gt;Log Out&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedOut(): void&lt;br /&gt;
{&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Not logged in&amp;lt;/h3&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;login&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;login&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'login\').submit(); return false;&amp;quot;&amp;gt;Log In&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// display client &amp;quot;home&amp;quot; page&lt;br /&gt;
if (!isset($_POST['action'])) {&lt;br /&gt;
    if (!empty($localToken['access_token'])) {&lt;br /&gt;
        displayMenuLoggedIn();&lt;br /&gt;
    } else {&lt;br /&gt;
        displayMenuLoggedOut();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if (isset($_POST['action'])) {&lt;br /&gt;
    // Building query array for resource dumping&lt;br /&gt;
    $repoQueryParameters = [&lt;br /&gt;
        'resource_type' =&amp;gt; 'user_information',&lt;br /&gt;
        'client_id' =&amp;gt; $config['client_id']&lt;br /&gt;
    ];&lt;br /&gt;
    switch ($_POST['action']) {&lt;br /&gt;
        case 'login':&lt;br /&gt;
            login($config['client_id'], $baseURL, $config['authorize_uri']);&lt;br /&gt;
            break;&lt;br /&gt;
        case 'logout':&lt;br /&gt;
            logout($baseURL);&lt;br /&gt;
            break;&lt;br /&gt;
        case 'view':&lt;br /&gt;
            // call to the resource server to retreive user information&lt;br /&gt;
            $resources = apiRequest(&lt;br /&gt;
                $config['resource_uri'],&lt;br /&gt;
                $repoQueryParameters,&lt;br /&gt;
                $localToken,&lt;br /&gt;
                false&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            // Separating headers from body&lt;br /&gt;
            list($resourceHeader, $resourceBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $resources, 2);&lt;br /&gt;
&lt;br /&gt;
            $resourceHeaders = explode(&amp;quot;\r\n&amp;quot;, $resourceHeader);&lt;br /&gt;
            $firstHeaderLine = array_shift($resourceHeaders);&lt;br /&gt;
&lt;br /&gt;
            // Displaying user information&lt;br /&gt;
            echo '&amp;lt;pre&amp;gt;';&lt;br /&gt;
            echo $resourceBody;&lt;br /&gt;
            echo '&amp;lt;/pre&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
            // Automatic refreshing token once access token is expired&lt;br /&gt;
            if (strpos($firstHeaderLine, &amp;quot;401&amp;quot;)) {&lt;br /&gt;
                $errorBody = json_decode($resourceBody, true);&lt;br /&gt;
                if ($errorBody['error'] == 'access_denied' &amp;amp;&amp;amp; isset($errorBody['hint'])) {&lt;br /&gt;
                    if ($errorBody['hint'] == 'Access token could not be verified') {&lt;br /&gt;
                        $token = apiRequest(&lt;br /&gt;
                            $config['token_uri'],&lt;br /&gt;
                            [&lt;br /&gt;
                                'grant_type'    =&amp;gt; 'refresh_token',&lt;br /&gt;
                                'refresh_token' =&amp;gt; $localToken['refresh_token'],&lt;br /&gt;
                                'client_id'     =&amp;gt; $config['client_id'],&lt;br /&gt;
                                'client_secret' =&amp;gt; empty($config['client_secret']) ? null : $config['client_secret']&lt;br /&gt;
                            ],&lt;br /&gt;
                            false,&lt;br /&gt;
                            true,&lt;br /&gt;
                            true&lt;br /&gt;
                        );&lt;br /&gt;
&lt;br /&gt;
                        // We store the access token in the session so the user is &amp;quot;connected&amp;quot;&lt;br /&gt;
                        // Only if the request has been successfully executed&lt;br /&gt;
                        if (isset($token['access_token'])) {&lt;br /&gt;
                            file_put_contents($localTokenFile, json_encode($token, true));&lt;br /&gt;
&lt;br /&gt;
                            // Redirecting the user's browser to the &amp;quot;home&amp;quot; page&lt;br /&gt;
                            header('Location: ' . $baseURL);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Once the browser has been redirected to the AS to ask for the user's authorization, assuming it has been granted,&lt;br /&gt;
// the browser will get back here with a &amp;quot;code&amp;quot; parameter in the query string&lt;br /&gt;
if (isset($_GET['code'])) {&lt;br /&gt;
    // The AS MUST redirect the browser here with the exact same state parameter we sent it before, so we check if it is indeed the same&lt;br /&gt;
    // to detect if the oauth flow has been tampered with&lt;br /&gt;
    if (!isset($_GET['state']) || $_SESSION['state'] != $_GET['state']) {&lt;br /&gt;
        header('Location: ' . $baseURL . '?error=invalid_state');&lt;br /&gt;
        die();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // We communicate directly with the AS to exchange the code received against an access token.&lt;br /&gt;
    // The id/secret pair is send to authenticate the client, the redirect_uri is sent to verify the code's validity&lt;br /&gt;
    $token = apiRequest(&lt;br /&gt;
        $config['token_uri'],&lt;br /&gt;
        [&lt;br /&gt;
            'grant_type'    =&amp;gt; 'authorization_code',&lt;br /&gt;
            'client_id'     =&amp;gt; $config['client_id'],&lt;br /&gt;
            'client_secret' =&amp;gt; empty($config['client_secret']) ? null : $config['client_secret'],&lt;br /&gt;
            'redirect_uri'  =&amp;gt; $baseURL,&lt;br /&gt;
            'code'          =&amp;gt; $_GET['code'],&lt;br /&gt;
            'code_verifier' =&amp;gt; $_SESSION['code_verifier']&lt;br /&gt;
        ]&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
    // We store the access token in the session so the user is &amp;quot;connected&amp;quot;&lt;br /&gt;
    // Only if the request has been successfully executed&lt;br /&gt;
    if (isset($token['access_token'])) {&lt;br /&gt;
        file_put_contents($localTokenFile, json_encode($token, true));&lt;br /&gt;
&lt;br /&gt;
        // Redirecting the user's browser to the &amp;quot;home&amp;quot; page&lt;br /&gt;
        header('Location: ' . $baseURL);&lt;br /&gt;
    } else {&lt;br /&gt;
        echo $token;&lt;br /&gt;
    }&lt;br /&gt;
    die();&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Ce script a été conçu pour montrer le fonctionnement du mécanisme afin de tester l'implémentation d'un serveur et n'a pas été testé extensivement. Il est conseillé d'utiliser une solution adaptée à un environnement de production.&lt;br /&gt;
&lt;br /&gt;
==Client Credentials==&lt;br /&gt;
Ce mécanisme d'autorisation est adapté pour l'automatisation. Il fonctionne de la manière suivante :&lt;br /&gt;
*Le client effectue la demande de jeton d'accès au serveur d'autorisation en fournissant ses identifiants.&lt;br /&gt;
*Le serveur authentifie le client avec les identifiants fournis et renvoie un jeton d'accès.&lt;br /&gt;
*Le client utilise ce jeton d'accès pour accéder à des données via l'API.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    +------+                       +-------------+                  +-----------+&lt;br /&gt;
    |Client|                       |   Serveur   |                  |  Serveur  |&lt;br /&gt;
    +--+---+                       |Autorisation |                  | Ressources|&lt;br /&gt;
       |                           +------+------+                  +-----+-----+&lt;br /&gt;
       |        Authentification          |                               |&lt;br /&gt;
       |         + Demande token          |                               |&lt;br /&gt;
       +---------------------------------&amp;gt;|                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |          Access token            |                               |&lt;br /&gt;
       |&amp;lt;---------------------------------+                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                      Requête vers|API                            |&lt;br /&gt;
       +----------------------------------+------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |&amp;lt;------------------------------+&lt;br /&gt;
       |                                  |  Vérification d'autorisation  |&lt;br /&gt;
       |                                  +------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                         Données /|Réponse                        |&lt;br /&gt;
       |&amp;lt;---------------------------------+-------------------------------+&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Demande de jeton d'accès===&lt;br /&gt;
Pour obtenir un jeton d'accès, il faut effectuer la requête suivante : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Les paramètres suivants sont nécessaires :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|client_secret||string||La passphrase reçue pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|grant_type||string||Le mécanisme d'autorisation utilisé. Ici, la valeur doit être ''client_credentials''.&lt;br /&gt;
|-&lt;br /&gt;
|scope||string||[[#Liste-des-scopes-disponibles|Liste des droits demandés par le client]], séparé par des espaces.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
;Ce mécanisme a la particularité de ne pas nécessiter d'URI de redirection, il n'est donc pas utile d'en renseigner un lors de l'enregistrement d'un client.&lt;br /&gt;
&lt;br /&gt;
Si la requête est correcte, un jeton d'accès (Access Token) est fourni en réponse dans un objet au format JSON.&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,&lt;br /&gt;
  &amp;quot;expires_in&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;access_token&amp;quot;: &amp;quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Script client : Client Credentials===&lt;br /&gt;
Voici un exemple simple d'un client OAuth2 pour le mécanisme d'authentification par les identifiants client (Client Credentials).&lt;br /&gt;
&lt;br /&gt;
Fichier de configuration ''config.clientcred.json'' :&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/nom-de-plateforme/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;/path/to/client/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;/path/to/client/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;/path/to/client/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;/path/to/client/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;/path/to/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;/path/to/server/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
Où &amp;lt;code&amp;gt;/path/to/client/&amp;lt;/code&amp;gt; est le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
*Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/ssl/ClientCredDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
*Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./ssl/ClientCredDemo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ce fichier de configuration doit se situer au même niveau que le script PHP dans le système de fichiers.&lt;br /&gt;
&lt;br /&gt;
Script php :&lt;br /&gt;
&amp;lt;php&amp;gt;&amp;lt;?php&lt;br /&gt;
$localTokenFile    = 'token.json';&lt;br /&gt;
// create token file if it does not exist&lt;br /&gt;
if (!file_exists($localTokenFile))&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
$config                 = json_decode(file_get_contents('config.clientcred.json'), true);&lt;br /&gt;
$localToken             = json_decode(file_get_contents($localTokenFile), true);&lt;br /&gt;
$GLOBALS['config']      = $config;&lt;br /&gt;
&lt;br /&gt;
// Build the baseURL, accounting for protocol, port, name and endpoint. Used for redirection&lt;br /&gt;
$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';&lt;br /&gt;
$port     = ($protocol == 'https://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 443)&lt;br /&gt;
    || ($protocol == 'http://' &amp;amp;&amp;amp; $_SERVER['SERVER_PORT'] == 80) ? '' : ':' . $_SERVER['SERVER_PORT'];&lt;br /&gt;
&lt;br /&gt;
$baseURL            = $protocol . $_SERVER['SERVER_NAME'] . $port . $_SERVER['PHP_SELF'];&lt;br /&gt;
$errorLog           = 'error_log.log';&lt;br /&gt;
$responseLog        = 'response_log.log';&lt;br /&gt;
$GLOBALS['baseURL'] = $baseURL;&lt;br /&gt;
&lt;br /&gt;
$replacementListItems = [&lt;br /&gt;
    1 =&amp;gt; &amp;quot;year&amp;quot;,&lt;br /&gt;
    2 =&amp;gt; &amp;quot;validityTypeId&amp;quot;,&lt;br /&gt;
    3 =&amp;gt; &amp;quot;icao&amp;quot;,&lt;br /&gt;
    4 =&amp;gt; &amp;quot;profileId&amp;quot;,&lt;br /&gt;
    7 =&amp;gt; &amp;quot;accountingId&amp;quot;,&lt;br /&gt;
    8 =&amp;gt; &amp;quot;paymentType&amp;quot;,&lt;br /&gt;
    9 =&amp;gt; &amp;quot;startDate&amp;quot;,&lt;br /&gt;
    10 =&amp;gt; &amp;quot;endDate&amp;quot;,&lt;br /&gt;
    11 =&amp;gt; &amp;quot;occupiedSeat&amp;quot;,&lt;br /&gt;
    12 =&amp;gt; &amp;quot;date&amp;quot;,&lt;br /&gt;
    13 =&amp;gt; &amp;quot;activityTypeId&amp;quot;,&lt;br /&gt;
    14 =&amp;gt; &amp;quot;age&amp;quot;,&lt;br /&gt;
    15 =&amp;gt; &amp;quot;resourceId&amp;quot;,&lt;br /&gt;
    16 =&amp;gt; &amp;quot;personId&amp;quot;,&lt;br /&gt;
    17 =&amp;gt; &amp;quot;accountId&amp;quot;,&lt;br /&gt;
    20 =&amp;gt; &amp;quot;rightPlacePersonId&amp;quot;,&lt;br /&gt;
    21 =&amp;gt; &amp;quot;month&amp;quot;,&lt;br /&gt;
    22 =&amp;gt; &amp;quot;numberMonth&amp;quot;,&lt;br /&gt;
    23 =&amp;gt; &amp;quot;oneValidityTypeId&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
&lt;br /&gt;
//Session cookies are used to store information necessary for the authorization code flow&lt;br /&gt;
session_start();&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function is used to make api calls to the RS&lt;br /&gt;
 *&lt;br /&gt;
 * @param       $url&lt;br /&gt;
 * @param       $post&lt;br /&gt;
 * @param array $headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return mixed&lt;br /&gt;
 */&lt;br /&gt;
function apiRequest($url, $post = null, $token = false, $auth = true, $headers = array())&lt;br /&gt;
{&lt;br /&gt;
    $ch = curl_init($url);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HEADER, true);&lt;br /&gt;
&lt;br /&gt;
    $method = 'get';&lt;br /&gt;
&lt;br /&gt;
    if ($post) {&lt;br /&gt;
        $method   = 'post';&lt;br /&gt;
        $postData = http_build_query($post);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POST, true);&lt;br /&gt;
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);&lt;br /&gt;
&lt;br /&gt;
        $headersToSign['Content-Type'] = 'application/x-www-form-urlencoded';&lt;br /&gt;
        $headersToSign['digest']       = 'SHA-256=' . base64_encode(hash('sha256', $postData, true));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $urlComponents = parse_url($url);&lt;br /&gt;
&lt;br /&gt;
    $headersToSign['(request-target)'] = $method . ' ' . $urlComponents['path'];&lt;br /&gt;
    $headersToSign['Host']             = $urlComponents['host'];&lt;br /&gt;
    $headersToSign['Date']             = gmdate('D, j M Y H:i:s T');&lt;br /&gt;
&lt;br /&gt;
    // generating the signature header&lt;br /&gt;
    $keyId                = openssl_x509_fingerprint(file_get_contents($GLOBALS['config']['sign_cert']));&lt;br /&gt;
    $privateKey           = file_get_contents($GLOBALS['config']['sign_key']);&lt;br /&gt;
    $headers['Signature'] = generateSignatureHeader($headersToSign, $keyId, $privateKey);&lt;br /&gt;
&lt;br /&gt;
    $headers['Accept']     = 'application/json';&lt;br /&gt;
    $headers['User-Agent'] = $GLOBALS['baseURL'];&lt;br /&gt;
    unset($headersToSign['(request-target)']);&lt;br /&gt;
    $headers               += $headersToSign;&lt;br /&gt;
&lt;br /&gt;
    if ($token) {&lt;br /&gt;
        $headers['Authorization'] = $token['token_type'] . ' ' . $token['access_token'];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // formatting the headers&lt;br /&gt;
    $httpFormattedHeaders = [];&lt;br /&gt;
    foreach ($headers as $key =&amp;gt; $value) {&lt;br /&gt;
        $httpFormattedHeaders[] = trim($key) . ': ' . trim($value);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    curl_setopt($ch, CURLOPT_HTTPHEADER, $httpFormattedHeaders);&lt;br /&gt;
    curl_setopt($ch, CURLINFO_HEADER_OUT, true);&lt;br /&gt;
&lt;br /&gt;
    // for development environment only&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);&lt;br /&gt;
    //curl_setopt($ch, CURLOPT_VERBOSE, true);&lt;br /&gt;
&lt;br /&gt;
    // defining TLS client certificates for Mutual TLS&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_CAINFO, $GLOBALS['config']['auth_cacert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLCERT, $GLOBALS['config']['auth_cert']);&lt;br /&gt;
    curl_setopt($ch, CURLOPT_SSLKEY, $GLOBALS['config']['auth_key']);&lt;br /&gt;
&lt;br /&gt;
    $response = curl_exec($ch);&lt;br /&gt;
&lt;br /&gt;
    // logging errors and responses&lt;br /&gt;
    errorLog(true, $response, $ch);&lt;br /&gt;
&lt;br /&gt;
    curl_close($ch);&lt;br /&gt;
&lt;br /&gt;
    // in case an authentication request is executed&lt;br /&gt;
    if ($auth) {&lt;br /&gt;
        list($responseHeader, $responseBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $response, 2);&lt;br /&gt;
&lt;br /&gt;
        $responseHeadersDigest = '';&lt;br /&gt;
        $responseHeadersSignature = '';&lt;br /&gt;
        // extracting digest and signature from headers&lt;br /&gt;
        $responseHeadersArray = explode(&amp;quot;\r\n&amp;quot;, $responseHeader);&lt;br /&gt;
        $responseProtocol = array_shift($responseHeadersArray);&lt;br /&gt;
&lt;br /&gt;
        foreach ($responseHeadersArray as $value) {&lt;br /&gt;
            list($responseHeadersKeys, $responseHeadersValue) = explode(&amp;quot;: &amp;quot;, $value, 2);&lt;br /&gt;
            $responseHeaders[strtolower($responseHeadersKeys)] = $responseHeadersValue;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        $responseDigestAlgo = '';&lt;br /&gt;
        $responseDigestKey = '';&lt;br /&gt;
        foreach ($responseHeaders as $key =&amp;gt; $value) {&lt;br /&gt;
            if ($key === &amp;quot;digest&amp;quot;) {&lt;br /&gt;
                $responseHeadersDigest = $value;&lt;br /&gt;
                // stripping SHA algorithm for later comparison&lt;br /&gt;
                list($responseDigestAlgo, $responseDigestKey) = explode(&amp;quot;=&amp;quot;, $responseHeadersDigest, 2);&lt;br /&gt;
            } else if ($key === &amp;quot;signature&amp;quot;)&lt;br /&gt;
                $responseHeadersSignature = $value;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // calculating response digest&lt;br /&gt;
        $responseDigest = base64_encode(hash(strtolower(str_replace(&amp;quot;-&amp;quot;, &amp;quot;&amp;quot;, $responseDigestAlgo)), $responseBody, true));&lt;br /&gt;
&lt;br /&gt;
        // checking digest validity&lt;br /&gt;
        if ($responseDigest !== $responseDigestKey) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Digests are not the same&amp;quot;);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // extracting variables from signature header&lt;br /&gt;
        $signatureArray = explode(&amp;quot;,&amp;quot;, $responseHeadersSignature);&lt;br /&gt;
        foreach ($signatureArray as $value) {&lt;br /&gt;
            list($signatureKey, $signatureValue) = explode(&amp;quot;=&amp;quot;, $value, 2);&lt;br /&gt;
            $signature[$signatureKey] = trim($signatureValue, '&amp;quot;');&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // generating siging string&lt;br /&gt;
        $signingStringArray = explode(&amp;quot; &amp;quot;, $signature['headers']);&lt;br /&gt;
        $signingString = '';&lt;br /&gt;
        foreach ($signingStringArray as $value) {&lt;br /&gt;
            $signingString = $signingString . trim($value) . &amp;quot;: &amp;quot; . trim($responseHeaders[$value]) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // trimming last '\n' character&lt;br /&gt;
        $signingString = trim($signingString);&lt;br /&gt;
&lt;br /&gt;
        // decoding signature&lt;br /&gt;
        $decodedSignature = base64_decode($signature['signature']);&lt;br /&gt;
&lt;br /&gt;
        // verifying signature&lt;br /&gt;
        $signatureVerify = openssl_verify($signingString, $decodedSignature, openssl_get_publickey(file_get_contents($GLOBALS['config']['sign_cert_server'])), 'RSA-SHA256');&lt;br /&gt;
&lt;br /&gt;
        if (!$signatureVerify) {&lt;br /&gt;
            errorLog(false, false, &amp;quot;Signature is not correct&amp;quot;);&lt;br /&gt;
            while (($err = openssl_error_string()))&lt;br /&gt;
                errorLog(false, false, $err);&lt;br /&gt;
            die();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return json_decode($responseBody, true);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return $response;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function logs curl responses and errors in text files&lt;br /&gt;
 *&lt;br /&gt;
 * @param mixed $response the response&lt;br /&gt;
 * @param mixed $request  the request handle, used to get errors&lt;br /&gt;
 */&lt;br /&gt;
function errorLog($curl, $response, $request = false)&lt;br /&gt;
{&lt;br /&gt;
    $timestamp = '[' . date('Y-m-d H:i:s') . ']:';&lt;br /&gt;
    global $errorLog;&lt;br /&gt;
    global $responseLog;&lt;br /&gt;
&lt;br /&gt;
    if ($response === false) {&lt;br /&gt;
        if ($curl)&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . curl_error($request) . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
        else&lt;br /&gt;
            file_put_contents($errorLog, $timestamp . $request . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    } else {&lt;br /&gt;
        file_put_contents($responseLog, $timestamp . &amp;quot;\n&amp;quot; . $response . &amp;quot;\n&amp;quot;, FILE_APPEND);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function generates the full signature header line from a set of headers, a certificate and the linked private key&lt;br /&gt;
 *&lt;br /&gt;
 * @param array  $headersToSign the headers to sign, in the $key =&amp;gt; $value format&lt;br /&gt;
 * @param string $certificate   the certificate linked to the used private key&lt;br /&gt;
 * @param string $privateKey    the private key used to sign the headers&lt;br /&gt;
 *&lt;br /&gt;
 * @return string the full signature header line&lt;br /&gt;
 */&lt;br /&gt;
function generateSignatureHeader(array $headersToSign, string $certificate, string $privateKey): string&lt;br /&gt;
{&lt;br /&gt;
    // generating the signing string and header list&lt;br /&gt;
    $headers         = '';&lt;br /&gt;
    $signatureString = '';&lt;br /&gt;
    foreach ($headersToSign as $key =&amp;gt; $value) {&lt;br /&gt;
        $normalizedHeaderKey = trim(strtolower($key));&lt;br /&gt;
        $headers             .= $normalizedHeaderKey . ' ';&lt;br /&gt;
        $signatureString     .= $normalizedHeaderKey . ': ' . trim($value) . &amp;quot;\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    $headers         = trim($headers);&lt;br /&gt;
    $signatureString = trim($signatureString);&lt;br /&gt;
&lt;br /&gt;
    // signing the signing string&lt;br /&gt;
    $signature = '';&lt;br /&gt;
    openssl_sign($signatureString, $signature, openssl_get_privatekey($privateKey), 'RSA-SHA256');&lt;br /&gt;
    $signature = base64_encode($signature);&lt;br /&gt;
&lt;br /&gt;
    // compiling the header line&lt;br /&gt;
    return &amp;quot;keyId=\&amp;quot;$certificate\&amp;quot;,algorithm=\&amp;quot;rsa-sha256\&amp;quot;,headers=\&amp;quot;$headers\&amp;quot;,signature=\&amp;quot;$signature\&amp;quot;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * This function deletes the access token from the session&lt;br /&gt;
 *&lt;br /&gt;
 * @param string $baseURL&lt;br /&gt;
 */&lt;br /&gt;
function logout(string $baseURL): void&lt;br /&gt;
{&lt;br /&gt;
    global $localTokenFile;&lt;br /&gt;
    file_put_contents($localTokenFile, '');&lt;br /&gt;
&lt;br /&gt;
    header('Location: ' . $baseURL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedIn(): void&lt;br /&gt;
{&lt;br /&gt;
    global $replacementListItems;&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Logged In&amp;lt;/h3&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;view_repos&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;label for=&amp;quot;report_id&amp;quot;&amp;gt;Report ID: &amp;lt;/label&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;number&amp;quot; id=&amp;quot;report_id&amp;quot; name=&amp;quot;report_id&amp;quot;&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;';&lt;br /&gt;
    foreach ($replacementListItems as $value) {&lt;br /&gt;
        echo '&amp;lt;label for=&amp;quot;' . $value . '&amp;quot;&amp;gt;' . $value . ': &amp;lt;/label&amp;gt;';&lt;br /&gt;
        echo '&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;' . $value . '&amp;quot; name=&amp;quot;' . $value . '&amp;quot;&amp;gt;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;';&lt;br /&gt;
    }&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;view&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'view_repos\').submit(); return false;&amp;quot;&amp;gt;View Repos&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;logout&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;logout&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'logout\').submit(); return false;&amp;quot;&amp;gt;Log Out&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function displayMenuLoggedOut(): void&lt;br /&gt;
{&lt;br /&gt;
    echo '&amp;lt;h2&amp;gt;&amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Home&amp;lt;/a&amp;gt;&amp;lt;/h2&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;h3&amp;gt;Not logged in&amp;lt;/h3&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;form id=&amp;quot;login&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;action&amp;quot; name=&amp;quot;action&amp;quot; value=&amp;quot;login&amp;quot;&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;javascript:{}&amp;quot; onclick=&amp;quot;document.getElementById(\'login\').submit(); return false;&amp;quot;&amp;gt;Log In&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;';&lt;br /&gt;
    echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// display client &amp;quot;home&amp;quot; page&lt;br /&gt;
if (!isset($_POST['action'])) {&lt;br /&gt;
    if (!empty($localToken['access_token'])) {&lt;br /&gt;
        displayMenuLoggedIn();&lt;br /&gt;
    } else {&lt;br /&gt;
        displayMenuLoggedOut();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if (isset($_POST['action'])) {&lt;br /&gt;
    $replacementList = [];&lt;br /&gt;
    // Building replacement list&lt;br /&gt;
    foreach ($replacementListItems as $key =&amp;gt; $value) {&lt;br /&gt;
        $replacementList[$value] = (isset($_POST[$value]) &amp;amp;&amp;amp; strlen($_POST[$value]) &amp;gt; 0) ? $_POST[$value] : null;&lt;br /&gt;
    }&lt;br /&gt;
    // Building query array&lt;br /&gt;
    $repoQueryParameters = [&lt;br /&gt;
        'resource_type' =&amp;gt; 'generic_report',&lt;br /&gt;
        'client_id' =&amp;gt; $config['client_id'],&lt;br /&gt;
        'report_id' =&amp;gt; (isset($_POST['report_id']) &amp;amp;&amp;amp; strlen($_POST['report_id']) &amp;gt; 0) ? $_POST['report_id'] : null,&lt;br /&gt;
        'replacementList' =&amp;gt; $replacementList&lt;br /&gt;
    ];&lt;br /&gt;
    switch ($_POST['action']) {&lt;br /&gt;
        case 'login':&lt;br /&gt;
            $token = apiRequest(&lt;br /&gt;
                $config['token_uri'],&lt;br /&gt;
                [&lt;br /&gt;
                    'grant_type'    =&amp;gt; 'client_credentials',&lt;br /&gt;
                    'client_id'     =&amp;gt; $config['client_id'],&lt;br /&gt;
                    'client_secret' =&amp;gt; empty($config['client_secret']) ? null : $config['client_secret'],&lt;br /&gt;
                    'scope'         =&amp;gt; 'genericreports.readonly reports.readonly'&lt;br /&gt;
                ]&lt;br /&gt;
            );&lt;br /&gt;
            // We store the access token in the session so the user is &amp;quot;connected&amp;quot;&lt;br /&gt;
            // Only if the request has been successfully executed&lt;br /&gt;
            if (isset($token['access_token'])) {&lt;br /&gt;
                file_put_contents($localTokenFile, json_encode($token, true));&lt;br /&gt;
&lt;br /&gt;
                // Redirecting the user's browser to the &amp;quot;home&amp;quot; page&lt;br /&gt;
                header('Location: ' . $baseURL);&lt;br /&gt;
            } else {&lt;br /&gt;
                echo $token;&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
        case 'logout':&lt;br /&gt;
            logout($baseURL);&lt;br /&gt;
            break;&lt;br /&gt;
        case 'view':&lt;br /&gt;
            // call to the resource server&lt;br /&gt;
            $resources = apiRequest(&lt;br /&gt;
                $config['resource_uri'],&lt;br /&gt;
                $repoQueryParameters,&lt;br /&gt;
                $localToken,&lt;br /&gt;
                false&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            // Separating headers from body&lt;br /&gt;
            list($resourceHeader, $resourceBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $resources, 2);&lt;br /&gt;
&lt;br /&gt;
            $resourceHeaders = explode(&amp;quot;\r\n&amp;quot;, $resourceHeader);&lt;br /&gt;
            $firstHeaderLine = array_shift($resourceHeaders);&lt;br /&gt;
&lt;br /&gt;
            // Building form for download CSV button&lt;br /&gt;
            echo '&amp;lt;form method=&amp;quot;post&amp;quot;&amp;gt;';&lt;br /&gt;
            foreach ($_POST as $key =&amp;gt; $value) {&lt;br /&gt;
                if ($key == &amp;quot;action&amp;quot;) {&lt;br /&gt;
                    $value = &amp;quot;download&amp;quot;;&lt;br /&gt;
                }&lt;br /&gt;
                echo '&amp;lt;input type=&amp;quot;hidden&amp;quot; id=&amp;quot;' . $key . '&amp;quot; name=&amp;quot;' . $key . '&amp;quot; value=&amp;quot;' . $value . '&amp;quot;&amp;gt;';&lt;br /&gt;
            }&lt;br /&gt;
            if (isset($_POST['report_id']) &amp;amp;&amp;amp; strlen($_POST['report_id']) &amp;gt; 0 &amp;amp;&amp;amp; !isset(json_decode($resourceBody, true)['error'])) {&lt;br /&gt;
                echo '&amp;lt;button&amp;gt;Download as CSV&amp;lt;/button&amp;gt;';&lt;br /&gt;
            }&lt;br /&gt;
            echo '&amp;lt;/form&amp;gt;';&lt;br /&gt;
&lt;br /&gt;
            // Displaying requested content&lt;br /&gt;
            echo '&amp;lt;pre&amp;gt;';&lt;br /&gt;
            echo (strpos($firstHeaderLine, &amp;quot;200&amp;quot;)) ? json_decode($resourceBody) : $resourceBody;&lt;br /&gt;
            echo '&amp;lt;/pre&amp;gt;';&lt;br /&gt;
            break;&lt;br /&gt;
        case 'download':&lt;br /&gt;
            // call to the resource server&lt;br /&gt;
            $resources = apiRequest(&lt;br /&gt;
                $config['resource_uri'],&lt;br /&gt;
                $repoQueryParameters,&lt;br /&gt;
                $localToken,&lt;br /&gt;
                false&lt;br /&gt;
            );&lt;br /&gt;
&lt;br /&gt;
            // Separating headers from body&lt;br /&gt;
            list($resourceHeader, $resourceBody) = explode(&amp;quot;\r\n\r\n&amp;quot;, $resources, 2);&lt;br /&gt;
            $resourceHeaders = explode(&amp;quot;\r\n&amp;quot;, $resourceHeader);&lt;br /&gt;
            array_shift($resourceHeaders);&lt;br /&gt;
&lt;br /&gt;
            // Dumping headers to insert them in current page&lt;br /&gt;
            foreach ($resourceHeaders as $key =&amp;gt; $value) {&lt;br /&gt;
                header($value);&lt;br /&gt;
            }&lt;br /&gt;
            echo json_decode($resourceBody);&lt;br /&gt;
            break;&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Ce script a été conçu pour montrer le fonctionnement du mécanisme et tester l'implémentation d'un serveur, il n'a pas été testé extensivement. Il est conseillé d'utiliser une solution adaptée à un environnement de production.&lt;br /&gt;
&lt;br /&gt;
==Refresh Token==&lt;br /&gt;
Refresh Token (ou jeton de rafraîchissement en français) est un mécanisme d'autorisation particulier. Il ne peut fonctionner en tant que tel, il fonctionne de pair avec [[#Authorization-Code|Authorization Code]]. Lorsqu'un jeton d'accès arrive est arrivé en fin de vie, si le client y est autorisé, il peut faire une demande de renouvellement de son jeton d'accès auprès du serveur d'autorisation en présentant son jeton de rafraîchissement. Le serveur d'autorisation vérifie la validité et génère un autre jeton d'accès qu'il transmet au client, sans que l'utilisateur final n'aît à se connecter de nouveau.&lt;br /&gt;
&lt;br /&gt;
Le principe de fonctionnement du rafraîchissement d'un jeton est le suivant :&lt;br /&gt;
* Le jeton d'accès du client est arrivé à péremption. Le client effectue une demande de renouvellement en transmettant son Refresh Token au serveur d'autorisation.&lt;br /&gt;
* Le serveur d'autorisation vérifie la validité des informations, &amp;quot;consomme&amp;quot; le jeton de rafraîchissement et génère une nouvelle paire de jetons&lt;br /&gt;
* Le client reçoit sa nouvelle paire et utilise le nouveau jeton d'accès pour accéder aux ressources&lt;br /&gt;
&lt;br /&gt;
    +------+                       +-------------+                  +-----------+&lt;br /&gt;
    |Client|                       |   Serveur   |                  |  Serveur  |&lt;br /&gt;
    +--+---+                       |Autorisation |                  | Ressources|&lt;br /&gt;
       |                           +------+------+                  +-----+-----+&lt;br /&gt;
       |        Authentification          |                               |&lt;br /&gt;
       |         + Refresh Token          |                               |&lt;br /&gt;
       +---------------------------------&amp;gt;|                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |    Access (+ Refresh) token      |                               |&lt;br /&gt;
       |&amp;lt;---------------------------------+                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                      Requête vers|API                            |&lt;br /&gt;
       +----------------------------------+------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                                  |&amp;lt;------------------------------+&lt;br /&gt;
       |                                  |  Vérification d'autorisation  |&lt;br /&gt;
       |                                  +------------------------------&amp;gt;|&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
       |                         Données /|Réponse                        |&lt;br /&gt;
       |&amp;lt;---------------------------------+-------------------------------+&lt;br /&gt;
       |                                  |                               |&lt;br /&gt;
&lt;br /&gt;
===Demande de renouvellement d'un jeton===&lt;br /&gt;
Pour obtenir un renouvellement de jeton d'accès, il faut effectuer la requête suivante : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/access_token.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Les paramètres suivants sont nécessaires :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant ''client_id'' reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|client_secret||string||La passphrase ''client_secret'' reçue pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|grant_type||string||Le mécanisme d'autorisation utilisé. Ici, la valeur doit être &amp;quot;refresh_token&amp;quot; (sans guillements).&lt;br /&gt;
|-&lt;br /&gt;
|scope||string||('''OPTIONNEL''') Liste des droits demandés par le client, séparés par des espaces.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Si la requête est correcte, un jeton d'accès ''access_token'' est fourni en réponse dans un objet au format JSON.&lt;br /&gt;
&amp;lt;javascript&amp;gt;{&lt;br /&gt;
  &amp;quot;token_type&amp;quot;: &amp;quot;Bearer&amp;quot;,&lt;br /&gt;
  &amp;quot;expires_in&amp;quot;: 3600,&lt;br /&gt;
  &amp;quot;access_token&amp;quot;: &amp;quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJSU-G7fOBOYzOgioSGNIQKI2A2OxjsNBbOOoaHsqNpsQxWZse3rofExAaGKh2tXbeuz1YAVhdLUGYgq-oKRK4ONFhw2NvcRf3QPxQXZImLWw&amp;quot;,&lt;br /&gt;
  &amp;quot;refresh_token&amp;quot;: &amp;quot;a59ef39fa9bab9b95cd554f921e7f3080a34c90f23d2b8031d692b5ff2d0993dcc392d9c7f9a43242337ef144c1a5fe1d0174413ade973e1b628ac0bbfc39b23973534&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Liste des scopes disponibles==&lt;br /&gt;
Un scope sur OAuth2 correspond à un droit d'accès sur une ressource particulière. Chaque scope est unique et indique de manière explicite le privilège qu'il donne. Il n'y a aucune restriction d'utilisation des scopes par rapport aux mécanismes. Chaque scope peut être utilisé avec n'importe quel mécanisme. Il n'y a que des recommandations vis à vis de leur utilisation. OpenFlyers définit une liste de scopes dédiée aux ressources accessibles par les clients. Ces scopes sont les suivants :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Description&lt;br /&gt;
|-&lt;br /&gt;
|default.login||Comportement par défaut lorsqu'aucun scope n'est précisé ou qu'un scope est invalide. Ce scope est recommandé pour '''Authorization Code'''.&lt;br /&gt;
|-&lt;br /&gt;
|genericreports.readonly||Accéder aux rapports génériques autorisés pour le client en lecture seule. Ce scope est recommandé pour '''Client Credentials'''.&lt;br /&gt;
|-&lt;br /&gt;
|reports.readonly||Accéder aux rapports personnalisés autorisés pour le client en lecture seule. Ce scope est recommandé pour '''Client Credentials'''.&lt;br /&gt;
|}&lt;br /&gt;
==Prolonger la durée de vie de la session du client de démonstration==&lt;br /&gt;
La session du client de démonstration est initiée avec la méthode PHP [https://www.php.net/manual/en/function.session-start.php session_start]. Cette session peut être interrompue soit en cliquant sur le bouton de déconnexion, soit en fermant le navigateur (car les cookies associés à cette session se détruisent par défaut lorsque le navigateur est fermé).&lt;br /&gt;
&lt;br /&gt;
Pour permettre à la session de rester active même après la fermeture du navigateur, il faut utiliser la méthode PHP [https://www.php.net/manual/en/function.session-set-cookie-params.php session_set_cookie_params]. Cette méthode donne la possibilité de définir une durée de vie pour les différents cookies associés à la session.&lt;br /&gt;
&amp;lt;php&amp;gt;// Set the parameters for the session cookie in a PHP session in order to configure its lifetime in 30 days&lt;br /&gt;
$oauth2DemoSessionLifeTime = time() + (86400 * 30);&lt;br /&gt;
session_set_cookie_params($oauth2DemoSessionLifeTime);&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NB: Cette approche n'est pas particulièrement sécurisée et peut présenter des risques de sécurité pour OpenFlyers. Par conséquent, elle doit être utilisée avec précaution.&lt;br /&gt;
&lt;br /&gt;
==Révocation de token==&lt;br /&gt;
Pour initier la demande de révocation, rediriger le navigateur de l'utilisateur vers l'URL : &amp;lt;code&amp;gt;POST https://openflyers.com/nom-de-plateforme/oauth/revoke.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée.&lt;br /&gt;
&lt;br /&gt;
Envoyer également le paramètre suivant:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|access_token||string||Le jeton d'accès (Chaîne de caractère unique permettant de prouver qu'un client OAuth a le droit d'accéder à une ressource.)&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;php&amp;gt; apiRequest(&lt;br /&gt;
                $config['revoke_uri'],&lt;br /&gt;
                ['access_token' =&amp;gt; $_SESSION['auth_token']['access_token']],&lt;br /&gt;
                null,&lt;br /&gt;
                false&lt;br /&gt;
            );&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La demande de révocation se fait quand l'utilisateur clique sur le bouton '''Se déconnecter''' pour l'un des deux Clients '''Authorization Code''' et '''Client Credentials'''.&lt;br /&gt;
&lt;br /&gt;
Si les jetons sont révoqués, l'utilisateur ne peut pas accéder à la plateforme OpenFlyers, il doit se reconnecter.&lt;br /&gt;
&lt;br /&gt;
==Utiliser l'API==&lt;br /&gt;
Une fois un jeton d'accès obtenu, les données sont accessibles par une requête POST exécutée vers l'URL : &amp;lt;code&amp;gt;https://openflyers.com/nom-de-plateforme/oauth/resources.php&amp;lt;/code&amp;gt;. Remplacer &amp;lt;code&amp;gt;nom-de-plateforme&amp;lt;/code&amp;gt; par le nom de la plateforme utilisée. La requête POST doit respecter une structure particulière. Cette structure diffère en fonction du type de ressource souhaité et chaque ressource ne peut être accédée qu'[[#Liste-des-scopes-disponibles|avec le scope qui lui est associé]]. Le jeton d'accès doit être renseigné dans l'en-tête HTTP ''Authorization'' en y indiquant la valeur complète du jeton d'accès reçu précédé du type de jeton reçu  : &amp;lt;code&amp;gt;Authorization: &amp;lt;token_type&amp;gt; &amp;lt;access_token&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Récupérer les informations de l'utilisateur connecté===&lt;br /&gt;
Ce type de ressource est nommé '''user_information'''. Cette ressource n'est accessible qu'avec le scope '''default.login'''. Cette ressource permet la récupération des informations de l'utilisateur connecté, en d'autre termes, l'utilisateur connecté lors de l'étape d'autorisation et correspondant à celui ayant émis la demande de jeton d'accès. À l'heure actuelle, seul l'identifiant de l'utilisateur connecté est retourné. La requête POST est construite de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|resource_type||string||Le type de ressource demandé, ici, ce champ correspond à '''user_information'''.&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Un exemple de requête complète au format JSON :&lt;br /&gt;
&amp;lt;javascript&amp;gt;POST /nom-de-plateforme/oauth/resources.php HTTP/1.1&lt;br /&gt;
Content-Type: application/x-www-form-urlencoded&lt;br /&gt;
Host: openflyers.com&lt;br /&gt;
Date: Wed, 04 Aug 2021 13:57:51 GMT&lt;br /&gt;
Accept: application/json&lt;br /&gt;
User-Agent: curl/7.64.1&lt;br /&gt;
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU&lt;br /&gt;
Signature: keyId=&amp;quot;58c450d937953829c8cca3613001f865a918da07&amp;quot;,&lt;br /&gt;
           algorithm=&amp;quot;rsa-sha256&amp;quot;,&lt;br /&gt;
           headers=&amp;quot;host content-type digest&amp;quot;,&lt;br /&gt;
           signature=&amp;quot;UsTjCPLsXzmo1b8FrA18SdLgaPamCpqR7tDHBhaiBnro6RbOkoD7=&amp;quot;&lt;br /&gt;
Digest: SHA-256=Bi6/9qfJXEWme2/9o7VQMyvf+MED523bWdtdi91opwk=&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;resource_type&amp;quot;:&amp;quot;user_information&amp;quot;,&lt;br /&gt;
    &amp;quot;client_id&amp;quot;:&amp;quot;d2615fe2020ec476&amp;quot;&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La réponse est retournée dans un conteneur JSON.&lt;br /&gt;
&lt;br /&gt;
===Récupérer les rapports génériques===&lt;br /&gt;
Ce type de ressource est nommé '''generic_report'''. Cette ressource n'est accessible qu'avec le scope '''genericreports.readonly'''. Cette ressource permet la récupération des rapports génériques au format CSV autorisés pour le profil de l'utilisateur associé au client OAuth2 enregistré. La requête POST est construite de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|resource_type||string||Le type de ressource demandé, ici, ce champ correspond à '''generic_report'''.&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|report_id||int||Identifiant du rapport souhaité.&lt;br /&gt;
|-&lt;br /&gt;
|replacementList||array||Tableau correspondant aux différents paramètres modifiables pour générer le rapport souhaité.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Un exemple de requête complète au format JSON :&lt;br /&gt;
&amp;lt;javascript&amp;gt;POST /nom-de-plateforme/oauth/resources.php HTTP/1.1&lt;br /&gt;
Content-Type: application/x-www-form-urlencoded&lt;br /&gt;
Host: openflyers.com&lt;br /&gt;
Date: Wed, 04 Aug 2021 13:57:51 GMT&lt;br /&gt;
Accept: application/json&lt;br /&gt;
User-Agent: curl/7.64.1&lt;br /&gt;
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU&lt;br /&gt;
Signature: keyId=&amp;quot;58c450d937953829c8cca3613001f865a918da07&amp;quot;,&lt;br /&gt;
           algorithm=&amp;quot;rsa-sha256&amp;quot;,&lt;br /&gt;
           headers=&amp;quot;host content-type digest&amp;quot;,&lt;br /&gt;
           signature=&amp;quot;UsTjCPLsXzmo1b8FrA18SdLgaPamCpqR7tDHBhaiBnro6RbOkoD7=&amp;quot;&lt;br /&gt;
Digest: SHA-256=Bi6/9qfJXEWme2/9o7VQMyvf+MED523bWdtdi91opwk=&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;resource_type&amp;quot;:&amp;quot;generic_report&amp;quot;,&lt;br /&gt;
    &amp;quot;client_id&amp;quot;:&amp;quot;d2615fe2020ec476&amp;quot;,&lt;br /&gt;
    &amp;quot;report_id&amp;quot;:135,&lt;br /&gt;
    &amp;quot;replacementList&amp;quot;:{&lt;br /&gt;
        &amp;quot;year&amp;quot;:2018&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La réponse est un fichier CSV retourné dans un conteneur JSON.&lt;br /&gt;
&lt;br /&gt;
===Récupérer les rapports personnalisés===&lt;br /&gt;
Ce type de ressource est nommé '''report'''. Cette ressource n'est accessible qu'avec le scope '''reports.readonly'''. Cette ressource permet la récupération des rapports personnalisés au format CSV autorisés pour le profil de l'utilisateur associé au client OAuth2 enregistré. La requête POST est construite de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Nom!!Type!!Description&lt;br /&gt;
|-&lt;br /&gt;
|resource_type||string||Le type de ressource demandé, ici, ce champ correspond à '''report'''.&lt;br /&gt;
|-&lt;br /&gt;
|client_id||string||L'identifiant unique reçu pendant l'enregistrement du client.&lt;br /&gt;
|-&lt;br /&gt;
|report_id||int||Identifiant du rapport souhaité.&lt;br /&gt;
|-&lt;br /&gt;
|replacementList||array||Tableau correspondant aux différents paramètres modifiables pour générer le rapport souhaité.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Un exemple de requête complète au format JSON :&lt;br /&gt;
&amp;lt;javascript&amp;gt;POST /nom-de-plateforme/oauth/resources.php HTTP/1.1&lt;br /&gt;
Content-Type: application/x-www-form-urlencoded&lt;br /&gt;
Host: openflyers.com&lt;br /&gt;
Date: Wed, 04 Aug 2021 13:57:51 GMT&lt;br /&gt;
Accept: application/json&lt;br /&gt;
User-Agent: curl/7.64.1&lt;br /&gt;
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU&lt;br /&gt;
Signature: keyId=&amp;quot;58c450d937953829c8cca3613001f865a918da07&amp;quot;,&lt;br /&gt;
           algorithm=&amp;quot;rsa-sha256&amp;quot;,&lt;br /&gt;
           headers=&amp;quot;host content-type digest&amp;quot;,&lt;br /&gt;
           signature=&amp;quot;UsTjCPLsXzmo1b8FrA18SdLgaPamCpqR7tDHBhaiBnro6RbOkoD7=&amp;quot;&lt;br /&gt;
Digest: SHA-256=Bi6/9qfJXEWme2/9o7VQMyvf+MED523bWdtdi91opwk=&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;resource_type&amp;quot;:&amp;quot;report&amp;quot;,&lt;br /&gt;
    &amp;quot;client_id&amp;quot;:&amp;quot;d2615fe2020ec476&amp;quot;,&lt;br /&gt;
    &amp;quot;report_id&amp;quot;:1,&lt;br /&gt;
    &amp;quot;replacementList&amp;quot;:{&lt;br /&gt;
        &amp;quot;year&amp;quot;:2020&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/javascript&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La réponse est un fichier CSV retourné dans un conteneur JSON.&lt;br /&gt;
&lt;br /&gt;
=Procédures=&lt;br /&gt;
==Créer un client à partir du code source==&lt;br /&gt;
;Prérequis&lt;br /&gt;
Un client de démonstration est disponible pour le logiciel OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/index.php&lt;br /&gt;
&lt;br /&gt;
;Télécharger Le code source du client de démonstration :&lt;br /&gt;
&lt;br /&gt;
Le code source est mis à disposition par OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/oauth2-demo-src.zip &lt;br /&gt;
&lt;br /&gt;
Le code source est structuré de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 src demo folder.png|800px]]&lt;br /&gt;
&lt;br /&gt;
* Le dossier '''css''' contient tout le matériel nécessaire à la stylisation de la page web.&lt;br /&gt;
* Le dossier '''img''' contient les images affichées sur la page web.&lt;br /&gt;
* Le dossier '''ssl''' est le dossier contenant tous les certificats et les clé privées associées à chaque client. Il doit respecter une structure particulière décrite ci-dessous.&lt;br /&gt;
* Le fichier '''ClientDemo.php''' contient la classe '''ClientDemo'''. Cette classe contient toutes les méthodes nécessaires au fonctionnement du client de démonstration OAuth2.&lt;br /&gt;
* Le fichier '''index.php''' est le fichier à appeler depuis le navigateur. Ce fichier correspond au fichier qui gère les appels à la classe '''ClientDemo''' et exécute les méthodes dans l'ordre.&lt;br /&gt;
&lt;br /&gt;
Le dossier '''ssl''' doit respecter la structure suivante :&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 demo tree.png]]&lt;br /&gt;
&lt;br /&gt;
;[[#Générer des certificats|Générer les certificats]] :&lt;br /&gt;
Après la génération des certificats, les clés privées 'auth.key' et 'sign.key' remplacent celles présentes dans les dossiers 'ssl/AuthCodeDemo' et 'ssl/ClientCredDemo'.&lt;br /&gt;
&lt;br /&gt;
;[[#Enregistrer un client|Enregistrer les clients]] :&lt;br /&gt;
&lt;br /&gt;
*Deux clients doivent être créés :&lt;br /&gt;
**Le premier pour le mécanisme d'autorisation '''Authorization Code''',&lt;br /&gt;
**Le second pour le mécanisme d'autorisation '''Client Credentials'''.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 demo manage.png|800px]]&lt;br /&gt;
&lt;br /&gt;
*Télécharger le certificat du CA OpenFlyers en cliquant sur le bouton '''Télécharger le certificat CA''' de la page de gestion. Télécharger aussi le certificat de signature du serveur en cliquant sur le bouton '''Télécharger le certificat de signature du serveur''' de la page de gestion. Placer les deux certificats téléchargés à la racine du dossier '''ssl'''.&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Authorization Code''' et les placer dans le répertoire '''ssl/AuthCodeDemo'''. &lt;br /&gt;
*Modifier le fichier '''ssl/AuthCodeDemo/config.authcode.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;authorize_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/authorize.php&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;path_to_client/ssl/AuthCodeDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;path_to_client/ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;path_to_client/ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Remplacer les &amp;lt;code&amp;gt;XXXXXXXXXXXXXXXX&amp;lt;/code&amp;gt; des champs &amp;lt;code&amp;gt;client_id&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;client_secret&amp;lt;/code&amp;gt; par les valeurs obtenues lors de [[#Enregistrer-un-client|l'enregistrement du client]].&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;mastructure&amp;lt;/code&amp;gt; par le nom de la structure sur laquelle la démo est testée.&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;path_to_client/&amp;lt;/code&amp;gt; par le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
**Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
**Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Client Credentials''' et les placer dans le répertoire '''ssl/ClientCredDemo'''.&lt;br /&gt;
*Modifier le fichier '''ssl/ClientCredDemo/config.clientcred.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;path_to_client/ssl/ClientCredDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;path_to_client/ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;path_to_client/ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Remplacer les &amp;lt;code&amp;gt;XXXXXXXXXXXXXXXX&amp;lt;/code&amp;gt; des champs &amp;lt;code&amp;gt;client_id&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;client_secret&amp;lt;/code&amp;gt; par les valeurs obtenues lors de [[#Enregistrer-un-client|l'enregistrement du client]].&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;mastructure&amp;lt;/code&amp;gt; par le nom de la structure sur laquelle la démo est testée.&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;path_to_client/&amp;lt;/code&amp;gt; par le chemin d'accès vers le dossier qui contient le code source du client de démonstration.&lt;br /&gt;
**Exemple sur '''windows''': &amp;lt;code&amp;gt;C:/wamp64/www/4.0/oauth-demo/&amp;lt;/code&amp;gt;.&lt;br /&gt;
**Exemple sur un serveur Linux '''debian''': &amp;lt;code&amp;gt;./&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Suivre la [[#Utiliser le client|procédure d'utilisation du client de démonstration]] pour faire fonctionner le client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NB''': Le certificat de signature du serveur est unique à chaque plateforme et serveur. Ainsi, si le serveur ou la plateforme est modifié, le certificat doit être renouvelé.&lt;br /&gt;
&lt;br /&gt;
==Enregistrer un client==&lt;br /&gt;
Pour utiliser l'API OAuth2, il faut enregistrer un client OAuth2 auprès d'OpenFlyers. Pour ceci, suivre les étapes suivantes :&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Pour le mécanisme d'authentification Client Credentials&lt;br /&gt;
*Créer un [[Gestion-des-profils#Ajouter-un-profil|nouveau profil]]. Ce profil doit permettre de gérer les droits du client OAuth2. Choisir un nom explicite, par exemple &amp;quot;Client OAuth rapports&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*Sélectionner les droits à assigner à ce profil. Ces droits limitent les données auxquelles le client OAuth2 a accès.&lt;br /&gt;
**Sélectionner les droits relatifs à l'enregistrement de clients OAuth2 dans l'onglet '''Admin''' (colonne '''Associé aux clients OAuth2''').&lt;br /&gt;
**Sélectionner les rapports accessibles par le profil précédemment créé.&lt;br /&gt;
&lt;br /&gt;
*Créer un nouvel utilisateur à partir du panneau de gestion. Cet utilisateur est virtuel et représente le serveur sur lequel fonctionne le client OAuth2.&lt;br /&gt;
**''Des identifiant et nom explicites sont recommandés (exemple : &amp;quot;serv1_oauth_client&amp;quot;)''&lt;br /&gt;
**'''Attention''' : tout utilisateur désactivé et associé à un client OAuth2 rend le client inactif, il faut donc changer l'utilisateur associé au client pour réactiver le client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Pour le mécanisme d'authentification Authorization Code&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Utilisateurs &amp;gt; Profils'''&lt;br /&gt;
*Dans l'onglet '''Généralités''', cocher la case relative à la colonne '''Connexion depuis l'extérieur (OAuth2)''' pour le profil souhaité.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Créer un nouveau client OAuth2&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Transferts &amp;gt; Exports &amp;gt; API OAuth2'''&lt;br /&gt;
[[File:Oauth2 manage.png|800px]]&lt;br /&gt;
*Cliquer sur le bouton Ajouter '''+''' ou '''Ajouter un client'''&lt;br /&gt;
[[File:Oauth2 client creation.png|800px]]&lt;br /&gt;
*Choisir un nom pour le client.&lt;br /&gt;
*Sélectionner le mécanisme d'autorisation utilisé par le client :&lt;br /&gt;
**'''Authorization Code''': permet d'utiliser OAuth2 comme solution SSO ou accéder à des données utilisateurs. Cette méthode peut être couplée avec le mécanisme de mémorisation de connexion (''Refresh Token'').&lt;br /&gt;
**'''Client Credentials''': permet d'utiliser OAuth2 dans un contexte d'automatisme.&lt;br /&gt;
*Saisir l'URI de redirection vers le client pour le mécanisme ''Authorization Code''.&lt;br /&gt;
*Sélectionner l'utilisateur virtuel créé précédemment pour le mécanisme ''Client Credentials''.&lt;br /&gt;
*[[#Générer-des-certificats|Générer deux CSR]] afin d'obtenir deux certificats signés et les saisir :&lt;br /&gt;
**'''Certificate Signing Request pour le certificat d'authentification''' est utilisé pour l'authentification mutuelle avec mTLS (auth_cert.csr.pem).&lt;br /&gt;
**'''Certificate Signing Request pour le certificat de signature''' est utilisé pour la signature des en-têtes HTTP (sign_cert.csr.pem).&lt;br /&gt;
&lt;br /&gt;
[[File:PublicKeysCopyScreen.png|900px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Cliquer sur '''Enregistrer'''.&lt;br /&gt;
&lt;br /&gt;
NB: La validité des certificats générés s'étend sur une période de '''3 années'''.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Sauvegarder le couple ID/passphrase&lt;br /&gt;
Un couple ID/passphrase (client_id/client_secret) est généré. Ces deux clées ne sont communiquées qu'une seule fois. Elle doivent être stockées en toute sécurité et gardées confidentielles,&lt;br /&gt;
et Mettre ces identifiants dans le fichier '''config.clientcred.json'''.&lt;br /&gt;
[[File:Oauth2 client created.png]]&lt;br /&gt;
&lt;br /&gt;
[[File:ConfigCredJsonScreen.png|600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Télécharger les certificats crt&lt;br /&gt;
Les certificats signés sont téléchargeables depuis l'interface de gestion des clients OAuth2, les certificats sont disponibles dans les onglets '''Certificat d'authentification''' et '''Certificat de signature''' et les mettre dans le dossier '''/ssl''' du client OAuth2.&lt;br /&gt;
[[File:Oauth2 client certificates.png]]&lt;br /&gt;
&lt;br /&gt;
;Téléchargez les certificats du serveur.&lt;br /&gt;
*Les certificats du CA d'OpenFlyers et de signature HTTP du serveur sont nécessaires. Ils sont téléchargeables depuis l'interface de configuration des clients OAuth2.&lt;br /&gt;
[[File:DownloadServerCertifScreen.png|900px]]&lt;br /&gt;
*Dans certains cas d'utilisation, il peut être nécessaire d'ajouter le certificat du CA d'OpenFlyers au Trust Store du système. Si cette étape n'est pas réalisée, les certificats peuvent être considérés comme invalides et peuvent ne pas être utilisables.&lt;br /&gt;
*Pour ajouter le certificat CA au Trust Store du système, suivre les étapes suivantes:&lt;br /&gt;
**Sous Linux, copier le certificat CA d'OpenFlyers dans le dossier &amp;lt;code&amp;gt;/usr/local/share/ca-certificates&amp;lt;/code&amp;gt; et exécuter la commande &amp;lt;code&amp;gt;sudo update-ca-certificates&amp;lt;/code&amp;gt;&lt;br /&gt;
**Sous Windows,&lt;br /&gt;
***Double-cliquer sur le certificat CA d'OpenFlyers téléchargé depuis l'interface d'enregistrement des clients OAuth2&lt;br /&gt;
***Cliquer sur '''Installer un certificat...'''&lt;br /&gt;
***Choisir l'emplacement de stockage (utilisateur ou ordinateur) et cliquer sur '''Suivant''' puis '''Suivant''' et enfin '''Terminer'''&lt;br /&gt;
&lt;br /&gt;
==Générer des certificats==&lt;br /&gt;
L'API OAuth2 implémente [https://tools.ietf.org/html/draft-cavage-http-signatures-10 HTTP Signature] et l'[[Wikipedia-en:Mutual_authentication#mTLS|authentification TLS mutuelle]]. Ces mécanismes utilisent chacun une paire certificat/clé privée différente.&lt;br /&gt;
&lt;br /&gt;
Pour obtenir ces certificats, il faut d'abord générer des Certificate Signing Request (CSR).&lt;br /&gt;
&lt;br /&gt;
La procédure est la suivante :&lt;br /&gt;
*[[OpenSSL#Installer-OpenSSL-dans-un-environnement-Windows|Télécharger OpenSSL pour Windows]] ou [[OpenSSL#Utiliser-Openssl-d'Apache-sous-WAMP|utiliser Openssl d'Apache sous WAMP]].&lt;br /&gt;
*Utiliser les deux fichiers de configuration ''sign_cert.conf'' et ''auth_cert.conf'' ci-dessous et les remplir.&lt;br /&gt;
&lt;br /&gt;
;Fichier de configuration OpenSSL - sign_cert.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;[req]&lt;br /&gt;
default_bits       = 4096                     # taille par défaut des nouvelles clés, peut être surchargé dans la commande&lt;br /&gt;
encrypt_key        = no                       # chiffrer la clé générée&lt;br /&gt;
distinguished_name = req_distinguished_name   # pointe vers la catégorie spécifiée pour le Distinguished Name&lt;br /&gt;
x509_extensions    = v3_req                   # pointe vers la catégorie spécifiée pour les extensions x509&lt;br /&gt;
prompt             = no&lt;br /&gt;
&lt;br /&gt;
[req_distinguished_name]&lt;br /&gt;
C                  =                          # code à deux chiffres du pays (ex: FR)&lt;br /&gt;
ST                 =                          # région/état (ex: Gironde)&lt;br /&gt;
L                  =                          # ville (ex: Bordeaux)&lt;br /&gt;
O                  =                          # organisation (ex: OpenFlyers)&lt;br /&gt;
OU                 =                          # unité organisationelle (ex: IT)&lt;br /&gt;
CN                 =                          # nom de domaine (ex: openflyers.com)&lt;br /&gt;
&lt;br /&gt;
[v3_req]&lt;br /&gt;
keyUsage           = digitalSignature         # pour quelles opérations la clé peut-elle être utilisée&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Fichier de configuration OpenSSL - auth_cert.conf&lt;br /&gt;
&amp;lt;pre&amp;gt;[req]&lt;br /&gt;
default_bits       = 4096                     # taille par défaut des nouvelles clés, peut être surchargé dans la commande&lt;br /&gt;
encrypt_key        = no                       # chiffrer la clé générée&lt;br /&gt;
distinguished_name = req_distinguished_name   # pointe vers la catégorie spécifiée pour le Distinguished Name&lt;br /&gt;
x509_extensions    = v3_req                   # pointe vers la catégorie spécifiée pour les extensions x509&lt;br /&gt;
prompt             = no&lt;br /&gt;
&lt;br /&gt;
[req_distinguished_name]&lt;br /&gt;
C                  =                          # code à deux chiffres du pays (ex: FR)&lt;br /&gt;
ST                 =                          # région/état (ex: Gironde)&lt;br /&gt;
L                  =                          # ville (ex: Bordeaux)&lt;br /&gt;
O                  =                          # organisation (ex: OpenFlyers)&lt;br /&gt;
OU                 =                          # unité organisationelle (ex: IT)&lt;br /&gt;
CN                 =                          # nom de domaine (ex: openflyers.com)&lt;br /&gt;
&lt;br /&gt;
[v3_req]&lt;br /&gt;
extendedKeyUsage   = clientAuth               # pour quelles opérations la clé peut-elle être utilisée&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Exécuter les commandes suivantes :&lt;br /&gt;
*&amp;lt;bash&amp;gt;openssl req -sha256 -newkey rsa -keyout sign.key -out sign_cert.csr.pem -outform PEM -config sign_cert.conf&amp;lt;/bash&amp;gt;&lt;br /&gt;
*&amp;lt;bash&amp;gt;openssl req -sha256 -newkey rsa -keyout auth.key -out auth_cert.csr.pem -outform PEM -config auth_cert.conf&amp;lt;/bash&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ces commandes prennent chacune en entrée le fichier de configuration et génèrent une clé privée et un Certificate Signing Request. &lt;br /&gt;
&lt;br /&gt;
Une fois ces CSR obtenus :&lt;br /&gt;
*Les renseigner dans les champs prévus à cet effet lors de la [[#Enregistrer-un-client|création d'un client]] et télécharger les certificats signés depuis l'interface une fois le client créé.&lt;br /&gt;
*Garder la clé privée confidentielle. Une fuite poserait un risque de sécurité. Elle va de paire avec le certificat distribué par l'autorité de certification OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
==Mettre en place une connexion à l'API OpenFlyers sur un serveur mutualisé==&lt;br /&gt;
;Note&lt;br /&gt;
La procédure ci-après est destinée à une mise en place lorsqu'il n'y a pas d'accès SSH en ligne de commande mais uniquement un accès FTP. Dans ce cas, la création des clés privées et publics est effectuée &amp;quot;en local&amp;quot;. Dans la procédure suivante elle est effectuée depuis un PC sous '''Windows'''.&lt;br /&gt;
&lt;br /&gt;
;Prérequis&lt;br /&gt;
*Posséder les accès FTP :&lt;br /&gt;
**Hôte : XXXXXXXXXXXXXXXXXX&lt;br /&gt;
**Login : XXXXXXXX&lt;br /&gt;
**Mot de passe :  XXXXXXXX&lt;br /&gt;
**Port : XX (par exemple 21)&lt;br /&gt;
*Télécharger Le code source du client de démonstration à disposition par OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/oauth2-demo-src.zip &lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
*[[#Générer des certificats|Générer les certificats]] en local.&lt;br /&gt;
*Remplacer les clés privées 'auth.key' et 'sign.key' présentes dans les dossiers 'ssl/AuthCodeDemo' et 'ssl/ClientCredDemo' par les clés générées.&lt;br /&gt;
*[[#Enregistrer un client|Enregistrer les deux clients]] :&lt;br /&gt;
**Le premier pour le mécanisme d'autorisation '''Authorization Code'''.&lt;br /&gt;
**Le second pour le mécanisme d'autorisation '''Client Credentials'''.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 demo manage.png|800px]]&lt;br /&gt;
&lt;br /&gt;
*Télécharger le certificat du CA OpenFlyers en cliquant sur le bouton '''Télécharger le certificat CA''' de la page de gestion. &lt;br /&gt;
*Télécharger aussi le certificat de signature du serveur en cliquant sur le bouton '''Télécharger le certificat de signature du serveur''' de la page de gestion.&lt;br /&gt;
*Placer les deux certificats téléchargés à la racine du dossier '''ssl'''.&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Authorization Code''' et les placer dans le répertoire '''ssl/AuthCodeDemo'''. &lt;br /&gt;
*Modifier le fichier '''ssl/AuthCodeDemo/config.authcode.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;authorize_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/authorize.php&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;./ssl/AuthCodeDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;./ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;./ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Télécharger les deux certificats ''Certificat d'authentification'' et ''Certificat de signature'' du client '''Client Credentials''' et les placer dans le répertoire '''ssl/ClientCredDemo'''.&lt;br /&gt;
*Modifier le fichier '''ssl/ClientCredDemo/config.clientcred.json''' en le remplissant de la manière suivante.&lt;br /&gt;
&amp;lt;php&amp;gt;{&lt;br /&gt;
  &amp;quot;client_id&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;client_secret&amp;quot;: &amp;quot;XXXXXXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
  &amp;quot;token_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/access_token.php&amp;quot;,&lt;br /&gt;
  &amp;quot;resource_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/resources.php&amp;quot;,&lt;br /&gt;
  &amp;quot;revoke_uri&amp;quot;: &amp;quot;https://openflyers.com/mastructure/oauth/revoke.php&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cert&amp;quot;: &amp;quot;./ssl/ClientCredDemo/auth_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_key&amp;quot;: &amp;quot;./ssl/ClientCredDemo/auth.key&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert&amp;quot;: &amp;quot;./ssl/ClientCredDemo/sign_cert.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_key&amp;quot;: &amp;quot;./ssl/ClientCredDemo/sign.key&amp;quot;,&lt;br /&gt;
  &amp;quot;auth_cacert&amp;quot;: &amp;quot;./ssl/ca.crt&amp;quot;,&lt;br /&gt;
  &amp;quot;sign_cert_server&amp;quot;: &amp;quot;./ssl/sign_cert_server.crt&amp;quot;&lt;br /&gt;
}&amp;lt;/php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*Remplacer les &amp;lt;code&amp;gt;XXXXXXXXXXXXXXXX&amp;lt;/code&amp;gt; des champs &amp;lt;code&amp;gt;client_id&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;client_secret&amp;lt;/code&amp;gt; par les valeurs obtenues lors de [[#Enregistrer-un-client|l'enregistrement du client]].&lt;br /&gt;
*Remplacer &amp;lt;code&amp;gt;mastructure&amp;lt;/code&amp;gt; par le nom de la structure sur laquelle la démo est testée.&lt;br /&gt;
&lt;br /&gt;
*Transférer le fichier &amp;quot;oauth-demo&amp;quot; vers le serveur mutualisé :&lt;br /&gt;
**Télécharger [http://filezilla-project.org/download.php?type=client FileZilla].&lt;br /&gt;
**Lancer FileZilla.&lt;br /&gt;
**Entrer l'URl du serveur mutualisé dans le champ '''Hôte'''.&lt;br /&gt;
**Entrer le login dans le champ '''Nom d'utilisateur'''.&lt;br /&gt;
**Entrer le mot de passe dans le champ '''Mot de passe'''.&lt;br /&gt;
**Entrer le port dans le champ '''Port'''.&lt;br /&gt;
**Cliquer sur le bouton Connexion.&lt;br /&gt;
**Accéder à l'emplacement du répertoire &amp;quot;oauth-demo&amp;quot; en local à gauche dans l'onglet &amp;quot;Site local&amp;quot;.&lt;br /&gt;
**Choisir l'emplacement où placer le répértoire oauth-demo dans l'anglet '''Site distant''' à droite.&lt;br /&gt;
**Glisser et déposer le oauth-demo à l'emplacement choisi.&lt;br /&gt;
[[File:Transfer OauthDemo To Shared Server.png|800px]]&lt;br /&gt;
*Accéder au client OAuth-demo depuis le serveur mutualisé en utilisant l'URL du domaine du serveur : url_de_domaine_de_serveur/oauth-demo/index.php&lt;br /&gt;
*Modifier la valeur '''URI de redirection vers le client''' du client '''AuthCodeDemo''' précédemment créé en remplaçant l'ancienne URL par la nouvelle.&lt;br /&gt;
&lt;br /&gt;
*Suivre la [[#Utiliser le client|procédure d'utilisation du client de démonstration]] pour faire fonctionner le client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NB''': Le certificat de signature du serveur est unique à chaque plateforme et serveur. Ainsi, si le serveur ou la plateforme est modifié, le certificat doit être renouvelé.&lt;br /&gt;
&lt;br /&gt;
==Récupérer les données d'un utilisateur==&lt;br /&gt;
*Cliquer sur le bouton '''Récupérer les informations utilisateur''', l'identifiant de l'utilisateur s'affiche.&lt;br /&gt;
*Utiliser l'identifiant récupérer afin de récupérer toute information associée à cet utilisateur en [[Gestion-des-rapports#Ajouter-un-rapport|créant de nouveaux rapports personnalisés]]&lt;br /&gt;
&lt;br /&gt;
==Utiliser le client==&lt;br /&gt;
;Prérequis&lt;br /&gt;
Un client de démonstration est disponible pour le logiciel OpenFlyers à cette adresse : https://openflyers.com/oauth2-demo/index.php&lt;br /&gt;
&lt;br /&gt;
Le client de démonstration se présente de la manière suivante.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2-client-demo.png]]&lt;br /&gt;
&lt;br /&gt;
La démonstration est composée de deux colonnes. La première, nommée '''Authorization Code''' correspond [[#Authorization Code|au mécanisme d'autorisation du même nom]]. Elle dispose d'un bouton permettant de se connecter ainsi que d'une section indiquant les informations relatives à l'état de la connexion. La seconde colonne, nommée '''Client Credentials''' correspond elle aussi [[#Client Credentials|au mécanisme d'autorisation du même nom]]. Comme pour la première colonne, les éléments qui y sont présentés sont identiques. La différence étant que le bouton de connexion n'a pas le même effet étant donné que ces deux mécanismes sont différents. Chaque mécanisme est indépendant et il est possible de se connecter à un des deux mécanismes sans se connecter à l'autre ou se connecter aux deux en même temps.&lt;br /&gt;
&lt;br /&gt;
;Le mécanisme '''Authorization Code'''&lt;br /&gt;
*Cliquer sur le bouton '''Se connecter''' (ce qui redirige le navigateur vers la page de connexion du logiciel OpenFlyers).&lt;br /&gt;
*Renseigner les identifiants de l'administrateur pour s'y connecter.&lt;br /&gt;
*Nom d'utilisateur : '''admini'''.&lt;br /&gt;
*Mot de passe : '''azerty'''.&lt;br /&gt;
&lt;br /&gt;
Une fois les informations saisies, la page suivante est affichée.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth authorize demo.png]]&lt;br /&gt;
&lt;br /&gt;
*Cliquer sur le bouton '''Autoriser l'application''' pour autoriser la connexion (ce qui se redirige le navigateur vers la page du client de démonstration OAuth2).&lt;br /&gt;
&lt;br /&gt;
La première colonne doit afficher l'état de connexion '''Connecté''' ainsi qu'un nouveau bouton '''Récupèrer les informations utilisateurs''' qui permet de récupérer les informations de l'utilisateur connecté.&lt;br /&gt;
&lt;br /&gt;
;Le mécanisme '''Client Credentials'''&lt;br /&gt;
*Cliquer sur le bouton de connexion '''Se connecter''': contrairement à celui du mécanisme '''Authorization Code''', ne redirige pas le navigateur vers la page de connexion du logiciel OpenFlyers. Le bouton de connexion utilise les identifiants du client, ici le couple clé privée/clé publique, pour initier la connexion avec le serveur d'autorisation et obtenir un jeton d'accès.&lt;br /&gt;
&lt;br /&gt;
Une fois la connexion établie, la seconde colonne doit afficher l'état de connexion '''Connecté''' ainsi qu'un menu déroulant '''Rapport à récupèrer''' et un nouveau bouton '''Récupèrer le rapport''' qui permet de récupérer les rapports génériques et personnalisés.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Le client, une fois connecté sur les deux mécanismes, se présente de la manière suivante.&lt;br /&gt;
&lt;br /&gt;
[[File:Oauth2 connected demo.png]]&lt;br /&gt;
&lt;br /&gt;
=Troubleshooting=&lt;br /&gt;
==500 Internal Server Error en récupérant le rapport==&lt;br /&gt;
La démo utilise les valeurs par défaut pour extraire les rapports. Une erreur 500 indique une &amp;quot;Erreur de syntaxe ou violation d'accès&amp;quot; lors de l'exécution de la requête du rapport. Cela se produit parce que le rapport n'a pas de valeurs par défaut associées, étant donné qu'il n'a jamais été visualisé dans l'interface web. Pour résoudre ce problème, il vous suffit de visualiser le rapport et de cocher la case &amp;quot;Mémoriser ce choix&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Erreur &amp;quot;File not found.&amp;quot;==&lt;br /&gt;
Cette erreur se produit lorsque l'URI utilisé n'existe pas sur le serveur OpenFlyers. Vérifier les URIs mis en place dans les fichiers de configuration et essayer de nouveau.&lt;br /&gt;
&lt;br /&gt;
==int_rsa_verify : longueur de signature incorrecte==&lt;br /&gt;
Ce problème pourrait survenir si les fichiers ca.cert et sign_cert_server.cert ne proviennent pas du même serveur que celui du client oauth2.&lt;br /&gt;
La solution est :&lt;br /&gt;
&lt;br /&gt;
*D'essayer depuis le début l'étape de [[#Générer-des-certificats|génération]] et de [[#Enregistrer-un-client|configuration des certificats]] avec jsut la modification du client existant.&lt;br /&gt;
&lt;br /&gt;
;Si cela ne fonctionne pas:&lt;br /&gt;
&lt;br /&gt;
*Essayez de créer [[#Enregistrer-un-client|un nouveau client]] et refaites la configuration des certificats.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=AERAL&amp;diff=12875</id>
		<title>AERAL</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=AERAL&amp;diff=12875"/>
		<updated>2024-10-02T17:27:46Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;Fichier:&amp;quot; to &amp;quot;File:&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de décrire le module OpenFlyers permettant de paramétrer et générer les statistiques Aeral (Acquisition et Exploitation des Rapports d'activités de l'Aviation Légère) requises par la DGAC pour les associations aéronautiques et qui se concrétise au travers du remplissage d'un formulaire dont la version PDF est disponible à cette adresse : https://www.formulaires.service-public.fr/gf/cerfa_12806.do .&lt;br /&gt;
&lt;br /&gt;
La DGAC préconise de ne pas remplir le formulaire PDF mais à la place le formulaire en ligne accessible à cette adresse : https://aeral.dg.aviation-civile.gouv.fr/WD220AWP/WD220Awp.exe/CONNECT/AERAL&lt;br /&gt;
&lt;br /&gt;
De son côté, la Fédération Française Aéronautique (FFA) propose un module qui permet de faciliter le remplissage des statistiques Aeral au travers de son outil SMILE. Une documentation concernant l'utilisation de ce module est disponible à cette adresse : https://faq.ffa-aero.fr/smile/docs/aeral/saisir-son-rapport-aeral-dans-smile/&lt;br /&gt;
&lt;br /&gt;
OpenFlyers s'interface avec le module SMILE de la FFA au travers d'un module de génération et d'envoi des statistiques Aeral. Ce module permet également d'automatiser l'envoi des données mensuelles vers SMILE FFA.&lt;br /&gt;
&lt;br /&gt;
==Chronologie des actions à effectuer sur OpenFlyers==&lt;br /&gt;
Lorsque la structure utilise la fonction de génération du rapport Aeral pour la première fois :&lt;br /&gt;
*Tenter de générer un premier rapport Aeral en allant dans '''Gestion &amp;gt; Rapports &amp;gt; Rapports spécifiques &amp;gt; Export Aeral'''&lt;br /&gt;
Si le robot OpenFlyers n'est pas en mesure de prédire l'ensemble des paramètres par défaut nécessaires à la génération du rapport, il renvoie vers le paramétrage. Sinon, il affiche les tableaux de statistiques.&lt;br /&gt;
&lt;br /&gt;
Dans tous les cas, '''ne pas tenir des données publiées lors de la première tentative et vérifier les paramètres''' :&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Structure &amp;gt; Paramétrage &amp;gt; Export Aeral'''&lt;br /&gt;
*Vérifier que les paramètres renseignés sont conformes à la configuration de la plateforme OpenFlyers en s'aidant des consignes et copies d'écrans publiées dans le chapitre [[#Admin-&amp;gt;-Structure-&amp;gt;-Paramétrage-&amp;gt;-Export-Aeral|Admin &amp;gt; Structure &amp;gt; Paramétrage &amp;gt; Export Aeral]] de cette page&lt;br /&gt;
&lt;br /&gt;
Si les paramètres ne sont pas définis ou sauvegardés, [[Alertes-de-configuration#Le-formulaire-de-configuration-de-l'export-aeral-n'a-pas-été-rempli-ou-sauvegardé|une alerte de configuration est affichée]].&lt;br /&gt;
&lt;br /&gt;
Une fois les paramètres définis :&lt;br /&gt;
*Retourner dans '''Gestion &amp;gt; Rapports &amp;gt; Rapports spécifiques &amp;gt; Export Aeral'''&lt;br /&gt;
*Vérifier l'année sélectionnée&lt;br /&gt;
*Cliquer sur le bouton '''Visualiser'''&lt;br /&gt;
*Vérifier la cohérence des statistiques générées&lt;br /&gt;
Une fois que les données sont considérées comme correctes, il faut recopier les données sur l'[https://aeral.dg.aviation-civile.gouv.fr/AERAL outil Aeral] '''sauf pour les aéro-clubs affiliés à la Fédération Française Aéronautique''' où cette dernière souhaite que les données remontent via son outil SMILE. Voir le chapitre suivant [[#Chronologie-des-actions-à-effectuer-sur-SMILE-FFA|Chronologie des actions à effectuer sur SMILE FFA]]&lt;br /&gt;
&lt;br /&gt;
==Chronologie des actions à effectuer sur SMILE FFA==&lt;br /&gt;
;Prérequis&lt;br /&gt;
*Avoir renseigné le '''Code FFA''' dans le formulaire [[#Coordonnées|Coordonnées]] présent dans '''Admin &amp;gt; Structure &amp;gt; Paramétrage &amp;gt; Export Aeral'''&lt;br /&gt;
*Avoir testé le code FFA de sorte à avoir le cadenas vert de verrouillé&lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
*Depuis '''Gestion &amp;gt; Rapports &amp;gt; Rapports spécifiques &amp;gt; Export Aeral''', une fois que la cohérence des statistiques générées a été vérifié, il faut :&lt;br /&gt;
*Cliquer sur le bouton '''Envoyer à SMILE'''&lt;br /&gt;
*[https://projet.ff-aero.fr/SMILE_II Aller sur SMILE AEROCLUB] et suivre la procédure suivante : https://faq.ffa-aero.fr/smile/docs/aeral/saisir-son-rapport-aeral-dans-smile/&lt;br /&gt;
*Il faut parcourir les onglets un par un de la gauche vers la droite en cliquant à chaque fois sur le bouton '''Nous avons reçu des données de votre logiciel de gestion d'Aeroclub OpenFlyers. Dates des données : fin 12/2022. CLIQUER ICI POUR CHARGER CES DONNEES AUTOMATIQUEMENT.''' puis cliquer sur le bouton '''Oui''' de la boite de dialogue demandant confirmation&lt;br /&gt;
*Une fois que tous les onglets ont été parcourus, les données importées et les vérifications effectuées, il faut cliquer sur le dernier onglet '''VALIDATION'''&lt;br /&gt;
Si les vérifications d'intégrité sont correctes sur SMILE, un pavé sur fond vert apparait avec 2 cases à cocher pour permettre l'envoi des données vers Aeral&lt;br /&gt;
&lt;br /&gt;
[[File:VALIDATION_SMILE.png|600px]]&lt;br /&gt;
&lt;br /&gt;
'''ATTENTION : il n'est possible d'envoyer les données qu'une seule fois depuis SMILE vers Aeral'''&lt;br /&gt;
&lt;br /&gt;
;Points d'attention&lt;br /&gt;
*les données ne remontent dans chaque formulaire SMILE qu'après avoir cliqué sur le bouton '''Nous avons reçu des données de votre logiciel de gestion d'Aeroclub OpenFlyers. Dates des données : fin 12/2022. CLIQUER ICI POUR CHARGER CES DONNEES AUTOMATIQUEMENT.'''&lt;br /&gt;
Il faut effectuer cette action pour CHAQUE onglet. Il est donc recommandé de parcourir les onglets de la gauche vers la droite.&lt;br /&gt;
*Il est possible d'exporter (pousser) les données depuis OpenFlyers vers SMILE FFA autant de fois qu'on le souhaite. Chaque nouvel envoi de données écrase l'envoi précédent effectué pour le même mois. Par contre, à chaque nouvel envoi, il faut cliquer sur le bouton d'import dans SMILE FFA pour chaque onglet du formulaire.&lt;br /&gt;
*A l'heure actuelle, SMILE récupère bien toutes les données OpenFlyers mais ne permet pas de les incorporer toutes. Ainsi il manque le bouton de synchronisation pour les onglets suivants :&lt;br /&gt;
**GENERAL : non souhaité par la FFA&lt;br /&gt;
**TERRAINS : prévu pour 2024&lt;br /&gt;
**BUREAU : à fiabiliser&lt;br /&gt;
**MATERIEL : prévu pour 2024&lt;br /&gt;
*Autant il est possible de pousser les données depuis OpenFlyers vers SMILE FFA autant de fois qu'on le souhaite, autant il n'est possible d'exporter de SMILE FFA vers Aeral qu'une seule fois. En cas d'erreur, il faut contacter la [https://www.ffa-aero.fr Fédération Française Aéronautique] pour déverrouiller le système et permettre d'effectuer un nouvel envoi.&lt;br /&gt;
&lt;br /&gt;
=Admin &amp;gt; Structure &amp;gt; Paramétrage &amp;gt; Export Aeral=&lt;br /&gt;
Pour accéder au paramétrage '''Export Aeral''', il faut disposer du droit [[Gestion-des-profils#Gestion-des-rapports|Gestion des rapports]].&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir générer les statistiques Aeral, il faut que toutes les questions du formulaire soient complétées. Ce dernier est pré-rempli automatiquement avec les données de la structure grâce à l'utilisation de [[#Prédictions|prédictions]] lors de la première tentative de génération des statistiques Aeral depuis [[#Gestion-&amp;gt;-Rapports-&amp;gt;-Rapports-spécifiques-&amp;gt;-Export-Aeral|Gestion &amp;gt; Rapports &amp;gt; Rapports spécifiques &amp;gt; Export Aeral]].&lt;br /&gt;
&lt;br /&gt;
Il est donc fortement recommandé de générer une première fois les statistiques '''AVANT''' d'éditer le contenu du paramétrage. En effet, une fois que les données de paramétrage des statistiques Aeral sont stockées, la prédiction est désactivée pour ne pas réinitialiser les valeurs enregistrées.&lt;br /&gt;
&lt;br /&gt;
Après une première génération des statistiques, le gestionnaire est invité à vérifier les paramètres pré-remplis du formulaire, à les corriger le cas échéant, et à renseigner manuellement les éléments restants.&lt;br /&gt;
&lt;br /&gt;
les données récupérées de ce formulaire affectent directement la manière dont le robot OpenFlyers traite les rapports. Si une donnée n'est pas présente dans le paramétrage de la structure, le gestionnaire doit sélectionner le choix '''Non applicable'''.&lt;br /&gt;
&lt;br /&gt;
==Coordonnées==&lt;br /&gt;
[[File:Aeral coordonnées.png|800px]]&lt;br /&gt;
&lt;br /&gt;
Pour les structures affiliées à la [https://www.ffa-aero.fr Fédération Française Aéronautique] :&lt;br /&gt;
*Renseigner '''Code FFA (10 chiffres sans espace et sans tiret)'''&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer''' en haut à droite&lt;br /&gt;
*Cliquer sur le bouton '''Valider le code FFA'''. Cela permet de tester le code FFA en envoyant les données des statistique AERAL à l'API SMILE FFA en mode de test.&lt;br /&gt;
Une fois que le code FFA est validé, le pictogramme du cadenas à droite passe vert/verrouillé&lt;br /&gt;
*Cliquer sur l'interrupteur '''Synchronisation Automatique SMILE FFA''' pour activer la synchronisation automatique les données AERAL vers le serveur SMILE de la FFA. L'interrupteur n'est activable que si le '''Code FFA''' est préalablement validé. Lorsque l'interrupteur est activé et [[#Admin-&amp;gt;-Structure-&amp;gt;-Paramétrage-&amp;gt;-Export-Aeral|le paramétrage Aeral]] est rempli et sauvegardé, les statistiques sont envoyées tous les 1er du mois à l'API SMILE FFA. Elles concernent la période du 1er janvier de l'année en cours au jour précédent la date d'envoi, sauf pour le 1er janvier où la période correspond à l'année précédente.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''NB''': Pour valider le code FFA, on click sur le bouton '''Valider le code FFA''':&lt;br /&gt;
*Si le code FFA est valide:&lt;br /&gt;
**Le champ de la saisie du code FFA sera verrouillé avec un cadenas qui passe en vert.&lt;br /&gt;
**L'interrupteur de la synchronisation automatique peut être activé.&lt;br /&gt;
**Le bouton '''Valider le code FFA''' disparaît ( le déverrouillage du Code FFA ne sera fait que par un admin interne d'OpenFlyers).&lt;br /&gt;
*Si le code FFA n'est pas valide:&lt;br /&gt;
**L'interrupteur de la synchronisation automatique devient désactivé.&lt;br /&gt;
**le champ de la saisie du code FFA sera déverrouillé avec un cadenas en rouge.&lt;br /&gt;
&lt;br /&gt;
*'''Département'''&lt;br /&gt;
*'''Région aéronautique'''&lt;br /&gt;
*'''Délégation régionale'''&lt;br /&gt;
*'''Date agrément DGAC'''&lt;br /&gt;
*'''Préfecture Agrément DGAC'''&lt;br /&gt;
*'''Numéro ATO'''&lt;br /&gt;
*'''Date d'obtention de l'ATO'''&lt;br /&gt;
*'''Numéro DTO'''&lt;br /&gt;
*'''Date d'obtention du DTO'''&lt;br /&gt;
*'''APE'''&lt;br /&gt;
&lt;br /&gt;
==Tarifs==&lt;br /&gt;
[[File:Aeral_ _Tarifs.png|800px]]&lt;br /&gt;
&lt;br /&gt;
*Droit d'entrée&lt;br /&gt;
*Cotisation&lt;br /&gt;
*Remise cotisation jeunes&lt;br /&gt;
*Tarif supplément instruction&lt;br /&gt;
&lt;br /&gt;
Les informations renseignées sont utilisées par le robot OpenFlyers pour générer le tableau [[#Tarifs|Tarifs]] du rapport Aeral.&lt;br /&gt;
&lt;br /&gt;
==Validité définissant la pratique d'une activité==&lt;br /&gt;
[[File:Aeral_ _Validité_définissant_la_pratique_d'une_activité.png|800px]]&lt;br /&gt;
&lt;br /&gt;
*Type de validité définissant un utilisateur &amp;quot;Avion&amp;quot;&lt;br /&gt;
*Type de validité définissant un utilisateur &amp;quot;Hélicoptère&amp;quot;&lt;br /&gt;
*Type de validité définissant un utilisateur &amp;quot;Planeur&amp;quot;&lt;br /&gt;
*Type de validité définissant un utilisateur &amp;quot;ULM classe 3 - 3 axes&amp;quot;&lt;br /&gt;
*Type de validité définissant un utilisateur &amp;quot;ULM classe 4 - autogire&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ces champs permettent à l'utilisateur de choisir le type de validité correspondant à chaque type d'activité.&lt;br /&gt;
&lt;br /&gt;
Les informations renseignées sont utilisées par le robot OpenFlyers pour générer le tableau ADHERENTS du rapport Aeral.&lt;br /&gt;
&lt;br /&gt;
==Correspondance validités / Brevets, licences ou qualifications==&lt;br /&gt;
[[File:Aeral_ _Correspondance_validités_Brevets_licences_ou_qualifications.png|800px]]&lt;br /&gt;
&lt;br /&gt;
*Activité Avion&lt;br /&gt;
**LAPL&lt;br /&gt;
**PPL&lt;br /&gt;
**CPL&lt;br /&gt;
**ATPL&lt;br /&gt;
**Qualif_Voltige&lt;br /&gt;
**Qualif_Montagne&lt;br /&gt;
**Qualif_Hydravion&lt;br /&gt;
**Qualif_IFR&lt;br /&gt;
**Qualif_VFR_Nuit&lt;br /&gt;
*Activité ULM&lt;br /&gt;
**Paramoteur&lt;br /&gt;
**Pendulaire&lt;br /&gt;
**Multiaxes&lt;br /&gt;
**Autogire&lt;br /&gt;
**Dirigeable&lt;br /&gt;
**Hélicoptère&lt;br /&gt;
*Activité Hélicoptère&lt;br /&gt;
**LAPL(H)&lt;br /&gt;
**PPL(H)&lt;br /&gt;
**CPL(H)&lt;br /&gt;
**ATPL(H)&lt;br /&gt;
*Activité Planeur&lt;br /&gt;
**VV/SPL/LAPL(S)&lt;br /&gt;
&lt;br /&gt;
Ces champs permettant l'utilisateur de choisir le type de validité correspondant à Brevets, licences ou qualifications pour chaque type d'activité.&lt;br /&gt;
&lt;br /&gt;
Les informations renseignées sont utilisées par le robot OpenFlyers pour générer le tableau FORMATIONS du rapport Aeral.&lt;br /&gt;
&lt;br /&gt;
==Validités correspondant à la cotisation de la structure==&lt;br /&gt;
[[File:Aeral_ _Validités_correspondant_à_la_cotisation_de_la_structure.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Les validités cochées dans cette partie sont utilisées par le robot OpenFlyers dans les tableaux [[#Adhérents-par-activité-X|Adhérents par activité X]] du rapport Aeral afin de déterminer les utilisateurs inscrits dans la structure durant l'année considérée.&lt;br /&gt;
&lt;br /&gt;
==Validité correspondant à la licence FFA==&lt;br /&gt;
Une liste déroulante comprenant tous les types de validités configurés pour obtenir la certification par l'API FFA.&lt;br /&gt;
&lt;br /&gt;
[[File:Aeral_ _Validité_correspondant_à_la_licence_FFA.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Si aucun type de validité n'est défini pour l'obtention de la certification via l'API FFA, le message d'erreur suivant sera affiché.&lt;br /&gt;
&lt;br /&gt;
[[File:Aeral_Validité_correspondant_à_la_licence_FFA_Warning.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
La validité cochée dans cette partie est utilisée par le robot OpenFlyers dans les tableaux [[#Adhérents-par-activité-X|Adhérents par activité X]] du rapport Aeral afin de déterminer les utilisateurs brevetés inscrits dans la structure durant l'année considérée.&lt;br /&gt;
&lt;br /&gt;
Voir le chapitre de non conformité [[#Ce-numéro-de-licence-FFA-n'a-pas-été-certifié-par-SMILE-et-ne-sera-donc-pas-pris-en-compte-lors-de-l'export|Ce numéro de licence FFA n'a pas été certifié par SMILE et ne sera donc pas pris en compte lors de l'export]] pour les explications sur ce message d'alerte.&lt;br /&gt;
&lt;br /&gt;
==Validités désignant les brevetés==&lt;br /&gt;
[[File:Aeral_ _Validités_désignant_les_brevetés.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Les validités sélectionnées dans ce champ permettent de définir les validités qui permettent de savoir une personne dispose d'un brevet ou non et donc par différence les personnes qui ne disposent d'aucun brevet sont considérées comme des élèves. Cette catégorisation des personnes est utilisée dans les rapports [[#Adhérents-par-activité-X|Adhérents par activité X]].&lt;br /&gt;
&lt;br /&gt;
==Activités pratiquées==&lt;br /&gt;
[[File:Aeral_ _Activités_pratiquées.png|200px]]&lt;br /&gt;
&lt;br /&gt;
Cocher les activités pratiquées par la structure.&lt;br /&gt;
&lt;br /&gt;
Les paramètres de cette partie sont utilisées par le robot OpenFlyers pour générer les tableaux [[#Activité-en-instruction-et-Activité-hors-instruction|Activité en instruction et Activité hors instruction]] ainsi que pour le tableau [[#Instructeurs|Instructeurs]] (pour la partie '''solo supervisé''') du rapport Aeral.&lt;br /&gt;
&lt;br /&gt;
==Correspondance activités / typologie des vols Aeral==&lt;br /&gt;
[[File:Aeral_ _Correspondance_activités_typologie_des_vols_Aeral.png|1200px]]&lt;br /&gt;
&lt;br /&gt;
*IFR&lt;br /&gt;
*VFR Nuit&lt;br /&gt;
*Nuit&lt;br /&gt;
*VFR jour navigation&lt;br /&gt;
*Navigation&lt;br /&gt;
*Montagne&lt;br /&gt;
*Voltige&lt;br /&gt;
*BIA&lt;br /&gt;
*Baptême de l'air&lt;br /&gt;
*Instruction&lt;br /&gt;
*Remorquage&lt;br /&gt;
*Treuillage&lt;br /&gt;
&lt;br /&gt;
Les informations renseignées sont utilisées par le robot OpenFlyers pour générer les tableau 'En_Instruction_Par_Activite pour la catégorie X' et 'Hors_Instruction_Par_Activite' du rapport Aeral.&lt;br /&gt;
&lt;br /&gt;
==Activité correspondant à Solo supervisé==&lt;br /&gt;
OpenFlyers recommande de ne pas saisir les vols solos supervisés avec l'instructeur en place droite mais de créer un champ spécifique pour renseigner le nom du superviseur. Le paramétrage correspondant est décrit dans le chapitre [[Gestion-des-activités#Paramétrage-des-vols-solos-supervisés|Paramétrage des vols solos supervisés]].&lt;br /&gt;
&lt;br /&gt;
*L'activité sélectionnée dans le champ autocomplète '''Solo Supervisé''' est utilisée par le robot OpenFlyers dans les tableaux 'En_Instruction_Par_Population pour la catégorie X' et 'En_Instruction_Par_Activite pour la catégorie X'  du rapport Aeral afin de déterminer les heures de vol en Solo Supervisé durant l'année considérée.&lt;br /&gt;
&lt;br /&gt;
[[File:Aeral_Instructeur_En_Place_Droite.png|1200px]]&lt;br /&gt;
*Si l'interrupteur '''instructeur en place droite''' est activé, les heures de vol en solo supervisé durant l'année considérée sont déterminées en fonction du fait qu'il y a un instructeur occupant la place droite et qui effectue un vol avec l'activité sélectionnée dans le champ '''Solo Supervisé'''.&lt;br /&gt;
&lt;br /&gt;
[[File:Aeral_Champ_Métier_Correspondant_Au_Superviseur.png|1200px]]&lt;br /&gt;
*Si l'interrupteur '''instructeur en place droite''' est désactivé, les heures de vol en solo supervisé durant l'année considérée sont déterminées en fonction du fait qu'il y a un superviseur qui effectue un vol avec l'activité sélectionnée dans le champ '''Solo Supervisé'''. Pour cela il faut renseigner le '''Champ métier correspondant au superviseur'''.&lt;br /&gt;
&lt;br /&gt;
==Matériels==&lt;br /&gt;
[[File:Aeral_ _Matériels.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Cocher le matériel dont dispose la structure.&lt;br /&gt;
&lt;br /&gt;
==Terrain==&lt;br /&gt;
[[File:Aeral_ _Terrain.png|800px]]&lt;br /&gt;
&lt;br /&gt;
Renseigner les informations concernant l'aérodrome utilisé.&lt;br /&gt;
&lt;br /&gt;
==Bureau==&lt;br /&gt;
[[File:Aeral_ _Bureau.png|800px]]&lt;br /&gt;
&lt;br /&gt;
Définir les personnelles exerçant les fonctions définies.&lt;br /&gt;
&lt;br /&gt;
==Personnel==&lt;br /&gt;
[[File:Aeral_ _Personnel.png|1600px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Renseigner les informatiques statistiques concernant le personnel.&lt;br /&gt;
&lt;br /&gt;
==Profil des adhérents non pilotes==&lt;br /&gt;
[[File:Aeral_ _Profil_des_adhérents_non_pilotes.png|300px]]&lt;br /&gt;
&lt;br /&gt;
Le profil sélectionné dans cette partie est utilisé par le robot OpenFlyers dans les tableaux [[#Adhérents-par-activité-X|Adhérents par activité X]] du rapport Aeral afin de déterminer les utilisateurs inscrits dans la structure qui rentrent la catégorie '''non pilotes'''.&lt;br /&gt;
&lt;br /&gt;
==Profil(s) désignant les instructeurs==&lt;br /&gt;
[[File:Aeral_ _Profil(s)_désignant_les_instructeurs.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Définir le profil permettant de désigner les utilisateurs instructeurs.&lt;br /&gt;
&lt;br /&gt;
Ce profil est utilisé par le robot OpenFlyers pour lister les utilisateurs dans le tableau [[#Instructeurs|Instructeurs]] du rapport Aeral.&lt;br /&gt;
&lt;br /&gt;
=Gestion &amp;gt; Rapports &amp;gt; Rapports spécifiques &amp;gt; Export Aeral=&lt;br /&gt;
Pour accéder au rapport '''Export Aeral''', il faut disposer du droit [[Gestion-des-profils#Voir-tous-les-rapports|Voir tous les rapports]] ou [[Gestion-des-profils#Gestion-des-rapports|Gestion des rapports]].&lt;br /&gt;
&lt;br /&gt;
Lors de la première tentative de génération d'un export Aeral, le robot OpenFlyers tente de devenir le paramétrage qui doit être mis en place. S'il arrive à renseigner l'ensemble des paramètres indispensables à la génération du rapport, alors il affiche les tableaux pour les statistiques Aeral. S'il n'est pas en mesure de prédire l'ensemble des paramètres par défaut nécessaires à la génération du rapport, il renvoie vers le [[#Admin-&amp;gt;-Structure-&amp;gt;-Paramétrage-&amp;gt;-Export-Aeral|paramétrage Aeral]].&lt;br /&gt;
&lt;br /&gt;
Avant de générer le bilan annuel, il faut s'assurer que toutes les informations sont renseignées, si ce n'est pas le cas alors le gestionnaire est redirigé vers le formulaire précédent.&lt;br /&gt;
&lt;br /&gt;
L'année affichée par défaut est :&lt;br /&gt;
*l'année précédente lorsque le mois actuel est compris entre le mois de janvier et le mois de mars inclus&lt;br /&gt;
*l'année actuelle dans le cas contraire&lt;br /&gt;
&lt;br /&gt;
La distinction entre '''jeunes''' et '''adultes''' dans les rapports se situe à :&lt;br /&gt;
*21 ans pour '''AVION'''.&lt;br /&gt;
*25 ans pour les autres catégories ('''ULM''', '''HELECOPTERE''' et '''PLANEUR''')&lt;br /&gt;
&lt;br /&gt;
Une personne est décomptée comme adulte dès lors que son année de naissance est supérieure ou égale à 21 ou 25 ans suivant la catégorie considérée.&lt;br /&gt;
&lt;br /&gt;
==Rapports issus de données de formulaire==&lt;br /&gt;
:* rapport Aeral ''' TERRAINS'''&lt;br /&gt;
:* rapport Aeral '''BUREAU'''&lt;br /&gt;
:* rapport Aeral '''PERSONNEL'''&lt;br /&gt;
:* rapport Aeral '''MATERIEL'''&lt;br /&gt;
&lt;br /&gt;
==Adhérents par activité X==&lt;br /&gt;
Ce rapport regroupe 4 tableaux qui correspondent chacun à un type d'activité :&lt;br /&gt;
*Avion&lt;br /&gt;
*Hélicoptère&lt;br /&gt;
*ULM&lt;br /&gt;
*Planeur&lt;br /&gt;
&lt;br /&gt;
Pour qu'un pratiquant soit pris en compte dans le recensement, il faut :&lt;br /&gt;
*Qu'il détienne au moins l'une des validités [[#Validités-correspondant-à-la-cotisation-de-la-structure|Validités correspondant à la cotisation de la structure]] et dont la date d'échéance doit être supérieure ou égale au 31/12 de l'année des statistiques.&lt;br /&gt;
*Qu'il dispose d'une date de naissance (cela permet d'exclure les utilisateurs qui ne correspondent pas à des utilisateurs réels en leur mettant une date de naissance vide)&lt;br /&gt;
&lt;br /&gt;
Pour chaque type d'activité, le robot OpenFlyers détermine les pratiquants en prenant en compte au moins l'un des éléments suivants :&lt;br /&gt;
*La pratique effective durant l'année sur un type d'aéronef correspondant au type d'activité&lt;br /&gt;
*La détention par un utilisateur d'une validité le définissant comme pratiquant de l'activité&lt;br /&gt;
&lt;br /&gt;
Le robot OpenFlyers prend en compte les utilisateurs désactivés.&lt;br /&gt;
&lt;br /&gt;
Une fois calculé le nombre de pratiquants, le robot OpenFlyers détermine le nombre de brevetés parmi ces pratiquants. Est considéré comme breveté un utilisateur qui dispose de l'une des validités sélectionnées dans le paramétrage [[#Validités-désignant-les-brevetés|Validités désignant les brevetés]], peu importe que la validité soit à jour ou non. Cela permet de déterminer, par soustraction, les personnes qui sont élèves. Dis autrement : est élève une personne qui ne possède pas une validité répertoriée comme étant une validité de type &amp;quot;brevet&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
La figure suivante résume l'approche adoptée pour générer les statistiques liées à ce rapport :&lt;br /&gt;
&lt;br /&gt;
[[File:Aeral_statistic_members_by_activity_schema_algorithm.png|800px]]&lt;br /&gt;
&lt;br /&gt;
==Instructeurs==&lt;br /&gt;
Pour calculer les heures de vol de chaque instructeur, il y a 2 façons possibles :&lt;br /&gt;
*Première méthode : Lorsqu'il n'y a pas de type d'activité de sélectionné dans le champ '''Activité correspondant à Solo supervisé''', le robot OpenFlyers détermine le total des heures de vol de l'instructeur en place droite, puis le total des heures de vols en place droite de l'instructeur pour lesquelles il y a le type d'activité sélectionné pour le paramètre '''Instruction'''&lt;br /&gt;
:'''Heures totales = total des heures en place droite '''&lt;br /&gt;
:'''Heures doubles = total des heures  en place droite avec le type d'activité correspondant à instruction'''&lt;br /&gt;
:'''Heures solo supervisé = Heures totales - Heures doubles'''&lt;br /&gt;
*Deuxième méthode : si le type d'activité solo supervisé est coché pour l'instructeur, dans ce cas on détermine le total des heures en solo supervisé comme étant la somme des heures de vols de l'instructeur pour lesquelles il y a comme type d'activité celle correspondant au paramètre '''Activité correspondant à Solo supervisé'''.&lt;br /&gt;
:'''Heures totales = total des heures en place droite avec le type d'activité correspondant à instruction'''&lt;br /&gt;
:'''Heures solo supervisé = total des heures en place droite avec le type d'activité correspondant à solo supervisé'''&lt;br /&gt;
:'''Heures doubles = Heures totales - Heures solo supervisé'''&lt;br /&gt;
&lt;br /&gt;
Voir le chapitre de non conformité [[#Ce-numéro-de-licence-FFA-n'a-pas-été-certifié-par-SMILE-et-ne-sera-donc-pas-pris-en-compte-lors-de-l'export|Ce numéro de licence FFA n'a pas été certifié par SMILE et ne sera donc pas pris en compte lors de l'export]] pour les explications sur ce message d'alerte.&lt;br /&gt;
&lt;br /&gt;
==Activité en instruction et Activité hors instruction==&lt;br /&gt;
&lt;br /&gt;
pour ces deux rapport aeral nous utilisons la même stratégie qui est définie ci-dessous, pour différencier entre ces deux types d'activité on se base sur la place du pilote : &lt;br /&gt;
&lt;br /&gt;
-En instruction place de pilote = 1.&lt;br /&gt;
&lt;br /&gt;
-Hors instruction place de pilote = 0.&lt;br /&gt;
&lt;br /&gt;
===Activité en instruction / Activité hors instruction pour les catégories AVION et HELECOPTERE===&lt;br /&gt;
&lt;br /&gt;
La stratégie retenue pour générer ces rapports Aeral a été de commencer par identifier les variables fiables qui sont présentes chez toutes les structures&lt;br /&gt;
(navigation, IFR, Nuit),qui sont récupérées soit à partir du [[#Admin &amp;gt; Structure &amp;gt; Paramétrage &amp;gt; Export Aeral| formulaire]], soit grâce à l'utilisation de [[#Types d'activités|prédictions sur les types d'activités]], et à partir desquelles on calcule le nombre d'heures de vol pour les autres types d'activité. &lt;br /&gt;
&lt;br /&gt;
[[File:Aeral_activity_types_partition_schema.png|650px]]&lt;br /&gt;
&lt;br /&gt;
Les données les plus fiables sont celles qui sont les plus spécifiques, par exemple, pour obtenir la valeur de VFR nuit si ce type d’activité n'est pas présente dans la structure alors on considère que le type d’activité nuit est le plus spécifique et donc il correspond à la donnée la plus fiable pour calculer ce type d’activité.&lt;br /&gt;
&lt;br /&gt;
Le calcul des heures de vol pour les différents types d'activité se fait en suivant les étapes suivantes:&lt;br /&gt;
:* On commence par l’obtention  des heures de vol total de toutes les activités confondues par une requête sql.&lt;br /&gt;
:* Ensuite, les heures de vol de chaque type d'activité sont calculées en fonction des données fournies par le gestionnaire dans le [[#Admin &amp;gt; Structure &amp;gt; Paramétrage &amp;gt; Export Aeral| formulaire]].&lt;br /&gt;
&lt;br /&gt;
La figure suivante représente le schéma de l'algorithme utilisé par le robot OpenFlyers pour calculer les heures de vol en fonction des données présente dans la structure :&lt;br /&gt;
&lt;br /&gt;
[[File:Aeral_statistic_activity_schema_algorithm.png|650px]]&lt;br /&gt;
&lt;br /&gt;
:*'''Exemple''':&lt;br /&gt;
on prend l'exemple suivant dans lequel la structure ne possède que les types d'activités suivants: IFR, NUIT et Navigation &lt;br /&gt;
&lt;br /&gt;
on commence par l'obtention le '''total des heures de vol''' : 2430&lt;br /&gt;
&lt;br /&gt;
ensuite on obtient le total '''IFR''' :  1000&lt;br /&gt;
&lt;br /&gt;
puisque le type d'activité VFR nuit n'est pas présent dans la structure:&lt;br /&gt;
&lt;br /&gt;
on commence par exécuter deux requête la première sur le type d'activité nuit et l'autre sur les deux types d'activité ifr et nuit on obtient par exemple:&lt;br /&gt;
&lt;br /&gt;
'''Nuit''' = 1200 &lt;br /&gt;
&lt;br /&gt;
'''IFR nuit''' = 400&lt;br /&gt;
&lt;br /&gt;
ce que nous aide à calculer la valeur de VFR Nuit(voir la relation dans la figure ci-dessus) &lt;br /&gt;
&lt;br /&gt;
'''VFR Nuit''': 1200 - 400 = 800.&lt;br /&gt;
&lt;br /&gt;
pour calculer VFR jour navigation:&lt;br /&gt;
&lt;br /&gt;
on commence par calculer navigation jour, pour cela on obtient la valeur de navigation = 700 et la valeur de navigation nuit = 300 à partir de la base de données, et donc &lt;br /&gt;
'''Navigation jour'''  = 700 - 300 = 400,&lt;br /&gt;
&lt;br /&gt;
ensuite de la même manière on obtient IFR Navigation = 330 et IFR navigation nuit = 200, pour calculer '''IFR navigation jour''' = 330 - 200 = 130.&lt;br /&gt;
&lt;br /&gt;
et en utilisant la relation défini dans figure ci-dessus, on calcule '''VFR jour navigation''' = 400 - 130 = 270.&lt;br /&gt;
&lt;br /&gt;
à la fin on déduit la valeur de VFR jour local en suivant les étapes suivants :&lt;br /&gt;
&lt;br /&gt;
*:On calcule tout d'abord les heures de vol de '''VFR jour''' = VFR - VFR nuit = 1430 - 800.&lt;br /&gt;
 &lt;br /&gt;
avec '''VFR''' = Total - IFR = 2430 - 1000  = 1430.&lt;br /&gt;
&lt;br /&gt;
*:ensuite on déduit la valeur de '''VFR Jour local''' = VFR jour - VFR jour navigation = 630 - 270 = 360&lt;br /&gt;
&lt;br /&gt;
===Activité en instruction / Activité hors instruction pour la catégorie ULM===&lt;br /&gt;
Pour générer les statistiques liée à ces rapports il faut prendre en compte que chaque vol de la catégorie ULM peut être classée selon la catégorie de la ressource, mais pour le moment les clients d'OpenFlyers utilisent deux catégories ULM qui sont: '''ULM classe 3 - 3 axes''' et '''ULM classe 4 - autogire'''.&lt;br /&gt;
&lt;br /&gt;
Pour résoudre ce problème on a calculé que les heures totales des vols, les heures de vols pour la catégorie de ressource '''ULM 3 axes''' (Heures_Multiaxes) et les heures de vols pour la catégorie de ressource '''ULM classe 4 - autogire''' (Heures_Autogire). Cependant on a transmis des zéros pour les autres catégories des ressources (Heures_Paramoteur, Heures_Pendulaire,  Heures_Dirigeable, Heures_Helicoptere et Heures_Dont_Vol_BIA).&lt;br /&gt;
&lt;br /&gt;
NB. Si l'un des clients a des catégories de ressources autres que ULM 3 axes et ULM classe 4 - autogire, il faudra ajouter les requêtes de génération des heures de vol pour chacune de ces catégories de ressource.&lt;br /&gt;
&lt;br /&gt;
===Activité en instruction / Activité hors instruction pour la catégorie PLANEUR===&lt;br /&gt;
[[File:Gliding_Activity_Categorization_Diagram.png|650px]]&lt;br /&gt;
&lt;br /&gt;
La stratégie adoptée pour générer ces rapports Aeral repose sur la prise en compte de divers aspects :&lt;br /&gt;
&lt;br /&gt;
*Extraire les heures totales de vol pour l'activité planeur, quelle que soit sa catégorie (en instruction, hors instruction, autres).&lt;br /&gt;
*Extraire les heures de vol étrangères spécifiquement pour l'activité planeur (Nationalité non française).&lt;br /&gt;
*Extraire les heures de vol des remorqueurs dans le cadre de l'activité planeur.&lt;br /&gt;
*Extraire les heures de vol en fonction du sexe pour la catégorie en instruction planeur.&lt;br /&gt;
*Extraire les heures de vol en fonction du sexe pour la catégorie hors instruction planeur.&lt;br /&gt;
*Extraire les heures de vol hors instruction destiné aux personnes françaises (Jeunes/Adultes) (total des heures, heures avec BIA, heures de vol de découverte).&lt;br /&gt;
*Extraire le nombre de vols hors instruction destiné aux personnes françaises (Jeunes/Adultes) selon le type d'activité (Remorqués, Treuillés, Lâchers solo, BPP Théorique, BPP Homologués).&lt;br /&gt;
&lt;br /&gt;
==Mouvements==&lt;br /&gt;
Pour calculer les mouvements sur la plateforme en comptant simplement les atterrissages des vols locaux.&lt;br /&gt;
&lt;br /&gt;
Sachant que 1 décollage ou 1 atterrissage ou 1 touch and go= 1 mouvement.&lt;br /&gt;
&lt;br /&gt;
mouvements locaux = total atterrissages vol locaux * 2&lt;br /&gt;
&lt;br /&gt;
==Tarifs==&lt;br /&gt;
ce rapport aeral consiste à renseigner les droits d'entrée, cotisation non pilote et cotisation Club pour les deux tranches d'age (Jeunes et Adultes).&lt;br /&gt;
&lt;br /&gt;
pour cela, les valeurs du droit d'entrée et de la cotisation non pilote sont directement attribuées pour les deux tranches d'age, en se basant sur les variables renseignées dans la [[#Admin &amp;gt; Structure &amp;gt; Paramétrage &amp;gt; Export Aeral| formulaire]] ou trouvées grâce à l'utilisation de [[#Prédictions|prédictions]].&lt;br /&gt;
&lt;br /&gt;
pour Cotisation Club on récupère la valeur ADULTES_Cotisation_Club directement à partir de la variable Cotisation.&lt;br /&gt;
&lt;br /&gt;
et on déduit '''Jeunes_Cotisation_Club = ADULTES_Cotisation_Club - remise Cotisation jeunes'''&lt;br /&gt;
&lt;br /&gt;
==Terrains==&lt;br /&gt;
&lt;br /&gt;
==Bureau==&lt;br /&gt;
Voir le chapitre de non conformité [[#Ce-numéro-de-licence-FFA-n'a-pas-été-certifié-par-SMILE-et-ne-sera-donc-pas-pris-en-compte-lors-de-l'export|Ce numéro de licence FFA n'a pas été certifié par SMILE et ne sera donc pas pris en compte lors de l'export]] pour les explications sur ce message d'alerte.&lt;br /&gt;
&lt;br /&gt;
==Aéronefs==&lt;br /&gt;
Ce tableau liste toutes les ressources de catégorie aéronefs (Avion, ULM, Hélicoptère, Planeur) :&lt;br /&gt;
*actives pour lesquelles l'option '''Saisie d'activité''' est cochée dans le paramétrage&lt;br /&gt;
*qui ont effectué au moins un vol dans l'année considérée&lt;br /&gt;
Le tableau contient les colonnes suivantes :&lt;br /&gt;
*Immatriculation qui correspond au nom de l'aéronef&lt;br /&gt;
*Modèle qui correspond au nom du type de ressource correspond&lt;br /&gt;
*Heures_Cette_Annee correspond au total des heures de vols effectuées par l'aéronef&lt;br /&gt;
*Heures_dont_en_Double correspond aux heures de vols pour lesquelles il y a 2 utilisateurs : 1 en place gauche et 1 en place droite.&lt;br /&gt;
*Heures_dont_en_Solo correspond à la différence de Heures_Cette_Annee et Heures_dont_en_Double.&lt;br /&gt;
*Tarif_Solo dont la valeur provient de la variable ayant pour nom &amp;quot;$tarifSolo + le nom du type d'aéronef&amp;quot;.&lt;br /&gt;
*Tarif_Double dont la valeur provient de la variable ayant pour nom &amp;quot;$tarifSolo + le nom du type d'aéronef&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Liste détaillée des personnes liée pour chaque nombre d'adhérents==&lt;br /&gt;
&lt;br /&gt;
Dans l'affichage des statistiques AERAL, pour les tableaux ADHERENTS PAR ACTIVITE X (avec X est une des catégories: AVION, HELICOPTERE, PLANEUR et ULM) et FORMATIONS, on associe pour chaque nombre de personnes différent de 0 un lien vers un nouvel onglet qui contient la table détaillée des personnes , cette dernière contient les informations suivantes :&lt;br /&gt;
*Nom&lt;br /&gt;
*Prénom&lt;br /&gt;
*Sexe&lt;br /&gt;
*Date de naissance&lt;br /&gt;
*Année de naissance	&lt;br /&gt;
*Génération&lt;br /&gt;
*Colonne dynamique pour chaque type de validité cochées en cas des '''Brevetes''': cette colonne contient une icône checked verte + la date d'obtention si la personne a la validité, sinon elle est vide&lt;br /&gt;
&lt;br /&gt;
=Prédictions=&lt;br /&gt;
Le principe de prédictions consiste à essayer de retrouver les paramètres nécessaires au remplissage du formulaire de statistiques AERAL en recherchant dans la base de données des mots clés spécifiques pour chaque référence.&lt;br /&gt;
&lt;br /&gt;
Liste des prédictions utilisées par le robot OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
==Tarifs==&lt;br /&gt;
===Tarif cotisation===&lt;br /&gt;
Le robot OpenFlyers cherche dans la liste des variables '''Admin &amp;gt; Ventes &amp;gt; Variables &amp;gt; Définition''' les occurrences :&lt;br /&gt;
#'''cotisation'''&lt;br /&gt;
#'''cotisation club'''&lt;br /&gt;
#'''cotisation &amp;lt;nom de la structure&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
===Tarif droit d'entrée===&lt;br /&gt;
Le robot OpenFlyers cherche dans la liste des variables '''Admin &amp;gt; Ventes &amp;gt; Variables &amp;gt; Définition''' les occurrences :&lt;br /&gt;
#'''Droit d'entrée'''&lt;br /&gt;
#'''Tarif entrée'''&lt;br /&gt;
&lt;br /&gt;
===Tarif instruction===&lt;br /&gt;
Le robot OpenFlyers cherche dans la liste des variables '''Admin &amp;gt; Ventes &amp;gt; Variables &amp;gt; Définition''' les occurrences :&lt;br /&gt;
#'''Tarif instruction'''&lt;br /&gt;
&lt;br /&gt;
===Remise cotisation jeune===&lt;br /&gt;
Le robot OpenFlyers cherche dans la liste des variables '''Admin &amp;gt; Ventes &amp;gt; Variables &amp;gt; Définition''' les occurrences :&lt;br /&gt;
#'''Remise cotisation jeune'''&lt;br /&gt;
&lt;br /&gt;
==Qualifications==&lt;br /&gt;
Le robot OpenFlyers cherche dans la liste des variables '''Admin &amp;gt; Ventes &amp;gt; Variables &amp;gt; Définition''' les occurrences :&lt;br /&gt;
#'''PPL'''&lt;br /&gt;
#'''Brevet de base'''&lt;br /&gt;
#'''CPL'''&lt;br /&gt;
#'''ATPL'''&lt;br /&gt;
#'''Brevet ULM'''&lt;br /&gt;
&lt;br /&gt;
==Profils==&lt;br /&gt;
===Non Pilotes===&lt;br /&gt;
Le robot OpenFlyers cherche dans la liste des profils '''Admin &amp;gt; Utilisateur &amp;gt; Profils''' les occurrences :&lt;br /&gt;
#'''Honoraire'''&lt;br /&gt;
#'''Non pilote'''&lt;br /&gt;
&lt;br /&gt;
===Instructeurs===&lt;br /&gt;
Le robot OpenFlyers cherche dans la liste des profils '''Admin &amp;gt; Utilisateur &amp;gt; Profils &amp;gt; Réservations''' les profils qui ont les deux droits suivants:&lt;br /&gt;
#'''Planning personnel'''&lt;br /&gt;
#'''Planning individuel visible pour les autres'''&lt;br /&gt;
&lt;br /&gt;
==Types d'activités==&lt;br /&gt;
Le robot OpenFlyers cherche dans la liste des variables '''Admin &amp;gt; Ventes &amp;gt; Variables &amp;gt; Définition''' des occurrences spécifiques pour chaque type d'activité :&lt;br /&gt;
&lt;br /&gt;
IFR :&lt;br /&gt;
#'''IFR'''&lt;br /&gt;
#'''IFR-FR'''&lt;br /&gt;
&lt;br /&gt;
Instruction :&lt;br /&gt;
#'''Instruction'''&lt;br /&gt;
#'''Double commande'''&lt;br /&gt;
&lt;br /&gt;
Navigation :&lt;br /&gt;
#'''Navigation'''&lt;br /&gt;
&lt;br /&gt;
Nuit :&lt;br /&gt;
#'''Nuit'''&lt;br /&gt;
#'''Vol de nuit'''&lt;br /&gt;
&lt;br /&gt;
VFR jour navigation :&lt;br /&gt;
#'''VFR jour navigation'''&lt;br /&gt;
&lt;br /&gt;
VFR nuit :&lt;br /&gt;
#'''VFR nuit'''&lt;br /&gt;
&lt;br /&gt;
Solo supervisé :&lt;br /&gt;
# '''Solo supervisé'''&lt;br /&gt;
&lt;br /&gt;
=Non-conformités=&lt;br /&gt;
==Ce numéro de licence FFA n'a pas été certifié par SMILE et ne sera donc pas pris en compte lors de l'export==&lt;br /&gt;
Si la validité correspondant à la licence FFA n'est pas spécifiée ou si les numéros de licence FFA dans les tableaux [[#Bureau_2|BUREAU]] et [[#Instructeurs|INSTRUCTEURS]] n'ont pas été validés par l'API FFA, ces licences seront signalées en rouge avec le message d'erreur '''Ce numéro de licence FFA n'a pas été certifié par SMILE et ne sera donc pas pris en compte lors de l'export''' en bas du tableau, et le JSON envoyé à SMILE ne les inclura pas.&lt;br /&gt;
&lt;br /&gt;
Pour corriger cette non-conformité, il est nécessaire que la validité associée à la licence FFA soit configurée pour être certifiée via l'API FFA dès que toute la colonne 'Numero_Licence_FFA' est signalée en rouge. Pour les numéros de licence FFA affichés en rouge, la certification par l'API FFA est impérative. En guise de solution, il est envisageable de forcer la certification par l'API FFA en naviguant vers Gestion &amp;gt; Utilisateurs &amp;gt; Validités.&lt;br /&gt;
&lt;br /&gt;
==Heures de vol pour les utilisateurs ayant le sexe '''Indéfini'''==&lt;br /&gt;
Dans les blocs Activité en instruction ET Activité hors instruction, s'il y a des heures de vol liées au sexe indéfini, nous ajoutons des lignes supplémentaires où nous stockons les heures sans celles du sexe indéfini.&lt;br /&gt;
&lt;br /&gt;
Pour corriger cette non-conformité, le bon sexe (M/F) doit être renseigné pour les utilisateurs ayant des vols enregistrés.&lt;br /&gt;
&lt;br /&gt;
==Numéro de licence FFA non renseigné==&lt;br /&gt;
Dans les blocs INSTRUCTEURS et BUREAU, si l'utilisateur n'a pas le Numéro de licence FFA la case s'affiche en rouge pour indiqué la nécessité de renseigner les numéros de licence FFA pour faire la correspondance côté SMILE FFA.&lt;br /&gt;
&lt;br /&gt;
Pour corriger cette non-conformité, le bon Numéro de licence FFA doit être renseigné pour le personnel de BUREAU et les instructeurs.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Interfa%C3%A7age-OpenFlyers-et-Teltonika&amp;diff=12874</id>
		<title>Interfaçage OpenFlyers et Teltonika</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Interfa%C3%A7age-OpenFlyers-et-Teltonika&amp;diff=12874"/>
		<updated>2024-10-02T17:27:08Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter l'interfaçage d'OpenFlyers avec les boitiers [https://teltonika-networks.com/ Teltonika].&lt;br /&gt;
&lt;br /&gt;
;Trackers testés par OpenFlyers&lt;br /&gt;
*[https://wiki.teltonika-gps.com/view/FMC125 Teltonika FMC 125]&lt;br /&gt;
*[https://wiki.teltonika-gps.com/view/FMC130 Teltonika FMC 130] comporte des entrées supplémentaires&lt;br /&gt;
&lt;br /&gt;
Ce sont des modèles 4G multi-systèmes satellitaires (GPS, GLONASS et Galileo).&lt;br /&gt;
&lt;br /&gt;
;Certificats&lt;br /&gt;
*https://wiki.teltonika-gps.com/view/FMC125_Certification_%26_Approvals&lt;br /&gt;
*https://wiki.teltonika-gps.com/view/FMC130_Certification_%26_Approvals&lt;br /&gt;
&lt;br /&gt;
;Compatibilité avec l'aéronautique&lt;br /&gt;
*Pour les ULMs, il n'y a pas de réglementation particulière&lt;br /&gt;
*Pour les aéronefs certifiés ELA2 (aéronef léger européen dont la masse maximale au décollage ne dépasse pas 2 tonnes), la réglementation EASA [https://www.easa.europa.eu/en/document-library/certification-specifications/cs-stan-issue-4 CS-STAN version 4], chapitre &amp;quot;Standard Change CS-SC106b&amp;quot; (installation of flight-time recorders), impose que les appareils installés à demeure sur l'aéronef ne dépassent pas une puissance d'émission de 100mW dès lors que l'aéronef est en mouvement. La documentation de certification Teltonika indique une puissance d'émission de 26,05dBm soit 402mW.&lt;br /&gt;
&lt;br /&gt;
Il existe à l'heure actuelle 2 solutions :&lt;br /&gt;
*Rajouter au boitier Teltonika un boitier d'alimentation autonome disposant de sa propre batterie (solution testée par OpenFlyers)&lt;br /&gt;
*Rajouter au boitier Teltonika un boitier d'interfaçage à une alimentation standardisée et installer sur l'aéronef ce type d'alimentation permettant au boitier de ne pas être considéré comme fixé sur l'appareil (solution non testée par OpenFlyers)&lt;br /&gt;
&lt;br /&gt;
OpenFlyers est ouvert à toute solution alternative qui n'émettrait pas durant le déplacement de l'aéronef et a sollicité Teltonika dans ce sens.&lt;br /&gt;
&lt;br /&gt;
;Paramétrage et installation&lt;br /&gt;
*Paramétrer le boitier pour qu'il envoie les données sur le serveur de réception des données OpenFlyers prévu à cet effet&lt;br /&gt;
*Équiper le boitier avec une carte SIM pour l'envoi des données&lt;br /&gt;
*Brancher le boitier sur la batterie via une connectique amovible de l'aéronef ou de façon autonome&lt;br /&gt;
&lt;br /&gt;
Pour la carte SIM, il existe une multitude de solutions. Ces prestataires fournissent une carte SIM avec un abonnement de type &amp;quot;Internet des Objets&amp;quot; (IoT &amp;quot;Internet of Things&amp;quot;) en anglais) permettant de ne faire que du transfert de données et qui est multi-opérateurs. A noter, que le tracker prend le meilleur des réseaux disponibles.&lt;br /&gt;
&lt;br /&gt;
;Exemples de fournisseurs de cartes SIM&lt;br /&gt;
*[https://www.korewireless.com/super-sim-card Kore Super SIM] a un cout de $2 par mois et le coût des data est de $0,10 par Mo&lt;br /&gt;
*[https://www.thingsmobile.com/fr/private/solutions/carte-sim-gps-tracker Things Mobile &amp;quot;Carte SIM pour GPS Tracker&amp;quot;] a un coût de 0,12 €/Mo&lt;br /&gt;
&lt;br /&gt;
=Variables pour les formules de calcul=&lt;br /&gt;
Les variables suivantes sont utilisables dans les formules :&lt;br /&gt;
&lt;br /&gt;
*TELTONIKA_ENGINE_START : Datetime de décollage&lt;br /&gt;
*TELTONIKA_OFFBLOCK_DATE : Datetime de départ bloc&lt;br /&gt;
*TELTONIKA_ONBLOCK_DATE : Datetime de bloc arrivée&lt;br /&gt;
*TELTONIKA_ENGINE_STOP : Datetime d'atterrissage&lt;br /&gt;
Ces variables sont directement transmises par Teltonika.&lt;br /&gt;
&lt;br /&gt;
Les fonctions suivantes peuvent être utilisées dans les formules pour le [[Configuration#Gestion-de-Teltonika|paramétrage de Teltonika]] :&lt;br /&gt;
*[[Formules-de-calcul#formatDate('patron',-'date')|formatDate]] : Permet de formater une date&lt;br /&gt;
*[[Formules-de-calcul#roundCeil(X,Y)|roundCeil]] : Arrondi à la minute supérieure la date transmise en paramètre&lt;br /&gt;
*[[Formules-de-calcul#roundFloor(X,Y)|roundFloor]] : Arrondi à la minute inférieure la date transmise en paramètre&lt;br /&gt;
*[[Formules-de-calcul#strtotime(string)|strtotime]] : Transforme une date en timestamp&lt;br /&gt;
&lt;br /&gt;
=Procédure=&lt;br /&gt;
==Configurer le tracker==&lt;br /&gt;
;Prérequis&lt;br /&gt;
*Avoir [[#Initialiser-le-tracker|initialisé le tracker]]&lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
Pour paramétrer le tracker il faut le connecter avec un PC. &lt;br /&gt;
*Il faut ouvrir le boitier du tracker et connecter un câble micro USB&lt;br /&gt;
&lt;br /&gt;
[[File:Connexion_pour_configuration.jpg|File:Connexion_pour_configuration.jpg]]&lt;br /&gt;
&lt;br /&gt;
*Aller sur le site de Teltonika pour télécharger la dernière version du [https://wiki.teltonika-gps.com/view/Teltonika_Configurator_versions programme de configuration]&lt;br /&gt;
*Reconnecter le tracker sur son bloc d’alimentation et le mettre sous tension&lt;br /&gt;
*Lancer le programme Teltonika Configurator, la page d’accueil doit détecter automatiquement le tracker connecté.&lt;br /&gt;
*Double-cliquer sur le device détecté&lt;br /&gt;
&lt;br /&gt;
[[File:Menu_Teltonika.JPG|File:Menu_Teltonika.JPG]]&lt;br /&gt;
&lt;br /&gt;
*Cliquer sur '''Load from file''' et charger le fichier de configuration fourni par OpenFlyers&lt;br /&gt;
*Beaucoup de paramètres sont disponibles, ne pas les modifier sans avertir OpenFlyers &lt;br /&gt;
*Cliquer sur '''Save to device'''&lt;br /&gt;
*Débrancher le câble et refermer le tracker&lt;br /&gt;
&lt;br /&gt;
Voir la documentation Teltonika pour la description des [https://wiki.teltonika-gps.com/view/FMC125_Configuration paramètres]&lt;br /&gt;
&lt;br /&gt;
==Initialiser le tracker==&lt;br /&gt;
;Références&lt;br /&gt;
*[https://wiki.teltonika-gps.com/images/0/05/QM-FMC125.pdf documentation officielle]&lt;br /&gt;
*[https://wiki.teltonika-gps.com/view/FMC125_First_Start Premier démarrage]&lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
*Ouvrir le tracker en écartant les clips latéraux&lt;br /&gt;
*Insérer une carte SIM au format mini (2FF : 25mm x 15mm) dans le slot inférieur. Coin coupé vers l’avant et contact vers le bas&lt;br /&gt;
*Ne pas connecter la batterie de secours située sous le circuit imprimé&lt;br /&gt;
*Refermer le tracker&lt;br /&gt;
*Brocher le tracker sur le bloc d’alimentation&lt;br /&gt;
&lt;br /&gt;
L'alimentation du tracker Teltonika FMC 125 peut être faite par une alimentation autonome sur batterie.&lt;br /&gt;
Voici par exemple la description de mise en œuvre d'un boitier (Conception hors OpenFlyers)&lt;br /&gt;
&lt;br /&gt;
[[File:Alimentation.JPG|File:Alimentation.JPG]]&lt;br /&gt;
 &lt;br /&gt;
*Basculer l’interrupteur de mise sous tension vers la gauche : la diode d’état doit s’allumer en rouge. L’alimentation est sous tension mais pas le tracker&lt;br /&gt;
*Appuyé sur le bouton blanc : la diode d’état doit passer au vert. Le tracker est sous tension&lt;br /&gt;
*Sur la face arrière du tracker les diodes d’état doivent s’allumer. La diode de droite indique la connexion au réseau cellulaire, celle de gauche la connexion au système satellitaire. Diode fixe pas de connexion, clignotant connexion établie&lt;br /&gt;
*En cas de chute de tension sous le seuil de décharge, le boitier se met en sécurité, la diode d'état repasse au rouge. Il faut recharger le boitier sinon il y a risque de destruction des batteries&lt;br /&gt;
&lt;br /&gt;
==Interfacer OpenFlyers avec Teltonika==&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Structure &amp;gt; Paramétrage &amp;gt; Activités'''&lt;br /&gt;
**Activer l'interrupteur '''Teltonika''' situé dans la 4ème colonne&lt;br /&gt;
**Renseigner les champs '''Nom d'utilisateur''' et '''Mot de passe'''.&lt;br /&gt;
**Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
*[[Gestion-des-ressources#Saisir-le-numéro-de-ressource-pour-l'API-de-geolocalisation|Configurer le numéro de l'API de géolocalisation pour les ressources]].&lt;br /&gt;
&lt;br /&gt;
=Récupération des vols Teltonika=&lt;br /&gt;
Chaque minute, le robot OpenFlyers interroge le serveur Teltonika pour vérifier s'il y a de nouveaux vols enregistrés. S'il y en a, ces vols sont sauvegardés dans OpenFlyers et les vols récupérés du côté de Teltonika sont marqués comme '''collected''' via la demande '''/confirmTrack'''.&lt;br /&gt;
&lt;br /&gt;
Teltonika utilise un système d'identifiant pour retrouver les pilotes et les aéronefs il est donc nécessaire de créer les champs métiers nécessaires et de les renseigner dans l'interface d'OpenFlyers.&lt;br /&gt;
 &lt;br /&gt;
*Si l'identifiant d'un aéronef chez Teltonika ne peut être retrouvé dans OpenFlyers alors le robot n'enregistrera pas le vol.&lt;br /&gt;
&lt;br /&gt;
Afin de retrouver un maximum d'informations le robot tente de retrouver une réservation avec la même ressource correspondant au vol communiqué par Teltonika:&lt;br /&gt;
*Il vérifie l'existence d'une réservation avec des horaires incluant l'heure médiane du vol Teltonika. En cas de présence, il se réfère aux informations de cette réservation.&lt;br /&gt;
*En l'absence de toute réservation, il recherche une réservation avec la même ressource dont les horaires se situent entre le début et la fin du vol remonté par Teltonika.&lt;br /&gt;
**S'il y a plusieurs réservations, alors il n'en prend aucune.&lt;br /&gt;
**Dès qu'une réservation correspondant au vol remonté par Teltonika est identifiée, les informations de cette réservation sont prises en compte par le robot.&lt;br /&gt;
&lt;br /&gt;
;Exemple&lt;br /&gt;
Pour un vol qui commence à 16h05 et se termine à 17h00, l'heure médiane est 16h32. La réservation correspondante pour ce vol sera celle qui inclut cette heure médiane.&lt;br /&gt;
&lt;br /&gt;
==Statut des pilotes==&lt;br /&gt;
Pour chaque pilote :&lt;br /&gt;
*Si un vol récupéré dans Teltonika peut être associé à une réservation =&amp;gt; Les statuts des pilotes sont celles définies dans la réservation.&lt;br /&gt;
*Si le vol ne peut être associé : &lt;br /&gt;
**S'il n'y a qu'un statut autorisé pour la place du pilote et pour l'avion =&amp;gt; Le statut du pilote est ce statut.&lt;br /&gt;
**Si le pilote est sur la première place =&amp;gt; Le statut du pilote est le statut &amp;quot;pilote&amp;quot; si il n'existe pas le premier statut.&lt;br /&gt;
**Si le pilote est sur la seconde place =&amp;gt; Le statut du pilote est le statut &amp;quot;Instructeur&amp;quot; si il n'existe pas le second statut.&lt;br /&gt;
&lt;br /&gt;
==Place des pilotes==&lt;br /&gt;
*Si un vol récupéré dans Teltonika peut être associé à une réservation =&amp;gt; Les places des pilotes sont celles définies dans la réservation.&lt;br /&gt;
*Si le vol ne peut être associé : &lt;br /&gt;
**S'il y a un seul pilote =&amp;gt; Sa place est celle par défaut (0, Gauche).&lt;br /&gt;
**S'il y a deux pilotes et que un seul à l'autorisation pour être sur la place de droite =&amp;gt; Le pilote ayant l'autorisation est à la place de droite et l'autre à la place de gauche.&lt;br /&gt;
**Si les deux pilotes ont les autorisations pour être sur la place de droite =&amp;gt; Le pilote 1 est sur la place de gauche le pilote 2 est sur la place de droite.&lt;br /&gt;
&lt;br /&gt;
=FAQ=&lt;br /&gt;
==Le boitier se connecte au serveur OpenFlyers Teltonika mais n'envoie pas de données==&lt;br /&gt;
Vérifier la configuration de la box Teltonika dans cette documentation : [[#Configurer-le-tracker|Configurer le tracker]].&lt;br /&gt;
==Page ressource: le numéro de ressource à renseigner est-il bien l'IMEI du boîtier ?==&lt;br /&gt;
Oui, il faut saisir l'IMEI dans le champ &amp;quot;numéro de ressource&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Page Structure &amp;gt; Activités: il y a un &amp;quot;nom utilisateur&amp;quot; et &amp;quot;Mot de passe&amp;quot; à renseigner. Que doit mettre à ce niveau ?==&lt;br /&gt;
Après avoir demandé à l'équipe d'Openflyers de créer un compte pour la plateforme sur le serveur Teltonika, insérer les identifiants fournis par Openflyers dans les champs nom d'utilisateur et mot de passe.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Interfa%C3%A7age-OpenFlyers-et-Teltonika&amp;diff=12873</id>
		<title>Interfaçage OpenFlyers et Teltonika</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Interfa%C3%A7age-OpenFlyers-et-Teltonika&amp;diff=12873"/>
		<updated>2024-10-02T17:26:12Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter l'interfaçage d'OpenFlyers avec les boitiers [https://teltonika-networks.com/ Teltonika].&lt;br /&gt;
&lt;br /&gt;
;Trackers testés par OpenFlyers&lt;br /&gt;
*[https://wiki.teltonika-gps.com/view/FMC125 Teltonika FMC 125]&lt;br /&gt;
*[https://wiki.teltonika-gps.com/view/FMC130 Teltonika FMC 130] comporte des entrées supplémentaires&lt;br /&gt;
&lt;br /&gt;
Ce sont des modèles 4G multi-systèmes satellitaires (GPS, GLONASS et Galileo).&lt;br /&gt;
&lt;br /&gt;
;Certificats&lt;br /&gt;
*https://wiki.teltonika-gps.com/view/FMC125_Certification_%26_Approvals&lt;br /&gt;
*https://wiki.teltonika-gps.com/view/FMC130_Certification_%26_Approvals&lt;br /&gt;
&lt;br /&gt;
;Compatibilité avec l'aéronautique&lt;br /&gt;
*Pour les ULMs, il n'y a pas de réglementation particulière&lt;br /&gt;
*Pour les aéronefs certifiés ELA2 (aéronef léger européen dont la masse maximale au décollage ne dépasse pas 2 tonnes), la réglementation EASA [https://www.easa.europa.eu/en/document-library/certification-specifications/cs-stan-issue-4 CS-STAN version 4], chapitre &amp;quot;Standard Change CS-SC106b&amp;quot; (installation of flight-time recorders), impose que les appareils installés à demeure sur l'aéronef ne dépassent pas une puissance d'émission de 100mW dès lors que l'aéronef est en mouvement. La documentation de certification Teltonika indique une puissance d'émission de 26,05dBm soit 402mW.&lt;br /&gt;
&lt;br /&gt;
Il existe à l'heure actuelle 2 solutions :&lt;br /&gt;
*Rajouter au boitier Teltonika un boitier d'alimentation autonome disposant de sa propre batterie (solution testée par OpenFlyers)&lt;br /&gt;
*Rajouter au boitier Teltonika un boitier d'interfaçage à une alimentation standardisée et installer sur l'aéronef ce type d'alimentation permettant au boitier de ne pas être considéré comme fixé sur l'appareil (solution non testée par OpenFlyers)&lt;br /&gt;
&lt;br /&gt;
OpenFlyers est ouvert à toute solution alternative qui n'émettrait pas durant le déplacement de l'aéronef et a sollicité Teltonika dans ce sens.&lt;br /&gt;
&lt;br /&gt;
;Paramétrage et installation&lt;br /&gt;
*Paramétrer le boitier pour qu'il envoie les données sur le serveur de réception des données OpenFlyers prévu à cet effet&lt;br /&gt;
*Équiper le boitier avec une carte SIM pour l'envoi des données&lt;br /&gt;
*Brancher le boitier sur la batterie via une connectique amovible de l'aéronef ou de façon autonome&lt;br /&gt;
&lt;br /&gt;
Pour la carte SIM, il existe une multitude de solutions. Ces prestataires fournissent une carte SIM avec un abonnement de type &amp;quot;Internet des Objets&amp;quot; (IoT &amp;quot;Internet of Things&amp;quot;) en anglais) permettant de ne faire que du transfert de données et qui est multi-opérateurs. A noter, que le tracker prend le meilleur des réseaux disponibles.&lt;br /&gt;
&lt;br /&gt;
;Exemples de fournisseurs de cartes SIM&lt;br /&gt;
*[https://www.korewireless.com/super-sim-card Kore Super SIM] a un cout de $2 par mois et le coût des data est de $0,10 par Mo&lt;br /&gt;
*[https://www.thingsmobile.com/fr/private/solutions/carte-sim-gps-tracker Things Mobile &amp;quot;Carte SIM pour GPS Tracker&amp;quot;] a un coût de 0,12 €/Mo&lt;br /&gt;
&lt;br /&gt;
=Variables pour les formules de calcul=&lt;br /&gt;
Les variables suivantes sont utilisables dans les formules :&lt;br /&gt;
&lt;br /&gt;
*TELTONIKA_ENGINE_START : Datetime de décollage&lt;br /&gt;
*TELTONIKA_OFFBLOCK_DATE : Datetime de départ bloc&lt;br /&gt;
*TELTONIKA_ONBLOCK_DATE : Datetime de bloc arrivée&lt;br /&gt;
*TELTONIKA_ENGINE_STOP : Datetime d'atterrissage&lt;br /&gt;
Ces variables sont directement transmises par Teltonika.&lt;br /&gt;
&lt;br /&gt;
Les fonctions suivantes peuvent être utilisées dans les formules pour le [[Configuration#Gestion-de-Teltonika|paramétrage de Teltonika]] :&lt;br /&gt;
*[[Formules-de-calcul#formatDate('patron',-'date')|formatDate]] : Permet de formater une date&lt;br /&gt;
*[[Formules-de-calcul#roundCeil(X,Y)|roundCeil]] : Arrondi à la minute supérieure la date transmise en paramètre&lt;br /&gt;
*[[Formules-de-calcul#roundFloor(X,Y)|roundFloor]] : Arrondi à la minute inférieure la date transmise en paramètre&lt;br /&gt;
*[[Formules-de-calcul#strtotime(string)|strtotime]] : Transforme une date en timestamp&lt;br /&gt;
&lt;br /&gt;
=Procédure=&lt;br /&gt;
==Configurer le tracker==&lt;br /&gt;
;Prérequis&lt;br /&gt;
*Avoir [[#Initialiser-le-tracker|initialisé le tracker]]&lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
Pour paramétrer le tracker il faut le connecter avec un PC. &lt;br /&gt;
*Il faut ouvrir le boitier du tracker et connecter un câble micro USB&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Connexion_pour_configuration.jpg|File:Connexion_pour_configuration.jpg]]&lt;br /&gt;
&lt;br /&gt;
*Aller sur le site de Teltonika pour télécharger la dernière version du [https://wiki.teltonika-gps.com/view/Teltonika_Configurator_versions programme de configuration]&lt;br /&gt;
*Reconnecter le tracker sur son bloc d’alimentation et le mettre sous tension&lt;br /&gt;
*Lancer le programme Teltonika Configurator, la page d’accueil doit détecter automatiquement le tracker connecté.&lt;br /&gt;
*Double-cliquer sur le device détecté&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Menu_Teltonika.JPG|File:Menu_Teltonika.JPG]]&lt;br /&gt;
&lt;br /&gt;
*Cliquer sur '''Load from file''' et charger le fichier de configuration fourni par OpenFlyers&lt;br /&gt;
*Beaucoup de paramètres sont disponibles, ne pas les modifier sans avertir OpenFlyers &lt;br /&gt;
*Cliquer sur '''Save to device'''&lt;br /&gt;
*Débrancher le câble et refermer le tracker&lt;br /&gt;
&lt;br /&gt;
Voir la documentation Teltonika pour la description des [https://wiki.teltonika-gps.com/view/FMC125_Configuration paramètres]&lt;br /&gt;
&lt;br /&gt;
==Initialiser le tracker==&lt;br /&gt;
;Références&lt;br /&gt;
*[https://wiki.teltonika-gps.com/images/0/05/QM-FMC125.pdf documentation officielle]&lt;br /&gt;
*[https://wiki.teltonika-gps.com/view/FMC125_First_Start Premier démarrage]&lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
*Ouvrir le tracker en écartant les clips latéraux&lt;br /&gt;
*Insérer une carte SIM au format mini (2FF : 25mm x 15mm) dans le slot inférieur. Coin coupé vers l’avant et contact vers le bas&lt;br /&gt;
*Ne pas connecter la batterie de secours située sous le circuit imprimé&lt;br /&gt;
*Refermer le tracker&lt;br /&gt;
*Brocher le tracker sur le bloc d’alimentation&lt;br /&gt;
&lt;br /&gt;
L'alimentation du tracker Teltonika FMC 125 peut être faite par une alimentation autonome sur batterie.&lt;br /&gt;
Voici par exemple la description de mise en œuvre d'un boitier (Conception hors OpenFlyers)&lt;br /&gt;
&lt;br /&gt;
[[Fichier:Alimentation.JPG|File:Alimentation.JPG]]&lt;br /&gt;
 &lt;br /&gt;
*Basculer l’interrupteur de mise sous tension vers la gauche : la diode d’état doit s’allumer en rouge. L’alimentation est sous tension mais pas le tracker&lt;br /&gt;
*Appuyé sur le bouton blanc : la diode d’état doit passer au vert. Le tracker est sous tension&lt;br /&gt;
*Sur la face arrière du tracker les diodes d’état doivent s’allumer. La diode de droite indique la connexion au réseau cellulaire, celle de gauche la connexion au système satellitaire. Diode fixe pas de connexion, clignotant connexion établie&lt;br /&gt;
*En cas de chute de tension sous le seuil de décharge, le boitier se met en sécurité, la diode d'état repasse au rouge. Il faut recharger le boitier sinon il y a risque de destruction des batteries&lt;br /&gt;
&lt;br /&gt;
==Interfacer OpenFlyers avec Teltonika==&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Structure &amp;gt; Paramétrage &amp;gt; Activités'''&lt;br /&gt;
**Activer l'interrupteur '''Teltonika''' situé dans la 4ème colonne&lt;br /&gt;
**Renseigner les champs '''Nom d'utilisateur''' et '''Mot de passe'''.&lt;br /&gt;
**Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
*[[Gestion-des-ressources#Saisir-le-numéro-de-ressource-pour-l'API-de-geolocalisation|Configurer le numéro de l'API de géolocalisation pour les ressources]].&lt;br /&gt;
&lt;br /&gt;
=Récupération des vols Teltonika=&lt;br /&gt;
Chaque minute, le robot OpenFlyers interroge le serveur Teltonika pour vérifier s'il y a de nouveaux vols enregistrés. S'il y en a, ces vols sont sauvegardés dans OpenFlyers et les vols récupérés du côté de Teltonika sont marqués comme '''collected''' via la demande '''/confirmTrack'''.&lt;br /&gt;
&lt;br /&gt;
Teltonika utilise un système d'identifiant pour retrouver les pilotes et les aéronefs il est donc nécessaire de créer les champs métiers nécessaires et de les renseigner dans l'interface d'OpenFlyers.&lt;br /&gt;
 &lt;br /&gt;
*Si l'identifiant d'un aéronef chez Teltonika ne peut être retrouvé dans OpenFlyers alors le robot n'enregistrera pas le vol.&lt;br /&gt;
&lt;br /&gt;
Afin de retrouver un maximum d'informations le robot tente de retrouver une réservation avec la même ressource correspondant au vol communiqué par Teltonika:&lt;br /&gt;
*Il vérifie l'existence d'une réservation avec des horaires incluant l'heure médiane du vol Teltonika. En cas de présence, il se réfère aux informations de cette réservation.&lt;br /&gt;
*En l'absence de toute réservation, il recherche une réservation avec la même ressource dont les horaires se situent entre le début et la fin du vol remonté par Teltonika.&lt;br /&gt;
**S'il y a plusieurs réservations, alors il n'en prend aucune.&lt;br /&gt;
**Dès qu'une réservation correspondant au vol remonté par Teltonika est identifiée, les informations de cette réservation sont prises en compte par le robot.&lt;br /&gt;
&lt;br /&gt;
;Exemple&lt;br /&gt;
Pour un vol qui commence à 16h05 et se termine à 17h00, l'heure médiane est 16h32. La réservation correspondante pour ce vol sera celle qui inclut cette heure médiane.&lt;br /&gt;
&lt;br /&gt;
==Statut des pilotes==&lt;br /&gt;
Pour chaque pilote :&lt;br /&gt;
*Si un vol récupéré dans Teltonika peut être associé à une réservation =&amp;gt; Les statuts des pilotes sont celles définies dans la réservation.&lt;br /&gt;
*Si le vol ne peut être associé : &lt;br /&gt;
**S'il n'y a qu'un statut autorisé pour la place du pilote et pour l'avion =&amp;gt; Le statut du pilote est ce statut.&lt;br /&gt;
**Si le pilote est sur la première place =&amp;gt; Le statut du pilote est le statut &amp;quot;pilote&amp;quot; si il n'existe pas le premier statut.&lt;br /&gt;
**Si le pilote est sur la seconde place =&amp;gt; Le statut du pilote est le statut &amp;quot;Instructeur&amp;quot; si il n'existe pas le second statut.&lt;br /&gt;
&lt;br /&gt;
==Place des pilotes==&lt;br /&gt;
*Si un vol récupéré dans Teltonika peut être associé à une réservation =&amp;gt; Les places des pilotes sont celles définies dans la réservation.&lt;br /&gt;
*Si le vol ne peut être associé : &lt;br /&gt;
**S'il y a un seul pilote =&amp;gt; Sa place est celle par défaut (0, Gauche).&lt;br /&gt;
**S'il y a deux pilotes et que un seul à l'autorisation pour être sur la place de droite =&amp;gt; Le pilote ayant l'autorisation est à la place de droite et l'autre à la place de gauche.&lt;br /&gt;
**Si les deux pilotes ont les autorisations pour être sur la place de droite =&amp;gt; Le pilote 1 est sur la place de gauche le pilote 2 est sur la place de droite.&lt;br /&gt;
&lt;br /&gt;
=FAQ=&lt;br /&gt;
==Le boitier se connecte au serveur OpenFlyers Teltonika mais n'envoie pas de données==&lt;br /&gt;
Vérifier la configuration de la box Teltonika dans cette documentation : [[#Configurer-le-tracker|Configurer le tracker]].&lt;br /&gt;
==Page ressource: le numéro de ressource à renseigner est-il bien l'IMEI du boîtier ?==&lt;br /&gt;
Oui, il faut saisir l'IMEI dans le champ &amp;quot;numéro de ressource&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Page Structure &amp;gt; Activités: il y a un &amp;quot;nom utilisateur&amp;quot; et &amp;quot;Mot de passe&amp;quot; à renseigner. Que doit mettre à ce niveau ?==&lt;br /&gt;
Après avoir demandé à l'équipe d'Openflyers de créer un compte pour la plateforme sur le serveur Teltonika, insérer les identifiants fournis par Openflyers dans les champs nom d'utilisateur et mot de passe.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Accueil&amp;diff=12722</id>
		<title>Accueil</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Accueil&amp;diff=12722"/>
		<updated>2024-09-06T17:51:20Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Bienvenue sur la [[Toutes les documentations|documentation]] d''''OpenFlyers version 4'''.&lt;br /&gt;
&lt;br /&gt;
You can also access to our [[OF-doc-en:Main-Page|english documentation]].&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Présentation=&lt;br /&gt;
[https://www.youtube.com/watch?v=-lqPyrtf1i4 Présentation vidéo OpenFlyers]&lt;br /&gt;
&lt;br /&gt;
OpenFlyers :&lt;br /&gt;
*[[Introduction]]&lt;br /&gt;
*[[Présentation d'OpenFlyers 4]]&lt;br /&gt;
*[[Compte client OpenFlyers et modèle commercial]]&lt;br /&gt;
**[[Compte-client-OpenFlyers-et-modèle-commercial#Plateforme-supplémentaire-de-test-(bac-à-sable)|Plateforme supplémentaire de test (bac à sable)]]&lt;br /&gt;
*[[Plateforme de démonstration]]&lt;br /&gt;
*[[Bien communiquer avec OpenFlyers]]&lt;br /&gt;
*[[Formations OpenFlyers]]&lt;br /&gt;
*[[Historique des versions]]&lt;br /&gt;
*[[Normes et réglementations]]&lt;br /&gt;
*[[Technologies de géolocalisation aéronautique]]&lt;br /&gt;
&lt;br /&gt;
Installation :&lt;br /&gt;
*[[Créer une plateforme OpenFlyers pour sa structure]]&lt;br /&gt;
*[[Bien débuter avec OpenFlyers]]&lt;br /&gt;
*[[Compatibilité des navigateurs]]&lt;br /&gt;
*[[Paiement en ligne|Paiement en ligne (TPE virtuel)]]&lt;br /&gt;
&lt;br /&gt;
[[Rapporter un bug]]&lt;br /&gt;
&lt;br /&gt;
[[Trucs et astuces]] :&lt;br /&gt;
*[[Kiosque PC|Mettre en place un PC kiosque]]&lt;br /&gt;
*[[Réseau Internet hybride|Mettre en place un réseau internet hybride]]&lt;br /&gt;
&lt;br /&gt;
=Tutoriels vidéos=&lt;br /&gt;
Vidéos tutorielles disponibles sur la [https://www.youtube.com/user/OpenFlyersFr chaîne YouTube OpenFlyers] :&lt;br /&gt;
*[https://www.youtube.com/watch?v=Mx8xxsWdaC8&amp;amp;t=31s Analyse automatisée des factures fournisseurs]&lt;br /&gt;
*[https://www.youtube.com/watch?v=_hjOHHXP_ig Clôturer la comptabilité]&lt;br /&gt;
*[https://www.youtube.com/watch?v=X9bIEzxXIDw&amp;amp;ab_channel=OpenFlyers Créer une plateforme bac à sable]&lt;br /&gt;
*[https://www.youtube.com/watch?v=VVCdPWlwglM&amp;amp;ab_channel=OpenFlyers Importer un relevé bancaire]&lt;br /&gt;
*[https://www.youtube.com/watch?v=Bgb32Ay6TVU Lettrer des écritures comptables]&lt;br /&gt;
*[https://www.youtube.com/watch?v=kUvWhUXyC5Q&amp;amp;ab_channel=OpenFlyers Ouvrir dans un nouvel onglet]&lt;br /&gt;
*[https://www.youtube.com/watch?v=8J-AEtHrPqg Paiement à la réservation]&lt;br /&gt;
*[https://www.youtube.com/watch?v=pjuE6h0yXJA&amp;amp;ab_channel=OpenFlyers Saisir un flux]&lt;br /&gt;
*[https://www.youtube.com/watch?v=QVUgYEfqDk0&amp;amp;t=1s&amp;amp;ab_channel=OpenFlyers Saisir une facture fournisseur]&lt;br /&gt;
*[https://www.youtube.com/watch?v=qNACMM6vv7sI Utilisation du menu]&lt;br /&gt;
*[https://www.youtube.com/watch?v=tzM6hyOIpnc Utilisation du planning de réservation]&lt;br /&gt;
*[https://www.youtube.com/watch?v=YylSewaTm4c Utilisation des tableaux]&lt;br /&gt;
&lt;br /&gt;
=Documentation Administrateurs=&lt;br /&gt;
[[Compte-client-OpenFlyers-et-modèle-commercial#Plateforme-supplémentaire-de-test|Créer une plateforme supplémentaire de test (bac à sable)]]&lt;br /&gt;
&lt;br /&gt;
[[Configuration]]&lt;br /&gt;
&lt;br /&gt;
[[Paramétrage]]&lt;br /&gt;
&lt;br /&gt;
[[Champs métiers]]&lt;br /&gt;
&lt;br /&gt;
[[Formules de calcul]]&lt;br /&gt;
&lt;br /&gt;
Alertes :&lt;br /&gt;
*[[Alertes administrateur|Alertes administrateur]]&lt;br /&gt;
*[[Alertes de configuration]]&lt;br /&gt;
*[[Alertes utilisateur]]&lt;br /&gt;
&lt;br /&gt;
Activité :&lt;br /&gt;
*[[Gestion des activités]]&lt;br /&gt;
*[[Gestion des types d'activités]]&lt;br /&gt;
*[[Règles de saisie]]&lt;br /&gt;
&lt;br /&gt;
[[Communications]]&lt;br /&gt;
&lt;br /&gt;
Comptabilité :&lt;br /&gt;
*Documentation générale :&lt;br /&gt;
**[[Comptabilité|Généralités sur la comptabilité]]&lt;br /&gt;
**[[Conseils spécifiques pour la comptabilité]]&lt;br /&gt;
**[[Écritures comptables]]&lt;br /&gt;
**[[Gestion des écritures comptables]]&lt;br /&gt;
*Configuration et utilisation :&lt;br /&gt;
**[[Configuration de la comptabilité]]&lt;br /&gt;
**[[Exporter un relevé bancaire depuis un site internet de banque]]&lt;br /&gt;
**[[Gestion des budgets]]&lt;br /&gt;
**[[Import dans un logiciel comptable tiers]]&lt;br /&gt;
**[[Utilisation de la comptabilité]]&lt;br /&gt;
*Documentation de référence :&lt;br /&gt;
**[[OF-doc-en::Accounting-export-template-list|Modèle de format d'export comptable]]&lt;br /&gt;
**[[Modèles de format d'import de relevé bancaire]]&lt;br /&gt;
**[[Modèle de facture ODT|Template ODT pour les factures]]&lt;br /&gt;
&lt;br /&gt;
[[Contrôle des accès]] :&lt;br /&gt;
*[[Installation armoire à clés]]&lt;br /&gt;
*[[Gestion armoire à clés]]&lt;br /&gt;
*[[FAQ armoire à clés]]&lt;br /&gt;
&lt;br /&gt;
[[Données]] et [[Règlement Général sur la Protection des Données|Règlement Général sur la Protection des Données (RGPD)]]&lt;br /&gt;
&lt;br /&gt;
Documents :&lt;br /&gt;
*[[Gestion des documents]]&lt;br /&gt;
&lt;br /&gt;
[[Facturation des clients]] :&lt;br /&gt;
*[[Gestion de la facturation des activités]]&lt;br /&gt;
*[[Gestion des produits et des ventes]]&lt;br /&gt;
&lt;br /&gt;
Facturation fournisseur :&lt;br /&gt;
*[[Exporter les factures bancaires depuis un site internet de banque]]&lt;br /&gt;
*[[Gestion des achats]]&lt;br /&gt;
&lt;br /&gt;
Formation :&lt;br /&gt;
*[[Gestion des formations]]&lt;br /&gt;
*[[Utilisation des formations]]&lt;br /&gt;
&lt;br /&gt;
Géolocalisation :&lt;br /&gt;
*[[Interfaçage OpenFlyers et Charterware]]&lt;br /&gt;
*[[Interfaçage OpenFlyers et ClickAndTakeoff]]&lt;br /&gt;
*[[Interfaçage OpenFlyers et Gesasso]]&lt;br /&gt;
*[[Interfaçage OpenFlyers et Teltonika]]&lt;br /&gt;
&lt;br /&gt;
[[Logs]]&lt;br /&gt;
&lt;br /&gt;
Maintenance :&lt;br /&gt;
*[[Maintenance aéronautique]]&lt;br /&gt;
*[[Suivi-de-maintenance|Suivi de maintenance]]&lt;br /&gt;
*[[Suivi des remarques de maintenance]]&lt;br /&gt;
&lt;br /&gt;
Rapports :&lt;br /&gt;
*[[AERAL]]&lt;br /&gt;
*[[Bibliothèque des rapports]]&lt;br /&gt;
*[[Fonctionnement du moteur des rapports]]&lt;br /&gt;
*[[Gestion des rapports]]&lt;br /&gt;
&lt;br /&gt;
Réservations externes :&lt;br /&gt;
*[[Configuration des réservations externes]]&lt;br /&gt;
*[[Utilisation des réservations externes]]&lt;br /&gt;
&lt;br /&gt;
[[Gestion des ressources|Ressources]]&lt;br /&gt;
&lt;br /&gt;
[[Gestion des stocks|Stocks]]&lt;br /&gt;
&lt;br /&gt;
[[Tableurs]]&lt;br /&gt;
&lt;br /&gt;
Utilisateurs :&lt;br /&gt;
*[[Gestion des utilisateurs]]&lt;br /&gt;
*[[Gestion des profils]]&lt;br /&gt;
*[[Liste de diffusion]]&lt;br /&gt;
*[[Mailing]]&lt;br /&gt;
*[[Suivi des emails]]&lt;br /&gt;
&lt;br /&gt;
[[Validités]] :&lt;br /&gt;
*[[Paramétrage des validités]]&lt;br /&gt;
&lt;br /&gt;
Documentation Webmasters et Développeurs :&lt;br /&gt;
*[[API OpenFlyers]]&lt;br /&gt;
*[[Interfaçage OpenFlyers et armoire à clés]]&lt;br /&gt;
*[[OpenSSL]]&lt;br /&gt;
*[[Récupération des vols par un logiciel tiers]]&lt;br /&gt;
*[[Structure de la base de données]]&lt;br /&gt;
&lt;br /&gt;
=Documentation Utilisateurs=&lt;br /&gt;
[[Actions]]&lt;br /&gt;
&lt;br /&gt;
[[Gestion des activités|Activités]] :&lt;br /&gt;
*[[Carnet de route]]&lt;br /&gt;
*[[Carnet de vol]]&lt;br /&gt;
&lt;br /&gt;
Alertes et messages :&lt;br /&gt;
*[[Présentation générale des alertes|Aspect]]&lt;br /&gt;
*[[Alertes de configuration]]&lt;br /&gt;
*[[Alertes utilisateur]]&lt;br /&gt;
&lt;br /&gt;
[[Airmate]]&lt;br /&gt;
&lt;br /&gt;
[[Connexion]]&lt;br /&gt;
&lt;br /&gt;
[[Documents]]&lt;br /&gt;
&lt;br /&gt;
[[Ergonomie]] :&lt;br /&gt;
*[[Barre supérieure]]&lt;br /&gt;
*[[Boîtes de dialogue]]&lt;br /&gt;
*[[Calendrier]]&lt;br /&gt;
*[[Formulaires]]&lt;br /&gt;
*Menu de navigation :&lt;br /&gt;
**[[Menu de navigation|Menu de l'interface légère]]&lt;br /&gt;
**[[Menu de l'interface dynamique]]&lt;br /&gt;
&lt;br /&gt;
[[Envoi des emails]]&lt;br /&gt;
&lt;br /&gt;
[[Éphémérides]]&lt;br /&gt;
&lt;br /&gt;
[[Fiche personnelle]]&lt;br /&gt;
&lt;br /&gt;
[[Gestion de la comptabilité côté utilisateur]]&lt;br /&gt;
&lt;br /&gt;
[[Navigateurs]]&lt;br /&gt;
&lt;br /&gt;
Rapports :&lt;br /&gt;
*[[Bibliothèque des rapports]]&lt;br /&gt;
&lt;br /&gt;
Réservations :&lt;br /&gt;
*[[Aspect du planning de réservation]]&lt;br /&gt;
*[[Gestion des disponibilités|Disponibilités]]&lt;br /&gt;
*[[Panier de réservation]]&lt;br /&gt;
*[[Planning (interface légère)]]&lt;br /&gt;
*[[Utilisation du planning de réservation]]&lt;br /&gt;
&lt;br /&gt;
[[Utilisation des réservations externes|Réservations externes]]&lt;br /&gt;
&lt;br /&gt;
Tableaux :&lt;br /&gt;
*[[Tableaux|Tableaux de l'interface légère]]&lt;br /&gt;
*[[Tableaux de l'interface dynamique|Tableaux de l'interface dynamique]]&lt;br /&gt;
&lt;br /&gt;
[[Validités]]&lt;br /&gt;
&lt;br /&gt;
[[Gestion des ventes côté utilisateur]]&lt;br /&gt;
&lt;br /&gt;
=[[Appli OpenFlyers]]=&lt;br /&gt;
&lt;br /&gt;
=[[Glossaire]]=&lt;br /&gt;
&lt;br /&gt;
=FAQ=&lt;br /&gt;
*[[FAQ administrateur]]&lt;br /&gt;
*[[FAQ AeroBox]]&lt;br /&gt;
*[[FAQ armoire à clés]]&lt;br /&gt;
*[[FAQ client]]&lt;br /&gt;
*[[FAQ comptabilité]]&lt;br /&gt;
*[[FAQ export]]&lt;br /&gt;
*[[Liste-de-diffusion#Questions-fréquentes|FAQ liste de diffusion]]&lt;br /&gt;
*[[FAQ utilisateur]]&lt;br /&gt;
*[[Interfaçage-OpenFlyers-et-Teltonika#FAQ|FAQ Teltonika]]&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=MediaWiki:Sidebar&amp;diff=12721</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=MediaWiki:Sidebar&amp;diff=12721"/>
		<updated>2024-09-06T17:38:47Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*navigation&lt;br /&gt;
**mainpage|mainpage&lt;br /&gt;
**Special:RecentChanges|Changements récents&lt;br /&gt;
*Documentations&lt;br /&gt;
**OF-doc1-fr:Accueil|OpenFlyers 1&lt;br /&gt;
**OF-doc2-fr:Accueil|OpenFlyers 2&lt;br /&gt;
**OF-doc3-fr:Accueil|OpenFlyers 3&lt;br /&gt;
**OF-doc4-fr:Accueil|OpenFlyers 4&lt;br /&gt;
*autres langues&lt;br /&gt;
**OF-doc-en:Main-Page|English&lt;br /&gt;
**OF-doc-es:Main-Page|Español&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Test&amp;diff=12720</id>
		<title>Test</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Test&amp;diff=12720"/>
		<updated>2024-09-06T17:36:46Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[OF-doc4-fr:Accueil]]&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Test&amp;diff=12719</id>
		<title>Test</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Test&amp;diff=12719"/>
		<updated>2024-09-06T17:36:18Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[OF-doc-en:Main-Page4]]&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Test&amp;diff=12718</id>
		<title>Test</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Test&amp;diff=12718"/>
		<updated>2024-09-06T17:36:05Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Created page with &amp;quot;[OF-doc-en:Main-Page4]&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[OF-doc-en:Main-Page4]&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=MediaWiki:Mainpage&amp;diff=12717</id>
		<title>MediaWiki:Mainpage</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=MediaWiki:Mainpage&amp;diff=12717"/>
		<updated>2024-09-06T17:16:56Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Created page with &amp;quot;Accueil&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Accueil&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Utilisation-de-la-comptabilit%C3%A9&amp;diff=12716</id>
		<title>Utilisation de la comptabilité</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Utilisation-de-la-comptabilit%C3%A9&amp;diff=12716"/>
		<updated>2024-09-06T16:38:17Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;OF_doc-en&amp;quot; to &amp;quot;OF-doc-en&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
=Présentation=&lt;br /&gt;
L'objet de cette page est de décrire la saisie des opérations de [[Comptabilité|comptabilité]] dans la [[Accueil|version 4 d'OpenFlyers]].&lt;br /&gt;
&lt;br /&gt;
==Date par défaut dans les formulaires==&lt;br /&gt;
La date proposée par défaut dans les formulaires de saisie (saisie des factures fournisseurs, saisie des transferts de compte à compte, etc.) est la date de la dernière écriture enregistrée.&lt;br /&gt;
&lt;br /&gt;
==Définitions==&lt;br /&gt;
===Compte d'export===&lt;br /&gt;
Pour chaque compte, il faut [[Configuration de la comptabilité#Définir_les_comptes_d'export|préciser un compte d'export]] qui sert dans le cas où on exporte la comptabilité vers un autre logiciel de comptabilité.&lt;br /&gt;
&lt;br /&gt;
Cela sert également si on souhaite éditer une comptabilité depuis OpenFlyers et son module de gestion des rapports tout en respectant un plan comptable codifié.&lt;br /&gt;
&lt;br /&gt;
=Clôturer l'exercice comptable=&lt;br /&gt;
[https://www.youtube.com/watch?v=_hjOHHXP_ig Vidéo tutorielle pour clôturer une comptabilité]&lt;br /&gt;
&lt;br /&gt;
''Attention : la clôture de la comptabilité ne doit être effectuée qu'une fois qu'on est sûr et certain de ne plus avoir à intervenir sur l'exercice à clôturer. Cette opération doit donc être temporisée dans le temps sachant qu'il est tout à fait possible de poursuivre son activité sur l'exercice suivant sans que l'exercice précédent ne soit clôturé.''&lt;br /&gt;
&lt;br /&gt;
OpenFlyers affiche une [[Alertes de configuration#L'exercice_comptable_courant_a_plus_d'un_an|alerte lorsque l'exercice en cours est ouvert depuis 400 jours]].&lt;br /&gt;
&lt;br /&gt;
Avant de clôturer, il faut :&lt;br /&gt;
*Si le bilan est effectué dans OpenFlyers, [[Écritures comptables#Écritures_de_fin_d'exercice_avant_la_clôture_de_la_comptabilité|saisir les écritures de fin d'exercice]]&lt;br /&gt;
*[[#Solder-les-comptes|Solder les comptes d'exploitation]].&lt;br /&gt;
*[[Utilisation-de-la-comptabilité#Valider-toutes-les-écritures|Valider toutes les écritures antérieures à la date de clôture]].&lt;br /&gt;
En effet, on ne peut clôturer qu'une période pour laquelle toutes les écritures comptables ont été validées sinon cela engendre [[Alertes-administrateur#Alertes-lors-de-la-clôture-de-la-comptabilité|des alertes]]. Si des comptes n'ont pas été [[#Solder-les-comptes|soldés]] alors un [[Alertes-administrateur#Alertes-lors-de-la-clôture-de-la-comptabilité|message d'alerte]] apparaitra. Il n'est également pas possible de clôturer sur une date future.&lt;br /&gt;
&lt;br /&gt;
Ensuite, pour clôturer :&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Exercice &amp;gt; Clôturer'''.&lt;br /&gt;
*Dans la première colonne, la date de début de l'exercice comptable est renseignée ainsi qu'un tableau intitulé '''Statistiques''' fournit des informations sur les écritures. Sa lecture est indispensable pour vérifier qu'il ne subsiste pas d'écriture non validée antérieures à la fin de la période de clôture souhaitée. Si tel est le cas, la date sera affichée en rouge. Dans ce scénario, il est nécessaire de localiser les écritures non validées et de les valider en utilisant le bouton &amp;quot;Aller vers la première écriture comptable non validée&amp;quot; pour les écritures comptables non validées, ou le bouton &amp;quot;Aller vers la première activité non validée&amp;quot; pour les activités non validées.&lt;br /&gt;
*Dans la deuxième colonne intitulée '''Gestion de l'exercice comptable''', renseigner le champ '''Date de clôture'''.&lt;br /&gt;
La date de début de nouvel exercice est automatiquement actualisée.&lt;br /&gt;
&lt;br /&gt;
Pour une structure qui a un exercice annuel correspondant à l'année civile les dates devraient être 31/12/XXXX et 01/01/XXXX+1&lt;br /&gt;
*Cliquer sur le bouton '''Clôturer l'exercice puis ouvrir un nouvel exercice'''.&lt;br /&gt;
&lt;br /&gt;
En cas d'erreur de clôture, il est possible de [[#Déclôturer-l'exercice-comptable|Déclôturer le dernier exercice clôturé]].&lt;br /&gt;
&lt;br /&gt;
=Créer un tarif pour la facturation des activités=&lt;br /&gt;
*'''Admin &amp;gt; Ventes &amp;gt; Variables &amp;gt; Définition'''&lt;br /&gt;
*Cliquer sur le bouton '''Ajouter'''&lt;br /&gt;
*Champ '''Nom de variable''', renseigner un nom de variable sous la forme ''tarifSoloXXXX'' en remplaçant XXXX par le nom du type de ressource pour lequel le tarif doit s'appliquer. Exemple : ''tarifSoloDR42''. Il est primordial de respecter la casse (c'est à dire les majuscules et minuscules).&lt;br /&gt;
*Champ '''Intitulé''', renseigner le nom en clair de la variable sous la forme ''Tarif Solo XXXX'' en remplaçant XXXX par le nom du type de ressource pour lequel le tarif doit s'appliquer.&lt;br /&gt;
*Champ '''Type de valeur''', laisser ''Nombre à virgule''&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
&lt;br /&gt;
Il faut ensuite associer une valeur au tarif :&lt;br /&gt;
*'''Admin &amp;gt; Ventes &amp;gt; Variables &amp;gt; Actualisation'''&lt;br /&gt;
*Cliquer sur le bouton '''Ajouter une nouvelle valeur à une variable existante''' en bas du tableau&lt;br /&gt;
*Champ '''Nom de variable''', sélectionner le nom de la variable précédemment créé&lt;br /&gt;
*Champ '''Valeur''', renseigner le tarif à associer à la variable&lt;br /&gt;
*Champ '''Date de début''', laisser la date renseignée par défaut : elle correspond à la date de début d'exercice comptable et permet de ne pas avoir de &amp;quot;trou tarifaire&amp;quot;&lt;br /&gt;
*Cliquer sur le bouton '''Enregistrer'''&lt;br /&gt;
&lt;br /&gt;
=Déclôturer l'exercice comptable=&lt;br /&gt;
;Prérequis&lt;br /&gt;
*Disposer du droit [[Gestion-des-profils#Gestion-des-comptabilités|Gestion des comptabilités]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Exercice &amp;gt; Déclôturer'''.&lt;br /&gt;
*Activer l'interrupteur '''Autoriser la déclôture de l'exercice''', le bouton '''Supprimer''' devient opérationnel sur la première ligne du tableau, qui correspond à la dernière clôture (la date la plus récente).&lt;br /&gt;
*Cliquer sur le button '''Supprimer'''.&lt;br /&gt;
&lt;br /&gt;
'''NB''': Il n'est pas permis de déclôturer l'exercice comptable en cas d'une seule clôture comptable.&lt;br /&gt;
&lt;br /&gt;
=Éditions=&lt;br /&gt;
==Compte de résultat==&lt;br /&gt;
;Description&lt;br /&gt;
&lt;br /&gt;
;Utilisation&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Gestion &amp;gt; Compte de résultat'''&lt;br /&gt;
*Sélectionner l'année souhaitée&lt;br /&gt;
*Cliquer sur le bouton '''Visualiser'''&lt;br /&gt;
&lt;br /&gt;
'''/!\ Si les écritures de mise à 0 des comptes d'exploitation ont été passées, l'affichage indiquera que des valeurs à 0 pour les exercices précédents'''&lt;br /&gt;
&lt;br /&gt;
==Grand livre==&lt;br /&gt;
;Description&lt;br /&gt;
Le [https://fr.wikipedia.org/wiki/Grand_livre grand livre] sert à lister l'ensemble des écritures comptables sur une période donnée dans l'ordre chronologique où ils ont lieu et l'ordre des numéros des flux. Il  présente pour chaque compte :&lt;br /&gt;
* Le solde initial&lt;br /&gt;
* La liste des écritures&lt;br /&gt;
* Le solde final&lt;br /&gt;
&lt;br /&gt;
;Utilisation&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Gestion &amp;gt; Grand livre'''&lt;br /&gt;
*Choisir la date de début '''du'''&lt;br /&gt;
*Choisir la date de fin '''au'''&lt;br /&gt;
*Sélectionner le '''Compte d'export de début'''&lt;br /&gt;
*Sélectionner le '''Compte d'export de fin'''&lt;br /&gt;
*Cliquer sur le bouton '''Sauver dans un fichier CSV'''&lt;br /&gt;
&lt;br /&gt;
'''/!\ Le grand livre n'affiche que les comptes ayant eu au moins une écriture comptable sur la période donnée.'''&lt;br /&gt;
&lt;br /&gt;
=Exporter la comptabilité=&lt;br /&gt;
''Conseil OpenFlyers : l'export de la comptabilité nécessite au préalable des actions irréversibles comme la validation de l'ensemble des écritures. Pour les personnes débutantes avec cette fonction et qui souhaite pouvoir exporter sans effectuer ces actions irréversibles, il est recommandé de [[Compte-client-OpenFlyers-et-modèle-commercial#Plateforme-supplémentaire-de-test|s'entrainer avec le bac à sable]] en effectuant une recopie de sa plateforme de production.''&lt;br /&gt;
&lt;br /&gt;
Pour les exports comptable, la date de début d'export proposée par défaut correspond à la date du mouvement le plus vieux qui n'ait pas été encore exporté.&lt;br /&gt;
==Actions à effectuer par ordre chronologique==&lt;br /&gt;
OpenFlyers permet d'exporter uniquement les [[Bien débuter avec OpenFlyers#Validation_des_écritures|écritures validées]] et ainsi ne propose par défaut comme période d'export que la période maximum exportable ne contenant que des écritures validées.&lt;br /&gt;
&lt;br /&gt;
Les exports se font généralement à intervalle régulier : tous les mois, tous les trimestres ou tous les ans.&lt;br /&gt;
&lt;br /&gt;
Si vous n'avez pas de logiciel de comptabilité, il est recommandé d'effectuer quand même l'export et de l'archiver sur un support de stockage (disque dur par exemple) pour conservation.&lt;br /&gt;
&lt;br /&gt;
Dans le cas du dernier export d'un exercice comptable donné, il est important de décider avant l'export si tout ou partie des écritures de fin d'exercice doivent être réalisées avant ou après. En général, si l'export sert ensuite à être retravaillé dans un logiciel de comptabilité, alors les écritures de fin d'exercice seront réalisées dans le logiciel de comptabilité et il ne faudra faire le &amp;quot;nettoyage&amp;quot; côté OpenFlyers qu'à l'issue de l'export comptable officiel. Ainsi les points 2 et 3 des &amp;quot;Opérations à effectuer avant tout export&amp;quot; ci-dessous doit être, dans certains cas, réalisé en partie ou en totalité après le point 2 des &amp;quot;Opérations supplémentaires pour l'export de fin d'exercice&amp;quot; ci-dessous.&lt;br /&gt;
&lt;br /&gt;
De plus, si vous utilisez un logiciel de comptabilité uniquement pour le bilan, c'est à dire que les charges sont gérées dans OpenFlyers, alors la clôture dans OpenFlyers doit être faite après la clôture dans ce logiciel de comptabilité. Il est ainsi possible de vérifier que les &amp;quot;A nouveaux&amp;quot; sont identiques dans les 2 logiciels et de corriger dans OpenFlyers si nécessaire. Il existe un [[OF-doc-en:Accounting_exports_3#Carry_forwards|rapport qui permet d'avoir les à nouveaux]].&lt;br /&gt;
&lt;br /&gt;
Prérequis à tout export comptable :&lt;br /&gt;
*[[Configuration de la comptabilité#Comptes_d'export|Attribuer les comptes d'export]] pour ne pas avoir l'alerte &amp;quot;[[#Vous_ne_pouvez_exporter_car_il_y_a_des_comptes_sans_valeur_d'export|Vous ne pouvez exporter car il y a des comptes sans valeur d'export]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Opérations à effectuer pour tout export :&lt;br /&gt;
#[[#Retrouver-les-écritures-non-validées|Retrouver les écritures non validées]] pour [[Bien débuter avec OpenFlyers#Validation_des_écritures|les valider]]&lt;br /&gt;
#[[#Export_de_la_comptabilité|Export de la comptabilité]]&lt;br /&gt;
#[[Import dans un logiciel comptable tiers|import dans un logiciel de comptabilité]]&lt;br /&gt;
&lt;br /&gt;
Opérations supplémentaires pour l'export de fin d'exercice :&lt;br /&gt;
#[[Écritures comptables#Écritures_de_fin_d'exercice_avant_la_clôture_de_la_comptabilité|Écritures de fin d'exercice avant la clôture de l'exercice]] dont le [[#Solder-les-comptes|solde des comptes d'exploitation]]&lt;br /&gt;
#Validation des écritures de fin d'exercice par la [[Utilisation de la comptabilité#Validation_d'un_flux|validation des flux]] correspondant.&lt;br /&gt;
#Ultime export pour stockage [[#Marquer_les_écritures_lors_de_l'export|en marquant les écritures]].&lt;br /&gt;
#[[#Clôturer-l'exercice-comptable|Clôture / ouverture du nouvel exercice comptable]].&lt;br /&gt;
#[[Écritures comptables#Écritures_de_début_d'exercice_après_l'ouverture_de_la_comptabilité|Écritures de début d'exercice après l'ouverture de la comptabilité]].&lt;br /&gt;
&lt;br /&gt;
==Alertes générées lors d'une tentative d'[[Utilisation de la comptabilité#Export-de-la-comptabilité|export comptable]]==&lt;br /&gt;
===Vous ne pouvez exporter car il y a des comptes sans valeur d'export===&lt;br /&gt;
Cette alerte bloquante apparait dans '''Comptes &amp;gt; Exporter''' avec les éléments suivants :&lt;br /&gt;
&amp;lt;pre&amp;gt;Vous ne pouvez exporter car il y a des comptes sans valeur d'export&lt;br /&gt;
intitulé de compte X (type de compte Y)&amp;lt;/pre&amp;gt;&lt;br /&gt;
Pour supprimer cette alerte, il faut [[Configuration de la comptabilité#Comptes_d'export|attribuer les comptes d'export manquants]].&lt;br /&gt;
&lt;br /&gt;
==Export de la comptabilité==&lt;br /&gt;
Pré-requis : vérifier que le format d'export pour votre logiciel est présent dans le tableau '''Format de l'export'''. S'il n'est pas présent, [[Configuration#Formats-d'export-à-afficher|le rendre visible depuis la page Configuration]].&lt;br /&gt;
&lt;br /&gt;
Pour exporter la comptabilité, il faut :&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Gestion &amp;gt; Exporter'''&lt;br /&gt;
&lt;br /&gt;
Dans la première colonne, le tableau '''Statistiques''' donne des informations sur les écritures. Sa lecture est indispensable pour vérifier qu'il ne subsiste pas d'écriture non validée antérieures à la fin de la période d'export souhaitée. Si c'est le cas, il faut alors [[#Retrouver-les-écritures-non-validées|trouver les écritures non validées]] et les valider.&lt;br /&gt;
&lt;br /&gt;
Dans la deuxième colonne: &lt;br /&gt;
*Choisir la '''Comptabilité''' à exporter.&lt;br /&gt;
*Indiquer la période que l'on souhaite exporter.&lt;br /&gt;
&lt;br /&gt;
Attention: la période proposée par défaut correspond à la plus grande période possible et ne correspond donc pas à la période souhaitée. Il faut donc modifier la date de fin.&lt;br /&gt;
&lt;br /&gt;
Exemples :&lt;br /&gt;
*Si on souhaite exporter '''une année civile complète''', alors il faut sélectionner comme date de fin le 31 décembre.&lt;br /&gt;
*Si on souhaite exporter '''un mois''', il faut sélectionner comme date de fin le dernier jour du mois concerné.&lt;br /&gt;
&lt;br /&gt;
Il est également possible de marquer les écritures exportées afin qu'elles ne soient plus ré-exportées. Cependant, à la place de cette zone de saisie, il peut apparaitre la liste des comptes sans [[#Compte_d'export|valeur d'export]] c'est à dire sans le numéro de compte du plan comptable. Dans ce cas, il faut d'abord rechercher le compte concerné dans '''Comptes &amp;gt; Lister les comptes''' puis attribuer au compte concerné une valeur d'export.&lt;br /&gt;
*Cocher ou non '''[[#Marquer_les_écritures_lors_de_l'export|Marquer les écritures]]'''.&lt;br /&gt;
*Dans la troisième colonne, sélectionner le format d'export souhaité.&lt;br /&gt;
*L'export s'effectue en cliquant sur le bouton '''Exporter'''.&lt;br /&gt;
*Il faut ensuite [[Import dans un logiciel comptable tiers|importer dans un logiciel comptable tiers]].&lt;br /&gt;
&lt;br /&gt;
'''Remarques :'''&lt;br /&gt;
*Sauf à avoir cocher la case '''Ecritures non validées''', il n'est possible d'exporter que des écritures validées. Par conséquent, s'il subsiste des écritures non validées sur la période d'export souhaitée, alors une alerte apparait signalant qu'il n'est pas possible d'exporter la période souhaitée.&lt;br /&gt;
*Dans le fichier d'export, les écritures sont triées par numéro de flux.&lt;br /&gt;
&lt;br /&gt;
===Exporter les écritures marquées comme exportées===&lt;br /&gt;
Il est possible de ré-exporter les écritures marquées comme ayant été déjà exportées (et [[#Marquer-les-écritures-lors-de-l'export|marquées comme tel]]) en cochant '''Ecritures marquées comme exportées''' dans la colonne '''Écriture'''. En cochant cette case, un message d'alerte apparait indiquant ''Attention : vous allez exporter des écritures marquées, elles ont sans doute déjà étaient importées dans la comptabilité réelle.''.&lt;br /&gt;
&lt;br /&gt;
===Exporter les écritures non validées===&lt;br /&gt;
Il est possible d'exporter les écritures non validées en cochant '''Ecritures non validées''' dans la colonne '''Écriture'''. En cochant cette case, un message d'alerte apparait indiquant ''Attention : vous allez exporter des écritures non validées, elles ne devraient pas être importées dans la comptabilité réelle.''.&lt;br /&gt;
&lt;br /&gt;
===Marquer les écritures lors de l'export===&lt;br /&gt;
Lors d'un export comptable, OpenFlyers donne la possibilité de marquer ou non les écritures qui vont être exportées. Cela permet :&lt;br /&gt;
*Soit de pouvoir ré-exporter des écritures déjà exportées (mais non marquées)&lt;br /&gt;
*Soit au contraire de ne plus exporter des écritures dont OpenFlyers sait qu'elles ont déjà été exportées car marquées.&lt;br /&gt;
&lt;br /&gt;
Ce choix se fait dans le formulaire d'export en cochant '''Marquer les écritures (elles ne pourront plus être exportées de nouveau)'''.&lt;br /&gt;
&lt;br /&gt;
Il est conseillé de toujours procéder à un 1er export sans marquer les écritures. Ainsi, si l'export se passe mal, on aura la garantie de pouvoir le refaire.&lt;br /&gt;
&lt;br /&gt;
=Lettrer des écritures comptables=&lt;br /&gt;
Tutoriel OpenFlyers : [https://www.youtube.com/watch?v=Bgb32Ay6TVU Lettrer des écritures comptables]&lt;br /&gt;
&lt;br /&gt;
Le [https://fr.wikipedia.org/wiki/Lettrage_comptable lettrage] est une opération comptable qui consiste à affecter un seul repère à 2 ou plusieurs entrées comptables dans ce compte. la somme des entrées au crédit devant être égale à la somme des entrées au débit.&lt;br /&gt;
&lt;br /&gt;
Pour pouvoir effectuer le lettrage il faut disposer du droit [[Gestion-des-profils#Gestion-des-comptes|Gestion des comptes]].&lt;br /&gt;
&lt;br /&gt;
==Annulation automatique du lettrage==&lt;br /&gt;
Dans le cas où un flux comptable est modifié ou annulé, les écritures comptables lettrées avec les écritures du flux concerné sont automatiquement délettrées.&lt;br /&gt;
&lt;br /&gt;
==Lettrage automatique==&lt;br /&gt;
Le lettrage automatique se fait lors de l'[[#Importer-un-relevé-bancaire|import de relevés bancaires]] en cochant la case à cocher '''Lettrer automatiquement les écritures comptables''' de l'interface correspondante. Un robot va alors essayer de trouver des écritures à lettrer. Son fonctionnement est le suivant :&lt;br /&gt;
*Génération de l'écriture comptable&lt;br /&gt;
*Recherche d'une écriture comptable ayant le montant inverse (somme des crédits et débits égal à 0) et appartenant au même compte&lt;br /&gt;
*Création d'un lettrage pour les deux écritures correspondantes ainsi qu'une date de lettrage&lt;br /&gt;
*Enregistrement de l'écriture dans la base de données.&lt;br /&gt;
Pour la recherche de l'écriture inverse, le robot se limite à X jours avant et Y jours après la date de l'écriture d'origine. X et Y sont définis dans le [[Configuration-de-la-comptabilité#Paramétrage-général-de-la-gestion-des-comptes|Paramétrage général de la gestion des comptes]].&lt;br /&gt;
&lt;br /&gt;
Si plusieurs écritures ont été trouvées dans la base de données comme correspondante alors le lettrage n'est pas fait. Si plusieurs écritures générées ont la même écriture correspondante seule, la première est lettrée.&lt;br /&gt;
&lt;br /&gt;
==Lettrer manuellement==&lt;br /&gt;
Le lettrage manuel est fait par l'utilisateur via l'interface '''Gestion &amp;gt; Comptes › Comptes &amp;gt; X'''. Pour ajouter un lettrage à une écriture il faut :&lt;br /&gt;
*Cliquer sur le bouton d'édition du lettrage en haut de la colonne lettrage&lt;br /&gt;
*Cliquer sur les écritures que l'on souhaite associer&lt;br /&gt;
*Chaque entrée sélectionnée est ajoutée au panier des écritures en attente de lettrage affiché en haut de l'extrait de compte. Le contenu de ce panier est préservé en affichant d'autres pages d'extraits de compte du compte concerné. Cela permet d'associer des écritures comptables réparties sur des dates éloignées.&lt;br /&gt;
*Re-cliquer sur le bouton d'édition.&lt;br /&gt;
OpenFlyers va alors s'assurer que la somme des entrées au crédit est égale à la somme des entrées au débit. Si c'est le cas alors le lettrage est effectué.&lt;br /&gt;
&lt;br /&gt;
Seules les écritures n'ayant pas encore de lettrage peuvent être sélectionnées par l'utilisateur.&lt;br /&gt;
&lt;br /&gt;
Pour supprimer un lettrage, il faut :&lt;br /&gt;
*Cliquer sur le bouton de dissociation en haut de la colonne lettrage&lt;br /&gt;
*Cliquer sur les écritures que l'on souhaite dissocier.&lt;br /&gt;
*Re-cliquer sur le bouton d'édition.&lt;br /&gt;
&lt;br /&gt;
L'ensemble des écritures sélectionnées n'auront alors plus de lettrage ainsi que leurs écritures correspondantes. Si l'utilisateur a sélectionné deux écritures correspondantes, leur lettrage sera supprimé comme si une seul avait été sélectionnée.&lt;br /&gt;
&lt;br /&gt;
Ainsi si l'on souhaite modifier le lettrage d'une écriture il faut dans un premier temps supprimer son lettrage puis en ajouter un nouveau.&lt;br /&gt;
&lt;br /&gt;
=Mettre à jour les tarifs=&lt;br /&gt;
==Mettre à jour les tarifs associés à des produits==&lt;br /&gt;
*'''Gestion &amp;gt; Ventes &amp;gt; Produits'''&lt;br /&gt;
&lt;br /&gt;
*Les tarifs sont définis dans la partie droite du tableau à partir de la colonne '''Tarif associé'''.&lt;br /&gt;
[[Image:Tableau_produits_actualisation_tarifs.png|800px]]&lt;br /&gt;
*Dans '''Historique des montants''', sélectionner '''Nouveau couple...''' pour créer un nouveau tarif.&lt;br /&gt;
*Saisir un nouveau '''Montant du tarif''' et la nouvelle '''Date d'entrée en vigueur du tarif''' à partir de laquelle le tarif s'appliquera. Vous pouvez anticiper un changement de tarif. Le tarif s'appliquera à la date du mouvement.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention''': si vous sélectionnez un couple existant dans '''Historique des montants''' et que vous modifiez le montant ou la date d'entrée en vigueur, alors vous changez le prix de cette période mais vous ne créez pas un nouveau tarif. Vous perdrez toute possibilité de corriger par exemple un vol à une date donnée. &lt;br /&gt;
&lt;br /&gt;
* S'il y a un message d'erreur &amp;quot;chaque variable doit disposer d'une valeur antérieure à la date de début de l'exercice comptable&amp;quot; cela signifie que la variable ne possède pas de valeur entre la date de début d'exercice (date définie dans '''Admin &amp;gt; Comptes &amp;gt; Gestion &amp;amp; Export''') et la date indiquée. Le programme refuse qu'il y ait une absence de tarif applicable. &lt;br /&gt;
*Chaque variable utilisée dans les formules de tarification doit avoir une valeur initialisée depuis une date antérieure à la date de début de l'exercice comptable&lt;br /&gt;
&lt;br /&gt;
==Mettre à jour les tarifs associés à des activités==&lt;br /&gt;
*'''Admin &amp;gt; Ventes &amp;gt; Variables &amp;gt; Actualisation'''&lt;br /&gt;
[[Image:Menu-vente-prix-actualisation-des-prix.jpg|250px]]&lt;br /&gt;
&lt;br /&gt;
Si vous souhaitez mettre à jour un tarif, c'est à dire définir un prix qui doit s'appliquer à partir d'une certaine date, alors il faut :&lt;br /&gt;
*Cliquer sur le bouton '''Ajouter une nouvelle valeur à une variable existante''' en bas du tableau et '''non pas sur l'icône crayon à droite de la ligne de tarif'''.&lt;br /&gt;
[[Image:Tableau-vente-prix-actualisation-de-prix.jpg|500px]]&lt;br /&gt;
&lt;br /&gt;
*Saisir une nouvelle valeur et la date à partir de laquelle le tarif s'appliquera. Vous pouvez anticiper un changement de tarif. Le tarif s'appliquera à la date du mouvement.&lt;br /&gt;
[[Image:Ajout-nouvelle-valeur-variable-tarif.png|400px]]&lt;br /&gt;
&lt;br /&gt;
'''Attention''': si vous cliquez sur l'icône &amp;quot;Édition&amp;quot; (Crayon dans la colonne action) et que vous modifiez la valeur, alors vous changez le prix de cette période mais vous ne créez pas un nouveau tarif. Vous perdrez toute possibilité de corriger par exemple un vol à une date donnée. &lt;br /&gt;
&lt;br /&gt;
*Si vous avez le message d'erreur &amp;quot;chaque variable doit disposer d'une valeur antérieure à la date de début de l'exercice comptable&amp;quot; cela signifie que la variable ne possède pas de valeur entre la date de début d'exercice (date définie dans '''Gestion &amp;gt; Comptes &amp;gt; Gestion &amp;gt; Gestion &amp;amp; Export''') et la date indiquée. Le programme refuse qu'il y ait un &amp;quot;trou tarifaire&amp;quot; (vols non facturés). &lt;br /&gt;
*Chaque variable utilisée dans les formules de tarification doit avoir une valeur initialisée depuis une date antérieure à la date de début de l'exercice comptable&lt;br /&gt;
&lt;br /&gt;
Après mise à jour des tarifs, s'il est nécessaire de mettre à jour les activités déjà saisies, alors il faut suivre la procédure [[Gestion-des-activités#Mettre-à-jour-les-entrées-comptables-associées-à-des-activités-non-validées|Mettre à jour les entrées comptables associées à des activités non validées]].&lt;br /&gt;
&lt;br /&gt;
==Supprimer les tarifs associés à des activités==&lt;br /&gt;
;Supprimer une valeur de tarif&lt;br /&gt;
*Accéder à '''Admin &amp;gt; Ventes &amp;gt; Variables &amp;gt; Actualisation'''&lt;br /&gt;
*Cliquer sur l'icone ''Supprimer'' (représentée par une poubelle dans la colonne Actions)&lt;br /&gt;
*Si deux valeurs ou plus de la même variable que celle que nous souhaitons supprimer ont une date de début antérieure ou égale à celle de l'exercice, alors la suppression est autorisée.&lt;br /&gt;
*Si une seule valeur de la même variable que celle que nous souhaitons supprimer a une date de début antérieure ou égale à la date de début de l'exercice, nous devons alors vérifier si la valeur que nous voulons supprimer a une date de début ultérieure à celle de l'exercice. Si tel est le cas, nous pouvons la supprimer.&lt;br /&gt;
*Dans tous les autres cas, la suppression n'est pas autorisée. Cela signifie soit qu'il n'y aura aucune valeur applicable à la date de début de l'exercice comptable, soit que la situation est déjà compromise, c'est-à-dire qu'aucune valeur applicable n'existe à la date de début de l'exercice comptable.&lt;br /&gt;
&lt;br /&gt;
;Supprimer une variable tarif&lt;br /&gt;
*Accéder à '''Admin &amp;gt; Ventes &amp;gt; Variables &amp;gt; Définition'''&lt;br /&gt;
*Cliquer sur l'icone ''Supprimer'' (représentée par une poubelle dans la colonne Actions)&lt;br /&gt;
*Si la valeur est utilisée dans une règle de facturation des '''Activités''' ou des '''Produits''', la suppression n'est pas autorisée et un message d'alerte s'affiche.&lt;br /&gt;
*Si aucune règle de facturation n'utilise cette variable tarif, la suppression sera autorisée, entraînant la suppression de toutes les valeurs associées à cette variable tarif.&lt;br /&gt;
&lt;br /&gt;
=Opérations sur les comptes=&lt;br /&gt;
==Afficher la liste des opérations d'un compte==&lt;br /&gt;
*S'il s'agit d'un compte ressource, aller sur '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Ressources'''.&lt;br /&gt;
*S'il s'agit d'un compte utilisateur, aller sur '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Utilisateurs'''.&lt;br /&gt;
*Sinon, aller sur '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Tous'''.&lt;br /&gt;
*Le cas échéant, cliquer la lettre correspond à la première lettre du nom du compte.&lt;br /&gt;
*Cliquer sur le pictogramme symbolisant une liste d'écritures dans la colonne '''Action''' de la ligne du compte concerné&lt;br /&gt;
&lt;br /&gt;
==Créer un compte==&lt;br /&gt;
===Créer un compte ressource===&lt;br /&gt;
Pour créer un compte ressource, il faut :&lt;br /&gt;
*Aller sur '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Ressources'''.&lt;br /&gt;
*Dans la ligne de la ressource concernée, cliquer sur l'icône check du compte souhaité.&lt;br /&gt;
&lt;br /&gt;
===Créer un compte utilisateur===&lt;br /&gt;
Pour créer un compte utilisateur, il faut :&lt;br /&gt;
*Aller sur '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Utilisateurs'''.&lt;br /&gt;
*Dans la ligne de l'utilisateur concerné, cliquer sur l'icône check du compte souhaité.&lt;br /&gt;
&lt;br /&gt;
===Créer un compte non-ressource non-utilisateur===&lt;br /&gt;
Pour créer un compte, il faut :&lt;br /&gt;
*Aller sur '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Tous'''.&lt;br /&gt;
*En bas du tableau, remplir la ligne et choisir la catégorie du compte&lt;br /&gt;
*Cliquer sur le bouton '''Ajouter'''&lt;br /&gt;
&lt;br /&gt;
==Créer un type de compte==&lt;br /&gt;
===Créer un type de compte ressource===&lt;br /&gt;
Pour créer un type de compte ressource, il faut :&lt;br /&gt;
*Aller sur '''Admin &amp;gt; Comptes &amp;gt; Ressources &amp;gt; Types actifs''' puis cliquer sur le bouton '''Ajouter un compte'''.&lt;br /&gt;
*Saisir les champs du formulaire et valider .&lt;br /&gt;
&lt;br /&gt;
==Désactiver un compte==&lt;br /&gt;
Pour désactiver un compte qui ne doit plus être utilisé, il faut que :&lt;br /&gt;
* le compte ne doit pas être utilisé dans une règle de tarification. Cela concerne directement les comptes et non pas les types de comptes. Ainsi, il est possible de désactiver un compte utilisateur ou un compte ressource alors qu'il existe des règles de tarification qui utilisent le même type de compte que le compte à désactiver.&lt;br /&gt;
* dans le cas d'un compte de type utilisateur, l'utilisateur possédant ce compte ne doit pas être lié à un profil qui requiert le type de compte &lt;br /&gt;
* le compte ne doit pas être utilisé par un type de facture fournisseur&lt;br /&gt;
* le compte ne doit pas créer de trou dans la comptabilité. C'est à dire que :&lt;br /&gt;
** le [[#Solder_un_compte|solde du compte doit être à 0]]&lt;br /&gt;
** les écritures associées à ce compte doivent être toutes validées&lt;br /&gt;
Ensuite, on peut procéder à sa désactivation en cliquant sur l'icône symbolisant une poubelle sur la ligne de ce compte. Un compte n'ayant jamais eu d'écriture est supprimé au lieu de passer à l'état désactivé.&lt;br /&gt;
&lt;br /&gt;
==Lister les comptes==&lt;br /&gt;
*Aller sur '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Ressources''' pour obtenir les comptes ressource&lt;br /&gt;
*Aller sur '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Utilisateurs''' pour obtenir les comptes utilisateur&lt;br /&gt;
*Aller sur '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Tous''' pour obtenir les autres comptes.&lt;br /&gt;
&lt;br /&gt;
Dans ces pages, le solde de chaque compte est calculé en prenant les écritures datant du début d'exercice comptable jusqu'à la fin de la journée courante dans le [[Configuration#Fuseau-horaire-de-la-structure|fuseau horaire de la structure]]. Ainsi, les écritures comptables avec une date comptable future ne sont pas prises en compte pour le calcul du solde.&lt;br /&gt;
&lt;br /&gt;
Le symbole '''*''' peut apparaître à gauche d'un solde : Cela signifie que le compte possède des écritures comptables dans le futur.&lt;br /&gt;
&lt;br /&gt;
==Renommer un compte==&lt;br /&gt;
*Aller sur '''Gestion &amp;gt; Comptes &amp;gt; Comptes &amp;gt; Tous'''&lt;br /&gt;
*Cliquer éventuellement sur la lettre correspond à la 1ère lettre du nom du compte concerné.&lt;br /&gt;
*Cliquer sur le champ de la colonne '''Nom''' du compte concerné.&lt;br /&gt;
*Changer le nom du compte.&lt;br /&gt;
*Cliquer en dehors de la zone de saisie afin de permettre l'enregistrement de la saisie et le rafraichissement du tableau.&lt;br /&gt;
&lt;br /&gt;
==Supprimer un compte créé en double==&lt;br /&gt;
Il peut arriver que deux comptes identiques soient créés par inadvertance. Dans ce cas, il est nécessaire de supprimer le compte en trop. Pour cela il faut :&lt;br /&gt;
*[[#Renommer-un-compte|Renommer le compte]] en trop pour qu'il ne porte pas le même nom que le compte initial. Cela peut se faire en lui rajoutant un numéro. Exemple : ''Compte en trop'' deviendra ''Compte en trop 1''.&lt;br /&gt;
*Si le compte comporte des écritures non validées, il est recommandé de modifier les écritures pour les affecter au bon compte. Pour cela, il faut :&lt;br /&gt;
*[[#Afficher-la-liste-des-opérations-d'un-compte|Afficher la liste des opérations du compte]].&lt;br /&gt;
*Cliquer sur le pictogramme symbolisant un crayon pour chaque ligne concernée afin d'éditer la saisie. Il est recommandé d'utiliser le [[Ergonomie#Clic-droit-et-clic-molette|clic droit ou le clic molette]] de la souris. Cela permet d'effectuer l'édition dans un nouvel onglet et ainsi de ne pas perdre la page contenant le détail du compte.&lt;br /&gt;
*S'il s'agit d'un flux, il suffit de modifier la saisie du flux, puis de cliquer sur le bouton '''Enregistrer'''.&lt;br /&gt;
*S'il s'agit d'une facture fournisseur, il faut d'abord modifier le type de facture fournisseur correspondant. Pour cela il faut :&lt;br /&gt;
**Aller dans '''Gestion &amp;gt; Achats &amp;gt; Types de facture fournisseur'''&lt;br /&gt;
**Retrouver le type de facture correspondant&lt;br /&gt;
**Cliquer sur le pictogramme symbolisant un crayon dans la colonne '''Actions''' de la ligne du type de facture fournisseur concerné.&lt;br /&gt;
**Modifier la sélection du champ '''Compte fournisseur ou trésorerie''' ou du champ '''Compte de charge, de bilan ou ressource''' pour y mettre le ''compte qui n'est pas en trop''.&lt;br /&gt;
**Cliquer sur le bouton '''Enregistrer'''.&lt;br /&gt;
:Ensuite, il est possible d'éditer la facture fournisseur et de la réenregistrer. Cela permet l'imputation sur le bon compte.&lt;br /&gt;
*Répéter l'opération d'édition de chaque ligne afin de faire disparaitre toutes les lignes non validées.&lt;br /&gt;
*Une fois qu'il ne reste plus de ligne non validée, alors il faut retourner sur l'affichage des comptes de même catégorie afin de pouvoir cliquer sur le pictogramme symbolisant une poubelle à l'intersection de la colonne '''Actions''' et de la ligne concernée.&lt;br /&gt;
&lt;br /&gt;
=Relever bancaire=&lt;br /&gt;
'''Attention :''' avant d'effectuer un import de relevé bancaire en production, il est vivement recommandé de le faire sur la [[Compte-client-OpenFlyers-et-modèle-commercial#Plateforme-supplémentaire-de-test-(bac-à-sable)|plateforme bac à sable]]. En effet, un import de relevé bancaire génère de nombreuses écritures qu'il peut être ensuite fastidieux de supprimer à la main en cas de mauvais import.&lt;br /&gt;
&lt;br /&gt;
De la même façon, lors des tests, il est recommandé d'importer qu'une petite période comptable (quelques jours) afin de ne pas générer de trop nombreuses écritures qui peuvent rendre totalement illisibles la consultation des comptes.&lt;br /&gt;
&lt;br /&gt;
Pour accéder à cette fonctionnalité il faut disposer des droits de [[Gestion-des-profils#Gestion-des-comptes|Gestion des comptes]] ou [[Gestion-des-profils#Saisir-tout-flux|Saisir tout flux]].&lt;br /&gt;
&lt;br /&gt;
Il est recommandé de saisir les [[Gestion-des-achats#Saisie-d'une-facture-fournisseur|factures fournisseurs]] avant d'effectuer l'import du relevé bancaire conformément au [[Comptabilité#Règles-de-saisies-de-la-comptabilité-courante|règles de saisies de la comptabilité courante]].&lt;br /&gt;
&lt;br /&gt;
Voir également le chapitre [[Conseils-spécifiques-pour-la-comptabilité#Rapprochement-des-encaissements|Rapprochement des encaissements]] concernant la ventilation des écritures comptables liées à des encaissements.&lt;br /&gt;
&lt;br /&gt;
==Importer par API==&lt;br /&gt;
Prérequis :&lt;br /&gt;
*Avoir [[Configuration-de-la-comptabilité#Agréger-des-comptes-bancaires|agrégé un ou plusieurs compte(s) bancaire(s)avec des comptes de trésorerie]].&lt;br /&gt;
&lt;br /&gt;
Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Relevé bancaire &amp;gt; Importer par API''':&lt;br /&gt;
*'''Compte de trésorerie''' : Sélectionner le compte de trésorerie qui va être mis à jour par import du relevé du compte bancaire agrégé avec ce compte.&lt;br /&gt;
*'''Lettrer automatiquement les écritures importées''' : en cochant cette case, le [[#Lettrage-automatique|lettrage automatique]] des écritures générées par l'import s'effectue&lt;br /&gt;
*Cliquer sur le bouton '''Importer'''&lt;br /&gt;
&lt;br /&gt;
Remarques : &lt;br /&gt;
* Si lors de l'import des lignes ne sont pas importées car déjà présentes en base de données, un avertissement du type suivant s'affiche :&lt;br /&gt;
&amp;lt;pre&amp;gt;20 lignes comprises entre 01-03-2023 et 30-03-2023 n'ont pas été importées&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Les écritures générés via l'importation par API sont identifiés dans la liste des mouvements par l'icône &amp;quot;B-Bancaire&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Importer par fichier==&lt;br /&gt;
[https://youtu.be/VVCdPWlwglM Vidéo tutorielle pour importer un relevé bancaire]&lt;br /&gt;
&lt;br /&gt;
Prérequis :&lt;br /&gt;
*L'export du relevé doit avoir été réalisé (voir les procédures pour chaque dans la page [[Exporter un relevé bancaire depuis un site internet de banque]])&lt;br /&gt;
*Les [[Configuration-de-la-comptabilité#Règles-d'imputations-automatiques|règles d'imputation]] doivent être paramétrées&lt;br /&gt;
&lt;br /&gt;
Utilisation depuis l'[[Présentation-d'OpenFlyers-4#Interface-légère|interface légère]] :&lt;br /&gt;
*'''Gestion &amp;gt; Comptes &amp;gt; Relevé bancaire &amp;gt; Importer par fichier'''&lt;br /&gt;
*'''Fichier''' : Sélectionner le fichier à importer&lt;br /&gt;
*'''Format d'import''' : Sélectionner le [[Modèles-de-format-d'import-de-relevé-bancaire#Format-d'import|format]] correspondant au fichier à importer. La sélection est mémorisée pour les imports suivants.&lt;br /&gt;
*'''Compte trésorerie''' : Sélectionner le compte de trésorerie qui va être débité. Lorsque le montant est négatif, ce compte est crédité.&lt;br /&gt;
:Le compte affiché par défaut est déterminé dans l'ordre suivant :&lt;br /&gt;
:#Compte utilisé lors du précédent import&lt;br /&gt;
:#Compte ayant le plus petit numéro d'export comptable&lt;br /&gt;
*'''Lettrer automatiquement les écritures importées''' : en cochant cette case, le [[#Lettrage-automatique|lettrage automatique]] des écritures générées par l'import s'effectue&lt;br /&gt;
*Cliquer sur le bouton '''Importer'''&lt;br /&gt;
&lt;br /&gt;
* S'il y a un message d'erreur ''[[#Ligne-:-xxx-déjà-présente-en-base-de-données|Ligne : xxx déjà présente en base de données]]'', l'import n'est pas réalisé afin de ne pas générer de doublons.&lt;br /&gt;
&lt;br /&gt;
Lors de l'import, des [[Comptabilité#Flux|flux]] sont générés. Ils sont définis en fonction des [[Configuration-de-la-comptabilité#Règles-d'imputations-automatiques|règles d'imputation]]. Il est ensuite possible de modifier ces écritures en [[Utilisation-de-la-comptabilité#Modifier-un-flux|modifiant les flux]] depuis la [[Gestion-de-la-comptabilité-côté-utilisateur#Extrait-de-compte|liste des mouvements]] ou le détail des comptes imputés. &lt;br /&gt;
&lt;br /&gt;
Le compte de banque sélectionné lors de l'import contient une ligne de débit ou de crédit pour chaque flux généré par l'import.&lt;br /&gt;
&lt;br /&gt;
==Ligne : xxx déjà présente en base de données==&lt;br /&gt;
Ce message d'erreur peut être généré lors de l'utilisation de la fonctionnalité d'import de relevé bancaire.&amp;lt;br/&amp;gt;&lt;br /&gt;
Il indique que la ligne affichée est déjà présente en base de données.&amp;lt;br/&amp;gt;&lt;br /&gt;
Dans ce cas, aucune ligne du fichier n'est chargée en base de données.&amp;lt;br/&amp;gt;&lt;br /&gt;
En cas de présence de cette erreur, vérifier que la période d'export de votre relevé bancaire ne chevauche pas la période de l'export précédant.&lt;br /&gt;
&lt;br /&gt;
=Retrouver les écritures non validées=&lt;br /&gt;
S'il y a beaucoup d'écritures à valider, il faut procéder de façon systématique en parcourant chaque interface de validation :&lt;br /&gt;
*Pour les activités, aller dans '''Gestion &amp;gt; Activités &amp;gt; Activités &amp;gt; Liste''' puis '''Valider les activités sélectionnés''' pour chaque ressource.&lt;br /&gt;
*Pour les encaissements, aller dans '''Gestion &amp;gt; Comptes &amp;gt; Pointer &amp;gt; X''' où X correspond au type de paiement à pointer.&lt;br /&gt;
*Pour les transferts, aller dans '''Gestion &amp;gt; Comptes &amp;gt; Flux &amp;gt; Valider''' puis '''valider les transferts'''.&lt;br /&gt;
*Pour les factures, aller dans '''Gestion &amp;gt; Achats &amp;gt; Liste des factures fournisseurs'''.&lt;br /&gt;
*Pour les ventes, aller dans '''Gestion &amp;gt; Ventes &amp;gt; Valider les ventes'''. Choisir ses critères de recherche et valider le formulaire. Ensuite cocher les différentes ventes listées puis '''Pointer les entrées sélectionnées'''.&lt;br /&gt;
En procédant ainsi, il ne doit normalement ne pas subsister d'écriture à valider. Cependant, si l'essentiel des écritures a été validé, alors il est plus rapide de rechercher les écritures à valider que de parcourir chaque interface de validation.&lt;br /&gt;
&lt;br /&gt;
Pour rechercher les écritures restantes à valider, il faut :&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Gestion &amp;gt; Gestion / Export'''&lt;br /&gt;
En-dessous du titre '''Statistiques''' figure un tableau :&lt;br /&gt;
&lt;br /&gt;
[[Image:Tableau_statistiques_gestion-export.png]]&lt;br /&gt;
&lt;br /&gt;
Dans l'exemple ci-dessus, on peut voir à la ligne ''Ecritures non validées'', colonne ''Date de première écriture'' l'horodatage &amp;quot;19/08/2013 14:45&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Cela veut dire qu'il y a au moins une écriture qui date du 19 août 2013 et qui n'a pas été validée.&lt;br /&gt;
&lt;br /&gt;
Pour retrouver cette écriture non validée, il faut :&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Flux &amp;gt; Mouvements'''&lt;br /&gt;
*Rechercher l'écriture d'après la date indiquée.&lt;br /&gt;
Son contenu permettra de savoir s'il s'agit d'un vol, d'un encaissement, d'un flux, etc. Si un doute subsiste sur le type d'écriture, il faut cliquer sur l'icône &amp;quot;modifier&amp;quot; de l'écriture considérée afin de se retrouver dans son formulaire d'édition.&lt;br /&gt;
&lt;br /&gt;
Si les vols non validés correspondent à une ressource qui a été désactivée, alors pour valider les vols concernés, il faut :&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Ressources &amp;gt; Actives''' désactiver temporairement '''Réservable''' et '''Saisie d'activité''' pour une ressource existante afin de pouvoir avoir la possibilité de réactiver l'autre ressource&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Ressources &amp;gt; Désactivées'''&lt;br /&gt;
*Réactiver la ressource concernée&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Ressources &amp;gt; Actives''' et activer temporairement '''Saisie d'activité''' pour la ressource concernée&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Activités &amp;gt; Liste d'activités''' puis cliquer le bouton de la colonne '''Valider les activités sélectionnées''' correspondant à la ressource concernée&lt;br /&gt;
*Pointer les activités de la ressource&lt;br /&gt;
*Retourner dans '''Gestion &amp;gt; Ressources &amp;gt; Actives''' et désactiver la ressource concernée en cliquant sur l'icône symbolisant une poubelle&lt;br /&gt;
*Toujours dans cette interface, remettre '''Réservable''' et '''Saisie d'activité''' pour la ressource temporairement désactivée&lt;br /&gt;
&lt;br /&gt;
Remarques :&lt;br /&gt;
*Le nombre d'écritures non validées indiqué dans le tableau '''Statistiques''' correspond au nombre TOTAL d'écritures non validées. En effet, OpenFlyers sait quand est-ce que vous commencez un exercice mais il ne sait pas quand est-ce que vous voulez qu'il s'arrête. Donc il prend toutes les écritures non validées.&lt;br /&gt;
*OpenFlyers ne permet d'exporter ou de clôturer que la période qui inclut des écritures validées. Dès qu'il rencontre une écriture non validée, il bloque toute action d'export ou de clôture.&lt;br /&gt;
&lt;br /&gt;
=Saisir des écritures comptables=&lt;br /&gt;
==Annuler une écriture comptable==&lt;br /&gt;
Dans le cas où une écriture comptable saisie n'a pas été encore validée, pour l'annuler, il faut cliquer sur le bouton symbolisant une poubelle. Cela supprimera complètement l'écriture.&lt;br /&gt;
&lt;br /&gt;
Dans le cas où une écriture comptable a été validée, il n'est plus possible de la supprimer du fait de l'[[Comptabilité#Inaltérabilité-des-données|inaltérabilité des données]]. Le seul moyen d'en annuler son effet consiste à saisir une écriture opposée. Pour cela, il faut [[#Contrepasser-une-écriture|contrepasser l'écriture]].&lt;br /&gt;
&lt;br /&gt;
Cette solution permet de garantir l'inaltérabilité des écritures qui peuvent avoir été saisies par d'autres personnes et surtout qui peuvent affecter des comptes d'utilisateurs.&lt;br /&gt;
&lt;br /&gt;
C'est comme pour un compte bancaire : un banquier ne supprime jamais une écriture sur un compte client. Il passe simplement une nouvelle écriture qui annule l'effet de la précédente.&lt;br /&gt;
&lt;br /&gt;
==Contrepasser une écriture==&lt;br /&gt;
Cette fonction nécessite le droit [[Gestion-des-profils#Gestion-des-comptes|gestion des comptes]].&lt;br /&gt;
&lt;br /&gt;
La fonction de contrepassation d'une écriture permet d'annuler l'effet d'une vente (produit stocké ou non stocké), d'un encaissement ou d'un flux. Cette fonction n'existe pas pour contrepasser la vente de validité ou la vente d'activité. Pour la vente d'activité, il faut [[Gestion-des-activités#Annuler-une-activité-validée|annuler l'activité validée]].&lt;br /&gt;
&lt;br /&gt;
;Procédure&lt;br /&gt;
*Aller sur la page d'un extrait de compte ou sur la liste des mouvements : '''Gestion &amp;gt; Comptes &amp;gt; Flux &amp;gt; Mouvements'''&lt;br /&gt;
*Dans la colonne '''Actions''', cliquer sur le pictogramme '''Contrepasser le flux'''&lt;br /&gt;
*Une alerte demande de confirmer le souhait de créer une écriture de contrepassation&lt;br /&gt;
*Cela crée une écriture opposée, à la date de l'écriture initiale, qui a pour commentaire le texte &amp;quot;Contrepassation flux X du XX/XX/XXXX&amp;quot;. L'écriture générée est directement validée.&lt;br /&gt;
&lt;br /&gt;
==Modifier un flux==&lt;br /&gt;
* Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Flux &amp;gt; Valider''' ou dans l'[[Gestion-de-la-comptabilité-côté-utilisateur#Extrait-de-compte|extrait de compte]]&lt;br /&gt;
* Cliquer sur l'icône &amp;quot;Crayon&amp;quot; correspond au flux à éditer&lt;br /&gt;
* [[#Saisir-un-flux|Procéder à éditer le flux]]&lt;br /&gt;
&lt;br /&gt;
==[[Écritures comptables#Avoir_clients|Saisie d'un avoir client]]==&lt;br /&gt;
Il faut [[#Saisir-un-flux|saisir un flux]] qui va créditer un compte utilisateur/client d'un certain montant et débiter un compte produit &amp;quot;Remise X&amp;quot; du même montant.&lt;br /&gt;
&lt;br /&gt;
==Saisir un flux==&lt;br /&gt;
Pour saisir un flux, il faut :&lt;br /&gt;
*Soit aller dans '''Gestion &amp;gt; Comptes &amp;gt; Flux &amp;gt; Saisir'''&lt;br /&gt;
*Soit afficher un extrait de compte et cliquer sur le bouton '''Saisir un flux''' situé en bas à droite de l'affichage du compte à droite de la ligne du solde.&lt;br /&gt;
Si le gestionnaire arrive sur le formulaire de saisie d'un flux depuis un extrait de compte, alors la première ligne est pré-remplie avec le compte depuis lequel le formulaire a été affiché.&lt;br /&gt;
&lt;br /&gt;
Sinon, Il faut sélectionner sur la première ligne de compte, le compte souhaité. Pour cela, il est possible de cliquer sur le champ afin de faire apparaitre la liste de tous les comptes. Ils sont regroupés par catégorie et dans chaque catégorie triés par ordre alphabétique. A droite de chaque nom de compte apparait entre parenthèses le compte d'export associé. &lt;br /&gt;
&lt;br /&gt;
Il est possible de renseigner dans le champ de saisie quelques lettres correspondantes à une partie du nom du compte afin de faire apparaitre la liste des comptes qui correspondent. Il est également possible de saisir quelques chiffres du compte d'export.&lt;br /&gt;
*Remplir le champ débit ou crédit selon le cas&lt;br /&gt;
S'il n'y a que 2 lignes comptables pour le flux :&lt;br /&gt;
*Sélectionner sur la 2ème ligne un compte de contre-partie&lt;br /&gt;
*Sur cette 2ème ligne, cliquer sur l'icône qui symbolise une balance avec une flèche bleue et intitulé &amp;quot;Equilibrer la dernière ligne&amp;quot;&lt;br /&gt;
S'il y a plus 2 lignes comptables pour le flux :&lt;br /&gt;
*Cliquer sur le pictogramme symbolisant un &amp;quot;plus&amp;quot; dans la colonne '''Action''' de la dernière ligne du flux afin de faire apparaitre une ligne supplémentaire&lt;br /&gt;
*Répéter cette opération autant de fois que nécessaire&lt;br /&gt;
Une fois que l'ensemble des lignes du flux sont remplies :&lt;br /&gt;
*Compléter éventuellement le champ '''commentaires'''&lt;br /&gt;
*Choisir une date comptable dans le champ '''Date comptable''' en cliquant sur l'icône associée. Si la date est à la date du jour l'heure courante est utilisée. Sinon la date est définie à 12:00 heure locale.&lt;br /&gt;
*Cliquer sur le bouton '''Valider'''&lt;br /&gt;
Remarque : La date comptable proposée par défaut correspond à la date comptable du dernier flux saisi. Cela permet de faciliter les [[Comptabilité#Règles_de_saisies_de_la_comptabilité_courante|saisies au vu du relevé de banque]].&lt;br /&gt;
&lt;br /&gt;
==Solder les comptes charges, produits et ressources==&lt;br /&gt;
Pour solder des comptes charges, produits et ressources en un seul flux vers un compte de contrepartie à partir de la date de début d'exercice comptable jusqu'à une date désirée, aller dans '''Gestion &amp;gt; Comptes &amp;gt; Gestion &amp;gt; Gestion / Export'''. Seulement les comptes actifs seront soldés.&lt;br /&gt;
&lt;br /&gt;
Dans cette interface :&lt;br /&gt;
* Décocher les comptes ressources à ne pas solder&lt;br /&gt;
* Sélectionner la date&lt;br /&gt;
* Sélectionner la comptabilité&lt;br /&gt;
* Choisir un compte de contrepartie&lt;br /&gt;
* Cliquer sur '''Générer les écritures'''&lt;br /&gt;
&lt;br /&gt;
==Solder un compte==&lt;br /&gt;
Pour solder un compte, il faut [[#Saisir-un-flux|saisir un flux]] avec la particularité que l'on souhaite &amp;quot;ramener le solde à zéro&amp;quot; d'un compte donné. Pour cela, il faut en plus des [[#Saisir-un-flux|opérations]] indiquées pour la saisie d'un flux, il faut :&lt;br /&gt;
*dans la première ligne de compte, sélectionner le compte concerné&lt;br /&gt;
*Cliquer sur l'icône qui symbolise une balance intitulé &amp;quot;Ramener le solde à zéro&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Validation d'un flux==&lt;br /&gt;
Pour pouvoir valider les flux, il faut disposer des droits [[Gestion-des-profils#Valider-tout-flux|Valider tout flux]] et [[Gestion-des-profils#Saisir-tout-flux|Saisir tout flux]].&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Flux &amp;gt; Valider'''&lt;br /&gt;
*Cocher dans la 1ère colonne '''Pointer''' les lignes à valider&lt;br /&gt;
*Cliquer sur le bouton '''Valider les flux sélectionnés (cette action est irréversible)'''&lt;br /&gt;
&lt;br /&gt;
=Solder les comptes=&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Gestion &amp;gt; Solder les comptes'''&lt;br /&gt;
*Dans la première colonne, laisser tous les comptes &amp;quot;Ressources&amp;quot; cochés sauf si certains ne sont pas des comptes d'exploitation&lt;br /&gt;
*Dans la deuxième colonne, la date proposée dans le champ '''A la date du''' doit correspondre au 31 décembre de l'année de l'exercice comptable en cours&lt;br /&gt;
*Si plusieurs comptabilités sont paramétrées, un le champ '''Comptabilité''' est visible, sélectionner la comptabilité souhaitée : il faudra effectuer cette opération pour chacune des comptabilités de la plateforme&lt;br /&gt;
*Dans le champ '''Compte de contrepartie''', sélectionner le compte de bilan souhaité&lt;br /&gt;
**Par défaut, est sélectionné, soit le compte '''Report à nouveau (Bilan)''' pour la comptabilité générale, soit le compte utilisé lors du précédent import&lt;br /&gt;
*Cliquer sur le bouton '''Générer les écritures'''&lt;br /&gt;
&lt;br /&gt;
Ce module génère alors un unique flux qui solde les comptes de charges, de produits et ceux liés aux ressources vers un compte de contrepartie de sorte que ces comptes soient ramenés à 0 à la date sélectionnée.&lt;br /&gt;
&lt;br /&gt;
Seuls les comptes actifs sont pris en compte.&lt;br /&gt;
&lt;br /&gt;
Le flux généré est modifiable.&lt;br /&gt;
&lt;br /&gt;
Après avoir cliqué sur le bouton '''Générer les écritures''', le gestionnaire est redirigé vers '''Admin &amp;gt; Comptes &amp;gt; Valider les flux''' avec par défaut l'affichage du mois et de l'année correspondant aux flux générés afin de lui permettre de valider ces flux. Cette opération est nécessaire avant de pouvoir [[#Clôturer-l'exercice-comptable|Clôturer l'exercice comptable]].&lt;br /&gt;
&lt;br /&gt;
=Valider toutes les écritures=&lt;br /&gt;
OpenFlyers permet de valider toutes les écritures comprises avant une date choisie.&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Gestion &amp;gt; Valider'''&lt;br /&gt;
*Dans la 1ère colonne intitulée '''Statistiques''', la date de début de l'exercice comptable est renseignée ainsi qu'un tableau indiquant le nombre d'écritures non validés avec la date de la première écriture non validée.&lt;br /&gt;
*Dans la 2ème colonne intitulée '''Valider''', renseigner la date '''Valider les écritures jusqu'au :''' en cliquant sur le calendrier.&lt;br /&gt;
** Cette date ne doit pas être inférieure à la date de début de l'exercice comptable.&lt;br /&gt;
** Et, ne doit pas être supérieure au 31 décembre de l'année précédente.&lt;br /&gt;
* Activer l'interrupteur '''Autoriser''' et cliquer sur le button '''Valider toutes les écritures'''&lt;br /&gt;
&lt;br /&gt;
=Factures fournisseurs=&lt;br /&gt;
==Saisir des factures fournisseurs==&lt;br /&gt;
[https://www.youtube.com/watch?v=QVUgYEfqDk0 Vidéo tutorielle pour saisir une facture fournisseur]&lt;br /&gt;
&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Achats &amp;gt; Saisie Factures fournisseurs'''.&lt;br /&gt;
*Vous vous retrouvez alors avec le formulaire de saisie suivant :&lt;br /&gt;
&lt;br /&gt;
2 cas peuvent se présenter :&lt;br /&gt;
*Soit [[#Saisir-une-facture-fournisseur-dont-le-type-de-facture-est-déjà-enregistré|le type de facture fournisseur correspondant à la facture à saisir est déjà existant]]&lt;br /&gt;
*Soit la facture fournisseur à saisir nécessite la création d'un nouveau type de facture fournisseur. Dans ce cas, il existe plusieurs façons de créer un nouveau type de facture fournisseur dont la possibilité de [[#Saisir-une-facture-fournisseur-dont-le-type-est-nouveau|le faire directement en saisissant la facture]].&lt;br /&gt;
&lt;br /&gt;
Vous pouvez importer un fichier en plus si nécessaire. Seulement [[Gestion-des-documents#Type-de-fichier-autorisé|certains types de fichiers sont autorisés]].&lt;br /&gt;
&lt;br /&gt;
===Saisir une facture fournisseur dont le type de facture est déjà enregistré===&lt;br /&gt;
*Sélectionner le '''type de facture fournisseur''' correspondant à la facture à saisie. Le nombre de champs à renseigner se réduit alors automatiquement :&lt;br /&gt;
*Reporter sur la facture originale le '''numéro de pointage''' qui apparaît dans le formulaire. Ce numéro de pointage est unique et permet de rapprocher les factures fournisseurs saisies dans OpenFlyers avec leurs originaux.&lt;br /&gt;
*Cocher &amp;quot;'''J'ai bien pris en compte cette valeur et je l'ai reporté sur ma facture'''&amp;quot;. A défaut, si vous validez, le système refusera votre saisie et une alerte apparaitra.&lt;br /&gt;
*Le champ '''Description''' permet d'indiquer toute information utile concernant la facture et d'en faciliter la recherche ultérieure.&lt;br /&gt;
*Indiquer la date de facturation en cliquant sur le calendrier. Il est possible de paramétrer le format d'affichage de la date en allant dans le menu '''Données/Affichage''' puis de modifier le contenu du champ '''fiche personnelle/Patron de format de date'''.&lt;br /&gt;
*Renseigner le '''montant hors taxe'''&lt;br /&gt;
*Renseigner la '''TVA''' (champ visible uniquement si la comptabilité est paramétrée pour la prise en compte de la TVA). Si la TVA est nulle, il faut indiquer 0.&lt;br /&gt;
*Cliquer sur '''Valider''' ou '''Valider et Saisir le suivant''' si vous avez plusieurs factures à saisir à la volée. Dans ce dernier cas, le formulaire de saisie de facture fournisseur s'affiche à nouveau et il faut reprendre les opérations de saisie depuis le début de ce paragraphe.&lt;br /&gt;
&lt;br /&gt;
===Saisir une facture fournisseur dont le type est nouveau===&lt;br /&gt;
Lors de la saisie d'un nouveau compte fournisseur, aucun élément n'est renseigné par défaut.&lt;br /&gt;
&lt;br /&gt;
Plusieurs parties du formulaire peuvent se réduire à partir du moment où dans le champ précédant la partie réductible, l'utilisateur remplace '''Autre...''' par un choix proposé. A contrario, en laissant '''Autre...''' ou '''Associer un nouveau compte''' (dans le cas du premier champ), c'est l'information saisie dans le champ suivant qui sera prise en compte.&lt;br /&gt;
&lt;br /&gt;
La saisie va consister à définir les ventilations comptables associée à ce type de facture fournisseur. A savoir :&lt;br /&gt;
*le fournisseur et son compte fournisseur qui sera crédité du montant des factures associées à ce type de facture fournisseur&lt;br /&gt;
*le compte de charge qui sera débité du montant des factures associées à ce type de facture fournisseur&lt;br /&gt;
*Si la gestion de la TVA est activée, le compte de TVA qui sera débité du montant de la TVA associée à ce type de facture fournisseur&lt;br /&gt;
*De plus, si la gestion des budgets est activée, il est demandé, pour chaque compte (fournisseur, charge et TVA), le budget à associer&lt;br /&gt;
&lt;br /&gt;
*Ainsi, si on doit saisir une facture fournisseur associée à un nouveau type de facture fournisseur, alors il faut laisser '''associer un nouveau compte''' au champ '''Type de facture fournisseur''' et renseigner l'intitulé souhaité pour le type de facture fournisseur dans le champ suivant '''Nom de type de facture'''&lt;br /&gt;
*Ensuite, dans le champ '''Fournisseur''', là aussi, 2 cas peuvent se présenter :&lt;br /&gt;
**Soit le fournisseur à mentionner est déjà dans la liste proposée dans le champ '''Fournisseur''' et auquel cas il faut le sélectionner (et le champ suivant '''Nom du fournisseur''' disparaitra)&lt;br /&gt;
**Soit le fournisseur à mentionner n'est pas déjà dans la liste proposée dans le champ '''Fournisseur''' et il faut dans ce cas :&lt;br /&gt;
***Si la gestion des budgets est active : choisir dans le champ suivant un '''Budget à attribuer'''' au fournisseur ou laisser '''Aucun budget'''. On peut, par exemple, sélectionner pour tous les fournisseurs un budget ''Fournisseurs''.&lt;br /&gt;
***Renseigner le champ '''Nom du fournisseur''' qui doit correspondre au fournisseur souhaité&lt;br /&gt;
***Choisir un compte d'export associé au nouveau fournisseur créé :&lt;br /&gt;
****Soit il existe déjà un compte d'export dans le champ '''Compte du fournisseur'''&lt;br /&gt;
****Soit il n'existe pas de compte d'export associable à ce nouveau fournisseur (en général on associe un compte d'export différent pour chaque compte défini dans OpenFlyers) et auquel cas, il faut renseigner le champ '''Compte fournisseur d'export'''. On peut, par exemple, saisir ''401NOMDUFOURNISSEUR'' dans le cas du plan comptable français.&lt;br /&gt;
***Si la gestion des budgets est active, le champ suivant est '''Budget à attribuer''' et OpenFlyers a dû le remplir par défaut avec la même valeur que pour le champ du même nom rattaché au '''Nom du fournisseur'''. Il ne doit pas y avoir besoin de modifier le contenu de ce champ.&lt;br /&gt;
*Dans le champ '''Compte de charge''', 2 cas peuvent se présenter :&lt;br /&gt;
**Soit le compte de charge à associer est déjà dans la liste proposée et auquel cas il faut le sélectionner&lt;br /&gt;
**Soit le compte de charge à associer n'est pas déjà dans la liste proposée et il faut dans ce cas :&lt;br /&gt;
***Si la gestion des budgets est active : choisir dans le champ suivant un '''Budget à attribuer''' au compte de charge que l'on crée ou laisser '''Aucun budget'''. On peut, par exemple, sélectionner un budget représentatif du type de facture et ainsi avoir la ventilation de toutes les factures fournisseurs par poste budgétaire&lt;br /&gt;
***Renseigner le champ '''Nom du compte''' avec l'intitulé correspondant au compte de charge à créer&lt;br /&gt;
***Renseigner le champ '''Compte d'export''' avec la valeur du plan comptable correspondante. Pour le plan comptable français, ce sera un compte en 6xx.&lt;br /&gt;
*Si la gestion de la TVA est activée, le champ '''Compte TVA du type de facture''' est présent et 2 cas peuvent se présenter :&lt;br /&gt;
**Soit le compte de TVA à associer à ce type de facture est dans la liste proposée et auquel cas il faut le sélectionner&lt;br /&gt;
**Soit le compte de TVA n'existe pas et il faut dans ce cas :&lt;br /&gt;
***Si la gestion des budgets est active : choisir dans le champ suivant un '''Budget à attribuer''' au compte de TVA que l'on crée ou laisser '''Aucun budget'''. On peut, par exemple, sélectionner un budget ''TVA Fournisseur''&lt;br /&gt;
***Renseigner le champ '''Nom de compte TVA'''. Par exemple, dans le cas des factures fournisseurs provenant de France : ''TVA déductible sur autres biens et services''&lt;br /&gt;
***Renseigner le champ '''Compte TVA d'export'''. Par exemple, dans le cas des factures fournisseurs provenant de France : ''445660''.&lt;br /&gt;
*Le reste de la saisie s'effectue comme pour la [[#Saisie_d'une_facture_fournisseur_dont_le_type_de_facture_est_déjà_enregistré|saisie d'une facture fournisseur dont le type de facture est déjà enregistré]].&lt;br /&gt;
&lt;br /&gt;
===Supprimer une facture fournisseur===&lt;br /&gt;
Pour supprimer une facture fournisseur qui aurait été saisie par erreur, il faut :&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Achats &amp;gt; Liste des factures fournisseurs''' ;&lt;br /&gt;
&lt;br /&gt;
*Rechercher le '''numéro de pointage''' de la facture concernée en ayant pris soin au préalable de sélectionner le mois de la facture (ou l'année complète pour lister l'ensemble des factures).&lt;br /&gt;
*Cliquer sur l'icône poubelle associée à la facture concernée.&lt;br /&gt;
&lt;br /&gt;
Le numéro de la facture supprimée n'existera plus dans la comptabilité. Il ne sera pas proposé à nouveau lors de la saisie d'une nouvelle facture. Par ailleurs, la numérotation des factures saisies a posteriori de la facture supprimée demeurera inchangée.&lt;br /&gt;
&lt;br /&gt;
===Supprimer un type de facture fournisseur===&lt;br /&gt;
Pour supprimer un type de facture fournisseur qui aurait été saisi par erreur, il faut :&lt;br /&gt;
&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Achats &amp;gt; Types de factures fournisseurs''' ;&lt;br /&gt;
&lt;br /&gt;
*Sélectionner le type de fournisseur concerné dans la colonne '''Nom''' ;&lt;br /&gt;
&lt;br /&gt;
*Cliquer sur l'icône poubelle associée à la facture concernée.&lt;br /&gt;
&lt;br /&gt;
==Saisir un [[Écritures comptables#Paiement_(à_un_fournisseur)|paiement à un fournisseur]]==&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Comptes &amp;gt; Flux &amp;gt; Saisir'''&lt;br /&gt;
*Sur la première ligne :&lt;br /&gt;
**dans la colonne '''Compte''' sélectionner le compte du fournisseur&lt;br /&gt;
**dans la colonne '''Débit''' saisir le montant du paiement que vous effectuez. Si vous souhaiter solder le compte du fournisseur, il vous suffit de cliquer sur l'icône représentant une balance et intitulée &amp;quot;Ramener le solde à zéro&amp;quot;&lt;br /&gt;
*Sur la deuxième ligne :&lt;br /&gt;
**dans la colonne '''Compte''' sélectionner le compte bancaire depuis lequel l'argent est débité&lt;br /&gt;
**cliquer sur l'icône représentant une balance avec une flèche bleue et intitulée &amp;quot;Equilibrer la dernière ligne&amp;quot;&lt;br /&gt;
*Dans le champ '''Commentaires''' saisir un texte libre&lt;br /&gt;
*Ne pas oublier de renseigner le champ '''Date comptable'''&lt;br /&gt;
*Cliquer sur le bouton '''Valider'''&lt;br /&gt;
&lt;br /&gt;
=Bon de commande et facture clients=&lt;br /&gt;
&lt;br /&gt;
==Visualiser des factures au format PDF==&lt;br /&gt;
Nous conseillons de se connecter en https à votre espace http://openflyers.com/demo-fr/index.php&lt;br /&gt;
&lt;br /&gt;
OpenFlyers propose par défaut un [[Modèle de facture ODT|modèle de facture]] qui permet d'éditer des factures PDF pour les prestations suivantes :&lt;br /&gt;
*les achats réalisés depuis le gestionnaire des ventes&lt;br /&gt;
**depuis la page du planning de réservation, cliquer sur le menu '''Comptes/Acheter'''.&lt;br /&gt;
*les validités qui ont été achetées/renouvelées&lt;br /&gt;
*les vols.&lt;br /&gt;
**Aller dans le menu '''Comptes/Etat/Pilote''' et se rendre dans la [[Gestion de la comptabilité côté utilisateur#Colonne-Numéro-de-pointage-ou-de-facture|colonne numéro de pointage ou de facture]]&lt;br /&gt;
&lt;br /&gt;
==Importer son [[Modèle de facture ODT|modèle de facture]]==&lt;br /&gt;
&lt;br /&gt;
'''/!\ En important un [[Modèle de facture ODT|modèle de facture]], ce sera celui-ci qui va être utilisé pour générer les nouvelles factures au format PDF. Les factures qui ont déjà créées avant la mise en place du nouveau modèle continuera d'appliquer les anciens versions du modèle ou ceux fournis par défaut par OF'''&lt;br /&gt;
&lt;br /&gt;
Le droit [[Gestion-des-profils#Gestion-du-paramétrage|Gestion du paramétrage]] est nécessaire pour cette fonctionnalité.&lt;br /&gt;
&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Structure &amp;gt; Imports &amp;gt; Templates ODT'''.&lt;br /&gt;
* Préparer le fichier ODT contenant tous les modèles utilisés qui doivent être organisés comme suit :&lt;br /&gt;
**'''page 1''' : Facture client&lt;br /&gt;
**'''page 2''' : Duplicata de la facture client&lt;br /&gt;
*Importer  le fichier&lt;br /&gt;
*Cocher '''Facturation client'''&lt;br /&gt;
*Valider&lt;br /&gt;
&lt;br /&gt;
==Calcul du montant HT, de la TVA et du montant TTC==&lt;br /&gt;
&lt;br /&gt;
Les différents montants sont calculés de la sorte :&lt;br /&gt;
* Pour la TVA, on effectue la somme des écritures de débit et de crédit liés aux&lt;br /&gt;
** comptes de catégorie TVA&lt;br /&gt;
** produits de type de vente TVA&lt;br /&gt;
* Pour le montant TTC, on effectue la somme des écritures de débit et de crédit liées aux&lt;br /&gt;
** comptes qui ne sont pas de catégorie TVA&lt;br /&gt;
** produits qui ne sont pas de type de vente TVA&lt;br /&gt;
* Pour le montant HT, on effectue la différence entre la TVA et le montant TTC&lt;br /&gt;
&lt;br /&gt;
==Relevés de factures clients==&lt;br /&gt;
Une facture client est un document unique. Les PDF d'une facture déjà exportée seront générés avec la mention &amp;quot;Duplicata&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Formulaire de sélection===&lt;br /&gt;
Ce formulaire permet d'établir une sélection générale de factures clients.&lt;br /&gt;
*Aller dans '''Gestion &amp;gt; Rapports &amp;gt; Rapports spécifiques &amp;gt; Relevés de factures clients'''&lt;br /&gt;
*Les champs &amp;quot;A partir du&amp;quot; et &amp;quot;Jusqu'au&amp;quot; permettent d'établir une sélection en fonction des dates de facturation. Pour éviter un temps de chargement trop long, il est conseillé de définir une plage d'un mois maximum.&lt;br /&gt;
*Le champ &amp;quot;Compte client&amp;quot; permet de sélectionner les relevés de factures d'un client particulier&lt;br /&gt;
*Le champ &amp;quot;Types de vols&amp;quot; permet de sélectionner des factures en fonction du type de vol&lt;br /&gt;
*Le champ &amp;quot;Produits non stockés&amp;quot; permet de sélectionner des factures en fonction de la nature du produit&lt;br /&gt;
*Le champ &amp;quot;Validités&amp;quot; permet de sélectionner des factures en fonction des produits de type &amp;quot;validité&amp;quot;&lt;br /&gt;
*Valider pour accéder aux factures à exporter&lt;br /&gt;
&lt;br /&gt;
===Tableau de factures à exporter===&lt;br /&gt;
Ce tableau est le résultat du formulaire. Il liste des factures clients.&lt;br /&gt;
*Sélectionner au cas par cas les factures à exporter&lt;br /&gt;
*Cliquer sur le bouton '''Générer PDF''' en bas du tableau pour générer le PDF des factures sélectionnées&lt;br /&gt;
*Cliquer sur le bouton '''Sauver dans un fichier CSV''' en bas du tableau pour exporter les factures sélectionnées au format CSV&lt;br /&gt;
&lt;br /&gt;
=Gestion des règlements clients=&lt;br /&gt;
==Saisir un encaissement==&lt;br /&gt;
&lt;br /&gt;
Préambule : Se référer aux [[Écritures comptables#Encaissement-(d'un-client)|mouvements associés à un encaissement client]] pour connaitre les mouvements créés lors de la saisie comptable.&lt;br /&gt;
&lt;br /&gt;
* Aller dans '''Planning &amp;gt; Comptes &amp;gt; Approvisionner''' ou '''Gestion &amp;gt; Comptes &amp;gt; Encaissements &amp;gt; Saisir'''&lt;br /&gt;
*'''Comptes clients''' :&lt;br /&gt;
**Si le payeur est un utilisateur de la plateforme, laisser sélectionné '''Utilisateur'''&lt;br /&gt;
**Sinon, sélectionner '''Non-utilisateur'''&lt;br /&gt;
*(facultatif) '''Email client''' : si '''Non-utilisateur''' est sélectionné, saisir l'adresse email du client où sera [[Envoi-des-emails#E-mail-de-reçu|envoyé le reçu pour le paiement]]&lt;br /&gt;
*'''Encaissement de l'utilisateur''' : sélectionner le nom de l'utilisateur effectuant le paiement&lt;br /&gt;
ou&lt;br /&gt;
*'''Compte à créditer''' : sélectionner le nom du client &amp;quot;connu&amp;quot; ou à défaut &amp;quot;Clients extérieurs&amp;quot;&lt;br /&gt;
** Seuls les [[Comptabilité#Comptes_clients|comptes clients]] et les [[Comptabilité#Comptes_utilisateurs|comptes utilisateurs]] peuvent recevoir des encaissements. En effet, comptablement, cela n'a pas de sens de faire un encaissement sur d'autres types de comptes.&lt;br /&gt;
** Il faut sélectionner le compte correspondant à celui qui a été facturé et donc débité.&lt;br /&gt;
*'''Type de règlement''' : sélectionner le type de règlement.&lt;br /&gt;
** Les types de règlement disponibles dépendent du compte à créditer pour s'assurer que [[Gestion-de-la-comptabilité-côté-utilisateur#Les-comptes-n'ont-pas-la-même-comptabilité|les comptes ont la même comptabilité]].&lt;br /&gt;
*'''Montant''' : indiquer le montant du paiement qui doit être dans l'intervalle '''[Montant minimum, Montant maximum]''' autorisé pour chaque [[Configuration-de-la-comptabilité#Types-d'encaissements|type d'encaissement]].&lt;br /&gt;
*'''Date du paiement''' :&lt;br /&gt;
**pour les paiements par chèque on laisse en général la date du jour qui correspond &amp;quot;au mieux&amp;quot; à la date à laquelle l'encaissement sera fait.&lt;br /&gt;
**pour les paiements en espèce on met la date à laquelle les sommes ont été reçus.&lt;br /&gt;
**pour les paiements par virement on met la date du virement.&lt;br /&gt;
*'''Heure du paiement''' : l'heure est saisie automatiquement et ne peut pas être saisie manuellement&lt;br /&gt;
**Si la date du paiement correspond à la date du jour alors c'est l'heure courante qui est saisi&lt;br /&gt;
**Autrement, l'heure est fixée à 12h00.&lt;br /&gt;
*Cliquer sur le bouton '''Valider''' ou le bouton '''VALIDER ET SAISIR LE SUIVANT'''&lt;br /&gt;
&lt;br /&gt;
==Saisir l'encaissement d'un comité d'entreprise ou d'un groupement d'utilisateurs==&lt;br /&gt;
Dans le cas où un comité d'entreprise ou un groupement d'utilisateurs (comme la DGAC dans le cas des contrôleurs aériens) prend en charge tout ou partie du coût d'une activité générée par OpenFlyers, la plateforme est normalement configurée pour que ce soit le compte du CE ou du groupement qui soit automatiquement débité lors de la saisie de l'activité.&lt;br /&gt;
&lt;br /&gt;
De ce fait, saisir dans OpenFlyers un règlement provenant d'une telle entité revient à [[#Saisir_un_encaissement|saisir un encaissement d'un &amp;quot;non-utilisateur&amp;quot; sur son propre compte client]].&lt;br /&gt;
&lt;br /&gt;
==Validation des règlements clients==&lt;br /&gt;
La personne en charge de la gestion des encaissements doit valider les règlements avant de remettre l'argent en banque, que la saisie soit faite pas un utilisateur final ou par un gestionnaire de la structure.&lt;br /&gt;
&lt;br /&gt;
Tant qu'une écriture n'est pas validée, elle apparaît différemment dans les extraits de compte afin de bien signifier que le mouvement n'est pas validé et que le solde du compte est donc susceptible d'être modifié. Une écriture non validée peut être modifiée mais '''Une fois la validation effectuée'''  il n'est plus possible de '''revenir en arrière'''. &lt;br /&gt;
&lt;br /&gt;
En cas d'erreur, la personne en charge de la tenue des comptes doit saisir une écriture d'annulation et ressaisir le règlement correct.&lt;br /&gt;
&lt;br /&gt;
Pour valider les règlements la personne en charge de la gestion des encaissements dispose d'une page accessible uniquement avec le droit &amp;quot;'''Valider les encaissements'''&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Voici la description de la tâche de validation des règlements de type &amp;quot;Chèques&amp;quot; :&lt;br /&gt;
*Récupérer les chèques et espèces à valider&lt;br /&gt;
*Classer les chèques par ordre de date.&lt;br /&gt;
*Aller dans la page '''Gestion &amp;gt; Comptes &amp;gt; Pointer &amp;gt; Chèques'''&lt;br /&gt;
*Cette pages affiche les règlements saisis et qui sont en attente de validation&lt;br /&gt;
*Cocher les règlements correspondants à aux chèques physiquement présents.&lt;br /&gt;
*Si des règlements ne sont pas dans la liste en attente, la personne en charge de la gestion des encaissements les ajoute à l'aide d'un bouton prévu à cet effet puis les coche.&lt;br /&gt;
*Si des saisies sont erronées, il faut les corriger puis les cocher.&lt;br /&gt;
*Supprimer les saisies inopportunes.&lt;br /&gt;
*Une fois que tout les chèques sont pointés, cliquer sur '''Éditer le bordereau de remise'''.&lt;br /&gt;
*On passe sur la page de la liste des règlements validés : faire une vérification&lt;br /&gt;
*Imprimer le bordereau de remise en banque avec la [[Navigateurs#Imprimer-avec-un-navigateur|fonction prévue à cet effet du navigateur]]&lt;br /&gt;
*Valider le bordereau. '''Attention, cette action est irréversible'''&lt;br /&gt;
A l'issue de cette procédure, il faut porter la remise en banque.&lt;br /&gt;
&lt;br /&gt;
Une fois le paiement validé, [[Envoi-des-emails#E-mail-de-reçu|un email sera automatiquement envoyé à l'utilisateur avec en pièce-jointe le reçu au format PDF]].&lt;br /&gt;
&lt;br /&gt;
Le processus est le même pour les autres types de règlements à l'exception des [[Paiement en ligne|paiements en ligne]] qui sont automatiquement validées et qui par conséquent ne nécessitent pas de pointage.&lt;br /&gt;
&lt;br /&gt;
Il est possible de retrouver la liste des encaissements par type et pour la période souhaitée dans le [[Gestion-des-rapports|rapport]] '''Gestion &amp;gt; Comptes &amp;gt; Rapports &amp;gt; Paiements par type'''.&lt;br /&gt;
&lt;br /&gt;
Le [[Gestion-des-rapports|rapport]] '''Gestion &amp;gt; Comptes &amp;gt; Rapports &amp;gt; Ventilation des encaissements''' permet d'avoir le tableau du total des encaissements par mois et par type.&lt;br /&gt;
&lt;br /&gt;
'''La validation régulière des règlements permet de bloquer les modifications par les utilisateurs et facilite la tenue de la comptabilité'''.&lt;br /&gt;
&lt;br /&gt;
=Cas particuliers=&lt;br /&gt;
==Ecritures manuelles dans le cadre [[Conseils spécifiques pour la comptabilité#Facturation_automatique_à_des_organismes_avec_ou_sans_quotas|d'une facturation automatique à un organisme tiers]]==&lt;br /&gt;
Normalement, le paramétrage d'une plateforme OpenFlyers est effectué pour que les écritures soient automatiquement réalisées lors de la saisie d'une activité.&lt;br /&gt;
&lt;br /&gt;
Cependant, si les écritures ne se sont pas effectuées automatiquement, ne serait-ce que dans le cas où le paramétrage a été mis en place ultérieurement à la saisie d'activité et que ces saisies ont été validées, il est nécessaire d'effectuer la saisie manuelle des flux permettant d'obtenir la [[Facturation des clients#Cascade_d'écritures_comptables|situation comptable souhaitée]].&lt;br /&gt;
&lt;br /&gt;
Ainsi, si l'utilisateur a été intégralement débité du montant de l'activité et qu'il faut simplement saisir une écriture permettant de créditer son compte du montant devant être débité à l'organisme tiers, il suffit de [[#Saisir-un-flux|saisir un flux]] qui va créditer son compte du montant concerné et débiter le compte de l'organisme tiers du même montant.&lt;br /&gt;
&lt;br /&gt;
De plus, si une gestion de quota est en place, il faut également corriger le compte de quota de l'utilisateur concerné sur le même modèle d'écriture que pour l'[[Conseils spécifiques pour la comptabilité#Initialisation_du_solde_d'heures_lors_de_la_mise_en_place_des_packs|initialisation d'un quota]] mais en sens opposé (le compte quota de l'utilisateur doit être débité au lieu d'être crédité et inversement pour le compte de bilan correspondant).&lt;br /&gt;
&lt;br /&gt;
==Gestion des baptêmes==&lt;br /&gt;
Certaines structures utilisent le terme &amp;quot;Vol découverte&amp;quot; pour parler des baptêmes de l'air. Il est important d'avoir en tête que le grand public ne connait que le terme &amp;quot;Baptême de l'air&amp;quot; et que par conséquent ce terme est sans commune mesure plus utilisé dans les moteurs de recherche en comparaison au terme &amp;quot;Vol découverte&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===Utiliser le [[Configuration de la comptabilité#Gestion_des_baptêmes|paramétrage préconisé des baptêmes]]===&lt;br /&gt;
On appelle dans l'exemple &amp;quot;Clients extérieurs&amp;quot; le compte client qui est utilisé pour les clients baptêmes. La dénomination peut changer d'une configuration à l'autre.&lt;br /&gt;
Lorsqu'un baptême est effectué :&lt;br /&gt;
#Saisir le vol avec comme type de vol &amp;quot;baptême&amp;quot; : le coût du vol au tarif solo est alors débité sur le compte client &amp;quot;Clients extérieurs&amp;quot;.&lt;br /&gt;
#Encaisser le paiement du baptême sur le compte client &amp;quot;Clients extérieurs&amp;quot; (qui est accessible dans le formulaire de saisie des encaissements en sélectionnant comme type d'utilisateur &amp;quot;non utilisateur&amp;quot;).&lt;br /&gt;
Ainsi, le compte client &amp;quot;Clients extérieurs&amp;quot; se retrouvera avec un solde correspondant à la différence entre le prix du baptême payé par le client et le prix du vol solo facturé par OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
Il suffit alors de passer une écriture, par exemple tous les mois, tous les trimestres ou tous les ans, entre le compte &amp;quot;Clients extérieurs&amp;quot; et un compte produit (par exemple compte produit &amp;quot;gain baptêmes&amp;quot;) qui va recevoir le solde du compte client &amp;quot;Clients extérieurs&amp;quot; afin de le ramener à 0.&lt;br /&gt;
&lt;br /&gt;
Cas pratique :&lt;br /&gt;
*Tarif solo : 100 €/h&lt;br /&gt;
*Tarif baptême : 60 €&lt;br /&gt;
*Vol effectué de 30 minutes&lt;br /&gt;
&lt;br /&gt;
Alors :&lt;br /&gt;
*En saisissant le vol de 30 minutes en tant que &amp;quot;baptême&amp;quot;, le compte &amp;quot;clients extérieurs&amp;quot; sera débité du montant du tarif solo soit 50 €.&lt;br /&gt;
*En saisissant l'encaissement du paiement de 60 € effectué par le baptisé, le compte &amp;quot;clients extérieurs&amp;quot; sera crédité de 60 €.&lt;br /&gt;
*Il est résulte sur le compte &amp;quot;clients extérieur&amp;quot; un solde positif de 10 €.&lt;br /&gt;
A la fin de l'année, le compte &amp;quot;clients extérieur&amp;quot; aura vu son solde augmenter au fur et à mesure que les baptêmes auront été effectuée. Admettons qu'il se retrouve avec un solde positif de 1210 €. Il faut alors passer un mouvement (via la saisie d'un flux) pour débiter le compte &amp;quot;clients extérieurs&amp;quot; de 1210 € et créditer un compte produit &amp;quot;delta baptêmes&amp;quot; de 1210 €. Ce faisant le solde du compte client &amp;quot;clients extérieurs&amp;quot; est ramené à 0 ce qui est important pour montrer comptablement que personne ne doit de l'argent à l'aéro-club et le gain spécifique aux baptêmes est enregistré dans le compte produit &amp;quot;delta baptêmes&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Mettre à jour un plafond d'heures ou d'argent sur une comptabilité parallèle==&lt;br /&gt;
Certaines plateformes sont paramétrées avec une comptabilité parallèle permettant de [[Conseils-spécifiques-pour-la-comptabilité#Facturation-automatique-à-des-organismes-avec-ou-sans-quotas|gérer des quotas d'heures ou d'argent]] pour des utilisateurs du fait de leur appartenance à une entreprise, un comité d'entreprise ou un comité d'établissement public, etc.&lt;br /&gt;
&lt;br /&gt;
Les utilisateurs disposent alors d'un 2ème compte qui permet de suivre l'évolution de leur utilisation du quota qui leur est attribué, par exemple annuellement. Si le montant crédité automatiquement ne correspond pas au quota auquel ils ont droit, il faut alors, pour chaque compte utilisateur concerné, saisir un flux qui permet de mettre à jour ce quota.&lt;br /&gt;
&lt;br /&gt;
Pour cela, il faut d'abord identifier le compte de contre-partie qui est utilisé pour les écritures comptables qui impactent ce compte. Généralement ce compte est un compte de bilan dont le nom est du type &amp;quot;Encours...&amp;quot;. Pour le trouver 2 méthodes :&lt;br /&gt;
#Aller sur '''Gestion &amp;gt; Comptes &amp;gt; Lister les comptes &amp;gt; Comptes bilan''' puis rechercher le compte concerné&lt;br /&gt;
#Aller sur le compte de suivi de quota d'un utilisateur concerné et identifier dans la cellule de la colonne '''Compte affecté''' et de la ligne d'une écriture comptable d'initialisation, le nom du compte de contre-partie.&lt;br /&gt;
&lt;br /&gt;
Une fois ce travail d'identification effectué, il faut, pour chaque compte utilisateur concerné, saisir un flux dans '''Gestion &amp;gt; Comptes &amp;gt; Flux &amp;gt; Saisir''', en mettant au crédit ou au débit le compte quota de l'utilisateur concerné et en contre-partie le compte d'encours identifié précédemment. Le montant doit correspondre à la différence entre ce qu'aurait du être le plafond initial et le plafond attribué. Si le plafond final est supérieur, alors c'est un crédit sur le compte utilisateur. Sinon, c'est un débit.&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Toutes-les-documentations&amp;diff=12715</id>
		<title>Toutes les documentations</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Toutes-les-documentations&amp;diff=12715"/>
		<updated>2024-09-06T16:38:17Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;OF_doc-en&amp;quot; to &amp;quot;OF-doc-en&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
Bienvenue sur la documentation d'OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
You can also access to our [[OF-doc-en:Main_Page|english documentation]].&lt;br /&gt;
&lt;br /&gt;
Si vous n'êtes pas encore client OpenFlyers, vous trouverez tous les renseignements dans cette [[OF_doc4-fr:Accueil|documentation]].&lt;br /&gt;
&lt;br /&gt;
=[[OF_doc1-fr:Accueil|Documentation OpenFlyers version 1]]=&lt;br /&gt;
=[[OF_doc2-fr:Accueil|Documentation OpenFlyers version 2]]=&lt;br /&gt;
=[[OF_doc3-fr:Accueil|Documentation OpenFlyers version 3]]=&lt;br /&gt;
=[[OF_doc4-fr:Accueil|Documentation OpenFlyers version 4]]=&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Suivi-des-remarques-de-maintenance&amp;diff=12714</id>
		<title>Suivi des remarques de maintenance</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Suivi-des-remarques-de-maintenance&amp;diff=12714"/>
		<updated>2024-09-06T16:38:16Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;OF_doc-en&amp;quot; to &amp;quot;OF-doc-en&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de décrire la mise en place d'un outil de '''suivi des remarques maintenance''' lors de la saisie d'une activité. Cet outil est basé sur les éléments suivants :&lt;br /&gt;
*Présence dans le formulaire de saisie des vols de 2 champs supplémentaires intitulés :&lt;br /&gt;
**&amp;quot;Remarques maintenance&amp;quot;&lt;br /&gt;
**&amp;quot;Réponse mécanicien&amp;quot;&lt;br /&gt;
*Présence d'un rapport accessible depuis '''Planning &amp;gt; Données &amp;gt; Rapports utilisateurs &amp;gt; Rapport personnalisés''' qui liste pour une ressource donnée les activités ayant une entrée dans le champ &amp;quot;Remarques maintenance&amp;quot; ou dans le champ &amp;quot;Réponse mécanicien&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=Paramétrage=&lt;br /&gt;
==Création des champs de saisie==&lt;br /&gt;
*Aller dans '''Admin &amp;gt; Structure &amp;gt; Variables &amp;gt; Champs métiers''' :&lt;br /&gt;
*En bas du tableau remplir la dernière ligne vide avec les éléments suivants :&lt;br /&gt;
**Colonne '''Nom de variable''' : ''maintenanceUserComment''&lt;br /&gt;
**Colonne '''Intitulé''' : ''Remarques maintenance''&lt;br /&gt;
**Colonne '''Catégorie''' : ''Vol''&lt;br /&gt;
**Colonne '''Type de valeur''' : ''Chaîne textuelle multi-ligne''&lt;br /&gt;
*Cliquer sur le bouton '''Ajouter''' à la fin de la ligne&lt;br /&gt;
*Répéter l'opration en bas du tableau remplir la dernière ligne vide avec les éléments suivants :&lt;br /&gt;
**Colonne '''Nom de variable''' : ''mechanicAnswer''&lt;br /&gt;
**Colonne '''Intitulé''' : ''Réponse mécanicien''&lt;br /&gt;
**Colonne '''Catégorie''' : ''Vol''&lt;br /&gt;
**Colonne '''Type de valeur''' : ''Chaîne textuelle multi-ligne''&lt;br /&gt;
*Cliquer sur le bouton '''Ajouter''' à la fin de la ligne&lt;br /&gt;
&lt;br /&gt;
==Mise en place du rapport==&lt;br /&gt;
*Rendre visible le rapport [[OF-doc-en:Export-generator-4#Flights-with-mechanic-remark|Vols avec une remarque maintenance]]&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
	<entry>
		<id>https://doc4-fr-mirror.openflyers.com/index.php?title=Import-dans-un-logiciel-comptable-tiers&amp;diff=12713</id>
		<title>Import dans un logiciel comptable tiers</title>
		<link rel="alternate" type="text/html" href="https://doc4-fr-mirror.openflyers.com/index.php?title=Import-dans-un-logiciel-comptable-tiers&amp;diff=12713"/>
		<updated>2024-09-06T16:38:16Z</updated>

		<summary type="html">&lt;p&gt;Lhenry: Text replacement - &amp;quot;OF_doc-en&amp;quot; to &amp;quot;OF-doc-en&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Présentation=&lt;br /&gt;
L'objet de cette page est de présenter les bonnes pratiques pour permettre l'import des écritures comptables générées par OpenFlyers dans les logiciels de comptabilités tiers et d'indiquer les procédures à suivre selon les logiciels connus.&lt;br /&gt;
&lt;br /&gt;
=Bonnes pratiques=&lt;br /&gt;
*La plupart des logiciels de comptabilités exigent que les comptes soient numérotés uniquement avec des chiffres (exemple : 706000) sauf pour les comptes fournisseurs et les comptes clients où les caractères alphanumériques sont acceptés (exemples : 411pdupont ou 401extal). Il est donc nécessaire dans OpenFlyers de [[Configuration de la comptabilité#Comptes_d'export|renseigner les comptes d'export selon ces règles]].&lt;br /&gt;
&lt;br /&gt;
=Exports/Imports=&lt;br /&gt;
Pour importer les écritures comptables générées par OpenFlyers dans un logiciel de comptabilité, il faut d'abord déterminer le format d'export comptable à utiliser dans OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
[[OF-doc-en:Accounting-export-template-list|Différents formats d'exports comptables]] sont disponibles dans OpenFlyers version 4.&lt;br /&gt;
&lt;br /&gt;
Le contenu de la colonne du libellé dépend de la catégorie du compte :&lt;br /&gt;
*Catégorie divers, charge, trésorerie, produit et taxe : c'est le nom du compte &lt;br /&gt;
*Catégorie utilisateur : c'est le type de compte utilisateur suivi du nom de l'utilisateur&lt;br /&gt;
*Catégorie ressource : c'est le type de compte ressource suivi du nom de la ressource&lt;br /&gt;
*Catégorie fournisseur : c'est le nom du fournisseur&lt;br /&gt;
&lt;br /&gt;
Le code du journal est défini en fonction des comptes d'exports impliqués dans le flux comptable. Voici les règles programmées par défaut :&lt;br /&gt;
#Les comptes d'export de racine &amp;quot;7&amp;quot; génèrent l'utilisation d'un code journal &amp;quot;VT&amp;quot;&lt;br /&gt;
#Les comptes d'export de racine &amp;quot;53&amp;quot; génèrent l'utilisation d'un code journal &amp;quot;CA&amp;quot;&lt;br /&gt;
#Les comptes d'export de racine &amp;quot;512&amp;quot; génèrent l'utilisation d'un code journal &amp;quot;BQ&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Ces règles s'appliquent par ordre croissant de racine d'export. Ainsi, la racine &amp;quot;7&amp;quot; est inférieure à la racine &amp;quot;53&amp;quot;. La règle de racine &amp;quot;7&amp;quot; s'applique donc en 1er et peut-être surpassée par la règle de racine &amp;quot;53&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Nous intégrons sur demande tout type de format d'export. Nous pouvons également personnaliser les formats d'export pour y modifier les règles de génération des codes journaux en sachant que les règles s'appliquent toujours par ordre croissant de racine.&lt;br /&gt;
&lt;br /&gt;
Une fois les écritures exportées dans un fichier, il faut les importer dans le logiciel de comptabilité. Vous trouverez dans les sous-chapitres ci-dessous les procédures pour certains logiciels. N'hésitez-pas à nous contacter pour compléter ces procédures afin d'y faire figurer la procédure pour votre logiciel de comptabilité.&lt;br /&gt;
&lt;br /&gt;
En cas de problème lors d'un import, une liste de messages d'erreurs est générée. Il est recommandé de copier/coller le détail des erreurs dans un [[Trucs-et-astuces#Editer-un-fichier-texte|éditeur de texte]] pour en facilité la lecture. En général, la lecture des messages d'erreur permet d'en comprendre l'origine et de trouver une solution.&lt;br /&gt;
&lt;br /&gt;
Si le problème d'import persiste, il faut [[#Rapporter_un_problème_d'import|rapporter le problème d'import]] à l'équipe OpenFlyers.&lt;br /&gt;
&lt;br /&gt;
Il faut être vigilant sur le fait les logiciels de comptabilité peuvent faire évoluer leur format d'import. Il faut donc faire des tests pour valider le format avant toute utilisation en production.&lt;br /&gt;
&lt;br /&gt;
==Import dans [http://www.ciel.com/logiciel-ciel-compta-evolution.aspx Ciel Compta Evolution]==&lt;br /&gt;
Depuis OpenFlyers, utiliser le format [[OF-doc-en:Accounting_export_template_CielXimport|Ciel Ximport]] pour exporter les écritures comptables.&lt;br /&gt;
&lt;br /&gt;
Pour la version 8.1 de Ciel Compta Evolution :&lt;br /&gt;
*Aller dans '''Divers &amp;gt; Relation Expert &amp;gt; Import...'''&lt;br /&gt;
&lt;br /&gt;
Pour la version 14.0 de Ciel Compta Evolution :&lt;br /&gt;
*Aller dans '''Echange &amp;gt; Importer les écritures'''&lt;br /&gt;
*Choisir '''Ciel'''&lt;br /&gt;
&lt;br /&gt;
==Import dans EBP==&lt;br /&gt;
''Documentation rédigée d'après la version 2012 du logiciel [http://www.ebp.com/ EBP Compta].''&lt;br /&gt;
&lt;br /&gt;
Dans OpenFlyers, il faut utiliser le format [[OF-doc-en:Accounting_export_template_Ebp2012|EBP 2012]] pour exporter les écritures comptables.&lt;br /&gt;
&lt;br /&gt;
Depuis le logiciel EBP :&lt;br /&gt;
*Aller dans '''Outils &amp;gt; Imports/Exports &amp;gt; Import texte au format EBP'''&lt;br /&gt;
*Une fenêtre s'ouvre intitulée '''Import texte au format EBP'''&lt;br /&gt;
*Dans le cas où il existe déjà des écritures comptables dans la comptabilité d'EBP, il est recommandé d'effectuer une sauvegarde du dossier comptable actuel en cliquant sur le bouton '''Sauver mon dossier maintenant'''. Cela permettra de restaurer la comptabilité en cas de mauvaise injection.&lt;br /&gt;
*Ensuite, cliquer sur le bouton '''Suivant &amp;gt;'''&lt;br /&gt;
*Dans '''Fichier à importer''', indiquer le nom du fichier généré par OpenFlyers à importer&lt;br /&gt;
*Laisser cochés '''Création automatique des comptes''' et '''Création automatique des journaux'''&lt;br /&gt;
*Laisser décochés les autres lignes sauf '''Changer les comptes racines en détail'''&lt;br /&gt;
*Cliquer sur '''Suivant &amp;gt;'''&lt;br /&gt;
*Cliquer sur '''Lancer'''&lt;br /&gt;
&lt;br /&gt;
==Caractères accentués dans les formats d'export==&lt;br /&gt;
Les formats d'export pour Ciel et EBP sont anciens (compatibilité avec d'anciennes versions), ils utilisent le format d'encodage CP850. Nos exports  pour ces logiciels sont convertis à ce format donc si vous les ouvrez avec un programme qui n'accepte pas cet encodage (tel que Word ou Excel) alors les caractères ne s'afficheront pas correctement. Nous conseillons le logiciel [http://fr.openoffice.org/ OpenOffice] pour les lire. Lors de l'import dans votre logiciel de comptabilité les écritures doivent apparaitre correctement. &lt;br /&gt;
&lt;br /&gt;
La tendance des programmes plus récents est de gérer l'encodage, si ces caractères n'apparaissent pas correctement nous contacter&lt;br /&gt;
*'''Conseils''': pour OpenOffice choisir dans l'import de texte : Europe occidentale (DOS/OS2-850 international). Voir [[FAQ-export#Import_de_fichiers_CSV_dans_OpenOffice/LibreOffice|FAQ csv reading with Oo]] pour ne pas avoir de conversion des colonnes avec des chiffres&lt;br /&gt;
* Pour le format d'export '''csv''' vous pouvez choisir directement l'encodage de sortie : pour Windows =&amp;gt; CP1252, pour Mac =&amp;gt; Mac Roman, pour Linux =&amp;gt; ISO-8859-15. Dans '''Admin &amp;gt; Configuration &amp;gt; Paramètres''' vous pouvez mettre une valeur par défaut qui sera utilisée dans tous les exports au format csv&lt;br /&gt;
&lt;br /&gt;
=Rapporter un problème d'import=&lt;br /&gt;
En cas de problème d'import d'un fichier dans un logiciel de comptabilité, il est nécessaire de faire un copier/coller de l'intégralité du détail des erreurs générées par le logiciel de comptabilité. Si ces erreurs contiennent des informations confidentielles, il est possible de nous envoyer par e-mail le détail des erreurs en indiquant le numéro de bug généré lors de la saisie du [[Rapporter un bug|rapport de bug]].&lt;/div&gt;</summary>
		<author><name>Lhenry</name></author>
	</entry>
</feed>