Exemple #1
0
static void
TransScrubOrphansFast (Transaction *trans, Account *root)
{
    GList *node;
    gchar *accname;

    if (!trans) return;
    g_return_if_fail (root);

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

        if (split->acc) continue;

        DEBUG ("Found an orphan \n");

        accname = g_strconcat (_("Orphan"), "-",
                               gnc_commodity_get_mnemonic (trans->common_currency),
                               NULL);
        orph = xaccScrubUtilityGetOrMakeAccount (root, trans->common_currency,
                                                 accname, ACCT_TYPE_BANK, FALSE);
        g_free (accname);
        if (!orph) continue;

        xaccSplitSetAccount(split, orph);
    }
}
Exemple #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)));

}
Exemple #3
0
/** Adds a split to a transaction.
 * @param trans The transaction to add a split to
 * @param account The account used for the split
 * @param book The book where the split should be stored
 * @param amount The amount of the split
 */
static void trans_add_split(Transaction* trans, Account* account, QofBook* book,
gnc_numeric amount)
{
    Split* split = xaccMallocSplit(book);
    xaccSplitSetAccount(split, account);
    xaccSplitSetParent(split, trans);
    xaccSplitSetAmount(split, amount);
    xaccSplitSetValue(split, amount);
    xaccSplitSetAction(split, "Deposit");
}
Exemple #4
0
/** Adds a split to a transaction.
 * @param trans The transaction to add a split to
 * @param account The account used for the split
 * @param book The book where the split should be stored
 * @param amount The amount of the split
 */
