Version 2025 r2 (release note)

De Wiki1000
(Différences entre les versions)
(Vue locale)
(Formats)
 
(38 révisions intermédiaires par un utilisateur sont masquées)
Ligne 3 : Ligne 3 :
  
 
''' PREVIEW '''
 
''' PREVIEW '''
 +
 +
==Langage==
 +
 +
* Valeur par défaut de paramètre
 +
: Il est possible de définir des valeurs par défaut aux paramètres des méthodes
 +
 +
<source lang="delphi">
 +
  MyClass = Class(TitObject)
 +
    Procedure TestDeffParams;
 +
    Procedure TestDefParamBool(p1:string; p2:boolean=true);
 +
    Procedure TestDefParamJson(p1:string; p2:TJson=nil);
 +
    Procedure TestDefParamJson2(p1:string; p2:TJson='{a:false}');
 +
    Procedure TestDefParamEnum(p1:string; p2:Integer=WFCAState_Etat2);
 +
    Procedure TestDefParamMulti(p1:string; p2:string='a'; p3:string='b');
 +
    Function TestDefParamOne(p1:string='a'):string;
 +
    Function TestDefParamFunc(p1:string='a'):string;
 +
  end;
 +
 +
Procedure MyClass.TestDefParamJson(p1:string; p2:TJson=nil);
 +
var json:TJson;
 +
begin
 +
  json := TJsonStruct.Create('{}');
 +
  //
 +
  // use Assigned insted of p2<>nil
 +
  //
 +
  if assigned(p2) then json.addStruct('p2',p2);
 +
end;
 +
 +
Procedure MyClass.TestDeffParams;
 +
var V:string;
 +
begin
 +
  V := TestDefParamFunc('c');
 +
  ShowMessage(V);
 +
 
 +
  TestDefParamOne;
 +
  TestDefParamOne();
 +
  TestDefParamOne('x');
 +
 
 +
  TestDefParamMulti('a');
 +
  TestDefParamMulti('a','1');
 +
  TestDefParamMulti('a','1','2');
 +
 
 +
  TestDefParamBool('a');
 +
  TestDefParamBool('a',false);
 +
  TestDefParamBool('a',true);
 +
 
 +
  TestDefParamJson2('b');
 +
  TestDefParamJson2('b','{a:true}');
 +
 +
  TestDefParamEnum('c');
 +
  TestDefParamEnum('c',WFCAState_Final);
 +
end;
 +
</source>
 +
 +
* Paramètre de type classe
 +
: Les paramètres de type classe peuvent être passé directement
 +
 +
<source lang="delphi">
 +
Type
 +
  MyClass1 = class
 +
    class procedure foo(rg:TRegClass);
 +
  end;
 +
 +
  MyClass2 = class
 +
    ....
 +
  end;
 +
 +
  MyClass3 = class
 +
    procedure oldbar();
 +
    procedure newbar();
 +
  end;
 +
 +
class procedure MyClass1.foo(rg:TRegClass);
 +
begin
 +
  // => MyClass2
 +
  showMessage(rg.aClassName);
 +
end;
 +
 +
procedure MyClass3.oldbar();
 +
var rg:TRegClass;
 +
begin
 +
  ModelManager.FindClass('MyClass2');
 +
  myClass1.foo(rg);
 +
end;
 +
 +
procedure MyClass3.newbar();
 +
begin
 +
  myClass1.foo(MyClass2);
 +
end;
 +
</source>
 +
 +
==Json==
 +
* Opérateur In
 +
: Un json de type structure supporte l'opérateur In
 +
 +
<source lang="delphi">
 +
Procedure TestJson;
 +
 +
function _foo(p:TJson):boolean;
 +
begin
 +
  Result := false;
 +
  if 'a' in p then
 +
    begin
 +
      Result := True;
 +
    end;
 +
end;
 +
 +
var js:TJson;
 +
begin
 +
  js := TJson.Create('{a:true}');
 +
  if _foo(js) then showMessage('ok') else showMessage('nok');
 +
end;
 +
</source>
 +
 +
 +
* Getter et Setter
 +
: Un json de type structure supporte l'accès direct aux valeur des membres
 +
 +
<source lang="delphi">
 +
Procedure TestJson;
 +
 +
function _foo(p:TJson):boolean;
 +
begin
 +
  Result := false;
 +
  if 'a' in p then
 +
    begin
 +
      Result := p['a'];
 +
    end;
 +
end;
 +
 +
var js:TJson;
 +
begin
 +
  js := TJson.Create('{a:true}');
 +
  js['b'] := False;
 +
  js['a'] := not js['b'];
 +
  if _foo(js) then showMessage('ok') else showMessage('nok');
 +
end;
 +
</source>
 +
 +
* Constructeur implicite
 +
: Un paramètre TJson peut être instancié à partir d'une chaine de caractère
 +
 +
<source lang="delphi">
 +
Procedure TestJson;
 +
 +
function _foo(p:TJson):boolean;
 +
begin
 +
  Result := false;
 +
  if 'a' in p then
 +
    begin
 +
      Result := p['a'];
 +
    end;
 +
end;
 +
 +
begin
 +
  if _foo('{a:true}') then showMessage('ok') else showMessage('nok');
 +
end;
 +
</source>
 +
 +
{{tip|La chaine doit être une constante, l'instanciation à partir d'une chaîne construite dynamiquement ne marche pas :
 +
 +
<source lang="delphi">
 +
Procedure TestJson;
 +
 +
function _foo(p:TJson):string;
 +
begin
 +
  Result := false;
 +
  if 'a' in p then
 +
    begin
 +
      Result := p['a'];
 +
    end;
 +
end;
 +
 +
var v:string;
 +
begin
 +
  v := 'une chaine';
 +
  if _foo('{a:"'+uneChaine+'"}')<>'' then showMessage('ok') else showMessage('nok'); // don't work !
 +
end;
 +
</source>
 +
 +
 +
}}
 +
 +
 +
