00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027
00028 #include <gnome.h>
00029 #include <glib/gi18n.h>
00030 #include <libguile.h>
00031 #include "swig-runtime.h"
00032
00033 #include "gncObject.h"
00034 #include "QueryCore.h"
00035 #include "QueryNew.h"
00036
00037 #include "dialog-utils.h"
00038 #include "gnc-component-manager.h"
00039 #include "gnc-ui.h"
00040 #include "gnc-gconf-utils.h"
00041 #include "gnc-gui-query.h"
00042 #include "gnc-ui-util.h"
00043 #include "qof.h"
00044 #include "gnc-date-edit.h"
00045 #include "gnc-amount-edit.h"
00046 #include "gnucash-sheet.h"
00047 #include "window-report.h"
00048 #include "dialog-search.h"
00049 #include "search-param.h"
00050 #include "gnc-session.h"
00051 #include "gncInvoice.h"
00052 #include "gncInvoiceP.h"
00053
00054 #include "gncEntryLedger.h"
00055
00056 #include "gnc-plugin-page.h"
00057 #include "gnc-general-search.h"
00058 #include "dialog-date-close.h"
00059 #include "dialog-invoice.h"
00060 #include "dialog-job.h"
00061 #include "business-gnome-utils.h"
00062 #include "dialog-payment.h"
00063 #include "dialog-tax-table.h"
00064 #include "dialog-billterms.h"
00065 #include "dialog-account.h"
00066 #include "guile-mappings.h"
00067
00068 #include "dialog-query-list.h"
00069
00070 #include "gnc-plugin-business.h"
00071 #include "gnc-plugin-page-invoice.h"
00072 #include "gnc-main-window.h"
00073
00074
00075
00076
00077
00078
00079 #if (__GNUC__ >= 4 && __GNUC_MINOR__ >= 2)
00080 # pragma GCC diagnostic ignored "-Waddress"
00081 #endif
00082
00083 #define DIALOG_NEW_INVOICE_CM_CLASS "dialog-new-invoice"
00084 #define DIALOG_VIEW_INVOICE_CM_CLASS "dialog-view-invoice"
00085
00086 #define GCONF_SECTION_SEARCH "dialogs/business/invoice_search"
00087
00088 #define LAST_POSTED_TO_ACCT "last-posted-to-acct"
00089
00090 void gnc_invoice_window_ok_cb (GtkWidget *widget, gpointer data);
00091 void gnc_invoice_window_cancel_cb (GtkWidget *widget, gpointer data);
00092 void gnc_invoice_window_help_cb (GtkWidget *widget, gpointer data);
00093 void gnc_invoice_id_changed_cb (GtkWidget *widget, gpointer data);
00094
00095 #define ENUM_INVOICE_TYPE(_) \
00096 _(NEW_INVOICE, ) \
00097 _(MOD_INVOICE, ) \
00098 _(EDIT_INVOICE, ) \
00099 _(VIEW_INVOICE, )
00100
00101 DEFINE_ENUM(InvoiceDialogType, ENUM_INVOICE_TYPE)
00102 AS_STRING_DEC(InvoiceDialogType, ENUM_INVOICE_TYPE)
00103 FROM_STRING_DEC(InvoiceDialogType, ENUM_INVOICE_TYPE)
00104
00105 FROM_STRING_FUNC(InvoiceDialogType, ENUM_INVOICE_TYPE)
00106 AS_STRING_FUNC(InvoiceDialogType, ENUM_INVOICE_TYPE)
00107
00108 struct _invoice_select_window {
00109 GNCBook * book;
00110 GncOwner * owner;
00111 QueryNew * q;
00112 GncOwner owner_def;
00113 };
00114
00115
00121 struct _invoice_window {
00122 GladeXML * xml;
00123
00124 GtkWidget * dialog;
00125 GncPluginPage *page;
00126
00127
00128 GtkWidget * total_label;
00129 GtkWidget * total_cash_label;
00130 GtkWidget * total_charge_label;
00131 GtkWidget * total_subtotal_label;
00132 GtkWidget * total_tax_label;
00133
00134
00135 GtkWidget * id_entry;
00136 GtkWidget * notes_text;
00137 GtkWidget * opened_date;
00138 GtkWidget * posted_date_hbox;
00139 GtkWidget * posted_date;
00140 GtkWidget * active_check;
00141
00142 GtkWidget * owner_box;
00143 GtkWidget * owner_label;
00144 GtkWidget * owner_choice;
00145 GtkWidget * job_label;
00146 GtkWidget * job_box;
00147 GtkWidget * job_choice;
00148 GtkWidget * billing_id_entry;
00149 GtkWidget * terms_menu;
00150
00151
00152 GtkWidget * proj_frame;
00153 GtkWidget * proj_cust_box;
00154 GtkWidget * proj_cust_choice;
00155 GtkWidget * proj_job_box;
00156 GtkWidget * proj_job_choice;
00157
00158
00159 GtkWidget * to_charge_frame;
00160 GtkWidget * to_charge_edit;
00161
00162 gint width;
00163
00164 GncBillTerm * terms;
00165 GnucashRegister * reg;
00166 GncEntryLedger * ledger;
00167
00168 invoice_sort_type_t last_sort;
00169
00170 InvoiceDialogType dialog_type;
00171 GUID invoice_guid;
00172 gint component_id;
00173 GNCBook * book;
00174 GncInvoice * created_invoice;
00175 GncOwner owner;
00176 GncOwner job;
00177
00178 GncOwner proj_cust;
00179 GncOwner proj_job;
00180
00181
00182 gboolean reset_tax_tables;
00183 };
00184
00185
00186 void gnc_invoice_window_closeCB (GtkWidget *widget, gpointer data);
00187 void gnc_invoice_window_active_toggled_cb (GtkWidget *widget, gpointer data);
00188 gboolean gnc_invoice_window_leave_notes_cb (GtkWidget *widget, GdkEventFocus *event, gpointer data);
00189
00190 #define INV_WIDTH_PREFIX "invoice_reg"
00191 #define BILL_WIDTH_PREFIX "bill_reg"
00192 #define VOUCHER_WIDTH_PREFIX "voucher_reg"
00193
00194 static void gnc_invoice_update_window (InvoiceWindow *iw, GtkWidget *widget);
00195 static InvoiceWindow * gnc_ui_invoice_modify (GncInvoice *invoice);
00196
00197
00198
00199
00200 static GtkWidget *
00201 iw_get_window (InvoiceWindow *iw)
00202 {
00203 if (iw->page)
00204 return gnc_plugin_page_get_window(iw->page);
00205 return iw->dialog;
00206 }
00207
00208 GtkWidget *
00209 gnc_invoice_get_register(InvoiceWindow *iw)
00210 {
00211 if (iw)
00212 return (GtkWidget *)iw->reg;
00213 return NULL;
00214 }
00215
00216
00217
00218
00219 static gboolean
00220 iw_ask_unpost (InvoiceWindow *iw)
00221 {
00222 GtkWidget *dialog, *toggle, *pixmap;
00223 GladeXML *xml;
00224 gint response;
00225 char *s;
00226
00227 xml = gnc_glade_xml_new ("invoice.glade", "Unpost Message Dialog");
00228 dialog = glade_xml_get_widget (xml, "Unpost Message Dialog");
00229 toggle = glade_xml_get_widget (xml, "yes_tt_reset");
00230 pixmap = glade_xml_get_widget (xml, "q_pixmap");
00231
00232 gtk_window_set_transient_for (GTK_WINDOW(dialog),
00233 GTK_WINDOW(iw_get_window(iw)));
00234
00235 iw->reset_tax_tables = FALSE;
00236
00237 s = gnome_program_locate_file (NULL,
00238 GNOME_FILE_DOMAIN_PIXMAP,
00239 "gnome-question.png", TRUE, NULL);
00240 if (s) {
00241 pixmap = gtk_image_new_from_file(s);
00242 g_free(s);
00243 }
00244
00245 gtk_widget_show_all(dialog);
00246
00247 response = gtk_dialog_run(GTK_DIALOG(dialog));
00248 if (response == GTK_RESPONSE_OK)
00249 iw->reset_tax_tables =
00250 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle));
00251
00252 gtk_widget_destroy(dialog);
00253 return (response == GTK_RESPONSE_OK);
00254 }
00255
00256
00257
00258
00259 static GncInvoice *
00260 iw_get_invoice (InvoiceWindow *iw)
00261 {
00262 if (!iw)
00263 return NULL;
00264
00265 return gncInvoiceLookup (iw->book, &iw->invoice_guid);
00266 }
00267
00268 static void gnc_ui_to_invoice (InvoiceWindow *iw, GncInvoice *invoice)
00269 {
00270 GtkTextBuffer* text_buffer;
00271 GtkTextIter start, end;
00272 gchar *text;
00273 Timespec ts;
00274
00275 if (iw->dialog_type == VIEW_INVOICE)
00276 return;
00277
00278 gnc_suspend_gui_refresh ();
00279
00280 gncInvoiceBeginEdit (invoice);
00281
00282 if (iw->active_check)
00283 gncInvoiceSetActive (invoice, gtk_toggle_button_get_active
00284 (GTK_TOGGLE_BUTTON (iw->active_check)));
00285
00286 text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(iw->notes_text));
00287 gtk_text_buffer_get_bounds (text_buffer, &start, &end);
00288 text = gtk_text_buffer_get_text (text_buffer, &start, &end, FALSE);
00289 gncInvoiceSetNotes (invoice, text);
00290
00291 if (iw->to_charge_edit)
00292 gncInvoiceSetToChargeAmount (invoice,
00293 gnc_amount_edit_get_amount
00294 (GNC_AMOUNT_EDIT (iw->to_charge_edit)));
00295
00296
00297 if (iw->dialog_type != EDIT_INVOICE) {
00298 gncInvoiceSetID (invoice, gtk_editable_get_chars
00299 (GTK_EDITABLE (iw->id_entry), 0, -1));
00300 gncInvoiceSetBillingID (invoice, gtk_editable_get_chars
00301 (GTK_EDITABLE (iw->billing_id_entry), 0, -1));
00302 gncInvoiceSetTerms (invoice, iw->terms);
00303
00304 ts = gnc_date_edit_get_date_ts (GNC_DATE_EDIT (iw->opened_date));
00305 gncInvoiceSetDateOpened (invoice, ts);
00306
00307 gnc_owner_get_owner (iw->owner_choice, &(iw->owner));
00308 if (iw->job_choice)
00309 gnc_owner_get_owner (iw->job_choice, &(iw->job));
00310
00311
00312 if (gncOwnerGetJob (&(iw->job)))
00313 gncInvoiceSetOwner (invoice, &(iw->job));
00314 else
00315 gncInvoiceSetOwner (invoice, &(iw->owner));
00316
00317
00318 gncInvoiceSetCurrency (invoice, gncOwnerGetCurrency (&iw->owner));
00319
00320
00321 if (gncOwnerGetJob (&iw->proj_job))
00322 gncInvoiceSetBillTo (invoice, &iw->proj_job);
00323 else
00324 gncInvoiceSetBillTo (invoice, &iw->proj_cust);
00325 }
00326
00327 gncInvoiceCommitEdit (invoice);
00328 gnc_resume_gui_refresh ();
00329 }
00330
00331 static gboolean
00332 gnc_invoice_window_verify_ok (InvoiceWindow *iw)
00333 {
00334 const char *res;
00335 gchar *string;
00336
00337
00338 if (!gnc_entry_ledger_check_close (iw_get_window(iw), iw->ledger))
00339 return FALSE;
00340
00341
00342 gnc_owner_get_owner (iw->owner_choice, &(iw->owner));
00343 res = gncOwnerGetName (&(iw->owner));
00344 if (res == NULL || safe_strcmp (res, "") == 0) {
00345 gnc_error_dialog (iw_get_window(iw),
00346
00347
00348
00349
00350
00351 _("You need to supply Billing Information."));
00352 return FALSE;
00353 }
00354
00355
00356 res = gtk_entry_get_text (GTK_ENTRY (iw->id_entry));
00357 if (safe_strcmp (res, "") == 0) {
00358
00359
00360
00361
00362 string = g_strdup_printf ("%.6" G_GINT64_FORMAT,
00363 gncInvoiceNextID(iw->book, &(iw->owner)));
00364 gtk_entry_set_text (GTK_ENTRY (iw->id_entry), string);
00365 g_free(string);
00366 }
00367
00368 return TRUE;
00369 }
00370
00371 static gboolean
00372 gnc_invoice_window_ok_save (InvoiceWindow *iw)
00373 {
00374 if (!gnc_invoice_window_verify_ok (iw))
00375 return FALSE;
00376
00377 {
00378 GncInvoice *invoice = iw_get_invoice (iw);
00379 if (invoice) {
00380 gnc_ui_to_invoice (iw, invoice);
00381 }
00382
00383 iw->created_invoice = invoice;
00384 }
00385 return TRUE;
00386 }
00387
00388 void
00389 gnc_invoice_window_ok_cb (GtkWidget *widget, gpointer data)
00390 {
00391 InvoiceWindow *iw = data;
00392
00393 if (!gnc_invoice_window_ok_save (iw))
00394 return;
00395
00396
00397 iw->invoice_guid = *xaccGUIDNULL ();
00398
00399
00400
00401
00402
00403 if (iw->dialog_type == NEW_INVOICE && iw->created_invoice)
00404 gnc_ui_invoice_edit (iw->created_invoice);
00405
00406 gnc_close_gui_component (iw->component_id);
00407 }
00408
00409 void
00410 gnc_invoice_window_cancel_cb (GtkWidget *widget, gpointer data)
00411 {
00412 InvoiceWindow *iw = data;
00413
00414 gnc_close_gui_component (iw->component_id);
00415 }
00416
00417 void
00418 gnc_invoice_window_help_cb (GtkWidget *widget, gpointer data)
00419 {
00420 gnc_gnome_help(HF_HELP, HL_USAGE);
00421 }
00422
00423 void
00424 gnc_invoice_window_destroy_cb (GtkWidget *widget, gpointer data)
00425 {
00426 InvoiceWindow *iw = data;
00427 GncInvoice *invoice = iw_get_invoice (iw);
00428
00429 gnc_suspend_gui_refresh ();
00430
00431 if (iw->dialog_type == NEW_INVOICE && invoice != NULL) {
00432 gncInvoiceBeginEdit (invoice);
00433 gncInvoiceDestroy (invoice);
00434 iw->invoice_guid = *xaccGUIDNULL ();
00435 }
00436
00437 gnc_entry_ledger_destroy (iw->ledger);
00438 gnc_unregister_gui_component (iw->component_id);
00439 gtk_widget_destroy(widget);
00440 gnc_resume_gui_refresh ();
00441
00442 g_free (iw);
00443 }
00444
00445 void
00446 gnc_invoice_window_closeCB (GtkWidget *widget, gpointer data)
00447 {
00448 gnc_invoice_window_ok_cb (widget, data);
00449 }
00450
00451 void
00452 gnc_invoice_window_editCB (GtkWidget *widget, gpointer data)
00453 {
00454 InvoiceWindow *iw = data;
00455 GncInvoice *invoice = iw_get_invoice (iw);
00456
00457 if (invoice)
00458 gnc_ui_invoice_modify (invoice);
00459 }
00460
00461 void
00462 gnc_invoice_window_recordCB (GtkWidget *widget, gpointer data)
00463 {
00464 InvoiceWindow *iw = data;
00465
00466 if (!iw || !iw->ledger)
00467 return;
00468
00469 if (!gnc_entry_ledger_commit_entry (iw->ledger))
00470 return;
00471
00472 gnucash_register_goto_next_virt_row (iw->reg);
00473 }
00474
00475 void
00476 gnc_invoice_window_cancelCB (GtkWidget *widget, gpointer data)
00477 {
00478 InvoiceWindow *iw = data;
00479
00480 if (!iw || !iw->ledger)
00481 return;
00482
00483 gnc_entry_ledger_cancel_cursor_changes (iw->ledger);
00484 }
00485
00486 void
00487 gnc_invoice_window_deleteCB (GtkWidget *widget, gpointer data)
00488 {
00489 InvoiceWindow *iw = data;
00490 GncEntry *entry;
00491
00492 if (!iw || !iw->ledger)
00493 return;
00494
00495
00496 entry = gnc_entry_ledger_get_current_entry (iw->ledger);
00497 if (!entry) {
00498 gnc_entry_ledger_cancel_cursor_changes (iw->ledger);
00499 return;
00500 }
00501
00502
00503 if (entry == gnc_entry_ledger_get_blank_entry (iw->ledger)) {
00504 gnc_entry_ledger_cancel_cursor_changes (iw->ledger);
00505 return;
00506 }
00507
00508
00509 {
00510 const char *message = _("Are you sure you want to delete the "
00511 "selected entry?");
00512 const char *order_warn = _("This entry is attached to an order and "
00513 "will be deleted from that as well!");
00514 char *msg;
00515 gboolean result;
00516
00517 if (gncEntryGetOrder (entry))
00518 msg = g_strconcat (message, "\n\n", order_warn, (char *)NULL);
00519 else
00520 msg = g_strdup (message);
00521
00522 result = gnc_verify_dialog (iw_get_window(iw), FALSE, msg);
00523 g_free (msg);
00524
00525 if (!result)
00526 return;
00527 }
00528
00529
00530 gnc_entry_ledger_delete_current_entry (iw->ledger);
00531 return;
00532 }
00533
00534 void
00535 gnc_invoice_window_duplicateCB (GtkWidget *widget, gpointer data)
00536 {
00537 InvoiceWindow *iw = data;
00538
00539 if (!iw || !iw->ledger)
00540 return;
00541
00542 gnc_entry_ledger_duplicate_current_entry (iw->ledger);
00543 }
00544
00545 void
00546 gnc_invoice_window_blankCB (GtkWidget *widget, gpointer data)
00547 {
00548 InvoiceWindow *iw = data;
00549
00550 if (!iw || !iw->ledger)
00551 return;
00552
00553 if (!gnc_entry_ledger_commit_entry (iw->ledger))
00554 return;
00555
00556 {
00557 VirtualCellLocation vcell_loc;
00558 GncEntry *blank;
00559
00560 blank = gnc_entry_ledger_get_blank_entry (iw->ledger);
00561 if (blank == NULL)
00562 return;
00563
00564 if (gnc_entry_ledger_get_entry_virt_loc (iw->ledger, blank, &vcell_loc))
00565 gnucash_register_goto_virt_cell (iw->reg, vcell_loc);
00566 }
00567 }
00568
00569 void
00570 gnc_invoice_window_printCB (GtkWidget *widget, gpointer data)
00571 {
00572 InvoiceWindow *iw = data;
00573 GncInvoice *invoice = iw_get_invoice (iw);
00574 SCM func, arg;
00575 SCM args = SCM_EOL;
00576 int report_id;
00577
00578 g_return_if_fail (invoice);
00579
00580 func = scm_c_eval_string ("gnc:invoice-report-create");
00581 g_return_if_fail (SCM_PROCEDUREP (func));
00582
00583 arg = SWIG_NewPointerObj(invoice, SWIG_TypeQuery("_p__gncInvoice"), 0);
00584 args = scm_cons (arg, args);
00585
00586
00587
00588 arg = scm_apply (func, args, SCM_EOL);
00589 g_return_if_fail (SCM_EXACTP (arg));
00590 report_id = scm_num2int (arg, SCM_ARG1, __FUNCTION__);
00591
00592
00593 if (report_id >= 0)
00594 reportWindow (report_id);
00595 }
00596
00597 void
00598 gnc_invoice_window_postCB (GtkWidget *widget, gpointer data)
00599 {
00600 InvoiceWindow *iw = data;
00601 GncInvoice *invoice;
00602 char *message, *memo, *ddue_label, *post_label, *acct_label, *question_label;
00603 Account *acc = NULL;
00604 GList * acct_types = NULL;
00605 Timespec ddue, postdate;
00606 gboolean accumulate;
00607 QofInstance *owner_inst;
00608 KvpFrame *kvpf;
00609 KvpValue *kvp_val;
00610
00611
00612 if (!gnc_invoice_window_verify_ok (iw))
00613 return;
00614
00615 invoice = iw_get_invoice (iw);
00616 if (!invoice)
00617 return;
00618
00619
00620 invoice = iw_get_invoice (iw);
00621 if (gncInvoiceGetEntries (invoice) == NULL) {
00622 gnc_error_dialog (iw_get_window(iw),
00623 _("The Invoice must have at least one Entry."));
00624 return;
00625 }
00626
00627
00628 if (gnc_numeric_negative_p(gncInvoiceGetTotal(invoice))) {
00629 gnc_error_dialog(iw_get_window(iw),
00630 _("You may not post an invoice with a negative total value."));
00631 return;
00632 }
00633
00634 if (iw->total_cash_label &&
00635 gnc_numeric_negative_p(gncInvoiceGetTotalOf(invoice, GNC_PAYMENT_CASH))) {
00636 gnc_error_dialog(iw_get_window(iw),
00637 _("You may not post an expense voucher with a negative total cash value."));
00638 return;
00639 }
00640
00641
00642
00643
00644 message = _("Do you really want to post the invoice?");
00645 ddue_label = _("Due Date");
00646 post_label = _("Post Date");
00647 acct_label = _("Post to Account");
00648 question_label = _("Accumulate Splits?");
00649
00650
00651 acct_types = gnc_business_account_types (&(iw->owner));
00652
00653
00654 timespecFromTime_t (&postdate, time(NULL));
00655 ddue = postdate;
00656 memo = NULL;
00657
00658 owner_inst = qofOwnerGetOwner (gncOwnerGetEndOwner (&(iw->owner)));
00659 kvpf = qof_instance_get_slots (owner_inst);
00660 acc = xaccAccountLookup (kvp_frame_get_guid (kvpf, LAST_POSTED_TO_ACCT),
00661 iw->book);
00662
00663
00664 accumulate = gnc_gconf_get_bool(GCONF_SECTION_INVOICE, "accumulate_splits", NULL);
00665
00666 if (!gnc_dialog_dates_acct_question_parented (iw_get_window(iw), message, ddue_label,
00667 post_label, acct_label, question_label, TRUE,
00668 acct_types, iw->book, iw->terms,
00669 &ddue, &postdate, &memo, &acc, &accumulate))
00670 return;
00671
00672
00673
00674
00675
00676 gnc_suspend_gui_refresh ();
00677 gncInvoiceBeginEdit (invoice);
00678 gnc_invoice_window_ok_save (iw);
00679
00680
00681 kvp_val = kvp_value_new_guid (qof_instance_get_guid (QOF_INSTANCE (acc)));;
00682 qof_begin_edit (owner_inst);
00683 kvp_frame_set_slot_nc (kvpf, LAST_POSTED_TO_ACCT, kvp_val);
00684 qof_instance_set_dirty (owner_inst);
00685 qof_commit_edit (owner_inst);
00686
00687
00688 gncInvoicePostToAccount (invoice, acc, &postdate, &ddue, memo, accumulate);
00689 gncInvoiceCommitEdit (invoice);
00690 gnc_resume_gui_refresh ();
00691
00692 if (memo)
00693 g_free (memo);
00694
00695
00696 iw->dialog_type = VIEW_INVOICE;
00697 gnc_entry_ledger_set_readonly (iw->ledger, TRUE);
00698
00699
00700 gnc_invoice_update_window (iw, NULL);
00701 gnc_table_refresh_gui (gnc_entry_ledger_get_table (iw->ledger), FALSE);
00702 }
00703
00704 void
00705 gnc_invoice_window_unpostCB (GtkWidget *widget, gpointer data)
00706 {
00707 InvoiceWindow *iw = data;
00708 GncInvoice *invoice;
00709 gboolean result;
00710
00711 invoice = iw_get_invoice (iw);
00712 if (!invoice)
00713 return;
00714
00715
00716 result = iw_ask_unpost(iw);
00717 if (!result) return;
00718
00719
00720 gnc_suspend_gui_refresh ();
00721 result = gncInvoiceUnpost (invoice, iw->reset_tax_tables);
00722 gnc_resume_gui_refresh ();
00723 if (!result) return;
00724
00725
00726 iw->dialog_type = EDIT_INVOICE;
00727 gnc_entry_ledger_set_readonly (iw->ledger, FALSE);
00728 gnc_invoice_update_window (iw, NULL);
00729 gnc_table_refresh_gui (gnc_entry_ledger_get_table (iw->ledger), FALSE);
00730 }
00731
00732 void gnc_invoice_window_cut_cb (GtkWidget *widget, gpointer data)
00733 {
00734 InvoiceWindow *iw = data;
00735 gnucash_register_cut_clipboard (iw->reg);
00736 }
00737
00738 void gnc_invoice_window_copy_cb (GtkWidget *widget, gpointer data)
00739 {
00740 InvoiceWindow *iw = data;
00741 gnucash_register_copy_clipboard (iw->reg);
00742 }
00743
00744 void gnc_invoice_window_paste_cb (GtkWidget *widget, gpointer data)
00745 {
00746 InvoiceWindow *iw = data;
00747 gnucash_register_paste_clipboard (iw->reg);
00748 }
00749
00750 void gnc_invoice_window_new_invoice_cb (GtkWidget *widget, gpointer data)
00751 {
00752 InvoiceWindow *iw = data;
00753 if (gncOwnerGetJob (&iw->job)) {
00754 gnc_ui_invoice_new (&iw->job, iw->book);
00755 } else {
00756 gnc_ui_invoice_new (&iw->owner, iw->book);
00757 }
00758 }
00759
00760 void gnc_business_call_owner_report (GncOwner *owner, Account *acc)
00761 {
00762 int id;
00763 SCM args;
00764 SCM func;
00765 SCM arg;
00766
00767 g_return_if_fail (owner);
00768
00769 args = SCM_EOL;
00770
00771 func = scm_c_eval_string ("gnc:owner-report-create");
00772 g_return_if_fail (SCM_PROCEDUREP (func));
00773
00774 if (acc) {
00775 swig_type_info * qtype = SWIG_TypeQuery("_p_Account");
00776 g_return_if_fail (qtype);
00777
00778 arg = SWIG_NewPointerObj(acc, qtype, 0);
00779 g_return_if_fail (arg != SCM_UNDEFINED);
00780 args = scm_cons (arg, args);
00781 } else {
00782 args = scm_cons (SCM_BOOL_F, args);
00783 }
00784
00785 arg = SWIG_NewPointerObj(owner, SWIG_TypeQuery("_p__gncOwner"), 0);
00786 g_return_if_fail (arg != SCM_UNDEFINED);
00787 args = scm_cons (arg, args);
00788
00789
00790 arg = scm_apply (func, args, SCM_EOL);
00791 g_return_if_fail (SCM_EXACTP (arg));
00792 id = scm_num2int (arg, SCM_ARG1, __FUNCTION__);
00793
00794 if (id >= 0)
00795 reportWindow (id);
00796 }
00797
00798 void gnc_invoice_window_report_owner_cb (GtkWidget *widget, gpointer data)
00799 {
00800 InvoiceWindow *iw = data;
00801 gnc_business_call_owner_report (&iw->owner, NULL);
00802 }
00803
00804 void gnc_invoice_window_payment_cb (GtkWidget *widget, gpointer data)
00805 {
00806 InvoiceWindow *iw = data;
00807 GncInvoice *invoice = iw_get_invoice(iw);
00808
00809 if (gncOwnerGetJob (&iw->job))
00810 gnc_ui_payment_new_with_invoice (&iw->job, iw->book, invoice);
00811 else
00812 gnc_ui_payment_new_with_invoice (&iw->owner, iw->book, invoice);
00813 }
00814
00815
00816
00817 void
00818 gnc_invoice_window_sort (InvoiceWindow *iw, invoice_sort_type_t sort_code)
00819 {
00820 QueryNew *query = gnc_entry_ledger_get_query (iw->ledger);
00821 GSList *p1 = NULL, *p2 = NULL, *p3 = NULL, *standard;
00822
00823 if (iw->last_sort == sort_code)
00824 return;
00825
00826 standard = g_slist_prepend (NULL, QUERY_DEFAULT_SORT);
00827
00828 switch (sort_code)
00829 {
00830 case BY_STANDARD:
00831 p1 = standard;
00832 break;
00833 case BY_DATE:
00834 p1 = g_slist_prepend (p1, ENTRY_DATE);
00835 p2 = standard;
00836 break;
00837 case BY_DATE_ENTERED:
00838 p1 = g_slist_prepend (p1, ENTRY_DATE_ENTERED);
00839 p2 = standard;
00840 break;
00841 case BY_DESC:
00842 p1 = g_slist_prepend (p1, ENTRY_DESC);
00843 p2 = standard;
00844 break;
00845 case BY_QTY:
00846 p1 = g_slist_prepend (p1, ENTRY_QTY);
00847 p2 = standard;
00848 break;
00849 case BY_PRICE:
00850 p1 = g_slist_prepend (p1, ((iw->owner.type == GNC_OWNER_CUSTOMER) ?
00851 ENTRY_IPRICE : ENTRY_BPRICE));
00852 p2 = standard;
00853 break;
00854 default:
00855 g_slist_free (standard);
00856 g_return_if_fail (FALSE);
00857 }
00858
00859 gncQuerySetSortOrder (query, p1, p2, p3);
00860 iw->last_sort = sort_code;
00861 gnc_entry_ledger_display_refresh (iw->ledger);
00862 }
00863
00864
00865
00866 void
00867 gnc_invoice_window_active_toggled_cb (GtkWidget *widget, gpointer data)
00868 {
00869 InvoiceWindow *iw = data;
00870 GncInvoice *invoice = iw_get_invoice(iw);
00871
00872 if (!invoice) return;
00873
00874 gncInvoiceSetActive (invoice,
00875 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
00876 }
00877
00878 gboolean
00879 gnc_invoice_window_leave_notes_cb (GtkWidget *widget, GdkEventFocus *event,
00880 gpointer data)
00881 {
00882 InvoiceWindow *iw = data;
00883 GncInvoice *invoice = iw_get_invoice(iw);
00884 GtkTextBuffer* text_buffer;
00885 GtkTextIter start, end;
00886 gchar *text;
00887
00888 if (!invoice) return FALSE;
00889
00890 text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(iw->notes_text));
00891 gtk_text_buffer_get_bounds (text_buffer, &start, &end);
00892 text = gtk_text_buffer_get_text (text_buffer, &start, &end, FALSE);
00893 gncInvoiceSetNotes (invoice, text);
00894 return FALSE;
00895 }
00896
00897 static gboolean
00898 gnc_invoice_window_leave_to_charge_cb (GtkWidget *widget, GdkEventFocus *event,
00899 gpointer data)
00900 {
00901 gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (widget));
00902 return FALSE;
00903 }
00904
00905 static void
00906 gnc_invoice_window_changed_to_charge_cb (GtkWidget *widget, gpointer data)
00907 {
00908 InvoiceWindow *iw = data;
00909 GncInvoice *invoice = iw_get_invoice(iw);
00910
00911 if (!invoice) return;
00912
00913 gncInvoiceSetToChargeAmount (invoice, gnc_amount_edit_get_amount
00914 (GNC_AMOUNT_EDIT (widget)));
00915 }
00916
00917 static GtkWidget *
00918 add_summary_label (GtkWidget *summarybar, const char *label_str)
00919 {
00920 GtkWidget *hbox;
00921 GtkWidget *label;
00922
00923 hbox = gtk_hbox_new(FALSE, 2);
00924 gtk_box_pack_start (GTK_BOX(summarybar), hbox, FALSE, FALSE, 5);
00925
00926 label = gtk_label_new (label_str);
00927 gtk_misc_set_alignment (GTK_MISC(label), 1.0, 0.5);
00928 gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
00929
00930 label = gtk_label_new ("");
00931 gtk_misc_set_alignment (GTK_MISC(label), 1.0, 0.5);
00932 gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
00933
00934 return label;
00935 }
00936
00937 GtkWidget *
00938 gnc_invoice_window_create_summary_bar (InvoiceWindow *iw)
00939 {
00940 GtkWidget *summarybar;
00941
00942 iw->total_label = NULL;
00943 iw->total_cash_label = NULL;
00944 iw->total_charge_label = NULL;
00945 iw->total_subtotal_label = NULL;
00946 iw->total_tax_label = NULL;
00947
00948 summarybar = gtk_hbox_new (FALSE, 4);
00949
00950 iw->total_label = add_summary_label (summarybar, _("Total:"));
00951
00952 switch (gncOwnerGetType (&iw->owner)) {
00953 case GNC_OWNER_CUSTOMER:
00954 case GNC_OWNER_VENDOR:
00955 iw->total_subtotal_label= add_summary_label (summarybar, _("Subtotal:"));
00956 iw->total_tax_label = add_summary_label (summarybar, _("Tax:"));
00957 break;
00958
00959 case GNC_OWNER_EMPLOYEE:
00960 iw->total_cash_label = add_summary_label (summarybar, _("Total Cash:"));
00961 iw->total_charge_label = add_summary_label (summarybar, _("Total Charge:"));
00962 break;
00963
00964 default:
00965 break;
00966 }
00967
00968 gtk_widget_show_all(summarybar);
00969 return summarybar;
00970 }
00971
00972 static int
00973 gnc_invoice_job_changed_cb (GtkWidget *widget, gpointer data)
00974 {
00975 InvoiceWindow *iw = data;
00976 GncInvoice *invoice;
00977 char const *msg = "";
00978
00979 if (!iw)
00980 return FALSE;
00981
00982 if (iw->dialog_type == VIEW_INVOICE)
00983 return FALSE;
00984
00985 gnc_owner_get_owner (iw->job_choice, &(iw->job));
00986 invoice = iw_get_invoice (iw);
00987
00988 if (iw->dialog_type == EDIT_INVOICE)
00989 return FALSE;
00990
00991 msg = gncJobGetReference (gncOwnerGetJob (&(iw->job)));
00992 gtk_entry_set_text (GTK_ENTRY (iw->billing_id_entry), msg ? msg : "");
00993
00994 return FALSE;
00995
00996 }
00997
00998 static GNCSearchWindow *
00999 gnc_invoice_select_job_cb (gpointer jobp, gpointer user_data)
01000 {
01001 GncJob *j = jobp;
01002 InvoiceWindow *iw = user_data;
01003 GncOwner owner, *ownerp;
01004
01005 if (!iw) return NULL;
01006
01007 if (j) {
01008 ownerp = gncJobGetOwner (j);
01009 gncOwnerCopy (ownerp, &owner);
01010 } else
01011 gncOwnerCopy (&(iw->owner), &owner);
01012
01013 return gnc_job_search (j, &owner, iw->book);
01014 }
01015
01016 static void
01017 gnc_invoice_update_job_choice (InvoiceWindow *iw)
01018 {
01019 if (iw->job_choice)
01020 gtk_container_remove (GTK_CONTAINER (iw->job_box), iw->job_choice);
01021
01022
01023 if (iw->owner.owner.undefined == NULL) {
01024 iw->job_choice = NULL;
01025
01026 } else
01027 switch (iw->dialog_type) {
01028 case VIEW_INVOICE:
01029 case EDIT_INVOICE:
01030 iw->job_choice =
01031 gnc_owner_edit_create (NULL, iw->job_box, iw->book, &(iw->job));
01032 break;
01033 case NEW_INVOICE:
01034 case MOD_INVOICE:
01035 iw->job_choice =
01036 gnc_general_search_new (GNC_JOB_MODULE_NAME, _("Select..."),
01037 gnc_invoice_select_job_cb, iw);
01038
01039 gnc_general_search_set_selected (GNC_GENERAL_SEARCH (iw->job_choice),
01040 gncOwnerGetJob (&iw->job));
01041 gnc_general_search_allow_clear (GNC_GENERAL_SEARCH (iw->job_choice),
01042 TRUE);
01043 gtk_box_pack_start (GTK_BOX (iw->job_box), iw->job_choice,
01044 TRUE, TRUE, 0);
01045
01046 g_signal_connect (G_OBJECT (iw->job_choice), "changed",
01047 G_CALLBACK (gnc_invoice_job_changed_cb), iw);
01048 break;
01049 }
01050
01051 if (iw->job_choice)
01052 gtk_widget_show_all (iw->job_choice);
01053 }
01054
01055 static GNCSearchWindow *
01056 gnc_invoice_select_proj_job_cb (gpointer jobp, gpointer user_data)
01057 {
01058 GncJob *j = jobp;
01059 InvoiceWindow *iw = user_data;
01060 GncOwner owner, *ownerp;
01061
01062 if (!iw) return NULL;
01063
01064 if (j) {
01065 ownerp = gncJobGetOwner (j);
01066 gncOwnerCopy (ownerp, &owner);
01067 } else
01068 gncOwnerCopy (&(iw->proj_cust), &owner);
01069
01070 return gnc_job_search (j, &owner, iw->book);
01071 }
01072
01073 static int
01074 gnc_invoice_proj_job_changed_cb (GtkWidget *widget, gpointer data)
01075 {
01076 InvoiceWindow *iw = data;
01077
01078 if (!iw)
01079 return FALSE;
01080
01081 if (iw->dialog_type == VIEW_INVOICE)
01082 return FALSE;
01083
01084 gnc_owner_get_owner (iw->proj_job_choice, &(iw->proj_job));
01085 return FALSE;
01086 }
01087
01088 static void
01089 gnc_invoice_update_proj_job (InvoiceWindow *iw)
01090 {
01091 if (iw->proj_job_choice)
01092 gtk_container_remove (GTK_CONTAINER (iw->proj_job_box),
01093 iw->proj_job_choice);
01094
01095 switch (iw->dialog_type) {
01096 case VIEW_INVOICE:
01097 case EDIT_INVOICE:
01098 iw->proj_job_choice =
01099 gnc_owner_edit_create (NULL, iw->proj_job_box, iw->book, &(iw->job));
01100 break;
01101 case NEW_INVOICE:
01102 case MOD_INVOICE:
01103 if (iw->proj_cust.owner.undefined == NULL) {
01104 iw->proj_job_choice = NULL;
01105 } else {
01106 iw->proj_job_choice =
01107 gnc_general_search_new (GNC_JOB_MODULE_NAME, _("Select..."),
01108 gnc_invoice_select_proj_job_cb, iw);
01109
01110 gnc_general_search_set_selected (GNC_GENERAL_SEARCH(iw->proj_job_choice),
01111 gncOwnerGetJob (&iw->proj_job));
01112 gnc_general_search_allow_clear (GNC_GENERAL_SEARCH (iw->proj_job_choice),
01113 TRUE);
01114 gtk_box_pack_start (GTK_BOX (iw->proj_job_box), iw->proj_job_choice,
01115 TRUE, TRUE, 0);
01116
01117 g_signal_connect (G_OBJECT (iw->proj_job_choice), "changed",
01118 G_CALLBACK (gnc_invoice_proj_job_changed_cb), iw);
01119 }
01120 break;
01121 }
01122
01123 if (iw->proj_job_choice)
01124 gtk_widget_show_all (iw->proj_job_choice);
01125 }
01126
01127 static int
01128 gnc_invoice_owner_changed_cb (GtkWidget *widget, gpointer data)
01129 {
01130 InvoiceWindow *iw = data;
01131 GncBillTerm *term = NULL;
01132 GncOwner owner;
01133
01134 if (!iw)
01135 return FALSE;
01136
01137 if (iw->dialog_type == VIEW_INVOICE)
01138 return FALSE;
01139
01140 gncOwnerCopy (&(iw->owner), &owner);
01141 gnc_owner_get_owner (iw->owner_choice, &owner);
01142
01143
01144 if (!gncOwnerEqual (&owner, &(iw->owner))) {
01145 GncInvoice *invoice;
01146
01147 gncOwnerCopy (&owner, &(iw->owner));
01148 gncOwnerInitJob (&(iw->job), NULL);
01149 invoice = iw_get_invoice (iw);
01150 gnc_entry_ledger_reset_query (iw->ledger);
01151 }
01152
01153 if (iw->dialog_type == EDIT_INVOICE)
01154 return FALSE;
01155
01156 switch (gncOwnerGetType (&(iw->owner))) {
01157 case GNC_OWNER_CUSTOMER:
01158 term = gncCustomerGetTerms (gncOwnerGetCustomer (&(iw->owner)));
01159 break;
01160 case GNC_OWNER_VENDOR:
01161 term = gncVendorGetTerms (gncOwnerGetVendor (&(iw->owner)));
01162 break;
01163 case GNC_OWNER_EMPLOYEE:
01164 term = NULL;
01165 break;
01166 default:
01167 g_warning ("Unknown owner type: %d\n", gncOwnerGetType (&(iw->owner)));
01168 break;
01169 }
01170
01171
01172 iw->terms = term;
01173 gnc_ui_optionmenu_set_value (iw->terms_menu, iw->terms);
01174
01175 gnc_invoice_update_job_choice (iw);
01176
01177 return FALSE;
01178 }
01179
01180 static int
01181 gnc_invoice_proj_cust_changed_cb (GtkWidget *widget, gpointer data)
01182 {
01183 InvoiceWindow *iw = data;
01184 GncOwner owner;
01185
01186 if (!iw)
01187 return FALSE;
01188
01189 if (iw->dialog_type == VIEW_INVOICE)
01190 return FALSE;
01191
01192 gncOwnerCopy (&(iw->proj_cust), &owner);
01193 gnc_owner_get_owner (iw->proj_cust_choice, &owner);
01194
01195
01196 if (!gncOwnerEqual (&owner, &(iw->proj_cust))) {
01197 gncOwnerCopy (&owner, &(iw->proj_cust));
01198 gncOwnerInitJob (&(iw->proj_job), NULL);
01199 }
01200
01201 if (iw->dialog_type == EDIT_INVOICE)
01202 return FALSE;
01203
01204 gnc_invoice_update_proj_job (iw);
01205
01206 return FALSE;
01207 }
01208
01209 static void
01210 gnc_invoice_dialog_close_handler (gpointer user_data)
01211 {
01212 InvoiceWindow *iw = user_data;
01213
01214 if (iw) {
01215 gtk_widget_destroy (iw->dialog);
01216 }
01217 }
01218
01219 static void
01220 gnc_invoice_window_close_handler (gpointer user_data)
01221 {
01222 InvoiceWindow *iw = user_data;
01223
01224 if (iw) {
01225 gnc_main_window_close_page(iw->page);
01226 iw->page = NULL;
01227 }
01228 }
01229
01230 static void
01231 gnc_invoice_reset_total_label (GtkLabel *label, gnc_numeric amt, gnc_commodity *com)
01232 {
01233 char string[256];
01234
01235 amt = gnc_numeric_convert (amt, gnc_commodity_get_fraction(com), GNC_RND_ROUND);
01236 xaccSPrintAmount (string, amt, gnc_default_print_info (TRUE));
01237 gtk_label_set_text (label, string);
01238 }
01239
01240 static void
01241 gnc_invoice_redraw_all_cb (GnucashRegister *g_reg, gpointer data)
01242 {
01243 InvoiceWindow *iw = data;
01244 GncInvoice * invoice;
01245 gnc_commodity * currency;
01246 gnc_numeric amount, to_charge_amt = gnc_numeric_zero();
01247
01248 if (!iw)
01249 return;
01250
01251
01252
01253
01254 invoice = iw_get_invoice (iw);
01255 if (!invoice)
01256 return;
01257
01258 currency = gncInvoiceGetCurrency (invoice);
01259
01260 if (iw->total_label) {
01261 amount = gncInvoiceGetTotal (invoice);
01262 gnc_invoice_reset_total_label (GTK_LABEL (iw->total_label), amount, currency);
01263 }
01264
01265 if (iw->total_subtotal_label) {
01266 amount = gncInvoiceGetTotalSubtotal (invoice);
01267 gnc_invoice_reset_total_label (GTK_LABEL (iw->total_subtotal_label), amount, currency);
01268 }
01269
01270 if (iw->total_tax_label) {
01271 amount = gncInvoiceGetTotalTax (invoice);
01272 gnc_invoice_reset_total_label (GTK_LABEL (iw->total_tax_label), amount, currency);
01273 }
01274
01275
01276
01277 if (iw->to_charge_edit) {
01278 gnc_amount_edit_evaluate (GNC_AMOUNT_EDIT (iw->to_charge_edit));
01279 to_charge_amt = gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(iw->to_charge_edit));
01280 }
01281
01282 if (iw->total_cash_label) {
01283 amount = gncInvoiceGetTotalOf (invoice, GNC_PAYMENT_CASH);
01284 amount = gnc_numeric_sub (amount, to_charge_amt,
01285 gnc_commodity_get_fraction (currency), GNC_RND_ROUND);
01286 gnc_invoice_reset_total_label (GTK_LABEL (iw->total_cash_label), amount, currency);
01287 }
01288
01289 if (iw->total_charge_label) {
01290 amount = gncInvoiceGetTotalOf (invoice, GNC_PAYMENT_CARD);
01291 amount = gnc_numeric_add (amount, to_charge_amt,
01292 gnc_commodity_get_fraction (currency), GNC_RND_ROUND);
01293 gnc_invoice_reset_total_label (G