Ir para conteúdo
  • Cadastre-se

dev botao

  • Este tópico foi criado há 3516 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Recommended Posts

Postado (editado)

Prezados.

 

Tenho prontas as rotinas que fazem o mapeamento do banco de dados para o EFD.

Pegamos por exemplo o 0400, das naturezas de operações (poderia ser todo bloco C).

 

Esse registro é exatamente igual no EFD e no PIS/COFINS.

Gostaria de reaproveitar o desenvolvimento porém infelizmente as classes não tem uma herança comum.

 

Alguém de vocês resolveu o reuso das rotinas de mapeamento ou implementou tudo 2 vezes?

 

obrigado

André

Editado por dremul
  • Consultores
Postado

Eu não entendi qual o problema.

[]'s

Consultor SAC ACBr

Elton
Profissionalize o ACBr na sua empresa, conheça o ACBr Pro.

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Um engenheiro de Controle de Qualidade(QA) entra num bar. Pede uma cerveja. Pede zero cervejas.
Pede 99999999 cervejas. Pede -1 cervejas. Pede um jacaré. Pede asdfdhklçkh.
Postado

Prezado.

 

Estou sem os fontes e o Delphi aqui nesse PC, então os nomes das classes serão aproximados.
 
Então, digamos que eu tenha uma rotina que faz o seguinte:
 
var
  oReg0400: TRegistroC400;
begin
  oReg0400 := efd.bloco_0.RegistroC400New.
  oReg0400.COD_NAT = ‘01’;
  oReg0400.DESC_NAT = ‘Venda de mercadoria’;
 
Bom, essa mesma rotina eu poderia utilizar para exportar o 0400 para o EFD (SPED ICMS/IPI) quanto para o EPC (SPED PIS/COFINS).
 
Porém, aquele registro C400 que eu declarei, é específico para a classe do EFD.
Não é uma classe genérica que eu possa usar para preencher o EFD e o EPC. São de “tipos” diferentes.
 
Então, como vocês fazem para reaproveitar o mesmo código de um report para preencher outro report? Entendeu?
 
abs
Postado (editado)

Sim, mas daí preciso repetir o código.

 

Vai ser uma cópia do código, porém instanciando uma classe diferente (apesar de ter os mesmos campos).

Um código semelhante vai existir 2 vezes.

Ex: se mudar o layout do C100 vou precisar arrumar as 2 implementações, apesar dos 2 registros serem idênticos.

 

Isso estaria resolvido se os 2 fossem a mesma classe ou partilhassem uma herança em comum (depois de TObject, com os campos).

Vou ver se consigo resolver isso com um type cast dinâmico ou algo parecido.

Se alguém tiver alguma ideia, estou aberto :wink:

 

abs

Editado por dremul
Postado

Bom, adicionando progresso:

 

Type casts não vão funcionar.

O Delphi vai gerar um erro de type cast inválido se tentado fazer um registro EFD virar EPC, mesmo que idênticos nas propriedades.

 

Pegar dinamicamente as propriedades para mover os valores de uma classe para a outra, numa rotina única usando RTTI, não vai funcionar porque as propriedades estão como public, não published.

 

Por enquanto é um beco sem saída, aparentemente vou precisar duplicar muito código.

  • Consultores
Postado

Envolveria muita alteração de código e muito trabalho para evitar problemas ao fazer o que você deseja. Além disso, não havia garantias que os registros seriam iguais e hoje ainda não há garantias de que vão continuar sendo. Por isso o mais simples na época foi fazer separado.

 

Mas se quiser propor mudanças para facilitar, fique a vontade para isso.

Depois você poderá anexar os códigos alterados e a gente vai analisar e subir para o SVN.

[]'s

Consultor SAC ACBr

Elton
Profissionalize o ACBr na sua empresa, conheça o ACBr Pro.

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Um engenheiro de Controle de Qualidade(QA) entra num bar. Pede uma cerveja. Pede zero cervejas.
Pede 99999999 cervejas. Pede -1 cervejas. Pede um jacaré. Pede asdfdhklçkh.
Postado

Olá Elton.

 

