Página 10 de 35

Meu modo de trabalho

Enviado: 25 Out 2019 23:07
por JoséQuintas
O processo inteiro de atualização.
Seria o mesmo que fazemos, se fôssemos fazer manual.

Primeiro um backup, afinal vamos mexer em DBFs...
atual1.png
Depois a atualização de estruturas.
Ela acaba acontecendo DUAS vezes: ANTES e DEPOIS das ATUALIZAÇÕES
atual2.png
Com estruturas ok, toda parte de conversão e ajustes de DBF
atual3.png
Após as conversões/atualizações, novamente a atualização de estrutura.
Porque: Porque posso estar adicionando um campo que vai conter o conteúdo de outro campo que vai ser eliminado.
Então... adiciono o novo campo ANTES de todas conversões, e removo o campo velho no final.

E no fim de tudo, uma reindexação de tudo que precisar ser reindexado.
As mudanças podem, e desta vez é certeza, necessitar criar novos índices.
A atualização de estrutura já apaga índices anteriores, pra evitar problemas.

E pronto.
Agora está pronto pra uso.

Agora instalar em TODOS os clientes antes de mexer em mais alguma coisa.
Na verdade era pra ter feito isso antes de todas as mexidas.... mas foi difícil resistir...

O ruim de muita atualização junta, é que fica demorada.
Por ser demorada.... corre muito o risco de um usuário entrar no aplicativo por outro terminal durante a atualização.
Isso pode ser problema....

Mas daqui pra frente... todas as atualizações vão ser assim: demoradas e perigosas se outro usuário entrar no aplicativo.

Vém mais mudanças de estrutura por aí... e a transferência pra MySQL.

Meu modo de trabalho

Enviado: 28 Out 2019 14:15
por JoséQuintas
Nem eu acredito no que eu fiz....

Bom...
É a preparação pra deixar DBF pronto pra MySQL...

Arquivo com 8 caracteres???? Porque??? não é mais DOS há muito tempo...

CTDIARI.DBF virou JPCONTABIL.DBF
JPCADAS.DBF virou JPCADASTRO.DBF e JPTRANSP.DBF (foi dividido)
JPCOMISS.DBF virou JPCOMISSAO.DBF
JPEMPRE.DBF virou JPEMPRESA.DBF
JPESTOQ.DBF virou JPESTOQUE.DBF
JPIMPOS.DBF virou JPIMPOSTO.DBF
JPLFISC.DBF virou JPFISCAL.DBF
JPNOTA.DBF virou JPNOTFIS.DBF
JPPEDI.DBF virou JPPEDIDO.DBF
JPVEICUL.DBF virou JPVEICULO.DBF
JPVENDED.DBF virou JPVENDEDOR.DBF

E campos chave:

JPCADASTRO, chave cdCodigo, virou IdCadas e depois idCadastro
JPTRANSP, chave cdCodigo, virou tpCodigo, depois idTransp
JPFINAN, chave fiNumLan, virou idFinan
JPITEM, chave era ieItem, virou idItem
JPFISCAL, chave era lfNumLan, virou idFiscal
JPNOTFIS, chave era nfNumLan virou idNotFis
JPFORPAG, chave era fpNumLan virou idForPag
JPCIDADE, chave era ciNumLan virou idCidade
JPCLISTA, chave era csNumLan virou IdCliSta
JPTRANSA, chave era trTransa virou idTransa
JPVEICULO, chave era veNumLan virou idVeiculo
JPVENDEDOR, chave era vdVendedor virou idVendedor
JPMOTORI, chave era moMotori virou idMotori
JPESTOQUE, chave era esNumLan virou idEstoque
JPPEDIDO, chave era pdPedido virou idPedido
JPIMPOSTO, chave era imNumLan virou idImposto
JPEMPRESA, chave era emNumLan virou IdEmpresa

E já estava em MySQL
Em JPREGUSO, chave era ruId virou IdRegUso

São alterações relativamente simples, mas alteram arquivos, estruturas, e todo fonte que faz uso dos arquivos e campos.
Ainda fiquei na dúvida, porque os campos dos arquivos começam com duas letras indicando o arquivo, e agora a chave ficou diferente do resto.
A minha chave dos arquivos passou a ser ID seguida do nome do arquivo.

