ab023d79c6bd190889a694249f5b24d27ea5370a
[cascardo/declara.git] / lib / isento.c
1 /*
2  *  Copyright (C) 2015  Thadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along
15  *  with this program; if not, write to the Free Software Foundation, Inc.,
16  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 #include "isento.h"
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include "cmd.h"
26 #include "list.h"
27 #include "util.h"
28 #include "totais.h"
29
30 static int isento_totais_update(struct declaracao *dec, struct isento *isento)
31 {
32         int r = 0;
33         switch (isento->codigo) {
34         case 82:
35                 isento->exclusivo = 0;
36                 r = totais_add(dec, "DOACOES", isento->valor);
37                 break;
38         case 93:
39                 isento->exclusivo = 0;
40                 r = totais_add(dec, "INDENIZACOES", isento->valor);
41                 break;
42         case 11:
43         case 96:
44                 isento->exclusivo = 1;
45                 r = totais_add(dec, "PLR", isento->valor);
46                 break;
47         case 97:
48         case 26:
49                 isento->exclusivo = 0;
50                 r = totais_add(dec, "OUTROSISENTOS", isento->valor);
51                 break;
52         case 12:
53         case 98:
54                 isento->exclusivo = 0;
55                 r = totais_add(dec, "POUPANCA", isento->valor);
56                 break;
57         case 13:
58                 isento->exclusivo = 0;
59                 r = totais_add(dec, "LUCROME", isento->valor);
60                 break;
61         case 6:
62         case 99:
63                 isento->exclusivo = 1;
64                 r = totais_add(dec, "APLICACOES", isento->valor);
65                 break;
66         }
67         if (isento->exclusivo) {
68                 r += totais_add(dec, "EXCLUSIVOS", isento->valor);
69                 if (isento->dependente) {
70                         r += totais_add(dec, "EXCLUSIVOSDEP", isento->valor);
71                 } else {
72                         r += totais_add(dec, "EXCLUSIVOSTIT", isento->valor);
73                 }
74         } else {
75                 r += totais_add(dec, "ISENTOS", isento->valor);
76                 if (isento->dependente) {
77                         r += totais_add(dec, "ISENTOSDEP", isento->valor);
78                 } else {
79                         r += totais_add(dec, "ISENTOSTIT", isento->valor);
80                 }
81         }
82         return r;
83 }
84
85 void isento_free(void *pointer)
86 {
87         struct isento *isento = pointer;
88         if (isento->cnpj)
89                 free(isento->cnpj);
90         if (isento->nome)
91                 free(isento->nome);
92         if (isento->descricao)
93                 free(isento->descricao);
94         free(isento);
95 }
96
97 static int isento_cmp(void *p1, void *p2)
98 {
99         struct isento *r1 = p1;
100         struct isento *r2 = p2;
101         if (r1->exclusivo != r2->exclusivo)
102                 return r2->exclusivo - r1->exclusivo;
103         /* O rendimento maior vem primeiro. */
104         if (r1->valor > r2->valor)
105                 return -1;
106         else if (r1->valor < r2->valor)
107                 return 1;
108         return 0;
109 }
110
111 static struct isento * isento_new(char **args, int argc)
112 {
113         struct isento *isento;
114         int r = 0;
115         isento = malloc(sizeof(*isento));
116
117         isento->exclusivo = 0;
118         if (!strcmp(args[0], "exclusivo")) {
119                 isento->exclusivo = 1;
120         }
121
122         r += set_int(args[1], &isento->codigo);
123         r += set_string(args[2], &isento->cnpj);
124         r += set_string(args[3], &isento->nome);
125         r += set_llong(args[4], &isento->valor);
126         if (r < 0 || isento->codigo < 0 ||
127             isento->valor < 0) {
128                 isento_free(isento);
129                 return NULL;
130         }
131         if (argc == 6) {
132                 r = set_int(args[5], &isento->dependente);
133         } else {
134                 isento->dependente = 0;
135         }
136         if (r < 0 || isento->dependente < 0) {
137                 isento_free(isento);
138                 return NULL;
139         }
140         if (argc == 7) {
141                 r = set_string(args[6], &isento->descricao);
142                 if (r < 0) {
143                         isento_free(isento);
144                         return NULL;
145                 }
146         } else {
147                 isento->descricao = NULL;
148         }
149         return isento;
150 }
151
152 static int run_isento(struct declaracao *dec, char **args, int argc)
153 {
154         struct isento *isento;
155         int r;
156         if (argc < 5 || argc > 7)
157                 return -EINVAL;
158         isento = isento_new(args, argc);
159         if (!isento)
160                 return -ENOMEM;
161         if (isento->dependente > list_size(dec->dependentes)) {
162                 isento_free(isento);
163                 return -EINVAL;
164         }
165         r = isento_totais_update(dec, isento);
166         if (r) {
167                 isento_free(isento);
168                 return r;
169         }
170         r = list_add(&dec->isentos, isento);
171         if (r < 0) {
172                 isento_free(isento);
173                 return r;
174         }
175         return 0;
176 }
177
178 void isento_salva(struct declaracao *dec, FILE *f)
179 {
180         int i;
181         struct isento *j;
182         for (i = 0; j = list_get(dec->isentos, i); i++) {
183                 if (j->codigo == 97 && j->exclusivo)
184                         fprintf(f, "exclusivo ");
185                 else
186                         fprintf(f, "isento ");
187                 fprintf(f, "%d \"%s\" \"%s\" %lld %d",
188                         j->codigo, j->cnpj, j->nome, j->valor, j->dependente);
189                 if (j->descricao)
190                         fprintf(f, " \"%s\"", j->descricao);
191                 fprintf(f, "\n");
192         }
193 }
194
195 static struct cmd cmd_isento = {
196         .name = "isento",
197         .run = run_isento,
198 };
199
200 static struct cmd cmd_exclusivo = {
201         .name = "exclusivo",
202         .run = run_isento,
203 };
204
205 int isento_cmd_init(void)
206 {
207         cmd_add(&cmd_isento);
208         cmd_add(&cmd_exclusivo);
209         return 0;
210 }
211
212 struct isento * isento_get(struct declaracao *dec, int codigo, int n)
213 {
214         struct isento *isento;
215         int i;
216         int j = 0;
217         for (i = 0; (isento = list_get(dec->isentos, i)); i++) {
218                 if (isento->codigo == codigo && j++ == n)
219                         break;
220         }
221         return isento;
222 }