Annexes

Dépendances et compatibilité des versions

Version de PHP et MySQL

Voici un tableau qui récapitule, pour chaque version du logiciel, les différentes versions de PHP et MySQL (ou MariaDB) qui sont officiellement supportées et testées.

Toute utilisation d'une version inférieure de PHP ne fonctionnera pas, c'est certain.
Les versions de PHP supérieures à celles indiquées fonctionnent sûrement sans problème la plupart du temps, mais n'ont pas encore été testées et ne sont donc pas supportées officiellement.

Version de Loxya PHP (versions testées) MySQL MariaDB
0.16.x (nov. 2021) 7.3 >= 5.7.9 >= 10.2.7
0.17.x (janv. 2022) 7.3 >= 5.7.9 >= 10.2.7
0.18.x (mars 2022) 7.4 >= 5.7.9 >= 10.2.7
0.19.x (juil. 2022) 7.4 >= 5.7.9 >= 10.2.7
0.20.x (mars 2023) 8.0 ou 8.1 >= 5.7.9 >= 10.2.7
0.21.x (mai 2023) 8.0 ou 8.1 >= 5.7.9 >= 10.2.7
0.22.x (août 2023) 8.0 ou 8.1 >= 5.7.9 >= 10.2.7
0.23.x (nov. 2023) 8.0 ou 8.1 >= 5.7.9 >= 10.2.7
0.24.x (mai 2024) 8.1, 8.2 ou 8.3 >= 5.7.9 >= 10.2.7
1.0.x (nov. 2024) 8.1, 8.2 ou 8.3 >= 5.7.9 >= 10.2.7
1.1.x (avril. 2025) 8.1, 8.2 ou 8.3 >= 5.7.9 >= 10.2.7
1.2.x (sept. 2025) 8.1, 8.2 ou 8.3 >= 5.7.9 >= 10.2.7
1.3.x (mai 2026) 8.1, 8.2 ou 8.3 >= 5.7.9 >= 10.2.7

Notes :

  • Le numéro de la version du logiciel installé se trouve dans le fichier src/VERSION.
  • L'information de la (les) version(s) de PHP officiellement supportée(s) pour la version installée est affichée dans le fichier composer.json, dans requirephp-64bits.

Modules PHP requis

Les extensions PHP (modules) requis par le logiciel sont les suivants :

bcmath, curl, dom, fileinfo, gettext, iconv, intl, json, mbstring, pcre, PDO, pdo_mysql, openssl, et xml.

Weasyprint

