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> 64 namespace bl = boost::locale;
66 #define DIALOG_LOAN_ASSISTANT_CM_CLASS "assistant-loan-setup" 68 static QofLogModule log_module = GNC_MOD_ASSISTANT;
87 struct LoanAssistantData_;
93 typedef struct RepayOptData_
101 gboolean throughEscrowP;
102 gboolean specSrcAcctP;
115 typedef 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 },
137 typedef 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
181 typedef struct rev_repayment_row
184 gnc_numeric *numCells;
190 typedef struct LoanData_
193 gnc_numeric principal;
197 GList *loan_schedule;
205 std::string repAmount;
210 GList *repayment_schedule;
218 int revRepayOptToColMap[ (
sizeof(REPAY_DEFAULTS)
227 typedef 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;
303 typedef struct toCreateSX_
321 static void loan_assistant_window_destroy_cb( GtkWidget *
object, gpointer user_data );
322 static void loan_assistant_close_handler( gpointer user_data );
325 static void loan_info_prep( GtkAssistant *assistant, gpointer user_data );
326 static void loan_info_prm_type_cb( GtkWidget *w, gpointer user_data );
327 static void loan_info_calc_update_cb( GtkWidget *widget, gpointer user_data );
328 void loan_info_page_valid_cb( GtkWidget *widget, gpointer user_data );
329 static gboolean loan_info_page_complete( GtkAssistant *assistant, gpointer user_data );
330 static void loan_info_page_save( GtkAssistant *assistant, gpointer user_data );
332 static void loan_opt_prep( GtkAssistant *assistant, gpointer user_data );
333 static void loan_opt_toggled_cb( GtkToggleButton *tb, gpointer user_data );
334 static void loan_opt_consistency_cb( GtkToggleButton *tb, gpointer user_data );
335 static void loan_opt_escrow_toggle_cb( GtkToggleButton *tb, gpointer user_data );
336 static void loan_opt_escrow_toggled_cb( GtkToggleButton *tb, gpointer user_data );
337 void loan_opt_page_valid_cb (GtkWidget *widget, gpointer user_data );
338 static gboolean loan_opt_page_complete( GtkAssistant *assistant, gpointer user_data );
340 static void loan_rep_prep ( GtkAssistant *assistant, gpointer user_data );
341 void loan_rep_page_valid_cb (GtkWidget *widget, gpointer user_data );
342 static gboolean loan_rep_page_complete( GtkAssistant *assistant, gpointer user_data );
343 static void loan_rep_page_save( GtkAssistant *assistant, gpointer user_data );
345 static void loan_pay_prep ( GtkAssistant *assistant, gpointer user_data );
347 static void loan_pay_use_esc_toggle_cb( GtkToggleButton *tb, gpointer user_data );
348 static void loan_pay_spec_src_setup(
LoanAssistantData *ldd, gboolean newState );
349 static void loan_pay_spec_src_toggle_cb( GtkToggleButton *tb, gpointer user_data );
350 static void loan_pay_freq_toggle_cb( GtkToggleButton *tb, gpointer user_data );
351 static void loan_pay_page_valid_cb (GtkWidget *widget, gpointer user_data );
352 static gboolean loan_pay_complete( GtkAssistant *assistant, gpointer user_data );
353 static gboolean loan_pay_all_opt_valid ( GtkAssistant *assistant, gpointer user_data );
354 static void loan_pay_back_button_cb( GtkButton *button, gpointer user_data );
355 static void loan_pay_next_button_cb( GtkButton *button, gpointer user_data );
357 static void loan_rev_prep ( GtkAssistant *assistant, gpointer user_data );
359 static void loan_rev_range_opt_changed_cb( GtkComboBox *combo, gpointer user_data );
360 static void loan_rev_range_changed_cb(
GNCDateEdit *gde, gpointer user_data );
361 static void loan_rev_get_loan_range(
LoanAssistantData *ldd, GDate *start, GDate *end );
362 static void loan_rev_get_dates(
LoanAssistantData *ldd, GDate *start, GDate *end );
363 static void loan_rev_update_view(
LoanAssistantData *ldd, GDate *start, GDate *end );
364 static void loan_rev_sched_list_free( gpointer data, gpointer user_data );
365 static void loan_rev_hash_to_list( gpointer key, gpointer val, gpointer user_data );
366 static void loan_rev_hash_free_date_keys( gpointer key, gpointer val, gpointer user_data );
371 static float loan_apr_to_simple_formula (
double rate,
double pmt_periods,
double comp_periods);
375 static void loan_tcSX_free( gpointer data, gpointer user_data );
378 void loan_assistant_prepare( GtkAssistant *assistant, GtkWidget *page, gpointer user_data );
379 void loan_assistant_finish( GtkAssistant *gtkassistant, gpointer user_data );
380 void loan_assistant_cancel( GtkAssistant *gtkassistant, gpointer user_data );
381 void loan_assistant_close( GtkAssistant *gtkassistant, gpointer user_data );
389 loan_assistant_close_handler( gpointer user_data )
392 gtk_widget_destroy( ldd->window );
398 loan_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,
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;
958 loan_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 );
998 loan_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 );
1011 loan_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 );
1028 gchar *valueStr = gtk_editable_get_chars( GTK_EDITABLE(ldd->prmLengthSpin),
1030 totalVal = strtol( valueStr, NULL, 10 );
1034 * ( gtk_combo_box_get_active( ldd->prmLengthType )
1037 gtk_spin_button_set_value( ldd->prmRemainSpin, remain );
1038 gtk_widget_show( GTK_WIDGET(ldd->prmRemainSpin) );
1043 loan_info_page_valid_cb (GtkWidget *widget, gpointer user_data )
1046 GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
1047 gint num = gtk_assistant_get_current_page (assistant);
1048 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1050 gtk_assistant_set_page_complete (assistant, page,
1051 loan_info_page_complete (assistant, ldd));
1057 loan_info_page_complete( GtkAssistant *assistant, gpointer user_data )
1061 gnc_commodity *currency;
1065 ldd->ld.primaryAcct = gnc_account_sel_get_account( ldd->prmAccountGAS );
1067 if ( ldd->ld.primaryAcct == NULL )
1072 print_info = gnc_commodity_print_info (currency, FALSE);
1073 gnc_amount_edit_set_print_info (GNC_AMOUNT_EDIT(ldd->prmOrigPrincGAE), print_info);
1074 gnc_amount_edit_set_fraction (GNC_AMOUNT_EDIT(ldd->prmOrigPrincGAE),
1077 result = gnc_amount_edit_expr_is_valid (GNC_AMOUNT_EDIT(ldd->prmOrigPrincGAE),
1078 &value, FALSE,
nullptr);
1088 loan_info_page_save( GtkAssistant *assistant, gpointer user_data )
1092 ldd->ld.primaryAcct = gnc_account_sel_get_account( ldd->prmAccountGAS );
1094 if ( ! ldd->ld.repPriAcct )
1096 ldd->ld.repPriAcct = ldd->ld.primaryAcct;
1098 ldd->ld.principal = gnc_amount_edit_get_amount( ldd->prmOrigPrincGAE );
1099 ldd->ld.interestRate = gtk_spin_button_get_value( ldd->prmIrateSpin );
1100 ldd->ld.rateType =
static_cast<IRateType
>( gtk_combo_box_get_active (ldd->prmIrateType ));
1101 ldd->ld.type =
static_cast<LoanType
>( gtk_combo_box_get_active( ldd->prmType ));
1103 if ( ldd->ld.type != GNC_FIXED )
1105 recurrenceListFree(&ldd->ld.loan_schedule);
1106 gnc_frequency_save_to_recurrence(ldd->prmVarGncFreq,
1107 &ldd->ld.loan_schedule,
1108 ldd->ld.varStartDate);
1116 tmpTT = gnc_date_edit_get_date( ldd->prmStartDateGDE );
1120 g_date_set_dmy( ldd->ld.startDate,
1122 static_cast<GDateMonth>(tmpTm->tm_mon + 1),
1123 (1900 + tmpTm->tm_year) );
1131 (gtk_combo_box_get_active( ldd->prmLengthType )
1132 == GNC_MONTHS) ? GNC_MONTHS : GNC_YEARS;
1134 gtk_spin_button_get_value_as_int( ldd->prmLengthSpin );
1135 ldd->ld.numMonRemain =
1136 gtk_spin_button_get_value_as_int( ldd->prmRemainSpin );
1144 loan_opt_prep( GtkAssistant *assistant, gpointer user_data )
1151 loan_info_page_save(assistant, ldd);
1153 if ( ldd->ld.escrowAcct )
1155 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->optEscrowCb), TRUE );
1156 gnc_account_sel_set_account( ldd->optEscrowGAS, ldd->ld.escrowAcct, FALSE );
1158 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
1160 rouid = ldd->repayOptsUI[i];
1161 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(rouid->optCb),
1162 rouid->optData->enabled );
1163 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(rouid->escrowCb),
1164 rouid->optData->throughEscrowP
1165 && rouid->optData->enabled
1166 && ldd->ld.escrowAcct );
1167 gtk_widget_set_sensitive( GTK_WIDGET(rouid->escrowCb),
1168 rouid->optData->enabled
1169 && ldd->ld.escrowAcct );
1176 loan_opt_toggled_cb( GtkToggleButton *tb, gpointer user_data )
1181 rouid->optData->enabled = gtk_toggle_button_get_active(tb);
1187 loan_opt_consistency_cb( GtkToggleButton *tb, gpointer user_data )
1189 GtkToggleButton *escrowCb;
1193 escrowCb = GTK_TOGGLE_BUTTON(rouid->escrowCb);
1195 gtk_toggle_button_set_active( escrowCb,
1196 gtk_toggle_button_get_active(
1198 rouid->ldd->optEscrowCb) )
1199 && rouid->optData->throughEscrowP
1200 && gtk_toggle_button_get_active(tb) );
1203 gtk_widget_set_sensitive( GTK_WIDGET(escrowCb),
1204 gtk_toggle_button_get_active(tb)
1205 && gtk_toggle_button_get_active(
1206 GTK_TOGGLE_BUTTON(rouid->ldd->optEscrowCb)) );
1212 loan_opt_escrow_toggle_cb( GtkToggleButton *tb, gpointer user_data )
1218 GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
1219 gint num = gtk_assistant_get_current_page (assistant);
1220 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1222 newState = gtk_toggle_button_get_active(tb);
1223 gtk_widget_set_sensitive( GTK_WIDGET(ldd->optEscrowHBox), newState );
1227 if (GNC_ACCOUNT_SEL( ldd->ld.escrowAcct) == NULL)
1228 gtk_assistant_set_page_complete (assistant, page, FALSE);
1232 ldd->ld.escrowAcct = NULL;
1233 gnc_account_sel_set_account( GNC_ACCOUNT_SEL( ldd->optEscrowGAS), NULL , FALSE );
1234 gtk_assistant_set_page_complete (assistant, page, TRUE);
1239 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
1241 rouid = ldd->repayOptsUI[i];
1247 g_signal_handlers_block_by_func( rouid->escrowCb,
1248 (gpointer) loan_opt_escrow_toggled_cb,
1250 gtk_toggle_button_set_active(
1251 GTK_TOGGLE_BUTTON(rouid->escrowCb),
1253 && gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(rouid->optCb) )
1254 && rouid->optData->throughEscrowP ) );
1255 gtk_widget_set_sensitive(
1256 GTK_WIDGET(rouid->escrowCb),
1258 && gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(rouid->optCb) ) );
1259 g_signal_handlers_unblock_by_func( rouid->escrowCb,
1260 (gpointer) loan_opt_escrow_toggled_cb,
1264 rouid->optData->from = ldd->ld.escrowAcct;
1268 rouid->optData->from = NULL;
1276 loan_opt_escrow_toggled_cb( GtkToggleButton *tb, gpointer user_data )
1281 rouid->optData->throughEscrowP = gtk_toggle_button_get_active( tb );
1286 loan_opt_page_valid_cb (GtkWidget *widget, gpointer user_data )
1290 GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
1291 gint num = gtk_assistant_get_current_page (assistant);
1292 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1294 gtk_assistant_set_page_complete (assistant, page,
1295 loan_opt_page_complete (assistant, ldd));
1301 loan_opt_page_complete( GtkAssistant *assistant, gpointer user_data )
1305 if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(ldd->optEscrowCb) ) )
1307 ldd->ld.escrowAcct =
1308 gnc_account_sel_get_account( ldd->optEscrowGAS );
1310 if ( ldd->ld.escrowAcct == NULL )
1315 ldd->ld.escrowAcct = NULL;
1323 update_repayment_formula_cb(GtkWidget *widget, gpointer user_data)
1327 recurrenceListFree(&ldd->ld.repayment_schedule);
1328 gnc_frequency_save_to_recurrence(ldd->repGncFreq,
1329 &ldd->ld.repayment_schedule,
1330 ldd->ld.repStartDate);
1332 ldd->ld.repAmount = loan_get_pmt_formula(ldd);
1333 if (!ldd->ld.repAmount.empty() )
1334 gtk_entry_set_text(ldd->repAmtEntry, ldd->ld.repAmount.c_str());
1339 loan_rep_prep( GtkAssistant *assistant, gpointer user_data )
1342 static gulong date_changed_handler_id = 0;
1344 if (date_changed_handler_id)
1346 g_signal_handler_disconnect(ldd->repGncFreq, date_changed_handler_id);
1347 date_changed_handler_id = 0;
1350 ldd->ld.repAmount = loan_get_pmt_formula(ldd);
1352 if ( ldd->ld.repMemo )
1353 gtk_entry_set_text( ldd->repTxnName, ldd->ld.repMemo );
1355 if (!ldd->ld.repAmount.empty() )
1356 gtk_entry_set_text(ldd->repAmtEntry, ldd->ld.repAmount.c_str());
1358 gnc_account_sel_set_account( ldd->repAssetsFromGAS, ldd->ld.repFromAcct, FALSE );
1359 gnc_account_sel_set_account( ldd->repPrincToGAS, ldd->ld.repPriAcct, FALSE );
1360 gnc_account_sel_set_account( ldd->repIntToGAS, ldd->ld.repIntAcct, FALSE );
1362 g_signal_handlers_block_by_func( ldd->repGncFreq,
1363 (gpointer) loan_rep_page_valid_cb, ldd );
1364 gnc_frequency_setup_recurrence(ldd->repGncFreq, ldd->ld.repayment_schedule,
1365 ldd->ld.repStartDate);
1366 date_changed_handler_id = g_signal_connect (ldd->repGncFreq,
"changed",
1367 G_CALLBACK (update_repayment_formula_cb), ldd);
1368 g_signal_handlers_unblock_by_func( ldd->repGncFreq,
1369 (gpointer) loan_rep_page_valid_cb, ldd );
1375 (i < ldd->ld.repayOptCount)
1376 && !ldd->ld.repayOpts[i]->enabled;
1379 if ( i < ldd->ld.repayOptCount )
1380 ldd->currentIdx = i;
1382 ldd->currentIdx = -1;
1388 loan_rep_page_valid_cb (GtkWidget *widget, gpointer user_data )
1391 GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
1392 gint num = gtk_assistant_get_current_page (assistant);
1393 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1395 gtk_assistant_set_page_complete (assistant, page,
1396 loan_rep_page_complete (assistant, ldd));
1402 loan_rep_page_complete( GtkAssistant *assistant, gpointer user_data )
1406 ldd->ld.repFromAcct =
1407 gnc_account_sel_get_account( ldd->repAssetsFromGAS );
1409 if ( ldd->ld.repFromAcct == NULL )
1412 ldd->ld.repPriAcct =
1413 gnc_account_sel_get_account( ldd->repPrincToGAS );
1415 if ( ldd->ld.repPriAcct == NULL )
1418 ldd->ld.repIntAcct =
1419 gnc_account_sel_get_account( ldd->repIntToGAS );
1421 if ( ldd->ld.repIntAcct == NULL )
1430 loan_rep_page_save( GtkAssistant *assistant, gpointer user_data )
1434 if ( ldd->ld.repMemo )
1435 g_free( ldd->ld.repMemo );
1437 gtk_editable_get_chars( GTK_EDITABLE(ldd->repTxnName), 0, -1 );
1440 ldd->ld.repAmount.replace(0, ldd->ld.repAmount.size(),
1441 gtk_editable_get_chars(GTK_EDITABLE(ldd->repAmtEntry), 0, -1));
1443 ldd->ld.repFromAcct =
1444 gnc_account_sel_get_account( ldd->repAssetsFromGAS );
1446 ldd->ld.repPriAcct =
1447 gnc_account_sel_get_account( ldd->repPrincToGAS );
1449 ldd->ld.repIntAcct =
1450 gnc_account_sel_get_account( ldd->repIntToGAS );
1457 loan_pay_prep( GtkAssistant *assistant, gpointer user_data )
1464 gint num = gtk_assistant_get_current_page (assistant);
1465 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1468 loan_rep_page_save(assistant, ldd);
1471 if (ldd->currentIdx == -1 )
1473 gtk_assistant_set_current_page (assistant, num + 1);
1477 g_assert( ldd->currentIdx >= 0 );
1478 g_assert( ldd->currentIdx <= ldd->ld.repayOptCount );
1480 rod = ldd->ld.repayOpts[ldd->currentIdx];
1481 str = g_string_sized_new( 32 );
1483 g_string_printf( str, _(
"Loan Repayment Option: \"%s\""), rod->name );
1484 gtk_assistant_set_page_title (assistant, page, str->str );
1487 gtk_entry_set_text( ldd->payTxnName, rod->txnMemo );
1488 g_string_printf( str,
"%0.2f", rod->amount );
1489 gtk_entry_set_text( ldd->payAmtEntry, str->str );
1491 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payUseEscrow),
1492 (ldd->ld.escrowAcct != NULL) );
1495 g_signal_handlers_block_by_func( ldd->payUseEscrow,
1496 (gpointer) loan_pay_use_esc_toggle_cb,
1499 loan_pay_use_esc_setup( ldd,
1500 (ldd->ld.escrowAcct != NULL)
1501 && rod->throughEscrowP );
1502 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payUseEscrow),
1503 (rod->throughEscrowP
1504 && ldd->ld.escrowAcct != NULL) );
1506 g_signal_handlers_unblock_by_func( ldd->payUseEscrow,
1507 (gpointer) loan_pay_use_esc_toggle_cb,
1512 g_signal_handlers_block_by_func( ldd->paySpecSrcAcct,
1513 (gpointer) loan_pay_spec_src_toggle_cb,
1515 loan_pay_spec_src_setup( ldd, rod->specSrcAcctP );
1516 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->paySpecSrcAcct),
1517 rod->specSrcAcctP );
1519 g_signal_handlers_unblock_by_func( ldd->paySpecSrcAcct,
1520 (gpointer) loan_pay_spec_src_toggle_cb,
1524 g_signal_handlers_block_by_func(ldd->payAcctToGAS,
1525 (gpointer) loan_pay_page_valid_cb, ldd );
1526 gnc_account_sel_set_account( ldd->payAcctToGAS, rod->to, FALSE );
1527 g_signal_handlers_unblock_by_func(ldd->payAcctToGAS,
1528 (gpointer) loan_pay_page_valid_cb, ldd );
1531 g_signal_handlers_block_by_func(ldd->payTxnFreqUniqRb,
1532 (gpointer) loan_pay_freq_toggle_cb, ldd );
1533 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqPartRb), !rod->FreqUniq );
1534 gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqUniqRb), rod->FreqUniq );
1535 g_signal_handlers_unblock_by_func(ldd->payTxnFreqUniqRb,
1536 (gpointer) loan_pay_freq_toggle_cb, ldd );
1538 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payFreqHBox), rod->FreqUniq );
1540 if ( rod->FreqUniq )
1542 g_signal_handlers_disconnect_by_func( ldd->payGncFreq,
1543 (gpointer) loan_pay_page_valid_cb, ldd );
1544 gtk_container_remove( GTK_CONTAINER(ldd->payFreqHBox), GTK_WIDGET(ldd->payGncFreq) );
1545 ldd->payGncFreq = NULL;
1546 ldd->payGncFreq = GNC_FREQUENCY(gnc_frequency_new_from_recurrence( rod->schedule, rod->startDate ));
1547 gtk_container_add( GTK_CONTAINER(ldd->payFreqHBox), GTK_WIDGET(ldd->payGncFreq) );
1548 g_signal_connect (ldd->payGncFreq,
"changed",
1549 G_CALLBACK (loan_pay_page_valid_cb), ldd);
1551 g_string_free( str, TRUE );
1552 loan_pay_page_valid_cb(GTK_WIDGET(ldd->window), ldd);
1558 loan_pay_page_valid_cb (GtkWidget *widget, gpointer user_data )
1561 GtkAssistant *assistant = GTK_ASSISTANT(ldd->window);
1562 gint num = gtk_assistant_get_current_page (assistant);
1563 GtkWidget *page = gtk_assistant_get_nth_page (assistant, num);
1565 gtk_assistant_set_page_complete (assistant, page,
1566 ( loan_pay_complete (assistant, ldd) &&
1567 loan_pay_all_opt_valid (assistant, ldd )));
1575 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payEscToLabel), newState );
1576 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payEscFromLabel), newState );
1579 g_signal_handlers_block_by_func( ldd->payAcctEscToGAS,
1580 (gpointer) loan_pay_page_valid_cb, ldd );
1581 g_signal_handlers_block_by_func( ldd->payAcctEscFromGAS,
1582 (gpointer) loan_pay_page_valid_cb, ldd );
1583 gnc_account_sel_set_account( ldd->payAcctEscToGAS, ldd->ld.escrowAcct, FALSE );
1584 gnc_account_sel_set_account( ldd->payAcctEscFromGAS, ldd->ld.escrowAcct, FALSE );
1585 g_signal_handlers_unblock_by_func( ldd->payAcctEscToGAS,
1586 (gpointer) loan_pay_page_valid_cb, ldd );
1587 g_signal_handlers_unblock_by_func( ldd->payAcctEscFromGAS,
1588 (gpointer) loan_pay_page_valid_cb, ldd );
1595 loan_pay_use_esc_toggle_cb( GtkToggleButton *tb, gpointer user_data )
1600 newState = gtk_toggle_button_get_active( tb );
1601 loan_pay_use_esc_setup( ldd, newState );
1609 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctFromLabel), newState );
1610 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payAcctFromGAS), newState );
1613 g_signal_handlers_block_by_func( ldd->payAcctFromGAS,
1614 (gpointer) loan_pay_page_valid_cb, ldd );
1615 gnc_account_sel_set_account( ldd->payAcctFromGAS, ldd->ld.repayOpts[ldd->currentIdx]->from, FALSE );
1616 g_signal_handlers_unblock_by_func( ldd->payAcctFromGAS,
1617 (gpointer) loan_pay_page_valid_cb, ldd );
1621 g_signal_handlers_block_by_func( ldd->payAcctFromGAS,
1622 (gpointer) loan_pay_page_valid_cb, ldd );
1623 gnc_account_sel_set_account( ldd->payAcctFromGAS, NULL, FALSE );
1624 ldd->ld.repayOpts[ldd->currentIdx]->from = NULL;
1625 g_signal_handlers_unblock_by_func( ldd->payAcctFromGAS,
1626 (gpointer) loan_pay_page_valid_cb, ldd );
1633 loan_pay_spec_src_toggle_cb( GtkToggleButton *tb, gpointer user_data )
1638 newState = gtk_toggle_button_get_active( tb );
1639 loan_pay_spec_src_setup( ldd, newState );
1645 loan_pay_freq_toggle_cb( GtkToggleButton *tb, gpointer user_data )
1650 g_assert( ldd->currentIdx >= 0 );
1651 g_assert( ldd->currentIdx <= ldd->ld.repayOptCount );
1653 rod = ldd->ld.repayOpts[ldd->currentIdx];
1655 rod->FreqUniq = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(ldd->payTxnFreqUniqRb) );
1656 gtk_widget_set_sensitive( GTK_WIDGET(ldd->payFreqHBox), rod->FreqUniq );
1658 if ( rod->FreqUniq )
1660 if ( rod->schedule == NULL )
1664 recurrenceSet(r, 1, PERIOD_MONTH, ldd->ld.startDate, WEEKEND_ADJ_NONE);
1665 rod->schedule = g_list_append(rod->schedule, r);
1667 if ( rod->startDate == NULL )
1669 rod->startDate = g_date_new();
1670 *rod->startDate = *ldd->ld.startDate;
1672 g_signal_handlers_block_by_func( ldd->payGncFreq,
1673 (gpointer) loan_pay_page_valid_cb, ldd );
1674 gnc_frequency_setup_recurrence(ldd->payGncFreq, rod->schedule, rod->startDate);
1675 g_signal_handlers_unblock_by_func( ldd->payGncFreq,
1676 (gpointer) loan_pay_page_valid_cb, ldd );
1682 recurrenceListFree(&rod->schedule);
1684 if ( rod->startDate )
1686 g_date_free( rod->startDate );
1687 rod->startDate = NULL;
1695 loan_pay_next_button_cb( GtkButton *button, gpointer user_data )
1701 if ( loan_pay_complete ( GTK_ASSISTANT(ldd->window), user_data ) != FALSE )
1704 for ( i = ldd->currentIdx + 1;
1705 (i < ldd->ld.repayOptCount)
1706 && !ldd->ld.repayOpts[i]->enabled; i++ )
1708 if ( i < ldd->ld.repayOptCount )
1710 ldd->currentIdx = i;
1711 loan_pay_prep( GTK_ASSISTANT(ldd->window), user_data );
1719 loan_pay_back_button_cb( GtkButton *button, gpointer user_data )
1725 if ( loan_pay_complete ( GTK_ASSISTANT(ldd->window), user_data ) != FALSE)
1728 for ( i = ldd->currentIdx - 1;
1729 (i > -1) && !ldd->ld.repayOpts[i]->enabled;
1734 ldd->currentIdx = i;
1735 loan_pay_prep( GTK_ASSISTANT(ldd->window), user_data );
1743 loan_pay_all_opt_valid ( GtkAssistant *assistant, gpointer user_data )
1751 for ( i = 0; (i < ldd->ld.repayOptCount); i++ )
1753 if (ldd->ld.repayOpts[i]->enabled)
1755 if (ldd->ld.repayOpts[i]->optValid)
1767 loan_pay_complete( GtkAssistant *assistant, gpointer user_data )
1773 g_assert( ldd->currentIdx >= 0 );
1774 g_assert( ldd->currentIdx <= ldd->ld.repayOptCount );
1775 rod = ldd->ld.repayOpts[ ldd->currentIdx ];
1777 tmpStr = gtk_editable_get_chars( GTK_EDITABLE(ldd->payTxnName),
1779 if ( rod->txnMemo != NULL )
1781 g_free( rod->txnMemo );
1783 rod->txnMemo = tmpStr;
1786 tmpStr = gtk_editable_get_chars( GTK_EDITABLE(ldd->payAmtEntry),
1788 rod->amount = (float)strtod( tmpStr, NULL );
1792 gtk_toggle_button_get_active(
1793 GTK_TOGGLE_BUTTON(ldd->paySpecSrcAcct) );
1796 if ( rod->specSrcAcctP )
1798 rod->from = gnc_account_sel_get_account( ldd->payAcctFromGAS );
1799 if ( rod->from == NULL )
1804 rod->to = gnc_account_sel_get_account( ldd->payAcctToGAS );
1805 if ( rod->to == NULL )
1809 rod->optValid = TRUE;
1812 if ( rod->FreqUniq )
1814 if ( rod->startDate == NULL )
1816 rod->startDate = g_date_new();
1818 recurrenceListFree(&rod->schedule);
1819 gnc_frequency_save_to_recurrence(ldd->payGncFreq, &rod->schedule, rod->startDate);
1821 if (! rod->schedule )
1833 loan_rev_prep( GtkAssistant *assistant, gpointer user_data )
1836 static const int BASE_COLS = 3;
1838 GtkListStore *store;
1839 GtkCellRenderer *renderer;
1840 GtkTreeViewColumn *column;
1846 if (ldd->currentIdx != -1)
1847 loan_pay_complete(assistant, ldd);
1850 if ( ldd->revView != NULL )
1852 gtk_widget_destroy( GTK_WIDGET(ldd->revView) );
1853 ldd->revView = NULL;
1856 ldd->ld.revNumPmts = BASE_COLS;
1858 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
1860 ldd->ld.revRepayOptToColMap[i] = -1;
1861 if ( ! ldd->ld.repayOpts[i]->enabled )
1867 ldd->ld.revRepayOptToColMap[i] = ldd->ld.revNumPmts;
1868 ldd->ld.revNumPmts += 1;
1871 types = g_new( GType, ldd->ld.revNumPmts + 1 );
1872 for ( i = 0; i < ldd->ld.revNumPmts + 1; i++ )
1873 types[i] = G_TYPE_STRING;
1874 store = gtk_list_store_newv(ldd->ld.revNumPmts + 1, types);
1877 ldd->revView = GTK_TREE_VIEW(
1878 gtk_tree_view_new_with_model( GTK_TREE_MODEL(store) ));
1879 g_object_unref(store);
1882 gtk_tree_view_set_grid_lines (GTK_TREE_VIEW(ldd->revView), gnc_tree_view_get_grid_lines_pref ());
1884 renderer = gtk_cell_renderer_text_new();
1885 column = gtk_tree_view_column_new_with_attributes(_(
"Date"), renderer,
1886 "text", LOAN_COL_DATE,
1888 gtk_tree_view_append_column(ldd->revView, column);
1890 renderer = gtk_cell_renderer_text_new();
1891 column = gtk_tree_view_column_new_with_attributes(_(
"Payment"), renderer,
1892 "text", LOAN_COL_PAYMENT,
1894 gtk_tree_view_append_column(ldd->revView, column);
1896 renderer = gtk_cell_renderer_text_new();
1897 column = gtk_tree_view_column_new_with_attributes(_(
"Principal"), renderer,
1898 "text", LOAN_COL_PRINCIPAL,
1900 gtk_tree_view_append_column(ldd->revView, column);
1902 renderer = gtk_cell_renderer_text_new();
1903 column = gtk_tree_view_column_new_with_attributes(_(
"Interest"), renderer,
1904 "text", LOAN_COL_INTEREST,
1906 gtk_tree_view_append_column(ldd->revView, column);
1910 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
1912 if ( ldd->ld.revRepayOptToColMap[i] == -1 )
1916 renderer = gtk_cell_renderer_text_new();
1917 column = gtk_tree_view_column_new_with_attributes
1918 (ldd->ld.repayOpts[i]->name, renderer,
1919 "text", LOAN_COL_INTEREST + col,
1921 gtk_tree_view_append_column(ldd->revView, column);
1926 gtk_container_add( GTK_CONTAINER(ldd->revScrollWin),
1927 GTK_WIDGET(ldd->revView) );
1928 gtk_widget_show( GTK_WIDGET(ldd->revView) );
1930 loan_rev_recalc_schedule( ldd );
1934 g_date_clear( &start, 1 );
1935 g_date_clear( &end, 1 );
1936 loan_rev_get_dates( ldd, &start, &end );
1937 loan_rev_update_view( ldd, &start, &end );
1944 loan_rev_range_opt_changed_cb( GtkComboBox *combo, gpointer user_data )
1949 opt = gtk_combo_box_get_active( ldd->revRangeOpt );
1950 gtk_widget_set_sensitive( GTK_WIDGET(ldd->revDateFrame),
1954 g_date_clear( &start, 1 );
1955 g_date_clear( &end, 1 );
1956 loan_rev_get_dates( ldd, &start, &end );
1957 loan_rev_update_view( ldd, &start, &end );
1964 loan_rev_range_changed_cb(
GNCDateEdit *gde, gpointer user_data )
1969 g_date_clear( &start, 1 );
1970 g_date_clear( &end, 1 );
1971 loan_rev_get_dates( ldd, &start, &end );
1972 loan_rev_update_view( ldd, &start, &end );
1982 struct tm *endDateMath;
1984 *start = *ldd->ld.startDate;
1986 endDateMath = g_new0(
struct tm, 1 );
1987 g_date_to_struct_tm (ldd->ld.startDate, endDateMath);
1988 monthsTotal = ( ldd->ld.numPer
1989 * ( ldd->ld.perSize == GNC_MONTHS ? 1 : 12 ) );
1990 endDateMath->tm_mon += monthsTotal;
1992 g_date_subtract_days( end, 1 );
1993 g_free (endDateMath);
2001 int range = gtk_combo_box_get_active( ldd->revRangeOpt );
2006 g_date_set_dmy( start, 1, G_DATE_JANUARY, g_date_get_year( start ) );
2007 g_date_set_dmy( end, 31, G_DATE_DECEMBER, g_date_get_year( start ) );
2012 g_date_add_years( end, 1 );
2015 loan_rev_get_loan_range( ldd, start, end );
2019 gnc_date_edit_get_date( ldd->revStartDate ) );
2021 gnc_date_edit_get_date( ldd->revEndDate ) );
2024 PERR(
"Unknown review date range option %d", range );
2033 loan_rev_sched_list_free( gpointer data, gpointer user_data )
2036 g_free( rrr->numCells );
2043 loan_rev_hash_to_list( gpointer key, gpointer val, gpointer user_data )
2045 GList **l = (GList**)user_data;
2049 DEBUG(
"%.8x, %.8x",
2050 GPOINTER_TO_UINT(key),
2051 GPOINTER_TO_UINT(val));
2055 rrr->date = *(GDate*)key;
2056 rrr->numCells = (gnc_numeric*)val;
2057 *l = g_list_append( *l, (gpointer)rrr );
2063 loan_rev_hash_free_date_keys( gpointer key, gpointer val, gpointer user_data )
2065 g_free( (GDate*)key );
2074 gnc_numeric *rowNumData;
2075 GHashTable *repayment_schedule;
2077 g_date_clear( &start, 1 );
2078 g_date_clear( &end, 1 );
2079 loan_rev_get_loan_range( ldd, &start, &end );
2089 GDate curDate, nextDate;
2093 auto pmtFormula = loan_get_pmt_formula(ldd);
2094 auto ppmtFormula = loan_get_ppmt_formula(ldd);
2095 auto ipmtFormula = loan_get_ipmt_formula(ldd);
2097 ivar = g_hash_table_new( g_str_hash, g_str_equal );
2098 g_date_clear( &curDate, 1 );
2100 g_date_subtract_days( &curDate, 1 );
2101 g_date_clear(&nextDate, 1);
2102 recurrenceListNextInstance(ldd->ld.repayment_schedule, &curDate, &nextDate);
2104 g_date_valid( &nextDate )
2105 && g_date_compare( &nextDate, &end ) <= 0 ;
2108 recurrenceListNextInstance(ldd->ld.repayment_schedule,
2109 &curDate, &nextDate))
2115 (gnc_numeric*)g_hash_table_lookup( repayment_schedule,
2117 if ( rowNumData == NULL)
2120 GDate *dateKeyCopy = g_date_new();
2122 *dateKeyCopy = nextDate;
2123 rowNumData = g_new0( gnc_numeric, ldd->ld.revNumPmts );
2124 g_assert( rowNumData != NULL );
2125 for ( j = 0; j < ldd->ld.revNumPmts; j++ )
2129 g_hash_table_insert( repayment_schedule,
2130 (gpointer)dateKeyCopy,
2131 (gpointer)rowNumData );
2136 ival = gnc_numeric_create( i, 1 );
2137 g_hash_table_insert( ivar, (gpointer)
"i", &ival );
2139 if ( ! gnc_exp_parser_parse_separate_vars(
2140 pmtFormula.c_str(), &val, &eloc, ivar ) )
2142 PERR(
"pmt Parsing error at %s", eloc );
2146 rowNumData[0] = val;
2148 if ( ! gnc_exp_parser_parse_separate_vars(
2149 ppmtFormula.c_str(), &val, &eloc, ivar ) )
2151 PERR(
"ppmt Parsing error at %s", eloc );
2155 rowNumData[1] = val;
2157 if ( ! gnc_exp_parser_parse_separate_vars(
2158 ipmtFormula.c_str(), &val, &eloc, ivar ) )
2160 PERR(
"ipmt Parsing error at %s", eloc );
2164 rowNumData[2] = val;
2167 g_hash_table_destroy( ivar );
2173 GDate curDate, nextDate;
2176 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
2178 if ( ! ldd->ld.repayOpts[i]->enabled )
2182 = ( ldd->ld.repayOpts[i]->schedule != NULL
2183 ? ldd->ld.repayOpts[i]->schedule
2184 : ldd->ld.repayment_schedule );
2186 g_date_clear( &curDate, 1 );
2188 g_date_subtract_days( &curDate, 1 );
2189 g_date_clear(&nextDate, 1);
2190 recurrenceListNextInstance(schedule, &curDate, &nextDate );
2191 for ( ; g_date_valid( &nextDate )
2192 && g_date_compare( &nextDate, &end ) <= 0;
2194 recurrenceListNextInstance(
2195 schedule, &curDate, &nextDate ) )
2201 rowNumData = (gnc_numeric*)g_hash_table_lookup( repayment_schedule,
2203 if ( rowNumData == NULL )
2206 GDate *dateKeyCopy = g_date_new();
2208 *dateKeyCopy = nextDate;
2209 rowNumData = g_new0( gnc_numeric, ldd->ld.revNumPmts );
2210 g_assert( rowNumData != NULL );
2211 for ( j = 0; j < ldd->ld.revNumPmts; j++ )
2215 g_hash_table_insert( repayment_schedule,
2216 (gpointer)dateKeyCopy,
2217 (gpointer)rowNumData );
2224 rowNumData[ ldd->ld.revRepayOptToColMap[i] ]
2232 if ( ldd->ld.revSchedule != NULL )
2234 g_list_foreach( ldd->ld.revSchedule,
2235 loan_rev_sched_list_free,
2237 g_list_free( ldd->ld.revSchedule );
2238 ldd->ld.revSchedule = NULL;
2240 g_hash_table_foreach( repayment_schedule, loan_rev_hash_to_list,
2241 &ldd->ld.revSchedule );
2242 g_hash_table_foreach( repayment_schedule, loan_rev_hash_free_date_keys,
2244 g_hash_table_destroy( repayment_schedule );
2245 ldd->ld.revSchedule =
2246 g_list_sort( ldd->ld.revSchedule, (GCompareFunc)g_date_compare );
2255 static const gchar *NO_AMT_CELL_TEXT =
" ";
2258 GtkListStore *store;
2261 pai = gnc_default_price_print_info(NULL);
2262 pai.min_decimal_places = 2;
2264 store = GTK_LIST_STORE(gtk_tree_view_get_model( ldd->revView ));
2266 gtk_list_store_clear( store );
2268 for ( l = ldd->ld.revSchedule; l != NULL; l = l->next )
2274 if ( g_date_compare( &rrr->date, start ) < 0 )
2276 if ( g_date_compare( &rrr->date, end ) > 0 )
2279 gtk_list_store_append(store, &iter);
2282 gtk_list_store_set( store, &iter, LOAN_COL_DATE, tmpBuf, -1 );
2284 for ( i = 0; i < ldd->ld.revNumPmts; i++ )
2291 gtk_list_store_set( store, &iter,
2292 i + 1, NO_AMT_CELL_TEXT,
2298 g_assert( numPrinted < 50 );
2300 gtk_list_store_set( store, &iter,
2321 gfloat loan_apr_to_simple_formula (
double rate,
double pmt_periods,
double comp_periods)
2326 simple_rate = pow(1 + (rate / comp_periods), comp_periods / pmt_periods) - 1;
2327 return (simple_rate);
2330 using boost::locale::conv::utf_to_utf;
2343 int do_frac_digits()
const {
return prec; }
2348 std::string to_str_with_prec (
const gdouble val)
2352 LCID lcid = GetThreadLocale();
2355 numfmt.NumDigits = prec;
2356 GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ILZERO, (LPWSTR)&numval,
2357 sizeof(numval)/
sizeof(
wchar_t));
2358 numfmt.LeadingZero = numval;
2359 wchar_t grouping[10];
2360 GetLocaleInfoW(lcid, LOCALE_SGROUPING, grouping,
2361 sizeof(grouping)/
sizeof(
wchar_t));
2362 auto semi = wcschr(grouping,
';');
2364 numfmt.Grouping = _wtoi(grouping);
2366 GetLocaleInfoW(lcid, LOCALE_SDECIMAL, decsep,
2367 sizeof(decsep)/
sizeof(
wchar_t) );
2368 numfmt.lpDecimalSep = decsep;
2370 GetLocaleInfoW(lcid, LOCALE_STHOUSAND, thousep,
2371 sizeof(thousep)/
sizeof(
wchar_t));
2372 numfmt.lpThousandSep = thousep;
2373 GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_INEGNUMBER,
2374 (LPWSTR)&numval,
sizeof(numval)/
sizeof(
wchar_t));
2375 numfmt.NegativeOrder = numval;
2377 std::wstringstream valstr;
2379 int size = GetNumberFormatW(lcid, 0, valstr.str().c_str(),
2380 &numfmt,
nullptr, 0);
2381 wchar_t* buf =
static_cast<wchar_t*
>(malloc(
sizeof(
wchar_t) * size));
2382 GetNumberFormatW(lcid, 0, valstr.str().c_str(), &numfmt, buf, size);
2383 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,
wchar_t> conv;
2384 std::string result = conv.to_bytes(buf);
2389 std::wstringstream valstr;
2391 valstr << std::put_money(val * pow(10, prec));
2392 return utf_to_utf<char>(valstr.str());
2396 static constexpr std::tuple<double, double>
2399 double ppy = 0.0, periods = 1.0;
2400 auto recurrences = ldd->ld.repayment_schedule;
2401 for (
auto node = recurrences; node; node = g_list_next(node))
2403 auto recurrence =
static_cast<Recurrence*
>(node->data);
2404 auto period_type = recurrenceGetPeriodType(recurrence);
2405 auto multiplier = recurrenceGetMultiplier(recurrence);
2412 ppy += 1.0 / multiplier;
2415 ppy = 365 / multiplier;
2418 ppy += 52.0 / multiplier;
2421 case PERIOD_END_OF_MONTH:
2422 case PERIOD_NTH_WEEKDAY:
2423 case PERIOD_LAST_WEEKDAY:
2424 ppy += 12.0 / multiplier;
2432 auto months = (ldd->ld.numPer * (ldd->ld.perSize == GNC_MONTHS ? 1 : 12));
2433 if ((
int)(months * ppy / 12) > 1)
2434 periods = (int)(months * ppy / 12) * 1.0;
2436 return {ppy, periods};
2442 g_assert( ldd != NULL );
2444 auto [ppy, periods] = periods_per_year(ldd);
2445 gdouble pass_thru_rate = ldd->ld.interestRate / 100.0;
2448 gdouble period_rate;
2449 auto rate_case = ldd->ld.rateType;
2452 case GNC_IRATE_SIMPLE:
2453 period_rate = pass_thru_rate;
2455 case GNC_IRATE_APR_DAILY:
2456 period_rate = loan_apr_to_simple_formula (pass_thru_rate, ppy, 365);
2458 case GNC_IRATE_APR_WEEKLY:
2459 period_rate = loan_apr_to_simple_formula (pass_thru_rate, ppy, 52);
2461 case GNC_IRATE_APR_MONTHLY:
2462 period_rate = loan_apr_to_simple_formula (pass_thru_rate, ppy, 12);
2464 case GNC_IRATE_APR_QUARTERLY:
2465 period_rate = loan_apr_to_simple_formula (pass_thru_rate, ppy, 4);
2467 case GNC_IRATE_APR_SEMIANNUALLY:
2468 period_rate = loan_apr_to_simple_formula (pass_thru_rate, ppy, 2);
2470 case GNC_IRATE_APR_ANNUALLY:
2471 period_rate = loan_apr_to_simple_formula (pass_thru_rate, ppy, 1);
2474 period_rate = ldd->ld.interestRate / 100;
2477 auto period_rate_str = to_str_with_prec<5> (period_rate);
2478 auto period_base_str = to_str_with_prec<2> (ppy);
2479 auto periods_str = to_str_with_prec<2> (periods);
2480 auto principal_str = to_str_with_prec<2> (principal);
2490 std::string formula;
2491 if (rate_case == GNC_IRATE_SIMPLE)
2492 formula = (bl::format (tpl) % period_rate_str %
2493 period_base_str % periods_str % principal_str).str();
2495 formula = (bl::format (tpl) % period_rate_str % periods_str % principal_str).str();
2502 if (ldd->ld.rateType == GNC_IRATE_SIMPLE)
2503 return loan_get_formula_internal (ldd,
"pmt( {1} / {2} : {3} : {4} : 0 : 0 )");
2505 return loan_get_formula_internal (ldd,
"pmt( {1} : {2} : {3} : 0 : 0 )");
2512 if (ldd->ld.rateType == GNC_IRATE_SIMPLE)
2513 return loan_get_formula_internal (ldd,
"ppmt( {1} / {2} : i : {3} : {4} : 0 : 0 )");
2515 return loan_get_formula_internal (ldd,
"ppmt( {1} : i : {2} : {3} : 0 : 0 )");
2522 if (ldd->ld.rateType == GNC_IRATE_SIMPLE)
2523 return loan_get_formula_internal (ldd,
"ipmt( {1} / {2} : i : {3} : {4} : 0 : 0 )");
2525 return loan_get_formula_internal (ldd,
"ipmt( {1} : i : {2} : {3} : 0 : 0 )");
2531 ld_calc_sx_instance_num(GDate *start_date, GList *schedule)
2534 GDate next_date, today;
2536 g_date_clear(&next_date, 1);
2537 g_date_clear(&today, 1);
2540 if (g_date_compare(start_date, &today) > 0)
2543 instance_count = -1;
2547 recurrenceListNextInstance(schedule, start_date, &next_date);
2549 while (g_date_compare(&next_date, &today) < 0);
2551 return instance_count;
2557 loan_tcSX_free( gpointer data, gpointer user_data )
2560 g_free( tcSX->
name );
2575 SchedXactions *sxes;
2581 xaccSchedXactionSetStartDate( sx, &tcSX->
start );
2582 xaccSchedXactionSetLastOccurDate( sx, &tcSX->last );
2587 ttxn_vec.push_back (tcSX->
mainTxn);
2591 g_assert (!ttxn_vec.empty());
2593 xaccSchedXactionSetTemplateTrans (sx, ttxn_vec, gnc_get_current_book());
2595 sxes = gnc_book_get_schedxactions(gnc_get_current_book());
2596 gnc_sxes_add_sx(sxes, sx);
2600 static TTSplitInfoPtr
2601 find_account_from_template_splits (
const TTInfoPtr& txn,
const Account* account)
2603 auto& splits{txn->get_template_splits ()};
2604 auto has_acct = [account](
auto ttinfo){
return ttinfo->get_account() == account; };
2605 auto it = std::find_if (splits.begin(), splits.end(), has_acct);
2606 return it == splits.end() ? nullptr : *it;
2686 TTSplitInfoPtr fromSplit;
2687 TTSplitInfoPtr ttsi;
2690 #define AMTBUF_LEN 64 2691 gchar amtBuf[AMTBUF_LEN];
2700 if ( rod->throughEscrowP && ldd->ld.escrowAcct )
2707 auto ttsi = find_account_from_template_splits (paymentSX->
mainTxn, ldd->ld.escrowAcct);
2709 gstr = g_string_new (ttsi->get_debit_formula());
2710 g_string_append_printf( gstr,
" + %s", amtBuf );
2711 ttsi->set_debit_formula (gstr->str);
2712 g_string_free( gstr, TRUE );
2717 if ( rod->from != NULL )
2724 auto ttsi = find_account_from_template_splits (tcSX->
escrowTxn, ldd->ld.escrowAcct);
2728 ttsi = std::make_shared<TTSplitInfo>();
2729 ttsi->set_memo (rod->txnMemo);
2730 ttsi->set_account (ldd->ld.escrowAcct);
2731 tcSX->
escrowTxn->append_template_split (ttsi);
2733 if ( (str = (gchar*)ttsi->get_credit_formula ())
2736 gstr = g_string_sized_new( 16 );
2743 gstr = g_string_new( str );
2744 g_string_append_printf( gstr,
" + " );
2746 g_string_append_printf( gstr,
"%s", amtBuf );
2747 ttsi->set_credit_formula (gstr->str);
2748 g_string_free( gstr, TRUE );
2755 fromSplit = find_account_from_template_splits (paymentSX->
mainTxn, ldd->ld.repFromAcct);
2756 g_assert (fromSplit);
2759 ttsi = std::make_shared<TTSplitInfo>();
2760 ttsi->set_memo (rod->txnMemo);
2761 ttsi->set_account (ldd->ld.escrowAcct);
2762 ttsi->set_credit_formula (amtBuf);
2763 tcSX->
escrowTxn->append_template_split (ttsi);
2771 if ( rod->from != NULL )
2777 fromSplit = find_account_from_template_splits (tcSX->
mainTxn, ldd->ld.repFromAcct);
2781 if ( fromSplit != NULL )
2784 gstr = g_string_new (fromSplit->get_credit_formula ());
2785 g_string_append_printf( gstr,
" + %s", amtBuf );
2786 fromSplit->set_credit_formula (gstr->str);
2787 g_string_free( gstr, TRUE );
2795 ttsi = std::make_shared<TTSplitInfo>();
2796 ttsi->set_memo (rod->txnMemo);
2797 ttsi->set_account (rod->from ? rod->from : ldd->ld.repFromAcct);
2798 ttsi->set_credit_formula (amtBuf);
2800 if ( rod->throughEscrowP )
2804 tti->append_template_split (ttsi);
2811 ttsi = std::make_shared<TTSplitInfo>();
2812 ttsi->set_memo (rod->txnMemo);
2813 ttsi->set_account (rod->to);
2814 ttsi->set_debit_formula (amtBuf);
2815 toTxn->append_template_split (ttsi);
2842 GList *repaySXes = NULL;
2847 TTSplitInfoPtr ttsi;
2850 paymentSX->
name = g_strdup(ldd->ld.repMemo);
2851 paymentSX->
start = *ldd->ld.startDate;
2852 paymentSX->last = *ldd->ld.repStartDate;
2853 g_date_subtract_months( &paymentSX->last, 1 );
2855 paymentSX->end = *ldd->ld.repStartDate;
2856 g_date_add_months( &paymentSX->end, ldd->ld.numMonRemain - 1);
2859 paymentSX->
schedule = ldd->ld.repayment_schedule;
2863 (ldd->ld.numPer * ( ldd->ld.perSize == GNC_YEARS ? 12 : 1 ))
2864 - ldd->ld.numMonRemain + 1;
2866 paymentSX->
mainTxn = std::make_shared<TTInfo>();
2870 GString *payMainTxnDesc = g_string_sized_new( 32 );
2871 g_string_printf( payMainTxnDesc,
2874 ( ldd->ld.escrowAcct == NULL
2876 : _(
"Escrow Payment") )
2879 paymentSX->
mainTxn->set_description(payMainTxnDesc->str);
2880 g_string_free( payMainTxnDesc, TRUE );
2902 srcAcct = ldd->ld.repFromAcct;
2903 if ( ldd->ld.escrowAcct != NULL )
2905 Account *realSrcAcct = srcAcct;
2906 srcAcct = ldd->ld.escrowAcct;
2907 auto formula = loan_get_pmt_formula(ldd);
2910 ttsi = std::make_shared<TTSplitInfo>();
2911 ttsi->set_memo (ldd->ld.repMemo);
2912 ttsi->set_account (realSrcAcct);
2913 ttsi->set_credit_formula (formula.c_str());
2914 ttxn->append_template_split (ttsi);
2919 ttsi = std::make_shared<TTSplitInfo>();
2920 ttsi->set_memo (ldd->ld.repMemo);
2921 ttsi->set_account (ldd->ld.escrowAcct);
2922 ttsi->set_debit_formula (formula.c_str());
2923 ttxn->append_template_split (ttsi);
2926 paymentSX->
escrowTxn = std::make_shared<TTInfo>();
2930 GString *escrowTxnDesc;
2931 escrowTxnDesc = g_string_new( ldd->ld.repMemo );
2932 g_string_append_printf( escrowTxnDesc,
" - %s", _(
"Payment") );
2933 paymentSX->
escrowTxn->set_description (escrowTxnDesc->str);
2934 g_string_free( escrowTxnDesc, TRUE );
2940 ttsi = std::make_shared<TTSplitInfo>();
2942 auto gstr = g_string_new( ldd->ld.repMemo );
2943 g_string_append_printf( gstr,
" - %s",
2945 ttsi->set_memo (gstr->str);
2946 g_string_free( gstr, TRUE );
2948 ttsi->set_account (srcAcct);
2949 auto formula = loan_get_pmt_formula(ldd);
2950 ttsi->set_credit_formula (formula.c_str());
2951 ttxn->append_template_split (ttsi);
2956 ttsi = std::make_shared<TTSplitInfo>();
2958 auto gstr = g_string_new( ldd->ld.repMemo );
2959 g_string_append_printf( gstr,
" - %s",
2961 ttsi->set_memo (gstr->str);
2962 g_string_free( gstr, TRUE );
2964 ttsi->set_account (ldd->ld.repPriAcct);
2965 auto formula = loan_get_ppmt_formula(ldd);
2966 ttsi->set_debit_formula (formula.c_str());
2967 ttxn->append_template_split (ttsi);
2972 ttsi = std::make_shared<TTSplitInfo>();
2974 auto gstr = g_string_new( ldd->ld.repMemo );
2975 g_string_append_printf( gstr,
" - %s",
2977 ttsi->set_memo (gstr->str);
2978 g_string_free( gstr, TRUE );
2980 ttsi->set_account (ldd->ld.repIntAcct);
2981 auto formula = loan_get_ipmt_formula(ldd);
2982 ttsi->set_debit_formula (formula.c_str());
2983 ttxn->append_template_split (ttsi);
2987 for ( i = 0; i < ldd->ld.repayOptCount; i++ )
2990 if ( ! rod->enabled )
2994 if ( rod->schedule != NULL )
2997 auto gstr = g_string_new( ldd->ld.repMemo );
2998 g_string_append_printf( gstr,
" - %s",
3000 tcSX->
name = g_strdup(gstr->str);
3001 tcSX->
start = *ldd->ld.startDate;
3002 tcSX->last = *ldd->ld.repStartDate;
3004 tcSX->end = tcSX->last;
3005 g_date_add_months( &tcSX->end, ldd->ld.numMonRemain );
3011 ld_calc_sx_instance_num(&tcSX->
start, rod->schedule);
3012 rod->schedule = NULL;
3013 tcSX->
mainTxn = std::make_shared<TTInfo>();
3015 tcSX->
mainTxn->set_description (gstr->str);
3016 tcSX->
escrowTxn = std::make_shared<TTInfo>();
3018 tcSX->
escrowTxn->set_description(gstr->str);
3020 g_string_free( gstr, TRUE );
3021 repaySXes = g_list_prepend (repaySXes, tcSX);
3026 ld_setup_repayment_sx( ldd, rod, paymentSX, tcSX );
3029 repaySXes = g_list_reverse (repaySXes);
3034 loan_create_sx_from_tcSX( ldd, paymentSX );
3036 for ( l = repaySXes; l; l = l->next )
3038 loan_create_sx_from_tcSX( ldd, (
toCreateSX*)l->data );
3042 loan_tcSX_free( paymentSX, NULL );
3043 g_list_foreach( repaySXes, loan_tcSX_free, NULL );
3044 g_list_free( repaySXes );
3050 loan_assistant_finish ( GtkAssistant *gtkassistant, gpointer user_data )
3053 loan_create_sxes( ldd );
3059 loan_assistant_cancel( GtkAssistant *gtkassistant, gpointer user_data )
3062 gnc_close_gui_component_by_data( DIALOG_LOAN_ASSISTANT_CM_CLASS, ldd );
3067 loan_assistant_close( GtkAssistant *gtkassistant, gpointer user_data )
3070 gnc_close_gui_component_by_data( DIALOG_LOAN_ASSISTANT_CM_CLASS, ldd );
3075 loan_assistant_prepare (GtkAssistant *assistant, GtkWidget *page,
3078 gint currentpage = gtk_assistant_get_current_page(assistant);
3080 switch (currentpage)
3084 loan_info_prep (assistant, user_data);
3088 loan_opt_prep (assistant, user_data);
3092 loan_rep_prep (assistant, user_data);
3096 loan_pay_prep (assistant, user_data);
3100 loan_rev_prep (assistant, user_data);
3112 gnc_ui_sx_loan_assistant_create (
void)
3119 gnc_loan_assistant_create (ldd);
3121 component_id = gnc_register_gui_component (DIALOG_LOAN_ASSISTANT_CM_CLASS,
3122 NULL, loan_assistant_close_handler,
3125 gnc_gui_component_watch_entity_type (component_id,
3127 QOF_EVENT_MODIFY | QOF_EVENT_DESTROY);
3129 gtk_widget_show_all (ldd->window);
3131 gnc_window_adjust_for_screen (GTK_WINDOW(ldd->window));
A transient struct used to collate the GDate and the gnc_numeric row-data for the repayment review sc...
void gnc_sx_set_schedule(SchedXaction *sx, GList *schedule)
void gnc_sx_set_instance_count(SchedXaction *sx, gint instance_num)
Sets the instance count to something other than the default.
TTInfoPtr mainTxn
The main/source transaction being created.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
Date and Time handling routines.
gnc_numeric double_to_gnc_numeric(double n, gint64 denom, gint how)
Convert a floating-point number to a gnc_numeric.
gint gnc_gdate_equal(gconstpointer gda, gconstpointer gdb)
Compares two GDate*'s for equality; useful for using GDate*'s as GHashTable keys. ...
utility functions for the GnuCash UI
Expense accounts are used to denote expenses.
gchar * name
The name of the SX.
guint gnc_gdate_hash(gconstpointer gd)
Provides a "hash" of a GDate* value; useful for using GDate*'s as GHashTable keys.
size_t qof_print_gdate(char *buf, size_t bufflen, const GDate *gd)
Convenience; calls through to qof_print_date_dmy_buff().
#define DEBUG(format, args...)
Print a debugging message.
The data relating to a single "repayment option" – a potential [sub-]transaction in the repayment...
#define PERR(format, args...)
Log a serious error.
The cash account type is used to denote a shoe-box or pillowcase stuffed with * cash.
gnc_commodity * gnc_default_currency(void)
Return the default currency set by the user.
void gnc_tm_free(struct tm *time)
free a struct tm* created with gnc_localtime() or gnc_gmtime()
gdouble gnc_numeric_to_double(gnc_numeric n)
Convert numeric to floating-point value.
The UI-side storage of the loan assistant data.
The default repayment options data.
Account handling public routines.
gnc_numeric gnc_numeric_convert(gnc_numeric n, gint64 denom, gint how)
Change the denominator of a gnc_numeric value to the specified denominator under standard arguments '...
gint instNum
The current 'instance-num' count.
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...
Anchor Scheduled Transaction info in a book.
A transient structure to contain SX details during the creation process.
GDate start
The start, last-occurred and end dates.
The bank account type denotes a savings or checking account held at a bank.
The UI-side storage of the repayment options.
Argument is not a valid number.
time64 gnc_mktime(struct tm *time)
calculate seconds from the epoch given a time struct
GList * schedule
The SX schedule.
#define MAX_DATE_LENGTH
The maximum length of a string created by the date printers.
struct tm * gnc_localtime(const time64 *secs)
fill out a time struct from a 64-bit time value.
asset (and liability) accounts indicate generic, generalized accounts that are none of the above...
All type declarations for the whole Gnucash engine.
int xaccSPrintAmount(char *bufp, gnc_numeric val, GNCPrintAmountInfo info)
Make a string representation of a gnc_numeric.
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed...
void xaccSchedXactionSetName(SchedXaction *sx, const gchar *newName)
A copy of the name is made.
liability (and asset) accounts indicate generic, generalized accounts that are none of the above...
void gnc_gdate_set_time64(GDate *gd, time64 time)
Set a GDate to a time64.
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity.
TTInfoPtr escrowTxn
The optional escrow transaction being created.
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
time64 gnc_time(time64 *tbuf)
get the current time
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
Check for error signal in value.
SchedXaction * xaccSchedXactionMalloc(QofBook *book)
Creates and initializes a scheduled transaction.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Scheduled Transactions public handling routines.
void xaccSchedXactionSetEndDate(SchedXaction *sx, const GDate *newEnd)
Set to an invalid GDate to turn off 'end-date' definition.
#define GNC_HOW_DENOM_SIGFIGS(n)
Build a 'how' value that will generate a denominator that will keep at least n significant figures in...
Data about a loan repayment.
The Credit card account is used to denote credit (e.g.