/***************************************************************************
 *   Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>  *
 ***************************************************************************/
/** @file
 * This file implements classes SKGDocumentBank.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include "skgdocumentbank.h"
#include "skgbankobject.h"
#include "skgaccountobject.h"
#include "skgunitobject.h"
#include "skgunitvalueobject.h"
#include "skgtraces.h"
#include "skgerror.h"
#include "skgservices.h"
#include "skgtransactionmng.h"

#include <klocale.h>
#include <kglobal.h>
#include <kicon.h>
#include <kcolorscheme.h>

#include <QSqlDatabase>
#include <QDBusConnection>

#include <cmath>

#ifdef Q_OS_WIN
#define isnan(a) _isnan(a)
#define isinf(a) !_finite(a)
#else
using std::isnan;
using std::isinf;
#endif

SKGDocumentBank::SKGDocumentBank() : SKGDocument(), m_computeBalances(true)
{
    SKGTRACEIN(10, "SKGDocumentBank::SKGDocumentBank");
    connect(this, SIGNAL(tableModified(QString,int)), this, SLOT(refreshCache(QString)));

    QDBusConnection dbus = QDBusConnection::sessionBus();
    dbus.registerObject("/skrooge/skgdocumentbank", this, QDBusConnection::ExportAllContents);
    dbus.registerService("org.skrooge");

    //Initialisation of not undoable tables
    SKGListNotUndoable.push_back("T.operationbalance");
    SKGListNotUndoable.push_back("T.budgetcategory");
}

SKGDocumentBank::~SKGDocumentBank()
{
    SKGTRACEIN(10, "SKGDocumentBank::~SKGDocumentBank");
}

SKGError SKGDocumentBank::computeBudgetCategoriesLinks()
{
    SKGError err;
    SKGTRACEINRC(5, "SKGDocumentBank::computeBudgetCategoriesLinks", err);
    //Remove computed values
    err = this->executeSqliteOrder("DELETE FROM budgetcategory");

    //Compute values
    if (!err) err = executeSqliteOrder(
                            "INSERT INTO budgetcategory (id, id_category) "
                            "SELECT b.id, c.id  "
                            "FROM budget b, category c WHERE "
                            "((b.rc_category_id<>0 AND (c.id=b.rc_category_id OR "
                            "(b.t_including_subcategories='Y' AND c.t_fullname LIKE (SELECT c2.t_fullname FROM category c2 WHERE c2.id=b.rc_category_id)||'"
                            % OBJECTSEPARATOR % "%')) OR (b.rc_category_id=0 AND c.id NOT IN (SELECT b2.rc_category_id FROM budget b2 WHERE b2.i_year=b.i_year AND "
                            "(b2.i_month=b.i_month OR b.i_month=0) AND b2.id<>b.id))))");

    return err;
}

void SKGDocumentBank::setComputeBalances(bool iEnabled)
{
    if (iEnabled != m_computeBalances) {
        m_computeBalances = iEnabled;
        computeBalances();
    }
}

SKGError SKGDocumentBank::computeBalances()
{
    SKGError err;
    SKGTRACEINRC(5, "SKGDocumentBank::computeBalances", err);
    //Remove computed values
    err = this->executeSqliteOrder("DELETE FROM operationbalance");

    if (m_computeBalances) {
        SKGStringListList result;
        if (!err) err = executeSelectSqliteOrder("SELECT id, rd_account_id, f_CURRENTAMOUNT FROM v_operation WHERE t_template='N' ORDER BY rd_account_id, d_date, id", result);
        int nb = result.count();
        double sum = 0;
        int currentAccount = 0;
        for (int i = 1; !err && i < nb; ++i) { //Ignore header
            QStringList line = result.at(i);
            QString idOp = line.at(0);
            int account = SKGServices::stringToInt(line.at(1));
            double val = SKGServices::stringToDouble(line.at(2));

            if (account != currentAccount) {
                sum = 0;
                currentAccount = account;
            }

            sum += val;
            err = this->executeSqliteOrder("INSERT INTO operationbalance (id,f_balance,r_operation_id) "
                                           "VALUES (" %
                                           SKGServices::intToString(i) % ',' %
                                           SKGServices::doubleToString(sum) % ',' %
                                           idOp %
                                           ")");
        }
    }
    return err;
}

SKGError SKGDocumentBank::endTransaction(bool succeedded)
{
    SKGError err;
    if (succeedded && getDepthTransaction() == 1) {
        if (getCachedValue("SKG_REFRESH_VIEW") == "Y") {
            QStringList listModifiedTables;
            err = this->getDistinctValues("doctransactionitem",
                                          "t_object_table",
                                          "rd_doctransaction_id=0",
                                          listModifiedTables);
            if (!err &&
                    (listModifiedTables.contains("operation") || listModifiedTables.contains("suboperation") || listModifiedTables.contains("unit") || listModifiedTables.contains("unitvalue"))
               ) {
                //Computation of cache
                err = computeBalances();
            }

            if (!err &&
                    (listModifiedTables.contains("operation") || listModifiedTables.contains("suboperation") || listModifiedTables.contains("unit") || listModifiedTables.contains("unitvalue") || listModifiedTables.contains("category") || listModifiedTables.contains("budget"))
               ) {
                //Computation of cache
                err = computeBudgetCategoriesLinks();
            }
        }
        //Clean main variations cache
        m_5mainVariations_cache.clear();
        m_5mainVariationsCat_cache.clear();
        m_5mainVariations_inputs = "";
    }

    SKGError err2 = SKGDocument::endTransaction(succeedded);
    if (!err && err2) err = err2;
    return err;
}

QString SKGDocumentBank::getViewsIndexesAndTriggersVersion()
{
    return "2011.11.05_" % getParameter("SKG_LANGUAGE");
}

SKGError SKGDocumentBank::refreshViewsIndexesAndTriggers()
{
    SKGError err;
    SKGTRACEINRC(5, "SKGDocumentBank::refreshViewsIndexesAndTriggers", err);

    QString version = getParameter("SKG_DB_BANK_VIEWS_VERSION");
    if (version == getViewsIndexesAndTriggersVersion()) return err;

    err = setParameter("SKG_DB_BANK_VIEWS_VERSION", getViewsIndexesAndTriggersVersion());

    QString dateFormatShort = "%Y-%m-%d";
    KLocale* locale = KGlobal::locale();
    bool negativePrefixCurrencySymbol = false;
    if (locale) {
        dateFormatShort = locale->dateFormatShort();
        negativePrefixCurrencySymbol = locale->negativePrefixCurrencySymbol();
    }

    //WARNING: Don't forget to update getViewVersion when this methode is modified
    /**
     * This constant is used to initialized the data model (trigger creation)
     * IF YOU MODIFY THIS METHOD, DO NOT FORGET TO MODIFY getViewsIndexesAndTriggersVersion TOO
     */
    QStringList BankInitialDataModelTrigger;
    BankInitialDataModelTrigger DELETECASCADEPARAMETER("bank")
    DELETECASCADEPARAMETER("account")
    DELETECASCADEPARAMETER("unit")
    DELETECASCADEPARAMETER("unitvalue")
    DELETECASCADEPARAMETER("category")
    DELETECASCADEPARAMETER("operation")
    DELETECASCADEPARAMETER("interest")
    DELETECASCADEPARAMETER("suboperation")
    DELETECASCADEPARAMETER("refund")
    DELETECASCADEPARAMETER("payee")
    DELETECASCADEPARAMETER("recurrentoperation")
    DELETECASCADEPARAMETER("rule")
    DELETECASCADEPARAMETER("budget")
    DELETECASCADEPARAMETER("budgetrule")


    //Compute fullname
            << "DROP TRIGGER IF EXISTS cpt_category_fullname3"
            /* << "CREATE TRIGGER cpt_category_fullname1 " //This trigger must be the first
             "AFTER UPDATE OF t_fullname ON category BEGIN "
             "UPDATE category SET t_name=t_name WHERE rd_category_id=new.id;"
             "END"*/

            << "DROP TRIGGER IF EXISTS cpt_category_fullname1"
            << "CREATE TRIGGER cpt_category_fullname1 "
            "AFTER INSERT ON category BEGIN "
            "UPDATE category SET t_fullname="
            "CASE WHEN rd_category_id IS NULL OR rd_category_id='' OR rd_category_id=0 THEN new.t_name ELSE (SELECT c.t_fullname FROM category c WHERE c.id=new.rd_category_id)||'" % OBJECTSEPARATOR % "'||new.t_name END "
            "WHERE id=new.id;"
            "END"

            << "DROP TRIGGER IF EXISTS cpt_category_fullname2"
            << "CREATE TRIGGER cpt_category_fullname2 "
            "AFTER UPDATE OF t_name, rd_category_id ON category BEGIN "
            "UPDATE category SET t_fullname="
            "CASE WHEN rd_category_id IS NULL OR rd_category_id='' OR rd_category_id=0 THEN new.t_name ELSE (SELECT c.t_fullname FROM category c WHERE c.id=new.rd_category_id)||'" % OBJECTSEPARATOR % "'||new.t_name END "
            "WHERE id=new.id;"
            "UPDATE category SET t_name=t_name WHERE rd_category_id=new.id;"
            "END"

            //-- Reparent suboperation on parent category when a category is removed
            << "DROP TRIGGER IF EXISTS fkdc_category_delete"
            << "CREATE TRIGGER fkdc_category_delete "
            "BEFORE DELETE ON category "
            "FOR EACH ROW BEGIN "
            "    UPDATE suboperation SET r_category_id=OLD.rd_category_id WHERE r_category_id=OLD.id; "
            "END "

            << "DROP TRIGGER IF EXISTS fkdc_category_parent_id_category_id"
            ;
    /**
     * This constant is used to initialized the data model (index creation)
     */
    QStringList BankInitialDataModelIndex;
    BankInitialDataModelIndex << "CREATE UNIQUE INDEX uidx_unit_name ON unit(t_name)"
                              << "CREATE UNIQUE INDEX uidx_unit_symbol ON unit(t_symbol)"

                              << "CREATE INDEX idx_unit_unit_id ON unitvalue(rd_unit_id)"
                              << "CREATE UNIQUE INDEX uidx_unitvalue ON unitvalue(d_date,rd_unit_id)"

                              << "CREATE UNIQUE INDEX uidx_bank_name ON bank(t_name)"

                              << "CREATE UNIQUE INDEX uidx_account_name ON account(t_name)"
                              << "CREATE INDEX idx_account_bank_id ON account(rd_bank_id)"
                              << "CREATE INDEX idx_account_type ON account(t_type)"

                              << "CREATE INDEX idx_category_category_id ON category(rd_category_id)"
                              << "CREATE INDEX idx_category_t_fullname ON category(t_fullname)"
                              << "CREATE UNIQUE INDEX uidx_category_parent_id_name ON category(t_name,rd_category_id)"
                              << "CREATE UNIQUE INDEX uidx_category_fullname ON  category(t_fullname)"

                              << "CREATE INDEX  idx_operation_account_id ON operation (rd_account_id)"
                              << "CREATE INDEX  idx_operation_tmp1_found_transfert ON operation (rc_unit_id, d_date)"
                              << "CREATE INDEX  idx_operation_grouped_operation_id ON operation (i_group_id)"
                              //<< "CREATE INDEX  idx_operation_t_mode ON operation (t_mode)"
                              //<< "CREATE INDEX  idx_operation_t_payee ON operation (t_payee)"
                              << "CREATE INDEX  idx_operation_i_number ON operation (i_number)"
                              << "CREATE INDEX  idx_operation_i_tmp ON operation (i_tmp)"
                              << "CREATE INDEX  idx_operation_rd_account_id ON operation (rd_account_id)"
                              << "CREATE INDEX  idx_operation_rc_unit_id ON operation (rc_unit_id)"
                              << "CREATE INDEX  idx_operation_t_status ON operation (t_status)"
                              << "CREATE INDEX  idx_operation_t_import_id ON operation (t_import_id)"
                              << "CREATE INDEX  idx_operation_t_template ON operation (t_template)"
                              << "CREATE INDEX  idx_operation_d_date ON operation (d_date)"

                              << "CREATE INDEX  idx_operationbalance_operation_id ON operationbalance (r_operation_id)"

                              << "CREATE INDEX idx_suboperation_operation_id ON suboperation (rd_operation_id)"
                              << "CREATE INDEX idx_suboperation_i_tmp ON suboperation (i_tmp)"
                              << "CREATE INDEX idx_suboperation_category_id ON suboperation (r_category_id)"
                              << "CREATE INDEX idx_suboperation_refund_id_id ON suboperation (r_refund_id)"

                              << "CREATE INDEX  idx_recurrentoperation_rd_operation_id ON recurrentoperation (rd_operation_id)"

                              << "CREATE UNIQUE INDEX uidx_refund_name ON refund(t_name)"
                              << "CREATE INDEX idx_refund_close ON refund(t_close)"

                              << "CREATE UNIQUE INDEX uidx_payee_name ON payee(t_name)"

                              << "CREATE INDEX  idx_interest_account_id ON interest (rd_account_id)"
                              << "CREATE UNIQUE INDEX uidx_interest ON interest(d_date,rd_account_id)"

                              << "CREATE INDEX idx_rule_action_type ON rule(t_action_type)"

                              << "CREATE UNIQUE INDEX uidx_budget ON budget(i_year,i_month, rc_category_id)"
                              << "CREATE INDEX idx_budget_category_id ON budget(rc_category_id)"
                              << "CREATE INDEX idx_budgetcategory_id ON budgetcategory (id)"
                              << "CREATE INDEX idx_budgetcategory_id_category ON budgetcategory (id_category)"
                              ;

    /**
     * This constant is used to initialized the data model (view creation)
     */
    QStringList BankInitialDataModelView;
    BankInitialDataModelView
    // ==================================================================
    //These following views contains only attributes used by corresponding class (better for performances)
    //unit
            << "CREATE VIEW  v_unit_displayname AS "
            "SELECT *, t_name||' ('||t_symbol||')' AS t_displayname FROM unit"

            << "CREATE VIEW  v_unit_tmp1 AS "
            "SELECT *,"
            "(SELECT count(1) FROM unitvalue s WHERE s.rd_unit_id=unit.id) AS i_NBVALUES, "
            "(CASE WHEN unit.rd_unit_id=0 THEN '' ELSE (SELECT (CASE WHEN s.t_symbol!='' THEN s.t_symbol ELSE s.t_name END) FROM unit s WHERE s.id=unit.rd_unit_id) END) AS t_UNIT,"
            "(CASE unit.t_type "
            "WHEN '1' THEN '" % SKGServices::stringToSqlString(i18nc("Noun", "Primary currency")) % "' "
            "WHEN '2' THEN '" % SKGServices::stringToSqlString(i18nc("Noun", "Secondary currency")) % "' "
            "WHEN 'C' THEN '" % SKGServices::stringToSqlString(i18nc("Noun, a country's currency", "Currency")) % "' "
            "WHEN 'S' THEN '" % SKGServices::stringToSqlString(i18nc("Noun, a financial share, as in a stock market", "Share")) % "' "
            "WHEN 'I' THEN '" % SKGServices::stringToSqlString(i18nc("Noun, a financial index like the Dow Jones, NASDAQ, CAC40...", "Index")) % "' "
            "ELSE '" % SKGServices::stringToSqlString(i18nc("Noun, a physical object like a house or a car", "Object")) % "' END) AS t_TYPENLS, "
            "(SELECT MIN(s.d_date) FROM  unitvalue s WHERE s.rd_unit_id=unit.id) AS d_MINDATE, "
            "(SELECT MAX(s.d_date) FROM  unitvalue s WHERE s.rd_unit_id=unit.id) AS d_MAXDATE "
            "from unit"

            << "CREATE VIEW  v_unit_tmp2 AS "
            "SELECT *,"
            "CASE WHEN v_unit_tmp1.t_type='1' THEN 1 ELSE IFNULL((SELECT s.f_quantity FROM unitvalue s WHERE s.rd_unit_id=v_unit_tmp1.id AND s.d_date=v_unit_tmp1.d_MAXDATE),1) END AS f_LASTVALUE "
            "from v_unit_tmp1"

            << "CREATE VIEW  v_unit AS "
            "SELECT *,"
            "v_unit_tmp2.f_LASTVALUE*IFNULL((SELECT s2.f_LASTVALUE FROM v_unit_tmp2 s2 WHERE s2.id=v_unit_tmp2.rd_unit_id) , 1) AS f_CURRENTAMOUNT "
            "from v_unit_tmp2"

            //unitvalue
            << "CREATE VIEW  v_unitvalue_displayname AS "
            "SELECT *, (SELECT t_displayname FROM v_unit_displayname WHERE unitvalue.rd_unit_id=v_unit_displayname.id)||' '||STRFTIME('" % dateFormatShort % "',d_date) AS t_displayname FROM unitvalue"

            << "CREATE VIEW  v_unitvalue AS "
            "SELECT * "
            "FROM unitvalue"

            //suboperation
            << "CREATE VIEW  v_suboperation AS "
            "SELECT * "
            "FROM suboperation"

            //operation
            << "CREATE VIEW  v_operation_numbers AS "
            "SELECT DISTINCT i_number, rd_account_id FROM operation"

            << "CREATE VIEW  v_operation_next_numbers AS "
            "SELECT T1.i_number+1 AS i_number FROM v_operation_numbers AS T1 LEFT OUTER JOIN v_operation_numbers T2 "
            "ON T2.rd_account_id=T1.rd_account_id AND T2.i_number=T1.i_number+1 "
            "WHERE T1.i_number!=0 AND (T2.i_number IS NULL) ORDER BY T1.i_number"

            << "CREATE VIEW  v_operation_tmp1 AS "
            "SELECT *,"
            "(SELECT t_name FROM payee s WHERE s.id=operation.r_payee_id) AS t_PAYEE,"
            "(SELECT TOTAL(s.f_value) FROM suboperation s WHERE s.rd_operation_id=operation.ID) AS f_QUANTITY,"
            "(SELECT count(1) FROM suboperation s WHERE s.rd_operation_id=operation.ID) AS i_NBSUBCATEGORY "
            "FROM operation"

            << "CREATE VIEW  v_operation AS "
            "SELECT *,"
            "(SELECT s.id FROM suboperation s WHERE s.rd_operation_id=v_operation_tmp1.id AND ABS(s.f_value)=(SELECT MAX(ABS(s2.f_value)) FROM suboperation s2 WHERE s2.rd_operation_id=v_operation_tmp1.id)) AS i_MOSTIMPSUBOP,"
            "((SELECT s.f_CURRENTAMOUNT FROM v_unit s WHERE s.id=v_operation_tmp1.rc_unit_id)*v_operation_tmp1.f_QUANTITY) AS f_CURRENTAMOUNT, "
            "(CASE WHEN v_operation_tmp1.i_group_id<>0 AND EXISTS (SELECT 1 FROM account a WHERE v_operation_tmp1.rd_account_id=a.id AND a.t_type<>'L') AND "
            "EXISTS (SELECT 1 FROM v_operation_tmp1 op2, account a WHERE op2.i_group_id=v_operation_tmp1.i_group_id "
            "AND op2.rd_account_id=a.id AND a.t_type<>'L' AND op2.rc_unit_id=v_operation_tmp1.rc_unit_id AND "
            "op2.f_QUANTITY=-v_operation_tmp1.f_QUANTITY) THEN 'Y' ELSE 'N' END) AS t_TRANSFER "
