Clipper On Line • Ver Tópico - Meu modo de trabalho

Meu modo de trabalho

Aqui você poderá oferecer suas Contribuições, Dicas e Tutoriais (Texto ou Vídeo) que sejam de interesse de todos.

Moderador: Moderadores

 

Meu modo de trabalho

Mensagempor JoséQuintas » 25 Mar 2020 18:46

Finalmente o Windows parece normal.
Hoje foi complicado... o dia inteiro perdido por causa do Windows.
Só agora testando a atualização nos backups.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 30 Mar 2020 09:49

mdfe.png


Menos dois.

Agora MDFE é totalmente SQL.
Esses JPMDFCAB e JPMDFDET não são mais usados.

Os demais maiores, continuo eliminando o uso do DBF.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 02 Abr 2020 12:40

Um relatório simples, alterado pra MySQL.

A parte de escolha de opções... sem alteração.

#include "inkey.ch"
#include "josequintas.ch"

MEMVAR nOpcOrdem, acTxtOrdem, midProdutoi, midProdutof, nOpcProDep, acTxtProDep, nOpcProduto
MEMVAR acTxtProduto, nOpcTipoEstoque, acTxtTipoEstoque, mIdProDep
MEMVAR nOpcProSec, acTxtProSec, nOpcProGru, acTxtProGru, mIdProSec, mIdProGru, nOpcPrinterType

PROCEDURE LJPITEM

   LOCAL nOpcGeral := 1, acTxtGeral := Array(8), nOpcTemp

   PRIVATE nOpcOrdem   := 1, acTxtOrdem := { "Código", "Alfabética", "Depto+Seção+Grupo", "Tributação" }
   PRIVATE nOpcProduto := 1, mIdProdutoi := 0, midProdutof := 0, acTxtProduto := { "Todos", "Intervalo" }
   PRIVATE nOpcProDep  := 1, mIdProDep := 0, acTxtProDep := { "Todos", "Específico" }
   PRIVATE nOpcProSec  := 1, mIdProSec := 0, acTxtProSec := { "Todos", "Específico" }
   PRIVATE nOpcProGru  := 1, mIdProGru := 0, acTxtProGru := { "Todos", "Específico" }
   PRIVATE nOpcTipoEstoque := 1, acTxtTipoEstoque := { "Todos", "Sim (Vendas)", "Não (Vendas)", "Inativo", "Ativo (Bens)", "Uso" }
   PRIVATE nOpcPrinterType := AppPrinterType()

   IF ! AbreArquivos( "jpempresa" )
      RETURN
   ENDIF

   WOpen( 5, 4, 7 + Len( acTxtGeral ), 45, "Opções disponíveis" )

   DO WHILE .T.

      acTxtGeral := { ;
         TxtImprime(), ;
         "Ordem.....: " + acTxtOrdem[ nOpcOrdem ], ;
         "Intervalo.: " + iif( nOpcProduto == 1, acTxtProduto[ 1 ], StrZero( midProdutoi, 6 ) + " A " + StrZero( midProdutof, 6 ) ), ;
         "Tipo Estoq: " + acTxtTipoEstoque[ nOpcTipoEstoque ], ;
         "Depto.....: " + Iif( nOpcProDep == 1, acTxtProDep[ nOpcProDep ], Str( mIdProDep, 6 ) ), ;
         "Seção.....: " + iif( nOpcProSec == 1, acTxtProSec[ nOpcProSec ], Str( mIdProSec, 6 ) ), ;
         "Grupo.....: " + iif( nOpcProGru == 1, acTxtProGru[ nOpcProGru ], Str( mIdProGru, 6 ) ), ;
         "Saída.....: " + TxtSaida()[ nOpcPrinterType ] }

      FazAchoice( 7, 5, 6 + Len( acTxtGeral ), 44, acTxtGeral, @nOpcGeral )

      nOpcTemp := 1
      DO CASE
      CASE LastKey() == K_ESC
         EXIT

      CASE nOpcGeral == nOpcTemp++
         IF ConfirmaImpressao()
            imprime()
         ENDIF

      CASE nOpcGeral == nOpcTemp++
         WAchoice( nOpcGeral + 6, 25, acTxtOrdem, @nOpcOrdem, "Ordem" )

      CASE nOpcGeral == nOpcTemp++
         JPPRODUTOClass():Intervalo( nOpcGeral + 6, 25, @nOpcProduto, @midProdutoi, @midProdutof )

      CASE nOpcGeral == nOpcTemp++
         WAchoice( nOpcGeral+6, 25, acTxtTipoEstoque, @nOpcTipoEstoque, "Tipo de Estoque" )

      CASE nOpcGeral == nOpcTemp++
         AUXPRODEPClass():Intervalo( nOpcGeral + 6, 25, @nOpcProDep, @mIdProDep )

      CASE nOpcGeral == nOpcTemp++
         AUXPROSECClass():Intervalo( nOpcGeral + 6, 25, @nOpcProSec, @mIdProSec )

      CASE nOpcGeral == nOpcTemp++
         AUXPROGRUClass():Intervalo( nOpcGeral + 6, 25, @nOpcProGru, @mIdProGru )

      CASE nOpcGeral == nOpcTemp
         WAchoice( nOpcGeral+6, 25, TxtSaida(), @nOpcPrinterType, "Saída" )
         AppPrinterType( nOpcPrinterType )

      ENDCASE
   ENDDO
   WClose()

   RETURN


A configuração do relatório, cabeçalho, etc. relativamente sem alterações

STATIC FUNCTION imprime()

   LOCAL oPDF, mProDep, mProSec, mProGru, mTripro, nKey
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   oPDF := PDFClass():New()
   oPDF:SetType( nOpcPrinterType )
   oPDF:Begin()
   nKey = 0

   oPDF:acHeader := {"","",""}
   oPDF:acHeader[ 1 ] = "LISTAGEM DO CADASTRO DE PRODUTOS"
   oPDF:acHeader[ 3 ] = Space(15) + "-PRODUTO/" + Pad( "DESCRICAO", 65, "-" ) + "  UN     PESO_LIQ     PESO_BRU     MEDIDAS"
   oPDF:acHeader[ 2 ] := "Ordem:" + acTxtOrdem[ nOpcOrdem ]
   IF nOpcProduto != 1
      oPDF:acHeader[ 2 ] := oPDF:acHeader[ 2 ] + ", de: "   + StrZero( midProdutoi, 6 ) + " ate: " + StrZero( midProdutof, 6 )
   ENDIF
   oPDF:acHeader[ 2 ] += ", Est:"+iif( nOpcTipoEstoque == 1, "Todos", acTxtTipoEstoque[ nOpcTipoEstoque ] )
   IF nOpcProDep == 2
      oPDF:acHeader[ 2 ] += ", Depto " + NumberSQL( mIdProDep )
   ENDIF
   IF nOpcProSec == 2
      oPDF:acHeader[ 2 ] += ", Secao " + NumberSQL( mIdProSec )
   ENDIF
   IF nOpcProGru == 2
      oPDF:acHeader[ 2 ] += ", Grupo " + NumberSQL( mIdProGru )
   ENDIF


