Página 1 de 2

Comando "recheado"

Enviado: 09 Jan 2020 12:48
por JoséQuintas

Código: Selecionar todos

   WITH OBJECT cnMySql
      :ExecuteCmd( "UPDATE JPESTOQUE SET ESCFOP = IF( ESTIPLAN = '2', '1.652', '5.656' ) WHERE LENGTH( ESCFOP ) < '2'" )
      :cSql := "SELECT LPAD( IDESTOQUE, 6, '0' ) AS ID, ESITEM, ESDATLAN, ESCLIFOR, ESCFOP, ESPEDIDO, ESTIPLAN, " + ;
         " ESNUMDOC AS NUMDOC," + ;
         " ESQTDE  * IF( JPITEM.IEQTDCOM < 1, 1, JPITEM.IEQTDCOM ) AS QTDE," + ;
         " ESQTDE * ESVALOR AS VALOR," + ;
         " JPITEM.IEUNID AS UNIDADE, JPITEM.IEANP AS ANPPRO," + ;
         " IF( TABANPINS.AIANP IS NULL OR JPANPOPE.AOANPREG = '1022002', JPCADASTRO.CDCNPJ, LPAD( '', 14, 0 ) ) AS CADCNPJ, " + ;
         " JPCADASTRO.CDCIDADE AS CADCIDADE, JPCADASTRO.CDUF AS CADUF, " + ;
         " JPCIDADE.CIIBGE AS IBGE," + ;
         " IF( TABANPINS.AIANP IS NULL OR JPANPOPE.AOANPREG = '1022002', TABANPLOC.ALANP, LPAD( '', 7, '0' ) ) AS ANPLOC," + ;
         " IF( TABANPINS.AIANP IS NULL OR JPANPOPE.AOANPREG = '1022002', LPAD( '', 7, '0' ), TABANPINS.AIANP ) AS ANPINS," + ;
         " IF( TABANPINS.AIANP IS NULL, LPAD( '',10,' '), TABANPAGE.AAANP ) AS ANPAGE," + ;
         " IF( TABANPINS.AIANP IS NULL OR JPANPOPE.AOANPREG = '1022002', TABANPATI.ATCNAE, LPAD( '', 5, '0' ) ) AS ANPATI," + ;
         " IF( TABANPINS.AIANP IS NULL, IF( JPCADASTRO.CDCNAE = '9999999', JPANPOPE.AOANPOUT, JPANPOPE.AOANPNREG ), JPANPOPE.AOANPREG ) AS ANPOPE" + ;
         " FROM JPESTOQUE" + ;
         " LEFT JOIN JPITEM ON JPITEM.IDITEM=JPESTOQUE.ESITEM" + ;
         " LEFT JOIN JPCADASTRO ON JPCADASTRO.IDCADASTRO = JPESTOQUE.ESCLIFOR" + ;
         " LEFT JOIN JPCIDADE ON JPCADASTRO.CDUF = JPCIDADE.CIUF AND JPCADASTRO.CDCIDADE = JPCIDADE.CINOME" + ;
         " LEFT JOIN " + ;
            " ( SELECT DISTINCT ALIBGE, ALANP FROM JPANPLOC WHERE LENGTH( ALVALATE ) < 1 ) AS TABANPLOC" + ;
            " ON TABANPLOC.ALIBGE = JPCIDADE.CIIBGE " + ;
         " LEFT JOIN " + ;
            " ( SELECT DISTINCT AICNPJ, AIANP FROM JPANPINS WHERE LENGTH( AIVALATE ) < 1 ) AS TABANPINS" + ;
            " ON TABANPINS.AICNPJ = IF( LENGTH( JPCADASTRO.CDCNPJ ) = 18," + ;
            " CONCAT( CONCAT( CONCAT( CONCAT( SUBSTR( JPCADASTRO.CDCNPJ, 1, 2 ), " + ;
            " SUBSTR( JPCADASTRO.CDCNPJ, 4, 3 ) ), SUBSTR( JPCADASTRO.CDCNPJ, 8, 3 ) ), " + ;
            " SUBSTR( JPCADASTRO.CDCNPJ, 12, 4 ) ), SUBSTR( JPCADASTRO.CDCNPJ, 17, 2 ) ), 'X' ) " + ;
         " LEFT JOIN " + ;
            " ( SELECT DISTINCT AACNPJ, AAANP FROM JPANPAGE WHERE LENGTH( AAVALATE ) < 1 ) AS TABANPAGE " + ;
            " ON TABANPAGE.AACNPJ = IF( LENGTH( JPCADASTRO.CDCNPJ ) = 18," + ;
            " CONCAT( CONCAT( SUBSTR( JPCADASTRO.CDCNPJ, 1, 2 ), SUBSTR( JPCADASTRO.CDCNPJ, 4, 3 ) ), SUBSTR( CDCNPJ, 8, 3 ) ), 'X' ) " + ;
         " LEFT JOIN JPANPOPE ON JPANPOPE.AOCFOP = JPESTOQUE.ESCFOP" + ;
         " LEFT JOIN " + ;
            " ( SELECT DISTINCT ATCNAE FROM JPANPATI WHERE LENGTH( ATVALATE ) < 1 ) AS TABANPATI" + ;
            " ON TABANPATI.ATCNAE = LEFT( JPCADASTRO.CDCNAE, 5 )" + ;
         " LEFT JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPESTOQUE.ESPEDIDO" + ;
         " LEFT JOIN JPNOTFIS ON JPNOTFIS.NFPEDIDO = JPPEDIDO.IDPEDIDO" + ;
         " WHERE ESDATLAN BETWEEN CAST( " + DateSql( dDataInicial ) + " AS DATE )" + ;
         " AND CAST( "  + DateSql( dDataFinal ) + " AS DATE )" + ;
         " AND JPITEM.IEANP IN ( " + ProdutoAnp( "", .T. ) + " )"
      :cSql += " AND ESQTDE <> 0" + ;
         " ORDER BY ESDATLAN, IDESTOQUE"
      :Execute()
      GrafTempo( "Gerando informações" )
      nAtual := 0
      nTotal := :RecordCount()
      DO WHILE ! :Eof()
         GrafTempo( nAtual++, nTotal )
         ImportaEstoque( cnMySql, dDataFinal, @nTotalComNfe, @nTotalSemNfe, lConsultaCnpj )
         :MoveNext()
      ENDDO
      :CloseRecordset()
   ENDWITH