//        "ROUND((SELECT s.f_CURRENTAMOUNT FROM v_unit s WHERE s.id=v_operation_tmp1.rc_unit_id)*v_operation_tmp1.f_QUANTITY, 2) AS f_CURRENTAMOUNT "
            "FROM v_operation_tmp1"

            << "CREATE VIEW  v_operation_displayname AS "
            "SELECT *, STRFTIME('" % dateFormatShort % "',d_date)||' '||IFNULL(t_PAYEE,'')||' '||"
            % (negativePrefixCurrencySymbol ? "(SELECT (CASE WHEN s.t_symbol!='' THEN s.t_symbol ELSE s.t_name END) FROM unit s WHERE s.id=v_operation.rc_unit_id)||' '||" : "") %
            "v_operation.f_CURRENTAMOUNT"
            % (!negativePrefixCurrencySymbol ? "||' '||(SELECT (CASE WHEN s.t_symbol!='' THEN s.t_symbol ELSE s.t_name END) FROM unit s WHERE s.id=v_operation.rc_unit_id)" : "") %
            " AS t_displayname FROM v_operation"

            << "CREATE VIEW  v_operation_delete AS "
            "SELECT *, (CASE WHEN t_status='Y' THEN '" %
            SKGServices::stringToSqlString(i18nc("Error message",  "You are not authorized to delete this operation because in \"checked\" status")) %
            "' END) t_delete_message FROM operation"

            //account
            << "CREATE VIEW  v_account AS "
            "SELECT "
            "*,"
            "(SELECT MAX(s.d_date) FROM  interest s WHERE s.rd_account_id=account.id) AS d_MAXDATE, "
            "(SELECT TOTAL(s.f_CURRENTAMOUNT) FROM v_operation s WHERE s.rd_account_id=account.id AND s.t_template='N') AS f_CURRENTAMOUNT "
            "FROM account"

            << "CREATE VIEW  v_account_delete AS "
            "SELECT *, (CASE WHEN EXISTS(SELECT 1 FROM operation WHERE rd_account_id=account.id AND d_date<>'0000-00-00' AND t_template='N' AND t_status='Y') THEN '" %
            SKGServices::stringToSqlString(i18nc("Error message",  "You are not authorized to delete this account because it contains some checked operations")) %
            "' END) t_delete_message FROM account"

            //bank
            << "CREATE VIEW  v_bank_displayname AS "
            "SELECT *, t_name AS t_displayname FROM bank"

            << "CREATE VIEW  v_account_displayname AS "
            "SELECT *, (SELECT t_displayname FROM v_bank_displayname WHERE account.rd_bank_id=v_bank_displayname.id)||'-'||t_name AS t_displayname FROM account"

            << "CREATE VIEW  v_bank AS "
            "SELECT *,"
            "(SELECT TOTAL(s.f_CURRENTAMOUNT) FROM v_account s WHERE s.rd_bank_id=bank.id) AS f_CURRENTAMOUNT "
            "FROM bank"

            //category
            << "CREATE VIEW  v_category_displayname AS "
            "SELECT *, t_fullname AS t_displayname FROM category"

            << "CREATE VIEW  v_category AS SELECT * "
            "FROM category"

            //recurrentoperation
            << "CREATE VIEW  v_recurrentoperation AS "
            "SELECT *,"
            "i_period_increment||' '||(CASE t_period_unit "
            "WHEN 'Y' THEN '" % SKGServices::stringToSqlString(i18nc("Noun",  "year(s)")) % "' "
            "WHEN 'M' THEN '" % SKGServices::stringToSqlString(i18nc("Noun",  "month(s)")) % "' "
            "WHEN 'W' THEN '" % SKGServices::stringToSqlString(i18nc("Noun",  "week(s)")) % "' "
            "ELSE '" % SKGServices::stringToSqlString(i18nc("Noun",  "day(s)")) % "' END) AS t_PERIODNLS "
            "FROM recurrentoperation"

            << "CREATE VIEW  v_recurrentoperation_displayname AS "
            "SELECT *, STRFTIME('" % dateFormatShort % "',d_date)||' '||SUBSTR((SELECT t_displayname FROM v_operation_displayname WHERE v_operation_displayname.id=v_recurrentoperation.rd_operation_id), 11) AS t_displayname FROM v_recurrentoperation"

            // ==================================================================
            //These following views contains all attributes needed for display
            //unitvalue
            << "CREATE VIEW  v_unitvalue_display AS "
            "SELECT *,"
            "IFNULL((SELECT (CASE WHEN s.t_symbol!='' THEN s.t_symbol ELSE s.t_name END) FROM unit s WHERE s.id=(SELECT s2.rd_unit_id FROM unit s2 WHERE s2.id=unitvalue.rd_unit_id)),'') AS t_UNIT,"
            "STRFTIME('%Y-%m',unitvalue.d_date) AS d_DATEMONTH,"
            "STRFTIME('%Y',unitvalue.d_date) AS d_DATEYEAR "
            "FROM unitvalue"

            //suboperation
            << "CREATE VIEW  v_suboperation_display AS "
            "SELECT *,"
            "IFNULL((SELECT s.t_fullname FROM category s WHERE s.id=v_suboperation.r_category_id),'') AS t_CATEGORY, "
            "IFNULL((SELECT s.t_name FROM refund s WHERE s.id=v_suboperation.r_refund_id),'') AS t_REFUND, "
            "(CASE WHEN v_suboperation.f_value>=0 THEN v_suboperation.f_value ELSE 0 END) AS f_VALUE_INCOME, "
            "(CASE WHEN v_suboperation.f_value<=0 THEN v_suboperation.f_value ELSE 0 END) AS f_VALUE_EXPENSE "
            "FROM v_suboperation"

            << "CREATE VIEW  v_suboperation_displayname AS "
            "SELECT *, t_CATEGORY||' : '||f_value AS t_displayname FROM v_suboperation_display"

            //operation
            << "CREATE VIEW  v_operation_display_all AS "
            "SELECT *,"
            "(SELECT s.t_name FROM account s WHERE s.id=v_operation.rd_account_id) AS t_ACCOUNT,"
            "(SELECT (CASE WHEN s.t_symbol!='' THEN s.t_symbol ELSE s.t_name END) FROM unit s WHERE s.id=v_operation.rc_unit_id) AS t_UNIT,"
            //"(SELECT s.t_comment FROM v_suboperation_display s WHERE s.id=v_operation.i_MOSTIMPSUBOP) AS t_COMMENT,"
            "(SELECT s.t_CATEGORY FROM v_suboperation_display s WHERE s.id=v_operation.i_MOSTIMPSUBOP) AS t_CATEGORY,"
            "(SELECT s.t_REFUND FROM v_suboperation_display s WHERE s.id=v_operation.i_MOSTIMPSUBOP) AS t_REFUND,"
            "(CASE WHEN v_operation.f_QUANTITY<0 THEN '-' WHEN v_operation.f_QUANTITY=0 THEN '' ELSE '+' END) AS t_TYPEEXPENSE, "
            "(CASE WHEN v_operation.f_QUANTITY<=0 THEN '" % SKGServices::stringToSqlString(i18nc("Noun, financial operations with a negative amount", "Expenditure")) % "' ELSE '" % SKGServices::stringToSqlString(i18nc("Noun, financial operations with a positive amount", "Income")) % "' END) AS t_TYPEEXPENSENLS, "
            "STRFTIME('%Y-W%W',v_operation.d_date) AS d_DATEWEEK,"
            "STRFTIME('%Y-%m',v_operation.d_date) AS d_DATEMONTH,"
            "STRFTIME('%Y',v_operation.d_date)||'-Q'||(CASE WHEN STRFTIME('%m',v_operation.d_date)<='03' THEN '1' WHEN STRFTIME('%m',v_operation.d_date)<='06' THEN '2' WHEN STRFTIME('%m',v_operation.d_date)<='09' THEN '3' ELSE '4' END) AS d_DATEQUARTER, "
            "STRFTIME('%Y',v_operation.d_date)||'-S'||(CASE WHEN STRFTIME('%m',v_operation.d_date)<='06' THEN '1' ELSE '2' END) AS d_DATESEMESTER, "
            "STRFTIME('%Y',v_operation.d_date) AS d_DATEYEAR, "
            "(SELECT count(1) FROM v_recurrentoperation s WHERE s.rd_operation_id=v_operation.id) AS i_NBRECURRENT,  "
            "(CASE WHEN v_operation.f_QUANTITY>=0 THEN v_operation.f_QUANTITY ELSE 0 END) AS f_QUANTITY_INCOME, "
            "(CASE WHEN v_operation.f_QUANTITY<=0 THEN v_operation.f_QUANTITY ELSE 0 END) AS f_QUANTITY_EXPENSE, "
            "(SELECT o2.f_balance FROM operationbalance o2 WHERE o2.r_operation_id=v_operation.id ) AS f_BALANCE, "
            "(CASE WHEN v_operation.f_QUANTITY>=0 THEN v_operation.f_CURRENTAMOUNT ELSE 0 END) AS f_CURRENTAMOUNT_INCOME, "
            "(CASE WHEN v_operation.f_QUANTITY<=0 THEN v_operation.f_CURRENTAMOUNT ELSE 0 END) AS f_CURRENTAMOUNT_EXPENSE "
            "FROM v_operation"

            << "CREATE VIEW  v_operation_template_display AS "
            "SELECT * FROM v_operation_display_all WHERE t_template='Y'"

            << "CREATE VIEW  v_operation_display AS "
            "SELECT * FROM v_operation_display_all WHERE d_date!='0000-00-00' AND t_template='N'"

            //unit
            << "CREATE VIEW  v_unit_display AS "
            "SELECT *,"
            "(SELECT TOTAL(o.f_QUANTITY) FROM v_operation_display o WHERE o.rc_unit_id=v_unit.id) AS f_QUANTITYOWNED "
            "FROM v_unit"

            //account
            << "CREATE VIEW  v_account_display AS "
            "SELECT "
            "(CASE t_type "
            "WHEN 'C' THEN '" % SKGServices::stringToSqlString(i18nc("Adjective, a current account", "Current")) % "' "
            "WHEN 'D' THEN '" % SKGServices::stringToSqlString(i18nc("Noun",  "Credit card")) % "' "
            "WHEN 'A' THEN '" % SKGServices::stringToSqlString(i18nc("Noun, the type of an account", "Assets")) % "' "
            "WHEN 'I' THEN '" % SKGServices::stringToSqlString(i18nc("Noun, a type of account WHERE you invest money", "Investment")) % "' "
            "WHEN 'W' THEN '" % SKGServices::stringToSqlString(i18nc("Noun, a type of account", "Wallet")) % "' "
            "WHEN 'L' THEN '" % SKGServices::stringToSqlString(i18nc("Noun, a type of account", "Loan")) % "' "
            "WHEN 'O' THEN '" % SKGServices::stringToSqlString(i18nc("Noun, as in other type of item", "Other")) % "' END) AS t_TYPENLS,"
            "bank.t_name  AS t_BANK,"
            "bank.t_bank_number AS t_BANK_NUMBER,"
            "bank.t_icon AS t_ICON,"
            "v_account.*,"
            "(v_account.f_CURRENTAMOUNT/(SELECT u.f_CURRENTAMOUNT FROM v_unit u, operation s WHERE u.id=s.rc_unit_id AND s.rd_account_id=v_account.id AND s.d_date='0000-00-00')) AS f_QUANTITY, "
            "(SELECT (CASE WHEN u.t_symbol!='' THEN u.t_symbol ELSE u.t_name END) FROM unit u, operation s WHERE u.id=s.rc_unit_id AND s.rd_account_id=v_account.id AND s.d_date='0000-00-00') AS t_UNIT, "
            "(SELECT TOTAL(s.f_CURRENTAMOUNT) FROM v_operation s WHERE s.rd_account_id=v_account.id AND s.t_status!='N' AND s.t_template='N') AS f_CHECKED, "
            "(SELECT TOTAL(s.f_CURRENTAMOUNT) FROM v_operation s WHERE s.rd_account_id=v_account.id AND s.t_status='N' AND s.t_template='N') AS f_COMING_SOON, "
            "(SELECT TOTAL(s.f_CURRENTAMOUNT) FROM v_operation s WHERE s.rd_account_id=v_account.id AND s.d_date<=date('now') AND s.t_template='N') AS f_TODAYAMOUNT, "
            "(SELECT count(1) FROM v_operation_display s WHERE s.rd_account_id=v_account.id) AS i_NBOPERATIONS, "
            "IFNULL((SELECT s.f_rate FROM interest s WHERE s.rd_account_id=v_account.id AND s.d_date=v_account.d_MAXDATE),0) AS f_RATE "
            "FROM v_account, bank WHERE bank.id=v_account.rd_bank_id"

            //operations
            << "CREATE VIEW  v_operation_consolidated AS "
            "SELECT "
            "(SELECT s.t_TYPENLS FROM v_account_display s WHERE s.id=op.rd_account_id) AS t_ACCOUNTTYPE,"
            "(SELECT u.t_TYPENLS FROM v_unit u WHERE u.id=op.rc_unit_id) AS t_UNITTYPE,"
            "sop.id AS i_SUBOPID, "
            "sop.r_refund_id AS r_refund_id, "
            "(CASE WHEN sop.t_comment='' THEN op.t_comment ELSE sop.t_comment END) AS t_REALCOMMENT, "
            "sop.t_CATEGORY AS t_REALCATEGORY, "
            "sop.t_REFUND AS t_REALREFUND, "
            "sop.r_category_id AS i_IDCATEGORY, "
            "(CASE WHEN sop.f_value<0 THEN '-' WHEN sop.f_value=0 THEN '' ELSE '+' END) AS t_TYPEEXPENSE, "
            "(CASE WHEN sop.f_value<0 THEN '" % SKGServices::stringToSqlString(i18nc("Noun, financial operations with a negative amount", "Expenditure")) % "' WHEN sop.f_value=0 THEN '' ELSE '" % SKGServices::stringToSqlString(i18nc("Noun, financial operations with a positive amount", "Income")) % "' END) AS t_TYPEEXPENSENLS, "
            "sop.f_value AS f_REALQUANTITY, "
            "sop.f_VALUE_INCOME AS f_REALQUANTITY_INCOME, "
            "sop.f_VALUE_EXPENSE AS f_REALQUANTITY_EXPENSE, "
            "((SELECT u.f_CURRENTAMOUNT FROM v_unit u WHERE u.id=op.rc_unit_id)*sop.f_value) AS f_REALCURRENTAMOUNT, "
            "((SELECT u.f_CURRENTAMOUNT FROM v_unit u WHERE u.id=op.rc_unit_id)*sop.f_VALUE_INCOME) AS f_REALCURRENTAMOUNT_INCOME, "
            "((SELECT u.f_CURRENTAMOUNT FROM v_unit u WHERE u.id=op.rc_unit_id)*sop.f_VALUE_EXPENSE) AS f_REALCURRENTAMOUNT_EXPENSE, "
            "op.* "
            "FROM v_operation_display_all AS op, v_suboperation_display AS sop WHERE op.t_template='N' AND sop.rd_operation_id=op.ID"

            << "CREATE VIEW  v_operation_prop AS "
            "SELECT "
            "p.id AS i_PROPPID, "
            "p.t_name AS i_PROPPNAME, "
            "p.t_value AS i_PROPVALUE, "
            "op.* "
            "FROM v_operation_consolidated AS op LEFT OUTER JOIN parameters AS p ON p.t_uuid_parent=op.id||'-operation'"

            //refund
            << "CREATE VIEW  v_refund_delete AS "
            "SELECT *, (CASE WHEN EXISTS(SELECT 1 FROM v_operation_consolidated WHERE r_refund_id=refund.id AND t_status='Y') THEN '" %
            SKGServices::stringToSqlString(i18nc("Error message",  "You are not authorized to delete this tracker because used by some checked operations")) %
            "' END) t_delete_message FROM refund"

            << "CREATE VIEW  v_refund AS "
            "SELECT *, "
            "(SELECT TOTAL(o.f_REALCURRENTAMOUNT) FROM v_operation_consolidated o WHERE o.r_refund_id=refund.id) AS f_CURRENTAMOUNT "
            "FROM refund"

            << "CREATE VIEW  v_refund_display AS "
            "SELECT *,"
            "(SELECT MIN(o.d_date) FROM v_operation_consolidated o WHERE o.r_refund_id=v_refund.id) AS d_FIRSTDATE, "
            "(SELECT MAX(o.d_date) FROM v_operation_consolidated o WHERE o.r_refund_id=v_refund.id) AS d_LASTDATE "
            " FROM v_refund"

            << "CREATE VIEW  v_refund_displayname AS "
            "SELECT *, t_name AS t_displayname FROM refund"

            //Payee
            << "CREATE VIEW  v_payee_delete AS "
            "SELECT *, (CASE WHEN EXISTS(SELECT 1 FROM operation WHERE r_payee_id=payee.id AND t_status='Y') THEN '" %
            SKGServices::stringToSqlString(i18nc("Error message",  "You are not authorized to delete this payee because used by some checked operations")) %
            "' END) t_delete_message FROM payee"

            << "CREATE VIEW  v_payee AS "
            "SELECT *, "
            "(SELECT TOTAL(o.f_CURRENTAMOUNT) FROM v_operation o WHERE o.r_payee_id=payee.id AND o.t_template='N') AS f_CURRENTAMOUNT "
            "FROM payee"

            << "CREATE VIEW  v_payee_display AS "
            "SELECT * "
            " FROM v_payee"

            << "CREATE VIEW  v_payee_displayname AS "
            "SELECT *, t_name AS t_displayname FROM payee"

            //category
            << "CREATE VIEW  v_category_delete AS "
            "SELECT *, (CASE WHEN EXISTS(SELECT 1 FROM v_operation_consolidated WHERE (t_REALCATEGORY=category.t_fullname OR t_REALCATEGORY like category.t_fullname||'%') AND t_status='Y') THEN '" %
            SKGServices::stringToSqlString(i18nc("Error message",  "You are not authorized to delete this category because used by some checked operations")) %
            "' END) t_delete_message FROM category"

            << "CREATE VIEW  v_category_display_tmp AS SELECT *,"
            "(SELECT count(distinct(so.rd_operation_id)) FROM operation o, suboperation so WHERE so.rd_operation_id=o.id AND so.r_category_id=v_category.ID AND o.t_template='N') AS i_NBOPERATIONS, "
            "(SELECT TOTAL(o.f_REALCURRENTAMOUNT) FROM v_operation_consolidated o WHERE o.i_IDCATEGORY=v_category.ID) AS f_REALCURRENTAMOUNT "
            "FROM v_category"

            << "CREATE VIEW  v_category_display AS SELECT *,"
            "f_REALCURRENTAMOUNT+(SELECT TOTAL(c.f_REALCURRENTAMOUNT) FROM vm_category_display_tmp c WHERE c.t_fullname LIKE vm_category_display_tmp.t_fullname||'" % OBJECTSEPARATOR % "%') AS f_SUMCURRENTAMOUNT, "
            "i_NBOPERATIONS+(SELECT CAST(TOTAL(c.i_NBOPERATIONS) AS INTEGER) FROM vm_category_display_tmp c WHERE c.t_fullname like vm_category_display_tmp.t_fullname||'" % OBJECTSEPARATOR % "%') AS i_SUMNBOPERATIONS, "
            "(CASE WHEN t_bookmarked='Y' THEN 'Y' WHEN EXISTS(SELECT 1 FROM category c WHERE c.t_bookmarked='Y' AND c.t_fullname like vm_category_display_tmp.t_fullname||'" % OBJECTSEPARATOR % "%') THEN 'C' ELSE 'N' END) AS t_HASBOOKMARKEDCHILD, "
            "(CASE WHEN vm_category_display_tmp.f_REALCURRENTAMOUNT<0 THEN '-' WHEN vm_category_display_tmp.f_REALCURRENTAMOUNT=0 THEN '' ELSE '+' END) AS t_TYPEEXPENSE,"
            "(CASE WHEN vm_category_display_tmp.f_REALCURRENTAMOUNT<0 THEN '" % SKGServices::stringToSqlString(i18nc("Noun, financial operations with a negative amount", "Expenditure")) % "' WHEN vm_category_display_tmp.f_REALCURRENTAMOUNT=0 THEN '' ELSE '" % SKGServices::stringToSqlString(i18nc("Noun, financial operations with a positive amount", "Income")) % "' END) AS t_TYPEEXPENSENLS "
            "FROM vm_category_display_tmp"

            //recurrentoperation
            << "CREATE VIEW  v_recurrentoperation_display AS "
            "SELECT rop.*, op.t_ACCOUNT, op.i_number, op.t_mode, op.i_group_id, op.t_TRANSFER, op.t_PAYEE, op.t_comment, op.t_CATEGORY, op.t_status, op.f_CURRENTAMOUNT "
            "FROM v_recurrentoperation rop, v_operation_display_all AS op WHERE rop.rd_operation_id=op.ID"

            //rule
            << "CREATE VIEW v_rule AS SELECT *,"
            "(SELECT COUNT(1) FROM rule r WHERE r.f_sortorder<=rule.f_sortorder) AS i_ORDER "
            "FROM rule"
            << "CREATE VIEW v_rule_displayname AS SELECT *, t_definition AS t_displayname FROM rule"

            //interest
            << "CREATE VIEW v_interest AS SELECT *,"
            "(SELECT s.t_name FROM account s WHERE s.id=interest.rd_account_id) AS t_ACCOUNT "
            " FROM interest"
            << "CREATE VIEW v_interest_displayname AS SELECT *, STRFTIME('" % dateFormatShort % "',d_date)||' '||f_rate||'%' AS t_displayname FROM interest"

            //budgetrule
            << "CREATE VIEW  v_budgetrule AS "
            "SELECT *, "
            "IFNULL((SELECT s.t_fullname FROM category s WHERE s.id=budgetrule.rc_category_id),'') AS t_CATEGORYCONDITION, "
            "IFNULL((SELECT s.t_fullname FROM category s WHERE s.id=budgetrule.rc_category_id_target),'') AS t_CATEGORY, "
            "(CASE "
            "WHEN budgetrule.i_condition=-1 THEN '" % SKGServices::stringToSqlString(i18nc("Noun", "Negative")) % "' "
            "WHEN budgetrule.i_condition=1 THEN '" % SKGServices::stringToSqlString(i18nc("Noun", "Positive")) % "' "
            "WHEN budgetrule.i_condition=0 THEN '" % SKGServices::stringToSqlString(i18nc("Noun", "All")) % "' "
            "END) AS t_WHENNLS, "
            "f_quantity||(CASE WHEN budgetrule.t_absolute='N' THEN '%' ELSE (SELECT t_symbol FROM unit WHERE t_type='1') END) AS t_WHATNLS,"
            "(CASE "
            "WHEN budgetrule.t_rule='N' THEN '" % SKGServices::stringToSqlString(i18nc("Noun", "Next")) % "' "
            "WHEN budgetrule.t_rule='C' THEN '" % SKGServices::stringToSqlString(i18nc("Noun", "Current")) % "' "
            "WHEN budgetrule.t_rule='Y' THEN '" % SKGServices::stringToSqlString(i18nc("Noun", "Year")) % "' "
            "END) AS t_RULENLS "
            "FROM budgetrule"

            << "CREATE VIEW  v_budgetrule_display AS "
            "SELECT * "
            " FROM v_budgetrule"

            << "CREATE VIEW  v_budgetrule_displayname AS "
            "SELECT *, t_WHENNLS||' '||t_WHATNLS||' '||t_RULENLS||' '||t_CATEGORY AS t_displayname FROM v_budgetrule"

            //budget
            << "CREATE VIEW  v_budget_tmp AS "
            "SELECT *, "
            "IFNULL((SELECT s.t_fullname FROM category s WHERE s.id=budget.rc_category_id),'') AS t_CATEGORY, "
            "(i_year||(CASE WHEN i_month=0 THEN '' WHEN i_month<10 THEN '-0'||i_month ELSE '-'||i_month END)) AS t_PERIOD, "
            "(SELECT TOTAL(o.f_REALCURRENTAMOUNT) FROM v_operation_consolidated o WHERE "
            "STRFTIME('%Y', o.d_date)=i_year AND (i_month=0 OR STRFTIME('%m', o.d_date)=i_month) AND "
            "o.i_IDCATEGORY IN (SELECT b2.id_category FROM budgetcategory b2 WHERE b2.id=budget.id)"
            ") AS f_CURRENTAMOUNT, "
            "(SELECT GROUP_CONCAT(v_budgetrule_displayname.t_displayname,',') FROM v_budgetrule_displayname WHERE "
            "(v_budgetrule_displayname.t_year_condition='N' OR budget.i_year=v_budgetrule_displayname.i_year) AND "
            "(v_budgetrule_displayname.t_month_condition='N' OR budget.i_month=v_budgetrule_displayname.i_month) AND "
            "(v_budgetrule_displayname.t_category_condition='N' OR budget.rc_category_id=v_budgetrule_displayname.rc_category_id) "
            "ORDER BY v_budgetrule_displayname.t_absolute DESC, v_budgetrule_displayname.id) AS t_RULES "
            "FROM budget"

            << "CREATE VIEW  v_budget AS "
            "SELECT *, "
            "(f_CURRENTAMOUNT-f_budgeted_modified) AS f_DELTABEFORETRANSFER, "
            "(f_CURRENTAMOUNT-f_budgeted_modified-f_transferred) AS f_DELTA "
            "FROM v_budget_tmp"

            << "CREATE VIEW  v_budget_display AS "
            "SELECT *, "
            "(f_CURRENTAMOUNT-f_budgeted_modified) AS f_DELTABEFORETRANSFER, "
            "(f_CURRENTAMOUNT-f_budgeted_modified-f_transferred) AS f_DELTA "
            "FROM vm_budget_tmp"

            << "CREATE VIEW  v_budget_displayname AS "
            "SELECT *, t_CATEGORY||' '||t_PERIOD||' '||f_budgeted_modified AS t_displayname FROM v_budget"
            ;

    if (!err) err = SKGDocument::refreshViewsIndexesAndTriggers();
    if (!err) {
        //Drop all views
        SKGStringListList list;
        err = executeSelectSqliteOrder("SELECT tbl_name, name, type FROM sqlite_master WHERE type IN ('view','index')", list);
        int nb = list.count();
        for (int i = 0; !err && i < nb; ++i) {
            QString name = list.at(i).at(1);
            QString table = SKGServices::getRealTable(list.at(i).at(0));
            QString type = list.at(i).at(2);
            if (table == "account" ||
                    table == "unit" ||
                    table == "unitvalue" ||
                    table == "bank" ||
                    table == "recurrentoperation" ||
                    table == "refund" ||
                    table == "payee" ||
                    table == "operation" ||
                    table == "operationbalance" ||
                    table == "interest" ||
                    table == "rule" ||
                    table == "suboperation" ||
                    table == "budget" ||
                    table == "budgetrule" ||
                    table == "budgetcategory" ||
                    table == "category") {
                QString sql = "DROP " % type % " IF EXISTS " % name;
                err = this->executeSqliteOrder(sql);
            }
        }
    }
    if (!err) err = this->executeSqliteOrders(BankInitialDataModelIndex);
    if (!err) err = this->executeSqliteOrders(BankInitialDataModelView);
    if (!err) err = this->executeSqliteOrders(BankInitialDataModelTrigger);
    if (!err) err = executeSqliteOrder("ANALYZE");

    return err;
}

