#include "declaracao.h"
#include "cmd.h"
#include "rendimento.h"
+#include "isento.h"
#include "pagamento.h"
#include "bem.h"
+#include "dependente.h"
#include "totais.h"
+#include "sistema.h"
static void gera_header(struct declaracao *dec, FILE *f)
{
fprintf(f, "%s", dec->cpf); /* CPF: 11 dígitos */
fprintf(f, " "); /* Filler */
fprintf(f, "1"); /* Tipo NI: Pessoa Física (1) */
- fprintf(f, "100"); /* Versão IRPF */
+ fprintf(f, "130"); /* Versão IRPF */
fprintf(f, "%-60.60s", dec->nome);
fprintf(f, "%s", dec->contribuinte.uf);
fprintf(f, "%s", "0000000000"); /* FIXME: hash */
fprintf(f, "1"); /* TODO: certificavel */
- fprintf(f, "%s", dec->contribuinte.dn);
+ fprintf(f, "%-8.8s", dec->contribuinte.dn);
fprintf(f, "%s", dec->tipo == COMPLETA ? "S" : "N");
fprintf(f, "%s", dec->restituicao ? "2" : "0"); /* TODO: resultado imposto, 2 - restituicao */
fprintf(f, "S"); /* TODO: gerada? */
fprintf(f, "%-10.10s", dec->retifica ?: ""); /* recibo retificada ex. atual */
fprintf(f, "2"); /* TODO: PGD */
- fprintf(f, "LINUX "); /* TODO: SO */
- fprintf(f, "3.16.0-"); /* TODO: versao SO */
- fprintf(f, "1.7.0_75 "); /* TODO: versao JVM */
+ fprintf(f, "%-14.14s", sistema_get_so(dec));
+ fprintf(f, "%-7.7s", sistema_get_so_versao(dec));
+ fprintf(f, "%-9.9s", sistema_get_jvm_versao(dec));
fprintf(f, "%-10.10s", ""); /* TODO: última declaração transmitida (pode ser vazio?) */
fprintf(f, "%04d", dec->contribuinte.cd_municipio);
- fprintf(f, " "); /* TODO: CPF conjuge */
+ fprintf(f, "%-11.11s", dec->conjuge.cpf ? : ""); /* TODO: CPF conjuge */
fprintf(f, "%d", dec->obrigatoria ? 1 : 0); /* obrigatoria entrega */
fprintf(f, "%013lld", dec->devido); /* imposto devido, carne-leao, complementar dos dependentes */
fprintf(f, "%-10.10s", dec->recibo ?: ""); /* recibo ex. anterior */
fprintf(f, "%-40.40s", dec->contribuinte.municipio);
fprintf(f, "%-60.60s", dec->nome);
fprintf(f, "%-11.11s", ""); /* CPF empregada */
- fprintf(f, "000000000000"); /* FIXME: MAC */
+ fprintf(f, "%-12.12s", sistema_get_mac(dec));
fprintf(f, "%08d", 0); /* Data saída */
fprintf(f, "%-11.11s", ""); /* CPF procurador */
fprintf(f, "%03d", dec->obrigatoria); /* criterio obrigatoriedade */
fprintf(f, "%013lld", 0); /* TODO: rendimentos PF ext. depend. */
fprintf(f, "%013lld", 0); /* TODO: carnê-leão PF? */
fprintf(f, "%013lld", 0); /* TODO: carnê-leão dependentes */
- fprintf(f, "%013lld", 0); /* TODO: dedução dependentes */
+ fprintf(f, "%013lld", totais_get(dec, "DEPENDENTES")); /* TODO: dedução dependentes */
fprintf(f, "%013lld", 0); /* TODO: previdência RRA */
fprintf(f, "%013lld", 0); /* TODO: previdência RRA dependentes */
fprintf(f, "%013lld", 0); /* TODO: pensão RRA */
fprintf(f, "%013lld", 0); /* TODO: valor quota */
fprintf(f, "%013lld", totais_get(dec, "ISENTOS")); /* rendimentos isentos */
fprintf(f, "%013lld", totais_get(dec, "EXCLUSIVOS")); /* rendimentos tributação exclusiva */
- fprintf(f, "%013lld", 0); /* TODO: conjuge */
+ fprintf(f, "%013lld", dec->conjuge.total); /* TODO: conjuge */
fprintf(f, "%013lld", 0); /* TODO: rendimento PJ dependente */
fprintf(f, "%013lld", 0); /* TODO: imposto retido dependente */
fprintf(f, "%013lld", 0); /* TODO: imposto ganhos de capital */
/* FIXME: completar campos */
}
+static void gera_isentos(struct declaracao *dec, FILE *f)
+{
+ fprintf(f, "23");
+ fprintf(f, "%-11.11s", dec->cpf);
+ fprintf(f, "%013lld", 0); /* TODO: bolsa de estudo */
+ fprintf(f, "%013lld", 0); /* TODO: pecúlio de previdência privada */
+ fprintf(f, "%013lld", 0); /* TODO: FGTS, aviso prévio indenizado */
+ fprintf(f, "%013lld", 0); /* TODO: ganho de capital isento */
+ fprintf(f, "%013lld", 0); /* TODO: lucros e dividendos */
+ fprintf(f, "%013lld", 0); /* TODO: atividade rural */
+ fprintf(f, "%013lld", 0); /* TODO: contribuintes com 65 anos ou mais */
+ fprintf(f, "%013lld", 0); /* TODO: pensão por invalidez */
+ fprintf(f, "%013lld", totais_get(dec, "POUPANCA"));
+ fprintf(f, "%013lld", 0); /* TODO: sócio ou titular de empresa */
+ fprintf(f, "%013lld", 0); /* TODO: herança, transferências patrimoniais */
+ fprintf(f, "%013lld", 0); /* TODO: outros rendimentos isentos */
+ fprintf(f, "%-60.60s", ""); /* FILLER1 */
+ fprintf(f, "%-13.13s", ""); /* FILLER2 */
+ fprintf(f, "%013lld", 0); /* TODO: alienação bens pequeno valor */
+ fprintf(f, "%013lld", 0); /* TODO: alienação único imóvel */
+ fprintf(f, "%013lld", 0); /* TODO: redução ganho capital */
+ fprintf(f, "%013lld", 0); /* TODO: total bens pequeno valor, transportado GC */
+ fprintf(f, "%013lld", 0); /* TODO: alienção único imóvel, transportado GC */
+ fprintf(f, "%013lld", 0); /* TODO: redução ganho capital, transportado GC */
+ fprintf(f, "%013lld", 0); /* TODO: ganho capital - moeda estrangeira */
+ fprintf(f, "%013lld", 0); /* TODO: ganho capital - moeda estrangeira, transportado */
+ fprintf(f, "%013lld", 0); /* TODO: GC total informado */
+ fprintf(f, "%013lld", 0); /* TODO: GC total transportado */
+ fprintf(f, "%013lld", 0); /* TODO: imposto renda anos anteriores */
+ fprintf(f, "%013lld", 0); /* TODO: rencimentos assalariados moeda estrangeira */
+ fprintf(f, "%013lld", 0); /* TODO: bonificações ações */
+ fprintf(f, "%013lld", 0); /* TODO: médicos residentes */
+ fprintf(f, "%013lld", 0); /* TODO: volutários da Copa */
+ fprintf(f, "%013lld", 0); /* TODO: meação e dissolução */
+ fprintf(f, "%013lld", 0); /* TODO: ganhos líquidos com ações */
+ fprintf(f, "%013lld", 0); /* TODO: ganhos de capital com ouro */
+ fprintf(f, "%013lld", 0); /* TODO: recuperação prejuízos na bolsa */
+ fprintf(f, "%013lld", 0); /* TODO: transportador de cargas */
+ fprintf(f, "%013lld", 0); /* TODO: transportador de passageiros */
+ fprintf(f, "%013lld", 0); /* TODO: retistuição imposto anos anteriores */
+}
+
+static void gera_exclusivos(struct declaracao *dec, FILE *f)
+{
+ fprintf(f, "24");
+ fprintf(f, "%-11.11s", dec->cpf);
+ fprintf(f, "%013lld", totais_get(dec, "DECIMOTERCEIRO"));
+ fprintf(f, "%013lld", 0); /* TODO: ganho de capital */
+ fprintf(f, "%013lld", 0); /* TODO: ganho líquido renda variável */
+ fprintf(f, "%013lld", totais_get(dec, "APLICACOES")); /* TODO: aplicações financeiras */
+ fprintf(f, "%013lld", 0); /* TODO: outros */
+ fprintf(f, "%-60.60s", ""); /* FILLER1 */
+ fprintf(f, "%013lld", 0); /* TODO: ganhos de capital alienação de bens */
+ fprintf(f, "%013lld", 0); /* TODO: ganhos de capital moeda estrangeira */
+ fprintf(f, "%013lld", 0); /* TODO: décimo terceiro dependentes */
+ fprintf(f, "%-13.13s", ""); /* FILLER2 */
+ fprintf(f, "%-60.60s", ""); /* FILLER3 */
+ fprintf(f, "%013lld", 0); /* TODO: RRA */
+ fprintf(f, "%013lld", 0); /* TODO: RRA dependentes */
+ fprintf(f, "%013lld", 0); /* TODO: Juros capital próprio */
+ fprintf(f, "%013lld", totais_get(dec, "PLR"));
+}
+
+static void gera_conjuge(struct declaracao *dec, FILE *f)
+{
+ fprintf(f, "29");
+ fprintf(f, "%-11.11s", dec->cpf);
+ fprintf(f, "%-11.11s", dec->conjuge.cpf);
+ fprintf(f, "%013lld", dec->conjuge.base);
+ fprintf(f, "%013lld", dec->conjuge.imposto);
+ fprintf(f, "%013lld", dec->conjuge.isento);
+ fprintf(f, "%013lld", dec->conjuge.exclusivo);
+ fprintf(f, "%013lld", dec->conjuge.rendpj_exigibilidade_suspensa);
+ fprintf(f, "%013lld", dec->conjuge.total);
+ fprintf(f, "%c", dec->conjuge.entregou ? 'S' : 'N');
+}
+
static void gera_trailler(struct declaracao *dec, FILE *f)
{
int i;
fprintf(f, "R9");
fprintf(f, "%s", dec->cpf); /* CPF: 11 dígitos */
fprintf(f, "%-3.3s", ""); /* FILLER */
- fprintf(f, "%-10.10s", "0000000000"); /* FIXME: hash */
+ fprintf(f, "%010u", dec->rhash);
}
static void gera_rendimento(struct declaracao *dec, FILE *f)
fprintf(f, "T");
}
+static void gera_isento(struct declaracao *dec, FILE *f, int codigo)
+{
+ struct isento *i;
+ i = isento_get(dec, codigo, dec->linhas[codigo]);
+ fprintf(f, "%02d", codigo);
+ fprintf(f, "%-11.11s", dec->cpf); /* Titular, TODO: dependente */
+ fprintf(f, "%05d", dec->linhas[codigo] + 1); /* Chave */
+ fprintf(f, "%c", 'T'); /* FIXME: dependente */
+ fprintf(f, "%-14.14s", i->cnpj);
+ fprintf(f, "%-60.60s", i->nome);
+ fprintf(f, "%013lld", i->valor);
+ fprintf(f, "%-11.11s", dec->cpf);
+}
+
+static void gera_plr(struct declaracao *dec, FILE *f)
+{
+ gera_isento(dec, f, 96);
+}
+
+static void gera_poupanca(struct declaracao *dec, FILE *f)
+{
+ gera_isento(dec, f, 98);
+}
+
+static void gera_aplicacoes(struct declaracao *dec, FILE *f)
+{
+ gera_isento(dec, f, 99);
+}
+
+static void gera_dependente(struct declaracao *dec, FILE *f)
+{
+ struct dependente *d;
+ d = list_get(dec->dependentes, dec->linhas[25]);
+
+ fprintf(f, "25");
+ fprintf(f, "%s", dec->cpf);
+ fprintf(f, "%05d", dec->linhas[25] + 1);
+ fprintf(f, "%02d", d->codigo);
+ fprintf(f, "%-60.60s", d->nome);
+ fprintf(f, "%-8.8s", d->dn);
+ fprintf(f, "%-11.11s", d->cpf);
+ /* TODO: Indicador de saída */
+ fprintf(f, " ");
+}
+
static void gera_bem(struct declaracao *dec, FILE *f)
{
struct bem *b;
typedef void (gera_linha)(struct declaracao *dec, FILE *f);
-static int wrap(gera_linha fn, struct declaracao *dec, FILE *f)
+static void update_hash(struct declaracao *dec, char *buf, size_t len)
+{
+ int r;
+ int linha;
+ r = sscanf(buf, "%2d", &linha);
+ if (r == 1 || !strncmp(buf, "T9", 2)) {
+ dec->hash = crc32(dec->hash, buf, len - 2);
+ dec->rhash = crc32(dec->rhash, buf, len - 2);
+ return;
+ } else if (strncmp(buf, "R9", 2) && strncmp(buf, "IRPF", 4)) {
+ dec->rhash = crc32(dec->rhash, buf, len - 2);
+ }
+}
+
+static int wrap(gera_linha fn, struct declaracao *dec, struct list *l)
{
FILE *m;
char *buf = NULL;
if (r == 1 && linha >= 0 && linha < 100) {
dec->linhas[linha]++;
}
- fwrite(buf, bsize, 1, f);
- free(buf);
- return 0;
+ update_hash(dec, buf, bsize);
+ return list_add(&l, buf);
+}
+
+static void insert_hash(struct declaracao *dec, char *irpf)
+{
+ uLong c = crc32(0L, NULL, 0);
+ char cpf[13];
+ char crc[11];
+ snprintf(cpf, 13, "%-8.8s.DEC", dec->cpf);
+ c = crc32(c, cpf, 12);
+ snprintf(crc, 11, "%010ld", dec->hash);
+ memcpy(irpf + 101, crc, 10);
+ c = crc32(c, irpf, strlen(irpf) - 12);
+ snprintf(crc, 11, "%010ld", c);
+ memcpy(irpf + strlen(irpf) - 12, crc, 10);
}
static int gera(struct declaracao *dec, char *filename)
int r;
int i;
struct rendimento *rendimento;
+ struct isento *isento;
struct pagamento *pagamento;
struct bem *bem;
+ struct dependente *dependente;
+ struct list *linhas;
+ char *buf;
+
+ linhas = list_new();
+ if (!linhas)
+ return -ENOMEM;
+
+ dec->hash = crc32(0L, NULL, 0);
+ dec->rhash = crc32(0L, NULL, 0);
-#define W(fn, dec, f) \
+#define W(fn) \
do { \
- r = wrap(fn, dec, f); \
+ r = wrap(fn, dec, linhas); \
if (r < 0) \
goto out; \
} while (0);
f = fopen(filename, "w");
if (!f)
- return -errno;
+ goto out_file;
memset(dec->linhas, 0, sizeof(dec->linhas));
- W(gera_header, dec, f);
- W(gera_contribuinte, dec, f);
+ W(gera_header);
+ W(gera_contribuinte);
if (dec->tipo == COMPLETA) {
- W(gera_completa, dec, f);
- W(gera_totais_completa, dec, f);
+ W(gera_completa);
+ W(gera_totais_completa);
} else {
- W(gera_simples, dec, f);
- W(gera_totais_simples, dec, f);
+ W(gera_simples);
+ W(gera_totais_simples);
}
for (i = 0; rendimento = list_get(dec->rendimento, i); i++) {
- W(gera_rendimento, dec, f);
+ W(gera_rendimento);
+ }
+
+ W(gera_isentos);
+ W(gera_exclusivos);
+
+ for (i = 0; (dependente = list_get(dec->dependentes, i)); i++) {
+ W(gera_dependente);
}
for (i = 0; (pagamento = list_get(dec->pagamentos, i)); i++) {
- W(gera_pagamento, dec, f);
+ W(gera_pagamento);
}
for (i = 0; (bem = list_get(dec->bens, i)); i++) {
- W(gera_bem, dec, f);
+ W(gera_bem);
+ }
+
+ W(gera_conjuge);
+
+ /* Rendimentos isentos e com tributação exclusiva */
+ /* Registros 82 a 89, e 92 a 99 */
+#define IW(fn, codigo) \
+ for (i = 0; ; i++) { \
+ isento = isento_get(dec, codigo, i); \
+ if (!isento) \
+ break; \
+ W(fn); \
+ }
+ IW(gera_plr, 96);
+ IW(gera_poupanca, 98);
+ IW(gera_aplicacoes, 99);
+
+ W(gera_trailler);
+ W(gera_reciboheader);
+ W(gera_recibodetalhe);
+ W(gera_recibotrailler);
+
+ insert_hash(dec, list_get(linhas, 0));
+ for (i = 0; (buf = list_get(linhas, i)); i++) {
+ fwrite(buf, strlen(buf), 1, f);
}
- W(gera_trailler, dec, f);
- W(gera_reciboheader, dec, f);
- W(gera_recibodetalhe, dec, f);
- W(gera_recibotrailler, dec, f);
+
fclose(f);
+ list_free(linhas, free);
return 0;
out:
fclose(f);
+out_file:
+ list_free(linhas, free);
return r;
}