From dd00f87d72820e15332e947df6256db5cda4aa91 Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Mon, 9 Apr 2018 20:13:54 -0300 Subject: [PATCH] =?utf8?q?Permite=20importa=C3=A7=C3=A3o=20de=20declara?= =?utf8?q?=C3=A7=C3=B5es.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 | 1 + lib/declaracao.c | 1 + lib/importa.c | 616 +++++++++++++++++++++++++++++++++++++++++++++++ lib/importa.h | 24 ++ 4 files changed, 642 insertions(+) create mode 100644 lib/importa.c create mode 100644 lib/importa.h diff --git a/lib/Makefile.am b/lib/Makefile.am index ecc17d4..a7586db 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -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 \ diff --git a/lib/declaracao.c b/lib/declaracao.c index 2fa6c4a..affe8d6 100644 --- a/lib/declaracao.c +++ b/lib/declaracao.c @@ -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 index 0000000..c78ca36 --- /dev/null +++ b/lib/importa.c @@ -0,0 +1,616 @@ +/* + * Copyright (C) 2015-2018 Thadeu Lima de Souza Cascardo + * + * 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 +#include +#include +#include +#include +#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 index 0000000..4728c5a --- /dev/null +++ b/lib/importa.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2018 Thadeu Lima de Souza Cascardo + * + * 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 -- 2.20.1