~siretart/gnucash/ubuntu-fullsource

« back to all changes in this revision

Viewing changes to src/business/business-core/file/gnc-entry-xml-v2.c

  • Committer: Reinhard Tartler
  • Date: 2008-08-03 07:25:46 UTC
  • Revision ID: siretart@tauware.de-20080803072546-y6p8xda8zpfi62ys
import gnucash_2.2.4.orig.tar.gz

The original tarball had the md5sum: 27e660297dc5b8ce574515779d05a5a5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/********************************************************************\
 
2
 * gnc-entry-xml-v2.c -- entry xml i/o implementation         *
 
3
 *                                                                  *
 
4
 * Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU>                *
 
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       gnu@gnu.org                   *
 
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
static void
 
96
maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
 
97
{
 
98
  if (str && strlen(str) > 0)
 
99
    xmlAddChild (ptr, text_to_dom_tree (tag, str));
 
100
}
 
101
 
 
102
static void
 
103
maybe_add_numeric (xmlNodePtr ptr, const char *tag, gnc_numeric num)
 
104
{
 
105
  if (!gnc_numeric_zero_p (num))
 
106
    xmlAddChild (ptr, gnc_numeric_to_dom_tree (tag, &num));
 
107
}
 
108
 
 
109
static xmlNodePtr
 
110
entry_dom_tree_create (GncEntry *entry)
 
111
{
 
112
    xmlNodePtr ret;
 
113
    Timespec ts;
 
114
    Account *acc;
 
115
    GncTaxTable *taxtable;
 
116
    GncOrder *order;
 
117
    GncInvoice *invoice;
 
118
 
 
119
    ret = xmlNewNode(NULL, BAD_CAST gnc_entry_string);
 
120
    xmlSetProp(ret, BAD_CAST "version", BAD_CAST entry_version_string);
 
121
 
 
122
    xmlAddChild(ret, guid_to_dom_tree(entry_guid_string,
 
123
                                      qof_instance_get_guid(QOF_INSTANCE(entry))));
 
124
 
 
125
    ts = gncEntryGetDate (entry);
 
126
    xmlAddChild(ret, timespec_to_dom_tree (entry_date_string, &ts));
 
127
 
 
128
    ts = gncEntryGetDateEntered (entry);
 
129
    xmlAddChild(ret, timespec_to_dom_tree (entry_dateentered_string, &ts));
 
130
    
 
131
    maybe_add_string (ret, entry_description_string,
 
132
                      gncEntryGetDescription (entry));
 
133
    maybe_add_string (ret, entry_action_string, gncEntryGetAction (entry));
 
134
    maybe_add_string (ret, entry_notes_string, gncEntryGetNotes (entry));
 
135
 
 
136
    maybe_add_numeric (ret, entry_qty_string, gncEntryGetQuantity (entry));
 
137
 
 
138
    /* cust invoice */
 
139
 
 
140
    acc = gncEntryGetInvAccount (entry);
 
141
    if (acc)
 
142
      xmlAddChild (ret, guid_to_dom_tree (entry_invacct_string,
 
143
                                          qof_instance_get_guid(QOF_INSTANCE(acc))));
 
144
 
 
145
    maybe_add_numeric (ret, entry_iprice_string, gncEntryGetInvPrice (entry));
 
146
 
 
147
    maybe_add_numeric (ret, entry_idiscount_string, gncEntryGetInvDiscount (entry));
 
148
    
 
149
    invoice = gncEntryGetInvoice (entry);
 
150
    if (invoice) {
 
151
      xmlAddChild (ret, guid_to_dom_tree (entry_invoice_string,
 
152
                                          qof_instance_get_guid(QOF_INSTANCE(invoice))));
 
153
 
 
154
      xmlAddChild(ret, text_to_dom_tree(entry_idisctype_string,
 
155
                                        gncAmountTypeToString (
 
156
                                       gncEntryGetInvDiscountType (entry))));
 
157
      xmlAddChild(ret, text_to_dom_tree(entry_idischow_string,
 
158
                                        gncEntryDiscountHowToString (
 
159
                                     gncEntryGetInvDiscountHow (entry))));
 
160
 
 
161
      xmlAddChild(ret, int_to_dom_tree(entry_itaxable_string,
 
162
                                       gncEntryGetInvTaxable (entry)));
 
163
      xmlAddChild(ret, int_to_dom_tree(entry_itaxincluded_string,
 
164
                                       gncEntryGetInvTaxIncluded (entry)));
 
165
    }
 