Era isso que tinha misturado na migração pra MySQL.
Desta vez fui fazendo uma coisa de cada vez, do ponto de vista de programação/alteração de fontes.
Nos clientes, ao instalar, vai tudo de uma vez.

Por enquanto instalei em 5 clientes, e tudo ok.
instalar = clicar na opção de atualizar aplicativo

Daqui pra frente, só atualizações sem volta... rumo ao MySQL e pronto.

Nota: durante o texto, outro cliente fez atualização.

Meu modo de trabalho

Enviado: 31 Out 2019 20:06
por JoséQuintas
Hoje liguei pra um cliente que tem movimentação pesada, pra ele atualizar o aplicativo...
Mas ele já tinha atualizado kkkk

Só ficou um sem atualizar, mas é praticamente monousuário, então nem vou me preocupar.
Quando atualizar... vai direto pra próxima.

A hora do MySQL chegou.

Meu modo de trabalho

Enviado: 05 Nov 2019 10:50
por JoséQuintas
Hoje começou a gravação dupla.
Como era de se esperar.... muita correção, mas tá indo.

Lembram da minha errorsys exagerada?
Pois é... tá ajudando....

Código: Selecionar todos

OK OPTION DEFAULT: Error DBFCDX/1021  Data width error: NFPESLIQ  
No DBF pode até aceitar campo estourado, mas no MySQL não.

Só não me perguntem porque o usuário anda emitindo nota com mais de 99 toneladas....
Talvez porque o aplicativo permite... kkkkk

Meu modo de trabalho

Enviado: 05 Nov 2019 11:17
por JoséQuintas
A título de curiosidade:
Joguei todo meu controle de numeração no lixo.

Código: Selecionar todos

   ...
   :QueryAdd( "NFFILIAL", mObs2Filial )
   :QueryAdd( "NFINFINC", LogInfo() )

   midNotFis := StrZero( :QueryExecuteInsert( "JPNOTFIS" ), 6 )

   :QueryAdd( "IDNOTFIS", midNotFis )
   :DBFQueryExecuteInsert( "JPNOTFIS" )
Ao incluir no MySQL, o próprio MySQL numera.
Então... adiciono a chave retornada antes de gravar no DBF.

Como a lista de campos e valores é igual para os dois, certeza de conteúdo igual.

Agora é continuar acompanhando, pra ver se errei em algum lugar.

Próxima etapa: se tá gravado no MySQL, pra que DBF?

Meu modo de trabalho

Enviado: 11 Nov 2019 09:36
por JoséQuintas
Aqui convém destacar uma coisa, TBROWSE:

Além de mostrar meu tbrowse em DBF, mostra meu início do MySQL, convertendo o resultado em DBF.

Código: Selecionar todos

METHOD GridSelection() CLASS ClassiClass

   LOCAL nSelect := Select(), oTBrowse
   LOCAL cnMySql := ADOClass():New( AppConexao() )
   LOCAL cTmpFile, cCdxFile

   cnMySql:cSql := "SELECT DESCRICAO, CLASSI, TIPO, TIPO1, GRUPO, GERAL, NIVEL FROM CLASSI ORDER BY CLASSI"
   cTmpFile     := cnMySql:SqlToDbf()
   SELECT 0
   USE ( cTmpFile ) ALIAS temp
   cCdxFile := MyTempFile( "CDX" )
   INDEX ON temp->classi TO ( cCdxFile )
   GOTO TOP

   oTBrowse := { ;
      { "Descricao",   {|| temp->Descricao } }, ;
      { "Classi",      {|| temp->Classi } }, ;
      { "Tipo",        {|| temp->Tipo } }, ;
      { "Tipo1",       {|| temp->Tipo1 } }, ;
      { "Grupo",       {|| temp->Grupo } }, ;
      { "Geral",       {|| temp->Geral } }, ;
      { "Nivel",       {|| temp->Nivel } } }
   FazBrowse( oTBrowse )
   IF LastKey() != K_ESC .AND. ! Eof()
      KEYBOARD temp->Classi + Chr( K_ENTER )
   ENDIF
   USE
   fErase( cTmpFile )
   fErase( cCdxFile )
   SELECT ( nSelect )

   RETURN NIL
