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 Set 2021 08:03

A contabilidade é até um bom exemplo de que vale a pena fazer do jeito que estou fazendo.

Tenho lá as contas, os lançamentos, e outros.
Estou terminando esse "outros", só vai sobrar contas e lançamentos.

Aonde altera esses arquivos? o cadastro, a inclusão de lançamentos e a alteração de lançamentos. 3 ou 4 fontes.
Aonde tira relatório? trocentos fontes.

Altero esses 4 fontes pra gravação dupla (DBF+SQL), toda gravação de SQL fica pronta.
Talvez leve um único dia pra fazer isso.
E posso instalar em cliente, sem problema algum, relatórios usando DBF vão continuar funcionando.

Percebeu o que aconteceu com isso?
Bastou 1 único dia e tá tudo duplicado em DBF e SQL
Significa que a partir do segundo dia, posso alterar o que eu quiser, na hora que eu quiser, de DBF pra SQL, e já colocar em prática.

Em momento algum precisei de versões diferentes.

Eu mesmo nem tinha notado isto com relação à contabilidade, vai ser muito mais fácil do que todo resto.

Se vale a pena? Com certeza.
Continua sendo alterar e já instalar.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 25 Set 2021 18:40

Não é exatamente um passo a passo.
Criei a tabela no SQL.
Agora criei a conversão:
STATIC FUNCTION Update0925E()

   IF ! File( "jpcontabil.dbf" )
      RETURN Nil
   ENDIF
   IF ! AbreArquivos( "jpcontabil" )
      QUIT
   ENDIF
   GOTO TOP
   DO WHILE ! Eof()
      IF ADORecCount( "JPCONTABIL", "IDCONTABIL=" + NumberSQL( jpcontabil->idContabil ) ) == 0
         :QueryAdd( "IDCONTABIL", jpcontabil->IDCONTABIL )
         :QueryAdd( "CTLOTE",     jpcontabil->CTLOTE )
         :QueryAdd( "CTLANC",     jpcontabil->CTLANC )
         :QueryAdd( "CTMOV",      jpcontabil->CTMOV )
         :QueryAdd( "CTPARTIDA",  jpcontabil->CTPARTIDA )
         :QueryAdd( "CTDATA",     jpcontabil->CTDATA )
         :QueryAdd( "CTCTADEB",   jpcontabil->ctCtaDeb )
         :QueryAdd( "CTCTACRE",   jpcontabil->ctCtaCre )
         :QueryAdd( "CTDEBCRE",   jpcontabil->CTDEBCRE )
         :QueryAdd( "CTCONTA1",   jpcontabil->CTCONTA1 )
         :QueryAdd( "CTCCONTA",   jpcontabil->CTCCONTA )
         :QueryAdd( "CTTEXTO",    jpcontabil->CTTEXTO )
         :QueryAdd( "CTVALOR",    jpcontabil->CTVALOR )
         :QueryAdd( "CTCCUSTO",   jpcontabil->CTCCUSTO )
         :QueryAdd( "CTCONTRA",   jpcontabil->CTCONTRA )
         :QueryAdd( "CTCONTA2",   jpcontabil->CTCONTA2 )
         :QueryAdd( "CTBAIXA",    jpcontabil->CTBAIXA )
         :QueryAdd( "CTINFINC",   jpcontabil->CTINFINC )
         :QueryAdd( "CTINFALT",   jpcontabil->CTINFALT )
         :QueryExecuteInsert( "JPCONTABIL" )
      ENDIF
      SKIP
   ENDDO
   GOTO TOP
   lDelete := Eof()
   IF lDelete
      fErase( "jpcontabil.dbf" )
   ENDIF

   RETURN Nil


Em seguida vou alterar aonde grava, pra atualizar simultâneo DBF e SQL.
Isso significa que segunda feira vai estar rodando nos clientes.

Sua pergunta, se vale a pena, acabou me chamando a atenção sobre isso.

Segunda feira toda contabilidade estará em DBF e em SQL.
Os relatórios NÃO alterados, vão buscar informação de DBF.
Cada relatório que eu alterar, vai buscar informação do SQL.
Trata-se apenas de alterar e colocar em funcionamento.