Comando relativamente básico, algo como USE ARQUIVO, SET RELATION.
Mas muitos arquivos/tabelas.

Comando "recheado"

Enviado: 09 Jan 2020 12:51
por JoséQuintas
As tabelas da ANP: JPANPINS, JPANPAGE, JPANPLOC, JPANPATI vém com registros DUPLICADOS, ou porque tem validade, ou porque estão duplicados mesmo.

Minha saída foi criar tabela temporária

Código: Selecionar todos

         " LEFT JOIN " + ;
            " ( SELECT DISTINCT ALIBGE, ALANP FROM JPANPLOC WHERE LENGTH( ALVALATE ) < 1 ) AS TABANPLOC" + ;
            " ON TABANPLOC.ALIBGE = JPCIDADE.CIIBGE " + ;
O mesmo pras 4 tabelas.
Foi a saída que usei, não sei se tem jeito melhor pra isso.

Comando "recheado"

Enviado: 09 Jan 2020 12:53
por JoséQuintas
Se existir código de instalação, precisa deixar alguns campos vazios ou zerados.
Foi esta a saída que usei.

Código: Selecionar todos

         " IF( TABANPINS.AIANP IS NULL, LPAD( '',10,' '), TABANPAGE.AAANP ) AS ANPAGE," + ;

Comando "recheado"

Enviado: 09 Jan 2020 12:55
por JoséQuintas
Tem produto comprado por balde, tambor, caixa com latas de 0.5 litros, etc.
Pra ANP só pode ir em litros.
Tenho um fator de conversão no cadastro de produtos.

Não existe conversão menor que 1, e nunca se sabe se o usuário configurou tudo, então a saída que usei foi esta:

Código: Selecionar todos

         " ESQTDE  * IF( JPITEM.IEQTDCOM < 1, 1, JPITEM.IEQTDCOM ) AS QTDE," + ;

Comando "recheado"

Enviado: 09 Jan 2020 12:57
por JoséQuintas
Pra retirar pontuação do CNPJ, pra poder relacionar com a da ANP, a saída que usei foi esta
SUBSTR() equivalente à função do Harbour, e CONCAT() que é específica pra somar string.

Código: Selecionar todos

         " LEFT JOIN " + ;
            " ( SELECT DISTINCT AICNPJ, AIANP FROM JPANPINS WHERE LENGTH( AIVALATE ) < 1 ) AS TABANPINS" + ;
            " ON TABANPINS.AICNPJ = IF( LENGTH( JPCADASTRO.CDCNPJ ) = 18," + ;
            " CONCAT( CONCAT( CONCAT( CONCAT( SUBSTR( JPCADASTRO.CDCNPJ, 1, 2 ), " + ;
            " SUBSTR( JPCADASTRO.CDCNPJ, 4, 3 ) ), SUBSTR( JPCADASTRO.CDCNPJ, 8, 3 ) ), " + ;
            " SUBSTR( JPCADASTRO.CDCNPJ, 12, 4 ) ), SUBSTR( JPCADASTRO.CDCNPJ, 17, 2 ) ), 'X' ) " + ;

