AJUDA COM REFATORA?ÃO

SINCLAIR 30/01/2015 16:57:49
#444146
Prezados,

Há um tópico sobre refatoração que me chamou atenção e pensei em aplicar em um pequeno bloco de meus códigos.

Em uma tela tenho 3 caixas de verificação sendo

[ ] Exibe Status FATURADO
[ ] Exibe Status AGUARDANDO
[ ] Exibe Demais Status

a tabela TabItens tem o campo Status Varchar(1) que funciona como flag, sendo [Ô]F[Ô] para Faturado, [Ô]A[Ô] para Aguardando, [Ô]B[Ô] para desistência do item, [Ô]C[Ô] para Em Transporte e alguns outros status possíveis.

Se marcar [Ô]Exibe Faturado[Ô] e Exibe Aguardando, por exemplo, poderia ser

Where Status in ([ô]F[ô],[ô]A[ô]) por exemplo.

A opção [Ô]Exibe Demais Status[Ô] faz com que sejam listados os status [Ô]C[Ô], [Ô]D[Ô], [Ô]H[Ô], etc. Claro, deverá desconsiderar o [ô]F[ô] e o [ô]A[ô] se não forem marcados. Ou considerar ambos/um deles, conforme o usuário selecione.

Tenho já um Código em VB6 que cria uma string na variável strComandoSQL e monta o sql conforme as opções selecionadas. Mas está feio o código. E complexo.

Algum colega ajuda a criar um código [Ô]limpo[Ô] e eficiente para o caso?
FFCOUTO 30/01/2015 18:17:01
#444149
Posta o código para a gente analisar. Ficará bem mais fácil indicar o que está errado (se estiver errado) e o que de ser feito (se precisar ser feito).
SINCLAIR 30/01/2015 18:22:47
#444150
Olá, FFCOUTO

Segue o código, conforme pediu.

Usei de outra situação no sistema antigo em VB6, mas o caso é exatamente o mesmo. Tem os campos para exibir ou não proprietário de uma torre, exibir ou não o fornecedor de energia de uma torre, exibir ou não ou demais clientes que tenham vinculo com a torre (excetuando proprietário e fornecedor de energia) e se deve ou não exibir contas que já estejam quitadas (contas ainda não quitadas têm o campo dtquitacao = [ô]01/01/1900[ô])

vw_ficontas é uma View que junta dados da tabela ficontas (contas a receber/pagar) com dados de zxcadgrl (cadastros de clientes e fornecedores) e de pvtorres (cadastro de torres).

é em vw_ficontas que faço o select.

        [ô]------------------------------------------------------------------------------------------------
[ô] !
[ô] !
[ô] FORMAR O COMANDO SQL QUE FAZ A FILTRAGEM DOS DADOS !
[ô] !
[ô] !
[ô]------------------------------------------------------------------------------------------------

[ô]----------------------------------------------------------------
[ô] !
[ô] Filtragem conforme opções marcadas !
[ô] !
[ô]----------------------------------------------------------------

[ô]-------------------------------------------------------------------------------------
[ô] Proprietário e Fornecedor de energia !
[ô]-------------------------------------------------------------------------------------

[ô]Inicialização
str_Operador_IN = [Ô] and (identregclifor in ([Ô]

[ô]Proprietário
str_Operador_IN = str_Operador_IN & IIf(Me.ck_Exibe_Contas_do_Proprietario.Value = 1, [Ô][ô][Ô] & NR_0022.txtIDENTREGPROPRIETARIO.Text & [Ô][ô],[Ô], [Ô][ô][ô][Ô])

[ô]Fornecedor de energia
str_Operador_IN = str_Operador_IN & IIf(Me.ck_Exibe_Contas_do_Proprietario.Value = 1, [Ô][ô][Ô] & NR_0022.txtIDENTREGFORNECEDORENERGIA.Text & [Ô][ô][Ô], [Ô][ô][ô][Ô])

[ô]Remover caracteres separadores de IN que sobrarem no final
str_Operador_IN = RemoveSeparadorDePieceNoInicioOuFinal(str_Operador_IN, [Ô],[Ô], False, True)

[ô]Término
str_Operador_IN = str_Operador_IN & [Ô]))[Ô]

