]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs_gui/facturas.c
littles correcciones, lo que esta escrito no es necesariamente cierto pero es lo...
[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         lst_facturas->fp_texto = emufs_crear("notas", param->tipo_arch_nota, param->tam_bloque_nota, 100);
896         PERR("Listo!");
897
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                 PERR("Leo registro");
908                 if (fread(&factura, sizeof(t_Factura), 1, fp) != 1) continue;
909                 factura.items = malloc(sizeof(t_Item)*factura.cant_items);
910                 fread(factura.items, factura.cant_items, sizeof(t_Item), fp);
911                 fread(&len, 1, sizeof(int), fp);
912                 factura.nota = malloc(len*sizeof(char));
913                 fread(factura.nota, 1, len, fp);
914                 PERR(factura.nota);
915                 PERR("Lo guardo");
916                 /* Listo, ya lei, ahora agrego */
917                 error = 0;
918                 id = lst_facturas->fp_texto->grabar_registro(lst_facturas->fp_texto, factura.nota, (param->tipo_arch_nota==T3)?100:(strlen(factura.nota)+1), &error);
919                 factura.reg_nota = id;
920                 save = procesar_guardar_factura(&factura, lst_facturas, &size);
921                 if (save != NULL) {
922                         int i;
923                         error = 0;
924                         id = lst_facturas->fp->grabar_registro(lst_facturas->fp, save, size, &error);
925                                         
926                         /* Agrego los Items al indice externo */
927                         for(i=0; i<factura.cant_items; i++) {
928                                 if (factura.items[i].numero != 0) {
929                                         CLAVE _k; /* HACK Para hacer mas rapido */
930                                         INDICE_DATO _dato;
931                                         _k.i_clave = factura.items[i].numero;
932                                         _dato.id = id;
933                                         lst_facturas->fp->externo->agregar_entrada(lst_facturas->fp->externo, _k, _dato);
934                                 }
935                         }
936                                 
937                         if (factura.items) {
938                                 free(factura.items);
939                                 factura.items = NULL;
940                         }
941                         if (factura.nota) {
942                                 free(factura.nota);
943                                 factura.nota = NULL;
944                         }
945                         free(save);
946                 }
947         }
948         fclose(fp);
949 }
950
951 int fact_exportar_xml(const char *filename)
952 {
953         int j;
954         t_Factura *fact;
955         EMUFS_REG_ID id, id1;
956         FILE *fp;
957         CLAVE k;
958         INDICE *idx;
959
960         idx = lst_facturas->fp->indices;
961
962         k = idx->obtener_menor_clave(idx);
963
964         if (!(fp = fopen(filename, "wt"))) return 0;
965         
966         fprintf(fp, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n");
967         fprintf(fp, "<FACTURAS>\n");
968         while (k.i_clave != -1) {
969                 fact = fact_buscar(lst_facturas, k.i_clave, &id, &id1);
970                 if (fact != NULL) {
971                         fprintf(fp, "\t<FACTURA NroFac=\"%08d\" ", fact->numero);
972                         fprintf(fp, "FechaEmisiĂłn=\"%s\" ", fact->emision);
973                         fprintf(fp, "FechaVto=\"%s\" ", fact->vencimiento);
974                         fprintf(fp, "NroRemito=\"%08d\" ", fact->numero_remito);
975                         fprintf(fp, "FP=\"%s\" ", fact->fp);
976                         fprintf(fp, "Estado=\"%s\" ", fact->estado);
977                         fprintf(fp, "NroCheque=\"%s\" ", fact->cheque);
978                         fprintf(fp, "PorcDoI=\"%.2f\" ", fact->procdoi);
979                         fprintf(fp, "NroCtaCte=\"%s\" ", fact->ctacte);
980                         fprintf(fp, ">\n");
981                         fprintf(fp, "\t\t<NOTA>%s</NOTA>\n", fact->nota);
982                         for(j=0; j<fact->cant_items; j++) {
983                                 if (fact->items[j].numero != 0)
984                                         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);
985                         }
986                         fprintf(fp, "\t</FACTURA>\n");
987                         free(fact);
988                 }
989                 k = idx->obtener_sig_clave(idx, k);
990         }
991         fprintf(fp, "\t</FACTURAS>\n");
992
993         fclose(fp);
994         return 1;
995 }
996
997 char *get_estado(char *s)
998 {
999         if (strcmp(s, "PN")==0) return "Pago Normal";
1000         if (strcmp(s, "CD")==0) return "Credito al dia";
1001         if (strcmp(s, "CM")==0) return "Credito en mora";
1002         if (strcmp(s, "SF")==0) return "Cheque sin fondos";
1003         if (strcmp(s, "PM")==0) return "Pagada con Mora";
1004         if (strcmp(s, "NC")==0) return "No Cobrada";
1005
1006         return s;
1007 }
1008
1009 char *get_forma_pago(char *s)
1010 {
1011         if (strcmp(s, "CO") == 0) return "Contado";
1012         if (strcmp(s, "CR") == 0) return "Credito";
1013         if (strcmp(s, "CH") == 0) return "Cheque";
1014
1015         return s;
1016 }
1017
1018 void fact_consultas_codigos(char *s)
1019 {
1020         EMUFS_REG_ID dummy;
1021         int desde_codigo, hasta_codigo;
1022         t_Factura *factura;
1023         t_Lista *lista;
1024         t_Form *form;
1025         WINDOW *win, *win1;
1026         INDICE *idx;
1027         CLAVE k, menor, mayor;
1028         int editar;
1029
1030         idx = lst_facturas->fp->indices;
1031
1032         win = newwin(LINES-4, COLS-2, 2, 1);
1033         win1 = derwin(win, LINES-6, COLS-4, 1, 1);
1034         werase(win);
1035         box(win, 0, 0);
1036         wrefresh(win);
1037         
1038         /* El usuario ingresa rango a listar */
1039         form = form_crear(win1);
1040         form_agregar_widget(form, INPUT, "Desde Codigo", 8, "0");
1041         form_agregar_widget(form, INPUT, "Hasta Codigo", 8, "99999999");
1042
1043         form_ejecutar(form, 2, 2);
1044
1045         desde_codigo = form_obtener_valor_int(form, "Desde Codigo");
1046         hasta_codigo = form_obtener_valor_int(form, "Hasta Codigo");
1047
1048         form_destruir(form);
1049         werase(win1);
1050         wrefresh(win1);
1051
1052         menor = idx->obtener_menor_clave(idx);
1053         mayor = idx->obtener_mayor_clave(idx);
1054
1055         if (desde_codigo < menor.i_clave)
1056                 desde_codigo = menor.i_clave;
1057         if (hasta_codigo > mayor.i_clave)
1058                 hasta_codigo = mayor.i_clave;
1059
1060         /* Creo la lista donde mostrar la consulta*/
1061         /* Muestro solo info relevante */
1062         lista = lista_crear(4, win1, COLS-4, LINES-6);
1063
1064         /* Creo las columnas */
1065         lista_agregar_columna(lista, "Numero", DATO_INT, 0, 8);    /* numero     */
1066         lista_agregar_columna(lista, "Fecha", DATO_STR, 10, 9);   /* emision    */
1067         lista_agregar_columna(lista, "Estado", DATO_STR, 20, 19);  /* estado     */
1068         lista_agregar_columna(lista, "F. Pago", DATO_STR, 40, 9);   /* fp         */
1069
1070         /* Leo los datos desde el archivo */
1071         k.i_clave = desde_codigo;
1072         while ((k.i_clave != -1) && (k.i_clave <= hasta_codigo)) {
1073                 factura = fact_buscar(lst_facturas, k.i_clave, &dummy, &dummy);
1074                 if (factura != NULL) {
1075                         lista_agregar_fila(lista,
1076                                 factura->numero,
1077                                 factura->emision,
1078                                 get_estado(factura->estado),
1079                                 get_forma_pago(factura->fp)
1080                         );
1081                 }
1082                 k = idx->obtener_sig_clave(idx, k);
1083         }
1084
1085         curs_set(0);
1086         editar = lista_ejecutar(lista);
1087         curs_set(1);
1088         
1089         if (editar != -1) {
1090                 char cc[20];
1091                 sprintf(cc, "%d", editar);
1092                 fact_modificar(cc);
1093         }
1094         
1095         wrefresh(win1);
1096         wrefresh(win);
1097         werase(win1);
1098         werase(win);
1099         wrefresh(win);
1100         delwin(win);
1101 }
1102
1103 float get_importe_factura(t_Item *items, int cant, float interes)
1104 {
1105         float a=0.0f;
1106         int i;
1107         for(i=0; i<cant; i++) {
1108                 a += atof(items[i].cv)*atof(items[i].pvu);
1109         }
1110         a += a*interes/100.0f;
1111         return a;
1112 }
1113
1114
1115 void fact_consultas_fechas(char *s)
1116 {
1117         char desde_fecha[10], hasta_fecha[10];
1118         char estado[6];
1119         t_Lista *lista;
1120         t_Form *form;
1121         WINDOW *win, *win1;
1122         INDICE *idx;
1123         CLAVE k_menor, k_mayor;
1124         int todo=0;
1125         int editar;
1126
1127         win = newwin(LINES-4, COLS-2, 2, 1);
1128         win1 = derwin(win, LINES-6, COLS-4, 1, 1);
1129         werase(win);
1130         box(win, 0, 0);
1131         wrefresh(win);
1132         
1133         /* El usuario ingresa rango a listar */
1134         form = form_crear(win1);
1135         form_agregar_widget(form, INPUT, "Desde Fecha", 8, "");
1136         form_agregar_widget(form, INPUT, "Hasta Fecha", 8, "");
1137         form_agregar_widget(form, RADIO, "Estado", 7, "Todos,PN,CD,CM,SF,PM,NC");
1138         form_ejecutar(form, 2, 2);
1139
1140         strcpy(desde_fecha, form_obtener_valor_char(form, "Desde Fecha"));
1141         strcpy(hasta_fecha, form_obtener_valor_char(form, "Hasta Fecha"));
1142         strcpy(estado, form_obtener_valor_char(form, "Estado"));
1143
1144         form_destruir(form);
1145         werase(win1);
1146         wrefresh(win1);
1147
1148         /* Si el usuario no ingreso alguno de los datos, lo obtengo del indice */
1149         idx = emufs_buscar_indice_por_nombre(lst_facturas->fp, "emision");
1150         if (idx==NULL) PERR("INDICE EMISION NO SE ENCUENTRA!!");
1151
1152         /* XXX Politica de seleccion de uso de ord externo
1153          *
1154          * Se usa ordenamiento externo en alguno de estos 2 casos :
1155          *   * Se requiere un listado de todo el rango de fechas
1156          *   * Se requiere un listado de todos los Estados
1157          *
1158          *   Para cualquier otro caso, se ordena directamente
1159          *   en la lista
1160          */
1161         if (strlen(desde_fecha) == 0) {
1162                 k_menor = idx->obtener_menor_clave(idx);
1163                 emufs_indice_obtener_valor_desde_clave(idx, k_menor, desde_fecha);
1164                 PERR("OBTUVE MENOR CLAVE DESDE EL INDICE");
1165                 PERR(desde_fecha);
1166                 todo++;
1167         }
1168         if (strlen(hasta_fecha) == 0) {
1169                 k_mayor = idx->obtener_mayor_clave(idx);
1170                 emufs_indice_obtener_valor_desde_clave(idx, k_mayor, hasta_fecha);
1171                 PERR("OBTUVE MAYOR CLAVE DESDE EL INDICE");
1172                 PERR(hasta_fecha);
1173                 todo++;
1174         }
1175
1176         if (strcmp(estado, "Todos") == 0) todo = 2;
1177
1178         if (todo == 2) {
1179                 /* Debo utilizar un ord, externo!! */
1180                 FILE *fp;
1181                 /* Creo el archivo a ordenar */
1182                 fp = fopen("tmp_ord.xxx", "w");
1183                 while (k_menor.i_clave != -1) {
1184                         t_Factura fact;
1185                         int error, cant, i;
1186                         char *leo;
1187                         t_OrdExt_Data ord;
1188                         EMUFS_REG_SIZE size;
1189                         INDICE_DATO *datos;
1190                         CLAVE k1;
1191                         datos = idx->buscar_entradas(idx, k_menor, &cant);
1192                         for(i=0; i<cant; i++) {
1193                                 error = 1;
1194                                 k1.i_clave = datos[i].id;
1195                                 leo = lst_facturas->fp->leer_registro(lst_facturas->fp, k1, &size, &error);
1196                                 if (leo != NULL) {
1197                                         procesar_leer_factura(&fact, leo, size, lst_facturas);
1198                                         free(leo);
1199                                         ord.numero = fact.numero;
1200                                         strcpy(ord.emision, fact.emision);
1201                                         strcpy(ord.estado, fact.estado);
1202                                         strcpy(ord.fp, fact.fp);
1203                                         ord.importe = get_importe_factura(fact.items, fact.cant_items, fact.procdoi);
1204                                         fwrite(&ord, sizeof(t_OrdExt_Data), 1, fp);
1205                                 }
1206                         }
1207                         if (datos) free(datos);
1208                         if (fact.items) free(fact.items);
1209                         k_menor = idx->obtener_sig_clave(idx, k_menor);
1210                 }
1211                 fclose(fp);
1212                 /* Mando a ordenar */
1213                 extsort("tmp_ord.xxx", 4096, sizeof(t_OrdExt_Data), comparar_externo);
1214         }
1215         /* Creo la lista donde mostrar la consulta*/
1216         /* Muestro solo info relevante */
1217         lista = lista_crear(4, win1, COLS-4, LINES-6);
1218
1219         /* Creo las columnas */
1220         lista_agregar_columna(lista, "Numero", DATO_INT, 0, 8);    /* numero     */
1221         lista_agregar_columna(lista, "Fecha", DATO_STR, 10, 9);   /* emision    */
1222         lista_agregar_columna(lista, "Estado", DATO_STR, 20, 19);  /* estado     */
1223         lista_agregar_columna(lista, "F. Pago", DATO_STR, 40, 9);   /* fp         */
1224         lista_agregar_columna(lista, "Importe", DATO_FLOAT, 50, 8);   /* importe         */
1225
1226         /* Leo los datos desde el archivo */
1227         if (todo != 2) {
1228                 while (k_menor.i_clave != -1) {
1229                         t_Factura fact;
1230                         int error, cant, i;
1231                         char *leo;
1232                         EMUFS_REG_SIZE size;
1233                         INDICE_DATO *datos;
1234                         CLAVE k1;
1235                         datos = idx->buscar_entradas(idx, k_menor, &cant);
1236                         for(i=0; i<cant; i++) {
1237                                 error = 1;
1238                                 k1.i_clave = datos[i].id;
1239                                 leo = lst_facturas->fp->leer_registro(lst_facturas->fp, k1, &size, &error);
1240                                 if (leo != NULL) {
1241                                         procesar_leer_factura(&fact, leo, size, lst_facturas);
1242                                         free(leo);
1243                                 }
1244                                 if (strcmp(estado, fact.estado) == 0) {
1245                                         lista_agregar_fila_ordenada(lista,
1246                                                 fact.numero,
1247                                                 fact.emision,
1248                                                 get_estado(fact.estado),
1249                                                 get_forma_pago(fact.fp),
1250                                                 get_importe_factura(fact.items, fact.cant_items, fact.procdoi)
1251                                         );
1252                                 }
1253                         }
1254                         if (datos) free(datos);
1255                         if (fact.items) free(fact.items);
1256                 }
1257                 k_menor = idx->obtener_sig_clave(idx, k_menor);
1258         } else {
1259                 /* Cargo la lista a partir del archivo ordenado externamente */
1260                 FILE *fp;
1261                 int j;
1262                 char st[3];
1263                 t_OrdExt_Data ord;
1264                 
1265                 j =( strcmp(estado, "Todos") == 0);
1266                 fp = fopen("tmp_ord.xxx", "r");
1267
1268                 /* si j == 1 tengo que paginar por estado */
1269                 fread(&ord, sizeof(t_OrdExt_Data), 1, fp);
1270                 strcpy(st, ord.estado);
1271                 while (!feof(fp)) {
1272                         lista_agregar_fila(lista,
1273                                 ord.numero,
1274                                 ord.emision,
1275                                 get_estado(ord.estado),
1276                                 get_forma_pago(ord.fp),
1277                                 ord.importe
1278                         );
1279                         strcpy(st, ord.estado);
1280                         
1281                         fread(&ord, sizeof(t_OrdExt_Data), 1, fp);
1282                         /* Si el estado cambio y j == 1 */
1283                         if ((strcmp(st, ord.estado) != 0) && (j == 1)) {
1284                                 /* Hago la pausa para mostrar lo que hay */
1285                                 editar = lista_ejecutar(lista);
1286                                 if (editar != -1) {
1287                                         char cc[20];
1288                                         sprintf(cc, "%d", editar);
1289                                         fact_modificar(cc);
1290                                 }
1291                                 /* bue, ya miraron, ahora limpio y sigo con el resto */
1292                                 lista_clear(lista);
1293                         }
1294                 }
1295
1296                 /* Elimino el archivo temporal */
1297                 unlink("tmp_ord.xxx");
1298         }
1299         curs_set(0);
1300         editar = lista_ejecutar(lista);
1301         curs_set(1);
1302         if (editar != -1) {
1303                 char cc[20];
1304                 sprintf(cc, "%d", editar);
1305                 fact_modificar(cc);
1306         }
1307         wrefresh(win1);
1308         wrefresh(win);
1309         werase(win1);
1310         werase(win);
1311         wrefresh(win);
1312         delwin(win);
1313 }
1314
1315 void fact_consultas_varias(char *nombre_indice, char *titulo)
1316 {
1317         int i, cant, error;
1318         char *desc, *tmp;
1319         t_Factura factura;
1320         t_Lista *lista;
1321         t_Form *form;
1322         INDICE_DATO *datos;
1323         WINDOW *win, *win1;
1324         CLAVE k;
1325         EMUFS *fs;
1326         EMUFS_REG_SIZE size;
1327         int editar;
1328
1329         fs = lst_facturas->fp;
1330
1331         win = newwin(LINES-4, COLS-2, 2, 1);
1332         win1 = derwin(win, LINES-6, COLS-4, 1, 1);
1333         werase(win);
1334         box(win, 0, 0);
1335         wrefresh(win);
1336         
1337         /* El usuario ingresa rango a listar */
1338         form = form_crear(win1);
1339         form_agregar_widget(form, INPUT, titulo, 50, "");
1340
1341         form_ejecutar(form, 2, 2);
1342
1343         tmp = form_obtener_valor_char(form, titulo);
1344         desc = malloc(sizeof(char)*(strlen(tmp)+1));
1345         strcpy(desc, tmp);
1346
1347         form_destruir(form);
1348         werase(win1);
1349         wrefresh(win1);
1350
1351         /* Creo la lista donde mostrar la consulta*/
1352         /* Muestro solo info relevante */
1353         lista = lista_crear(4, win1, COLS-4, LINES-6);
1354
1355         /* Creo las columnas */
1356         lista_agregar_columna(lista, "Numero", DATO_INT, 0, 8);    /* numero     */
1357         lista_agregar_columna(lista, "Fecha", DATO_STR, 10, 9);   /* emision    */
1358         lista_agregar_columna(lista, "Estado", DATO_STR, 20, 19);  /* estado     */
1359         lista_agregar_columna(lista, "Forma Pago", DATO_STR, 40, 19);   /* fp         */
1360
1361         /* Leo los datos desde el archivo */
1362         datos = emufs_buscar_registros(fs, nombre_indice, desc, &cant);
1363         for(i=0; i<cant; i++) {
1364                 k.i_clave = datos[i].id;
1365                 error = 1;
1366                 tmp = (char *)fs->leer_registro(fs, k, &size, &error);
1367                 if (tmp != NULL) {
1368                         procesar_leer_factura(&factura, tmp, size, lst_facturas);
1369                         lista_agregar_fila(lista,
1370                                 factura.numero,
1371                                 factura.emision,
1372                                 get_estado(factura.estado),
1373                                 get_forma_pago(factura.fp)
1374                         );
1375                         free(tmp);
1376                 } else {
1377                         PERR("NO SE PUDO RECUPERAR EL REGISTRO DE DATOS");
1378                 }
1379         }
1380
1381         curs_set(0);
1382         editar = lista_ejecutar(lista);
1383         curs_set(1);
1384         if (editar != -1) {
1385                 char cc[20];
1386                 sprintf(cc, "%d", editar);
1387                 fact_modificar(cc);
1388         }
1389         
1390         wrefresh(win1);
1391         wrefresh(win);
1392         werase(win1);
1393         werase(win);
1394         wrefresh(win);
1395         delwin(win);
1396 }
1397
1398 void fact_consultas(char *s)
1399 {
1400         MENU(mi_menu) {
1401                 MENU_OPCION("por Codigos", "Consulta de Articulos por rango de codigo."),
1402                 MENU_OPCION("por Fecha de Emision", "Consulta por fecha unica"),
1403                 MENU_OPCION("por Rango de Fecha", "Consulta por rando de fecha de emision"),
1404                 MENU_OPCION("por Presentacion", "Consulta por Presentacion"),
1405                 MENU_OPCION("Volver", "Volver al menu anterior.")
1406         };
1407         int opt;
1408         
1409         while ((opt = menu_ejecutar(mi_menu, 5, "Consulta de Articulos")) != 4) {
1410                 switch (opt) {
1411                         case 0:
1412                                 fact_consultas_codigos(s);
1413                         break;
1414                         case 1:
1415                                 fact_consultas_varias("emision", "Fecha");
1416                         break;
1417                         case 2:
1418                                 fact_consultas_fechas(s);
1419                         break;
1420                         case 3:
1421                                 fact_consultas_varias("presentacion", "Presentacion");
1422                 }
1423         }
1424 }
1425
1426 void imprimir1(WINDOW *win, int y, int x, char *s, char *b)
1427 {
1428         wmove(win, y, x);
1429         waddstr(win, s);
1430         waddstr(win, b);
1431 }
1432
1433 void mostrar_fact(WINDOW *win, CLAVE k, char *s, INDICE *idx)
1434 {
1435         t_Factura *fact;
1436         EMUFS_REG_ID dummy;
1437         int y = 3;
1438         char numero[10];
1439         /* XXX SOLO PARA CODIGO XXX */
1440         
1441         wattron(win, COLOR_PAIR(COLOR_RED));
1442         mvwaddstr(win, 1, 5, "Recorriendo Facturas por indice ");
1443         waddstr(win, s);
1444         wattroff(win, COLOR_PAIR(COLOR_RED));
1445
1446         wattron(win, A_BOLD);
1447         mvwaddstr(win, 18, 5, "Teclas:");
1448         wattroff(win, A_BOLD);
1449         mvwaddstr(win, 19, 5, " L = Siguiente");
1450         mvwaddstr(win, 20, 5, " K = Anterior");
1451
1452         if (strcmp(s, "numero") == 0) {
1453                 fact = fact_buscar(lst_facturas, k.i_clave, &dummy, &dummy);
1454         } else {
1455                 INDICE_DATO *datos;
1456                 EMUFS_REG_SIZE size;
1457                 int cant, error;
1458                 char *tmp;
1459
1460                 fact = (t_Factura *)malloc(sizeof(t_Factura));
1461                 /* Ya se cual tengo que retornar. Ahora veo si lo cargo desde el archivo */
1462                 PERR("Busco todos los datos que tengan esta clave");
1463                 datos = idx->buscar_entradas(idx, k, &cant);
1464                 if (datos == NULL) {
1465                         free(fact);
1466                         fact = NULL;
1467                 } else {
1468                         k.i_clave = datos[0].id;
1469                         PERR("Leo el primer dato");
1470                         error = 1;
1471                         tmp = lst_facturas->fp->leer_registro(lst_facturas->fp, k, &size, &error);
1472                         if (tmp == NULL) {
1473                                 free(fact);
1474                                 fact = NULL;
1475                         } else {
1476                                 if (procesar_leer_factura(fact, tmp, size, lst_facturas) != 0) {
1477                                         free(fact);
1478                                         free(tmp);
1479                                         fact = NULL;
1480                                 }
1481                         }
1482                         free(datos);
1483                 }
1484         }
1485
1486         if (fact != NULL) {
1487                 sprintf(numero, "%08d", fact->numero);
1488
1489                 imprimir1(win, y++, 5, "Numero      : ", numero);
1490                 imprimir1(win, y++, 5, "Fecha Emision : ", fact->emision);
1491                 imprimir1(win, y++, 5, "Fecha Vto     : ", fact->vencimiento);
1492                 imprimir1(win, y++, 5, "Estado        : ", fact->estado);
1493                 imprimir1(win, y++, 5, "Forma de Pago : ", fact->fp);
1494                 imprimir1(win, y++, 5, "Cuenta Cte    : ", fact->ctacte);
1495                 imprimir1(win, y++, 5, "Cheque Nro    : ", fact->cheque);
1496                 sprintf(numero, "%08d", fact->numero_remito);
1497                 imprimir1(win, y++, 5, "Remito        : ", numero);
1498                 sprintf(numero, "%.2f", fact->procdoi);
1499                 imprimir1(win, y++, 5, "% Descuento   : ", numero);
1500                 sprintf(numero, "%d", fact->cant_items);
1501                 imprimir1(win, y++, 5, "Cant de Items : ", numero);
1502
1503                 if (fact->items) free(fact->items);
1504                 free(fact);
1505         } else {
1506                 PERR("NO EXISTE LA FACTURA");
1507         }
1508 }
1509
1510 void fact_recorrer_con_indice(char *s)
1511 {
1512         WINDOW *win, *win1;
1513         INDICE *idx;
1514         CLAVE stack[1000]; /* shhhh */
1515         CLAVE k;
1516         int stack_pos=0, c;
1517                 
1518         PERR("Busco indice");
1519         idx = emufs_buscar_indice_por_nombre(lst_facturas->fp, s);
1520
1521         win = newwin(LINES-4, COLS-2, 2, 1);
1522         win1 = derwin(win, LINES-6, COLS-4, 1, 1);
1523         werase(win);
1524         box(win, 0, 0);
1525         wrefresh(win);
1526
1527         PERR("Obtengo clave menor");
1528         k = idx->obtener_menor_clave(idx);
1529         
1530         PERR("Muestro el primer elemento");
1531         mostrar_fact(win1, k, s, idx);
1532         wrefresh(win1);
1533         PERR("Sigue el usuario");
1534         curs_set(0);
1535         stack[0] = k;
1536         while ((c=wgetch(win)) != 13) {
1537                 switch (c) {
1538                         case 'L':
1539                         case 'l':
1540                                 stack[stack_pos++] = k; /* Guardo la clave para poder volver */
1541                                 k = idx->obtener_sig_clave(idx, k);
1542                                 /* TODO Verificar que no me pase del fin */
1543                                 break;
1544                         case 'K':
1545                         case 'k':
1546                                 /* recupero la anterior */
1547                                 stack_pos--;
1548                                 if (stack_pos < 0) stack_pos = 0;
1549                                 k = stack[stack_pos];
1550                                 break;
1551                         default:
1552                                 continue;
1553                 }
1554                 werase(win1);
1555                 mostrar_fact(win1, k, s, idx);
1556                 wrefresh(win1);
1557         }
1558         curs_set(1);
1559
1560         werase(win1);
1561         werase(win);
1562         wrefresh(win);
1563         delwin(win);
1564 }
1565
1566 void fact_recorrer()
1567 {
1568         char *ind[5] = {"numero", "emision", "vto", "cheque", "ctacte"};
1569         MENU(mi_menu) {
1570                 MENU_OPCION("Numero", "Recorrer por Indice Numero Factura"),
1571                 MENU_OPCION("Emision", "Recorrer por Indice Fecha Emision"),
1572                 MENU_OPCION("Vencimiento", "Recorrer por Indice Fecha Vencimiento"),
1573                 MENU_OPCION("Cheque", "Recorrer por Indice Cheque"),
1574                 MENU_OPCION("Cuenta Cte", "Recorrer por Indice Cuenta Cte"),
1575                 MENU_OPCION("Volver", "Volver al menu anterior.")
1576         };
1577         int opt;
1578         while ((opt = menu_ejecutar(mi_menu, 6, "Recorrer Facturas")) != 5) {
1579                 fact_recorrer_con_indice(ind[opt]);
1580         }
1581 }
1582
1583 int fact_hay_con_item(int numero)
1584 {
1585         INDICE *idx;
1586         CLAVE k;
1587         INDICE_DATO dato;
1588         /* Busco si existe alguna factura que contenga al articulo "numero" */
1589         idx = lst_facturas->fp->externo;
1590
1591         k.i_clave = numero;
1592         dato = idx->existe_entrada(idx, k);
1593
1594         if (dato.id == -1)
1595                 return 0; /* No existe factura que contenga este articulo!! */
1596
1597         return 1; /* Hay alguna factura que contiene el articulo */
1598 }
1599
1600 int comparar_externo(void *it1, void *it2)
1601 {
1602         t_OrdExt_Data *d1, *d2;
1603         d1 = (t_OrdExt_Data *)it1;
1604         d2 = (t_OrdExt_Data *)it2;
1605
1606         /* Primero veo de ordenar por Estado */
1607         if (strcmp(d1->estado, d2->estado) == 0) {
1608                 /* Tienen el mismo estado, los ordeno por numero de fatura */
1609                 return d1->numero - d2->numero;
1610         }
1611
1612         /* como no son iguales, comparo los estados */
1613         return strcmp(d1->estado, d2->estado);
1614 }
1615
1616 static void dump_facturas(char *tmpfile)
1617 {
1618         t_Factura *fact;
1619         EMUFS_REG_ID id;
1620         FILE *fp;
1621         CLAVE k;
1622         INDICE *idx;
1623         int len;
1624
1625         PERR("1");
1626         idx = lst_facturas->fp->indices;
1627         if (idx == NULL) {
1628                 PERR("LO QUE?!! ... NO TENGO INDICE PRIMARIO!");
1629         }
1630         PERR("2");
1631         k = idx->obtener_menor_clave(idx);
1632
1633         PERR("3");
1634         if (!(fp = fopen(tmpfile, "wb"))) {
1635                 PERR("Error al crear archivo temporal");
1636                 return;
1637         }
1638         
1639         while (k.i_clave != -1) {
1640                 PERR("Busco articulo");
1641                 fact = fact_buscar(lst_facturas, k.i_clave, &id, &id);
1642                 PERR("Done");
1643                 if (fact != NULL) {
1644                         PERR("Agrego Archivo");
1645                         fwrite(fact, 1, sizeof(t_Articulo), fp);
1646                         /* Guardo items */
1647                         fwrite(fact->items, fact->cant_items, sizeof(t_Item), fp);
1648                         /* Guardo longitud de la nota */
1649                         len = strlen(fact->nota)+1;
1650                         fwrite(&len, 1, sizeof(int), fp);
1651                         fwrite(fact->nota, 1, len, fp);
1652                         if (fact->items) free(fact->items);
1653                         if (fact->nota) free(fact->nota);
1654                         free(fact);
1655                         PERR("Done");
1656                 }
1657                 k = idx->obtener_sig_clave(idx, k);
1658         }
1659
1660         fclose(fp);
1661 }