GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-entry-xml-v2.c
1 /********************************************************************\
2  * gnc-entry-xml-v2.c -- entry xml i/o implementation *
3  * *
4  * Copyright (C) 2002 Derek Atkins <[email protected]> *
5  * *
6  * This program is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU General Public License as *
8  * published by the Free Software Foundation; either version 2 of *
9  * the License, or (at your option) any later version. *
10  * *
11  * This program is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14  * GNU General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License*
17  * along with this program; if not, contact: *
18  * *
19  * Free Software Foundation Voice: +1-617-542-5942 *
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21  * Boston, MA 02110-1301, USA [email protected] *
22  * *
23 \********************************************************************/
24 
25 #include "config.h"
26 
27 #include <glib.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "gnc-xml-helper.h"
32 
33 #include "sixtp.h"
34 #include "sixtp-utils.h"
35 #include "sixtp-parsers.h"
36 #include "sixtp-utils.h"
37 #include "sixtp-dom-parsers.h"
38 #include "sixtp-dom-generators.h"
39 
40 #include "gnc-xml.h"
41 #include "io-gncxml-gen.h"
42 #include "io-gncxml-v2.h"
43 
44 #include "gncEntryP.h"
45 #include "gncOrderP.h"
46 #include "gncInvoiceP.h"
47 #include "gncTaxTableP.h"
48 #include "gnc-entry-xml-v2.h"
49 #include "gnc-owner-xml-v2.h"
50 
51 #define _GNC_MOD_NAME GNC_ID_ENTRY
52 
53 static QofLogModule log_module = GNC_MOD_IO;
54 
55 const gchar *entry_version_string = "2.0.0";
56 
57 /* ids */
58 #define gnc_entry_string "gnc:GncEntry"
59 #define entry_guid_string "entry:guid"
60 #define entry_date_string "entry:date"
61 #define entry_dateentered_string "entry:entered"
62 #define entry_description_string "entry:description"
63 #define entry_action_string "entry:action"
64 #define entry_notes_string "entry:notes"
65 #define entry_qty_string "entry:qty"
66 
67 /* cust inv */
68 #define entry_invacct_string "entry:i-acct"
69 #define entry_iprice_string "entry:i-price"
70 #define entry_idiscount_string "entry:i-discount"
71 #define entry_idisctype_string "entry:i-disc-type"
72 #define entry_idischow_string "entry:i-disc-how"
73 #define entry_itaxable_string "entry:i-taxable"
74 #define entry_itaxincluded_string "entry:i-taxincluded"
75 #define entry_itaxtable_string "entry:i-taxtable"
76 
77 /* vend bill */
78 #define entry_billacct_string "entry:b-acct"
79 #define entry_bprice_string "entry:b-price"
80 #define entry_btaxable_string "entry:b-taxable"
81 #define entry_btaxincluded_string "entry:b-taxincluded"
82 #define entry_btaxtable_string "entry:b-taxtable"
83 #define entry_billable_string "entry:billable"
84 #define entry_billto_string "entry:billto"
85 
86 /* emp bill */
87 #define entry_billpayment_string "entry:b-pay"
88 
89 /* other stuff */
90 #define entry_order_string "entry:order"
91 #define entry_invoice_string "entry:invoice"
92 #define entry_bill_string "entry:bill"
93 #define entry_slots_string "entry:slots"
94 
95 /* EFFECTIVE FRIEND FUNCTION */
96 extern KvpFrame *qof_instance_get_slots (const QofInstance*);
97 
98 static void
99 maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
100 {
101  if (str && strlen(str) > 0)
102  xmlAddChild (ptr, text_to_dom_tree (tag, str));
103 }
104 
105 static void
106 maybe_add_numeric (xmlNodePtr ptr, const char *tag, gnc_numeric num)
107 {
108  if (!gnc_numeric_zero_p (num))
109  xmlAddChild (ptr, gnc_numeric_to_dom_tree (tag, &num));
110 }
111 
112 static xmlNodePtr
113 entry_dom_tree_create (GncEntry *entry)
114 {
115  xmlNodePtr ret;
116  Timespec ts;
117  Account *acc;
118  GncTaxTable *taxtable;
119  GncOrder *order;
120  GncInvoice *invoice;
121  KvpFrame *kf;
122 
123  ret = xmlNewNode(NULL, BAD_CAST gnc_entry_string);
124  xmlSetProp(ret, BAD_CAST "version", BAD_CAST entry_version_string);
125 
126  xmlAddChild(ret, guid_to_dom_tree(entry_guid_string,
127  qof_instance_get_guid(QOF_INSTANCE(entry))));
128 
129  ts = gncEntryGetDate (entry);
130  xmlAddChild(ret, timespec_to_dom_tree (entry_date_string, &ts));
131 
132  ts = gncEntryGetDateEntered (entry);
133  xmlAddChild(ret, timespec_to_dom_tree (entry_dateentered_string, &ts));
134 
135  maybe_add_string (ret, entry_description_string,
136  gncEntryGetDescription (entry));
137  maybe_add_string (ret, entry_action_string, gncEntryGetAction (entry));
138  maybe_add_string (ret, entry_notes_string, gncEntryGetNotes (entry));
139 
140  maybe_add_numeric (ret, entry_qty_string, gncEntryGetQuantity (entry));
141 
142  /* cust invoice */
143 
144  acc = gncEntryGetInvAccount (entry);
145  if (acc)
146  xmlAddChild (ret, guid_to_dom_tree (entry_invacct_string,
147  qof_instance_get_guid(QOF_INSTANCE(acc))));
148 
149  maybe_add_numeric (ret, entry_iprice_string, gncEntryGetInvPrice (entry));
150 
151  maybe_add_numeric (ret, entry_idiscount_string, gncEntryGetInvDiscount (entry));
152 
153  invoice = gncEntryGetInvoice (entry);
154  if (invoice)
155  {
156  xmlAddChild (ret, guid_to_dom_tree (entry_invoice_string,
157  qof_instance_get_guid(QOF_INSTANCE(invoice))));
158 
159  xmlAddChild(ret, text_to_dom_tree(entry_idisctype_string,
160  gncAmountTypeToString (
161  gncEntryGetInvDiscountType (entry))));
162  xmlAddChild(ret, text_to_dom_tree(entry_idischow_string,
164  gncEntryGetInvDiscountHow (entry))));
165 
166  xmlAddChild(ret, int_to_dom_tree(entry_itaxable_string,
167  gncEntryGetInvTaxable (entry)));
168  xmlAddChild(ret, int_to_dom_tree(entry_itaxincluded_string,
169  gncEntryGetInvTaxIncluded (entry)));
170  }
171 
172  taxtable = gncEntryGetInvTaxTable (entry);
173  if (taxtable)
174  xmlAddChild (ret, guid_to_dom_tree (entry_itaxtable_string,
175  qof_instance_get_guid (QOF_INSTANCE(taxtable))));
176 
177  /* vendor bills */
178 
179  acc = gncEntryGetBillAccount (entry);
180  if (acc)
181  xmlAddChild (ret, guid_to_dom_tree (entry_billacct_string,
182  qof_instance_get_guid (QOF_INSTANCE(acc))));
183 
184  maybe_add_numeric (ret, entry_bprice_string, gncEntryGetBillPrice (entry));
185 
186  invoice = gncEntryGetBill (entry);
187  if (invoice)
188  {
189  GncOwner *owner;
190  xmlAddChild (ret, guid_to_dom_tree (entry_bill_string,
191  qof_instance_get_guid(QOF_INSTANCE(invoice))));
192  xmlAddChild(ret, int_to_dom_tree(entry_billable_string,
193  gncEntryGetBillable (entry)));
194  owner = gncEntryGetBillTo (entry);
195  if (owner && owner->owner.undefined != NULL)
196  xmlAddChild (ret, gnc_owner_to_dom_tree (entry_billto_string, owner));
197 
198  xmlAddChild(ret, int_to_dom_tree(entry_btaxable_string,
199  gncEntryGetBillTaxable (entry)));
200  xmlAddChild(ret, int_to_dom_tree(entry_btaxincluded_string,
201  gncEntryGetBillTaxIncluded (entry)));
202  maybe_add_string (ret, entry_billpayment_string,
203  gncEntryPaymentTypeToString (gncEntryGetBillPayment (entry)));
204  }
205 
206  taxtable = gncEntryGetBillTaxTable (entry);
207  if (taxtable)
208  xmlAddChild (ret, guid_to_dom_tree (entry_btaxtable_string,
209  qof_instance_get_guid (QOF_INSTANCE(taxtable))));
210 
211  /* Other stuff */
212 
213  order = gncEntryGetOrder (entry);
214  if (order)
215  xmlAddChild (ret, guid_to_dom_tree (entry_order_string,
216  qof_instance_get_guid(QOF_INSTANCE (order))));
217 
218  kf = qof_instance_get_slots (QOF_INSTANCE(entry));
219  if (kf)
220  {
221  xmlNodePtr kvpnode = kvp_frame_to_dom_tree(entry_slots_string, kf);
222  if (kvpnode)
223  {
224  xmlAddChild(ret, kvpnode);
225  }
226  }
227 
228  return ret;
229 }
230 
231 /***********************************************************************/
232 
234 {
235  GncEntry *entry;
236  QofBook *book;
237  Account *acc;
238 };
239 
240 static inline gboolean
241 set_string(xmlNodePtr node, GncEntry* entry,
242  void (*func)(GncEntry *entry, const char *txt))
243 {
244  char* txt = dom_tree_to_text(node);
245  g_return_val_if_fail(txt, FALSE);
246 
247  func(entry, txt);
248  g_free(txt);
249  return TRUE;
250 }
251 
252 static inline gboolean
253 set_timespec(xmlNodePtr node, GncEntry* entry,
254  void (*func)(GncEntry *entry, Timespec ts))
255 {
256  Timespec ts = dom_tree_to_timespec (node);
257  if (!dom_tree_valid_timespec(&ts, node->name)) return FALSE;
258 
259  func(entry, ts);
260  return TRUE;
261 }
262 
263 static inline gboolean
264 set_numeric(xmlNodePtr node, GncEntry* entry,
265  void (*func)(GncEntry *entry, gnc_numeric num))
266 {
267  gnc_numeric* num = dom_tree_to_gnc_numeric(node);
268  g_return_val_if_fail(num, FALSE);
269 
270  func(entry, *num);
271  g_free(num);
272  return TRUE;
273 }
274 
275 static inline gboolean
276 set_boolean(xmlNodePtr node, GncEntry* entry,
277  void (*func)(GncEntry *entry, gboolean val))
278 {
279  gint64 val;
280 
281  if (!dom_tree_to_integer(node, &val))
282  return FALSE;
283  func (entry, (gboolean)val);
284  return TRUE;
285 }
286 
287 static inline gboolean
288 set_account(xmlNodePtr node, struct entry_pdata *pdata,
289  void (*func)(GncEntry *entry, Account *acc))
290 {
291  GncGUID *guid;
292  Account * acc;
293 
294  guid = dom_tree_to_guid (node);
295  g_return_val_if_fail (guid, FALSE);
296  acc = xaccAccountLookup (guid, pdata->book);
297  g_free (guid);
298  g_return_val_if_fail (acc, FALSE);
299 
300  if (func)
301  func (pdata->entry, acc);
302  else
303  pdata->acc = acc;
304  return TRUE;
305 }
306 
307 static inline gboolean
308 set_taxtable (xmlNodePtr node, struct entry_pdata *pdata,
309  void (*func)(GncEntry *entry, GncTaxTable *taxtable))
310 {
311  GncGUID *guid;
312  GncTaxTable *taxtable;
313 
314  guid = dom_tree_to_guid (node);
315  g_return_val_if_fail (guid, FALSE);
316  taxtable = gncTaxTableLookup (pdata->book, guid);
317  if (!taxtable)
318  {
319  taxtable = gncTaxTableCreate (pdata->book);
320  gncTaxTableBeginEdit (taxtable);
321  gncTaxTableSetGUID (taxtable, guid);
322  gncTaxTableCommitEdit (taxtable);
323  }
324  else
325  gncTaxTableDecRef (taxtable);
326 
327  func (pdata->entry, taxtable);
328  g_free(guid);
329  return TRUE;
330 }
331 
332 static gboolean
333 entry_guid_handler (xmlNodePtr node, gpointer entry_pdata)
334 {
335  struct entry_pdata *pdata = entry_pdata;
336  GncGUID *guid;
337  GncEntry *entry;
338 
339  guid = dom_tree_to_guid(node);
340  g_return_val_if_fail (guid, FALSE);
341  entry = gncEntryLookup (pdata->book, guid);
342  if (entry)
343  {
344  gncEntryDestroy (pdata->entry);
345  pdata->entry = entry;
346  gncEntryBeginEdit (entry);
347  }
348  else
349  {
350  gncEntrySetGUID(pdata->entry, guid);
351  }
352 
353  g_free(guid);
354 
355  return TRUE;
356 }
357 
358 static gboolean
359 entry_date_handler (xmlNodePtr node, gpointer entry_pdata)
360 {
361  struct entry_pdata *pdata = entry_pdata;
362 
363  return set_timespec(node, pdata->entry, gncEntrySetDate);
364 }
365 
366 static gboolean
367 entry_dateentered_handler (xmlNodePtr node, gpointer entry_pdata)
368 {
369  struct entry_pdata *pdata = entry_pdata;
370 
371  return set_timespec(node, pdata->entry, gncEntrySetDateEntered);
372 }
373 
374 static gboolean
375 entry_description_handler (xmlNodePtr node, gpointer entry_pdata)
376 {
377  struct entry_pdata *pdata = entry_pdata;
378 
379  return set_string(node, pdata->entry, gncEntrySetDescription);
380 }
381 
382 static gboolean
383 entry_action_handler (xmlNodePtr node, gpointer entry_pdata)
384 {
385  struct entry_pdata *pdata = entry_pdata;
386 
387  return set_string(node, pdata->entry, gncEntrySetAction);
388 }
389 
390 static gboolean
391 entry_notes_handler (xmlNodePtr node, gpointer entry_pdata)
392 {
393  struct entry_pdata *pdata = entry_pdata;
394 
395  return set_string(node, pdata->entry, gncEntrySetNotes);
396 }
397 
398 static gboolean
399 entry_qty_handler (xmlNodePtr node, gpointer entry_pdata)
400 {
401  struct entry_pdata *pdata = entry_pdata;
402 
403  return set_numeric(node, pdata->entry, gncEntrySetQuantity);
404 }
405 
406 /* Cust invoice */
407 
408 static gboolean
409 entry_invacct_handler (xmlNodePtr node, gpointer entry_pdata)
410 {
411  struct entry_pdata *pdata = entry_pdata;
412  return set_account (node, pdata, gncEntrySetInvAccount);
413 }
414 
415 static gboolean
416 entry_iprice_handler (xmlNodePtr node, gpointer entry_pdata)
417 {
418  struct entry_pdata *pdata = entry_pdata;
419 
420  return set_numeric(node, pdata->entry, gncEntrySetInvPrice);
421 }
422 
423 static gboolean
424 entry_idiscount_handler (xmlNodePtr node, gpointer entry_pdata)
425 {
426  struct entry_pdata *pdata = entry_pdata;
427 
428  return set_numeric(node, pdata->entry, gncEntrySetInvDiscount);
429 }
430 
431 static gboolean
432 entry_idisctype_handler (xmlNodePtr node, gpointer entry_pdata)
433 {
434  struct entry_pdata *pdata = entry_pdata;
435  GncAmountType type;
436  char *str;
437  gboolean ret;
438 
439  str = dom_tree_to_text (node);
440  g_return_val_if_fail (str, FALSE);
441 
442  ret = gncAmountStringToType (str, &type);
443  g_free (str);
444 
445  if (ret)
446  gncEntrySetInvDiscountType(pdata->entry, type);
447 
448  return ret;
449 }
450 
451 static gboolean
452 entry_idischow_handler (xmlNodePtr node, gpointer entry_pdata)
453 {
454  struct entry_pdata *pdata = entry_pdata;
455  GncDiscountHow how;
456  char *str;
457  gboolean ret;
458 
459  str = dom_tree_to_text (node);
460  g_return_val_if_fail (str, FALSE);
461 
462  ret = gncEntryDiscountStringToHow (str, &how);
463  g_free (str);
464 
465  if (ret)
466  gncEntrySetInvDiscountHow(pdata->entry, how);
467 
468  return ret;
469 }
470 
471 static gboolean
472 entry_itaxable_handler (xmlNodePtr node, gpointer entry_pdata)
473 {
474  struct entry_pdata *pdata = entry_pdata;
475  return set_boolean (node, pdata->entry, gncEntrySetInvTaxable);
476 }
477 
478 static gboolean
479 entry_itaxincluded_handler (xmlNodePtr node, gpointer entry_pdata)
480 {
481  struct entry_pdata *pdata = entry_pdata;
482  return set_boolean (node, pdata->entry, gncEntrySetInvTaxIncluded);
483 }
484 
485 static gboolean
486 entry_itaxtable_handler (xmlNodePtr node, gpointer entry_pdata)
487 {
488  struct entry_pdata *pdata = entry_pdata;
489  return set_taxtable (node, pdata, gncEntrySetInvTaxTable);
490 }
491 
492 /* vendor bills */
493 
494 static gboolean
495 entry_billacct_handler (xmlNodePtr node, gpointer entry_pdata)
496 {
497  struct entry_pdata *pdata = entry_pdata;
498  return set_account (node, pdata, gncEntrySetBillAccount);
499 }
500 
501 static gboolean
502 entry_bprice_handler (xmlNodePtr node, gpointer entry_pdata)
503 {
504  struct entry_pdata *pdata = entry_pdata;
505 
506  return set_numeric(node, pdata->entry, gncEntrySetBillPrice);
507 }
508 
509 static gboolean
510 entry_btaxable_handler (xmlNodePtr node, gpointer entry_pdata)
511 {
512  struct entry_pdata *pdata = entry_pdata;
513  return set_boolean (node, pdata->entry, gncEntrySetBillTaxable);
514 }
515 
516 static gboolean
517 entry_btaxincluded_handler (xmlNodePtr node, gpointer entry_pdata)
518 {
519  struct entry_pdata *pdata = entry_pdata;
520  return set_boolean (node, pdata->entry, gncEntrySetBillTaxIncluded);
521 }
522 
523 static gboolean
524 entry_btaxtable_handler (xmlNodePtr node, gpointer entry_pdata)
525 {
526  struct entry_pdata *pdata = entry_pdata;
527  return set_taxtable (node, pdata, gncEntrySetBillTaxTable);
528 }
529 
530 static gboolean
531 entry_billable_handler (xmlNodePtr node, gpointer entry_pdata)
532 {
533  struct entry_pdata *pdata = entry_pdata;
534  return set_boolean (node, pdata->entry, gncEntrySetBillable);
535 }
536 
537 static gboolean
538 entry_billto_handler (xmlNodePtr node, gpointer entry_pdata)
539 {
540  struct entry_pdata *pdata = entry_pdata;
541  GncOwner billto;
542  gboolean ret;
543 
544  ret = gnc_dom_tree_to_owner (node, &billto, pdata->book);
545  if (ret)
546  gncEntrySetBillTo (pdata->entry, &billto);
547 
548  return ret;
549 }
550 
551 /* employee bills */
552 static gboolean
553 entry_billpayment_handler (xmlNodePtr node, gpointer entry_pdata)
554 {
555  struct entry_pdata *pdata = entry_pdata;
556  GncEntryPaymentType type;
557  char *str;
558  gboolean ret;
559 
560  str = dom_tree_to_text (node);
561  g_return_val_if_fail (str, FALSE);
562 
563  ret = gncEntryPaymentStringToType (str, &type);
564  g_free (str);
565 
566  if (ret)
567  gncEntrySetBillPayment(pdata->entry, type);
568 
569  return ret;
570 }
571 
572 /* The rest of the stuff */
573 
574 static gboolean
575 entry_order_handler (xmlNodePtr node, gpointer entry_pdata)
576 {
577  struct entry_pdata *pdata = entry_pdata;
578  GncGUID *guid;
579  GncOrder *order;
580 
581  guid = dom_tree_to_guid (node);
582  g_return_val_if_fail (guid, FALSE);
583  order = gncOrderLookup (pdata->book, guid);
584  if (!order)
585  {
586  order = gncOrderCreate (pdata->book);
587  gncOrderBeginEdit (order);
588  gncOrderSetGUID (order, guid);
589  gncOrderCommitEdit (order);
590  }
591  gncOrderBeginEdit (order);
592  gncOrderAddEntry (order, pdata->entry);
593  gncOrderCommitEdit (order);
594 
595  g_free(guid);
596  return TRUE;
597 }
598 
599 static gboolean
600 entry_invoice_handler (xmlNodePtr node, gpointer entry_pdata)
601 {
602  struct entry_pdata *pdata = entry_pdata;
603  GncGUID *guid;
604  GncInvoice *invoice;
605 
606  guid = dom_tree_to_guid (node);
607  g_return_val_if_fail (guid, FALSE);
608  invoice = gncInvoiceLookup (pdata->book, guid);
609  if (!invoice)
610  {
611  invoice = gncInvoiceCreate (pdata->book);
612  gncInvoiceBeginEdit (invoice);
613  gncInvoiceSetGUID (invoice, guid);
614  gncInvoiceCommitEdit (invoice);
615  }
616  gncInvoiceBeginEdit (invoice);
617  gncInvoiceAddEntry (invoice, pdata->entry);
618  gncInvoiceCommitEdit (invoice);
619 
620  g_free(guid);
621  return TRUE;
622 }
623 
624 static gboolean
625 entry_bill_handler (xmlNodePtr node, gpointer entry_pdata)
626 {
627  struct entry_pdata *pdata = entry_pdata;
628  GncGUID *guid;
629  GncInvoice *invoice;
630 
631  guid = dom_tree_to_guid (node);
632  g_return_val_if_fail (guid, FALSE);
633  invoice = gncInvoiceLookup (pdata->book, guid);
634  if (!invoice)
635  {
636  invoice = gncInvoiceCreate (pdata->book);
637  gncInvoiceBeginEdit (invoice);
638  gncInvoiceSetGUID (invoice, guid);
639  gncInvoiceCommitEdit (invoice);
640  }
641  gncInvoiceBeginEdit (invoice);
642  gncBillAddEntry (invoice, pdata->entry);
643  gncInvoiceCommitEdit (invoice);
644 
645  g_free(guid);
646  return TRUE;
647 }
648 
649 /* Support for older XML versions */
650 
651 static gboolean
652 entry_acct_handler (xmlNodePtr node, gpointer entry_pdata)
653 {
654  struct entry_pdata *pdata = entry_pdata;
655  /* XXX: try to figure out if this is an 'invoice' or a 'bill' --
656  * we have to wait until the end!
657  */
658 
659  return set_account (node, pdata, NULL);
660 }
661 
662 static gboolean
663 entry_price_handler (xmlNodePtr node, gpointer entry_pdata)
664 {
665  struct entry_pdata *pdata = entry_pdata;
666  gboolean res;
667 
668  /* just set both.. Don't worry about extra data if it's wrong */
669  res = set_numeric(node, pdata->entry, gncEntrySetInvPrice);
670  if (res)
671  gncEntrySetBillPrice (pdata->entry, gncEntryGetInvPrice (pdata->entry));
672  return res;
673 }
674 
675 static gboolean
676 entry_slots_handler (xmlNodePtr node, gpointer entry_pdata)
677 {
678  struct entry_pdata *pdata = entry_pdata;
679 
680  return dom_tree_to_kvp_frame_given
681  (node, qof_instance_get_slots (QOF_INSTANCE (pdata->entry)));
682 }
683 
684 static struct dom_tree_handler entry_handlers_v2[] =
685 {
686  { entry_guid_string, entry_guid_handler, 1, 0 },
687  { entry_date_string, entry_date_handler, 1, 0 },
688  { entry_dateentered_string, entry_dateentered_handler, 1, 0 },
689  { entry_description_string, entry_description_handler, 0, 0 },
690  { entry_action_string, entry_action_handler, 0, 0 },
691  { entry_notes_string, entry_notes_handler, 0, 0 },
692  { entry_qty_string, entry_qty_handler, 0, 0 },
693 
694  /* cust invoice */
695  { entry_invacct_string, entry_invacct_handler, 0, 0 },
696  { entry_iprice_string, entry_iprice_handler, 0, 0 },
697  { entry_idiscount_string, entry_idiscount_handler, 0, 0 },
698  { entry_idisctype_string, entry_idisctype_handler, 0, 0 },
699  { entry_idischow_string, entry_idischow_handler, 0, 0 },
700  { entry_itaxable_string, entry_itaxable_handler, 0, 0 },
701  { entry_itaxincluded_string, entry_itaxincluded_handler, 0, 0 },
702  { entry_itaxtable_string, entry_itaxtable_handler, 0, 0 },
703 
704  /* vendor invoice */
705  { entry_billacct_string, entry_billacct_handler, 0, 0 },
706  { entry_bprice_string, entry_bprice_handler, 0, 0 },
707  { entry_btaxable_string, entry_btaxable_handler, 0, 0 },
708  { entry_btaxincluded_string, entry_btaxincluded_handler, 0, 0 },
709  { entry_btaxtable_string, entry_btaxtable_handler, 0, 0 },
710  { entry_billable_string, entry_billable_handler, 0, 0 },
711  { entry_billto_string, entry_billto_handler, 0, 0 },
712 
713  /* employee stuff */
714  { entry_billpayment_string, entry_billpayment_handler, 0, 0 },
715 
716  /* Other stuff */
717  { entry_order_string, entry_order_handler, 0, 0 },
718  { entry_invoice_string, entry_invoice_handler, 0, 0 },
719  { entry_bill_string, entry_bill_handler, 0, 0 },
720  { entry_slots_string, entry_slots_handler, 0, 0 },
721 
722  /* Old XML support */
723  { "entry:acct", entry_acct_handler, 0, 0 },
724  { "entry:price", entry_price_handler, 0, 0 },
725  { "entry:discount", entry_idiscount_handler, 0, 0 },
726  { "entry:disc-type", entry_idisctype_handler, 0, 0 },
727  { "entry:disc-how", entry_idischow_handler, 0, 0 },
728  { "entry:taxable", entry_itaxable_handler, 0, 0 },
729  { "entry:taxincluded", entry_itaxincluded_handler, 0, 0 },
730  { "entry:taxtable", entry_itaxtable_handler, 0, 0 },
731  { NULL, 0, 0, 0 }
732 };
733 
734 static GncEntry*
735 dom_tree_to_entry (xmlNodePtr node, QofBook *book)
736 {
737  struct entry_pdata entry_pdata;
738  gboolean successful;
739 
740  entry_pdata.entry = gncEntryCreate(book);
741  entry_pdata.book = book;
742  entry_pdata.acc = NULL;
743  gncEntryBeginEdit (entry_pdata.entry);
744 
745  successful = dom_tree_generic_parse (node, entry_handlers_v2,
746  &entry_pdata);
747  if (entry_pdata.acc != NULL)
748  {
749  if (gncEntryGetBill (entry_pdata.entry))
750  gncEntrySetBillAccount (entry_pdata.entry, entry_pdata.acc);
751  else
752  gncEntrySetInvAccount (entry_pdata.entry, entry_pdata.acc);
753  }
754 
755  if (successful)
756  gncEntryCommitEdit (entry_pdata.entry);
757  else
758  {
759  PERR ("failed to parse entry tree");
760  gncEntryDestroy (entry_pdata.entry);
761  entry_pdata.entry = NULL;
762  }
763 
764  return entry_pdata.entry;
765 }
766 
767 static gboolean
768 gnc_entry_end_handler(gpointer data_for_children,
769  GSList* data_from_children, GSList* sibling_data,
770  gpointer parent_data, gpointer global_data,
771  gpointer *result, const gchar *tag)
772 {
773  GncEntry *entry;
774  xmlNodePtr tree = (xmlNodePtr)data_for_children;
775  gxpf_data *gdata = (gxpf_data*)global_data;
776  QofBook *book = gdata->bookdata;
777 
778 
779  if (parent_data)
780  {
781  return TRUE;
782  }
783 
784  /* OK. For some messed up reason this is getting called again with a
785  NULL tag. So we ignore those cases */
786  if (!tag)
787  {
788  return TRUE;
789  }
790 
791  g_return_val_if_fail(tree, FALSE);
792 
793  entry = dom_tree_to_entry(tree, book);
794  if (entry != NULL)
795  {
796  gdata->cb(tag, gdata->parsedata, entry);
797  }
798 
799  xmlFreeNode(tree);
800 
801  return entry != NULL;
802 }
803 
804 static sixtp *
805 entry_sixtp_parser_create(void)
806 {
807  return sixtp_dom_parser_new(gnc_entry_end_handler, NULL, NULL);
808 }
809 
810 static void
811 do_count (QofInstance * entry_p, gpointer count_p)
812 {
813  int *count = count_p;
814  (*count)++;
815 }
816 
817 static int
818 entry_get_count (QofBook *book)
819 {
820  int count = 0;
821  qof_object_foreach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
822  return count;
823 }
824 
825 static void
826 xml_add_entry (QofInstance * entry_p, gpointer out_p)
827 {
828  xmlNodePtr node;
829  GncEntry *entry = (GncEntry *) entry_p;
830  FILE *out = out_p;
831 
832  if (ferror(out))
833  return;
834 
835  /* Don't save non-attached entries! */
836  if (!(gncEntryGetOrder (entry) || gncEntryGetInvoice (entry) ||
837  gncEntryGetBill (entry)))
838  return;
839 
840  node = entry_dom_tree_create (entry);
841  xmlElemDump(out, NULL, node);
842  xmlFreeNode (node);
843  if (ferror(out) || fprintf(out, "\n") < 0)
844  return;
845 }
846 
847 static gboolean
848 entry_write (FILE *out, QofBook *book)
849 {
850  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_entry, (gpointer) out);
851  return ferror(out) == 0;
852 }
853 
854 static gboolean
855 entry_ns(FILE *out)
856 {
857  g_return_val_if_fail(out, FALSE);
858  return gnc_xml2_write_namespace_decl(out, "entry");
859 }
860 
861 void
862 gnc_entry_xml_initialize (void)
863 {
864  static GncXmlDataType_t be_data =
865  {
866  GNC_FILE_BACKEND_VERS,
867  gnc_entry_string,
868  entry_sixtp_parser_create,
869  NULL, /* add_item */
870  entry_get_count,
871  entry_write,
872  NULL, /* scrub */
873  entry_ns,
874  };
875 
876  qof_object_register_backend (_GNC_MOD_NAME,
878  &be_data);
879 }
gboolean qof_object_register_backend(QofIdTypeConst type_name, const char *backend_name, gpointer be_data)
Definition: sixtp.h:93
const GncGUID * qof_instance_get_guid(gconstpointer)
void gncEntrySetQuantity(GncEntry *entry, gnc_numeric quantity)
Definition: gncEntry.c:552
void gncEntrySetDate(GncEntry *entry, Timespec date)
Definition: gncEntry.c:481
#define GNC_FILE_BACKEND
Definition: io-gncxml-v2.h:99
Use a 64-bit unsigned int timespec.
Definition: gnc-date.h:299
gboolean gnc_numeric_zero_p(gnc_numeric a)
Timespec gncEntryGetDate(const GncEntry *entry)
Definition: gncEntry.c:878
#define PERR(format, args...)
Definition: qoflog.h:237
Definition: guid.h:65
void qof_object_foreach_sorted(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
api for GnuCash version 2 XML-based file format
void gncBillAddEntry(GncInvoice *bill, GncEntry *entry)
Definition: gncInvoice.c:686
void qof_object_foreach(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
const char * gncEntryDiscountHowToString(GncDiscountHow how)
Definition: gncEntry.c:112
gboolean gnc_xml2_write_namespace_decl(FILE *out, const char *name_space)
struct KvpFrameImpl KvpFrame
Definition: kvp_frame.h:76
gnc_numeric gncEntryGetQuantity(const GncEntry *entry)
Definition: gncEntry.c:919
GncAmountType
Definition: gncTaxTable.h:93
const gchar * QofLogModule
Definition: qofid.h:89
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
Definition: Account.c:1827