Permite importação de declarações.
authorThadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
Mon, 9 Apr 2018 23:13:54 +0000 (20:13 -0300)
committerThadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
Tue, 10 Apr 2018 03:01:59 +0000 (00:01 -0300)
Arquivos de declaração gerados para transmissão podem agora ser importados.

A importação não realiza alguns cálculos e, portanto, deve ser utilizada apenas
para salvar novo arquivo, que deve ser reprocessado.

lib/Makefile.am
lib/declaracao.c
lib/importa.c [new file with mode: 0644]
lib/importa.h [new file with mode: 0644]

index ecc17d4..a7586db 100644 (file)
@@ -8,6 +8,7 @@ libreceita_la_SOURCES = declaracao.c declaracao.h \
        sistema.c sistema.h \
        calcula.c calcula.h \
        gera.c gera.h \
+       importa.c importa.h \
        base.c base.h \
        list.c list.h \
        util.c util.h \
index 2fa6c4a..affe8d6 100644 (file)
@@ -146,6 +146,7 @@ void dec_cmd_init(void)
        dependente_cmd_init();
        calcula_cmd_init();
        gera_cmd_init();
+       importa_cmd_init();
        sistema_cmd_init();
        help_cmd_init();
 }
diff --git a/lib/importa.c b/lib/importa.c
new file mode 100644 (file)
index 0000000..c78ca36
--- /dev/null
@@ -0,0 +1,616 @@
+/*
+ *  Copyright (C) 2015-2018  Thadeu Lima de Souza Cascardo <cascardo@minaslivre.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "importa.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <zlib.h>
+#include "declaracao.h"
+#include "cmd.h"
+#include "rendimento.h"
+#include "carne.h"
+#include "isento.h"
+#include "pagamento.h"
+#include "bem.h"
+#include "dependente.h"
+#include "totais.h"
+#include "sistema.h"
+#include "ano.h"
+
+#define COPY(size) \
+       if (size > sizeof(buffer) - 2) \
+               return -ENOSPC; \
+       if (pos + size >= len) \
+               return pos; \
+       memcpy(buffer, line + pos, size); \
+       buffer[size] = 0; \
+       pos += size;
+
+#define COPYI(field, size) \
+       COPY(size) \
+       field = atoi(buffer);
+
+#define COPYL(field, size) \
+       COPY(size) \
+       field = strtoull(buffer, NULL, 10);
+
+#define COPYS(field, size) \
+       COPY(size); \
+       field = strdup(buffer);
+
+#define COPYDI(field, size) \
+       COPYI(dec->field, size)
+
+#define COPYDL(field, size) \
+       COPYL(dec->field, size)
+
+#define COPYDS(field, size) \
+       COPYS(dec->field, size)
+
+#define COPYC(field, size) \
+       COPYS(dec->contribuinte.field, size)
+
+static int importa_header(struct declaracao *dec, char *line, size_t len)
+{
+       int pos = 0;
+       char buffer[256];
+
+       pos += 8;
+       COPYDI(ano, 4);
+       pos += 4;
+       pos += 4;
+       pos += 1;
+       COPYDS(cpf, 11);
+       pos += 3;
+       pos += 1;
+       pos += 3;
+       COPYDS(nome, 60);
+       COPYC(uf, 2);
+       pos += 10;
+       pos += 1;
+       COPYC(dn, 8);
+       COPY(1);
+       if (buffer[0] == 'S')
+               dec->tipo = COMPLETA;
+       else
+               dec->tipo = SIMPLES;
+       pos += 1;
+       pos += 1;
+       COPYDS(retifica, 10);
+       pos += 1;
+       COPYDS(sistema.so, 14);
+       COPYDS(sistema.so_versao, 7);
+       COPYDS(sistema.jvm_versao, 9);
+       pos += 10;
+       COPYDI(contribuinte.cd_municipio, 4);
+       pos += 11;
+       pos += 1;
+       pos += 13;
+       COPYDS(recibo, 10);
+
+       //fprintf(f, "%d", dec->retifica ? 0 : (dec->recibo ? 2 : 1));
+       pos += 1;
+
+       pos += 2;
+       pos += 1;
+       pos += 1;
+       COPYC(cep, 8);
+       pos += 1;
+       COPYDS(banco, 3);
+       COPYDS(agencia, 4);
+       pos += 1;
+       pos += 8;
+       pos += 13;
+       pos += 1;
+       pos += 11;
+       pos += 1;
+       pos += 11;
+       pos += 1;
+       pos += 11;
+       pos += 1;
+       pos += 11;
+       pos += 13;
+       pos += 14 * 4;
+       pos += 114;
+       pos += 14;
+       pos += 14;
+       pos += 11;
+       pos += 11;
+       COPYC(municipio, 40);
+       pos += 60;
+       pos += 11;
+       COPYDS(sistema.mac, 12);
+       pos += 8;
+       pos += 11;
+       pos += 3;
+       pos += 13;
+       pos += 14;
+       pos += 14;
+       pos += 13;
+       pos += 13;
+       pos += 13;
+       pos += 13;
+       COPYDS(dvconta, 2);
+       pos += 1;
+       COPYDI(contribuinte.natureza_ocupacao, 2);
+       pos += 66;
+       pos += 10;
+
+       /* Mudanças de 2016 */
+
+       if (dec->ano >= 2016) {
+               pos += 7 * 14;
+       }
+
+       /* Fim das mudanças de 2016 */
+
+       pos += 3;
+
+       return pos;
+}
+
+static int importa_contribuinte(struct declaracao *dec, char *line, size_t len)
+{
+       int pos = 0;
+       char buffer[256];
+
+       pos += 2;
+       pos += 11;
+
+       COPYDS(nome, 60);
+       COPYC(tipo_logradouro, 15);
+       COPYC(logradouro, 40);
+       COPYC(numero, 6);
+       COPYC(complemento, 21);
+       COPYC(bairro, 19);
+       COPYC(cep, 8);
+       pos += 1;
+       COPYDI(contribuinte.cd_municipio, 4);
+       COPYC(municipio, 40);
+       COPYC(uf, 2);
+       pos += 3;
+       pos += 3;
+
+       if (dec->ano == 2015) {
+               pos += 112;
+       } else if (dec->ano >= 2016) {
+               pos += 90;
+               COPYC(nit, 11);
+               COPYDS(conjuge.cpf, 11);
+       }
+       if (dec->ano <= 2017) {
+               COPYC(ddd, 4);
+               COPYC(telefone, 9);
+       } else {
+               pos += 13;
+       }
+       COPYC(dn, 8);
+       COPYC(titulo_eleitor, 13);
+       COPYDI(contribuinte.ocupacao_principal, 3);
+       COPYDI(contribuinte.natureza_ocupacao, 2);
+       pos += 1;
+       pos += 1;
+       pos += 1;
+       pos += 1;
+       pos += 1;
+       COPYDS(retifica, 12);
+       COPYDS(banco, 3);
+       COPYDS(agencia, 4);
+       pos += 1;
+       pos += 1;
+       COPYDS(contacorrente, 13);
+       COPYDS(dvconta, 2);
+       pos += 1;
+       pos += 1;
+       pos += 14;
+       COPYDS(recibo, 10);
+       pos += 1;
+       pos += 11;
+       if (dec->ano >= 2016)
+               pos += 20;
+       if (dec->ano >= 2017) {
+               COPYC(celular, 11);
+               pos += 1;
+       }
+       if (dec->ano >= 2018) {
+               COPYC(ddd, 2);
+               COPYC(telefone, 9);
+       }
+
+       return pos;
+}
+
+static int importa_conjuge(struct declaracao *dec, char *line, size_t len)
+{
+       int pos = 0;
+       char buffer[256];
+
+       pos += 2;
+       pos += 11;
+       COPYDS(conjuge.cpf, 11);
+       COPYDL(conjuge.base, 13);
+       COPYDL(conjuge.imposto, 13);
+       COPYDL(conjuge.isento, 13);
+       COPYDL(conjuge.exclusivo, 13);
+       COPYDL(conjuge.rendpj_exigibilidade_suspensa, 13);
+       COPYDL(conjuge.total, 13);
+       COPY(1);
+       if (buffer[0] == 'S')
+               dec->conjuge.entregou = 1;
+       else
+               dec->conjuge.entregou = 0;
+
+       return pos;
+}
+
+static int ignore_line(struct declaracao *dec, char *line, size_t len)
+{
+       return 0;
+}
+
+static int importa_rendimento(struct declaracao *dec, char *line, size_t len)
+{
+       struct rendimento *rend;
+       int pos = 0;
+       char buffer[256];
+       int r;
+
+       rend = malloc(sizeof(*rend));
+       if (!rend)
+               return -ENOMEM;
+       pos += 2;
+       pos += 11;
+       COPYS(rend->cnpj, 14);
+       COPYS(rend->nome, 60);
+       COPYL(rend->rendimento, 13);
+       COPYL(rend->previdencia, 13);
+       COPYL(rend->decimoterceiro, 13);
+       COPYL(rend->imposto, 13);
+       COPYS(rend->saida, 8);
+       COPYL(rend->imposto_13o, 13);
+       if ((r = list_add(&dec->rendimento, rend)) < 0) {
+               rendimento_free(rend);
+               return r;
+       }
+       return pos;
+}
+
+static int importa_pagamento(struct declaracao *dec, char *line, size_t len)
+{
+       struct pagamento *p;
+       int pos = 0;
+       char buffer[256];
+       int r;
+
+       p = malloc(sizeof(*p));
+       if (!p)
+               return -ENOMEM;
+
+       pos += 2;
+       pos += 11;
+       COPYI(p->codigo, 2);
+       COPYI(p->dependente, 5);
+       COPYS(p->cnpj, 14);
+       COPYS(p->nome, 60);
+       /* TODO: NIT */
+       pos += 11;
+       COPYL(p->pagamento, 13);
+       COPYL(p->reembolso, 13);
+       if (dec->ano >= 2016) {
+               /* TODO: contribuição do ente público patrocinador (FUNPRESP?) */
+               pos += 13;
+       }
+       /* PF ou PJ? */
+       pos += 1;
+       /* Titular (T), Dependente (D), Alimentando (A), FIXME Alimentando */
+       pos += 1;
+       if ((r = list_add(&dec->pagamentos, p)) < 0) {
+               pagamento_free(p);
+               return r;
+       }
+       return pos;
+}
+
+static int importa_isento(struct declaracao *dec, char *line, size_t len)
+{
+       struct isento *i;
+       int pos = 0;
+       char buffer[256];
+       int r;
+
+       i = malloc(sizeof(*i));
+       if (!i)
+               return -ENOMEM;
+
+       COPYI(i->codigo, 2);
+       pos += 11;
+       pos += 5;
+       /* Titular (T), Dependente (D), Alimentando (A), FIXME Alimentando */
+       pos += 1;
+       COPYS(i->cnpj, 14);
+       COPYS(i->nome, 60);
+       COPYL(i->valor, 13);
+       /* TODO: Suportar dependente */
+       pos += 11;
+       if ((r = list_add(&dec->isentos, i)) < 0) {
+               isento_free(i);
+               return r;
+       }
+       return pos;
+}
+
+static int importa_outrosisentos(struct declaracao *dec, char *line, size_t len)
+{
+       struct isento *i;
+       int pos = 0;
+       char buffer[256];
+       int r;
+
+       r = importa_isento(dec, line, len);
+       if (r > 0)
+               pos = r;
+       else
+               return r;
+       i = list_get(dec->isentos, list_size(dec->isentos));
+       if (!i)
+               return -EINVAL;
+       COPYI(i->exclusivo, 1);
+       i->exclusivo -= 1;
+       COPYS(i->descricao, 60);
+       return pos;
+}
+
+static int importa_isento2(struct declaracao *dec, char *line, size_t len)
+{
+       struct isento *i;
+       int pos = 0;
+       char buffer[256];
+       int r;
+
+       i = malloc(sizeof(*i));
+       if (!i)
+               return -ENOMEM;
+
+       pos += 2;
+       pos += 11;
+       /* TODO: Suporte a dependente */
+       pos += 1;
+       pos += 11;
+       /* Sub-código */
+       COPYI(i->codigo, 4);
+       COPYS(i->cnpj, 14);
+       COPYS(i->nome, 60);
+       COPYL(i->valor, 13);
+       if ((r = list_add(&dec->isentos, i)) < 0) {
+               isento_free(i);
+               return r;
+       }
+       return pos;
+}
+
+
+static int importa_dependente(struct declaracao *dec, char *line, size_t len)
+{
+       struct dependente *d;
+       int pos = 0;
+       char buffer[256];
+       int r;
+
+       d = malloc(sizeof(*d));
+       if (!d)
+               return -ENOMEM;
+
+       pos += 2;
+       pos += 11;
+       pos += 5;
+       COPYI(d->codigo, 2);
+       COPYS(d->nome, 60);
+       COPYS(d->dn, 8);
+       COPYS(d->cpf, 11);
+       pos += 1;
+       if (dec->ano >= 2016) {
+               /* TODO: NIT/PIS/PASEP de Pessoa Física no exterior */
+               pos += 11;
+       }
+       if ((r = list_add(&dec->dependentes, d)) < 0) {
+               dependente_free(d);
+               return r;
+       }
+       return pos;
+}
+
+static int importa_bem(struct declaracao *dec, char *line, size_t len)
+{
+       struct bem *b;
+       int pos = 0;
+       char buffer[514];
+       int r;
+
+       b = malloc(sizeof(*b));
+       if (!b)
+               return -ENOMEM;
+
+       pos += 2;
+       pos += 11;
+       COPYI(b->codigo, 2);
+
+       /* FIXME: exterior */
+       pos += 1;
+       pos += 3;
+
+       COPYS(b->descricao, 512);
+       COPYL(b->valor_anterior, 13);
+       COPYL(b->valor, 13);
+
+       /* Imóvel */
+       COPYS(b->logradouro, 40);
+       COPYS(b->numero, 6);
+       COPYS(b->complemento, 40);
+       COPYS(b->bairro, 40);
+       COPYS(b->cep, 9);
+       COPYS(b->uf, 2);
+       COPYI(b->cd_municipio, 4);
+       COPYS(b->municipio, 40);
+       /* FIXME: Registro de imóveis, Nao (0), Sim (1), Vazio (2) */
+       pos += 1;
+       COPYS(b->matricula, 40);
+       COPYS(b->registro, 40);
+       COPYL(b->area, 11);
+       /* FIXME: Area, M2 (0), Ha (1), Vazio (2) */
+       pos += 1;
+       COPYS(b->cartorio, 60);
+
+       /* Número de chave */
+       pos += 5;
+       if ((r = list_add(&dec->bens, b)) < 0) {
+               bem_free(b);
+               return r;
+       }
+       return pos;
+}
+
+static int importa_carne(struct declaracao *dec, char *line, size_t len)
+{
+       struct carne *carne;
+       int pos = 0;
+       char buffer[256];
+       int r;
+
+       carne = malloc(sizeof(*carne));
+       if (!carne)
+               return -ENOMEM;
+       pos += 2;
+       pos += 11;
+       COPY(1);
+       if (buffer[0] == 'S') {
+               return -ENOTSUP;
+       }
+       pos += 11;
+       COPYI(carne->mes, 2);
+       COPYL(carne->rendimento, 13);
+       COPYL(carne->alugueis, 13);
+       COPYL(carne->outros, 13);
+       COPYL(carne->exterior, 13);
+       COPYL(carne->caixa, 13);
+       COPYL(carne->alimentos, 13);
+       COPYL(carne->dependentes, 13);
+       COPYL(carne->previdencia, 13);
+       COPYL(carne->base, 13);
+       COPYL(carne->imposto, 13);
+       if ((r = list_add(&dec->carne, carne)) < 0) {
+               carne_free(carne);
+               return r;
+       }
+       return pos;
+}
+
+static struct {
+       char *prefix;
+       int (*func)(struct declaracao *, char *, size_t);
+} prefixes[] = {
+       { "IRPF", importa_header },
+       { "16", importa_contribuinte },
+       { "17", ignore_line },
+       { "18", ignore_line },
+       { "19", ignore_line },
+       { "20", ignore_line },
+       { "21", importa_rendimento },
+       { "22", importa_carne },
+       { "23", ignore_line },
+       { "24", ignore_line },
+       { "25", importa_dependente },
+       { "26", importa_pagamento },
+       { "27", importa_bem },
+       { "29", importa_conjuge },
+       { "82", importa_isento },
+       { "84", importa_isento2 },
+       { "88", importa_isento2 },
+       { "93", importa_isento },
+       { "96", importa_isento },
+       { "97", importa_outrosisentos },
+       { "98", importa_isento },
+       { "99", importa_isento },
+       { "T9", ignore_line },
+       { "HR", ignore_line },
+       { "DR", ignore_line },
+       { "R9", ignore_line },
+};
+
+static int importa_linha(struct declaracao *dec, char *line, size_t len)
+{
+       int i;
+
+       for (i = 0; i < sizeof(prefixes)/sizeof(prefixes[0]); i++)
+               if (!strncmp(prefixes[i].prefix, line, strlen(prefixes[i].prefix)))
+                       return prefixes[i].func(dec, line, len);
+
+       return -EINVAL;
+}
+
+static int importa(struct declaracao *dec, char *filename)
+{
+       char *line = NULL;
+       size_t lsz = 0;
+       FILE *f;
+       int r = 0;
+       int n = 1;
+
+       f = fopen(filename, "r");
+       if (!f) {
+               r = -errno;
+               dec_set_error(dec, "Não foi possível abrir arquivo %s: %s.",
+                             filename, strerror(errno));
+               goto out_file;
+       }
+       while ((r = getline(&line, &lsz, f)) > 0) {
+               r = importa_linha(dec, line, r);
+               if (r < 0) {
+                       fprintf(stderr, "Não foi possível importar linha %d: %s\n",
+                               n, dec->error ?: strerror(-r));
+               }
+               n++;
+       }
+
+       fclose(f);
+       return 0;
+out_file:
+       return r;
+}
+
+static int run_importa(struct declaracao *dec, char **args, int argc)
+{
+       if (argc != 2) {
+               dec_set_error(dec, "Comando %s recebe um nome de arquivo como parâmetro.",
+                             args[0]);
+               return -EINVAL;
+       }
+       return importa(dec, args[1]);
+}
+
+static struct cmd cmd_importa = {
+       .name = "importa",
+       .run = run_importa,
+};
+
+int importa_cmd_init(void)
+{
+       cmd_add(&cmd_importa);
+       return 0;
+}
diff --git a/lib/importa.h b/lib/importa.h
new file mode 100644 (file)
index 0000000..4728c5a
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *  Copyright (C) 2018  Thadeu Lima de Souza Cascardo <cascardo@minaslivre.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _IMPORTA_H
+#define _IMPORTA_H
+
+int importa_cmd_init(void);
+
+#endif