* Enumérateurs
 +
: Un json de type strutucture supporte l'énumérateur sur les clés
 +
: Un json de type tableau supporte l'énumérateur sur les éléments
 +
 +
<source lang="delphi">
 +
//Procedure TestJson;
 +
 +
procedure _enumValues(p:TJson);
 +
var i:Integer; V:Variant;
 +
begin
 +
  forEach V in p index i do
 +
    begin
 +
      showMessageFmt('%d:%s',[i,V]);
 +
    end;
 +
end;
 +
 +
procedure _enumKeys(p:TJson);
 +
var i:Integer; Key,Keys,stag:string;
 +
begin
 +
  Keys := ''; stag := '';
 +
  forEach key in p index i do
 +
    begin
 +
      Keys := Keys+stag+inttostr(i)+':'+key;
 +
      stag := ',';
 +
    end;
 +
  showMessage(Keys);
 +
end;
 +
 +
begin
 +
  _enumKeys('{a:true, b:false}');
 +
  _enumValues('[{a:true, b:false},{a:false, b:true}]');
 +
end;
 +
</source>
 +
 +
==Modèle==
 +
 +
===Classes===
 +
 +
* Méthode AllocOID
 +
 +
<source lang="delphi">class function AllocOID:TOID;</source>
 +
* Alloue un oid de la classe
 +
: Peut être utile dans les tests unitaires
 +
 +
* Méthode ToJson()
 +
 +
<source lang="delphi">procedure ToJson(SA:variant);</source>
 +
 +
* Sérialize l'objet en json
 +
: SA peut être un TJsonArray ou un TJsonStruct
 +
 +
===Classes SQL===
 +
 +
* Options de rôle : NoRefIndex
 +
 +
* Options de rôle : NoForeignKey
  
 
==Script==
 
==Script==
 +
 +
===Trace===
 +
 +
<source lang="delphi">procedure dbgClear();</source>
 +
: Vide la trace
 +
 +
<source lang="delphi">procedure dbgEnable(value:boolean);</source>
 +
: Active / désactive la trace
  
 
===Vue locale===
 
===Vue locale===
Ligne 23 : Ligne 271 :
 
</source>
 
</source>
  
* Une vue locale peut contenir des attributs non mappés dans la définition.
+
* Une vue locale peut contenir des attributs non mappés dans la définition, ces attributs peuvent ensuite être mappés dynamiquement par le selecteur en utilisant addColumn()
  
 
'''Exemple:'''
 
'''Exemple:'''
Ligne 64 : Ligne 312 :
 
   vue1 = viewOf(ClassA)
 
   vue1 = viewOf(ClassA)
 
   p1:TEnum(enumName) = ...;
 
   p1:TEnum(enumName) = ...;
 +
  end;
 +
</source>
 +
 +
* Qualifier d'attribut NotInGroupBy
 +
 +
<source lang="delphi">
 +
Type
 +
  vue1 = viewOf(ClassA)
 +
  p1:string = expression('...') notInGroupBy;
 
   end;
 
   end;
 
</source>
 
</source>
Ligne 77 : Ligne 334 :
  
 
   vue2 = viewOf(vue1)
 
   vue2 = viewOf(vue1)
   p1:string = ...;
+
   p2:string = ...;
 
   [inherited and (...)]
 
   [inherited and (...)]
 
   end;
 
   end;
 +
</source>
 +
 +
'''Exemple:'''
 +
 +
<source lang="delphi">
 +
//function GetSelector(iGroupBy:string; iFilter:TJsonArray):TSelector;
 +
Type
 +
  // défini une classe de base avec tous les filtres
 +
  //
 +
  vueEcritureLettrage = viewOf(TEcriture)
 +
    lettrable:boolean = compteGeneral.lettrable notInSelect;
 +
    idEtablissement:TOID = piece.oidEtablissement notInSelect;
 +
    idCompteGeneral:TOID = oidCompteGeneral notInSelect;
 +
    idRoleTiers:TOID = oidroleTiers notInSelect;
 +
    [(lettrable=true)
 +
      and ((oidLettrageEcriture='') or (dateLettrage=0))
 +
      and (typeEcriture<>0)
 +
      and (piece.lot.origineLot<>0)
 +
      and (eDate>=%ArgDateInf)
 +
      and (eDate<=%ArgDateSup)
 +
      and (idEtablissement=%ArgEtablissement)
 +
      and (idCompteGeneral=%ArgCompteGeneral)
 +
      and (idRoleTiers=%ArgRoleTiers)
 +
    ]
 +
  end;
 +
 +
  // Hérite de tous les filtres
 +
  //
 +
  vueEcritureLettrageGroupBy = viewOf(vueEcritureLettrage)
 +
    dateMin:TDatetime = min(eDate);
 +
    dateMax:TDatetime = max(eDate);
 +
    ACount:Integer = count(oid);
 +
    credit:Currency = sum('credit:TCValue');
 +
    debit:Currency = sum('debit:TCValue');
 +
    solde:Currency = sumDiff(debit,credit);
 +
    [inherited]
 +
  end;
 +
 +
begin
 +
  Result := vueLettrageGroupBy.CreateSelector('','',True,[]);
 +
end;
 
</source>
 
</source>
  
Ligne 99 : Ligne 397 :
 
Type
 
Type
 
   vue2 = viewOf(class1.foo.vue1)
 
   vue2 = viewOf(class1.foo.vue1)
   p1:string = ...;
+
   p2:string = ...;
 
   end;
 
   end;
 
begin
 
begin
Ligne 110 : Ligne 408 :
 
Une expression existe peut être utilisée dans les filtres comme une valeur logique
 
Une expression existe peut être utilisée dans les filtres comme une valeur logique
  