166
 
 
167
    taxtable = gncEntryGetInvTaxTable (entry);
 
168
    if (taxtable)
 
169
      xmlAddChild (ret, guid_to_dom_tree (entry_itaxtable_string,
 
170
                                          qof_instance_get_guid (QOF_INSTANCE(taxtable))));
 
171
 
 
172
    /* vendor bills */
 
173
 
 
174
    acc = gncEntryGetBillAccount (entry);
 
175
    if (acc)
 
176
      xmlAddChild (ret, guid_to_dom_tree (entry_billacct_string,
 
177
                                          qof_instance_get_guid (QOF_INSTANCE(acc))));
 
178
 
 
179
    maybe_add_numeric (ret, entry_bprice_string, gncEntryGetBillPrice (entry));
 
180
 
 
181
    invoice = gncEntryGetBill (entry);
 
182
    if (invoice) {
 
183
      GncOwner *owner;
 
184
      xmlAddChild (ret, guid_to_dom_tree (entry_bill_string,
 
185
                                          qof_instance_get_guid(QOF_INSTANCE(invoice))));
 
186
      xmlAddChild(ret, int_to_dom_tree(entry_billable_string,
 
187
                                       gncEntryGetBillable (entry)));
 
188
      owner = gncEntryGetBillTo (entry);
 
189
      if (owner && owner->owner.undefined != NULL)
 
190
        xmlAddChild (ret, gnc_owner_to_dom_tree (entry_billto_string, owner));
 
191
 
 
192
      xmlAddChild(ret, int_to_dom_tree(entry_btaxable_string,
 
193
                                       gncEntryGetBillTaxable (entry)));
 
194
      xmlAddChild(ret, int_to_dom_tree(entry_btaxincluded_string,
 
195
                                       gncEntryGetBillTaxIncluded (entry)));
 
196
      maybe_add_string (ret, entry_billpayment_string,
 
197
                gncEntryPaymentTypeToString (gncEntryGetBillPayment (entry)));
 
198
    }
 
199
 
 
200
    taxtable = gncEntryGetBillTaxTable (entry);
 
201
    if (taxtable)
 
202
      xmlAddChild (ret, guid_to_dom_tree (entry_btaxtable_string,
 
203
                                          qof_instance_get_guid (QOF_INSTANCE(taxtable))));
 
204
 
 
205
    /* Other stuff */
 
206
 
 
207
    order = gncEntryGetOrder (entry);
 
208
    if (order)
 
209
      xmlAddChild (ret, guid_to_dom_tree (entry_order_string,
 
210
                                          qof_instance_get_guid(QOF_INSTANCE (order))));
 
211
 
 
212
    return ret;
 
213
}
 
214
 
 
215
/***********************************************************************/
 
216
 
 
217
struct entry_pdata
 
218
{
 
219
  GncEntry *entry;
 
220
  QofBook *book;
 
221
  Account *acc;
 
222
};
 
223
 
 
224
static inline gboolean
 
225
set_string(xmlNodePtr node, GncEntry* entry,
 
226
           void (*func)(GncEntry *entry, const char *txt))
 
227
{
 
228
  char* txt = dom_tree_to_text(node);
 
229
  g_return_val_if_fail(txt, FALSE);
 
230
    
 
231
  func(entry, txt);
 
232
  g_free(txt);
 
233
  return TRUE;
 
234
}
 
235
 
 
236
static inline gboolean
 
237
set_timespec(xmlNodePtr node, GncEntry* entry,
 
238
           void (*func)(GncEntry *entry, Timespec ts))
 
239
{
 
240
  Timespec ts = dom_tree_to_timespec (node);
 
241
  if (!dom_tree_valid_timespec(&ts, node->name)) return FALSE;
 
242
    
 
243
  func(entry, ts);
 
244
  return TRUE;
 
245
}
 
246
 
 
247
static inline gboolean
 