E o tbrowse agora direto em ADO:

Código: Selecionar todos

METHOD GridSelection() CLASS JPAGENDAClass

   LOCAL oTBrowse, cnMySql := ADOClass():new( AppConexao() )

   WITH OBJECT cnMySql
      :cSql := "SELECT AGNOME, AGTELEFONE, AGTELEF2, AGTELEF3, AGCIDADE, AGUF, IDAGENDA FROM JPAGENDA ORDER BY AGNOME"
      :Execute()
      oTBrowse := { ;
         { "NOME",     { || :String( "AGNOME", 30 ) } }, ;
         { "TELEFONE", { || :String( "AGTELEFONE", 13 ) } }, ;
         { "TELEF2",   { || :String( "AGTELEF2", 13 ) } }, ;
         { "TELEF3",   { || :String( "AGTELEF3", 13 ) } }, ;
         { "CIDADE",   { || :String( "AGCIDADE", 15 ) } }, ;
         { "UF",       { || :String( "AGUF", 2 ) } } }
      BrowseADO( cnMySql, oTBrowse, "AGNOME", { || StrZero( :Number( "IDAGENDA" ), 6 ) } )
      :CloseRecordset()
   ENDWITH

   RETURN NIL
O destaque nisso é o seguinte: ao mesmo tempo que estou adaptando meus fontes para o ADO, também estou adaptando o uso do ADO aos meus fontes, ao meu estilo.
Seja DBF ou ADO, crio um array com o conteúdo do tbrowse.

Já comentei por aqui:
Deixar fontes simples/limpos/padronizados, antes de complicar.
Tenho meu estilo/padrão de trabalho criado, então vou seguindo esse estilo/padrão.
É diferente de sair remendando qualquer fonte de qualquer jeito.
Bastam pequenos ajustes no estilo/padrão, e estou usando uma base de dados totalmente diferente, quase do mesmo jeito que fazia antes.

Tem uma coisa interessante: no MySQL meus códigos são numéricos, já no DBF/aplicativo sempre foram caractere.
Na hora de montar a string para o MySQL, basta eu somar o campo, sem precisar nenhuma conversão.
"SELECT * FROM JPCADASTRO WHERE IdCadastro=" + midCadastro

Foi sem querer... Apenas queria usar o incremental no MySQL para os campos que no DBF hoje são string.
Parecia que isso ia ser problema, afinal são tipos diferentes, mas acabou facilitando as coisas.

Meu modo de trabalho

Enviado: 11 Nov 2019 13:27
por JoséQuintas
Transportadoras... lembram?
separei do cadastro, ficava junto com clientes.
JPCADAS virou JPCADASTRO e JPTRANSP
Hoje deixei somente MySQL.
JPTRANSP.DBF é o primeiro DBF eliminado da temporada - e junto JPTRANSP.CDX
Não deu tempo nem de completar um mês de uso.

Transportadoras é pouco usado, por isso foi rápido.
Basicamente entra no cadastro de clientes, e na nota/nota eletrônica.
Listagem... só uma.

Meu modo de trabalho

Enviado: 11 Nov 2019 13:43
por JoséQuintas
As atualizações de versão....
22 de outubro, transportadoras virou arquivo separado

Código: Selecionar todos