A preparação do que vai imprimir, com certeza mudou.


   WITH OBJECT cnSQL
      :cSQL := "SELECT" + ;
            " IDPRODUTO, IEPRODEP, IEPROSEC, IEPROGRU, IETIPO, IETRIPRO, IEDESCRI," + ;
            " IELARGURA, IEALTURA, IEPROFUND, IEUNID, IEPESLIQ, IEPESBRU," + ;
            " PRODEP.AXDESCRI AS PRODEPDESCRI," + ;
            " PROSEC.AXDESCRI AS PROSECDESCRI," + ;
            " PROGRU.AXDESCRI AS PROGRUDESCRI," + ;
            " TRIPRO.AXDESCRI AS TRIPRODESCRI" + ;
         " FROM JPITEM" + ;
         " LEFT JOIN JPAUXILIAR AS PRODEP ON PRODEP.AXTABELA = " + StringSQL( AUX_PRODEP ) + ;
            " AND PRODEP.AXCODIGO = JPITEM.IEPRODEP" + ;
         " LEFT JOIN JPAUXILIAR AS PROSEC ON PROSEC.AXTABELA = " + StringSQL( AUX_PROSEC ) + ;
            " AND PROSEC.AXCODIGO = JPITEM.IEPROSEC" + ;
         " LEFT JOIN JPAUXILIAR AS PROGRU ON PROGRU.AXTABELA = " + StringSQL( AUX_PROGRU ) + ;
            " AND PROGRU.AXCODIGO = JPITEM.IEPROGRU" + ;
         " LEFT JOIN JPAUXILIAR AS TRIPRO ON TRIPRO.AXTABELA = " + StringSQL( AUX_TRIPRO ) + ;
            " AND TRIPRO.AXCODIGO = JPITEM.IETRIPRO" + ;
         " WHERE 1 = 1"
      IF nOpcProduto == 2
         :cSQL += " AND IDPRODUTO BETWEEN " + NumberSQL( mIdProdutoi ) + " AND " + NumberSql( mIdProdutof )
      ENDIF
      IF nOpcProDep == 2
         :cSQL += " AND IEPRODEP = " + NumberSQL( mIdProDep )
      ENDIF
      IF nOpcProSec == 2
         :cSQL += " AND IEPROSEC = " + NumberSQL( mIdProSec )
      ENDIF
      IF nOpcProGru == 2
         :cSQL += " AND IEPROGRU = " + NumberSQL( mIdProGru )
      ENDIF
      IF nOpcTipoEstoque != 1
         :cSQL += " AND IETIPO = " + StringSQL( Substr( "XSNIAU", nOpcTipoEstoque, 1 ) )
      ENDIF
      DO CASE
      CASE nOpcOrdem == 1; :cSQL += " ORDER BY IDPRODUTO"
      CASE nOpcOrdem == 2; :cSQL += " ORDER BY IEDESCRI"
      CASE nOpcOrdem == 3; :cSQL += " ORDER BY PRODEPDESCRI, PROSECDESCRI, PROGRUDESCRI, IEDESCRI"
      CASE nOpcOrdem == 4; :cSQL += " ORDER BY IETRIPRO"
      ENDCASE
      :Execute()


E a impressão, agora pegando do MYSQL

      mProDep := 0
      mProSec := 0
      mProGru := 0
      mTriPro := 0
      DO WHILE nKey != K_ESC .AND. ! :Eof()
         nKey = Inkey()
         oPDF:MaxRowTest()
         IF nOpcOrdem == 3 .AND. :Number( "IEPRODEP" ) != mProDep
            oPDF:DrawText( oPDF:nRow + 1, 0, "D:" + Str( :Number( "IEPRODEP" ), 6 ) + " - " + :String( "PRODEPDESCRI" ) )
            mProDep := :Number( "IEPRODEP" )
            mProSec := 0
            mProGru := 0
            oPDF:nRow += 3
            oPDF:MaxRowTest()
         ENDIF
         IF nOpcOrdem == 3 .AND. :Number( "IEPROSEC" ) != mProSec
            oPDF:DrawText( oPDF:nRow+1, 5, "S:" + Str( :Number( "IEPROSEC" ), 6 ) + " - " + :String( "PROSECDESCRI" ) )
            mProSec := :Number( "IEPROSEC" )
            mProGru := 0
            oPDF:nRow += 2
            oPDF:MaxRowTest()
         ENDIF
         IF nOpcOrdem == 3 .AND. :Number( "IEPROGRU" ) != mProGru
            oPDF:DrawText( oPDF:nRow+1, 10, "G:" + Str( :Number( "IEPROGRU" ), 6 ) + " - " + :String( "PROGRUDESCRI" ) )
            mProGru := :Number( "IEPROGRU" )
            oPDF:nRow += 2
            oPDF:MaxRowTest()
         ENDIF
         IF nOpcOrdem == 4 .AND. :Number( "IETRIPRO" ) != mTriPro
            oPDF:DrawText( oPDF:nRow+1, 15, "T:" + Str( :Number( "IETRIPRO" ), 6 ) + " - " + :String( "TRIPRODESCRI" ) )
            mTriPro := :Number( "IETRIPRO" )
            oPDF:nRow += 3
            oPDF:MaxRowTest()
         ENDIF
         oPDF:DrawText( oPDF:nRow, 20, Str( :Number( "IDPRODUTO" ), 6 ) )
         oPDF:DrawText( oPDF:nRow, oPDF:nCol + 2, :String( "IEDESCRI", 60 ) )
         oPDF:DrawText( oPDF:nRow, oPDF:nCol + 2, :String( "IEUNID", 6 ) )
         oPDF:DrawText( oPDF:nRow, oPDF:nCol + 2, :Number( "IEPESLIQ" ), PicVal( 9, 3 ) )
         oPDF:DrawText( oPDF:nRow, oPDF:nCol + 2, :Number( "IEPESBRU" ), PicVal( 9, 3 ) )
         oPDF:DrawText( oPDF:nRow, oPDF:nCol + 2, Ltrim( Str( :Number( "IEALTURA" ) ) ) + "x" + ;
            Ltrim( Str( :Number( "IELARGURA" ) ) ) + "x" + Ltrim( Str( :Number( "IEPROFUND" ) ) ) )
         oPDF:nRow += 1
         :MoveNext()
      ENDDO
      :CloseRecordset()
   ENDWITH
   oPDF:End()

   RETURN NIL


relatorio.png
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 02 Abr 2020 13:01

Comentários sobre o relatório anterior:

Em DBF, abria produtos (JPITEM) e JPAUXILIAR pras tabelas auxiliares.
Acho que nem precisa dizer, mas precisava posicionar departamento, seção, grupo, tributação. (SEEK com o índice correto).
Também precisava indexar, conforme a ordem.
E mais os IFs. conforme a seleção, para os filtros.

Em SQL... os IFs continuam, mas pra montagem do comando SQL.
E o comando SQL substituiu tudo.

Nenhum arquivo aberto, nenhuma preocupação com índice, apenas um comando SQL que pede tudo e vém pronto.
É praticamente um comando SQL, e imprimir.
Dá até pra pensar em expandir as opções, porque vai ser mexer no comando SQL, e mexer na impressão.

No final, relatório de cadastro, ou um mais "sofisticado", podem ficar relativamente iguais.
Lógico, sempre tem exceções, mas na regra geral seria isso.

Acaba se tornando relativamente mais fácil fazer manutenção em um relatório. (ou pra apresentação em tela com um browse).

Está aí, não tinha pensado nisso, mas.....
Agora poderia dar a opção de fazer um browse ao invés do relatório, usando o resultado do comando SQL !!!
Ou pra gerar em Excel !!!

Vixe... ainda migrando e novas possibilidades aparecendo....

Pois é... chamar a atenção de novo pra isso: só trocando DBF pra MySQL, e facilidades começando a aparecer.
De repente, qualquer relatório pra Excel ou outra coisa...
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 04 Abr 2020 01:00

Um outro fonte alterado.
Apesar de relativamente simples, é mais interessante.