248
set_numeric(xmlNodePtr node, GncEntry* entry,
 
249
           void (*func)(GncEntry *entry, gnc_numeric num))
 
250
{
 
251
  gnc_numeric* num = dom_tree_to_gnc_numeric(node);
 
252
  g_return_val_if_fail(num, FALSE);
 
253
    
 
254
  func(entry, *num);
 
255
  g_free(num);
 
256
  return TRUE;
 
257
}
 
258
 
 
259
static inline gboolean
 
260
set_boolean(xmlNodePtr node, GncEntry* entry,
 
261
            void (*func)(GncEntry *entry, gboolean val))
 
262
{
 
263
    gint64 val;
 
264
 
 
265
    if (!dom_tree_to_integer(node, &val))
 
266
      return FALSE;
 
267
    func (entry, (gboolean)val);
 
268
    return TRUE;
 
269
}
 
270
 
 
271
static inline gboolean
 
272
set_account(xmlNodePtr node, struct entry_pdata *pdata,
 
273
            void (*func)(GncEntry *entry, Account *acc))
 
274
{
 
275
    GUID *guid;
 
276
    Account * acc;
 
277
 
 
278
    guid = dom_tree_to_guid (node);
 
279
    g_return_val_if_fail (guid, FALSE);
 
280
    acc = xaccAccountLookup (guid, pdata->book);
 
281
    g_free (guid);
 
282
    g_return_val_if_fail (acc, FALSE);
 
283
 
 
284
    if (func)
 
285
      func (pdata->entry, acc);
 
286
    else
 
287
      pdata->acc = acc;
 
288
    return TRUE;
 
289
}
 
290
 
 
291
static inline gboolean
 
292
set_taxtable (xmlNodePtr node, struct entry_pdata *pdata,
 
293
              void (*func)(GncEntry *entry, GncTaxTable *taxtable))
 
294
{
 
295
    GUID *guid;
 
296
    GncTaxTable *taxtable;
 
297
 
 
298
    guid = dom_tree_to_guid (node);
 
299
    g_return_val_if_fail (guid, FALSE);
 
300
    taxtable = gncTaxTableLookup (pdata->book, guid);
 
301
    if (!taxtable) {
 
302
      taxtable = gncTaxTableCreate (pdata->book);
 
303
      gncTaxTableBeginEdit (taxtable);
 
304
      gncTaxTableSetGUID (taxtable, guid);
 
305
      gncTaxTableCommitEdit (taxtable);
 
306
    } else
 
307
      gncTaxTableDecRef (taxtable);
 
308
 
 
309
    func (pdata->entry, taxtable);
 
310
    g_free(guid);
 
311
    return TRUE;
 
312
}
 
313
 
 
314
static gboolean
 
315
entry_guid_handler (xmlNodePtr node, gpointer entry_pdata)
 
316
{
 
317
    struct entry_pdata *pdata = entry_pdata;
 
318
    GUID *guid;
 
319
    GncEntry *entry;
 
320
 
 
321
    guid = dom_tree_to_guid(node);
 
322
    g_return_val_if_fail (guid, FALSE);
 
323
    entry = gncEntryLookup (pdata->book, guid);
 
324
    if (entry) {
 
325
      gncEntryDestroy (pdata->entry);
 
326
      pdata->entry = entry;
 
327
      gncEntryBeginEdit (entry);
 
328
    } else {
 
329
      gncEntrySetGUID(pdata->entry, guid);
 
330
    }
 
331
 
 
332
    g_free(guid);
 
333
    
 
334
    return TRUE;
 
335
}
 
336
 
 
337
static gboolean
 
338
entry_date_handler (xmlNodePtr node, gpointer entry_pdata)
 
339
{
 
340
    struct entry_pdata *pdata = entry_pdata;
 
341
 
 
342
    return set_timespec(node, pdata->entry, gncEntrySetDate);
 
343
}
 
344
 
 
345
static gboolean
 
346
entry_dateentered_handler (xmlNodePtr node, gpointer entry_pdata)
 
347
{
 
348
    struct entry_pdata *pdata = entry_pdata;
 
349
 
 
350
    return set_timespec(node, pdata->entry, gncEntrySetDateEntered);
 
351
}
 
352
 
 
353
static gboolean
 
