예제 #1
0
파일: Scrub.c 프로젝트: Bob-IT/gnucash
void
xaccTransScrubOrphans (Transaction *trans)
{
    SplitList *node;
    QofBook *book = NULL;
    Account *root = NULL;

    if (!trans) return;

    for (node = trans->splits; node; node = node->next)
    {
        Split *split = node->data;

        if (split->acc)
        {
            TransScrubOrphansFast (trans, gnc_account_get_root(split->acc));
            return;
        }
    }

    /* If we got to here, then *none* of the splits belonged to an
     * account.  Not a happy situation.  We should dig an account
     * out of the book the transaction belongs to.
     * XXX we should probably *always* to this, instead of the above loop!
     */
    PINFO ("Free Floating Transaction!");
    book = xaccTransGetBook (trans);
    root = gnc_book_get_root_account (book);
    TransScrubOrphansFast (trans, root);
}
예제 #2
0
/** Adds a split to a transaction.
 * @param trans The transaction to add a split to
 * @param account The split's account
 * @param amount The split's amount
 * @param rec_state The split's reconcile status
 * @param rec_date The split's reconcile date
 * @param price The split's conversion rate from account commodity to transaction commodity
 */
static void trans_add_split (Transaction* trans, Account* account, GncNumeric amount,
                            const boost::optional<std::string>& action,
                            const boost::optional<std::string>& memo,
                            const boost::optional<char>& rec_state,
                            const boost::optional<GncDate>& rec_date,
                            const boost::optional<GncNumeric> price)
{
    QofBook* book = xaccTransGetBook (trans);
    auto split = xaccMallocSplit (book);
    xaccSplitSetAccount (split, account);
    xaccSplitSetParent (split, trans);
    xaccSplitSetAmount (split, static_cast<gnc_numeric>(amount));
    auto trans_curr = xaccTransGetCurrency(trans);
    auto acct_comm = xaccAccountGetCommodity(account);
    GncNumeric value;
    if (gnc_commodity_equiv(trans_curr, acct_comm))
        value = amount;
    else if (price)
        value = amount * *price;
    else
    {
        auto time = xaccTransRetDatePosted (trans);
        /* Import data didn't specify price, let's lookup the nearest in time */
        auto nprice =
            gnc_pricedb_lookup_nearest_in_time64(gnc_pricedb_get_db(book),
                                                 acct_comm, trans_curr, time);
        if (nprice)
        {
            /* Found a usable price. Let's check if the conversion direction is right */
            GncNumeric rate;
            if (gnc_commodity_equiv(gnc_price_get_currency(nprice), trans_curr))
                rate = gnc_price_get_value(nprice);
            else
                rate = static_cast<GncNumeric>(gnc_price_get_value(nprice)).inv();

            value = amount * rate;
        }
        else
        {
            PWARN("No price found, using a price of 1.");
            value = amount;
        }
    }
    xaccSplitSetValue (split, static_cast<gnc_numeric>(value));

    if (memo)
        xaccSplitSetMemo (split, memo->c_str());
    /* Note, this function assumes the num/action switch is done at a higher level
     * if needed by the book option */
    if (action)
        xaccSplitSetAction (split, action->c_str());

    if (rec_state && *rec_state != 'n')
        xaccSplitSetReconcile (split, *rec_state);
    if (rec_state && *rec_state == YREC && rec_date)
        xaccSplitSetDateReconciledSecs (split,
                static_cast<time64>(GncDateTime(*rec_date, DayPart::neutral)));

}
예제 #3
0
파일: Scrub.c 프로젝트: Bob-IT/gnucash
static Split *
get_balance_split (Transaction *trans, Account *root, Account *account,
                   gnc_commodity *commodity)
{
    Split *balance_split;
    gchar *accname;

    if (!account ||
        !gnc_commodity_equiv (commodity, xaccAccountGetCommodity(account)))
    {
        if (!root)
        {
            root = gnc_book_get_root_account (xaccTransGetBook (trans));
            if (NULL == root)
            {
                /* This can't occur, things should be in books */
                PERR ("Bad data corruption, no root account in book");
                return NULL;
            }
        }
        accname = g_strconcat (_("Imbalance"), "-",
                               gnc_commodity_get_mnemonic (commodity), NULL);
        account = xaccScrubUtilityGetOrMakeAccount (root, commodity,
                                                    accname, ACCT_TYPE_BANK, FALSE);
        g_free (accname);
        if (!account)
        {
            PERR ("Can't get balancing account");
            return NULL;
        }
    }

    balance_split = xaccTransFindSplitByAccount(trans, account);

    /* Put split into account before setting split value */
    if (!balance_split)
    {
        balance_split = xaccMallocSplit (qof_instance_get_book(trans));

        xaccTransBeginEdit (trans);
        xaccSplitSetParent(balance_split, trans);
        xaccSplitSetAccount(balance_split, account);
        xaccTransCommitEdit (trans);
    }

    return balance_split;
}
예제 #4
0
파일: Scrub.c 프로젝트: Bob-IT/gnucash
/* Find the trading split for a commodity, but don't create any splits
   or accounts if they don't already exist. */