SKGError SKGDocumentBank::migrate(bool& oMigrationDone)
{
    SKGError err;
    SKGTRACEINRC(5, "SKGDocumentBank::migrate", err);
    oMigrationDone = false;
    QStringList migrationSteps;
    {
        migrationSteps
        //============
                << ""
                << "0.1"
                << "0.2"
                << "ALTER TABLE unit ADD COLUMN rc_unit_id INTEGER NOT NULL DEFAULT 0"
                //============
                << ""
                << "0.2"
                << "0.3"
                << "DROP TABLE IF EXISTS unitvalue2"
                << "CREATE TABLE unitvalue2("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "rd_unit_id INTEGER NOT NULL,"
                "d_date DATE NOT NULL,"
                "f_quantity FLOAT NOT NULL CHECK (f_quantity>=0))"

                << "INSERT INTO unitvalue2 (id,rd_unit_id,d_date,f_quantity) SELECT id,rd_unit_id,d_date,f_value FROM unitvalue"

                << "DROP TABLE IF EXISTS unitvalue"
                << "ALTER TABLE unitvalue2 RENAME TO unitvalue"
                //============
                << ""
                << "0.3"
                << "0.4"
                << "ALTER TABLE operation ADD COLUMN t_import_id TEXT DEFAULT ''"
                //============
                << ""
                << "0.4"
                << "0.5"
                << "DROP TABLE IF EXISTS recurrentoperation"
                << "CREATE TABLE recurrentoperation ("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "d_date DATE NOT NULL DEFAULT '0000-00-00',"
                "rd_operation_id INTEGER NOT NULL,"
                "i_period_increment INTEGER NOT NULL DEFAULT 1 CHECK (i_period_increment>=0),"
                "t_period_unit TEXT NOT NULL DEFAULT 'M' CHECK (t_period_unit IN ('D', 'M', 'Y')),"
                "t_auto_write VARCHAR(1) DEFAULT 'Y' CHECK (t_auto_write IN ('Y', 'N')),"
                "i_auto_write_days INTEGER NOT NULL DEFAULT 5 CHECK (i_auto_write_days>=0),"
                "t_warn VARCHAR(1) DEFAULT 'Y' CHECK (t_auto_write IN ('Y', 'N')),"
                "i_warn_days INTEGER NOT NULL DEFAULT 5 CHECK (i_warn_days>=0)"
                ")"
                << "ALTER TABLE operation ADD COLUMN r_recurrentoperation_id INTEGER NOT NULL DEFAULT 0"
                //============
                << ""
                << "0.5"
                << "0.6"
                << "ALTER TABLE account ADD COLUMN t_comment TEXT NOT NULL DEFAULT ''"
                //============
                << ""
                << "0.6"
                << "0.7"
                << "DROP TABLE IF EXISTS unit2"
                << "CREATE TABLE unit2("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "t_name TEXT NOT NULL,"
                "t_symbol TEXT NOT NULL DEFAULT '',"
                "t_country TEXT NOT NULL DEFAULT '',"
                "t_type VARCHAR(1) NOT NULL DEFAULT 'C' CHECK (t_type IN ('1', '2', 'C', 'S', 'O')),"
                //1=main currency, 2=secondary currency, C=currencies S=share O=object
                "t_internet_code TEXT NOT NULL DEFAULT '',"
                "rd_unit_id INTEGER NOT NULL DEFAULT 0)"

                << "INSERT INTO unit2 (id,t_name,t_symbol,t_country,t_type,t_internet_code,rd_unit_id) SELECT id,t_name,t_symbol,t_country,t_type,t_internet_code,rc_unit_id FROM unit"

                << "DROP TABLE IF EXISTS unit"
                << "ALTER TABLE unit2 RENAME TO unit"
                //============
                << ""
                << "0.7"
                << "0.8"
                << "DELETE FROM operation WHERE id IN (SELECT id FROM operation op WHERE NOT EXISTS(SELECT 1 FROM suboperation sop WHERE sop.rd_operation_id=op.id))"
                //============
                << ""
                << "0.8"
                << "0.9"
                << "UPDATE operation SET i_group_id=0 WHERE i_group_id=''"
                //============
                << ""
                << "0.9"
                << "1.0"
                << "DROP TABLE IF EXISTS unit2"
                << "CREATE TABLE unit2("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "t_name TEXT NOT NULL,"
                "t_symbol TEXT NOT NULL DEFAULT '',"
                "t_country TEXT NOT NULL DEFAULT '',"
                "t_type VARCHAR(1) NOT NULL DEFAULT 'C' CHECK (t_type IN ('1', '2', 'C', 'S', 'I', 'O')),"
                //1=main currency, 2=secondary currency, C=currencies S=share, I=index, O=object
                "t_internet_code TEXT NOT NULL DEFAULT '',"
                "rd_unit_id INTEGER NOT NULL DEFAULT 0)"

                << "INSERT INTO unit2 (id,t_name,t_symbol,t_country,t_type,t_internet_code,rd_unit_id) SELECT id,t_name,t_symbol,t_country,t_type,t_internet_code,rd_unit_id FROM unit"

                << "DROP TABLE IF EXISTS unit"
                << "ALTER TABLE unit2 RENAME TO unit"
                //============
                << ""
                << "1.0"
                << "1.1"
                << "DELETE FROM parameters WHERE t_name LIKE 'SKG_MONTHLY_REPORT_%'"
                //============
                << ""
                << "1.1"
                << "1.2"
                << "ALTER TABLE suboperation ADD COLUMN t_comment TEXT NOT NULL DEFAULT ''"
                //============
                << ""
                << "1.2"
                << "1.3"
                << "UPDATE node SET f_sortorder=id WHERE f_sortorder IS NULL OR f_sortorder=''"
                //============
                << ""
                << "1.3"
                << "1.4"
                << "DROP TABLE IF EXISTS refund"
                << "CREATE TABLE refund ("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "t_name TEXT NOT NULL DEFAULT '',"
                "t_comment TEXT NOT NULL DEFAULT '',"
                "t_close VARCHAR(1) DEFAULT 'N' CHECK (t_close IN ('Y', 'N')))"

                << "ALTER TABLE suboperation ADD COLUMN r_refund_id INTEGER NOT NULL DEFAULT 0"
                //============
                << ""
                << "1.4"
                << "1.5"
                << "DELETE FROM parameters WHERE (t_name LIKE 'SKG_DEFAULT_%' AND t_name!='SKG_DEFAULT_PROPERTIES') OR t_name='DBVERSION'"
                //============
                << ""
                << "1.5"
                << "1.6"
                << "CREATE TABLE rule ("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "t_description TEXT NOT NULL DEFAULT '',"
                "t_definition TEXT NOT NULL DEFAULT '',"
                "f_sortorder FLOAT"
                ")"
                //============
                << ""
                << "1.6"
                << "1.7"
                << "CREATE TABLE action ("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "rd_rule_id INTEGER NOT NULL,"
                "t_description TEXT NOT NULL DEFAULT '',"
                "t_definition TEXT NOT NULL DEFAULT ''"
                ")"
                << "DELETE FROM rule"
                << "DROP TABLE IF EXISTS budget"
                //============
                << ""
                << "1.7"
                << "1.8"
                << "DROP TABLE IF EXISTS action"
                << "ALTER TABLE rule ADD COLUMN t_action_description TEXT NOT NULL DEFAULT ''"
                << "ALTER TABLE rule ADD COLUMN t_action_definition TEXT NOT NULL DEFAULT ''"
                << "DROP TRIGGER IF EXISTS fkdc_rule_action_id_rd_rule_id"
                //============
                << ""
                << "1.8"
                << "1.9"
                << "DROP TABLE IF EXISTS operation2"
                << "CREATE TABLE operation2("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "i_group_id INTEGER NOT NULL DEFAULT 0,"
                "i_number INTEGER DEFAULT 0 CHECK (i_number>=0),"
                "d_date DATE NOT NULL DEFAULT '0000-00-00',"
                "rd_account_id INTEGER NOT NULL,"
                "t_mode TEXT NOT NULL DEFAULT '',"
                "t_payee TEXT NOT NULL DEFAULT '',"
                "t_comment TEXT NOT NULL DEFAULT '',"
                "rc_unit_id INTEGER NOT NULL,"
                "t_status VARCHAR(1) DEFAULT 'N' CHECK (t_status IN ('N', 'P', 'Y')),"
                "t_bookmarked VARCHAR(1) DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N')),"
                "t_imported VARCHAR(1) DEFAULT 'N' CHECK (t_imported IN ('Y', 'N', 'P')),"
                "t_import_id TEXT DEFAULT '',"
                "r_recurrentoperation_id INTEGER NOT NULL DEFAULT 0)"

                << "INSERT INTO operation2 (id,i_group_id,i_number,d_date,rd_account_id,t_mode,t_payee,t_comment,rc_unit_id,"
                "t_status,t_bookmarked,t_imported,t_import_id,r_recurrentoperation_id) "
                "SELECT id,i_group_id,i_number,d_date,rd_account_id,t_mode,t_payee,t_comment,rc_unit_id,"
                "(CASE WHEN t_status='C' THEN 'Y' ELSE t_status END),t_bookmarked,t_imported,t_import_id,r_recurrentoperation_id FROM operation"

                << "DROP TABLE IF EXISTS operation"
                << "ALTER TABLE operation2 RENAME TO operation"
                //============
                << ""
                << "1.9"
                << "2.0"
                << "ALTER TABLE operation ADD COLUMN i_tmp INTEGER NOT NULL DEFAULT 0"
                << "ALTER TABLE suboperation ADD COLUMN i_tmp INTEGER NOT NULL DEFAULT 0"
                //============
                << ""
                << "2.0"
                << "2.1"
                << "ALTER TABLE operation ADD COLUMN t_template VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_template IN ('Y', 'N'))"
                //============
                << ""
                << "2.1"
                << "2.2"
                << "UPDATE recurrentoperation SET d_date=date(d_date,i_period_increment||(CASE WHEN t_period_unit='Y' THEN ' year' ELSE (CASE WHEN t_period_unit='M' THEN ' month' ELSE ' day' END) END))"


                << "DROP TABLE IF EXISTS recurrentoperation2"
                << "CREATE TABLE recurrentoperation2 ("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "d_date DATE NOT NULL DEFAULT '0000-00-00',"
                "rd_operation_id INTEGER NOT NULL,"
                "i_period_increment INTEGER NOT NULL DEFAULT 1 CHECK (i_period_increment>=0),"
                "t_period_unit TEXT NOT NULL DEFAULT 'M' CHECK (t_period_unit IN ('D', 'M', 'Y')),"
                "t_auto_write VARCHAR(1) DEFAULT 'Y' CHECK (t_auto_write IN ('Y', 'N')),"
                "i_auto_write_days INTEGER NOT NULL DEFAULT 5 CHECK (i_auto_write_days>=0),"
                "t_warn VARCHAR(1) DEFAULT 'Y' CHECK (t_warn IN ('Y', 'N')),"
                "i_warn_days INTEGER NOT NULL DEFAULT 5 CHECK (i_warn_days>=0),"
                "t_times VARCHAR(1) DEFAULT 'N' CHECK (t_times IN ('Y', 'N')),"
                "i_nb_times INTEGER NOT NULL DEFAULT 1 CHECK (i_nb_times>=0)"
                ")"

                << "INSERT INTO recurrentoperation2 (id,d_date,rd_operation_id,i_period_increment,t_period_unit,t_auto_write,i_auto_write_days,t_warn,i_warn_days) "
                "SELECT id,d_date,rd_operation_id,i_period_increment,t_period_unit,t_auto_write,i_auto_write_days,t_warn,i_warn_days FROM recurrentoperation"

                << "DROP TABLE IF EXISTS recurrentoperation"
                << "ALTER TABLE recurrentoperation2 RENAME TO recurrentoperation"
                //============
                << ""
                << "2.2"
                << "2.3"
                << "UPDATE rule SET t_definition=replace(t_definition,'%9','#ATT#')"
                << "UPDATE rule SET t_definition=replace(t_definition,'''%1''','''#V1S#''')"
                << "UPDATE rule SET t_definition=replace(t_definition,'''%2''','''#V2S#''')"
                << "UPDATE rule SET t_definition=replace(t_definition,'''%%1%''','''%#V1S#%''')"
                << "UPDATE rule SET t_definition=replace(t_definition,'''%1%''','''#V1S#%''')"
                << "UPDATE rule SET t_definition=replace(t_definition,'''%%1''','''%#V1S#''')"
                << "UPDATE rule SET t_definition=replace(t_definition,'%1','#V1#')"
                << "UPDATE rule SET t_definition=replace(t_definition,'%2','#V2#')"

                << "UPDATE rule SET t_action_definition=replace(t_action_definition,'%9','#ATT#')"
                << "UPDATE rule SET t_action_definition=replace(t_action_definition,'''%1''','''#V1S#''')"
                << "UPDATE rule SET t_action_definition=replace(t_action_definition,'''%2''','''#V2S#''')"
                << "UPDATE rule SET t_action_definition=replace(t_action_definition,'''%%1%''','''%#V1S#%''')"
                << "UPDATE rule SET t_action_definition=replace(t_action_definition,'''%1%''','''#V1S#%''')"
                << "UPDATE rule SET t_action_definition=replace(t_action_definition,'''%%1''','''%#V1S#''')"
                << "UPDATE rule SET t_action_definition=replace(t_action_definition,'%1','#V1#')"
                << "UPDATE rule SET t_action_definition=replace(t_action_definition,'%2','#V2#')"
                //============
                << ""
                << "2.3"
                << "2.4"
                << "UPDATE operation SET t_template='N' WHERE t_template NOT IN ('Y', 'N')"
                //============
                << ""
                << "2.4"
                << "2.5"
                << "ALTER TABLE rule ADD COLUMN t_action_type VARCHAR(1) DEFAULT 'S' CHECK (t_action_type IN ('S', 'U', 'A'))"
                << "UPDATE rule SET t_action_type='S' WHERE t_action_type NOT IN ('S', 'U', 'A') AND  t_action_definition=''"
                << "UPDATE rule SET t_action_type='U' WHERE t_action_type NOT IN ('S', 'U', 'A') AND  t_action_definition!=''"
                //============
                << ""
                << "2.5"
                << "2.6"
                << "ALTER TABLE unit ADD COLUMN i_nbdecimal INT NOT NULL DEFAULT 2"
                << "UPDATE unit SET i_nbdecimal=2"
                //============
                << ""
                << "2.6"
                << "2.7"
                << "CREATE TABLE operation2("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "i_group_id INTEGER NOT NULL DEFAULT 0,"
                "i_number INTEGER DEFAULT 0 CHECK (i_number>=0),"
                "d_date DATE NOT NULL DEFAULT '0000-00-00',"
                "rd_account_id INTEGER NOT NULL,"
                "t_mode TEXT NOT NULL DEFAULT '',"
                "t_payee TEXT NOT NULL DEFAULT '',"
                "t_comment TEXT NOT NULL DEFAULT '',"
                "rc_unit_id INTEGER NOT NULL,"
                "t_status VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_status IN ('N', 'P', 'Y')),"
                "t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N')),"
                "t_imported VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_imported IN ('Y', 'N', 'P', 'T')),"
                "t_template VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_template IN ('Y', 'N')),"
                "t_import_id TEXT NOT NULL DEFAULT '',"
                "i_tmp INTEGER NOT NULL DEFAULT 0,"
                "r_recurrentoperation_id INTEGER NOT NULL DEFAULT 0)"

                << "INSERT INTO operation2 ("
                "id,i_group_id,i_number,d_date,rd_account_id,t_mode,t_payee,t_comment,rc_unit_id,t_status,t_bookmarked,t_imported,t_template,t_import_id,i_tmp,r_recurrentoperation_id) "
                "SELECT id,i_group_id,i_number,d_date,rd_account_id,t_mode,t_payee,t_comment,rc_unit_id,t_status,t_bookmarked,t_imported,t_template,t_import_id,i_tmp,r_recurrentoperation_id FROM operation"

                << "DROP TABLE IF EXISTS operation"
                << "ALTER TABLE operation2 RENAME TO operation"
                //============
                << ""
                << "2.7"
                << "2.8"
                << "UPDATE rule SET t_action_type='U' WHERE t_action_type='S' AND  t_action_definition!=''"
                //============
                << ""
                << "2.8"
                << "2.9"
                << "DROP TABLE IF EXISTS interest"
                << "CREATE TABLE interest("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "rd_account_id INTEGER NOT NULL,"
                "d_date DATE NOT NULL,"
                "f_rate FLOAT NOT NULL CHECK (f_rate>=0),"
                "t_income_value_date_mode VARCHAR(1) NOT NULL DEFAULT 'F' CHECK (t_income_value_date_mode IN ('F', '0', '1', '2', '3', '4', '5')),"
                "t_expenditure_value_date_mode VARCHAR(1) NOT NULL DEFAULT 'F' CHECK (t_expenditure_value_date_mode IN ('F', '0', '1', '2', '3', '4', '5')),"
                "t_base VARCHAR(3) NOT NULL DEFAULT '24' CHECK (t_base IN ('24', '360', '365'))"
                ")"
                //============
                << ""
                << "2.9"
                << "3.0"
                //Current month
                << "UPDATE node SET t_data=replace(t_data, 'period=\"\"1\"\"', 'period=\"\"1\"\" interval=\"\"2\"\" nb_intervals=\"\"1\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Previous month
                << "UPDATE node SET t_data=replace(t_data, 'period=\"\"2\"\"', 'period=\"\"2\"\" interval=\"\"2\"\" nb_intervals=\"\"1\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Current year
                << "UPDATE node SET t_data=replace(t_data, 'period=\"\"3\"\"', 'period=\"\"1\"\" interval=\"\"3\"\" nb_intervals=\"\"1\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Previous year
                << "UPDATE node SET t_data=replace(t_data, 'period=\"\"4\"\"', 'period=\"\"2\"\" interval=\"\"3\"\" nb_intervals=\"\"1\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Last 30 days
                << "UPDATE node SET t_data=replace(t_data, 'period=\"\"5\"\"', 'period=\"\"3\"\" interval=\"\"0\"\" nb_intervals=\"\"30\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Last 3 months
                << "UPDATE node SET t_data=replace(t_data, 'period=\"\"6\"\"', 'period=\"\"3\"\" interval=\"\"2\"\" nb_intervals=\"\"3\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Last 6 months
                << "UPDATE node SET t_data=replace(t_data, 'period=\"\"7\"\"', 'period=\"\"3\"\" interval=\"\"2\"\" nb_intervals=\"\"6\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Last 12 months
                << "UPDATE node SET t_data=replace(t_data, 'period=\"\"8\"\"', 'period=\"\"3\"\" interval=\"\"2\"\" nb_intervals=\"\"12\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Last 2 years
                << "UPDATE node SET t_data=replace(t_data, 'period=\"\"9\"\"', 'period=\"\"3\"\" interval=\"\"3\"\" nb_intervals=\"\"2\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Last 3 years
                << "UPDATE node SET t_data=replace(t_data, 'period=\"\"10\"\"', 'period=\"\"3\"\" interval=\"\"3\"\" nb_intervals=\"\"3\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Last 5 years
                << "UPDATE node SET t_data=replace(t_data, 'period=\"\"11\"\"', 'period=\"\"3\"\" interval=\"\"3\"\" nb_intervals=\"\"5\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Custom...
                << "UPDATE node SET t_data=replace(t_data, 'period=\"\"12\"\"', 'period=\"\"4\"\"') WHERE t_data like '%Skrooge report plugin%'"

                //All without transfers
                << "UPDATE node SET t_data=replace(t_data, 'type=\"\"0\"\"', 'incomes=\"\"Y\"\" expenses=\"\"Y\"\" transfers=\"\"N\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Income without transfers
                << "UPDATE node SET t_data=replace(t_data, 'type=\"\"1\"\"', 'incomes=\"\"Y\"\" expenses=\"\"N\"\" transfers=\"\"N\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Expenditure without transfers
                << "UPDATE node SET t_data=replace(t_data, 'type=\"\"2\"\"', 'incomes=\"\"N\"\" expenses=\"\"Y\"\" transfers=\"\"N\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //All with transfers
                << "UPDATE node SET t_data=replace(t_data, 'type=\"\"3\"\"', 'incomes=\"\"Y\"\" expenses=\"\"Y\"\" transfers=\"\"Y\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Income with transfers
                << "UPDATE node SET t_data=replace(t_data, 'type=\"\"4\"\"', 'incomes=\"\"Y\"\" expenses=\"\"N\"\" transfers=\"\"Y\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //Expenditure with transfers
                << "UPDATE node SET t_data=replace(t_data, 'type=\"\"5\"\"', 'incomes=\"\"N\"\" expenses=\"\"Y\"\" transfers=\"\"Y\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //============
                << ""
                << "3.0"
                << "3.1"
                << "UPDATE node SET t_data=replace(t_data, 'columns=\"\"2\"\"', 'columns=\"\"4\"\"') WHERE t_data like '%Skrooge report plugin%'"
                << "UPDATE node SET t_data=replace(t_data, 'columns=\"\"1\"\"', 'columns=\"\"3\"\"') WHERE t_data like '%Skrooge report plugin%'"
                //============
                << ""
                << "3.1"
                << "3.2"
                << "UPDATE parameters SET t_name='SKGSEARCH_DEFAULT_PARAMETERS' WHERE t_name='SKGIMPORT_DEFAULT_PARAMETERS'"
                //============
                << ""
                << "3.2"
                << "3.3"
                << "UPDATE node SET t_data=replace(t_data, ' columns=&quot;4&quot;', ' columns=&quot;&quot;') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' columns=&quot;3&quot;', ' columns=&quot;d_DATEYEAR&quot;') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' columns=&quot;2&quot;', ' columns=&quot;d_DATESEMESTER&quot;') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' columns=&quot;1&quot;', ' columns=&quot;d_DATEQUARTER&quot;') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' columns=&quot;0&quot;', ' columns=&quot;d_DATEMONTH&quot;') WHERE t_data like '%graphicViewState=%'"

                << "UPDATE node SET t_data=replace(t_data, ' columns=\"\"4\"\"', ' columns=\"\"\"\"') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' columns=\"\"3\"\"', ' columns=\"\"d_DATEYEAR\"\"') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' columns=\"\"2\"\"', ' columns=\"\"d_DATESEMESTER\"\"') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' columns=\"\"1\"\"', ' columns=\"\"d_DATEQUARTER\"\"') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' columns=\"\"0\"\"', ' columns=\"\"d_DATEMONTH\"\"') WHERE t_data like '%graphicViewState=%'"

                << "UPDATE parameters SET t_value=replace(t_value, ' columns=&quot;4&quot;', ' columns=&quot;&quot;') WHERE t_name='SKGDASHBOARD_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' columns=&quot;3&quot;', ' columns=&quot;d_DATEYEAR&quot;') WHERE t_name='SKGDASHBOARD_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' columns=&quot;2&quot;', ' columns=&quot;d_DATESEMESTER&quot;') WHERE t_name='SKGDASHBOARD_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' columns=&quot;1&quot;', ' columns=&quot;d_DATEQUARTER&quot;') WHERE t_name='SKGDASHBOARD_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' columns=&quot;0&quot;', ' columns=&quot;d_DATEMONTH&quot;') WHERE t_name='SKGDASHBOARD_DEFAULT_PARAMETERS'"


                << "UPDATE node SET t_data=replace(t_data, ' lines=&quot;0&quot;', ' lines=&quot;t_REALCATEGORY&quot;') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=&quot;1&quot;', ' lines=&quot;t_payee&quot;') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=&quot;2&quot;', ' lines=&quot;t_mode&quot;') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=&quot;3&quot;', ' lines=&quot;t_TYPEEXPENSENLS&quot;') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=&quot;4&quot;', ' lines=&quot;t_status&quot;') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=&quot;5&quot;', ' lines=&quot;t_ACCOUNTTYPE&quot;') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=&quot;6&quot;', ' lines=&quot;t_UNITTYPE&quot;') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=&quot;7&quot;', ' lines=&quot;t_REALREFUND&quot;') WHERE t_data like '%graphicViewState=%'"

                << "UPDATE node SET t_data=replace(t_data, ' lines=\"\"0\"\"', ' lines=\"\"t_REALCATEGORY\"\"') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=\"\"1\"\"', ' lines=\"\"t_payee\"\"') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=\"\"2\"\"', ' lines=\"\"t_mode\"\"') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=\"\"3\"\"', ' lines=\"\"t_TYPEEXPENSENLS\"\"') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=\"\"4\"\"', ' lines=\"\"t_status\"\"') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=\"\"5\"\"', ' lines=\"\"t_ACCOUNTTYPE\"\"') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=\"\"6\"\"', ' lines=\"\"t_UNITTYPE\"\"') WHERE t_data like '%graphicViewState=%'"
                << "UPDATE node SET t_data=replace(t_data, ' lines=\"\"7\"\"', ' lines=\"\"t_REALREFUND\"\"') WHERE t_data like '%graphicViewState=%'"

                << "UPDATE parameters SET t_value=replace(t_value, ' lines=&quot;0&quot;', ' lines=&quot;t_REALCATEGORY&quot;') WHERE t_name='SKGDASHBOARD_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=&quot;1&quot;', ' lines=&quot;t_payee&quot;') WHERE t_name='SKGDASHBOARD_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=&quot;2&quot;', ' lines=&quot;t_mode&quot;') WHERE t_name='SKGDASHBOARD_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=&quot;3&quot;', ' lines=&quot;t_TYPEEXPENSENLS&quot;') WHERE t_name='SKGDASHBOARD_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=&quot;4&quot;', ' lines=&quot;t_status&quot;') WHERE t_name='SKGDASHBOARD_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=&quot;5&quot;', ' lines=&quot;t_ACCOUNTTYPE&quot;') WHERE t_name='SKGDASHBOARD_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=&quot;6&quot;', ' lines=&quot;t_UNITTYPE&quot;') WHERE t_name='SKGDASHBOARD_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=&quot;7&quot;', ' lines=&quot;t_REALREFUND&quot;') WHERE t_name='SKGDASHBOARD_DEFAULT_PARAMETERS'"
                //============
                << ""
                << "3.3"
                << "3.4"
                << "UPDATE parameters SET t_value=replace(t_value, ' columns=\"4\"', ' columns=\"\"') WHERE t_name='SKGREPORT_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' columns=\"3\"', ' columns=\"d_DATEYEAR\"') WHERE t_name='SKGREPORT_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' columns=\"2\"', ' columns=\"d_DATESEMESTER\"') WHERE t_name='SKGREPORT_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' columns=\"1\"', ' columns=\"d_DATEQUARTER\"') WHERE t_name='SKGREPORT_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' columns=\"0\"', ' columns=\"d_DATEMONTH\"') WHERE t_name='SKGREPORT_DEFAULT_PARAMETERS'"


                << "UPDATE parameters SET t_value=replace(t_value, ' lines=\"0\"', ' lines=\"t_REALCATEGORY\"') WHERE t_name='SKGREPORT_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=\"1\"', ' lines=\"t_payee\"') WHERE t_name='SKGREPORT_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=\"2\"', ' lines=\"t_mode\"') WHERE t_name='SKGREPORT_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=\"3\"', ' lines=\"t_TYPEEXPENSENLS\"') WHERE t_name='SKGREPORT_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=\"4\"', ' lines=\"t_status\"') WHERE t_name='SKGREPORT_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=\"5\"', ' lines=\"t_ACCOUNTTYPE\"') WHERE t_name='SKGREPORT_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=\"6\"', ' lines=\"t_UNITTYPE\"') WHERE t_name='SKGREPORT_DEFAULT_PARAMETERS'"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=\"7\"', ' lines=\"t_REALREFUND\"') WHERE t_name='SKGREPORT_DEFAULT_PARAMETERS'"
                //============
                << ""
                << "3.4"
                << "3.5"
                << "ALTER TABLE account ADD COLUMN t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N'))"
                << "UPDATE account SET t_bookmarked='N'"
                //============
                << ""
                << "3.5"
                << "3.6"
                << "ALTER TABLE rule ADD COLUMN t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N'))"
                << "UPDATE rule SET t_bookmarked='N'"
                //============
                << ""
                << "3.6"
                << "3.7"
                << "UPDATE suboperation SET r_category_id=0 WHERE r_category_id=(SELECT id FROM category WHERE t_name='')"
                << "DELETE FROM category WHERE t_name=''"
                //============
                << ""
                << "3.7"
                << "3.8"
                << "UPDATE recurrentoperation SET t_times='N' WHERE t_times IS NULL"
                //============
                << ""
                << "3.8"
                << "3.9"
                << "UPDATE node SET t_data=replace(t_data, 'Skrooge dashboard plugin', 'Dashboard plugin') WHERE t_data like '%Skrooge dashboard plugin%'"
                //============
                << ""
                << "3.9"
                << "4.0"
                << "UPDATE rule SET t_definition=replace(t_definition, '" % SKGServices::stringToSqlString("date('now','-1") % "', '" % SKGServices::stringToSqlString("date('now','start of month','-1") % "')"
                //============
                << ""
                << "4.0"
                << "4.1"
                << "UPDATE rule SET t_definition=replace(t_definition,'t_REFUND','t_REALREFUND')"
                << "UPDATE rule SET t_action_definition=replace(t_action_definition,'t_REFUND','t_REALREFUND')"
                //============
                << ""
                << "4.1"
                << "4.2"
                << "UPDATE operation SET t_imported='Y' WHERE t_imported='T'"
                << "UPDATE operation SET t_imported='N' WHERE t_imported!='N' AND t_import_id='';"
                //============
                << ""
                << "4.2"
                << "4.3"
                <<  "CREATE TABLE payee ("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "t_name TEXT NOT NULL DEFAULT '',"
                "t_address TEXT NOT NULL DEFAULT '')"

                << "INSERT INTO payee (t_name) "
                "SELECT distinct(operation.t_payee) FROM operation WHERE operation.t_payee<>''"

                << "CREATE TABLE operation2("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "i_group_id INTEGER NOT NULL DEFAULT 0,"
                "i_number INTEGER DEFAULT 0 CHECK (i_number>=0),"
                "d_date DATE NOT NULL DEFAULT '0000-00-00',"
                "rd_account_id INTEGER NOT NULL,"
                "t_mode TEXT NOT NULL DEFAULT '',"
                "r_payee_id INTEGER NOT NULL DEFAULT 0,"
                "t_comment TEXT NOT NULL DEFAULT '',"
                "rc_unit_id INTEGER NOT NULL,"
                "t_status VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_status IN ('N', 'P', 'Y')),"
                "t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N')),"
                "t_imported VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_imported IN ('Y', 'N', 'P', 'T')),"
                "t_template VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_template IN ('Y', 'N')),"
                "t_import_id TEXT NOT NULL DEFAULT '',"
                "i_tmp INTEGER NOT NULL DEFAULT 0,"
                "r_recurrentoperation_id INTEGER NOT NULL DEFAULT 0)"

                << "INSERT INTO operation2 ("
                "id,i_group_id,i_number,d_date,rd_account_id,t_mode,r_payee_id,t_comment,rc_unit_id,t_status,t_bookmarked,t_imported,t_template,t_import_id,i_tmp,r_recurrentoperation_id) "
                "SELECT id,i_group_id,i_number,d_date,rd_account_id,t_mode,(CASE WHEN (SELECT payee.id FROM payee WHERE payee.t_name=operation.t_payee) IS NULL THEN 0 ELSE (SELECT payee.id FROM payee WHERE payee.t_name=operation.t_payee) END),t_comment,rc_unit_id,t_status,t_bookmarked,t_imported,t_template,t_import_id,i_tmp,r_recurrentoperation_id FROM operation"

                << "DROP TABLE IF EXISTS operation"
                << "ALTER TABLE operation2 RENAME TO operation"

                << "UPDATE parameters SET t_value=replace(t_value, 't_payee', 't_PAYEE') WHERE t_name like '%_DEFAULT_PARAMETERS'"
                //============
                << ""
                << "4.3"
                << "4.4"
                << "UPDATE rule SET t_definition=replace(t_definition, 't_payee', 't_PAYEE') WHERE t_definition like '%t_payee'"
                << "UPDATE node SET t_data=replace(t_data, 't_payee', 't_PAYEE') WHERE t_data like '%t_payee'"
                //============
                << ""
                << "4.4"
                << "4.5"
                << "UPDATE rule SET t_definition=replace(t_definition, 't_payee', 't_PAYEE') WHERE t_definition like '%t_payee%'"
                << "UPDATE rule SET t_action_definition=replace(t_action_definition, 't_payee', 't_PAYEE') WHERE t_action_definition like '%t_payee%'"
                //============
                << ""
                << "4.5"
                << "4.6"
                << "DELETE FROM suboperation WHERE NOT EXISTS (SELECT 1 FROM operation WHERE operation.id=suboperation.rd_operation_id)"
                //============
                << ""
                << "4.6"
                << "4.7"
                << "UPDATE node SET t_data=replace(t_data, ' smoothScrolling=&quot;N&quot;', ' zoomPosition=&quot;0&quot;') WHERE t_data like '% smoothScrolling=&quot;N&quot;%'"
                << "UPDATE node SET t_data=replace(t_data, ' smoothScrolling=&quot;Y&quot;', ' zoomPosition=&quot;0&quot;') WHERE t_data like '% smoothScrolling=&quot;Y&quot;%'"
                << "UPDATE parameters SET t_value=replace(t_value, ' smoothScrolling=&quot;N&quot;', ' zoomPosition=&quot;0&quot;') WHERE t_value like '% smoothScrolling=&quot;N&quot;%'"
                << "UPDATE parameters SET t_value=replace(t_value, ' smoothScrolling=&quot;Y&quot;', ' zoomPosition=&quot;0&quot;') WHERE t_value like '% smoothScrolling=&quot;Y&quot;%'"
                //============
                << ""
                << "4.7"
                << "4.8"
                << "CREATE TABLE operationbalance("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "f_balance FLOAT NOT NULL DEFAULT 0,"
                "r_operation_id INTEGER NOT NULL)"
                //============
                << ""
                << "4.8"
                << "4.9"
                <<
                "UPDATE node SET t_data=replace(t_data, ' lines=&quot;t_ACCOUNTTYPE&quot; nbLevelLines=&quot;0&quot;', ' lines=&quot;&quot; nbLevelLines=&quot;0&quot;')"
                << "UPDATE node SET t_data=replace(t_data, ' lines=\"\"t_ACCOUNTTYPE\"\" nbLevelLines=\"\"0\"\"', ' lines=\"\"\"\" nbLevelLines=\"\"0\"\"')"
                << "UPDATE node SET t_data=replace(t_data, ' lines=&amp;quot;t_ACCOUNTTYPE&amp;quot; nbLevelLines=&amp;quot;0&amp;quot;', ' lines=&amp;quot;&amp;quot; nbLevelLines=&amp;quot;0&amp;quot;')"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=&amp;quot;t_ACCOUNTTYPE&amp;quot; nbLevelLines=&amp;quot;0&amp;quot;', ' lines=&amp;quot;&amp;quot; nbLevelLines=&amp;quot;0&amp;quot;')"

                << "UPDATE node SET t_data=replace(t_data, ' lines=&quot;t_UNITTYPE&quot;', ' lines=&quot;t_UNITTYPE&quot; lines2=&quot;t_UNIT&quot;')"
                << "UPDATE node SET t_data=replace(t_data, ' lines=\"\"t_UNITTYPE\"\"', ' lines=\"\"t_UNITTYPE\"\"  lines2=\"\"t_UNIT\"\"')"
                << "UPDATE node SET t_data=replace(t_data, ' lines=&amp;quot;t_UNITTYPE&amp;quot;', ' lines=&amp;quot;t_UNITTYPE&amp;quot; lines2=&amp;quot;t_UNIT&amp;quot;')"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=&amp;quot;t_UNITTYPE&amp;quot;', ' lines=&amp;quot;t_UNITTYPE&amp;quot; lines2=&amp;quot;t_UNIT&amp;quot;')"

                << "UPDATE node SET t_data=replace(t_data, ' lines=&quot;t_ACCOUNTTYPE&quot;', ' lines=&quot;t_ACCOUNTTYPE&quot; lines2=&quot;t_ACCOUNT&quot;')"
                << "UPDATE node SET t_data=replace(t_data, ' lines=\"\"t_ACCOUNTTYPE\"\"', ' lines=\"\"t_ACCOUNTTYPE\"\"  lines2=\"\"t_ACCOUNT\"\"')"
                << "UPDATE node SET t_data=replace(t_data, ' lines=&amp;quot;t_ACCOUNTTYPE&amp;quot;', ' lines=&amp;quot;t_ACCOUNTTYPE&amp;quot; lines2=&amp;quot;t_ACCOUNT&amp;quot;')"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=&amp;quot;t_ACCOUNTTYPE&amp;quot;', ' lines=&amp;quot;t_ACCOUNTTYPE&amp;quot; lines2=&amp;quot;t_ACCOUNT&amp;quot;')"

                //============
                << ""
                << "4.9"
                << "5.0"
                << "CREATE TABLE budget ("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "rc_category_id INTEGER NOT NULL DEFAULT 0,"
                "f_budgeted FLOAT NOT NULL DEFAULT 0.0,"
                "i_year INTEGER NOT NULL DEFAULT 2010,"
                "i_month INTEGER NOT NULL DEFAULT 0 CHECK (i_month>=0 AND i_month<=12)"
                ")"
                //============
                << ""
                << "5.0"
                << "5.1"
                << "CREATE TABLE budgetrule ("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "rc_category_id INTEGER NOT NULL DEFAULT 0,"
                "i_year INTEGER NOT NULL DEFAULT 2010,"
                "i_month INTEGER NOT NULL DEFAULT 0 CHECK (i_month>=0 AND i_month<=12),"
                "i_condition INTEGER NOT NULL DEFAULT 0 CHECK (i_condition IN (-1,0,1)),"
                "f_quantity FLOAT NOT NULL DEFAULT 0.0,"
                "t_absolute TEXT NOT NULL DEFAULT 'Y' CHECK (t_absolute IN ('Y', 'N')),"
                "rc_category_id_target INTEGER NOT NULL DEFAULT 0,"
                "t_rule TEXT NOT NULL DEFAULT 'N' CHECK (t_rule IN ('N', 'C', 'Y'))"
                ")"
                //============
                << ""
                << "5.1"
                << "5.2"
                << "CREATE TABLE budgetcategory("
                "id INTEGER NOT NULL DEFAULT 0,"
                "id_category INTEGER NOT NULL DEFAULT 0)"
                //============
                << ""
                << "5.2"
                << "5.3"
                << "ALTER TABLE budget ADD COLUMN f_budgeted_modified FLOAT NOT NULL DEFAULT 0.0"
                << "UPDATE budget SET f_budgeted_modified=f_budgeted"
                //============
                << ""
                << "5.3"
                << "5.4"
                << "UPDATE node SET t_data=replace(t_data, ' lines=&quot;&quot;', ' lines=&quot;#NOTHING#&quot;')"
                << "UPDATE node SET t_data=replace(t_data, ' lines=\"\"\"\"', ' lines=\"\"#NOTHING#\"\"')"
                << "UPDATE node SET t_data=replace(t_data, ' lines=&amp;quot;&amp;quot;', ' lines=&amp;quot;#NOTHING#&amp;quot;')"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines=&amp;quot;&amp;quot;', ' lines=&amp;quot;#NOTHING#&amp;quot;')"

                << "UPDATE node SET t_data=replace(t_data, ' lines2=&quot;&quot;', ' lines2=&quot;#NOTHING#&quot;')"
                << "UPDATE node SET t_data=replace(t_data, ' lines2=\"\"\"\"', ' lines2=\"\"#NOTHING#\"\"')"
                << "UPDATE node SET t_data=replace(t_data, ' lines2=&amp;quot;&amp;quot;', ' lines2=&amp;quot;#NOTHING#&amp;quot;')"
                << "UPDATE parameters SET t_value=replace(t_value, ' lines2=&amp;quot;&amp;quot;', ' lines2=&amp;quot;#NOTHING#&amp;quot;')"

                << "UPDATE node SET t_data=replace(t_data, ' columns=&quot;&quot;', ' columns=&quot;#NOTHING#&quot;')"
                << "UPDATE node SET t_data=replace(t_data, ' columns=\"\"\"\"', ' columns=\"\"#NOTHING#\"\"')"
                << "UPDATE node SET t_data=replace(t_data, ' columns=&amp;quot;&amp;quot;', ' columns=&amp;quot;#NOTHING#&amp;quot;')"
                << "UPDATE parameters SET t_value=replace(t_value, ' columns=&amp;quot;&amp;quot;', ' columns=&amp;quot;#NOTHING#&amp;quot;')"
                //============
                << ""
                << "5.4"
                << "5.5"
                << "ALTER TABLE budgetrule ADD COLUMN t_category_condition TEXT NOT NULL DEFAULT 'Y' CHECK (t_category_condition IN ('Y', 'N'))"
                << "ALTER TABLE budgetrule ADD COLUMN t_year_condition TEXT NOT NULL DEFAULT 'Y' CHECK (t_year_condition IN ('Y', 'N'))"
                << "ALTER TABLE budgetrule ADD COLUMN t_month_condition TEXT NOT NULL DEFAULT 'Y' CHECK (t_month_condition IN ('Y', 'N'))"

                << "UPDATE budgetrule SET t_year_condition='Y'"
                << "UPDATE budgetrule SET t_year_condition='N', i_year=2010 WHERE i_year=0"
                << "UPDATE budgetrule SET t_month_condition='Y'"
                << "UPDATE budgetrule SET t_month_condition='N', i_month=1 WHERE i_month=0"
                << "UPDATE budgetrule SET t_category_condition='Y'"
                << "UPDATE budgetrule SET t_category_condition='N' WHERE rc_category_id=0"
                //============
                << ""
                << "5.5"
                << "5.6"
                << "ALTER TABLE budgetrule ADD COLUMN t_category_target TEXT NOT NULL DEFAULT 'Y' CHECK (t_category_target IN ('Y', 'N'))"
                << "UPDATE budgetrule SET t_category_target='N'"
                //============
                << ""
                << "5.6"
                << "5.7"
                << "ALTER TABLE budget ADD COLUMN f_transferred FLOAT NOT NULL DEFAULT 0.0"
                << "UPDATE budget SET f_transferred=0"
                //============
                << ""
                << "5.7"
                << "5.8"
                << "ALTER TABLE budget ADD COLUMN t_including_subcategories TEXT NOT NULL DEFAULT 'N' CHECK (t_including_subcategories IN ('Y', 'N'));"
                << "UPDATE budget SET t_including_subcategories='N'"
                //============
                << ""
                << "5.8"
                << "5.9"
                << "DELETE FROM parameters WHERE t_uuid_parent='advices';"
                //============
                << ""
                << "5.9"
                << "6.0"
                << "UPDATE category SET t_name=t_name;"
                //============
                << ""
                << "6.0"
                << "6.1"
                << "UPDATE node SET t_data=replace(t_data,'t_type', 't_TYPENLS')"
                << "UPDATE parameters SET t_value=replace(t_value, 't_type', 't_TYPENLS') where t_name like '%_DEFAULT_PARAMETERS'"
                //============
                << ""
                << "6.1"
                << "6.2"
                << "CREATE TABLE account2("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "t_name TEXT NOT NULL,"
                "t_number TEXT NOT NULL DEFAULT '',"
                "t_agency_number TEXT NOT NULL DEFAULT '',"
                "t_agency_address TEXT NOT NULL DEFAULT '',"
                "t_comment TEXT NOT NULL DEFAULT '',"
                "t_close VARCHAR(1) DEFAULT 'N' CHECK (t_close IN ('Y', 'N')),"
                "t_type VARCHAR(1) NOT NULL DEFAULT 'C' CHECK (t_type IN ('C', 'D', 'A', 'I', 'O', 'W')),"
                //C=current D=credit card A=assets (for objects) I=Investment W=Wallet O=other
                "t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N')),"
                "rd_bank_id INTEGER NOT NULL)"
                << "INSERT INTO account2 (id, t_name, t_number, t_agency_number, t_agency_address, t_comment, t_close, t_type, t_bookmarked, rd_bank_id) "
                "SELECT id, t_name, t_number, t_agency_number, t_agency_address, t_comment, t_close, t_type, t_bookmarked, rd_bank_id FROM account"
                << "DROP TABLE IF EXISTS account"
                << "ALTER TABLE account2 RENAME TO account"
                //============
                << ""
                << "6.2"
                << "6.3"
                << "ALTER TABLE suboperation ADD COLUMN t_formula TEXT NOT NULL DEFAULT '';"
                << "UPDATE suboperation SET t_formula=''"
                //============
                << ""
                << "6.3"
                << "6.4"
                << "CREATE TABLE vm_category_display_tmp(  id INT,  t_name TEXT,  t_fullname TEXT,  rd_category_id INT,  i_NBOPERATIONS,  f_REALCURRENTAMOUNT)"
                //============
                << ""
                << "6.4"
                << "6.5"
                << "ALTER TABLE category ADD COLUMN t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N'));"
                << "ALTER TABLE payee ADD COLUMN t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N'));"
                << "UPDATE category SET t_bookmarked='N'"
                << "UPDATE payee SET t_bookmarked='N'"
                //============
                << ""
                << "6.5"
                << "6.6"
                << "CREATE TABLE vm_budget_tmp(  id INT,  rc_category_id INT,  f_budgeted REAL,  i_year INT,  i_month INT,  f_budgeted_modified REAL,  f_transferred REAL,  t_including_subcategories TEXT,  t_CATEGORY,  t_PERIOD,  f_CURRENTAMOUNT,  t_RULES)"
                //============
                << ""
                << "6.6"
                << "6.7"
                << "DROP TABLE IF EXISTS vm_category_display_tmp"
                << "CREATE TABLE vm_category_display_tmp(  id INT,  t_name TEXT,  t_fullname TEXT,  rd_category_id INT,  i_NBOPERATIONS,  f_REALCURRENTAMOUNT, t_bookmarked)"
                //============
                << ""
                << "6.7"
                << "6.8"
                << "CREATE TABLE recurrentoperation2 ("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "d_date DATE NOT NULL DEFAULT '0000-00-00',"
                "rd_operation_id INTEGER NOT NULL,"
                "i_period_increment INTEGER NOT NULL DEFAULT 1 CHECK (i_period_increment>=0),"
                "t_period_unit TEXT NOT NULL DEFAULT 'M' CHECK (t_period_unit IN ('D', 'W', 'M', 'Y')),"
                "t_auto_write VARCHAR(1) DEFAULT 'Y' CHECK (t_auto_write IN ('Y', 'N')),"
                "i_auto_write_days INTEGER NOT NULL DEFAULT 5 CHECK (i_auto_write_days>=0),"
                "t_warn VARCHAR(1) DEFAULT 'Y' CHECK (t_warn IN ('Y', 'N')),"
                "i_warn_days INTEGER NOT NULL DEFAULT 5 CHECK (i_warn_days>=0),"
                "t_times VARCHAR(1) DEFAULT 'N' CHECK (t_times IN ('Y', 'N')),"
                "i_nb_times INTEGER NOT NULL DEFAULT 1 CHECK (i_nb_times>=0)"
                ")"

                << "INSERT INTO recurrentoperation2 (id,d_date,rd_operation_id,i_period_increment,t_period_unit,t_auto_write,i_auto_write_days,t_warn,i_warn_days,t_times,i_nb_times) "
                "SELECT id,d_date,rd_operation_id,i_period_increment,t_period_unit,t_auto_write,i_auto_write_days,t_warn,i_warn_days,t_times,i_nb_times FROM recurrentoperation"

                << "DROP TABLE IF EXISTS recurrentoperation"
                << "ALTER TABLE recurrentoperation2 RENAME TO recurrentoperation"
                //============
                << ""
                << "6.8"
                << "6.9"
                << "CREATE TABLE category2 ("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "t_name TEXT NOT NULL DEFAULT '' CHECK (t_name NOT LIKE '%" % OBJECTSEPARATOR % "%'),"
                "t_fullname TEXT,"
                "rd_category_id INT,"
                "t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N'))"
                ")"
                << "INSERT INTO category2 (id, t_name, t_fullname, rd_category_id, t_bookmarked) "
                "SELECT id, t_name, t_fullname, r_category_id, t_bookmarked FROM category"

                << "DROP TABLE IF EXISTS category"
                << "ALTER TABLE category2 RENAME TO category"

                << "DROP TABLE IF EXISTS vm_category_display_tmp"
                << "CREATE TABLE vm_category_display_tmp(  id INT,  t_name TEXT,  t_fullname TEXT,  rd_category_id INT,  i_NBOPERATIONS,  f_REALCURRENTAMOUNT, t_bookmarked)"
                //============
                << ""
                << "6.9"
                << "7.0"
                << "DELETE FROM parameters WHERE t_name LIKE 'SKG_MONTHLY_REPORT_%'"
                //============ SKROOGE 1.0.0 ^^^
                << ""
                << "7.0"
                << "7.1"
                << "ALTER TABLE unit ADD COLUMN t_source TEXT NOT NULL DEFAULT ''"
                << "UPDATE unit SET t_source=''"
                //============
                << ""
                << "7.1"
                << "7.2"
                << "UPDATE unit SET t_source='Yahoo' WHERE t_source='' AND t_internet_code<>''"
                //============
                << ""
                << "7.2"
                << "7.3"
                << "CREATE TABLE account2("
                "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                "t_name TEXT NOT NULL,"
                "t_number TEXT NOT NULL DEFAULT '',"
                "t_agency_number TEXT NOT NULL DEFAULT '',"
                "t_agency_address TEXT NOT NULL DEFAULT '',"
                "t_comment TEXT NOT NULL DEFAULT '',"
                "t_close VARCHAR(1) DEFAULT 'N' CHECK (t_close IN ('Y', 'N')),"
                "t_type VARCHAR(1) NOT NULL DEFAULT 'C' CHECK (t_type IN ('C', 'D', 'A', 'I', 'L', 'W', 'O')),"
                //C=current D=credit card A=assets (for objects) I=Investment W=Wallet L=Loan O=other
                "t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N')),"
                "rd_bank_id INTEGER NOT NULL)"
                << "INSERT INTO account2 (id, t_name, t_number, t_agency_number, t_agency_address, t_comment, t_close, t_type, t_bookmarked, rd_bank_id) "
                "SELECT id, t_name, t_number, t_agency_number, t_agency_address, t_comment, t_close, t_type, t_bookmarked, rd_bank_id FROM account"
                << "DROP TABLE IF EXISTS account"
                << "ALTER TABLE account2 RENAME TO account"
                //============ SKROOGE 1.1.0 ^^^
                ;
    }


    {
        int nbSteps = migrationSteps.count();
        SKGBEGINPROGRESSTRANSACTION(*this, "#INTERNAL#" % i18nc("Progression step", "Migrate document"), err, 5);
        if (!err) {
            QString version = getParameter("SKG_DB_BANK_VERSION");
            QString initialversion = version;
            QString lastversion = "7.3";
            if (version.isEmpty()) {
                SKGTRACEL(10) << "Initial creation" << endl;
                /**
                 * This constant is used to initialized the data model.
                 * Rules for attribute name:
                 *    t_xxx for TEXT and VARCHAR
                 *    d_xxx for DATE
                 *    f_xxx for FLOAT
                 *    i_xxx for INTEGER
                 *    r_xxx for a link without constraint
                 *    rc_pointed_table_pointed_attribute_xxx for link on other an object in named "pointed_table" with "pointed_attribute"=id of pointing object
                 *                                       a constraint will be created without DELETE CASCADE
                 *    rd_pointed_table_pointed_attribute_xxx for link on other an object in named "pointed_table" with "pointed_attribute"=id of pointing object
                 *                                       a constraint will be created with DELETE CASCADE
                 *    xxx must be in lower case for R/W attributes and in upper case for R/O attributes
                 * Rules for table name:
                 *    v_yyy for views
                 */
                QStringList BankInitialDataModel;
                BankInitialDataModel
                // ==================================================================
                //Table unit
                        << "CREATE TABLE unit("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "t_name TEXT NOT NULL,"
                        "t_symbol TEXT NOT NULL DEFAULT '',"
                        "t_country TEXT NOT NULL DEFAULT '',"
                        "t_type VARCHAR(1) NOT NULL DEFAULT 'C' CHECK (t_type IN ('1', '2', 'C', 'S', 'I', 'O')),"
                        //1=main currency, 2=secondary currency, C=currencies S=share, I=index, O=object
                        "t_internet_code TEXT NOT NULL DEFAULT '',"
                        "i_nbdecimal INT NOT NULL DEFAULT 2,"
                        "rd_unit_id INTEGER NOT NULL DEFAULT 0,"
                        "t_source TEXT NOT NULL DEFAULT ''"
                        ")"

                        // ==================================================================
                        //Table unitvalue
                        << "CREATE TABLE unitvalue("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "rd_unit_id INTEGER NOT NULL,"
                        "d_date DATE NOT NULL,"
                        "f_quantity FLOAT NOT NULL CHECK (f_quantity>=0))"

                        // ==================================================================
                        //Table bank
                        << "CREATE TABLE bank ("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "t_name TEXT NOT NULL DEFAULT '',"
                        "t_bank_number TEXT NOT NULL DEFAULT '',"
                        "t_icon TEXT NOT NULL DEFAULT '')"

                        // ==================================================================
                        //Table account
                        << "CREATE TABLE account("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "t_name TEXT NOT NULL,"
                        "t_number TEXT NOT NULL DEFAULT '',"
                        "t_agency_number TEXT NOT NULL DEFAULT '',"
                        "t_agency_address TEXT NOT NULL DEFAULT '',"
                        "t_comment TEXT NOT NULL DEFAULT '',"
                        "t_close VARCHAR(1) DEFAULT 'N' CHECK (t_close IN ('Y', 'N')),"
                        "t_type VARCHAR(1) NOT NULL DEFAULT 'C' CHECK (t_type IN ('C', 'D', 'A', 'I', 'W', 'L', 'O')),"
                        //C=current D=credit card A=assets (for objects) I=Investment W=Wallet O=other
                        "t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N')),"
                        "rd_bank_id INTEGER NOT NULL)"

                        // ==================================================================
                        //Table interest
                        << "CREATE TABLE interest("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "rd_account_id INTEGER NOT NULL,"
                        "d_date DATE NOT NULL,"
                        "f_rate FLOAT NOT NULL CHECK (f_rate>=0),"
                        "t_income_value_date_mode VARCHAR(1) NOT NULL DEFAULT 'F' CHECK (t_income_value_date_mode IN ('F', '0', '1', '2', '3', '4', '5')),"
                        "t_expenditure_value_date_mode VARCHAR(1) NOT NULL DEFAULT 'F' CHECK (t_expenditure_value_date_mode IN ('F', '0', '1', '2', '3', '4', '5')),"
                        "t_base VARCHAR(3) NOT NULL DEFAULT '24' CHECK (t_base IN ('24', '360', '365'))"
                        ")"

                        // ==================================================================
                        //Table category
                        << "CREATE TABLE category ("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "t_name TEXT NOT NULL DEFAULT '' CHECK (t_name NOT LIKE '%" % OBJECTSEPARATOR % "%'),"
                        "t_fullname TEXT,"
                        "rd_category_id INT,"
                        "t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N'))"
                        ")"

                        << "CREATE TABLE vm_category_display_tmp(  id INT,  t_name TEXT,  t_fullname TEXT,  rd_category_id INT,  i_NBOPERATIONS,  f_REALCURRENTAMOUNT, t_bookmarked)"

                        // ==================================================================
                        //Table operation
                        << "CREATE TABLE operation("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "i_group_id INTEGER NOT NULL DEFAULT 0,"
                        "i_number INTEGER DEFAULT 0 CHECK (i_number>=0),"
                        "d_date DATE NOT NULL DEFAULT '0000-00-00',"
                        "rd_account_id INTEGER NOT NULL,"
                        "t_mode TEXT NOT NULL DEFAULT '',"
                        "r_payee_id INTEGER NOT NULL DEFAULT 0,"
                        "t_comment TEXT NOT NULL DEFAULT '',"
                        "rc_unit_id INTEGER NOT NULL,"
                        "t_status VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_status IN ('N', 'P', 'Y')),"
                        "t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N')),"
                        "t_imported VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_imported IN ('Y', 'N', 'P', 'T')),"
                        "t_template VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_template IN ('Y', 'N')),"
                        "t_import_id TEXT NOT NULL DEFAULT '',"
                        "i_tmp INTEGER NOT NULL DEFAULT 0,"
                        "r_recurrentoperation_id INTEGER NOT NULL DEFAULT 0)"

                        << "CREATE TABLE operationbalance("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "f_balance FLOAT NOT NULL DEFAULT 0,"
                        "r_operation_id INTEGER NOT NULL)"

                        // ==================================================================
                        //Table refund
                        << "CREATE TABLE refund ("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "t_name TEXT NOT NULL DEFAULT '',"
                        "t_comment TEXT NOT NULL DEFAULT '',"
                        "t_close VARCHAR(1) DEFAULT 'N' CHECK (t_close IN ('Y', 'N')))"

                        // ==================================================================
                        //Table payee
                        << "CREATE TABLE payee ("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "t_name TEXT NOT NULL DEFAULT '',"
                        "t_address TEXT NOT NULL DEFAULT '',"
                        "t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N'))"
                        ")"

                        // ==================================================================
                        //Table suboperation
                        << "CREATE TABLE suboperation("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "t_comment TEXT NOT NULL DEFAULT '',"
                        "rd_operation_id INTEGER NOT NULL,"
                        "r_category_id INTEGER NOT NULL DEFAULT 0,"
                        "f_value FLOAT NOT NULL DEFAULT 0.0,"
                        "t_formula TEXT NOT NULL DEFAULT '',"
                        "i_tmp INTEGER NOT NULL DEFAULT 0,"
                        "r_refund_id INTEGER NOT NULL DEFAULT 0)"

                        // ==================================================================
                        //Table recurrentoperation
                        << "CREATE TABLE recurrentoperation ("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "d_date DATE NOT NULL DEFAULT '0000-00-00',"
                        "rd_operation_id INTEGER NOT NULL,"
                        "i_period_increment INTEGER NOT NULL DEFAULT 1 CHECK (i_period_increment>=0),"
                        "t_period_unit TEXT NOT NULL DEFAULT 'M' CHECK (t_period_unit IN ('D', 'W', 'M', 'Y')),"
                        "t_auto_write VARCHAR(1) DEFAULT 'Y' CHECK (t_auto_write IN ('Y', 'N')),"
                        "i_auto_write_days INTEGER NOT NULL DEFAULT 5 CHECK (i_auto_write_days>=0),"
                        "t_warn VARCHAR(1) DEFAULT 'Y' CHECK (t_warn IN ('Y', 'N')),"
                        "i_warn_days INTEGER NOT NULL DEFAULT 5 CHECK (i_warn_days>=0),"
                        "t_times VARCHAR(1) DEFAULT 'N' CHECK (t_times IN ('Y', 'N')),"
                        "i_nb_times INTEGER NOT NULL DEFAULT 1 CHECK (i_nb_times>=0)"
                        ")"

                        // ==================================================================
                        //Table rule
                        << "CREATE TABLE rule ("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "t_description TEXT NOT NULL DEFAULT '',"
                        "t_definition TEXT NOT NULL DEFAULT '',"
                        "t_action_description TEXT NOT NULL DEFAULT '',"
                        "t_action_definition TEXT NOT NULL DEFAULT '',"
                        "t_action_type VARCHAR(1) DEFAULT 'S' CHECK (t_action_type IN ('S', 'U', 'A')),"
                        "t_bookmarked VARCHAR(1) NOT NULL DEFAULT 'N' CHECK (t_bookmarked IN ('Y', 'N')),"
                        "f_sortorder FLOAT"
                        ")"

                        // ==================================================================
                        //Table budget
                        << "CREATE TABLE budget ("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "rc_category_id INTEGER NOT NULL DEFAULT 0,"
                        "t_including_subcategories TEXT NOT NULL DEFAULT 'N' CHECK (t_including_subcategories IN ('Y', 'N')),"
                        "f_budgeted FLOAT NOT NULL DEFAULT 0.0,"
                        "f_budgeted_modified FLOAT NOT NULL DEFAULT 0.0,"
                        "f_transferred FLOAT NOT NULL DEFAULT 0.0,"
                        "i_year INTEGER NOT NULL DEFAULT 2010,"
                        "i_month INTEGER NOT NULL DEFAULT 0 CHECK (i_month>=0 AND i_month<=12)"
                        ")"

                        << "CREATE TABLE budgetcategory("
                        "id INTEGER NOT NULL DEFAULT 0,"
                        "id_category INTEGER NOT NULL DEFAULT 0)"

                        << "CREATE TABLE budgetrule ("
                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
                        "rc_category_id INTEGER NOT NULL DEFAULT 0,"
                        "t_category_condition TEXT NOT NULL DEFAULT 'Y' CHECK (t_category_condition IN ('Y', 'N')),"
                        "t_year_condition TEXT NOT NULL DEFAULT 'Y' CHECK (t_year_condition IN ('Y', 'N')),"
                        "i_year INTEGER NOT NULL DEFAULT 2010,"
                        "i_month INTEGER NOT NULL DEFAULT 0 CHECK (i_month>=0 AND i_month<=12),"
                        "t_month_condition TEXT NOT NULL DEFAULT 'Y' CHECK (t_month_condition IN ('Y', 'N')),"
                        "i_condition INTEGER NOT NULL DEFAULT 0 CHECK (i_condition IN (-1,0,1)),"
                        "f_quantity FLOAT NOT NULL DEFAULT 0.0,"
                        "t_absolute TEXT NOT NULL DEFAULT 'Y' CHECK (t_absolute IN ('Y', 'N')),"
                        "rc_category_id_target INTEGER NOT NULL DEFAULT 0,"
                        "t_category_target TEXT NOT NULL DEFAULT 'Y' CHECK (t_category_target IN ('Y', 'N')),"
                        "t_rule TEXT NOT NULL DEFAULT 'N' CHECK (t_rule IN ('N', 'C', 'Y'))"
                        ")"

                        << "CREATE TABLE vm_budget_tmp(  id INT,  rc_category_id INT,  f_budgeted REAL,  i_year INT,  i_month INT,  f_budgeted_modified REAL,  f_transferred REAL,  t_including_subcategories TEXT,  t_CATEGORY,  t_PERIOD,  f_CURRENTAMOUNT,  t_RULES)"
                        ;

                if (!err)  err = this->executeSqliteOrders(BankInitialDataModel);

                //Set new version
                version = lastversion;
                if (!err) err = SKGDocument::setParameter("SKG_DB_BANK_VERSION", version);
            }

            if (!err && SKGServices::stringToDouble(version) > SKGServices::stringToDouble(lastversion)) {
                err = SKGError(ERR_ABORT, i18nc("Error message", "Impossible to load a document generated by a more recent version"));
            }

            if (!err) {
                QString v1;
                QString v2;
                bool computeCaches = false;
                for (int i = 0; !err && i < nbSteps; ++i) {
                    if (migrationSteps.at(i).isEmpty()) {
                        ++i;
                        v1 = migrationSteps.at(i);
                        ++i;
                        v2 = migrationSteps.at(i);
                        if (version == v1) {
                            SKGTRACEL(10) << "Migration from " << v1 << " to " << v2 << endl;
                            for (int j = i + 1; !err && j < nbSteps; ++j) {
                                QString sql = migrationSteps.at(j);
                                if (!sql.isEmpty()) {
                                    ++i;
                                    if (!err) err = this->executeSqliteOrder(sql);
                                } else {
                                    break;
                                }
                            }

                            if (v1 == "4.7" || v1 == "5.1" || v1 == "5.7" || v1 == "5.9") computeCaches = true;

                            //Set new version
                            version = v2;
                            if (!err) err = SKGDocument::setParameter("SKG_DB_BANK_VERSION", version);
                            oMigrationDone = true;
                        }
                    }
                }
                if (!err) err = stepForward(1, i18nc("Progression step", "Refresh views"));

                if (!err && computeCaches) {
                    err = refreshViewsIndexesAndTriggers();
                    if (!err) err = stepForward(2, i18nc("Progression step", "Computation of balances"));
                    if (!err) err = computeBalances();
                    if (!err) err = stepForward(3, i18nc("Progression step", "Computation of budgets"));
                    if (!err) err = computeBudgetCategoriesLinks();
                    if (!err) err = stepForward(4);
                }

                if (!err) {
                    bool mig = false;
                    err = SKGDocument::migrate(mig);
                    oMigrationDone = oMigrationDone | mig;
                } else err.addError(ERR_FAIL, i18nc("Error message: Could not perform database migration", "Database migration from version %1 to version %2 failed", initialversion, version));
                if (!err) err = stepForward(5);
            }
        }
    }

    return err;
}