Comando "recheado"

Enviado: 09 Jan 2020 12:58
por JoséQuintas
Intervalo de datas usando between, e a função CAST() pra deixar fuso horário de fora.
Já comentei sobre isto em outro post

Código: Selecionar todos

         " WHERE ESDATLAN BETWEEN CAST( " + DateSql( dDataInicial ) + " AS DATE )" + ;
         " AND CAST( "  + DateSql( dDataFinal ) + " AS DATE )" + ;

Comando "recheado"

Enviado: 09 Jan 2020 13:00
por JoséQuintas
filtro, com a lista dos produtos que interessam pra ANP

Código: Selecionar todos

         " AND JPITEM.IEANP IN ( " + ProdutoAnp( "", .T. ) + " )"

Comando "recheado"

Enviado: 09 Jan 2020 13:02
por JoséQuintas
O equivalente a StrZero()

Código: Selecionar todos

SELECT LPAD( IDESTOQUE, 6, '0' )

Comando "recheado"

Enviado: 09 Jan 2020 13:08
por JoséQuintas
Por enquanto parei por aí nesse comando, porque precisava entregar o arquivo resultado ao governo.

Ainda vão entrar mais coisas no comando pra eliminar do fonte PRG.

Deu trabalho.
Muitos problemas foram por causa das tabelas da ANP contendo duplicações.

Mas....
MySQL é phoda... pediu pra ele, ele faz.

O comando vasculha movimento de estoque, clientes, produtos, cidades, pedidos, notas fiscais, as 4 tabelas da ANP, etc.
É do servidor, não é local.
Sei lá... 1 segundo... porque ainda tem coisa em PRG...

Esqueci deste:

Código: Selecionar todos

         " LEFT JOIN JPPEDIDO ON JPPEDIDO.IDPEDIDO = JPESTOQUE.ESPEDIDO" + ;
         " LEFT JOIN JPNOTFIS ON JPNOTFIS.NFPEDIDO = JPPEDIDO.IDPEDIDO" + ;
relaciono pelo número do pedido, mas .... nem toda nota tem pedido, e nem todo estoque tem pedido...
Se relacionar direto estoque com nota... os zerados se multiplicavam...
Minha saída foi primeiro relacionar com pedidos, e depois com notas.
Desta forma, os zerados não atrapalham, porque não existe pedido zero.

Comando "recheado"

Enviado: 09 Jan 2020 14:57
por JoséQuintas
Recapitulando/traduzindo estilo DBF:

O comando equivale a:

- Criar temporário de JPANPINS, com SET FILTER aplicado
- Criar temporário de JPANPAGE, com SET FILTER aplicado
- Criar temporário de JPANPLOC, com SET FILTER aplicado
- Fazer SEEK em JPCADASTRO
- Fazer SEEK em JPITEM
- Fazer SEEK em JPCIDADE
- Fazer SEEK em JPPEDIDO
- Fazer SEEK em JPNOTFIS
- Fazer SEEK em JPANPINS
- Fazer SEEK em JPANPAGE
- Fazer SEEK em JPANPLOC
- Fazer SEEK em JPANPOPE
- Fazer SET FILTER no JPESTOQUE por data

Não considerem que o MySQL é complicado, pelo contrário, considerem que ele tem muitos recursos, que podem ser usados justamente pra facilitar as coisas.
Pode ser usado igual DBF, e ficar pesquisando um registro por vez, mas.... se ele pode fazer tudo, pra que ficar fazendo "manual" ?
Quanto mais pronto o servidor puder enviar, menos processamento local e menos informação pela rede.

1 segundo pra ter o resultado pronto.... usando DBF, em 1 segundo ainda estaria abrindo os arquivos...

Estou tentando repassar a "sensação" que estou tendo....
É difícil acreditar que coisas que levavam quase 1 hora, agora estão prontas em 1 segundo.

No começo eu achava que tinha dado problema, por ser tão rápido.
Agora estou começando a me acostumar com essa "nova velocidade".

Comando "recheado"

Enviado: 10 Jan 2020 09:08
por Mario Mesquita
Bom dia a todos.

Impressionante. Tanto a linha de comando quanto a performance. Interessante como dentro dos comandos SQL, não se usa a linguagem, e sim os comandos do próprio SQL. Uma pequena lição pra quem quer começar a usar SQL, como eu.

Saudações,
Mario.

Comando "recheado"

Enviado: 11 Jan 2020 00:04
por JoséQuintas
Criei uma tabela pros produtos ANP, retirei do fonte, e acrescentei no comando.
Tipo isto:

Código: Selecionar todos

select iditem, ieanp
 from jpitem 
where ieanp in ( select idanppro from jpanppro ) 
Deixa o fonte mais simples, e deixa flexível pro usuário alterar a lista.
No comando anterior, tinha rotina com um array de produtos pra montar a lista.
Agora basta pegar dessa tabela nova e pronto.

Comando "recheado"

Enviado: 11 Jan 2020 15:49
por JoséQuintas
Só de curiosidade, sobre a lista de produtos.
Substitui este fonte, que gerava a lista pro MySQL (e pra rotina antiga em DBF):

Código: Selecionar todos

FUNCTION ProdutoAnpComb( cAnp, cDescricao, lListaSql )

   LOCAL nItem, cLista := "", aProduto
   LOCAL aList := { ;
      { 820101032, "L",  "DIESEL B S10/S50 PRA GERACAO ENERGIA" }, ;
      { 820101026, "L",  "DIESEL B S1800 PRA GERACAO DE ENERGIA" }, ;
      { 820101027, "L",  "DIESEL B S500 PRA GERACAO DE ENERGIA" }, ;
      { 820101017, "L",  "MIST DIESEL MARITMO 98% 2%" }, ;
      { 820101018, "L",  "DIESEL MARITMO 95% 5%" }, ;
      { 820101019, "L",  "DIESEL MARITMO DMB B2" }, ;
      { 820101020, "L",  "DIESEL MARITMO DMB B5" }, ;
      { 820101021, "L",  "DIESEL NAUTICO B2 ESPECIAL PPM ENXOFRE" }, ;
      { 420201001, "L",  "DIESEL MARITMO" }, ;
      { 420201003, "L",  "DMB MDO" }, ;
      { 430101004, "L",  "OLEO COMB TURBINA GERADORA" }, ;
      { 510103001, "KG", "OLEO COMBUSTIVEL 3 OC3" }, ;
      { 510101001, "KG", "OLEO COMBUSTIVEL 1A" }, ;
      { 510101002, "KG", "OLEO COMBUSTIVEL 2A" }, ;
      { 510102001, "KG", "OLEO COMBUSTIVEL B1" }, ;
      { 510102002, "KG", "OLEO COMBUSTIVEL B2" }, ;
      { 510201001, "KG", "OLEO COMBUSTIVEL MARITMO" }, ;
      { 510201003, "KG", "OLEO COMBUSTIVEL MARITMO MISTURA" }, ;
      { 510301003, "KG", "OLEO COMBUSTIVEL GERACAO ELETRICA" }, ;
      { 560101001, "L",  "OLEO DE XISTO" }, ;
      { 820101033, "L",  "OLEO DIESEL S10 ADITIVADO" }, ;
      { 820101034, "L",  "OLEO DIESEL S10 COMUM" }, ;
      { 820101011, "L",  "OLEO DIESEL BS1800 ADITIVADO" }, ;
      { 820101003, "L",  "MIST DIESEL 95% 5%" }, ;
      { 820101013, "L",  "OLEO DIESEL BS500 ADITIVADO" }, ;
      { 820101012, "L",  "OLEO DIESEL BS500 COMUM" }, ;
      { 420202001, "L",  "OLEO DIESEL NAUTICO ESP ENXOFRE 200 PPM" }, ;
      { 510301001, "KG", "OUTROS OLEOS COMBUSTIVEIS" }, ;
      { 410102001, "L",  "QUEROSENE ILUMINANTE" } }

   hb_Default( @lListaSql, .F. )

   IF lListaSql
      FOR EACH aProduto IN aList
         cLista += iif( aProduto:__EnumIndex == 1, "", ", " ) + StringSql( StrZero( aProduto[ 1 ], 9 ) )
      NEXT
   ELSE
      IF ( nItem := AScan( aList, { | e | Val( cAnp ) == e[ 1 ] } ) ) != 0
         cDescricao := aList[ nItem, 3 ]
         RETURN .T.
      ENDIF
      RETURN .F.
   ENDIF

   RETURN cLista

FUNCTION ProdutoAnpOut( cAnp, cDescricao, lListaSql )

   LOCAL nItem, cLista := "", aProduto
   LOCAL aList := { ;
      { 650101004, "KG", "GRAXAS DE CALCIO" }, ;
      { 650101003, "KG", "GRAXAS DE LITIO" }, ;
      { 650101001, "KG", "GRAXAS MINERAIS" }, ;
      { 650101002, "KG", "OUTRAS GRAXAS" }, ;
      { 620502001, "L",  "MOTORES 2 TEMPOS" }, ;
      { 620501002, "L",  "CICLO DIESEL" }, ;
      { 620501001, "L",  "CICLO OTTO" }, ;
      { 620601003, "L",  "CORRENTE DE MOTOSSERRA" }, ;
      { 620601001, "L",  "OLEOS EXTENSORES E PLASTICICANTES" }, ;
      { 620601004, "L",  "OUTROS OLEOS LUBRIF ACABADOS" }, ;
      { 620601002, "L",  "PULVERIZACAO AGRICOLA" }, ;
      { 620401001, "L",  "OLEOS LUBRIF FERROVIARIOS" }, ;
      { 620101002, "L",  "ENGRENAGENS E SISTEMAS CIRCULATORIOS" }, ;
      { 620101007, "L",  "ESTAMPAGEM" }, ;
      { 620101001, "L",  "HIDRAULICO" }, ;
      { 620101004, "L",  "ISOLANTE TIPO A" }, ;
      { 620101005, "L",  "ISOLANTE TIPO B" }, ;
      { 620101008, "L",  "OUTROS OLEOS LUBRIF INDUST" }, ;
      { 620101003, "L",  "PROCESSO" }, ;
      { 620101006, "L",  "TEXTIL AMACIANTE DE FIBRAS" }, ;
      { 620301001, "L",  "OLEOS LUBRIF MARITMOS" }, ;
      { 620201001, "L",  "OLEOS LUBRIF AVIACAO" }, ;
      { 660101001, "L",  "OLEOS LUBRIF PARAF GRAXAS INTERMED" }, ;
      { 620505001, "L",  "OUTROS OLEOS LUBRIF AUTOMOTIVOS" }, ;
      { 620504001, "L",  "TRANSMISSAO AUTOMATICA" }, ;
      { 620503001, "L",  "TRANSMISSOES E SISTEMAS HIDRAULICOS" } }

   hb_Default( @lListaSql, .F. )
   IF lListaSql
      FOR EACH aProduto IN aList
         cLista += iif( aProduto:__EnumIndex == 1, "", ", " ) + StringSql( StrZero( aProduto[ 1 ], 9 ) )
      NEXT
   ELSE
      IF ( nItem := AScan( aList, { | e | Val( cAnp ) == e[ 1 ] } ) ) != 0
         cDescricao := aList[ nItem, 3 ]
         RETURN .T.
      ENDIF
      RETURN .F.
   ENDIF

   RETURN cLista

FUNCTION ProdutoAnp( cAnp, lListaSQL )

   hb_Default( @lListaSQL, .F. )

   IF lListaSQL
      RETURN ProdutoAnpComb( cAnp, , .T. ) + ", " + ProdutoAnpOut( cAnp, , .T. )
   ENDIF

   RETURN ProdutoAnpComb( cAnp ) .OR. ProdutoAnpOut( cAnp )

por esta linha no comando

Código: Selecionar todos

         " AND JPITEM.IEANP IN ( SELECT IDANPPRO FROM JPANPPRO WHERE APISIMP = 'S' )"
Agora tem a tabela flexível, que o cliente pode adicionar/remover produtos, e ficou tudo mais simples.
Pra DBF usava em array, e na primeira conversão pra MySQL usei o array pra criar o comando.
Agora em tabela simplificou.

Comando "recheado"

Enviado: 14 Jan 2020 11:49
por Marcos Kieron
Só para ajudar, recheado não significa necessariamente bom.
Sempre é melhor o simples.

Comando "recheado"

Enviado: 14 Jan 2020 14:20
por JoséQuintas
Marcos Kieron escreveu:Só para ajudar, recheado não significa necessariamente bom.
Sempre é melhor o simples.
Com certeza.
O "recheado", foi mais no sentido de dizer que tem vários comandos juntos, que podem servir de exemplo.

Sempre repito aqui: sou principiante do MySQL, ainda começando a usar no dia a dia, e aprendendo.
Justamente por ainda ter DBFs no aplicativo, e ainda fazer uso deles, nem adianta querer aprofundar muito no MySQL.
Por enquanto só na fase de me livrar dos DBFs, qualquer coisa que eu conseguir fazer a mais, já é uma vantagem.

Estou mostrando apenas pra ajudar a quem ainda vai começar, pra já adiantar alguma coisa que é possível fazer.
Depois eu mesmo e cada um que for fazendo, juntos vamos descobrindo mais opções.