354
entry_description_handler (xmlNodePtr node, gpointer entry_pdata)
 
355
{
 
356
    struct entry_pdata *pdata = entry_pdata;
 
357
 
 
358
    return set_string(node, pdata->entry, gncEntrySetDescription);
 
359
}
 
360
 
 
361
static gboolean
 
362
entry_action_handler (xmlNodePtr node, gpointer entry_pdata)
 
363
{
 
364
    struct entry_pdata *pdata = entry_pdata;
 
365
 
 
366
    return set_string(node, pdata->entry, gncEntrySetAction);
 
367
}
 
368
 
 
369
static gboolean
 
370
entry_notes_handler (xmlNodePtr node, gpointer entry_pdata)
 
371
{
 
372
    struct entry_pdata *pdata = entry_pdata;
 
373
 
 
374
    return set_string(node, pdata->entry, gncEntrySetNotes);
 
375
}
 
376
 
 
377
static gboolean
 
378
entry_qty_handler (xmlNodePtr node, gpointer entry_pdata)
 
379
{
 
380
    struct entry_pdata *pdata = entry_pdata;
 
381
 
 
382
    return set_numeric(node, pdata->entry, gncEntrySetQuantity);
 
383
}
 
384
 
 
385
/* Cust invoice */
 
386
 
 
387
static gboolean
 
388
entry_invacct_handler (xmlNodePtr node, gpointer entry_pdata)
 
389
{
 
390
    struct entry_pdata *pdata = entry_pdata;
 
391
    return set_account (node, pdata, gncEntrySetInvAccount);
 
392
}
 
393
 
 
394
static gboolean
 
395
entry_iprice_handler (xmlNodePtr node, gpointer entry_pdata)
 
396
{
 
397
    struct entry_pdata *pdata = entry_pdata;
 
398
 
 
399
    return set_numeric(node, pdata->entry, gncEntrySetInvPrice);
 
400
}
 
401
 
 
402
static gboolean
 
403
entry_idiscount_handler (xmlNodePtr node, gpointer entry_pdata)
 
404
{
 
405
    struct entry_pdata *pdata = entry_pdata;
 
406
 
 
407
    return set_numeric(node, pdata->entry, gncEntrySetInvDiscount);
 
408
}
 
409
 
 
410
static gboolean
 
411
entry_idisctype_handler (xmlNodePtr node, gpointer entry_pdata)
 
412
{
 
413
    struct entry_pdata *pdata = entry_pdata;
 
414
    GncAmountType type;
 
415
    char *str;
 
416
    gboolean ret;
 
417
 
 
418
    str = dom_tree_to_text (node);
 
419
    g_return_val_if_fail (str, FALSE);
 
420
 
 
421
    ret = gncAmountStringToType (str, &type);
 
422
    g_free (str);
 
423
 
 
424
    if (ret)
 
425
      gncEntrySetInvDiscountType(pdata->entry, type);
 
426
 
 
427
    return ret;
 
428
}
 
429
 
 
430
static gboolean
 
431
entry_idischow_handler (xmlNodePtr node, gpointer entry_pdata)
 
432
{
 
433
    struct entry_pdata *pdata = entry_pdata;
 
434
    GncDiscountHow how;
 
435
    char *str;
 
436
    gboolean ret;
 
437
 
 
438
    str = dom_tree_to_text (node);
 
439
    g_return_val_if_fail (str, FALSE);
 
440
 
 
441
    ret = gncEntryDiscountStringToHow (str, &how);
 
442
    g_free (str);
 
443
 
 
444
    if (ret)
 
445
      gncEntrySetInvDiscountHow(pdata->entry, how);
 
446
 
 
447
    return ret;
 
448
}
 
449
 
 
450
static gboolean
 
451
entry_itaxable_handler (xmlNodePtr node, gpointer entry_pdata)
 
452
{
 
453
    struct entry_pdata *pdata = entry_pdata;
 
454
    return set_boolean (node, pdata->entry, gncEntrySetInvTaxable);
 
455
}
 
456
 
 
457
static gboolean
 
458
entry_itaxincluded_handler (xmlNodePtr node, gpointer entry_pdata)
 