STATIC FUNCTION Update1022B()

   SayScroll( "Transferindo transportadoras" )
   IF ! AbreArquivos( "jptransp", "jpcadastro" )
      QUIT
   ENDIF
   SELECT jpcadastro
   SET ORDER TO 0
   GOTO TOP
   GrafTempo( "JPTRANSP" )
   DO WHILE ! Eof()
      GrafTempo( RecNo(), LastRec() )
      IF jpcadastro->cdTipo != "3"
         SKIP
         LOOP
      ENDIF
      SELECT jptransp
      RecAppend()
      REPLACE ;
         jptransp->tpCodigo   WITH jpcadastro->cdCodigo, ;
         jptransp->idTransp   WITH iif( Empty( jpcadastro->idCadas ), jpcadastro->cdCodigo, jpcadastro->idCadas ), ;
         jptransp->tpNome     WITH jpcadastro->cdNome, ;
         jptransp->tpApelido  WITH jpcadastro->cdApelido, ;
         jptransp->tpCnpj     WITH jpcadastro->cdCnpj, ;
         jptransp->tpEndereco WITH jpcadastro->cdEndereco, ;
         jptransp->tpNumero   WITH jpcadastro->cdNumero, ;
         jptransp->tpCompl    WITH jpcadastro->cdCompl, ;
         jptransp->tpBairro   WITH jpcadastro->cdBairro, ;
         jptransp->tpCidade   WITH jpcadastro->cdCidade, ;
         jptransp->tpUF       WITH jpcadastro->cdUF, ;
         jptransp->tpCep      WITH jpcadastro->cdCep, ;
         jptransp->tpTelefone WITH jpcadastro->cdTelefone, ;
         jptransp->tpInsEst   WITH jpcadastro->cdInsEst, ;
         jptransp->tpContato  WITH jpcadastro->cdContato, ;
         jptransp->tpTelef2   WITH jpcadastro->cdTelef2, ;
         jptransp->tpTelef3   WITH jpcadastro->cdTelef3, ;
         jptransp->tpTelef4   WITH jpcadastro->cdFax, ;
         jptransp->tpEmail    WITH jpcadastro->cdEmail, ;
         jptransp->tpHomePage WITH jpcadastro->cdHomePage, ;
         jptransp->tpObs      WITH jpcadastro->cdObs, ;
         jptransp->tpStatus   WITH jpcadastro->cdStatus, ;
         jptransp->tpInfInc   WITH jpcadastro->cdInfInc, ;
         jptransp->tpInfAlt   WITH jpcadastro->cdInfAlt
      SELECT jpcadastro
      RecLock()
      DELETE
      RecUnlock()
      SKIP
   ENDDO
   CLOSE DATABASES
   Mensagem()

   RETURN NIL
23/outubro, teve o campo chave alterado

Código: Selecionar todos

STATIC FUNCTION Update1023D()

   IF ! AbreArquivos( "jptransp" )
      QUIT
   ENDIF
   SayScroll( "Atualizando JPTRANSP" )
   SET ORDER TO 0
   GOTO TOP
   GrafTempo( "JPTRANSP" )
   DO WHILE ! Eof()
      GrafTempo( RecNo(), LastRec() )
      IF Empty( jptransp->idTransp )
         RecLock()
         REPLACE jptransp->idTransp WITH jptransp->tpCodigo
         RecUnlock()
      ENDIF
      SKIP
   ENDDO
   CLOSE DATABASES
   Mensagem()

   RETURN NIL
03/novembro.... checagem de códigos repetidos - em dbf pode acontecer, e gravação dupla mysql

Código: Selecionar todos

STATIC FUNCTION Update1103()

   IF AppConexao() == NIL
      RETURN NIL
   ENDIF
   VerificaNumeracao( "JPTRANSP", "IDTRANSP", "TPOBS" )
   CopyDbfToMySql( "JPTRANSP", .T., .F., .T. )

   RETURN NIL
E hoje.... deixou de existir em DBF.

Foram 20 dias, mas não exclusivo nesse arquivo, foi reorganizando o aplicativo, preparando rotinas, etc.

Como eu disse antes, sem pressa.
Quem precisa se acostumar a não existir DBF sou eu, e não o aplicativo kkkk
Devagar chega lá.

Meu modo de trabalho

Enviado: 13 Nov 2019 11:42
por JoséQuintas
O browse de clientes anterior - DBF

Código: Selecionar todos

