Estrutura de Classes

De Wiki do Leitão
Ir para: navegação, pesquisa

SPEDFiscalFile e SPEDContribFile

As classes SPEDFiscalFile e SPEDContribFile são a base da escrutura do arquivo de SPED Fiscal e SPED Contribuições, respectivamente. Elas representam o próprio arquivo, e sua estrutura interna os dados dos arquivos.


Para começar a montar um arquivo de SPED é necessário instanciar um desses objetos.


SPEDRegister

SPEDRegister é uma classe abstrata utilizada para representar de forma genérica um registro de qualquer um dos arquivos SPED. Para cada registro dos arquivos do SPED, uma nova classe deve ser implementada extendendo a SPEDRegister, como explicado a seguir no capítulo #SPEDFiscalXXX e SPEDContribXXX.


SPEDFiscalXXX e SPEDContribXXX

As classes SPEDFiscalFile e SPEDContribFile são compostas por uma estrutura de classes que extendem SPEDRegister. Essas classes mantêm os prefixos SPEDFiscal e SPEDContrib seguidos do nome do registro correpondente.

Por exemplo: SPEDFiscalC800 representa o registro C800 do arquivo do SPED Fiscal.


Dentro de cada uma dessas classes que representa um registro existem atributos para receber os valores dos campos desse registro, além de uma lista, hash ou referência para eventuais registros filhos que o registro possa ter.


Padrão de Nomes dos Atributos

Dentro das classes de registros, os atributos devem seguir o seguinte padrão de nome:

rXX_NNNNN[_AUITO]

Onde:

  • r - Prefixo 'r' fixo, para indicar que trata-se de um atributo de registro do SPED;
  • XX - Número do atributo na documentação do SPED, sempre com dois dígitos. Utilizado para organizar o código e indicar a ordem de escrita dos atributos (número da coluna) no arquivo do SPED;
  • _ - Separador do número e o nome do atributo.
  • NNNNNN - Nome do atributo como definido no próprio arquivo do SPED.
  • [_AUTO] - O sufixo _AUTO é adicionado aos atributos que não são definidos diretamente quando o registro é criado/atualizado, mas sim pelo método calculateFields(), conforme explicado com mais detalhes em #calculateFields().


Exemplos de atributos da classe SPEDFiscal0000, que representa o registro 0000 do arquivo SPED Fiscal:

  • r02_COD_VER
  • r03_COD_FIN
  • r04_DT_INI
  • r05_DT_FIN
  • r06_NOME
  • r07_CNPJ


Padrão de Nomes dos Registros Filhos

Quando um registro apresenta um, ou uma coleção, de registros filhos o nome do atirbuto deve seguir o seguinte padrão de nome:

rXXXX

Onde:

  • r - prefixo para indicar que o atributo é um registro;
  • XXXX' - nome do registro filho que este atributo representa. Ex: C100 para o registro C100. O atributo pode ser uma coleção (list ou map) ou uma referência direta nos casos de 1:1.

Annotation SPEDField

Cada atributo criado nas classes filhas de SPEDRegister devem ser anotadas com a annotation SPEDField.

Essa annotation permite especificar o tipo de dado que é esperado no arquivo SPED, e garantir que o framework realize algumas validações no momento da escrita e ainda formate o valor no formato esperado. Por exemplo:

  • valida campos com o formato esperado, tipo CPF, CNPJ, Email, etc.;
  • valida o tamanho máximo do campo no arquivo para truncar Strings;
  • garante o número certo de decimais arredondando ou acrescentando zeros automaticamente ao valor, de acordo com a definição do manual do SPED.


Há mais definições no SPEDField, verificar JavaDoc do SPEDField

Métodos Internos da SPEDRegister

A classe pai de todos os registros já inclui alguns métodos com código padrão, ou simplesmente para definir a assinatura que permite o tratamento uniforme de todos os registros. São eles:

writeFileRegister()

Este método tem uma implementação padrão com a finalidade de escrever o conteúdo do registro no formato do arquivo SPED esperado. Escreve tanto o registro atual, como chama recursivamente os registros filhos encontrados recursivamente.

Note 64.png
Utiliza o padrão de nomes dos atributos
Esse método busca por reflexão os métodos que têm a assinatura de acordo com o nome padrão dos atributos definidos anteriormente.

Caso os métodos do registro fujam do padrão esperado, este método pode não funcionar corretamente.


countRegister()

Este método tem uma implementação padrão que retorna o total de registros (linhas) que é gerado por este registro e seus registros filhos. Útil para criar os registros de contadores de registros 9900 exigidos pelos SPED Fiscal e Contribuições.


get01_Register()

Como em todos os registros o primeiro atributo é sempre o código que identifica o registro, a classe SPEDRegister já mantém a assinatura do método get01_Register como padrão na classe pai para facilitar o manuseio, diminuindo casts.

