gnucash master: Multiple changes pushed
Geert Janssens
gjanssens at code.gnucash.org
Mon Feb 17 20:08:50 EST 2014
Updated via https://github.com/Gnucash/gnucash/commit/0c7c3356 (commit)
via https://github.com/Gnucash/gnucash/commit/f0f3a8e8 (commit)
from https://github.com/Gnucash/gnucash/commit/8cc9f175 (commit)
commit 0c7c3356029c89650da31bd1ad0e77d6e764425e
Author: Geert Janssens <janssens-geert at telenet.be>
Date: Tue Feb 18 02:03:44 2014 +0100
Bug 724578 - Problems clearing incompletely paid invoices
diff --git a/src/business/business-gnome/dialog-payment.c b/src/business/business-gnome/dialog-payment.c
index 5777bb0..b380f3c 100644
--- a/src/business/business-gnome/dialog-payment.c
+++ b/src/business/business-gnome/dialog-payment.c
@@ -666,9 +666,14 @@ gnc_payment_ok_cb (GtkWidget *widget, gpointer data)
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(pw->docs_list_tree_view));
gtk_tree_selection_selected_foreach (selection, get_selected_lots, &selected_lots);
- /* If the 'xfer_acct' account and the post account don't have the same
- currency, we need to get the user to specify the exchange rate */
- if (!gnc_commodity_equal(xaccAccountGetCommodity(pw->xfer_acct), xaccAccountGetCommodity(pw->post_acct)))
+ /* When the payment amount is 0, the selected documents cancel each other out
+ * so no money is actually transferred.
+ * For non-zero payments money will be transferred between the post account
+ * and the transfer account. In that case if these two accounts don't have
+ * the same currency the user is asked to enter the exchange rate.
+ */
+ if (!gnc_numeric_zero_p (pw->amount_tot) &&
+ !gnc_commodity_equal(xaccAccountGetCommodity(pw->xfer_acct), xaccAccountGetCommodity(pw->post_acct)))
{
XferDialog* xfer;
diff --git a/src/engine/gncOwner.c b/src/engine/gncOwner.c
index 872671a..61968d6 100644
--- a/src/engine/gncOwner.c
+++ b/src/engine/gncOwner.c
@@ -1034,12 +1034,14 @@ gncOwnerApplyPayment (const GncOwner *owner, Transaction *txn, GList *lots,
GList *selected_lots = NULL;
/* Verify our arguments */
- if (!owner || !posted_acc || !xfer_acc) return;
+ if (!owner || !posted_acc
+ || (!xfer_acc && !gnc_numeric_zero_p (amount)) ) return;
g_return_if_fail (owner->owner.undefined);
- /* Create a lot for this payment */
- payment_lot = gncOwnerCreatePaymentLot (owner, txn, posted_acc, xfer_acc,
- amount, exch, date, memo, num);
+ /* If there's a real amount to transfer create a lot for this payment */
+ if (!gnc_numeric_zero_p (amount))
+ payment_lot = gncOwnerCreatePaymentLot (owner, txn, posted_acc, xfer_acc,
+ amount, exch, date, memo, num);
if (lots)
selected_lots = lots;
commit f0f3a8e812a730a704280c0476f934b5acf00eb8
Author: Geert Janssens <janssens-geert at telenet.be>
Date: Mon Feb 17 23:49:54 2014 +0100
Rework payment dialog to better guide the user
diff --git a/src/business/business-gnome/dialog-payment.c b/src/business/business-gnome/dialog-payment.c
index 1c7c41a..5777bb0 100644
--- a/src/business/business-gnome/dialog-payment.c
+++ b/src/business/business-gnome/dialog-payment.c
@@ -60,6 +60,8 @@ struct _payment_window
{
GtkWidget * dialog;
+ GtkWidget * payment_warning;
+ GtkWidget * ok_button;
GtkWidget * num_entry;
GtkWidget * memo_entry;
GtkWidget * post_combo;
@@ -75,6 +77,8 @@ struct _payment_window
GncOwner owner;
GncInvoice * invoice;
Account * post_acct;
+ Account * xfer_acct;
+ gnc_numeric amount_tot;
GList * acct_types;
GList * acct_commodities;
@@ -142,6 +146,7 @@ static gboolean gnc_payment_dialog_has_pre_existing_txn(const PaymentWindow* pw)
}
int gnc_payment_dialog_post_to_changed_cb (GtkWidget *widget, gpointer data);
void gnc_payment_dialog_document_selection_changed_cb (GtkWidget *widget, gpointer data);
+void gnc_payment_dialog_xfer_acct_changed_cb (GtkWidget *widget, gpointer data);
void gnc_payment_ok_cb (GtkWidget *widget, gpointer data);
void gnc_payment_cancel_cb (GtkWidget *widget, gpointer data);
void gnc_payment_window_destroy_cb (GtkWidget *widget, gpointer data);
@@ -159,6 +164,80 @@ gnc_payment_window_refresh_handler (GHashTable *changes, gpointer data)
pw->post_acct = gnc_account_select_combo_fill (pw->post_combo, pw->book, pw->acct_types, pw->acct_commodities);
}
+static gboolean
+gnc_payment_window_check_payment (PaymentWindow *pw)
+{
+ const char *conflict_msg = NULL;
+ Account *post, *acc;
+ gnc_numeric amount_deb, amount_cred;
+ gboolean enable_xfer_acct = TRUE;
+ GtkTreeSelection *selection;
+
+ if (!pw)
+ return FALSE;
+
+ /* Verify the "post" account */
+ if (!pw->post_acct)
+ {
+ conflict_msg = _("You must enter a valid account name for posting.");
+ goto update_cleanup;
+ }
+
+ /* Verify the user has selected an owner */
+ gnc_owner_get_owner (pw->owner_choice, &(pw->owner));
+ if (!gncOwnerIsValid(&pw->owner))
+ {
+ conflict_msg = _("You must select a company for payment processing.");
+ goto update_cleanup;
+ }
+
+ /* Verify at least one document is selected */
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(pw->docs_list_tree_view));
+ if (!gtk_tree_selection_count_selected_rows (selection))
+ {
+ conflict_msg = _("You must select at least one document or pre-payment to process.");
+ goto update_cleanup;
+ }
+
+ /* Test the total amount */
+ amount_deb = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (pw->amount_debit_edit));
+ amount_cred = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (pw->amount_credit_edit));
+ pw->amount_tot = gnc_numeric_sub (amount_cred, amount_deb,
+ gnc_commodity_get_fraction (xaccAccountGetCommodity (pw->post_acct)),
+ GNC_HOW_RND_ROUND_HALF_UP);
+
+ if (gnc_numeric_check (pw->amount_tot) || gnc_numeric_zero_p (pw->amount_tot))
+ enable_xfer_acct = FALSE;
+ else
+ {
+ /* Verify the user has selected a transfer account */
+ pw->xfer_acct = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(pw->acct_tree));
+ if (!pw->xfer_acct)
+ {
+ conflict_msg = _("You must select a transfer account from the account tree.");
+ }
+ }
+
+update_cleanup:
+ gtk_widget_set_sensitive (pw->acct_tree, enable_xfer_acct);
+
+ /* Check if there are issues preventing a successful payment */
+ gtk_widget_set_tooltip_text (pw->payment_warning, conflict_msg);
+ if (conflict_msg)
+ {
+ gtk_widget_show (pw->payment_warning);
+ gtk_widget_set_sensitive (pw->ok_button, FALSE);
+ return FALSE;
+ }
+ else
+ {
+ gtk_widget_hide (pw->payment_warning);
+ gtk_widget_set_sensitive (pw->ok_button, TRUE);
+ }
+
+ return TRUE;
+}
+
static void
gnc_payment_window_close_handler (gpointer data)
{
@@ -237,6 +316,7 @@ gnc_payment_dialog_highlight_document (PaymentWindow *pw)
GtkTreeIter iter;
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(pw->docs_list_tree_view));
GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(pw->docs_list_tree_view));
+ gtk_tree_selection_unselect_all (selection);
if (gtk_tree_model_get_iter_first (model, &iter))
{
@@ -260,8 +340,6 @@ gnc_payment_dialog_highlight_document (PaymentWindow *pw)
gtk_tree_selection_select_iter (selection, &iter);
gnc_payment_dialog_document_selection_changed (pw);
}
- else
- gtk_tree_selection_unselect_iter (selection, &iter);
}
while (gtk_tree_model_iter_next (model, &iter));
}
@@ -478,6 +556,9 @@ gnc_payment_dialog_owner_changed_cb (GtkWidget *widget, gpointer data)
gnc_payment_dialog_owner_changed(pw);
}
+ /* Reflect if the payment could complete now */
+ gnc_payment_window_check_payment (pw);
+
return FALSE;
}
@@ -489,6 +570,20 @@ gnc_payment_dialog_document_selection_changed_cb (GtkWidget *widget, gpointer da
if (!pw) return;
gnc_payment_dialog_document_selection_changed (pw);
+
+ /* Reflect if the payment could complete now */
+ gnc_payment_window_check_payment (pw);
+}
+
+void
+gnc_payment_dialog_xfer_acct_changed_cb (GtkWidget *widget, gpointer data)
+{
+ PaymentWindow *pw = data;
+
+ if (!pw) return;
+
+ /* Reflect if the payment could complete now */
+ gnc_payment_window_check_payment (pw);
}
int
@@ -510,6 +605,9 @@ gnc_payment_dialog_post_to_changed_cb (GtkWidget *widget, gpointer data)
else
gnc_payment_dialog_highlight_document (pw);
+ /* Reflect if the payment could complete now */
+ gnc_payment_window_check_payment (pw);
+
return FALSE;
}
@@ -541,56 +639,15 @@ gnc_payment_ok_cb (GtkWidget *widget, gpointer data)
{
PaymentWindow *pw = data;
const char *text = NULL;
- Account *post, *acc;
- gnc_numeric amount_deb, amount_cred, amount_tot;
if (!pw)
return;
- /* Verify the total amount is non-zero */
- amount_deb = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (pw->amount_debit_edit));
- amount_cred = gnc_amount_edit_get_amount (GNC_AMOUNT_EDIT (pw->amount_credit_edit));
- amount_tot = gnc_numeric_sub (amount_cred, amount_deb,
- gnc_commodity_get_fraction (xaccAccountGetCommodity (pw->post_acct)),
- GNC_HOW_RND_ROUND_HALF_UP);
-
- if (gnc_numeric_check (amount_tot) || gnc_numeric_zero_p (amount_tot))
- {
- text = _("You must enter the amount of the payment. "
- "The payment amount must not be zero.");
- gnc_error_dialog (pw->dialog, "%s", text);
- return;
- }
-
- /* Verify the user has selected an owner */
- gnc_owner_get_owner (pw->owner_choice, &(pw->owner));
- if (!gncOwnerIsValid(&pw->owner))
- {
- text = _("You must select a company for payment processing.");
- gnc_error_dialog (pw->dialog, "%s", text);
- return;
- }
-
- /* Verify the user has selected a transfer account */
- acc = gnc_tree_view_account_get_selected_account (GNC_TREE_VIEW_ACCOUNT(pw->acct_tree));
- if (!acc)
- {
- text = _("You must select a transfer account from the account tree.");
- gnc_error_dialog (pw->dialog, "%s", text);
- return;
- }
-
- /* Verify the "post" account */
-
- post = gnc_account_select_combo_get_active (pw->post_combo);
- if (!post)
- {
- text = _("You must enter a valid account name for posting.");
- gnc_error_dialog (pw->dialog, "%s", text);
- return;
- }
-
- /* Ok, now execute the payment */
+ /* The gnc_payment_window_check_payment function
+ * ensures we have valid owner, post account, transfer account
+ * and amount so we can proceed with the payment.
+ * Note: make sure it's called before all entry points to this function !
+ */
gnc_suspend_gui_refresh ();
{
const char *memo, *num;
@@ -609,19 +666,19 @@ gnc_payment_ok_cb (GtkWidget *widget, gpointer data)
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(pw->docs_list_tree_view));
gtk_tree_selection_selected_foreach (selection, get_selected_lots, &selected_lots);
- /* If the 'acc' account and the post account don't have the same
+ /* If the 'xfer_acct' account and the post account don't have the same
currency, we need to get the user to specify the exchange rate */
- if (!gnc_commodity_equal(xaccAccountGetCommodity(acc), xaccAccountGetCommodity(post)))
+ if (!gnc_commodity_equal(xaccAccountGetCommodity(pw->xfer_acct), xaccAccountGetCommodity(pw->post_acct)))
{
XferDialog* xfer;
text = _("The transfer and post accounts are associated with different currencies. Please specify the conversion rate.");
- xfer = gnc_xfer_dialog(pw->dialog, acc);
+ xfer = gnc_xfer_dialog(pw->dialog, pw->xfer_acct);
gnc_info_dialog(pw->dialog, "%s", text);
- gnc_xfer_dialog_select_to_account(xfer, post);
- gnc_xfer_dialog_set_amount(xfer, amount_tot);
+ gnc_xfer_dialog_select_to_account(xfer, pw->post_acct);
+ gnc_xfer_dialog_set_amount(xfer, pw->amount_tot);
/* All we want is the exchange rate so prevent the user from thinking
it makes sense to mess with other stuff */
@@ -640,12 +697,13 @@ gnc_payment_ok_cb (GtkWidget *widget, gpointer data)
auto_pay = gnc_prefs_get_bool (GNC_PREFS_GROUP_BILL, GNC_PREF_AUTO_PAY);
gncOwnerApplyPayment (&pw->owner, pw->pre_existing_txn, selected_lots,
- post, acc, amount_tot, exch, date, memo, num, auto_pay);
+ pw->post_acct, pw->xfer_acct, pw->amount_tot,
+ exch, date, memo, num, auto_pay);
}
gnc_resume_gui_refresh ();
- /* Save the transfer account, acc */
- gnc_payment_dialog_remember_account(pw, acc);
+ /* Save the transfer account, xfer_acct */
+ gnc_payment_dialog_remember_account(pw, pw->xfer_acct);
gnc_ui_payment_window_destroy (pw);
}
@@ -694,8 +752,9 @@ gnc_payment_acct_tree_row_activated_cb (GtkWidget *widget, GtkTreePath *path,
else
gtk_tree_view_expand_row(view, path, FALSE);
}
- else
- /* It's an account without any children, so click the Ok button. */
+ else if (gnc_payment_window_check_payment (pw))
+ /* It's an account without any children
+ * If all conditions for a valid payment are met click the Ok button. */
gnc_payment_ok_cb(widget, pw);
}
}
@@ -717,6 +776,9 @@ gnc_payment_leave_amount_cb (GtkWidget *widget, GdkEventFocus *event,
GNC_HOW_RND_ROUND_HALF_UP);
gnc_ui_payment_window_set_amount (pw, amount_tot);
+
+ /* Reflect if the payment could complete now */
+ gnc_payment_window_check_payment (pw);
}
/* Select the list of accounts to show in the tree */
@@ -829,6 +891,8 @@ new_payment_window (GncOwner *owner, QofBook *book, GncInvoice *invoice)
pw->dialog = GTK_WIDGET (gtk_builder_get_object (builder, "Payment Dialog"));
/* Grab the widgets and build the dialog */
+ pw->payment_warning = GTK_WIDGET (gtk_builder_get_object (builder, "payment_warning"));
+ pw->ok_button = GTK_WIDGET (gtk_builder_get_object (builder, "okbutton"));
pw->num_entry = GTK_WIDGET (gtk_builder_get_object (builder, "num_entry"));
pw->memo_entry = GTK_WIDGET (gtk_builder_get_object (builder, "memo_entry"));
pw->post_combo = GTK_WIDGET (gtk_builder_get_object (builder, "post_combo"));
@@ -957,6 +1021,11 @@ new_payment_window (GncOwner *owner, QofBook *book, GncInvoice *invoice)
g_signal_connect (G_OBJECT (pw->acct_tree), "row-activated",
G_CALLBACK (gnc_payment_acct_tree_row_activated_cb), pw);
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(pw->acct_tree));
+ g_signal_connect (G_OBJECT (selection), "changed",
+ G_CALLBACK (gnc_payment_dialog_xfer_acct_changed_cb), pw);
+
+
/* Register with the component manager */
pw->component_id =
gnc_register_gui_component (cm_class,
@@ -980,6 +1049,9 @@ new_payment_window (GncOwner *owner, QofBook *book, GncInvoice *invoice)
gnc_general_search_grab_focus(GNC_GENERAL_SEARCH(pw->owner_choice));
}
+ /* Reflect if the payment could complete now */
+ gnc_payment_window_check_payment (pw);
+
/* Warn the user if they have no valid post-to accounts */
{
const gchar *text;
diff --git a/src/business/business-gnome/gtkbuilder/dialog-payment.glade b/src/business/business-gnome/gtkbuilder/dialog-payment.glade
index 8d85946..a07a3e4 100644
--- a/src/business/business-gnome/gtkbuilder/dialog-payment.glade
+++ b/src/business/business-gnome/gtkbuilder/dialog-payment.glade
@@ -650,6 +650,18 @@ In case of an over-payment or if no invoice was selected, GnuCash will automatic
<property name="position">1</property>
</packing>
</child>
+ <child>
+ <object class="GtkImage" id="payment_warning">
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-dialog-warning</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">False</property>
Summary of changes:
src/business/business-gnome/dialog-payment.c | 195 ++++++++++++++-------
.../business-gnome/gtkbuilder/dialog-payment.glade | 12 ++
src/engine/gncOwner.c | 10 +-
3 files changed, 154 insertions(+), 63 deletions(-)
More information about the gnucash-changes
mailing list