]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs_gui/facturas.c
6de465efc3a7bc2df366a5c8074fa8044220e4d2
[z.facultad/75.06/emufs.git] / emufs_gui / facturas.c
1
2 #include "facturas.h"
3 #include "idx.h"
4 #include "common.h"
5 #include "menu.h"
6 #include "lista.h"
7 #include "articulos.h"
8 #include "base.h"
9 #include "extsort.h"
10
11 static t_LstFacturas *lst_facturas;
12
13 /* Procesa una factura antes de enviarla al archivo para guardarla */
14 static void *procesar_guardar_factura(t_Factura *f, t_LstFacturas *lst, EMUFS_REG_SIZE *size);
15 static int procesar_leer_factura(t_Factura *dst, void *src, EMUFS_REG_SIZE size, t_LstFacturas *lst);
16
17 #ifdef TP_PRIMER_ENTREGA
18 /* Manejo de la lista en memoria */
19 static t_Reg_Factura *crear_nodo_factura(EMUFS_REG_ID reg, EMUFS_REG_ID texto, unsigned int num);
20 static int agregar_nodo_factura(t_LstFacturas *lst, t_Reg_Factura *nodo);
21 int eliminar_nodo_factura(t_LstFacturas *lst, t_Reg_Factura *nodo);
22 #endif
23
24 static void dump_facturas(char *tmpfile);
25
26 /* Tipo de dato a meter en el archivo para un ord. externo */
27 typedef struct _ord_data_ {
28         int numero;
29         char emision[9];
30         char estado[3];
31         char fp[3];
32         float importe;
33 } t_OrdExt_Data;
34
35 int comparar_externo(void *it1, void *it2);
36
37 /* Funciones para carga desde el XML */
38 static t_Item *leer_items(xmlNode *, int *cant, int size);
39 static char *leer_nota(xmlNode *, int max);
40
41 t_LstFacturas *fact_get_lst()
42 {
43         return lst_facturas;
44 }
45
46 /* Hack! ... Si no existe propiedad retorna "" */
47 char *xml_get_prop(xmlNode *node, char *nombre)
48 {
49         char *s;
50         s = xmlGetProp(node, nombre);
51         if (s == NULL) {
52                 s = malloc(1);
53                 s[0] = '\0';
54                 return s;
55         }
56         return s;
57 }
58
59 #ifdef TP_PRIMER_ENTREGA
60 int eliminar_nodo_factura(t_LstFacturas *lst, t_Reg_Factura *nodo)
61 {
62         if (nodo == NULL) return 0;
63         if (nodo->ant == NULL) {
64                 /* Me piden borrar el primer nodo */
65                 if (nodo->sig) {
66                         nodo->sig->ant = NULL;
67                 }
68                 lst->primero = nodo->sig;
69         } else {
70                 if (nodo->sig) {
71                         nodo->sig->ant = nodo->ant;
72                 }
73                 nodo->ant->sig = nodo->sig;
74         }
75         free(nodo);
76         return 1;
77 }
78
79 t_Reg_Factura *crear_nodo_factura(EMUFS_REG_ID reg, EMUFS_REG_ID texto, unsigned int num)
80 {
81         t_Reg_Factura *tmp;
82         if (reg == EMUFS_NOT_FOUND) return NULL;
83         tmp = malloc(sizeof(t_Reg_Factura));
84         if (tmp == NULL) return NULL;
85         tmp->sig = tmp->ant = NULL;
86         tmp->num_reg = reg;
87         tmp->texto_reg = texto;
88         tmp->numero = num;
89
90         return tmp;
91 }
92
93 int agregar_nodo_factura(t_LstFacturas *lst, t_Reg_Factura *nodo)
94 {
95         if (nodo == NULL) return 0;
96
97         if (lst->primero) {
98                 lst->primero->ant = nodo;
99                 nodo->sig = lst->primero;
100                 lst->primero = nodo;
101         } else {
102                 lst->primero = nodo;
103         }
104         return 1;
105 }
106 #endif /*TP_PRIMER_ENTREGA*/
107
108 t_Item *leer_items(xmlNode *node, int *cant, int size)
109 {
110         t_Item *tmp;
111         int count;
112         char *prop;
113         if (size == -1) {
114                 tmp = NULL;
115                 count = 0;
116                 node = node->children;
117                 while (node) {
118                         if (node->type == XML_ELEMENT_NODE) {
119                                 if (strcmp(node->name, "ITEMVENTA") == 0) {
120                                         count++;
121                                         tmp = realloc(tmp, sizeof(t_Item)*count);
122                                         memset(&tmp[count-1], 0, sizeof(t_Item));
123                                         prop = xml_get_prop(node, "NroArtĂ­culo");
124                                         tmp[count-1].numero = atoi(prop);
125                                         xmlFree(prop);
126                                         strncpy(tmp[count-1].cv, prop = xml_get_prop(node, "CV"), 8); xmlFree(prop);
127                                         tmp[count-1].cv[8] = '\0';
128                                         strncpy(tmp[count-1].pvu, prop = xml_get_prop(node, "PVU"), 8); xmlFree(prop);
129                                         tmp[count-1].pvu[8] = '\0';
130                                 }
131                         }
132                         node = node->next;
133                 }
134                 *cant = count;
135         } else {
136                 (*cant) = size;
137                 tmp = (t_Item *)malloc(sizeof(t_Item)*size);
138                 memset(tmp, 0, sizeof(t_Item)*size);
139
140                 count = 0;
141                 node = node->children;
142                 while (node) {
143                         if (node->type == XML_ELEMENT_NODE) {
144                                 if (strcmp(node->name, "ITEMVENTA") == 0) {
145                                         memset(&tmp[count], 0, sizeof(t_Item));
146                                         prop = xml_get_prop(node, "NroArtĂ­culo");
147                                         tmp[count].numero = atoi(prop);
148                                         xmlFree(prop);
149                                         strncpy(tmp[count].cv, prop = xml_get_prop(node, "CV"), 8); xmlFree(prop);
150                                         tmp[count].cv[8] = '\0';
151                                         strncpy(tmp[count].pvu, prop = xml_get_prop(node, "PVU"), 8); xmlFree(prop);
152                                         tmp[count].pvu[8] = '\0';
153                                         count++;
154                                 }
155                         }
156                         if (count == size) break; /* No me entran mas items! */
157                         node = node->next;
158                 }
159         }
160         return tmp;
161 }
162
163 char *leer_nota(xmlNode *node, int max)
164 {
165         xmlNode *tmp;
166         char *salida;
167         tmp = node->children;
168         while (tmp) {
169                 if (tmp->type == XML_ELEMENT_NODE) {
170                         if (strcmp(tmp->name, "NOTA") == 0) {
171                                 break;
172                         }
173                 }
174                 tmp = tmp->next;
175         }
176
177         if (tmp) {
178                 if (max == -1) {
179                         salida = (char *)malloc(sizeof(char)*(strlen(XML_GET_CONTENT(tmp->children))+1));
180                         strcpy(salida, XML_GET_CONTENT(tmp->children));
181                 } else {
182                         salida = (char *)malloc(sizeof(char)*max);
183                         strncpy(salida, XML_GET_CONTENT(tmp->children), max-1);
184                         salida[max-1] = '\0';
185                 }
186         } else {
187                 if (max == -1) {
188                         salida = (char *)malloc(sizeof(char));
189                         salida[0] = '\0';
190                 } else {
191                         salida = (char *)malloc(sizeof(char)*max);
192                         memset(salida, 0, max);
193                 }
194         }
195         return salida;
196 }
197
198
199 t_LstFacturas *fact_cargar(t_Parametros *param)
200 {
201         xmlDocPtr document;
202         xmlNode *node, *inicio;
203         int error = 0, cant_items;
204         char *prop;
205         EMUFS_REG_SIZE size;
206         t_LstFacturas *tmp;
207         t_Factura *factura;
208         EMUFS_REG_ID id;
209         
210         lst_facturas = NULL;
211
212         tmp = (t_LstFacturas *)malloc(sizeof(t_LstFacturas));
213         if (tmp == NULL) return NULL;
214         lst_facturas = tmp;
215         tmp->primero = NULL;
216
217         if (param != NULL) {
218                 PERR("Voy a cargar de un XML");
219                 PERR(param->xml_fact);
220                 document = xmlReadFile(param->xml_fact, "ISO-8859-1",0);
221                 if (document == NULL) {
222                         PERR("Error al leer documento!!");
223                         free(tmp);
224                         lst_facturas = NULL;
225                         return NULL;
226                 }
227
228                 inicio = NULL;
229                 node = xmlDocGetRootElement(document);
230                 /* Busco el TAG principal "ARTICULOS" */
231                 while (node) {
232                         if (node->type == XML_ELEMENT_NODE) {
233                                 if (strcmp(node->name, "FACTURAS") == 0) {
234                                         inicio = node->children;
235                                         break;
236                                 }
237                         }
238                         node = node->next;
239                 }
240
241                 /* En el registro no guardo los punteros de nota ni items. Si guardo la cantidad de items
242                  * y los items al final del registro.
243                  */
244                 if (param->tipo_arch_fact == T3) {
245                         /* Limito a 10 items en el caso de registro constante! */
246                         cant_items = 10;
247                 } else {
248                         cant_items = 0;
249                 }
250                 tmp->fp = emufs_crear("facturas", param->tipo_arch_fact, param->tam_bloque_fact, sizeof(t_Factura)-sizeof(char *)-sizeof(t_Item*)+cant_items*sizeof(t_Item));
251                 emufs_agregar_indice(tmp->fp, "ctacte", IND_SELECCION, param->ind_fac[4].tipo_arbol, IDX_STRING, STRUCT_OFFSET(factura, emision), param->ind_fac[4].tam_bloque, 5);
252                 emufs_agregar_indice(tmp->fp, "cheque", IND_SELECCION, param->ind_fac[3].tipo_arbol, IDX_STRING, STRUCT_OFFSET(factura, emision), param->ind_fac[3].tam_bloque, 4);
253                 emufs_agregar_indice(tmp->fp, "vto", IND_SELECCION, param->ind_fac[2].tipo_arbol, IDX_STRING, STRUCT_OFFSET(factura, emision), param->ind_fac[2].tam_bloque, 1);
254                 emufs_agregar_indice(tmp->fp, "emision", IND_EXAHUSTIVO, param->ind_fac[1].tipo_arbol, IDX_STRING, STRUCT_OFFSET(factura, emision), param->ind_fac[1].tam_bloque, 0);
255                 emufs_agregar_indice(tmp->fp, "numero", IND_PRIMARIO, param->ind_fac[0].tipo_arbol, IDX_INT, 0, param->ind_fac[0].tam_bloque, 0);
256
257                 /* Creo el indice externo por Nro Articulo */
258                 tmp->fp->externo = emufs_indice_crear(tmp->fp, "articulo", IND_SELECCION, IND_B, IDX_INT, 0, 512, 0);
259
260                 tmp->fp_texto = emufs_crear("notas", param->tipo_arch_nota, param->tam_bloque_nota, 100);
261                 for (node=inicio ; node ; node = node->next) {
262                         if (node->type == XML_ELEMENT_NODE) {
263                                 if (strcmp(node->name, "FACTURA") == 0) {
264                                         t_Factura fact;
265                                         void *save;
266                                         memset(&fact, 0, sizeof(t_Factura));
267                                         prop = xml_get_prop(node, "NroFac");
268                                         fact.numero = atoi(prop); xmlFree(prop);
269                                         prop = xml_get_prop(node, "PorcDoI");
270                                         fact.procdoi = atof(prop); xmlFree(prop);
271                                         prop = xml_get_prop(node, "NroRemito");
272                                         fact.numero_remito = atoi(prop); xmlFree(prop);
273                                         strncpy(fact.emision, prop = xml_get_prop(node, "FechaEmisiĂłn"), 8); xmlFree(prop);
274                                         fact.emision[8] = '\0';
275                                         strncpy(fact.vencimiento, prop = xml_get_prop(node, "FechaVto"), 8); xmlFree(prop);
276                                         fact.vencimiento[8] = '\0';
277                                         strncpy(fact.estado, prop = xml_get_prop(node, "Estado"), 2); xmlFree(prop);
278                                         fact.estado[2] = '\0';
279                                         strncpy(fact.fp, prop = xml_get_prop(node, "FP"), 2); xmlFree(prop);
280                                         fact.fp[2] = '\0';
281                                         strncpy(fact.ctacte, prop = xml_get_prop(node, "NroCtaCte"), 5); xmlFree(prop);
282                                         fact.ctacte[5] = '\0';
283                                         strncpy(fact.cheque, prop = xml_get_prop(node, "NroCheque"), 18); xmlFree(prop);
284                                         fact.cheque[18] = '\0';
285
286                                         fact.nota = leer_nota(node, ((param->tipo_arch_nota==T3)?100:-1));
287                                         fact.items = leer_items(node, &fact.cant_items, (param->tipo_arch_fact==T3)?10:-1);
288
289                                         error = 0;
290                                         id = tmp->fp_texto->grabar_registro(tmp->fp_texto, fact.nota, (param->tipo_arch_nota==T3)?100:(strlen(fact.nota)+1), &error);
291                                         fact.reg_nota = id;
292                                         save = procesar_guardar_factura(&fact, lst_facturas, &size);
293                                         if (save != NULL) {
294                                                 int i;
295                                                 error = 0;
296                                                 id = tmp->fp->grabar_registro(tmp->fp, save, size, &error);
297                                         
298                                                 /* Agrego los Items al indice externo */
299                                                 for(i=0; i<fact.cant_items; i++) {
300                                                         if (fact.items[i].numero != 0) {
301                                                                 CLAVE _k; /* HACK Para hacer mas rapido */
302                                                                 INDICE_DATO _dato;
303                                                                 _k.i_clave = fact.items[i].numero;
304                                                                 _dato.id = id;
305                                                                 tmp->fp->externo->agregar_entrada(tmp->fp->externo, _k, _dato);
306                                                         }
307                                                 }
308                                                 
309                                                 if (fact.items) {
310                                                         free(fact.items);
311                                                         fact.items = NULL;
312                                                 }
313                                                 if (fact.nota) {
314                                                         free(fact.nota);
315                                                         fact.nota = NULL;
316                                                 }
317                                                 free(save);
318                                         }
319                                 }
320                         }
321                 }
322                 xmlFreeDoc(document);
323                 xmlCleanupParser();
324         } else {
325                 PERR("Voy a recuperar desde un archivo");
326                 tmp->fp = emufs_abrir("facturas");
327                 if (tmp->fp == NULL) {
328                         PERR("No se pudo cargar archivo de facturas!");
329                         free(tmp);
330                         lst_facturas = NULL;
331                         return NULL;
332                 }
333                 tmp->fp_texto = emufs_abrir("notas");
334                 if (tmp->fp_texto == NULL) {
335                         PERR("No se pudo cargar archivo de notas!");
336                         emufs_destruir(tmp->fp);
337                         free(tmp);
338                         lst_facturas = NULL;
339                         return NULL;
340                 }
341         }
342
343         PERR("Facturas todo Ok");
344         return lst_facturas;
345 }
346
347 int fact_liberar(t_LstFacturas *l)
348 {
349         t_Reg_Factura *del;
350         if (l == NULL) l = lst_facturas;
351         if (l == NULL) return 1;
352
353         emufs_destruir(l->fp);
354         emufs_destruir(l->fp_texto);
355         while (l->primero) {
356                 del = l->primero;
357                 l->primero = l->primero->sig;
358                 free(del);
359         }
360         free(l);
361
362         lst_facturas = NULL;
363         return 0;
364 }
365
366 t_Factura *fact_buscar(t_LstFacturas *lst, int numero, EMUFS_REG_ID *id, EMUFS_REG_ID *id_texto)
367 {
368         t_Factura *fact;
369         char *leo;
370         EMUFS_REG_SIZE size;
371         int error;
372         CLAVE k;
373         if (lst == NULL) return NULL;
374
375         fact = NULL;
376         k = emufs_indice_generar_clave_desde_valor(lst->fp->indices, (char*)&numero);
377         error = 0;
378         leo = lst->fp->leer_registro(lst->fp, k, &size, &error);
379         PERR("Registro Leido");
380         if (leo != NULL) {
381                 fact = (t_Factura *)malloc(sizeof(t_Factura));
382                 if (fact == NULL) {
383                         free(leo);
384                         return NULL;
385                 }
386                 PERR("Procesando");
387                 procesar_leer_factura(fact, leo, size, lst);
388                 /* y esto ??!
389                 (*id) = reg->num_reg;
390                 (*id_texto) = reg->texto_reg;
391                 */
392                 free(leo);
393                 PERR("Leo nota");
394                 k.i_clave = fact->reg_nota;
395                 error = 0;
396                 fact->nota = lst->fp_texto->leer_registro(lst->fp_texto, k, &size, &error);
397                 PERR("DONE");
398         }
399         
400         return fact;
401 }
402
403 t_Factura *fact_form_buscar(WINDOW *win, EMUFS_REG_ID *id, EMUFS_REG_ID *id_texto)
404 {
405         t_Form *form;
406         t_Factura *fact;
407
408         form = form_crear(win);
409         form_agregar_widget(form, INPUT, "Numero de Factura", 8, "");
410         form_ejecutar(form, 1,1);
411         fact = fact_buscar(lst_facturas, form_obtener_valor_int(form, "Numero de Factura"), id, id_texto);
412         form_destruir(form);
413
414         return fact;
415 }
416
417 void fact_eliminar(char *s)
418 {
419         WINDOW *win;
420         t_Factura *fact;
421         EMUFS_REG_ID id;
422         CLAVE k;
423         INDICE_DATO dummy;
424                                                                         
425         win = newwin(LINES-4, COLS-2, 2, 1);
426         box(win, 0, 0);
427         
428         fact = fact_form_buscar(win, &id, &id);
429
430         if (fact == NULL) {
431                 wattron(win, COLOR_PAIR(COLOR_YELLOW));
432                 mvwaddstr(win, 2, 1, "No existe artĂ­culo con ese cĂłdigo. Abortando!");
433                 wattroff(win, COLOR_PAIR(COLOR_YELLOW));
434                 wrefresh(win);
435                 getch();
436                 werase(win);
437                 wrefresh(win);
438                 delwin(win);
439                 return;
440         }
441
442         k = emufs_indice_generar_clave_desde_valor(lst_facturas->fp->indices, (char *)(&fact->numero));
443         lst_facturas->fp->borrar_registro(lst_facturas->fp, k, dummy);
444         k.i_clave = fact->reg_nota;
445         lst_facturas->fp_texto->borrar_registro(lst_facturas->fp_texto, k, dummy);
446
447         if (fact->items) free(fact->items);
448         if (fact->nota) free(fact->nota);
449         free(fact);
450 }
451
452 void fact_modificar(char *s)
453 {
454         WINDOW *win, *items, *nota, *subnota;
455         t_Form *form, *form_nota;
456         t_Factura *fact;
457         EMUFS_REG_SIZE size;
458         EMUFS_REG_ID id, id_texto;
459         int error;
460         char tmp_str[10];
461         void *entrada;
462
463         win = newwin(LINES-4, COLS-2, 2, 1);
464         box(win, 0, 0);
465         
466         if (s == NULL) {
467                 fact = fact_form_buscar(win, &id, &id_texto);
468         } else {
469                 fact = fact_buscar(lst_facturas, atoi(s), &id, &id_texto);
470         }
471
472         if (fact == NULL) {
473                 wattron(win, COLOR_PAIR(COLOR_YELLOW));
474                 mvwaddstr(win, 2, 1, "No existe factura con ese cĂłdigo. Abortando!");
475                 wattroff(win, COLOR_PAIR(COLOR_YELLOW));
476                 wrefresh(win);
477                 getch();
478                 werase(win);
479                 wrefresh(win);
480                 delwin(win);
481                 return;
482         }
483
484         mvwaddch(win, 10, 0, ACS_LTEE);
485         mvwhline(win, 10, 1, ACS_HLINE, COLS-3);
486         mvwaddch(win, 10, COLS-3, ACS_RTEE);
487         wrefresh(win);
488
489         items = derwin(win, LINES-20, COLS-4, 15, 1);
490         nota = derwin(win, 9, COLS-62, 1, 56);
491         subnota = derwin(nota, 7, COLS-64, 1, 1);
492         box(nota, 0, 0);
493         mvwaddstr(nota, 0, 1, "Nota :");
494         wrefresh(nota);
495         wrefresh(items);
496
497         form = form_crear(win);
498         sprintf(tmp_str, "%08d", fact->numero);
499         form_agregar_widget(form, INPUT, "Numero de Factura", 8, tmp_str);
500         form_agregar_widget(form, INPUT, "Fecha Emision", 8, fact->emision);
501         form_agregar_widget(form, INPUT, "Fecha Vto", 8, fact->vencimiento);
502         sprintf(tmp_str, "%08d", fact->numero_remito);
503         form_agregar_widget(form, INPUT, "Nro Remito", 8, tmp_str);
504         form_agregar_widget(form, RADIO, "Estado", 6, "PN,CD,CM,SF,PM,NC");
505         form_agregar_widget(form, RADIO, "Forma de pago", 3, "CO,CR,CH");
506         sprintf(tmp_str, "%02.2f", fact->procdoi);
507         form_agregar_widget(form, INPUT, "%% Descuento", 5, tmp_str);
508         form_agregar_widget(form, INPUT, "Cuenta Cte", 5, fact->ctacte);
509         form_agregar_widget(form, INPUT, "Cheque Nro", 18, fact->cheque);
510
511         mvwaddstr(subnota, 0, 0, fact->nota);
512         wrefresh(subnota);
513         form_ejecutar(form, 1,1);
514
515         form_nota = form_crear(subnota);
516         form_agregar_widget(form_nota, INPUT, "", 255, fact->nota);
517         form_ejecutar(form_nota, 0, 0);
518
519         fact->numero = form_obtener_valor_int(form, "Numero de Factura");
520         strcpy(fact->emision, form_obtener_valor_char(form, "Fecha Emision"));
521         strcpy(fact->vencimiento, form_obtener_valor_char(form, "Fecha Vto"));
522         fact->numero_remito = form_obtener_valor_int(form, "Nro Remito");
523         strcpy(fact->estado, form_obtener_valor_char(form, "Estado"));
524         strcpy(fact->fp, form_obtener_valor_char(form, "Forma de pago"));
525         fact->procdoi = form_obtener_valor_float(form, "%% Descuento");
526         strcpy(fact->ctacte, form_obtener_valor_char(form, "Cuenta Cte"));
527         strcpy(fact->cheque, form_obtener_valor_char(form, "Cheque Nro"));
528
529         form_destruir(form);
530
531         free(fact->nota);
532         fact->nota = form_obtener_valor_char(form_nota, "");
533
534         form_destruir(form_nota);
535
536         entrada = procesar_guardar_factura(fact, lst_facturas, &size);
537         if (entrada) {
538                 CLAVE k;
539                 INDICE_DATO dummy;
540                 k = emufs_indice_generar_clave_desde_valor(lst_facturas->fp->indices, (char *)&fact->numero);
541                 lst_facturas->fp->modificar_registro(lst_facturas->fp, k, entrada, size, &error, dummy);
542                 k.i_clave = id_texto;
543                 id_texto = lst_facturas->fp_texto->modificar_registro(lst_facturas->fp_texto, k, fact->nota, strlen(fact->nota)+1, &error, dummy);
544                 free(entrada);
545         }
546
547         free(fact->items);
548         free(fact);
549
550         werase(win);
551         wrefresh(win);
552         delwin(subnota);
553         delwin(nota);
554         delwin(items);
555         delwin(win);
556 }
557
558 void fact_agregar(char *s)
559 {
560         WINDOW *win, *items, *nota, *subnota;
561         t_Form *form, *form_nota;
562         t_Item *its = NULL;
563         t_Factura fact;
564         EMUFS_REG_SIZE size;
565         EMUFS_REG_ID id_texto;
566         int y_actual, cant, error;
567         float total;
568         char *entrada;
569
570         win = newwin(LINES-4, COLS-2, 2, 1);
571         box(win, 0, 0);
572         mvwaddch(win, 10, 0, ACS_LTEE);
573         mvwhline(win, 10, 1, ACS_HLINE, COLS-3);
574         mvwaddch(win, 10, COLS-3, ACS_RTEE);
575         wrefresh(win);
576
577         items = derwin(win, LINES-20, COLS-4, 15, 1);
578         nota = derwin(win, 9, COLS-62, 1, 56);
579         subnota = derwin(nota, 7, COLS-64, 1, 1);
580         box(nota, 0, 0);
581         mvwaddstr(nota, 0, 1, "Nota :");
582         wrefresh(nota);
583         wrefresh(items);
584
585         form = form_crear(win);
586         form_agregar_widget(form, INPUT, "Numero de Factura", 8, "");
587         form_agregar_widget(form, INPUT, "Fecha Emision", 8, "");
588         form_agregar_widget(form, INPUT, "Fecha Vto", 8, "");
589         form_agregar_widget(form, INPUT, "Nro Remito", 8, "");
590         form_agregar_widget(form, RADIO, "Estado", 6, "PN,CD,CM,SF,PM,NC");
591         form_agregar_widget(form, RADIO, "Forma de pago", 3, "CO,CR,CH");
592         form_agregar_widget(form, INPUT, "%% Descuento", 5, "");
593         form_agregar_widget(form, INPUT, "Cuenta Cte", 5, "");
594         form_agregar_widget(form, INPUT, "Cheque Nro", 18, "");
595
596         form_ejecutar(form, 1,1);
597
598         form_nota = form_crear(subnota);
599         form_agregar_widget(form_nota, INPUT, "", 255, "");
600         form_ejecutar(form_nota, 0, 0);
601
602         /* XXX No destruir form_nota hasta el final !!!!! XXX */
603
604         fact.numero = form_obtener_valor_int(form, "Numero de Factura");
605         strcpy(fact.emision, form_obtener_valor_char(form, "Fecha Emision"));
606         strcpy(fact.vencimiento, form_obtener_valor_char(form, "Fecha Vto"));
607         fact.numero_remito = form_obtener_valor_int(form, "Nro Remito");
608         strcpy(fact.estado, form_obtener_valor_char(form, "Estado"));
609         strcpy(fact.fp, form_obtener_valor_char(form, "Forma de pago"));
610         fact.procdoi = form_obtener_valor_float(form, "%% Descuento");
611         strcpy(fact.ctacte, form_obtener_valor_char(form, "Cuenta Cte"));
612         strcpy(fact.cheque, form_obtener_valor_char(form, "Cheque Nro"));
613
614         form_destruir(form);
615
616         form = form_crear(win);
617         form_agregar_widget(form, INPUT, "Nro de Articulo (* == fin)", 8, "");
618         form_agregar_widget(form, INPUT, "Cant. Vendida", 8, "");
619         /*form_agregar_widget(form, INPUT, "PVU", 8, "");*/
620         y_actual = 0;
621         scrollok(items, 1);
622         mvwaddstr(win, 15, 2, "Numero");
623         mvwaddstr(win, 15, 11, "Cant. Vendida");
624         mvwaddstr(win, 15, 31, "PVU");
625         mvwaddstr(win, 15, 41, "Subtotal");
626         cant = 0;
627         total = 0.0f;
628         do {
629                 form_set_valor(form, "Nro de Articulo (* == fin)", "");
630                 form_set_valor(form, "Cant. Vendida", "");
631                 /*form_set_valor(form, "PVU", "");*/
632                 form_ejecutar(form, 2, 11);
633
634                 entrada = form_obtener_valor_char(form, "Nro de Articulo (* == fin)");
635
636                 if ((entrada[0] != '\0') && (entrada[0] != '*')){
637                         /* Veamos si existe el articulo */
638                         t_Articulo *art;
639                         EMUFS_REG_ID dummy;
640
641                         art = art_obtener(NULL, atoi(entrada), &dummy);
642
643                         if (art != NULL) {
644                                 char subtotal[20];
645                                 char *cv;
646                                 y_actual++;
647                                 if (y_actual > LINES-22) {
648                                         y_actual = LINES-22;
649                                         wscrl(items, 1);
650                                 }
651                                 cv = form_obtener_valor_char(form, "Cant. Vendida");
652                                 mvwaddstr(items, y_actual, 1, entrada);
653                                 mvwaddstr(items, y_actual, 10, cv);
654                                 mvwaddstr(items, y_actual, 30, art->pvu);
655
656                                 sprintf(subtotal, "%.2f", atof(cv)*atof(art->pvu));
657                                 total += atof(subtotal);
658
659                                 mvwaddstr(items, y_actual, 40, subtotal);
660
661                                 wrefresh(items);
662                                 /* Agrego el Item */
663                                 cant++;
664                                 its = (t_Item *)realloc(its, cant*sizeof(t_Item));
665                                 if (its != NULL) {
666                                         art_actualizar_stock(atoi(entrada), atoi(cv));
667                                         its[cant-1].numero = atoi(entrada);
668                                         strcpy(its[cant-1].cv, cv);
669                                         strcpy(its[cant-1].pvu, art->pvu);
670                                 }
671                                 free(art);
672                         }
673                 }
674         } while (entrada[0] != '*');
675
676         if (lst_facturas->fp->tipo == T3) {
677                 if (cant != 10) {
678                         /* TODO Limitar en la GUI en lugar de truncar! */
679                         its = (t_Item *)realloc(its, 10*sizeof(t_Item));
680                         if (its == NULL) {
681                                 cant = 0;
682                         } else {
683                                 memset(its+sizeof(t_Item)*cant, 0, (10-cant)*sizeof(t_Item));
684                                 cant = 10;
685                         }
686                 }
687         }
688         fact.items = its;
689         fact.cant_items = cant;
690         fact.nota = form_obtener_valor_char(form_nota, "");
691
692         id_texto = lst_facturas->fp_texto->grabar_registro(lst_facturas->fp_texto, fact.nota, strlen(fact.nota)+1, &error);
693         fact.reg_nota = id_texto;
694
695         entrada = procesar_guardar_factura(&fact,lst_facturas, &size);
696         if (entrada) {
697                 error = 0;
698                 PERR("GUARDANDO NUEVA FACTURA");
699                 lst_facturas->fp->grabar_registro(lst_facturas->fp, entrada, size, &error);
700                 PERR("DONE");
701                 free(entrada);
702         }
703                                                                         
704         if (its) free(its);
705         form_destruir(form);
706         form_destruir(form_nota);
707
708         werase(win);
709         wrefresh(win);
710         delwin(items);
711         delwin(subnota);
712         delwin(nota);
713         delwin(win);
714 }
715
716 void *procesar_guardar_factura(t_Factura *f, t_LstFacturas *lst, EMUFS_REG_SIZE *size)
717 {
718         char *tmp=NULL;
719         int i[12];
720
721         switch (lst->fp->tipo) {
722                 case T1:
723                 case T2:
724                 case T4:
725                         /* Calculo el tamaño que voy a necesitar */
726                         i[0] = sizeof(int);
727                         i[1] = sizeof(float);
728                         i[2] = sizeof(int);
729                         i[3] = sizeof(int);
730                         i[4] = sizeof(EMUFS_BLOCK_ID);
731                         i[5] = sizeof(char)*(strlen(f->emision)+1); /* +1 por el \0 para separar */
732                         i[6] = sizeof(char)*(strlen(f->vencimiento)+1); /* +1 por el \0 para separar */
733                         i[7] = sizeof(char)*(strlen(f->estado)+1); /* +1 por el \0 para separar */
734                         i[8] = sizeof(char)*(strlen(f->fp)+1); /* +1 por el \0 para separar */
735                         i[9] = sizeof(char)*(strlen(f->ctacte)+1); /* +1 por el \0 para separar */
736                         i[10] = sizeof(char)*(strlen(f->cheque)+1); /* +1 por el \0 para separar */
737                         i[11] = sizeof(t_Item)*f->cant_items;
738                         (*size) = i[0]+i[1]+i[2]+i[3]+i[4]+i[5]+i[6]+i[7]+i[8]+i[9]+i[10]+i[11];
739                         tmp = (char *)malloc(*size);
740                         if (tmp == NULL) return NULL;
741                         memset(tmp, 0, *size);
742                         /* Ahora copio la info */
743                         memcpy(tmp, &f->numero, i[0]);
744                         memcpy(tmp+i[0], &f->procdoi, i[1]);
745                         memcpy(tmp+i[0]+i[1], &f->numero_remito, i[2]);
746                         memcpy(tmp+i[0]+i[1]+i[2], &f->cant_items, i[3]);
747                         memcpy(tmp+i[0]+i[1]+i[2]+i[3], &f->reg_nota, i[4]);
748                         memcpy(tmp+i[0]+i[1]+i[2]+i[3]+i[4], f->emision, i[5]);
749                         memcpy(tmp+i[0]+i[1]+i[2]+i[3]+i[4]+i[5], f->vencimiento, i[6]);
750                         memcpy(tmp+i[0]+i[1]+i[2]+i[3]+i[4]+i[5]+i[6], f->estado, i[7]);
751                         memcpy(tmp+i[0]+i[1]+i[2]+i[3]+i[4]+i[5]+i[6]+i[7], f->fp, i[8]);
752                         memcpy(tmp+i[0]+i[1]+i[2]+i[3]+i[4]+i[5]+i[6]+i[7]+i[8], f->ctacte, i[9]);
753                         memcpy(tmp+i[0]+i[1]+i[2]+i[3]+i[4]+i[5]+i[6]+i[7]+i[8]+i[9], f->cheque, i[10]);
754                         if (i[11] != 0)
755                                 memcpy(tmp+i[0]+i[1]+i[2]+i[3]+i[4]+i[5]+i[6]+i[7]+i[8]+i[9]+i[10], f->items, i[11]);
756                 break;
757                 case T3:
758                 case T5:
759                         (*size) = sizeof(t_Factura)-sizeof(char *)-sizeof(t_Item *) + f->cant_items*sizeof(t_Item);
760                         tmp = (char *)malloc(*size);
761                         if (tmp == NULL) return NULL;
762                         memcpy(tmp, f, sizeof(t_Factura)-sizeof(char *)-sizeof(t_Item *));
763                         memcpy(tmp+sizeof(t_Factura)-sizeof(char *)-sizeof(t_Item *), f->items, f->cant_items*sizeof(t_Item));
764         }
765         return tmp;
766 }
767
768 static int procesar_leer_factura(t_Factura *dst, void *src, EMUFS_REG_SIZE size, t_LstFacturas *lst)
769 {
770         char *ini, *fin;
771         /*int dummy;*/
772
773         if (lst == NULL) {
774                 PERR("Puntero a lista NULO");
775                 return 0;
776         }
777         if (lst->fp == NULL) {
778                 PERR("EMUFS No creado!");
779                 return 0;
780         }
781
782         switch (lst->fp->tipo) {
783                 case T1:
784                 case T2:
785                 case T4:
786                         ini = (char *)src;
787                         /* Copio los campos numericos, muy facil:-) */
788                         memcpy(&dst->numero, ini, sizeof(int));
789                         ini+=sizeof(int);
790                         
791                         memcpy(&dst->procdoi, ini, sizeof(float));
792                         ini+=sizeof(float);
793
794                         memcpy(&dst->numero_remito, ini, sizeof(int));
795                         ini+=sizeof(int);
796                         
797                         memcpy(&dst->cant_items, ini, sizeof(int));
798                         ini+=sizeof(int);
799                         
800                         memcpy(&dst->reg_nota, ini, sizeof(EMUFS_BLOCK_ID));
801                         ini+=sizeof(EMUFS_BLOCK_ID);
802
803                         /* Ahora empieza el juego */
804                         /* Los \0 son los delimitadores de campo! */
805                         fin = ini;
806                         while (*fin!='\0') fin++;
807                         memcpy(dst->emision, ini, fin-ini+1);
808                         
809                         ini = fin+1;
810                         fin = ini;
811                         while (*fin!='\0') fin++;
812                         memcpy(dst->vencimiento, ini, fin-ini+1);
813                         
814                         ini = fin+1;
815                         fin = ini;
816                         while (*fin!='\0') fin++;
817                         memcpy(dst->estado, ini, fin-ini+1);
818                         
819                         ini = fin+1;
820                         fin = ini;
821                         while (*fin!='\0') fin++;
822                         memcpy(dst->fp, ini, fin-ini+1);
823                         
824                         ini = fin+1;
825                         fin = ini;
826                         while (*fin!='\0') fin++;
827                         memcpy(dst->ctacte, ini, fin-ini+1);
828                         
829                         ini = fin+1;
830                         fin = ini;
831                         while (*fin!='\0') fin++;
832                         memcpy(dst->cheque, ini, fin-ini+1);
833
834                         if (dst->cant_items > 0) {
835                                 /* Ahora tengo que cargar los items */
836                                 dst->items = (t_Item *)malloc(sizeof(t_Item)*dst->cant_items);
837
838                                 ini = fin+1;
839                                 fin = (char *)src+size;
840                                 memcpy(dst->items, ini, fin-ini);
841
842                         } else {
843                                 dst->items = NULL;
844                         }
845                         /*dst->nota = lst->fp_texto->leer_registro(lst->fp_texto, dst->reg_nota, (EMUFS_REG_SIZE *)&dummy, &dummy);*/
846                         return 0;
847                 break;
848                 case T3:
849                 case T5:
850                         /* Se que tengo 10 items */
851                         /* TODO : Ver porque leer_registro_tipo3 tira mal el size */
852                         size = lst->fp->tam_reg;
853                         memcpy(dst, src, size-sizeof(t_Item)*10);
854                         dst->items = (t_Item *)malloc(10*sizeof(t_Item));
855                         memcpy(dst->items, src+size-sizeof(t_Item)*10, 10*sizeof(t_Item));
856                         /*dst->nota = lst->fp_texto->leer_registro(lst->fp_texto, dst->reg_nota, (EMUFS_REG_SIZE *)&dummy, &dummy);*/
857         }
858         return 0;
859 }
860
861 void fact_reformatear(t_Parametros *param)
862 {
863         char *tmpfile = "tmp_xxx.xxx";
864         FILE *fp;
865         EMUFS *emu;
866         t_Factura factura, *una_factura;
867         int cant_items;
868
869         PERR("CREO TEMPORAL FACTURAS");
870         dump_facturas(tmpfile);
871         PERR("LISTO");
872
873         PERR("Libero lo viejo");
874         fact_liberar(NULL);
875         PERR("Done");
876
877         PERR("Creo todo de nuevo");
878         lst_facturas  = (t_LstFacturas *)malloc(sizeof(t_LstFacturas));
879         lst_facturas->primero = NULL;
880         if (param->tipo_arch_fact == T3) {
881                 /* Limito a 10 items en el caso de registro constante! */
882                 cant_items = 10;
883         } else {
884                 cant_items = 0;
885         }
886         emu = lst_facturas->fp = emufs_crear("facturas", param->tipo_arch_fact, param->tam_bloque_fact, sizeof(t_Factura)-sizeof(char *)-sizeof(t_Item*)+cant_items*sizeof(t_Item));
887         emufs_agregar_indice(emu, "ctacte", IND_SELECCION, param->ind_fac[4].tipo_arbol, IDX_STRING, STRUCT_OFFSET(una_factura, emision), param->ind_fac[4].tam_bloque, 5);
888         emufs_agregar_indice(emu, "cheque", IND_SELECCION, param->ind_fac[3].tipo_arbol, IDX_STRING, STRUCT_OFFSET(una_factura, emision), param->ind_fac[3].tam_bloque, 4);
889         emufs_agregar_indice(emu, "vto", IND_SELECCION, param->ind_fac[2].tipo_arbol, IDX_STRING, STRUCT_OFFSET(una_factura, emision), param->ind_fac[2].tam_bloque, 1);
890         emufs_agregar_indice(emu, "emision", IND_EXAHUSTIVO, param->ind_fac[1].tipo_arbol, IDX_STRING, STRUCT_OFFSET(una_factura, emision), param->ind_fac[1].tam_bloque, 0);
891         emufs_agregar_indice(emu, "numero", IND_PRIMARIO, param->ind_fac[0].tipo_arbol, IDX_INT, 0, param->ind_fac[0].tam_bloque, 0);
892
893         /* Creo el indice externo por Nro Articulo */
894         emu->externo = emufs_indice_crear(emu, "articulo", IND_SELECCION, IND_B, IDX_INT, 0, 512, 0);
895         PERR("Listo!");
896
897         lst_facturas->fp_texto = emufs_crear("notas", param->tipo_arch_nota, param->tam_bloque_nota, 100);
898
899         fp = fopen(tmpfile, "r");
900         if (fp == NULL) PERR("Ciao!");
901         while (!feof(fp)) {
902                 void *save;
903                 int len, error;
904                 EMUFS_REG_ID id;
905                 EMUFS_REG_SIZE size;
906                 /* Leo la factura */
907                 if (fread(&factura, sizeof(t_Articulo), 1, fp) != 1) continue;
908                 factura.items = malloc(sizeof(t_Item)*factura.cant_items);
909                 fread(factura.items, factura.cant_items, sizeof(t_Item), fp);
910                 fread(&len, 1, sizeof(int), fp);
911                 factura.nota = malloc(len*sizeof(char));
912                 fread(factura.nota, 1, len, fp);
913
914                 /* Listo, ya lei, ahora agrego */
915                 error = 0;
916                 id = lst_facturas->fp_texto->grabar_registro(lst_facturas->fp_texto, factura.nota, (param->tipo_arch_nota==T3)?100:(strlen(factura.nota)+1), &error);
917                 factura.reg_nota = id;
918                 save = procesar_guardar_factura(&factura, lst_facturas, &size);
919                 if (save != NULL) {
920                         int i;
921                         error = 0;
922                         id = lst_facturas->fp->grabar_registro(lst_facturas->fp, save, size, &error);
923                                         
924                         /* Agrego los Items al indice externo */
925                         for(i=0; i<factura.cant_items; i++) {
926                                 if (factura.items[i].numero != 0) {
927                                         CLAVE _k; /* HACK Para hacer mas rapido */
928                                         INDICE_DATO _dato;
929                                         _k.i_clave = factura.items[i].numero;
930                                         _dato.id = id;
931                                         lst_facturas->fp->externo->agregar_entrada(lst_facturas->fp->externo, _k, _dato);
932                                 }
933                         }
934                                 
935                         if (factura.items) {
936                                 free(factura.items);
937                                 factura.items = NULL;
938                         }
939                         if (factura.nota) {
940                                 free(factura.nota);
941                                 factura.nota = NULL;
942                         }
943                         free(save);
944                 }
945         }
946         fclose(fp);
947 }
948
949 int fact_exportar_xml(const char *filename)
950 {
951         int j;
952         t_Factura *fact;
953         EMUFS_REG_ID id, id1;
954         FILE *fp;
955         CLAVE k;
956         INDICE *idx;
957
958         idx = lst_facturas->fp->indices;
959
960         k = idx->obtener_menor_clave(idx);
961
962         if (!(fp = fopen(filename, "wt"))) return 0;
963         
964         fprintf(fp, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n");
965         fprintf(fp, "<FACTURAS>\n");
966         while (k.i_clave != -1) {
967                 fact = fact_buscar(lst_facturas, k.i_clave, &id, &id1);
968                 if (fact != NULL) {
969                         fprintf(fp, "\t<FACTURA NroFac=\"%08d\" ", fact->numero);
970                         fprintf(fp, "FechaEmisiĂłn=\"%s\" ", fact->emision);
971                         fprintf(fp, "FechaVto=\"%s\" ", fact->vencimiento);
972                         fprintf(fp, "NroRemito=\"%08d\" ", fact->numero_remito);
973                         fprintf(fp, "FP=\"%s\" ", fact->fp);
974                         fprintf(fp, "Estado=\"%s\" ", fact->estado);
975                         fprintf(fp, "NroCheque=\"%s\" ", fact->cheque);
976                         fprintf(fp, "PorcDoI=\"%.2f\" ", fact->procdoi);
977                         fprintf(fp, "NroCtaCte=\"%s\" ", fact->ctacte);
978                         fprintf(fp, ">\n");
979                         fprintf(fp, "\t\t<NOTA>%s</NOTA>\n", fact->nota);
980                         for(j=0; j<fact->cant_items; j++) {
981                                 if (fact->items[j].numero != 0)
982                                         fprintf(fp, "\t\t<ITEMVENTA NroArtĂ­culo=\"%08d\" CV=\"%s\" PVU=\"%s\" />\n", fact->items[j].numero, fact->items[j].cv, fact->items[j].pvu);
983                         }
984                         fprintf(fp, "\t</FACTURA>\n");
985                         free(fact);
986                 }
987                 k = idx->obtener_sig_clave(idx, k);
988         }
989         fprintf(fp, "\t</FACTURAS>\n");
990
991         fclose(fp);
992         return 1;
993 }
994
995 char *get_estado(char *s)
996 {
997         if (strcmp(s, "PN")==0) return "Pago Normal";
998         if (strcmp(s, "CD")==0) return "Credito al dia";
999         if (strcmp(s, "CM")==0) return "Credito en mora";
1000         if (strcmp(s, "SF")==0) return "Cheque sin fondos";
1001         if (strcmp(s, "PM")==0) return "Pagada con Mora";
1002         if (strcmp(s, "NC")==0) return "No Cobrada";
1003
1004         return s;
1005 }
1006
1007 char *get_forma_pago(char *s)
1008 {
1009         if (strcmp(s, "CO") == 0) return "Contado";
1010         if (strcmp(s, "CR") == 0) return "Credito";
1011         if (strcmp(s, "CH") == 0) return "Cheque";
1012
1013         return s;
1014 }
1015
1016 void fact_consultas_codigos(char *s)
1017 {
1018         EMUFS_REG_ID dummy;
1019         int desde_codigo, hasta_codigo;
1020         t_Factura *factura;
1021         t_Lista *lista;
1022         t_Form *form;
1023         WINDOW *win, *win1;
1024         INDICE *idx;
1025         CLAVE k, menor, mayor;
1026         int editar;
1027
1028         idx = lst_facturas->fp->indices;
1029
1030         win = newwin(LINES-4, COLS-2, 2, 1);
1031         win1 = derwin(win, LINES-6, COLS-4, 1, 1);
1032         werase(win);
1033         box(win, 0, 0);
1034         wrefresh(win);
1035         
1036         /* El usuario ingresa rango a listar */
1037         form = form_crear(win1);
1038         form_agregar_widget(form, INPUT, "Desde Codigo", 8, "0");
1039         form_agregar_widget(form, INPUT, "Hasta Codigo", 8, "99999999");
1040
1041         form_ejecutar(form, 2, 2);
1042
1043         desde_codigo = form_obtener_valor_int(form, "Desde Codigo");
1044         hasta_codigo = form_obtener_valor_int(form, "Hasta Codigo");
1045
1046         form_destruir(form);
1047         werase(win1);
1048         wrefresh(win1);
1049
1050         menor = idx->obtener_menor_clave(idx);
1051         mayor = idx->obtener_mayor_clave(idx);
1052
1053         if (desde_codigo < menor.i_clave)
1054                 desde_codigo = menor.i_clave;
1055         if (hasta_codigo > mayor.i_clave)
1056                 hasta_codigo = mayor.i_clave;
1057
1058         /* Creo la lista donde mostrar la consulta*/
1059         /* Muestro solo info relevante */
1060         lista = lista_crear(4, win1, COLS-4, LINES-6);
1061
1062         /* Creo las columnas */
1063         lista_agregar_columna(lista, "Numero", DATO_INT, 0, 8);    /* numero     */
1064         lista_agregar_columna(lista, "Fecha", DATO_STR, 10, 9);   /* emision    */
1065         lista_agregar_columna(lista, "Estado", DATO_STR, 20, 19);  /* estado     */
1066         lista_agregar_columna(lista, "F. Pago", DATO_STR, 40, 9);   /* fp         */
1067
1068         /* Leo los datos desde el archivo */
1069         k.i_clave = desde_codigo;
1070         while ((k.i_clave != -1) && (k.i_clave <= hasta_codigo)) {
1071                 factura = fact_buscar(lst_facturas, k.i_clave, &dummy, &dummy);
1072                 if (factura != NULL) {
1073                         lista_agregar_fila(lista,
1074                                 factura->numero,
1075                                 factura->emision,
1076                                 get_estado(factura->estado),
1077                                 get_forma_pago(factura->fp)
1078                         );
1079                 }
1080                 k = idx->obtener_sig_clave(idx, k);
1081         }
1082
1083         curs_set(0);
1084         editar = lista_ejecutar(lista);
1085         curs_set(1);
1086         
1087         if (editar != -1) {
1088                 char cc[20];
1089                 sprintf(cc, "%d", editar);
1090                 fact_modificar(cc);
1091         }
1092         
1093         wrefresh(win1);
1094         wrefresh(win);
1095         werase(win1);
1096         werase(win);
1097         wrefresh(win);
1098         delwin(win);
1099 }
1100
1101 float get_importe_factura(t_Item *items, int cant, float interes)
1102 {
1103         float a=0.0f;
1104         int i;
1105         for(i=0; i<cant; i++) {
1106                 a += atof(items[i].cv)*atof(items[i].pvu);
1107         }
1108         a += a*interes/100.0f;
1109         return a;
1110 }
1111
1112
1113 void fact_consultas_fechas(char *s)
1114 {
1115         char desde_fecha[10], hasta_fecha[10];
1116         char estado[6];
1117         t_Lista *lista;
1118         t_Form *form;
1119         WINDOW *win, *win1;
1120         INDICE *idx;
1121         CLAVE k_menor, k_mayor;
1122         int todo=0;
1123         int editar;
1124
1125         win = newwin(LINES-4, COLS-2, 2, 1);
1126         win1 = derwin(win, LINES-6, COLS-4, 1, 1);
1127         werase(win);
1128         box(win, 0, 0);
1129         wrefresh(win);
1130         
1131         /* El usuario ingresa rango a listar */
1132         form = form_crear(win1);
1133         form_agregar_widget(form, INPUT, "Desde Fecha", 8, "");
1134         form_agregar_widget(form, INPUT, "Hasta Fecha", 8, "");
1135         form_agregar_widget(form, RADIO, "Estado", 7, "Todos,PN,CD,CM,SF,PM,NC");
1136         form_ejecutar(form, 2, 2);
1137
1138         strcpy(desde_fecha, form_obtener_valor_char(form, "Desde Fecha"));
1139         strcpy(hasta_fecha, form_obtener_valor_char(form, "Hasta Fecha"));
1140         strcpy(estado, form_obtener_valor_char(form, "Estado"));
1141
1142         form_destruir(form);
1143         werase(win1);
1144         wrefresh(win1);
1145
1146         /* Si el usuario no ingreso alguno de los datos, lo obtengo del indice */
1147         idx = emufs_buscar_indice_por_nombre(lst_facturas->fp, "emision");
1148         if (idx==NULL) PERR("INDICE EMISION NO SE ENCUENTRA!!");
1149
1150         /* XXX Politica de seleccion de uso de ord externo
1151          *
1152          * Se usa ordenamiento externo en alguno de estos 2 casos :
1153          *   * Se requiere un listado de todo el rango de fechas
1154          *   * Se requiere un listado de todos los Estados
1155          *
1156          *   Para cualquier otro caso, se ordena directamente
1157          *   en la lista
1158          */
1159         if (strlen(desde_fecha) == 0) {
1160                 k_menor = idx->obtener_menor_clave(idx);
1161                 emufs_indice_obtener_valor_desde_clave(idx, k_menor, desde_fecha);
1162                 PERR("OBTUVE MENOR CLAVE DESDE EL INDICE");
1163                 PERR(desde_fecha);
1164                 todo++;
1165         }
1166         if (strlen(hasta_fecha) == 0) {
1167                 k_mayor = idx->obtener_mayor_clave(idx);
1168                 emufs_indice_obtener_valor_desde_clave(idx, k_mayor, hasta_fecha);
1169                 PERR("OBTUVE MAYOR CLAVE DESDE EL INDICE");
1170                 PERR(hasta_fecha);
1171                 todo++;
1172         }
1173
1174         if (strcmp(estado, "Todos") == 0) todo = 2;
1175
1176         if (todo == 2) {
1177                 /* Debo utilizar un ord, externo!! */
1178                 FILE *fp;
1179                 /* Creo el archivo a ordenar */
1180                 fp = fopen("tmp_ord.xxx", "w");
1181                 while (k_menor.i_clave != -1) {
1182                         t_Factura fact;
1183                         int error, cant, i;
1184                         char *leo;
1185                         t_OrdExt_Data ord;
1186                         EMUFS_REG_SIZE size;
1187                         INDICE_DATO *datos;
1188                         CLAVE k1;
1189                         datos = idx->buscar_entradas(idx, k_menor, &cant);
1190                         for(i=0; i<cant; i++) {
1191                                 error = 1;
1192                                 k1.i_clave = datos[i].id;
1193                                 leo = lst_facturas->fp->leer_registro(lst_facturas->fp, k1, &size, &error);
1194                                 if (leo != NULL) {
1195                                         procesar_leer_factura(&fact, leo, size, lst_facturas);
1196                                         free(leo);
1197                                         ord.numero = fact.numero;
1198                                         strcpy(ord.emision, fact.emision);
1199                                         strcpy(ord.estado, fact.estado);
1200                                         strcpy(ord.fp, fact.fp);
1201                                         ord.importe = get_importe_factura(fact.items, fact.cant_items, fact.procdoi);
1202                                         fwrite(&ord, sizeof(t_OrdExt_Data), 1, fp);
1203                                 }
1204                         }
1205                         if (datos) free(datos);
1206                         if (fact.items) free(fact.items);
1207                         k_menor = idx->obtener_sig_clave(idx, k_menor);
1208                 }
1209                 fclose(fp);
1210                 /* Mando a ordenar */
1211                 extsort("tmp_ord.xxx", 4096, sizeof(t_OrdExt_Data), comparar_externo);
1212         }
1213         /* Creo la lista donde mostrar la consulta*/
1214         /* Muestro solo info relevante */
1215         lista = lista_crear(4, win1, COLS-4, LINES-6);
1216
1217         /* Creo las columnas */
1218         lista_agregar_columna(lista, "Numero", DATO_INT, 0, 8);    /* numero     */
1219         lista_agregar_columna(lista, "Fecha", DATO_STR, 10, 9);   /* emision    */
1220         lista_agregar_columna(lista, "Estado", DATO_STR, 20, 19);  /* estado     */
1221         lista_agregar_columna(lista, "F. Pago", DATO_STR, 40, 9);   /* fp         */
1222         lista_agregar_columna(lista, "Importe", DATO_FLOAT, 50, 8);   /* importe         */
1223
1224         /* Leo los datos desde el archivo */
1225         if (todo != 2) {
1226                 while (k_menor.i_clave != -1) {
1227                         t_Factura fact;
1228                         int error, cant, i;
1229                         char *leo;
1230                         EMUFS_REG_SIZE size;
1231                         INDICE_DATO *datos;
1232                         CLAVE k1;
1233                         datos = idx->buscar_entradas(idx, k_menor, &cant);
1234                         for(i=0; i<cant; i++) {
1235                                 error = 1;
1236                                 k1.i_clave = datos[i].id;
1237                                 leo = lst_facturas->fp->leer_registro(lst_facturas->fp, k1, &size, &error);
1238                                 if (leo != NULL) {
1239                                         procesar_leer_factura(&fact, leo, size, lst_facturas);
1240                                         free(leo);
1241                                 }
1242                                 if (strcmp(estado, fact.estado) == 0) {
1243                                         lista_agregar_fila_ordenada(lista,
1244                                                 fact.numero,
1245                                                 fact.emision,
1246                                                 get_estado(fact.estado),
1247                                                 get_forma_pago(fact.fp),
1248                                                 get_importe_factura(fact.items, fact.cant_items, fact.procdoi)
1249                                         );
1250                                 }
1251                         }
1252                         if (datos) free(datos);
1253                         if (fact.items) free(fact.items);
1254                 }
1255                 k_menor = idx->obtener_sig_clave(idx, k_menor);
1256         } else {
1257                 /* Cargo la lista a partir del archivo ordenado externamente */
1258                 FILE *fp;
1259                 int j;
1260                 char st[3];
1261                 t_OrdExt_Data ord;
1262                 
1263                 j =( strcmp(estado, "Todos") == 0);
1264                 fp = fopen("tmp_ord.xxx", "r");
1265
1266                 /* si j == 1 tengo que paginar por estado */
1267                 fread(&ord, sizeof(t_OrdExt_Data), 1, fp);
1268                 strcpy(st, ord.estado);
1269                 while (!feof(fp)) {
1270                         lista_agregar_fila(lista,
1271                                 ord.numero,
1272                                 ord.emision,
1273                                 get_estado(ord.estado),
1274                                 get_forma_pago(ord.fp),
1275                                 ord.importe
1276                         );
1277                         strcpy(st, ord.estado);
1278                         
1279                         fread(&ord, sizeof(t_OrdExt_Data), 1, fp);
1280                         /* Si el estado cambio y j == 1 */
1281                         if ((strcmp(st, ord.estado) != 0) && (j == 1)) {
1282                                 /* Hago la pausa para mostrar lo que hay */
1283                                 editar = lista_ejecutar(lista);
1284                                 if (editar != -1) {
1285                                         char cc[20];
1286                                         sprintf(cc, "%d", editar);
1287                                         fact_modificar(cc);
1288                                 }
1289                                 /* bue, ya miraron, ahora limpio y sigo con el resto */
1290                                 lista_clear(lista);
1291                         }
1292                 }
1293
1294                 /* Elimino el archivo temporal */
1295                 unlink("tmp_ord.xxx");
1296         }
1297         curs_set(0);
1298         editar = lista_ejecutar(lista);
1299         curs_set(1);
1300         if (editar != -1) {
1301                 char cc[20];
1302                 sprintf(cc, "%d", editar);
1303                 fact_modificar(cc);
1304         }
1305         wrefresh(win1);
1306         wrefresh(win);
1307         werase(win1);
1308         werase(win);
1309         wrefresh(win);
1310         delwin(win);
1311 }
1312
1313 void fact_consultas_varias(char *nombre_indice, char *titulo)
1314 {
1315         int i, cant, error;
1316         char *desc, *tmp;
1317         t_Factura factura;
1318         t_Lista *lista;
1319         t_Form *form;
1320         INDICE_DATO *datos;
1321         WINDOW *win, *win1;
1322         CLAVE k;
1323         EMUFS *fs;
1324         EMUFS_REG_SIZE size;
1325         int editar;
1326
1327         fs = lst_facturas->fp;
1328
1329         win = newwin(LINES-4, COLS-2, 2, 1);
1330         win1 = derwin(win, LINES-6, COLS-4, 1, 1);
1331         werase(win);
1332         box(win, 0, 0);
1333         wrefresh(win);
1334         
1335         /* El usuario ingresa rango a listar */
1336         form = form_crear(win1);
1337         form_agregar_widget(form, INPUT, titulo, 50, "");
1338
1339         form_ejecutar(form, 2, 2);
1340
1341         tmp = form_obtener_valor_char(form, titulo);
1342         desc = malloc(sizeof(char)*(strlen(tmp)+1));
1343         strcpy(desc, tmp);
1344
1345         form_destruir(form);
1346         werase(win1);
1347         wrefresh(win1);
1348
1349         /* Creo la lista donde mostrar la consulta*/
1350         /* Muestro solo info relevante */
1351         lista = lista_crear(4, win1, COLS-4, LINES-6);
1352
1353         /* Creo las columnas */
1354         lista_agregar_columna(lista, "Numero", DATO_INT, 0, 8);    /* numero     */
1355         lista_agregar_columna(lista, "Fecha", DATO_STR, 10, 9);   /* emision    */
1356         lista_agregar_columna(lista, "Estado", DATO_STR, 20, 19);  /* estado     */
1357         lista_agregar_columna(lista, "Forma Pago", DATO_STR, 40, 19);   /* fp         */
1358
1359         /* Leo los datos desde el archivo */
1360         datos = emufs_buscar_registros(fs, nombre_indice, desc, &cant);
1361         for(i=0; i<cant; i++) {
1362                 k.i_clave = datos[i].id;
1363                 error = 1;
1364                 tmp = (char *)fs->leer_registro(fs, k, &size, &error);
1365                 if (tmp != NULL) {
1366                         procesar_leer_factura(&factura, tmp, size, lst_facturas);
1367                         lista_agregar_fila(lista,
1368                                 factura.numero,
1369                                 factura.emision,
1370                                 get_estado(factura.estado),
1371                                 get_forma_pago(factura.fp)
1372                         );
1373                         free(tmp);
1374                 } else {
1375                         PERR("NO SE PUDO RECUPERAR EL REGISTRO DE DATOS");
1376                 }
1377         }
1378
1379         curs_set(0);
1380         editar = lista_ejecutar(lista);
1381         curs_set(1);
1382         if (editar != -1) {
1383                 char cc[20];
1384                 sprintf(cc, "%d", editar);
1385                 fact_modificar(cc);
1386         }
1387         
1388         wrefresh(win1);
1389         wrefresh(win);
1390         werase(win1);
1391         werase(win);
1392         wrefresh(win);
1393         delwin(win);
1394 }
1395
1396 void fact_consultas(char *s)
1397 {
1398         MENU(mi_menu) {
1399                 MENU_OPCION("por Codigos", "Consulta de Articulos por rango de codigo."),
1400                 MENU_OPCION("por Fecha de Emision", "Consulta por fecha unica"),
1401                 MENU_OPCION("por Rango de Fecha", "Consulta por rando de fecha de emision"),
1402                 MENU_OPCION("por Presentacion", "Consulta por Presentacion"),
1403                 MENU_OPCION("Volver", "Volver al menu anterior.")
1404         };
1405         int opt;
1406         
1407         while ((opt = menu_ejecutar(mi_menu, 5, "Consulta de Articulos")) != 4) {
1408                 switch (opt) {
1409                         case 0:
1410                                 fact_consultas_codigos(s);
1411                         break;
1412                         case 1:
1413                                 fact_consultas_varias("emision", "Fecha");
1414                         break;
1415                         case 2:
1416                                 fact_consultas_fechas(s);
1417                         break;
1418                         case 3:
1419                                 fact_consultas_varias("presentacion", "Presentacion");
1420                 }
1421         }
1422 }
1423
1424 void imprimir1(WINDOW *win, int y, int x, char *s, char *b)
1425 {
1426         wmove(win, y, x);
1427         waddstr(win, s);
1428         waddstr(win, b);
1429 }
1430
1431 void mostrar_fact(WINDOW *win, CLAVE k, char *s, INDICE *idx)
1432 {
1433         t_Factura *fact;
1434         EMUFS_REG_ID dummy;
1435         int y = 3;
1436         char numero[10];
1437         /* XXX SOLO PARA CODIGO XXX */
1438         
1439         wattron(win, COLOR_PAIR(COLOR_RED));
1440         mvwaddstr(win, 1, 5, "Recorriendo Facturas por indice ");
1441         waddstr(win, s);
1442         wattroff(win, COLOR_PAIR(COLOR_RED));
1443
1444         wattron(win, A_BOLD);
1445         mvwaddstr(win, 18, 5, "Teclas:");
1446         wattroff(win, A_BOLD);
1447         mvwaddstr(win, 19, 5, " L = Siguiente");
1448         mvwaddstr(win, 20, 5, " K = Anterior");
1449
1450         if (strcmp(s, "numero") == 0) {
1451                 fact = fact_buscar(lst_facturas, k.i_clave, &dummy, &dummy);
1452         } else {
1453                 INDICE_DATO *datos;
1454                 EMUFS_REG_SIZE size;
1455                 int cant, error;
1456                 char *tmp;
1457
1458                 fact = (t_Factura *)malloc(sizeof(t_Factura));
1459                 /* Ya se cual tengo que retornar. Ahora veo si lo cargo desde el archivo */
1460                 PERR("Busco todos los datos que tengan esta clave");
1461                 datos = idx->buscar_entradas(idx, k, &cant);
1462                 if (datos == NULL) {
1463                         free(fact);
1464                         fact = NULL;
1465                 } else {
1466                         k.i_clave = datos[0].id;
1467                         PERR("Leo el primer dato");
1468                         error = 1;
1469                         tmp = lst_facturas->fp->leer_registro(lst_facturas->fp, k, &size, &error);
1470                         if (tmp == NULL) {
1471                                 free(fact);
1472                                 fact = NULL;
1473                         } else {
1474                                 if (procesar_leer_factura(fact, tmp, size, lst_facturas) != 0) {
1475                                         free(fact);
1476                                         free(tmp);
1477                                         fact = NULL;
1478                                 }
1479                         }
1480                         free(datos);
1481                 }
1482         }
1483
1484         if (fact != NULL) {
1485                 sprintf(numero, "%08d", fact->numero);
1486
1487                 imprimir1(win, y++, 5, "Numero      : ", numero);
1488                 imprimir1(win, y++, 5, "Fecha Emision : ", fact->emision);
1489                 imprimir1(win, y++, 5, "Fecha Vto     : ", fact->vencimiento);
1490                 imprimir1(win, y++, 5, "Estado        : ", fact->estado);
1491                 imprimir1(win, y++, 5, "Forma de Pago : ", fact->fp);
1492                 imprimir1(win, y++, 5, "Cuenta Cte    : ", fact->ctacte);
1493                 imprimir1(win, y++, 5, "Cheque Nro    : ", fact->cheque);
1494                 sprintf(numero, "%08d", fact->numero_remito);
1495                 imprimir1(win, y++, 5, "Remito        : ", numero);
1496                 sprintf(numero, "%.2f", fact->procdoi);
1497                 imprimir1(win, y++, 5, "% Descuento   : ", numero);
1498                 sprintf(numero, "%d", fact->cant_items);
1499                 imprimir1(win, y++, 5, "Cant de Items : ", numero);
1500
1501                 if (fact->items) free(fact->items);
1502                 free(fact);
1503         } else {
1504                 PERR("NO EXISTE LA FACTURA");
1505         }
1506 }
1507
1508 void fact_recorrer_con_indice(char *s)
1509 {
1510         WINDOW *win, *win1;
1511         INDICE *idx;
1512         CLAVE stack[1000]; /* shhhh */
1513         CLAVE k;
1514         int stack_pos=0, c;
1515                 
1516         PERR("Busco indice");
1517         idx = emufs_buscar_indice_por_nombre(lst_facturas->fp, s);
1518
1519         win = newwin(LINES-4, COLS-2, 2, 1);
1520         win1 = derwin(win, LINES-6, COLS-4, 1, 1);
1521         werase(win);
1522         box(win, 0, 0);
1523         wrefresh(win);
1524
1525         PERR("Obtengo clave menor");
1526         k = idx->obtener_menor_clave(idx);
1527         
1528         PERR("Muestro el primer elemento");
1529         mostrar_fact(win1, k, s, idx);
1530         wrefresh(win1);
1531         PERR("Sigue el usuario");
1532         curs_set(0);
1533         stack[0] = k;
1534         while ((c=wgetch(win)) != 13) {
1535                 switch (c) {
1536                         case 'L':
1537                         case 'l':
1538                                 stack[stack_pos++] = k; /* Guardo la clave para poder volver */
1539                                 k = idx->obtener_sig_clave(idx, k);
1540                                 /* TODO Verificar que no me pase del fin */
1541                                 break;
1542                         case 'K':
1543                         case 'k':
1544                                 /* recupero la anterior */
1545                                 stack_pos--;
1546                                 if (stack_pos < 0) stack_pos = 0;
1547                                 k = stack[stack_pos];
1548                                 break;
1549                         default:
1550                                 continue;
1551                 }
1552                 werase(win1);
1553                 mostrar_fact(win1, k, s, idx);
1554                 wrefresh(win1);
1555         }
1556         curs_set(1);
1557
1558         werase(win1);
1559         werase(win);
1560         wrefresh(win);
1561         delwin(win);
1562 }
1563
1564 void fact_recorrer()
1565 {
1566         char *ind[5] = {"numero", "emision", "vto", "cheque", "ctacte"};
1567         MENU(mi_menu) {
1568                 MENU_OPCION("Numero", "Recorrer por Indice Numero Factura"),
1569                 MENU_OPCION("Emision", "Recorrer por Indice Fecha Emision"),
1570                 MENU_OPCION("Vencimiento", "Recorrer por Indice Fecha Vencimiento"),
1571                 MENU_OPCION("Cheque", "Recorrer por Indice Cheque"),
1572                 MENU_OPCION("Cuenta Cte", "Recorrer por Indice Cuenta Cte"),
1573                 MENU_OPCION("Volver", "Volver al menu anterior.")
1574         };
1575         int opt;
1576         while ((opt = menu_ejecutar(mi_menu, 6, "Recorrer Facturas")) != 5) {
1577                 fact_recorrer_con_indice(ind[opt]);
1578         }
1579 }
1580
1581 int fact_hay_con_item(int numero)
1582 {
1583         INDICE *idx;
1584         CLAVE k;
1585         INDICE_DATO dato;
1586         /* Busco si existe alguna factura que contenga al articulo "numero" */
1587         idx = lst_facturas->fp->externo;
1588
1589         k.i_clave = numero;
1590         dato = idx->existe_entrada(idx, k);
1591
1592         if (dato.id == -1)
1593                 return 0; /* No existe factura que contenga este articulo!! */
1594
1595         return 1; /* Hay alguna factura que contiene el articulo */
1596 }
1597
1598 int comparar_externo(void *it1, void *it2)
1599 {
1600         t_OrdExt_Data *d1, *d2;
1601         d1 = (t_OrdExt_Data *)it1;
1602         d2 = (t_OrdExt_Data *)it2;
1603
1604         /* Primero veo de ordenar por Estado */
1605         if (strcmp(d1->estado, d2->estado) == 0) {
1606                 /* Tienen el mismo estado, los ordeno por numero de fatura */
1607                 return d1->numero - d2->numero;
1608         }
1609
1610         /* como no son iguales, comparo los estados */
1611         return strcmp(d1->estado, d2->estado);
1612 }
1613
1614 static void dump_facturas(char *tmpfile)
1615 {
1616         t_Factura *fact;
1617         EMUFS_REG_ID id;
1618         FILE *fp;
1619         CLAVE k;
1620         INDICE *idx;
1621         int len;
1622
1623         PERR("1");
1624         idx = lst_facturas->fp->indices;
1625         if (idx == NULL) {
1626                 PERR("LO QUE?!! ... NO TENGO INDICE PRIMARIO!");
1627         }
1628         PERR("2");
1629         k = idx->obtener_menor_clave(idx);
1630
1631         PERR("3");
1632         if (!(fp = fopen(tmpfile, "wb"))) {
1633                 PERR("Error al crear archivo temporal");
1634                 return;
1635         }
1636         
1637         while (k.i_clave != -1) {
1638                 PERR("Busco articulo");
1639                 fact = fact_buscar(lst_facturas, k.i_clave, &id, &id);
1640                 PERR("Done");
1641                 if (fact != NULL) {
1642                         PERR("Agrego Archivo");
1643                         fwrite(fact, 1, sizeof(t_Articulo), fp);
1644                         /* Guardo items */
1645                         fwrite(fact->items, fact->cant_items, sizeof(t_Item), fp);
1646                         /* Guardo longitud de la nota */
1647                         len = strlen(fact->nota)+1;
1648                         fwrite(&len, 1, sizeof(int), fp);
1649                         fwrite(fact->nota, 1, len, fp);
1650                         if (fact->items) free(fact->items);
1651                         if (fact->nota) free(fact->nota);
1652                         free(fact);
1653                         PERR("Done");
1654                 }
1655                 k = idx->obtener_sig_clave(idx, k);
1656         }
1657
1658         fclose(fp);
1659 }