METHOD GridSelection() CLASS JPCADASTROClass

   LOCAL oElement, nSelect := Select(), cOrdSetFocus, oTBrowse

   IF Select( "jpclista" ) == 0
      SELECT 0
      AbreArquivos( "jpclista" )
      Errorsys_WriteErrorLog( "Faltou abrir jpclista", 3 )
   ENDIF
   SELECT jpcadastro
   oTBrowse := { ;
      { "Nome",        {|| jpcadastro->cdNome } }, ;
      { "Apelido",     {|| jpcadastro->cdApelido } }, ;
      { "Código",      {|| jpcadastro->idCadastro } }, ;
      { "UF",          {|| jpcadastro->cdUf } }, ;
      { "Cidade",      {|| jpcadastro->cdCidade } }, ;
      { "Ref.Mapa",    {|| jpcadastro->cdMapa } },  ;
      { "Endereço",    {|| jpcadastro->cdEndereco } }, ;
      { "Número",      {|| jpcadastro->cdNumero } }, ;
      { "Complemento", {|| jpcadastro->cdCompl } }, ;
      { "Cnpj",        {|| jpcadastro->cdCnpj } } }
   FOR EACH  oElement IN oTBrowse
      AAdd( oElement, {|| iif( ! Encontra( jpcadastro->cdStatus, "jpclista", "numlan" ) .OR. Val( jpcadastro->cdStatus ) < 2, { 1, 2 }, ;
         iif( Trim( jpclista->csBloqueio ) == "0", { 3, 2 }, ;
         iif( Trim( jpclista->csBloqueio ) == "1", { 4, 2 }, { 7, 2 } ) ) ) } )
   NEXT
   cOrdSetFocus := ordSetFocus()
   ordSetFocus( "nome" )
   FazBrowse( oTBrowse )
   IF LastKey() != K_ESC .AND. ! Eof()
      KEYBOARD jpcadastro->idCadastro + Chr( K_ENTER )
   ENDIF
   ordSetFocus( cOrdSetFocus )
   SELECT ( nSelect )

   RETURN NIL
o browse atual - ADO/MySQL

Código: Selecionar todos

METHOD GridSelection() CLASS JPCADASTROClass

   LOCAL oElement, oTBrowse, cnMySql := ADOClass():New( AppConexao() )

   WITH OBJECT cnMySql
      :cSql := "SELECT IDCADASTRO, CDNOME, CDAPELIDO, CDUF, CDCIDADE, CDMAPA, CDENDERECO, " + ;
         "CDNUMERO, CDCOMPL, CDCNPJ, JPCLISTA.CSBLOQUEIO AS STATUS FROM JPCADASTRO " + ;
         "LEFT JOIN JPCLISTA ON JPCLISTA.IDCLISTA = JPCADASTRO.CDSTATUS " + ;
         "ORDER BY CDNOME"
      :Execute()
      oTBrowse := { ;
         { "NOME",        { || :String( "CDNOME", 40 ) } }, ;
         { "APELIDO",     { || :String( "CDAPELIDO", 20 ) } }, ;
         { "CÓDIGO",      { || StrZero( :Number( "IDCADASTRO" ), 6 ) } }, ;
         { "UF",          { || :String( "CDUF", 2 ) } }, ;
         { "CIDADE",      { || :String( "CDCIDADE", 21 ) } }, ;
         { "REF.MAPA",    { || :String( "CDMAPA", 30 ) } }, ;
         { "ENDEREÇO",    { || :String( "CDENDERECO", 40 ) } }, ;
         { "NÚMERO",      { || :String( "CDNUMERO", 10 ) } }, ;
         { "COMPLEMENTO", { || :String( "CDCOMPL", 20 ) } }, ;
         { "CNPJ",        { || :String( "CDCNPJ", 18 ) } } }
      FOR EACH oElement IN oTBrowse
         AAdd( oElement, { || iif( :String( "STATUS", 1 ) == "0", { 3,2 }, ;
                              iif( :String( "STATUS", 1 ) == "1", { 4,2 }, { 7,2 } ) ) } )
      NEXT
      BrowseADO( cnMySql, oTBrowse, "CDNOME", { || StrZero( :String( "IDCADASTRO" ), 6 ) } )
      :CloseRecordset()
   ENDWITH

   RETURN NIL
Nada de testar arquivo aberto, nada de salvar área atual, nada de arquivos.
Apenas pede informação pro servidor e faz o browse.

Lembrando:
No MySQL estou usando VARCHAR como tipo de campo, então as strings não tem tamanho fixo.
Aproveitei na classe a função :String() pra já definir o tamanho que eu quero, dispensando conversões extras, e simplificando muito

Meu modo de trabalho

Enviado: 20 Nov 2019 21:17
por JoséQuintas
Até já coloquei em outro post, mas aqui é a mudança com o tempo, não faria sentido colocar junto ao outro post.

Aqui o tbrowse era somente DBF:

Código: Selecionar todos

