/** 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;
}
Exemple #6
0
/**
 * 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;
}