Obrigado pela sua resposta.

Então, vejo 2 possibilidades:

 

1) alteramos as classes de public para published e utilizamos RTTI para criar uma rotina que dinamicamente mapea os campos de mesmo nome de uma classe pra outra

2) criamos métodos Assign nas classes que ficaria parecido com

 

  oPisCofins0400 := epc.Bloco_0.Registro0400New();

  oPisCofins0400.Assign(IntanciaClasseEFD_0400);

 

Esse método Assign moveria manualmente, campo por campo, as propriedades da instância do EFD para o EPC.

 

Bom, a opção [1] é mais simples de ser implementada, mas depende dos administradores do código ACBR concordarem.

A opção [2] é o que eu vou implementar para os registros que eu gero caso a [1] não seja adotada por vocês.

 

O que vocês acham?

  • Consultores
Postado

Particularmente, não vejo problemas com a implementação 1.

 

Se ninguém for contra, você poderia fazer as alterações, testar e anexar aqui no fórum os arquivos para que a gente pudesse enviar ao repositório.

[]'s

Consultor SAC ACBr

Elton
Profissionalize o ACBr na sua empresa, conheça o ACBr Pro.

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Um engenheiro de Controle de Qualidade(QA) entra num bar. Pede uma cerveja. Pede zero cervejas.
Pede 99999999 cervejas. Pede -1 cervejas. Pede um jacaré. Pede asdfdhklçkh.
  • 4 meses depois ...
Postado (editado)

Prezados.

 

Demorou para postar algo aqui porque não estava trabalhando nesse tópico.

Porém, voltei ao tópico hoje e montei um POC.

Ele precisa ser estendido para, por exemplo, outros tipos além de string.

Mas antes de eu continuar preciso passar com vocês uma alteração que será necessária nas classes do Acbr para que RTTI funcione.

 

Então, eu criei uma rotina que atribui dinamicamente todas as propriedades de uma classe do EFD para as propriedades do PCO.

 

Esse código faz as atribuições dinâmicas:

procedure TdmFerramentasAdmin.TestaReuso;
var
  oEfd_Reg: ACBrEFDBloco_0.TRegistro0000;
  oPco_Reg: ACBrEPCBloco_0.TRegistro0000;
  iPropIndex: Integer;
  iPropCount: Integer;
  pList: PPropList;
  rInfo, rInfoCheck: PPropInfo;
const
  TypeKinds: TTypeKinds = [tkString, tkLString, tkWString];
begin

  oEfd_Reg := efd.Bloco_0.Registro0000New();
  oEfd_Reg.NOME := 'Teste 1';

  oPco_Reg := pco.Bloco_0.Registro0000New();

  GetMem(pList, SizeOf(pList^));
  try
    iPropCount := GetPropList(oPco_Reg.ClassInfo, TypeKinds, pList);

    for iPropIndex := 0 to iPropCount - 1 do
    begin
      rInfo := pList^[iPropIndex];

      rInfoCheck := GetPropInfo(oEfd_Reg, rInfo.Name);
      if rInfoCheck = nil then
        Continue;

      if Assigned(rInfo^.SetProc) then
      case rInfo^.PropType^.Kind of
        tkString, tkLString, tkWString:
          SetStrProp(oPco_Reg, rInfo, GetPropValue(oEfd_Reg, rInfo.Name));
      end;
    end;
  finally
    FreeMem(pList);
  end;

  pco.IniciaGeracao();
  pco.SaveFileTXT();
end;

Porém, para o RTTI funcionar, tanto as classes do EFD quanto do PCO precisam ficar como abaixo (com published ao invés de public, adicionando as diretivas de compilação):

