/** used to compare 2 iters and sort the by reconcile number first, and * by date and no transaction after * always put the white line below * \param model the GtkTreeModel * \param iter_1 * \param iter_2 * \return -1 if iter_1 is above iter_2 * */ gint gsb_transactions_list_sort_by_reconcile_nb ( gint transaction_number_1, gint transaction_number_2 ) { gint return_value; if ( gsb_data_transaction_get_reconcile_number ( transaction_number_1) == gsb_data_transaction_get_reconcile_number ( transaction_number_2)) return gsb_transactions_list_sort_by_date_and_no ( transaction_number_1, transaction_number_2 ); else { const gchar *temp_1; const gchar *temp_2; temp_1 = gsb_data_reconcile_get_name ( gsb_data_transaction_get_reconcile_number ( transaction_number_1)); temp_2 = gsb_data_reconcile_get_name ( gsb_data_transaction_get_reconcile_number ( transaction_number_2)); /* g_utf8_collate is said not very fast, must try with big big account to check * if it's enough, for me it's ok (cedric), eventually, change with gsb_strcasecmp */ return_value = g_utf8_collate ( g_utf8_casefold ( temp_1 ? temp_1 : "", -1 ), g_utf8_casefold ( temp_2 ? temp_2 : "", -1 )); } if ( return_value ) return return_value; else return gsb_transactions_list_sort_by_date_and_no ( transaction_number_1, transaction_number_2 ); }
/** * remove a reconcile * all the transactions marked by that reconcile will be marked P * and lose the link to that reconcile * * \param reconcile_number the reconcile we want to remove * * \return TRUE ok * */ gboolean gsb_data_reconcile_remove ( gint reconcile_number ) { struct_reconcile *reconcile; GSList *list_tmp; reconcile = gsb_data_reconcile_get_structure ( reconcile_number ); if (!reconcile) return FALSE; reconcile_list = g_list_remove ( reconcile_list, reconcile ); _gsb_data_reconcile_free ( reconcile ); /* remove that reconcile of the transactions */ list_tmp = gsb_data_transaction_get_complete_transactions_list (); while (list_tmp) { gint transaction_number = gsb_data_transaction_get_transaction_number (list_tmp -> data); if ( gsb_data_transaction_get_reconcile_number (transaction_number) == reconcile_number ) { gsb_data_transaction_set_reconcile_number ( transaction_number, 0 ); gsb_data_transaction_set_marked_transaction ( transaction_number, OPERATION_POINTEE ); } list_tmp = list_tmp -> next; } return TRUE; }
/** * function called when the user come to the manually association page * update the list of transactions to associate and fill the labels * * \param assistant * \param new_page * * \return FALSE * */ gboolean gsb_assistant_reconcile_config_update_manu_asso ( GtkWidget *assistant, gint new_page ) { gchar *string; GSList *tmp_list; gint transaction_number; GtkListStore *store; /* update the string containing the number of transactions to link */ string = g_strdup_printf (_("Still %d transactions to link with a reconciliation."), transactions_to_link); gtk_label_set_text ( GTK_LABEL (label_transactions_to_link_3), string); g_free (string); gtk_misc_set_alignment ( GTK_MISC (label_transactions_to_link_3), 0, 0.5 ); /* fill the list with the transactions to link */ store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (treeview_transactions_to_link))); gtk_list_store_clear (GTK_LIST_STORE (store)); tmp_list = gsb_data_transaction_get_transactions_list (); while (tmp_list) { transaction_number = gsb_data_transaction_get_transaction_number (tmp_list -> data); if ( gsb_data_transaction_get_marked_transaction (transaction_number) == OPERATION_RAPPROCHEE && !gsb_data_transaction_get_reconcile_number (transaction_number)) { gchar *amount_str; gchar *date_str; GtkTreeIter iter; date_str = gsb_format_gdate (gsb_data_transaction_get_date (transaction_number)); amount_str = utils_real_get_string (gsb_data_transaction_get_amount (transaction_number)); gtk_list_store_append ( GTK_LIST_STORE (store), &iter ); gtk_list_store_set ( GTK_LIST_STORE (store), &iter, TRANSACTION_DATE, date_str, TRANSACTION_PAYEE, gsb_data_payee_get_name (gsb_data_transaction_get_party_number (transaction_number), TRUE), TRANSACTION_AMOUNT, amount_str, TRANSACTION_ACCOUNT, gsb_data_account_get_name (gsb_data_transaction_get_account_number (transaction_number)), TRANSACTION_NUMBER, transaction_number, -1 ); g_free (amount_str); g_free (date_str); } tmp_list = tmp_list -> next; } return FALSE; }
/** * function called when the user come to the automatically association page * fill the label and show the button if possible * * \param assistant * \param new_page * * \return FALSE * */ gboolean gsb_assistant_reconcile_config_update_auto_asso ( GtkWidget *assistant, gint new_page ) { gchar *string; GSList *tmp_list; gint associate_number; /* update the string containing the number of transactions to link */ string = g_strdup_printf (_("Still %d transactions to link with a reconciliation."), transactions_to_link); gtk_label_set_text ( GTK_LABEL (label_transactions_to_link_2), string); g_free (string); gtk_misc_set_alignment ( GTK_MISC (label_transactions_to_link_2), 0, 0.5 ); /* calculate how many transactions can be associated automatically, * to avoid to do that 2 times, we set each transactions in a structure with * the associated number of bank reconciliation */ if (list_association) { g_slist_free (list_association); list_association = NULL; } tmp_list = gsb_data_transaction_get_transactions_list (); while (tmp_list) { gint transaction_number; transaction_number = gsb_data_transaction_get_transaction_number (tmp_list -> data); if (gsb_data_transaction_get_marked_transaction (transaction_number) == OPERATION_RAPPROCHEE && !gsb_data_transaction_get_reconcile_number (transaction_number)) { /* ok we are on a marked R transaction without reconcile number, * we search for that reconcile */ gint reconcile_number; reconcile_number = gsb_data_reconcile_get_number_by_date (gsb_data_transaction_get_date (transaction_number), gsb_data_transaction_get_account_number (transaction_number)); if (reconcile_number) { struct association_transaction_reconcile *association; association = g_malloc0 (sizeof (struct association_transaction_reconcile)); if (!association) { dialogue_error_memory (); return FALSE; } association -> transaction_number = transaction_number; association -> reconcile_number = reconcile_number; list_association = g_slist_append ( list_association, association ); } } tmp_list = tmp_list -> next; } /* set the number of possible links */ associate_number = g_slist_length (list_association); if (associate_number) { string = g_strdup_printf (_("Grisbi can associate %d transactions to a reconciliation.\n" "Please click on the launch button to create the links."), associate_number); gtk_widget_set_sensitive ( button_run_association, TRUE ); } else { string = my_strdup (_("There is no transaction that Grisbi can link.\n" "Check if you created all the necesssary reconciliations.")); gtk_widget_set_sensitive ( button_run_association, FALSE ); } gtk_label_set_text ( GTK_LABEL (label_possible_association), string); g_free (string); return FALSE; }
/** * function called to launch the reconcile_config assistant * calculate the number of transactions to link, and refuse to run the assistant if none * * \param * * \return GtkResponseType, the returned value from the assistant * */ GtkResponseType gsb_assistant_reconcile_config_run ( void ) { GtkResponseType return_value; GSList *transactions_list = NULL; GSList *tmp_list; gint transaction_number; GtkWidget *assistant; gchar* tmpstr; tmp_list = gsb_data_transaction_get_transactions_list (); while (tmp_list) { transaction_number = gsb_data_transaction_get_transaction_number (tmp_list -> data); if ( gsb_data_transaction_get_marked_transaction (transaction_number) == OPERATION_RAPPROCHEE && !gsb_data_transaction_get_reconcile_number (transaction_number)) transactions_list = g_slist_append ( transactions_list, GINT_TO_POINTER (transaction_number)); tmp_list = tmp_list -> next; } if (!transactions_list) { dialogue (_("No marked transactions without reconciliation found!")); return GTK_RESPONSE_CANCEL; } /* get the number of transactions to associate, we will decrease it for each association */ transactions_to_link = g_slist_length (transactions_list); /* come here if we have some orphan transactions * this can happen by 2 ways : * for old users of Grisbi, before i don't remember what version, there were no reconcile number, * the reconciled transactions were juste marked R * before the 0.6.0, ctrl R didn't permit to choose a reconciliation * * for the 2nd item, no problem, we show a list of reconciles and the user can choose what reconcile he wants * for the first item the problem is there is no reconcile number to go with that transactions... * so we will use the assistant to * -permit to create a reconcile directly (not possible normaly in the configuration * -permit to choose a reconcile number for each transactions without reconcile * - do an automatic find for reconcile, usefull in the first item, when very much * transactions without reconcile, but we need to make the old reconciles before, * and set the good date for all the reconciles (because grisbi set them automatically * at the first update to grisbi 0.6.0 )*/ /* first, create the assistant */ tmpstr = g_strdup_printf (_("Grisbi found %d marked transactions not associated with a reconciliation number, " "this can happen for old users of Grisbi or from a misuse of the Ctrl-R shortcut.\n\n" "This assistant will help you make the link between such transactions and a reconciliation.\n\n" "Before continuing, you should first check if all the dates of the existing reconciliations are good " "because Grisbi will try to guess them not very precisely " "(you will be able to create new reconciliations in the next step). " "Previous reconciliations will be available too."), transactions_to_link ); assistant = gsb_assistant_new ( _("Associate orphan transactions to a reconciliation"), tmpstr, "reconat.png", NULL ); g_free ( tmpstr ); gsb_assistant_add_page ( assistant, gsb_assistant_reconcile_config_page_menu (assistant), RECONCILE_ASSISTANT_MENU, RECONCILE_ASSISTANT_INTRO, RECONCILE_ASSISTANT_NEW_RECONCILE, NULL ); gsb_assistant_add_page ( assistant, gsb_assistant_reconcile_config_page_new_reconcile (), RECONCILE_ASSISTANT_NEW_RECONCILE, RECONCILE_ASSISTANT_MENU, RECONCILE_ASSISTANT_MENU, NULL ); gsb_assistant_add_page ( assistant, gsb_assistant_reconcile_config_page_automatically_associate (assistant), RECONCILE_ASSISTANT_AUTOMATICALLY_ASSOCIATE, RECONCILE_ASSISTANT_MENU, RECONCILE_ASSISTANT_MENU, G_CALLBACK (gsb_assistant_reconcile_config_update_auto_asso)); gsb_assistant_add_page ( assistant, gsb_assistant_reconcile_config_page_manually_associate (assistant), RECONCILE_ASSISTANT_MANUALLY_ASSOCIATE, RECONCILE_ASSISTANT_MENU, RECONCILE_ASSISTANT_MENU, G_CALLBACK (gsb_assistant_reconcile_config_update_manu_asso)); gsb_assistant_add_page ( assistant, gsb_assistant_reconcile_config_page_success (), RECONCILE_ASSISTANT_SUCCESS, RECONCILE_ASSISTANT_MENU, RECONCILE_ASSISTANT_MENU, NULL ); return_value = gsb_assistant_run (assistant); gtk_widget_destroy (assistant); return return_value; }
/** * export a transaction given in param in the file given in param * * \param transaction_number * \param csv_file * \param print_balance will set a balance for each transaction in the csv file * not set for archive export, set (but usefull ?) for account export * * \return TRUE ok, FALSE problem * */ static gboolean gsb_csv_export_transaction ( gint transaction_number, FILE *csv_file, gboolean print_balance ) { gsb_real amount; gint return_exponent; gint account_number; gchar* tmpstr; const GDate *value_date, *date; gint payment_method; account_number = gsb_data_transaction_get_account_number (transaction_number); /* Si c'est une ventilation d'opération (càd une opération fille), elle n'est pas traitée à la base du "if" mais plus loin, quand son opé ventilée sera exportée */ if ( gsb_data_transaction_get_mother_transaction_number (transaction_number) ) return TRUE; return_exponent = gsb_data_currency_get_floating_point ( gsb_data_account_get_currency (account_number)); /* met la date */ date = gsb_data_transaction_get_date ( transaction_number ); if ( date ) { CSV_CLEAR_FIELD (csv_field_date); csv_field_date = g_strdup_printf ("%d/%d/%d", g_date_get_day ( date ), g_date_get_month ( date ), g_date_get_year ( date ) ); } value_date = gsb_data_transaction_get_value_date ( transaction_number ); if ( value_date ) { CSV_CLEAR_FIELD (csv_field_date_val); csv_field_date_val = g_strdup_printf ("%d/%d/%d", g_date_get_day ( value_date ), g_date_get_month ( value_date ), g_date_get_year ( value_date ) ); } /* met le pointage */ CSV_CLEAR_FIELD (csv_field_pointage); switch ( gsb_data_transaction_get_marked_transaction ( transaction_number ) ) { case OPERATION_NORMALE: csv_field_pointage = my_strdup (""); break; case OPERATION_POINTEE: csv_field_pointage = my_strdup ("P"); break; case OPERATION_TELERAPPROCHEE: csv_field_pointage = my_strdup ("T"); break; case OPERATION_RAPPROCHEE: csv_field_pointage = my_strdup ("R"); break; } /* met les notes */ CSV_CLEAR_FIELD(csv_field_notes); if ( gsb_data_transaction_get_notes ( transaction_number ) ) csv_field_notes = my_strdup (gsb_data_transaction_get_notes ( transaction_number )); /* met le tiers */ CSV_CLEAR_FIELD(csv_field_tiers); csv_field_tiers = g_strdup ( gsb_data_payee_get_name ( gsb_data_transaction_get_party_number ( transaction_number ), FALSE ) ); /* met le numero du rapprochement */ if ( gsb_data_transaction_get_reconcile_number ( transaction_number ) ) { CSV_CLEAR_FIELD (csv_field_rappro); csv_field_rappro = my_strdup ( gsb_data_reconcile_get_name ( gsb_data_transaction_get_reconcile_number ( transaction_number ) ) ); } /* Met les informations bancaires de l'opération. Elles n'existent qu'au niveau de l'opération mère */ CSV_CLEAR_FIELD(csv_field_info_bank); if ( gsb_data_transaction_get_bank_references ( transaction_number ) ) { csv_field_info_bank = my_strdup ( gsb_data_transaction_get_bank_references ( transaction_number ) ); } /* met le montant, transforme la devise si necessaire */ amount = gsb_data_transaction_get_adjusted_amount ( transaction_number, return_exponent); CSV_CLEAR_FIELD (csv_field_credit); if (amount.mantissa >= 0 ) csv_field_credit = utils_real_get_string (amount); else csv_field_debit = utils_real_get_string (gsb_real_abs (amount)); /* met le cheque si c'est un type à numerotation automatique */ payment_method = gsb_data_transaction_get_method_of_payment_number ( transaction_number ); CSV_CLEAR_FIELD (csv_field_cheque); if (gsb_data_payment_get_automatic_numbering (payment_method)) csv_field_cheque = my_strdup ( gsb_data_transaction_get_method_of_payment_content ( transaction_number ) ); if ( gsb_data_transaction_get_budgetary_number ( transaction_number ) != -1 ) { CSV_CLEAR_FIELD (csv_field_imput); csv_field_imput = my_strdup ( gsb_data_budget_get_name ( gsb_data_transaction_get_budgetary_number ( transaction_number ), 0, "" ) ); if ( gsb_data_transaction_get_sub_budgetary_number ( transaction_number ) != -1 ) { CSV_CLEAR_FIELD (csv_field_sous_imput); csv_field_sous_imput = my_strdup ( gsb_data_budget_get_sub_budget_name ( gsb_data_transaction_get_budgetary_number ( transaction_number ), gsb_data_transaction_get_sub_budgetary_number ( transaction_number ), NULL ) ); } } /* Piece comptable */ CSV_CLEAR_FIELD (csv_field_piece); csv_field_piece = my_strdup ( gsb_data_transaction_get_voucher ( transaction_number ) ); /* Balance */ if (print_balance) { current_balance = gsb_real_add ( current_balance, amount ); CSV_CLEAR_FIELD (csv_field_solde); csv_field_solde = utils_real_get_string (current_balance); } /* Number */ CSV_CLEAR_FIELD (csv_field_operation); csv_field_operation = g_strdup_printf("%d", transaction_number ); /* Account name */ CSV_CLEAR_FIELD (csv_field_account); csv_field_account = my_strdup (gsb_data_account_get_name (account_number)); /* Financial Year */ if ( gsb_data_transaction_get_financial_year_number ( transaction_number ) != -1 ) { CSV_CLEAR_FIELD (csv_field_exercice ); csv_field_exercice = my_strdup (gsb_data_fyear_get_name(gsb_data_transaction_get_financial_year_number ( transaction_number ))); } /* on met soit un virement, soit une ventilation, soit les catégories */ /* Si c'est une opération ventilée, on recherche toutes les ventilations de cette opération et on les traite immédiatement. */ /* et les met à la suite */ /* la catégorie de l'opé sera celle de la première opé de ventilation */ if ( gsb_data_transaction_get_split_of_transaction ( transaction_number ) ) { GSList *pSplitTransactionList; CSV_CLEAR_FIELD (csv_field_categ); csv_field_categ = my_strdup (_("Split of transaction")); csv_add_record(csv_file,FALSE, print_balance); pSplitTransactionList = gsb_data_transaction_get_transactions_list (); while ( pSplitTransactionList ) { gint pSplitTransaction; pSplitTransaction = gsb_data_transaction_get_transaction_number ( pSplitTransactionList -> data ); if ( gsb_data_transaction_get_account_number ( pSplitTransaction ) == gsb_data_transaction_get_account_number (transaction_number) && gsb_data_transaction_get_mother_transaction_number ( pSplitTransaction ) == transaction_number ) { /* on commence par mettre la catég et sous categ de l'opé et de l'opé de ventilation */ CSV_CLEAR_FIELD (csv_field_ventil); csv_field_ventil = my_strdup (_("B")); /* -> mark */ CSV_CLEAR_FIELD (csv_field_operation); csv_field_operation = g_strdup_printf("%d", pSplitTransaction ); if ( gsb_data_transaction_get_contra_transaction_number ( pSplitTransaction ) > 0) { /* c'est un virement */ CSV_CLEAR_FIELD (csv_field_categ); csv_field_categ = my_strdup (_("Transfer")); tmpstr = g_strconcat ( "[", gsb_data_account_get_name ( gsb_data_transaction_get_contra_transaction_account ( pSplitTransaction ) ), "]", NULL ); /* TODO dOm : is it necessary to duplicate memory with my_strdup since it was already newly allocated memory ? */ CSV_CLEAR_FIELD (csv_field_sous_categ); csv_field_sous_categ = my_strdup (tmpstr); g_free ( tmpstr ); } else { if ( gsb_data_transaction_get_category_number ( pSplitTransaction ) != -1 ) { CSV_CLEAR_FIELD (csv_field_categ); csv_field_categ = my_strdup ( gsb_data_category_get_name ( gsb_data_transaction_get_category_number ( pSplitTransaction ), 0, "" ) ); if ( gsb_data_transaction_get_sub_category_number ( pSplitTransaction ) != -1 ) { CSV_CLEAR_FIELD (csv_field_sous_categ); csv_field_sous_categ = my_strdup ( gsb_data_category_get_sub_category_name ( gsb_data_transaction_get_category_number ( pSplitTransaction ), gsb_data_transaction_get_sub_category_number ( pSplitTransaction ), NULL ) ); } } } /* met les notes de la ventilation */ if ( gsb_data_transaction_get_notes ( pSplitTransaction ) ) { CSV_CLEAR_FIELD (csv_field_notes); csv_field_notes = my_strdup (gsb_data_transaction_get_notes ( pSplitTransaction )); } /* met le montant de la ventilation */ amount = gsb_data_transaction_get_adjusted_amount ( pSplitTransaction, return_exponent ); CSV_CLEAR_FIELD (csv_field_montant); csv_field_montant = utils_real_get_string (amount); /* met le rapprochement */ if ( gsb_data_transaction_get_reconcile_number ( pSplitTransaction ) ) { CSV_CLEAR_FIELD (csv_field_rappro); csv_field_rappro = my_strdup ( gsb_data_reconcile_get_name ( gsb_data_transaction_get_reconcile_number ( pSplitTransaction ) ) ); } /* met le chèque si c'est un type à numéotation automatique */ payment_method = gsb_data_transaction_get_method_of_payment_number ( pSplitTransaction ); if (gsb_data_payment_get_automatic_numbering (payment_method)) { CSV_CLEAR_FIELD (csv_field_cheque); csv_field_cheque = my_strdup ( gsb_data_transaction_get_method_of_payment_content ( pSplitTransaction ) ); } /* Budgetary lines */ if ( gsb_data_transaction_get_budgetary_number ( pSplitTransaction ) != -1 ) { CSV_CLEAR_FIELD (csv_field_imput); csv_field_imput = my_strdup ( gsb_data_budget_get_name ( gsb_data_transaction_get_budgetary_number ( pSplitTransaction ), 0, "" ) ); if ( gsb_data_transaction_get_sub_budgetary_number ( pSplitTransaction ) != -1 ) { CSV_CLEAR_FIELD (csv_field_sous_imput); csv_field_sous_imput = my_strdup ( gsb_data_budget_get_sub_budget_name ( gsb_data_transaction_get_budgetary_number ( pSplitTransaction ), gsb_data_transaction_get_sub_budgetary_number ( pSplitTransaction ), NULL ) ); } } /* Piece comptable */ CSV_CLEAR_FIELD (csv_field_piece); csv_field_piece = my_strdup ( gsb_data_transaction_get_voucher ( pSplitTransaction ) ); /* Financial Year */ if ( gsb_data_transaction_get_financial_year_number ( pSplitTransaction ) != -1 ) { CSV_CLEAR_FIELD (csv_field_exercice ); csv_field_exercice = my_strdup (gsb_data_fyear_get_name(gsb_data_transaction_get_financial_year_number ( pSplitTransaction ))); } csv_add_record(csv_file,FALSE, print_balance); } pSplitTransactionList = pSplitTransactionList -> next; } csv_clear_fields(TRUE); } else { gchar *tmpstr; gint contra_transaction_number = gsb_data_transaction_get_contra_transaction_number ( transaction_number ); switch (contra_transaction_number) { case 0: /* normal category */ if ( gsb_data_transaction_get_category_number ( transaction_number ) != -1 ) { CSV_CLEAR_FIELD (csv_field_categ); csv_field_categ = my_strdup ( gsb_data_category_get_name ( gsb_data_transaction_get_category_number ( transaction_number ), 0, "" ) ); if ( gsb_data_transaction_get_sub_category_number ( transaction_number ) != -1 ) { CSV_CLEAR_FIELD (csv_field_sous_categ); csv_field_sous_categ = my_strdup ( gsb_data_category_get_sub_category_name ( gsb_data_transaction_get_category_number ( transaction_number ), gsb_data_transaction_get_sub_category_number ( transaction_number ), NULL ) ); } } break; case -1: /* transfer to deleted account */ CSV_CLEAR_FIELD (csv_field_categ); csv_field_categ = my_strdup (_("Transfer")); tmpstr = g_strconcat ( "[", _("Deleted account"), "]", NULL ); /* TODO dOm : is it necessary to duplicate memory with my_strdup since it was already newly allocated memory ? */ CSV_CLEAR_FIELD (csv_field_sous_categ); csv_field_sous_categ = my_strdup (tmpstr); g_free ( tmpstr ); break; default: /* transfer */ CSV_CLEAR_FIELD (csv_field_categ); csv_field_categ = my_strdup (_("Transfer")); tmpstr = g_strconcat ( "[", gsb_data_account_get_name ( gsb_data_transaction_get_contra_transaction_account ( transaction_number ) ), "]", NULL ); /* TODO dOm : is it necessary to duplicate memory with my_strdup since it was already newly allocated memory ? */ CSV_CLEAR_FIELD (csv_field_sous_categ); csv_field_sous_categ = my_strdup (tmpstr); g_free ( tmpstr ); } csv_add_record(csv_file,TRUE, print_balance); } return TRUE; }