459
{
 
460
    struct entry_pdata *pdata = entry_pdata;
 
461
    return set_boolean (node, pdata->entry, gncEntrySetInvTaxIncluded);
 
462
}
 
463
 
 
464
static gboolean
 
465
entry_itaxtable_handler (xmlNodePtr node, gpointer entry_pdata)
 
466
{
 
467
    struct entry_pdata *pdata = entry_pdata;
 
468
    return set_taxtable (node, pdata, gncEntrySetInvTaxTable);
 
469
}
 
470
 
 
471
/* vendor bills */
 
472
 
 
473
static gboolean
 
474
entry_billacct_handler (xmlNodePtr node, gpointer entry_pdata)
 
475
{
 
476
    struct entry_pdata *pdata = entry_pdata;
 
477
    return set_account (node, pdata, gncEntrySetBillAccount);
 
478
}
 
479
 
 
480
static gboolean
 
481
entry_bprice_handler (xmlNodePtr node, gpointer entry_pdata)
 
482
{
 
483
    struct entry_pdata *pdata = entry_pdata;
 
484
 
 
485
    return set_numeric(node, pdata->entry, gncEntrySetBillPrice);
 
486
}
 
487
 
 
488
static gboolean
 
489
entry_btaxable_handler (xmlNodePtr node, gpointer entry_pdata)
 
490
{
 
491
    struct entry_pdata *pdata = entry_pdata;
 
492
    return set_boolean (node, pdata->entry, gncEntrySetBillTaxable);
 
493
}
 
494
 
 
495
static gboolean
 
496
entry_btaxincluded_handler (xmlNodePtr node, gpointer entry_pdata)
 
497
{
 
498
    struct entry_pdata *pdata = entry_pdata;
 
499
    return set_boolean (node, pdata->entry, gncEntrySetBillTaxIncluded);
 
500
}
 
501
 
 
502
static gboolean
 
503
entry_btaxtable_handler (xmlNodePtr node, gpointer entry_pdata)
 
504
{
 
505
    struct entry_pdata *pdata = entry_pdata;
 
506
    return set_taxtable (node, pdata, gncEntrySetBillTaxTable);
 
507
}
 
508
 
 
509
static gboolean
 
510
entry_billable_handler (xmlNodePtr node, gpointer entry_pdata)
 
511
{
 
512
    struct entry_pdata *pdata = entry_pdata;
 
513
    return set_boolean (node, pdata->entry, gncEntrySetBillable);
 
514
}
 
515
 
 
516
static gboolean
 
517
entry_billto_handler (xmlNodePtr node, gpointer entry_pdata)
 
518
{
 
519
  struct entry_pdata *pdata = entry_pdata;
 
520
  GncOwner billto;
 
521
  gboolean ret;
 
522
 
 
523
  ret = gnc_dom_tree_to_owner (node, &billto, pdata->book);
 
524
  if (ret)
 
525
    gncEntrySetBillTo (pdata->entry, &billto);
 
526
 
 
527
  return ret;
 
528
}
 
529
 
 
530
/* employee bills */
 
531
static gboolean
 
532
entry_billpayment_handler (xmlNodePtr node, gpointer entry_pdata)
 
533
{
 
534
    struct entry_pdata *pdata = entry_pdata;
 
535
    GncEntryPaymentType type;
 
536
    char *str;
 
537
    gboolean ret;
 
538
 
 
539
    str = dom_tree_to_text (node);
 
540
    g_return_val_if_fail (str, FALSE);
 
541
 
 
542
    ret = gncEntryPaymentStringToType (str, &type);
 
543
    g_free (str);
 
544
 
 
545
    if (ret)
 
546
      gncEntrySetBillPayment(pdata->entry, type);
 
547
 
 
548
    return ret;
 
549
}
 
550
 
 
551
/* The rest of the stuff */
 
552
 
 
553
static gboolean
 
554
entry_order_handler (xmlNodePtr node, gpointer entry_pdata)
 
