Пример #1
0
/* Opens the dialog to create a new account with given name, commodity, parent, type.
 * Returns the new account, or NULL if it couldn't be created.. */
static Account *gnc_ofx_new_account(const char* name,
                                    const gnc_commodity * account_commodity,
                                    Account *parent_account,
                                    GNCAccountType new_account_default_type)
{
    Account *result;
    GList * valid_types = NULL;

    g_assert(name);
    g_assert(account_commodity);
    g_assert(parent_account);

    if (new_account_default_type != ACCT_TYPE_NONE)
    {
        // Passing the types as gpointer
        valid_types =
            g_list_prepend(valid_types,
                           GINT_TO_POINTER(new_account_default_type));
        if (!xaccAccountTypesCompatible(xaccAccountGetType(parent_account), new_account_default_type))
        {
            // Need to add the parent's account type
            valid_types =
                g_list_prepend(valid_types,
                               GINT_TO_POINTER(xaccAccountGetType(parent_account)));
        }
    }
    result = gnc_ui_new_accounts_from_name_with_defaults (name,
             valid_types,
             account_commodity,
             parent_account);
    g_list_free(valid_types);
    return result;
}
static void
balance_cell_data_func (GtkTreeViewColumn *tree_column,
                        GtkCellRenderer *cell,
                        GtkTreeModel *model,
                        GtkTreeIter *iter,
                        gpointer user_data)
{
    Account *account;
    gnc_numeric balance;
    const gchar *string;
    GNCPrintAmountInfo print_info;
    hierarchy_data *data = (hierarchy_data *)user_data;
    gboolean allow_value;

    g_return_if_fail (GTK_TREE_MODEL (model));
    account = gnc_tree_view_account_get_account_from_iter (model, iter);

    balance = get_final_balance (data->balance_hash, account);
    if (gnc_numeric_zero_p (balance))
    {
        string = "";
    }
    else
    {
        print_info = gnc_account_print_info (account, FALSE);
        string = xaccPrintAmount (balance, print_info);
    }

    if (xaccAccountGetType(account) == ACCT_TYPE_EQUITY ||
            xaccAccountGetType(account) == ACCT_TYPE_TRADING)
    {
        allow_value = FALSE;
        string = _("zero");
    }
    else
    {
        GncAccountMergeDisposition disp;
        disp = determine_merge_disposition(gnc_book_get_root_account(gnc_get_current_book()), account);
        if (disp == GNC_ACCOUNT_MERGE_DISPOSITION_CREATE_NEW)
        {
            allow_value = !xaccAccountGetPlaceholder(account);
        }
        else
        {
            allow_value = FALSE;
            string = _("existing account");
        }
    }
    g_object_set (G_OBJECT (cell),
                  "text", string,
                  "editable", allow_value,
                  "sensitive", allow_value,
                  NULL);
}
Пример #3
0
void
xaccAccountScrubCommodity (Account *account)
{
    gnc_commodity *commodity;

    if (!account) return;
    if (xaccAccountGetType(account) == ACCT_TYPE_ROOT) return;

    commodity = xaccAccountGetCommodity (account);
    if (commodity) return;

    /* Use the 'obsolete' routines to try to figure out what the
     * account commodity should have been. */
    commodity = xaccAccountGetCommodity (account);
    if (commodity)
    {
        xaccAccountSetCommodity (account, commodity);
        return;
    }

    commodity = DxaccAccountGetCurrency (account);
    if (commodity)
    {
        xaccAccountSetCommodity (account, commodity);
        return;
    }

    PERR ("Account \"%s\" does not have a commodity!",
          xaccAccountGetName(account));
}
Пример #4
0
/* Opens up a register window to display a single account */
GNCLedgerDisplay *
gnc_ledger_display_simple (Account *account)
{
    SplitRegisterType reg_type;
    GNCAccountType acc_type = xaccAccountGetType (account);
    gboolean use_double_line;
    GNCLedgerDisplay *ld;

    ENTER("account=%p", account);

    switch (acc_type)
    {
    case ACCT_TYPE_PAYABLE:
    case ACCT_TYPE_RECEIVABLE:
        use_double_line = TRUE;
        break;
    default:
        use_double_line = FALSE;
        break;
    }

    reg_type = gnc_get_reg_type (account, LD_SINGLE);

    ld = gnc_ledger_display_internal (account, NULL, LD_SINGLE, reg_type,
                                      gnc_get_default_register_style(acc_type),
                                      use_double_line, FALSE);
    LEAVE("%p", ld);
    return ld;
}
Пример #5
0
// ////////////////////////////////////////////////////////////
static void increment_if_asset_account (gpointer data,
                                        gpointer user_data)
{
    int *r = user_data;
    const Split *split = data;
    const Account *account = xaccSplitGetAccount(split);
    if (xaccAccountIsAssetLiabType(xaccAccountGetType(account)))
        ++(*r);
}
static gboolean
gnc_stock_split_assistant_view_filter_income (Account  *account,
        gpointer  data)
{
    GNCAccountType type;

    type = xaccAccountGetType(account);
    return (type == ACCT_TYPE_INCOME);
}
Пример #7
0
void
gncScrubBusinessAccount (Account *acc)
{
    if (!acc) return;
    if (FALSE == xaccAccountIsAPARType (xaccAccountGetType (acc))) return;

    gncScrubBusinessAccountLots (acc);
    gncScrubBusinessAccountSplits (acc);
}
static gboolean
gnc_stock_split_assistant_view_filter_asset (Account  *account,
        gpointer  data)
{
    GNCAccountType type;

    type = xaccAccountGetType(account);
    return ((type == ACCT_TYPE_BANK) || (type == ACCT_TYPE_CASH) ||
            (type == ACCT_TYPE_ASSET));
}
Пример #9
0
static gint predicate_is_apar_account(gconstpointer a,
                                      gconstpointer user_data)
{
    const Split *split = a;
    const Account *account = xaccSplitGetAccount(split);
    if (xaccAccountIsAPARType(xaccAccountGetType(account)))
        return 0;
    else
        return -1;
}
Пример #10
0
/*
 * Given an owner, extract the open balance from the owner and then
 * convert it to the desired currency.
 */