FUNCTION MsgSemRegra( cModulo )

   LOCAL cTexto := ""

   hb_Default( @cModulo, m_Prog )

   cTexto += "REGRA DE TRIBUTAÇÃO:" + hb_eol()
   cTexto += hb_eol()
   cTexto += "Transação..........: "
   IF Empty( jppedido->pdTransa )
      cTexto += MSG_DESCONHECIDO
   ELSE
      cTexto += jppedido->pdTransa + " " + DescricaoJPTRANSA( jppedido->pdTransa )
   ENDIF
   cTexto += hb_eol() + hb_eol()
   cTexto += "Tributação UF......: "
   IF Empty( jpuf->ufTriUf )
      cTexto += MSG_DESCONHECIDO
   ELSE
      cTexto += jpuf->ufTriUf + " " + Trim( AUXTRIUFClass():Descricao( jpuf->ufTriUf ) )
   ENDIF
   cTexto += hb_eol()
   cTexto += Space(10) + jpcadastro->cdUf
   cTexto += hb_eol() + hb_eol()
   cTexto += "Tributação Cadastro: "
   IF Empty( jpcadastro->cdTriCad )
      cTexto += MSG_DESCONHECIDO
   ELSE
      cTexto += jpcadastro->cdTriCad + " " + Trim( AUXTRICADClass():Descricao( jpcadastro->cdTriCad ) )
   ENDIF
   cTexto += hb_eol()
   cTexto += Space(10) + jpcadastro->idCadastro + " " + jpcadastro->cdNome
   cTexto += hb_eol() + hb_eol()
   Encontra( jpcadastro->cdUf, "jpuf", "numlan" )
   cTexto += "Tributação Produto.: "
   IF Empty( jpitem->ieTriPro )
      cTexto += MSG_DESCONHECIDO
   ELSE
      cTexto += jpitem->ieTriPro + " " + Trim( AUXTRIPROClass():Descricao( jpitem->ieTriPro ) )
   ENDIF
   cTexto += hb_eol()
   cTexto += Space(10) + jpitem->idProduto + " " + jpitem->ieDescri
   cTexto += hb_eol() + hb_eol()
   IF Empty( jpitped->ipPisCst )
      cTexto += "*** produto sem CST PIS ***" + hb_eol()
   ENDIF
   cTexto += "Posição:" + cModulo + hb_eol()
   cTexto += hb_eol()
   cTexto += "Não foi encontrada uma regra de tributação para essa combinação de informações" + hb_eol()
   cTexto += "Pode ser alguma informação errada, ou falta cadastrar uma regra de tributação com esta combinação" + hb_eol()
   cTexto += "Se for na confirmação do pedido, pode faltar passar na digitação de produto pra atualizar pedido" + hb_eol()

   MsgWarning( cTexto )

   RETURN NIL


O que ele usa:
- JPITPED - produtos dos pedidos
- JPPEDIDO - pedidos
- JPCADASTRO - cadastros
- JPTRANSA - transação
- JPITEM - produtos
- JPUF - pra UFs
- JPAUXILIAR - para descrição de tributação de UF
- JPAUXILIAR - pra descrição de tributação de cadastro
- JPAUXILIAR - pra descrição de tributação de produto
Por isso é interessante: são 7 DBFs, mas equivalente a 9 DBFs.

Como ficou em SQL: o de sempre, o comando e o uso do resultado.

FUNCTION MsgSemRegra( mIdItPed, cModulo )

   LOCAL cTexto := ""
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   hb_Default( @cModulo, m_Prog )

   WITH OBJECT cnSQL
      :cSQL := "SELECT" + ;
         " JPPEDIDO.PDTRANSA, JPTRANSA.TRDESCRI," + ;
         " JPPEDIDO.PDCADASTRO, JPCADASTRO.CDNOME, JPCADASTRO.CDTRICAD, TRICAD.AXDESCRI AS TRICADDESCRI," + ;
         " JPCADASTRO.CDUF, JPUF.UFTRIUF, TRIUF.AXDESCRI AS TRIUFDESCRI," + ;
         " JPITPED.IPPRODUTO, JPITEM.IEDESCRI, JPITEM.IETRIPRO, TRIPRO.AXDESCRI AS TRIPRODESCRI" + ;
         " FROM JPITPED" + ;
         " LEFT JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPITPED.IPPEDIDO" + ;
         " LEFT JOIN JPITEM ON JPITEM.IDPRODUTO = JPITPED.IPPRODUTO" + ;
         " LEFT JOIN JPCADASTRO ON JPCADASTRO.IDCADASTRO = JPPEDIDO.PDCADASTRO" + ;
         " LEFT JOIN JPTRANSA ON JPTRANSA.IDTRANSA = JPPEDIDO.PDTRANSA" + ;
         " LEFT JOIN JPUF ON JPUF.UFUF = JPCADASTRO.CDUF" + ;
         " LEFT JOIN JPAUXILIAR AS TRICAD ON TRICAD.AXTABELA = " + StringSQL( AUX_TRICAD ) + ;
            " AND TRICAD.AXCODIGO = JPCADASTRO.CDTRICAD" + ;
         " LEFT JOIN JPAUXILIAR AS TRIPRO ON TRIPRO.AXTABELA = " + StringSQL( AUX_TRIPRO ) + ;
            " AND TRIPRO.AXCODIGO = JPITEM.IETRIPRO" + ;
         " LEFT JOIN JPAUXILIAR AS TRIUF ON TRIUF.AXTABELA = " + StringSQL( AUX_TRIUF ) + ;
            " AND TRIUF.AXCODIGO = JPUF.UFTRIUF" + ;
         " WHERE JPITPED.IDITPED = " + NumberSQL( midItPed )
      :Execute()
      cTexto += "REGRA DE TRIBUTAÇÃO:" + hb_eol()
      cTexto += hb_eol()
      cTexto += "Transação..........: "
      IF :Number( "PDTRANSA" ) == 0
         cTexto += MSG_DESCONHECIDO
      ELSE
         cTexto += Str( :Number( "PDTRANSA" ), 6 ) + " " + :String( "TRDESCRI" )
      ENDIF
      cTexto += hb_eol() + hb_eol()
      cTexto += "Tributação UF......: "
      IF :Number( "UFTRIUF" ) = 0
         cTexto += MSG_DESCONHECIDO
      ELSE
         cTexto += Str( :Number( "UFTRIUF" ), 6 ) + " " + :String( "TRIUFDESCRI" )
      ENDIF
      cTexto += hb_eol()
      cTexto += Space(10) + :String( "CDUF", 2 )
      cTexto += hb_eol() + hb_eol()
      cTexto += "Tributação Cadastro: "
      IF :Number( "CDTRICAD" ) == 0
         cTexto += MSG_DESCONHECIDO
      ELSE
         cTexto += Str( :Number( "CDTRICAD" ), 6 )+ " " + :String( "TRICADDESCRI" )
      ENDIF
      cTexto += hb_eol()
      cTexto += Space(10) + Str( :Number( "PDCADASTRO" ), 6 ) + " " + :String( "CDNOME" )
      cTexto += hb_eol() + hb_eol()
      cTexto += "Tributação Produto.: "
      IF :Number( "IETRIPRO" ) == 0
         cTexto += MSG_DESCONHECIDO
      ELSE
         cTexto += Str( :Number( "IETRIPRO" ), 6 ) + " " + :String( "TRIPRODESCRI" )
      ENDIF
      cTexto += hb_eol()
      cTexto += Space(10) + Str( :Number( "IPPRODUTO" ), 6 ) + " " + :String( "IEDESCRI" )
      cTexto += hb_eol() + hb_eol()
      cTexto += "Posição:" + cModulo + hb_eol()
      cTexto += hb_eol()
      cTexto += "Não foi encontrada uma regra de tributação para essa combinação de informações" + hb_eol()
      cTexto += "Pode ser alguma informação errada, ou falta cadastrar uma regra de tributação com esta combinação" + hb_eol()
      cTexto += "Se for na confirmação do pedido, pode faltar passar na digitação de produto pra atualizar pedido" + hb_eol()
      :CloseRecordset()
   ENDWITH
   MsgWarning( cTexto )

   RETURN NIL