[ô]Formar o comando SQL
str_Comando_SQL_Parte_01 = [Ô]select * from vw_ficontas where (codemp=[Ô] & CodigoEmpresa & [Ô]) and (snexcluido=[ô]N[ô]) and (id_torre_vinculada=[ô][Ô] & NR_0022.txtIDENTREG.Text & [Ô][ô])[Ô] & str_Operador_IN & IIf(Me.ck_Ocultar_Contas_Quitadas.Value = 1, [Ô] and (dtquitacao=[ô]01/01/1900[ô])[Ô], [Ô][Ô])

[ô]-------------------------------------------------------------------------------------
[ô] Exibir contas de demais cadastros que tenham vínculo com a torre !
[ô]-------------------------------------------------------------------------------------

If Me.ck_Exibe_Contas_demais_Cadastros.Value = 1 Then

[ô]Para INSERIR todos os demais cadastros
str_Comando_SQL_Parte_02 = [Ô]select * from vw_ficontas where (codemp=[Ô] & CodigoEmpresa & [Ô]) and (snexcluido=[ô]N[ô]) and (id_torre_vinculada=[ô][Ô] & NR_0022.txtIDENTREG.Text & [Ô][ô])[Ô] & [Ô] and (identregclifor<>[ô]AZBXAZBXAZBXAZBX[ô]) and (identregclifor not in ([ô][Ô] & NR_0022.txtIDENTREGPROPRIETARIO.Text & [Ô][ô],[ô][Ô] & NR_0022.txtIDENTREGFORNECEDORENERGIA.Text & [Ô][ô]))[Ô] & IIf(Me.ck_Ocultar_Contas_Quitadas.Value = 1, [Ô] and (dtquitacao=[ô]01/01/1900[ô])[Ô], [Ô][Ô])

Else

[ô]Para SUPRIMIR todos os demais cadastros
str_Comando_SQL_Parte_02 = [Ô]select * from vw_ficontas where (codemp=[Ô] & CodigoEmpresa & [Ô]) and (snexcluido=[ô]N[ô]) and (id_torre_vinculada=[ô][Ô] & NR_0022.txtIDENTREG.Text & [Ô][ô])[Ô] & [Ô] and (identregclifor=[ô]AZBXAZBXAZBXAZBX[ô]) and (identregclifor not in ([ô][Ô] & NR_0022.txtIDENTREGPROPRIETARIO.Text & [Ô][ô],[ô][Ô] & NR_0022.txtIDENTREGFORNECEDORENERGIA.Text & [Ô][ô]))[Ô] & IIf(Me.ck_Ocultar_Contas_Quitadas.Value = 1, [Ô] and (dtquitacao=[ô]01/01/1900[ô])[Ô], [Ô][Ô])

End If

[ô]----------------------------------------------------------------
[ô] !
[ô] Selecionar os dados !
[ô] !
[ô]----------------------------------------------------------------

Set Registros01 = Conect_PG_SQL_Local.Execute([Ô]select [Ô] & vbCrLf & _
[Ô] * [Ô] & vbCrLf & _
[Ô]from [Ô] & vbCrLf & _
[Ô] ([Ô] & vbCrLf & _
[Ô] [Ô] & str_Comando_SQL_Parte_01 & vbCrLf & _
[Ô] union all[Ô] & vbCrLf & _
[Ô] [Ô] & str_Comando_SQL_Parte_02 & vbCrLf & _
[Ô] ) as Query[Ô] & vbCrLf & _
[Ô]order by dtvencto asc, nome_cliente asc[Ô] & vbCrLf _
)


Tudo de bom.
MARCELO.TREZE 30/01/2015 22:30:55
#444157
é alguma coisa da pra melhorar vamos tentar

