• R/O
  • SSH
  • HTTPS

cico: Commit


Commit MetaInfo

Revisión18 (tree)
Tiempo2020-03-11 03:16:14
Autorderekwildstar

Log Message

Incluído código para detecção de Memory Leaks
A tabela de saldos agora é uma query e o campo de saldo mensal não é mais um agregado, mas sim um campo que é resultado de uma soma (sum(saldo) over()) na consulta
Criada a função FormatarHorasMinutos
Refeitos os métodos ObterSaldoGlobal e ObterSaldoMensal
Correção na ordem dos parâmetros de FullBalance em AtualizarSaldos e incluída uma chamada a ObterSaldoGlobal após a atualização do saldo
Os saldos mensais agora aparecem em cores
Removida a dependência da unit TimeSpan em UCiCo.pas
Incluída a função Finalize para evitar Memory Leaks (comentários no código de OpenHoursViewPage)
Incluída verificação em FullBalance para impedir que seja calculado um saldo de um mês posterior ao mes atual ou anterior a Novembro de 2017

Cambiar Resumen

Diferencia incremental

--- trunk/client/prj/CiCo.dpr (revision 17)
+++ trunk/client/prj/CiCo.dpr (revision 18)
@@ -1,6 +1,7 @@
11 program CiCo;
22
33 uses
4+// FastMM4, //Ative o map file detalhado
45 Winapi.Windows,
56 Winapi.Messages,
67 Vcl.Forms,
@@ -44,7 +45,14 @@
4445 Halt;
4546 end;
4647
47- ReportMemoryLeaksOnShutdown := True;
48+ {$WARN SYMBOL_PLATFORM OFF}
49+ if DebugHook > 0 then
50+ begin
51+ ReportMemoryLeaksOnShutdown := True; // Padrão do Delphi
52+// FullDebugModeScanMemoryPoolBeforeEveryOperation := True;
53+// SuppressMessageBoxes := False;
54+ end;
55+ {$WARN SYMBOL_PLATFORM ON}
4856
4957 Application.Initialize;
5058
--- trunk/client/prj/CiCo.dproj (revision 17)
+++ trunk/client/prj/CiCo.dproj (revision 18)
@@ -5,7 +5,7 @@
55 <FrameworkType>VCL</FrameworkType>
66 <MainSource>CiCo.dpr</MainSource>
77 <Base>True</Base>
8- <Config Condition="'$(Config)'==''">Debug</Config>
8+ <Config Condition="'$(Config)'==''">Release</Config>
99 <Platform Condition="'$(Platform)'==''">Win32</Platform>
1010 <TargetedPlatforms>1</TargetedPlatforms>
1111 <AppType>Application</AppType>
@@ -61,7 +61,7 @@
6161 <SanitizedProjectName>CiCo</SanitizedProjectName>
6262 <VerInfo_Locale>1046</VerInfo_Locale>
6363 <VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
64- <Custom_Styles>Glossy|VCLSTYLE|$(BDSCOMMONDIR)\Styles\Glossy.vsf</Custom_Styles>
64+ <Custom_Styles>Carbon|VCLSTYLE|$(BDSCOMMONDIR)\Styles\Carbon.vsf;Glossy|VCLSTYLE|$(BDSCOMMONDIR)\Styles\Glossy.vsf</Custom_Styles>
6565 </PropertyGroup>
6666 <PropertyGroup Condition="'$(Base_Win32)'!=''">
6767 <DCC_UsePackage>DBXSqliteDriver;adsprovider250;DBXInterBaseDriver;vclactnband;vclFireDAC;QuickReportR;RtmRxCtl;tethering;svnui;JvGlobus;dclRBDBE1925;FireDACADSDriver;rbRIDE1925;myprovider250;JvMM;vcltouch;JvBands;vcldb;bindcompfmx;svn;JvJans;unidac250;JvNet;inetdb;oraprovider250;JvAppFrm;KRKOTANotifiersR;KRKStandardControlsR;rbTC1925;KRKCustomizedActionsR;FmxTeeUI;JvDotNetCtrls;dbfprovider250;fmx;fmxdae;rbIDE1925;KRKNetworkControlsR;JvWizards;dbexpress;IndyCore;vclx;JvPageComps;dsnap;nexusprovider250;JvDB;PackageClassesUteis;VCLRESTComponents;rbTCUI1925;rbFireDAC1925;KRKShellControlsR;PNGComponentsR;JclDeveloperTools;rbDB1925;rbRTL1925;vclie;KRKWin32ControlsR;bindengine;DBXMySQLDriver;vquery250;FireDACMySQLDriver;JvCmp;JvHMI;dclRBFireDAC1925;FireDACCommonODBC;tdsprovider250;dclRBE1925;rbRCL1925;ibprovider250;UIRibbonPackageDR;IndyIPCommon;bindcompdbx;JvCustom;vcl;IndyIPServer;JvXPCtrls;dac250;IndySystem;dsnapcon;KRKDataControlsR;rbDBE1925;FireDACMSAccDriver;fmxFireDAC;vclimg;MyConnectionBrokerR;TeeDB;Jcl;aseprovider250;JvCore;JvCrypt;FireDACPgDriver;pgprovider250;FMXTee;liteprovider250;DbxCommonDriver;JvDlgs;JvRuntimeDesign;JvManagedThreads;Tee;rbUSER1925;rbDIDE1925;xmlrtl;JvTimeFramework;fmxobj;vclwinx;unidacfmx250;rtl;rbUSERDesign1925;DbxClientDriver;dacvcl250;rbADO1925;rbRest1925;CustomIPTransport;vcldsnap;odbcprovider250;JvSystem;JvStdCtrls;db2provider250;rbRAP1925;bindcomp;appanalytics;officeXPrt;crcontrols250;rbDAD1925;IndyIPClient;rbBDE1925;bindcompvcl;TeeUI;rbCIDE1925;JvDocking;dbxcds;VclSmp;unidacvcl250;adortl;JvPascalInterpreter;RtmRxDB;JclVcl;dacfmx250;dsnapxml;dclRBADO1925;dbrtl;IndyProtocols;inetdbxpress;JvControls;KRKAdditionalControlsR;JvPrintPreview;accessprovider250;mongoprovider250;JclContainers;fmxase;$(DCC_UsePackage)</DCC_UsePackage>
@@ -91,6 +91,7 @@
9191 <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
9292 <VerInfo_AutoGenVersion>true</VerInfo_AutoGenVersion>
9393 <Icon_MainIcon>..\res\icons8-user-48.ico</Icon_MainIcon>
94+ <DCC_UnitSearchPath>..\src\lib\FastMM;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
9495 </PropertyGroup>
9596 <PropertyGroup Condition="'$(Cfg_2)'!=''">
9697 <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
@@ -104,6 +105,7 @@
104105 <VerInfo_Locale>1033</VerInfo_Locale>
105106 <Icon_MainIcon>..\res\icons8-user-48.ico</Icon_MainIcon>
106107 <AppDPIAwarenessMode>PerMonitor</AppDPIAwarenessMode>
108+ <VerInfo_AutoGenVersion>true</VerInfo_AutoGenVersion>
107109 </PropertyGroup>
108110 <ItemGroup>
109111 <DelphiCompile Include="$(MainSource)">
@@ -147,7 +149,9 @@
147149 <Source>
148150 <Source Name="MainSource">CiCo.dpr</Source>
149151 </Source>
150- <Excluded_Packages/>
152+ <Excluded_Packages>
153+ <Excluded_Packages Name="$(BDSBIN)\dcloffice2k260.bpl">Microsoft Office 2000 Sample Automation Server Wrapper Components</Excluded_Packages>
154+ </Excluded_Packages>
151155 </Delphi.Personality>
152156 <Deployment Version="3">
153157 <DeployFile LocalName="..\bin\CiCo.exe" Configuration="Release" Class="ProjectOutput">
--- trunk/client/src/cico/UDAMOPrincipal.pas (revision 17)
+++ trunk/client/src/cico/UDAMOPrincipal.pas (revision 18)
@@ -25,13 +25,13 @@
2525 FDTAEventostipo: TWideStringField;
2626 FDTAEventosmomento: TDateTimeField;
2727 DASOEventos: TDataSource;
28- FDTASaldos: TFDTable;
28+ FDTASaldos: TFDQuery;
2929 FDTASaldosano: TIntegerField;
3030 FDTASaldosmes: TIntegerField;
3131 FDTASaldossaldo: TIntegerField;
3232 DASOSaldos: TDataSource;
3333 FDTASaldosdia: TIntegerField;
34- FDTASaldosSaldoMensal: TAggregateField;
34+ FDTASaldossaldomensal: TLargeintField;
3535 procedure TMERTimer(Sender: TObject);
3636 procedure APEVMinimize(Sender: TObject);
3737 procedure Sair1Click(Sender: TObject);
@@ -42,7 +42,7 @@
4242 procedure APEVMessage(var Msg: tagMSG; var Handled: Boolean);
4343 procedure FDTASaldosdiaGetText(Sender: TField; var Text: string; DisplayText: Boolean);
4444 procedure FDTASaldossaldoGetText(Sender: TField; var Text: string; DisplayText: Boolean);
45- procedure FDTASaldosSaldoMensalGetText(Sender: TField; var Text: string; DisplayText: Boolean);
45+ procedure FDTASaldossaldomensalGetText(Sender: TField; var Text: string; DisplayText: Boolean);
4646 private
4747 { Private declarations }
4848 FLoggedUserName: String;
@@ -51,6 +51,7 @@
5151 procedure OpenTables;
5252 procedure DoMonthBalance(AMes: Byte; AAno: Word; ASaldos: TSaldos);
5353 procedure AtualizarSaldos(AAnoInicial: Word = 0; AMesInicial: Byte = 0);
54+ function FormatarHorasMinutos(AMinutos: SmallInt): String;
5455 public
5556 { Public declarations }
5657 function LimparCPF(ACPF: String): String;
@@ -94,23 +95,34 @@
9495 end;
9596
9697 procedure TDAMOPrincipal.ObterSaldoGlobal;
98+var
99+ Ano: Word;
100+ Mes: Byte;
97101 begin
98102 FORMPrincipal.PNBBSaldoGlobal.Font.Color := clWhite;
99103
100- FDTASaldos.Filtered := False;
104+ Ano := FDTASaldos.ParamByName('ano').AsWord;
105+ Mes := FDTASaldos.ParamByName('mes').AsByte;
101106 try
102- if FDTASaldosSaldoMensal.Value > 0 then
107+ FDTASaldos.ParamByName('mes').Clear;
108+ FDTASaldos.ParamByName('ano').Clear;
109+ FDTASaldos.Refresh;
110+
111+ if (FDTASaldos.RecordCount > 0) and (not FDTASaldosSaldoMensal.IsNull) then
103112 begin
104- FORMPrincipal.PNBBSaldoGlobal.Caption := FormatDateTime(' hh:nn',FDTASaldosSaldoMensal.Value / 24 / 60);
105- FORMPrincipal.PNBBSaldoGlobal.Font.Color := clLime;
113+ if FDTASaldosSaldoMensal.AsInteger > 0 then
114+ FORMPrincipal.PNBBSaldoGlobal.Font.Color := clLime
115+ else if FDTASaldosSaldoMensal.AsInteger < 0 then
116+ FORMPrincipal.PNBBSaldoGlobal.Font.Color := clRed;
117+
118+ FORMPrincipal.PNBBSaldoGlobal.Caption := FormatarHorasMinutos(FDTASaldosSaldoMensal.AsInteger);
106119 end
107120 else
108- begin
109- FORMPrincipal.PNBBSaldoGlobal.Caption := FormatDateTime('-hh:nn',FDTASaldosSaldoMensal.Value / 24 / 60);
110- FORMPrincipal.PNBBSaldoGlobal.Font.Color := clRed;
111- end
121+ FORMPrincipal.PNBBSaldoGlobal.Caption := ' 00:00';
112122 finally
113- FDTASaldos.Filtered := True;
123+ FDTASaldos.ParamByName('ano').AsWord := Ano;
124+ FDTASaldos.ParamByName('mes').AsByte := Mes;
125+ FDTASaldos.Refresh;
114126 end;
115127 end;
116128
@@ -118,21 +130,14 @@
118130 begin
119131 FORMPrincipal.PNBBSaldoDoMes.Font.Color := clWhite;
120132
121- // Por conta deste ser um campo agregado, precisamos verificar se existem
122- // dados sendo exibidos no dataset, pois ele termina somando todos os
123- // registros quando o dataset filtrado fica vazio
124133 if (FDTASaldos.RecordCount > 0) and (not FDTASaldosSaldoMensal.IsNull) then
125134 begin
126- if FDTASaldosSaldoMensal.Value > 0 then
127- begin
128- FORMPrincipal.PNBBSaldoDoMes.Caption := FormatDateTime(' hh:nn',FDTASaldosSaldoMensal.Value / 24 / 60);
129- FORMPrincipal.PNBBSaldoDoMes.Font.Color := clLime;
130- end
131- else
132- begin
133- FORMPrincipal.PNBBSaldoDoMes.Caption := FormatDateTime('-hh:nn',FDTASaldosSaldoMensal.Value / 24 / 60);
135+ if FDTASaldosSaldoMensal.AsInteger > 0 then
136+ FORMPrincipal.PNBBSaldoDoMes.Font.Color := clLime
137+ else if FDTASaldosSaldoMensal.AsInteger < 0 then
134138 FORMPrincipal.PNBBSaldoDoMes.Font.Color := clRed;
135- end
139+
140+ FORMPrincipal.PNBBSaldoDoMes.Caption := FormatarHorasMinutos(FDTASaldosSaldoMensal.AsInteger);
136141 end
137142 else
138143 FORMPrincipal.PNBBSaldoDoMes.Caption := ' 00:00';
@@ -216,9 +221,9 @@
216221
217222 procedure TDAMOPrincipal.AplicarFiltro;
218223 begin
219- FDTASaldos.Filtered := False;
220- FDTASaldos.Filter := 'ano = ' + FORMPrincipal.CBBXYears.Text + ' and mes = ' + Succ(FORMPrincipal.TASEMonths.TabIndex).ToString;
221- FDTASaldos.Filtered := True;
224+ FDTASaldos.ParamByName('ano').AsWord := StrToInt(FORMPrincipal.CBBXYears.Text);
225+ FDTASaldos.ParamByName('mes').AsByte := Succ(FORMPrincipal.TASEMonths.TabIndex);
226+ FDTASaldos.Refresh;
222227 end;
223228
224229 procedure TDAMOPrincipal.GUIToConfig;
@@ -267,10 +272,11 @@
267272 ,FORMPrincipal.LAEDSenha.Text // Para não ter que decodificar a senha novamente
268273 ,Configuracoes.Matricula
269274 ,DoMonthBalance
270- ,AAnoInicial
271- ,AMesInicial);
275+ ,AMesInicial
276+ ,AAnoInicial);
272277 finally
273278 FDTASaldos.Refresh;
279+ ObterSaldoGlobal;
274280 Screen.Cursor := crDefault;
275281 end;
276282 end;
@@ -354,18 +360,31 @@
354360 procedure TDAMOPrincipal.FDTASaldossaldoGetText(Sender: TField; var Text: string; DisplayText: Boolean);
355361 begin
356362 if DisplayText and (not Sender.IsNull) then
357- if Sender.AsInteger > 0 then
358- Text := FormatDateTime(' hh:nn',Sender.AsInteger / 24 / 60)
359- else
360- Text := FormatDateTime('-hh:nn',Sender.AsInteger / 24 / 60)
363+ Text := FormatarHorasMinutos(Sender.AsInteger);
361364 end;
362365
363-procedure TDAMOPrincipal.FDTASaldosSaldoMensalGetText(Sender: TField; var Text: string; DisplayText: Boolean);
366+procedure TDAMOPrincipal.FDTASaldossaldomensalGetText(Sender: TField; var Text: string; DisplayText: Boolean);
364367 begin
368+ // Este evento só é disparado quando existe algum componente DataAware
369+ // conectado ao campo, por isso existe um TDBText no form principal que não
370+ // exibe nada, ele só serve para que o evento seja disparado e possamos exibir
371+ // seus valores em outros locas, como por exemplo, o botão de saldo mensal
365372 if DisplayText then
366373 ObterSaldoMensal;
367374 end;
368375
376+function TDAMOPrincipal.FormatarHorasMinutos(AMinutos: SmallInt): String;
377+begin
378+ Result := FormatFloat('00',Abs(AMinutos) div 60) + ':' + FormatFloat('00',Abs(AMinutos) mod 60);
379+
380+ if AMinutos < 0 then
381+ Result := '-' + Result
382+ else if AMinutos > 0 then
383+ Result := '+' + Result
384+ else
385+ Result := ' ' + Result;
386+end;
387+
369388 procedure TDAMOPrincipal.TMERTimer(Sender: TObject);
370389 var
371390 Data: String;
--- trunk/client/src/cico/UFORMPrincipal.pas (revision 17)
+++ trunk/client/src/cico/UFORMPrincipal.pas (revision 18)
@@ -72,6 +72,8 @@
7272 procedure CBBXYearsChange(Sender: TObject);
7373 procedure PNBBSaldoDoMesClick(Sender: TObject);
7474 procedure PNBBSaldoGlobalClick(Sender: TObject);
75+ procedure DBGrid2DrawColumnCell(Sender: TObject; const Rect: TRect;
76+ DataCol: Integer; Column: TColumn; State: TGridDrawState);
7577 private
7678 { Private declarations }
7779 FAcaoAutomatica: Boolean;
@@ -196,6 +198,22 @@
196198 end;
197199 end;
198200
201+procedure TFORMPrincipal.DBGrid2DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
202+var
203+ H: Integer;
204+begin
205+ if (Column.Field.FieldName = 'saldo') and (Column.Field.AsString <> '') then
206+ begin
207+ H := StringReplace(Column.Field.AsString,':','',[]).ToInteger;
208+ if H < 0 then
209+ TDBGrid(Sender).Canvas.Font.Color := clRed
210+ else if H > 0 then
211+ TDBGrid(Sender).Canvas.Font.Color := clLime;
212+ end;
213+
214+ TDBGrid(Sender).DefaultDrawColumnCell(Rect,DataCol,Column,State);
215+end;
216+
199217 procedure TFORMPrincipal.EuJaExisto(var Msg: TMessage);
200218 begin
201219 DAMOPrincipal.EuJaExisto;
--- trunk/client/src/lib/UCiCo.pas (revision 17)
+++ trunk/client/src/lib/UCiCo.pas (revision 18)
@@ -51,7 +51,7 @@
5151 uses
5252 KRK.Rtl.Win.WinInet.Utilities, Winapi.Windows, Winapi.WinInet,
5353 System.Classes, KRK.RegExp.Utils, System.RegularExpressionsCore, MSHTML,
54- StrUtils, TimeSpan;
54+ StrUtils;
5555
5656 const
5757 URLBASEH = 'https://homologacao-controlefrequencia.app.tjpe.gov.br/';
@@ -707,7 +707,19 @@
707707 //: minutos correspondente
708708 function GetMinutes(AText: String): SmallInt;
709709 begin
710- Result := TTimeSpan.Parse(Trim(AText)).Minutes + TTimeSpan.Parse(Trim(AText)).Hours * 60;
710+ // Não se pode usar TimeSpan porque ele só trabalha com valores até 23:59 e eu
711+ // preciso retornar uma quantidade ilimitada de horas com seus minutos
712+ with TStringList.Create do
713+ try
714+ Delimiter := ':';
715+ DelimitedText := Trim(AText);
716+ Result := Abs(Strings[0].ToInteger) * 60 + Strings[1].ToInteger;
717+
718+ if Strings[0][1] = '-' then
719+ Result := -Result;
720+ finally
721+ Free;
722+ end;
711723 end;
712724
713725 //: Executa um parser no conteúdo de uma página de visualização de horas, a fim
@@ -760,7 +772,7 @@
760772 //: obrigatório navegar até a página do mês que se quer visualizar. O sistema de
761773 //: controle de frequência foi implantado em novembro de 2017, portanto este
762774 //: deve ser o mês inicial a ser considerado. A função retorna o ViewState
763-function OpenMainHoursViewPage(AHandle: THandle; AProducao: Boolean; AViewState: String; AIdBotao: String): TAdditionalInfo;
775+function OpenMainHoursViewPage(AHandle: THandle; AProducao: Boolean; const AViewState: String; AIdBotao: String): TAdditionalInfo;
764776 var
765777 RO: TRequestOptions;
766778 RE: TResponse;
@@ -826,11 +838,17 @@
826838 //: função retorna o ViewState, que deve ser usado em chamadas subsequantes bem
827839 //: como o mês e o ano correspondente a página. Quando AParaTras = False, a
828840 //: função simulará um clique no botão para avançar nas páginas de meses
829-function OpenHoursViewPage(AHandle: THandle; AProducao: Boolean; AViewState: String; APraTras: Boolean = True): TAdditionalInfo;
841+function OpenHoursViewPage(AHandle: THandle; AProducao: Boolean; const AViewState: String; APraTras: Boolean = True): TAdditionalInfo;
830842 var
831843 RO: TRequestOptions;
832844 RE: TResponse;
833845 begin
846+ // TAdditionalInfo possui strings e por algum motivo, devido a função atual
847+ // ser chamada dentro de um loop que usa parte de seu result como parâmetro de
848+ // uma próxima chamada, havia um memory leak. Usando Finalize antes de
849+ // ZeroMemory resolveu o problema. Leia isso:
850+ // http://forum.madshi.net/viewtopic.php?f=4&t=28177
851+ Finalize(Result);
834852 ZeroMemory(@Result,SizeOf(TAdditionalInfo));
835853 ZeroMemory(@RO,SizeOf(TRequestOptions));
836854 ZeroMemory(@RE,SizeOf(TResponse));
@@ -916,7 +934,9 @@
916934 // Quando AMes e AAno tiverem, ambos, um valor diferente de zero este valor
917935 // será usado como mês/ano final da varredura. Caso esta condição não for
918936 // satisfeita, a função vai percorrer todos os mêses até encontrar o mês/ano
919- // base (11/2017)
937+ // base (11/2017). Também está sendo feita uma verificação para que não
938+ // sejam verificados meses posteriores ao mês atual ou anteriores a novembro
939+ // de 2017
920940 if (AMes = 0) or (AAno = 0) then
921941 begin
922942 AMes := 11;
@@ -923,13 +943,16 @@
923943 AAno := 2017;
924944 end;
925945
926- if not ((AdditionalInfo.Ano = AAno) and (AdditionalInfo.Mes = AMes)) then
927- repeat
928- AdditionalInfo := OpenHoursViewPage(AHandle,AProducao,AdditionalInfo.ViewState);
946+ if (EncodeDate(AAno,AMes,1) >= EncodeDate(2017,11,1)) and (EncodeDate(AAno,AMes,1) <= EncodeDate(AdditionalInfo.Ano,AdditionalInfo.Mes,1)) then
947+ begin
948+ if not ((AdditionalInfo.Ano = AAno) and (AdditionalInfo.Mes = AMes)) then
949+ repeat
950+ AdditionalInfo := OpenHoursViewPage(AHandle,AProducao,AdditionalInfo.ViewState);
929951
930- if Assigned(AOnMonthBalance) then
931- AOnMonthBalance(AdditionalInfo.Mes,AdditionalInfo.Ano,AdditionalInfo.Saldos);
932- until (AdditionalInfo.Ano = AAno) and (AdditionalInfo.Mes = AMes);
952+ if Assigned(AOnMonthBalance) then
953+ AOnMonthBalance(AdditionalInfo.Mes,AdditionalInfo.Ano,AdditionalInfo.Saldos);
954+ until (AdditionalInfo.Ano = AAno) and (AdditionalInfo.Mes = AMes);
955+ end;
933956
934957 // Fase 5: Realiza o logout
935958 ExecuteLogout(AHandle,AProducao);
Show on old repository browser