METHOD GridSelection() CLASS JPPEDIDOClass

   LOCAL nCont, oTBrowse, nSelect := Select()

   IF Select( "jptransa" ) == 0
      SELECT 0
      AbreArquivos( "jptransa" )
      Errorsys_WriteErrorLog( "Faltou abrir jptransa", 3 )
   ENDIF
   IF Select( "jpnotfis" ) == 0
      SELECT 0
      AbreArquivos( "jpnotfis" )
      Errorsys_WriteErrorLog( "Faltou abrir jpnotfis", 3 )
   ENDIF
   IF Select( "jpcadastro" ) == 0
      SELECT 0
      AbreArquivos( "jpcadastro" )
      Errorsys_WriteErrorLog( "Faltou abrir jpcadas", 3 )
   ENDIF
   SELECT jppedido
   oTBrowse := { ;
      { "PEDIDO",      {|| jppedido->idPedido } }, ;
      { "DT.EMIS.",    {|| jppedido->pdDatEmi } }, ;
      { "CLIENTE",     {|| jppedido->pdCliFor + " " + ReturnValue( "", Encontra( jppedido->pdCliFor, "jpcadastro", "numlan" ) ) + Pad( jpcadastro->cdNome, 30 ) } }, ;
      { "NF",          {|| ReturnValue( "", Encontra( jppedido->idPedido, "jpnotfis", "pedido" ) ) + Right( jpnotfis->nfFilial, 2 ) + "." + jpnotfis->nfNotFis } }, ;
      { "SITUAÇÃO",    {|| Pad( Pedido():Status(), 10 ) } }, ;
      { "TRANSAÇÃO",   {|| ReturnValue( "", Encontra( jppedido->pdTransa, "jptransa", "numlan" ) ) + Pad( jptransa->trDescri, 12 ) } }, ;
      { "VAL.NF",      {|| Transform( jppedido->pdValNot, "999,999,999.99" ) } } }
   FOR nCont = 1 TO Len( oTBrowse )
      AAdd( oTBrowse[ nCont ], {|| ;
         iif( "NF." $ Pedido():Status() .OR. "CANCELADO" $ Pedido():Status() .OR. "DEM." $ Pedido():Status(), { 1, 2 }, ;
         iif( "FATURAR" $ Pedido():Status(), { 7, 2 }, { 6, 2 } ) ) } )
   NEXT
   FazBrowse( oTbrowse )
   IF LastKey() != K_ESC .AND. ! Eof()
      KEYBOARD jppedido->idPedido + Chr( K_ENTER )
   ENDIF
   SELECT ( nSelect )

   RETURN NIL
Aqui ficou parcial DBF/MySQL

Código: Selecionar todos

WITH OBJECT cnMySql
   :cSql := "SELECT IDPEDIDO, PDDATEMI, PDCLIFOR, LEFT( JPCADASTRO.CDNOME, 30 ) AS NOME, " + ;
    "PDTRANSA, PDVALNOT, PDCONF, PDSTATUS " + ;
    "FROM JPPEDIDO " + ;
    "LEFT JOIN JPCADASTRO ON JPPEDIDO.PDCLIFOR = JPCADASTRO.IDCADASTRO " + ;
    "WHERE PDDATEMI > " + DateSql( Date() - 180 )
   :Execute()
   oTBrowse := { ;
    { "PEDIDO",  { || StrZero( :Number( "IDPEDIDO" ), 6 ) } }, ;
    { "DT.EMIS.", { || :Date( "PDDATEMI" ) } }, ;
    { "CLIENTE", { || :String( "PDCLIFOR", 6 ) + " " + :String( "NOME", 30 ) } }, ;
    { "NF",    { || ReturnValue( "", Encontra( StrZero( :Number( "IDPEDIDO" ), 6 ), "jpnotfis", "pedido" ) ) + Right( jpnotfis->nfFilial, 2 ) + "." + jpnotfis->nfNotFis } }, ;
    { "SITUAÇÃO", { || Pad( PedidoStatus( StrZero( :Number( "IDPEDIDO" ), 6 ), :String( "PDSTATUS", 2 ), :String( "PDCONF", 2 ) ), 10 ) } }, ;
    { "TRANSAÇÃO", { || ReturnValue( "", Encontra( :String( "PDTRANSA", 6 ), "jptransa", "numlan" ) ) + Pad( jptransa->trDescri, 12 ) } }, ;
    { "VAL.NF",  { || Transform( :Number( "PDVALNOT" ), "999,999,999.99" ) } } }
   FOR nCont = 1 TO Len( oTBrowse )
    AAdd( oTBrowse[ nCont ], { | cStatus | cStatus := PedidoStatus( StrZero( :Number( "IDPEDIDO" ), 6 ), ;
      :String( "PDSTATUS", 2 ), :String( "PDCONF", 2 ) ), ;
      iif( "NF." $ cStatus .OR. "CANCELADO" $ cStatus, { 1, 2 }, ;
      iif( "FATURAR" $ cStatus, { 7, 2 }, { 6, 2 } ) ) } )
   NEXT
   BrowseADO( cnMySql, oTBrowse, "NOME", { || StrZero( :Number( "IDPEDIDO" ), 6 ) } )
   :CloseRecordset()
 ENDWITH