{$M+}
  //REGISTRO 0000: ABERTURA DO ARQUIVO DIGITAL E IDENTIFICAÇÃO DA PESSOA JURÍDICA
  TRegistro0000 = class
  private
    FCOD_VER          : TACBrCodVer;{TACBrVersaoLeiaute;}             //Código da versão do leiaute conforme a tabela 3.1.1
    FTIPO_ESCRIT      : TACBrTipoEscrit;{TACBrTipoEscrituracao;}          //Tipo de escrituração: 0 - Original; 1 – Retificadora;
    FIND_SIT_ESP      : TACBrIndSitEsp;{TACBrIndicadorSituacaoEspecial;} //Indicador de situação especial: 0 - Abertura; 1 - Cisão; 2 - Fusão; 3 - Incorporação; 4 – Encerramento;
    FNUM_REC_ANTERIOR : string;                         //Número do Recibo da Escrituração anterior a ser retificada, utilizado quando TIPO_ESCRIT for igual a 1
    FDT_INI           : TDateTime;                      //Data inicial das informações contidas no arquivo
    FDT_FIN           : TDateTime;                      //Data final das informações contidas no arquivo
    FNOME             : string;                         //Nome empresarial da pessoa jurídica
    FCNPJ             : string;                         //Número de inscrição do estabelecimento matriz da pessoa jurídica no CNPJ
    FUF               : string;                         //Sigla da Unidade da Federação da pessoa jurídica
    FCOD_MUN          : integer;                        //Código do município do domicílio fiscal da pessoa jurídica, conforme a tabela IBGE
    FSUFRAMA          : string;                         //Inscrição da pessoa jurídica na Suframa
    FIND_NAT_PJ       : TACBrIndNatPJ;{TACBrIndicadorNaturezaPJ;}       //Indicador da natureza da pessoa jurídica: 00 – Sociedade empresária em geral 01 – Sociedade cooperativa 02 – Entidade sujeita ao PIS/Pasep exclusivamente com base na Folha de Salários
    FIND_ATIV         : TACBrIndAtiv;{TACBrIndicadorAtividade;}        //Indicador de tipo de atividade preponderante: 0 – Industrial ou equiparado a industrial; 1 – Prestador de serviços; 2 - Atividade de comércio; 3 – Atividade financeira; 4 – Atividade imobiliária; 9 – Outros.
  published
    property COD_VER          : TACBrCodVer{TACBrVersaoLeiaute}             read FCOD_VER          write FCOD_VER;
    property TIPO_ESCRIT      : TACBrTipoEscrit{TACBrTipoEscrituracao}          read FTIPO_ESCRIT      write FTIPO_ESCRIT;
    property IND_SIT_ESP      : TACBrIndSitEsp{TACBrIndicadorSituacaoEspecial} read FIND_SIT_ESP      write FIND_SIT_ESP;
    property NUM_REC_ANTERIOR : string                         read FNUM_REC_ANTERIOR write FNUM_REC_ANTERIOR;
    property DT_INI           : TDateTime                      read FDT_INI           write FDT_INI;
    property DT_FIN           : TDateTime                      read FDT_FIN           write FDT_FIN;
    property NOME             : string                         read FNOME             write FNOME;
    property CNPJ             : string                         read FCNPJ             write FCNPJ;
    property UF               : string                         read FUF               write FUF;
    property COD_MUN          : integer                        read FCOD_MUN          write FCOD_MUN;
    property SUFRAMA          : string                         read FSUFRAMA          write FSUFRAMA;
    property IND_NAT_PJ       : TACBrIndNatPJ{TACBrIndicadorNaturezaPJ}       read FIND_NAT_PJ       write FIND_NAT_PJ;
    property IND_ATIV         : TACBrIndAtiv{TACBrIndicadorAtividade}        read FIND_ATIV         write FIND_ATIV;
  end;
{$M-}

Como só vai funcionar com essa alteração, para aperfeiçoar a rotina e entregar no Acbr preciso ter certeza que as alterações das classes to Acbr serão também adicionadas.

 

E então? O que acham?

 

abs

André

Editado por dremul
  • Moderadores
Postado

Bom dia!

primeiro damos suporte ao Delphi e Lazarus!

os dois devem de trabalhar sem problema e tendo as mesmas funcionalidades!

veja que em nenhum momento a gente faz o código pensando em uma única IDE

então não sei se será possível fazer o que está querendo ! 

 

sugiro que se precisa faça localmente e vá mantendo com merges as alterações que efetuamos no svn