555
{
 
556
    struct entry_pdata *pdata = entry_pdata;
 
557
    GUID *guid;
 
558
    GncOrder *order;
 
559
 
 
560
    guid = dom_tree_to_guid (node);
 
561
    g_return_val_if_fail (guid, FALSE);
 
562
    order = gncOrderLookup (pdata->book, guid);
 
563
    if (!order) {
 
564
      order = gncOrderCreate (pdata->book);
 
565
      gncOrderBeginEdit (order);
 
566
      gncOrderSetGUID (order, guid);
 
567
      gncOrderCommitEdit (order);
 
568
    }
 
569
    gncOrderBeginEdit (order);
 
570
    gncOrderAddEntry (order, pdata->entry);
 
571
    gncOrderCommitEdit (order);
 
572
 
 
573
    g_free(guid);
 
574
    return TRUE;
 
575
}
 
576
 
 
577
static gboolean
 
578
entry_invoice_handler (xmlNodePtr node, gpointer entry_pdata)
 
579
{
 
580
    struct entry_pdata *pdata = entry_pdata;
 
581
    GUID *guid;
 
582
    GncInvoice *invoice;
 
583
 
 
584
    guid = dom_tree_to_guid (node);
 
585
    g_return_val_if_fail (guid, FALSE);
 
586
    invoice = gncInvoiceLookup (pdata->book, guid);
 
587
    if (!invoice) {
 
588
      invoice = gncInvoiceCreate (pdata->book);
 
589
      gncInvoiceBeginEdit (invoice);
 
590
      gncInvoiceSetGUID (invoice, guid);
 
591
      gncInvoiceCommitEdit (invoice);
 
592
    }
 
593
    gncInvoiceBeginEdit (invoice);
 
594
    gncInvoiceAddEntry (invoice, pdata->entry);
 
595
    gncInvoiceCommitEdit (invoice);
 
596
 
 
597
    g_free(guid);
 
598
    return TRUE;
 
599
}
 
600
 
 
601
static gboolean
 
602
entry_bill_handler (xmlNodePtr node, gpointer entry_pdata)
 
603
{
 
604
    struct entry_pdata *pdata = entry_pdata;
 
605
    GUID *guid;
 
606
    GncInvoice *invoice;
 
607
 
 
608
    guid = dom_tree_to_guid (node);
 
609
    g_return_val_if_fail (guid, FALSE);
 
610
    invoice = gncInvoiceLookup (pdata->book, guid);
 
611
    if (!invoice) {
 
612
      invoice = gncInvoiceCreate (pdata->book);
 
613
      gncInvoiceBeginEdit (invoice);
 
614
      gncInvoiceSetGUID (invoice, guid);
 
615
      gncInvoiceCommitEdit (invoice);
 
616
    }
 
617
    gncInvoiceBeginEdit (invoice);
 
618
    gncBillAddEntry (invoice, pdata->entry);
 
619
    gncInvoiceCommitEdit (invoice);
 
620
 
 
621
    g_free(guid);
 
622
    return TRUE;
 
623
}
 
624
 
 
625
/* Support for older XML versions */
 
626
 
 
627
static gboolean
 
628
entry_acct_handler (xmlNodePtr node, gpointer entry_pdata)
 
629
{
 
630
    struct entry_pdata *pdata = entry_pdata;
 
631
    /* XXX: try to figure out if this is an 'invoice' or a 'bill' --
 
632
     * we have to wait until the end!
 
633
     */
 
634
 
 
635
    return set_account (node, pdata, NULL);
 
636
}
 
637
 
 
638
static gboolean
 
639
entry_price_handler (xmlNodePtr node, gpointer entry_pdata)
 
640
{
 
641
    struct entry_pdata *pdata = entry_pdata;
 
642
    gboolean res;
 
643
 
 
644
    /* just set both.. Don't worry about extra data if it's wrong */
 
645
    res = set_numeric(node, pdata->entry, gncEntrySetInvPrice);
 
646
    if (res)
 
647
      gncEntrySetBillPrice (pdata->entry, gncEntryGetInvPrice (pdata->entry));
 
648
    return res;
 
649
}
 
650
 
 
651
static gboolean
 
652
entry_slots_handler (xmlNodePtr node, gpointer entry_pdata)
 
653
{
 
654
  return TRUE;
 
655
}
 
