27#include <glib/gi18n.h>
34#include "assistant-loan.h"
36#include "SchedXaction.hpp"
38#include "SX-ttinfo.hpp"
39#include "gnc-amount-edit.h"
40#include "gnc-account-sel.h"
42#include "gnc-exp-parser.h"
43#include "gnc-component-manager.h"
44#include "dialog-utils.h"
47#include "gnc-gui-query.h"
49#include "gnc-frequency.h"
55#include <gnc-locale-utils.hpp>
56#include <boost/locale.hpp>
64namespace bl = boost::locale;
66#define DIALOG_LOAN_ASSISTANT_CM_CLASS "assistant-loan-setup"
68static QofLogModule log_module = GNC_MOD_ASSISTANT;
87struct LoanAssistantData_;
93typedef struct RepayOptData_
101 gboolean throughEscrowP;
102 gboolean specSrcAcctP;
115typedef struct RepayOptDataDefault_
118 const char *defaultTxnMemo;
119 gboolean escrowDefault;
120 gboolean specSrcAcctDefault;
126 { N_(
"Taxes"), N_(
"Tax Payment"), TRUE, FALSE },
127 { N_(
"Insurance"), N_(
"Insurance Payment"), TRUE, FALSE },
129 { N_(
"PMI"), N_(
"PMI Payment"), TRUE, FALSE },
130 { N_(
"Other Expense"), N_(
"Miscellaneous Payment"), FALSE, FALSE },
137typedef struct RepayOptUI_
141 struct LoanAssistantData_ *ldd;
142 GtkCheckButton *optCb;
143 GtkCheckButton *escrowCb;
151 GNC_VARIABLE_3_1 = GNC_VARIABLE,
169 GNC_IRATE_APR_WEEKLY,
170 GNC_IRATE_APR_MONTHLY,
171 GNC_IRATE_APR_QUARTERLY,
172 GNC_IRATE_APR_SEMIANNUALLY,
173 GNC_IRATE_APR_ANNUALLY
181typedef struct rev_repayment_row
184 gnc_numeric *numCells;
190typedef struct LoanData_
193 gnc_numeric principal;
197 GList *loan_schedule;
205 std::string repAmount;
210 GList *repayment_schedule;
218 int revRepayOptToColMap[ (
sizeof(REPAY_DEFAULTS)
227typedef struct LoanAssistantData_
230 GtkWidget *assistant;
244 GNCAccountSel *prmAccountGAS;
245 GNCAmountEdit *prmOrigPrincGAE;
246 GtkSpinButton *prmIrateSpin;
247 GtkComboBox *prmType;
248 GtkFrame *prmVarFrame;
251 GtkSpinButton *prmLengthSpin;
252 GtkComboBox *prmLengthType;
253 GtkSpinButton *prmRemainSpin;
254 GtkComboBox *prmIrateType;
258 GtkCheckButton *optEscrowCb;
259 GtkBox *optEscrowHBox;
260 GNCAccountSel *optEscrowGAS;
263 GtkEntry *repTxnName;
265 GtkEntry *repAmtEntry;
266 GNCAccountSel *repAssetsFromGAS;
267 GNCAccountSel *repPrincToGAS;
268 GNCAccountSel *repIntToGAS;
269 GtkFrame *repFreqFrame;
273 GtkEntry *payTxnName;
274 GtkEntry *payAmtEntry;
275 GNCAccountSel *payAcctFromGAS;
276 GNCAccountSel *payAcctEscToGAS;
277 GNCAccountSel *payAcctEscFromGAS;
278 GNCAccountSel *payAcctToGAS;
280 GtkCheckButton *payUseEscrow;
281 GtkCheckButton *paySpecSrcAcct;
282 GtkLabel *payAcctFromLabel;
283 GtkLabel *payEscToLabel;
284 GtkLabel *payEscFromLabel;
285 GtkRadioButton *payTxnFreqPartRb;
286 GtkRadioButton *payTxnFreqUniqRb;
291 GtkComboBox *revRangeOpt;
292 GtkFrame *revDateFrame;
296 GtkScrolledWindow *revScrollWin;
297 GtkTreeView *revView;
303typedef struct toCreateSX_
321static void loan_assistant_window_destroy_cb( GtkWidget *
object, gpointer user_data );
322static void loan_assistant_close_handler( gpointer user_data );
325static void loan_info_prep( GtkAssistant *assistant, gpointer user_data );
326static void loan_info_prm_type_cb( GtkWidget *w, gpointer user_data );
327static void loan_info_calc_update_cb( GtkWidget *widget, gpointer user_data );
328void loan_info_page_valid_cb( GtkWidget *widget, gpointer user_data );
329static gboolean loan_info_page_complete( GtkAssistant *assistant, gpointer user_data );
330static void loan_info_page_save( GtkAssistant *assistant, gpointer user_data );
332static void loan_opt_prep( GtkAssistant *assistant, gpointer user_data );
333static void loan_opt_toggled_cb( GtkToggleButton *tb, gpointer user_data );
334static void loan_opt_consistency_cb( GtkToggleButton *tb, gpointer user_data );
335static void loan_opt_escrow_toggle_cb( GtkToggleButton *tb, gpointer user_data );
336static void loan_opt_escrow_toggled_cb( GtkToggleButton *tb, gpointer user_data );
337void loan_opt_page_valid_cb (GtkWidget *widget, gpointer user_data );
338static gboolean loan_opt_page_complete( GtkAssistant *assistant, gpointer user_data );
340static void loan_rep_prep ( GtkAssistant *assistant, gpointer user_data );
341void loan_rep_page_valid_cb (GtkWidget *widget, gpointer user_data );
342static gboolean loan_rep_page_complete( GtkAssistant *assistant, gpointer user_data );
343static void loan_rep_page_save( GtkAssistant *assistant, gpointer user_data );
345static void loan_pay_prep ( GtkAssistant *assistant, gpointer user_data );
347static void loan_pay_use_esc_toggle_cb( GtkToggleButton *tb, gpointer user_data );
349static void loan_pay_spec_src_toggle_cb( GtkToggleButton *tb, gpointer user_data );
350static void loan_pay_freq_toggle_cb( GtkToggleButton *tb, gpointer user_data );
351static void loan_pay_page_valid_cb (GtkWidget *widget, gpointer user_data );
352static gboolean loan_pay_complete( GtkAssistant *assistant, gpointer user_data );
353static gboolean loan_pay_all_opt_valid ( GtkAssistant *assistant, gpointer user_data );
354static void loan_pay_back_button_cb( GtkButton *button, gpointer user_data );
355static void loan_pay_next_button_cb( GtkButton *button, gpointer user_data );
357static void loan_rev_prep ( GtkAssistant *assistant, gpointer user_data );
359static void loan_rev_range_opt_changed_cb( GtkComboBox *combo, gpointer user_data );
360static void loan_rev_range_changed_cb(
GNCDateEdit *gde, gpointer user_data );
361static void loan_rev_get_loan_range(
LoanAssistantData *ldd, GDate *start, GDate *end );
362static void loan_rev_get_dates(
LoanAssistantData *ldd, GDate *start, GDate *end );
363static void loan_rev_update_view(
LoanAssistantData *ldd, GDate *start, GDate *end );
364static void loan_rev_sched_list_free( gpointer data, gpointer user_data );
365static void loan_rev_hash_to_list( gpointer key, gpointer val, gpointer user_data );
366static void loan_rev_hash_free_date_keys( gpointer key, gpointer val, gpointer user_data );
371static float loan_apr_to_simple_formula (
double rate,
double pmt_periods,
double comp_periods);
375static void loan_tcSX_free( gpointer data, gpointer user_data );
378void loan_assistant_prepare( GtkAssistant *assistant, GtkWidget *page, gpointer user_data );
379void loan_assistant_finish( GtkAssistant *gtkassistant, gpointer user_data );
380void loan_assistant_cancel( GtkAssistant *gtkassistant, gpointer user_data );
381void loan_assistant_close( GtkAssistant *gtkassistant, gpointer user_data );
389loan_assistant_close_handler( gpointer user_data )
392 gtk_widget_destroy( ldd->window );
398loan_assistant_window_destroy_cb( GtkWidget *
object, gpointer user_data )
404 gnc_unregister_gui_component_by_data (DIALOG_LOAN_ASSISTANT_CM_CLASS, ldd);
412 g_date_free( ldd->ld.startDate );
413 g_date_free( ldd->ld.varStartDate );
414 recurrenceListFree(&ldd->ld.loan_schedule);
416 if ( ldd->ld.repMemo )
417 g_free( ldd->ld.repMemo );
419 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
425 g_free( rod->txnMemo );
427 if ( rod->startDate )
428 g_date_free( rod->startDate );
430 if (rod->schedule != NULL)
431 recurrenceListFree(&rod->schedule);
433 g_free( ldd->ld.repayOpts[i] );
434 g_free( ldd->repayOptsUI[i] );
436 g_free( ldd->ld.repayOpts );
437 g_free( ldd->repayOptsUI );
439 g_date_free( ldd->ld.repStartDate );
444 if ( ldd->ld.revSchedule )
446 g_list_foreach( ldd->ld.revSchedule,
447 loan_rev_sched_list_free,
449 g_list_free( ldd->ld.revSchedule );
450 ldd->ld.revSchedule = NULL;
464 loan_assistant_data_init( ldd );
466 builder = gtk_builder_new();
468 gnc_builder_add_from_file (builder ,
"assistant-loan.glade",
"len_liststore");
469 gnc_builder_add_from_file (builder ,
"assistant-loan.glade",
"range_liststore");
470 gnc_builder_add_from_file (builder ,
"assistant-loan.glade",
"type_liststore");
471 gnc_builder_add_from_file (builder ,
"assistant-loan.glade",
"rate_liststore");
473 gnc_builder_add_from_file (builder ,
"assistant-loan.glade",
"loan_mortgage_assistant");
474 window = GTK_WIDGET(gtk_builder_get_object (builder,
"loan_mortgage_assistant"));
475 ldd->window = window;
478 gtk_widget_set_name (GTK_WIDGET(window),
"gnc-id-assistant-loan");
481 gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
482 GTK_WIDGET(gtk_builder_get_object(builder,
"loan_intro_page")),
484 gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
485 GTK_WIDGET(gtk_builder_get_object(builder,
"loan_options_page")),
487 gtk_assistant_set_page_complete (GTK_ASSISTANT (window),
488 GTK_WIDGET(gtk_builder_get_object(builder,
"loan_review_page")),
493 ldd->prmTable = GTK_GRID(gtk_builder_get_object(builder,
"param_table"));
494 ldd->prmVarFrame = GTK_FRAME(gtk_builder_get_object(builder,
"type_freq_frame"));
495 ldd->prmIrateSpin = GTK_SPIN_BUTTON (gtk_builder_get_object(builder,
"irate_spin"));
496 ldd->prmType = GTK_COMBO_BOX (gtk_builder_get_object(builder,
"type_combobox"));
497 gtk_combo_box_set_active( GTK_COMBO_BOX( ldd->prmType), FALSE );
498 ldd->prmLengthSpin = GTK_SPIN_BUTTON (gtk_builder_get_object(builder,
"len_spin"));
499 ldd->prmLengthType = GTK_COMBO_BOX (gtk_builder_get_object(builder,
"len_opt"));
500 gtk_combo_box_set_active( GTK_COMBO_BOX( ldd->prmLengthType), FALSE );
501 ldd->prmRemainSpin = GTK_SPIN_BUTTON (gtk_builder_get_object(builder,
"rem_spin"));
502 ldd->prmIrateType = GTK_COMBO_BOX (gtk_builder_get_object(builder,
"irate_type_combobox"));
503 gtk_combo_box_set_active( GTK_COMBO_BOX( ldd->prmIrateType), FALSE );
508 ldd->repTable = GTK_GRID(gtk_builder_get_object(builder,
"repay_table"));
509 ldd->repTxnName = GTK_ENTRY(gtk_builder_get_object(builder,
"txn_title"));
510 ldd->repAmtEntry = GTK_ENTRY(gtk_builder_get_object(builder,
"amount_ent"));
511 ldd->repFreqFrame = GTK_FRAME(gtk_builder_get_object(builder,
"freq_frame"));
515 ldd->optVBox = GTK_BOX(gtk_builder_get_object(builder,
"loan_options_page"));
516 ldd->optEscrowCb = GTK_CHECK_BUTTON(gtk_builder_get_object(builder,
"opt_escrow_cb"));
517 ldd->optEscrowHBox = GTK_BOX(gtk_builder_get_object(builder,
"opt_escrow_hbox"));
521 ldd->payTable = GTK_GRID(gtk_builder_get_object(builder,
"pay_table"));
522 ldd->payTxnName = GTK_ENTRY(gtk_builder_get_object(builder,
"pay_txn_title"));
523 ldd->payAmtEntry = GTK_ENTRY(gtk_builder_get_object(builder,
"pay_amt_ent"));
524 ldd->payUseEscrow = GTK_CHECK_BUTTON(gtk_builder_get_object(builder,
"pay_use_escrow"));
525 ldd->paySpecSrcAcct = GTK_CHECK_BUTTON(gtk_builder_get_object(builder,
"pay_specify_source"));
526 ldd->payAcctFromLabel = GTK_LABEL(gtk_builder_get_object(builder,
"pay_from_account_label"));
527 ldd->payEscToLabel = GTK_LABEL(gtk_builder_get_object(builder,
"pay_escrow_to_label"));
528 ldd->payEscFromLabel = GTK_LABEL(gtk_builder_get_object(builder,
"pay_escrow_from_label"));
529 ldd->payTxnFreqPartRb = GTK_RADIO_BUTTON(gtk_builder_get_object(builder,
"pay_txn_part_rb"));
530 ldd->payTxnFreqUniqRb = GTK_RADIO_BUTTON(gtk_builder_get_object(builder,
"pay_uniq_freq_rb"));
531 ldd->payFreqHBox = GTK_BOX(gtk_builder_get_object(builder,
"pay_freq_hbox"));
535 ldd->revTable = GTK_GRID(gtk_builder_get_object(builder,
"rev_date_range_table"));
536 ldd->revRangeOpt = GTK_COMBO_BOX(gtk_builder_get_object(builder,
"rev_range_opt"));
537 ldd->revDateFrame = GTK_FRAME(gtk_builder_get_object(builder,
"rev_date_frame"));
538 ldd->revScrollWin = GTK_SCROLLED_WINDOW(gtk_builder_get_object(builder,
"rev_scrollwin"));
548 GList *liabilityAcct;
551 GList *paymentFromAccts;
553 GList *paymentToAccts;
562 liabilityAcct = NULL;
563 paymentFromAccts = NULL;
564 paymentToAccts = NULL;
566 liabilityAcct = g_list_append( liabilityAcct,
567 GINT_TO_POINTER( ACCT_TYPE_LIABILITY ) );
568 for ( i = 0; i < fromLen; i++ )
571 = g_list_append( paymentFromAccts,
572 GINT_TO_POINTER( paymentFroms[i] ) );
574 = g_list_append( paymentToAccts,
575 GINT_TO_POINTER( paymentFroms[i] ) );
578 for ( i = 0; i < toLen; i++ )
580 paymentToAccts = g_list_append( paymentToAccts,
581 GINT_TO_POINTER( paymentTos[i] ) );
588 struct gas_in_tables_data
592 gboolean newAcctAbility;
593 int left, top, width, height;
594 GList *allowableAccounts;
598 { &ldd->prmAccountGAS, ldd->prmTable, TRUE, 1, 0, 1, 1, liabilityAcct },
599 { &ldd->repAssetsFromGAS, ldd->repTable, TRUE, 1, 2, 1, 1, paymentFromAccts },
600 { &ldd->repPrincToGAS, ldd->repTable, TRUE, 1, 3, 1, 1, paymentToAccts },
601 { &ldd->repIntToGAS, ldd->repTable, TRUE, 3, 3, 1, 1, paymentToAccts },
602 { &ldd->payAcctFromGAS, ldd->payTable, TRUE, 1, 4, 1, 1, paymentFromAccts },
603 { &ldd->payAcctEscToGAS, ldd->payTable, FALSE, 3, 4, 1, 1, paymentToAccts },
604 { &ldd->payAcctEscFromGAS, ldd->payTable, FALSE, 1, 5, 1, 1, paymentFromAccts },
605 { &ldd->payAcctToGAS, ldd->payTable, TRUE, 3, 5, 1, 1, paymentToAccts },
609 ldd->prmOrigPrincGAE = GNC_AMOUNT_EDIT(gnc_amount_edit_new());
610 gtk_grid_attach (GTK_GRID(ldd->prmTable), GTK_WIDGET(ldd->prmOrigPrincGAE), 1, 1, 1, 1);
612 gtk_widget_set_halign (GTK_WIDGET(ldd->prmOrigPrincGAE), GTK_ALIGN_FILL);
613 gtk_widget_set_hexpand (GTK_WIDGET(ldd->prmOrigPrincGAE), FALSE);
614 g_object_set (GTK_WIDGET(ldd->prmOrigPrincGAE),
"margin", 2,
nullptr);
616 g_signal_connect (G_OBJECT(ldd->prmOrigPrincGAE),
"changed",
617 G_CALLBACK(loan_info_page_valid_cb), ldd);
619 for ( i = 0; gas_data[i].loc != NULL; i++ )
621 GNCAccountSel *gas = GNC_ACCOUNT_SEL(gnc_account_sel_new());
623 gnc_account_sel_set_new_account_ability(
624 gas, gas_data[i].newAcctAbility );
625 if ( gas_data[i].allowableAccounts != NULL )
627 gnc_account_sel_set_acct_filters(
628 gas, gas_data[i].allowableAccounts, NULL );
631 gtk_grid_attach (GTK_GRID(gas_data[i].
table),
638 gtk_widget_set_halign (GTK_WIDGET(gas), GTK_ALIGN_FILL);
639 gnc_account_sel_set_new_account_modal (GNC_ACCOUNT_SEL(gas),
true);
640 g_object_set (GTK_WIDGET(gas),
"margin", 2,
nullptr);
641 *(gas_data[i].loc) = gas;
646 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctEscToGAS), FALSE );
647 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctEscFromGAS), FALSE );
652 struct gde_in_tables_data
656 int left, top, width, height;
660 { &ldd->prmStartDateGDE, ldd->prmTable, 1, 4, 1, 1 },
661 { &ldd->revStartDate, ldd->revTable, 1, 0, 1, 1 },
662 { &ldd->revEndDate, ldd->revTable, 1, 1, 1, 1 },
666 for ( i = 0; gde_data[i].loc != NULL; i++ )
673 gtk_grid_attach (GTK_GRID(gde_data[i].
table),
674 GTK_WIDGET( *gde_data[i].loc ),
680 gtk_widget_set_halign (GTK_WIDGET( *gde_data[i].loc ), GTK_ALIGN_START);
681 gtk_widget_set_hexpand (GTK_WIDGET( *gde_data[i].loc ), FALSE);
682 g_object_set (GTK_WIDGET( *gde_data[i].loc ),
"margin", 0,
nullptr);
687 gtk_widget_set_sensitive( GTK_WIDGET(ldd->prmVarFrame), FALSE );
689 g_signal_connect( ldd->prmType,
"changed",
690 G_CALLBACK( loan_info_prm_type_cb ),
698 a = GTK_ADJUSTMENT(gtk_adjustment_new( 8.0, 0.001,
701 gtk_spin_button_set_adjustment( ldd->prmIrateSpin, a );
702 gtk_spin_button_set_value( ldd->prmIrateSpin, 8.00 );
703 gtk_spin_button_set_snap_to_ticks( ldd->prmIrateSpin, TRUE );
705 a = GTK_ADJUSTMENT(gtk_adjustment_new( 360, 1,
708 gtk_spin_button_set_adjustment( ldd->prmLengthSpin, a );
709 g_signal_connect( ldd->prmLengthSpin,
"changed",
710 G_CALLBACK( loan_info_calc_update_cb ),
712 g_signal_connect( ldd->prmStartDateGDE,
"date-changed",
713 G_CALLBACK( loan_info_calc_update_cb ),
715 g_signal_connect( ldd->prmLengthSpin,
"value-changed",
716 G_CALLBACK( loan_info_calc_update_cb ),
718 g_signal_connect( ldd->prmLengthType,
"changed",
719 G_CALLBACK( loan_info_calc_update_cb ),
722 a = GTK_ADJUSTMENT(gtk_adjustment_new( 360, 1,
725 gtk_spin_button_set_adjustment( ldd->prmRemainSpin, a );
728 g_signal_connect( ldd->optEscrowCb,
"toggled",
729 G_CALLBACK(loan_opt_escrow_toggle_cb), ldd );
730 gtk_widget_set_sensitive( GTK_WIDGET(ldd->optEscrowHBox), FALSE );
731 ldd->optEscrowGAS = GNC_ACCOUNT_SEL(gnc_account_sel_new());
732 g_object_set (ldd->optEscrowGAS,
"entry-width", 50, NULL);
733 gnc_account_sel_set_new_account_modal (GNC_ACCOUNT_SEL(ldd->optEscrowGAS),
true);
734 gnc_account_sel_set_new_account_ability( ldd->optEscrowGAS, TRUE );
735 gtk_container_add( GTK_CONTAINER(ldd->optEscrowHBox),
736 GTK_WIDGET(ldd->optEscrowGAS) );
751 str = g_string_sized_new( 32 );
753 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
755 rouid = ldd->repayOptsUI[i];
756 vb = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
757 gtk_box_set_homogeneous (GTK_BOX (vb), FALSE);
758 gtk_widget_set_margin_start (GTK_WIDGET(vb), 12);
764 g_string_printf( str,
_(
"… pay \"%s\"?"),
765 rouid->optData->name );
768 gtk_check_button_new_with_label(
770 gtk_box_pack_start( GTK_BOX(vb),
771 GTK_WIDGET(rouid->optCb),
775 gtk_check_button_new_with_label(
776 _(
"via Escrow account?") ));
777 gtk_widget_set_sensitive(
778 GTK_WIDGET(rouid->escrowCb),
781 gtk_box_pack_start( GTK_BOX(vb), GTK_WIDGET(rouid->escrowCb), FALSE, FALSE, 2 );
782 gtk_widget_set_margin_start (GTK_WIDGET(rouid->escrowCb), 12);
784 g_signal_connect( rouid->optCb,
"toggled",
785 G_CALLBACK(loan_opt_toggled_cb),
787 g_signal_connect( rouid->optCb,
"toggled",
788 G_CALLBACK(loan_opt_consistency_cb),
790 g_signal_connect( rouid->escrowCb,
"toggled",
791 G_CALLBACK(loan_opt_escrow_toggled_cb),
794 gtk_box_pack_start( GTK_BOX(ldd->optVBox), GTK_WIDGET(vb), FALSE, FALSE, 2 );
795 gtk_widget_show_all( GTK_WIDGET(ldd->optVBox) );
797 g_string_free( str, TRUE );
800 g_signal_connect( ldd->payUseEscrow,
"toggled",
801 G_CALLBACK(loan_pay_use_esc_toggle_cb), ldd );
802 g_signal_connect( ldd->paySpecSrcAcct,
"toggled",
803 G_CALLBACK(loan_pay_spec_src_toggle_cb), ldd );
804 g_signal_connect( ldd->payTxnFreqUniqRb,
"toggled",
805 G_CALLBACK(loan_pay_freq_toggle_cb), ldd );
809 hbox = GTK_BOX(gtk_builder_get_object(builder,
"type_freq_hbox"));
810 ldd->prmVarGncFreq = GNC_FREQUENCY(gnc_frequency_new( NULL, NULL ));
811 gtk_box_pack_start( GTK_BOX(hbox) , GTK_WIDGET(ldd->prmVarGncFreq), TRUE, FALSE, 0 );
812 g_signal_connect (ldd->prmVarGncFreq,
"changed",
813 G_CALLBACK (loan_info_page_valid_cb), ldd);
817 hbox = GTK_BOX(gtk_builder_get_object(builder,
"freq_frame_hbox"));
818 ldd->repGncFreq = GNC_FREQUENCY(gnc_frequency_new( NULL, NULL ));
819 gtk_box_pack_start( GTK_BOX(hbox) , GTK_WIDGET(ldd->repGncFreq), TRUE, FALSE, 0 );
820 g_signal_connect (ldd->repGncFreq,
"changed",
821 G_CALLBACK (loan_rep_page_valid_cb), ldd);
824 ldd->payGncFreq = GNC_FREQUENCY(gnc_frequency_new( NULL, NULL ));
825 gtk_container_add( GTK_CONTAINER(ldd->payFreqHBox), GTK_WIDGET(ldd->payGncFreq) );
827 g_signal_connect (ldd->payGncFreq,
"changed",
828 G_CALLBACK (loan_pay_page_valid_cb), ldd);
830 butt = GTK_WIDGET(gtk_builder_get_object(builder,
"pay_back_button"));
831 g_signal_connect (butt,
"clicked",
832 G_CALLBACK (loan_pay_back_button_cb), ldd);
834 butt = GTK_WIDGET(gtk_builder_get_object(builder,
"pay_next_button"));
835 g_signal_connect (butt,
"clicked",
836 G_CALLBACK (loan_pay_next_button_cb), ldd);
842 g_signal_connect (ldd->prmAccountGAS,
"account_sel_changed",
843 G_CALLBACK (loan_info_page_valid_cb), ldd);
844 g_signal_connect( ldd->prmIrateType,
"changed",
845 G_CALLBACK( loan_info_page_valid_cb ), ldd );
849 g_signal_connect (ldd->optEscrowGAS,
"account_sel_changed",
850 G_CALLBACK (loan_opt_page_valid_cb), ldd);
854 g_signal_connect (ldd->repAssetsFromGAS,
"account_sel_changed",
855 G_CALLBACK (loan_rep_page_valid_cb), ldd);
856 g_signal_connect (ldd->repIntToGAS,
"account_sel_changed",
857 G_CALLBACK (loan_rep_page_valid_cb), ldd);
858 g_signal_connect (ldd->repPrincToGAS,
"account_sel_changed",
859 G_CALLBACK (loan_rep_page_valid_cb), ldd);
863 g_signal_connect (ldd->payAcctFromGAS,
"account_sel_changed",
864 G_CALLBACK (loan_pay_page_valid_cb), ldd);
865 g_signal_connect (ldd->payAcctToGAS,
"account_sel_changed",
866 G_CALLBACK (loan_pay_page_valid_cb), ldd);
867 g_signal_connect (ldd->payAcctEscFromGAS,
"account_sel_changed",
868 G_CALLBACK (loan_pay_page_valid_cb), ldd);
869 g_signal_connect (ldd->payAcctEscToGAS,
"account_sel_changed",
870 G_CALLBACK (loan_pay_page_valid_cb), ldd);
874 gtk_combo_box_set_active( ldd->revRangeOpt, 0 );
875 g_signal_connect( ldd->revRangeOpt,
"changed",
876 G_CALLBACK( loan_rev_range_opt_changed_cb ),
878 g_signal_connect( ldd->revStartDate,
"date-changed",
879 G_CALLBACK( loan_rev_range_changed_cb ),
881 g_signal_connect( ldd->revEndDate,
"date-changed",
882 G_CALLBACK( loan_rev_range_changed_cb ),
886 g_signal_connect( ldd->window,
"destroy",
887 G_CALLBACK(loan_assistant_window_destroy_cb),
890 gtk_builder_connect_signals(builder, ldd);
891 g_object_unref(G_OBJECT(builder));
893 gtk_widget_show_all( ldd->window );
906 for ( optCount = 0; REPAY_DEFAULTS[optCount].name != NULL; optCount++ )
909 ldd->currentIdx = -1;
911 ldd->ld.principal = gnc_numeric_zero();
912 ldd->ld.startDate = g_date_new();
913 ldd->ld.varStartDate = g_date_new();
915 ldd->ld.loan_schedule = NULL;
916 ldd->ld.repayment_schedule = NULL;
919 recurrenceSet(r, 1, PERIOD_MONTH, ldd->ld.startDate, WEEKEND_ADJ_NONE);
920 ldd->ld.repayment_schedule = g_list_append(ldd->ld.repayment_schedule, r);
923 ldd->ld.repMemo = g_strdup(
_(
"Loan") );
924 ldd->ld.repStartDate = g_date_new();
925 ldd->ld.repayOptCount = optCount;
929 for ( i = 0; i < optCount; i++ )
931 g_assert( REPAY_DEFAULTS[i].name != NULL );
934 ldd->repayOptsUI[i]->ldd = ldd;
936 optData = ldd->ld.repayOpts[i]
937 = ldd->repayOptsUI[i]->optData
940 optData->enabled = FALSE;
941 optData->optValid = FALSE;
942 optData->FreqUniq = FALSE;
943 optData->name = g_strdup(
_(REPAY_DEFAULTS[i].name) );
944 optData->txnMemo = g_strdup(
_(REPAY_DEFAULTS[i].
946 optData->amount = 0.0;
947 optData->throughEscrowP = REPAY_DEFAULTS[i].escrowDefault;
948 optData->specSrcAcctP = REPAY_DEFAULTS[i].specSrcAcctDefault;
949 optData->schedule = NULL;
950 optData->startDate = NULL;
958loan_info_prep( GtkAssistant *assistant, gpointer user_data )
962 gnc_amount_edit_set_amount( ldd->prmOrigPrincGAE, ldd->ld.principal );
963 gtk_spin_button_set_value( ldd->prmIrateSpin, ldd->ld.interestRate );
964 gtk_combo_box_set_active( ldd->prmIrateType, ldd->ld.rateType );
965 gtk_combo_box_set_active( ldd->prmType, ldd->ld.type );
966 if ( ldd->ld.type != GNC_FIXED )
968 g_signal_handlers_block_by_func( GNC_FREQUENCY( ldd->prmVarGncFreq),
969 (gpointer) loan_info_page_valid_cb, ldd );
970 gnc_frequency_setup_recurrence(ldd->prmVarGncFreq, ldd->ld.loan_schedule, ldd->ld.varStartDate);
971 g_signal_handlers_unblock_by_func( GNC_FREQUENCY( ldd->prmVarGncFreq),
972 (gpointer) loan_info_page_valid_cb, ldd );
979 tmpTm = g_new0(
struct tm, 1 );
981 g_date_to_struct_tm (ldd->ld.startDate, tmpTm);
982 gnc_date_edit_set_time (ldd->prmStartDateGDE,
989 gtk_spin_button_set_value( ldd->prmLengthSpin, ldd->ld.numPer );
990 gtk_combo_box_set_active( ldd->prmLengthType, ldd->ld.perSize );
991 gtk_spin_button_set_value( ldd->prmRemainSpin, ldd->ld.numMonRemain );
998loan_info_prm_type_cb( GtkWidget *w, gpointer user_data )
1003 index = gtk_combo_box_get_active( ldd->prmType );
1004 gtk_widget_set_sensitive( GTK_WIDGET(ldd->prmVarFrame),
1005 index != GNC_FIXED );
1011loan_info_calc_update_cb( GtkWidget *w, gpointer user_data )
1015 int i, totalVal, total, remain;
1017 g_date_clear( &start, 1 );
1018 g_date_clear( &now, 1 );
1021 for ( i = 0; g_date_compare( &start, &now ) < 0; i++ )
1023 g_date_add_months( &start, 1 );
1027 totalVal = gtk_spin_button_get_value_as_int (ldd->prmLengthSpin);
1029 * ( gtk_combo_box_get_active( ldd->prmLengthType )
1032 gtk_spin_button_set_value( ldd->prmRemainSpin, remain );
1033 gtk_widget_show( GTK_WIDGET(ldd->prmRemainSpin) );
1038loan_info_page_valid_cb (GtkWidget *widget, gpointer user_data )
1041 GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
1042 gint num = gtk_assistant_get_current_page (assistant);
1043 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1045 gtk_assistant_set_page_complete (assistant, page,
1046 loan_info_page_complete (assistant, ldd));
1052loan_info_page_complete( GtkAssistant *assistant, gpointer user_data )
1056 gnc_commodity *currency;
1060 ldd->ld.primaryAcct = gnc_account_sel_get_account( ldd->prmAccountGAS );
1062 if ( ldd->ld.primaryAcct == NULL )
1067 print_info = gnc_commodity_print_info (currency, FALSE);
1068 gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT(ldd->prmOrigPrincGAE), print_info);
1069 gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT(ldd->prmOrigPrincGAE),
1072 result = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT(ldd->prmOrigPrincGAE),
1073 &value, FALSE,
nullptr);
1083loan_info_page_save( GtkAssistant *assistant, gpointer user_data )
1087 ldd->ld.primaryAcct = gnc_account_sel_get_account( ldd->prmAccountGAS );
1089 if ( ! ldd->ld.repPriAcct )
1091 ldd->ld.repPriAcct = ldd->ld.primaryAcct;
1093 ldd->ld.principal = gnc_amount_edit_get_amount( ldd->prmOrigPrincGAE );
1094 ldd->ld.interestRate = gtk_spin_button_get_value( ldd->prmIrateSpin );
1095 ldd->ld.rateType =
static_cast<IRateType
>( gtk_combo_box_get_active (ldd->prmIrateType ));
1096 ldd->ld.type =
static_cast<LoanType
>( gtk_combo_box_get_active( ldd->prmType ));
1098 if ( ldd->ld.type != GNC_FIXED )
1100 recurrenceListFree(&ldd->ld.loan_schedule);
1101 gnc_frequency_save_to_recurrence(ldd->prmVarGncFreq,
1102 &ldd->ld.loan_schedule,
1103 ldd->ld.varStartDate);
1111 tmpTT = gnc_date_edit_get_date( ldd->prmStartDateGDE );
1115 g_date_set_dmy( ldd->ld.startDate,
1117 static_cast<GDateMonth
>(tmpTm->tm_mon + 1),
1118 (1900 + tmpTm->tm_year) );
1126 (gtk_combo_box_get_active( ldd->prmLengthType )
1127 == GNC_MONTHS) ? GNC_MONTHS : GNC_YEARS;
1129 gtk_spin_button_get_value_as_int( ldd->prmLengthSpin );
1130 ldd->ld.numMonRemain =
1131 gtk_spin_button_get_value_as_int( ldd->prmRemainSpin );
1139loan_opt_prep( GtkAssistant *assistant, gpointer user_data )
1146 loan_info_page_save(assistant, ldd);
1148 if ( ldd->ld.escrowAcct )
1150 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->optEscrowCb), TRUE );
1151 gnc_account_sel_set_account( ldd->optEscrowGAS, ldd->ld.escrowAcct, FALSE );
1153 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
1155 rouid = ldd->repayOptsUI[i];
1156 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(rouid->optCb),
1157 rouid->optData->enabled );
1158 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(rouid->escrowCb),
1159 rouid->optData->throughEscrowP
1160 && rouid->optData->enabled
1161 && ldd->ld.escrowAcct );
1162 gtk_widget_set_sensitive( GTK_WIDGET(rouid->escrowCb),
1163 rouid->optData->enabled
1164 && ldd->ld.escrowAcct );
1171loan_opt_toggled_cb( GtkToggleButton *tb, gpointer user_data )
1176 rouid->optData->enabled = gtk_toggle_button_get_active(tb);
1182loan_opt_consistency_cb( GtkToggleButton *tb, gpointer user_data )
1184 GtkToggleButton *escrowCb;
1188 escrowCb = GTK_TOGGLE_BUTTON(rouid->escrowCb);
1190 gtk_toggle_button_set_active( escrowCb,
1191 gtk_toggle_button_get_active(
1193 rouid->ldd->optEscrowCb) )
1194 && rouid->optData->throughEscrowP
1195 && gtk_toggle_button_get_active(tb) );
1198 gtk_widget_set_sensitive( GTK_WIDGET(escrowCb),
1199 gtk_toggle_button_get_active(tb)
1200 && gtk_toggle_button_get_active(
1201 GTK_TOGGLE_BUTTON(rouid->ldd->optEscrowCb)) );
1207loan_opt_escrow_toggle_cb( GtkToggleButton *tb, gpointer user_data )
1213 GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
1214 gint num = gtk_assistant_get_current_page (assistant);
1215 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1217 newState = gtk_toggle_button_get_active(tb);
1218 gtk_widget_set_sensitive( GTK_WIDGET(ldd->optEscrowHBox), newState );
1222 if (GNC_ACCOUNT_SEL( ldd->ld.escrowAcct) == NULL)
1223 gtk_assistant_set_page_complete (assistant, page, FALSE);
1227 ldd->ld.escrowAcct = NULL;
1228 gnc_account_sel_set_account( GNC_ACCOUNT_SEL( ldd->optEscrowGAS), NULL , FALSE );
1229 gtk_assistant_set_page_complete (assistant, page, TRUE);
1234 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
1236 rouid = ldd->repayOptsUI[i];
1242 g_signal_handlers_block_by_func( rouid->escrowCb,
1243 (gpointer) loan_opt_escrow_toggled_cb,
1245 gtk_toggle_button_set_active(
1246 GTK_TOGGLE_BUTTON(rouid->escrowCb),
1248 && gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(rouid->optCb) )
1249 && rouid->optData->throughEscrowP ) );
1250 gtk_widget_set_sensitive(
1251 GTK_WIDGET(rouid->escrowCb),
1253 && gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(rouid->optCb) ) );
1254 g_signal_handlers_unblock_by_func( rouid->escrowCb,
1255 (gpointer) loan_opt_escrow_toggled_cb,
1259 rouid->optData->from = ldd->ld.escrowAcct;
1263 rouid->optData->from = NULL;
1271loan_opt_escrow_toggled_cb( GtkToggleButton *tb, gpointer user_data )
1276 rouid->optData->throughEscrowP = gtk_toggle_button_get_active( tb );
1281loan_opt_page_valid_cb (GtkWidget *widget, gpointer user_data )
1285 GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
1286 gint num = gtk_assistant_get_current_page (assistant);
1287 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1289 gtk_assistant_set_page_complete (assistant, page,
1290 loan_opt_page_complete (assistant, ldd));
1296loan_opt_page_complete( GtkAssistant *assistant, gpointer user_data )
1300 if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(ldd->optEscrowCb) ) )
1302 ldd->ld.escrowAcct =
1303 gnc_account_sel_get_account( ldd->optEscrowGAS );
1305 if ( ldd->ld.escrowAcct == NULL )
1310 ldd->ld.escrowAcct = NULL;
1318update_repayment_formula_cb(GtkWidget *widget, gpointer user_data)
1322 recurrenceListFree(&ldd->ld.repayment_schedule);
1323 gnc_frequency_save_to_recurrence(ldd->repGncFreq,
1324 &ldd->ld.repayment_schedule,
1325 ldd->ld.repStartDate);
1327 ldd->ld.repAmount = loan_get_pmt_formula(ldd);
1328 if (!ldd->ld.repAmount.empty() )
1329 gtk_entry_set_text(ldd->repAmtEntry, ldd->ld.repAmount.c_str());
1334loan_rep_prep( GtkAssistant *assistant, gpointer user_data )
1337 static gulong date_changed_handler_id = 0;
1339 if (date_changed_handler_id)
1341 g_signal_handler_disconnect(ldd->repGncFreq, date_changed_handler_id);
1342 date_changed_handler_id = 0;
1345 ldd->ld.repAmount = loan_get_pmt_formula(ldd);
1347 if ( ldd->ld.repMemo )
1348 gtk_entry_set_text( ldd->repTxnName, ldd->ld.repMemo );
1350 if (!ldd->ld.repAmount.empty() )
1351 gtk_entry_set_text(ldd->repAmtEntry, ldd->ld.repAmount.c_str());
1353 gnc_account_sel_set_account( ldd->repAssetsFromGAS, ldd->ld.repFromAcct, FALSE );
1354 gnc_account_sel_set_account( ldd->repPrincToGAS, ldd->ld.repPriAcct, FALSE );
1355 gnc_account_sel_set_account( ldd->repIntToGAS, ldd->ld.repIntAcct, FALSE );
1357 g_signal_handlers_block_by_func( ldd->repGncFreq,
1358 (gpointer) loan_rep_page_valid_cb, ldd );
1359 gnc_frequency_setup_recurrence(ldd->repGncFreq, ldd->ld.repayment_schedule,
1360 ldd->ld.repStartDate);
1361 date_changed_handler_id = g_signal_connect (ldd->repGncFreq,
"changed",
1362 G_CALLBACK (update_repayment_formula_cb), ldd);
1363 g_signal_handlers_unblock_by_func( ldd->repGncFreq,
1364 (gpointer) loan_rep_page_valid_cb, ldd );
1370 (i < ldd->ld.repayOptCount)
1371 && !ldd->ld.repayOpts[i]->enabled;
1374 if ( i < ldd->ld.repayOptCount )
1375 ldd->currentIdx = i;
1377 ldd->currentIdx = -1;
1383loan_rep_page_valid_cb (GtkWidget *widget, gpointer user_data )
1386 GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
1387 gint num = gtk_assistant_get_current_page (assistant);
1388 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1390 gtk_assistant_set_page_complete (assistant, page,
1391 loan_rep_page_complete (assistant, ldd));
1397loan_rep_page_complete( GtkAssistant *assistant, gpointer user_data )
1401 ldd->ld.repFromAcct =
1402 gnc_account_sel_get_account( ldd->repAssetsFromGAS );
1404 if ( ldd->ld.repFromAcct == NULL )
1407 ldd->ld.repPriAcct =
1408 gnc_account_sel_get_account( ldd->repPrincToGAS );
1410 if ( ldd->ld.repPriAcct == NULL )
1413 ldd->ld.repIntAcct =
1414 gnc_account_sel_get_account( ldd->repIntToGAS );
1416 if ( ldd->ld.repIntAcct == NULL )
1425loan_rep_page_save( GtkAssistant *assistant, gpointer user_data )
1429 if ( ldd->ld.repMemo )
1430 g_free( ldd->ld.repMemo );
1432 gtk_editable_get_chars( GTK_EDITABLE(ldd->repTxnName), 0, -1 );
1435 ldd->ld.repAmount = gtk_entry_get_text(ldd->repAmtEntry);
1437 ldd->ld.repFromAcct =
1438 gnc_account_sel_get_account( ldd->repAssetsFromGAS );
1440 ldd->ld.repPriAcct =
1441 gnc_account_sel_get_account( ldd->repPrincToGAS );
1443 ldd->ld.repIntAcct =
1444 gnc_account_sel_get_account( ldd->repIntToGAS );
1451loan_pay_prep( GtkAssistant *assistant, gpointer user_data )
1458 gint num = gtk_assistant_get_current_page (assistant);
1459 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1462 loan_rep_page_save(assistant, ldd);
1465 if (ldd->currentIdx == -1 )
1467 gtk_assistant_set_current_page (assistant, num + 1);
1471 g_assert( ldd->currentIdx >= 0 );
1472 g_assert( ldd->currentIdx <= ldd->ld.repayOptCount );
1474 rod = ldd->ld.repayOpts[ldd->currentIdx];
1475 str = g_string_sized_new( 32 );
1477 g_string_printf( str,
_(
"Loan Repayment Option: \"%s\""), rod->name );
1478 gtk_assistant_set_page_title (assistant, page, str->str );
1481 gtk_entry_set_text( ldd->payTxnName, rod->txnMemo );
1482 g_string_printf( str,
"%0.2f", rod->amount );
1483 gtk_entry_set_text( ldd->payAmtEntry, str->str );
1485 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payUseEscrow),
1486 (ldd->ld.escrowAcct != NULL) );
1489 g_signal_handlers_block_by_func( ldd->payUseEscrow,
1490 (gpointer) loan_pay_use_esc_toggle_cb,
1493 loan_pay_use_esc_setup( ldd,
1494 (ldd->ld.escrowAcct != NULL)
1495 && rod->throughEscrowP );
1496 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payUseEscrow),
1497 (rod->throughEscrowP
1498 && ldd->ld.escrowAcct != NULL) );
1500 g_signal_handlers_unblock_by_func( ldd->payUseEscrow,
1501 (gpointer) loan_pay_use_esc_toggle_cb,
1506 g_signal_handlers_block_by_func( ldd->paySpecSrcAcct,
1507 (gpointer) loan_pay_spec_src_toggle_cb,
1509 loan_pay_spec_src_setup( ldd, rod->specSrcAcctP );
1510 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->paySpecSrcAcct),
1511 rod->specSrcAcctP );
1513 g_signal_handlers_unblock_by_func( ldd->paySpecSrcAcct,
1514 (gpointer) loan_pay_spec_src_toggle_cb,
1518 g_signal_handlers_block_by_func(ldd->payAcctToGAS,
1519 (gpointer) loan_pay_page_valid_cb, ldd );
1520 gnc_account_sel_set_account( ldd->payAcctToGAS, rod->to, FALSE );
1521 g_signal_handlers_unblock_by_func(ldd->payAcctToGAS,
1522 (gpointer) loan_pay_page_valid_cb, ldd );
1525 g_signal_handlers_block_by_func(ldd->payTxnFreqUniqRb,
1526 (gpointer) loan_pay_freq_toggle_cb, ldd );
1527 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqPartRb), !rod->FreqUniq );
1528 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqUniqRb), rod->FreqUniq );
1529 g_signal_handlers_unblock_by_func(ldd->payTxnFreqUniqRb,
1530 (gpointer) loan_pay_freq_toggle_cb, ldd );
1532 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payFreqHBox), rod->FreqUniq );
1534 if ( rod->FreqUniq )
1536 g_signal_handlers_disconnect_by_func( ldd->payGncFreq,
1537 (gpointer) loan_pay_page_valid_cb, ldd );
1538 gtk_container_remove( GTK_CONTAINER(ldd->payFreqHBox), GTK_WIDGET(ldd->payGncFreq) );
1539 ldd->payGncFreq = NULL;
1540 ldd->payGncFreq = GNC_FREQUENCY(gnc_frequency_new_from_recurrence( rod->schedule, rod->startDate ));
1541 gtk_container_add( GTK_CONTAINER(ldd->payFreqHBox), GTK_WIDGET(ldd->payGncFreq) );
1542 g_signal_connect (ldd->payGncFreq,
"changed",
1543 G_CALLBACK (loan_pay_page_valid_cb), ldd);
1545 g_string_free( str, TRUE );
1546 loan_pay_page_valid_cb(GTK_WIDGET(ldd->window), ldd);
1552loan_pay_page_valid_cb (GtkWidget *widget, gpointer user_data )
1555 GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
1556 gint num = gtk_assistant_get_current_page (assistant);
1557 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1559 gtk_assistant_set_page_complete (assistant, page,
1560 ( loan_pay_complete (assistant, ldd) &&
1561 loan_pay_all_opt_valid (assistant, ldd )));
1569 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payEscToLabel), newState );
1570 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payEscFromLabel), newState );
1573 g_signal_handlers_block_by_func( ldd->payAcctEscToGAS,
1574 (gpointer) loan_pay_page_valid_cb, ldd );
1575 g_signal_handlers_block_by_func( ldd->payAcctEscFromGAS,
1576 (gpointer) loan_pay_page_valid_cb, ldd );
1577 gnc_account_sel_set_account( ldd->payAcctEscToGAS, ldd->ld.escrowAcct, FALSE );
1578 gnc_account_sel_set_account( ldd->payAcctEscFromGAS, ldd->ld.escrowAcct, FALSE );
1579 g_signal_handlers_unblock_by_func( ldd->payAcctEscToGAS,
1580 (gpointer) loan_pay_page_valid_cb, ldd );
1581 g_signal_handlers_unblock_by_func( ldd->payAcctEscFromGAS,
1582 (gpointer) loan_pay_page_valid_cb, ldd );
1589loan_pay_use_esc_toggle_cb( GtkToggleButton *tb, gpointer user_data )
1594 newState = gtk_toggle_button_get_active( tb );
1595 loan_pay_use_esc_setup( ldd, newState );
1603 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctFromLabel), newState );
1604 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctFromGAS), newState );
1607 g_signal_handlers_block_by_func( ldd->payAcctFromGAS,
1608 (gpointer) loan_pay_page_valid_cb, ldd );
1609 gnc_account_sel_set_account( ldd->payAcctFromGAS, ldd->ld.repayOpts[ldd->currentIdx]->from, FALSE );
1610 g_signal_handlers_unblock_by_func( ldd->payAcctFromGAS,
1611 (gpointer) loan_pay_page_valid_cb, ldd );
1615 g_signal_handlers_block_by_func( ldd->payAcctFromGAS,
1616 (gpointer) loan_pay_page_valid_cb, ldd );
1617 gnc_account_sel_set_account( ldd->payAcctFromGAS, NULL, FALSE );
1618 ldd->ld.repayOpts[ldd->currentIdx]->from = NULL;
1619 g_signal_handlers_unblock_by_func( ldd->payAcctFromGAS,
1620 (gpointer) loan_pay_page_valid_cb, ldd );
1627loan_pay_spec_src_toggle_cb( GtkToggleButton *tb, gpointer user_data )
1632 newState = gtk_toggle_button_get_active( tb );
1633 loan_pay_spec_src_setup( ldd, newState );
1639loan_pay_freq_toggle_cb( GtkToggleButton *tb, gpointer user_data )
1644 g_assert( ldd->currentIdx >= 0 );
1645 g_assert( ldd->currentIdx <= ldd->ld.repayOptCount );
1647 rod = ldd->ld.repayOpts[ldd->currentIdx];
1649 rod->FreqUniq = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqUniqRb) );
1650 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payFreqHBox), rod->FreqUniq );
1652 if ( rod->FreqUniq )
1654 if ( rod->schedule == NULL )
1658 recurrenceSet(r, 1, PERIOD_MONTH, ldd->ld.startDate, WEEKEND_ADJ_NONE);
1659 rod->schedule = g_list_append(rod->schedule, r);
1661 if ( rod->startDate == NULL )
1663 rod->startDate = g_date_new();
1664 *rod->startDate = *ldd->ld.startDate;
1666 g_signal_handlers_block_by_func( ldd->payGncFreq,
1667 (gpointer) loan_pay_page_valid_cb, ldd );
1668 gnc_frequency_setup_recurrence(ldd->payGncFreq, rod->schedule, rod->startDate);
1669 g_signal_handlers_unblock_by_func( ldd->payGncFreq,
1670 (gpointer) loan_pay_page_valid_cb, ldd );
1676 recurrenceListFree(&rod->schedule);
1678 if ( rod->startDate )
1680 g_date_free( rod->startDate );
1681 rod->startDate = NULL;
1689loan_pay_next_button_cb( GtkButton *button, gpointer user_data )
1695 if ( loan_pay_complete ( GTK_ASSISTANT(ldd->window), user_data ) != FALSE )
1698 for ( i = ldd->currentIdx + 1;
1699 (i < ldd->ld.repayOptCount)
1700 && !ldd->ld.repayOpts[i]->enabled; i++ )
1702 if ( i < ldd->ld.repayOptCount )
1704 ldd->currentIdx = i;
1705 loan_pay_prep( GTK_ASSISTANT(ldd->window), user_data );
1713loan_pay_back_button_cb( GtkButton *button, gpointer user_data )
1719 if ( loan_pay_complete ( GTK_ASSISTANT(ldd->window), user_data ) != FALSE)
1722 for ( i = ldd->currentIdx - 1;
1723 (i > -1) && !ldd->ld.repayOpts[i]->enabled;
1728 ldd->currentIdx = i;
1729 loan_pay_prep( GTK_ASSISTANT(ldd->window), user_data );
1737loan_pay_all_opt_valid ( GtkAssistant *assistant, gpointer user_data )
1745 for ( i = 0; (i < ldd->ld.repayOptCount); i++ )
1747 if (ldd->ld.repayOpts[i]->enabled)
1749 if (ldd->ld.repayOpts[i]->optValid)
1761loan_pay_complete( GtkAssistant *assistant, gpointer user_data )
1766 g_assert( ldd->currentIdx >= 0 );
1767 g_assert( ldd->currentIdx <= ldd->ld.repayOptCount );
1768 rod = ldd->ld.repayOpts[ ldd->currentIdx ];
1770 if ( rod->txnMemo != NULL )
1772 g_free( rod->txnMemo );
1774 rod->txnMemo = g_strdup (gtk_entry_get_text (GTK_ENTRY(ldd->payTxnName)));
1775 rod->amount = (float)strtod (gtk_entry_get_text (GTK_ENTRY(ldd->payAmtEntry)), NULL);
1778 gtk_toggle_button_get_active(
1779 GTK_TOGGLE_BUTTON(ldd->paySpecSrcAcct) );
1782 if ( rod->specSrcAcctP )
1784 rod->from = gnc_account_sel_get_account( ldd->payAcctFromGAS );
1785 if ( rod->from == NULL )
1790 rod->to = gnc_account_sel_get_account( ldd->payAcctToGAS );
1791 if ( rod->to == NULL )
1795 rod->optValid = TRUE;
1798 if ( rod->FreqUniq )
1800 if ( rod->startDate == NULL )
1802 rod->startDate = g_date_new();
1804 recurrenceListFree(&rod->schedule);
1805 gnc_frequency_save_to_recurrence(ldd->payGncFreq, &rod->schedule, rod->startDate);
1807 if (! rod->schedule )
1819loan_rev_prep( GtkAssistant *assistant, gpointer user_data )
1822 static const int BASE_COLS = 3;
1824 GtkListStore *store;
1825 GtkCellRenderer *renderer;
1826 GtkTreeViewColumn *column;
1832 if (ldd->currentIdx != -1)
1833 loan_pay_complete(assistant, ldd);
1836 if ( ldd->revView != NULL )
1838 gtk_widget_destroy( GTK_WIDGET(ldd->revView) );
1839 ldd->revView = NULL;
1842 ldd->ld.revNumPmts = BASE_COLS;
1844 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
1846 ldd->ld.revRepayOptToColMap[i] = -1;
1847 if ( ! ldd->ld.repayOpts[i]->enabled )
1853 ldd->ld.revRepayOptToColMap[i] = ldd->ld.revNumPmts;
1854 ldd->ld.revNumPmts += 1;
1857 types = g_new( GType, ldd->ld.revNumPmts + 1 );
1858 for ( i = 0; i < ldd->ld.revNumPmts + 1; i++ )
1859 types[i] = G_TYPE_STRING;
1860 store = gtk_list_store_newv(ldd->ld.revNumPmts + 1, types);
1863 ldd->revView = GTK_TREE_VIEW(
1864 gtk_tree_view_new_with_model( GTK_TREE_MODEL(store) ));
1865 g_object_unref(store);
1868 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW(ldd->revView), gnc_tree_view_get_grid_lines_pref ());
1870 renderer = gtk_cell_renderer_text_new();
1871 column = gtk_tree_view_column_new_with_attributes(
_(
"Date"), renderer,
1872 "text", LOAN_COL_DATE,
1874 gtk_tree_view_append_column(ldd->revView, column);
1876 renderer = gtk_cell_renderer_text_new();
1877 column = gtk_tree_view_column_new_with_attributes(
_(
"Payment"), renderer,
1878 "text", LOAN_COL_PAYMENT,
1880 gtk_tree_view_append_column(ldd->revView, column);
1882 renderer = gtk_cell_renderer_text_new();
1883 column = gtk_tree_view_column_new_with_attributes(
_(
"Principal"), renderer,
1884 "text", LOAN_COL_PRINCIPAL,
1886 gtk_tree_view_append_column(ldd->revView, column);
1888 renderer = gtk_cell_renderer_text_new();
1889 column = gtk_tree_view_column_new_with_attributes(
_(
"Interest"), renderer,
1890 "text", LOAN_COL_INTEREST,
1892 gtk_tree_view_append_column(ldd->revView, column);
1896 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
1898 if ( ldd->ld.revRepayOptToColMap[i] == -1 )
1902 renderer = gtk_cell_renderer_text_new();
1903 column = gtk_tree_view_column_new_with_attributes
1904 (ldd->ld.repayOpts[i]->name, renderer,
1905 "text", LOAN_COL_INTEREST + col,
1907 gtk_tree_view_append_column(ldd->revView, column);
1912 gtk_container_add( GTK_CONTAINER(ldd->revScrollWin),
1913 GTK_WIDGET(ldd->revView) );
1914 gtk_widget_show( GTK_WIDGET(ldd->revView) );
1916 loan_rev_recalc_schedule( ldd );
1920 g_date_clear( &start, 1 );
1921 g_date_clear( &end, 1 );
1922 loan_rev_get_dates( ldd, &start, &end );
1923 loan_rev_update_view( ldd, &start, &end );
1930loan_rev_range_opt_changed_cb( GtkComboBox *combo, gpointer user_data )
1935 opt = gtk_combo_box_get_active( ldd->revRangeOpt );
1936 gtk_widget_set_sensitive( GTK_WIDGET(ldd->revDateFrame),
1940 g_date_clear( &start, 1 );
1941 g_date_clear( &end, 1 );
1942 loan_rev_get_dates( ldd, &start, &end );
1943 loan_rev_update_view( ldd, &start, &end );
1950loan_rev_range_changed_cb(
GNCDateEdit *gde, gpointer user_data )
1955 g_date_clear( &start, 1 );
1956 g_date_clear( &end, 1 );
1957 loan_rev_get_dates( ldd, &start, &end );
1958 loan_rev_update_view( ldd, &start, &end );
1968 struct tm *endDateMath;
1970 *start = *ldd->ld.startDate;
1972 endDateMath = g_new0(
struct tm, 1 );
1973 g_date_to_struct_tm (ldd->ld.startDate, endDateMath);
1974 monthsTotal = ( ldd->ld.numPer
1975 * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) );
1976 endDateMath->tm_mon += monthsTotal;
1978 g_date_subtract_days( end, 1 );
1979 g_free (endDateMath);
1987 int range = gtk_combo_box_get_active( ldd->revRangeOpt );
1992 g_date_set_dmy( start, 1, G_DATE_JANUARY, g_date_get_year( start ) );
1993 g_date_set_dmy( end, 31, G_DATE_DECEMBER, g_date_get_year( start ) );
1998 g_date_add_years( end, 1 );
2001 loan_rev_get_loan_range( ldd, start, end );
2005 gnc_date_edit_get_date( ldd->revStartDate ) );
2007 gnc_date_edit_get_date( ldd->revEndDate ) );
2010 PERR(
"Unknown review date range option %d", range );
2019loan_rev_sched_list_free( gpointer data, gpointer user_data )
2022 g_free( rrr->numCells );
2029loan_rev_hash_to_list( gpointer key, gpointer val, gpointer user_data )
2031 GList **l = (GList**)user_data;
2035 DEBUG(
"%.8x, %.8x",
2036 GPOINTER_TO_UINT(key),
2037 GPOINTER_TO_UINT(val));
2041 rrr->date = *(GDate*)key;
2042 rrr->numCells = (gnc_numeric*)val;
2043 *l = g_list_append( *l, (gpointer)rrr );
2049loan_rev_hash_free_date_keys( gpointer key, gpointer val, gpointer user_data )
2051 g_free( (GDate*)key );
2060 gnc_numeric *rowNumData;
2061 GHashTable *repayment_schedule;
2063 g_date_clear( &start, 1 );
2064 g_date_clear( &end, 1 );
2065 loan_rev_get_loan_range( ldd, &start, &end );
2075 GDate curDate, nextDate;
2079 auto pmtFormula = loan_get_pmt_formula(ldd);
2080 auto ppmtFormula = loan_get_ppmt_formula(ldd);
2081 auto ipmtFormula = loan_get_ipmt_formula(ldd);
2083 ivar = g_hash_table_new( g_str_hash, g_str_equal );
2084 g_date_clear( &curDate, 1 );
2086 g_date_subtract_days( &curDate, 1 );
2087 g_date_clear(&nextDate, 1);
2088 recurrenceListNextInstance(ldd->ld.repayment_schedule, &curDate, &nextDate);
2090 g_date_valid( &nextDate )
2091 && g_date_compare( &nextDate, &end ) <= 0 ;
2094 recurrenceListNextInstance(ldd->ld.repayment_schedule,
2095 &curDate, &nextDate))
2101 (gnc_numeric*)g_hash_table_lookup( repayment_schedule,
2103 if ( rowNumData == NULL)
2106 GDate *dateKeyCopy = g_date_new();
2108 *dateKeyCopy = nextDate;
2109 rowNumData = g_new0( gnc_numeric, ldd->ld.revNumPmts );
2110 g_assert( rowNumData != NULL );
2111 for ( j = 0; j < ldd->ld.revNumPmts; j++ )
2115 g_hash_table_insert( repayment_schedule,
2116 (gpointer)dateKeyCopy,
2117 (gpointer)rowNumData );
2122 ival = gnc_numeric_create( i, 1 );
2123 g_hash_table_insert( ivar, (gpointer)
"i", &ival );
2125 if ( ! gnc_exp_parser_parse_separate_vars(
2126 pmtFormula.c_str(), &val, &eloc, ivar ) )
2128 PERR(
"pmt Parsing error at %s", eloc );
2131 val = gnc_numeric_convert( val, 100, GNC_HOW_RND_ROUND_HALF_UP );
2132 rowNumData[0] = val;
2134 if ( ! gnc_exp_parser_parse_separate_vars(
2135 ppmtFormula.c_str(), &val, &eloc, ivar ) )
2137 PERR(
"ppmt Parsing error at %s", eloc );
2140 val = gnc_numeric_convert( val, 100, GNC_HOW_RND_ROUND_HALF_UP );
2141 rowNumData[1] = val;
2143 if ( ! gnc_exp_parser_parse_separate_vars(
2144 ipmtFormula.c_str(), &val, &eloc, ivar ) )
2146 PERR(
"ipmt Parsing error at %s", eloc );
2149 val = gnc_numeric_convert( val, 100, GNC_HOW_RND_ROUND_HALF_UP );
2150 rowNumData[2] = val;
2153 g_hash_table_destroy( ivar );
2159 GDate curDate, nextDate;
2162 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
2164 if ( ! ldd->ld.repayOpts[i]->enabled )
2168 = ( ldd->ld.repayOpts[i]->schedule != NULL
2169 ? ldd->ld.repayOpts[i]->schedule
2170 : ldd->ld.repayment_schedule );
2172 g_date_clear( &curDate, 1 );
2174 g_date_subtract_days( &curDate, 1 );
2175 g_date_clear(&nextDate, 1);
2176 recurrenceListNextInstance(schedule, &curDate, &nextDate );
2177 for ( ; g_date_valid( &nextDate )
2178 && g_date_compare( &nextDate, &end ) <= 0;
2180 recurrenceListNextInstance(
2181 schedule, &curDate, &nextDate ) )
2187 rowNumData = (gnc_numeric*)g_hash_table_lookup( repayment_schedule,
2189 if ( rowNumData == NULL )
2192 GDate *dateKeyCopy = g_date_new();
2194 *dateKeyCopy = nextDate;
2195 rowNumData = g_new0( gnc_numeric, ldd->ld.revNumPmts );
2196 g_assert( rowNumData != NULL );
2197 for ( j = 0; j < ldd->ld.revNumPmts; j++ )
2201 g_hash_table_insert( repayment_schedule,
2202 (gpointer)dateKeyCopy,
2203 (gpointer)rowNumData );
2210 rowNumData[ ldd->ld.revRepayOptToColMap[i] ]
2218 if ( ldd->ld.revSchedule != NULL )
2220 g_list_foreach( ldd->ld.revSchedule,
2221 loan_rev_sched_list_free,
2223 g_list_free( ldd->ld.revSchedule );
2224 ldd->ld.revSchedule = NULL;
2226 g_hash_table_foreach( repayment_schedule, loan_rev_hash_to_list,
2227 &ldd->ld.revSchedule );
2228 g_hash_table_foreach( repayment_schedule, loan_rev_hash_free_date_keys,
2230 g_hash_table_destroy( repayment_schedule );
2231 ldd->ld.revSchedule =
2232 g_list_sort( ldd->ld.revSchedule, (GCompareFunc)g_date_compare );
2241 static const gchar *NO_AMT_CELL_TEXT =
" ";
2244 GtkListStore *store;
2247 pai = gnc_default_price_print_info(NULL);
2248 pai.min_decimal_places = 2;
2250 store = GTK_LIST_STORE(gtk_tree_view_get_model( ldd->revView ));
2252 gtk_list_store_clear( store );
2254 for ( l = ldd->ld.revSchedule; l != NULL; l = l->next )
2260 if ( g_date_compare( &rrr->date, start ) < 0 )
2262 if ( g_date_compare( &rrr->date, end ) > 0 )
2265 gtk_list_store_append(store, &iter);
2268 gtk_list_store_set( store, &iter, LOAN_COL_DATE, tmpBuf, -1 );
2270 for ( i = 0; i < ldd->ld.revNumPmts; i++ )
2277 gtk_list_store_set( store, &iter,
2278 i + 1, NO_AMT_CELL_TEXT,
2284 g_assert( numPrinted < 50 );
2286 gtk_list_store_set( store, &iter,
2307gfloat loan_apr_to_simple_formula (
double rate,
double pmt_periods,
double comp_periods)
2312 simple_rate = pow(1 + (rate / comp_periods), comp_periods / pmt_periods) - 1;
2313 return (simple_rate);
2316using boost::locale::conv::utf_to_utf;
2329 int do_frac_digits()
const {
return prec; }
2334std::string to_str_with_prec (
const gdouble val)
2338 LCID lcid = GetThreadLocale();
2341 numfmt.NumDigits = prec;
2342 GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ILZERO, (LPWSTR)&numval,
2343 sizeof(numval)/
sizeof(
wchar_t));
2344 numfmt.LeadingZero = numval;
2345 wchar_t grouping[10];
2346 GetLocaleInfoW(lcid, LOCALE_SGROUPING, grouping,
2347 sizeof(grouping)/
sizeof(
wchar_t));
2348 auto semi = wcschr(grouping,
';');
2350 numfmt.Grouping = _wtoi(grouping);
2352 GetLocaleInfoW(lcid, LOCALE_SDECIMAL, decsep,
2353 sizeof(decsep)/
sizeof(
wchar_t) );
2354 numfmt.lpDecimalSep = decsep;
2356 GetLocaleInfoW(lcid, LOCALE_STHOUSAND, thousep,
2357 sizeof(thousep)/
sizeof(
wchar_t));
2358 numfmt.lpThousandSep = thousep;
2359 GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_INEGNUMBER,
2360 (LPWSTR)&numval,
sizeof(numval)/
sizeof(
wchar_t));
2361 numfmt.NegativeOrder = numval;
2363 std::wstringstream valstr;
2365 int size = GetNumberFormatW(lcid, 0, valstr.str().c_str(),
2366 &numfmt,
nullptr, 0);
2367 wchar_t* buf =
static_cast<wchar_t*
>(malloc(
sizeof(
wchar_t) * size));
2368 GetNumberFormatW(lcid, 0, valstr.str().c_str(), &numfmt, buf, size);
2369#pragma GCC diagnostic push
2370#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
2371 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,
wchar_t> conv;
2372#pragma GCC diagnostic pop
2373 std::string result = conv.to_bytes(buf);
2378 std::wstringstream valstr;
2380 valstr << std::put_money(val * pow(10, prec));
2381 return utf_to_utf<char>(valstr.str());
2385static std::tuple<double, double>
2388 double ppy = 0.0, periods = 1.0;
2389 auto recurrences = ldd->ld.repayment_schedule;
2390 for (
auto node = recurrences; node; node = g_list_next(node))
2392 auto recurrence =
static_cast<Recurrence*
>(node->data);
2393 auto period_type = recurrenceGetPeriodType(recurrence);
2394 auto multiplier = recurrenceGetMultiplier(recurrence);
2401 ppy += 1.0 / multiplier;
2404 ppy = 365 / multiplier;
2407 ppy += 52.0 / multiplier;
2410 case PERIOD_END_OF_MONTH:
2411 case PERIOD_NTH_WEEKDAY:
2412 case PERIOD_LAST_WEEKDAY:
2413 ppy += 12.0 / multiplier;
2421 auto months = (ldd->ld.numPer * (ldd->ld.perSize == GNC_MONTHS ? 1 : 12));
2422 if ((
int)(months * ppy / 12) > 1)
2423 periods = (int)(months * ppy / 12) * 1.0;
2425 return {ppy, periods};
2431 g_assert( ldd != NULL );
2433 auto [ppy, periods] = periods_per_year(ldd);
2434 gdouble pass_thru_rate = ldd->ld.interestRate / 100.0;
2437 gdouble period_rate;
2438 auto rate_case = ldd->ld.rateType;
2441 case GNC_IRATE_SIMPLE:
2442 period_rate = pass_thru_rate;
2444 case GNC_IRATE_APR_DAILY:
2445 period_rate = loan_apr_to_simple_formula (pass_thru_rate, ppy, 365);
2447 case GNC_IRATE_APR_WEEKLY:
2448 period_rate = loan_apr_to_simple_formula (pass_thru_rate, ppy, 52);
2450 case GNC_IRATE_APR_MONTHLY:
2451 period_rate = loan_apr_to_simple_formula (pass_thru_rate, ppy, 12);
2453 case GNC_IRATE_APR_QUARTERLY:
2454 period_rate = loan_apr_to_simple_formula (pass_thru_rate, ppy, 4);
2456 case GNC_IRATE_APR_SEMIANNUALLY:
2457 period_rate = loan_apr_to_simple_formula (pass_thru_rate, ppy, 2);
2459 case GNC_IRATE_APR_ANNUALLY:
2460 period_rate = loan_apr_to_simple_formula (pass_thru_rate, ppy, 1);
2463 period_rate = ldd->ld.interestRate / 100;
2466 auto period_rate_str = to_str_with_prec<5> (period_rate);
2467 auto period_base_str = to_str_with_prec<2> (ppy);
2468 auto periods_str = to_str_with_prec<2> (periods);
2469 auto principal_str = to_str_with_prec<2> (principal);
2479 std::string formula;
2480 if (rate_case == GNC_IRATE_SIMPLE)
2481 formula = (bl::format (tpl) % period_rate_str %
2482 period_base_str % periods_str % principal_str).str();
2484 formula = (bl::format (tpl) % period_rate_str % periods_str % principal_str).str();
2491 if (ldd->ld.rateType == GNC_IRATE_SIMPLE)
2492 return loan_get_formula_internal (ldd,
"pmt( {1} / {2} : {3} : {4} : 0 : 0 )");
2494 return loan_get_formula_internal (ldd,
"pmt( {1} : {2} : {3} : 0 : 0 )");
2501 if (ldd->ld.rateType == GNC_IRATE_SIMPLE)
2502 return loan_get_formula_internal (ldd,
"ppmt( {1} / {2} : i : {3} : {4} : 0 : 0 )");
2504 return loan_get_formula_internal (ldd,
"ppmt( {1} : i : {2} : {3} : 0 : 0 )");
2511 if (ldd->ld.rateType == GNC_IRATE_SIMPLE)
2512 return loan_get_formula_internal (ldd,
"ipmt( {1} / {2} : i : {3} : {4} : 0 : 0 )");
2514 return loan_get_formula_internal (ldd,
"ipmt( {1} : i : {2} : {3} : 0 : 0 )");
2520ld_calc_sx_instance_num(GDate *start_date, GList *schedule)
2523 GDate next_date, today;
2525 g_date_clear(&next_date, 1);
2526 g_date_clear(&today, 1);
2529 if (g_date_compare(start_date, &today) > 0)
2532 instance_count = -1;
2536 recurrenceListNextInstance(schedule, start_date, &next_date);
2538 while (g_date_compare(&next_date, &today) < 0);
2540 return instance_count;
2546loan_tcSX_free( gpointer data, gpointer user_data )
2549 g_free( tcSX->
name );
2564 SchedXactions *sxes;
2570 xaccSchedXactionSetStartDate( sx, &tcSX->
start );
2571 xaccSchedXactionSetLastOccurDate( sx, &tcSX->last );
2576 ttxn_vec.push_back (tcSX->
mainTxn);
2580 g_assert (!ttxn_vec.empty());
2582 xaccSchedXactionSetTemplateTrans (sx, ttxn_vec, gnc_get_current_book());
2584 sxes = gnc_book_get_schedxactions(gnc_get_current_book());
2585 gnc_sxes_add_sx(sxes, sx);
2589static TTSplitInfoPtr
2590find_account_from_template_splits (
const TTInfoPtr& txn,
const Account* account)
2592 auto& splits{txn->get_template_splits ()};
2593 auto has_acct = [account](
auto ttinfo){
return ttinfo->get_account() == account; };
2594 auto it = std::find_if (splits.begin(), splits.end(), has_acct);
2595 return it == splits.end() ? nullptr : *it;
2675 TTSplitInfoPtr fromSplit;
2676 TTSplitInfoPtr ttsi;
2679#define AMTBUF_LEN 64
2680 gchar amtBuf[AMTBUF_LEN];
2689 if ( rod->throughEscrowP && ldd->ld.escrowAcct )
2696 auto ttsi = find_account_from_template_splits (paymentSX->
mainTxn, ldd->ld.escrowAcct);
2698 gstr = g_string_new (ttsi->get_debit_formula());
2699 g_string_append_printf( gstr,
" + %s", amtBuf );
2700 ttsi->set_debit_formula (gstr->str);
2701 g_string_free( gstr, TRUE );
2706 if ( rod->from != NULL )
2713 auto ttsi = find_account_from_template_splits (tcSX->
escrowTxn, ldd->ld.escrowAcct);
2717 ttsi = std::make_shared<TTSplitInfo>();
2718 ttsi->set_memo (rod->txnMemo);
2719 ttsi->set_account (ldd->ld.escrowAcct);
2720 tcSX->
escrowTxn->append_template_split (ttsi);
2722 if ( (str = (gchar*)ttsi->get_credit_formula ())
2725 gstr = g_string_sized_new( 16 );
2732 gstr = g_string_new( str );
2733 g_string_append_printf( gstr,
" + " );
2735 g_string_append_printf( gstr,
"%s", amtBuf );
2736 ttsi->set_credit_formula (gstr->str);
2737 g_string_free( gstr, TRUE );
2744 fromSplit = find_account_from_template_splits (paymentSX->
mainTxn, ldd->ld.repFromAcct);
2745 g_assert (fromSplit);
2748 ttsi = std::make_shared<TTSplitInfo>();
2749 ttsi->set_memo (rod->txnMemo);
2750 ttsi->set_account (ldd->ld.escrowAcct);
2751 ttsi->set_credit_formula (amtBuf);
2752 tcSX->
escrowTxn->append_template_split (ttsi);
2760 if ( rod->from != NULL )
2766 fromSplit = find_account_from_template_splits (tcSX->
mainTxn, ldd->ld.repFromAcct);
2770 if ( fromSplit != NULL )
2773 gstr = g_string_new (fromSplit->get_credit_formula ());
2774 g_string_append_printf( gstr,
" + %s", amtBuf );
2775 fromSplit->set_credit_formula (gstr->str);
2776 g_string_free( gstr, TRUE );
2784 ttsi = std::make_shared<TTSplitInfo>();
2785 ttsi->set_memo (rod->txnMemo);
2786 ttsi->set_account (rod->from ? rod->from : ldd->ld.repFromAcct);
2787 ttsi->set_credit_formula (amtBuf);
2789 if ( rod->throughEscrowP )
2793 tti->append_template_split (ttsi);
2800 ttsi = std::make_shared<TTSplitInfo>();
2801 ttsi->set_memo (rod->txnMemo);
2802 ttsi->set_account (rod->to);
2803 ttsi->set_debit_formula (amtBuf);
2804 toTxn->append_template_split (ttsi);
2831 GList *repaySXes = NULL;
2836 TTSplitInfoPtr ttsi;
2839 paymentSX->
name = g_strdup(ldd->ld.repMemo);
2840 paymentSX->
start = *ldd->ld.startDate;
2841 paymentSX->last = *ldd->ld.repStartDate;
2842 g_date_subtract_months( &paymentSX->last, 1 );
2844 paymentSX->end = *ldd->ld.repStartDate;
2845 g_date_add_months( &paymentSX->end, ldd->ld.numMonRemain - 1);
2848 paymentSX->
schedule = ldd->ld.repayment_schedule;
2852 (ldd->ld.numPer * ( ldd->ld.perSize == GNC_YEARS ? 12 : 1 ))
2853 - ldd->ld.numMonRemain + 1;
2855 paymentSX->
mainTxn = std::make_shared<TTInfo>();
2859 GString *payMainTxnDesc = g_string_sized_new( 32 );
2860 g_string_printf( payMainTxnDesc,
2863 ( ldd->ld.escrowAcct == NULL
2865 :
_(
"Escrow Payment") )
2868 paymentSX->
mainTxn->set_description(payMainTxnDesc->str);
2869 g_string_free( payMainTxnDesc, TRUE );
2891 srcAcct = ldd->ld.repFromAcct;
2892 if ( ldd->ld.escrowAcct != NULL )
2894 Account *realSrcAcct = srcAcct;
2895 srcAcct = ldd->ld.escrowAcct;
2896 auto formula = loan_get_pmt_formula(ldd);
2899 ttsi = std::make_shared<TTSplitInfo>();
2900 ttsi->set_memo (ldd->ld.repMemo);
2901 ttsi->set_account (realSrcAcct);
2902 ttsi->set_credit_formula (formula.c_str());
2903 ttxn->append_template_split (ttsi);
2908 ttsi = std::make_shared<TTSplitInfo>();
2909 ttsi->set_memo (ldd->ld.repMemo);
2910 ttsi->set_account (ldd->ld.escrowAcct);
2911 ttsi->set_debit_formula (formula.c_str());
2912 ttxn->append_template_split (ttsi);
2915 paymentSX->
escrowTxn = std::make_shared<TTInfo>();
2919 GString *escrowTxnDesc;
2920 escrowTxnDesc = g_string_new( ldd->ld.repMemo );
2921 g_string_append_printf( escrowTxnDesc,
" - %s",
_(
"Payment") );
2922 paymentSX->
escrowTxn->set_description (escrowTxnDesc->str);
2923 g_string_free( escrowTxnDesc, TRUE );
2929 ttsi = std::make_shared<TTSplitInfo>();
2931 auto gstr = g_string_new( ldd->ld.repMemo );
2932 g_string_append_printf( gstr,
" - %s",
2934 ttsi->set_memo (gstr->str);
2935 g_string_free( gstr, TRUE );
2937 ttsi->set_account (srcAcct);
2938 auto formula = loan_get_pmt_formula(ldd);
2939 ttsi->set_credit_formula (formula.c_str());
2940 ttxn->append_template_split (ttsi);
2945 ttsi = std::make_shared<TTSplitInfo>();
2947 auto gstr = g_string_new( ldd->ld.repMemo );
2948 g_string_append_printf( gstr,
" - %s",
2950 ttsi->set_memo (gstr->str);
2951 g_string_free( gstr, TRUE );
2953 ttsi->set_account (ldd->ld.repPriAcct);
2954 auto formula = loan_get_ppmt_formula(ldd);
2955 ttsi->set_debit_formula (formula.c_str());
2956 ttxn->append_template_split (ttsi);
2961 ttsi = std::make_shared<TTSplitInfo>();
2963 auto gstr = g_string_new( ldd->ld.repMemo );
2964 g_string_append_printf( gstr,
" - %s",
2966 ttsi->set_memo (gstr->str);
2967 g_string_free( gstr, TRUE );
2969 ttsi->set_account (ldd->ld.repIntAcct);
2970 auto formula = loan_get_ipmt_formula(ldd);
2971 ttsi->set_debit_formula (formula.c_str());
2972 ttxn->append_template_split (ttsi);
2976 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
2979 if ( ! rod->enabled )
2983 if ( rod->schedule != NULL )
2986 auto gstr = g_string_new( ldd->ld.repMemo );
2987 g_string_append_printf( gstr,
" - %s",
2989 tcSX->
name = g_strdup(gstr->str);
2990 tcSX->
start = *ldd->ld.startDate;
2991 tcSX->last = *ldd->ld.repStartDate;
2993 tcSX->end = tcSX->last;
2994 g_date_add_months( &tcSX->end, ldd->ld.numMonRemain );
3000 ld_calc_sx_instance_num(&tcSX->
start, rod->schedule);
3001 rod->schedule = NULL;
3002 tcSX->
mainTxn = std::make_shared<TTInfo>();
3004 tcSX->
mainTxn->set_description (gstr->str);
3005 tcSX->
escrowTxn = std::make_shared<TTInfo>();
3007 tcSX->
escrowTxn->set_description(gstr->str);
3009 g_string_free( gstr, TRUE );
3010 repaySXes = g_list_prepend (repaySXes, tcSX);
3015 ld_setup_repayment_sx( ldd, rod, paymentSX, tcSX );
3018 repaySXes = g_list_reverse (repaySXes);
3023 loan_create_sx_from_tcSX( ldd, paymentSX );
3025 for ( l = repaySXes; l; l = l->next )
3027 loan_create_sx_from_tcSX( ldd, (
toCreateSX*)l->data );
3031 loan_tcSX_free( paymentSX, NULL );
3032 g_list_foreach( repaySXes, loan_tcSX_free, NULL );
3033 g_list_free( repaySXes );
3039loan_assistant_finish ( GtkAssistant *gtkassistant, gpointer user_data )
3042 loan_create_sxes( ldd );
3048loan_assistant_cancel( GtkAssistant *gtkassistant, gpointer user_data )
3051 gnc_close_gui_component_by_data( DIALOG_LOAN_ASSISTANT_CM_CLASS, ldd );
3056loan_assistant_close( GtkAssistant *gtkassistant, gpointer user_data )
3059 gnc_close_gui_component_by_data( DIALOG_LOAN_ASSISTANT_CM_CLASS, ldd );
3064loan_assistant_prepare (GtkAssistant *assistant, GtkWidget *page,
3067 gint currentpage = gtk_assistant_get_current_page(assistant);
3069 switch (currentpage)
3073 loan_info_prep (assistant, user_data);
3077 loan_opt_prep (assistant, user_data);
3081 loan_rep_prep (assistant, user_data);
3085 loan_pay_prep (assistant, user_data);
3089 loan_rev_prep (assistant, user_data);
3101gnc_ui_sx_loan_assistant_create (
void)
3108 gnc_loan_assistant_create (ldd);
3110 component_id = gnc_register_gui_component (DIALOG_LOAN_ASSISTANT_CM_CLASS,
3111 NULL, loan_assistant_close_handler,
3114 gnc_gui_component_watch_entity_type (component_id,
3116 QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
3118 gtk_widget_show_all (ldd->window);
3120 gnc_window_adjust_for_screen (GTK_WINDOW(ldd->window));
Account handling public routines.
Anchor Scheduled Transaction info in a book.
Scheduled Transactions public handling routines.
Date and Time handling routines.
All type declarations for the whole Gnucash engine.
utility functions for the GnuCash UI
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed.
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity
@ ACCT_TYPE_EXPENSE
Expense accounts are used to denote expenses.
@ ACCT_TYPE_BANK
The bank account type denotes a savings or checking account held at a bank.
@ ACCT_TYPE_ASSET
asset (and liability) accounts indicate generic, generalized accounts that are none of the above.
@ ACCT_TYPE_CASH
The cash account type is used to denote a shoe-box or pillowcase stuffed with * cash.
@ ACCT_TYPE_LIABILITY
liability (and asset) accounts indicate generic, generalized accounts that are none of the above.
@ ACCT_TYPE_CREDIT
The Credit card account is used to denote credit (e.g.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
time64 gnc_mktime(struct tm *time)
calculate seconds from the epoch given a time struct
gboolean gnc_gdate_equal(gconstpointer gda, gconstpointer gdb)
Compares two GDate*'s for equality; useful for using GDate*'s as GHashTable keys.
#define MAX_DATE_LENGTH
The maximum length of a string created by the date printers.
void gnc_gdate_set_time64(GDate *gd, time64 time)
Set a GDate to a time64.
guint gnc_gdate_hash(gconstpointer gd)
Provides a "hash" of a GDate* value; useful for using GDate*'s as GHashTable keys.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
void gnc_tm_free(struct tm *time)
free a struct tm* created with gnc_localtime() or gnc_gmtime()
time64 gnc_time(time64 *tbuf)
get the current time
struct tm * gnc_localtime(const time64 *secs)
fill out a time struct from a 64-bit time value.
size_t qof_print_gdate(char *buf, size_t len, const GDate *gd)
Convenience; calls through to qof_print_date_dmy_buff().
int xaccSPrintAmount(char *bufp, gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
#define DEBUG(format, args...)
Print a debugging message.
#define PERR(format, args...)
Log a serious error.
double gnc_numeric_to_double(gnc_numeric in)
Convert numeric to floating-point value.
gnc_numeric double_to_gnc_numeric(double in, gint64 denom, gint how)
Convert a floating-point number to a gnc_numeric.
gnc_numeric gnc_numeric_error(GNCNumericErrorCode error_code)
Create a gnc_numeric object that signals the error condition noted by error_code, rather than a numbe...
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.
#define GNC_HOW_DENOM_SIGFIGS(n)
Build a 'how' value that will generate a denominator that will keep at least n significant figures in...
@ GNC_ERROR_ARG
Argument is not a valid number.
@ GNC_HOW_RND_ROUND_HALF_UP
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
void gnc_sx_set_schedule(SchedXaction *sx, GList *schedule)
SchedXaction * xaccSchedXactionMalloc(QofBook *book)
Creates and initializes a scheduled transaction.
void xaccSchedXactionSetName(SchedXaction *sx, const gchar *newName)
A copy of the name is made.
void xaccSchedXactionSetEndDate(SchedXaction *sx, const GDate *newEnd)
Set to an invalid GDate to turn off 'end-date' definition.
void gnc_sx_set_instance_count(SchedXaction *sx, gint instance_num)
Sets the instance count to something other than the default.
The UI-side storage of the loan assistant data.
Data about a loan repayment.
The default repayment options data.
The data relating to a single "repayment option" – a potential [sub-]transaction in the repayment.
The UI-side storage of the repayment options.
A transient struct used to collate the GDate and the gnc_numeric row-data for the repayment review sc...
A transient structure to contain SX details during the creation process.
TTInfoPtr mainTxn
The main/source transaction being created.
gint instNum
The current 'instance-num' count.
TTInfoPtr escrowTxn
The optional escrow transaction being created.
GDate start
The start, last-occurred and end dates.
gchar * name
The name of the SX.
GList * schedule
The SX schedule.