La présence du logiciel Weasyprint est requise depuis la version 1.3 de Loxya. Il est utilisé pour la génération des documents PDF du logiciel (fiches de sortie, devis, factures, export de la liste du matériel ou des rapports d'inventaire).

La version minimale requise est Weasyprint 66.0.

Vous trouverez plus d'informations sur ce point dans la documentation de l'installation de Loxya à l'étape "configurer le serveur".

Ajouter un logo en en-tête des PDF

Pour ajouter le logo de votre structure en en-tête des fiches de sortie, des devis et des factures, il faut :

  1. Ajouter le fichier du logo dans le dossier src/public/img/. Ce fichier doit être une image du type JPEG ou PNG. Dans l'idéal, cette image ne devrait avoir une résolution d'au moins 400x250 pixels (notez aussi le rapport d'affichage, qui devrait rester plus large que haut). Évitez tout de même les images trop volumineuses, qui pourraient ralentir la génération des documents PDF.
  2. Assurez-vous que le fichier est bien accessible en lecture par l'utilisateur système du serveur web (par ex. www-data).
  3. Ensuite, dans le fichier de configuration, insérer la clé organization.logo avec comme valeur le nom de ce fichier.
    Pour exemple, voici un extrait du fichier de configuration modifié pour ajouter un logo logo.jpg :
    },
    "organization": {
        "logo": "logo.jpg",
        (...)

Paramétrer l'envoi d'e-mails

Dans le fichier /src/App/Config/settings.json, vous pouvez ajouter une section qui permettra au logiciel d’envoyer des e-mails, grâce à la fonction mail du serveur, ou alors via un serveur SMTP, ou encore en utilisant l’API de Mailjet (service d’envoi d’e-mails). Cette section se présente ainsi :

    "email": {
        "from": {
            "email": "notifications@example.com",
            "name": "Notifications Exemple"
        },
        "driver": "mail",
        "smtp": {
            "host": "your.smtp.com",
            "port": 465,
            "username": "notifications@example.com",
            "password": "mot-de-passe-smtp",
            "security": "ssl"
        },
        "mailjet": {
            "apiKey": "Clé d’API de Mailjet",
            "apiSecretKey": "Clé secrète pour l’API de Mailjet"
        }
    },

Il faut bien sûr ne pas oublier d’utiliser la bonne valeur de driver ("mail", "smtp" ou "mailjet") selon le service choisi et renseigné.

Retrouvez le détail de chaque paramètre du fichier de configuration dans cette section.

Pour tester ces paramètres en envoyant un e-mail de test, vous pouvez utiliser la commande suivante dans un terminal, en vous plaçant dans le dossier racine du projet :

./bin/console test:email votre-adresse@exemple.com

Vous devriez ensuite recevoir un e-mail à l'adresse donnée dont le sujet est « Test de la configuration Loxya », et le corps du message « L'envoi des e-mails depuis Loxya fonctionne correctement ! ». Si ce n'est pas le cas, alors le message d'erreur affiché dans votre terminal vous donnera plus d'informations sur l'origine du problème.

Configurer les notifications ( Premium)

Une fois que l’envoi des e-mails est configuré (voir point précédent), vous pouvez activer et paramétrer les notifications elles-mêmes. Pour cela, il faut utiliser la section suivante dans le fichier /src/App/Config/settings.json :

    "notifications": {
        "overdue": {
            "enabled": true,
            "days": [1, 15, 22, 27, 30]
        },
        "preparers": {
            "enabled": true,
            "daysBefore": 1
        }
    },

Vous pouvez activer les notifications suivantes en mettant à true les paramètres enabled de :

  • overdue : Envoi d’une notification au bénéficiaire d’un événement ou d’une réservation, tant qu’il n’a pas retourné l’intégralité du matériel.
  • preparers : Envoi d’une notification au préparateur de commande assigné à un événement, quelques jours avant le début de cet événement.

Bien entendu, pour que l’envoi des notifications fonctionne, il faut paramétrer une tâche CRON (voir ci-dessous).

Retrouvez le détail de chaque paramètre du fichier de configuration dans cette section.

Variables d'environnement serveur

La présence d'un fichier nommée .env à la racine du projet permettra à Loxya de configurer certains aspect de son propre fonctionnement.

Voici un exemple de fichier env, avec des commentaires expliquant les possibilités :

APP_ENV=production

# - Permet de voir le contenu des documents exportés (pdf, csv, etc.)
#   dans le navigateur à la place de les télécharger sous forme de fichier.
DEBUG_EXPORT=false

# - Permet de définir la timezone de l'application.
TIMEZONE=Europe/Paris
  • APP_ENV permet de définir le type d'installation de Loxya. Dans la plupart des cas, il faut laisser la valeur "production" à moins de réellement savoir ce que vous faites.
  • DEBUG_EXPORT est un booléen qui permet d'empêcher la création des fichiers PDF, lors de la génération des documents par Loxya (fiches de sortie, devis, factures...), mais plutôt d'avoir un rendu "brut" en HTML du document, à ouvrir dans un nouvel onglet. Cela peut être utile lors de la modification des modèles de documents, pour gagner du temps.
  • TIMEZONE permet de forcer le fuseau horaire de votre instance de Loxya sur un fuseau précis, quand le serveur lui-même n'est pas configuré sur le même fuseau horaire que vos utilisateurs.

Tâches CRON

Certaines tâches doivent être exécutées régulièrement par le logiciel, comme par exemple l’envoi de notifications par e-mail, ou le "nettoyage" de données obsolètes.

Dans le fichier src/App/Config/CRON.json se trouve la liste des tâches à créer, avec :

  • time : La récurrence à utiliser. Par exemple, "daily" signifie une fois par jour (à vous de choisir l’heure précise).
  • command : La commande à exécuter, grâce à bin/console (en spécifiant le chemin complet). Par exemple :
    /var/www/loxya/bin/console notifications:reminders.

Choisir et paramétrer un scanner de code-barres ( Premium)

Les codes-barres peuvent être :

  • soit générés par Loxya (en mode "auto", voir la configuration), et il vous suffit de les télécharger pour les imprimer.
  • soit fournis par l'utilisateur (en mode "manuel", voir la configuration).

Plusieurs formats de codes-barres sont pris en charge. Codes-barres à deux dimensions :

  • format QR Code
  • format PDF417

Et des codes-barres à 1 dimension :

  • format Code 39
  • format Code 128

Attention
En mode "manuel", ainsi que pour les codes-barres à 1 dimension, le scanner de codes-barres devra impérativement pouvoir ajouter automatiquement un préfixe et un suffixe au code-barre scanné. Assurez-vous donc de choisir un modèle qui permet cela.

  • Le préfixe à ajouter est composé des caractères suivants : ^#[
  • Le suffixe à ajouter est composé des caractères suivants : ]#$

Généralement, il suffit de scanner les caractères ASCII correspondants dans le manuel utilisateur de la scanette pour les activer.

Dans un éditeur de texte, en scannant un code-barre, vous devriez voir apparaître une chaîne de caractères ressemblant à ceci : ^#[C0D384R]#$

Si c'est le cas, alors votre douchette est correctement paramétrée 👍. Sinon, il faut revoir sa configuration, notamment la langue qui correspond à la disposition de votre clavier.

Authentification unique (SSO) via CAS ou SAML2 ( Premium)

Vous avez la possibilité d’utiliser un système d’authentification unique via un serveur CAS, et / ou SAML2.

Pour cela, vous devez bien sûr autoriser l'instance du logiciel à accéder à votre serveur CAS ou SAML2, et le paramétrer correctement. Ensuite, vous pouvez activer la fonctionnalité en renseignant la section suivante du fichier /src/App/Config/settings.json :

    "auth": {
        "cookie": "auth",
        "CAS": {
            "enabled": true,
            "host": "your.cas.server",
            "uri": "/cas",
            "port": 8080,
            "cert": false,
            "attributes": {
                "pseudo": "givenName",
                "email": ["mail", "email"],
                "firstName": "firstName",
                "lastName": "lastName",
                "group": "group"
            },
            "groupsMapping": {
                "MonGroupeBeneficiaireCAS": "visitor"
            },
            "beneficiaryGroups": ["MonGroupeBeneficiaireCAS"],
            "defaultGroup": null,
            "nonCASUserLinking": true
        },
        "SAML2": {
            "enabled": true,
            "signRequests": false,
            "signingCert": {
                "key": "La clé du certificat de votre instance du logiciel",
                "cert": "Le certificat de votre instance du logiciel, encodé en base64"
            },
            "idp": {
                "entityId": "URL de l'Identity Provider",
                "singleSignOnServiceUrl": "URL du service de login",
                "singleLogoutServiceUrl": "URL du service de logout",
                "signingCert": "Le certificat de votre Identity Provider"
            },
            "attributes": {
                "pseudo": "givenName",
                "email": ["mail", "email"],
                "firstName": "first_name",
                "lastName": "last_name",
                "group": "group"
            },
            "beneficiaryGroups": ["MonGroupeBeneficiaireSAML2"],
            "groupsMapping": {
                "Administrateur": "admin",
                "MonGroupeBeneficiaireSAML2": "visitor"
            },
            "defaultGroup": null,
            "nonSAMLUserLinking": true,
            "disableUnsolicitedRequests": false,
            "proxyVars": false
        }
    },

Retrouvez le détail de chaque paramètre du fichier de configuration dans cette section.

Pour activer l'une ou l'autre (ou les deux) méthodes d'authentification, il faut utiliser le paramètre enabled des clés auth.cas et/ou auth.saml2, en lui mettant la valeur true.

CAS

Voici le détail de chaque paramètre qu'il vous faudra renseigner pour faire fonctionner la SSO avec CAS Dans Loxya.

host

Il s'agit du nom d'hôte de votre serveur CAS. Par exemple cas.votre-domaine.com

port

Le numéro de port à utiliser pour la connexion au serveur CAS. Par défaut, 8443.

uri

L'URI à laquelle le serveur CAS répond. Par exemple, /cas.

cert

Le certificat du serveur CAS. Cette option accepte plusieurs valeurs :

  • false: Désactive la verification SSL du serveur CAS.
  • Le chemin vers le fichier de certificat au format PEM.

Mapping des attributs

L'option attributes permet de mettre en correspondance les données attendues pour créer un utilisateur dans Loxya, avec les attributs qui sont renvoyés dans la réponse du fournisseur d'identité (IdP).

La valeur de ce paramètre attend un tableau associatif (objet JSON) qui contient les clés suivantes :

  • pseudo : l'attribut à utiliser pour créer le pseudo de l'utilisateur. Par exemple, givenName. Attention, cette valeur doit être unique pour chacun de vos utilisateurs.
  • email : l'attribut à utiliser pour créer l'adresse e-mail de l'utilisateur.
  • group : l'attribut à utiliser pour créer le rôle de l'utilisateur. Par exemple, group ou role.
  • firstName : l'attribut à utiliser pour créer le prénom de l'utilisateur. Par exemple, firstName.
  • lastName : l'attribut à utiliser pour créer le nom de famille de l'utilisateur. Par exemple, lastName.

Si vous spécifiez un tableau en valeur de l'une de ces clés, la valeur de la clé sera cherché dans tous les attributs correspondants. Dès qu'un de ces attributs existe, c'est cette valeur qui sera utilisée.
Par exemple, si vous définissez : "email": ["mail", "e-mail"], l'attribut mail sera recherché pour l'adresse e-mail de l'utilisateur. Si cet attribut n'existe pas ou qu'il est vide, alors c'est l'attribut e-mail sera recherché. Si aucun attribut n'est trouvé, alors une valeur de remplacement par défaut sera utilisée quand c'est possible (pour l'email ce sera un email fictif / interne à l'application par exemple).

Groupe(s) liés aux bénéficiaires

Le paramètre beneficiaryGroups permet de définir un (ou plusieurs) groupes CAS qui, si présents dans l'attribut de groupe retourné par le fournisseur d'identité (voir l'attribut "group" ci-dessus), feront de l'utilisateur un bénéficiaire pouvant réserver via la réservation publique (si cette fonctionnalité est activée et disponible).

Si la valeur de cette option est null (c'est le cas par défaut), la fonctionnalité sera désactivée (= pas de création de profils bénéficiaire lors de la connexion CAS). Il est à noter que ceci ne remplace pas la récupération du groupe dont il est fait mention ci-dessous. Cette option permet seulement d'indiquer que l'utilisateur est aussi un bénéficiaire.

Vous avez également la possibilité d'utiliser un caractère « wildcard » (joker) pour ce paramètre, c'est à dire le caractère *. Ainsi, tout utilisateur qui se connecte pour la première fois via CAS aura un compte bénéficiaire associé, peu importe son groupe CAS. Cela est aussi utile si votre serveur CAS ne remonte pas les groupes des utilisateurs.

À vous ensuite de choisir dans quel groupe vous voulez le mettre du côté de Loxya via l'option groupsMapping et/ou defaultGroup.

Exemples de valeur :

  • "MonGroupeBénéficiaireCAS"
  • ["MonGroupeBénéficiaireCAS1", "MonGroupeBénéficiaireCAS2"]
  • *

Mapping des groupes / rôles

Le paramètre groupsMapping permet de mettre en correspondance un groupe Loxya avec un groupe provenant de l'attribut de groupe retourné par le fournisseur d'identité (voir l'attribut "group" ci-dessus).

Les rôles Loxya disponibles sont les suivants :

  • administration : Administration,
  • management : Gestion,
  • readonly-planning-general : Consultation du planning général,
  • readonly-planning-self : Consultation de son propre planning,
  • external : Externe (accès aux demandes de réservation uniquement).

Exemple de valeur : ["MonGroupeBénéficiaireCAS" => "external"].

Le paramètre defaultGroup permet de définir un rôle à l'utilisateur même si aucune correspondance n'a été trouvée avec l'attribut fourni via le groupsMapping ci-dessus.

  • Si la valeur de cette option est non null, l'utilisateur sera automatiquement assigné à ce groupe ci.
  • Si la valeur est null, l'utilisateur ne sera pas autorisé à se connecter.

Rattachement des utilisateurs existants

En activant le paramètre nonCASUserLinking (en le mettant sur true), vous activez le rattachement des utilisateurs CAS avec les utilisateurs existants.

Si cette option est activée, un utilisateur CAS qui se connecte avec une adresse e-mail déjà connue par Loxya pour un utilisateur non lié à SAML sera automatiquement rattaché à cet utilisateur, et disposera de ses autorisations.

Si cette option est désactivée, les utilisateurs CAS ayant déjà un compte non CAS dans l'application seront rejetés.

SAML 2.0

Voici le détail de chaque paramètre qu'il vous faudra renseigner pour faire fonctionner la SSO avec SAML 2.0 dans Loxya.

signRequests

Il s'agit d'une option qui permet d'activer ou non la signature des requêtes envoyées au fournisseur d'identité (IdP). Le certificat utilisé pour signez ces requêtes est un certificat x509 fourni dans le paramètre signingCert (voir ci-dessous).

Par défaut, cette option est désactivée (= false). Vous pouvez l'activer (en la mettant à true) si votre IdP exige des requêtes sécurisées.

signingCert

Le paramètre auth.SAML2.signinCert et ses clés key et cert servent à renseigner le certificat qui sera utilisé pour signer les requêtes (et les réponses) au fournisseur d'identité. Ce certificat doit-être fourni, que la signature des requêtes (c'est à dire le paramètre signRequests ci-dessus) soit activée ou non.

Vous pouvez générer ces deux valeurs via la commande suivante (attention à bien remplacer ce qui se trouve entre crochets par le nom de domaine de votre instance de Loxya) :

openssl req \
    -x509 -nodes -days 3652 -new -newkey rsa:3072 \
    -subj '/CN=[Hôte de l'instance de Loxya]/C=FR' \
    -keyout signingCert.key \
    -out signingCert.crt

La commande ci-dessus générera deux fichiers à l'endroit ou elle est exécutée :

  • Un fichier signingCert.key dont le contenu doit être mis en valeur de signingCert.key.
    Pour cela, récupérez son contenu via : awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' ./signingCert.key | pbcopy
    Ceci devrait produire une chaîne commençant par -----BEGIN PRIVATE KEY-----\n.
  • Un fichier signingCert.crt dont le contenu doit être mis en valeur de signingCert.cert.
    Pour cela, récupérez son contenu via : awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' ./signingCert.crt | pbcopy Ceci devrait produire une chaîne commençant par -----BEGIN CERTIFICATE-----\n.

NOTE : Les fichiers générés ci-dessus ne seront pas utilisés par l'application directement donc vous pouvez en disposer comme vous voulez.

Le fournisseur d'identité (IdP)

Les 4 paramètres se trouvant dans auth.SAML2.idp servent à définir les URLs et le certificat que Loxya devra utiliser pour effectuer l'authentification des utilisateurs via SAML 2.0 auprès de votre IdP ("Identity Provider").

entityId

Il s'agit de l'URI de votre fournisseur d'identité. Généralement, cette URI ressemble à https://[idp-url]/metadata.

singleSignOnServiceUrl

Il s'agit de l'URL d'accès à la connexion ("Single Sign On", ou "SSO") du fournisseur d'identité. Généralement, elle ressemble à https://[idp-url]/sso.

singleLogoutServiceUrl

Il s'agit de l'URL d'accès à la déconnexion ("Single Logout Service", ou "SLS") du fournisseur d'identité. Généralement, elle ressemble à https://[idp-url]/sls.

signinCert

Le paramètre auth.SAML2.idp.signinCert renseigne le certificat public du fournisseur d'identité (IdP). Il attend une chaîne de caractère, que vous pouvez récupérer à partir du fichier de certificat public de l'IdP (au format PEM), en exécutant la commande suivante :

awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' "[le fichier du certificat].crt" | pbcopy

Ceci devrait produire une chaîne commençant par -----BEGIN CERTIFICATE-----\n. C'est cette chaîne qu'il faut renseigner dans le paramètre auth.SAML2.idp.signinCert.

Mapping des attributs

L'option attributes permet de mettre en correspondance les données attendues pour créer un utilisateur dans Loxya, avec les attributs qui sont renvoyés dans la réponse du fournisseur d'identité (IdP).

La valeur de ce paramètre attend un tableau associatif (objet JSON) qui contient les clés suivantes :

  • pseudo : l'attribut à utiliser pour créer le pseudo de l'utilisateur. Par exemple, givenName.
  • email : l'attribut à utiliser pour créer l'adresse e-mail de l'utilisateur.
  • group : l'attribut à utiliser pour créer le rôle de l'utilisateur. Par exemple, group ou role.
  • firstName : l'attribut à utiliser pour créer le prénom de l'utilisateur. Par exemple, firstName.
  • lastName : l'attribut à utiliser pour créer le nom de famille de l'utilisateur. Par exemple, lastName.

Si vous spécifiez un tableau en valeur de l'une de ces clés, la valeur de la clé sera cherché dans tous les attributs correspondants. Dès qu'un de ces attributs existe, c'est cette valeur qui sera utilisée.
Par exemple, si vous définissez : "email": ["mail", "e-mail"], l'attribut mail sera recherché pour l'adresse e-mail de l'utilisateur. Si cet attribut n'existe pas ou qu'il est vide, alors c'est l'attribut e-mail sera recherché. Si aucun attribut n'est trouvé, alors une valeur de remplacement par défaut sera utilisée quand c'est possible (pour l'email ce sera un email fictif / interne à l'application par exemple).

Groupe(s) liés aux bénéficiaires

Le paramètre beneficiaryGroups permet de définir un (ou plusieurs) groupes SAML 2.0 qui, si présents dans l'attribut de groupe retourné par le fournisseur d'identité (voir l'attribut "group" ci-dessus), feront de l'utilisateur un bénéficiaire pouvant réserver via la réservation publique (si cette fonctionnalité est activée et disponible).

Si la valeur de cette option est null (c'est le cas par défaut), la fonctionnalité sera désactivée (= pas de création de profils bénéficiaire lors de la connexion SAML 2.0). Il est à noter que ceci ne remplace pas la récupération du groupe dont il est fait mention ci-dessous. Cette option permet seulement d'indiquer que l'utilisateur est aussi un bénéficiaire.

Vous avez également la possibilité d'utiliser un caractère « wildcard » (joker) pour ce paramètre, c'est à dire le caractère *. Ainsi, tout utilisateur qui se connecte pour la première fois via SAML 2.0 aura un compte bénéficiaire associé, peu importe son groupe. Cela est aussi utile si votre IdP ne remonte pas correctement les groupes des utilisateurs.

À vous ensuite de choisir dans quel groupe vous voulez le mettre du côté de Loxya via l'option groupsMapping et/ou defaultGroup.
Exemples de valeur :

  • "MonGroupeBénéficiaireSAML"
  • ["MonGroupeBénéficiaireSAML1", "MonGroupeBénéficiaireSAML2"]
  • *

Mapping des groupes / rôles

Le paramètre groupsMapping permet de mettre en correspondance un groupe Loxya avec un groupe provenant de l'attribut de groupe retourné par le fournisseur d'identité (voir l'attribut "group" ci-dessus).

Les rôles Loxya disponibles sont les suivants :

  • administration : Administration,
  • management : Gestion,
  • readonly-planning-general : Consultation du planning général,
  • readonly-planning-self : Consultation de son propre planning,
  • external : Externe (accès aux demandes de réservation uniquement).

Exemple de valeur : ["MonGroupeBénéficiaireSAML" => "external"].

Le paramètre defaultGroup permet de définir un rôle à l'utilisateur même si aucune correspondance n'a été trouvée avec l'attribut fourni via le groupsMapping ci-dessus.

  • Si la valeur de cette option est non null, l'utilisateur sera automatiquement assigné à ce groupe ci.
  • Si la valeur est null, l'utilisateur ne sera pas autorisé à se connecter.

Rattachement des utilisateurs existants

En activant le paramètre nonSAMLUserLinking (en le mettant sur true), vous activez le rattachement des utilisateurs SAML 2.0 avec les utilisateurs existants.

Si cette option est activée, un utilisateur SAML 2.0 qui se connecte avec une adresse e-mail déjà connue par Loxya pour un utilisateur non lié à SAML sera automatiquement rattaché à cet utilisateur, et disposera de ses autorisations.

Si cette option est désactivée, les utilisateurs SAML ayant déjà un compte non SAML dans l'application seront rejetés.

Permettre à l'IdP de connecter / déconnecter une session Loxya

Le paramètre disableUnsolicitedRequests permet de désactiver la prise en charge des requêtes de connexion / déconnexion qui proviennent du fournisseur d'identité sans que l'utilisateur soit passé par Loxya pour provoquer ces actions.

Par défaut, cette option est sur false, c'est à dire que l'IdP peut déconnecter un utilisateur qui serait en train d'utiliser Loxya.

Définir un Proxy

Le paramètre proxyVars permet d'utiliser les headers X-Forwarded-* / HTTP_X_FORWARDED_PROTO pour déterminer le port / domaine / protocole.

Ceci est utile notamment si l'application tourne derriere un load balancer qui met fin au protocole SSL.

Coefficient de tarif dégressif

Obsolète : Depuis la version 1.0, plusieurs coefficients de tarif dégressif sont paramétrables, directement dans les paramètres du logiciel.

Le fichier de configuration en détail

Ce fichier est créé automatiquement par l'assistant d'installation, mais en cas de modification il est bon de savoir à quoi servent ses composantes.

Important
Veillez bien à ne pas casser la structure du fichier de configuration, car cela pourrait rendre le logiciel complètement inutilisable.

Exemple (format JSON)

Voici un exemple de contenu de ce fichier de configuration principal, expliqué ligne par ligne dans un tableau, en dessous :

{
    "baseUrl": "https://example-loxya.net",
    "mainCountry": "FR",
    "defaultLang": "fr",
    "currency": "EUR",
    "JWTSecret": "super_long_secret_string_to_never_commit",
    "healthcheck": true,
    "enableCORS": false,
    "sessionExpireHours": 12,
    "maxItemsPerPage": 100,
    "maxFetchPeriod": 90,
    "maxConcurrentFetches": 2,
    "returnPolicy": "auto",
    "billingMode": "partial",
    "features": {
        "technicians": true,
        "ata-carnet": false
    },
    "db": {
        "host": "localhost",
        "port": 3306,
        "database": "loxya",
        "username": "myuser",
        "password": "mypassword",
        "prefix": ""
    },
    "organization": {
        "name": "Votre société",
        "logo": "votre_logo.jpg",
        "registrationId": "12345678900015",
        "legalType": "FR.SARL",
        "shareCapital": "45000",
        "activityCode": "90.01Z",
        "tradeRegistryCity": "Paris",
        "isVatExempted": false,
        "vatExemptionCode": null,
        "vatExemptionReason": null,
        "vatNumber": "FR11233445566",
        "isVatDueOnInvoice": false,
        "street": [
            "32, rue du matos",
            "Bat. gauche"
        ],
        "postalCode": "75000",
        "administrativeArea": null,
        "locality": "Paris",
        "country": "FR",
        "phone": "+33123456789",
        "email": "contact@your-company.com",
        "website": "https://your-company.com"
    },
    "estimates": {
        "validityDays": 15
    },
    "invoices": {
        "routingIdentifier": "0225:123456789",
        "paymentTermDays": 30,
        "paymentMethods": {
            "cheque": true,
            "transfer": {
                "holder": "Votre société",
                "iban": "FR76 1234 5678 9000 1234 5678 987",
                "bic": "SBMAAA20"
            },
            "cash": false,
            "card": false
        },
        "mentions": {
            "seller-identity": null,
            "trade-register": null,
            "vat-due-on-invoice": null,
            "no-early-payment-discount": null,
            "late-payment-penalty": null,
            "late-payment-flat-fee": null
        }
    },
    "measurementUnits": {
        "materials": {
            "weight": "kg"
        }
    },
    "proxy": {
        "enabled": false,
        "host": "proxy.loxya.test",
        "port": 3128
    },
    "colorSwatches": [
        "#f5006b",
        "#06b5a9",
        "#f8ad14",
        "#9fde3f",
        "#ff6e21"
    ],
    "logger": {
        "timezone": "Europe/Paris",
        "level": 200,
        "max_files": 5
    },
    "maxFileUploadSize": 26214400,
    "authorizedFileTypes": ["application/pdf", "application/zip", "text/csv", "..."],
    "authorizedImageTypes": ["image/jpeg", "image/png", "image/webp", "..."],
    "email": {
        "from": {
            "email": "noreply@example.com",
            "name": "Notification Loxya"
        },
        "driver": "mail",
        "smtp": {
            "host": "localhost",
            "port": 1025,
            "username": null,
            "password": null,
            "security": ""
        },
        "mailjet": {
            "apiKey": "mailjet-api-key",
            "apiSecretKey": "mailjet-api-secret"
        }
    },

    //////////////////////////////////////////////////
    // La suite est spécifique à la variante Premium :
    //////////////////////////////////////////////////

    "enableApiDocs": true,
    "barcodes": {
        "mode": "auto",
        "format": "qr-code"
    },
    "handScanner": {
        "scanTimeout": 100,
        "inputLayout": "azerty"
    },
    "exports": {
        "materials": {
            "advanced": true
        }
    },
    "auth": {
        "cookie": "auth",
        "inactivityWatcher": {
            "enabled": false,
            "threshold": 3,
        },
        "CAS": {
            "enabled": false,
            "host": "cas.loxya.dev",
            "port": 8080,
            "uri": "/cas",
            "cert": false,
            "attributes": {
                "pseudo": "givenName",
                "email": ["mail", "email"],
                "firstName": "first_name",
                "lastName": "last_name",
                "group": "group"
            },
            "beneficiaryGroups": "*",
            "groupsMapping": {
                "Administrateur": "administration",
                "MonGroupeBeneficiaireCAS": "external"
            },
            "defaultGroup": "external",
            "nonCASUserLinking": true
        },
        "SAML2": {
            "enabled": false,
            "signRequests": false,
            "signingCert": {
                "key": null,
                "cert": null
            },
            "idp": {
                "entityId": null,
                "singleSignOnServiceUrl": null,
                "singleLogoutServiceUrl": null,
                "signingCert": null
            },
            "attributes": {
                "pseudo": "givenName",
                "email": ["mail", "email"],
                "firstName": "first_name",
                "lastName": "last_name",
                "group": "group"
            },
            "beneficiaryGroups": "*",
            "groupsMapping": {
                "Administrateur": "administration",
                "MonGroupeBeneficiaireCAS": "external"
            },
            "defaultGroup": "external",
            "nonSAMLUserLinking": true,
            "disableUnsolicitedRequests": false,
            "proxyVars": false
        }
    },
    "signup": {
        "restrictedEmailDomains": ["my-company.com", "other.org"],
        "expireAfter": 120,
        "requireAddress": "auto",
        "allowCompanies": true,
        "maxRegistrationBeforeCooldown": 2
    },
    "legalDocuments": {
        "privacyPolicy": null,
        "termsOfUse": null,
    },
    "notifications": {
        "overdue": {
            "enabled": true,
            "days": [1, 15, 22, 27, 30],
            "events": {
                "enabled": true
            },
            "reservations": {
                "enabled": true
            }
        },
        "preparers": {
            "enabled": true,
            "daysBefore": 1
        }
    }
}

Détails du fichier de configuration

Clé Description Type de valeur Valeur par défaut
baseUrl Adresse web (URL) de l'application string [URL actuel]
mainCountry Le code ISO du pays principal où est utilisé le logiciel string "FR"
defaultLang Langue de l'interface par défaut (en étant non connecté) "fr" ou "en" "fr"
currency Le code ISO de la devise à utiliser pour les prix et les montants string "EUR"
JWTSecret Passphrase utilisée pour la création du JWT (Json Web Token) string [Valeur aléatoire]
healthcheck Détermine si la route /healthcheck est activée ou non.
Cette route permet de savoir si l'API est accessible. Elle retourne la date de dernière modification.
boolean false
enableCORS Activer le "Cross Origin Resource Sharing" boolean false
sessionExpireHours Nombre d'heures avant expiration d'une session utilisateur.
Attention, ne pas utiliser la valeur 0, car cela risque de faire planter le login !
integer 12
maxItemsPerPage Nombre d'enregistrements retournés par pages pour la pagination integer 100
maxFetchPeriod Période maximale (en jours) pendant laquelle les données peuvent être récupérées integer 90
maxConcurrentFetches Nombre de requêtes simultanées maximum pour la récupération du matériel manquant integer 2
returnPolicy Politique de retour des événements et réservations "auto" ou "manual" "auto"
billingMode Le mode d'utilisation de la facturation. Trois valeurs possibles :
- all : facturation de tous les événements,
- partial : facturation des événements facturables uniquement,
- none : pas de facturation du tout (mode prêt)
string "partial"
colorSwatches Liste des couleurs personnalisées, à utiliser dans le color-picker de de l'étape 1 de l'édition des événements.
Exemple : ["#f5006b", "#06b5a9", "#365576"].
array (ou null) null
features Activation / désactivation de certaines fonctionnalités. object
→ features.technicians Activation ou non de la fonctionnalité de gestion des techniciens. boolean true
maxFileUploadSize Taille maximum des fichiers pouvant être envoyés integer 26 214 400 (25Mo)
authorizedFileTypes Liste des types de fichiers pouvant être envoyés array une liste prédéfinie
authorizedImageTypes Liste des types de fichiers images pouvant être envoyés array une liste prédéfinie
db Informations de connection à la base de données MySQL object
→ db.host Le nom du serveur hôte à utiliser pour la connexion MySQL string "localhost"
→ db.port Le numéro de port du serveur hôte pour la connexion MySQL string 3306
→ db.username Le nom de l'utilisateur MySQL à utiliser pour la connexion à la base de données string "root"
→ db.password Le mot de passe de l'utilisateur MySQL string ""
→ db.database Le nom de la base de données string "loxya"
→ db.prefix Un préfixe éventuel à ajouter devant chaque nom de table de la base de données string ""
organization Informations de l'organisation pour la création des documents (devis, factures...) object
→ organization.name Raison sociale (nom) de l'organisation string ""
→ organization.logo Nom du fichier (image JPG ou PNG) du logo l'organisation, à placer dans le dossier src/public/img/ string (ou null) null
→ organization.registrationId Numéro d'identification de l'organisation (par ex. le n° SIRET ou SIREN en France) string null
→ organization.legalType Type de structure légale de l'organisation (par ex. "FR.SARL" ou "FR.SAS" en France) string null
→ organization.shareCapital Montant du capital social si pertinent pour l'organisation (société) string null
→ organization.activityCode Le code de l'activité principale de l'organisation (société) (par ex. le code APE en France) string null
→ organization.tradeRegistryCity La ville où l'organisation est immatriculée (par ex. le R.C.S. en France) string null
→ organization.isVatExempted Est-ce que l'organisation est exemptée de T.V.A. ? (par ex. en France, les micro-entreprises) boolean false
→ organization.vatExemptionCode Si l'organisation est exemptée de T.V.A., le code d'exemption string null
→ organization.vatExemptionReason Si l'organisation est exemptée de T.V.A., le code de la raison de l'exemption string null
→ organization.vatNumber Numéro de TVA intracommunautaire de l'organisation (si assujettie) string ""
→ organization.isVatDueOnInvoice Est-ce que l'organisation est assujettie à la T.V.A. sur les débits plutôt qu'à l'encaissement ? boolean false
→ organization.street Adresse postale (rue et numéro) de l'organisation. Possibilité de passer un tableau avec deux lignes pour ajouter un complément d'adresse. string ou array []
→ organization.postalCode Code postal de l'organisation string null
→ organization.administrativeArea Subdivision administrative de l'organisation string null
→ organization.locality Localité (ville ou village) de l'organisation string null
→ organization.country Code ISO du pays de l'organisation string "FR"
→ organization.phone Numéro de téléphone de l'organisation string null
→ organization.email Adresse email de contact de l'organisation string null
estimates Paramètres des devis object
→ estimates.validityDays Durée (en jours) par défaut de la validité des devis number 15
invoices Paramètres de la facturation object
→ invoices.routingIdentifier Adresse électronique de l'organisation pour l'envoi des e-factures. Utilisé notamment pour recevoir les statuts de traitement des e-factures (dans le cadre du e-invoicing). string null
→ invoices.paymentTermDays Délai de paiement par défaut (en jours) des factures. 0 signifie "à réception". number 15
→ invoices.paymentMethods Moyens de paiements pris en charge object
    → invoices.paymentMethods.cash Prendre en charge les paiements en espèces. boolean false
    → invoices.paymentMethods.card Prendre en charge les paiements en carte bancaire. boolean false
    → invoices.paymentMethods.cheque Prendre en charge les paiements par chèque. boolean false
    → invoices.paymentMethods.transfert Prendre en charge les paiements par virement bancaire SEPA. object null
        → invoices.paymentMethods.transfert.holder Le nom du titulaire du compte bancaire. string null
        → invoices.paymentMethods.transfert.iban L'IBAN du compte bancaire. string null
        → invoices.paymentMethods.transfert.bic Le code BIC/SWIFT du compte bancaire. string null
→ invoices.mentions Textes personnalisés pour les mentions légales des devis et factures. Permet d'écraser les mentions par défaut, et d'ajouter celles qui ne sont pas affichées par défaut. object
    → invoices.mentions.seller-identity Identité complète du vendeur. string [pré-rempli]
    → invoices.mentions.trade-register Mention d'immatriculation au registre du commerce. string [pré-rempli]
    → invoices.mentions.vat-due-on-invoice Mention d'option pour la "TVA sur les débits". string [pré-rempli]
    → invoices.mentions.no-early-payment-discount Absence d'escompte pour paiement anticipé. string null
    → invoices.mentions.late-payment-penalty Pénalité exigible en cas de retard de paiement. string [pré-rempli]
    → invoices.mentions.late-payment-flat-fee Indemnité forfaitaire pour frais de recouvrement en cas de retard de paiement. string [pré-rempli]
measurementUnits Unités de mesure à utiliser object
→ measurementUnits.materials Unités de mesure à utiliser pour le matériel object
    → measurementUnits.materials.weight Unité de mesure du poids du matériel string "kg"
proxy Utilisation d'un proxy : un objet contenant les données du proxy object
→ proxy.enabled Activation du proxy ou non boolean false
→ proxy.host Nom d'hôte du proxy string ""
→ proxy.port Numéro du port du proxy number
logger Paramétrage du logging (fichiers de logs du système, voir dans /src/var/logs) object
→ logger.level Le niveau de log à utiliser (voir cette documentation.) number 250
→ logger.max_files Le nombre maximum de fichiers de log à conserver number 10
email Paramétrage de l'envoi des e-mails object
→ email.from Nom et adresse e-mail de l'expéditeur.
Peut aussi être une simple chaîne de caractère (devant être une adresse e-mail valide).
object (ou string) ""
    → email.from.email Adresse e-mail de l'expéditeur string
    → email.from.name Nom de l'expéditeur string
→ email.driver Type de système à utiliser pour l'envoi des e-mails. Peut être soit mail, soit smtp, soit mailjet (voir ci-dessous) string "mail"
→ email.smtp Pour une utilisation du système d'envoi smtp (voir ci-dessus) object
    → email.smtp.host Nom d'hôte du serveur SMTP à utiliser string "localhost"
    → email.smtp.port Numéro du port SMTP à utiliser number 1025
    → email.smtp.username Nom d'utilisateur pour le compte SMTP à utiliser string (ou null) null
    → email.smtp.password Mot de passe pour le compte SMTP string (ou null) null
    → email.smtp.security Type de cryptage à utiliser pour SMTP. Peut être une chaîne vide, ou tls, ou ssl string ""
→ email.mailjet Pour une utilisation de l'API de Mailjet pour envoyer les e-mails object
    → email.mailjet.apiKey Votre clé d'API fournie par Mailjet string (ou null) null
    → email.mailjet.apiSecretKey Votre clé secrète fournie par Mailjet string (ou null) null

Les éléments suivants sont spécifiques à la variante Premium :

Clé Description Type de valeur Valeur par défaut
enableApiDocs Activation de la documentation de l'API boolean true
barcodes Paramétrage de la génération des codes-barres object
→ barcodes.mode Mode de génération des codes-barres. Si auto, l'application génère elle-même les codes-barres depuis un identifiant interne. Si manual, l'application attend que le contenu de chaque code-barres soit passé. "auto" ou "manual" "auto"
→ barcodes.format Type de codes-barres à prendre en charge (qr-code, pdf417, code39 ou code128). string "qr-code"
handScanner Paramétrage du scanner de code-barres object
→ handScanner.scanTimeout Le temps (en millisecondes) permettant de détecter un scan de code-barres. number 100
→ handScanner.inputLayout Le type de clavier à émuler (doit être similaire à celui utilisé par les utilisateurs) . string "qwerty"
exports Configuration du comportement des fonctionnalités d'export de données. object
→ exports.materials Configuration du comportement des fonctionnalités d'export de données relatives au matériel. object
→    exports.materials.advanced Inclusion ou non des données des codes-barres du matériel et des unités de matériel. boolean true
auth Paramétrage de l'authentification object
→ auth.cookie Nom du cookie à utiliser pour le stockage de session. string "auth"
→ auth.inactivityWatcher Déconnexion automatique de l'utilisateur externe. object
    → auth.inactivityWatcher.enabled Pour activer la déconnexion automatique. boolean false
    → auth.inactivityWatcher.threshold Délai avant que l'utilisateur ne soit considéré comme inactif (en minutes). number 3
→ auth.CAS Paramétrage de l'authentification CAS. object
    → auth.CAS.enabled Pour activer l'authentification unifiée (SSO) via un serveur CAS. boolean false
    → auth.CAS.host Nom complet du serveur CAS hôte. string "cas.loxya.test"
    → auth.CAS.port Numéro du port pour accéder au serveur CAS. number 8443
    → auth.CAS.uri Chemin vers l'authentification sur le serveur CAS. string "/cas"
    → auth.CAS.cert Pour activer ou non la récupération du certificat SSL. boolean false
    → auth.CAS.attributes Paramétrage fin de la correspondance des attributs CAS pour la création des utilisateurs dans Loxya. Peuvent être soit une chaîne de caractère, soit un tableau. Si c'est un tableau, le premier attribut trouvé avec une valeur non nulle sera utilisé. object
        → auth.CAS.attributes.pseudo Les noms des attributs CAS à utiliser pour construire le pseudo de l'utilisateur. string (ou array) "givenName"
        → auth.CAS.attributes.email Les noms des attributs CAS à utiliser pour construire l'adresse email de l'utilisateur. string (ou array) ["mail", "email"]
        → auth.CAS.attributes.group Les noms des attributs CAS à utiliser pour choisir le groupe de l'utilisateur. string (ou array) "group"
        → auth.CAS.attributes.firstName Les noms des attributs CAS à utiliser pour construire le prénom de l'utilisateur. string (ou array) "first_name"
        → auth.CAS.attributes.lastName Les noms des attributs CAS à utiliser pour construire le nom de famille de l'utilisateur. string (ou array) "last_name"
    → auth.CAS.beneficiaryGroups Un (ou plusieurs) groupe(s) CAS dont la présence permettra de créer un bénéficiaire en même temps que l'utilisateur. string (ou array) (ou null) null
    → auth.CAS.groupsMapping Un tableau de correspondance entre les groupes CAS et les groupes des utilisateurs de Loxya.
Par exemple : { "Administrateur": "admin", "Etudiant": "external" }
object {}
    → auth.CAS.defaultGroup Le groupe utilisateur de Loxya à utiliser si aucun groupe CAS n'a été trouvé dans groupsMapping (voir ci-dessus).
Si null, l'utilisateur ne sera pas autorisé à se connecter.
string (ou null) null
    → auth.CAS.nonCASUserLinking Quand un utilisateur se connecte via CAS pour la première fois alors qu'un utilisateur existe déjà avec la même adresse e-mail, détermine si le système doit le lier à son compte CAS ou non. boolean true
→ auth.SAML2 Paramétrage de l'authentification SAML 2.0. object
    → auth.SAML2.enabled Pour activer l'authentification unifiée (SSO) en utilisant SAML 2.0. boolean false
    → auth.SAML2.signRequests Détermine si les requêtes envoyées au fournisseur d'identité (IDP) doivent être signées ou non. boolean false
    → auth.SAML2.signingCert Le certificat qui sera utilisé pour signer les requêtes et les réponses au fournisseur d'identité (IDP).
Obligatoire, même si la signature des requête est désactivée.
object
        → auth.SAML2.signingCert.key Le contenu d'un fichier "signinCert.key" valide (généré via openssl). string null
        → auth.SAML2.signingCert.cert Le contenu d'un fichier "signinCert.crt" valide (généré via openssl). string null
    → auth.SAML2.idp Configuration du fournisseur d'identité (IdP). object
        → auth.SAML2.idp.entityId Identifiant (URI) du fournisseur d'identité. string null
        → auth.SAML2.idp.singleSignOnServiceUrl L'URL de l'endpoint SSO (= Connexion) du fournisseur d'identité. string null
        → auth.SAML2.idp.singleLogoutServiceUrl L'URL de l'endpoint SLS (= Déconnexion) du fournisseur d'identité. string null
        → auth.SAML2.idp.signingCert Le contenu du certificat public du fournisseur d'identité. string null
    → auth.SAML2.attributes Paramétrage fin de la correspondance des attributs SAML2 pour la création des utilisateurs dans Loxya. Peuvent être soit une chaîne de caractère, soit un tableau. Si c'est un tableau, le premier attribut trouvé avec une valeur non nulle sera utilisé. object
        → auth.SAML2.attributes.pseudo Les noms des attributs SAML2 à utiliser pour construire le pseudo de l'utilisateur. string (ou array) "givenName"
        → auth.SAML2.attributes.email Les noms des attributs SAML2 à utiliser pour construire l'adresse email de l'utilisateur. string (ou array) ["mail", "email"]
        → auth.SAML2.attributes.group Les noms des attributs SAML2 à utiliser pour choisir le groupe de l'utilisateur. string (ou array) "group"
        → auth.SAML2.attributes.firstName Les noms des attributs SAML2 à utiliser pour construire le prénom de l'utilisateur. string (ou array) "first_name"
        → auth.SAML2.attributes.lastName Les noms des attributs SAML2 à utiliser pour construire le nom de famille de l'utilisateur. string (ou array) "last_name"
    → auth.SAML2.beneficiaryGroups Un (ou plusieurs) groupe(s) SAML2 dont la présence permettra de créer un bénéficiaire en même temps que l'utilisateur. string (ou array) (ou null) null
    → auth.SAML2.groupsMapping Un tableau de correspondance entre les groupes SAML2 et les groupes des utilisateurs de Loxya.
Par exemple : { "Administrateur": "admin", "Etudiant": "external" }
object {}
    → auth.SAML2.defaultGroup Le groupe utilisateur de Loxya à utiliser si aucun groupe SAML2 n'a été trouvé dans groupsMapping (voir ci-dessus).
Si null, l'utilisateur ne sera pas autorisé à se connecter.
string (ou null) null
    → auth.SAML2.nonSAMLUserLinking Quand un utilisateur se connecte via SAML2 pour la première fois alors qu'un utilisateur existe déjà avec la même adresse e-mail, détermine si le système doit le lier à son compte SAML2 ou non. boolean true
    → auth.SAML2.disableUnsolicitedRequests Détermine si Loxya doit prendre en charge les requêtes de connexion / déconnexion provenant du fournisseur d'identité sans que l'utilisateur soit passé par Loxya. boolean false
    → auth.SAML2.proxyVars Permet d'utiliser les headers X-Forwarded-* / HTTP_X_FORWARDED_PROTO pour déterminer le port / domaine / protocole. Ceci est utile notamment si l'application tourne derriere un load balancer qui met fin au protocole SSL. boolean false
signup Paramétrage de l'inscription publique object
→ auth.restrictedEmailDomains Permet de restreindre le(s) domaine(s) des adresses e-mails acceptées pour la création de compte array null
→ auth.expireAfter Délai au delà duquel les comptes en cours de création, non confirmés, expirent (en minutes) integer 120
→ auth.requireAddress L'adresse postale est-elle requise lors de l'inscription ? Si "auto", l'adresse sera requise si la facturation est activée string (ou boolean) "auto"
→ auth.allowCompanies L'inscription est-elle ouverte aux entreprises ? boolean true
→ auth.maxRegistrationBeforeCooldown Le nombre de création de comptes "temporaires" pour une même IP avant qu'une temporisation ne soit mise en place integer 2
legalDocuments Liens vers les documents légaux qui seront notamment utilisés pour rediriger les utilisateurs lorsqu'ils demandent à els consulter lors de leur inscription object
→ logger.privacyPolicy Lien vers la politique de confidentialité string (ou null) null
→ logger.termsOfUse Lien vers les conditions générales d'utilisation string (ou null) null
notifications Paramétrage des notifications object
→ notifications.overdue Notifications en cas de non retour du matériel à temps par les bénéficiaires object
    → notifications.overdue.enabled Activation de ce type de notification boolean false
    → notifications.overdue.days Liste du nombre de jours après lesquels il faut envoyer une notification tant que le matériel n'est pas restitué. array [1,15,22,27,30]
→ notifications.preparers Notifications des préparateurs de commande avant un événement object
    → notifications.preparers.enabled Activation de ce type de notification boolean false
    → notifications.preparers.daysBefore Nombre de jours avant la date de l'événement pour envoyer la notification. number 1

Personnaliser les devis et factures

Attention
En France, la modification de la structure des données des factures est fortement déconseillée, à moins de savoir parfaitement ce que vous faites, car avec la facturation électronique et notamment le format de fichier "Factur-X", la norme impose une correspondance stricte entre la partie visuelle du PDF et le contenu de la partie XML du fichier. Cela est d'autant plus vrai que Loxya utilise le mode EXTENDED-CTC-FR de la norme EN 16931.

Il est possible de personnaliser la présentation des devis et factures, en modifiant les fichiers suivants :

  • src/views/pdf/estimate/index.twig pour les devis,
  • src/views/pdf/invoice/index.twig pour les factures.

Il s'agit d'un fichier écrit en HTML, il faut donc maîtriser ce langage. Le système de template utilisé est Twig 3 . Le système fourni des variables permettant d'afficher les diverses données de la facture. Pour utiliser une variable, il suffit d'écrire son nom entre double-accolades, comme ceci : {{ variable }}, ou {{ variable.name }}.

Pour modifier le style des éléments qui composent ces documents, vous pouvez modifier les fichiers SCSS suivants :

  • src/views/pdf/estimate/index.scss pour les devis,
  • src/views/pdf/invoice/index.scss pour les factures.

Voici la liste des variables disponibles (vous pouvez vous inspirer de ce qui est contenu dans les fichiers originaux pour plus de détails) :

Variable Description Type
locale Langue utilisée pour les traductions (fr, ou en). string
number Numéro de la facture ou du devis. string
isDraft Est-ce un brouillon ? boolean
isCreditNote Est-ce un avoir ? boolean
isPrepayment Est-ce une facture d'acompte ? boolean
date Date du devis ou de la facture. DateTime*
dueDate Date d'expiration du devis ou d'échéance de la facture DateTime*
dueDelay Délai en jour avant expiration du devis ou échéance de la facture number

seller

Informations du vendeur (votre organisation).

object
seller.name Nom (raison sociale) du vendeur. string
seller.logo Logo à afficher en en-tête de la facture. string
seller.identifier Le numéro d'identification du vendeur (SIRET/SIREN en France). string
seller.address Adresse complète du vendeur (utiliser la méthode .format() pour l'affichage). object
seller.country Pays du vendeur (un objet contenant notamment le code et le nom du pays). object
seller.phone Numéro de téléphone du vendeur. string
seller.email Adresse e-mail de contact du vendeur. string
seller.vatNumber Le numéro de T.V.A. du vendeur (si applicable). string
seller.activityCode Le code de l'activité du vendeur (APE en France). string
seller.shareCapital Le montant du capital social du vendeur (si applicable). string
seller.tradeRegistryCity La ville d'enregistrement du vendeur (registre du commerce en France) (si applicable). string

buyer

Information de l'acheteur (bénéficiaire)

object
buyer.name Le nom complet de l'acheteur (raison sociale si c'est une société). string
buyer.isCompany Est ce que l'acheteur est une société ? boolean
buyer.identifier Le numéro d'identification de l'acheteur (SIRET/SIREN en France), si c'est une société. string
buyer.vatNumber Le numéro de T.V.A. de l'acheteur, si c'est une société. string
buyer.isSameVatArea Et-ce que l'acheteur (si c'est une société) est dans la même zone légale de T.V.A. que le vendeur ? boolean
buyer.address Adresse complète de l'acheteur (utiliser la méthode .format() pour l'affichage). object
buyer.country Pays de l'acheteur (un objet contenant notamment le code et le nom du pays). object
buyer.contactName Le nom complet de la personne contact associée à l'acheteur (si c'est une société). string
buyer.serviceCode Le code service de l'acheteur (si c'est une institution par exemple). string
buyer.reference La référence de l'acheteur. string
currency Devise utilisée dans le document (code ISO, par ex. EUR). string
orderNumber Numéro du bon de commande string
parentEstimate Le devis auquel est rattaché la facture
(un objet avec les données du devis, notamment number et date)
object
parentInvoice La facture à laquelle est rattaché l'avoir
(un objet avec les données de la facture, notamment number et date)
object

booking

L'événement ou la réservation lié au devis ou à la facture (si pertinent)

object
booking.type Le type de booking (événement ou réservation) string
booking.title Le titre de l'événement (si c'en est un) string
booking.reference La référence de la réservation (si c'en est une) string
booking.period La période (de facturation) de l'événement ou réservation Period***

materials

Détail du matériel, trié par sous-catégories (voir ci-dessous).

object
materials[category] La liste du matériel de la catégorie (le nom de la catégorie est dans la clé). array
materials[category][x][reference] Référence du matériel. string
materials[category][x][name] Nom du matériel. string
materials[category][x][description] Description du matériel. string
materials[category][x][quantity] Quantité du matériel. integer
materials[category][x][unit_price_period] Tarif de location (unité) pour la période. float**
materials[category][x][unit_replacement_price] Prix de remplacement du matériel (unité). float**
materials[category][x][tax] La taxe associée au matériel (voir la macro lineTax dans le fichier original). object
materials[category][x][has_discount] Est-ce que la ligne de matériel a une remise ? boolean
materials[category][x][discount_rate] Le taux de remise du matériel. float**
materials[category][x][total_without_taxes] Montant total hors taxe pour la ligne de matériel. float**

extras

Lignes additionnelles.

array
extras[x].description Description de la ligne additionnelle. string
extras[x].quantity Quantité de la ligne additionnelle. integer
extras[x].unit_price Prix unitaire de la ligne additionnelle. float**
extras[x].total_without_taxes Sous-total hors-taxes de la ligne additionnelle. float**
extras[x].tax La taxe associée au matériel (voir la macro lineTax dans le fichier original). object
extras[x].has_discount Est-ce que la ligne additionnelle a une remise ? number
extras[x].discount_rate Le taux de remise de la ligne additionnelle. number

prepayments

Les acomptes existants (liés au même devis)

array
prepayments[x].index Le numéro d'apparition dans la liste des acomptes. integer
prepayments[x].date La date de l'acompte. DateTime*
prepayments[x].number Le numéro de facture de l'acompte. string
prepayments[x].tax La taxe associée à l'acompte (voir la macro lineTax dans le fichier original). object
prepayments[x].amount Le montant de l'acompte. string
totalPrepayments Montant total des acomptes existants float**
hasGlobalDiscount Y a-t-il une remise globale ? boolean
globalDiscountRate Taux de la remise globale (en %). float**
totalGlobalDiscount Montant total de la remise. float**
totalWithoutGlobalDiscount Montant total hors remise globale. float**
totalWithoutTaxes Montant total hors taxes. float**
totalTaxes Montant total des taxes. float**
totalWithTaxes Montant total toutes taxes comprises. float**
globalTaxRegime Le régime de taxe à utiliser (voir Loxya\Support\Invoicing\TaxRegime) TaxRegime
isVatExempted Est-ce que le devis ou la facture est exemptée de T.V.A. ? boolean
isVatOutOfScope Est-ce que le devis ou la facture est hors contexte de la facturation électronique ? boolean
isSimpleVatSystem Est-ce que le système de taxe s'appelle "T.V.A." ou non ? boolean

taxFootnotes

Liste de notes à propos des taxes

array
taxFootnotes[x].index Le numéro d'apparition dans la liste des notes de T.V.A. integer
taxFootnotes[x].reason La note de T.V.A. elle-même. string
globalTaxExemptionReason Mention expliquant la raison d'exemption de T.V.A. string
legalMentions Liste des mentions légales (tableau de string) array
specialMentions Mention spéciale string
paymentMethods Méthodes de paiement acceptées (tableau d'objets contenant la clé value). array

bankTransferData

Le RIB du vendeur (compte bancaire à créditer)

object
bankTransferData.iban Le code IBAN à afficher. string
bankTransferData.bic Le code BIC/SWIFT à afficher. string
bankTransferData.holder Le nom complet du détenteur du compte. string
showTotalReplacementPrice Faut-il afficher le total des valeurs de remplacement du matériel ? boolean
totalReplacement Montant total des valeurs de remplacement du matériel float**
showTotalisableProperties Faut-il afficher les totaux des caractéristiques spéciales ? boolean

totalisableProperties

Liste des caractéristiques spéciales à totaliser

array
totalisableProperties[x].name Le nom de la caractéristique spéciale. string
totalisableProperties[x].value La valeur du total correspondant à la caractéristique spéciale. float**
totalisableProperties[x].unit L'unité de mesure éventuelle de la caractéristique spéciale. string

Personnaliser les fiches de sortie

De même que pour les devis et factures, il est possible de modifier les fichiers suivants pour personnaliser les fiches de sortie :

  • src/views/pdf/event-summary.twig pour les événements,
  • src/views/pdf/reservation-summary.twig pour les réservations ( Premium).

Il s'agit également d'un fichier écrit en HTML, avec le système de template Twig 3 . Des variables permettent d'utiliser les données de l'événement ou la réservation, qu'il suffit d'écrire entre double-accolades, comme ceci : {{ variable }}, ou {{ variable.name }}.

Voici la liste des variables disponibles :

Variable Description Type
now Date du jour DateTime*
currency Devise de la facture (code ISO, par ex. EUR). string
locale Langue utilisée pour les traductions (fr, ou en). string
currencyName Nom de la devise de la facture (p. ex. Euro). string
sortedBy Le classement général du matériel (soit lists, soit parks) string
materialDisplayMode Le classement du matériel dans les listes (voir les paramètres) string
customText Texte personnalisé en bas de page (voir les paramètres).
Contient les clés : title (le titre) et content (le texte).
Array
showLegalNumbers Les numéros légaux doivent-ils apparaître ? (voir les paramètres) boolean
showReplacementPrices Les valeurs de remplacement doivent-elles apparaître dans la liste du matériel ? (voir les paramètres) boolean
showDescriptions Les descriptions du matériel doivent-elles apparaître dans la liste ? (voir les paramètres) boolean
showTags Les tags associés au matériel doivent-ils apparaître dans la liste ? (voir les paramètres) boolean
showUnitsSerialNumbers Les numéros de série des unités du matériel doivent-ils apparaître dans la liste ? (voir les paramètres) boolean
showPictures Les photos du matériel doivent-elles apparaître dans la liste ? (voir les paramètres) boolean

company

Informations de votre société.

Array
company.name Nom de votre société. string
company.street Adresse de votre société (rue et n°). string
company.zipCode Code postal de votre société. string
company.locality Ville de votre société. string
company.country Pays de votre société. string
company.phone Numéro de téléphone de votre société. string
company.email Adresse e-mail de contact de votre société. string
company.vatNumber Le numéro de T.V.A. de votre société. string
company.legalNumbers Numéros spéciaux de votre société.
(Par exemple, n° SIRET ou code APE, voir fichier de config).
Pour chaque numéro, les clés name et value sont disponibles.
Array

event

Informations de l'événement à facturer.

Array
event.title Titre (nom) de l'événement. string
event.description Description de l'événement. string
event.operation_period Période d'exploitation de l'événement. Period***
event.mobilization_period Période de mobilisation du matériel de l'événement. Period***
event.location Localisation (lieu) de l'événement. string
event.preparer Le préparateur de commande de l'événement (avec full_name, email, phone...) Array
event.is_confirmed L'événement est-il confirmé ? boolean
event.total_replacement Le montant total des valeurs de remplacement du matériel de l'événement. float**

beneficiaries
La liste des bénéficiaires de l'événement. Array
beneficiaries[x][full_name] Nom complet du bénéficiaire. string
beneficiaries[x][street] Adresse (rue et numéro) du bénéficiaire. string
beneficiaries[x][postal_code] Code postal du bénéficiaire. string
beneficiaries[x][locality] Ville du bénéficiaire. string

technicians
La liste des assignations de techniciens de l'événement. Array
technicians[x][name] Nom complet du technicien. string
technicians[x][phone] Numéro de téléphone du technicien. string
technicians[x][assignments] Liste des assignations du technicien.
Chaque élément contient : period (dates de l'assignation) et position (poste du technicien).
Array

materialsSorted

Liste du matériel (le tri dépend de materialDisplayMode et de sortedBy).

Array
materialsSorted[x][name] Nom de la sous-catégorie, ou du parc. string
materialsSorted[x][materials] Liste du matériel de la sous-catégorie ou du parc. Array
materialsSorted[x][materials][x][reference] Référence du matériel. string
materialsSorted[x][materials][x][name] Nom du matériel. string
materialsSorted[x][materials][x][quantity] Quantité du matériel alloué. integer
materialsSorted[x][materials][x][rentalPrice] Tarif de location (unité). float**
materialsSorted[x][materials][x][replacementPrice] Prix de remplacement total du matériel. float**
materialsSorted[x][materials][x][total] Montant total pour le matériel. float**

totalisableProperties

Liste des caractéristiques spéciales à totaliser

array
totalisableProperties[x].name Le nom de la caractéristique spéciale. string
totalisableProperties[x].value La valeur du total correspondant à la caractéristique spéciale. float**
totalisableProperties[x].unit L'unité de mesure éventuelle de la caractéristique spéciale. string

* Les variables du type DateTime peuvent être formatées avec le filtre format_date() de Twig .
** Les variables du type float peuvent être formatées avec le filtre format_currency() de Twig si on veut un montant en devise, ou bien le filtre format_percent_number() si on veut un nombre en %. *** Les variables du type Period peuvent être formatées avec le filtre format_period(type, locale).