Version 2025 r2 (release note)
(→Sélecteur) |
(→Formats) |
||
| (40 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=== | ||
| + | |||
| + | * Une vue locale peut contenir des attributs "oidXXX" sans définir le rôle | ||
| + | |||
| + | '''Exemple:''' | ||
| + | |||
| + | <source lang="delphi"> | ||
| + | Type | ||
| + | vue1 = viewOf(ClassA) | ||
| + | p1:TEnum(enumName) = ...; | ||
| + | oidRef:TOID = oidrefB; | ||
| + | .. | ||
| + | idRefB:TOID = oidrefB notInSelect; | ||
| + | [ (idRefB=%ArgRefB) and ....] | ||
| + | end; | ||
| + | </source> | ||
| + | |||
| + | * 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:''' | ||
| + | |||
| + | <source lang="delphi"> | ||
| + | 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; | ||
| + | </source> | ||
* Paramètre de type de donnée | * Paramètre de type de donnée | ||
| Ligne 14 : | 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 27 : | Ligne 334 : | ||
vue2 = viewOf(vue1) | vue2 = viewOf(vue1) | ||
| − | + | p2:string = ...; | |
| − | [inherited] | + | [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> | ||
* Scope de vue locale | * Scope de vue locale | ||
| − | Une vue locale peut être référencée en dehors de la méthode | + | Une vue locale peut être référencée en dehors de la méthode où elle est définie. |
<source lang="delphi"> | <source lang="delphi"> | ||
| Ligne 49 : | Ligne 397 : | ||
Type | Type | ||
vue2 = viewOf(class1.foo.vue1) | vue2 = viewOf(class1.foo.vue1) | ||
| − | + | p2:string = ...; | |
end; | end; | ||
begin | begin | ||
| Ligne 59 : | Ligne 407 : | ||
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 | ||
| + | |||
| + | {{tip|Une expression Exists() est beaucoup plus rapide qu'un "Count<>0"} | ||
<source lang="delphi"> | <source lang="delphi"> | ||
| Ligne 72 : | 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, | + | * 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 84 : | 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 144 : | 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
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;
- 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 2 |