Parece complicado, mas é o de sempre.

SELECT com a seleção dos campos que interessam

" JPPEDIDO.PDTRANSA, JPTRANSA.TRDESCRI," + ;
" JPPEDIDO.PDCADASTRO, JPCADASTRO.CDNOME, JPCADASTRO.CDTRICAD, TRICAD.AXDESCRI AS TRICADDESCRI," + ;
" JPCADASTRO.CDUF, JPUF.UFTRIUF, TRIUF.AXDESCRI AS TRIUFDESCRI," + ;
" JPITPED.IPPRODUTO, JPITEM.IEDESCRI, JPITEM.IETRIPRO, TRIPRO.AXDESCRI AS TRIPRODESCRI" + ;

se quiser comparar com DBF, seria só trocar o ponto pelo ->
por exemplo, jpcadastro.cdnome, equivale a jpcadastro->cdnome, seria o campo CDNOME que está na tabela JPCADASTRO

FROM com a indicação de onde vém

FROM JPITPED - vém dos produtos dos pedidos (itens do pedido)

LEFT JOIN é o relacionamento, pra "ensinar" o MySQL qual a ligação/relacionamento entre os arquivos

" LEFT JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPITPED.IPPEDIDO" + ;
vai usar o campo jpitped->ipPedido pra procurar nos pedidos o jppedido->idPedido com mesmo número

WHERE pra indicar o filtro

" WHERE JPITPED.IDITPED = " + NumberSQL( midItPed )
Vai procurar o lançamento de produto para um pedido, aonde a identificação desse lançamento é esse número

Em termos práticos: a partir do lançamento no pedido, vai pesquisar todas as informações relacionadas a ele. (as que interessam neste fonte)
E isso é feito usando um único comando SQL.
Então, o comando diz qual a informação, e como o servidor vai fazer pra pegar a informação.

O comando grande não significa que vai demorar mais.
Por último: o retorno, NESSE CASO, é apenas um registro com todo conteúdo indicado.
A partir daí, só usar o registro.

Nota:
Só lembrando que eu decidi fazer desse jeito, não significa que é a única forma de fazer isso.
E esses relacionamentos poderiam já ter sido definidos previamente na própria base de dados, e nem precisar colocar no comando.
É só uma das muitas possibilidades de se fazer isso.
Ainda estou saindo dos DBFs... vou fazendo do jeito que conheço...
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 05 Abr 2020 18:27

Este tive que apelar pra algum método de debug, porque estava falhando.
Agora resolvido.
Acho que o nome diz tudo.

METHOD CalculaImpostosProduto( mIdItPed ) CLASS SubPedidoClass

   LOCAL mipIcmBas, mipIcmAli, mipIcmRed, mipIcmVal, mipCfop, mipTribut, mipIpiCst, mipIpiEnq
   LOCAL mipFcpAli, mipFcpVal, mipIcmCst, mipPisCst, mipPisEnq, mipCofCst, mipCofEnq
   LOCAL mipIpiBas, mipIpiAli, mipIpiVal, mipImpAli, mipImpVal
   LOCAL mipIssBas, mipIssAli, mipIssVal
   LOCAL mipPisBas, mipPisAli, mipPisVal
   LOCAL mipCofBas, mipCofAli, mipCofVal
   LOCAL mipSubBas, mipSubIva, mipSubAli, mipSubRed, mipSubVal
   LOCAL mipValNot, mipIIBas, mipIIVal
   LOCAL mipIcsBas, mipIcsVal, mipIcsAli, mipIpiIcm
   LOCAL mipValPro, mipValFre, mipValSeg, mipValOut, nCont, mipLeis, mTmpLei, mipValExt
   LOCAL mipValDes, mipIIAli, mipDifAlii, mipDifAliu, mipDifAlif, mipDifVali, mipDifValf, mipDifBas, mipDifCal
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   IF mIdItPed == 0
      RETURN NIL
   ENDIF
   WITH OBJECT cnSQL
      :cSQL := ;
         " SELECT JPITPED.*," + ;
         " JPPEDIDO.PDTRANSA," + ;
         " JPCADASTRO.CDUFENT, JPCADASTRO.CDTRICAD," + ;
         " JPITEM.IETRIPRO," + ;
         " JPUF.UFTRIUF," + ;
         " JPTRANSA.TRREACAO," + ;
         " JPIBPT.IBNACALI," + ;
         " JPIBPT.IBIMPALI," + ;
         " JPIMPOSTO.*" + ;
         " FROM JPITPED" + ;
         " LEFT JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPITPED.IPPEDIDO" + ;
         " LEFT JOIN JPCADASTRO ON JPCADASTRO.IDCADASTRO = JPPEDIDO.PDCADASTRO" + ;
         " LEFT JOIN JPITEM ON JPITEM.IDPRODUTO = JPITPED.IPPRODUTO" + ;
         " LEFT JOIN JPUF ON JPUF.UFUF = JPCADASTRO.CDUFENT" + ;
         " LEFT JOIN JPTRANSA ON JPTRANSA.IDTRANSA = JPPEDIDO.PDTRANSA" + ;
         " LEFT JOIN JPIMPOSTO" + ;
         " ON  JPIMPOSTO.IMTRANSA = JPPEDIDO.PDTRANSA" + ;
         " AND JPIMPOSTO.IMTRIUF = JPUF.UFTRIUF" + ;
         " AND JPIMPOSTO.IMTRICAD = JPCADASTRO.CDTRICAD" + ;
         " AND JPIMPOSTO.IMTRIPRO = JPITEM.IETRIPRO" + ;
         " LEFT JOIN JPIBPT ON JPIBPT.IBCODIGO = JPITEM.IENCM" + ;
         " WHERE IDITPED = " + NumberSQL( midItPed )
      :Execute()
      MsgExclamation( ;
         "pdtransa: " + :String( "PDTRANSA" ) + hb_Eol() + ;
         "triuf: " + :String( "UFTRIUF" ) + hb_Eol() + ;
         "tricad:" + :String( "CDTRICAD" ) + hb_Eol() + ;
         "tripro:" + :String( "IETRIPRO" ) + hb_Eol() + ;
         "tribut:" + :String( "IDIMPOSTO" ) + hb_Eol() + ;
         "ok" )
...


É o uso do anterior, regra de tributação, e algo mais.

Por enquanto me limitando a converter de DBF pra MySQL.
Provavelmente não precisaria fazer um produto por vez, mas preciso alterar com cuidado, e por enquanto ainda tem a gravação em DBF compatível.
Depois.... quando não precisar mais do DBF, e apagar o DBF, aí vou repassar pra fazer mais coisas por vez.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 06 Abr 2020 15:34

Só a título de curiosidade:

   IF ! Encontra( jppedido->pdCadastro, "jpcadastro", "numlan" ) .AND. jppedido->pdConf != "S"
      MsgWarning( "INVÁLIDO! Cliente sem cadastro!" )
      RETURN .F.
   ENDIF
   IF ! jpcadastro->cdSitFaz $ " 1"
      MsgStop( "INVÁLIDO! Irregularidade do cadastro na SEFAZ!" )
      RETURN .F.
   ENDIF