[ô]Inicialização
With Me.ck_Exibe_Contas_do_Proprietario
str_Operador_IN = [Ô] and (identregclifor in ([Ô] & IIf(.Value = 1, [Ô][ô][Ô] & _
NR_0022.txtIDENTREGPROPRIETARIO.Text & _
[Ô][ô],[ô][Ô] & NR_0022.txtIDENTREGFORNECEDORENERGIA.Text & [Ô][ô][Ô], [Ô][ô][ô],[ô][ô][Ô])
End With
[ô]Remover caracteres separadores de IN que sobrarem no final <---- não sei como está esta função mas acredito que um replace ajudaria
str_Operador_IN = RemoveSeparadorDePieceNoInicioOuFinal(str_Operador_IN, [Ô],[Ô], False, True)

[ô]Término
str_Operador_IN = str_Operador_IN & [Ô]))[Ô]

[ô]Formar o comando SQL
str_Comando_SQL_Parte_01 = [Ô]select * from vw_ficontas where (codemp=[Ô] & CodigoEmpresa & [Ô]) and (snexcluido=[ô]N[ô]) and (id_torre_vinculada=[ô][Ô] & NR_0022.txtIDENTREG.Text & [Ô][ô])[Ô] & str_Operador_IN & IIf(Me.ck_Ocultar_Contas_Quitadas.Value = 1, [Ô] and (dtquitacao=[ô]01/01/1900[ô])[Ô], [Ô][Ô])

[ô]-------------------------------------------------------------------------------------
[ô] Exibir contas de demais cadastros que tenham vínculo com a torre !
[ô]-------------------------------------------------------------------------------------

With Me.ck_Exibe_Contas_demais_Cadastros

[ô]Para INSERIR ou SUPRIMIR todos os demais cadastros
str_Comando_SQL_Parte_02 = [Ô]select * from vw_ficontas where (codemp=[Ô] & CodigoEmpresa & [Ô]) and (snexcluido=[ô]N[ô]) and (id_torre_vinculada=[ô][Ô] & NR_0022.txtIDENTREG.Text & [Ô][ô])[Ô] & [Ô] and (identregclifor[Ô] & IIF(.Value = 1,[Ô]<>[Ô],[Ô]=[Ô]) &[Ô][ô]AZBXAZBXAZBXAZBX[ô]) and (identregclifor not in ([ô][Ô] & NR_0022.txtIDENTREGPROPRIETARIO.Text & [Ô][ô],[ô][Ô] & NR_0022.txtIDENTREGFORNECEDORENERGIA.Text & [Ô][ô]))[Ô] & IIf(Me.ck_Ocultar_Contas_Quitadas.Value = 1, [Ô] and (dtquitacao=[ô]01/01/1900[ô])[Ô], [Ô][Ô])

End With

[ô]----------------------------------------------------------------
[ô] !
[ô] Selecionar os dados !
[ô] !
[ô]----------------------------------------------------------------

Set Registros01 = Conect_PG_SQL_Local.Execute([Ô]select * from ([Ô] & _
[Ô] & str_Comando_SQL_Parte_01 & [Ô]union all[Ô] & _
[Ô] & str_Comando_SQL_Parte_02 & _
[Ô] ) as Query order by dtvencto asc, nome_cliente asc[Ô])
)
SINCLAIR 31/01/2015 07:34:45
#444162
Colegas,

Obrigado por terem respondido.

Antes de encerrar o tópico, vou fazer mais algumas tentativas de refatoração.

Caso mudanças sejam realmente feitas, postarei como ficou o código.

Tudo de bom.
FFCOUTO 31/01/2015 12:20:28
#444165
Resposta escolhida
ZEUZEBIO3,

Neste fim de semana vou olhar seu código mais a fundo.
Pelo que pude ver rapidamente, seu código aplica vários filtros num Select.
Aguarde pela minha resposta, ok.
Abraços
SINCLAIR 31/01/2015 12:38:14
#444166
Olá, Fabiano...