gnc_numeric
gncOwnerGetBalanceInCurrency (const GncOwner *owner,
                              const gnc_commodity *report_currency)
{
    gnc_numeric balance = gnc_numeric_zero ();
    GList *acct_list, *acct_node, *acct_types, *lot_list = NULL, *lot_node;
    QofBook *book;
    gnc_commodity *owner_currency;
    GNCPriceDB *pdb;

    g_return_val_if_fail (owner, gnc_numeric_zero ());

    /* Get account list */
    book       = qof_instance_get_book (qofOwnerGetOwner (owner));
    acct_list  = gnc_account_get_descendants (gnc_book_get_root_account (book));
    acct_types = gncOwnerGetAccountTypesList (owner);
    owner_currency = gncOwnerGetCurrency (owner);

    /* For each account */
    for (acct_node = acct_list; acct_node; acct_node = acct_node->next)
    {
        Account *account = acct_node->data;

        /* Check if this account can have lots for the owner, otherwise skip to next */
        if (g_list_index (acct_types, (gpointer)xaccAccountGetType (account))
                == -1)
            continue;


        if (!gnc_commodity_equal (owner_currency, xaccAccountGetCommodity (account)))
            continue;

        /* Get a list of open lots for this owner and account */
        lot_list = xaccAccountFindOpenLots (account, gncOwnerLotMatchOwnerFunc,
                                            (gpointer)owner, NULL);
        /* For each lot */
        for (lot_node = lot_list; lot_node; lot_node = lot_node->next)
        {
            GNCLot *lot = lot_node->data;
            gnc_numeric lot_balance = gnc_lot_get_balance (lot);
            GncInvoice *invoice = gncInvoiceGetInvoiceFromLot(lot);
            if (invoice)
               balance = gnc_numeric_add (balance, lot_balance,
                                          gnc_commodity_get_fraction (owner_currency), GNC_HOW_RND_ROUND_HALF_UP);
        }
    }

    pdb = gnc_pricedb_get_db (book);

    if (report_currency)
        balance = gnc_pricedb_convert_balance_latest_price (
                      pdb, balance, owner_currency, report_currency);

    return balance;
}
Пример #11
0
static gboolean
skip_income_acct_cb (Account *account, gpointer user_data)
{
    GNCAccountType type;

    /* Don't add A/R, A/P, Bank, Cash, or Equity accounts */
    type = xaccAccountGetType (account);
    if (type == ACCT_TYPE_PAYABLE || type == ACCT_TYPE_RECEIVABLE ||
            type == ACCT_TYPE_CASH || type == ACCT_TYPE_BANK ||
            type == ACCT_TYPE_EQUITY || type == ACCT_TYPE_TRADING)
    {
        return TRUE;
    }

    /* If this is a BILL, then leave out the incomes */
    if (type == ACCT_TYPE_INCOME) return TRUE;

    /* Don't add placeholder accounts */
    if (xaccAccountGetPlaceholder (account)) return TRUE;

    return FALSE;
}
Пример #12
0
void
gncScrubBusinessAccountLots (Account *acc)
{
    LotList *lots, *node;
    gint lot_count = 0;
    gint curr_lot_no = 1;
    const gchar *str;

    if (!acc) return;
    if (FALSE == xaccAccountIsAPARType (xaccAccountGetType (acc))) return;

    str = xaccAccountGetName(acc);
    str = str ? str : "(null)";

    ENTER ("(acc=%s)", str);
    PINFO ("Cleaning up superfluous lot links in account %s \n", str);
    xaccAccountBeginEdit(acc);

    lots = xaccAccountGetLotList(acc);
    lot_count = g_list_length (lots);
    for (node = lots; node; node = node->next)
    {
        GNCLot *lot = node->data;

        PINFO("Start processing lot %d of %d",
              curr_lot_no, lot_count);

        if (lot)
            gncScrubBusinessLot (lot);

        PINFO("Finished processing lot %d of %d",
              curr_lot_no, lot_count);
        curr_lot_no++;
    }
    g_list_free(lots);
    xaccAccountCommitEdit(acc);
    LEAVE ("(acc=%s)", str);
}
Пример #13
0
void
ViewletModel::rightVGenerate(::Account *selectedAccount)
{
    ::QofBook *book = gnc_account_get_book(selectedAccount);
    ::Account *rootAccount = gnc_book_get_root_account(book);

    GList *accountsGList = gnc_account_get_descendants(rootAccount);
    AccountQList accountsList = accountFromGList(accountsGList);

    int numOfAccounts = accountsList.count();
    qDebug()<<"Total num of accounts: "<<numOfAccounts;

    AccountQList expenseAccountsList;
    for(int i = 0; i < numOfAccounts; i++)
    {
        if(xaccAccountGetType(accountsList.at(i)) == 8)
        {
            expenseAccountsList.append(accountsList.at(i));
        }
    }

    SplitQList splitsList = buildSplitListDateSort(expenseAccountsList);
    buildMiniJournalStruct(splitsList);
}
Пример #14
0
/*******************************************************
 * csv_tree_export
 *
 * write a list of accounts settings to a text file
 *******************************************************/