Seria fácil alterar o primeiro IF pra ADO.
Mas o segundo IF, e provavelmente mais coisas no fonte, dependem do posicionamento do cliente, que é feito no primeiro IF.
É por isso que as alterações precisam ser feitas devagar.
Lógico... um SELECT detalhado no MySQL pode acabar atendendo o fonte inteiro.

Por isso, às vezes é melhor reorganizar o fonte primeiro, pra facilitar o que vém depois.
De repente até ajeitar o fonte para pegar tudo do dbf logo no começo, e depois só substituir para um comando SQL.
Cada caso é um caso.... cada fonte é um fonte, que pode ter solução igual ou diferente do que já foi feito antes.

Lembrando: no meu caso, tem tudo no DBF ou no MySQL, então estou eliminando a necessidade de pegar do DBF - mantendo posicionamento do DBF apenas aonde grava - enquanto precisa dele.
Devagar tá indo...
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 06 Abr 2020 16:42

Também a título de curiosidade....

Tive que trocar a versão no cliente, durante as alterações....
Ok, sem problemas, apenas confirmei se era melhor cancelar o que estava pela metade, ou terminar e instalar.

E surgiu um problema: o produto estava no MYSQL mas NÃO no DBF.

Cadastrei o código no DBF, entrei na alteração do cadastro, e fui até o final.
Ao terminar, atualizou também esse código equivalente no DBF.
É... se não fosse o DBF não teria problema kkkk
Mas é lógico, NÃO é problema em usar DBF, é porque cometi algum erro, e não gravou no DBF.

Esse problema aconteceu com versão anterior, que estava em uso.
Até revisei na versão atual, mas parece tudo ok.
Por enquanto é aguardar se vai acontecer de novo.

Pois é... trata-se de uma alteração geral, alterar devagar e com cuidado não significa que não acontecem problemas...
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 20 Abr 2020 18:37

NÃO parei com as alterações.
É que agora é tudo com cuidado.
Pedidos, financeiro, boletos, bancos, faturamento, etc. essas coisas.
Usando ao máximo números nos campos chave, e deixando de usar DBF como referência principal.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 27 Abr 2020 19:30

Mais um relatório simples.
É só um total por fornecedor, do contas a pagar.
Vou começar a alterar ainda, aqui é o fonte atual usando DBF, que está rodando no cliente (se é que algum usa).

/*
PFINANRELMAIFOR - RELATORIO DE MAIORES FORNECEDORES
1997.04 José Quintas
*/

#include "inkey.ch"

MEMVAR m_DeAte, m_Datai, m_Dataf, m_Ordem, m_DbfTmp, m_NtxTmp, m_TxtOrdem, m_TxtDeAte, nOpcPrinterType

PROCEDURE pFinanRelMaiFor

   LOCAL  nOpcGeral := 1, m_TxtMenu, m_Temp, mDefault, m_Conf := 2, m_Stru

   PRIVATE m_txtordem := { "Valor (Decresc)", "Fornecedor" }
   PRIVATE m_deate    := 1
   PRIVATE m_datai    := Ctod( "" )
   PRIVATE m_dataf    := Ctod( "" )
   PRIVATE m_txtdeate := { "Todas", "Intervalo" }

   nOpcPrinterType := AppPrinterType()

   IF ! AbreArquivos( "jpcadastro", "jpconfi", "jpempresa", "jpfinan", "jpsenha", "jptabel" )
      RETURN
   ENDIF
   SELECT jpfinan

   m_DbfTmp := MyTempFile( "DBF" )
   m_NtxTmp := MyTempFile( "CDX" )

   m_Stru := { ;
      { "FORNEC",  "C",  6, 0 }, ;
      { "NOME",    "C", 30, 0 }, ;
      { "XXCNPJ",  "C", 18, 0 }, ;
      { "VALOR",   "N", 17, 2 } }
   SELECT 0
   dbCreate( m_DbfTmp, m_Stru )
   USE (m_DbfTmp) EXCLUSIVE NEW ALIAS temp

   mDefault  := LeCnfRel()
   m_ordem   := iif( mDefault[ 1 ] > 2, 1, mDefault[ 1 ] )
   m_txtmenu := Array(5)

   WOpen( 5, 4, 7 + Len( m_txtmenu ), 45, "Opções disponíveis" )

   DO WHILE .T.

      m_txtmenu := { ;
         TxtImprime(), ;
         TxtSalva(), ;
         "Ordem.....: " + m_txtordem[ m_ordem ], ;
         "Datas.....: " + iif( m_DeAte == 1, m_txtdeate[ 1 ], ;
         Dtoc( m_datai ) + " a " + Dtoc( m_dataf ) ), ;
         "Saída.....: " + TxtSaida()[ nOpcPrinterType ] }

      FazAchoice( 7, 5, 6 + Len( m_txtmenu ), 44, m_txtmenu, @nOpcGeral )

      m_Temp := 1
      DO CASE
      CASE LastKey() == K_ESC
         EXIT

      CASE nOpcGeral == m_Temp++
         IF ConfirmaImpressao()
            imprime()
         ENDIF

      CASE nOpcGeral == m_Temp++
         m_conf = 2
         WAchoice( nOpcGeral+6, 25, TxtConf(), @m_conf, TxtSalva() )
         IF m_conf == 1 .AND. LastKey() != K_ESC
            GravaCnfRel( { m_Ordem } )
         ENDIF

      CASE nOpcGeral == m_Temp++
         WAchoice( nOpcGeral + 6, 25, m_txtordem, @m_ordem, "Ordem de Impressão" )

      CASE nOpcGeral == m_Temp++
         DataIntervalo( nOpcGeral + 6, 25, @m_DeAte, @m_Datai, @m_Dataf )

      CASE nOpcGeral == m_Temp
         WAchoice( nOpcGeral + 6, 25, TxtSaida(), @nOpcPrinterType, "Saída" )
         AppPrinterType( nOpcPrinterType )

      ENDCASE
   ENDDO
   WClose()
   CLOSE DATABASES
   fErase(m_DbfTmp)
   fErase(m_NtxTmp)

   RETURN

