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