GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-tree-util-split-reg.c
1 /********************************************************************\
2  * gnc-tree-util-split-reg.c -- GtkTreeView implementation *
3  * to display registers in a GtkTreeView. *
4  * *
5  * Copyright (C) 2006-2007 Chris Shoemaker <[email protected]> *
6  * Copyright (C) 2012 Robert Fewell *
7  * *
8  * This program is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU General Public License as *
10  * published by the Free Software Foundation; either version 2 of *
11  * the License, or (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License*
19  * along with this program; if not, contact: *
20  * *
21  * Free Software Foundation Voice: +1-617-542-5942 *
22  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
23  * Boston, MA 02110-1301, USA [email protected] *
24  * *
25 \********************************************************************/
26 
27 #include "config.h"
28 
29 #include <gtk/gtk.h>
30 #include <glib/gi18n.h>
31 #include <stdlib.h>
32 #include <string.h>
33 
34 #include "gnc-tree-util-split-reg.h"
35 #include "gnc-tree-model-split-reg.h"
36 #include "gnc-tree-view-split-reg.h"
37 
38 #include "gnc-ui.h"
39 #include "dialog-utils.h"
40 #include "dialog-transfer.h"
41 #include "engine-helpers.h"
42 #include "Transaction.h"
43 
44 
45 #define SPLIT_TRANS_STR _("-- Split Transaction --")
46 #define STOCK_SPLIT_STR _("-- Stock Split --")
47 
49 static QofLogModule log_module = GNC_MOD_LEDGER;
50 
51 /*****************************************************************************/
52 
53 
54 /* Is current split a security account */
55 static gboolean
56 gtu_sr_use_security (GncTreeViewSplitReg *view)
57 {
58  RowDepth depth;
59  Account *account = NULL;
60  Split *split;
61 
62  split = gnc_tree_view_split_reg_get_current_split (view);
63 
64  depth = gnc_tree_view_reg_get_selected_row_depth (view);
65 
66  if (!split)
67  return TRUE;
68 
69  if (depth != SPLIT3)
70  return TRUE;
71 
72  if (!account)
73  account = xaccSplitGetAccount (split);
74 
75  if (!account)
76  return TRUE;
77 
79  {
81  return TRUE;
82  }
83 
84  return xaccAccountIsPriced (account);
85 }
86 
87 
88 /* Get the rate from the price db */
89 static gnc_numeric
90 gtu_sr_get_rate_from_db (gnc_commodity *from, gnc_commodity *to)
91 {
92  GNCPrice *prc;
93  gnc_numeric rate_split;
94  gboolean have_rate = FALSE;
95  QofBook *book = gnc_get_current_book ();
96 
97  /* Do we have a rate allready */
98  prc = gnc_pricedb_lookup_latest (gnc_pricedb_get_db (book), from, to);
99  if (prc)
100  {
101  rate_split = gnc_price_get_value (prc);
102  gnc_price_unref (prc);
103  have_rate = TRUE;
104  }
105 
106  /* Lets try reversing the commodities */
107  if (!have_rate)
108  {
109  prc = gnc_pricedb_lookup_latest (gnc_pricedb_get_db (book), to, from);
110  if (prc)
111  {
112  rate_split = gnc_numeric_div (gnc_numeric_create (100, 100), gnc_price_get_value (prc),
114 
115  gnc_price_unref (prc);
116  have_rate = TRUE;
117  }
118  }
119 
120  /* No rate, set to 1/1 */
121  if (!have_rate)
122  rate_split = gnc_numeric_create (100, 100);
123 
124  return rate_split;
125 }
126 
127 
128 /* Do we need an exchange rate */
129 static gboolean
130 gtu_sr_needs_exchange_rate (GncTreeViewSplitReg *view, Transaction *trans, Split *split)
131 {
132  gnc_commodity *split_com, *txn_curr, *reg_com;
133 
134  ENTER("gtu_sr_needs_exchange_rate - trans %p and split %p", trans, split);
135 
136  txn_curr = xaccTransGetCurrency (trans);
137  split_com = xaccAccountGetCommodity (xaccSplitGetAccount (split));
138  if (split_com && txn_curr && !gnc_commodity_equiv (split_com, txn_curr))
139  {
140  LEAVE("gtu_sr_needs_exchange_rate split_com to txn_curr return TRUE");
141  return TRUE;
142  }
143 
144  reg_com = gnc_tree_view_split_reg_get_reg_commodity (view);
145  if (split_com && reg_com && !gnc_commodity_equiv (split_com, reg_com))
146  {
147  LEAVE("gtu_sr_needs_exchange_rate split_com and reg_com return TRUE");
148  return TRUE;
149  }
150  LEAVE("No Exchange rate needed");
151  return FALSE;
152 }
153 
154 
155 /* Either sets the value and amount for split and returns TRUE, or
156  does nothing and returns FALSE. */
157 static gboolean
158 gtu_sr_handle_exchange_rate (GncTreeViewSplitReg *view, gnc_numeric amount, Transaction *trans, Split *split, gboolean force)
159 {
160  GncTreeModelSplitReg *model;
161  XferDialog *xfer;
162  gboolean rate_split_ok, rate_reg_ok;
163  gnc_numeric rate_split, rate_reg, value;
164  Account *reg_acc;
166  gnc_commodity *reg_comm = gnc_tree_view_split_reg_get_reg_commodity (view);
167  gnc_commodity *trans_curr = xaccTransGetCurrency (trans);
168  gboolean expanded;
169  gboolean have_rate = TRUE;
170 
171  ENTER("handle_exchange_rate amount %s, trans %p and split %p force %d", gnc_numeric_to_string (amount), trans, split, force);
172 
173 
174  model = gnc_tree_view_split_reg_get_model_from_view (view);
175 
176  reg_acc = gnc_tree_model_split_reg_get_anchor (model);
177 
178  /* Rate from trans-curr to split-comm */
179  rate_split_ok = xaccTransGetRateForCommodity (trans, xfer_comm, split, &rate_split);
180  DEBUG("rate_split_ok %d and xfer_comm %s", rate_split_ok, gnc_commodity_get_fullname (xfer_comm));
181 
182  /* Rate from trans-curr to reg-comm */
183  rate_reg_ok = xaccTransGetRateForCommodity (trans, reg_comm, split, &rate_reg);
184  DEBUG("rate_reg_ok %d and reg_comm %s", rate_reg_ok, gnc_commodity_get_fullname (reg_comm));
185 
186  /* Are we expanded */
187  expanded = gnc_tree_view_split_reg_trans_expanded (view, trans);
188 
189  if (gnc_commodity_equal (trans_curr, xfer_comm) && rate_split_ok)
190  {
191  xaccSplitSetAmount (split, amount);
192  xaccSplitSetValue (split, amount);
193  return TRUE;
194  }
195 
196  if (rate_reg_ok && rate_split_ok && !force)
197  {
198  value = gnc_numeric_div (amount, rate_reg, gnc_commodity_get_fraction (trans_curr), GNC_HOW_DENOM_REDUCE);
199  amount = gnc_numeric_mul (value, rate_split, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND);
200  }
201  else
202  {
203  if (!rate_split_ok)
204  rate_split = gtu_sr_get_rate_from_db (reg_comm, xfer_comm);
205 
206  /* create the exchange-rate dialog */
207  xfer = gnc_xfer_dialog (NULL, NULL);
208 
209  gnc_xfer_dialog_is_exchange_dialog (xfer, &rate_split);
210 
211  /* fill in the dialog entries */
212  gnc_xfer_dialog_set_description (xfer, xaccTransGetDescription (trans));
213  gnc_xfer_dialog_set_memo (xfer, xaccSplitGetMemo (split));
214 
215  /* Get per book option */
216  gnc_xfer_dialog_set_num (xfer, gnc_get_num_action (trans, split));
217  gnc_xfer_dialog_set_date (xfer, timespecToTime64 (xaccTransRetDatePostedTS (trans)));
218 
219  value = amount;
220  if (gnc_xfer_dialog_run_exchange_dialog (xfer, &rate_split, value, reg_acc, trans, xfer_comm, expanded))
221  {
222  if (!rate_split_ok)
223  rate_split = gnc_numeric_create (1, 1);
224  have_rate = FALSE;
225  }
226  else
227  have_rate = TRUE;
228 
229  amount = gnc_numeric_mul (value, rate_split, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND);
230  }
231  xaccSplitSetAmount (split, amount);
232  xaccSplitSetValue (split, value);
233 
234  LEAVE("handle_exchange_rate set split %p amt=%s; and val=%s", split, gnc_numeric_to_string (amount), gnc_numeric_to_string (value));
235  return have_rate;
236 }
237 
238 
239 /* Returns the value denom */
240 static int
241 gtu_sr_get_value_denom (Split *split)
242 {
243  gnc_commodity *currency;
244  int denom;
245 
246  currency = xaccTransGetCurrency (xaccSplitGetParent (split));
247  denom = gnc_commodity_get_fraction (currency);
248  if (denom == 0)
249  {
250  gnc_commodity *commodity = gnc_default_currency ();
251  denom = gnc_commodity_get_fraction (commodity);
252  if (denom == 0)
253  denom = 100;
254  }
255  return denom;
256 }
257 
258 
259 /* Returns the amount denom */
260 static int
261 gtu_sr_get_amount_denom (Split *split)
262 {
263  int denom;
264 
266  if (denom == 0)
267  {
268  gnc_commodity *commodity = gnc_default_currency ();
269  denom = gnc_commodity_get_fraction (commodity);
270  if (denom == 0)
271  denom = 100;
272  }
273  return denom;
274 }
275 
276 
277 
278 /*###########################################################################*/
279 
280 
281 
282 /* return TRUE if we have a RATE; return FALSE if we do not. */
283 gboolean
284 gnc_tree_util_split_reg_has_rate (GncTreeViewSplitReg *view)
285 {
286  GncTreeModelSplitReg *model;
287 
288  model = gnc_tree_view_split_reg_get_model_from_view (view);
289 
290  switch (model->type)
291  {
292  case BANK_REGISTER2:
293  case CASH_REGISTER2:
294  case ASSET_REGISTER2:
295  case CREDIT_REGISTER2:
296  case LIABILITY_REGISTER2:
297  case INCOME_REGISTER2:
298  case EXPENSE_REGISTER2:
299  case EQUITY_REGISTER2:
300  case TRADING_REGISTER2:
301  case GENERAL_LEDGER2:
302  case INCOME_LEDGER2:
303  case SEARCH_LEDGER2:
304  return TRUE;
305 
306  case STOCK_REGISTER2:
307  case CURRENCY_REGISTER2:
308  case PORTFOLIO_LEDGER2:
309  case RECEIVABLE_REGISTER2:
310  case PAYABLE_REGISTER2:
311  default:
312  return FALSE;
313  }
314 }
315 
316 
317 /* Is this split part of a multi split transaction */
318 gboolean
319 gnc_tree_util_split_reg_is_multi (Split *split)
320 {
321  gboolean multi = FALSE;
322  Split *osplit;
323 
324  if (!split)
325  return FALSE;
326 
327  osplit = xaccSplitGetOtherSplit (split);
328 
329  if (osplit)
330  multi = FALSE;
331  else
332  {
333  /* For multi-split transactions and stock splits,
334  * use a special value. */
335  osplit = xaccTransGetSplit (xaccSplitGetParent (split), 1);
336 
337  if (osplit)
338  multi = TRUE;
339  else if (g_strcmp0 ("stock-split", xaccSplitGetType (split)) == 0)
340  multi = TRUE;
341  else
342  multi = FALSE;
343  }
344  return multi;
345 }
346 
347 
348 /* Return the string entry for transfer column and if multi */
349 const char *
350 gnc_tree_util_split_reg_get_transfer_entry (Split *split, gboolean *is_multi)
351 {
352  static char *name = NULL;
353  gboolean multi = FALSE;
354 
355  Split *osplit;
356 
357  if (is_multi)
358  *is_multi = multi;
359 
360  if (!split)
361  return NULL;
362 
363  osplit = xaccSplitGetOtherSplit (split);
364 
365  g_free (name);
366 
367  if (osplit)
369  else
370  {
371  /* For multi-split transactions and stock splits,
372  * use a special value. */
373  osplit = xaccTransGetSplit (xaccSplitGetParent (split), 1);
374  if (osplit)
375  {
376  name = g_strdup (SPLIT_TRANS_STR);
377  multi = TRUE;
378  }
379  else if (g_strcmp0 ("stock-split", xaccSplitGetType (split)) == 0)
380  {
381  name = g_strdup (STOCK_SPLIT_STR);
382  multi = TRUE;
383  }
384  else
385  name = g_strdup ("");
386  }
387 
388  if (is_multi)
389  *is_multi = multi;
390 
391  return name;
392 }
393 
394 
395 /* Return the string entry for transfer column when template */
396 const char *
397 gnc_tree_util_split_reg_template_get_transfer_entry (Split *split)
398 {
399  static char *name = NULL;
400  Account *account;
401  GncGUID *guid = NULL;
402 
403  /* Callers either g_strdup the return or use it as a temp for comparison,
404  so we keep our static ref and free it on every call. */
405  g_free (name);
406 
407  if (!split)
408  return NULL;
409  qof_instance_get (QOF_INSTANCE (split),
410  "sx-account", &guid,
411  NULL);
412  account = xaccAccountLookup (guid, gnc_get_current_book ());
413  name = account ? gnc_get_account_name_for_register (account) : NULL;
414 
415  return name;
416 }
417 
418 
419 const char *
420 gnc_tree_util_split_reg_template_get_fdebt_entry (Split *split)
421 {
422  gchar *formula = NULL;
423 
424  g_return_val_if_fail (split != NULL, NULL);
425  qof_instance_get (QOF_INSTANCE (split),
426  "sx-debit-formula", &formula,
427  NULL);
428 
429  return formula;
430 }
431 
432 const char *
433 gnc_tree_util_split_reg_template_get_fcred_entry (Split *split)
434 {
435  gchar *formula = NULL;
436 
437  g_return_val_if_fail (split != NULL, NULL);
438  qof_instance_get (QOF_INSTANCE (split),
439  "sx-credit-formula", &formula,
440  NULL);
441 
442  return formula;
443 }
444 
445 
446 gchar *
447 gnc_tree_util_split_reg_get_date_help (GDate *date)
448 {
449  char string[1024];
450  struct tm tm;
451 
452  if (g_date_valid (date))
453  {
454  struct tm tm;
455  memset (&tm, 0, sizeof (tm));
456  g_date_to_struct_tm (date, &tm);
457  qof_strftime (string, sizeof (string), _("%A %d %B %Y"), &tm);
458  return g_strdup (string);
459  }
460  else
461  return g_strdup (" ");
462 }
463 
464 
465 void
466 gnc_tree_util_split_reg_parse_date (GDate *parsed, const char *datestr)
467 {
468  int day, month, year;
469  gboolean use_autoreadonly = qof_book_uses_autoreadonly (gnc_get_current_book ());
470 
471  if (!parsed) return;
472  if (!datestr) return;
473 
474  if (!qof_scan_date (datestr, &day, &month, &year))
475  {
476  // Couldn't parse date, use today
477  struct tm tm_today;
478  gnc_tm_get_today_start (&tm_today);
479  day = tm_today.tm_mday;
480  month = tm_today.tm_mon + 1;
481  year = tm_today.tm_year + 1900;
482  }
483 
484  // If we have an auto-read-only threshold, do not accept a date that is
485  // older than the threshold.
486  if (use_autoreadonly)
487  {
488  GDate *d = g_date_new_dmy (day, month, year);
489  GDate *readonly_threshold = qof_book_get_autoreadonly_gdate (gnc_get_current_book());
490  if (g_date_compare (d, readonly_threshold) < 0)
491  {
492  g_warning("Entered date %s is before the \"auto-read-only threshold\"; resetting to the threshold.", datestr);
493 #if 0
494  GtkWidget *dialog = gtk_message_dialog_new (NULL,
495  0,
496  GTK_MESSAGE_ERROR,
497  GTK_BUTTONS_OK,
498  "%s", _("Cannot store a transaction at this date"));
499  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
500  "%s", _("The entered date of the new transaction is older than the \"Read-Only Threshold\" set for this book. "
501  "This setting can be changed in File -> Properties -> Accounts."));
502  gtk_dialog_run (GTK_DIALOG (dialog));
503  gtk_widget_destroy (dialog);
504 #endif
505 
506  // Reset the date to the threshold date
507  day = g_date_get_day (readonly_threshold);
508  month = g_date_get_month (readonly_threshold);
509  year = g_date_get_year (readonly_threshold);
510  }
511  g_date_free (d);
512  g_date_free (readonly_threshold);
513  }
514  g_date_set_dmy (parsed, day, month, year);
515 }
516 
517 
518 gboolean
519 gnc_tree_util_split_reg_rotate (GncTreeViewSplitReg *view, GtkTreeViewColumn *col, Transaction *trans, Split *split)
520 {
521  GtkCellRenderer *cr0 = NULL;
522  GList *renderers;
523  ViewCol viewcol;
524 
525  // Get the first renderer, it has the view-column value.
526  renderers = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (col));
527  cr0 = g_list_nth_data (renderers, 0);
528  g_list_free (renderers);
529 
530  viewcol = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cr0), "view_column"));
531 
532  if (viewcol == COL_RECN)
533  {
534  const char recn_flags[] = {NREC, CREC, 0}; // List of reconciled flags
535  const gchar *flags;
536  const gchar *text;
537  gchar *this_flag;
538  gint index = 0;
539  char rec;
540 
541  flags = recn_flags;
542 
543  text = g_strdup_printf("%c", xaccSplitGetReconcile (split));
544 
545  /* Find the existing text in the list of flags */
546  this_flag = strstr (flags, text);
547 
548  if (this_flag != NULL && *this_flag != '\0')
549  {
550  /* In the list, choose the next item in the list
551  (wrapping around as necessary). */
552  index = this_flag - flags;
553 
554  if (flags[index + 1] != '\0')
555  index = index + 1;
556  else
557  index = 0;
558 
559  rec = recn_flags[index];
560  }
561  else
562  rec = NREC;
563 
564  gnc_tree_view_split_reg_set_dirty_trans (view, trans);
565  if (!xaccTransIsOpen (trans))
566  xaccTransBeginEdit (trans);
567 
568  xaccSplitSetReconcile (split, rec);
569  return TRUE;
570  }
571 
572  if (viewcol == COL_TYPE)
573  {
574  const char type_flags[] = {TXN_TYPE_INVOICE, TXN_TYPE_PAYMENT, 0}; // list of type flags
575  const gchar *flags;
576  const gchar *text;
577  gchar *this_flag;
578  gint index = 0;
579  char type;
580 
581  flags = type_flags;
582 
583  text = g_strdup_printf("%c", xaccTransGetTxnType (trans));
584 
585  /* Find the existing text in the list of flags */
586  this_flag = strstr (flags, text);
587 
588  if (this_flag != NULL && *this_flag != '\0')
589  {
590  /* In the list, choose the next item in the list
591  (wrapping around as necessary). */
592  index = this_flag - flags;
593 
594  if (flags[index + 1] != '\0')
595  index = index + 1;
596  else
597  index = 0;
598 
599  type = type_flags[index];
600  }
601  else
602  type = TXN_TYPE_NONE;
603 
604  gnc_tree_view_split_reg_set_dirty_trans (view, trans);
605  if (!xaccTransIsOpen (trans))
606  xaccTransBeginEdit (trans);
607 
608  xaccTransSetTxnType (trans, type);
609  return TRUE;
610  }
611  return FALSE;
612 }
613 
614 /*###########################################################################*/
615 
616 /* returns TRUE if you need to convert the split's value to the local
617  * (account) display currency. Returns FALSE if you can just use the
618  * split->value directly.
619  */
620 gboolean
621 gnc_tree_util_split_reg_needs_conv_rate (GncTreeViewSplitReg *view,
622  Transaction *trans, Account *acc)
623 {
624  gnc_commodity *trans_cur, *acc_com;
625 
626  /* If there is not a RATE_CELL, then don't do anything */
627  if (!gnc_tree_util_split_reg_has_rate (view))
628  return FALSE;
629 
630  /* if txn->currency == acc->commodity, then return FALSE */
631  acc_com = xaccAccountGetCommodity (acc);
632  trans_cur = xaccTransGetCurrency (trans);
633  if (trans_cur && acc_com && gnc_commodity_equal (trans_cur, acc_com))
634  return FALSE;
635 
636  return TRUE;
637 }
638 
639 
640 gboolean
641 gnc_tree_util_split_reg_needs_amount (GncTreeViewSplitReg *view, Split *split)
642 {
643  Transaction *txn = xaccSplitGetParent (split);
644  Account *acc = xaccSplitGetAccount (split);
645 
646  return gnc_tree_util_split_reg_needs_conv_rate (view, txn, acc);
647 }
648 
649 /*###########################################################################*/
650 
652 gnc_tree_util_split_reg_get_value_for (GncTreeViewSplitReg *view, Transaction *trans, Split *split, gboolean is_blank)
653 {
654  gnc_numeric ret_num;
655  GNCPrintAmountInfo ret_print_info;
656 
657  if (gnc_tree_util_split_reg_get_debcred_entry (view, trans, split, is_blank, &ret_num, &ret_print_info))
658  return ret_num;
659  else
660  return gnc_numeric_zero();
661 }
662 
663 
664 gboolean
665 gnc_tree_util_split_reg_get_debcred_entry (GncTreeViewSplitReg *view,
666  Transaction *trans, Split *split,
667  gboolean is_blank, gnc_numeric *ret_num,
668  GNCPrintAmountInfo *ret_print_info)
669 
670 {
671  GncTreeModelSplitReg *model;
672  gnc_commodity *currency;
673 
674  model = gnc_tree_view_split_reg_get_model_from_view (view);
675 
676  currency = xaccTransGetCurrency (trans);
677  if (!currency)
678  currency = gnc_default_currency ();
679 
680  if (is_blank)
681  {
682  gnc_numeric imbalance;
683  Account *acc;
684 
685  imbalance = xaccTransGetImbalanceValue (trans);
686 
687  if (gnc_numeric_zero_p (imbalance))
688  return FALSE;
689 
690  if (xaccTransUseTradingAccounts (trans))
691  {
692  MonetaryList *imbal_list;
693  gnc_monetary *imbal_mon;
694  imbal_list = xaccTransGetImbalance (trans);
695 
696  if (!imbal_list)
697  {
698  /* No commodity imbalance, there shouldn't be a value imablance. */
699  return FALSE;
700  }
701 
702  if (imbal_list->next)
703  {
704  /* Multiple currency imbalance. */
705  gnc_monetary_list_free (imbal_list);
706  return FALSE;
707  }
708 
709  imbal_mon = imbal_list->data;
710  if (!gnc_commodity_equal (gnc_monetary_commodity (*imbal_mon), currency))
711  {
712  /* Imbalance is in wrong currency */
713  gnc_monetary_list_free (imbal_list);
714  return FALSE;
715  }
716 
717  if (!gnc_numeric_equal (gnc_monetary_value (*imbal_mon), imbalance))
718  {
719  /* Value and commodity imbalances differ */
720  gnc_monetary_list_free (imbal_list);
721  return FALSE;
722  }
723 
724  /* Done with the imbalance list */
725  gnc_monetary_list_free (imbal_list);
726  }
727 
728  imbalance = gnc_numeric_neg (imbalance);
729 
730  acc = gnc_tree_model_split_reg_get_anchor (model);
731 
732  if (gnc_tree_util_split_reg_needs_conv_rate (view, trans, acc))
733  {
734  imbalance = gnc_numeric_mul (imbalance,
735  xaccTransGetAccountConvRate (trans, acc),
736  gnc_commodity_get_fraction (currency),
738  }
739  else
740  {
741  imbalance = gnc_numeric_convert (imbalance,
742  gnc_commodity_get_fraction (currency),
744  }
745 
746  *ret_num = imbalance;
747  *ret_print_info = gnc_account_print_info (acc, FALSE);
748  return TRUE;
749  }
750 
751  {
752  gnc_numeric amount;
753  gnc_commodity *split_commodity;
754  GNCPrintAmountInfo print_info;
755  Account *account;
756  gnc_commodity *commodity;
757 
758  account = gnc_tree_model_split_reg_get_anchor (model);
759 
760  commodity = xaccAccountGetCommodity (account);
761  split_commodity = xaccAccountGetCommodity (xaccSplitGetAccount (split));
762 
763  if (xaccTransUseTradingAccounts (trans))
764  {
765  gboolean use_symbol, is_current = FALSE;
766  Split *current_split = gnc_tree_view_split_reg_get_current_split (view);
767  RowDepth depth = gnc_tree_view_reg_get_selected_row_depth (view);
768 
769  if ((split == current_split) && (depth == SPLIT3))
770  is_current = TRUE;
771 
772  if (model->type == STOCK_REGISTER2 ||
773  model->type == CURRENCY_REGISTER2 ||
774  model->type == PORTFOLIO_LEDGER2)
775  {
776  gnc_commodity *amount_commodity;
777  /* security register. If this split has price and shares columns,
778  use the value, otherwise use the amount. */
779  if (gtu_sr_use_security (view))
780  {
781  amount = xaccSplitGetValue (split);
782  amount_commodity = currency;
783  }
784  else
785  {
786  amount = xaccSplitGetAmount (split);
787  amount_commodity = split_commodity;
788  }
789  /* Show the currency if it is not the default currency */
790  if (is_current ||
791  gnc_commodity_equiv (amount_commodity, gnc_default_currency ()))
792  use_symbol = FALSE;
793  else
794  use_symbol = TRUE;
795  print_info = gnc_commodity_print_info (amount_commodity, use_symbol);
796  }
797  else
798  {
799  /* non-security register, always use the split amount. */
800  amount = xaccSplitGetAmount (split);
801  if (is_current ||
802  gnc_commodity_equiv (split_commodity, commodity))
803  use_symbol = FALSE;
804  else
805  use_symbol = TRUE;
806  print_info = gnc_commodity_print_info (split_commodity, use_symbol);
807  }
808  }
809  else
810  {
811  /* If this account is not a stock/mutual/currency account, and
812  * currency != the account commodity, then use the SplitAmount
813  * instead of the SplitValue.
814  */
815  switch (model->type)
816  {
817  case STOCK_REGISTER2:
818  case CURRENCY_REGISTER2:
819  case PORTFOLIO_LEDGER2:
820  amount = xaccSplitGetValue (split);
821  print_info = gnc_commodity_print_info (currency, FALSE);
822  break;
823 
824  default:
825  if (commodity && !gnc_commodity_equal (commodity, currency))
826  /* Convert this to the "local" value */
827  amount = xaccSplitConvertAmount (split, account);
828  else
829  amount = xaccSplitGetValue (split);
830  print_info = gnc_account_print_info (account, FALSE);
831  break;
832  }
833  }
834 
835  if (gnc_numeric_zero_p (amount))
836  return FALSE;
837 
838  *ret_num = amount;
839  *ret_print_info = print_info;
840  return TRUE;
841  }
842 }
843 
844 /*###########################################################################*/
845 
846 void
847 gnc_tree_util_split_reg_set_value_for (GncTreeViewSplitReg *view, Transaction *trans, Split *split, gnc_numeric input, gboolean force)
848 {
849  GncTreeModelSplitReg *model;
850  GtkWidget *window;
851  Account *anchor;
852  Account *acct = xaccSplitGetAccount (split);
853  gnc_commodity *currency;
854  gnc_numeric value, amount, rate;
855 
856  ENTER("set_value_for trans %p and split %p input %s force %d", trans, split, gnc_numeric_to_string (input), force);
857 
858  currency = xaccTransGetCurrency (trans);
859 
860  model = gnc_tree_view_split_reg_get_model_from_view (view);
861 
862  anchor = gnc_tree_model_split_reg_get_anchor (model);
863 
864  if (gnc_numeric_zero_p (input))
865  {
866  xaccSplitSetValue (split, input);
867  xaccSplitSetAmount (split, input);
868  LEAVE("input is zero");
869  return;
870  }
871 
872  window = gnc_tree_view_split_reg_get_parent (view);
873 
874  if (gtu_sr_needs_exchange_rate (view, trans, split))
875  {
876  if (gtu_sr_handle_exchange_rate (view, input, trans, split, force))
877  {
878  ; //FIXME ??????
879  }
880  else
881  {
882  gnc_error_dialog (window, "%s",
883  _("Exchange Rate Canceled, using existing rate or default 1 to 1 rate if this is a new transaction."));
884  }
885  LEAVE("used exchange rate");
886  return;
887  }
888 
889  gnc_tree_util_split_reg_save_amount_values (view, trans, split, input);
890 
891  LEAVE(" ");
892 }
893 
894 void
895 gnc_tree_util_split_reg_save_amount_values (GncTreeViewSplitReg *view, Transaction *trans, Split *split, gnc_numeric input)
896 {
897  GncTreeModelSplitReg *model;
898  Account *acc;
899  gnc_numeric new_amount, convrate, amtconv, value;
900  gnc_commodity *curr, *reg_com, *xfer_com;
901  Account *xfer_acc;
902 
903  ENTER("View is %p, trans is %p, split is %p, input is %s", view, trans, split, gnc_numeric_to_string (input));
904 
905  model = gnc_tree_view_split_reg_get_model_from_view (view);
906 
907  new_amount = input;
908 
909  acc = gnc_tree_model_split_reg_get_anchor (model);
910 
911  xfer_acc = xaccSplitGetAccount (split);
912  xfer_com = xaccAccountGetCommodity (xfer_acc);
913  reg_com = xaccAccountGetCommodity (acc);
914  curr = xaccTransGetCurrency (trans);
915 
916  if (!xaccTransGetRateForCommodity (trans, reg_com, NULL, &convrate))
917  convrate = gnc_numeric_create (100, 100);
918 
919  amtconv = convrate;
920 
921  if (gnc_tree_util_split_reg_needs_conv_rate (view, trans, acc))
922  {
923 
924  /* If we are in an expanded register and the xfer_acc->comm !=
925  * reg_acc->comm then we need to compute the convrate here.
926  * Otherwise, we _can_ use the rate_cell!
927  */
928  if (gnc_commodity_equal (reg_com, xfer_com))
929  amtconv = xaccTransGetAccountConvRate (trans, acc);
930  }
931 
932  if (xaccTransUseTradingAccounts (trans))
933  {
934  /* Using currency accounts, the amount is probably really the
935  amount and not the value. */
936  gboolean is_amount;
937 
938  if (model->type == STOCK_REGISTER2 ||
939  model->type == CURRENCY_REGISTER2 ||
940  model->type == PORTFOLIO_LEDGER2)
941  {
942  if (xaccAccountIsPriced (xfer_acc) ||
944  is_amount = FALSE;
945  else
946  is_amount = TRUE;
947  }
948  else
949  {
950  is_amount = TRUE;
951  }
952 
953  if (is_amount)
954  {
955  xaccSplitSetAmount (split, new_amount);
956  if (gnc_tree_util_split_reg_needs_amount (view, split))
957  {
958  value = gnc_numeric_div (new_amount, amtconv,
961  xaccSplitSetValue (split, value);
962  }
963  else
964  xaccSplitSetValue (split, new_amount);
965  }
966  else
967  {
968  xaccSplitSetValue (split, new_amount);
969  }
970  LEAVE(" ");
971  return;
972  }
973 
974  /* How to interpret new_amount depends on our view of this
975  * transaction. If we're sitting in an account with the same
976  * commodity as the transaction, then we can set the Value and then
977  * compute the amount. Otherwise we are setting the "converted
978  * value". This means we need to convert new_amount to the actual
979  * 'value' by dividing by the convrate in order to set the value.
980  */
981 
982  /* Now compute/set the split value. Amount is in the register
983  * currency but we need to convert to the txn currency.
984  */
985  if (gnc_tree_util_split_reg_needs_conv_rate (view, trans, acc))
986  {
987  /* convert the amount to the Value ... */
988  value = gnc_numeric_div (new_amount, amtconv,
991  xaccSplitSetValue (split, value);
992  }
993  else
994  {
995  xaccSplitSetValue (split, new_amount);
996  }
997 
998  /* Now re-compute the Amount from the Value. We may need to convert
999  * from the Value back to the amount here using the convrate from
1000  * earlier.
1001  */
1002  value = xaccSplitGetValue (split);
1003 
1004  if (gnc_tree_util_split_reg_needs_amount (view, split))
1005  {
1006  acc = xaccSplitGetAccount (split);
1007  new_amount = gnc_numeric_mul (value, convrate,
1010  xaccSplitSetAmount (split, new_amount);
1011  }
1012  else
1013  {
1014  xaccSplitSetAmount (split, value);
1015  }
1016  LEAVE(" ");
1017 }
1018 
1019 /*###########################################################################*/
1020 
1021 /* Takes the input with column and sets the price / amount / value so they are consistent */
1022 void
1023 gnc_tree_util_set_number_for_input (GncTreeViewSplitReg *view, Transaction *trans, Split *split, gnc_numeric input, gint viewcol)
1024 {
1025  GncTreeModelSplitReg *model;
1026  gnc_numeric price;
1027  gnc_numeric amount;
1028  gnc_numeric value;
1029 
1030  gboolean price_changed = FALSE; // Price of each share
1031  gboolean value_changed = FALSE; // Total value of shares
1032  gboolean amount_changed = FALSE; // No of shares
1033 
1034  gboolean recalc_amount = FALSE;
1035  gboolean recalc_price = FALSE;
1036  gboolean recalc_value = FALSE;
1037  gboolean expanded = FALSE;
1038  int denom;
1039  Account *account = NULL;
1040 
1041  ENTER("trans %p and split %p and input is %s and viewcol is %d", trans, split, gnc_numeric_to_string (input), viewcol);
1042 
1043  model = gnc_tree_view_split_reg_get_model_from_view (view);
1044 
1045  /* Check for sub account view */
1046  if (!gnc_tree_model_split_reg_get_sub_account (model))
1047  account = gnc_tree_model_split_reg_get_anchor (model);
1048 
1049  expanded = gnc_tree_view_split_reg_trans_expanded (view, trans);
1050 
1051  if (!account)
1052  account = xaccSplitGetAccount (split);
1053 
1054  if (!xaccAccountIsPriced (account))
1055  return;
1056 
1057  /* If we are using commodity trading accounts then the value may
1058  not really be the value. Punt if so. */
1060  {
1061  gnc_commodity *acc_commodity;
1062  acc_commodity = xaccAccountGetCommodity (account);
1063  if (!(xaccAccountIsPriced (account) || !gnc_commodity_is_iso (acc_commodity)))
1064  return;
1065  }
1066 
1067  if (gnc_numeric_zero_p (input))
1068  {
1069  xaccSplitSetValue (split, input);
1070  xaccSplitSetAmount (split, input);
1071  LEAVE("zero");
1072  return;
1073  }
1074 
1075  amount = xaccSplitGetAmount (split);
1076  value = xaccSplitGetValue (split);
1077 
1078  if (viewcol == COL_AMTVAL && !expanded)
1079  {
1080  value_changed = TRUE;
1081  if (gnc_numeric_zero_p (amount))
1082  {
1083  xaccSplitSetValue (split, input);
1084  xaccSplitSetAmount (split, input);
1085  LEAVE("");
1086  return;
1087  }
1088  }
1089  else if (viewcol == COL_AMTVAL && expanded)
1090  {
1091  amount_changed = TRUE;
1092  if (gnc_numeric_zero_p (value))
1093  {
1094  xaccSplitSetValue (split, input);
1095  xaccSplitSetAmount (split, input);
1096  LEAVE("");
1097  return;
1098  }
1099  }
1100 
1101  if (viewcol == COL_PRICE)
1102  {
1103  price_changed = TRUE;
1104  if (gnc_numeric_zero_p (value))
1105  {
1106  amount = gnc_numeric_create (1,1);
1107  value = gnc_numeric_mul (input, amount, GNC_DENOM_AUTO, GNC_HOW_RND_ROUND);
1108  xaccSplitSetValue (split, input);
1109  xaccSplitSetAmount (split, amount);
1110  LEAVE("");
1111  return;
1112  }
1113  }
1114 
1115  if ((viewcol == COL_CREDIT || viewcol == COL_DEBIT) && !expanded)
1116  {
1117  amount_changed = TRUE;
1118  if (gnc_numeric_zero_p (value))
1119  {
1120  xaccSplitSetValue (split, input);
1121  xaccSplitSetAmount (split, input);
1122  LEAVE("");
1123  return;
1124  }
1125  }
1126  else if ((viewcol == COL_CREDIT || viewcol == COL_DEBIT) && expanded)
1127  {
1128  value_changed = TRUE;
1129  if (gnc_numeric_zero_p (value))
1130  {
1131  xaccSplitSetValue (split, input);
1132  xaccSplitSetAmount (split, input);
1133  LEAVE("");
1134  return;
1135  }
1136  }
1137 
1138  DEBUG("value_changed %d, price_changed %d, amount_changed %d", value_changed, price_changed, amount_changed);
1139 
1140  {
1141  int choice;
1142  int default_value;
1143  GList *node;
1144  GList *radio_list = NULL;
1145  const char *title = _("Recalculate Transaction");
1146  const char *message = _("The values entered for this transaction "
1147  "are inconsistent. Which value would you "
1148  "like to have recalculated?");
1149 
1150  if (amount_changed)
1151  radio_list = g_list_append (radio_list,
1152  g_strdup_printf ("%s (%s)",
1153  _("_Shares"), _("Changed")));
1154  else
1155  radio_list = g_list_append (radio_list, g_strdup (_("_Shares")));
1156 
1157  if (price_changed)
1158  radio_list = g_list_append (radio_list,
1159  g_strdup_printf ("%s (%s)",
1160  _("_Price"), _("Changed")));
1161  else
1162  radio_list = g_list_append (radio_list, g_strdup (_("_Price")));
1163 
1164  if (value_changed)
1165  radio_list = g_list_append (radio_list,
1166  g_strdup_printf ("%s (%s)",
1167  _("_Value"), _("Changed")));
1168  else
1169  radio_list = g_list_append (radio_list, g_strdup (_("_Value")));
1170 
1171  if(expanded)
1172  {
1173  if (price_changed)
1174  default_value = 2; /* change the value */
1175  else
1176  default_value = 1; /* change the price */
1177  }
1178  else
1179  {
1180  if (price_changed)
1181  default_value = 0; /* change the amount / shares */
1182  else
1183  default_value = 1; /* change the price */
1184  }
1185  choice = gnc_choose_radio_option_dialog
1186  (gnc_tree_view_split_reg_get_parent (view),
1187  title,
1188  message,
1189  _("_Recalculate"),
1190  default_value,
1191  radio_list);
1192 
1193  for (node = radio_list; node; node = node->next)
1194  g_free (node->data);
1195 
1196  g_list_free (radio_list);
1197 
1198  switch (choice)
1199  {
1200  case 0: /* Modify number of shares */
1201  recalc_amount = TRUE;
1202  break;
1203  case 1: /* Modify the share price */
1204  recalc_price = TRUE;
1205  break;
1206  case 2: /* Modify total value */
1207  recalc_value = TRUE;
1208  break;
1209  default: /* Cancel */
1210  LEAVE(" " );
1211  return;
1212  }
1213  }
1214 
1215  DEBUG("recalc_value %d, recalc_price %d, recalc_amount %d", recalc_value, recalc_price, recalc_amount);
1216 
1217  if (recalc_amount)
1218  {
1219  denom = gtu_sr_get_amount_denom (split);
1220 
1221  if (amount_changed)
1222  {
1223  LEAVE("");
1224  return;
1225  }
1226 
1227  if (price_changed)
1228  price = input;
1229  else
1230  price = gnc_numeric_div (value, amount, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
1231 
1232  if (value_changed)
1233  {
1234  xaccSplitSetValue (split, input);
1235  amount = gnc_numeric_div (input, price, denom, GNC_HOW_RND_ROUND_HALF_UP);
1236  xaccSplitSetAmount (split, amount);
1237  }
1238  else
1239  {
1240  amount = gnc_numeric_div (value, price, denom, GNC_HOW_RND_ROUND_HALF_UP);
1241  xaccSplitSetAmount (split, amount);
1242  }
1243  }
1244 
1245  if (recalc_price)
1246  {
1247  if (price_changed)
1248  {
1249  LEAVE("");
1250  return;
1251  }
1252 
1253  if (amount_changed)
1254  {
1255  xaccSplitSetAmount (split, input);
1256  xaccSplitSetValue (split, value);
1257  }
1258 
1259  if (value_changed)
1260  {
1261  xaccSplitSetValue (split, input);
1262  xaccSplitSetAmount (split, amount);
1263  }
1264  }
1265 
1266  if (recalc_value)
1267  {
1268  denom = gtu_sr_get_value_denom (split);
1269 
1270  if (value_changed)
1271  {
1272  LEAVE("");
1273  return;
1274  }
1275 
1276  if (price_changed)
1277  price = input;
1278  else
1279  price = gnc_numeric_div (value, amount, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
1280 
1281  if (amount_changed)
1282  {
1283  xaccSplitSetAmount (split, input);
1284  value = gnc_numeric_mul (input, price, denom, GNC_HOW_RND_ROUND_HALF_UP);
1285  xaccSplitSetValue (split, value);
1286  }
1287  else
1288  {
1289  value = gnc_numeric_mul (amount, price, denom, GNC_HOW_RND_ROUND_HALF_UP);
1290  xaccSplitSetValue (split, value);
1291  }
1292  }
1293 
1294  /* If the number of splits is two, change other split to balance */
1295  if (!gnc_tree_util_split_reg_is_multi (split) && expanded)
1296  {
1297  Split *osplit;
1298  gnc_commodity *osplit_com;
1299 
1300  osplit = xaccSplitGetOtherSplit (split);
1301 
1302  value = xaccSplitGetValue (split);
1303 
1304  osplit_com = xaccAccountGetCommodity (xaccSplitGetAccount (osplit));
1305 
1306  if (gnc_commodity_is_currency (osplit_com))
1307  {
1308  xaccSplitSetValue (osplit, gnc_numeric_neg (value));
1309  xaccSplitSetAmount (osplit, gnc_numeric_neg (value));
1310  }
1311  }
1312  LEAVE("");
1313 }
1314 
1315 
1316 /* Set the value for the given input amount */
1317 void
1318 gnc_tree_util_set_value_for_amount (GncTreeViewSplitReg *view, Transaction *trans, Split *split, gnc_numeric input)
1319 {
1320  gnc_numeric split_rate;
1321  gnc_numeric amount;
1322  gnc_numeric value, new_value;
1323  int denom;
1324 
1325  ENTER("trans %p and split %p and input is %s", trans, split, gnc_numeric_to_string (input));
1326 
1327  if (gnc_numeric_zero_p (input))
1328  {
1329  xaccSplitSetValue (split, input);
1330  xaccSplitSetAmount (split, input);
1331  LEAVE("zero");
1332  return;
1333  }
1334 
1335  amount = xaccSplitGetAmount (split);
1336  value = xaccSplitGetValue (split);
1337 
1338  denom = gtu_sr_get_value_denom (split);
1339 
1340  split_rate = gnc_numeric_div (value, amount, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
1341  if (gnc_numeric_check (split_rate) != GNC_ERROR_OK)
1342  split_rate = gnc_numeric_create (100,100);
1343 
1344  new_value = gnc_numeric_mul (input, split_rate, denom, GNC_HOW_RND_ROUND_HALF_UP);
1345 
1346  xaccSplitSetValue (split, new_value);
1347  xaccSplitSetAmount (split, input);
1348 
1349  LEAVE("");
1350 }
1351 
1352 
1353 /* Get the rate */
1355 gnc_tree_util_get_rate_for (GncTreeViewSplitReg *view, Transaction *trans, Split *split, gboolean is_blank)
1356 {
1357  gnc_numeric num;
1358 
1359  ENTER("trans %p and split %p is_blank %d", trans, split, is_blank);
1360 
1361  num = gnc_tree_util_split_reg_get_value_for (view, trans, split, is_blank);
1362 //FIXME Not sure about this...
1363  if (xaccTransUseTradingAccounts (trans))
1365  else
1367 
1368  LEAVE("split %p and return num is %s", split, gnc_numeric_to_string (num));
1369  return num;
1370 }
1371 
1372 
1373 /*****************************************************************************/
void xaccSplitSetValue(Split *s, gnc_numeric amt)
Definition: Split.c:1294
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
gboolean gnc_commodity_is_currency(const gnc_commodity *cm)
char xaccTransGetTxnType(const Transaction *trans)
Definition: Transaction.c:2302
int gnc_commodity_get_fraction(const gnc_commodity *cm)
time64 timespecToTime64(Timespec ts)
void qof_instance_get(const QofInstance *inst, const gchar *first_param,...)
Wrapper for g_object_get.
Split * xaccTransGetSplit(const Transaction *trans, int i)
Definition: Transaction.c:2144
gboolean xaccTransUseTradingAccounts(const Transaction *trans)
Definition: Transaction.c:1015
gboolean xaccAccountIsPriced(const Account *acc)
Definition: Account.c:4249
gboolean xaccTransIsOpen(const Transaction *trans)
Definition: Transaction.c:1819
#define TXN_TYPE_INVOICE
Definition: Transaction.h:120
int xaccAccountGetCommoditySCU(const Account *acc)
Definition: Account.c:2458
gnc_numeric gnc_numeric_neg(gnc_numeric a)
void gnc_price_unref(GNCPrice *p)
Definition: gnc-pricedb.c:272
#define DEBUG(format, args...)
Definition: qoflog.h:255
char xaccSplitGetReconcile(const Split *split)
Definition: Split.c:1980
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
gboolean gnc_numeric_zero_p(gnc_numeric a)
void xaccSplitSetReconcile(Split *split, char recn)
Definition: Split.c:1826
Transaction * xaccSplitGetParent(const Split *split)
Definition: Split.c:1903
gchar * gnc_numeric_to_string(gnc_numeric n)
#define ENTER(format, args...)
Definition: qoflog.h:261
GNCPriceDB * gnc_pricedb_get_db(QofBook *book)
Definition: gnc-pricedb.c:872
Definition: guid.h:65
gnc_commodity * gnc_default_currency(void)
Definition: gnc-ui-util.c:939
gchar * gnc_get_account_name_for_register(const Account *account)
Definition: gnc-ui-util.c:282
void xaccTransSetTxnType(Transaction *trans, char type)
Definition: Transaction.c:2016
#define TXN_TYPE_NONE
Definition: Transaction.h:119
GDate * qof_book_get_autoreadonly_gdate(const QofBook *book)
void xaccSplitSetAmount(Split *s, gnc_numeric amt)
Definition: Split.c:1258
gnc_numeric gnc_numeric_convert(gnc_numeric n, gint64 denom, gint how)
gnc_numeric xaccTransGetImbalanceValue(const Transaction *trans)
Definition: Transaction.c:1036
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
void gnc_monetary_list_free(MonetaryList *list)
const char * xaccTransGetDescription(const Transaction *trans)
Definition: Transaction.c:2184
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
gsize qof_strftime(gchar *buf, gsize max, const gchar *format, const struct tm *tm)
gnc_numeric gnc_numeric_div(gnc_numeric x, gnc_numeric y, gint64 denom, gint how)
void xaccTransBeginEdit(Transaction *trans)
Definition: Transaction.c:1380
#define TXN_TYPE_PAYMENT
Definition: Transaction.h:121
#define CREC
Definition: Split.h:67
void gnc_tm_get_today_start(struct tm *tm)
Definition: SplitP.h:71
gnc_numeric xaccSplitGetValue(const Split *split)
Definition: Split.c:1993
Account * xaccSplitGetAccount(const Split *s)
Definition: Split.c:968
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Definition: Account.c:3148
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Definition: Transaction.c:1348
MonetaryList * xaccTransGetImbalance(const Transaction *trans)
Definition: Transaction.c:1052
Timespec xaccTransRetDatePostedTS(const Transaction *trans)
Definition: Transaction.c:2243
gboolean qof_scan_date(const char *buff, int *day, int *month, int *year)
Split * xaccSplitGetOtherSplit(const Split *split)
Definition: Split.c:2086
#define LEAVE(format, args...)
Definition: qoflog.h:271
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
const char * xaccSplitGetMemo(const Split *split)
Definition: Split.c:1968
GNCPrice * gnc_pricedb_lookup_latest(GNCPriceDB *db, const gnc_commodity *commodity, const gnc_commodity *currency)
Definition: gnc-pricedb.c:1309
gboolean qof_book_uses_autoreadonly(const QofBook *book)
const char * xaccSplitGetType(const Split *s)
Definition: Split.c:2048
#define GNC_DENOM_AUTO
Definition: gnc-numeric.h:246
API for Transactions and Splits (journal entries)
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
gboolean gnc_commodity_is_iso(const gnc_commodity *cm)
const gchar * QofLogModule
Definition: qofid.h:89
#define NREC
Definition: Split.h:70
gnc_numeric xaccSplitGetAmount(const Split *split)
Definition: Split.c:1987
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
Definition: Account.c:1827