« Version 2025 r2 (release note) » : différence entre les versions
Aucun résumé des modifications |
|||
(23 versions intermédiaires par le même utilisateur non affiché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.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> | |||
* 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. | |||
'''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 278 : | ||
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 28 : | Ligne 301 : | ||
vue2 = viewOf(vue1) | vue2 = viewOf(vue1) | ||
p1:string = ...; | p1:string = ...; | ||
[inherited] | [inherited and (...)] | ||
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; | 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 59 : | Ligne 373 : | ||
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" | |||
<source lang="delphi"> | <source lang="delphi"> | ||
Ligne 71 : | Ligne 387 : | ||
[(bb=true) and (....)] | [(bb=true) and (....)] | ||
end; | end; | ||
</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> | </source> | ||
==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 TdbfLogOpe | |||
: S'applique à CopyTo() | |||
* RmvParameter() | |||
: Permet de retirer un paramètre qui a été ajouté par AddParameter() | |||
* Amélioration de CopyTo | * Amélioration de CopyTo | ||
: 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 SQL | : 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 ... | |||
===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> | |||
===ToJson()=== | |||
<source lang="delphi">procedure ToJson(SA:TJsonArray);</source> | |||
Sérialize tous les objets retournés par le sélecteur au format JSon comptabible avec les tables react | |||
'''Exemple:''' | |||
<source lang="delphi"> | |||
//procedure GetData(SRows:TJsonArray); | |||
Type | |||
myView = viewOf(...) | |||
... | |||
end; | |||
===UpdateFrom=== | var sel:TSelector; | ||
begin | |||
// Selector to retreive the data | |||
// | |||
sel := myView.CreateSelector('','',True,[]); | |||
sel.ToJson(SRows); | |||
end; | |||
</source> | |||
===UpdateFrom()=== | |||
<source lang="delphi"> | <source lang="delphi"> | ||
Ligne 140 : | Ligne 610 : | ||
tm0.modeLettrage = 1 | tm0.modeLettrage = 1 | ||
; | ; | ||
</pre> | |||
==Table temporaire== | |||
* TDatabase.AllocTempTable(JobId:string) | |||
: Génère un nom de table temporaire | |||
* TDatabase.DropTempTables(JobId:string) | |||
: Supprime (drop) les tables temporaires | |||
<source lang="delphi"> | |||
Type | |||
vue = viewOf(...) | |||
end; | |||
var sel:TSelector; aJob,aTempTable1,aTempTable2,aTempTable3,aTempTable4:string; keepTables:boolean; | |||
begin | |||
Result := FALSE; | |||
aJob := 'ANA'; | |||
keepTables := False; | |||
sel := vueUnion.CreateSelector('','',True,[]); | |||
sel.useCTE := True; | |||
sel.NoShare := True; | |||
sel.NoFrameworks := True; | |||
sel.NoOrderBy := True; | |||
sel.AnyWhere := True; | |||
try | |||
// Add the maxLevel by oidGCA to the temp table | |||
aTempTable1 := ClassManager.DefDatabase.AllocTempTable(aJob); | |||
sel.InsertInto(aTempTable1,['maxLevel'],['Expression(max(level) over(partition by oidGroupeCumulAnalytique))']); | |||
//showMessageFmt('%s : %d',[aTempTable1, sel.lastOpeAffected]); | |||
// | |||
sel := vueCumulExtCols.CreateSelector('','',True,[]); | |||
sel.SourceTableName := aTempTable1; | |||
aTempTable2 := ClassManager.DefDatabase.AllocTempTable(aJob); | |||
sel.InsertInto(aTempTable2,[],[]); | |||
//showMessageFmt('%s : %d',[aTempTable2, sel.lastOpeAffected]); | |||
sel := vueCumulFlat.CreateSelector('','',True,[]); | |||
sel.SourceTableName := aTempTable2; | |||
aTempTable3 := ClassManager.DefDatabase.AllocTempTable(aJob); | |||
sel.InsertInto(aTempTable3,[],[]); | |||
//showMessageFmt('%s : %d',[aTempTable3, sel.lastOpeAffected]); | |||
sel := vueCumulFlatMontant.CreateSelector('','',True,[]); | |||
sel.SourceTableName := aTempTable3; | |||
sel.AddParameter('ArgDeviseTC','EUR'); | |||
aTempTable4 := ClassManager.DefDatabase.AllocTempTable(aJob); | |||
sel.InsertInto(aTempTable4,[],[]); | |||
//showMessageFmt('%s : %d',[aTempTable4, sel.lastOpeAffected]); | |||
finally | |||
if not KeepTables then ClassManager.DefDatabase.DropTempTables(aJob); | |||
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> | |||
[[Category:Version 2025 R2]] | [[Category:Version 2025 R2]] | ||
[[Category:Release note]] | [[Category:Release note]] |
Dernière version du 22 mai 2025 à 08:04
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.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>
- 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
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
- 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.
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
<source lang="delphi"> Type
vue1 = viewOf(ClassA) p1:TEnum(enumName) = ...; end;
</source>
- Qualifier d'attribut NotInGroupBy
<source lang="delphi"> Type
vue1 = viewOf(ClassA) p1:string = expression('...') notInGroupBy; end;
</source>
- Héritage de vue locale
<source lang="delphi"> Type
vue1 = viewOf(ClassA) p1:string = ...; [...] end;
vue2 = viewOf(vue1) p1:string = ...; [inherited and (...)] 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>
- Scope de vue locale
Une vue locale peut être référencée en dehors de la méthode où elle est définie.
<source lang="delphi"> procedure Class1.foo; Type
vue1 = viewOf(ClassA) p1:string = ...; end;
begin
...
end;
procedure Class2.bar; Type
vue2 = viewOf(class1.foo.vue1) p1:string = ...; end;
begin
...
end; </source>
- Expression Exists()
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"
<source lang="delphi"> 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;
</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>
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 TdbfLogOpe
- 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 ...
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>
ToJson()
<source lang="delphi">procedure ToJson(SA:TJsonArray);</source>
Sérialize tous les objets retournés par le sélecteur au format JSon comptabible avec les tables react
Exemple:
<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>
UpdateFrom()
<source lang="delphi"> function updateFrom(sel:TSelector; iMatchedProps:Array of string; iUpdatedProps:Array of string; iUpdatedValue:Array of variant):Integer; </source>
Permet de mettre à jour une classe à partir d'un sélecteur et d'une colonne de correspondance.
Exemple :
<source lang="delphi"> 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; </source>
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 ;
Table temporaire
- TDatabase.AllocTempTable(JobId:string)
- Génère un nom de table temporaire
- TDatabase.DropTempTables(JobId:string)
- Supprime (drop) les tables temporaires
<source lang="delphi"> Type
vue = viewOf(...) end;
var sel:TSelector; aJob,aTempTable1,aTempTable2,aTempTable3,aTempTable4:string; keepTables:boolean; begin
Result := FALSE; aJob := 'ANA'; keepTables := False;
sel := vueUnion.CreateSelector(,,True,[]); sel.useCTE := True; sel.NoShare := True; sel.NoFrameworks := True; sel.NoOrderBy := True; sel.AnyWhere := True;
try // Add the maxLevel by oidGCA to the temp table aTempTable1 := ClassManager.DefDatabase.AllocTempTable(aJob); sel.InsertInto(aTempTable1,['maxLevel'],['Expression(max(level) over(partition by oidGroupeCumulAnalytique))']); //showMessageFmt('%s : %d',[aTempTable1, sel.lastOpeAffected]); // sel := vueCumulExtCols.CreateSelector(,,True,[]); sel.SourceTableName := aTempTable1;
aTempTable2 := ClassManager.DefDatabase.AllocTempTable(aJob); sel.InsertInto(aTempTable2,[],[]); //showMessageFmt('%s : %d',[aTempTable2, sel.lastOpeAffected]);
sel := vueCumulFlat.CreateSelector(,,True,[]); sel.SourceTableName := aTempTable2; aTempTable3 := ClassManager.DefDatabase.AllocTempTable(aJob); sel.InsertInto(aTempTable3,[],[]); //showMessageFmt('%s : %d',[aTempTable3, sel.lastOpeAffected]);
sel := vueCumulFlatMontant.CreateSelector(,,True,[]); sel.SourceTableName := aTempTable3; sel.AddParameter('ArgDeviseTC','EUR');
aTempTable4 := ClassManager.DefDatabase.AllocTempTable(aJob); sel.InsertInto(aTempTable4,[],[]); //showMessageFmt('%s : %d',[aTempTable4, sel.lastOpeAffected]);
finally if not KeepTables then ClassManager.DefDatabase.DropTempTables(aJob); 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>