⇧
Exécuter Function Coopérative - 30/12/2024 13:55:53
#DECLARE($classe : Object; $params : Object)->$numProc : Integer
var $nomProcess; $nomTache : Text
var $data : Object
var $trace : cs._Trace
$trace:=cs._Trace.me
$numProc:=0
Case of
: (Not(OB Is defined($params; "functionID")))
$trace.EnvoyerMessages([msgk_event; msgk_log]; "Initialisation :"; Current method name; "'functionID' n'est pas défini dans $2")
: (Value type($params.functionID)#Is text)
$trace.EnvoyerMessages([msgk_event; msgk_log]; "Initialisation :"; Current method name; "'$2.functionID' n'est pas un texte")
: (Not(OB Is defined($params; "numProcessAppelant")))
$trace.EnvoyerMessages([msgk_event; msgk_log]; "Initialisation :"; Current method name; "'numProcessAppelant' n'est pas défini dans $2")
: ($params.numProcessAppelant=-1)
$nomTache:=$params.nomTache
$nomProcess:="$ALV_process_"+$nomTache
If (OB Is defined($params; "nomProcess"))
$nomProcess:=$params.nomProcess
End if
// créer le nouveau process
$params.numProcessAppelant:=Current process
$numProc:=New process(Current method name; 0; $nomProcess; $classe; $params; *)
Else
// c'est ok
cs.$composant.new().InitProcess()
// construire la classe
$data:=$classe.new()
If ($data[$params.functionID]#Null)
// lancer le traitement demandé
$data[$params.functionID]($params)
// ici pas de callBack
Else
$trace.EnvoyerMessages([msgk_event; msgk_log]; "Initialisation :"; Current method name; "La classe "+$classe.name+" n'est pas de function "+$params.functionID)
End if
$numProc:=Current process
End case
⇧
Bac à sable JLOG - 04/01/2026 17:27:58
Partagée entre composants et base hôte
var $commande; $i : Integer
var $c : Collection
var $o : Object:=New object
//cs.$composant.new().InitProcess()
//cs.$LogsWebImport.new().ExtaireLesChamps($x)
$c:=[0]
//$c.push(1)
$c.push(3)
//$c.push(4)
//$c.push(5)
$commande:=0
For each ($i; $c)
$commande:=$commande ?+ $i
End for each
If ($commande ?? 0)
// afficher la console de l'application
var $params : Object
$params:=New object
$params.Commande:="Afficher"
$params.sourceLogs:=ALV Client APP
$params.wndTitre:="Logs Composant JLOGS"
$params.nbrMaxLogs:=2000
cs.xSDK.EvenementsALV.me.AfficherEditeur($params)
Waiting(60)
End if
If ($commande ?? 1)
cs.$LogsWebImport.new().ImporterLogs()
End if
If ($commande ?? 3)
// lire la BDD Web
cs.$LogsWebEditeur.new().OuvrirFormulaire($o)
End if
If ($commande ?? 4)
// lire la BDD App
cs.$LogsAppImport.new().ImporterLogs()
End if
If ($commande ?? 5)
//$o.execute:=Formula(cs.$LogsAppImport.new().NettoyerBDD())
//CALL WORKER("WK_Composant_JLOG"; Formula($o.execute()))
// editer la BDD App
cs.$LogsAppEditeur.new().OuvrirFormulaire($o)
End if
If ($commande ?? 31)
cs.$composant.new().ModifierTraduction()
End if
⇧
Exécuter Function Préemptive - 03/06/2025 11:20:25
Capable de process préemptif
#DECLARE($classe : Object; $params : Object)->$numProc : Integer
var $nomProcess; $nomTache : Text
var $data : Object
var $trace : cs._Trace
$trace:=cs._Trace.me
$numProc:=0
Case of
: (Not(OB Is defined($params; "functionID")))
$trace.EnvoyerMessages([msgk_event; msgk_log]; "Initialisation :"; Current method name; "'functionID' n'est pas défini dans $params")
: (Value type($params.functionID)#Is text)
$trace.EnvoyerMessages([msgk_event; msgk_log]; "Initialisation :"; Current method name; "'$params.functionID' n'est pas un texte")
: (Not(OB Is defined($params; "nomTache")))
// nécessaire pour tuer la tâche
$trace.EnvoyerMessages([msgk_event; msgk_log]; "Initialisation :"; Current method name; "'nomTache' n'est pas défini dans $params")
: (Not(OB Is defined($params; "numProcessAppelant")))
$trace.EnvoyerMessages([msgk_event; msgk_log]; "Initialisation :"; Current method name; "'numProcessAppelant' n'est pas défini dans $params")
: ($params.numProcessAppelant=-1)
$nomTache:=$params.nomTache
// supprimer la tâche existante
cs.xSDK.RegistreTaches.new().Tuer($nomTache)
$nomProcess:="$JLOG_"+$nomTache
If (OB Is defined($params; "nomProcess"))
$nomProcess:=$params.nomProcess
End if
// créer le nouveau process
$params.numProcessAppelant:=Current process
$numProc:=New process(Current method name; 0; $nomProcess; $classe; $params; *)
Else
// c'est ok
// construire la classe
$data:=$classe.new()
$data.InitProcess()
If ($data[$params.functionID]#Null)
// créer la tâche associée
// numProcessAppelant est nécessaire pour tuer toutes les tâches d'un même process
$params.tache:=cs.xSDK.RegistreTaches.new().Inscrire(New object("nomProcess"; Current process name; "nomTache"; $params.nomTache; "numProcessAppelant"; $params.numProcessAppelant))
// lancer le traitement demandé
$data[$params.functionID]($params)
// désinscrire la tâche 'nomTache'
$params.tache.DésInscrire()
Else
$trace.EnvoyerMessages([msgk_event; msgk_log]; "Initialisation :"; Current method name; "La classe "+$classe.name+" n'est pas de function "+$params.functionID)
End if
$numProc:=Current process
End case
⇧
traceHandler - 23/12/2024 10:08:40
Capable de process préemptif
cs._Trace.me.Intercepter()
⇧
COMPILER - 09/12/2024 18:55:23
var ErrorNum : Integer
var ErrorDescription : Text
ARRAY LONGINT(ID; 0)
ARRAY LONGINT(BYTES_SENT; 0)
ARRAY TEXT(ADRESS_IP; 0)
ARRAY TEXT(COOKIE; 0)
ARRAY TEXT(HOST_NAME; 0)
ARRAY TEXT(URL_PAGE; 0)
ARRAY TEXT(USER_AGENT; 0)
ARRAY TEXT(USER_NAME; 0)
ARRAY TEXT(HTTP_REQUEST; 0)
ARRAY TEXT(ADRESS_IP_SERVER; 0)
ARRAY LONGINT(SERVER_STATUS; 0)
ARRAY TEXT(URI; 0)
ARRAY TEXT(URI_QUERY; 0)
ARRAY TEXT(URI_STEM; 0)
ARRAY DATE(DATE_GMT_CONNEXION; 0)
ARRAY TEXT(TIME_GMT; 0)
ARRAY LONGINT(DELAY_SERVER; 0)
⇧
[class]$composant - 06/02/2026 18:01:58
property trace : cs._Trace
property nomServeurWeb; FichierRessources; FormatJournal; racineXML; nomFichier : Text
property dossiersLogs; fichiersLogs : Collection
Class constructor()
This.trace:=cs._Trace.me
// ----------------------
// MARK:Installation
// ----------------------
Function InitVariablesJLOG()
var $data : Object
//••••• variables globales système •••••
Use (Storage)
Storage["System"]:=New shared object
Storage["Processes"]:=New shared object
Storage["Host"]:=New shared object
End use
Use (Storage.System)
Storage.System.Status:=0
Storage.System.estExecuteDansHote:=False
// tout le monde n'est pas initialisé ; on ne sait pas si on est serveur Web
Storage.System.estServeurWeb:=False
Storage.System.AlertesHôte:=6 // gère les messages d'alerte
$data:=cs.xSDK.EnvironnementALV.new()
Storage.System.typeApplication:=$data.typeApplication()
Storage.System.estServeur:=$data.estServeur()
Storage.System.estClient:=$data.estClient()
End use
// partager des ressources
$data:=New object
// fichier de ressources
$data.chemin:=Get 4D folder(Current resources folder)+"DataJLOG.xml"
// mémoriser
cs.xSDK.ResourceALV.me.Inscrire(Est Ressource JLog; $data)
Function Installer()
Use (Storage.System)
Storage.System.estExecuteDansAPP:=cs.xSDK.EnvironnementALV.new().estExecuteDansAPP()
End use
This.InstallerDonnéesHote()
Function InstallerDonnéesHote()
// lire les données d'installation
var $attribut : Text
var $data : Object
Case of
: (Not(Storage.System.estExecuteDansHote))
// exécution du composant en local
: (Not(Storage.System.estExecuteDansAPP))
// exécution du composant dans un composant
: (Storage.System.typeApplication=ALV Client APP)
: (Storage.System.typeApplication=4D Remote mode)
// filtrer
Else
$data:=New object
EXECUTE METHOD(Lire Données Hôte Partagées; $data)
// recopier les données reçues
Use (Storage.Host)
For each ($attribut; OB Keys($data))
Storage.Host[$attribut]:=$data[$attribut]
End for each
End use
End case
Function InitProcess()
ON ERR CALL(Formula(traceHandler).source) // gestion des erreurs
ErrorNum:=0
ErrorDescription:=""
Function InitResult()->$result : Object
$result:=New object("Error"; 0; "ErrorDescription"; "")
Function getDossierLogs($params : Object)->$result : Object
// renvoyer le dossier des logs en fonction de l'environnement
$result:=New object("dossier"; Null)
Case of
: (Not(OB Is defined($params; "typeApplicationImport")))
// circuler
: ($params.typeApplicationImport=ALV Serveur APP)
$result.dossier:=Folder(Data file; fk platform path).parent.folder("Logs")
: ($params.typeApplicationImport=ALV Client APP)
$result.dossier:=Folder(fk home folder).folder("Library/Caches/AinsiLaVie Client").folders().query("name = :1"; "AinsiLaVie_srv-sourderie_ainsilavie_fr@")
If ($result.dossier.length>0)
$result.dossier:=$result.dossier[0].folder("Logs")
End if
: ($params.typeApplicationImport=ALV BDD mère)
$result.dossier:=Folder(fk logs folder; *)
: ($params.typeApplicationImport=100)
$result.dossier:=Folder(Structure file; fk platform path).parent.parent.parent.folder($params.nomDossierTest).folder("Logs")
End case
// ----------------------
// MARK:Editeurs
// ----------------------
Function ModifierTraduction()
// ouvrir l'éditeur des traductions
cs.xSDK.TraductionsEditeur.new().ModifierTraductions()
Function _OuvrirFormulaire_process($params : Object)
// méthode du process U_Nav LogsWeb
var $wndNum : Integer
var $nomForm : Text
// récupérer les paramètres (peuvent avoir changé depuis l'ouverture)
This.Installer()
NO DEFAULT TABLE
// la fenêtre est ouverte en taille normale
//$wndNum:=Open form window($nomForm; Movable form dialog box; Horizontally centered; Vertically centered; *)
$nomForm:=$params.nomFormulaire
$wndNum:=Open form window($nomForm; -Palette form window; Horizontally centered; Vertically centered; *)
// initialiser la valeur
DIALOG($params.nomFormulaire; This)
CLOSE WINDOW
CLEAR VARIABLE($wndNum)
Function FixerEtatOccupé($état : Boolean)
OBJECT SET VISIBLE(*; "AsynchroProgress"; $état)
Form.AsynchroProgress:=Num($état)
Function estOccupé()->$result : Boolean
$result:=(Form.AsynchroProgress=1)
Function TerminerAction()
Form.FixerEtatOccupé(False)
// ----------------------
// MARK:Requetes HTTP
// ----------------------
Function RequeterDossierLogsServeur($params : Object)
// principe : la demande est envoyée au serveur Web Hôte
// 'sur connexion Web' reçoit l'URL et appelle xJLOG.$composant.RequeteJournaux() ; résultat dans .reqRetour
// attention, ici il faut requeter les serveur Web avec une function d'une classe qui renvoie un objet
If (Storage.System.estExecuteDansHote)
ASSERT(This.trace.DebugerMethode("Post requête"; Current method name; JSON Stringify($params; *)))
// envoyer la requête HTTP
Storage.Host.RequeteHTTP.call().Requeter("/4DHTTP/xJLOG/$composant/RequeteJournaux"; "GET"; $params; "blob")
Else
$params.reqRetour:=Null
End if
Function RequeteJournaux($params : Object)
// ici on est sur le serveur ; traitement des requetes HTTP de la base hôte
// on doit renvoyer un objet, que le serveur Web hote enverra
var $dataTexte : Text
var $data; $classObjet : Object
// conteneur les données
$params.reqRetour:=Null
Case of
: ($params=Null)
: (Not(OB Is defined($params; "functionID")))
: (OB Is defined(This; $params.functionID))
$data:=This[$params.functionID]($params)
: (OB Is defined(cs.$LogsAppImport.new(); $params.functionID))
// ok à traiter par cette classe
$classObjet:=cs.$LogsAppImport.new()
$classObjet[$params.functionID]($params)
: (OB Is defined(cs.$LogsWebImport.new(); $params.functionID))
// ok à traiter par cette classe
$classObjet:=cs.$LogsWebImport.new()
$classObjet[$params.functionID]($params)
End case
Function LireLogs()->$result : Collection
// renvoyer le contenu de chaque fichier de la collection This.fichiersLogs
var $fichierLogs : 4D.File
var $fhandle : 4D.FileHandle
var $lines : Collection
$result:=New collection
If (This.fichiersLogs.length>0)
For each ($fichierLogs; This.fichiersLogs)
$fhandle:=$fichierLogs.open("read")
$lines:=New collection
While (Not($fhandle.eof))
$lines.push($fhandle.readLine())
End while
$result.push(New object("nomFichier"; $fichierLogs.fullName; "contenu"; $lines))
This.trace.EnvoyerMessages([msgk_event; msgk_log]; "Lignes trouvées "+Choose($lines.length>0; "[OK]"; "[KO]"); Current method name; String($lines.length)+" lignes (entête et logs)")
End for each
End if
// ----------------------
// MARK:Utilitaires
// ----------------------
Function EncoderBase64($params : Variant)->$result : Text
var $dataBlob : Blob
SET BLOB SIZE($dataBlob; 0)
VARIABLE TO BLOB($params; $dataBlob)
BASE64 ENCODE($dataBlob; $result)
Function DécoderBase64($dataTexte : Text)->$result : Variant
var $dataBlob : Blob
SET BLOB SIZE($dataBlob; 0)
BASE64 DECODE($dataTexte; $dataBlob)
BLOB TO VARIABLE($dataBlob; $result)
⇧
[class]_BDD - 06/02/2026 17:59:28
property Logs; Log : Collection
property NomsChamps; ParamsChamps : Collection
Class extends $composant
Class constructor()
ARRAY LONGINT(TABID; 0)
ARRAY TEXT(TABFICHIER; 0)
Super()
// ----------------------
// MARK:BDD
// ----------------------
Function getDossierBDD_Log($contexte : Text; $nomDossiertest : Text)->$chemin : Text
var $fichier; $nomDossier : Text
var $dossier : 4D.Folder
$fichier:=""
$dossier:=Null
Case of
: (Not(cs.xSDK.ResourceALV.me.SetVariable(Est Ressource JLog; $contexte; Is text; ->$fichier)))
// pas de nom du dossier de la BDD journaux Web
: (Not(Storage.System.estExecuteDansHote))
// exécution en local ; utiliser une BDD de test
$dossier:=Folder(Structure file(*); fk platform path)
$dossier:=$dossier.parent.parent.parent.folder($nomDossiertest).folder($fichier)
: (Storage.System.typeApplication=ALV Serveur APP)
: (Storage.System.typeApplication=ALV Client APP)
// hors sujet
: (Not(cs.xSDK.ResourceALV.me.SetVariable(Est Ressource JLog; "DossierJournauxALV"; Is text; ->$nomDossier)))
Else
$dossier:=Folder(fk data folder; *).folder($nomDossier).folder($fichier)
End case
$chemin:=""
Case of
: ($dossier=Null)
: ($dossier.exists)
// c'est bon
$chemin:=$dossier.platformPath
: ($dossier.create())
// c'est créé
$chemin:=$dossier.platformPath
Else
$chemin:=""
End case
ASSERT(This.trace.DebugerMethode("$LogAppEditeur"; Current method name; "dossier de la BDD des journaux App : "+$chemin))
This.trace.Créer(-16101*Num($chemin=""); Current method name; "le chemin du dossier de la BDD des journaux App est vide").LeverException([msgk_event; msgk_log])
Function OuvrirBDD_Externe($cheminBDD : Text)->$chemin : Text
var $sql_BDDpath; $sql_BDDcourantePath : Text
// SQL ne peut pas utiliser directement $cheminDossier
$sql_BDDpath:=$cheminBDD
// lire la BDD externe ouverte
$sql_BDDcourantePath:=""
Begin SQL
SELECT DATABASE_PATH() FROM _USER_SCHEMAS LIMIT 1 INTO :$sql_BDDcourantePath;
End SQL
If (Position("/"; $sql_BDDcourantePath)>0)
$sql_BDDcourantePath:=Convert path POSIX to system($sql_BDDcourantePath)
End if
Case of
: ($sql_BDDpath+".4DB"=$sql_BDDcourantePath)
// déjà ouverte, ne rien faire
: (Test path name($sql_BDDpath+".4DB")=Is a document)
// ouverture d'une BDD $nomBDD existante
Begin SQL
USE DATABASE DATAFILE :$sql_BDDpath AUTO_CLOSE;
End SQL
// attention ici on est thread-safe
This.trace.EnvoyerMessages([msgk_event]; "Ouverture de la BDD"; Current method name; "<"+$sql_BDDpath+">")
Else
// nouvelle BDD externe
//-- créer les fichiers $fichier.4DB et $fichier.4DD
// rappel : la structure sera créée par apprentissage des fichiers log
Begin SQL
CREATE DATABASE IF NOT EXISTS DATAFILE :$sql_BDDpath;
USE DATABASE DATAFILE :$sql_BDDpath AUTO_CLOSE;
End SQL
// créer la structure
This.CreerTablesEnBDD()
This.trace.EnvoyerMessages([msgk_event]; "Création de la BDD"; Current method name; "<"+$sql_BDDpath+">")
End case
$chemin:=$sql_BDDpath
// Maintenant toutes les requêtes SQL du process sont dirigées vers $sql_BDDpath
Function CreerTablesEnBDD()
// créer toutes les table et leurs champs suivant le format 'FormatBDD'
var $table; $champ : Object
var $texte : Text
var $afaire : Boolean
// peut être dejà fait
ARRAY TEXT($tables; 0)
Begin SQL
SELECT TABLE_NAME FROM _USER_TABLES INTO :$tables;
End SQL
$afaire:=True
Case of
: (Size of array($tables)=0)
: (Find in array($tables; This.FormatJournal)=-1)
Else
$afaire:=False
End case
If ($afaire)
// les tables sont à créer
For each ($table; This.getFormatBDD())
// on a une table
Case of
: (Not(OB Is defined($table; "nomTable")))
: (Not(OB Is defined($table; "champs")))
: ($table.champs.length=0)
Else
// ok on a une table et ses champs
// créer la commande de création d'une table et ses champs
$texte:="CREATE TABLE IF NOT EXISTS "+$table.nomTable
// lister les champs
$texte:=$texte+" ("
For each ($champ; $table.champs)
$texte:=$texte+$champ.champ+" "+$champ.type+", "
End for each
// fermer
$texte:=Substring($texte; 1; Length($texte)-2)+");"
End case
Begin SQL
EXECUTE IMMEDIATE :$texte;
End SQL
// id automatique
$texte:="ALTER TABLE "+$table.nomTable+" MODIFY id ENABLE AUTO_INCREMENT;"
Begin SQL
EXECUTE IMMEDIATE :$texte;
End SQL
End for each
End if
Function LireLogsEnBDD($typeApplication : Integer; $c : Collection)
// requête SQL de la BDD ; résultat dans $c
var $data; $champ : Object
var $ref_colonne; $expression_arithmétique : Text
var $sql_Commande : Text
var $i : Integer
var $ptr : Pointer
Case of
: ($c=Null)
Else
// ok on a tout
// lister les params champs de la BDD
This.getFormatBDD()
// ils sont dans This.ParamsChamps
// construire la requête : This.ParamsChamps contient la liste des noms de champ SQL à sélectionner
// attention : un tableau process de nom This.ParamsChamps.champ doit exister avec le même type que la colonne SQL de ce nom
// initialiser avec l'ID et le nom de fichier
$ref_colonne:="ID, Fichier"
$expression_arithmétique:=":TABID, :FICHIER"
For each ($champ; This.ParamsChamps)
$ref_colonne:=$ref_colonne+", "+$champ.champ
$expression_arithmétique:=$expression_arithmétique+", "+":"+$champ.champ
End for each
// les données de logs
$sql_Commande:="SELECT "+$ref_colonne+" FROM "+This.FormatJournal+" WHERE TypeApp = "+String($typeApplication)+" INTO "+$expression_arithmétique+";"
Begin SQL
EXECUTE IMMEDIATE : $sql_Commande;
End SQL
// passer en objet : créer les données de la liste Box
For ($i; 1; Size of array(TABID))
$data:=New object("ID"; TABID{$i})
For each ($champ; This.ParamsChamps)
$ptr:=Get pointer($champ.champ)
$data[$champ.libelle]:=$ptr->{$i}
// ajouter l'info Fichier
$data.nomFichier:=FICHIER{$i}
End for each
$c.push($data)
End for
End case
Function FermerBDD_Externe()
Begin SQL
USE DATABASE SQL_INTERNAL;
End SQL
This.trace.EnvoyerMessages([msgk_event]; "Fermeture de la BDD "+Choose(ok=1; "OK"; "KO"); Current method name; "")
Function getFormatBDD()->$result : Collection
var $erreur : Object
var $fichier : 4D.File
$erreur:=This.InitResult()
$result:=[]
$fichier:=Folder(fk resources folder).file(This.FichierRessources)
Case of
: (Not($fichier.exists))
$erreur.Error:=-15063
$erreur.ErrorDescription:="Le fichier ressources du journal "+This.FichierRessources+" n'existe pas"
: (This.FormatJournal="")
This.trace.EnvoyerMessages([msgk_event]; "Lecture du format [KO]"; Current method name; "Le format du journal n'est pas défini")
Else
// c'est ok
// le format complet de la BDD
$result:=JSON Parse($fichier.getText(); Is collection)
// les paramètres des champs
This.ParamsChamps:=$result.query("nomTable = :1"; This.FormatJournal)[0]["champs"].copy()
// supprimer les champs inutiles pour l'import / édition
This.ParamsChamps.shift() // le ID du log
This.ParamsChamps.shift() // le lien vers le fichier
End case
This.trace.Créer($erreur.Error; Current method name; $erreur.ErrorDescription).LeverException([msgk_event; msgk_log])
Function LireFormatBDD()->$result : Object
// lire les données des différents champs possibles de la BDD
// lecture en ressource du composant
var $fichier : 4D.File
var $dataTexte; $ElémentXML; $attribut : Text
var $params : Object
var $i : Integer
var $c : Collection
TRACE
$result:=This.InitResult()
// lire le format correspondant des champs de la BDD
$fichier:=Folder(fk resources folder).file("DataJLOG.xml")
If ($fichier.exists)
$dataTexte:=""
$result:=cs.xSDK.XML.me.LireFichier($fichier; ->$dataTexte)
This.racineXML:=DOM Parse XML variable($dataTexte)
$ElémentXML:=DOM Find XML element(This.racineXML; "format_"+This.FormatJournal)
$result.Error:=-16013*Num(ok=0)
$result.ErrorDescription:="structure "+"format_"+This.FormatJournal+" non trouvée"
Else
$result.Error:=-16103
$result.ErrorDescription:="fichier "+$fichier.platformPath+" inexistant"
End if
// lire dans la structure XML les données des champs (pour SQL, ListBox...)
This.ParamsChamps:=New collection
If ($result.Error=0)
// lire les élément de chaque champ
ARRAY TEXT($tabXML; 0)
$ElémentXML:=DOM Find XML element(This.racineXML; "format_"+This.FormatJournal+"/champ"; $tabXML)
// collection des données à récupérer
$c:=New collection("nomLog"; "colonneSQL"; "typeSQL"; "libelle"; "entete")
// récupérer les données de chaque champ SQL trouvé dans la BDD
For ($i; 1; Size of array($tabXML))
$params:=New object
For each ($attribut; $c)
$ElémentXML:=DOM Find XML element($tabXML{$i}; $attribut)
If (ok=1)
// on a le nom du Log
DOM GET XML ELEMENT VALUE($ElémentXML; $dataTexte)
$params[$attribut]:=$dataTexte
End if
End for each
If (OB Keys($params).length=$c.length)
// pas d'erreur
This.ParamsChamps.push($params)
End if
End for
End if
// ----------------------
// MARK:Requetes SQL en BDD
// ----------------------
Function EnregistrerFichier($logs : Object)->$result : Text
var $sql_Commande; $UUID : Text
ALERT(Current method name)
Case of
: (Not(OB Is defined($logs; "nomFichier")))
// oops
: ($logs.nomFichier="")
Else
$UUID:=Generate UUID
$sql_Commande:="INSERT INTO FICHIERS (ID_unique, Nom) VALUES ('"+$UUID+"', '"+$logs.nomFichier+"');"
ErrorNum:=0
Begin SQL
START TRANSACTION;
EXECUTE IMMEDIATE :$sql_Commande;
COMMIT TRANSACTION;
End SQL
$result:=Choose(ErrorNum=0; $UUID; "")
End case
Function EnregistrementFichierExiste($logs : Object)->$result : Boolean
// indique si le log est déjà importé
var $sql_Commande : Text
// l'enregistrement existe s'il existe des logs avec ce nom de fichier
If (OB Is defined($logs; "nomFichier"))
$sql_Commande:="SELECT id FROM "+This.FormatJournal+" WHERE Fichier = '"+$logs.nomFichier+"' INTO :TABID;"
Begin SQL
EXECUTE IMMEDIATE :$sql_Commande;
End SQL
End if
$result:=(Size of array(TABID)>0)
Function EnregistrerLog()->$result : Boolean
// enregistrer this.Log dans la BDD
var $ref_colonne; $expression_arithmétique; $sql_Commande : Text
var $data : Object
// construire la liste de colonnes et les data associées
$ref_colonne:=""
$expression_arithmétique:=""
For each ($data; This.Log)
$ref_colonne:=$ref_colonne+", "+$data.Champ
// coder la valeur en fonction du type de value BDD
Case of
: ($data.typeValeur="INT")
$expression_arithmétique:=$expression_arithmétique+", "+String($data.Valeur)
: (($data.typeValeur="VARCHAR@") | ($data.typeValeur="TIMESTAMP"))
$expression_arithmétique:=$expression_arithmétique+", "+"'"+$data.Valeur+"'"
End case
End for each
// ajouter le lien avec la table FICHIERS
$ref_colonne:="Fichier"+$ref_colonne
$expression_arithmétique:="'"+This.nomFichier+"'"+$expression_arithmétique
$sql_Commande:="INSERT INTO "+This.FormatJournal+" ("+$ref_colonne+") VALUES ("+$expression_arithmétique+");"
ErrorNum:=0
Begin SQL
START TRANSACTION;
EXECUTE IMMEDIATE :$sql_Commande;
COMMIT TRANSACTION;
End SQL
$result:=(ErrorNum=0)
Function LireFichiers($dossierLogs : Object)->$result : Collection
var $sql_Commande : Text
$result:=New collection
// filtrer les dossiers 'associés"
If (OB Is defined($dossierLogs; "typeApplicationImport"))
//
$sql_Commande:="SELECT DISTINCT Fichier FROM "+This.FormatJournal+" WHERE TypeApp = "+String($dossierLogs.typeApplicationImport)+" INTO :TABFICHIER;"
Begin SQL
EXECUTE IMMEDIATE :$sql_Commande;
End SQL
ARRAY TO COLLECTION($result; TABFICHIER)
End if
Function SupprimerFichier($nomFichier)
var $sql_Commande : Text
$sql_Commande:="DELETE FROM "+This.FormatJournal+" WHERE Fichier = '"+$nomFichier+"';"
Begin SQL
EXECUTE IMMEDIATE :$sql_Commande;
End SQL
⇧
[class]$LogsWebImport - 13/11/2025 13:05:00
property fichiersLogs : Collection
property dossierLogs : Object
property dossierLogsTempo : 4D.Folder
Class extends $LogsWeb
Class constructor()
Super()
// ----------------------
// MARK:Import fichiers Logs
// ----------------------
Function ImporterLogs($params : Object)
// mettre à jour la BDD avec les nouveaux fichiers logs
var $dossierLogs : Object
var $logs : Object
This.OuvrirBDD_Log()
// ici la BDD est ouverte, les tables et champs sont créés et This.ParamsChamps est renseignés
// Sélectionner les dossiers à importer
This.FixerParametresDossiersLogs()
// This.dossiersLogs est renseigné.
This.dossiersLogs:=This.dossiersLogs.query("typeApplicationImport != :1"; Null)
For each ($dossierLogs; This.dossiersLogs)
// importer les logs des fichiers du dossier this.dossierLogs
This.trace.EnvoyerMessages([msgk_event; msgk_log]; "Démarrage import des fichiers"; Current method name; "Fichiers logs de l'application <"+String($dossierLogs.nomApplicationEditeur+">"))
This.dossierLogs:=$dossierLogs
This.LireFichiersLogs()
// $logs contient pour chaque fichier son nom et sa collection de logs
Case of
: (This.Logs=Null)
// pb serveur
: (This.Logs.length=0)
Else
Begin SQL
START TRANSACTION;
End SQL
For each ($logs; This.Logs)
If (Not(This.EnregistrementFichierExiste($logs)))
// le fichier n'existe pas ; l'importer
This.nomFichier:=$logs.nomFichier
This.EnregistrerLogs($logs)
This.trace.EnvoyerMessages([msgk_event; msgk_log]; "Import [OK]"; Current method name; "Fichier '"+This.nomFichier+"' importé")
End if
End for each
Begin SQL
COMMIT TRANSACTION;
End SQL
End case
This.trace.EnvoyerMessages([msgk_event; msgk_log]; "Fin import des fichiers"; Current method name; "Fichiers logs de l'application <"+String($dossierLogs.nomApplicationEditeur+">"))
End for each
This.FermerBDD_Externe()
// retour au requêteur ; en mode debug $params peut être absent
If (Count parameters>0)
$params.execute:=Formula(cs.$LogsWebEditeur.new()[$params.functionIDcallBack]())
CALL FORM($params.wndRef; Formula($params.execute().source))
End if
Function LireFichiersLogs()
// lire les logs des fichiers Logs du dossier This.dossierLogs
var $params : Object
This.Logs:=New collection
Case of
: (Not(OB Is defined(This.dossierLogs; "methodeReq")))
// erreur initialisation
: (Not(OB Is defined(This; This.dossierLogs.methodeReq)))
// erreur méthode de requête
Else
// lancer la lecture de tous ces fichiers
// il faut toujours un paramètre (compatibilité avec le cas d'un appel par le serveur
$params:=This.dossierLogs
$params.functionID:="RequeterDossierLogsWebLocal"
This[This.dossierLogs.methodeReq]($params)
// le resultat est dans .reqRetour ; peut être null si pb serveur
This.Logs:=Null
If ($params.reqRetour#Null)
This.Logs:=$params.reqRetour.Logs
End if
End case
Function EnregistrerLogs($logs : Object)
// importer dans la BDD les logs de $logs
var $log : Text
var $compteur : Integer
$compteur:=0
Case of
: (This.nomFichier="")
// il y a eu une erreur (est traitée)
: (Not(OB Is defined($logs; "contenu")))
// oops
: ($logs.contenu.length=0)
This.trace.Créer(-15068; Current method name; "Le fichier '"+$logs.nomFichier+"' est vide").LeverException([msgk_event; msgk_log])
Else
For each ($log; $logs.contenu)
// analyser chaque ligne du fichier
Case of
: ($log="#Remark: format@")
// on a le format du journal
If (("LOG_"+Substring($log; Position("format "; $log; *)+Length("format ")))#This.FormatJournal)
This.trace.EnvoyerMessages([msgk_event; msgk_log]; "Import [KO]"; Current method name; "Le fichier <"+$logs.nomFichier+"> n'est pas au format attendu ("+This.FormatJournal+")")
// dans cette version on abandonne
break
End if
: (Substring($log; 1; 7)="#Fields")
: ($log="#@") // autres entêtes
// ne rien faire
Else
// ok un bon log
// récupérer les données de ce log
This.LireLog($log)
$compteur:=$compteur+Num(This.EnregistrerLog())
End case
End for each
This.trace.EnvoyerMessages([msgk_event; msgk_log]; "Logs de "+$logs.nomFichier+Choose($compteur>0; " [OK]"; " [KO]"); Current method name; Choose($compteur>0; String($compteur)+" logs traités"; "Aucun log traité")+" sur "+String($logs.length)+" lus")
End case
Function RequeterDossierLogsWebLocal($dossierLogs : Object)
// renvoyer le contenu des fichiers logs du dossier logs courant
// attention ici on est sur la BDD mère ou le serveur
var $data : Object
var $nomDossier : Text:=""
// lire le dossier des logs
$data:=This.getDossierLogs($dossierLogs)
This.fichiersLogs:=New collection
Case of
: ($data.dossier=Null)
: (Not(cs.xSDK.ResourceALV.me.SetVariable(Est Ressource JLog; "DossierLogsWeb"; Is text; ->$nomDossier)))
// pb quelque part
: (OB Is defined($dossierLogs; "sousDossier"))
This.fichiersLogs:=$data.dossier.folder($dossierLogs.sousDossier).folder($nomDossier).files(fk ignore invisible)
Else
This.fichiersLogs:=$data.dossier.folder($nomDossier).files(fk ignore invisible)
End case
If ($data.dossier=Null)
$data.dossier:="Dossier inconnu"
Else
$data.dossier:=$data.dossier.platformPath
End if
// sélectionner les fichiers logs
//This.FiltrerFichiers()
This.trace.EnvoyerMessages([msgk_event; msgk_log]; String(This.fichiersLogs.length)+" fichiers trouvés à traiter "+Choose(This.fichiersLogs.length>0; "[OK]"; "[KO]"); Current method name; "Dans le dossier <"+$data.dossier+">")
// mettre les fichiers au format d'import dans un dossier de travail
This.FormaterFichiers()
// récupérer le contenu pour une utilisation locale
$data.Logs:=This.LireLogs()
// supprimer le dossier de travail
This.dossierLogsTempo.delete(Delete with contents)
// retourner le résultat
$dossierLogs.reqRetour:=$data
Function LireLog($log : Text)
// décoder la ligne $log et créer la collection de champs trouvés dans this.Logd
var $champs : Collection
var $champ : Text
var $indiceChamp : Integer
// trouver tous les $champs (des champs entiers ou des morceaux de champ)
$champs:=This.ExtaireLesChamps($log)
Case of
: ($champs=Null)
This.trace.Créer(-16108; Current method name; "Erreur de parsing du log "+$log).LeverException([msgk_event; msgk_log])
: ($champs.length=0)
Else
// c'est ok
This.Log:=New collection
// indice de progression de lecture des champs
$indiceChamp:=0
For each ($champ; $champs)
This.AjouterChamp($champ; ->$indiceChamp)
End for each
End case
Function AjouterChamp($mot : Text; $indiceChamp : Pointer)
var $champ : Object
Case of
: ($indiceChamp->>This.ParamsChamps.length)
// bug dans la trace : TIME apparait 2 fois ; filtrer ce cas
This.trace.Créer(-16999; Current method name; "trop de champs dans la trace ELF").LeverException([msgk_event; msgk_log])
Else
$champ:=New object
$champ.Champ:=This.ParamsChamps[$indiceChamp->].champ
$champ.typeValeur:=This.ParamsChamps[$indiceChamp->].type
$champ.Valeur:=$mot
This.Log.push($champ)
// pour la suite
$indiceChamp->:=$indiceChamp->+1
End case
// ----------------------
// MARK:Format ELF
// ----------------------
Function FormaterFichiers()
var $c : Collection
var $fichier; $fichierCopie : 4D.File
This.dossierLogsTempo:=Folder(fk documents folder).folder("tempo_"+Current method name)
This.dossierLogsTempo.create()
If (This.fichiersLogs.length>0)
This.fichiersLogs:=This.fichiersLogs.orderBy("fullName asc")
$c:=New collection
For each ($fichier; This.fichiersLogs)
$fichierCopie:=$fichier.copyTo(This.dossierLogsTempo; fk overwrite)
This.FormaterFichier($fichierCopie)
$c.push($fichierCopie)
End for each
This.fichiersLogs:=$c
End if
Function FormaterFichier($fichier : 4D.File)
var $texte; $oldValeur; $newValeur : Text
var $indexDebut; $indexFin : Integer
$texte:=$fichier.getText("UTF-8"; Document with CR)
// remplacer {retourchariot par {
$texte:=Replace string($texte; "{"+Char(Carriage return); "{")
$texte:=Replace string($texte; Char(Carriage return)+"}"; "}")
// rappel : le blanc est le caractère de séparation de valeurs de champs
// => remplacer les blancs dans les valeurs
$indexDebut:=0
Repeat
$indexDebut:=Position(Char(Double quote); $texte; $indexDebut)
$indexFin:=Position(Char(Double quote); $texte; $indexDebut+1)
$oldValeur:=Substring($texte; $indexDebut; $indexFin-$indexDebut+1)
Case of
: ($indexDebut=0)
// c'est fini
$indexDebut:=-1
: ($indexFin=0)
// fin de la valeur du champ
$indexDebut:=-1
: (Split string($oldValeur; " ").length<2)
// pas de blanc dans la valeur, ne rien faire
$indexDebut:=$indexFin+1
Else
// remplacer
$newValeur:=Replace string($oldValeur; " "; Char(160))
$texte:=Replace string($texte; $oldValeur; $newValeur)
$indexDebut:=$indexFin+1
End case
Until ($indexDebut=-1)
// idem avec
$indexDebut:=0
Repeat
$indexDebut:=Position(Char(Quote); $texte; $indexDebut)
$indexFin:=Position(Char(Quote); $texte; $indexDebut+1)
$oldValeur:=Substring($texte; $indexDebut; $indexFin-$indexDebut+1)
Case of
: ($indexDebut=0)
// c'est fini
$indexDebut:=-1
: ($indexFin=0)
// fin de la valeur du champ
$indexDebut:=-1
: (Split string($oldValeur; " ").length<2)
// pas de blanc dans la valeur, ne rien faire
$indexDebut:=$indexFin+1
Else
// remplacer
$newValeur:=Replace string($oldValeur; " "; Char(160))
$texte:=Replace string($texte; $oldValeur; $newValeur)
$indexDebut:=$indexFin+1
End case
Until ($indexDebut=-1)
$fichier.setText($texte; "UTF-8"; Document with CR)
Function ExtaireLesChamps($log)->$result : Collection
// traiter les trucs zarbis
var $champs : Collection
$result:=Null
// pb avec 4D Mobile
// remplacer 2 blancs par un blanc
$log:=Replace string($log; " "; " ")
// remplacer les champs vides par un null
$log:=Replace string($log; Char(Double quote)+Char(Double quote); "NULL")
// trouver tous les mots (des champs entiers ou des morceaux de champ)
$champs:=Split string($log; " "; sk trim spaces)
// recomposer les champs complexes (qui ont explosé dans le split)
$champs:=This.TraiterAgentAgent($champs)
$champs:=This.TraiterURI($champs)
// ici 15 champs ; le champ time est double, en supprimer un
$result:=$champs.remove($champs.length-2)
If ($result.length#14)
// autre pb ?
This.trace.EnvoyerMessages([msgk_event; msgk_log]; "Log non standard"; Current method name; $champs.join(" "))
$result:=Null
End if
// pour être compatibles des functions communes, il faut un TypeApp
$result.push(String(This.dossierLogs.TypeApp))
Function TraiterAgentAgent($champs : Collection)->$result : Collection
// le 'user-agent' démarre au champ 5 jusqu'à la méthode
var $indice : Integer
var $c : Collection
var $champ; $texte : Text
$indice:=-1
For each ($champ; New collection("GET"; "POST"; "HEAD")) While ($indice=-1)
$indice:=$champs.indexOf($champ)
End for each
Case of
: ($champs.length=14)
: ($champs.length=15)
// cas nominal ; $indice vaut 7 (non testé)
: ($indice=-1)
// log sans 'user-agent'
Else
// reconstituer le 'user-agent'
// il faut concatener entre les indices 5 et $indice -1
$c:=$champs.slice(5; $indice-1)
// créer le champ complet
$texte:=$c.join(" ")
// purger $champs
$champs:=$champs.remove(5; $c.length)
// replacer dans $champs
$champs:=$champs.insert(5; $texte)
End case
// encoder
$champs[5]:=This.EncoderBase64($champs[5])
$result:=$champs.copy()
Function TraiterURI($champs : Collection)->$result : Collection
// le 'user-agent' démarre au champ 10 jusqu'au champ .length-4 (= 11 dans le cas normal
var $c : Collection
var $texte : Text
Case of
: ($champs.length=14)
// cas nominal ; $indice vaut 7 (non testé)
: ($champs.length<16)
// quoi?
Else
// reconstituer le 'user-agent'
$c:=$champs.slice(10; $champs.length-4)
// créer le champ complet
$texte:=$c.join(" ")
// purger $champs
$champs:=$champs.remove(10; $c.length)
// replacer dans $champs
$champs:=$champs.insert(10; $texte)
End case
// encoders
$champs[10]:=This.EncoderBase64($champs[10])
$result:=$champs.copy()
⇧
[class]$LogsAppEditeur - 04/01/2026 10:59:08
property EnvALV : cs.xSDK.EnvironnementALV
property functionID; nomOBJ : Text
property LogsApp : Collection
Class extends $LogsApp
Class constructor()
Super()
This.EnvALV:=cs.xSDK.EnvironnementALV.new()
Function OuvrirFormulaire($params : Object)
// ouvrir l'éditeur de la BDD des journaux
//var $params : Object
var $numProc : Integer
//$params:=New object
$params.functionID:="_OuvrirFormulaire_process"
$params.numProcessAppelant:=-1 // dans un process externe
$params.nomProcess:="U_Nav?LogsApp"
$params.nomTache:="EditionJAPP"
$params.nomFormulaire:="U_Nav LogsApp"
$numProc:=Exécuter Function Coopérative(cs.$LogsAppEditeur; $params)
// ----------------------
//MARK:FORM Events
// ----------------------
Function _TraiterFORMevent()
If (OB Is defined(FORM Event; "objectName"))
// event d'un objet formulaire
This.functionID:="_fct_"+FORM Event.objectName
This.nomOBJ:=FORM Event.objectName
Else
// event du formulaire
This.functionID:="_fct_Formulaire"
This.nomOBJ:=""
End if
If (OB Is defined(This; This.functionID))
This[This.functionID]()
End if
Function _fct_Formulaire()
Case of
: (Form event code=On Load)
SHOW PROCESS(Current process)
This.onEndLoad()
This.MettreAjourImport()
: (Form event code=On Deactivate)
This.FermerBDD_Externe()
: (Form event code=On Close Box)
CANCEL
End case
Function onEndLoad()
var $c : Collection:=["PopupListeApps"]
var $nomOBJ : Text
For each ($nomOBJ; $c)
If (OB Is defined(This; "_fct_"+$nomOBJ))
This.nomOBJ:=$nomOBJ
This["_fct_"+$nomOBJ]()
End if
End for each
Function MettreAjourImport()
// mettre à jour la BDD avec les fichiers récents (non importés)
var $data : Object
// dans un worker
$data:=New object("params"; New object)
$data.params.wndRef:=Current form window
$data.params.functionIDcallBack:="TerminerAction"
$data.execute:=Formula(cs.$LogsAppImport.new().MettreAjourImport(This.params))
CALL WORKER("WK_Composant_JLOG"; Formula($data.execute()))
This.FixerEtatOccupé(True)
Function _fct_LogsApp()
Case of
: (Form event code=On Load)
This.FormaterTypeAPP()
This.FormaterDescription()
End case
Function _fct_PopupListeApps()
var $data : Object
Case of
: (Form event code=On Load)
// lister les App
This.FixerParametresDossiersLogs()
// This.dossiersLogs est renseigné. Sélectionner les dossiers à importer
This.dossiersLogs:=This.dossiersLogs.query("typeApplicationEditeur != :1"; Null).orderBy("nomApplicationEditeur asc")
Form[This.nomOBJ]:=New object
Form[This.nomOBJ].values:=This.dossiersLogs.extract("nomApplicationEditeur")
Form[This.nomOBJ].index:=-1
Form[This.nomOBJ].currentValue:=Choose(This.dossiersLogs.length=0; Localized string("27"); Localized string("21"))
: (Form event code=On Data Change)
Case of
: (Form[This.nomOBJ].index=-1)
// rien de sélectionner
: (This.estOccupé())
// action en cours
Else
// lister les logsApp du serveur sélectionné
// dans un worker
$data:=New object("params"; New object)
$data.params:=OB Copy(This.dossiersLogs[This[This.nomOBJ].index])
$data.params.wndRef:=Current form window
$data.params.functionIDcallBack:="AfficherSélection"
$data.execute:=Formula(cs.$LogsAppEditeur.new().ToutSelectionner(This.params))
CALL WORKER("WK_Composant_JLOG"; Formula($data.execute()))
This.FixerEtatOccupé(True)
End case
End case
Function FormaterTypeAPP()->$result : Text
var $typeAPP : Object
$result:=""
If (Form.LogCourant#Null)
$typeAPP:=This.EnvALV.Applications.query("type = :1"; Form.LogCourant.TypeApplication).first()
$result:=$typeAPP.nomLong
End if
Function FormaterDescription()->$result : Text
// mettre en forme les textes JSON
var $i : Integer
var $objet : Object
$result:=""
If (Form.LogCourant#Null)
$i:=Position("{"; Form.LogCourant.Description)
If ($i>0)
$objet:=JSON Parse(Substring(Form.LogCourant.Description; $i))
$result:=Substring(Form.LogCourant.Description; 1; $i-1)+Char(Carriage return)+JSON Stringify($objet; *)
Else
$result:=Form.LogCourant.Description
End if
End if
// ----------------------
// MARK:Actions
// -----------------------
Function AfficherSélection($params : Object)
// retour d'un call à un worker
// méthode appelée dans le formulaire
var $data; $log : Object
$data:=This.DécoderBase64($params.result)
// alimenter le formulaire
// fixer les titres de la LB LogsApp
Case of
: (Not(OB Is defined(Form; "ParamsChamps")))
: (Form.ParamsChamps=Null)
Else
For each ($params; Form.ParamsChamps)
OBJECT SET TITLE(*; "LogsApp"+$params.libelle; $params.entete)
End for each
End case
OBJECT SET VISIBLE(*; "LogsApp"; False)
Case of
: (Not(OB Is defined($data; "LogsApp")))
: ($data.LogsApp=Null)
Else
// décoder les descriptions
For each ($log; $data.LogsApp)
$log.Description:=This.DécoderBase64($log.Description)
End for each
// trier par date
$data.LogsApp:=$data.LogsApp.orderBy("Date asc")
// afficher
Form.LogsApp:=$data.LogsApp
OBJECT SET VISIBLE(*; "LogsApp"; Form.LogsApp.length>0)
End case
This.TerminerAction()
Function ToutSelectionner($params : Object)
// afficher tous les logs
// méthode appelée dans un worker
This.InitProcess()
// initialiser les variables process pour les sélection SQL
ARRAY TEXT(FICHIER; 0)
ARRAY LONGINT(TYPEAPP; 0)
ARRAY TEXT(ORIGINE; 0)
ARRAY TEXT(DATE_GMT_LOG; 0)
ARRAY TEXT(NOM_PROCESS; 0)
ARRAY TEXT(NOM_FUNCTION; 0)
ARRAY TEXT(LIBELLE; 0)
ARRAY TEXT(DESCRIPTION; 0)
// les lister
This.LireLogsEnBDD($params)
// retourner la liste
This.postCallBack($params)
Function LireLogsEnBDD($params : Object)
// requête SQL de la BDD ; résultat dans $params.reqRetour
var $typeApplication : Integer
This.OuvrirBDD_Log()
This.LogsApp:=New collection
For each ($typeApplication; $params.typeApplicationEditeur)
Super.LireLogsEnBDD($typeApplication; This.LogsApp)
End for each
This.FermerBDD_Externe()
// renvoyer le résultat
$params.reqRetour:=New object
$params.reqRetour.LogsApp:=This.LogsApp
Function postCallBack($params : Object)
// appeler le formulaire $params.wndRef
var $data : Object
$data:=New object
$data.params:=OB Copy($params)
// il n'y a que le texte qui semble passer dans les .params
$data.params.result:=This.EncoderBase64($params.reqRetour)
// nettoyer
OB REMOVE($data.params; "reqRetour")
// construire l'appel au requêteur
$data.execute:=Formula(cs.$LogsAppEditeur.new()[$params.functionIDcallBack](This.params))
CALL FORM($params.wndRef; Formula($data.execute().source))
⇧
[class]$LogsWebEditeur - 19/01/2026 11:34:08
property URL_geoIP : Text:="https://fr.geoipview.com/"
property functionID; nomOBJ : Text
property LogsWeb : Collection
Class extends $LogsWeb
Class constructor()
Super()
This.LogsWeb:=Null
// ----------------------
// MARK:Formulaire
// -----------------------
Function OuvrirFormulaire($params : Object)
// ouvrir l'éditeur de la BDD des journaux
var $numProc : Integer
$params.functionID:="_OuvrirFormulaire_process"
$params.numProcessAppelant:=-1 // dans un process externe
$params.nomProcess:="U_Nav?LogsWeb"
$params.nomTache:="EditionJWEB"
$params.nomFormulaire:="U_Nav LogsWeb"
$numProc:=Exécuter Function Coopérative(cs.$LogsWebEditeur; $params)
// ----------------------
//MARK:FORM Events
// ----------------------
Function _TraiterFORMevent()
If (OB Is defined(FORM Event; "objectName"))
// event d'un objet formulaire
This.functionID:="_fct_"+FORM Event.objectName
This.nomOBJ:=FORM Event.objectName
Else
// event du formulaire
This.functionID:="_fct_Formulaire"
This.nomOBJ:=""
End if
If (OB Is defined(This; This.functionID))
This[This.functionID]()
End if
Function _fct_Formulaire()
Case of
: (Form event code=On Load)
SHOW PROCESS(Current process)
This.onEndLoad()
This.MettreAjourImport()
// attention : ici le minuteur est toujours actif (la roue doit tourner quand la palette passe en arrière plan)
: (Form event code=On Timer)
//Afficher Progression Process
: (Form event code=On Close Box)
CANCEL
End case
Function onEndLoad()
var $c : Collection:=["PopupListeServeurs"; "ZoneWeb"]
var $nomOBJ : Text
For each ($nomOBJ; $c)
If (OB Is defined(This; "_fct_"+$nomOBJ))
This.nomOBJ:=$nomOBJ
This["_fct_"+$nomOBJ]()
End if
End for each
Function MettreAjourImport()
// mettre à jour la BDD avec les fichiers récents (non importés)
var $data : Object
// dans un worker
$data:=New object("params"; New object)
$data.params.wndRef:=Current form window
$data.params.functionIDcallBack:="TerminerAction"
$data.execute:=Formula(cs.$LogsWebImport.new().ImporterLogs(This.params))
CALL WORKER("WK_Composant_JLOG"; Formula($data.execute()))
This.FixerEtatOccupé(True)
Function _fct_PopupListeServeurs()
var $data : Object
Case of
: (Form event code=On Load)
// lister les serveurs Web
This.FixerParametresDossiersLogs()
// This.dossiersLogs est renseigné. Sélectionner les dossiers à importer
This.dossiersLogs:=This.dossiersLogs.query("typeApplicationEditeur != :1"; Null)
Form[This.nomOBJ]:=New object
Form[This.nomOBJ].values:=This.dossiersLogs.extract("nomApplicationEditeur")
Form[This.nomOBJ].index:=-1
Form[This.nomOBJ].currentValue:=Choose(This.dossiersLogs.length=0; Localized string("4"); Localized string("1"))
: (Form event code=On Data Change)
Case of
: (Form[This.nomOBJ].index=-1)
// rien de sélectionner
: (This.estOccupé())
// action en cours
Else
// lister les logsWeb du serveur sélectionné
// dans un worker
$data:=New object("params"; New object)
$data.params:=OB Copy(This.dossiersLogs[This[This.nomOBJ].index])
$data.params.wndRef:=Current form window
$data.params.functionIDcallBack:="AfficherSélection"
$data.execute:=Formula(cs.$LogsWebEditeur.new().ToutSelectionner(This.params))
CALL WORKER("WK_Composant_JLOG"; Formula($data.execute().source))
This.FixerEtatOccupé(True)
End case
End case
Function _fct_LogsWeb()
var $i; $j : Integer
var $attribut : Text
var $data : Object
var $c : Collection
Case of
: ((Right click) | (Contextual click)) // Clic droit ou Control+clic
// gestion des modifications
// log sélectionnée = Form.LogCourant
// créer le popMenu
$c:=New collection(Localized string("3003"); Localized string("3002"))
// ajouter les menus contextuels
If (Form.LogCourant#Null)
// lire la ligne sélectionnée
LISTBOX GET CELL POSITION(*; "LogsWeb"; $j; $i) // colonne, ligne
// colonne sélectionnée -> attribut de Form.LogCourant
LISTBOX GET OBJECTS(*; "LogsWeb"; $tabObjetsLB)
$attribut:=Replace string($tabObjetsLB{($j-1)*3+2}; "LogsWeb"; "")
// menu lié à cette ligne
$c.unshift(Localized string("3001")+Form.LogCourant[$attribut]+Localized string("3")+Char(Double quote)+$attribut+Char(Double quote))
End if
$j:=Pop up menu($c.join(";"))
// attention, menu dynamique, dans l'ordre :
Case of
: ($j=$c.length)
// re initiliser la liste
$data:=New object("params"; New object)
$data.params:=OB Copy(This.dossiersLogs[Form.PopupListeServeurs.index])
$data.params.wndRef:=Current form window
$data.params.functionIDcallBack:="AfficherSélection"
$data.execute:=Formula(cs.$LogsWebEditeur.new().ToutSelectionner(This.params))
CALL WORKER("WK_Composant_JLOG"; Formula($data.execute().source))
Form.FixerEtatOccupé(True)
: ($j=($c.length-1))
CONFIRM("Supprimer les "+String(This.LogsWeb.length)+" logs de la sélection courante"; "Annuler"; "OK")
// attention : le btn par defaut est Annuler
If (ok=0)
// supprimer de la BDD la sélection courante
$data:=New object
$data.sélection:=Form.LogsWeb.extract("ID")
$data.wndRef:=Current form window
$data.functionIDcallBack:="AfficherSélection"
$data.execute:=Formula(cs.$LogsWebEditeur.new().SupprimerSelection($data))
CALL WORKER("WK_Composant_JLOG"; Formula($data.execute().source))
//CALL WORKER("WK_Composant_JLOG"; Formula from string("cs.$LogsWebEditeur.new().SupprimerSélection($1)"); $data)
Form.FixerEtatOccupé(True)
End if
: ($j=1)
// chercher dans la sélection courante la valeur de la ligne / colonne du clic
Form.LogsWeb:=Form["LogsWeb"].query($attribut+" = :1"; Form.LogCourant[$attribut])
End case
: (Form event code=On Clicked)
WA OPEN URL(*; "zoneWeb"; Form.URL_geoIP+"?q="+Form.LogCourant.Adress_IP+"&x=0&y=0")
End case
Function _fct_ZoneWeb()
Case of
: (Form event code=On Load)
WA OPEN URL(*; Form.nomOBJ; Form.URL_geoIP)
End case
// ----------------------
// MARK:Actions
// -----------------------
Function AfficherSélection($params : Object)
// retour d'un call à un worker
// méthode appelée dans le formulaire
var $data; $log : Object
$data:=This.DécoderBase64($params.result)
// alimenter le formulaire
// fixer les titres de la LB LogsWeb
Case of
: (Not(OB Is defined(Form; "ParamsChamps")))
: (Form.ParamsChamps=Null)
Else
For each ($params; Form.ParamsChamps)
OBJECT SET TITLE(*; "LogsWeb"+$params.libelle; $params.entete)
End for each
End case
OBJECT SET VISIBLE(*; "LogsWeb"; False)
Case of
: (Not(OB Is defined($data; "LogsWeb")))
: ($data.LogsWeb=Null)
Else
// décoder les champss complexes
For each ($log; $data.LogsWeb)
$log.Agent:=This.DécoderBase64($log.Agent)
$log.URI:=This.DécoderBase64($log.URI)
End for each
// trier par date
$data.LogsWeb:=$data.LogsWeb.orderBy("Date asc")
// afficher
Form.LogsWeb:=$data.LogsWeb
OBJECT SET VISIBLE(*; "LogsWeb"; Form.LogsWeb.length>0)
End case
This.TerminerAction()
Function ToutSelectionner($params : Object)
// afficher tous les logs
// méthode appelée dans un worker
This.InitProcess()
// initialiser les variables process pour les sélection SQL
ARRAY TEXT(FICHIER; 0)
ARRAY LONGINT(BYTES_SENT; 0)
ARRAY TEXT(ADRESS_IP; 0)
ARRAY TEXT(COOKIE; 0)
ARRAY TEXT(HOST_NAME; 0)
ARRAY TEXT(URL_PAGE; 0)
ARRAY TEXT(USER_AGENT; 0)
ARRAY TEXT(USER_NAME; 0)
ARRAY TEXT(HTTP_REQUEST; 0)
ARRAY TEXT(ADRESS_IP_SERVER; 0)
ARRAY LONGINT(SERVER_STATUS; 0)
ARRAY TEXT(URI; 0)
ARRAY TEXT(URI_QUERY; 0)
ARRAY TEXT(URI_STEM; 0)
ARRAY DATE(DATE_GMT_CONNEXION; 0)
ARRAY TEXT(TIME_GMT; 0)
ARRAY LONGINT(DELAY_SERVER; 0)
ARRAY LONGINT(TYPEAPP; 0)
// les lister
This.LireLogsEnBDD($params)
// retourner la liste
This.postCallBack($params)
Function LireLogsEnBDD($params : Object)
// requête SQL de la BDD ; résultat dans $params.reqRetour
var $typeApplication : Integer
This.OuvrirBDD_Log()
This.LogsWeb:=New collection
For each ($typeApplication; $params.typeApplicationEditeur)
Super.LireLogsEnBDD($typeApplication; This.LogsWeb)
End for each
This.FermerBDD_Externe()
// renvoyer le résultat
$params.reqRetour:=New object
$params.reqRetour.LogsWeb:=This.LogsWeb
Function postCallBack($params : Object)
// appeler le formulaire $params.wndRef
var $data : Object
$data:=New object
$data.params:=OB Copy($params)
// il n'y a que le texte qui semble passer dans les .params
$data.params.result:=This.EncoderBase64($params.reqRetour)
// nettoyer
OB REMOVE($data.params; "reqRetour")
// construire l'appel au requêteur
$data.execute:=Formula(cs.$LogsWebEditeur.new()[$params.functionIDcallBack](This.params))
CALL FORM($params.wndRef; Formula($data.execute().source))
Function SupprimerSelection($params : Object)
// supprimer la sélection courante de log et afficher ce qui reste
// méthode appelée dans un worker
ALERT("TODO delete dans BDD (dans cette version, on ne touche pas aux fichiers origine)")
//This.InitProcess()
//$params.functionID:="SupprimerLogs"
//This.Exécuter($params)
//This.trace.Créer($params.reqRetour.Error; $params.functionID; $params.reqRetour.ErrorDescription).LeverException([msgk_event; msgk_log])
// afficher ce qui reste
This.ToutSelectionner($params)
Function Exécuter($params : Object)
// exécuter la requête en local ou sur le serveur sélectionné, selon $params.methodeReq
var $result : Object
var $attribut : Text
// requêter le serveur
$result:=This[$params.methodeReq]($params)
// mémoriser le resultat dans this
For each ($attribut; OB Keys($result))
This[$attribut]:=$result[$attribut]
End for each
⇧
[class]$LogsWeb - 10/08/2026 10:06:07
Class extends _BDD
Class constructor()
Super()
// fichier des paramètres de la BDD
This.FichierRessources:="Data_LOG_ELF.json"
// paramètres du journal
This.FormatJournal:="LOG_ELF"
// lire les paramètres de champs
This.getFormatBDD()
Function FixerParametresDossiersLogs()
// chaque élément de la liste contient les paramètres de lecture d'un dossier Log (Serveur Web hôte, Serveur Web)
This.dossiersLogs:=New collection
// toujours disponibles
This.dossiersLogs.push(New object("TypeApp"; ALV Serveur APP; "typeApplicationImport"; ALV Serveur APP; "methodeReq"; "RequeterDossierLogsServeur"; "typeApplicationEditeur"; [ALV Serveur APP]; "nomApplicationEditeur"; Localized string("38")))
This.dossiersLogs.push(New object("TypeApp"; ALV Serveur APP; "typeApplicationImport"; ALV Serveur APP; "methodeReq"; "RequeterDossierLogsServeur"; "typeApplicationEditeur"; [ALV Serveur APP]; "nomApplicationEditeur"; Localized string("39"); "sousDossier"; "ALV Serveur Web"))
// non accessible hors base hôte
If (Storage.System.estExecuteDansHote)
This.dossiersLogs.push(New object("TypeApp"; ALV BDD mère; "typeApplicationImport"; ALV BDD mère; "methodeReq"; "RequeterDossierLogsWebLocal"; "typeApplicationEditeur"; [ALV BDD mère]; "nomApplicationEditeur"; Localized string("40")))
End if
// pour les tests
This.AjouterDossierDeTest(This.dossiersLogs)
// ordonner
This.dossiersLogs:=This.dossiersLogs.orderBy("nomApplicationEditeur asc")
Function AjouterDossierDeTest($c : Collection)
// ajouter le dossier pour les tests
If ((Not(Storage.System.estExecuteDansHote)) | Storage.Host.estDebugAPP())
// pour les tests depuis la BDD mère ou le composant
$c.push(New object("TypeApp"; 100; "typeApplicationImport"; 100; "methodeReq"; "RequeterDossierLogsWebLocal"; "typeApplicationEditeur"; [100]; "nomApplicationEditeur"; Localized string("41"); "nomDossierTest"; "Test JWEB"))
End if
// ----------------------
// MARK:Requêtes SQL
// ----------------------
Function OuvrirBDD_Log()->$chemin : Text
var $sql_BDDpath : Text
// fixer le nom de la BDD externe ouvrir
$sql_BDDpath:=This.getDossierBDD_Log("DossierJournalWeb"; "test JWEB")+"LogsWeb"
$chemin:=This.OuvrirBDD_Externe($sql_BDDpath)
Function SupprimerLogs($params : Object)
var $ID : Integer
var $result : Object
This.nomServeurWeb:=$params.nomServeurWeb
This.OuvrirBDD_Log()
$result:=This.InitResult()
$result.Error:=-15068
Case of
: (Not(OB Is defined($params; "sélection")))
$result.ErrorDescription:="'sélection' n'est pas défini dans $params"
: (Value type($params.sélection)#Is collection)
$result.ErrorDescription:="'$params.sélection' n'est pas une collection"
: ($params.sélection.length=0)
$result.ErrorDescription:="'$params.sélection' est une collection vide"
Else
$result.Error:=0
$result.ErrorDescription:=String($params.sélection.length)+" enregistrements détruits"
// on fait bourin (pas de DELETE par un $tab)
For each ($ID; $params.sélection)
Begin SQL
DELETE FROM LOGS WHERE ID = :$ID;
End SQL
If (ok=0)
$result.Error:=$result.Error+1
$result.ErrorDescription:=String($result.Error)+" enregistrements non détruits sur "+String($params.sélection.length)
End if
End for each
End case
$result.success:=($result.Error=0)
$params.reqRetour:=$result
This.FermerBDD_Externe()
⇧
[class]$LogsAppImport - 04/01/2026 17:27:19
property dossierLogs : Object
Class extends $LogsApp
Class constructor()
Super()
Function MettreAjourImport($params : Object)
This.NettoyerBDD()
This.ImporterLogs($params)
// ----------------------
// MARK:Import fichiers Logs
// ----------------------
Function ImporterLogs($params : Object)
// mettre à jour la BDD avec les nouveaux fichiers logs
var $dossierLogs : Object
var $logs : Object
This.OuvrirBDD_Log()
// ici la BDD est ouverte, les tables et champs sont créés et This.ParamsChamps est renseignés
// Sélectionner les dossiers à importer
This.FixerParametresDossiersLogs()
// This.dossiersLogs est renseigné.
This.dossiersLogs:=This.dossiersLogs.query("typeApplicationImport != :1"; Null)
For each ($dossierLogs; This.dossiersLogs)
// importer les logs des fichiers du dossier this.dossierLogs
This.trace.EnvoyerMessages([msgk_event; msgk_log]; "Démarrage import des fichiers"; Current method name; "Fichiers logs de l'application "+String($dossierLogs.nomApplication))
This.dossierLogs:=$dossierLogs
This.LireFichiersLogs()
// $logs contient pour chaque fichier son nom et sa collection de logs
Case of
: (This.Logs=Null)
// pb serveur
: (This.Logs.length=0)
Else
Begin SQL
START TRANSACTION;
End SQL
For each ($logs; This.Logs)
If (Not(This.EnregistrementFichierExiste($logs)))
// le fichier n'existe pas ; l'importer
This.nomFichier:=$logs.nomFichier
This.EnregistrerLogs($logs)
This.trace.EnvoyerMessages([msgk_event; msgk_log]; "Import [OK]"; Current method name; "Fichier '"+This.nomFichier+"' importé en BDD")
End if
End for each
Begin SQL
COMMIT TRANSACTION;
End SQL
End case
This.trace.EnvoyerMessages([msgk_event; msgk_log]; "Fin import des fichiers"; Current method name; "Fichiers logs de l'application "+String($dossierLogs.nomApplication))
End for each
This.FermerBDD_Externe()
// retour au requêteur ; en mode debug $params peut être absent
If (Count parameters>0)
$params.execute:=Formula(cs.$LogsAppEditeur.new()[$params.functionIDcallBack]())
CALL FORM($params.wndRef; Formula($params.execute()))
End if
Function LireFichiersLogs()
// lire les logs des fichiers Logs du dossier $dossierLogs
var $params : Object
This.Logs:=New collection
Case of
: (Not(OB Is defined(This.dossierLogs; "methodeReq")))
// erreur initialisation
: (Not(OB Is defined(This; This.dossierLogs.methodeReq)))
// erreur méthode de requête
Else
// lancer la lecture de tous ces fichiers
// il faut toujours un paramètre (compatibilité avec le cas d'un appel par le serveur
$params:=This.dossierLogs
$params.functionID:="RequeterDossierLogsAppLocal"
This[This.dossierLogs.methodeReq]($params)
// le resultat est dans .reqRetour ; peut être null si pb serveur
This.Logs:=Null
If ($params.reqRetour#Null)
This.Logs:=$params.reqRetour.Logs
End if
End case
Function EnregistrerLogs($logs : Object)
// importer dans la BDD les logs de $logs
var $c : Collection
var $log : Text
var $compteur : Integer
$compteur:=0
Case of
: (This.nomFichier="")
// il y a eu une erreur (est traitée)
: (Not(OB Is defined($logs; "contenu")))
// oops
: ($logs.contenu.length=0)
This.trace.Créer(-15068; Current method name; "Le fichier '"+$logs.nomFichier+"' est vide").LeverException([msgk_event; msgk_log])
Else
For each ($log; $logs.contenu)
// analyser chaque ligne du fichier
$c:=Split string($log; Char(Tab))
// ajouter le type d'application (en premier)
$c.unshift(This.dossierLogs.typeApplicationImport)
// filtrer les entêtes
Case of
: ($log="")
: ($log="Crée@")
: ($c.length#This.ParamsChamps.length)
// trop ou pas assez d'info
This.trace.Créer(-15068; Current method name; Choose($c.length>This.ParamsChamps.length; "Trop "; "Pas assez ")+"d'informations dans le log '"+$log+"'").LeverException([msgk_event; msgk_log])
Else
// ok un bon log
// pour faire passer les "caractères spéciaux", transformer la description en blob encodé b64 (ne pas utiliser directement un blob, incompatible de .LireLog() )
// RAPPEL : pas de "caractères spéciaux" dans le champ libellé (génère une Err SQL)
$c[$c.length-1]:=This.EncoderBase64($c[$c.length-1])
// crée les données à enregistrer
This.LireLog($c)
$compteur:=$compteur+Num(This.EnregistrerLog())
End case
End for each
This.trace.EnvoyerMessages([msgk_event; msgk_log]; "Logs de "+$logs.nomFichier+Choose($compteur>0; " [OK]"; " [KO]"); Current method name; Choose($compteur>0; String($compteur)+" logs lus et traités"; "Aucun log traité")+" sur "+String($logs.contenu.length)+" lus")
End case
Function LireLog($valeurs : Collection)
// renseigner la valeur de chaque champ
// attention .ParamsChamps et $valeurs doivent être 2 collections synchrones
var $i : Integer
var $champ : Object
This.Log:=New collection
For ($i; 0; This.ParamsChamps.length-1)
$champ:=New object
$champ.Champ:=This.ParamsChamps[$i].champ
$champ.typeValeur:=This.ParamsChamps[$i].type
$champ.Valeur:=$valeurs[$i]
This.Log.push($champ)
End for
Function RequeterDossierLogsAppLocal($dossierLogs : Object)
// renvoyer le contenu des fichiers logs du dossier logs APP courant
// attention ici on est sur la BDD mère ou le serveur
var $data : Object
// lire le dossier des logs
$data:=This.getDossierLogs($dossierLogs)
// lister les fichiers logs logs
If ($data.dossier=Null)
This.fichiersLogs:=New collection
Else
This.fichiersLogs:=$data.dossier.files(fk ignore invisible)
End if
// renseigner le chemin du dossier
If ($data.dossier=Null)
$data.dossier:="Dossier inconnu"
Else
$data.dossier:=$data.dossier.platformPath
End if
// sélectionner les fichiers logs
This.FiltrerFichiers()
This.trace.EnvoyerMessages([msgk_event; msgk_log]; String(This.fichiersLogs.length)+" fichiers trouvés à traiter "+Choose(This.fichiersLogs.length>0; "[OK]"; "[KO]"); Current method name; "Dans le dossier <"+$data.dossier+">")
// récupérer le contenu pour une utilisation locale
$data.Logs:=This.LireLogs()
// retourner le résultat
$dossierLogs.reqRetour:=$data
Function FiltrerFichiers()
var $date : Text
// sélectionner les fichiers logs
This.fichiersLogs:=This.fichiersLogs.query("name = :1 and extension = :2"; "@.log"; ".txt").orderBy("name asc")
// supprimer le fichier d'aujourd'hui
$date:=String(Current date; ISO date) // attention cf 4D : ce format n'est pas conforme à la norme ISO8601
$date:=Substring($date; 1; 10)
Case of
: (This.fichiersLogs.length=0)
: (This.fichiersLogs[This.fichiersLogs.length-1].name#("@"+$date+"@"))
Else
This.fichiersLogs.pop()
End case
// ----------------------
// MARK:Suppression Logs
// ----------------------
Function NettoyerBDD()
// supprimer de la BDD les logs dont les fichiers ne sont plus sur le disque
var $dossierLogs : Object
var $c : Collection
var $nomFichier : Text
This.InitProcess()
This.OuvrirBDD_Log()
// ici la BDD est ouverte, les tables et champs sont créés et This.ParamsChamps est renseignés
// Sélectionner les dossiers à en cours
This.FixerParametresDossiersLogs()
For each ($dossierLogs; This.dossiersLogs)
This.dossierLogs:=$dossierLogs
This.LireFichiersLogs()
// lire les fichiers en BDD
$c:=This.LireFichiers($dossierLogs)
Case of
: ($c.length=0)
// BDD vide
: (This.fichiersLogs.length=0)
// pas de fichiers logs
: ($dossierLogs.typeApplicationImport=100)
// pas toucher aux fichiers test
Else
For each ($nomFichier; $c)
If (This.fichiersLogs.indexOf($nomFichier)=-1)
// ce fichier n'existe plus ; supprimer son contenu de la BDD
This.SupprimerFichier($nomFichier)
This.trace.EnvoyerMessages([msgk_event; msgk_log]; "Suppression fichier"; Current method name; "Suppression des logs du fichier "+$nomFichier)
End if
End for each
End case
End for each
This.FermerBDD_Externe()
Waiting(10)
⇧
[class]$LogsApp - 10/08/2026 10:05:42
Class extends _BDD
Class constructor()
Super()
// fichier des paramètres de la BDD
This.FichierRessources:="Data_LOG_APP.json"
// paramètres du journal
This.FormatJournal:="LOG_APP"
// lire les paramètres de champs
This.getFormatBDD()
Function FixerParametresDossiersLogs()
// chaque élément de la liste contient les paramètres de lecture d'un dossier Log (Serveur APP, client APP et BDDmère)
This.dossiersLogs:=New collection
// toujours disponibles
This.dossiersLogs.push(New object("nomApplication"; "Serveur APP"; "typeApplicationImport"; ALV Serveur APP; "methodeReq"; "RequeterDossierLogsServeur"; "typeApplicationEditeur"; [ALV Serveur APP]; "nomApplicationEditeur"; Localized string("22")))
This.dossiersLogs.push(New object("nomApplication"; "Client APP"; "typeApplicationImport"; ALV Client APP; "methodeReq"; "RequeterDossierLogsAppLocal"; "typeApplicationEditeur"; [ALV Client APP]; "nomApplicationEditeur"; Localized string("23")))
// éditeur uniquement
This.dossiersLogs.push(New object("nomApplication"; "Serveur APP"; "typeApplicationEditeur"; [ALV Serveur APP; ALV Client APP]; "nomApplicationEditeur"; Localized string("24")))
// non accessible hors base hôte
If (Storage.System.estExecuteDansHote)
This.dossiersLogs.push(New object("nomApplication"; "BDD mère"; "typeApplicationImport"; ALV BDD mère; "methodeReq"; "RequeterDossierLogsAppLocal"; "typeApplicationEditeur"; [ALV BDD mère]; "nomApplicationEditeur"; Localized string("25")))
End if
// pour les tests, quelque soit l'environnement
This.AjouterDossierDeTest(This.dossiersLogs)
Function AjouterDossierDeTest($c : Collection)
// ajouter le dossier pour les tests
If ((Not(Storage.System.estExecuteDansHote)) | Storage.Host.estDebugAPP())
// pour les tests depuis la BDD mère ou le composant
$c.push(New object("nomApplication"; "Dossier Test"; "typeApplicationImport"; 100; "methodeReq"; "RequeterDossierLogsAppLocal"; "typeApplicationEditeur"; [100]; "nomApplicationEditeur"; Localized string("26"); "nomDossierTest"; "Test JAPP"))
End if
// ----------------------
// MARK:Requêtes SQL
// ----------------------
Function OuvrirBDD_Log()->$chemin : Text
var $sql_BDDpath : Text
// fixer le nom de la BDD externe ouvrir
$sql_BDDpath:=This.getDossierBDD_Log("DossierJournalApp"; "Test JAPP")+"LogsApp"
$chemin:=This.OuvrirBDD_Externe($sql_BDDpath)
⇧
[class]_Trace - 03/06/2025 11:20:44
property cible : cs.xSDK.Traces
property success : Boolean
singleton Class constructor()
This.cible:=cs.xSDK.Traces.new()
This.success:=False
Function set Error($numError : Integer)
This.cible.Error:=$numError
Function get Error()->$result : Integer
$result:=This.cible.Error
Function set ErrorDescription($description : Text)
This.cible.ErrorDescription:=$description
Function get ErrorDescription()->$result : Text
$result:=This.cible.ErrorDescription
Function Intercepter()
ErrorNum:=This.cible.Intercepter("JLOG"; Error; Error method; Error line; Error formula)
Function Initialiser($nomMethode : Text)->$result : Object
This.cible.CréerErreur("JLOG"; 0; $nomMethode; "")
$result:=This
Function Créer($Error : Integer; $nomMethode : Text; $ErrorDescription : Text)->$result : Object
This.cible.CréerErreur("JLOG"; $Error; $nomMethode; $ErrorDescription)
$result:=This
Function FixerSuccess()
This.cible.FixerSuccess()
This.success:=This.cible.success
Function LeverException($options : Collection)
// renseigner le label de l'erreur
This.cible.ErrorLabel:=Localized string(String(This.cible.Error))
// lancer le traitement de l'erreur
This.cible.LeverException($options)
Function EnvoyerMessages($options : Collection; $libellé : Text; $source : Text; $description : Text)
This.cible.EnvoyerMessages($options; "JLOG"; $libellé; $source; $description)
Function DebugerMethode($libellé : Text; $source : Text; $description : Text)->$result : Boolean
// mettre à jour l'état (activation / désactivation des ASSERT)
cs.$composant.new().InstallerDonnéesHote()
$result:=This.cible.DebugerMethode(Storage.Host; "JLOG"; $libellé; $source; $description)
⇧
[ ]U_Nav Masque - 08/06/2025 15:27:47
Form._TraiterFORMevent()
⇧
[ ]U_Nav LogsApp - 08/06/2025 15:27:47
Form._TraiterFORMevent()
⇧
[ ]U_Nav LogsWeb - 08/06/2025 15:27:37
Form._TraiterFORMevent()
⇧
onStartup - 10/08/2026 10:06:23
// ne s'exécute pas dans une base hôte
ON ERR CALL(Formula(traceHandler).source; ek global)
cs.$composant.new().InitVariablesJLOG()
// pour exécution en locale
Use (Storage.Host)
Storage.Host.Session_Etat:=0
End use
// démarrer le worker
CALL WORKER("WK_Composant_JLOG"; Formula from string("cs.$composant.new().InitProcess()"))
⇧
onExit - 01/04/2025 19:52:03
// ne s'exécute pas dans une base hôte
// exporter le code du composant si pas compilé
ON ERR CALL(Formula(traceHandler).source; ek local)
cs.xSDK.ExportCode4D.new().DémarrerComposant()
⇧
onWebConnection - 04/04/2024 16:59:38
Pas de code
⇧
onWebAuthentication - 07/12/2021 18:01:29
Pas de code
⇧
onSystemEvent - 07/12/2021 18:01:29
Pas de code
⇧
onHostDatabaseEvent - 06/02/2026 17:59:22
#DECLARE($numEvent : Integer)
// Méthode base sur événement base hôte
Case of
: ($numEvent=On before host database startup)
// ici pas d'interaction avec les autres composants et la BDDmère
ON ERR CALL(Formula(ErrorHandler).source; ek local)
cs.$composant.new().InitVariablesJLOG()
Use (Storage.System)
Storage.System.estExecuteDansHote:=True
End use
// déactiver les ASSERT si le composant est compilé (réactivable par les options d'appel du composant)
SET ASSERT ENABLED(Not(Is compiled mode))
// démarrer le worker
CALL WORKER("WK_Composant_JLOGS"; Formula from string("cs.$composant.new().InitProcess()"))
: ($numEvent=On after host database startup)
// à faire ici tout est initialisé, en particulier le monde extérieur
ON ERR CALL(Formula(traceHandler).source; ek global)
cs.$composant.new().Installer()
: ($numEvent=On before host database exit)
// placer ici le code à exécuter avant le "Sur fermeture" de la base hôte
: ($numEvent=On after host database exit)
// placer ici le code à exécuter après le "Sur fermeture" de la base hôte
End case