São 2 selects, sendo um para que insira na cláusula IN o código (chamado identreg) do proprietário do terreno onde fica a torre e/ou do fornecedor de energia para a torre.

O outro select é para incluir na resultset outros cadastros (de outras pessoas) que possam ter financeiro ligado à torre, como o cidadão que vai lá capinar o terreno onde a torre está ou a prefeitura que pode cobrar IPTU.

No cadastro da torre sempre tem o identreg do proprietário do terreno. Nem sempre tem o identreg do fornecedor de energia elétrica. No financeiro pode haver contas para os mesmos e para terceiros (contas lançadas manualmente) que quando do lançamento se escolhe alguma torre que tenha vínculo.

Então a filtragem é assim:

  • Incluir ou não o proprietário no resultset
  • Incluir ou não o fornecedor de energia no resultset
  • Incluir ou não outros cadastros no resultset

    Eu fiz um select com IN para os identreg de proprietário e fornecedor de energia (no campo identregclifor de vw_ficontas) e outro select para identregclifor se quaisquer outros cadastros (nenhum identreg é igual a
  • [ô]AZBXAZBXAZBX[ô]). Neste segundo select eu coloco o NOT IN para os identreg do proprietário e fornecedor de energia, porque se marcar somente esta opção (a terceira) o identregclifor <> [ô]AZBXAZBXAZBX[ô] pegaria os identregclifor de proprietário e fornecedor (que não deve pegar porque foram desmarcados).

    Aguardo sim, colega. E muito obrigado por sua atenção.

    Tudo de bom.
    FFCOUTO 01/02/2015 17:26:56
    #444191
    ZEUZEBIO3,

    Como prometido aqui está o seu código refatorado.
    Algumas observações devem ser feitas:
    1) O ideal seria você colar esse código numa classe e alterar os controles checkbox e textbox para propriedades da classe. A partir daí você apenas instancia a classe, seta as propriedades, executa a consulta e destrói a instacia.
    2) Ao usar um campo data e esta possuir a condição de não ser setada, como a data de quitação do seu exemplo, use null para preenche-la e desta forma você poderá usar o operador Is Null.
    3) Use parâmetros no lugar de concatenar a string de sql, dessa forma você evita ataques de sql injection.

    Qualquer dúvida no novo código é só postar

    [ô]Essas variáveis devem ser declaradas na sessão Declarations para que fiquem visíveis a todas as funções abaixo.
    Private strSqlComando1 As String
    Private strSqlComando2 As String

    [ô]----------------------------------------------------------------
    [ô] REALIZA A FILTRAGEM DOS DADOS !
    [ô]----------------------------------------------------------------
    Public Sub Consultar()
    [ô]----------------------------------------------------------------
    [ô] Filtragem conforme opções marcadas !
    [ô]----------------------------------------------------------------

    [ô]----------------------------------------------------------------
    [ô] Proprietário e Fornecedor de energia !
    [ô]----------------------------------------------------------------
    PrepararComandoBase strSqlComando1
    PrepararFiltroCadastroPrincipal strSqlComando1, False
    PrepararFiltroContasQuitadas strSqlComando1

    [ô]-------------------------------------------------------------------
    [ô] Exibir contas de demais cadastros que tenham vínculo com a torre !
    [ô]-------------------------------------------------------------------
    Dim bolOutrosCadastros As Boolean

    [ô]Quando [ô]True[ô] a consulta vai INSERIR todos os demais cadastros
    [ô]Quanto [ô]False[ô] a consulta vai SUPRIMIR todos os demais cadastros
    bolOutrosCadastros = (ck_Exibe_Contas_demais_Cadastros.Value = 1)

    PrepararComandoBase strSqlComando2
    PrepararFiltroOutrosCadastros strSqlComando2, IIf(bolOutrosCadastros, [Ô]<>[Ô], [Ô]=[Ô])
    PrepararFiltroCadastroPrincipal strSqlComando2, True
    PrepararFiltroContasQuitadas strSqlComando2

    [ô]----------------------------------------------------------------
    [ô] Selecionar os dados !
    [ô]----------------------------------------------------------------
    Dim strSqlComando As String

    strSqlComando = [Ô]SELECT * FROM ([Ô] & _
    strSqlComando1 & [Ô] UNION ALL [Ô] & strSqlComando2 & [Ô]) AS Query [Ô] & _
    [Ô]ORDER BY dtvencto ASC, nome_cliente ASC;[Ô]

    Set Registros01 = Conect_PG_SQL_Local.Execute(strSqlComando)
    End Sub

    Private Sub PrepararComandoBase(ByRef strSQL As String)
    [ô]realiza a montagem do comando 1
    strSQL = [Ô]SELECT * FROM vw_ficontas [Ô]
    strSQL = strSQL & [Ô]WHERE (codemp = [Ô] & CodigoEmpresa & [Ô]) [Ô]
    strSQL = strSQL & [Ô]AND (snexcluido = [ô]N[ô]) [Ô]
    strSQL = strSQL & [Ô]AND (id_torre_vinculada = [ô][Ô] & NR_0022.txtIDENTREG.Text & [Ô][ô]) [Ô]
    End Sub

    Private Sub PrepararFiltroCadastroPrincipal(ByRef strSQL As String, ByVal bExcluir As Boolean)
    Dim inOper() As String
    Dim intCountFilter As Integer

    [ô]nenhum filtro foi especificado
    intCountFilter = -1

    If (ck_Exibe_Contas_do_Proprietario.Value = 1) Then
    intCountFilter = intCountFilter + 1
    ReDim Preserve inOper(intCountFilter)
    inOper(intCountFilter) = NR_0022.txtIDENTREGPROPRIETARIO.Text
    End If

    If (ck_Exibe_Contas_do_Proprietario.Value = 1) Then
    intCountFilter = intCountFilter + 1
    ReDim Preserve inOper(intCountFilter)
    inOper(intCountFilter) = NR_0022.txtIDENTREGFORNECEDORENERGIA.Text
    End If

    If intCountFilter > -1 Then
    strSQL = strSQL & [Ô] AND (identregclifor [Ô] & IIf(bExcluir, [Ô]NOT[Ô], [Ô][Ô]) & [Ô] IN ([Ô] & Join(inOper, [Ô], [Ô]) & [Ô])) [Ô]
    End If
    End Sub

    Private Sub PrepararFiltroOutrosCadastros(ByRef strSQL As String, ByVal operComparacao As String)
    [ô]O ideal é substituir a sequencia de caracteres por uma sequencia de 5 astericos
    [ô]strSQL = strSQL & Replace([Ô]AND (identregclifor %1 [ô]*****[ô]) [Ô], [Ô]%1[Ô], operComparacao)

    strSQL = strSQL & Replace([Ô]AND (identregclifor %1 [ô]AZBXAZBXAZBXAZBX[ô]) [Ô], [Ô]%1[Ô], operComparacao)
    End Sub

    Private Sub PrepararFiltroContasQuitadas(ByRef strSQL As String)
    [ô]O correto é utilizar o campo com valor null e não uma data antiga para
    [ô]informar o seu não preenchimento

    [ô]Com null ficara dessa forma
    [ô]If (ck_Ocultar_Contas_Quitadas.Value = 1) Then
    [ô] strSQL = strSQL & [Ô] AND (dtquitacao IS NULL) [Ô]
    [ô]End If

    [ô]Usando um valor antigo
    If (ck_Ocultar_Contas_Quitadas.Value = 1) Then
    strSQL = strSQL & [Ô] AND (dtquitacao = [ô]01/01/1900[ô]) [Ô]
    End If
    End Sub


    Espero ter ajudado.
    SINCLAIR 02/02/2015 09:41:49
    #444212
    Colega FFCOUTO.

    Maravilha.

    Código Entendido e Refatorado.

    Vou colocar na parte de adições da versão no novo sistema.

    Grato e Tudo de bom!
    Tópico encerrado , respostas não são mais permitidas