static Split *
find_trading_split (Transaction *trans, Account *root,
                    gnc_commodity *commodity)
{
    Account *trading_account;
    Account *ns_account;
    Account *account;

    if (!root)
    {
        root = gnc_book_get_root_account (xaccTransGetBook (trans));
        if (NULL == root)
        {
            /* This can't occur, things should be in books */
            PERR ("Bad data corruption, no root account in book");
            return NULL;
        }
    }

    trading_account = gnc_account_lookup_by_name (root, _("Trading"));
    if (!trading_account)
    {
        return NULL;
    }

    ns_account = gnc_account_lookup_by_name (trading_account,
                                             gnc_commodity_get_namespace(commodity));
    if (!ns_account)
    {
        return NULL;
    }

    account = gnc_account_lookup_by_name (ns_account,
                                          gnc_commodity_get_mnemonic(commodity));
    if (!account)
    {
        return NULL;
    }

    return xaccTransFindSplitByAccount(trans, account);
}
예제 #5
0
파일: Scrub.c 프로젝트: Bob-IT/gnucash
/* Get the trading split for a given commodity, creating it (and the
   necessary accounts) if it doesn't exist. */
static Split *
get_trading_split (Transaction *trans, Account *root,
                   gnc_commodity *commodity)
{
    Split *balance_split;
    Account *trading_account;
    Account *ns_account;
    Account *account;
    gnc_commodity *default_currency = NULL;

    if (!root)
    {
        root = gnc_book_get_root_account (xaccTransGetBook (trans));
        if (NULL == root)
        {
            /* This can't occur, things should be in books */
            PERR ("Bad data corruption, no root account in book");
            return NULL;
        }
    }

    /* Get the default currency.  This is harder than it seems.  It's not
       possible to call gnc_default_currency() since it's a UI function.  One
       might think that the currency of the root account would do, but the root
       account has no currency.  Instead look for the Income placeholder account
       and use its currency.  */
    default_currency = xaccAccountGetCommodity(gnc_account_lookup_by_name(root,
                                                                          _("Income")));
    if (! default_currency)
    {
        default_currency = commodity;
    }

    trading_account = xaccScrubUtilityGetOrMakeAccount (root,
                                                        default_currency,
                                                        _("Trading"),
                                                        ACCT_TYPE_TRADING, TRUE);
    if (!trading_account)
    {
        PERR ("Can't get trading account");
        return NULL;
    }

    ns_account = xaccScrubUtilityGetOrMakeAccount (trading_account,
                                                   default_currency,
                                                   gnc_commodity_get_namespace(commodity),
                                                   ACCT_TYPE_TRADING, TRUE);
    if (!ns_account)
    {
        PERR ("Can't get namespace account");
        return NULL;
    }

    account = xaccScrubUtilityGetOrMakeAccount (ns_account, commodity,
                                                gnc_commodity_get_mnemonic(commodity),
                                                ACCT_TYPE_TRADING, FALSE);
    if (!account)
    {
        PERR ("Can't get commodity account");
        return NULL;
    }


    balance_split = xaccTransFindSplitByAccount(trans, account);

    /* Put split into account before setting split value */
    if (!balance_split)
    {
        balance_split = xaccMallocSplit (qof_instance_get_book(trans));

        xaccTransBeginEdit (trans);
        xaccSplitSetParent(balance_split, trans);
        xaccSplitSetAccount(balance_split, account);
        xaccTransCommitEdit (trans);
    }

    return balance_split;
}
static const char*
node_and_transaction_equal (xmlNodePtr node, Transaction* trn)
{
    xmlNodePtr mark;

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

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

    if (!node->name || g_strcmp0 ((char*)node->name, "gnc:transaction"))
    {
        return "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, "trn:id") == 0)
        {
            if (!equals_node_val_vs_guid (mark, xaccTransGetGUID (trn)))
            {
                return "ids differ";
            }
        }

        /* This test will fail for many splits where the transaction has
         * splits in different commodities -- eg, buying or selling a
         * stock. jralls 2010-11-02 */
        else if (g_strcmp0 ((char*)mark->name, "trn:currency") == 0)
        {
#if 0
            if (!equals_node_val_vs_commodity (
                    mark, xaccTransGetCurrency (trn), xaccTransGetBook (trn)))
            {
                return g_strdup ("currencies differ");
            }
#endif
        }
        else if (g_strcmp0 ((char*)mark->name, "trn:num") == 0)
        {
            if (!equals_node_val_vs_string (mark, xaccTransGetNum (trn)))
            {
                return "nums differ";
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "trn:date-posted") == 0)
        {
            if (!equals_node_val_vs_date (mark, xaccTransRetDatePostedTS (trn)))
            {
                return "posted dates differ";
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "trn:date-entered") == 0)
        {
            if (!equals_node_val_vs_date (mark, xaccTransRetDateEnteredTS (trn)))
            {
                return "entered dates differ";
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "trn:description") == 0)
        {
            if (!equals_node_val_vs_string (mark, xaccTransGetDescription (trn)))
            {
                return "descriptions differ";
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "trn:slots") == 0)
        {
            if (!equals_node_val_vs_kvp_frame (mark,
                                               qof_instance_get_slots (QOF_INSTANCE (trn))))
            {
                return "slots differ";
            }
        }
        else if (g_strcmp0 ((char*)mark->name, "trn:splits") == 0)
        {
            const char* msg = equals_node_val_vs_splits (mark, trn);
            if (msg != NULL)
            {
                return msg;
            }
        }
        else
        {
            return "unknown node";
        }
    }

    return NULL;
}