void csv_tree_export (CsvExportInfo *info)
{
    FILE    *fh;
    Account *root;
    Account *acc;
    GList   *accts, *ptr;

    ENTER("");
    DEBUG("File name is : %s", info->file_name);

    /* Get list of Accounts */
    root = gnc_book_get_root_account (gnc_get_current_book());
    accts = gnc_account_get_descendants_sorted (root);
    info->failed = FALSE;

    /* Open File for writing */
    fh = g_fopen (info->file_name, "w");
    if (fh != NULL)
    {
        gchar *header;
        gchar *part1;
        gchar *part2;
        const gchar *currentSel;
        gchar *end_sep;
        gchar *mid_sep;
        int i;


        /* Set up separators */
        if (info->use_quotes)
        {
            end_sep = "\"";
            mid_sep = g_strconcat ("\"", info->separator_str, "\"", NULL);
        }
        else
        {
            end_sep = "";
            mid_sep = g_strconcat (info->separator_str, NULL);
        }

        /* Header string, 'eol = end of line marker' */
        header = g_strconcat (end_sep, _("type"), mid_sep, _("full_name"), mid_sep, _("name"), mid_sep,
                                _("code"), mid_sep, _("description"), mid_sep, _("color"), mid_sep,
                                _("notes"), mid_sep, _("commoditym"), mid_sep, _("commodityn"), mid_sep,
                                _("hidden"), mid_sep, _("tax"), mid_sep, _("place_holder"), end_sep, EOLSTR, NULL);
        DEBUG("Header String: %s", header);

        /* Write header line */
        if (!write_line_to_file (fh, header))
        {
            info->failed = TRUE;
            g_free (mid_sep);
            g_free (header);
            return;
        }
        g_free (header);

        /* Go through list of accounts */
        for (ptr = accts, i = 0; ptr; ptr = g_list_next (ptr), i++)
        {
            gchar *fullname = NULL;
            gchar *str_temp = NULL;
            acc = ptr->data;
            DEBUG("Account being processed is : %s", xaccAccountGetName (acc));
            /* Type */
            currentSel = xaccAccountTypeEnumAsString (xaccAccountGetType (acc));
            part1 = g_strconcat (end_sep, currentSel, mid_sep, NULL);
            /* Full Name */
            fullname = gnc_account_get_full_name (acc);
            str_temp = csv_test_field_string (info, fullname);
            part2 = g_strconcat (part1, str_temp, mid_sep, NULL);
            g_free (str_temp);
            g_free (fullname);
            g_free (part1);
            /* Name */
            currentSel = xaccAccountGetName (acc);
            str_temp = csv_test_field_string (info, currentSel);
            part1 = g_strconcat (part2, str_temp, mid_sep, NULL);
            g_free (str_temp);
            g_free (part2);
            /* Code */
            currentSel = xaccAccountGetCode (acc) ? xaccAccountGetCode (acc) : "";
            str_temp = csv_test_field_string (info, currentSel);
            part2 = g_strconcat (part1, str_temp, mid_sep, NULL);
            g_free (str_temp);
            g_free (part1);
            /* Description */
            currentSel = xaccAccountGetDescription (acc) ? xaccAccountGetDescription (acc) : "";
            str_temp = csv_test_field_string (info, currentSel);
            part1 = g_strconcat (part2, str_temp, mid_sep, NULL);
            g_free (str_temp);
            g_free (part2);
            /* Color */
            currentSel = xaccAccountGetColor (acc) ? xaccAccountGetColor (acc) : "" ;
            str_temp = csv_test_field_string (info, currentSel);
            part2 = g_strconcat (part1, str_temp, mid_sep, NULL);
            g_free (str_temp);
            g_free (part1);
            /* Notes */
            currentSel = xaccAccountGetNotes (acc) ? xaccAccountGetNotes (acc) : "" ;
            str_temp = csv_test_field_string (info, currentSel);
            part1 = g_strconcat (part2, str_temp, mid_sep, NULL);
            g_free (str_temp);
            g_free (part2);
            /* Commodity Mnemonic */
            currentSel = gnc_commodity_get_mnemonic (xaccAccountGetCommodity (acc));
            str_temp = csv_test_field_string (info, currentSel);
            part2 = g_strconcat (part1, str_temp, mid_sep, NULL);
            g_free (str_temp);
            g_free (part1);
            /* Commodity Namespace */
            currentSel = gnc_commodity_get_namespace (xaccAccountGetCommodity (acc));
            str_temp = csv_test_field_string (info, currentSel);
            part1 = g_strconcat (part2, str_temp, mid_sep, NULL);
            g_free (str_temp);
            g_free (part2);
            /* Hidden */
            currentSel = xaccAccountGetHidden (acc) ? "T" : "F" ;
            part2 = g_strconcat (part1, currentSel, mid_sep, NULL);
            g_free (part1);
            /* Tax */
            currentSel = xaccAccountGetTaxRelated (acc) ? "T" : "F" ;
            part1 = g_strconcat (part2, currentSel, mid_sep, NULL);
            g_free (part2);
            /* Place Holder / end of line marker */
            currentSel = xaccAccountGetPlaceholder (acc) ? "T" : "F" ;
            part2 = g_strconcat (part1, currentSel, end_sep, EOLSTR, NULL);
            g_free (part1);

            DEBUG("Account String: %s", part2);

            /* Write to file */
            if (!write_line_to_file (fh, part2))
            {
                info->failed = TRUE;
                break;
            }
            g_free (part2);
        }
        g_free (mid_sep);
    }
    else
        info->failed = TRUE;
    if (fh)
        fclose (fh);

    g_list_free (accts);
    LEAVE("");
}
Пример #15
0
static void
lot_scrub_cb (Account *acc, gpointer data)
{
    if (FALSE == xaccAccountIsAPARType (xaccAccountGetType (acc))) return;
    gncScrubBusinessAccount (acc);
}
Пример #16
0
static SplitRegisterType
gnc_get_reg_type (Account *leader, GNCLedgerDisplayType ld_type)
{
    GNCAccountType account_type;
    SplitRegisterType reg_type;

    if (ld_type == LD_GL)
        return GENERAL_JOURNAL;

    account_type = xaccAccountGetType (leader);

    if (ld_type == LD_SINGLE)
    {
        switch (account_type)
        {
        case ACCT_TYPE_BANK:
            return BANK_REGISTER;

        case ACCT_TYPE_CASH:
            return CASH_REGISTER;

        case ACCT_TYPE_ASSET:
            return ASSET_REGISTER;

        case ACCT_TYPE_CREDIT:
            return CREDIT_REGISTER;

        case ACCT_TYPE_LIABILITY:
            return LIABILITY_REGISTER;

        case ACCT_TYPE_PAYABLE:
            return PAYABLE_REGISTER;

        case ACCT_TYPE_RECEIVABLE:
            return RECEIVABLE_REGISTER;

        case ACCT_TYPE_STOCK:
        case ACCT_TYPE_MUTUAL:
            return STOCK_REGISTER;

        case ACCT_TYPE_INCOME:
            return INCOME_REGISTER;

        case ACCT_TYPE_EXPENSE:
            return EXPENSE_REGISTER;

        case ACCT_TYPE_EQUITY:
            return EQUITY_REGISTER;

        case ACCT_TYPE_CURRENCY:
            return CURRENCY_REGISTER;

        case ACCT_TYPE_TRADING:
            return TRADING_REGISTER;

        default:
            PERR ("unknown account type %d\n", account_type);
            return BANK_REGISTER;
        }
    }

    if (ld_type != LD_SUBACCOUNT)
    {
        PERR ("unknown ledger type %d\n", ld_type);
        return BANK_REGISTER;
    }

    switch (account_type)
    {
    case ACCT_TYPE_BANK:
    case ACCT_TYPE_CASH:
    case ACCT_TYPE_ASSET:
    case ACCT_TYPE_CREDIT:
    case ACCT_TYPE_LIABILITY:
    case ACCT_TYPE_RECEIVABLE:
    case ACCT_TYPE_PAYABLE:
    {
        /* If any of the sub-accounts have ACCT_TYPE_STOCK or
         * ACCT_TYPE_MUTUAL types, then we must use the PORTFOLIO_LEDGER
         * ledger. Otherwise, a plain old GENERAL_JOURNAL will do. */
        gpointer ret;
        reg_type = GENERAL_JOURNAL;

        ret = gnc_account_foreach_descendant_until(leader, look_for_portfolio_cb, NULL);
        if (ret) reg_type = PORTFOLIO_LEDGER;
        break;
    }

    case ACCT_TYPE_STOCK:
    case ACCT_TYPE_MUTUAL:
    case ACCT_TYPE_CURRENCY:
        reg_type = PORTFOLIO_LEDGER;
        break;

    case ACCT_TYPE_INCOME:
    case ACCT_TYPE_EXPENSE:
        reg_type = INCOME_LEDGER;
        break;

    case ACCT_TYPE_EQUITY:
    case ACCT_TYPE_TRADING:
        reg_type = GENERAL_JOURNAL;
        break;

    default:
        PERR ("unknown account type:%d", account_type);
        reg_type = GENERAL_JOURNAL;
        break;
    }

    return reg_type;
}
static gchar*
node_and_account_equal (xmlNodePtr node, Account* act)
{
    xmlNodePtr mark;

    while (g_strcmp0 ((char*)node->name, "text") == 0)
    {
        node = node->next;
    }

    if (!check_dom_tree_version (node, "2.0.0"))
    {
        return g_strdup ("version wrong.  Not 2.0.0 or not there");
    }

    if (!node->name || g_strcmp0 ((char*)node->name, "gnc:account"))
    {
        return g_strdup ("Name of toplevel node is bad");
    }

    for (mark = node->xmlChildrenNode; mark; mark = mark->next)
    {
        if (g_strcmp0 ((char*)mark->name, "text") == 0)
        {
        }
        else if (g_strcmp0 ((char*)mark->name, "act:name") == 0)
        {
            if (!equals_node_val_vs_string (mark, xaccAccountGetName (act)))
            {
                return g_strdup ("names differ");
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "act:id") == 0)
        {
            if (!equals_node_val_vs_guid (mark, xaccAccountGetGUID (act)))
            {
                return g_strdup ("ids differ");
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "act:type") == 0)
        {
            gchar* txt;
            GNCAccountType type;

            txt = dom_tree_to_text (mark);

            if (!txt)
            {
                return g_strdup ("couldn't get type string");
            }
            else if (!xaccAccountStringToType (txt, &type))
            {
                g_free (txt);
                return g_strdup ("couldn't convert type string to int");
            }
            else if (type != xaccAccountGetType (act))
            {
                g_free (txt);
                return g_strdup ("types differ");
            }
            else
            {
                g_free (txt);
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "act:commodity") == 0)
        {
            /* This is somewhat BS, because if the commodity isn't a
               currency (and therefore built in) there isn't a
               corresponding currency in the XML, skip the test. jralls
               2010-11-02 */
            if (xaccAccountGetCommodity (act) == NULL) continue;
            if (!equals_node_val_vs_commodity (
                    mark, xaccAccountGetCommodity (act),
                    gnc_account_get_book (act)))
            {
                return g_strdup ("commodities differ");
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "act:code") == 0)
        {
            if (!equals_node_val_vs_string (mark, xaccAccountGetCode (act)))
            {
                return g_strdup ("codes differ");
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "act:description") == 0)
        {
            if (!equals_node_val_vs_string (
                    mark, xaccAccountGetDescription (act)))
            {
                return g_strdup ("descriptions differ");
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "act:slots") == 0)
        {
            /* xaccAccountDeleteOldData (act); */

            if (!equals_node_val_vs_kvp_frame (mark,
                                               qof_instance_get_slots (QOF_INSTANCE (act))))
            {
                return g_strdup ("slots differ");
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "act:parent") == 0)
        {
            if (!equals_node_val_vs_guid (
                    mark, xaccAccountGetGUID (gnc_account_get_parent (act))))
            {
                return g_strdup ("parent ids differ");
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "act:commodity-scu") == 0)
        {
            if (!equals_node_val_vs_int (mark, xaccAccountGetCommoditySCU (act)))
            {
                return g_strdup ("commodity scus differ");
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "act:hidden") == 0)
        {
            if (!equals_node_val_vs_boolean (mark, xaccAccountGetHidden (act)))
            {
                return g_strdup ("Hidden flags differ");
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "act:placeholder") == 0)
        {
            if (!equals_node_val_vs_boolean (mark, xaccAccountGetPlaceholder (act)))
            {
                return g_strdup ("Placeholder flags differ");
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "act:security") == 0)
        {
            return NULL; // This tag is ignored.
        }
        else
        {
            return g_strdup_printf ("unknown node in dom tree: %s", mark->name);
        }
    }

    return NULL;
}
Пример #18
0
void
GncSqlAccountBackend::load_all (GncSqlBackend* sql_be)
{
    QofBook* pBook;
    ParentGuidVec l_accounts_needing_parents;
    g_return_if_fail (sql_be != NULL);

    ENTER ("");

    pBook = sql_be->book();

    std::stringstream sql;
    sql << "SELECT * FROM " << TABLE_NAME;
    auto stmt = sql_be->create_statement_from_sql(sql.str());
    auto result = sql_be->execute_select_statement(stmt);
    for (auto row : *result)
        load_single_account (sql_be, row, l_accounts_needing_parents);

    sql.str("");
    sql << "SELECT DISTINCT guid FROM " << TABLE_NAME;
    gnc_sql_slots_load_for_sql_subquery (sql_be, sql.str().c_str(),
                                         (BookLookupFn)xaccAccountLookup);

    /* While there are items on the list of accounts needing parents,
       try to see if the parent has now been loaded.  Theory says that if
       items are removed from the front and added to the back if the
       parent is still not available, then eventually, the list will
       shrink to size 0. */
    if (!l_accounts_needing_parents.empty())
    {
        auto progress_made = true;
        std::reverse(l_accounts_needing_parents.begin(),
                     l_accounts_needing_parents.end());
	auto end = l_accounts_needing_parents.end();
        while (progress_made)
        {
            progress_made = false;
            end = std::remove_if(l_accounts_needing_parents.begin(), end,
				 [&](ParentGuidPtr s)
				 {
				     auto pParent = xaccAccountLookup (&s->guid,
								       sql_be->book());
				     if (pParent != nullptr)
				     {
					 gnc_account_append_child (pParent,
								   s->pAccount);
					 progress_made = true;
					 delete s;
					 return true;
				     }
				     return false;
				 });
        }

        /* Any non-ROOT accounts left over must be parented by the root account */
        auto root = gnc_book_get_root_account (pBook);
        end = std::remove_if(l_accounts_needing_parents.begin(), end,
			     [&](ParentGuidPtr s)
			     {
				 if (xaccAccountGetType (s->pAccount) != ACCT_TYPE_ROOT)
				     gnc_account_append_child (root, s->pAccount);
				 delete s;
				 return true;
			     });
    }

#if LOAD_TRANSACTIONS_AS_NEEDED
    /* Load starting balances */
    auto bal_slist = gnc_sql_get_account_balances_slist (sql_be);
    for (auto bal = bal_slist; bal != NULL; bal = bal->next)
    {
        acct_balances_t* balances = (acct_balances_t*)bal->data;

        qof_instance_increase_editlevel (balances->acct);
        g_object_set (balances->acct,
                      "start-balance", &balances->balance,
                      "start-cleared-balance", &balances->cleared_balance,
                      "start-reconciled-balance", &balances->reconciled_balance,
                      NULL);

        qof_instance_decrease_editlevel (balances->acct);
    }
    if (bal_slist != NULL)
    {
        g_slist_free (bal_slist);
    }
#endif
    LEAVE ("");
}
/**
 * @fixme Move this non-GUI code into the engine.
 **/
