]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs_gui/articulos.c
* Agrego un par de datos mas.
[z.facultad/75.06/emufs.git] / emufs_gui / articulos.c
1
2 #include "articulos.h"
3 #include "idx.h"
4 #include "gui.h"
5 #include "common.h"
6
7 static t_LstArticulos *lst_articulos;
8
9 static t_Articulo *art_form_buscar(WINDOW *win, EMUFS_REG_ID *id);
10
11 static void *procesar_guardar_articulo(t_Articulo *src, EMUFS_REG_SIZE *size, t_LstArticulos *lst);
12 static int procesar_leer_articulo(t_Articulo *dst, void *src, EMUFS_REG_SIZE size, t_LstArticulos *lst);
13
14 /* Manejo de la lista doble */
15 static t_Reg_Articulo *crear_nodo_articulo(EMUFS_REG_ID reg, unsigned int num);
16 static int agregar_nodo_articulo(t_LstArticulos *lst, t_Reg_Articulo *nodo);
17 static int eliminar_nodo_articulo(t_LstArticulos *lst, t_Reg_Articulo *nodo);
18
19 t_LstArticulos *art_get_lst()
20 {
21         return lst_articulos;
22 }
23
24 int eliminar_nodo_articulo(t_LstArticulos *lst, t_Reg_Articulo *nodo)
25 {
26         if (nodo == NULL) return 0;
27         if (nodo->ant == NULL) {
28                 /* Me piden borrar el primer nodo */
29                 if (nodo->sig) {
30                         nodo->sig->ant = NULL;
31                 }
32                 lst->primero = nodo->sig;
33         } else {
34                 if (nodo->sig) {
35                         nodo->sig->ant = nodo->ant;
36                 }
37                 nodo->ant->sig = nodo->sig;
38         }
39         free(nodo);
40         return 1;
41 }
42
43 t_Reg_Articulo *crear_nodo_articulo(EMUFS_REG_ID reg, unsigned int num)
44 {
45         t_Reg_Articulo *tmp;
46         if (reg == EMUFS_NOT_FOUND) return NULL;
47         tmp = malloc(sizeof(t_Reg_Articulo));
48         if (tmp == NULL) return NULL;
49         tmp->sig = tmp->ant = NULL;
50         tmp->num_reg = reg;
51         tmp->numero = num;
52
53         return tmp;
54 }
55
56 int agregar_nodo_articulo(t_LstArticulos *lst, t_Reg_Articulo *nodo)
57 {
58         if (nodo == NULL) return 0;
59
60         if (lst->primero) {
61                 lst->primero->ant = nodo;
62                 nodo->sig = lst->primero;
63                 lst->primero = nodo;
64         } else {
65                 lst->primero = nodo;
66         }
67         return 1;
68 }
69
70 t_LstArticulos *art_cargar(const char *filename, int tipo, int tam_bloque)
71 {
72         xmlDocPtr document;
73         xmlNode *node, *inicio;
74         int error = 0, i;
75         char *prop;
76         EMUFS_REG_SIZE size;
77         t_LstArticulos *tmp;
78         lst_articulos = NULL;
79         EMUFS_REG_ID id, *indices, indices_cant;
80
81         tmp = (t_LstArticulos *)malloc(sizeof(t_LstArticulos));
82         if (tmp == NULL) return NULL;
83         lst_articulos = tmp;
84         tmp->primero = NULL;
85
86         if (filename != NULL) {
87                 PERR("Voy a crear desde un XML");
88                 document = xmlReadFile(filename, "ISO-8859-1",0);
89                 if (document == NULL) {
90                         free(tmp);
91                         lst_articulos = NULL;
92                         return NULL;
93                 }
94
95                 inicio = NULL;
96                 node = xmlDocGetRootElement(document);
97                 /* Busco el TAG principal "ARTICULOS" */
98                 while (node) {
99                         if (node->type == XML_ELEMENT_NODE) {
100                                 if (strcmp(node->name, "ARTICULOS") == 0) {
101                                         inicio = node->children;
102                                         break;
103                                 }
104                         }
105                         node = node->next;
106                 }
107
108                 tmp->fp = emufs_crear("articulos", tipo-1, tam_bloque, sizeof(t_Articulo));
109                 for (node=inicio ; node ; node = node->next) {
110                         if (node->type == XML_ELEMENT_NODE) {
111                                 if (strcmp(node->name, "ARTICULO") == 0) {
112                                         t_Articulo art;
113                                         void *save;
114                                         memset(&art, '*', sizeof(t_Articulo));
115                                         prop = xml_get_prop(node, "NroArtículo");
116                                         art.numero = atoi(prop);
117                                         xmlFree(prop);
118                                         strncpy(art.desc, prop = xml_get_prop(node, "Descripción"), 50); xmlFree(prop);
119                                         art.desc[50] = '\0'; /* Me aseguro de que este */
120                                         strncpy(art.presentacion, prop = xml_get_prop(node, "Presentación"), 30); xmlFree(prop);
121                                         art.presentacion[30] = '\0'; /* Me aseguro de que este */
122                                         strncpy(art.existencia, prop = xml_get_prop(node, "Existencia"), 8); xmlFree(prop);
123                                         art.existencia[8] = '\0'; /* Me aseguro de que este */
124                                         strncpy(art.ubicacion, prop = xml_get_prop(node, "Ubicación"), 30); xmlFree(prop);
125                                         strncpy(art.pvu, prop = xml_get_prop(node, "PVU"), 8); xmlFree(prop);
126                                         art.pvu[8] = '\0'; /* Me aseguro de que este */
127                                         strncpy(art.emin, prop = xml_get_prop(node, "Emín"), 8); xmlFree(prop);
128                                         art.emin[8] = '\0'; /* Me aseguro de que este */
129                                         /* Ya leido el articulo ahora paso a guardarlo en el archivo y agregarlo a la lista */
130                                         save = procesar_guardar_articulo(&art, &size, lst_articulos);
131                                         if (save != NULL) {
132                                                 error = 0;
133                                                 id = tmp->fp->grabar_registro(tmp->fp, save, size, &error);
134                                                 agregar_nodo_articulo(tmp, crear_nodo_articulo(id, art.numero));
135                                                 free(save);
136                                         }
137                                 }
138                         }
139                 }
140                 xmlFreeDoc(document);
141                 xmlCleanupParser();
142         } else {
143                 PERR("Voy a recuperar desde un archivo");
144                 tmp->fp = emufs_abrir("articulos");
145                 if (tmp->fp == NULL) {
146                         PERR("No se pudo cargar archivo de articulos.");
147                         free(tmp);
148                         lst_articulos = NULL;
149                         return NULL;
150                 }
151                 /* Ahora trato de recuperar la info */
152                 indices = emufs_idx_get(tmp->fp, &indices_cant);
153                 for(i=0; i<indices_cant; i++) {
154                         t_Articulo art;
155                         void *save;
156                         /* Leo el registro */
157                         error = 0;
158                         save = tmp->fp->leer_registro(tmp->fp, indices[i], &size, &error);
159                         if (procesar_leer_articulo(&art, save, size, tmp) == 1) {
160                                 agregar_nodo_articulo(tmp, crear_nodo_articulo(indices[i], art.numero));
161                                 free(save);
162                         }
163                 }
164                 free(indices);
165         }
166
167         return tmp;
168 }
169
170 int art_liberar(t_LstArticulos *l)
171 {
172         t_Reg_Articulo *del;
173         if (l == NULL) l = lst_articulos;
174         if (l == NULL) return 1;
175
176         emufs_destruir(l->fp);
177         while (l->primero) {
178                 del = l->primero;
179                 l->primero = l->primero->sig;
180                 free(del);
181         }
182         free(l);
183
184         lst_articulos = NULL;
185         return 0;
186 }
187
188 t_Articulo *art_obtener(t_LstArticulos *lst, int numero, EMUFS_REG_ID *id)
189 {
190         t_Articulo *art;
191         t_Reg_Articulo *nodo;
192         void *tmp;
193         int error = 0;
194         EMUFS_REG_SIZE size;
195         int n = numero;
196
197         if (lst == NULL) lst = lst_articulos;
198         if (lst == NULL) return NULL;
199         nodo = lst->primero;
200         while (nodo) {
201                 if (n == nodo->numero) {
202                         (*id) = nodo->num_reg;
203                         art = (t_Articulo *)malloc(sizeof(t_Articulo));
204                         /* Ya se cual tengo que retornar. Ahora veo si lo cargo desde el archivo */
205                         error = 0;
206                         tmp = lst->fp->leer_registro(lst->fp, nodo->num_reg, &size, &error);
207                         
208                         if (error) {
209                                 free(art);
210                                 return NULL;
211                         }
212
213                         if (procesar_leer_articulo(art, tmp, size, lst_articulos) != 1) {
214                                 free(art);
215                                 free(tmp);
216                                 return NULL;
217                         }
218                         free(tmp);
219                         return art;
220                 }
221                 nodo = nodo->sig;
222         }
223
224         return NULL;
225 }
226
227 t_Articulo *art_form_buscar(WINDOW *win, EMUFS_REG_ID *id)
228 {
229         t_Form *form;
230         t_Articulo *articulo;
231
232         form = form_crear(win);
233         form_agregar_widget(form, INPUT, "Numero de Artículo", 8, "");
234         form_ejecutar(form, 1,1);
235         articulo = art_obtener(NULL, form_obtener_valor_int(form, "Numero de Artículo"), id);
236         form_destruir(form);
237
238         return articulo;
239 }
240
241 void art_modificar(char *s)
242 {
243         WINDOW *win;
244         t_Form *form;
245         t_Articulo *articulo;
246         char num[11];
247         void *tmp;
248         int error;
249         EMUFS_REG_SIZE size;
250         EMUFS_REG_ID id;
251
252         win = newwin(9, COLS-2, 13, 1);
253         box(win, 0, 0);
254         wrefresh(win);
255
256         if (s == NULL) {
257                 articulo = art_form_buscar(win, &id);
258         } else {
259                 id = atoi(s);
260                 /* Leo el registro directamente */
261                 articulo = (t_Articulo *)malloc(sizeof(t_Articulo));
262                 /* Ya se cual tengo que retornar. Ahora veo si lo cargo desde el archivo */
263                 error = 0;
264                 tmp = lst_articulos->fp->leer_registro(lst_articulos->fp, id, &size, &error);
265                 if (error) {
266                         free(articulo);
267                         articulo = NULL;
268                 } else {
269                         if (procesar_leer_articulo(articulo, tmp, size, lst_articulos) != 1) {
270                                 free(articulo);
271                                 articulo = NULL;
272                         }
273                         free(tmp);
274                 }
275         }
276
277         if (articulo != NULL) {
278                 form = form_crear(win);
279                 sprintf(num, "%08d", articulo->numero);
280                 form_agregar_widget(form, INPUT, "Numero de Artículo", 8, num);
281                 form_es_modificable(form, "Numero de Artículo" , 0);
282                 form_agregar_widget(form, INPUT, "Descripción", 50, articulo->desc);
283                 form_agregar_widget(form, INPUT, "Presentación", 30, articulo->presentacion);
284                 form_agregar_widget(form, INPUT, "Stock Actual", 8, articulo->existencia);
285                 form_agregar_widget(form, INPUT, "Ubicacion", 30, articulo->ubicacion);
286                 form_agregar_widget(form, INPUT, "PVU", 8, articulo->pvu);
287                 form_agregar_widget(form, INPUT, "Stock Mínimo", 8, articulo->emin);
288                 form_ejecutar(form, 1,1);
289
290                 /* Actualizar registro */
291                 articulo->numero = form_obtener_valor_int(form, "Numero de Artículo");
292                 strcpy(articulo->desc, form_obtener_valor_char(form, "Descripción"));
293                 strcpy(articulo->presentacion, form_obtener_valor_char(form, "Presentación"));
294                 strcpy(articulo->existencia, form_obtener_valor_char(form, "Stock Actual"));
295                 strcpy(articulo->ubicacion, form_obtener_valor_char(form, "Ubicacion"));
296                 strcpy(articulo->pvu, form_obtener_valor_char(form, "PVU"));
297                 strcpy(articulo->emin, form_obtener_valor_char(form, "Stock Mínimo"));
298                 /* Ya actualice los datos, ahora veo de grabarlos */
299                 tmp = procesar_guardar_articulo(articulo, &size, lst_articulos);
300                 if (tmp) {
301                         error = 0;
302                         lst_articulos->fp->modificar_registro(lst_articulos->fp, id, tmp, size, &error);
303                         free(tmp);
304                 }
305                 
306                 form_destruir(form);
307                 free(articulo);
308         } else {        
309                 wattron(win, COLOR_PAIR(COLOR_YELLOW));
310                 mvwaddstr(win, 6, 4, "No existe artículo con ese código. Abortando!");
311                 wattroff(win, COLOR_PAIR(COLOR_YELLOW));
312                 wrefresh(win);
313                 getch();
314         }
315         werase(win);
316         wrefresh(win);
317         delwin(win);
318 }
319
320 void art_eliminar(char *s)
321 {
322         WINDOW *win;
323         t_Articulo *articulo;
324         t_Reg_Articulo *nodo;
325         EMUFS_REG_ID id;
326
327         win = newwin(8, COLS-2, 13, 1);
328         box(win, 0, 0);
329         wrefresh(win);
330
331         articulo = art_form_buscar(win, &id);
332
333         if (articulo == NULL) {
334                 wattron(win, COLOR_PAIR(COLOR_YELLOW));
335                 mvwaddstr(win, 6, 4, "No existe artículo con ese código. Abortando!");
336                 wattroff(win, COLOR_PAIR(COLOR_YELLOW));
337                 wrefresh(win);
338                 getch();
339         } else {
340                 nodo = lst_articulos->primero;
341                 while (nodo) {
342                         if (nodo->numero == articulo->numero) {
343                                 lst_articulos->fp->borrar_registro(lst_articulos->fp, nodo->num_reg);
344                                 eliminar_nodo_articulo(lst_articulos, nodo);
345                                 break;
346                         }
347                         nodo = nodo->sig;
348                 }
349                 free(articulo);
350         }
351
352         werase(win);
353         wrefresh(win);
354         delwin(win);
355 }
356
357 void art_agregar(char *s)
358 {
359         WINDOW *win;
360         t_Form *form;
361         t_Articulo art;
362         t_Reg_Articulo *nuevo;
363         void *save;
364         int error = 0, existe;
365         EMUFS_REG_SIZE size;
366         EMUFS_REG_ID id;
367
368         win = newwin(9, COLS-2, 13, 1);
369         box(win, 0, 0);
370         wrefresh(win);
371
372         form = form_crear(win);
373         form_agregar_widget(form, INPUT, "Numero de Artículo", 8, "");
374         form_agregar_widget(form, INPUT, "Descripción", 50, "");
375         form_agregar_widget(form, INPUT, "Presentación", 30, "");
376         form_agregar_widget(form, INPUT, "Stock Actual", 8, "");
377         form_agregar_widget(form, INPUT, "Ubicacion", 30, "");
378         form_agregar_widget(form, INPUT, "PVU", 8, "");
379         form_agregar_widget(form, INPUT, "Stock Mínimo", 8, "");
380         form_ejecutar(form, 1,1);
381         
382         art.numero = atoi(form_obtener_valor_char(form, "Numero de Artículo"));
383         existe = 0;
384         nuevo = lst_articulos->primero;
385         while (nuevo) {
386                 if (art.numero == nuevo->numero) {
387                         existe = 1;
388                         break;
389                 }
390                 nuevo = nuevo->sig;
391         }
392         
393         if (!existe) {
394                 strcpy(art.desc, form_obtener_valor_char(form, "Descripción"));
395                 strcpy(art.presentacion, form_obtener_valor_char(form, "Presentación"));
396                 strcpy(art.existencia, form_obtener_valor_char(form, "Stock Actual"));
397                 strcpy(art.ubicacion, form_obtener_valor_char(form, "Ubicacion"));
398                 strcpy(art.pvu, form_obtener_valor_char(form, "PVU"));
399                 strcpy(art.emin, form_obtener_valor_char(form, "Stock Mínimo"));
400
401                 /* Ya leido el articulo ahora paso a guardarlo en el archivo y agregarlo a la lista */
402                 save = procesar_guardar_articulo(&art, &size, lst_articulos);
403                 if (save != NULL) {
404                         error = 0;
405                         id = lst_articulos->fp->grabar_registro(lst_articulos->fp, save, size, &error);
406                         if (error) {
407                                 wattron(win, COLOR_PAIR(COLOR_YELLOW));
408                                 mvwaddstr(win, 6, 4, "Error al tratar de agregar el nuevo registro");
409                                 wattroff(win, COLOR_PAIR(COLOR_YELLOW));
410                                 wrefresh(win);
411                                 getch();
412                         } else {
413                                 agregar_nodo_articulo(lst_articulos, crear_nodo_articulo(id, art.numero));
414                         }
415                         free(save);
416                 }
417         } else {
418                 wattron(win, COLOR_PAIR(COLOR_YELLOW));
419                 mvwaddstr(win, 7, 1, "El código ya existe!. Abortando.");
420                 wattroff(win, COLOR_PAIR(COLOR_YELLOW));
421                 wrefresh(win);
422                 getch();
423         }
424         form_destruir(form);
425
426         werase(win);
427         wrefresh(win);
428         delwin(win);
429 }
430
431 int procesar_leer_articulo(t_Articulo *dst, void *src, EMUFS_REG_SIZE size, t_LstArticulos *lst)
432 {
433         char *fin, *ini;
434         switch (lst->fp->tipo) {
435                 case T1:
436                 case T2:
437                         ini = (char *)src;
438                         /* Copio el primer campo, esto es facil :-) */
439                         memset(dst, 0, sizeof(t_Articulo));
440                         memcpy(&dst->numero, ini, sizeof(unsigned int));
441                         ini+=sizeof(unsigned int);
442                         /* Ahora empieza el juego */
443                         /* Los \0 son los delimitadores de campo! */
444                         fin = ini;
445                         while (*fin!='\0') fin++;
446                         memcpy(dst->desc, ini, fin-ini+1);
447                         
448                         ini = fin+1;
449                         fin = ini;
450                         while (*fin!='\0') fin++;
451                         memcpy(dst->presentacion, ini, fin-ini+1);
452                         
453                         ini = fin+1;
454                         fin = ini;
455                         while (*fin!='\0') fin++;
456                         memcpy(dst->existencia, ini, fin-ini+1);
457                         
458                         ini = fin+1;
459                         fin = ini;
460                         while (*fin!='\0') fin++;
461                         memcpy(dst->ubicacion, ini, fin-ini+1);
462                         
463                         ini = fin+1;
464                         fin = ini;
465                         while (*fin!='\0') fin++;
466                         memcpy(dst->pvu, ini, fin-ini+1);
467                         
468                         ini = fin+1;
469                         fin = (char *)src+size;
470                         memcpy(dst->emin, ini, fin-ini);
471
472                         break;
473                 case T3:
474                         memcpy(dst, src, sizeof(t_Articulo));
475         }
476
477         return 1; /* Todo ok */
478 }
479
480 void *procesar_guardar_articulo(t_Articulo *src, EMUFS_REG_SIZE *size, t_LstArticulos *lst)
481 {
482         char *tmp=NULL;
483         int i[7];
484         char *from = (char *)src;
485         switch(lst->fp->tipo) {
486                 case T1:
487                 case T2:
488                         /* Calculo el tamaño que voy a necesitar */
489                         i[0] = sizeof(unsigned int);
490                         i[1] = sizeof(char)*(strlen(src->desc)+1);
491                         i[2] = sizeof(char)*(strlen(src->presentacion)+1);
492                         i[3] = sizeof(char)*(strlen(src->existencia)+1);
493                         i[4] = sizeof(char)*(strlen(src->ubicacion)+1); 
494                         i[5] = sizeof(char)*(strlen(src->pvu)+1);
495                         i[6] = sizeof(char)*(strlen(src->emin)+1);
496                         (*size) = i[0]+i[1]+i[2]+i[3]+i[4]+i[5]+i[6];
497                         tmp = (char *)malloc((*size));
498                         if (tmp == NULL) return NULL;
499                         memset(tmp, 0, *size);
500                         memcpy(tmp, &src->numero, i[0]);
501                         memcpy(tmp+i[0], src->desc, i[1]);
502                         memcpy(tmp+i[0]+i[1], src->presentacion, i[2]);
503                         memcpy(tmp+i[0]+i[1]+i[2], src->existencia, i[3]);
504                         memcpy(tmp+i[0]+i[1]+i[2]+i[3], src->ubicacion, i[4]);
505                         memcpy(tmp+i[0]+i[1]+i[2]+i[3]+i[4], src->pvu, i[5]);
506                         memcpy(tmp+i[0]+i[1]+i[2]+i[3]+i[4]+i[5], src->emin, i[6]);
507                 break;
508                 case T3:
509                         /* Lleno el lugar no ocupado de los strings con *, para que el ver
510                          * registro se vea bien 
511                          */
512                         tmp = (char *)malloc(sizeof(t_Articulo));
513                         memset(tmp, '*', sizeof(t_Articulo));
514                         memcpy(tmp, from, sizeof(t_Articulo));
515                         (*size) = sizeof(t_Articulo);
516         }
517         return tmp;
518 }
519
520 void art_reformatear(int tipo, int tam_bloque, int tam_reg)
521 {
522         EMUFS *nuevo, *old;
523         EMUFS_REG_ID *indices, id;
524         EMUFS_REG_SIZE indices_total, i, size;
525         t_Articulo art;
526         t_LstArticulos *lst_nueva;
527         int error;
528         char *save;
529
530         PERR("==== EMPIEZO ====\n");
531         old = lst_articulos->fp;
532
533         /* Creo el nuevo file */
534         PERR("Creo el archivo\n");
535         nuevo = emufs_crear("emufs_tmp", tipo, tam_bloque, sizeof(t_Articulo));
536         if (nuevo == NULL) {
537                 PERR("ARCHIVO NUEVO NO CREADO");
538                 return;
539         }
540
541         /* Creo la nueva lista */
542         lst_nueva = (t_LstArticulos *)malloc(sizeof(t_LstArticulos));
543         lst_nueva->primero = NULL;
544         lst_nueva->fp = nuevo;
545
546         /* Leo los indices del archivo viejo */
547         PERR("Obtengo Indices\n");
548         indices = emufs_idx_get(old, &indices_total);
549         if (indices == NULL) {
550                 art_liberar(lst_nueva);
551                 return;
552         }
553
554         PERR("Proceso datos\n");
555         for(i=0; i<indices_total; i++) {
556                 error = 0;
557                 save = old->leer_registro(old, indices[i], &size, &error);
558                 if (procesar_leer_articulo(&art, save, size, lst_articulos) == 1) {
559                         free(save);
560                         /* Lei un registro Ok. Lo salvo en el archivo nuevo */
561                         save = procesar_guardar_articulo(&art, &size, lst_nueva);
562                         if (save) {
563                                 error = 0;
564                                 id = nuevo->grabar_registro(nuevo, save, size, &error);
565                                 agregar_nodo_articulo(lst_nueva, crear_nodo_articulo(id, art.numero));
566                                 free(save);
567                         }
568                 }
569         }
570
571         free(indices);
572
573         PERR("Libero lo viejo\n");
574         art_liberar(lst_articulos);
575
576         PERR("Ahora tengo lo nuevo\n");
577         lst_articulos = lst_nueva;
578
579         /* El nuevo tiene como nombre emufs_tmp, lo cambio a mano! */
580         free(lst_articulos->fp->nombre);
581         lst_articulos->fp->nombre = (char *)malloc(sizeof(char)*(strlen("articulos")+1));
582         strcpy(lst_articulos->fp->nombre, "articulos");
583         
584         /* Muevo los archivos! */
585         /* TODO : Poner en otro lugar mas generico! */
586         PERR("Renombre!!\n");
587         rename("emufs_tmp.dat", "articulos.dat");
588         rename("emufs_tmp.idx", "articulos.idx");
589         rename("emufs_tmp.fsc", "articulos.fsc");
590         rename("emufs_tmp.did", "articulos.did");
591         PERR("==== TERMINE ====\n");
592 }
593
594 int art_exportar_xml(const char *filename)
595 {
596         t_Reg_Articulo *nodo;
597         t_Articulo *art;
598         EMUFS_REG_ID id;
599         FILE *fp;
600
601         if (lst_articulos->primero == NULL) return 0;
602
603         nodo = lst_articulos->primero;
604
605         if (!(fp = fopen(filename, "wt"))) return 0;
606         
607         fprintf(fp, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n\n");
608         fprintf(fp, "<ARTICULOS>\n");
609         while (nodo) {
610                 art = art_obtener(lst_articulos, nodo->numero, &id);
611                 if (art != NULL) {
612                         fprintf(fp, "\t<ARTICULO ");
613                         fprintf(fp, "NroArtículo=\"%d\" ", nodo->numero);
614                         fprintf(fp, "Descripción=\"%s\" ", art->desc);
615                         fprintf(fp, "Presentación=\"%s\" ", art->presentacion);
616                         fprintf(fp, "Ubicación=\"%s\" ", art->ubicacion);
617                         fprintf(fp, "Existencia=\"%s\" ", art->existencia);
618                         fprintf(fp, "PVU=\"%s\" ", art->pvu);
619                         fprintf(fp, "Emín=\"%s\" />\n", art->emin);
620                         free(art);
621                 }
622                 nodo = nodo->sig;
623         }
624         fprintf(fp, "</ARTICULOS>\n");
625
626         fclose(fp);
627         return 1;
628 }
629