656
 
 
657
static struct dom_tree_handler entry_handlers_v2[] = {
 
658
    { entry_guid_string, entry_guid_handler, 1, 0 },
 
659
    { entry_date_string, entry_date_handler, 1, 0 },
 
660
    { entry_dateentered_string, entry_dateentered_handler, 1, 0 },
 
661
    { entry_description_string, entry_description_handler, 0, 0 },
 
662
    { entry_action_string, entry_action_handler, 0, 0 },
 
663
    { entry_notes_string, entry_notes_handler, 0, 0 },
 
664
    { entry_qty_string, entry_qty_handler, 0, 0 },
 
665
 
 
666
    /* cust invoice */
 
667
    { entry_invacct_string, entry_invacct_handler, 0, 0 },
 
668
    { entry_iprice_string, entry_iprice_handler, 0, 0 },
 
669
    { entry_idiscount_string, entry_idiscount_handler, 0, 0 },
 
670
    { entry_idisctype_string, entry_idisctype_handler, 0, 0 },
 
671
    { entry_idischow_string, entry_idischow_handler, 0, 0 },
 
672
    { entry_itaxable_string, entry_itaxable_handler, 0, 0 },
 
673
    { entry_itaxincluded_string, entry_itaxincluded_handler, 0, 0 },
 
674
    { entry_itaxtable_string, entry_itaxtable_handler, 0, 0 },
 
675
 
 
676
    /* vendor invoice */
 
677
    { entry_billacct_string, entry_billacct_handler, 0, 0 },
 
678
    { entry_bprice_string, entry_bprice_handler, 0, 0 },
 
679
    { entry_btaxable_string, entry_btaxable_handler, 0, 0 },
 
680
    { entry_btaxincluded_string, entry_btaxincluded_handler, 0, 0 },
 
681
    { entry_btaxtable_string, entry_btaxtable_handler, 0, 0 },
 
682
    { entry_billable_string, entry_billable_handler, 0, 0 },
 
683
    { entry_billto_string, entry_billto_handler, 0, 0 },
 
684
 
 
685
    /* employee stuff */
 
686
    { entry_billpayment_string, entry_billpayment_handler, 0, 0 },
 
687
 
 
688
    /* Other stuff */
 
689
    { entry_order_string, entry_order_handler, 0, 0 },
 
690
    { entry_invoice_string, entry_invoice_handler, 0, 0 },
 
691
    { entry_bill_string, entry_bill_handler, 0, 0 },
 
692
    { entry_slots_string, entry_slots_handler, 0, 0 },
 
693
 
 
694
    /* Old XML support */
 
695
    { "entry:acct", entry_acct_handler, 0, 0 },
 
696
    { "entry:price", entry_price_handler, 0, 0 },
 
697
    { "entry:discount", entry_idiscount_handler, 0, 0 },
 
698
    { "entry:disc-type", entry_idisctype_handler, 0, 0 },
 
699
    { "entry:disc-how", entry_idischow_handler, 0, 0 },
 
700
    { "entry:taxable", entry_itaxable_handler, 0, 0 },
 
701
    { "entry:taxincluded", entry_itaxincluded_handler, 0, 0 },
 
702
    { "entry:taxtable", entry_itaxtable_handler, 0, 0 },
 
703
    { NULL, 0, 0, 0 }
 
704
};
 
705
 
 
706
static GncEntry*
 
707
dom_tree_to_entry (xmlNodePtr node, QofBook *book)
 
708
{
 
709
    struct entry_pdata entry_pdata;
 
710
    gboolean successful;
 
711
 
 
712
    entry_pdata.entry = gncEntryCreate(book);
 
713
    entry_pdata.book = book;
 
714
    entry_pdata.acc = NULL;
 
715
    gncEntryBeginEdit (entry_pdata.entry);
 
716
 
 
717
    successful = dom_tree_generic_parse (node, entry_handlers_v2,
 
718
                                         &entry_pdata);
 
719
    if (entry_pdata.acc != NULL) {
 
720
      if (gncEntryGetBill (entry_pdata.entry))
 
721
        gncEntrySetBillAccount (entry_pdata.entry, entry_pdata.acc);
 
722
      else
 
723
        gncEntrySetInvAccount (entry_pdata.entry, entry_pdata.acc);
 
724
    }
 
725
 
 
726
    if (successful)
 
727
      gncEntryCommitEdit (entry_pdata.entry);
 
728
    else
 
729
    {
 
730
        PERR ("failed to parse entry tree");
 
731
        gncEntryDestroy (entry_pdata.entry);
 
732
        entry_pdata.entry = NULL;
 
733
    }
 
734
 
 
735
    return entry_pdata.entry;
 
736
}
 