SKGError SKGDocumentBank::dump(int iMode)
{
    SKGError err;
    if (getDatabase()) {
        //dump parameters
        SKGTRACE << "=== START DUMP BANK DOCUMENT ===" << endl;
        err = SKGDocument::dump(iMode);

        if (iMode & DUMPUNIT) {
            SKGTRACE << "=== DUMPUNIT (UNITS))===" << endl;
            err.addError(dumpSelectSqliteOrder("SELECT * FROM v_unit_display ORDER BY id"));

            SKGTRACE << "=== DUMPUNIT (VALUES) ===" << endl;
            err.addError(dumpSelectSqliteOrder("SELECT * FROM v_unitvalue_display ORDER BY rd_unit_id, d_date"));
        }

        if (iMode & DUMPACCOUNT) {
            SKGTRACE << "=== DUMPACCOUNT (BANKS) ===" << endl;
            err.addError(dumpSelectSqliteOrder("SELECT * FROM v_bank ORDER BY id"));

            SKGTRACE << "=== DUMPACCOUNT (ACCOUNTS) ===" << endl;
            err.addError(dumpSelectSqliteOrder("SELECT * FROM v_account_display ORDER BY rd_bank_id, id"));
        }

        if (iMode & DUMPOPERATION) {
            SKGTRACE << "=== DUMPOPERATION (OPERATIONS) ===" << endl;
            err.addError(dumpSelectSqliteOrder("SELECT * FROM v_operation_display_all ORDER BY id"));

            SKGTRACE << "=== DUMPOPERATION (SUBOPERATIONS) ===" << endl;
            err.addError(dumpSelectSqliteOrder("SELECT * FROM v_suboperation_display ORDER BY rd_operation_id, id"));

            SKGTRACE << "=== DUMPOPERATION (RECURRENT) ===" << endl;
            err.addError(dumpSelectSqliteOrder("SELECT * FROM v_recurrentoperation ORDER BY rd_operation_id, id"));

            SKGTRACE << "=== DUMPOPERATION (TRACKER) ===" << endl;
            err.addError(dumpSelectSqliteOrder("SELECT * FROM v_refund ORDER BY id"));
        }

        if (iMode & DUMPPAYEE) {
            SKGTRACE << "=== DUMPOPERATION (PAYEE) ===" << endl;
            err.addError(dumpSelectSqliteOrder("SELECT * FROM v_payee ORDER BY id"));
        }

        if (iMode & DUMPCATEGORY) {
            SKGTRACE << "=== DUMPCATEGORY ===" << endl;
            err.addError(dumpSelectSqliteOrder("SELECT * FROM v_category_display ORDER BY rd_category_id, id"));
        }

        SKGTRACE << "=== END DUMP BANK DOCUMENT ===" << endl;
    }

    return err;
}

