File indexing completed on 2024-06-23 05:03:15
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 OFX import / export. 0008 * 0009 * @author Stephane MANKOWSKI / Guillaume DE BURE 0010 */ 0011 #include "skgimportpluginofx.h" 0012 0013 #include <qcryptographichash.h> 0014 #include <qfile.h> 0015 0016 #include <klocalizedstring.h> 0017 #include <kpluginfactory.h> 0018 0019 #include "skgbankincludes.h" 0020 #include "skgimportexportmanager.h" 0021 #include "skgservices.h" 0022 #include "skgtraces.h" 0023 0024 SKGError SKGImportPluginOfx::m_ofxError; 0025 QStringList SKGImportPluginOfx::m_ofxInitialBalanceName; 0026 QList<double> SKGImportPluginOfx::m_ofxInitialBalanceAmount; 0027 QList<QDate> SKGImportPluginOfx::m_ofxInitialBalanceDate; 0028 QMap<QString, SKGAccountObject> SKGImportPluginOfx::m_accounts; 0029 /** 0030 * This plugin factory. 0031 */ 0032 K_PLUGIN_CLASS_WITH_JSON(SKGImportPluginOfx, "metadata.json") 0033 0034 SKGImportPluginOfx::SKGImportPluginOfx(QObject* iImporter, const QVariantList& iArg) 0035 : SKGImportPlugin(iImporter) 0036 { 0037 SKGTRACEINFUNC(10) 0038 Q_UNUSED(iArg) 0039 SKGImportPluginOfx::m_accounts.clear(); 0040 } 0041 0042 SKGImportPluginOfx::~SKGImportPluginOfx() 0043 = default; 0044 0045 bool SKGImportPluginOfx::isImportPossible() 0046 { 0047 SKGTRACEINFUNC(10) 0048 return (m_importer->getDocument() == nullptr ? true : m_importer->getFileNameExtension() == QStringLiteral("OFX") || m_importer->getFileNameExtension() == QStringLiteral("QFX")); 0049 } 0050 0051 SKGError SKGImportPluginOfx::importFile() 0052 { 0053 if (m_importer->getDocument() == nullptr) { 0054 return SKGError(ERR_ABORT, i18nc("Error message", "Invalid parameters")); 0055 } 0056 0057 SKGError err; 0058 SKGTRACEINFUNCRC(2, err) 0059 0060 if (!QFile(m_importer->getLocalFileName()).exists()) { 0061 err.setReturnCode(ERR_INVALIDARG).setMessage(i18nc("Error message", "Open file '%1' failed", m_importer->getFileName().toDisplayString())); 0062 } 0063 IFOKDO(err, m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Import step", "Import %1 file", "OFX"))) 0064 IFOK(err) { 0065 SKGImportPluginOfx::m_ofxError = SKGError(); 0066 SKGImportPluginOfx::m_ofxInitialBalanceName.clear(); 0067 SKGImportPluginOfx::m_ofxInitialBalanceAmount.clear(); 0068 SKGImportPluginOfx::m_ofxInitialBalanceDate.clear(); 0069 0070 try { 0071 // Check file type 0072 // auto type = libofx_detect_file_type( m_importer->getLocalFileName().toUtf8().data()); 0073 0074 LibofxContextPtr ctx = libofx_get_new_context(); 0075 0076 ofx_set_account_cb(ctx, SKGImportPluginOfx::ofxAccountCallback, m_importer); 0077 ofx_set_statement_cb(ctx, SKGImportPluginOfx::ofxStatementCallback, m_importer); 0078 ofx_set_transaction_cb(ctx, SKGImportPluginOfx::ofxTransactionCallback, m_importer); 0079 // ofx_set_security_cb(ctx, ofxSecurityCallback, this); 0080 libofx_proc_file(ctx, m_importer->getLocalFileName().toUtf8().data(), AUTODETECT); 0081 IFOKDO(err, SKGImportPluginOfx::m_ofxError) { 0082 // This is an option ==> no error management 0083 SKGError err2; 0084 int nb = SKGImportPluginOfx::m_ofxInitialBalanceName.count(); 0085 for (int i = 0; !err2 && i < nb; ++i) { 0086 SKGAccountObject act; 0087 err2 = m_importer->getDocument()->getObject(QStringLiteral("v_account"), "t_number='" % SKGServices::stringToSqlString(m_ofxInitialBalanceName.at(i)) % '\'', act); 0088 0089 // Date of balance 0090 auto date = m_ofxInitialBalanceDate.at(i); 0091 0092 // Get unit 0093 SKGUnitObject unit; 0094 if (!err2) { 0095 err2 = m_importer->getDefaultUnit(unit); 0096 } 0097 0098 // Current amount 0099 double currentAmount = act.getAmount(date); 0100 0101 // Update account 0102 if (!err2) { 0103 err2 = act.setInitialBalance(m_ofxInitialBalanceAmount.at(i) - currentAmount, unit); 0104 } 0105 if (!err2) { 0106 err2 = act.save(); 0107 } 0108 if (!err2) { 0109 err2 = m_importer->getDocument()->sendMessage(i18nc("An information message", "The initial balance of '%1' has been set", act.getName())); 0110 } 0111 } 0112 } 0113 libofx_free_context(ctx); 0114 } catch (...) { // NOLINT(whitespace/parens) 0115 err = SKGError(ERR_HANDLE, i18nc("Error message", "OFX import failed")); 0116 } 0117 0118 SKGImportPluginOfx::m_ofxInitialBalanceName.clear(); 0119 SKGImportPluginOfx::m_ofxInitialBalanceAmount.clear(); 0120 SKGImportPluginOfx::m_ofxInitialBalanceDate.clear(); 0121 0122 SKGENDTRANSACTION(m_importer->getDocument(), err) 0123 } 0124 return err; 0125 } 0126 0127 QString SKGImportPluginOfx::getAccountName(OfxAccountData* iAccountData) 0128 { 0129 SKGTRACEINFUNC(3) 0130 QString accountNumber; 0131 if (iAccountData != nullptr) { 0132 accountNumber = QString::fromUtf8(iAccountData->account_id); 0133 QString bankNumber = QString::fromUtf8(iAccountData->bank_id); 0134 // Correction BUG 234771 vvvvv 0135 accountNumber = accountNumber.trimmed(); 0136 bankNumber = bankNumber.trimmed(); 0137 if (accountNumber.isEmpty()) { 0138 accountNumber = QString::fromUtf8(iAccountData->account_number); 0139 } 0140 // Correction BUG 234771 ^^^^^ 0141 if (accountNumber.startsWith(bankNumber % ' ')) { 0142 accountNumber = accountNumber.right(accountNumber.length() - bankNumber.length() - 1); 0143 QStringList splitNumbers = accountNumber.split(' '); 0144 if (splitNumbers.count() == 2) { 0145 accountNumber = splitNumbers.at(1); 0146 } 0147 } 0148 } 0149 SKGTRACEL(3) << "accountNumber=" << accountNumber << SKGENDL; 0150 return accountNumber; 0151 } 0152 0153 SKGError SKGImportPluginOfx::getAccount(OfxAccountData* iAccountData, SKGDocumentBank* iDoc, SKGAccountObject& oAccount) 0154 { 0155 SKGError err; 0156 SKGTRACEINFUNCRC(3, err) 0157 if ((iAccountData != nullptr) && (iDoc != nullptr)) { 0158 // Check if account is already existing 0159 QString name = getAccountName(iAccountData); 0160 if (m_accounts.contains(name)) { 0161 SKGTRACEL(3) << "Found in index" << SKGENDL; 0162 oAccount = m_accounts[name]; 0163 } else { 0164 SKGTRACEL(3) << "NOT found in index" << SKGENDL; 0165 QString wc = "t_number='" % SKGServices::stringToSqlString(name) % "' OR EXISTS(SELECT 1 FROM parameters WHERE t_uuid_parent=v_account.id||'-account' AND t_name='alias' AND t_value= '" % SKGServices::stringToSqlString(name) % "')"; 0166 err = iDoc->getObject(QStringLiteral("v_account"), wc, oAccount); 0167 } 0168 } 0169 0170 return err; 0171 } 0172 0173 int SKGImportPluginOfx::ofxStatementCallback(struct OfxStatementData data, void* pv) // clazy:exclude=function-args-by-ref 0174 { 0175 if (SKGImportPluginOfx::m_ofxError) { 0176 return 0; 0177 } 0178 SKGTRACEINFUNCRC(5, SKGImportPluginOfx::m_ofxError) 0179 0180 auto* impotExporter = static_cast<SKGImportExportManager*>(pv); 0181 if (impotExporter == nullptr) { 0182 return 0; 0183 } 0184 SKGDocumentBank* doc = impotExporter->getDocument(); 0185 if (doc == nullptr) { 0186 return 0; 0187 } 0188 0189 // // Get data 0190 OfxAccountData* accountData = data.account_ptr; 0191 if ((accountData != nullptr) && static_cast<bool>(data.ledger_balance_valid)) { 0192 // Get account 0193 SKGAccountObject act; 0194 SKGImportPluginOfx::m_ofxError = getAccount(accountData, doc, act); 0195 if (!SKGImportPluginOfx::m_ofxError) { 0196 impotExporter->addAccountToCheck(act, data.ledger_balance); 0197 if (act.getNbOperation() > 1) { 0198 SKGImportPluginOfx::m_ofxError = doc->sendMessage(i18nc("An information message", "The initial balance of '%1' has not been set because some transactions are already existing", act.getName())); 0199 } else { 0200 auto d = QDate::currentDate(); 0201 if (static_cast<bool>(data.ledger_balance_date_valid)) { 0202 QDateTime date_time; 0203 date_time.setSecsSinceEpoch(data.ledger_balance_date); 0204 d = date_time.date(); 0205 } 0206 m_ofxInitialBalanceName.push_back(getAccountName(accountData)); 0207 m_ofxInitialBalanceDate.push_back(d); 0208 m_ofxInitialBalanceAmount.push_back(data.ledger_balance); 0209 } 0210 } 0211 } 0212 0213 return SKGImportPluginOfx::m_ofxError.getReturnCode(); 0214 } 0215 0216 int SKGImportPluginOfx::ofxAccountCallback(struct OfxAccountData data, void* pv) 0217 { 0218 if (SKGImportPluginOfx::m_ofxError) { 0219 return 0; 0220 } 0221 SKGTRACEINFUNCRC(5, SKGImportPluginOfx::m_ofxError) 0222 0223 auto* impotExporter = static_cast<SKGImportExportManager*>(pv); 0224 if (impotExporter == nullptr) { 0225 return 0; 0226 } 0227 SKGDocumentBank* doc = impotExporter->getDocument(); 0228 if (doc == nullptr) { 0229 return 0; 0230 } 0231 0232 SKGObjectBase tmp; 0233 QString agencyNumber = QString::fromUtf8(data.branch_id); 0234 QString accountNumber = QString::fromUtf8(data.account_id); 0235 QString bankNumber = QString::fromUtf8(data.bank_id); 0236 // Correction BUG 234771 vvvvv 0237 accountNumber = accountNumber.trimmed(); 0238 bankNumber = bankNumber.trimmed(); 0239 // Correction BUG 234771 ^^^^^ 0240 if (accountNumber.isEmpty()) { 0241 accountNumber = QString::fromUtf8(data.account_number); 0242 } 0243 if (accountNumber.startsWith(bankNumber % ' ')) { 0244 accountNumber = accountNumber.right(accountNumber.length() - bankNumber.length() - 1); 0245 QStringList splitNumbers = accountNumber.split(' '); 0246 if (splitNumbers.count() == 2) { 0247 agencyNumber = splitNumbers.at(0); 0248 accountNumber = splitNumbers.at(1); 0249 } 0250 } 0251 0252 // Check if account is already existing 0253 SKGAccountObject account; 0254 SKGImportPluginOfx::m_ofxError = getAccount(&data, doc, account); 0255 if (!SKGImportPluginOfx::m_ofxError) { 0256 // Already existing 0257 account = tmp; 0258 SKGImportPluginOfx::m_ofxError = impotExporter->setDefaultAccount(&account); 0259 } else { 0260 // Not existing 0261 QString bankId = (static_cast<bool>(data.bank_id_valid) ? QString::fromUtf8(data.bank_id) : QString::fromUtf8(data.broker_id)); 0262 if (!bankId.isEmpty()) { 0263 bankId = i18nc("Adjective, an unknown item", "Unknown"); 0264 } 0265 0266 // Check if bank is already existing 0267 SKGBankObject bank; 0268 SKGImportPluginOfx::m_ofxError = doc->getObject(QStringLiteral("v_bank"), "t_bank_number='" % SKGServices::stringToSqlString(bankId) % '\'', tmp); 0269 if (!SKGImportPluginOfx::m_ofxError) { 0270 // Already existing 0271 bank = tmp; 0272 } else { 0273 // Create new bank 0274 bank = SKGBankObject(doc); 0275 SKGImportPluginOfx::m_ofxError = bank.setName(bankId); 0276 if (!SKGImportPluginOfx::m_ofxError) { 0277 SKGImportPluginOfx::m_ofxError = bank.setNumber(QString::fromUtf8(data.bank_id)); 0278 } 0279 if (!SKGImportPluginOfx::m_ofxError) { 0280 SKGImportPluginOfx::m_ofxError = bank.save(); 0281 } 0282 } 0283 0284 // Create new account 0285 QString name = QString::fromUtf8(data.account_name); 0286 if (name.isEmpty()) { 0287 name = QString::fromUtf8(data.account_id); 0288 } else { 0289 name = name.remove(QStringLiteral("Bank account ")); 0290 } 0291 if (name.isEmpty()) { 0292 name = QString::fromUtf8(data.account_id); 0293 } 0294 0295 if (!SKGImportPluginOfx::m_ofxError) { 0296 SKGImportPluginOfx::m_ofxError = bank.addAccount(account); 0297 } 0298 if (!SKGImportPluginOfx::m_ofxError) { 0299 SKGImportPluginOfx::m_ofxError = account.setName(name); 0300 } 0301 if (!SKGImportPluginOfx::m_ofxError) { 0302 SKGImportPluginOfx::m_ofxError = account.setNumber(accountNumber); 0303 } 0304 if (!SKGImportPluginOfx::m_ofxError) { 0305 SKGImportPluginOfx::m_ofxError = account.setAgencyNumber(agencyNumber); 0306 } 0307 if (!SKGImportPluginOfx::m_ofxError) { 0308 SKGImportPluginOfx::m_ofxError = account.setComment(QString::fromUtf8(data.account_name)); 0309 } 0310 SKGAccountObject::AccountType type = SKGAccountObject::CURRENT; 0311 if (static_cast<bool>(data.account_type_valid)) { 0312 switch (data.account_type) { 0313 case OfxAccountData::OFX_CHECKING: 0314 case OfxAccountData::OFX_SAVINGS: 0315 case OfxAccountData::OFX_CREDITLINE: 0316 case OfxAccountData::OFX_CMA: 0317 type = SKGAccountObject::CURRENT; 0318 break; 0319 case OfxAccountData::OFX_MONEYMRKT: 0320 case OfxAccountData::OFX_INVESTMENT: 0321 type = SKGAccountObject::INVESTMENT; 0322 break; 0323 case OfxAccountData::OFX_CREDITCARD: 0324 type = SKGAccountObject::CREDITCARD; 0325 break; 0326 default: 0327 break; 0328 } 0329 } 0330 0331 if (!SKGImportPluginOfx::m_ofxError) { 0332 SKGImportPluginOfx::m_ofxError = account.setType(type); 0333 } 0334 if (!SKGImportPluginOfx::m_ofxError) { 0335 SKGImportPluginOfx::m_ofxError = account.save(); 0336 m_accounts[accountNumber] = account; 0337 SKGTRACEL(3) << "Add account '" << accountNumber << "' in index" << SKGENDL; 0338 } 0339 0340 if (!SKGImportPluginOfx::m_ofxError) { 0341 SKGImportPluginOfx::m_ofxError = impotExporter->setDefaultAccount(&account); 0342 } 0343 0344 SKGTRACEL(10) << "Account [" << name << "] created" << SKGENDL; 0345 } 0346 0347 if (static_cast<bool>(data.currency_valid)) { 0348 // Check if unit is already existing 0349 SKGUnitObject unit(doc); 0350 SKGImportPluginOfx::m_ofxError = doc->getObject(QStringLiteral("v_unit"), "t_name='" % SKGServices::stringToSqlString(QString::fromUtf8(data.currency)) % "' OR t_name like '%(" % SKGServices::stringToSqlString(QString::fromUtf8(data.currency)) % ")%'", tmp); 0351 if (!SKGImportPluginOfx::m_ofxError) { 0352 // Already existing 0353 unit = tmp; 0354 SKGImportPluginOfx::m_ofxError = impotExporter->setDefaultUnit(&unit); 0355 } else { 0356 // Create new account 0357 SKGImportPluginOfx::m_ofxError = unit.setName(QString::fromUtf8(data.currency)); 0358 if (!SKGImportPluginOfx::m_ofxError) { 0359 SKGImportPluginOfx::m_ofxError = unit.setSymbol(QString::fromUtf8(data.currency)); 0360 } 0361 if (!SKGImportPluginOfx::m_ofxError) { 0362 SKGImportPluginOfx::m_ofxError = unit.save(); 0363 } 0364 0365 if (!SKGImportPluginOfx::m_ofxError) { 0366 SKGImportPluginOfx::m_ofxError = impotExporter->setDefaultUnit(&unit); 0367 } 0368 } 0369 } 0370 return SKGImportPluginOfx::m_ofxError.getReturnCode(); 0371 } 0372 0373 int SKGImportPluginOfx::ofxTransactionCallback(struct OfxTransactionData data, void* pv) // clazy:exclude=function-args-by-ref 0374 { 0375 if (SKGImportPluginOfx::m_ofxError) { 0376 return 0; 0377 } 0378 SKGTRACEINFUNCRC(5, SKGImportPluginOfx::m_ofxError) 0379 0380 auto* impotExporter = static_cast<SKGImportExportManager*>(pv); 0381 if (impotExporter == nullptr) { 0382 return 0; 0383 } 0384 SKGDocumentBank* doc = impotExporter->getDocument(); 0385 if (doc == nullptr) { 0386 return 0; 0387 } 0388 0389 // Get account 0390 SKGAccountObject account; 0391 SKGImportPluginOfx::m_ofxError = getAccount(data.account_ptr, doc, account); 0392 if (!SKGImportPluginOfx::m_ofxError) { 0393 // Get transaction date 0394 QDateTime date_time; 0395 date_time.setSecsSinceEpoch(static_cast<bool>(data.date_initiated_valid) ? data.date_initiated : data.date_posted); 0396 QDate date = date_time.date(); 0397 0398 // Get unit 0399 SKGUnitObject unit; 0400 SKGImportPluginOfx::m_ofxError = impotExporter->getDefaultUnit(unit); 0401 0402 // Create id 0403 QString ID; 0404 if (static_cast<bool>(data.fi_id_valid)) { 0405 if (QString::fromUtf8(data.fi_id).count('0') != QString::fromUtf8(data.fi_id).count()) { 0406 ID = QStringLiteral("ID-") % QString::fromUtf8(data.fi_id); 0407 } 0408 } else if (static_cast<bool>(data.reference_number_valid)) { 0409 if (QString::fromUtf8(data.reference_number).count('0') != QString::fromUtf8(data.reference_number).count()) { 0410 ID = QStringLiteral("REF-") % data.reference_number; 0411 } 0412 } 0413 0414 if (ID.isEmpty()) { 0415 QByteArray hash = QCryptographicHash::hash(QString(SKGServices::dateToSqlString(date) % SKGServices::doubleToString(data.amount)).toUtf8(), QCryptographicHash::Md5); 0416 ID = QStringLiteral("ID-") % hash.toHex(); 0417 } 0418 0419 // Create operation 0420 SKGOperationObject ope; 0421 if (!SKGImportPluginOfx::m_ofxError) { 0422 SKGImportPluginOfx::m_ofxError = account.addOperation(ope, true); 0423 } 0424 if (!SKGImportPluginOfx::m_ofxError) { 0425 SKGImportPluginOfx::m_ofxError = ope.setDate(date); 0426 } 0427 if (!SKGImportPluginOfx::m_ofxError) { 0428 SKGImportPluginOfx::m_ofxError = ope.setUnit(unit); 0429 } 0430 if (!SKGImportPluginOfx::m_ofxError) { 0431 SKGImportPluginOfx::m_ofxError = ope.setAttribute(QStringLiteral("t_imported"), QStringLiteral("T")); 0432 } 0433 if (!SKGImportPluginOfx::m_ofxError) { 0434 SKGImportPluginOfx::m_ofxError = ope.setImportID(ID); 0435 } 0436 if (!SKGImportPluginOfx::m_ofxError) { 0437 QString payeeName; 0438 if (static_cast<bool>(data.payee_id_valid)) { 0439 payeeName = QString::fromUtf8(data.payee_id); 0440 } else if (static_cast<bool>(data.name_valid)) { 0441 payeeName = QString::fromUtf8(data.name); 0442 } 0443 if (!payeeName.isEmpty()) { 0444 SKGPayeeObject payeeObj; 0445 SKGImportPluginOfx::m_ofxError = SKGPayeeObject::createPayee(doc, payeeName, payeeObj); 0446 if (!SKGImportPluginOfx::m_ofxError) { 0447 SKGImportPluginOfx::m_ofxError = ope.setPayee(payeeObj); 0448 } 0449 } 0450 } 0451 if (!SKGImportPluginOfx::m_ofxError && static_cast<bool>(data.memo_valid)) { 0452 SKGImportPluginOfx::m_ofxError = ope.setComment(QString::fromUtf8(data.memo)); 0453 } 0454 if (!SKGImportPluginOfx::m_ofxError && static_cast<bool>(data.check_number_valid)) { 0455 SKGImportPluginOfx::m_ofxError = ope.setNumber(data.check_number); 0456 } 0457 if (!SKGImportPluginOfx::m_ofxError && static_cast<bool>(data.invtransactiontype_valid)) { 0458 SKGImportPluginOfx::m_ofxError = ope.setMode(i18nc("Noun, the title of an item", "Title")); 0459 } 0460 if (!SKGImportPluginOfx::m_ofxError && static_cast<bool>(data.transactiontype_valid)) { 0461 QString mode; 0462 if (data.transactiontype == OFX_CREDIT) { 0463 mode = i18nc("Noun, type of OFX transaction", "Credit"); 0464 } else if (data.transactiontype == OFX_DEBIT) { 0465 mode = i18nc("Noun, type of OFX transaction", "Debit"); 0466 } else if (data.transactiontype == OFX_INT) { 0467 mode = i18nc("Noun, type of OFX transaction", "Interest"); 0468 } else if (data.transactiontype == OFX_DIV) { 0469 mode = i18nc("Noun, type of OFX transaction", "Dividend"); 0470 } else if (data.transactiontype == OFX_FEE) { 0471 mode = i18nc("Noun, type of OFX transaction", "FI fee"); 0472 } else if (data.transactiontype == OFX_SRVCHG) { 0473 mode = i18nc("Noun, type of OFX transaction", "Service charge"); 0474 } else if (data.transactiontype == OFX_DEP) { 0475 mode = i18nc("Noun, type of OFX transaction", "Deposit"); 0476 } else if (data.transactiontype == OFX_ATM) { 0477 mode = i18nc("Noun, type of OFX transaction", "ATM"); 0478 } else if (data.transactiontype == OFX_POS) { 0479 mode = i18nc("Noun, type of OFX transaction", "Point of sale"); 0480 } else if (data.transactiontype == OFX_XFER) { 0481 mode = i18nc("An transaction mode", "Transfer"); 0482 } else if (data.transactiontype == OFX_CHECK) { 0483 mode = i18nc("An transaction mode", "Check"); 0484 } else if (data.transactiontype == OFX_PAYMENT) { 0485 mode = i18nc("Noun, type of OFX transaction", "Electronic payment"); 0486 } else if (data.transactiontype == OFX_CASH) { 0487 mode = i18nc("An transaction mode", "Withdrawal"); 0488 } else if (data.transactiontype == OFX_DIRECTDEP) { 0489 mode = i18nc("Noun, type of OFX transaction", "Deposit"); 0490 } else if (data.transactiontype == OFX_REPEATPMT) { 0491 mode = i18nc("Noun, type of OFX transaction", "Repeating payment"); 0492 } else if (data.transactiontype == OFX_DIRECTDEBIT) { 0493 mode = i18nc("An transaction mode", "Direct debit"); 0494 } 0495 0496 SKGImportPluginOfx::m_ofxError = ope.setMode(mode); 0497 } 0498 if (!SKGImportPluginOfx::m_ofxError) { 0499 SKGImportPluginOfx::m_ofxError = ope.save(); 0500 } 0501 0502 // Create sub operation 0503 SKGSubOperationObject subop; 0504 if (!SKGImportPluginOfx::m_ofxError) { 0505 SKGImportPluginOfx::m_ofxError = ope.addSubOperation(subop); 0506 } 0507 if (!SKGImportPluginOfx::m_ofxError && static_cast<bool>(data.amount_valid)) { 0508 bool mustFlipSign = (data.transactiontype == OFX_DEBIT || data.transactiontype == OFX_FEE || data.transactiontype == OFX_SRVCHG || 0509 data.transactiontype == OFX_PAYMENT || data.transactiontype == OFX_CASH || data.transactiontype == OFX_DIRECTDEBIT || 0510 data.transactiontype == OFX_REPEATPMT) && data.amount > 0; // OFX spec version 2.1.1, section 3.2.9.2 0511 double sign = mustFlipSign ? -1.0 : 1.0; 0512 double commission = static_cast<bool>(data.commission_valid) ? data.commission : 0; 0513 SKGImportPluginOfx::m_ofxError = subop.setQuantity(sign * (data.amount + commission)); 0514 } 0515 if (!SKGImportPluginOfx::m_ofxError && static_cast<bool>(data.memo_valid)) { 0516 SKGImportPluginOfx::m_ofxError = subop.setComment(QString::fromUtf8(data.memo)); 0517 } 0518 if (!SKGImportPluginOfx::m_ofxError) { 0519 SKGImportPluginOfx::m_ofxError = subop.save(); 0520 } 0521 0522 // Commission 0523 if (!SKGImportPluginOfx::m_ofxError && static_cast<bool>(data.commission_valid) && static_cast<bool>(data.amount_valid) && data.commission > 0) { 0524 // Create splitter operation 0525 SKGSubOperationObject subop2; 0526 if (!SKGImportPluginOfx::m_ofxError) { 0527 SKGImportPluginOfx::m_ofxError = ope.addSubOperation(subop2); 0528 } 0529 if (!SKGImportPluginOfx::m_ofxError) { 0530 SKGImportPluginOfx::m_ofxError = subop2.setComment(i18nc("Noun, a quantity of money taken by a financial institution to perform an operation", "Commission")); 0531 } 0532 if (!SKGImportPluginOfx::m_ofxError) { 0533 SKGImportPluginOfx::m_ofxError = subop2.setQuantity(-data.commission); 0534 } 0535 if (!SKGImportPluginOfx::m_ofxError) { 0536 SKGImportPluginOfx::m_ofxError = subop2.save(); 0537 } 0538 } 0539 } 0540 return SKGImportPluginOfx::m_ofxError.getReturnCode(); 0541 } 0542 0543 QString SKGImportPluginOfx::getMimeTypeFilter() const 0544 { 0545 return "*.ofx *.qfx|" % i18nc("A file format", "OFX file"); 0546 } 0547 0548 #include <skgimportpluginofx.moc>