Note : Une expression Exists() est beaucoup plus rapide qu'un "Count<>0"
+
{{tip|Une expression Exists() est beaucoup plus rapide qu'un "Count<>0"}
  
 
<source lang="delphi">
 
<source lang="delphi">
Ligne 124 : Ligne 422 :
 
   end;
 
   end;
 
</source>
 
</source>
 +
 +
* Expression de Sous requête
 +
 +
Une expression peut être définie par une sous requête
 +
 +
<source lang="delphi">
 +
Type
 +
  VueTauxADate = ViewOf(TTauxADate)
 +
    idTVA : TOid = oidTVA;
 +
    tDate : Date = tDate;
 +
    taux : float = taux;
 +
  end;
 +
 +
  vueMontantTVA = viewOf(TEcriture)
 +
    dateEcriture:TDatetime=eDate notInSelect;
 +
    oidTVA:TOID = ProfilTVA.oidTVA notInSelect;
 +
    oidPiece:TOID = oidPiece;
 +
    montantTVAReel:Currency = vueTauxADate.select('taux * self.montant_TCValue /100','(tDate<=self.dateEcriture)and(idTVA=self.oidTVA)','',True,[]);
 +
    montantTVAReel_CodeDevise:string = montantTVAReel:CodeDevise;
 +
  end;
 +
</source>
 +
 +
==ToJson==
 +
 +
Permet de sérialiser l'objet ou l'ensemble d'objets au format json compatible avec les tables du client React
 +
 +
<pre> procedure TObject.ToJson(SA:TJsonArray);</pre>
 +
<pre> procedure TObject.ToJsonEx(SA:TJsonArray; iOptions:TSerializeJsonOptions);</pre>
 +
<pre> procedure TSelector.ToJson(SA:TJsonArray);</pre>
 +
<pre> procedure TSelector.ToJsonEx(SA:TJsonArray; iOptions:TSerializeJsonOptions);</pre>
 +
<pre> procedure TRole.ToJson(SA:TJsonArray);</pre>
 +
 +
TSerializeJsonOptions :
 +
 +
* sjoIdAsGuid
 +
: Le membre id de la sérialisation sera un GUID
 +
 +
* sjoIdAsOid
 +
: Le membre id de la sérialisation sera l'OID de l'objet
 +
 +
<source lang="delphi">
 +
 +
//procedure GetData(SRows:TJsonArray);
 +
Type
 +
  myView = viewOf(...)
 +
  ...
 +
  end;
 +
 +
var sel:TSelector;
 +
begin
 +
  // Selector to retreive the data
 +
  //
 +
  sel := myView.CreateSelector('','',True,[]);
 +
  sel.ToJson(SRows);
 +
end;
 +
</source>
 +
 +
===Formats===
 +
 +
Le formattage de la sérialisation des propriétés peut être controllé par les propriétés du type
 +
 +
<pre>
 +
Type
 +
  vue = viewOf(...)
 +
    p:string(typeParam1,typeParam2,typeParam3) = x;
 +
  end;
 +
</pre>
 +
 +
 +
{|class="wikitable"
 +
|-
 +
!Type de l'attribut
 +
!TypeParam1
 +
!TypeParam2
 +
!TypeParam3
 +
!Usage
 +
|-
 +
|Currency
 +
|fmtTC
 +
| -
 +
| -
 +
|Le montant est considéré en valeur de tenue de compte
 +
|-
 +
|Currency
 +
|fmtRP
 +
| -
 +
| -
 +
|Le montant est considéré en valeur de reporting
 +
|-
 +
|String contenant un TfwParameters
 +
|fmtParameters
 +
| -
 +
| -
 +
|Valeur des paramètres
 +
|-
 +
|String contenant un TfwParameters
 +
|fmtParameter
 +
|Nom du paramètre
 +
|Valeur par défaut si le paramètre n'existe pas
 +
|Valeur du paramètre
 +
|-
 +
|String
 +
|fmtTaskCategory
 +
| -
 +
| -
 +
|Catégorie de tâche
 +
|-
 +
|oid de TdbfDocument
 +
|fmtDocumentUrl
 +
|Paramètre optionnel contenant le nom du document
 +
|Paramètre optionnel contenant une url externe
 +
|Lien sur le document
 +
|-
 +
|Datetime
 +
|fmtUTC
 +
| -
 +
| -
 +
|La date en considérée UTC et convertie en date locale
 +
|-
 +
|Integer (idOTP)
 +
|fmtClassLabel
 +
| -
 +
| -
 +
|Le libellé de la classe
 +
|-
 +
|Integer (idOTP)
 +
|fmtClassName
 +
| -
 +
| -
 +
|Le nom de la classe
 +
|}
  
 
==Sélecteur==
 
==Sélecteur==
  
* lastOpeStamp, lastAffectedStamp
+
* lastOpeStamp, lastOpeAffected, lastOpeFirstOID
 
: Attributs mis à jour par la dernière opération assembliste.
 
: Attributs mis à jour par la dernière opération assembliste.
 +
 +
* operationId, operation
 +
: Permet d'enregistrer les opérations dans la table TsqlOperation
 +
: S'applique à CopyTo()
  
 
* RmvParameter()
 
* RmvParameter()
Ligne 136 : Ligne 569 :
 
: Permet de créer des objets à partir d'un sélecteur
 
: Permet de créer des objets à partir d'un sélecteur
  
* CopyTo, Update, UpdateFrom  
+
* CopyTo, Update, UpdateFrom
 
: Fonctionne sur les classes de stéréotype SQL
 
: Fonctionne sur les classes de stéréotype SQL
  
===UpdateFrom===
+
* InsertInto
 +
: Permet de créer une table temporaire à partir d'un sélecteur
 +
: Réalise un select ... into TEMPTABLE from ...
 +
 
 +
* SourceTableName
 +
: Permet de sélectionner une table SQL comme source de l'opération
 +
: Utiliser dans les opérations ensemblistes sur des tables temporaires
 +
 
 +
===TsqlOperation===
 +
 
 +
Classe SQL définie par le framework et permettant d'enregistrer les opérations du sélecteur
 +
 
 +
<source lang="delphi">
 +
  TsqlOperation = Class(TsqlObject)
 +
  public
 +
    class procedure CleanOpe(iOpeId:string);
 +
    //
 +
    property action: StringS[128];
 +
    property id: SQLIdentity;
 +
    property oidSourceObject: TOID;
 +
    property oidTargetObject: TOID;
 +
    property opeId: StringS[128];
 +
    property operation: StringS[128];
 +
    property SourceObject: Ref(roGeneric,roNotExternal,roNoForeignKey,roNoRoleIndex) of TitObject;
 +
    property TargetObject: Ref(roGeneric,roNotExternal,roNoForeignKey,roNoRoleIndex) of TitObject;
 +
  end;
 +
</source>
 +
 
 +
* opeId, operationId
 +
: Un identifiant unique (guid) identifiant l'ensemble des opérations
 +
 
 +
* opération
 +
: Nom de l'opération dans l'ensemble des opérations
 +
 
 +
* action
 +
: Action de l'opération
 +
: Par exemple INSERT pour un CopyTo
 +
 
 +
* oidSourceObject
 +
: identifiant de l'objet source dans l'opération
 +
: Par exemple l'objet source de la copie pour un CopyTo
 +
 
 +
* oidTargetObject
 +
: identifiant de l'objet cible dans l'opération
 +
: Par exemple l'objet copié par un CopyTo
 +
 
 +
'''Exemple d'utilisation:'''
 +
 
 +
<source lang="delphi">
 +
 
 +
// Créer des écritures a partir des réglements
 +
//
 +
procedure  _doCreateEcritureReglements(iOidPiece:string; iOpeId:string);
 +
var sel:TSelector;
 +
begin
 +
  sel := vueEcritureReglement.CreateSelector('(oidBordereau=%1)','',True,[oidBordereauReglement]);
 +
  sel.AddParameter('ArgBordereau',oidBordereauReglement);
 +
  sel.Operation := 'EcrReg';
 +
  sel.OpeId := iOpeId;
 +
  //
 +
  sel.CopyTo('TEcriture',['oidpiece','eDate','sens','sensProrata','regimeTVA','typeEcriture'],[
 +
    iOidPiece,
 +
    BordereauReglement.dateReglement,
 +
    sens_credit,
 +
    sens_credit,
 +
    regimeTVA_Encaissements,
 +
    typeEcriture_Brouillard
 +
  ]);
 +
end;
 +
 
 +
 +
Type
 +
  vueUpdateReglement = viewOf(TReglement)
 +
  vl:TsqlOperation = join('(opeId=%ArgOpeId) and (operation=%ArgOperation) and (oidSourceObject=self.oid)');
 +
  oidEcriture:TOID = oidEcriture;
 +
  oidTargetEcriture:TOID = vl.oidTargetObject;
 +
  oidBordereau:TOID = oidBordereauReglement;
 +
  end;
 +
 
 +
// Met à jour l'oidEcriture créée sur les réglements correspondants
 +
..
 +
procedure _doUpdateReglementsEcriture(iOidPiece:string; iOpeId:string);
 +
var sel:TSelector;
 +
begin
 +
  sel := vueUpdateReglement.CreateSelector('(oidBordereau=%1)','',True,[oidBordereauReglement]);
 +
  sel.AddParameter('ArgOpeId',iOpeId);
 +
  sel.AddParameter('ArgOperation','EcrReg');
 +
  //
 +
  sel.Update(['oidEcriture'],['oidTargetEcriture']);
 +
end;
 +
 
 +
begin
 +
  aOpeId := CreateGuid;
 +
  withP long transaction do
 +
  begin
 +
    aOidPiece := _doCreatePiece();
 +
    _doCreateEcritureReglements(aOidPiece,aOpeId);
 +
    _doUpdateReglementsEcriture(aOidPice,aOpeId);
 +
    ...
 +
    TsqlOperation.CleanOpe(aOpeId);
 +
  end;
 +
end;
 +
</source>
 +
 
 +
===UpdateFrom()===
  
 
<source lang="delphi">
 
<source lang="delphi">
Ligne 196 : Ligne 733 :
 
;
 
;
 
</pre>
 
</pre>
 +
 +
==Opérations ensemblistes SQL==
 +
 +
Des opérations ensemblistes utilisant des tables SQL temporaires peuvent être réalisées en utilisant l'opération InserInto du selecteur.
 +
 +
===Table temporaire===
 +
 +
* TDatabase.AllocTempTable(JobId:string)
 +
: Génère un nom de table temporaire
 +
 +
* TDatabase.DropTempTables(JobId:string)
 +
: Supprime (drop) les tables temporaires
 +
 +
===Vue SQL locale===
 +
 +
Une vue SQL locale permet d'utiliser une table SQL comme source d'opération d'un sélecteur
 +
 +
<source lang="delphi">
 +
Type
 +
  // define an interface
 +
  intf = interface
 +
  ...
 +
  end;
 +
 +
  // create a view which support the interface
 +
  // will be used to create the temp table
 +
  //
 +
  vue = viewOf(MyClass,intf)
 +
  end;
 +
 +
  // define a sql class based on the interface
 +
  //
 +
  sql = sqlClass(intf)
 +
  end;
 +
 +
  // view on the sql class
 +
  //
 +
  vue2 = viewOf(sql)
 +
  ...
 +
  end;
 +
 +
var sel:Tselector; aJob,aTempTable:string; keepTables:boolean;
 +
begin
 +
  // Alloc a temp table name
 +
  //
 +
  aJob := CreateGuid;
 +
  aTempTable := ClassManager.DefDatabase.AllocTempTable(aJob);
 +
  KeepTables := false; // for debuging
 +
  try
 +
  // Create a temp table from MyClass view
 +
  //
 +
  sel := vue.CreateSelector(...);
 +
  sel.insertInto(aTempTable,[...],[...]); // we create a tempTable
 +
 +
  // Query the temp table throught the vue2
 +
  //
 +
  sel := vue2.CreateSelector(...);
 +
  sel.SourceTableName := aTempTable; // because we select the tempTable
 +
 +
  ...
 +
  finally
 +
  if not KeepTables then ClassManager.DefDatabase.DropTempTables(aJob);
 +
  end;
 +
end;
 +
</source>
 +
 +
==Updater==
 +
 +
Classe technique permettant de mettre à jour un attribut sur un ensemble d'objet.
 +
 +
'''Exemple : Mise à jour des compteurs qui ne peuvent pas être déterminés en SQL'''
 +
 +
<source lang="delphi">
 +
Type
 +
  // Should returns all attributes part of the counter
 +
  //
 +
  vueNumeroPiece = viewOf(TPiece)
 +
  pDate:TDatetime = pDate;
 +
  numero:TCounter = numero;
 +
  end;
 +
 +
procedure _doUpdateNumeroPiece(iOidPiece:string);
 +
var sel:TSelector; vueNP:vueNumeroPiece; upd:TUpdater;
 +
begin
 +
  upd := TPiece.CreateUpdater('numero');
 +
  //
 +
  sel := vueNumeroPiece.CreateSelector('(oid=%1)','',True,[iOidPiece]);
 +
  forEach vueNP in sel.AsCursor do
 +
    begin
 +
      vueNP.numero.AllocValue;
 +
      upd.AddValue(vueNP.OID,vueNP.numero.value);
 +
    end;
 +
  //
 +
  upd.Execute;
 +
end;
 +
 +
begin
 +
 
 +
end;
 +
 +
</source>
 +
 +
==Interface==
 +
 +
* [[Améliorations des contrôles d'interface (Version 11.00 2025 r2)]]
  
 
[[Category:Version 2025 R2]]
 
[[Category:Version 2025 R2]]
 
[[Category:Release note]]
 
[[Category:Release note]]

Version actuelle en date du 25 septembre 2025 à 08:15

Modèle:Version2025r1

Sommaire


PREVIEW

Langage

  • Valeur par défaut de paramètre
Il est possible de définir des valeurs par défaut aux paramètres des méthodes
  MyClass = Class(TitObject)
    Procedure TestDeffParams;
    Procedure TestDefParamBool(p1:string; p2:boolean=true);
    Procedure TestDefParamJson(p1:string; p2:TJson=nil);
    Procedure TestDefParamJson2(p1:string; p2:TJson='{a:false}');
    Procedure TestDefParamEnum(p1:string; p2:Integer=WFCAState_Etat2);
    Procedure TestDefParamMulti(p1:string; p2:string='a'; p3:string='b');
    Function TestDefParamOne(p1:string='a'):string;
    Function TestDefParamFunc(p1:string='a'):string;
  end;
 
Procedure MyClass.TestDefParamJson(p1:string; p2:TJson=nil);
var json:TJson;
begin
  json := TJsonStruct.Create('{}');
  //
  // use Assigned insted of p2<>nil
  //
  if assigned(p2) then json.addStruct('p2',p2);
end;
 
Procedure MyClass.TestDeffParams;
var V:string;
begin
  V := TestDefParamFunc('c'); 
  ShowMessage(V); 
 
  TestDefParamOne;
  TestDefParamOne(); 
  TestDefParamOne('x'); 
 
  TestDefParamMulti('a'); 
  TestDefParamMulti('a','1'); 
  TestDefParamMulti('a','1','2'); 
 
  TestDefParamBool('a'); 
  TestDefParamBool('a',false); 
  TestDefParamBool('a',true); 
 
  TestDefParamJson2('b');
  TestDefParamJson2('b','{a:true}'); 
 
  TestDefParamEnum('c');
  TestDefParamEnum('c',WFCAState_Final); 
end;
  • Paramètre de type classe
Les paramètres de type classe peuvent être passé directement
Type
  MyClass1 = class
    class procedure foo(rg:TRegClass);
  end;
 
  MyClass2 = class
    ....
  end;
 
  MyClass3 = class
    procedure oldbar();
    procedure newbar();
  end;
 
class procedure MyClass1.foo(rg:TRegClass);
begin
  // => MyClass2
  showMessage(rg.aClassName);
end;
 
procedure MyClass3.oldbar();
var rg:TRegClass;
begin
  ModelManager.FindClass('MyClass2');
  myClass1.foo(rg);
end;
 
procedure MyClass3.newbar();
begin
  myClass1.foo(MyClass2);
end;

Json

  • Opérateur In
Un json de type structure supporte l'opérateur In
Procedure TestJson;
 
 function _foo(p:TJson):boolean;
 begin
   Result := false; 
   if 'a' in p then
    begin
      Result := True;
    end; 
 end; 
 
var js:TJson;
begin
  js := TJson.Create('{a:true}'); 
  if _foo(js) then showMessage('ok') else showMessage('nok');
end;


  • Getter et Setter
Un json de type structure supporte l'accès direct aux valeur des membres
Procedure TestJson;
 
 function _foo(p:TJson):boolean;
 begin
   Result := false; 
   if 'a' in p then
    begin
      Result := p['a'];
    end; 
 end; 
 
var js:TJson;
begin
  js := TJson.Create('{a:true}'); 
  js['b'] := False; 
  js['a'] := not js['b']; 
  if _foo(js) then showMessage('ok') else showMessage('nok');
end;
  • Constructeur implicite
Un paramètre TJson peut être instancié à partir d'une chaine de caractère
Procedure TestJson;
 
 function _foo(p:TJson):boolean;
 begin
   Result := false; 
   if 'a' in p then
    begin
      Result := p['a'];
    end; 
 end; 
 
begin
  if _foo('{a:true}') then showMessage('ok') else showMessage('nok');
end;
Tip-20px.png Tip : La chaine doit être une constante, l'instanciation à partir d'une chaîne construite dynamiquement ne marche pas :
Procedure TestJson;
 
 function _foo(p:TJson):string;
 begin
   Result := false; 
   if 'a' in p then
    begin
      Result := p['a'];
    end; 
 end; 
 
var v:string;
begin
  v := 'une chaine';
  if _foo('{a:"'+uneChaine+'"}')<>'' then showMessage('ok') else showMessage('nok'); // don't work !
end;



  • Enumérateurs
Un json de type strutucture supporte l'énumérateur sur les clés
Un json de type tableau supporte l'énumérateur sur les éléments
//Procedure TestJson;
 
 procedure _enumValues(p:TJson);
 var i:Integer; V:Variant;
 begin
   forEach V in p index i do
    begin
      showMessageFmt('%d:%s',[i,V]); 
    end; 
 end; 
 
 procedure _enumKeys(p:TJson);
 var i:Integer; Key,Keys,stag:string; 
 begin
   Keys := ''; stag := '';
   forEach key in p index i do
    begin
      Keys := Keys+stag+inttostr(i)+':'+key;
      stag := ','; 
    end; 
   showMessage(Keys); 
 end; 
 
begin
  _enumKeys('{a:true, b:false}'); 
  _enumValues('[{a:true, b:false},{a:false, b:true}]'); 
end;

Modèle

Classes

  • Méthode AllocOID
class function AllocOID:TOID;
  • Alloue un oid de la classe
Peut être utile dans les tests unitaires
  • Méthode ToJson()
procedure ToJson(SA:variant);
  • Sérialize l'objet en json
SA peut être un TJsonArray ou un TJsonStruct

Classes SQL

  • Options de rôle : NoRefIndex
  • Options de rôle : NoForeignKey

Script

Trace

procedure dbgClear();
Vide la trace
procedure dbgEnable(value:boolean);
Active / désactive la trace

Vue locale

  • Une vue locale peut contenir des attributs "oidXXX" sans définir le rôle

Exemple:

Type
  vue1 = viewOf(ClassA)
   p1:TEnum(enumName) = ...;
   oidRef:TOID = oidrefB;
   ..
   idRefB:TOID = oidrefB notInSelect;
   [ (idRefB=%ArgRefB) and ....]
  end;
  • Une vue locale peut contenir des attributs non mappés dans la définition, ces attributs peuvent ensuite être mappés dynamiquement par le selecteur en utilisant addColumn()

Exemple:

Type
  vue1 = viewOf(ClassA)
    ACount:Integer = count(oid)
    oidRef:TOID;
    codeRef:string;
    libelleRef:string;
   ..
   [  ...]
  end;
 
var sel:TSelector;
begin
  sel := vue1.createSelector();
  case iGroupBy of
   'refB':
     begin
       sel.AddColumn('oidrefB','oidRef'); 
       sel.AddColumn('refB.code','codeRef'); 
       sel.AddColumn('refB.Caption','libelleRef'); 
     end;
   'refC':
     begin
       sel.AddColumn('oidrefC','oidRef'); 
       sel.AddColumn('refC.code','codeRef'); 
       sel.AddColumn('refC.Caption','libelleRef'); 
     end;
  end; 
end;
  • Paramètre de type de donnée
Type
  vue1 = viewOf(ClassA)
   p1:TEnum(enumName) = ...;
  end;
  • Qualifier d'attribut NotInGroupBy
Type
  vue1 = viewOf(ClassA)
   p1:string = expression('...') notInGroupBy;
  end;
  • Héritage de vue locale
Type
  vue1 = viewOf(ClassA)
   p1:string = ...;
   [...]
  end;
 
  vue2 = viewOf(vue1)
   p2:string = ...;
   [inherited and (...)]
  end;

Exemple:

//function GetSelector(iGroupBy:string; iFilter:TJsonArray):TSelector;
Type
  // défini une classe de base avec tous les filtres
  //
  vueEcritureLettrage = viewOf(TEcriture)
    lettrable:boolean = compteGeneral.lettrable notInSelect; 
    idEtablissement:TOID = piece.oidEtablissement notInSelect; 
    idCompteGeneral:TOID = oidCompteGeneral notInSelect; 
    idRoleTiers:TOID = oidroleTiers notInSelect; 
    [(lettrable=true) 
      and ((oidLettrageEcriture='') or (dateLettrage=0)) 
      and (typeEcriture<>0)
      and (piece.lot.origineLot<>0)
      and (eDate>=%ArgDateInf) 
      and (eDate<=%ArgDateSup) 
      and (idEtablissement=%ArgEtablissement) 
      and (idCompteGeneral=%ArgCompteGeneral)
      and (idRoleTiers=%ArgRoleTiers)
    ] 
  end;
 
  // Hérite de tous les filtres
  //
  vueEcritureLettrageGroupBy = viewOf(vueEcritureLettrage)
    dateMin:TDatetime = min(eDate);
    dateMax:TDatetime = max(eDate); 
    ACount:Integer = count(oid); 
    credit:Currency = sum('credit:TCValue'); 
    debit:Currency = sum('debit:TCValue'); 
    solde:Currency = sumDiff(debit,credit); 
    [inherited] 
  end; 
 
begin
  Result := vueLettrageGroupBy.CreateSelector('','',True,[]);
end;
  • Scope de vue locale

Une vue locale peut être référencée en dehors de la méthode où elle est définie.

procedure Class1.foo;
Type
  vue1 = viewOf(ClassA)
   p1:string = ...;
  end;
begin
  ...
end;
 
procedure Class2.bar;
Type
  vue2 = viewOf(class1.foo.vue1)
   p2:string = ...;
  end;
begin
  ...
end;
  • Expression Exists()

Une expression existe peut être utilisée dans les filtres comme une valeur logique

{{tip|Une expression Exists() est beaucoup plus rapide qu'un "Count<>0"}

Type
  vue1 = viewOf(ClassA)
   id:string = ...;
  end;
 
  vue2 = viewOf(ClassB)
   id:string = ...;
   bb:boolean = vue1.Exists('(id=self.id)',True,[]) notInSelect;
   [(bb=true) and (....)]
  end;
  • Expression de Sous requête

Une expression peut être définie par une sous requête

Type
  VueTauxADate = ViewOf(TTauxADate)
    idTVA : TOid = oidTVA;
    tDate : Date = tDate;
    taux : float = taux; 
  end;
 
  vueMontantTVA = viewOf(TEcriture)
    dateEcriture:TDatetime=eDate notInSelect;
    oidTVA:TOID = ProfilTVA.oidTVA notInSelect; 
    oidPiece:TOID = oidPiece; 
    montantTVAReel:Currency = vueTauxADate.select('taux * self.montant_TCValue /100','(tDate<=self.dateEcriture)and(idTVA=self.oidTVA)','',True,[]); 
    montantTVAReel_CodeDevise:string = montantTVAReel:CodeDevise; 
  end;

ToJson

Permet de sérialiser l'objet ou l'ensemble d'objets au format json compatible avec les tables du client React

 procedure TObject.ToJson(SA:TJsonArray);
 procedure TObject.ToJsonEx(SA:TJsonArray; iOptions:TSerializeJsonOptions);
 procedure TSelector.ToJson(SA:TJsonArray);
 procedure TSelector.ToJsonEx(SA:TJsonArray; iOptions:TSerializeJsonOptions);
 procedure TRole.ToJson(SA:TJsonArray);

TSerializeJsonOptions :

  • sjoIdAsGuid
Le membre id de la sérialisation sera un GUID
  • sjoIdAsOid
Le membre id de la sérialisation sera l'OID de l'objet
//procedure GetData(SRows:TJsonArray);
Type
  myView = viewOf(...)
   ...
  end; 
 
var sel:TSelector; 
begin
  // Selector to retreive the data
  // 
  sel := myView.CreateSelector('','',True,[]);
  sel.ToJson(SRows); 
end;

Formats

Le formattage de la sérialisation des propriétés peut être controllé par les propriétés du type

Type
  vue = viewOf(...)
    p:string(typeParam1,typeParam2,typeParam3) = x;
  end;


Type de l'attribut TypeParam1 TypeParam2 TypeParam3 Usage
Currency fmtTC - - Le montant est considéré en valeur de tenue de compte
Currency fmtRP - - Le montant est considéré en valeur de reporting
String contenant un TfwParameters fmtParameters - - Valeur des paramètres
String contenant un TfwParameters fmtParameter Nom du paramètre Valeur par défaut si le paramètre n'existe pas Valeur du paramètre
String fmtTaskCategory - - Catégorie de tâche
oid de TdbfDocument fmtDocumentUrl Paramètre optionnel contenant le nom du document Paramètre optionnel contenant une url externe Lien sur le document
Datetime fmtUTC - - La date en considérée UTC et convertie en date locale
Integer (idOTP) fmtClassLabel - - Le libellé de la classe
Integer (idOTP) fmtClassName - - Le nom de la classe

Sélecteur

  • lastOpeStamp, lastOpeAffected, lastOpeFirstOID
Attributs mis à jour par la dernière opération assembliste.
  • operationId, operation
Permet d'enregistrer les opérations dans la table TsqlOperation
S'applique à CopyTo()
  • RmvParameter()
Permet de retirer un paramètre qui a été ajouté par AddParameter()
  • Amélioration de CopyTo
Permet de créer des objets à partir d'un sélecteur
  • CopyTo, Update, UpdateFrom
Fonctionne sur les classes de stéréotype SQL
  • InsertInto
Permet de créer une table temporaire à partir d'un sélecteur
Réalise un select ... into TEMPTABLE from ...
  • SourceTableName
Permet de sélectionner une table SQL comme source de l'opération
Utiliser dans les opérations ensemblistes sur des tables temporaires

TsqlOperation

Classe SQL définie par le framework et permettant d'enregistrer les opérations du sélecteur

  TsqlOperation = Class(TsqlObject)
  public
    class procedure CleanOpe(iOpeId:string);
    //
    property action: StringS[128];
    property id: SQLIdentity;
    property oidSourceObject: TOID;
    property oidTargetObject: TOID;
    property opeId: StringS[128];
    property operation: StringS[128];
    property SourceObject: Ref(roGeneric,roNotExternal,roNoForeignKey,roNoRoleIndex) of TitObject;
    property TargetObject: Ref(roGeneric,roNotExternal,roNoForeignKey,roNoRoleIndex) of TitObject;
  end;
  • opeId, operationId
Un identifiant unique (guid) identifiant l'ensemble des opérations
  • opération
Nom de l'opération dans l'ensemble des opérations
  • action
Action de l'opération
Par exemple INSERT pour un CopyTo
  • oidSourceObject
identifiant de l'objet source dans l'opération
Par exemple l'objet source de la copie pour un CopyTo
  • oidTargetObject
identifiant de l'objet cible dans l'opération
Par exemple l'objet copié par un CopyTo

Exemple d'utilisation:

 // Créer des écritures a partir des réglements
 //
 procedure  _doCreateEcritureReglements(iOidPiece:string; iOpeId:string);
 var sel:TSelector; 
 begin
   sel := vueEcritureReglement.CreateSelector('(oidBordereau=%1)','',True,[oidBordereauReglement]); 
   sel.AddParameter('ArgBordereau',oidBordereauReglement); 
   sel.Operation := 'EcrReg'; 
   sel.OpeId := iOpeId; 
   // 
   sel.CopyTo('TEcriture',['oidpiece','eDate','sens','sensProrata','regimeTVA','typeEcriture'],[
    iOidPiece,
    BordereauReglement.dateReglement, 
    sens_credit,
    sens_credit, 
    regimeTVA_Encaissements,
    typeEcriture_Brouillard 
   ]); 
 end;
 
 
Type
  vueUpdateReglement = viewOf(TReglement)
   vl:TsqlOperation = join('(opeId=%ArgOpeId) and (operation=%ArgOperation) and (oidSourceObject=self.oid)'); 
   oidEcriture:TOID = oidEcriture; 
   oidTargetEcriture:TOID = vl.oidTargetObject; 
   oidBordereau:TOID = oidBordereauReglement; 
  end; 
 
 // Met à jour l'oidEcriture créée sur les réglements correspondants
 ..
 procedure _doUpdateReglementsEcriture(iOidPiece:string; iOpeId:string);
 var sel:TSelector; 
 begin
   sel := vueUpdateReglement.CreateSelector('(oidBordereau=%1)','',True,[oidBordereauReglement]); 
   sel.AddParameter('ArgOpeId',iOpeId); 
   sel.AddParameter('ArgOperation','EcrReg'); 
   //
   sel.Update(['oidEcriture'],['oidTargetEcriture']); 
 end; 
 
begin
  aOpeId := CreateGuid;
  withP long transaction do
   begin
     aOidPiece := _doCreatePiece();
     _doCreateEcritureReglements(aOidPiece,aOpeId);
     _doUpdateReglementsEcriture(aOidPice,aOpeId); 
     ...
     TsqlOperation.CleanOpe(aOpeId);
   end;
end;

UpdateFrom()

function updateFrom(sel:TSelector; iMatchedProps:Array of string; iUpdatedProps:Array of string; iUpdatedValue:Array of variant):Integer;

Permet de mettre à jour une classe à partir d'un sélecteur et d'une colonne de correspondance.

Exemple :

Type
  // Update the temp table 
  vueTemp = viewOf(TempLettrage)
    reference1:string = reference1;
    reference2:string = reference2;
    modeLettrage:Integer = modeLettrage; 
  end;
 
  vueRef1 = viewOf(TempLettrage)
    //ACount:Integer = count(id);
    ATotal:Currency = sumSign(montant:TCValue,sens,'1');
    reference1:string = reference1; 
    [(modeLettrage=0) and (reference1<>'')] 
  end; 
 
var selT,selG:TSelector;
begin
  withP long transaction do
    begin
     // for updating the temp table on "match" 
     selT := vueTemp.CreateSelector('','',True,[]);
 
     // Lettrage sur reference 1 
     selG := vueRef1.CreateSelector('(ATotal=0)','',True,[]);
     selG.useCTE := True; 
     selT.UpdateFrom(selG,['reference1'],['modeLettrage'],[1]); 
    end;
end;
with CTE as (
select sum(case when t0.sens=1 then ISNULL(t0.montant_TCValue, 0) else -ISNULL(t0.montant_TCValue, 0) end)  as "ATotal",t0.reference1  as "reference1"
from dbo.TEMPLETTRAGE t0 WITH (NOLOCK)
where ((t0.modeLettrage = 0) and (t0.reference1 IS NOT NULL))
group by t0.reference1
)
merge into dbo.TEMPLETTRAGE tm0 using (
SELECT  *
FROM CTE
Where (ATotal = 0.0000)
) tm1 on (tm1.reference1=tm0.reference1)
when matched then update set
tm0.modeLettrage = 1
;

Opérations ensemblistes SQL

Des opérations ensemblistes utilisant des tables SQL temporaires peuvent être réalisées en utilisant l'opération InserInto du selecteur.

Table temporaire

  • TDatabase.AllocTempTable(JobId:string)
Génère un nom de table temporaire
  • TDatabase.DropTempTables(JobId:string)
Supprime (drop) les tables temporaires

Vue SQL locale

Une vue SQL locale permet d'utiliser une table SQL comme source d'opération d'un sélecteur

Type
  // define an interface
  intf = interface
   ...
  end;
 
  // create a view which support the interface
  // will be used to create the temp table
  //
  vue = viewOf(MyClass,intf)
  end;
 
  // define a sql class based on the interface
  //
  sql = sqlClass(intf)
  end;
 
  // view on the sql class
  //
  vue2 = viewOf(sql)
   ...
  end;
 
var sel:Tselector; aJob,aTempTable:string; keepTables:boolean;
begin
  // Alloc a temp table name
  //
  aJob := CreateGuid;
  aTempTable := ClassManager.DefDatabase.AllocTempTable(aJob);
  KeepTables := false; // for debuging
  try
   // Create a temp table from MyClass view
   //
   sel := vue.CreateSelector(...);
   sel.insertInto(aTempTable,[...],[...]); // we create a tempTable
 
   // Query the temp table throught the vue2 
   //
   sel := vue2.CreateSelector(...);
   sel.SourceTableName := aTempTable; // because we select the tempTable
 
  ...
  finally
  if not KeepTables then ClassManager.DefDatabase.DropTempTables(aJob); 
  end; 
end;

Updater

Classe technique permettant de mettre à jour un attribut sur un ensemble d'objet.

Exemple : Mise à jour des compteurs qui ne peuvent pas être déterminés en SQL

Type
  // Should returns all attributes part of the counter
  //
  vueNumeroPiece = viewOf(TPiece)
   pDate:TDatetime = pDate;
   numero:TCounter = numero; 
  end; 
 
 procedure _doUpdateNumeroPiece(iOidPiece:string);
 var sel:TSelector; vueNP:vueNumeroPiece; upd:TUpdater;
 begin
   upd := TPiece.CreateUpdater('numero'); 
   // 
   sel := vueNumeroPiece.CreateSelector('(oid=%1)','',True,[iOidPiece]);
   forEach vueNP in sel.AsCursor do
    begin
      vueNP.numero.AllocValue;
      upd.AddValue(vueNP.OID,vueNP.numero.value); 
    end; 
   //
   upd.Execute; 
 end; 
 
begin
 
end;

Interface





Whos here now:   Members 0   Guests 0   Bots & Crawlers 1
 
Outils personnels