Consultor SAC ACBr Juliomar Marchetti
 

Projeto ACBr

skype: juliomar
telegram: juliomar
e-mail: [email protected]
http://www.juliomarmarchetti.com.br
MVP_NewLogo_100x100_Transparent-02.png
 

 

  • Consultores
Postado

Tem como você fazer um aplicativo simples de teste e exemplo? Assim poderíamos testar no Lazarus.

[]'s

Consultor SAC ACBr

Elton
Profissionalize o ACBr na sua empresa, conheça o ACBr Pro.

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Um engenheiro de Controle de Qualidade(QA) entra num bar. Pede uma cerveja. Pede zero cervejas.
Pede 99999999 cervejas. Pede -1 cervejas. Pede um jacaré. Pede asdfdhklçkh.
Postado

Olá.

 

Projeto anexado.

Lembrando que para funcionar é necessário alterar 2 objetos no Acbr.

O anexo também inclui esses objetos, como devem ficar.

 

Não é necessário recompilar os componentes.

 

Minha intenção seria fazer essa alteração (pelo menos no momento) somente para Bloco 0 e C.

 

abs

André

ReusoSped.zip

Postado

Existe forma mais fácil de resolver isso de forma a não impactar o código em incompatibilidade entre as versões D7...XE8 e Lazarus, não vejo essas alterações a principio com bons olhos.

 

Você pode criar uma class, função, procedure o que achar melhor, no seu sistema para que ao alimentar esses registros o qual acredita que a rotina replica código e tanto do Sped Fiscal e Contribuição ou outro chama-la, isso passa ser a ser responsabilidade de quem o faz, não do componente.

--
Isaque Pinheiro
Aracruz/ES - Brasil
___________________________________________________________________________
Site Oficial: www.isaquepinheiro.com.br 
Youtube: youtube.com/isaquepinheirooficialbr
Facebook: facebook.com.br/isaquepinheirooficialbr
Instagram: instagram.com/isaquepinheirooficialbr
Linkdin: https://www.linkedin.com/in/isaquepinheirooficialbr

Conheça o Projeto ORMBr Framework for Delphi - https://www.ormbr.com.br

 

Postado (editado)

Olá Isaque.

 

Não sei se entendi sua sugestão.

Você diz uma rotina genérica que preenche ambos registros?

Não tem como fazer isso com pouco código e dinâmico visto que as classes não possuem uma herança em comum.

 

Daria para fazer as atribuições manualmente, de propriedades com o mesmo nome (mesma tag), uma por uma, isso é um procedimento manual e característica de um método Assign, que foi a outra alternativa que imaginei. Mais trabalhosa sim, precisa ser mantida depois, mas feita somente 1x por um de nós.

 

Sobre as alterações, minha dúvida está mais no Lazarus que desconheço.

As versões mais altas de Delphi possuem uma forma mais simples de usar RTTI, mas essa forma aqui não é incompatível.

E a diretiva de compilação é somente para dizer ao compilador para tratar a classe de forma igual a TPersistent.

 

Temos várias alternativas:

1) Implementar por Assign, já que vou fazer isso igual

Com isso cada pessoa que precisar vai ter que implementar o Assign. Cada propriedade nova na classe não pode ser esquecida de ser adicionada ao Assign.

Assign também normalmente é de objetos da mesma classe, então na verdade eu indicaria fazer uma nova classe com métodos estáticos para jogar de um tipo pra outro. Até para evitar referência circular entre as classes.

 

2) Só mudar as classes do Acbr com o Published e o {M}

Só serve pra mim. Não faz muito sentido em um código aberto.

 

3) Mudar as classes do Acbr e entregar a rotina RTTI

Acredito que nenhum de nós tem exatamente todos ambientes instalados para testar compatibilidade. Acredito que não exista problema. Sempre tem a possibilidade de isolar código com diretivas se algum problema for encontrado. Também o erro só deve acontecer se alguém tentar usar a rotina RTTI.

 

@Elton: algum retorno no Lazarus?

 

abs

André

Editado por dremul
Postado (editado)