Aqui ficou mais MySQL ainda, pegando informação do MySQLJPNOTFIS ao invés de DBF.JPNOTFIS

Código: Selecionar todos

METHOD GridSelection() CLASS JPPEDIDOClass

   LOCAL nCont, oTBrowse, nSelect := Select(), cnMySql := ADOClass():New( AppConexao() )

   IF Select( "jptransa" ) == 0
      SELECT 0
      AbreArquivos( "jptransa" )
      Errorsys_WriteErrorLog( "Faltou abrir jptransa", 3 )
   ENDIF
   WITH OBJECT cnMySql
      :cSql := "SELECT IDPEDIDO, PDDATEMI, PDCLIFOR, LEFT( JPCADASTRO.CDNOME, 30 ) AS NOME, " + ;
         "PDTRANSA, PDVALNOT, PDCONF, PDSTATUS, JPNOTFIS.IDNOTFIS AS NOTFIS, RIGHT( JPNOTFIS.NFFILIAL, 2 ) AS FILIAL " + ;
         "FROM JPPEDIDO " + ;
         "LEFT JOIN JPCADASTRO ON JPPEDIDO.PDCLIFOR = JPCADASTRO.IDCADASTRO " + ;
         "LEFT JOIN JPNOTFIS ON JPPEDIDO.IDPEDIDO = JPNOTFIS.NFPEDIDO " + ;
         "WHERE PDDATEMI > " + DateSql( Date() - 180 )
      :Execute()
      oTBrowse := { ;
         { "PEDIDO",    { || StrZero( :Number( "IDPEDIDO" ), 6 ) } }, ;
         { "DT.EMIS.",  { || :Date( "PDDATEMI" ) } }, ;
         { "CLIENTE",   { || :String( "PDCLIFOR", 6 ) + " " + :String( "NOME", 30 ) } }, ;
         { "NF",        { || :String( "FILIAL", 2 ) + "." + StrZero( :Number( "NOTFIS" ), 6 ) } }, ;
         { "SITUAÇÃO",  { || Pad( PedidoStatus( StrZero( :Number( "IDPEDIDO" ), 6 ), :String( "PDSTATUS", 2 ), :String( "PDCONF", 2 ) ), 10 ) } }, ;
         { "TRANSAÇÃO", { || ReturnValue( "", Encontra( :String( "PDTRANSA", 6 ), "jptransa", "numlan" ) ) + Pad( jptransa->trDescri, 12 ) } }, ;
         { "VAL.NF",    { || Transform( :Number( "PDVALNOT" ), "999,999,999.99" ) } } }
      FOR nCont = 1 TO Len( oTBrowse )
         AAdd( oTBrowse[ nCont ], { | cStatus | cStatus := PedidoStatus( StrZero( :Number( "IDPEDIDO" ), 6 ), ;
            :String( "PDSTATUS", 2 ), :String( "PDCONF", 2 ) ), ;
            iif( "NF." $ cStatus .OR. "CANCELADO" $ cStatus, { 1, 2 }, ;
            iif( "FATURAR" $ cStatus, { 7, 2 }, { 6, 2 } ) ) } )
      NEXT
      BrowseADO( cnMySql, oTBrowse, "NOME", { || StrZero( :Number( "IDPEDIDO" ), 6 ) } )
      :CloseRecordset()
   ENDWITH
   SELECT ( nSelect )

   RETURN NIL