static void trans_add_split (Transaction* trans, Account* account, QofBook* book,
                            gnc_numeric amount, const char *num)
{
    Split* split = xaccMallocSplit (book);
    xaccSplitSetAccount (split, account);
    xaccSplitSetParent (split, trans);
    xaccSplitSetAmount (split, amount);
    xaccSplitSetValue (split, amount);
    /* set tran-num and/or split-action per book option */
    gnc_set_num_action (trans, split, num, NULL);
}
Exemple #5
0
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;
}
Exemple #6
0
/* 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;
}
Transaction *
gnc_ab_trans_to_gnc(const AB_TRANSACTION *ab_trans, Account *gnc_acc)
{
    QofBook *book;
    Transaction *gnc_trans;
    const gchar *fitid;
    const GWEN_TIME *valuta_date;
    time64 current_time;
    const char *custref;
    gchar *description;
    Split *split;
    gchar *memo;

    g_return_val_if_fail(ab_trans && gnc_acc, NULL);

    /* Create new GnuCash transaction for the given AqBanking one */
    book = gnc_account_get_book(gnc_acc);
    gnc_trans = xaccMallocTransaction(book);
    xaccTransBeginEdit(gnc_trans);

    /* Date / Time */
    valuta_date = AB_Transaction_GetValutaDate(ab_trans);
    if (!valuta_date)
    {
        const GWEN_TIME *normal_date = AB_Transaction_GetDate(ab_trans);
        if (normal_date)
            valuta_date = normal_date;
    }
    if (valuta_date)
        xaccTransSetDatePostedSecsNormalized(gnc_trans, GWEN_Time_toTime_t(valuta_date));
    else
        g_warning("transaction_cb: Oops, date 'valuta_date' was NULL");

    xaccTransSetDateEnteredSecs(gnc_trans, gnc_time (NULL));

    /* Currency.  We take simply the default currency of the gnucash account */
    xaccTransSetCurrency(gnc_trans, xaccAccountGetCommodity(gnc_acc));

    /* Trans-Num or Split-Action set with gnc_set_num_action below per book
     * option */

    /* Description */
    description = gnc_ab_description_to_gnc(ab_trans);
    xaccTransSetDescription(gnc_trans, description);
    g_free(description);

    /* Notes. */
    /* xaccTransSetNotes(gnc_trans, g_notes); */
    /* But Nobody ever uses the Notes field? */

    /* Add one split */
    split = xaccMallocSplit(book);
    xaccSplitSetParent(split, gnc_trans);
    xaccSplitSetAccount(split, gnc_acc);

    /* Set the transaction number or split action field based on book option.
     * We use the "customer reference", if there is one. */
    custref = AB_Transaction_GetCustomerReference(ab_trans);
    if (custref && *custref
            && g_ascii_strncasecmp(custref, "NONREF", 6) != 0)
        gnc_set_num_action (gnc_trans, split, custref, NULL);

    /* Set OFX unique transaction ID */
    fitid = AB_Transaction_GetFiId(ab_trans);
    if (fitid && *fitid)
        gnc_import_set_split_online_id(split, fitid);

    {
        /* Amount into the split */
        const AB_VALUE *ab_value = AB_Transaction_GetValue(ab_trans);
        double d_value = ab_value ? AB_Value_GetValueAsDouble (ab_value) : 0.0;
        AB_TRANSACTION_TYPE ab_type = AB_Transaction_GetType (ab_trans);
        gnc_numeric gnc_amount;

        /*printf("Transaction with value %f has type %d\n", d_value, ab_type);*/
        /* If the value is positive, but the transaction type says the
           money is transferred away from our account (Transfer instead of
           DebitNote), we switch the value to negative. */
        if (d_value > 0.0 && ab_type == AB_Transaction_TypeTransfer)
            d_value = -d_value;

        gnc_amount = double_to_gnc_numeric(
                         d_value,
                         xaccAccountGetCommoditySCU(gnc_acc),
                         GNC_HOW_RND_ROUND_HALF_UP);
        if (!ab_value)
            g_warning("transaction_cb: Oops, value was NULL.  Using 0");
        xaccSplitSetBaseValue(split, gnc_amount, xaccAccountGetCommodity(gnc_acc));
    }

    /* Memo in the Split. */
    memo = gnc_ab_memo_to_gnc(ab_trans);
    xaccSplitSetMemo(split, memo);
    g_free(memo);

    return gnc_trans;
}
static gboolean
create_each_transaction_helper(Transaction *template_txn, void *user_data)
{
    Transaction *new_txn;
    GList *txn_splits, *template_splits;
    Split *copying_split;
    gnc_commodity *first_cmdty = NULL;
    gboolean err_flag = FALSE;
    SxTxnCreationData *creation_data;

    creation_data = (SxTxnCreationData*)user_data;

    /* FIXME: In general, this should [correctly] deal with errors such
       as not finding the approrpiate Accounts and not being able to
       parse the formula|credit/debit strings. */

    new_txn = xaccTransClone(template_txn);
    xaccTransBeginEdit(new_txn);

    g_debug("creating template txn desc [%s] for sx [%s]",
            xaccTransGetDescription(new_txn),
            xaccSchedXactionGetName(creation_data->instance->parent->sx));

    /* clear any copied KVP data */
    qof_instance_set_slots(QOF_INSTANCE(new_txn), kvp_frame_new());

    /* Bug#500427: copy the notes, if any */
    if (xaccTransGetNotes(template_txn) != NULL)
    {
        xaccTransSetNotes(new_txn, g_strdup(xaccTransGetNotes(template_txn)));
    }

    xaccTransSetDate(new_txn,
                     g_date_get_day(&creation_data->instance->date),
                     g_date_get_month(&creation_data->instance->date),
                     g_date_get_year(&creation_data->instance->date));

    /* the accounts and amounts are in the kvp_frames of the splits. */
    template_splits = xaccTransGetSplitList(template_txn);
    txn_splits = xaccTransGetSplitList(new_txn);
    if ((template_splits == NULL) || (txn_splits == NULL))
    {
        g_critical("transaction w/o splits for sx [%s]",
                   xaccSchedXactionGetName(creation_data->instance->parent->sx));
        xaccTransDestroy(new_txn);
        xaccTransCommitEdit(new_txn);
        return FALSE;
    }

    for (;
            txn_splits && template_splits;
            txn_splits = txn_splits->next, template_splits = template_splits->next)
    {
        Split *template_split;
        Account *split_acct;
        gnc_commodity *split_cmdty = NULL;

        /* FIXME: Ick.  This assumes that the split lists will be ordered
           identically. :( They are, but we'd rather not have to count on
           it. --jsled */
        template_split = (Split*)template_splits->data;
        copying_split = (Split*)txn_splits->data;

        if (!_get_template_split_account(creation_data->instance, template_split, &split_acct, creation_data->creation_errors))
        {
            err_flag = TRUE;
            break;
        }

        /* clear out any copied Split frame data. */
        qof_instance_set_slots(QOF_INSTANCE(copying_split), kvp_frame_new());

        split_cmdty = xaccAccountGetCommodity(split_acct);
        if (first_cmdty == NULL)
        {
            first_cmdty = split_cmdty;
            xaccTransSetCurrency(new_txn, first_cmdty);
        }

        xaccSplitSetAccount(copying_split, split_acct);

        {
            gnc_numeric credit_num, debit_num, final;
            gint gncn_error;

            credit_num = gnc_numeric_zero();
            debit_num = gnc_numeric_zero();

            _get_credit_formula_value(creation_data->instance, template_split, &credit_num, creation_data->creation_errors);
            _get_debit_formula_value(creation_data->instance, template_split, &debit_num, creation_data->creation_errors);

            final = gnc_numeric_sub_fixed( debit_num, credit_num );

            gncn_error = gnc_numeric_check(final);
            if (gncn_error != GNC_ERROR_OK)
            {
                GString *err = g_string_new("");
                g_string_printf(err, "error %d in SX [%s] final gnc_numeric value, using 0 instead",
                                gncn_error, xaccSchedXactionGetName(creation_data->instance->parent->sx));
                g_critical("%s", err->str);
                if (creation_data->creation_errors != NULL)
                    *creation_data->creation_errors = g_list_append(*creation_data->creation_errors, err);
                else
                    g_string_free(err, TRUE);
                final = gnc_numeric_zero();
            }