File indexing completed on 2024-06-09 05:03:46

0001 /***************************************************************************
0002  * SPDX-FileCopyrightText: 2022 S. MANKOWSKI stephane@mankowski.fr
0003  * SPDX-FileCopyrightText: 2022 G. DE BURE support@mankowski.fr
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  ***************************************************************************/
0006 /** @file
0007  * This file is Skrooge plugin for IIF import / export.
0008  *
0009  * @author Stephane MANKOWSKI / Guillaume DE BURE
0010  */
0011 #include "skgimportpluginiif.h"
0012 
0013 #include <kpluginfactory.h>
0014 
0015 #include <qcryptographichash.h>
0016 #include <qfile.h>
0017 #include <qsavefile.h>
0018 
0019 #include "skgbankincludes.h"
0020 #include "skgimportexportmanager.h"
0021 #include "skgservices.h"
0022 #include "skgtraces.h"
0023 
0024 /**
0025 * Opening balance string
0026  */
0027 #define OPENINGBALANCE "Opening Balance"
0028 
0029 /**
0030  * This plugin factory.
0031  */
0032 K_PLUGIN_CLASS_WITH_JSON(SKGImportPluginIif, "metadata.json")
0033 
0034 SKGImportPluginIif::SKGImportPluginIif(QObject* iImporter, const QVariantList& iArg)
0035     : SKGImportPlugin(iImporter)
0036 {
0037     SKGTRACEINFUNC(10)
0038     Q_UNUSED(iArg)
0039 }
0040 
0041 SKGImportPluginIif::~SKGImportPluginIif()
0042     = default;
0043 
0044 bool SKGImportPluginIif::isImportPossible()
0045 {
0046     SKGTRACEINFUNC(10)
0047     return isExportPossible();
0048 }
0049 
0050 QString SKGImportPluginIif::getVal(const QStringList& iVals, const QString& iAttribute) const
0051 {
0052     QString output;
0053 
0054     // Get the corresponding header
0055     QStringList header = m_headers["!" % iVals[0]];
0056     if (!header.isEmpty()) {
0057         // Get index of getAttribute
0058         int pos = header.indexOf(iAttribute);
0059         if (pos != -1 && pos < iVals.count()) {
0060             output = iVals[pos].trimmed();
0061         }
0062     }
0063     return output;
0064 }
0065 
0066 SKGError SKGImportPluginIif::importFile()
0067 {
0068     if (m_importer->getDocument() == nullptr) {
0069         return SKGError(ERR_ABORT, i18nc("Error message", "Invalid parameters"));
0070     }
0071 
0072     SKGError err;
0073     SKGTRACEINFUNCRC(2, err)
0074 
0075     // Create account if needed
0076     QDateTime now = QDateTime::currentDateTime();
0077     QString postFix = SKGServices::dateToSqlString(now);
0078 
0079     // Begin transaction
0080     err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Import step", "Import %1 file", "IIF"), 3);
0081     IFOK(err) {
0082         // Open file
0083         QFile file(m_importer->getLocalFileName());
0084         if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
0085             err.setReturnCode(ERR_INVALIDARG).setMessage(i18nc("Error message",  "Open file '%1' failed", m_importer->getFileName().toDisplayString()));
0086         } else {
0087             QTextStream stream(&file);
0088             if (!m_importer->getCodec().isEmpty()) {
0089                 stream.setCodec(m_importer->getCodec().toLatin1().constData());
0090             }
0091 
0092             // Import
0093             SKGOperationObject operation;
0094             SKGSubOperationObject suboperation;
0095             int index = 0;
0096             while (!stream.atEnd() && !err) {
0097                 // Read line
0098                 QString line = stream.readLine().trimmed();
0099                 if (!line.isEmpty()) {
0100                     QStringList vals = SKGServices::splitCSVLine(line, '\t');
0101                     if (vals[0].startsWith(QLatin1Char('!'))) {
0102                         // This is a header
0103                         m_headers[vals[0]] = vals;
0104                     } else {
0105                         // This is an item
0106                         QString t = vals[0].trimmed();
0107                         if (t == QStringLiteral("ACCNT")) {
0108                             // This is an account
0109                             QString accountType = getVal(vals, QStringLiteral("ACCNTTYPE"));
0110                             QString name = getVal(vals, QStringLiteral("NAME"));
0111                             /*
0112                             AP: Accounts payable            DONE: ACCOUNT
0113                             AR: Accounts receivable     DONE: ACCOUNT
0114                             BANK: Checking or savings       DONE: ACCOUNT
0115                             CCARD: Credit card account      DONE: ACCOUNT
0116                             COGS: Cost of goods sold        DONE: CATEGORY
0117                             EQUITY: Capital/Equity      DONE: CATEGORY
0118                             EXEXP: Other expense        DONE: CATEGORY
0119                             EXINC: Other income         DONE: CATEGORY
0120                             EXP: Expense            DONE: CATEGORY
0121                             FIXASSET: Fixed asset       DONE: ACCOUNT
0122                             INC: Income             DONE: CATEGORY
0123                             LTLIAB: Long term liability     DONE: ACCOUNT
0124                             NONPOSTING: Non-posting account DONE: ACCOUNT
0125                             OASSET: Other asset         DONE: ACCOUNT
0126                             OCASSET: Other current asset    DONE: ACCOUNT
0127                             OCLIAB: Other current liability DONE: ACCOUNT*/
0128                             if (accountType == QStringLiteral("BANK") || accountType == QStringLiteral("AP") || accountType == QStringLiteral("AR") ||
0129                                 accountType == QStringLiteral("OCASSET") || accountType == QStringLiteral("FIXASSET") || accountType == QStringLiteral("OASSET") ||
0130                                 accountType == QStringLiteral("OCLIAB") || accountType == QStringLiteral("LTLIAB") ||
0131                                 accountType == QStringLiteral("CCARD") || accountType == QStringLiteral("NONPOSTING")) {
0132                                 // Check if the account already exist
0133                                 SKGAccountObject account;
0134                                 err = SKGNamedObject::getObjectByName(m_importer->getDocument(), QStringLiteral("account"), name, account);
0135                                 IFKO(err) {
0136                                     // Create account
0137                                     SKGBankObject bank(m_importer->getDocument());
0138                                     err = bank.setName(i18nc("Noun",  "Bank for import %1", postFix));
0139                                     if (!err && bank.load().isFailed()) {
0140                                         err = bank.save(false);
0141                                     }
0142                                     IFOKDO(err, bank.addAccount(account))
0143                                     IFOKDO(err, account.setName(name))
0144                                     if (!err && account.load().isFailed()) {
0145                                         IFOKDO(err, account.setType(accountType == QStringLiteral("BANK") || accountType == QStringLiteral("AP") || accountType == QStringLiteral("AR") ? SKGAccountObject::CURRENT :
0146                                                                     accountType == QStringLiteral("OCASSET") || accountType == QStringLiteral("FIXASSET") || accountType == QStringLiteral("OASSET") || accountType == QStringLiteral("EQUITY") ? SKGAccountObject::ASSETS :
0147                                                                     accountType == QStringLiteral("OCLIAB") || accountType == QStringLiteral("LTLIAB") ? SKGAccountObject::LOAN :
0148                                                                     accountType == QStringLiteral("CCARD") ? SKGAccountObject::CREDITCARD :
0149                                                                     SKGAccountObject::OTHER))
0150                                         IFOKDO(err, account.setAgencyNumber(getVal(vals, QStringLiteral("ACCNUM"))))
0151                                         IFOKDO(err, account.setComment(getVal(vals, QStringLiteral("DESC"))))
0152                                         IFOKDO(err, account.save())
0153                                         m_accounts[name] = account;
0154                                     }
0155                                 }
0156                             } else {
0157                                 // This is a category
0158                                 SKGCategoryObject category;
0159                                 QString originalName = name;
0160                                 IFOKDO(err, SKGCategoryObject::createPathCategory(m_importer->getDocument(), name.replace(':', OBJECTSEPARATOR), category))
0161                                 m_categories[originalName] = category;
0162                             }
0163                         } else if (t == QStringLiteral("CUST")) {
0164                             // This is a payee
0165                             QString name = getVal(vals, QStringLiteral("NAME"));
0166                             SKGPayeeObject payee;
0167                             IFOKDO(err, SKGPayeeObject::createPayee(m_importer->getDocument(), name, payee))
0168 
0169                             QString address = getVal(vals, QStringLiteral("BADDR1")) % " " %
0170                                               getVal(vals, QStringLiteral("BADDR2")) % " " %
0171                                               getVal(vals, QStringLiteral("BADDR3")) % " " %
0172                                               getVal(vals, QStringLiteral("BADDR4")) % " " %
0173                                               getVal(vals, QStringLiteral("BADDR5")) % " " %
0174                                               getVal(vals, QStringLiteral("SADDR1")) % " " %
0175                                               getVal(vals, QStringLiteral("SADDR2")) % " " %
0176                                               getVal(vals, QStringLiteral("SADDR3")) % " " %
0177                                               getVal(vals, QStringLiteral("SADDR4")) % " " %
0178                                               getVal(vals, QStringLiteral("SADDR5"));
0179                             address = address.trimmed();
0180 
0181                             IFOKDO(err, payee.setAddress(address))
0182                             IFOKDO(err, payee.save())
0183                             m_payees[name] = payee;
0184                         } else if (t == QStringLiteral("VEND")) {
0185                             // This is a payee
0186                             QString name = getVal(vals, QStringLiteral("NAME"));
0187                             SKGPayeeObject payee;
0188                             IFOKDO(err, SKGPayeeObject::createPayee(m_importer->getDocument(), getVal(vals, QStringLiteral("NAME")), payee))
0189 
0190                             QString address = getVal(vals, QStringLiteral("ADDR1")) % " " %
0191                                               getVal(vals, QStringLiteral("ADDR2")) % " " %
0192                                               getVal(vals, QStringLiteral("ADDR3")) % " " %
0193                                               getVal(vals, QStringLiteral("ADDR4")) % " " %
0194                                               getVal(vals, QStringLiteral("ADDR5"));
0195                             address = address.trimmed();
0196 
0197                             IFOKDO(err, payee.setAddress(address))
0198                             IFOKDO(err, payee.save())
0199                             m_payees[name] = payee;
0200                         } else if (t == QStringLiteral("ENDTRNS")) {
0201                             operation = SKGOperationObject();
0202                             suboperation = SKGSubOperationObject();
0203                         } else if (t == QStringLiteral("TRNS")) {
0204                             // This is an operation
0205                             SKGAccountObject account = m_accounts.value(getVal(vals, QStringLiteral("ACCNT")));
0206                             IFOKDO(err, account.addOperation(operation))
0207 
0208                             QDate date = SKGServices::stringToTime(SKGServices::dateToSqlString(getVal(vals, QStringLiteral("DATE")), QStringLiteral("MM/DD/YYYY"))).date();
0209                             IFOKDO(err, operation.setDate(date))
0210                             IFOKDO(err, operation.setStatus(getVal(vals, QStringLiteral("CLEAR")) == QStringLiteral("Y") ? SKGOperationObject::CHECKED : SKGOperationObject::NONE))
0211 
0212                             QString number = getVal(vals, QStringLiteral("DOCNUM"));
0213                             if (!number.isEmpty()) {
0214                                 IFOKDO(err, operation.setNumber(number))
0215                             }
0216 
0217                             // If an initial balance is existing for the account then we use the unit else we look for the most appropriate unit
0218                             SKGUnitObject unit;
0219                             double initBalance;
0220                             account.getInitialBalance(initBalance, unit);
0221                             if (!unit.exist()) {
0222                                 err = m_importer->getDefaultUnit(unit, &date);
0223                             }
0224                             IFOKDO(err, operation.setUnit(unit))
0225 
0226                             IFOKDO(err, operation.setMode(getVal(vals, QStringLiteral("TRNSTYPE"))))
0227                             QString p = getVal(vals, QStringLiteral("NAME"));
0228                             if (!p.isEmpty()) {
0229                                 IFOKDO(err, operation.setPayee(m_payees[p]))
0230                             }
0231                             IFOKDO(err, operation.setComment(getVal(vals, QStringLiteral("MEMO"))))
0232                             IFOKDO(err, operation.save())
0233                         } else if (t == QStringLiteral("SPL")) {
0234                             // This is a sub operation
0235                             QString a = getVal(vals, QStringLiteral("ACCNT"));
0236                             if (m_categories.contains(a)) {
0237                                 // This is a split
0238                                 SKGCategoryObject cat = m_categories.value(a);
0239                                 IFOKDO(err, operation.addSubOperation(suboperation))
0240                                 IFOKDO(err, suboperation.setQuantity(-SKGServices::stringToDouble(getVal(vals, QStringLiteral("AMOUNT")))))
0241                                 IFOKDO(err, suboperation.setCategory(cat))
0242                                 IFOKDO(err, suboperation.setComment(getVal(vals, QStringLiteral("MEMO"))))
0243                                 IFOKDO(err, suboperation.save())
0244                             } else if (m_accounts.contains(a)) {
0245                                 // This is a transfer
0246                                 SKGAccountObject act = m_accounts.value(a);
0247 
0248                                 SKGOperationObject operation2;
0249                                 IFOKDO(err, act.addOperation(operation2))
0250 
0251                                 QDate date = SKGServices::stringToTime(SKGServices::dateToSqlString(getVal(vals, QStringLiteral("DATE")), QStringLiteral("MM/DD/YYYY"))).date();
0252                                 IFOKDO(err, operation2.setDate(date))
0253                                 IFOKDO(err, operation2.setStatus(getVal(vals, QStringLiteral("CLEAR")) == QStringLiteral("Y") ? SKGOperationObject::CHECKED : SKGOperationObject::NONE))
0254 
0255                                 QString number = getVal(vals, QStringLiteral("DOCNUM"));
0256                                 if (!number.isEmpty()) {
0257                                     IFOKDO(err, operation2.setNumber(number))
0258                                 }
0259 
0260                                 SKGUnitObject unit;
0261                                 IFOKDO(err, operation.getUnit(unit))
0262                                 IFOKDO(err, operation2.setUnit(unit))
0263 
0264                                 IFOKDO(err, operation2.setMode(getVal(vals, QStringLiteral("TRNSTYPE"))))
0265                                 QString p = getVal(vals, QStringLiteral("NAME"));
0266                                 if (!p.isEmpty()) {
0267                                     IFOKDO(err, operation2.setPayee(m_payees[p]))
0268                                 }
0269                                 IFOKDO(err, operation2.setComment(getVal(vals, QStringLiteral("MEMO"))))
0270                                 IFOKDO(err, operation2.save())
0271 
0272                                 SKGSubOperationObject suboperation2;
0273                                 SKGCategoryObject cat = m_categories.value(a);
0274                                 IFOKDO(err, operation2.addSubOperation(suboperation2))
0275                                 IFOKDO(err, suboperation2.setQuantity(SKGServices::stringToDouble(getVal(vals, QStringLiteral("AMOUNT")))))
0276                                 IFOKDO(err, suboperation2.setCategory(cat))
0277                                 IFOKDO(err, suboperation2.setComment(getVal(vals, QStringLiteral("MEMO"))))
0278                                 IFOKDO(err, suboperation2.save())
0279 
0280                                 IFOKDO(err, operation2.setGroupOperation(operation))
0281                                 IFOKDO(err, operation2.save())
0282 
0283                                 IFOKDO(err, operation.addSubOperation(suboperation))
0284                                 IFOKDO(err, suboperation.setQuantity(-SKGServices::stringToDouble(getVal(vals, QStringLiteral("AMOUNT")))))
0285                                 IFOKDO(err, suboperation.setCategory(cat))
0286                                 IFOKDO(err, suboperation.setComment(getVal(vals, QStringLiteral("MEMO"))))
0287                                 IFOKDO(err, suboperation.save())
0288                             }
0289                         }
0290                     }
0291 
0292                     ++index;
0293                     if (!err && index % 500 == 0) {
0294                         err = m_importer->getDocument()->executeSqliteOrder(QStringLiteral("ANALYZE"));
0295                     }
0296                 }
0297 
0298                 // Lines treated
0299                 IFOKDO(err, m_importer->getDocument()->stepForward(3))
0300             }
0301 
0302             // close file
0303             file.close();
0304         }
0305     }
0306     SKGENDTRANSACTION(m_importer->getDocument(),  err)
0307 
0308     return err;
0309 }
0310 
0311 bool SKGImportPluginIif::isExportPossible()
0312 {
0313     SKGTRACEINFUNC(10)
0314     return (m_importer->getDocument() == nullptr ? true : m_importer->getFileNameExtension() == QStringLiteral("IIF"));
0315 }
0316 
0317 SKGError SKGImportPluginIif::exportFile()
0318 {
0319     if (m_importer->getDocument() == nullptr) {
0320         return SKGError(ERR_ABORT, i18nc("Error message", "Invalid parameters"));
0321     }
0322     SKGError err;
0323     SKGTRACEINFUNCRC(2, err)
0324 
0325     // Read parameters
0326     auto listUUIDs = SKGServices::splitCSVLine(m_exportParameters.value(QStringLiteral("uuid_of_selected_accounts_or_operations")));
0327 
0328     QStringList listOperationsToExport;
0329     listOperationsToExport.reserve(listUUIDs.count());
0330     QStringList listAccountsToExport;
0331     listAccountsToExport.reserve(listUUIDs.count());
0332     for (const auto& uuid : qAsConst(listUUIDs)) {
0333         if (uuid.endsWith(QLatin1String("-operation"))) {
0334             listOperationsToExport.push_back(uuid);
0335         } else if (uuid.endsWith(QLatin1String("-account"))) {
0336             listAccountsToExport.push_back(uuid);
0337         }
0338     }
0339 
0340     if ((listAccountsToExport.count() != 0) || (listOperationsToExport.count() != 0)) {
0341         IFOKDO(err, m_importer->getDocument()->sendMessage(i18nc("An information message",  "Only selected accounts and transactions have been exported")))
0342     }
0343 
0344     // Open file
0345     QSaveFile file(m_importer->getLocalFileName(false));
0346     if (!file.open(QIODevice::WriteOnly)) {
0347         err.setReturnCode(ERR_INVALIDARG).setMessage(i18nc("Error message",  "Save file '%1' failed", m_importer->getFileName().toDisplayString()));
0348     } else {
0349         QTextStream stream(&file);
0350         if (!m_importer->getCodec().isEmpty()) {
0351             stream.setCodec(m_importer->getCodec().toLatin1().constData());
0352         }
0353 
0354         err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export %1 file", "IIF"), 4);
0355         IFOK(err) {
0356             // Export accounts
0357             stream << "!ACCNT\tNAME\tACCNTTYPE\tDESC\tACCNUM\tEXTRA\n";
0358             SKGObjectBase::SKGListSKGObjectBase accounts;
0359             IFOKDO(err, m_importer->getDocument()->getObjects(QStringLiteral("v_account_display"), QStringLiteral("1=1 ORDER BY t_name, id"), accounts))
0360             int nbaccount = accounts.count();
0361             if (!err && (nbaccount != 0)) {
0362                 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export accounts"), nbaccount);
0363                 for (int i = 0; !err && i < nbaccount; ++i) {
0364                     SKGAccountObject act(accounts.at(i));
0365                     if (listAccountsToExport.isEmpty() || listAccountsToExport.contains(act.getUniqueID())) {
0366                         SKGAccountObject::AccountType type = act.getType();
0367                         stream << "ACCNT"
0368                                << '\t' << act.getName()
0369                                << '\t' << (type == SKGAccountObject::ASSETS ? "FIXASSET" : (type == SKGAccountObject::LOAN ? "OCLIAB" : type == SKGAccountObject::CREDITCARD ? "CCARD" : "BANK"))
0370                                << '\t' << act.getComment()
0371                                << '\t' << act.getAgencyNumber()
0372                                << '\t'
0373                                << SKGENDL;
0374                     }
0375                     IFOKDO(err, m_importer->getDocument()->stepForward(i + 1))
0376                 }
0377 
0378                 SKGENDTRANSACTION(m_importer->getDocument(),  err)
0379             }
0380             IFOKDO(err, m_importer->getDocument()->stepForward(1))
0381 
0382             // Export categories
0383             SKGObjectBase::SKGListSKGObjectBase categories;
0384             IFOKDO(err, m_importer->getDocument()->getObjects(QStringLiteral("v_category_display_tmp"), QStringLiteral("1=1 ORDER BY t_fullname, id"), categories))
0385             int nbcat = categories.count();
0386             if (!err && (nbcat != 0)) {
0387                 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export categories"), nbcat);
0388                 for (int i = 0; !err && i < nbcat; ++i) {
0389                     SKGCategoryObject cat(categories.at(i));
0390                     QString catName = cat.getFullName();
0391                     if (!catName.isEmpty()) {
0392                         stream << "ACCNT"
0393                                << '\t' << catName.replace(OBJECTSEPARATOR, QStringLiteral(":"))
0394                                << '\t' << (SKGServices::stringToDouble(cat.getAttribute(QStringLiteral("f_REALCURRENTAMOUNT"))) < 0 ? "EXP" : "INC")
0395                                << '\t'
0396                                << '\t'
0397                                << '\t'
0398                                << SKGENDL;
0399                     }
0400                     IFOKDO(err, m_importer->getDocument()->stepForward(i + 1))
0401                 }
0402 
0403                 SKGENDTRANSACTION(m_importer->getDocument(),  err)
0404             }
0405             IFOKDO(err, m_importer->getDocument()->stepForward(2))
0406 
0407             // Export payees
0408             stream << "!CUST\tNAME\tBADDR1\n";
0409             SKGObjectBase::SKGListSKGObjectBase payees;
0410             IFOKDO(err, m_importer->getDocument()->getObjects(QStringLiteral("v_payee_display"), QStringLiteral("1=1 ORDER BY t_name, id"), payees))
0411             int nbpayee = payees.count();
0412             if (!err && (nbpayee != 0)) {
0413                 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export payees"), nbpayee);
0414                 for (int i = 0; !err && i < nbpayee; ++i) {
0415                     SKGPayeeObject payee(payees.at(i));
0416                     stream << "CUST"
0417                            << '\t' << payee.getName()
0418                            << '\t' << payee.getAddress()
0419                            << SKGENDL;
0420                     IFOKDO(err, m_importer->getDocument()->stepForward(i + 1))
0421                 }
0422 
0423                 SKGENDTRANSACTION(m_importer->getDocument(),  err)
0424             }
0425             IFOKDO(err, m_importer->getDocument()->stepForward(3))
0426 
0427             // Export transactions
0428             stream << "!TRNS\tTRNSID\tTRNSTYPE\tDATE\tACCNT\tNAME\tCLASS\tAMOUNT\tDOCNUM\tCLEAR\tMEMO\n";
0429             stream << "!SPL\tSPLID\tTRNSTYPE\tDATE\tACCNT\tNAME\tCLASS\tAMOUNT\tDOCNUM\tCLEAR\tMEMO\n";
0430             stream << "!ENDTRNS\n";
0431             SKGObjectBase::SKGListSKGObjectBase transactions;
0432             IFOKDO(err, m_importer->getDocument()->getObjects(QStringLiteral("v_operation_display"), QStringLiteral("1=1 ORDER BY d_date, id"), transactions))
0433             int nbop = transactions.count();
0434             if (!err && (nbop != 0)) {
0435                 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export transactions"), nbop);
0436                 for (int i = 0; !err && i < nbop; ++i) {
0437                     SKGOperationObject op(transactions.at(i));
0438                     SKGAccountObject a;
0439                     op.getParentAccount(a);
0440                     if ((listOperationsToExport.isEmpty() || listOperationsToExport.contains(op.getUniqueID())) &&
0441                         (listAccountsToExport.isEmpty() || listAccountsToExport.contains(a.getUniqueID()))) {
0442                         stream << "TRNS"
0443                                << '\t' << SKGServices::intToString(op.getID())
0444                                << '\t' << "PAYMENT"
0445                                << '\t' << op.getDate().toString(QStringLiteral("M/d/yyyy"))
0446                                << '\t' << op.getAttribute(QStringLiteral("t_ACCOUNT"))
0447                                << '\t' << op.getAttribute(QStringLiteral("t_PAYEE"))
0448                                << '\t' << op.getAttribute(QStringLiteral("t_CATEGORY")).replace(OBJECTSEPARATOR, QStringLiteral(":"))
0449                                << '\t' << SKGServices::doubleToString(op.getAmount(QDate::currentDate()))
0450                                << '\t' << op.getNumber()
0451                                << '\t' << (op.getStatus() == SKGOperationObject::CHECKED ? QStringLiteral("Y") : QStringLiteral("N"))
0452                                << '\t' << op.getComment()
0453                                << SKGENDL;
0454 
0455                         // Export sub transactions
0456                         SKGObjectBase::SKGListSKGObjectBase sops;
0457                         err = op.getSubOperations(sops);
0458                         int nbsops = sops.count();
0459                         for (int j = 0; !err && j < nbsops; ++j) {
0460                             SKGSubOperationObject sop(sops.at(j));
0461                             SKGCategoryObject cat;
0462                             sop.getCategory(cat);
0463                             stream << "SPL"
0464                                    << '\t' << SKGServices::intToString(sop.getID())
0465                                    << '\t' << "PAYMENT"
0466                                    << '\t' << op.getDate().toString(QStringLiteral("M/d/yyyy"))
0467                                    << '\t' << cat.getFullName().replace(OBJECTSEPARATOR, QStringLiteral(":"))
0468                                    << '\t' << op.getAttribute(QStringLiteral("t_PAYEE"))
0469                                    << '\t'
0470                                    << '\t' << SKGServices::doubleToString(-sop.getQuantity())
0471                                    << '\t' << op.getNumber()
0472                                    << '\t' << (op.getStatus() == SKGOperationObject::CHECKED ? QStringLiteral("Y") : QStringLiteral("N"))
0473                                    << '\t' << sop.getComment()
0474                                    << SKGENDL;
0475                         }
0476                     }
0477                     stream << "ENDTRNS" << SKGENDL;
0478                     IFOKDO(err, m_importer->getDocument()->stepForward(i + 1))
0479                 }
0480 
0481                 SKGENDTRANSACTION(m_importer->getDocument(),  err)
0482             }
0483             IFOKDO(err, m_importer->getDocument()->stepForward(4))
0484 
0485             SKGENDTRANSACTION(m_importer->getDocument(),  err)
0486         }
0487     }
0488 
0489     // Close file
0490     file.commit();
0491     return err;
0492 }
0493 
0494 QString SKGImportPluginIif::getMimeTypeFilter() const
0495 {
0496     return "*.iif|" % i18nc("A file format", "Intuit Interchange Format file");
0497 }
0498 
0499 #include "skgimportpluginiif.moc"