STATIC FUNCTION imprime()

   LOCAL oPDF, nKey, m_Soma, m_Total

   SELECT Temp
   ZAP
   INDEX ON temp->Fornec TO ( m_NtxTmp )

   SELECT jpfinan
   GOTO TOP
   DO WHILE ! Eof()
      GrafProc()
      IF jpfinan->fiTipLan != "2"
         SKIP
         LOOP
      ENDIF
      IF m_DeAte==2
         IF jpfinan->fiDatEmi < m_Datai .OR. jpfinan->fiDatEmi > m_Dataf
            SKIP
            LOOP
         ENDIF
      ENDIF
      encontra( jpfinan->fiCadastro, "jpcadastro", "numlan" )
      IF ! encontra( jpfinan->fiCadastro, "temp" )
         SELECT temp
         RecAppend()
         REPLACE ;
            temp->Fornec WITH jpfinan->fiCadastro, ;
            Temp->xxCnpj WITH jpcadastro->cdCnpj, ;
            Temp->Nome WITH jpcadastro->cdNome
         RecUnlock()
      ENDIF
      SELECT temp
      RecLock()
      REPLACE Temp->Valor WITH temp->Valor + jpfinan->fiValor
      RecUnlock()
      SELECT jpfinan
      SKIP
   ENDDO

   oPDF := PDFClass():New()
   oPDF:SetType( nOpcPrinterType )
   oPDF:Begin()

   nKey = 0

   oPDF:acHeader := { "", "", "" }
   oPDF:acHeader[ 1 ] := "CONTAS A PAGAR"
   oPDF:acHeader[ 2 ] := "MAIORES FORNECEDORES - Ordem: " + m_txtordem[ m_ordem ]
   IF m_deate == 2
      oPDF:acHeader[ 2 ] += " - Data: " + Dtoc( m_datai ) + " a " + Dtoc( m_dataf )
   ENDIF
   oPDF:acHeader[ 3 ] := "-----------NOME DO FORNECEDOR-----------  -------C.G.C.-------  -----FATURAMENTO----  %TOTAL"

   SELECT Temp
   IF m_Ordem == 1
      INDEX ON -temp->valor TO ( m_NtxTmp )
   ELSE
      INDEX ON temp->nome TO ( m_NtxTmp )
   ENDIF
   SUM temp->Valor TO m_Total
   m_Soma := 0
   GOTO TOP
   DO WHILE nKey != K_ESC .AND. ! Eof()
      grafproc()
      nKey = Inkey()
      oPDF:MaxRowTest()
      oPDF:DrawText( oPDF:nRow, 0, Temp->Nome )
      oPDF:DrawText( oPDF:nRow, 42, Temp->xxCnpj )
      oPDF:DrawText( oPDF:nRow, 64, Temp->Valor, PicVal(14,2) )
      oPDF:DrawText( oPDF:nRow, 86, ( Temp->Valor * 100 / m_Total ), "@E 999.99" )
      m_Soma += temp->Valor
      oPDF:nRow  += 1
      SKIP
   ENDDO
   IF oPDF:nPageNumber != 0
      oPDF:MaxRowTest()
      oPDF:DrawText( oPDF:nRow, 0, "TOTAL IMPRESSO....:" )
      oPDF:DrawText( oPDF:nRow, 64, m_Soma, PicVal(14,2) )
      oPDF:DrawText( oPDF:nRow, 86, ( m_Soma * 100 / m_Total ), "@E 999.99" )
      oPDF:nRow += 1
      oPDF:MaxRowTest()
   ENDIF
   oPDF:End()

   RETURN NIL
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 27 Abr 2020 19:48

pronto.

/*
PFINANRELMAIFOR - RELATORIO DE MAIORES FORNECEDORES
1997.04 José Quintas
*/

#include "inkey.ch"

MEMVAR nOpcData, m_Datai, m_Dataf, nOpcOrdem, acTxtOrdem, acTxtData, nOpcPrinterType

PROCEDURE pFinanRelMaiFor

   LOCAL  nOpcGeral := 1, acTxtGeral, m_Temp, mDefault, m_Conf := 2

   PRIVATE acTxtOrdem := { "Valor (Decresc)", "Fornecedor" }
   PRIVATE nOpcData    := 1
   PRIVATE m_datai    := Ctod( "" )
   PRIVATE m_dataf    := Ctod( "" )
   PRIVATE acTxtData := { "Todas", "Intervalo" }

   nOpcPrinterType := AppPrinterType()

   IF ! AbreArquivos( "jpcadastro", "jpconfi", "jpempresa", "jpfinan", "jpsenha", "jptabel" )
      RETURN
   ENDIF
   SELECT jpfinan

   mDefault  := LeCnfRel()
   nOpcOrdem   := iif( mDefault[ 1 ] > 2, 1, mDefault[ 1 ] )
   acTxtGeral := Array(5)

   WOpen( 5, 4, 7 + Len( acTxtGeral ), 45, "Opções disponíveis" )

   DO WHILE .T.

      acTxtGeral := { ;
         TxtImprime(), ;
         TxtSalva(), ;
         "Ordem.....: " + acTxtOrdem[ nOpcOrdem ], ;
         "Datas.....: " + iif( nOpcData == 1, acTxtData[ 1 ], ;
         Dtoc( m_datai ) + " a " + Dtoc( m_dataf ) ), ;
         "Saída.....: " + TxtSaida()[ nOpcPrinterType ] }

      FazAchoice( 7, 5, 6 + Len( acTxtGeral ), 44, acTxtGeral, @nOpcGeral )

      m_Temp := 1
      DO CASE
      CASE LastKey() == K_ESC
         EXIT

      CASE nOpcGeral == m_Temp++
         IF ConfirmaImpressao()
            imprime()
         ENDIF

      CASE nOpcGeral == m_Temp++
         m_conf = 2
         WAchoice( nOpcGeral+6, 25, TxtConf(), @m_conf, TxtSalva() )
         IF m_conf == 1 .AND. LastKey() != K_ESC
            GravaCnfRel( { nOpcOrdem } )
         ENDIF

      CASE nOpcGeral == m_Temp++
         WAchoice( nOpcGeral + 6, 25, acTxtOrdem, @nOpcOrdem, "Ordem de Impressão" )

      CASE nOpcGeral == m_Temp++
         DataIntervalo( nOpcGeral + 6, 25, @nOpcData, @m_Datai, @m_Dataf )

      CASE nOpcGeral == m_Temp
         WAchoice( nOpcGeral + 6, 25, TxtSaida(), @nOpcPrinterType, "Saída" )
         AppPrinterType( nOpcPrinterType )

      ENDCASE
   ENDDO
   WClose()
   CLOSE DATABASES

   RETURN

STATIC FUNCTION imprime()

   LOCAL oPDF, nKey, m_Total
   LOCAL cnSQL := ADOClass():New( AppConexao() )

   oPDF := PDFClass():New()
   oPDF:SetType( nOpcPrinterType )
   oPDF:Begin()
   nKey = 0
   oPDF:acHeader := { "", "", "" }
   oPDF:acHeader[ 1 ] := "CONTAS A PAGAR"
   oPDF:acHeader[ 2 ] := "MAIORES FORNECEDORES - Ordem: " + acTxtOrdem[ nOpcOrdem ]
   IF nOpcData == 2
      oPDF:acHeader[ 2 ] += " - Data: " + Dtoc( m_datai ) + " a " + Dtoc( m_dataf )
   ENDIF
   oPDF:acHeader[ 3 ] := "-----------NOME DO FORNECEDOR-----------  -------C.G.C.-------  -----FATURAMENTO----  %TOTAL"
   WITH OBJECT cnSQL
      :cSQL := "SELECT SUM( FIVALOR ) AS TOTAL, FICADASTRO," + ;
         " JPCADASTRO.CDNOME, JPCADASTRO.CDCNPJ" + ;
         " FROM JPFINAN" + ;
         " LEFT JOIN JPCADASTRO ON JPCADASTRO.IDCADASTRO = JPFINAN.FICADASTRO" + ;
         " WHERE FITIPLAN = '2'"
      IF nOpcData == 2
         :cSQL += " AND FIDATEMI BETWEEN CAST( " + DateSQL( m_Datai ) + " AS DATE )" + ;
            " AND CAST( " + DateSQL( m_Dataf ) + " AS DATE )"
      ENDIF
      :cSQL += " GROUP BY FICADASTRO"
      IF nOpcOrdem == 1
         :cSQL += " ORDER BY TOTAL DESC"
      ELSE
         :cSQL += " ORDER BY CDNOME"
      ENDIF
      :Execute()
      m_Total := 0
      DO WHILE ! :Eof()
         m_Total += :Number( "TOTAL" )
         :MoveNext()
      ENDDO
      :MoveFirst()
      DO WHILE nKey != K_ESC .AND. ! :Eof()
         grafproc()
         nKey = Inkey()
         oPDF:MaxRowTest()
         oPDF:DrawText( oPDF:nRow, 0, :String( "CDNOME", 30 ) )
         oPDF:DrawText( oPDF:nRow, 42, :String( "CDCNPJ", 18 ) )
         oPDF:DrawText( oPDF:nRow, 64, :Number( "TOTAL" ), PicVal(14,2) )
         oPDF:DrawText( oPDF:nRow, 86, ( :Number( "TOTAL" ) * 100 / m_Total ), "@E 999.99" )
         oPDF:nRow  += 1
         :MoveNext()
      ENDDO
      IF oPDF:nPageNumber != 0
         oPDF:MaxRowTest()
         oPDF:DrawText( oPDF:nRow, 0, "TOTAL IMPRESSO....:" )
         oPDF:DrawText( oPDF:nRow, 64, m_Total, PicVal(14,2) )
         oPDF:DrawText( oPDF:nRow, 86, 100, "@E 999.99" )
         oPDF:nRow += 1
         oPDF:MaxRowTest()
      ENDIF
      :CloseRecordset()
   ENDWITH
   oPDF:End()

   RETURN NIL