O próximo será JPTRANSA e pronto, nenhum DBF para esse tbrowse.

Tive que modificar o campo de pedido em JPNOTFIS, porque nem tinha paciência de esperar o tbrowse, de tão demorado que tinha ficado.
Depois de alterar o campo pra numérico, e criar índice... aí sim ficou instantâneo.

Alterar de string para numérico no MySQL é simples... ou quase.
Se o conteúdo for numérico, a alteração é instantânea, mas se contiver algo diferente... aí precisa ajustar o conteúdo diferente primeiro.

Quanto à migração pra MySQL:
Por enquanto eliminando a necessidade de DBFs, nos TBROWSEs, e módulos sem complicação.

Lembrando:
É sempre no esquema do cliente clicar e já atualizar.
Deu certo já fica disponível pra quem quiser.
Sempre em frente, e sempre funcionando.

Meu modo de trabalho

Enviado: 21 Nov 2019 21:43
por JoséQuintas
A solução foi acrescentar na conversão isto aqui:

Código: Selecionar todos

      IF Val( jpnotfis->nfPedido ) == 0
         RecLock()
         REPLACE jpnotfis->nfPedido WITH "0"
         RecUnlock()
      ENDIF
É conversão que JÁ FOI feita em vários clientes.
Tive que alterar a conversão "antiga", que vai ser usada somente nos atrasadinhos.

Meu modo de trabalho

Enviado: 25 Nov 2019 15:53
por asimoes
Olá Quintas,

Vi que você usa a função LPAD é a mesma função PadL() ? os parâmetros são parecidos

Meu modo de trabalho

Enviado: 25 Nov 2019 15:56
por JoséQuintas
asimoes escreveu:Vi que você usa a função LPAD é a mesma função PadL() ? os parâmetros são parecidos
Sim, com a diferença de que no MySQL pode ser campo numérico.
Ou seja, substitui Padl() e StrZero().

Meu modo de trabalho

Enviado: 25 Nov 2019 19:55
por asimoes
JoséQuintas escreveu:Sim, com a diferença de que no MySQL pode ser campo numérico.
Ou seja, substitui Padl() e StrZero().
Na documentação da PadL diz que ela aceita tipo Caracter , Data e Número

Código: Selecionar todos

PadC(), PadL(), and PadR() are conversion functions that convert the value of an expression to a character string, padded with a fill character. The functions accept for <expression> values of data type Character, Date and Numeric. 

Meu modo de trabalho

Enviado: 27 Nov 2019 05:32
por JoséQuintas
Só recapitulando como estou fazendo.
Neste momento migrando o arquivo de transações para o MySQL.

1. Alterei a parte do MySQL pra criar a tabela no MySQL
2. Criei a rotina de atualização, que grava o arquivo JPTRANSA.DBF na tabela JPTRANSA
3. Alterei o cadastro de transações, pra atualizar no DBF e no MySQL ao mesmo tempo
Então existe DBF e MySQL e os dois estão sendo atualizados.
Pronto pra instalação nos clientes.

Vantagem desse método:
Tô alterando e colocando pra funcionar.
Pra gravar duplicado, praticamente só alterei o fonte do cadastro, o que foi rápido.

E agora?
O que usa informação do DBF funciona, e o que usar informação do MySQL também funciona.
Então, posso ir alterando e trocando no cliente CADA fonte.
É teste prático de CADA alteração assim que for feita.
Se não precisar mais do DBF, só apagar.

Nota:
Aonde usa notas fiscais e pedidos, ainda não terminei de alterar, é muuuito fonte.
Mas tudo está funcionando, seja DBF ou MySQL.

Uma opção disponível, não que eu vá usar:
Se apagar agora dos DBFs informação anterior a 2018, relatórios em DBF não terão a informação, mas em MySQL sim.
Seria perigoso se fosse reutilizada a numeração de lançamentos, mas se é o MySQL que passou a fornecer o número... nunca vai repetir.
A vantagem seria menos DBF pra processar, deixando a parte de DBF mais rápida.