static void
gnc_ui_accounts_recurse (Account *parent, GList **currency_list,
                         GNCSummarybarOptions options)
{
    gnc_numeric start_amount;
    gnc_numeric start_amount_default_currency;
    gnc_numeric end_amount;
    gnc_numeric end_amount_default_currency;
    GNCAccountType account_type;
    gnc_commodity * account_currency;
    gnc_commodity * euro_commodity;
    GNCCurrencyAcc *currency_accum = NULL;
    GNCCurrencyAcc *euro_accum = NULL;
    GNCCurrencyAcc *grand_total_accum = NULL;
    GNCCurrencyAcc *non_curr_accum = NULL;
    GList *children, *node;
    gboolean non_currency = FALSE;
    Timespec end_timespec;
    Timespec start_timespec;

    if (parent == NULL) return;

    children = gnc_account_get_children(parent);
    for (node = children; node; node = g_list_next(node))
    {
        Account *account = node->data;

        account_type = xaccAccountGetType(account);
        account_currency = xaccAccountGetCommodity(account);

        if (options.grand_total)
            grand_total_accum = gnc_ui_get_currency_accumulator(currency_list,
                                options.default_currency,
                                TOTAL_GRAND_TOTAL);

        if (options.euro)
        {
            euro_commodity = gnc_get_euro ();
            euro_accum = gnc_ui_get_currency_accumulator(currency_list,
                         euro_commodity,
                         TOTAL_CURR_TOTAL);
        }
        else
            euro_commodity = NULL;

        if (!gnc_commodity_is_currency(account_currency))
        {
            non_currency = TRUE;
            non_curr_accum = gnc_ui_get_currency_accumulator(currency_list,
                             options.default_currency,
                             TOTAL_NON_CURR_TOTAL);
        }

        if (!non_currency || options.non_currency)
        {
            currency_accum = gnc_ui_get_currency_accumulator(currency_list,
                             account_currency,
                             TOTAL_SINGLE);
        }

        switch (account_type)
        {
        case ACCT_TYPE_BANK:
        case ACCT_TYPE_CASH:
        case ACCT_TYPE_ASSET:
        case ACCT_TYPE_STOCK:
        case ACCT_TYPE_MUTUAL:
        case ACCT_TYPE_CREDIT:
        case ACCT_TYPE_LIABILITY:
        case ACCT_TYPE_PAYABLE:
        case ACCT_TYPE_RECEIVABLE:
            end_amount = xaccAccountGetBalanceAsOfDate(account, options.end_date);
            timespecFromTime_t(&end_timespec, options.end_date);
            end_amount_default_currency =
                xaccAccountConvertBalanceToCurrencyAsOfDate
                (account, end_amount, account_currency, options.default_currency,
                 timespecToTime_t(timespecCanonicalDayTime(end_timespec)));

            if (!non_currency || options.non_currency)
            {
                currency_accum->assets =
                    gnc_numeric_add (currency_accum->assets, end_amount,
                                     gnc_commodity_get_fraction (account_currency),
                                     GNC_HOW_RND_ROUND_HALF_UP);
            }

            if (non_currency)
            {
                non_curr_accum->assets =
                    gnc_numeric_add (non_curr_accum->assets, end_amount_default_currency,
                                     gnc_commodity_get_fraction (options.default_currency),
                                     GNC_HOW_RND_ROUND_HALF_UP);
            }

            if (options.grand_total)
            {
                grand_total_accum->assets =
                    gnc_numeric_add (grand_total_accum->assets, end_amount_default_currency,
                                     gnc_commodity_get_fraction (options.default_currency),
                                     GNC_HOW_RND_ROUND_HALF_UP);
            }

            if (options.euro && (currency_accum != euro_accum))
            {
                euro_accum->assets =
                    gnc_numeric_add (euro_accum->assets,
                                     gnc_convert_to_euro(account_currency, end_amount),
                                     gnc_commodity_get_fraction (euro_commodity),
                                     GNC_HOW_RND_ROUND_HALF_UP);
            }

            gnc_ui_accounts_recurse(account, currency_list, options);
            break;
        case ACCT_TYPE_INCOME:
        case ACCT_TYPE_EXPENSE:
            start_amount = xaccAccountGetBalanceAsOfDate(account, options.start_date);
            timespecFromTime_t(&start_timespec, options.start_date);
            start_amount_default_currency =
                xaccAccountConvertBalanceToCurrencyAsOfDate
                (account, start_amount, account_currency, options.default_currency,
                 timespecToTime_t(timespecCanonicalDayTime(start_timespec)));
            end_amount = xaccAccountGetBalanceAsOfDate(account, options.end_date);
            timespecFromTime_t(&end_timespec, options.end_date);
            end_amount_default_currency =
                xaccAccountConvertBalanceToCurrencyAsOfDate
                (account, end_amount, account_currency, options.default_currency,
                 timespecToTime_t(timespecCanonicalDayTime(end_timespec)));

            if (!non_currency || options.non_currency)
            {
                currency_accum->profits =
                    gnc_numeric_add (currency_accum->profits, start_amount,
                                     gnc_commodity_get_fraction (account_currency),
                                     GNC_HOW_RND_ROUND_HALF_UP);
                currency_accum->profits =
                    gnc_numeric_sub (currency_accum->profits, end_amount,
                                     gnc_commodity_get_fraction (account_currency),
                                     GNC_HOW_RND_ROUND_HALF_UP);
            }

            if (non_currency)
            {
                non_curr_accum->profits =
                    gnc_numeric_add (non_curr_accum->profits, start_amount_default_currency,
                                     gnc_commodity_get_fraction (options.default_currency),
                                     GNC_HOW_RND_ROUND_HALF_UP);
                non_curr_accum->profits =
                    gnc_numeric_sub (non_curr_accum->profits, end_amount_default_currency,
                                     gnc_commodity_get_fraction (options.default_currency),
                                     GNC_HOW_RND_ROUND_HALF_UP);
            }

            if (options.grand_total)
            {
                grand_total_accum->profits =
                    gnc_numeric_add (grand_total_accum->profits,
                                     start_amount_default_currency,
                                     gnc_commodity_get_fraction (options.default_currency),
                                     GNC_HOW_RND_ROUND_HALF_UP);
                grand_total_accum->profits =
                    gnc_numeric_sub (grand_total_accum->profits,
                                     end_amount_default_currency,
                                     gnc_commodity_get_fraction (options.default_currency),
                                     GNC_HOW_RND_ROUND_HALF_UP);
            }

            if (options.euro && (currency_accum != euro_accum))
            {
                euro_accum->profits =
                    gnc_numeric_add (euro_accum->profits,
                                     gnc_convert_to_euro(account_currency, start_amount),
                                     gnc_commodity_get_fraction (euro_commodity),
                                     GNC_HOW_RND_ROUND_HALF_UP);
                euro_accum->profits =
                    gnc_numeric_sub (euro_accum->profits,
                                     gnc_convert_to_euro(account_currency, end_amount),
                                     gnc_commodity_get_fraction (euro_commodity),
                                     GNC_HOW_RND_ROUND_HALF_UP);
            }

            gnc_ui_accounts_recurse(account, currency_list, options);
            break;
        case ACCT_TYPE_EQUITY:
            /* no-op, see comments at top about summing assets */
            break;
            /**
             * @fixme I don't know if this is right or if trading accounts should be
             *        treated like income and expense accounts.
             **/
        case ACCT_TYPE_TRADING:
            break;
        case ACCT_TYPE_CURRENCY:
        default:
            break;
        }
    }
    g_list_free(children);
}
Пример #20
0
int ofx_proc_transaction_cb(struct OfxTransactionData data, void * transaction_user_data)
{
    char dest_string[255];
    time64 current_time = gnc_time (NULL);
    Account *account;
    Account *investment_account = NULL;
    Account *income_account = NULL;
    gchar *investment_account_text, *investment_account_onlineid;
    gnc_commodity *currency = NULL;
    gnc_commodity *investment_commodity = NULL;
    gnc_numeric gnc_amount, gnc_units;
    QofBook *book;
    Transaction *transaction;
    Split *split;
    gchar *notes, *tmp;

    g_assert(gnc_ofx_importer_gui);

    if (!data.account_id_valid)
    {
        PERR("account ID for this transaction is unavailable!");
        return 0;
    }

    account = gnc_import_select_account(gnc_gen_trans_list_widget(gnc_ofx_importer_gui),
                                        data.account_id, 0, NULL, NULL,
                                        ACCT_TYPE_NONE, NULL, NULL);
    if (account == NULL)
    {
        PERR("Unable to find account for id %s", data.account_id);
        return 0;
    }
    /***** Validate the input strings to ensure utf8 *****/
    if (data.name_valid)
        gnc_utf8_strip_invalid(data.name);
    if (data.memo_valid)
        gnc_utf8_strip_invalid(data.memo);
    if (data.check_number_valid)
        gnc_utf8_strip_invalid(data.check_number);
    if (data.reference_number_valid)
        gnc_utf8_strip_invalid(data.reference_number);

    /***** Create the transaction and setup transaction data *******/
    book = gnc_account_get_book(account);
    transaction = xaccMallocTransaction(book);
    xaccTransBeginEdit(transaction);

    /* Note: Unfortunately libofx <= 0.9.5 will not report a missing
     * date field as an invalid one. Instead, it will report it as
     * valid and return a completely bogus date. Starting with
     * libofx-0.9.6 (not yet released as of 2012-09-09), it will still
     * be reported as valid but at least the date integer itself is
     * just plain zero. */
    if (data.date_posted_valid && (data.date_posted != 0))
    {
        /* The hopeful case: We have a posted_date */
        xaccTransSetDatePostedSecsNormalized(transaction, data.date_posted);
    } else if (data.date_initiated_valid && (data.date_initiated != 0))
    {
        /* No posted date? Maybe we have an initiated_date */
        xaccTransSetDatePostedSecsNormalized(transaction, data.date_initiated);
    }
    else
    {
        /* Uh no, no valid date. As a workaround use today's date */
        xaccTransSetDatePostedSecsNormalized(transaction, current_time);
    }

    xaccTransSetDateEnteredSecs(transaction, current_time);

    /* Put transaction name in Description, or memo if name unavailable */
    if (data.name_valid)
    {
        xaccTransSetDescription(transaction, data.name);
    }
    else if (data.memo_valid)
    {
        xaccTransSetDescription(transaction, data.memo);
    }

    /* Put everything else in the Notes field */
    notes = g_strdup_printf("OFX ext. info: ");

    if (data.transactiontype_valid)
    {
        tmp = notes;
        notes = g_strdup_printf("%s%s%s", tmp, "|Trans type:",
                                gnc_ofx_ttype_to_string(data.transactiontype));
        g_free(tmp);
    }

    if (data.invtransactiontype_valid)
    {
        tmp = notes;
        notes = g_strdup_printf("%s%s%s", tmp, "|Investment Trans type:",
                                gnc_ofx_invttype_to_str(data.invtransactiontype));
        g_free(tmp);
    }
    if (data.memo_valid && data.name_valid) /* Copy only if memo wasn't put in Description */
    {
        tmp = notes;
        notes = g_strdup_printf("%s%s%s", tmp, "|Memo:", data.memo);
        g_free(tmp);
    }
    if (data.date_funds_available_valid)
    {
        Timespec ts;
        timespecFromTime64(&ts, data.date_funds_available);
        gnc_timespec_to_iso8601_buff (ts, dest_string);
        tmp = notes;
        notes = g_strdup_printf("%s%s%s", tmp, "|Date funds available:", dest_string);
        g_free(tmp);
    }
    if (data.server_transaction_id_valid)
    {
        tmp = notes;
        notes = g_strdup_printf("%s%s%s", tmp, "|Server trans ID (conf. number):", data.server_transaction_id);
        g_free(tmp);
    }
    if (data.standard_industrial_code_valid)
    {
        tmp = notes;
        notes = g_strdup_printf("%s%s%ld", tmp, "|Standard Industrial Code:", data.standard_industrial_code);
        g_free(tmp);

    }
    if (data.payee_id_valid)
    {
        tmp = notes;
        notes = g_strdup_printf("%s%s%s", tmp, "|Payee ID:", data.payee_id);
        g_free(tmp);
    }

    //PERR("WRITEME: GnuCash ofx_proc_transaction():Add PAYEE and ADRESS here once supported by libofx! Notes=%s\n", notes);

    /* Ideally, gnucash should process the corrected transactions */
    if (data.fi_id_corrected_valid)
    {
        PERR("WRITEME: GnuCash ofx_proc_transaction(): WARNING: This transaction corrected a previous transaction, but we created a new one instead!\n");
        tmp = notes;
        notes = g_strdup_printf("%s%s%s%s", tmp, "|This corrects transaction #", data.fi_id_corrected, "but GnuCash didn't process the correction!");
        g_free(tmp);
    }
    xaccTransSetNotes(transaction, notes);
    g_free(notes);

    if (data.account_ptr && data.account_ptr->currency_valid)
    {
        DEBUG("Currency from libofx: %s", data.account_ptr->currency);
        currency = gnc_commodity_table_lookup( gnc_get_current_commodities (),
                                               GNC_COMMODITY_NS_CURRENCY,
                                               data.account_ptr->currency);
    }
    else
    {
        DEBUG("Currency from libofx unavailable, defaulting to account's default");
        currency = xaccAccountGetCommodity(account);
    }

    xaccTransSetCurrency(transaction, currency);
    if (data.amount_valid)
    {
        if (!data.invtransactiontype_valid)
        {
            /***** Process a normal transaction ******/
            DEBUG("Adding split; Ordinary banking transaction, money flows from or into the source account");
            split = xaccMallocSplit(book);
            xaccTransAppendSplit(transaction, split);
            xaccAccountInsertSplit(account, split);

            gnc_amount = gnc_ofx_numeric_from_double_txn(data.amount, transaction);
            xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction));

            /* set tran-num and/or split-action per book option */
            if (data.check_number_valid)
            {
                gnc_set_num_action(transaction, split, data.check_number, NULL);
            }
            else if (data.reference_number_valid)
            {
                gnc_set_num_action(transaction, split, data.reference_number, NULL);
            }
            /* Also put the ofx transaction's memo in the
             * split's memo field */
            if (data.memo_valid)
            {
                xaccSplitSetMemo(split, data.memo);
            }
            if (data.fi_id_valid)
            {
                gnc_import_set_split_online_id(split, data.fi_id);
            }
        }

        else if (data.unique_id_valid
                 && data.security_data_valid
                 && data.security_data_ptr != NULL
                 && data.security_data_ptr->secname_valid)
        {
            gboolean choosing_account = TRUE;
            /********* Process an investment transaction **********/
            /* Note that the ACCT_TYPE_STOCK account type
               should be replaced with something derived from
               data.invtranstype*/

            // We have an investment transaction. First select the correct commodity.
            investment_commodity = gnc_import_select_commodity(data.unique_id,
                                   FALSE,
                                   NULL,
                                   NULL);
            if (investment_commodity != NULL)
            {
                // As we now have the commodity, select the account with that commodity.

                investment_account_text = g_strdup_printf( /* This string is a default account
                                                              name. It MUST NOT contain the
                                                              character ':' anywhere in it or
                                                              in any translations.  */
                                              _("Stock account for security \"%s\""),
                                              data.security_data_ptr->secname);

                investment_account_onlineid = g_strdup_printf( "%s%s", data.account_id, data.unique_id);
                investment_account = gnc_import_select_account(NULL,
                                                               investment_account_onlineid,
                                                               1,
                                                               investment_account_text,
                                                               investment_commodity,
                                                               ACCT_TYPE_STOCK,
                                                               NULL,
                                                               NULL);

                // but use it only if that's really the right commodity
                if (investment_account
                        && xaccAccountGetCommodity(investment_account) != investment_commodity)
                    investment_account = NULL;

                // Loop until we either have an account, or the user pressed Cancel
                while (!investment_account && choosing_account)
                {
                    // No account with correct commodity automatically found.

                    // But are we in auto-create mode and already know a parent?
                    if (auto_create_commodity && ofx_parent_account)
                    {
                        // Yes, so use that as parent when auto-creating the new account below.
                        investment_account = ofx_parent_account;
                    }
                    else
                    {
                        // Let the user choose an account
                        investment_account = gnc_import_select_account(
                                                 gnc_gen_trans_list_widget(gnc_ofx_importer_gui),
                                                 data.unique_id,
                                                 TRUE,
                                                 investment_account_text,
                                                 investment_commodity,
                                                 ACCT_TYPE_STOCK,
                                                 NULL,
                                                 &choosing_account);
                    }
                    // Does the chosen account have the right commodity?
                    if (investment_account && xaccAccountGetCommodity(investment_account) != investment_commodity)
                    {
                        if (auto_create_commodity
                                && xaccAccountTypesCompatible(xaccAccountGetType(investment_account),
                                                              ACCT_TYPE_STOCK))
                        {
                            // The user chose an account, but it does
                            // not have the right commodity. Also,
                            // auto-creation is on. Hence, we create a
                            // new child account of the selected one,
                            // and this one will have the right
                            // commodity.
                            Account *parent_account = investment_account;
                            investment_account =
                                gnc_ofx_new_account(investment_account_text,
                                                    investment_commodity,
                                                    parent_account,
                                                    ACCT_TYPE_STOCK);
                            if (investment_account)
                            {
                                gnc_import_set_acc_online_id(investment_account, data.unique_id);
                                choosing_account = FALSE;
                                ofx_parent_account = parent_account;
                            }
                            else
                            {
                                ofx_parent_account = NULL;
                            }
                        }
                        else
                        {
                            // No account with matching commodity. Ask the user
                            // whether to continue or abort.
                            choosing_account =
                                gnc_verify_dialog(
                                    gnc_gen_trans_list_widget(gnc_ofx_importer_gui), TRUE,
                                    "The chosen account \"%s\" does not have the correct "
                                    "currency/security \"%s\" (it has \"%s\" instead). "
                                    "This account cannot be used. "
                                    "Do you want to choose again?",
                                    xaccAccountGetName(investment_account),
                                    gnc_commodity_get_fullname(investment_commodity),
                                    gnc_commodity_get_fullname(xaccAccountGetCommodity(investment_account)));
                            // We must also delete the online_id that was set in gnc_import_select_account()
                            gnc_import_set_acc_online_id(investment_account, "");
                            investment_account = NULL;
                        }
                    }
                }
                if (!investment_account)
                {
                    PERR("No investment account found for text: %s\n", investment_account_text);
                }
                g_free (investment_account_text);
                g_free (investment_account_onlineid);
                investment_account_text = NULL;

                if (investment_account != NULL &&
                        data.unitprice_valid &&
                        data.units_valid &&
                        ( data.invtransactiontype != OFX_INCOME ) )
                {
                    DEBUG("Adding investment split; Money flows from or into the stock account");
                    split = xaccMallocSplit(book);
                    xaccTransAppendSplit(transaction, split);
                    xaccAccountInsertSplit(investment_account, split);

                    gnc_amount = gnc_ofx_numeric_from_double (ofx_get_investment_amount(&data),
                                 investment_commodity);
                    gnc_units = gnc_ofx_numeric_from_double (data.units, investment_commodity);
                    xaccSplitSetAmount(split, gnc_units);
                    xaccSplitSetValue(split, gnc_amount);

                    /* set tran-num and/or split-action per book option */
                    if (data.check_number_valid)
                    {
                        gnc_set_num_action(transaction, split, data.check_number, NULL);
                    }
                    else if (data.reference_number_valid)
                    {
                        gnc_set_num_action(transaction, split,
                                                data.reference_number, NULL);
                    }
                    if (data.security_data_ptr->memo_valid)
                    {
                        xaccSplitSetMemo(split, data.security_data_ptr->memo);
                    }
                    if (data.fi_id_valid)
                    {
                        gnc_import_set_split_online_id(split, data.fi_id);
                    }
                }
                else
                {
                    if (investment_account)
                        PERR("The investment account, units or unitprice was not found for the investment transaction");
                }
            }
            else
            {
                PERR("Commodity not found for the investment transaction");
            }

            if (data.invtransactiontype_valid && investment_account)
            {
                if (data.invtransactiontype == OFX_REINVEST
                        || data.invtransactiontype == OFX_INCOME)
                {
                    DEBUG("Now let's find an account for the destination split");

                    income_account = gnc_ofx_kvp_get_assoc_account(investment_account);

                    if (income_account == NULL)
                    {
                        DEBUG("Couldn't find an associated income account");
                        investment_account_text = g_strdup_printf( /* This string is a default account
                                                                      name. It MUST NOT contain the
                                                                      character ':' anywhere in it or
                                                                      in any translations.  */
                                                      _("Income account for security \"%s\""),
                                                      data.security_data_ptr->secname);
                        income_account = gnc_import_select_account(
                                             gnc_gen_trans_list_widget(gnc_ofx_importer_gui),
                                             NULL,
                                             1,
                                             investment_account_text,
                                             currency,
                                             ACCT_TYPE_INCOME,
                                             NULL,
                                             NULL);
                        gnc_ofx_kvp_set_assoc_account(investment_account,
                                                      income_account);
                        DEBUG("KVP written");

                    }
                    else
                    {
                        DEBUG("Found at least one associated income account");
                    }
                }
                if (income_account != NULL &&
                        data.invtransactiontype == OFX_REINVEST)
                {
                    DEBUG("Adding investment split; Money flows from the income account");
                    split = xaccMallocSplit(book);
                    xaccTransAppendSplit(transaction, split);
                    xaccAccountInsertSplit(income_account, split);

                    gnc_amount = gnc_ofx_numeric_from_double_txn (data.amount, transaction);
                    xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction));

                    // Set split memo from ofx transaction name or memo
                    gnc_ofx_set_split_memo(&data, split);
                }
                if (income_account != NULL &&
                        data.invtransactiontype == OFX_INCOME)
                {
                    DEBUG("Adding investment split; Money flows from the income account");
                    split = xaccMallocSplit(book);
                    xaccTransAppendSplit(transaction, split);
                    xaccAccountInsertSplit(income_account, split);

                    gnc_amount = gnc_ofx_numeric_from_double_txn (-data.amount,/*OFX_INCOME amounts come in as positive numbers*/
                                 transaction);
                    xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction));

                    // Set split memo from ofx transaction name or memo
                    gnc_ofx_set_split_memo(&data, split);
                }
            }

            if (data.invtransactiontype_valid
                    && data.invtransactiontype != OFX_REINVEST)
            {
                DEBUG("Adding investment split; Money flows from or to the cash account");
                split = xaccMallocSplit(book);
                xaccTransAppendSplit(transaction, split);
                xaccAccountInsertSplit(account, split);

                gnc_amount = gnc_ofx_numeric_from_double_txn(
                                 -ofx_get_investment_amount(&data), transaction);
                xaccSplitSetBaseValue(split, gnc_amount,
                                      xaccTransGetCurrency(transaction));

                // Set split memo from ofx transaction name or memo
                gnc_ofx_set_split_memo(&data, split);
            }
        }

        /* Send transaction to importer GUI. */
        if (xaccTransCountSplits(transaction) > 0)
        {
            DEBUG("%d splits sent to the importer gui", xaccTransCountSplits(transaction));
            gnc_gen_trans_list_add_trans (gnc_ofx_importer_gui, transaction);
        }
        else
        {
            PERR("No splits in transaction (missing account?), ignoring.");
            xaccTransDestroy(transaction);
            xaccTransCommitEdit(transaction);
        }
    }
    else
    {
        PERR("The transaction doesn't have a valid amount");
        xaccTransDestroy(transaction);
        xaccTransCommitEdit(transaction);
    }

    return 0;
}//end ofx_proc_transaction()
Пример #21
0
static gnc_commodity *
xaccTransFindCommonCurrency (Transaction *trans, QofBook *book)
{
    gnc_commodity *com_scratch;
    GList *node = NULL;
    GSList *comlist = NULL, *found = NULL;

    if (!trans) return NULL;

    if (trans->splits == NULL) return NULL;

    g_return_val_if_fail (book, NULL);

    /* Find the most commonly used currency among the splits.  If a given split
       is in a non-currency commodity, then look for an ancestor account in a
       currency, but prefer currencies used directly in splits.  Ignore trading
       account splits in this whole process, they don't add any value to this algorithm. */
    for (node = trans->splits; node; node = node->next)
    {
        Split *s = node->data;
        unsigned int curr_weight;

        if (s == NULL || s->acc == NULL) continue;
        if (xaccAccountGetType(s->acc) == ACCT_TYPE_TRADING) continue;
        com_scratch = xaccAccountGetCommodity(s->acc);
        if (com_scratch && gnc_commodity_is_currency(com_scratch))
        {
            curr_weight = 3;
        }
        else
        {
            com_scratch = gnc_account_get_currency_or_parent(s->acc);
            if (com_scratch == NULL) continue;
            curr_weight = 1;
        }
        if ( comlist )
        {
            found = g_slist_find_custom(comlist, com_scratch, commodity_equal);
        }
        if (comlist == NULL || found == NULL)
        {
            CommodityCount *count = g_slice_new0(CommodityCount);
            count->commodity = com_scratch;
            count->count = curr_weight;
            comlist = g_slist_append(comlist, count);
        }
        else
        {
            CommodityCount *count = (CommodityCount*)(found->data);
            count->count += curr_weight;
        }
    }
    found = g_slist_sort( comlist, commodity_compare);

    if ( found && found->data && (((CommodityCount*)(found->data))->commodity != NULL))
    {
        return ((CommodityCount*)(found->data))->commodity;
    }
    /* We didn't find a currency in the current account structure, so try
     * an old one. */
    return xaccTransFindOldCommonCurrency( trans, book );
}
Пример #22
0
static void
load_all_accounts (GncSqlBackend* be)
{
    GncSqlStatement* stmt = NULL;
    GncSqlResult* result;
    QofBook* pBook;
    GList* l_accounts_needing_parents = NULL;
    GSList* bal_slist;
    GSList* bal;

    g_return_if_fail (be != NULL);

    ENTER ("");

    pBook = be->book;

    stmt = gnc_sql_create_select_statement (be, TABLE_NAME);
    if (stmt == NULL)
    {
        LEAVE ("stmt == NULL");
        return;
    }
    result = gnc_sql_execute_select_statement (be, stmt);
    gnc_sql_statement_dispose (stmt);
    if (result != NULL)
    {
        GncSqlRow* row = gnc_sql_result_get_first_row (result);
        gchar* sql;

        while (row != NULL)
        {
            load_single_account (be, row, &l_accounts_needing_parents);
            row = gnc_sql_result_get_next_row (result);
        }
        gnc_sql_result_dispose (result);

        sql = g_strdup_printf ("SELECT DISTINCT guid FROM %s", TABLE_NAME);
        gnc_sql_slots_load_for_sql_subquery (be, sql, (BookLookupFn)xaccAccountLookup);
        g_free (sql);

        /* While there are items on the list of accounts needing parents,
           try to see if the parent has now been loaded.  Theory says that if
           items are removed from the front and added to the back if the
           parent is still not available, then eventually, the list will
           shrink to size 0. */
        if (l_accounts_needing_parents != NULL)
        {
            gboolean progress_made = TRUE;
            Account* root;
            Account* pParent;
            GList* elem;

            while (progress_made)
            {
                progress_made = FALSE;
                for (elem = l_accounts_needing_parents; elem != NULL;)
                {
                    account_parent_guid_struct* s = (account_parent_guid_struct*)elem->data;
                    pParent = xaccAccountLookup (&s->guid, be->book);
                    if (pParent != NULL)
                    {
                        GList* next_elem;

                        gnc_account_append_child (pParent, s->pAccount);
                        next_elem = g_list_next (elem);
                        l_accounts_needing_parents = g_list_delete_link (l_accounts_needing_parents,
                                                                         elem);
                        g_free (s);
                        elem = next_elem;
                        progress_made = TRUE;
                    }
                    else
                    {
                        /* Can't be up in the for loop because the 'then' clause reads inside a node freed
                           by g_list_delete_link(). */
                        elem = g_list_next (elem);
                    }
                }
            }

            /* Any non-ROOT accounts left over must be parented by the root account */
            root = gnc_book_get_root_account (pBook);
            while (l_accounts_needing_parents != NULL)
            {
                account_parent_guid_struct* s = (account_parent_guid_struct*)
                                                l_accounts_needing_parents->data;
                if (xaccAccountGetType (s->pAccount) != ACCT_TYPE_ROOT)
                {
                    gnc_account_append_child (root, s->pAccount);
                }
                g_free (s);
                l_accounts_needing_parents = g_list_delete_link (l_accounts_needing_parents,
                                                                 l_accounts_needing_parents);
            }
        }

        /* Load starting balances */
        bal_slist = gnc_sql_get_account_balances_slist (be);
        for (bal = bal_slist; bal != NULL; bal = bal->next)
        {
            acct_balances_t* balances = (acct_balances_t*)bal->data;

            qof_instance_increase_editlevel (balances->acct);
            g_object_set (balances->acct,
                          "start-balance", &balances->balance,
                          "start-cleared-balance", &balances->cleared_balance,
                          "start-reconciled-balance", &balances->reconciled_balance,
                          NULL);

            qof_instance_decrease_editlevel (balances->acct);
        }
        if (bal_slist != NULL)
        {
            g_slist_free (bal_slist);
        }
    }

    LEAVE ("");
}
Пример #23
0
Account *
gnc_account_select_combo_fill (GtkWidget *combo, QofBook *book,
                               GList *acct_types, GList *acct_commodities)
{
    GtkListStore *store;
    GtkTreeIter iter;
    GList *list, *node;
    const gchar *text;

    g_return_val_if_fail (combo && GTK_IS_COMBO_BOX(combo), NULL);
    g_return_val_if_fail (book, NULL);
    g_return_val_if_fail (acct_types, NULL);

    /* Figure out if anything is set in the combo */
    text = gtk_entry_get_text(GTK_ENTRY (gtk_bin_get_child(GTK_BIN (GTK_COMBO_BOX(combo)))));

    g_object_set_data (G_OBJECT(combo), "book", book);
    list = gnc_account_get_descendants (gnc_book_get_root_account (book));

    /* Clear the existing list */
    store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo)));
    gtk_list_store_clear(store);

    /* Add the account names to the combo box */
    for (node = list; node; node = node->next)
    {
        Account *account = node->data;
        char *name;

        /* Only present accounts of the appropriate type */
        if (g_list_index (acct_types, (gpointer)xaccAccountGetType (account))
                == -1)
            continue;

        /* Only present accounts with the right commodity, if that's a
           restriction */
        if (acct_commodities)
        {
            if ( g_list_find_custom( acct_commodities,
                                     GINT_TO_POINTER(xaccAccountGetCommodity(account)),
                                     gnc_commodity_compare_void) == NULL )
            {
                continue;
            }
        }

        name = gnc_account_get_full_name (account);
        gtk_list_store_append(store, &iter);
        gtk_list_store_set (store, &iter, 0, name, -1);

        /* Save the first account name in case no account name was set */
        if (!text || g_strcmp0 (text, "") == 0)
        {
            text = g_strdup (name);
        }
        g_free(name);
    }
    gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);

    g_list_free (list);

    gnc_cbwe_set_by_string(GTK_COMBO_BOX(combo), text);

    return gnc_account_select_combo_get_active (combo);
}