SKGError SKGDocumentBank::addOrModifyUnitValue(const QString& iUnitName, const QDate& iDate, double iValue, SKGUnitValueObject* oValue)
{
    SKGError err;
    SKGTRACEINRC(10, "SKGDocumentBank::addOrModifyUnitValue", err);

    //Creation or update of the unit
    bool insertOrUpdate = true;
    SKGUnitObject unit(this);
    err = unit.setName(iUnitName);
    if (!err) err = unit.setSymbol(iUnitName);
    if (!unit.exist()) {
        insertOrUpdate = false;
        if (!err) err = unit.save(insertOrUpdate);
    } else err = unit.load();

    //Creation or update of the value
    SKGUnitValueObject value;
    if (!err) err = unit.addUnitValue(value);
    if (!err) err = value.setDate(iDate);
    if (!err) err = value.setQuantity(iValue);
    if (!err) err = value.save(insertOrUpdate);

    if (oValue) *oValue = value;

    //Add error if needed
    if (err) err.addError(ERR_FAIL, i18nc("Error message",  "Operation '%1' on '%2' failed", QString("SKGDocumentBank::addOrModifyUnitValue"), iUnitName));
    return err;
}

QString SKGDocumentBank::formatMoney(double iValue, SKGServices::SKGUnitInfo iUnit) const
{
    KLocale* locale = KGlobal::locale();

    //Get std colors
    KColorScheme scheme(QPalette::Normal);
    QString negative = scheme.foreground(KColorScheme::NegativeText).color().name();
    QString neutral = scheme.foreground(KColorScheme::NormalText).color().name();

    //Return value
    return QString("<font color=\"") %
           (iValue < 0 ? negative : neutral) %
           "\">" %
           SKGServices::stringToHtml(locale ? locale->formatMoney(iValue / iUnit.Value, iUnit.Symbol, iUnit.NbDecimal) : SKGServices::doubleToString(round(iValue / iUnit.Value / 100) * 100) % ' ' % iUnit.Symbol) %
           "</font>";
}