737
 
 
738
static gboolean
 
739
gnc_entry_end_handler(gpointer data_for_children,
 
740
                         GSList* data_from_children, GSList* sibling_data,
 
741
                         gpointer parent_data, gpointer global_data,
 
742
                         gpointer *result, const gchar *tag)
 
743
{
 
744
    int successful;
 
745
    GncEntry *entry;
 
746
    xmlNodePtr tree = (xmlNodePtr)data_for_children;
 
747
    gxpf_data *gdata = (gxpf_data*)global_data;
 
748
    QofBook *book = gdata->bookdata;
 
749
 
 
750
    successful = TRUE;
 
751
 
 
752
    if(parent_data)
 
753
    {
 
754
        return TRUE;
 
755
    }
 
756
 
 
757
    /* OK.  For some messed up reason this is getting called again with a
 
758
       NULL tag.  So we ignore those cases */
 
759
    if(!tag)
 
760
    {
 
761
        return TRUE;
 
762
    }
 
763
 
 
764
    g_return_val_if_fail(tree, FALSE);
 
765
 
 
766
    entry = dom_tree_to_entry(tree, book);
 
767
    if(entry != NULL)
 
768
    {
 
769
        gdata->cb(tag, gdata->parsedata, entry);
 
770
    }
 
771
 
 
772
    xmlFreeNode(tree);
 
773
 
 
774
    return entry != NULL;
 
775
}
 
776
 
 
777
static sixtp *
 
778
entry_sixtp_parser_create(void)
 
779
{
 
780
  return sixtp_dom_parser_new(gnc_entry_end_handler, NULL, NULL);
 
781
}
 
782
 
 
783
static void
 
784
do_count (QofInstance * entry_p, gpointer count_p)
 
785
{
 
786
  int *count = count_p;
 
787
  (*count)++;
 
788
}
 
789
 
 
790
static int
 
791
entry_get_count (QofBook *book)
 
792
{
 
793
  int count = 0;
 
794
  qof_object_foreach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
 
795
  return count;
 
796
}
 
797
 
 
798
static void
 
799
xml_add_entry (QofInstance * entry_p, gpointer out_p)
 
800
{
 
801
  xmlNodePtr node;
 
802
  GncEntry *entry = (GncEntry *) entry_p;
 
803
  FILE *out = out_p;
 
804
 
 
805
  /* Don't save non-attached entries! */
 
806
  if (!(gncEntryGetOrder (entry) || gncEntryGetInvoice (entry) ||
 
807
        gncEntryGetBill (entry)))
 
808
    return;
 
809
 
 
810
  node = entry_dom_tree_create (entry);
 
811
  xmlElemDump(out, NULL, node);
 
812
  fprintf(out, "\n");
 
813
  xmlFreeNode (node);
 
814
}
 
815
 
 
816
static void
 
817
entry_write (FILE *out, QofBook *book)
 
818
{
 
819
  qof_object_foreach (_GNC_MOD_NAME, book, xml_add_entry, (gpointer) out);
 
820
}
 
821
 
 
822
static void
 
823
entry_ns(FILE *out)
 
824
{
 
825
  g_return_if_fail(out);
 
826
  gnc_xml2_write_namespace_decl(out, "entry");
 
827
}
 
828
 
 
829
void
 
830
gnc_entry_xml_initialize (void)
 
831
{
 
832
  static GncXmlDataType_t be_data = {
 
833
    GNC_FILE_BACKEND_VERS,
 
834
    gnc_entry_string,
 
835
    entry_sixtp_parser_create,
 
836
    NULL,                       /* add_item */
 
837
    entry_get_count,
 
838
    entry_write,
 
839
    NULL,                       /* scrub */
 
840
    entry_ns,
 
841
  };
 
842
 
 
843
  qof_object_register_backend (_GNC_MOD_NAME,
 
844
                            GNC_FILE_BACKEND,
 
845
                            &be_data);
 
846
}