18 minutos, incluindo dar uma geral no fonte até nos nomes de variáveis.
Acho que tá bom pra um simples.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 06 Mai 2020 16:01

Uma alteração mais simples, lembrando que é usando minha classe pra ADO.
Na tela do financeiro, mostrando todos os lançamentos referentes ao mesmo pedido do lançamento atual.

   IF mIdPedido != 0
      Encontra( StrZero( mIdPedido, 6 ), "jppedido", "pedido" )
      @ mRow+2, 0 SAY "Valor do pedido:" + Transform( jppedido->pdValNot, PicVal(14,2) )
      @ mRow+3, 0 SAY ""
      mRecNo  := RecNo()
      OrdSetFocus( "pedido" )
      SEEK StrZero( mIdPedido, 6 )
      mCol := 1
      DO WHILE Val( jpfinan->fiPedido ) == mIdPedido .AND. Row() < MaxRow()-3 .AND. ! Eof()
         @ Row(), mCol SAY "Lanc." + jpfinan->idFinan + " " + Dtoc( jpfinan->fiDatVen ) + Transform( jpfinan->fiValor, PicVal(14,2) ) + iif( Empty( jpfinan->fiDatPag ), "AB", "PG" )
         IF mCol == 1
            mCol := 55
         ELSE
            mCol := 1
            @ Row()+1, 0 SAY ""
         ENDIF
         SKIP
      ENDDO
      OrdSetFocus( "jpfinan1" )
      GOTO mRecNo
   ENDIF


agora alterado

   IF mIdPedido != 0
      WITH OBJECT cnSQL
         :cSQL := "SELECT IDPEDIDO, PDVALNOT, JPFINAN.IDFINAN, JPFINAN.FIDATVEN," + ;
            " JPFINAN.FIDATPAG, JPFINAN.FIVALOR" + ;
            " FROM JPPEDIDO" + ;
            " LEFT JOIN JPFINAN ON JPFINAN.FIPEDIDO = JPPEDIDO.IDPEDIDO" + ;
            " WHERE IDPEDIDO = " + NumberSQL( mIdPedido )
         :Execute()
         @ mRow+2, 0 SAY "Valor do pedido:" + Transform( :Number( "PDVALNOT" ), PicVal(14,2) )
         @ mRow+3, 0 SAY ""
         mCol := 1
         DO WHILE Row() < MaxRow()-3 .AND. ! :Eof()
            @ Row(), mCol SAY "Lanc." + Str( :Number( "IDFINAN" ), 6 ) + " " + ;
               Dtoc( :Date( "FIDATVEN" ) ) + Transform( :Number( "FIVALOR" ), PicVal(14,2) ) + ;
               iif( Empty( :Date( "FIDATPAG" ) ), "AB", "PG" )
            IF mCol == 1
               mCol := 55
            ELSE
               mCol := 1
               @ Row()+1, 0 SAY ""
            ENDIF
            :MoveNext()
         ENDDO
         :CloseRecordset()
      ENDWITH
   ENDIF


Até que o fonte não alterou muito a lógica, mas agora sem DBF.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 06 Mai 2020 16:26

Aproveitando pra mostrar a mudança em variáveis.
Ficou muito legal.

   mIdFinanceiro := ::axKeyValue[ 1 ]
   Encontra( StrZero( mIdFinanceiro, 6 ), "jpfinan", "numlan" )
   WITH OBJECT cnSQL
      :cSQL := "SELECT * FROM JPFINAN WHERE IDFINAN = " + NumberSQL( mIdFinanceiro )
      :Execute()
      mfiDatPag   := :Date( "FIDATPAG" )
      mVlBaixa    := :Number( "FIVALOR" )
      mfiNumDoc   := :String( "FINUMDOC", 9 )
      mfiParcela  := :String( "FIPARCELA", 3 )
      mfiTipDoc   := :String( "FITIPDOC", 6 )
      mIdCadastro := :Number( "FICADASTRO" )
      mfiDatEmi   := :Date( "FIDATEMI" )
      mfiDatVen   := :Date( "FIDATVEN" )
      mfiValor    := :Number( "FIVALOR" )
      mIdPortador := :Number( "FIPORTADOR" )
      mfiDatCan   := :Date( "FIDATCAN" )
      mIdCCusto   := :Number( "FICCUSTO" )
      mIdVendedor := :Number( "FIVENDEDOR" )
      mfiObs      := :String( "FIOBS", 100 )
      mfiNumBan   := :Number( "FINUMBAN" )
      mIdPedido   := :Number( "FIPEDIDO" )
      mIdOperacao := :Number( "FIOPERACAO" )
   ENDWITH


No arquivo/tabela do financeiro, é tudo começando com FI.
Pra variáveis acrescente o prefixo m, no caso desse financeiro mFI.
Mas....
Nas mudanças durante a conversão, alterei tudo que é campo como o campo chave de cada tabela.
Isso facilitou muito no aplicativo em geral.

FICADASTRO, FIPORTADOR, FICCUSTO, FIVENDEDOR, FIPEDIDO, FIOPERACAO
esses agora mudaram para
mIdCadastro, mIdPortador, mIdCCusto, mIdVendedor, mIdPedido, mIdOperacao

Isso no aplicativo, durante o uso.
Nas tabelas seguem como eram antes, exceto terem mudado de caractere para numérico NO MYSQL.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 07 Mai 2020 01:40

Tava convertendo esta parte:

   Encontra( StrZero( mIdFinanceiro, 6 ), "jpfinan", "numlan" )
   IF ! Empty( jpfinan->fiDatPag ) .OR. ! Empty( jpfinan->fiDatCan )
      MsgWarning( "Documento já possui baixa" )
      RETURN NIL
   ENDIF


Aí pensei... porque não...

   IF ADORecCount( "JPFINAN", "IDFINAN = " + NumberSQL( midFinanceiro ) + ;
      " AND FIDATPAG IS NULL AND FIDATCAN IS NULL" ) == 0
      MsgWarning( "Documento já possui baixa" )
      RETURN NIL
   ENDIF


Não vou ter o registro atual no MySQL, mas pra não encher de fonte, simplifiquei apenas testando se existe o lançamento sem baixa.
Convém lembrar que na tela vai estar o lançamento, então ele existe.
É uma solução interessante, pra não buscar o lançamento só pra pegar esses dois campos e testar.

Isso não é uma coisa que uma conversão automática, ou RDD faria pra mim.
Devagarzinho, sem pressa, o uso do DBF vai sumindo...