QString SKGDocumentBank::formatPercentage(double iValue, bool iInvertColors) const
{
    KLocale* locale = KGlobal::locale();

    //Get std colors
    KColorScheme scheme(QPalette::Normal);
    QString negative = scheme.foreground(KColorScheme::NegativeText).color().name();
    QString positive = scheme.foreground(KColorScheme::PositiveText).color().name();

    //Return value
    QString p = (locale ? locale->formatMoney(iValue, "%", 2) : SKGServices::doubleToString(iValue) % " %");
    if (iValue > 0) p = '+' % p;
    if (p.count() > 10 || isnan(iValue) || isinf(iValue)) p = QChar(8734);
    return "<font color=\"" %
           QString((iValue < 0 && !iInvertColors) || (iValue >= 0 && iInvertColors) ? negative : positive) %
           "\">" % SKGServices::stringToHtml(p) %
           "</font>";
}

SKGServices::SKGUnitInfo SKGDocumentBank::getPrimaryUnit()
{
    SKGServices::SKGUnitInfo output;

    output.Name = getCachedValue("primaryUnitCache");
    if (output.Name.isEmpty()) {
        this->refreshCache("unit");
        output.Name = getCachedValue("primaryUnitCache");
    }
    output.Value = 1;
    output.Symbol = getCachedValue("primaryUnitSymbolCache");
    output.NbDecimal = SKGServices::stringToInt(getCachedValue("primaryUnitDecimalCache"));

    return output;
}

SKGServices::SKGUnitInfo SKGDocumentBank::getSecondaryUnit()
{
    SKGServices::SKGUnitInfo output;

    output.Name = getCachedValue("secondaryUnitCache");
    if (output.Name.isEmpty()) {
        this->refreshCache("unit");
        output.Name = getCachedValue("secondaryUnitCache");
    }
    output.Symbol = getCachedValue("secondaryUnitSymbolCache");
    output.Value = SKGServices::stringToDouble(getCachedValue("secondaryUnitValueCache"));
    output.NbDecimal = SKGServices::stringToInt(getCachedValue("secondaryUnitDecimalCache"));

    return output;
}

void SKGDocumentBank::refreshCache(const QString& iTable)
{
    if (iTable == "unit") {
        SKGStringListList result;
        executeSelectSqliteOrder("SELECT t_name, t_symbol, i_nbdecimal FROM unit WHERE t_type='1'", result);
        if (result.size() == 2) {
            addValueInCache("primaryUnitCache", result.at(1).at(0));
            addValueInCache("primaryUnitSymbolCache", result.at(1).at(1));
            addValueInCache("primaryUnitDecimalCache", result.at(1).at(2));
        } else {
            addValueInCache("primaryUnitCache", "");
            addValueInCache("primaryUnitSymbolCache", "");
            addValueInCache("primaryUnitDecimalCache", "2");
        }

        executeSelectSqliteOrder("SELECT t_name, t_symbol, f_CURRENTAMOUNT, i_nbdecimal FROM v_unit WHERE t_type='2'", result);
        if (result.size() == 2) {
            addValueInCache("secondaryUnitCache", result.at(1).at(0));
            addValueInCache("secondaryUnitSymbolCache", result.at(1).at(1));
            addValueInCache("secondaryUnitValueCache", result.at(1).at(2));
            addValueInCache("secondaryUnitDecimalCache", result.at(1).at(3));
        } else {
            addValueInCache("secondaryUnitCache", "");
            addValueInCache("secondaryUnitSymbolCache", "");
            addValueInCache("secondaryUnitValueCache", "1");
            addValueInCache("secondaryUnitDecimalCache", "2");
        }
    }
}

SKGError SKGDocumentBank::addOrModifyAccount(const QString& iName, const QString& iNumber, const QString& iBankName)
{
    SKGError err;
    SKGTRACEINRC(10, "SKGDocumentBank::addOrModifyAccount", err);

    //Creation or update of the bank
    SKGBankObject bank(this);
    err = bank.setName(iBankName);
    if (!err)  err = bank.save();

    //Creation or update of the account
    SKGAccountObject account;
    if (!err) err = bank.addAccount(account);
    if (!err) err = account.setAttribute("rd_bank_id", SKGServices::intToString(bank.getID()));
    if (!err) err = account.setName(iName);
    if (!err) err = account.setAttribute("t_number", iNumber);
    if (!err) err = account.save();

    if (err) err.addError(ERR_FAIL, i18nc("Error message",  "Operation '%1' on '%2' failed", QString("SKGDocumentBank::addOrModifyAccount"), iName));
    return err;
}

QString SKGDocumentBank::getFileExtension() const
{
    return "skg";
}

QString SKGDocumentBank::getDocumentHeader() const
{
    return "SKROOGE";
}

QList<SKGDocument::SKGModelTemplate> SKGDocumentBank::getDisplaySchemas(const QString& iRealTable) const
{
    QList<SKGDocument::SKGModelTemplate> listSchema;

    //Get properties
    QStringList properties;
    this->getDistinctValues("parameters", "t_name", "t_uuid_parent like '%-" % iRealTable % '\'', properties);

    //Build property schema
    QString propSchema;
    int nb = properties.count();
    for (int i = 0; i < nb; ++i)
        propSchema += ";p_" % properties.at(i) % "|N";

    //Build schemas
    if (iRealTable == "operation") {
        SKGModelTemplate def;
        def.id = "default";
        def.name = i18nc("Noun, the default value of an item", "Default");
        def.icon = "edit-undo";
        def.schema = "d_date;i_NBRECURRENT;t_bookmarked;t_ACCOUNT;i_number;t_mode;t_PAYEE;t_comment;t_REALCOMMENT;t_CATEGORY;t_REALCATEGORY;t_status;"
                     "f_REALCURRENTAMOUNT;f_REALCURRENTAMOUNT_EXPENSE|N;f_REALCURRENTAMOUNT_INCOME|N;"
                     "f_CURRENTAMOUNT;f_CURRENTAMOUNT_EXPENSE|N;f_CURRENTAMOUNT_INCOME|N;"
                     "f_QUANTITY|N;f_QUANTITY_EXPENSE|N;f_QUANTITY_INCOME|N;f_REALQUANTITY|N;f_REALQUANTITY_EXPENSE|N;f_REALQUANTITY_INCOME|N;"
                     "t_imported|N;t_REALREFUND|N;t_REFUND|N"
                     ";f_BALANCE|N" % propSchema
                     ;
        listSchema.push_back(def);

        SKGModelTemplate minimum;
        minimum.id = "minimum";
        minimum.name = i18nc("Noun, the minimum value of an item", "Minimum");
        minimum.icon = "";
        minimum.schema = "d_date;i_NBRECURRENT|N;t_bookmarked|N;t_ACCOUNT;i_number|N;t_mode|N;t_PAYEE|N;t_comment|N;t_REALCOMMENT|N;t_CATEGORY|N;t_REALCATEGORY|N;t_status;"
                         "f_REALCURRENTAMOUNT;f_REALCURRENTAMOUNT_EXPENSE|N;f_REALCURRENTAMOUNT_INCOME|N;"
                         "f_CURRENTAMOUNT;f_CURRENTAMOUNT_EXPENSE|N;f_CURRENTAMOUNT_INCOME|N;"
                         "f_QUANTITY|N;f_QUANTITY_EXPENSE|N;f_QUANTITY_INCOME|N;f_REALQUANTITY|N;f_REALQUANTITY_EXPENSE|N;f_REALQUANTITY_INCOME|N;"
                         "t_imported|N;t_REALREFUND|N;t_REFUND|N"
                         ";f_BALANCE|N" % propSchema
                         ;
        listSchema.push_back(minimum);

        SKGModelTemplate doubleColumn;
        doubleColumn.id = "doublecolumn";
        doubleColumn.name = i18nc("Noun",  "Amount in 2 columns");
        doubleColumn.icon = "";
        doubleColumn.schema = "d_date;i_NBRECURRENT;t_bookmarked;t_ACCOUNT;i_number;t_mode;t_PAYEE;t_comment;t_REALCOMMENT;t_CATEGORY;t_REALCATEGORY;t_status;"
                              "f_REALCURRENTAMOUNT|N;f_REALCURRENTAMOUNT_EXPENSE|Y;f_REALCURRENTAMOUNT_INCOME|Y;"
                              "f_CURRENTAMOUNT|N;f_CURRENTAMOUNT_EXPENSE|Y;f_CURRENTAMOUNT_INCOME|Y;"
                              "f_QUANTITY|N;f_QUANTITY_EXPENSE|N;f_QUANTITY_INCOME|N;f_REALQUANTITY|N;f_REALQUANTITY_EXPENSE|N;f_REALQUANTITY_INCOME|N;"
                              "t_imported|N;t_REALREFUND|N;t_REFUND|N"
                              ";f_BALANCE|N" % propSchema
                              ;
        listSchema.push_back(doubleColumn);

        SKGModelTemplate amountEntered;
        amountEntered.id = "amountentered";
        amountEntered.name = i18nc("Noun",  "Amount entered");
        amountEntered.icon = "";
        amountEntered.schema = "d_date;i_NBRECURRENT;t_bookmarked;t_ACCOUNT;i_number;t_mode;t_PAYEE;t_comment;t_REALCOMMENT;t_CATEGORY;t_REALCATEGORY;t_status;"
                               "f_REALCURRENTAMOUNT|N;f_REALCURRENTAMOUNT_EXPENSE|N;f_REALCURRENTAMOUNT_INCOME|N;"
                               "f_CURRENTAMOUNT|N;f_CURRENTAMOUNT_EXPENSE|N;f_CURRENTAMOUNT_INCOME|N;"
                               "f_QUANTITY|Y;f_QUANTITY_EXPENSE|N;f_QUANTITY_INCOME|N;f_REALQUANTITY|Y;f_REALQUANTITY_EXPENSE|N;f_REALQUANTITY_INCOME|N;"
                               "t_imported|N;t_REALREFUND|N;t_REFUND|N"
                               ";f_BALANCE|N" % propSchema
                               ;
        listSchema.push_back(amountEntered);

        SKGModelTemplate doubleColumnEntered;
        doubleColumnEntered.id = "doublecolumnentered";
        doubleColumnEntered.name = i18nc("Noun",  "Amount entered in 2 columns");
        doubleColumnEntered.icon = "";
        doubleColumnEntered.schema = "d_date;i_NBRECURRENT;t_bookmarked;t_ACCOUNT;i_number;t_mode;t_PAYEE;t_comment;t_REALCOMMENT;t_CATEGORY;t_REALCATEGORY;t_status;"
                                     "f_REALCURRENTAMOUNT|N;f_REALCURRENTAMOUNT_EXPENSE|N;f_REALCURRENTAMOUNT_INCOME|N;"
                                     "f_CURRENTAMOUNT|N;f_CURRENTAMOUNT_EXPENSE|N;f_CURRENTAMOUNT_INCOME|N;"
                                     "f_QUANTITY|N;f_QUANTITY_EXPENSE|Y;f_QUANTITY_INCOME|Y;f_REALQUANTITY|N;f_REALQUANTITY_EXPENSE|Y;f_REALQUANTITY_INCOME|Y;"
                                     "t_imported|N;t_REALREFUND|N;t_REFUND|N"
                                     ";f_BALANCE|N" % propSchema
                                     ;
        listSchema.push_back(doubleColumnEntered);
    } else if (iRealTable == "recurrentoperation") {
        SKGModelTemplate def;
        def.id = "default";
        def.name = i18nc("Noun, the default value of an item", "Default");
        def.icon = "edit-undo";
        def.schema = "d_date;t_PERIODNLS;i_nb_times;i_auto_write_days;i_warn_days;t_ACCOUNT;i_number;t_mode;t_PAYEE;t_comment;t_CATEGORY;"
                     "t_status;f_CURRENTAMOUNT" % propSchema;
        listSchema.push_back(def);

        SKGModelTemplate minimum;
        minimum.id = "minimum";
        minimum.name = i18nc("Noun, the minimum value of an item", "Minimum");
        minimum.icon = "";
        minimum.schema = "d_date;t_PERIODNLS;i_nb_times;i_auto_write_days;i_warn_days;t_ACCOUNT;i_number|N;t_mode|N;t_PAYEE;t_comment|N;t_CATEGORY|N;"
                         "t_status;f_CURRENTAMOUNT" % propSchema;
        listSchema.push_back(minimum);
    } else if (iRealTable == "account") {
        SKGModelTemplate def;
        def.id = "default";
        def.name = i18nc("Noun, the default value of an item", "Default");
        def.icon = "edit-undo";
        def.schema = "t_BANK;t_close;t_bookmarked;t_name;t_TYPENLS;t_BANK_NUMBER;t_agency_number;t_number;t_agency_address;t_comment;f_CURRENTAMOUNT;f_QUANTITY|N;f_TODAYAMOUNT|N;f_CHECKED;f_COMING_SOON;i_NBOPERATIONS;f_RATE|N" % propSchema;
        listSchema.push_back(def);

        SKGModelTemplate minimum;
        minimum.id = "minimum";
        minimum.name = i18nc("Noun, the minimum value of an item", "Minimum");
        minimum.icon = "";
        minimum.schema = "t_BANK;t_close;t_bookmarked|N;t_name;t_TYPENLS|N;t_BANK_NUMBER|N;t_agency_number|N;t_number|N;t_agency_address|N;t_comment|N;f_CURRENTAMOUNT|N;f_QUANTITY|N;f_TODAYAMOUNT|N;f_CHECKED|N;f_COMING_SOON|N;i_NBOPERATIONS|N;f_RATE|N" % propSchema;
        listSchema.push_back(minimum);

        SKGModelTemplate intermediate;
        intermediate.id = "intermediate";
        intermediate.name = i18nc("Noun, an intermediate value between two extremums", "Intermediate");
        intermediate.icon = "";
        intermediate.schema = "t_BANK;t_close;t_bookmarked;t_name;t_TYPENLS|N;t_BANK_NUMBER|N;t_agency_number|N;t_number|N;t_agency_address|N;t_comment|N;f_CURRENTAMOUNT;f_QUANTITY|N;f_TODAYAMOUNT|N,f_CHECKED;f_COMING_SOON;i_NBOPERATIONS|N;f_RATE|N" % propSchema;
        listSchema.push_back(intermediate);
    } else if (iRealTable == "category") {
        SKGModelTemplate def;
        def.id = "default";
        def.name = i18nc("Noun, the default value of an item", "Default");
        def.icon = "edit-undo";
        def.schema = "t_name;t_bookmarked;i_NBOPERATIONS;f_REALCURRENTAMOUNT;i_SUMNBOPERATIONS;f_SUMCURRENTAMOUNT" % propSchema;
        listSchema.push_back(def);

        SKGModelTemplate minimum;
        minimum.id = "minimum";
        minimum.name = i18nc("Noun, the minimum value of an item", "Minimum");
        minimum.icon = "";
        minimum.schema = "t_name;t_bookmarked;i_NBOPERATIONS|N;f_REALCURRENTAMOUNT|N;i_SUMNBOPERATIONS|N;f_SUMCURRENTAMOUNT|N" % propSchema;
        listSchema.push_back(minimum);

        SKGModelTemplate op;
        op.id = "with_operations";
        op.name = i18nc("Noun",  "With operations");
        op.icon = "";
        op.schema = "t_name;t_bookmarked;i_NBOPERATIONS;f_REALCURRENTAMOUNT;i_SUMNBOPERATIONS|N;f_SUMCURRENTAMOUNT|N" % propSchema;
        listSchema.push_back(op);

        SKGModelTemplate op2;
        op2.id = "with_cumulative_operations";
        op2.name = i18nc("Noun",  "With cumulative operations");
        op2.icon = "";
        op2.schema = "t_name;t_bookmarked;i_NBOPERATIONS|N;f_REALCURRENTAMOUNT|N;i_SUMNBOPERATIONS;f_SUMCURRENTAMOUNT" % propSchema;
        listSchema.push_back(op2);
    } else if (iRealTable == "unit") {
        SKGModelTemplate def;
        def.id = "default";
        def.name = i18nc("Noun, the default value of an item", "Default");
        def.icon = "edit-undo";
        def.schema = "t_name;t_symbol;t_country;t_TYPENLS;t_source;t_internet_code;f_CURRENTAMOUNT;f_QUANTITYOWNED;i_nbdecimal;t_UNIT" % propSchema;
        listSchema.push_back(def);

        SKGModelTemplate minimum;
        minimum.id = "minimum";
        minimum.name = i18nc("Noun, the minimum value of an item", "Minimum");
        minimum.icon = "";
        minimum.schema = "t_name;t_symbol;t_country|N;t_TYPENLS;t_source|N;t_internet_code|N;f_CURRENTAMOUNT|N;f_QUANTITYOWNED|N;i_nbdecimal|N;t_UNIT|N" % propSchema;
        listSchema.push_back(minimum);
    } else if (iRealTable == "unitvalue") {
        SKGModelTemplate def;
        def.id = "default";
        def.name = i18nc("Noun, the default value of an item", "Default");
        def.icon = "edit-undo";
        def.schema = "d_date;f_quantity;t_UNIT|N" % propSchema;
        listSchema.push_back(def);
    } else if (iRealTable == "refund") {
        SKGModelTemplate def;
        def.id = "default";
        def.name = i18nc("Noun, the default value of an item", "Default");
        def.icon = "edit-undo";
        def.schema = "t_name;t_comment;t_close;d_FIRSTDATE;d_LASTDATE;f_CURRENTAMOUNT" % propSchema;
        listSchema.push_back(def);

        SKGModelTemplate minimum;
        minimum.id = "minimum";
        minimum.name = i18nc("Noun, the minimum value of an item", "Minimum");
        minimum.icon = "";
        minimum.schema = "t_name;t_comment|N;t_close;d_FIRSTDATE|N;d_LASTDATE|N;f_CURRENTAMOUNT" % propSchema;
        listSchema.push_back(minimum);
    } else if (iRealTable == "payee") {
        SKGModelTemplate def;
        def.id = "default";
        def.name = i18nc("Noun, the default value of an item", "Default");
        def.icon = "edit-undo";
        def.schema = "t_name;t_bookmarked;t_address;f_CURRENTAMOUNT" % propSchema;
        listSchema.push_back(def);

        SKGModelTemplate minimum;
        minimum.id = "minimum";
        minimum.name = i18nc("Noun, the minimum value of an item", "Minimum");
        minimum.icon = "";
        minimum.schema = "t_name;t_bookmarked;t_address|N;f_CURRENTAMOUNT" % propSchema;
        listSchema.push_back(minimum);
    } else if (iRealTable == "rule") {
        SKGModelTemplate def;
        def.id = "default";
        def.name = i18nc("Noun, the default value of an item", "Default");
        def.icon = "edit-undo";
        def.schema = "i_ORDER;t_bookmarked;t_action_type;t_description;t_action_description" % propSchema;
        listSchema.push_back(def);
    } else if (iRealTable == "interest") {
        SKGModelTemplate def;
        def.id = "default";
        def.name = i18nc("Noun, the default value of an item", "Default");
        def.icon = "edit-undo";
        def.schema = "d_date;f_rate;t_income_value_date_mode;t_expenditure_value_date_mode;t_base" % propSchema;
        listSchema.push_back(def);

        SKGModelTemplate minimum;
        minimum.id = "minimum";
        minimum.name = i18nc("Noun, the minimum value of an item", "Minimum");
        minimum.icon = "";
        minimum.schema = "d_date;f_rate;t_income_value_date_mode|N;t_expenditure_value_date_mode|N;t_base|N" % propSchema;
        listSchema.push_back(minimum);
    } else if (iRealTable == "interest_result") {
        SKGModelTemplate def;
        def.id = "default";
        def.name = i18nc("Noun, the default value of an item", "Default");
        def.icon = "edit-undo";
        def.schema = "d_date;d_valuedate;t_comment;f_currentamount;f_coef;f_rate;f_annual_interest;f_accrued_interest" % propSchema;
        listSchema.push_back(def);

        SKGModelTemplate minimum;
        minimum.id = "minimum";
        minimum.name = i18nc("Noun, the minimum value of an item", "Minimum");
        minimum.icon = "";
        minimum.schema = "d_date;d_valuedate|N;t_comment|N;f_currentamount|N;f_coef|N;f_rate;f_annual_interest;f_accrued_interest|N" % propSchema;
        listSchema.push_back(minimum);
    } else if (iRealTable == "budget") {
        SKGModelTemplate def;
        def.id = "default";
        def.name = i18nc("Noun, the default value of an item", "Default");
        def.icon = "edit-undo";
        def.schema = "t_CATEGORY;t_PERIOD;i_year|N;i_month|N;f_budgeted;f_budgeted_modified;f_CURRENTAMOUNT;f_DELTABEFORETRANSFER|N;f_DELTA;t_RULES" % propSchema;
        listSchema.push_back(def);

        SKGModelTemplate minimum;
        minimum.id = "minimum";
        minimum.name = i18nc("Noun, the minimum value of an item", "Minimum");
        minimum.icon = "";
        minimum.schema = "t_CATEGORY;t_PERIOD;i_year|N;i_month|N;f_budgeted|N;f_budgeted_modified;f_CURRENTAMOUNT;f_DELTABEFORETRANSFER|N;f_DELTA;t_RULES|N" % propSchema;
        listSchema.push_back(minimum);
    } else if (iRealTable == "budgetrule") {
        SKGModelTemplate def;
        def.id = "default";
        def.name = i18nc("Noun, the default value of an item", "Default");
        def.icon = "edit-undo";
        def.schema = "t_CATEGORYCONDITION;i_year;i_month;t_WHENNLS;t_WHATNLS;t_RULENLS;t_CATEGORY" % propSchema;
        listSchema.push_back(def);
    } else listSchema = SKGDocument::getDisplaySchemas(iRealTable);

    return listSchema ;
}

QIcon SKGDocumentBank::getIcon(const QString& iString) const
{
    QString att = iString.toLower();

    if (att.endsWith(QLatin1String("t_bookmarked"))) return KIcon("rating");
    if (att.endsWith(QLatin1String("f_balance"))) return KIcon("office-chart-line");
    if (att.endsWith(QLatin1String("i_nbrecurrent"))) return KIcon("chronometer");
    if (att.endsWith(QLatin1String("t_status")) ||
            att.endsWith(QLatin1String("f_checked")) ||
            att.endsWith(QLatin1String("f_coming_soon"))) return KIcon("dialog-ok");
    if (att.endsWith(QLatin1String("t_close"))) return KIcon("window-close");
    if (att.endsWith(QLatin1String("t_categorycondition")) ||
            att.endsWith(QLatin1String("t_category")) ||
            att.endsWith(QLatin1String("t_realcategory"))) return KIcon("skrooge_category");
    if (att.endsWith(QLatin1String("t_symbol"))) return KIcon("view-currency-list");
    if (att.endsWith(QLatin1String("t_typeexpensenls"))) return KIcon("skrooge_type");
    if (att.endsWith(QLatin1String("t_typenls"))) {
        if (att.contains("v_unit")) return KIcon("view-stock-account");
        if (att.contains("v_account")) return KIcon("view-credit-card-account");
    }
    if (att.endsWith(QLatin1String("t_unit")) ||
            att.endsWith(QLatin1String("t_unittype"))) return KIcon("view-currency-list");
    if (att.endsWith(QLatin1String("f_balance")) ||
            att.endsWith(QLatin1String("f_value")) ||
            att.endsWith(QLatin1String("f_currentamount")) ||
            att.endsWith(QLatin1String("f_todayamount")) ||
            att.endsWith(QLatin1String("f_sumcurrentamount")) ||
            att.endsWith(QLatin1String("f_quantity")) ||
            att.endsWith(QLatin1String("f_realcurrentamount"))) return KIcon("skrooge_type");
    if (att.endsWith(QLatin1String("_expense"))) return KIcon("list-remove");
    if (att.endsWith(QLatin1String("_income")) ||
            att.endsWith(QLatin1String("f_annual_interest")) ||
            att.endsWith(QLatin1String("f_accrued_interest"))) return KIcon("list-add");
    if (att.endsWith(QLatin1String("t_description")))  return KIcon("edit-find");
    if (att.endsWith(QLatin1String("t_action_description")))  return KIcon("system-run");
    if (att.endsWith(QLatin1String("t_imported")))  return KIcon("utilities-file-archiver");
    if (att.endsWith(QLatin1String("t_refund")) ||
            att.endsWith(QLatin1String("t_realrefund")))  return KIcon("skrooge_tracker");
    if (att.endsWith(QLatin1String("t_mode")))  return KIcon("skrooge_credit_card");
    if (att.endsWith(QLatin1String("t_account")) ||
            att.endsWith(QLatin1String("t_accounttype")))  return KIcon("kwalletmanager");
    if (att.endsWith(QLatin1String("t_payee"))) return KIcon("skrooge_payee");
    if (att.endsWith(QLatin1String("t_comment")) ||
            att.endsWith(QLatin1String("t_realcomment"))) return KIcon("draw-freehand");
    if (att.endsWith(QLatin1String("t_warn")) ||
            att.endsWith(QLatin1String("i_warn_days"))) return KIcon("dialog-warning");
    if (att.endsWith(QLatin1String("t_name"))) {
        if (att.contains("v_account")) return KIcon("kwalletmanager");
        if (att.contains("v_category")) return KIcon("skrooge_category");
        if (att.contains("v_refund")) return KIcon("skrooge_tracker");
        if (att.contains("v_unit")) return KIcon("view-currency-list");
        if (att.contains("v_payee")) return KIcon("skrooge_payee");
    }
    if (att.endsWith(QLatin1String("f_rate"))) return KIcon("skrooge_more");
    if (att.endsWith(QLatin1String("t_internet_code")) || att.endsWith(QLatin1String("t_source"))) return KIcon("download");
    if (att.contains(QLatin1String(".d_")) || att.startsWith(QLatin1String("d_"))) return KIcon("view-calendar");
    if (att.endsWith(QLatin1String("i_year")) || att.endsWith(QLatin1String("i_month")) || att.endsWith(QLatin1String("t_period"))) return KIcon("view-calendar");
    if (att.endsWith(QLatin1String("f_delta"))) return KIcon("security-high");
    if (att.endsWith(QLatin1String("f_deltabeforetransfer"))) return KIcon("security-medium");
    if (att.endsWith(QLatin1String("f_budgeted")) || att.endsWith(QLatin1String("f_budgeted_modified"))) return KIcon("view-income-categories");
    if (att.endsWith(QLatin1String("t_rules"))) return KIcon("system-run");
    if (att.endsWith(QLatin1String("t_whennls"))) return KIcon("view-calendar");
    if (att.endsWith(QLatin1String("t_whatnls"))) return KIcon("skrooge_type");
    if (att.endsWith(QLatin1String("t_rulenls"))) return KIcon("view-income-categories");
    if (att.endsWith(QLatin1String("t_bank"))) return KIcon("view-bank");
    return SKGDocument::getIcon(iString);
}

QString SKGDocumentBank::getDisplay(const QString& iString) const
{
    QString output = iString.toLower();

    //Internationallization
    if (output.endsWith(QLatin1String("account.t_name")) ||
            output.endsWith(QLatin1String("t_account"))) return i18nc("Noun, an account as in a bank account", "Account");
    if (output.endsWith(QLatin1String("t_accounttype"))) return i18nc("Noun, an account as in a bank account", "Account's type");
    if (output.endsWith(QLatin1String("t_operationname"))) return i18nc("Noun, a financial operation", "Operation");
    if (output.endsWith(QLatin1String("t_name"))) return i18nc("Noun, the name of an item", "Name");
    if (output.endsWith(QLatin1String("account.f_value")) ||
            output.endsWith(QLatin1String("f_balance"))) return i18nc("Noun, as in commercial balance", "Balance");
    if (output.endsWith(QLatin1String("f_value"))) return i18nc("Name, the numerical amount of a financial operation", "Amount");
    if (output.endsWith(QLatin1String("f_currentamount")) ||
            output.endsWith(QLatin1String("f_realcurrentamount"))) return i18nc("Name, the numerical amount of a financial operation", "Amount");
    if (output.endsWith(QLatin1String("f_todayamount"))) return i18nc("Name, the numerical amount of a financial operation", "Today amount");
    if (output.endsWith(QLatin1String("f_currentamount_income")) ||
            output.endsWith(QLatin1String("f_realcurrentamount_income"))) return i18nc("Noun, financial operations with a positive amount", "Income");
    if (output.endsWith(QLatin1String("f_currentamount_expense")) ||
            output.endsWith(QLatin1String("f_realcurrentamount_expense"))) return i18nc("Noun, financial operations with a negative amount", "Expenditure");
    if (output.endsWith(QLatin1String("f_quantity_income")) ||
            output.endsWith(QLatin1String("f_realquantity_income"))) return i18nc("Noun",  "Income entered");
    if (output.endsWith(QLatin1String("f_quantity_expense")) ||
            output.endsWith(QLatin1String("f_realquantity_expense"))) return i18nc("Noun",  "Expenditure entered");
    if (output.endsWith(QLatin1String("f_quantityowned"))) return i18nc("Noun",  "Quantity owned");
    if (output.endsWith(QLatin1String("quantity"))) return i18nc("Noun",  "Amount entered");
    if (output.endsWith(QLatin1String("account.t_number"))) return i18nc("Noun",  "Account number");
    if (output.endsWith(QLatin1String("t_number")) ||
            output.endsWith(QLatin1String("i_number"))) return i18nc("Noun, a number identifying an item", "Number");
    if (output.endsWith(QLatin1String("t_bank_number"))) return i18nc("Noun",  "Bank number");
    if (output.endsWith(QLatin1String("t_agency_number"))) return i18nc("Noun",  "Agency number");
    if (output.endsWith(QLatin1String("t_agency_address"))) return i18nc("Noun",  "Agency address");
    if (output.endsWith(QLatin1String("t_address"))) return i18nc("Noun",  "Address");
    if (output.endsWith(QLatin1String("t_payee"))) return i18nc("A person or institution receiving a payment, or paying the operation", "Payee");
    if (output.endsWith(QLatin1String("t_comment")) ||
            output.endsWith(QLatin1String("t_realcomment"))) return i18nc("Noun, a user comment on an item", "Comment");
    if (output.endsWith(QLatin1String("t_mode"))) return i18nc("Noun, the mode used for payment of the operation (Credit Card, Cheque, Transfer...)", "Mode");
    if (output.contains("recurrentoperation") && output.endsWith(QLatin1String("d_date"))) return i18nc("Noun",  "Next occurrence");
    if (output.endsWith(QLatin1String("d_date"))) return i18nc("Noun, the date of an item", "Date");
    if (output.endsWith(QLatin1String("d_dateweek"))) return i18nc("Noun, 7 days", "Week");
    if (output.endsWith(QLatin1String("d_datemonth"))) return i18nc("Noun, the months in a year", "Month");
    if (output.endsWith(QLatin1String("d_datequarter"))) return i18nc("Noun, 3 months", "Quarter");
    if (output.endsWith(QLatin1String("d_datesemester"))) return i18nc("Noun, 6 months", "Semester");
    if (output.endsWith(QLatin1String("d_dateyear"))) return  i18nc("Noun, the years in a century", "Year");
    if (output.endsWith(QLatin1String("d_date"))) return i18nc("Noun, the date of an item", "Date");
    if (output.endsWith(QLatin1String("d_firstdate"))) return i18nc("Noun, the date of an item", "First date");
    if (output.endsWith(QLatin1String("d_lastdate"))) return i18nc("Noun, the date of an item", "Last date");
    if (output.endsWith(QLatin1String("t_categorycondition")) ||
            output.endsWith(QLatin1String("t_category")) ||
            output.endsWith(QLatin1String("t_realcategory"))) return i18nc("Noun, the category of an item", "Category");
    if (output.endsWith(QLatin1String("t_bank"))) return i18nc("Noun, a financial institution", "Bank");
    if (output.endsWith(QLatin1String("t_unit"))) return i18nc("Noun, the unit of an operation, usually a currency or a share", "Unit");
    if (output.endsWith(QLatin1String("t_unittype"))) return i18nc("Noun, the unit of an operation, usually a currency or a share", "Unit's type");
    if (output.endsWith(QLatin1String("f_checked"))) return i18nc("Adjective, has an item been checked or not", "Checked");
    if (output.endsWith(QLatin1String("f_coming_soon"))) return i18nc("Adjective, a foreseen value", "Foreseen");
    if (output.endsWith(QLatin1String("t_symbol"))) return i18nc("Noun, ahe unit symbol, something in the line of $, €, £...", "Symbol");
    if (output.endsWith(QLatin1String("t_country"))) return i18nc("Noun, a country in the world (France, China...)", "Country");
    if (output.endsWith(QLatin1String("t_type")) ||
            output.endsWith(QLatin1String("t_typenls"))) return i18nc("Noun, the type of an item", "Type");
    if (output.endsWith(QLatin1String("t_typeexpensenls"))) return i18nc("Noun, the type of an item", "Type");
    if (output.endsWith(QLatin1String("t_internet_code"))) return i18nc("Noun",  "Internet code");
    if (output.endsWith(QLatin1String("i_nboperations"))) return i18nc("Noun",  "Number of operations");
    if (output.endsWith(QLatin1String("t_periodnls"))) return i18nc("Noun, how frequently something occurs", "Periodicity");
    if (output.endsWith(QLatin1String("i_auto_write_days"))) return i18nc("Automatically write something", "Auto write");
    if (output.endsWith(QLatin1String("i_nb_times"))) return i18nc("Noun",  "Nb of occurrences");
    if (output.endsWith(QLatin1String("i_warn_days"))) return i18nc("Verb, warn the user about an event", "Warn");
    if (output.endsWith(QLatin1String("t_close"))) return i18nc("Adjective, a closed item", "Closed");
    if (output.endsWith(QLatin1String("t_bookmarked"))) return i18nc("Adjective, an highlighted item", "Highlighted");
    if (output.endsWith(QLatin1String("t_status"))) return i18nc("Noun, the status of an item", "Status");
    if (output.endsWith(QLatin1String("i_nbrecurrent"))) return i18nc("Adjective, an item scheduled to happen on a regular basis", "Scheduled");
    if (output.endsWith(QLatin1String("i_sumnboperations"))) return i18nc("Noun",  "Number of operations (cumulative)");
    if (output.endsWith(QLatin1String("f_sumcurrentamount"))) return i18nc("Noun",  "Amount (cumulative)");
    if (output.endsWith(QLatin1String("t_description"))) return i18nc("Noun",  "Search description");
    if (output.endsWith(QLatin1String("t_action_description"))) return i18nc("Noun",  "Process description");
    if (output.endsWith(QLatin1String("t_action_type"))) return i18nc("Noun, the type of action", "Action type");
    if (output.endsWith(QLatin1String("t_refund")) ||
            output.endsWith(QLatin1String("t_realrefund"))) return i18nc("Noun, something that is used to track items", "Tracker");
    if (output.endsWith(QLatin1String("t_imported"))) return i18nc("Noun",  "Import status");
    if (output.endsWith(QLatin1String("i_nbdecimal"))) return i18nc("Noun, after the dot",  "Nb decimal");
    if (output.endsWith(QLatin1String("f_rate"))) return i18nc("Noun, for a share",  "Rate");
    if (output.endsWith(QLatin1String("d_valuedate"))) return i18nc("Noun",  "Value date");
    if (output.endsWith(QLatin1String("f_coef"))) return i18nc("Noun",  "Coef");
    if (output.endsWith(QLatin1String("f_annual_interest"))) return i18nc("Noun",  "Annual Interest");
    if (output.endsWith(QLatin1String("f_accrued_interest"))) return i18nc("Noun",  "Accrued Interest");
    if (output.endsWith(QLatin1String("t_income_value_date_mode"))) return i18nc("Noun",  "Value date for credit");
    if (output.endsWith(QLatin1String("t_expenditure_value_date_mode"))) return i18nc("Noun",  "Value date for debit");
    if (output.endsWith(QLatin1String("t_base"))) return i18nc("Noun",  "Base computation");
    if (output.endsWith(QLatin1String("i_year"))) return i18nc("Noun",  "Year");
    if (output.endsWith(QLatin1String("i_month"))) return i18nc("Noun",  "Month");
    if (output.endsWith(QLatin1String("t_period"))) return i18nc("Noun",  "Period");
    if (output.endsWith(QLatin1String("i_order"))) return i18nc("Noun, sort order", "Order");
    if (output.endsWith(QLatin1String("t_whennls"))) return i18nc("Noun", "When");
    if (output.endsWith(QLatin1String("t_whatnls"))) return i18nc("Noun", "What");
    if (output.endsWith(QLatin1String("t_rulenls"))) return i18nc("Noun", "Impacted budget");
    if (output.endsWith(QLatin1String("t_rules"))) return i18nc("Noun", "Rules");
    if (output.endsWith(QLatin1String("f_budgeted"))) return i18nc("Noun", "Originally budgeted");
    if (output.endsWith(QLatin1String("f_budgeted_modified"))) return i18nc("Noun", "Budgeted");
    if (output.endsWith(QLatin1String("f_delta"))) return i18nc("Noun", "Delta");
    if (output.endsWith(QLatin1String("f_deltabeforetransfer"))) return i18nc("Noun", "Original delta");
    if (output.endsWith(QLatin1String("t_source"))) return i18nc("Noun", "Download source");
    if (output.endsWith(QLatin1String("#nothing#"))) return i18nc("Noun, the absence of anything", "-- Nothing --");
    return SKGDocument::getDisplay(iString);
}

QString SKGDocumentBank::getRealAttribute(const QString& iString) const
{
    if (iString.endsWith(QLatin1String("t_BANK"))) return "bank.rd_bank_id.t_name";
    if (iString.endsWith(QLatin1String("t_BANK_NUMBER"))) return "bank.rd_bank_id.t_bank_number";
    return SKGDocument::getRealAttribute(iString);
}

SKGServices::AttributeType SKGDocumentBank::getAttributeType(const QString& iAttributeName) const
{
    SKGServices::AttributeType output = SKGServices::TEXT;
    if (iAttributeName == "t_status" || iAttributeName == "t_imported") return SKGServices::TRISTATE;
    else if (iAttributeName == "t_close" || iAttributeName == "t_bookmarked"  || iAttributeName == "t_auto_write" || iAttributeName == "t_warn") return SKGServices::BOOL;
    else output = SKGDocument::getAttributeType(iAttributeName);
    return output;
}


QVariantList SKGDocumentBank::getBudget(const QString& iMonth)
{
    SKGTRACEIN(10, "SKGDocumentBank::getBudget");
    QVariantList table;
    SKGStringListList listTmp;
    SKGError err = executeSelectSqliteOrder("SELECT t_CATEGORY, f_budgeted, f_CURRENTAMOUNT, f_DELTABEFORETRANSFER, f_budgeted_modified  FROM v_budget "
                                            "where t_PERIOD='" % iMonth % "' ORDER BY t_CATEGORY;",
                                            listTmp);
    int nbval = listTmp.count();
    if (!err && nbval > 1) {
        QVariantList line;
        line << "sum" << getDisplay("t_CATEGORY") << getDisplay("f_budgeted_modified") << getDisplay("f_CURRENTAMOUNT") << getDisplay("f_DELTA");
        table.push_back(line);
        double sum1 = 0;
        double sum2 = 0;
        double sum3 = 0;
        double sum4 = 0;
        for (int i = 1; i < nbval; ++i) { //Ignore header
            double v1 = SKGServices::stringToDouble(listTmp.at(i).at(1));
            double v2 = SKGServices::stringToDouble(listTmp.at(i).at(2));
            double v3 = SKGServices::stringToDouble(listTmp.at(i).at(3));
            double v4 = SKGServices::stringToDouble(listTmp.at(i).at(4));
            QVariantList line;
            line << false << listTmp.at(i).at(0) << v1 << v2 << v3 << v4;
            table.push_back(line);

            sum1 += v1;
            sum2 += v2;
            sum3 += v3;
            sum4 += v4;
        }
        {
            QVariantList line;
            line << true << i18nc("Noun, the numerical total of a sum of values", "Total") << sum1 << sum2 << sum3 << sum4;
            table.push_back(line);
        }
    }
    return table;
}

QVariantList SKGDocumentBank::get5MainCategories(const QString& iMonth)
{
    SKGTRACEIN(10, "SKGDocumentBank::get5MainCategories");
    QVariantList table;
    SKGServices::SKGUnitInfo primary = getPrimaryUnit();

    SKGStringListList listTmp;
    SKGError err = executeSelectSqliteOrder("SELECT t_REALCATEGORY, TOTAL(f_REALCURRENTAMOUNT) FROM v_operation_consolidated "
                                            "where t_TRANSFER='N' AND d_DATEMONTH='" % iMonth % "' AND t_TYPEEXPENSE='-' "
                                            "group by t_REALCATEGORY order by TOTAL(f_REALCURRENTAMOUNT) LIMIT 5;",
                                            listTmp);
    int nbval = listTmp.count();
    if (!err && nbval) {
        QVariantList line;
        line << "sum" << getDisplay("t_REALCATEGORY") << iMonth;
        table.push_back(line);

        for (int i = 1; i < nbval; ++i) { //Ignore header
            double v = qAbs(SKGServices::stringToDouble(listTmp.at(i).at(1)));
            QVariantList line;
            line << false << listTmp.at(i).at(0) << v;
            table.push_back(line);
        }
    }
    return table;
}

QStringList SKGDocumentBank::get5MainCategoriesVariationList(const QString& iMonth, const QString& iPreviousMonth, bool iOnlyIssues, QStringList* oCategoryList)
{
    SKGTRACEIN(10, "SKGDocumentBank::get5MainCategoriesVariationList");
    //Compute input string
    QString inputString = iMonth % iPreviousMonth % (iOnlyIssues ? 'Y' : 'N') % (oCategoryList ? 'Y' : 'N');

    //Use cache or not
    QStringList output;
    if (inputString == m_5mainVariations_inputs) {
        //Yes
        output = m_5mainVariations_cache;
        if (oCategoryList) *oCategoryList = m_5mainVariationsCat_cache;
    }
    m_5mainVariations_inputs = inputString;

    if (output.isEmpty()) {
        SKGServices::SKGUnitInfo primary = getPrimaryUnit();

        SKGStringListList listTmp;
        SKGError err = executeSelectSqliteOrder("select *, 100*(A2-A1)/ABS(A1) as 'V' from "
                                                "(SELECT t_REALCATEGORY as 'C1', TOTAL(f_REALCURRENTAMOUNT) as 'A1' FROM v_operation_consolidated where "
                                                "t_TRANSFER='N' AND d_DATEMONTH='" % iPreviousMonth % "' AND t_TYPEEXPENSE='-' group by t_REALCATEGORY) A,"
                                                "(SELECT t_REALCATEGORY as 'C2', TOTAL(f_REALCURRENTAMOUNT) as 'A2' FROM v_operation_consolidated where "
                                                "t_TRANSFER='N' AND d_DATEMONTH='" % iMonth % "' AND t_TYPEEXPENSE='-' group by t_REALCATEGORY) B "
                                                "WHERE A.C1=B.C2 AND ABS(A2-A1)/ABS(A1)>0.1 ORDER BY ABS(A2-A1) DESC LIMIT 5;",
                                                listTmp);
        if (!err) {
            //Clear the list
            m_5mainVariations_cache.clear();
            m_5mainVariationsCat_cache.clear();

            //Fill list
            int nbval = listTmp.count();
            for (int i = 1; i < nbval; ++i) { //Ignore header
                QString m = listTmp.at(i).at(1);
                /*Example of sentences:
                  Expenses in category "Food > Grocery" in November decreased by 14% for a total  of 220,48€.
                  Expenses in category "Food" (no subcategory) in November increased by 24% for a total of 70,20€.
                  Expenses in category "Automotive > Fuel" in November increased by 24% for a total of 122,48€.
                  Expenses in category "Misc" in November decreased by 30% for a total of 36,52€.
                  This month, you spent 75,00€ in Category "Bills > Subscriptions". No expense in that category was found in previous month
                  Expenses with mode "withdrawal" reprensented 60,00€ of your expenses in current month*/
                QString c1 = listTmp.at(i).at(0);
                double a1 = SKGServices::stringToDouble(listTmp.at(i).at(1));
                double a2 = SKGServices::stringToDouble(listTmp.at(i).at(3));
                double v = SKGServices::stringToDouble(listTmp.at(i).at(4));

                QString a2f = formatMoney(fabs(a2), primary);
                if (a1 < 0 && a2 < 0) {
                    QString vf = formatPercentage(fabs(v), v < 0);
                    if (v < 0) {
                        m_5mainVariations_cache.push_back(i18n("Expenses in category <b>'%1'</b> increased by <b>%2</b> for a total of <b>%3</b>.", c1, vf, a2f));
                        m_5mainVariationsCat_cache.push_back(c1);
                    } else {
                        if (!iOnlyIssues) {
                            m_5mainVariations_cache.push_back(i18n("Expenses in category <b>'%1'</b> decreased by <b>%2</b> for a total of <b>%3</b>.", c1, vf, a2f));
                            m_5mainVariationsCat_cache.push_back(c1);

                        }
                    }
                } else if (a1 > 0 && a2 > 0) {
                    QString vf = formatPercentage(fabs(v));
                    if (v > 0) {
                        if (!iOnlyIssues) {
                            m_5mainVariations_cache.push_back(i18n("Incomes in category <b>'%1'</b> increased by <b>%2</b> for a total of <b>%3</b>.", c1, vf, a2f));
                            m_5mainVariationsCat_cache.push_back(c1);

                        }
                    } else {
                        m_5mainVariations_cache.push_back(i18n("Incomes in category <b>'%1'</b> decreased by <b>%2</b> for a total of <b>%3</b>.", c1, vf, a2f));
                        m_5mainVariationsCat_cache.push_back(c1);
                    }
                }

            }
        }
        output = m_5mainVariations_cache;
        if (oCategoryList) *oCategoryList = m_5mainVariationsCat_cache;
    }
    return output;
}

#include "skgdocumentbank.moc"