No entanto, esse método é abstrato e deve sempre ser implementado pela classe filha, e deve retornar o nome código do registro (que, por via de regra, deve ser o sufixo da classe), por exemplo: C800, conforme definido para o campo 01 do registro no manual do SPED.


calculateFields()

Este método tem a finalidade de calcular todos os campos que são "calculáveis" a partir de outros, isto é, cuja definição de valor esteja definida no manual do SPED com uma regra de preenchimento baseado em outros campos. Um exemplo comum são os registros acumuladores de valores totais de registros filhos.


O objetivo desse método é permitir que campos que são calculados com base nos valores de outros registros possam ser calculados só ao final, ao invés de a cada vez que um novo registro é criado ou alterado.


Note 64.png
De Olho na Performance
Note que o objetivo aqui é melhorar a performance, logo, deve-se ponderar quando a definição de um campo deve ser feita no método calculateFields ou diretamente na definição do registro.


Por exemplo, se o campo é calculado com valores do próprio registro, e esse não sofre muita alteração, como por exemplo o campo total do preço de venda de um item, cujo valor é definido pela quantidade e custo por unidade do próprio registro, deve ser definido diretamente ao criar/alterar o registro. Já que esse cálculo não será refeito muitas vezes e não precisa ser recalculado quando outros registros são alterados, em outras palavras: não sofre influência de outros registros.


Em contra partida, registros de totalizadores, contadores, impostos, etc., que são calculados com base em outros registros do arquivos, podem (e devem) ser calculados so ao final, depois que todos os registros que alteram seu valor terminarem de ser criados. Esses valores devem ser atualizados somente no método de cálculo, já que se calcular a cada registro criado teremos um monte de cálculos desnecessários ocorrendo durante a criação do arquivo. Em outras palavras: esses atributos sofrem influência de outros registros.



Stop 256.png
Atributos Cálculados Devem Ter o Sufixo _AUTO
Lembre-se que todo o atributo atualizado automaticamente pelo método calculateFields() deve ter o sufixo _AUTO no seu nome para evidenciar para o desenvolvedor os campos que são calculados e os que necessariamente precisam ser definidos.

Assim, fica sempre evidente que qualquer valor definido neste registro provavelmente será alterado durante os cálculos automáticos de finalização do arquivo do SPED.


Java 256.png Sugestão de Override do calculateFields()
  @Override
  public void calculate(String uuid) throws RFWException {
    if (uuid == null || !uuid.equals(this.getLastUUID())) { // Se UUID recebido for diferente da última rodada de cálculo, devemos realizar os cálculos.

      // Realiza os cáculos que devem ser realizados antes dos cálculos dos registros filhos

      super.calculate(uuid); // Chama a classe pai para salvar o UUID e calcular os registros filhos recursivamente

      // Realiza os cálculos que dependen dos registros filhos já calculados
    }
  }

SPEDFiscalBuilder e SPEDContribBuilder

Essas classes são classes utilitárias de métodos estáticos para facilitar a tarefa de montar e manipular os arquivos de SPED e seus registros. Nesta classe são disponiblizados vários métodos utilitádios, alguns, são caracterizados pelos seus prefixos, veja:

  • add[Registro]() - os métodos add tem a finalidade de adicionar um determinado registro dentro da estrutura do SPED. Os argumentos solicitados dependem da necessidade de cada registro e pode haver mais de uma opção para a criação de um mesmo registro. Os detalhes de cada método estarão escritos no seu javadoc.

Os métodos de add basicamente criam o objeto e o adicionam ao arquivo SPED passado. Em alguns casos eles podem:

  • Cria automaticamente outros registros relacionados - (O método já recebe todos os parâmetros necessários e cria todos os registros pais ou relacionados automaticamente, quando faz sentido para a operação);
  • Garante que apenas um registro seja criado para a chave única - Alguns registros devem ser únicos, como por exemplo os registros de Pessoas (PF e PJ) ou de produtos, os métodos de Add verificam automaticamente se já existe um registro desses e, ao invés de criar um novo, retorna o registro que corresponde aos dados passados.


Note 64.png
Relacionamento e Acumuladores
Note que na especificação do SPED há registros que são únicos, outros tem um relacionamento 1:N (que podem ou não ser únicos de acordo com um identificador único / chave).

O método add criará o registro na estrutura se ele ainda não existir, porém, se for único duas ações podem ocorrer:

  • os dados do registro atual serão substituídos pelos novos valores recebidos; ou,
  • para registros que tem atributos cujos valores são acumulativos (como totais de venda agrupados por CFOP) o método add poderá acumular os valores automaticamente (somando o valor recebido com o valor já existente atualmente no atributo do registro).


Verifique o javadoc de cada método para mais detalhes sobre seu funcionamento.