E importante:
A criação da função ADORecCount() foi justamente pra economizar fonte.
São essas "coisinhas" que facilitam, e não o uso de um ou outro tipo de conexão.

Lembram: somos programadores, precisamos considerar que somos nosso cliente e trabalhar mais pra nós... a fim de trabalharmos menos.... rs

E .... fazendo devagar dá pra pensar mais e trabalhar menos...
Se estivesse com pressa de converter tudo, talvez não tivesse pensado nisso.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 07 Mai 2020 11:44

Mais outra função que criei como quebra-galho, e é interessante.
É uma função simples, pra retornar um campo do SQL.
Aqui um exemplo de uso, antes e depois:

         DO CASE
         CASE mfiTipLan == "D"
            OrdSetFocus("jpfinan2") // fiTipLan + fiNumDoc
         CASE mfiTipLan == "B"
            OrdSetFocus("numbanco") // fiNumBan
         OTHERWISE
            OrdSetFocus("numlan") // idFinan
         ENDCASE
         @ 5, 0 SAY "Num. Docto...........:" GET mfiNumDoc PICTURE "@K 999999999" VALID FillZeros( @mfiNumDoc ) WHEN mfiTipLan == "D"
         @ Row(), 35 SAY "Parcela.." GET mfiParcela PICTURE "@K 999" WHEN mfiTipLan == "D" VALID FillZeros( @mfiParcela )
         @ 6, 0 SAY "Num.Bancário.........:" GET mfiNumBan PICTURE "@K 999999" WHEN mfiTipLan == "B"
         @ 7, 0 SAY "Num.Lançamento.......:" GET midFinanceiro   PICTURE "@K 999999" VALID OkNumLanFin( @midFinanceiro ) WHEN ! mfiTipLan $ "DB"
         @ 8, 0 SAY "Valor Original.......:" GET mfiValor    PICTURE PicVal(14,2)
         @ 9, 0 SAY "Juros(+) Descto(-)...:" GET mfiJurDes   PICTURE PicVal(14,2)
         Mensagem( "Digite campos, F9 Pesquisa ESC Sai" )
         READ
         Mensagem()
         IF LastKey() == K_ESC
            EXIT
         ENDIF
         DO CASE
         CASE mfiTipLan == "D"
            SEEK "1" + mfiNumDoc + mfiParcela
            nRecFound := RecNo()
            DO WHILE jpfinan->fiTipLan == "1" .AND. jpfinan->fiNumDoc == mfiNumDoc .AND. jpfinan->fiParcela == mfiParcela .AND. ! Eof()
               nRecFound := RecNo()
               SKIP
            ENDDO
            GOTO (nRecFound)
         CASE mfiTipLan == "B"
            SEEK StrZero( mfiNumBan, 6 )
         OTHERWISE
            SEEK StrZero( midFinanceiro, 6 )
         ENDCASE
         IF Eof()
            MsgWarning( "Documento não cadastrado!" )
            LOOP
         ENDIF
         Encontra( jpfinan->fiCadastro, "jpcadastro", "numlan" )


Primeiro pensar...
o objetivo é encontrar um lançamento no financeiro, podendo ser 3 critérios diferentes.
O que identifica a pesquisa pode variar, mas o resultado é um lançamento, então.... IdFinanceiro

         @ 5, 0 SAY "Num. Docto...........:" GET mfiNumDoc PICTURE "@K 999999999" VALID FillZeros( @mfiNumDoc ) WHEN mfiTipLan == "D"
         @ Row(), 35 SAY "Parcela.." GET mfiParcela PICTURE "@K 999" WHEN mfiTipLan == "D" VALID FillZeros( @mfiParcela )
         @ 6, 0 SAY "Num.Bancário.........:" GET mfiNumBan PICTURE "@K 999999" WHEN mfiTipLan == "B"
         @ 7, 0 SAY "Num.Lançamento.......:" GET midFinanceiro   PICTURE "@K 999999" VALID OkNumLanFin( @midFinanceiro ) WHEN ! mfiTipLan $ "DB"
         @ 8, 0 SAY "Valor Original.......:" GET mfiValor    PICTURE PicVal(14,2)
         @ 9, 0 SAY "Juros(+) Descto(-)...:" GET mfiJurDes   PICTURE PicVal(14,2)
         Mensagem( "Digite campos, F9 Pesquisa ESC Sai" )
         READ
         Mensagem()
         IF LastKey() == K_ESC
            EXIT
         ENDIF
         DO CASE
         CASE mfiTipLan == "D"
            nIdFinanceiro := ADOField( "IDFINAN", "N", "JPFINAN", "FITIPLAN = '1'" + ;
               " AND FINUMDOC = " + StringSql( mfiNumDoc ) + " AND FIPARCELA = " + StringSql( mfiParcela ) + ;
               " ORDER BY IDFINAN DESC" )
         CASE mfiTipLan == "B"
            mIdFinanceiro := ADOField( "IDFINAN", "N", "JPFINAN", "FINUMBAN = " + StringSQL( mfiNumBan ) )
         OTHERWISE
            midFinanceiro := ADOField( "IDFINAN", "N", "JPFINAN", "IDFINAN = " + NumberSQL( mIdFinanceiro ) )
         ENDCASE
         IF mIdFinanceiro == 0
            MsgWarning( "Documento não cadastrado!" )
            LOOP
         ENDIF
         Encontra( StrZero( mIdFinanceiro, 6 ), "jpfinan", "numlan" )
         Encontra( jpfinan->fiCadastro, "jpcadastro", "numlan" )


Relativamente simples: seja qual for a pesquisa, retorna a ID do lançamento.
E cada pesquisa usando o que entra na pesquisa.

A função usa o nome do campo, "N" pra identificar que é retorno numérico, a tabela, e o comando SQL.
A identificação de tipo é porque no SQL poderia conter um NULL no campo, então o tipo garante que o retorno vai ser numérico, porque vai converter NULL pra número 0.

A função só precisa combinar os parâmetros.
Numa forma resumida:

ADOField( cCampo, cTipo, cTabela, cCriterio )

"SELECT " + cCampo + " FROM " + cTabela + " WHERE " + cCriterio

É até pouco pra usar função mas... considerando fazer consulta, testar resultado, e até poder usar em IF, a torna interessante.
Comparando com DBF, é como abrir arquivo, posicionar com SEEK, e retornar o campo.

Porque entrou esta parte?
Encontra( StrZero( mIdFinanceiro, 6 ), "jpfinan", "numlan" )

Não dependo mais do DBF pra ESSA pesquisa, mas falta alterar o resto do fonte.
Tudo bem, por enquanto o que importa é reduzir o uso de DBF mas que o fonte continue funcionando.
Melhor alterar aos poucos, pra evitar perder o controle.
Essa parte garante que não vai faltar nada pro resto do fonte.

De quebra, eu poderia acabar com outros índices, e manter somente o índice por ID no DBF !!!
Apenas uma possibilidade, com certeza continuar caminhando pra eliminar o dbf de vez.
A gravação dupla está sendo legal nisso: no mesmo fonte, tanto faz se pego do MySQL ou DBF.
Basta ir eliminando a necessidade do DBF e pronto, depois só apagar tudo do DBF.
José M. C. Quintas
Harbour 3.4, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, hbnetio, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"
Avatar de usuário

JoséQuintas
Colaborador

Colaborador
 
Mensagens: 14318
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 13 vezes
Mens.Curtidas: 859 vezes

Anterior Próximo



Retornar para Contribuições, Dicas e Tutoriais

Quem está online

Usuários vendo este fórum: Google [Bot], Semrush [Bot] e 3 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro