/***************************************************************************
 *   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 is a test script.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include <qfile.h>

#include "skgtestmacro.h"
#include "skgbankincludes.h"

/**
 * The main function of the unit test
 * @param argc the number of arguments
 * @param argv the list of arguments
 */
int main(int argc, char** argv)
{
    Q_UNUSED(argc);
    Q_UNUSED(argv);

    // Init test
    SKGINITTEST(true);

    QString filename = SKGTest::getTestPath("OUT") % "/skgtestoperation.skg";
    QDate now = QDate::currentDate();
    QDate tomorrow = QDate::currentDate().addDays(+1);
    // ============================================================================
    {
        // Test bank document
        SKGDocumentBank document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGUnitValueObject unit_euro_val1;
        SKGBankObject bank(&document1);
        SKGUnitObject unit_euro(&document1);
        SKGAccountObject account;
        SKGError err;
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "BANK_T1", err);

            // Creation bank
            SKGTESTERROR("BANK:setName", bank.setName("CREDIT COOP"), true);
            SKGTESTERROR("BANK:save", bank.save(), true);

            // Creation account
            SKGTESTERROR("BANK:addAccount", bank.addAccount(account), true);
            SKGTESTERROR("ACCOUNT:setName", account.setName("Courant steph"), true);

            SKGOperationObject op_1;
            SKGTESTERROR("ACCOUNT:addOperation", account.addOperation(op_1), false);
            SKGTESTERROR("OP:setParentAccount", op_1.setParentAccount(account), false);

            SKGTESTERROR("ACCOUNT:setClosed", account.setClosed(true), true);
            SKGTESTERROR("ACCOUNT:save", account.save(), true);

            // Creation operation ==> failed
            SKGTESTERROR("ACCOUNT:addOperation", account.addOperation(op_1), false);

            // Reopen account
            SKGTESTERROR("ACCOUNT:setClosed", account.setClosed(false), true);
            SKGTESTERROR("ACCOUNT:save", account.save(), true);

            // Creation unit
            SKGTESTERROR("UNIT:setName", unit_euro.setName("euro"), true);
            SKGTESTERROR("UNIT:save", unit_euro.save(), true);

            // Creation unitvalue
            SKGTESTERROR("UNIT:addUnitValue", unit_euro.addUnitValue(unit_euro_val1), true);
            SKGTESTERROR("UNITVALUE:setQuantity", unit_euro_val1.setQuantity(1), true);
            SKGTESTERROR("UNITVALUE:setDate", unit_euro_val1.setDate(now), true);
            SKGTESTERROR("UNITVALUE:save", unit_euro_val1.save(), true);

            // Creation operation ==> OK
            SKGTESTERROR("ACCOUNT:addOperation", account.addOperation(op_1), true);

            SKGSubOperationObject subop_1;
            SKGTESTERROR("OPE:addSubOperation", op_1.addSubOperation(subop_1), false);

            SKGTESTERROR("OPE:setDate", op_1.setDate(now), true);
            SKGTESTERROR("OPE:setUnit", op_1.setUnit(unit_euro), true);
            SKGTESTERROR("OPE:save", op_1.save(), true);

            SKGTESTERROR("OPE:addSubOperation", op_1.addSubOperation(subop_1), true);
            SKGTESTERROR("SUBOPE:save", subop_1.save(), true);

            SKGTESTERROR("OPE:setDate", op_1.setDate(now), true);
            SKGTESTERROR("OPE:save", op_1.save(), true);

            SKGTEST("OPE:getDate", SKGServices::dateToSqlString(op_1.getDate()), SKGServices::dateToSqlString(now));
            SKGTEST("SUBOPE:getDate", SKGServices::dateToSqlString(subop_1.getDate()), SKGServices::dateToSqlString(now));

            SKGTESTERROR("SUBOPE:setDate", subop_1.setDate(tomorrow), true);
            SKGTESTERROR("SUBOPE:save", subop_1.save(), true);

            SKGTEST("SUBOPE:getDate", SKGServices::dateToSqlString(subop_1.getDate()), SKGServices::dateToSqlString(tomorrow));

            SKGTESTERROR("OPE:setDate", op_1.setDate(tomorrow), true);
            SKGTESTERROR("OPE:save", op_1.save(), true);
            SKGTESTERROR("SUBOPE:load", subop_1.load(), true);

            SKGTEST("OPE:getDate", SKGServices::dateToSqlString(op_1.getDate()), SKGServices::dateToSqlString(tomorrow));
            SKGTEST("SUBOPE:getDate", SKGServices::dateToSqlString(subop_1.getDate()), SKGServices::dateToSqlString(tomorrow.addDays(+1)));
        }
    }

    // ============================================================================
    {
        // Test bank document
        SKGDocumentBank document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGUnitValueObject unit_euro_val1;
        SKGBankObject bank(&document1);
        SKGUnitObject unit_euro(&document1);
        SKGAccountObject account;
        SKGError err;
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "BANK_T1", err);

            // Creation bank
            SKGTESTERROR("BANK:setName", bank.setName("CREDIT COOP"), true);
            SKGTESTERROR("BANK:save", bank.save(), true);

            // Creation account
            SKGTESTERROR("BANK:addAccount", bank.addAccount(account), true);
            SKGTESTERROR("ACCOUNT:setName", account.setName("Courant steph"), true);
            SKGTESTERROR("ACCOUNT:setNumber", account.setNumber("12345P"), true);
            SKGTESTERROR("ACCOUNT:save", account.save(), true);

            // Creation unit
            SKGTESTERROR("UNIT:setName", unit_euro.setName("euro"), true);
            SKGTESTERROR("UNIT:save", unit_euro.save(), true);

            // Creation unitvalue
            SKGTESTERROR("UNIT:addUnitValue", unit_euro.addUnitValue(unit_euro_val1), true);
            SKGTESTERROR("UNITVALUE:setQuantity", unit_euro_val1.setQuantity(1), true);
            SKGTESTERROR("UNITVALUE:setDate", unit_euro_val1.setDate(now), true);
            SKGTESTERROR("UNITVALUE:save", unit_euro_val1.save(), true);

            // Creation categories
            SKGCategoryObject cat_1(&document1);
            SKGTESTERROR("CAT:setName", cat_1.setName("transport"), true);
            SKGTESTERROR("CAT:save", cat_1.save(), true);

            SKGCategoryObject cat_2;
            SKGTESTERROR("CAT:addCategory", cat_1.addCategory(cat_2), true);
            SKGTESTERROR("CAT:setName", cat_2.setName("train"), true);
            SKGTESTERROR("CAT:save", cat_2.save(), true);

            // Creation operation
            SKGOperationObject mainOperation;
            double balance = 0;
            for (int i = 1; i <= 10; ++i) {
                SKGOperationObject op_1;
                SKGTESTERROR("ACCOUNT:addOperation", account.addOperation(op_1), true);
                SKGTESTERROR("OPE:setTemplate", op_1.setTemplate(true), true);
                SKGTESTBOOL("OPE:isTemplate", op_1.isTemplate(), true);
                SKGTESTERROR("OPE:setTemplate", op_1.setTemplate(false), true);
                SKGTESTBOOL("OPE:isTemplate", op_1.isTemplate(), false);
                SKGTESTERROR("OPE:setNumber", op_1.setNumber(1000 + i), true);
                SKGTESTERROR("OPE:setMode", op_1.setMode("cheque"), true);
                SKGTESTERROR("OPE:setComment", op_1.setComment("10 tickets"), true);
                SKGTESTERROR("OPE:setDate", op_1.setDate(now), true);
                SKGTESTERROR("OPE:setUnit", op_1.setUnit(unit_euro), true);
                SKGUnitObject u;
                SKGTESTERROR("OPE:setUnit", op_1.getUnit(u), true);
                SKGTESTERROR("OPE:bookmark", op_1.bookmark(i % 2 == 0), true);
                SKGTESTERROR("OPE:save", op_1.save(), true);
                if (i == 1) {
                    mainOperation = op_1;
                    SKGTESTERROR("OPE:setGroupOperation", mainOperation.setGroupOperation(mainOperation), true);
                    SKGTESTERROR("OPE:save", mainOperation.save(), true);
                } else {
                    if (!op_1.isBookmarked()) {
                        SKGTESTERROR("OPE:setGroupOperation", op_1.setGroupOperation(mainOperation), true);
                    }
                    SKGTESTERROR("OPE:save", op_1.save(), true);
                }

                // Creation suboperation
                for (int j = 1; j <= 5; ++j) {
                    SKGSubOperationObject subop_1;
                    SKGTESTERROR("OPE:addSubOperation", op_1.addSubOperation(subop_1), true);
                    SKGTESTERROR("SUBOPE:setCategory", subop_1.setCategory(cat_2), true);
                    SKGTESTERROR("SUBOPE:setComment", subop_1.setComment("subop"), true);
                    SKGTEST("SUBOPE:getComment", subop_1.getComment(), "subop");
                    SKGTESTERROR("OPE:setFormula", subop_1.setFormula("total*0.196"), true);
                    SKGTEST("SUBOPE:getFormula", subop_1.getFormula(), "total*0.196");
                    SKGTESTERROR("SUBOPE:setQuantity", subop_1.setQuantity(i * j), true);
                    SKGTESTERROR("SUBOPE:save", subop_1.save(), true);

                    SKGTESTERROR("SUBOPE:load", subop_1.load(), true);
                    SKGOperationObject opget;
                    SKGTESTERROR("SUBOPE:getParentOperation", subop_1.getParentOperation(opget), true);
                    SKGTESTBOOL("OPE:comparison", (opget == op_1), true);

                    SKGSubOperationObject subop_12 = subop_1;
                    SKGSubOperationObject subop_13(SKGObjectBase(subop_1));
                    SKGSubOperationObject subop_14 = SKGSubOperationObject(subop_1);

                    SKGObjectBase subop_base = subop_1;
                    SKGSubOperationObject subop_15;
                    subop_15 = subop_base;
                }

                // Checks
                SKGTESTERROR("OPE:load", op_1.load(), true);
                SKGTEST("OPE:getCurrentAmount", op_1.getCurrentAmount(), i * 15);
                balance += i * 15;
                SKGTEST("OPE:getNbSubOperations", op_1.getNbSubOperations(), 5);
                SKGTEST("OPE:getBalance", op_1.getBalance(), balance);
            }

            SKGTESTERROR("ACCOUNT:load", account.load(), true);
            SKGTEST("ACCOUNT:getCurrentAmount", account.getCurrentAmount(), 55 * 15);
            SKGTEST("ACCOUNT:getAmount", account.getAmount(QDate::currentDate()), 55 * 15);

            SKGUnitObject getUnit;
            SKGTESTERROR("ACCOUNT:getUnit", account.getUnit(getUnit), true);
            SKGTESTBOOL("ACCOUNT:unit", (getUnit == unit_euro), true);

            SKGTESTERROR("OPE:load", mainOperation.load(), true);
            SKGObjectBase::SKGListSKGObjectBase oGroupedOperations;
            SKGTESTERROR("OPE:getGroupedOperations", mainOperation.getGroupedOperations(oGroupedOperations), true);
            SKGTEST("OPE:oGroupedOperations", oGroupedOperations.size(), 2);  // Normal
            SKGTESTBOOL("OPE:isInGroup", mainOperation.isInGroup(), true);  // Normal
            SKGOperationObject mainOpe;
            SKGTESTERROR("OPE:getGroupedOperations", mainOperation.getGroupOperation(mainOpe), true);
            SKGTESTBOOL("OPE:isImported", mainOperation.isImported(), false);
            SKGTESTBOOL("OPE:isTransfer", mainOperation.isTransfer(mainOpe), false);

            SKGTEST("OPE:getAmount", mainOpe.getAmount(QDate::currentDate()), 135);

            SKGAccountObject acc;
            SKGTESTERROR("OPE:getParentAccount", mainOperation.getParentAccount(acc), true);
            SKGTESTBOOL("OPE:account==acc", (account == acc), true);
            SKGTEST("OPE:getImportID", mainOperation.getImportID(), "");

            SKGObjectBase::SKGListSKGObjectBase oSubOperations;
            SKGTESTERROR("OPE:getSubOperations", mainOperation.getSubOperations(oSubOperations), true);
            SKGTEST("OPE:oSubOperations", oSubOperations.size(), 5);

            SKGTESTERROR("BANK:load", bank.load(), true);
        }  // A commit is done here because the scope is close

        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "BANK_T2", err);

            SKGTESTERROR("UNITVALUE:setQuantity", unit_euro_val1.setQuantity(2.5), true);
            SKGTESTERROR("UNITVALUE:save", unit_euro_val1.save(), true);

            SKGTESTERROR("ACCOUNT:load", account.load(), true);
            SKGTEST("ACCOUNT:getCurrentAmount", account.getCurrentAmount(), 55 * 15 * 2.5);

            SKGTESTERROR("BANK:load", bank.load(), true);
            SKGTEST("BANK:getCurrentAmount", bank.getCurrentAmount(), 55 * 15 * 2.5);
        }

        QFile(filename).remove();
        SKGTESTERROR("DOC:saveAs", document1.saveAs(filename), true);

        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "BANK_T3", err);

            // Test foreign key constrain
            SKGTESTERROR("UNIT:remove", unit_euro.remove(), false);
        }
    }

    // ============================================================================
    {
        // Test bank document
        SKGDocumentBank document1;
        SKGTESTERROR("document1.load", document1.load(filename), true);

        SKGAccountObject account;
        SKGTESTERROR("SKGAccountObject::getObjectByName", SKGAccountObject::getObjectByName(&document1, "v_account", "Courant steph", account), true);

        SKGTEST("ACCOUNT:getCurrentAmount", account.getCurrentAmount(), 55 * 15 * 2.5);

        SKGBankObject bank;
        SKGTESTERROR("SKGBankObject::getObjectByName", SKGBankObject::getObjectByName(&document1, "v_bank", "CREDIT COOP", bank), true);

        SKGTEST("BANK:getCurrentAmount", bank.getCurrentAmount(), 55 * 15 * 2.5);

        SKGTESTERROR("BANK:undoRedoTransaction", document1.undoRedoTransaction(), true);

        SKGTESTERROR("ACCOUNT:load", account.load(), true);
        SKGTEST("ACCOUNT:getCurrentAmount", account.getCurrentAmount(), 55 * 15);
        SKGTESTERROR("BANK:load", bank.load(), true);
        SKGTEST("BANK:getCurrentAmount", bank.getCurrentAmount(), 55 * 15);

        // delete cascade
        SKGError err;
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "BANK_T2", err);

            SKGTESTERROR("BANK:delete", bank.remove(), true);
        }
        QStringList oResult;
        SKGTESTERROR("BANK:getDistinctValues", document1.getDistinctValues("bank", "id", oResult), true);
        SKGTEST("BANK:oResult.size", oResult.size(), 0);
        SKGTESTERROR("ACCOUNT:getDistinctValues", document1.getDistinctValues("account", "id", oResult), true);
        SKGTEST("ACCOUNT:oResult.size", oResult.size(), 0);
        SKGTESTERROR("OPE:getDistinctValues", document1.getDistinctValues("operation", "id", oResult), true);
        SKGTEST("OPE:oResult.size", oResult.size(), 0);
        SKGTESTERROR("SUBOPE:getDistinctValues", document1.getDistinctValues("suboperation", "id", oResult), true);
        SKGTEST("SUBOPE:oResult.size", oResult.size(), 0);

        SKGTESTERROR("BANK:undoRedoTransaction", document1.undoRedoTransaction(), true);
        SKGTESTERROR("BANK:undoRedoTransaction(SKGDocument::REDO)", document1.undoRedoTransaction(SKGDocument::REDO), true);


        QFile(filename).remove();
    }

    // ============================================================================
    {
        // Test bank document
        SKGDocumentBank document1;
        SKGTESTERROR("document1.initialize()", document1.initialize(), true);
        SKGUnitValueObject unit_euro_val1;
        SKGBankObject bank(&document1);
        SKGUnitObject unit_euro(&document1);
        SKGAccountObject account1;
        SKGAccountObject account2;
        SKGError err;
        {
            // Scope of the transaction
            SKGBEGINTRANSACTION(document1, "BANK_T1", err);

            // Creation bank
            SKGTESTERROR("BANK:setName", bank.setName("CREDIT COOP"), true);
            SKGTESTERROR("BANK:save", bank.save(), true);

            // Creation account
            SKGTESTERROR("BANK:addAccount", bank.addAccount(account1), true);
            SKGTESTERROR("ACCOUNT:setName", account1.setName("Courant steph"), true);
            SKGTESTERROR("ACCOUNT:setType", account1.setType(SKGAccountObject::CURRENT), true);
            SKGTESTERROR("ACCOUNT:save", account1.save(), true);

            SKGTESTERROR("BANK:addAccount", bank.addAccount(account2), true);
            SKGTESTERROR("ACCOUNT:setName", account2.setName("Loan"), true);
            SKGTESTERROR("ACCOUNT:setType", account2.setType(SKGAccountObject::CURRENT), true);
            SKGTESTERROR("ACCOUNT:save", account2.save(), true);

            // Creation unit
            SKGTESTERROR("UNIT:setName", unit_euro.setName("euro"), true);
            SKGTESTERROR("UNIT:save", unit_euro.save(), true);

            // Creation unitvalue
            SKGTESTERROR("UNIT:addUnitValue", unit_euro.addUnitValue(unit_euro_val1), true);
            SKGTESTERROR("UNITVALUE:setQuantity", unit_euro_val1.setQuantity(1), true);
            SKGTESTERROR("UNITVALUE:setDate", unit_euro_val1.setDate(now), true);
            SKGTESTERROR("UNITVALUE:save", unit_euro_val1.save(), true);

            // Creation operations
            SKGOperationObject op_1;
            SKGTESTERROR("ACCOUNT:addOperation", account1.addOperation(op_1), true);
            SKGTESTERROR("OPE:setDate", op_1.setDate(now), true);
            SKGTESTERROR("OPE:setUnit", op_1.setUnit(unit_euro), true);
            SKGTESTERROR("OPE:setNumber", op_1.setNumber(5490990004), true);
            SKGTESTERROR("OPE:save", op_1.save(), true);
            SKGTEST("OPE:getNumber", op_1.getNumber(), qlonglong(5490990004));

            SKGSubOperationObject subop_1;
            SKGTESTERROR("OPE:addSubOperation", op_1.addSubOperation(subop_1), true);
            SKGTESTERROR("SUBOPE:setQuantity", subop_1.setQuantity(10), true);
            SKGTESTERROR("SUBOPE:save", subop_1.save(), true);

            SKGOperationObject op_2;
            SKGTESTERROR("ACCOUNT:addOperation", account2.addOperation(op_2), true);
            SKGTESTERROR("OPE:setDate", op_2.setDate(now), true);
            SKGTESTERROR("OPE:setUnit", op_2.setUnit(unit_euro), true);
            SKGTESTERROR("OPE:save", op_2.save(), true);

            SKGSubOperationObject subop_2;
            SKGTESTERROR("OPE:addSubOperation", op_2.addSubOperation(subop_2), true);
            SKGTESTERROR("SUBOPE:setQuantity", subop_2.setQuantity(-10), true);
            SKGTESTERROR("SUBOPE:save", subop_2.save(), true);


            SKGTESTERROR("OPE:setGroupOperation", op_1.setGroupOperation(op_2), true);
            SKGTESTERROR("OPE:setStatus", op_1.setStatus(SKGOperationObject::POINTED), true);
            SKGTESTERROR("OPE:save", op_1.save(), true);

            SKGOperationObject tmp;
            SKGOperationObject tmp2;
            SKGTESTBOOL("OPE:isTransfer", op_1.isTransfer(tmp), true);
            SKGTESTBOOL("OPE:isTransfer", tmp.isTransfer(tmp2), true);
            SKGTESTBOOL("OPE:equal", (tmp == op_2), true);

            SKGTESTERROR("ACCOUNT:setType", account2.setType(SKGAccountObject::LOAN), true);
            SKGTESTERROR("ACCOUNT:save", account2.save(), true);

            SKGTESTERROR("OPE:load", op_1.load(), true);
            SKGTESTBOOL("OPE:isTransfer", op_1.isTransfer(tmp), false);
            SKGTESTBOOL("OPE:isTransfer", tmp.isTransfer(tmp2), false);
            SKGTESTBOOL("OPE:equal", (tmp == op_2), true);

            SKGTESTERROR("OPE:mergeSuboperations", op_1.mergeSuboperations(op_2), true);

            SKGTESTERROR("ACCOUNT:setLinkedAccount", account1.setLinkedAccount(account2), true);
            SKGAccountObject account2_2;
            SKGTESTERROR("ACCOUNT:getLinkedAccount", account1.getLinkedAccount(account2_2), true);
            SKGTESTBOOL("OPE:equal", (account2 == account2_2), true);

            SKGObjectBase::SKGListSKGObjectBase accounts;
            SKGTESTERROR("ACCOUNT:getLinkedByAccounts", account2.getLinkedByAccounts(accounts), true);

            SKGTESTERROR("ACCOUNT:transferDeferredOperations", account1.transferDeferredOperations(account2), true);

            // Creation template
            SKGOperationObject template1;
            SKGTESTERROR("ACCOUNT:addOperation", account1.addOperation(template1), true);
            SKGTESTERROR("OPE:setDate", template1.setDate(now.addDays(-5)), true);
            SKGTESTERROR("OPE:setUnit", template1.setUnit(unit_euro), true);
            SKGTESTERROR("OPE:setComment", template1.setComment("Comment op"), true);
            SKGTESTERROR("OPE:setTemplate", template1.setTemplate(true), true);
            SKGTESTERROR("OPE:save", template1.save(), true);

            SKGSubOperationObject template1_1;
            SKGTESTERROR("OPE:addSubOperation", template1.addSubOperation(template1_1), true);
            SKGTESTERROR("SUBOPE:setDate", template1_1.setDate(now.addDays(-4)), true);
            SKGTESTERROR("SUBOPE:setQuantity", template1_1.setQuantity(10), true);
            SKGTESTERROR("SUBOPE:setComment", template1.setComment("Comment sub op 1"), true);
            SKGTESTERROR("SUBOPE:save", template1_1.save(), true);

            SKGSubOperationObject template1_2;
            SKGTESTERROR("OPE:addSubOperation", template1.addSubOperation(template1_2), true);
            SKGTESTERROR("SUBOPE:setDate", template1_2.setDate(now.addDays(-3)), true);
            SKGTESTERROR("SUBOPE:setQuantity", template1_2.setQuantity(90), true);
            SKGTESTERROR("SUBOPE:setComment", template1_2.setComment("Comment sub op 2"), true);
            SKGTESTERROR("SUBOPE:save", template1_2.save(), true);

            // Creation op
            SKGOperationObject opbasic;
            SKGTESTERROR("ACCOUNT:addOperation", account1.addOperation(opbasic), true);
            SKGTESTERROR("OPE:setDate", opbasic.setDate(now), true);
            SKGTESTERROR("OPE:setUnit", opbasic.setUnit(unit_euro), true);
            SKGTESTERROR("OPE:setComment", opbasic.setComment("Comment op2"), true);
            SKGTESTERROR("OPE:save", opbasic.save(), true);

            SKGSubOperationObject opbasic_1;
            SKGTESTERROR("OPE:addSubOperation", opbasic.addSubOperation(opbasic_1), true);
            SKGTESTERROR("SUBOPE:setQuantity", opbasic_1.setQuantity(200), true);
            SKGTESTERROR("SUBOPE:save", opbasic_1.save(), true);

            document1.dump(DUMPOPERATION);

            SKGTESTERROR("SUBOPE:load", template1.load(), true);
            SKGTEST("OPE:getCurrentAmount", template1.getCurrentAmount(), 100);
            SKGTEST("OPE:getNbSubOperations", template1.getNbSubOperations(), 2);

            SKGTESTERROR("SUBOPE:load", opbasic.load(), true);
            SKGTEST("OPE:getCurrentAmount", opbasic.getCurrentAmount(), 200);
            SKGTEST("OPE:getNbSubOperations", opbasic.getNbSubOperations(), 1);

            // Apply the template
            SKGOperationObject op;
            SKGTESTERROR("OPE:duplicate", template1.duplicate(op), true);
            SKGTESTERROR("OPE:mergeAttribute", op.mergeAttribute(opbasic, SKGOperationObject::PROPORTIONAL), true);
            document1.dump(DUMPOPERATION);

            SKGTEST("OPE:getCurrentAmount", template1.getCurrentAmount(), 100);
            SKGTEST("OPE:getNbSubOperations", template1.getNbSubOperations(), 2);

            SKGTEST("OPE:getCurrentAmount", op.getCurrentAmount(), 200);
            SKGTEST("OPE:getNbSubOperations", op.getNbSubOperations(), 2);
        }
    }

    // End test
    SKGENDTEST();
}