Eu acho que vale a pena, porque está pronto, ao mesmo tempo que não está pronto.
Está pronto no sentido de que tudo continua funcionando.
Posso esquecer que DBF existe, mesmo ele existindo.
Posso usar todos os relatórios em DBF, mesmo estando tudo em SQL.
A partir daí, é questão de tempo, é ir alterando e colocando em prática.

Este é o ponto:
Temos mais consultas do que gravações, então, alterar as gravações é rápido.
Gravando em DBF e em SQL... tá tudo liberado pra fazer o que quiser, quando quiser.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 26 Set 2021 12:30

O único problema é que mudei de idéia, e estou reformando toda contabilidade.
Agora vou ter que mudar tudo de uma vez.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 26 Set 2021 16:23

Só pra dar uma idéia:

Acabei com o uso de lotes, acabei com os saldos mensais que ficavam no plano de contas, acabei com gravação de débito e crédito em separado.
Com isso, obrigatoriamente mexer em tudo.

O mais engraçado, é que isso torna tudo ilimitado, e vai facilitar demais as coisas.

Resumindo:
Acabei com os DBFs, mas por enquanto acabei com o módulo contábil.
Quem atualizar vai ficar sem contabilidade.
Estou confiando que vou fazer tudo rápido, antes de alguém atualizar.
Uma nova contabilidade diferente da anterior o mais rápido possível, sem opção de voltar atrás.
Vai ficar tudo convertido pra SQL, pronto pra uso, mas sem aplicativo.

STATIC FUNCTION Update0925G()

   LOCAL cnSQL := ADOLocal()

   WITH OBJECT cnSQL
      IF ! :TableExists( "JPCTCONTA" )
         RETURN Nil
      ENDIF
      FOR nCont = 1 TO 96
         IF :FieldExists( "CPDEB" + StrZero( nCont, 2 ), "JPCTCONTA" )
            :ExecuteCmd( "ALTER TABLE JPCTCONTA DROP COLUMN CPDEB" + StrZero( nCont, 2 ) )
         ENDIF
         IF :FieldExists( "CPCRE" + StrZero( nCont, 2 ), "JPCTCONTA" )
            :ExecuteCmd( "ALTER TABLE JPCTCONTA DROP COLUMN CPCRE" + StrZero( nCont, 2 ) )
         ENDIF
      NEXT
      FOR EACH cName IN { "CPTMPANT", "CPTMPDEB", "CPTMPCRE", "CPALTERADA" }
         IF :FieldExists( cName, "JPCTCONTA" )
            :ExecuteCmd( "ALTER TABLE JPCTCONTA DROP COLUMN " + cName )
         ENDIF
      NEXT
   ENDWITH

   RETURN Nil


Só pra dar uma idéia, estou APAGANDO 196 campos do plano de contas, que mantinham os saldos mensais.
Com certeza, todo aplicativo é baseado nisso, por enquanto.
Ainda não faço nenhuma idéia de como vou fazer pra atualizar as contas sintéticas, ou como vou apurar o lucro com a mudança.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 26 Set 2021 18:29

saldocontabil.png


Isso é apenas parte da necessidade.
Mas substituir 192 campos por um comando de menos de um milésimo de segundo... vale a pena.
Falta muito ainda, por enquanto só fazendo testes.

Uma necessidade extra pra procedure, e outras situações, e esse COALESCE(), pra não retornar NULO.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 27 Set 2021 18:20

contabil.png


Que tal um balancete de qualquer período, usando somente SQL?
Ainda é protótipo, sem encerramento de exercício automático.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 27 Set 2021 18:55

contabil.png


Agora com apuração automática de lucro.
Ainda não sei como vou fazer pra gerar esses lançamentos automáticos no diário.
também não sei como vou atualizar sintéticas.
devagar tá indo.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 27 Set 2021 19:20

METHOD SaldoCredito( nNumMes ) CLASS CTCONTAClass

   LOCAL nValor

   IF Type( "nOpcOficial" ) != "N"
      nOpcOficial= 1
   ENDIF
   IF nNumMes < 1 .OR. nNumMes > CONTABIL_MESMAX
      nValor := 0
   ELSE
      nValor := jpctconta->( FieldGet( FieldPos( "CPCRE" + StrZero( nNumMes, 2 ) ) ) )
   ENDIF

   RETURN nValor

METHOD SaldoDebito( nNumMes ) CLASS CTCONTAClass

   LOCAL nValor

   IF Type( "nOpcOficial" ) != "N"
      nOpcOficial := 1
   ENDIF
   IF nNumMes < 1 .OR. nNumMes > CONTABIL_MESMAX
      nValor := 0
   ELSE
      nValor := jpctconta->( FieldGet( FieldPos( "CPDEB" + StrZero( nNumMes, 2 ) ) ) )
   ENDIF

   RETURN nValor

METHOD SaldoAnterior( nNumMes ) CLASS CTCONTAClass

   LOCAL nValor

   nValor := ::SaldoAtual( nNumMes - 1 )

   RETURN nValor

METHOD SaldoAtual( nNumMes ) CLASS CTCONTAClass

   LOCAL nValor, nCont

   IF Type( "nOpcOficial" ) != "N"
      nOpcOficial := 1
   ENDIF
   nNumMes := Min( Max( nNumMes, 0 ), CONTABIL_MESMAX )
   nValor := jpctconta->cpSdAnt
   FOR nCont = 1 TO nNumMes
      nValor += ::SaldoDebito( nCont ) - ::SaldoCredito( nCont )
   NEXT

   RETURN nValor


Antes, tinha os 96 meses no plano de contas, isso foi eliminado.
Estou criando rotinas "equivalentes" às anteriores.
Ao invés de 96 meses em aberto, passou a ser ilimitado.
De quebra, as rotinas equivalentes ficam no SQL.

Dá pra destacar um uso interessante nessas rotinas:
Tinha lá DEB01, DEB02.... DEB96, e CRE01, CRE02... CRE96.
Criei duas rotinas pra retornar UM campo desses usando FieldGet. SaldoDebito( nCont ), SaldoCredito( nCont ).
A partir daí, para o mes 12:
nSaldo := 0
FOR nCont = 1 TO 12
   nSaldo += SaldoDebito( nCont ) - SaldoCredito( nCont )
NEXT


Se fosse muito antigamente, eu acharia complicação, porque parece dar muitas voltas pra chegar num resultado.
Mas pense bem:
      nValor := jpctconta->( FieldGet( FieldPos( "CPDEB" + StrZero( nNumMes, 2 ) ) ) )

Imagine isso em tudo que é rotina.
Do jeito que eu fiz, só essas rotinas básicas tem isso, as demais usam a função.
Dá pra dizer que deixei a complicação num fonte simples, e os fontes "mais complicados" ficaram simples com o uso dessas funções.

Vai tudo pro lixo agora.
No SQL faço tudo diretamente por DATA, não mais um número de 1 a 96.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 27 Set 2021 21:11

contabil.png


Acho que completei o que faltava referente a saldos.
Agora sim, falta atualizar sintéticas pra encerrar a parte de saldos.
Depois vai ser a parte de gerar lançamentos automáticos.

Parece piada, mas....
Ainda não mexi em fonte Harbour.
Quando tudo estiver pronto... só aí vou mexer nos fontes Harbour.
Vou apagar muita coisa.

Pois é...
Imaginei que o contábil seria diferente, e por isso deixei pra converter por último.
Estou fazendo uso de tudo que tinha aprendido até agora.

Isso me lembra dos componentes.... que permitem aproveitar a lógica de DBFs....
Aproveitar o que? e pra que?
A contabilidade está quase pronta, e nem mexi no Harbour kkkkk

O ADO é bom por isso: a gente se preocupa apenas com o que é importante.

Nem importa se é Windows, Linux, Harbour, XHarbour, celular, etc.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 28 Set 2021 08:59

O que estou percebendo é o seguinte:

Vou acabar usando muito SELECT de SELECT de SELECT, o que é ruim de codificar.
Não usei ainda, mas acho que VIEW vai facilitar isso.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 28 Set 2021 11:54

jpa.png


Meu teste de hoje.
O que tem de diferente?
Só o endereço do servidor.
Estou usando a base real do cliente, no aplicativo rodando em minha máquina.

É meu primeiro teste do tipo.
Na pasta só precisa do arquivo de configuração e nada mais.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Meu modo de trabalho

Mensagempor JoséQuintas » 02 Out 2021 12:42

Até o livro diário tá virando SQL...

CREATE PROCEDURE ze_ContabilDiario( nMes INT(11) )

BEGIN

DECLARE dInicial, dFinal, dFechamento DATE;
DECLARE nAno, nMes, nFecha INT(11);

SET nAno := ( SELECT EMANOBASE FROM JPEMPRESA WHERE IDEMPRESA = 1 );
SET nFecha := ( SELECT EMFECHA FROM JPEMPRESA WHERE IDEMPRESA = 1 );
SET dInicial := CONCAT( LPAD( nAno, 4, '0' ), '-01-01' );
SET dInicial := DATE_ADD( dInicial, INTERVAL nMes - 1 MONTH );

SET dFinal   := LAST_DAY( dInicial );

SET nAno := YEAR( dInicial );
SET nMes := MONTH( dInicial );

SET nMes := MONTH( dInicial );
SET nMes := FLOOR( ( nMes - 1 ) / nFecha ) * nFecha;
SET dFechamento := CONCAT( LPAD( nAno, 4, '0' ), '-', LPAD( nMes, 2, '0' ), '-01' );
SET dFechamento := LAST_DAY( dFechamento );

SELECT IDCONTABIL AS LANCAMENTO,
   CTDATA AS DATA,
   CTCTADEB AS CONTA,
   CTCTACRE AS CONTRA,
   CTCCUSTO AS CCUSTO,
   'D' AS DEBCRE,
   1 AS ORDEM,
   CTVALOR AS VALOR,
   CTTEXTO AS HISTORICO,
   CTCCUSTO AS CCUSTO,
   CADCONTA.CPNOME AS CONTANOME,
   CADCONTA.CPCODIGO AS CONTACLASS,
   CADCONTRA.CPNOME AS CONTRANOME,
   CADCONTRA.CPCODIGO AS CONTRACLASS,
   JPTABCCUSTO.CCUSTONOME
FROM JPCONTABIL
LEFT JOIN JPCTCONTA AS CADCONTA ON CTCTADEB = CADCONTA.IDCTCONTA
LEFT JOIN JPCTCONTA AS CADCONTRA ON CTCTACRE = CADCONTRA.IDCTCONTA
LEFT JOIN JPTABCCUSTO ON CTCCUSTO = JPTABCCUSTO.IDCCUSTO
WHERE DATE( CTDATA ) BETWEEN DATE( dInicial ) AND DATE( dFinal ) AND CTCTADEB != 0

UNION ALL

SELECT IDCONTABIL AS LANCAMENTO,
   CTDATA AS DATA,
   CTCTACRE AS CONTA,
   CTCTADEB AS CONTRA,
   CTCCUSTO AS CCUSTO,
   'C' AS DEBCRE,
   2 AS ORDEM,
   CTVALOR AS VALOR,
   CTTEXTO AS HISTORICO,
   CTCCUSTO AS CCUSTO,
   CADCONTA.CPNOME AS CONTANOME,
   CADCONTA.CPCODIGO AS CONTACLASS,
   CADCONTRA.CPNOME AS CONTRANOME,
   CADCONTRA.CPCODIGO AS CONTRACLASS,
   JPTABCCUSTO.CCUSTONOME
FROM JPCONTABIL
LEFT JOIN JPCTCONTA AS CADCONTA ON CTCTACRE = CADCONTA.IDCTCONTA
LEFT JOIN JPCTCONTA AS CADCONTRA ON CTCTADEB = CADCONTRA.IDCTCONTA
LEFT JOIN JPTABCCUSTO ON CTCCUSTO = JPTABCCUSTO.IDCCUSTO
WHERE DATE( CTDATA ) BETWEEN DATE( dInicial ) AND DATE( dFinal ) AND CTCTACRE != 0

ORDER BY CTDATA, IDCONTABIL, ORDEM;

END


Com certeza tá incompleto, falta o fechamento automático.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Gerar XML

Mensagempor JoséQuintas » 03 Out 2021 09:24

Não sei até onde vou chegar, mas estou no começo....

CREATE FUNCTION ze_XmlTag( cTag VARCHAR(1000), cValue VARCHAR(1000) )
RETURNS VARCHAR(2000)

BEGIN

DECLARE cXml VARCHAR(2000) DEFAULT '';

IF LENGTH( TRIM( cValue ) ) = 0 THEN
   SET cXml := CONCAT( '<', cTag, '/>' );
ELSE
   SET cXml := CONCAT( '<', cTag, '>', cValue, '</', cTag, '>' );
END IF;

RETURN cXml;

END
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Gerar XML

Mensagempor JoséQuintas » 03 Out 2021 10:12

Como o MySQL não aceita parâmetro em branco, vai precisar de uma pra cada quantidade de decimais.
A mais usada é com duas decimais, que resolve a maioria dos casos, até que foi fácil.

CREATE FUNCTION ze_XmlNumber( nValor DECIMAL(16,2) )
RETURNS VARCHAR(1000)

BEGIN

DECLARE cXml VARCHAR(1000) DEFAULT '';

SET cXml := CONCAT( nValor, '' );

RETURN cXml;

END


Testei com 1 e 1.333, e retorna 1.00 e 1.33
O que eu queria: 2 decimais
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Gerar XML

Mensagempor JoséQuintas » 03 Out 2021 11:05

Precisei de checagens a mais, apesar que o primeiro teste foi com registro inválido.

cria tag

CREATE FUNCTION ze_XmlTag( cTag VARCHAR(1000), cValue VARCHAR(1000) )
RETURNS VARCHAR(2000)

BEGIN

DECLARE cXml VARCHAR(2000) DEFAULT '';

IF LENGTH( TRIM( cValue ) ) = 0 THEN
   SET cXml := CONCAT( '<', cTag, '/>' );
ELSE
   SET cXml := CONCAT( '<', cTag, '>', cValue, '</', cTag, '>' );
END IF;

RETURN cXml;

END


converte valor

CREATE FUNCTION ze_NumberXml( nValor DECIMAL(16,2) )
RETURNS VARCHAR(1000)

BEGIN

DECLARE cXml VARCHAR(1000) DEFAULT '';

SET cXml := CONCAT( COALESCE( nValor, 0 ), '' );

RETURN cXml;

END


Bloco ICMS 00

CREATE FUNCTION ze_NfeBlocoProdutoIcms00( nIdItPed INT(11) )
RETURNS VARCHAR(1000)

BEGIN

DECLARE cXml VARCHAR(1000);
DECLARE cOrigem CHAR(1);
DECLARE cCst VARCHAR(10);
DECLARE nIcmBas DECIMAL(16,2);
DECLARE nIcmAli DECIMAL(16,2);
DECLARE nIcmVal DECIMAL(16,2);

SELECT
SUBSTR( IPICMCST, 1, 1 ), SUBSTR( IPICMCST, 2 ), IPICMBAS, IPICMALI, IPICMVAL
FROM JPITPED WHERE IDITPED = nidItPed
INTO cOrigem, cCst, nIcmBas, nIcmAli, nIcmVal;

SET cXml := CONCAT( '<ICMS00>',
   ze_XmlTag( 'orig', COALESCE( cOrigem, '' ) ),
   ze_XmlTag( 'CST', COALESCE( cCst, '' ) ),
   ze_XmlTag( 'modBC', '3' ),
   ze_XmlTag( 'vBC', ze_NumberXML( nIcmBas ) ),
   ze_XmlTag( 'pICMS', ze_NumberXML( nIcmAli ) ),
   ze_XmlTag( 'vICMS', ze_NumberXml( nIcmVal ) ),
   '</ICMS00>' );

RETURN cXml;

END


icms00.png


Esse é um dos maiores fontes em Harbour.
Por enquanto é teste, mas é interessante gerar usando apenas SQL.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg, multithread, dbfcdx, ADO+MySql, PNotepad
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18155
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Anterior Próximo



Retornar para Contribuições, Dicas e Tutoriais

Quem está online

Usuários vendo este fórum: Nenhum usuário registrado online e 16 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