Aqui tem a documentação sobre a diretiva de compilação:

http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/compdirsruntimetypeinformation_xml.html

 

Veja que ali ele diz que a diretiva serve exatamente para ativar o RTTI para as propriedades da classe. Também para tornar visível coisas fora da Published.

Isso exatamente porque nas versões mais altas do Delphi o RTTI é um pouco diferente e tudo no published já está liberado.

Nas versões mais baixar (a minha é D7) é preciso da diretiva pra liberar a published em si pra RTTI.

 

Então, nós poderíamos trocar de public pra published pra todas versões, mas adicionar o {M} somente para algumas versões, começando com o D7 (talvez somente esse inclusive)

Editado por dremul
Postado

André, qual o sentido de ao alimentar uma class de um sped, ela alimentar uma class semelhante do outro sped, os speds tem prazos diferentes para serem gerados e entregues.

  • Curtir 1

--
Isaque Pinheiro
Aracruz/ES - Brasil
___________________________________________________________________________
Site Oficial: www.isaquepinheiro.com.br 
Youtube: youtube.com/isaquepinheirooficialbr
Facebook: facebook.com.br/isaquepinheirooficialbr
Instagram: instagram.com/isaquepinheirooficialbr
Linkdin: https://www.linkedin.com/in/isaquepinheirooficialbr

Conheça o Projeto ORMBr Framework for Delphi - https://www.ormbr.com.br

 

Postado

Isaque.

 

Eu tenho rotinas que exportam o bloco C por período (empresa/filial/ ...).

Eu passo uma interface com parâmetros que me devolvem ele preenchido.

Está tudo pronto.

 

Eu poderia usar esse mesmo módulo para os 2 relatórios.

 

A questão é que o Acbr tem um erro de design:

Como no layout alguns registros possuem a seguinte documentação:

"Registro com estrutura, campos e conteúdo definidos e constantes no Leiaute da Escrituração Fiscal Digital – EFD (ICMS e IPI)"
A classe do registro deveria ser a mesma nos 2 SPEDs.
 
Mas eu também sei o motivo disso: eu trabalhei no Contribuições desde bem cedo (incluindo quando ainda não estava liberado para o público em geral). Então me lembro que no início não era assim e todos "front runners" duplicaram as estruturas. Eu também projetei a duplicação disso na SAP por exemplo (https://br.linkedin.com/in/mullera).
PS: a minha dúvida aqui é para uma coisa pessoal, um sistema que fiz para um negócio de minha família a mais de 10 anos atrás e mantenho por que gosto ;-)
 
No topo das alternativas também imagino
4) Unificamos as classes. Isso pode gerar impacto em quem usa, por isso não recomendado
5) Eu resolvo meu problema já que ele é pequeno. Só entrego poucos registros. Essa a mais fácil pra mim, só imaginei que seria interessante contribuir ;-)
 
Bom, vou de alternativa (5).
Se surgir algum outro ponto que possa ser interessante para o grupo, eu aviso.
Agradeço à todos pelo interesse.
 
abs
André
  • Consultores
Postado

@Elton: algum retorno no Lazarus?

 

Opa. Eu ia olhar hoje, mas surgiu um imprevisto aqui na empresa. :(

Acho que essa semana vai ficar meio apertado de eu olhar. Talvez mais alguém possa ajudar a testar.

[]'s

Consultor SAC ACBr

Elton
Profissionalize o ACBr na sua empresa, conheça o ACBr Pro.

Projeto ACBr     Telefone:(15) 2105-0750 WhatsApp(15)99790-2976.

Um engenheiro de Controle de Qualidade(QA) entra num bar. Pede uma cerveja. Pede zero cervejas.
Pede 99999999 cervejas. Pede -1 cervejas. Pede um jacaré. Pede asdfdhklçkh.
  • Este tópico foi criado há 3516 dias atrás.
  • Talvez seja melhor você criar um NOVO TÓPICO do que postar uma resposta aqui.

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora
×
×
  • Criar Novo...

Informação Importante

Colocamos cookies em seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies, caso contrário, assumiremos que você está bem para continuar.